Monstermakers doubt.. Created 7 years ago2016-10-22 20:01:08 UTC by abbadon abbadon

Created 7 years ago2016-10-22 20:01:08 UTC by abbadon abbadon

Posted 7 years ago2016-10-22 20:01:08 UTC Post #332097
Hi. Even If I was working with this entity for the last 12 years, I have come to a problem caused by one of the weapons of the Mod I´m working on : when I use this weapon, it overrides the Delay flag which is set to -1 , then the Maxlivechildren flag is also overriden, and because of that the Monstermaker start creating ALL of the remaining monsters even if Monstercount is set to 1000, which is the case... Imagine what chaos!!.

Because I cannot fix this, at least for now, I thought about changing how monstermakers spawn monsters.

In the TWHL definitions I have found this:
Number of monsters (monstercount) - The maximum number of entities to spawn. -1 is infinite.

Frequency (delay) - Delay, in seconds, between each monster being spawned. If -1, a new monster will only be spawned after the previous has been killed.

Max live children (m_imaxlivechildren) - Maximum number of live children allowed at one time. Spawnings will be suspended until a monster dies. A value of -1 means infinite.
Well, I know that what frequency does is that a new monster is spawned, in # secs. that is, instantaneously afer one monster is killed, or at a certain amount of time if you put, let´s say, 1 or 10 or 60 secs, right?.

But, what if I put NO frequency and use the Maxlivechildren alone with the monstercount?. Will it act as a limiter of how many monsters could be dookied on?, I mean, if I put Maxlivechildren = 10 and I kill one of them, should the entity Monstermaker create a new one to replace it or it will stay OFF until all 10 of those monsters die?.
Posted 7 years ago2016-10-22 20:54:56 UTC Post #332098
The frequency controls how often it checks to see if it can spawn another monster. If Max live children is set, then if there are fewer than that number alive it will spawn another monster. Otherwise, it will check again in frequency seconds. If Max live children is not set, it will spawn another monster every frequency seconds.

Note that frequency only applies if toggle use behavior is enabled (meaning cyclic mode is disabled).

You could add a flag that tells it to only start spawning monsters again if all monsters have died.

To do that i'd keep track of how many monsters have been spawned since the last time all of them have died. Once that number equals Max live children and m_cLiveChildren is 0, you'll know that all children have died. You can then reset the spawned monsters counter and start over.

Something like this in CMonsterMaker::MakeMonster:
[code]
if( m_iMaxLiveChildren > 0 )
{
	if( FBitSet( pev->spawnflags, SF_MONSTERMAKER_GROUPED ) )
	{
		if( m_cSpawnedChildren >= m_iMaxLiveChildren )
		{
			if( m_cLiveChildren > 0 )
			{
				//Not all children have been spawned or died yet, so don't allow spawning.
				return;
			}
			//All children have been spawned and have died.
			m_cSpawnedChildren = 0;
		}
	}
	if ( m_cLiveChildren >= m_iMaxLiveChildren )
	{// not allowed to make a new one yet. Too many live ones out right now.
		return;
	}
}
[/code]

SF_MONSTERMAKER_GROUPED is the flag that controls this behavior. I'm using the term grouped to mean spawning monsters in groups of m_cMaxLiveChildren.

m_cSpawnedChildren should be incremented later in the method to track monster spawns.
Posted 7 years ago2016-10-23 14:43:42 UTC Post #332100
Thanks (again, I owe you another!) Solokiller :) , should this go in the Makemonster function?. Also, I have seen this in the same function:

[quote]CBaseEntity *pList[2];
int count = UTIL_EntitiesInBox( pList, 2, mins, maxs, FL_CLIENT|FL_MONSTER );

if ( count )
{
	// don't build a stack of monsters!
	return;
}
[/quote]

As I see, and as I could "translate" from C++ to human language, it keeps the monstermaker from creating a number of entities greater than the engine´s limit, right?,sooo... will this part be the culprit of all my troubles? I mean, would some part of it was overriden by this code from the weapon I have mentioned before ?:

[quote]
float		flAdjustedDamage;
float		flDist;
CBaseEntity *pEntity = NULL;
// iterate on all entities in the vicinity.
[blue]while ((pEntity = UTIL_FindEntityInSphere( pEntity, pev->origin, 800 )) != NULL)[/blue]
{
	if ( pEntity->pev->takedamage != DAMAGE_NO )
	{
		{
				flAdjustedDamage = 30;
[/quote]

etc, etc. that is in the PrimaryAttack code, the rest of the code is related to visual effects so I don´t think it could cause the problem. o

I have asked this some time ago, and received help and advices on how should I try to fix it, but, and I admint that it is because of my lack of skills in coding, after some time I get tired of trying things to fix it, and started to search a shortcut through mapping instead of coding.

Thanks again!!
Posted 7 years ago2016-10-23 15:03:09 UTC Post #332103
EDIT: sorry Solokiller, of course the code must go in MakeMonster...
Something like this in CMonsterMaker::MakeMonster:
I was so tired last night and also I focus my attention in the block of code... ;)

Also, you said...
m_cSpawnedChildren should be incremented later in the method to track monster spawns.
...should this be like this?, putting the declaration of the integer in the first lines of the monstermaker.cpp file, in class CMonsterMaker : public CBaseMonster
int m_cSpawnedChildren;
Also, should I set a value for m_cSpawnedChildren?, something like:
m_cSpawnedChildren = 40;
And put it into the MakeMonster function, of course. If the MaxLiveChildren flag is overriden, the m_cSpawnedChildren value will keep the MonsterMaker from spawning more monsters, right?

I think it´ll work but about the code I had written is on where i have more doubts. BUt the thing of which I doubt the most is where to put the SF_MONSTERMAKER_GROUPED part, maybe in a monstermaker.h file?
Posted 7 years ago2016-10-23 15:52:16 UTC Post #332104
m_cSpawnedChildren should be set to 0 in Spawn since it tracks how many children have been spawned for the current group.

It'll stop it from spawning more monsters until all monsters in the current group have died.

In the SDK the spawnflags for monstermaker are defined in monstermaker.cpp, so you can put it there.
Posted 7 years ago2016-10-23 15:59:09 UTC Post #332105
Ok, I´ll make a backup file of this and implement it on the mod´s sdk. Wish me luck! :)

Thanks Solokiller!
Posted 7 years ago2017-01-22 22:57:24 UTC Post #333146
Hi Solokiller. Tried (after many months) to re-add the code you provided , I did use a lot of combinations, but with no luck. I did not say anything before because I prefer to try until surrender before bothering you again. The fact is that after a bunch of tries I still get two errors:
-------------------Configuration: hl - Win32 Release-------------------
Compiling...
monstermaker.cpp
C:\DevZWC20\Elementos\Single-Player Source\dlls\monstermaker.cpp(251) : error C2059: syntax error : ')'
C:\DevZWC20\Elementos\Single-Player Source\dlls\monstermaker.cpp(252) : error C2143: syntax error : missing ';' before '{'
Error executing cl.exe.

hl.dll - 2 error(s), 0 warning(s)
The code is as follows:

Under
#define SF_MONSTERMAKER_MONSTERCLIP 8 // Children are blocked by monsterclip
I put:
//=========================================================
// SOlokillers Spawn LIMITER
//=========================================================
#define SF_MONSTERMAKER_GROUPED
//=========================================================
Then into:
class CMonsterMaker : public CBaseMonster
I put:
int m_cSpawnedChildren;// SOlokillers Spawn LIMITER
And then into:
void CMonsterMaker::MakeMonster( void )
I put:

[quote]//====================================================================
// Solokillers Monstermaker LIMITER
//====================================================================
if (m_iMaxLiveChildren > 0)
{
	if(FBitSet(pev->spawnflags, SF_MONSTERMAKER_GROUPED ))
	{
		if(m_cSpawnedChildren>=m_iMaxLiveChildren)
		{
			if(m_cLiveChildren>0)
			{
				return;
			}

		}
	m_cSpawnedChildren = 0;
	}
}
if(m_cLiveChildren >=m_iMaxLiveChildren)
{
	return;
}
//======================================================================
//======================================================================[/quote]
What´s wrong?, afaik i did not make any mistakes this time... :(
Posted 7 years ago2017-01-22 23:01:18 UTC Post #333147
You defined SF_MONSTERMAKER_GROUPED improperly, it should be like this:
#define SF_MONSTERMAKER_GROUPED 16
You'll have to choose a proper value, 16 is the first one that isn't in use as far as i can tell.
Posted 7 years ago2017-01-23 00:01:56 UTC Post #333148
Can´t believe that is what is failing this last two months!!! :(, I feel SO stupid...

BTW: I tested it and... well, the monstermakers still spit all theyr children alltogehter. :( . Again, I am sure I did something wrong, or ALL wrong. You told me something like making incremental check of monsters created.
m_cSpawnedChildren should be incremented later in the method to track monster spawns.
You mean something like this?

[quote] m_cSpawnedChildren = 0;
for ( i = 0; i < m_cSpawnedChildren; i++ )[/quote]
and something after it, so if "i" equals or is more than, lets say, 100, it "returns;" directly, I am not sure what to write there but, is this what you say I need?
Posted 7 years ago2017-01-23 16:36:53 UTC Post #333153
No i just mean incrementing the variable itself to track the number of spawned children.

It sounds like what you want is all of the monstermakers to obey the same spawn restrictions so they pull from a pool of spawn-able monsters. That requires a large scale redesign that i can't explain on a whim, so if needed i can implement that in HLE first (it's a useful thing to have) and then you can integrate it into your own mod.
Posted 7 years ago2017-01-23 16:49:31 UTC Post #333154
You mean something like this?

Quote:
m_cSpawnedChildren = 0;
for ( i = 0; i < m_cSpawnedChildren; i++ )

and something after it, so if "i" equals or is more than, lets say, 100, it "returns;" directly, I am not sure what to write there but, is this what you say I need?
If I translate your code above, it means:

1) Set "m_cSpawnedChildren" to 0.
2) For "i" starting to 0 while "i < m_cSpawnedChildren (i)" is true and "increment i" at each step.

What Solokiller meant is that each time the "monstermaker" create the monster, you should increment m_cSpawnedChildren (either use "m_cSpawnedChildren++" or "m_cSpawnedChildren = m_cSpawnedChildren + 1", the first one is better for code readability).

Also to reply to one of your unanswered question, you asked what this code does :
CBaseEntity *pList[2];
int count = UTIL_EntitiesInBox( pList, 2, mins, maxs, FL_CLIENT|FL_MONSTER );

if ( count )
{
// don't build a stack of monsters!
return;
}
This code count the number of entities close to the "monstermaker's" origin, if that variable is anything but 0, the spawn is denied (otherwise you block the spawned and spawning entities, if you want to add a "telefrag" feature, that would be the place to do it).

EDIT : Ninja'ed again xD
Posted 7 years ago2017-01-23 17:35:00 UTC Post #333155
Oh thanks!, as always, Solokiller and Shepard to the rescue!. Solokiller is right, because the FEMP weapon cause the monstermakers to start spawning all the monsters without restrictions, I need something that prevent this to happen and controls all the spawned monsters. Also, I have found that the turrets caused this same problem when killing sentinels. For one reason that I don't know, the bullets fired by the turrets and the blast from the FEMP weapon destroy the maxlivechildren and the delay flag of the monstermakers... :(
Posted 7 years ago2017-01-24 20:45:48 UTC Post #333166
Hi again. I have found this on the "makemonster" part:

[quote] CBaseEntity *pList[2];
int count = UTIL_EntitiesInBox( pList, 2, mins, maxs, FL_MONSTER ); //

if ( count )
{
	// don't build a stack of monsters! //
	UTIL_ClientPrintAll( HUD_PRINTNOTIFY, "count limit reached!! \n");//NEW, I want to know if this work...
	return;
}
[/quote]

Could this be modified to, lets say, control the entities (monsters) and if the numbre is more than "x" make the makemonster part return 0?
Posted 7 years ago2017-01-25 00:18:58 UTC Post #333167
What do you mean by "control the entities" ?

Like I said above, the code you've copied/pasted act as an "anti-spawn blocker", it just count the number of entities having the FL_MONSTER flag (monsters and players) in a "box" close to the spawn area and if at least an entity is found then the spawn is denied.
Posted 7 years ago2017-01-25 12:24:59 UTC Post #333174
Sorry, I used the wrong word, I mean monsters of course. I will look forward another function more suitable to do what I need. ;)

Ehmmm... I know this could be a matter of very basic C++ knowledge, but, how can UTIL_FindEntityByClassname be used to return the number of entities (by class name, of course) and then compare this number to a fixed int to start/stop the makemonster function?.

This will be in every monstermaker, so the MM will check this number individually each time the makemonster function is started.
Posted 7 years ago2017-01-25 13:57:25 UTC Post #333180
You can do that, but it's expensive to loop them every time. It might be easier to track entity creation and destruction and store the number somewhere. Unfortunately the messy way that the SDK uses to handle this makes this non-trivial to implement.

In HLE you should be able to store a global map of classname->entity count that gets updated in OnCreate and OnDestroy, respectively.

In the SDK you'll need to do it in GetClassPtr and add the NEW_DLL_FUNCTIONS::pfnOnFreeEntPrivateData callback, because that's where OnDestroy gets called. The vanilla SDK does not implement it, though it is used by Ricochet IIRC.
Posted 7 years ago2017-01-25 21:03:12 UTC Post #333181
Oh, wow, that´s coding in god mode. I will try to make it via mapping hacks, limiting the maxlivechildren and giving some time (delay) between spawns (actually some of them are set to -1 or instant). Thank you so much!, you saved me a lot of hours trying to find a solution! :) As always, both you are the best :P

BTW: I did take a look in the Github's page where people write about HL issues, and I want to post this monstermaker's issue because I did not found nothing similar in the post I did read. Will it be a good idea?

Nevermind, I did post the issue. ;)
Posted 7 years ago2017-01-25 23:32:27 UTC Post #333182
Half-Life's GitHub issues is not the appropriate place to post your mod's issues, you should post on GitHub if and only if you have an issue with Gold Source itself and/or you want to suggest something.
Posted 7 years ago2017-01-25 23:56:44 UTC Post #333183
Oh, thought that the weapon problem should be interesting, I mean, the weapon can cause a malfunction to an entity that is not suposed to be affected by a weapon. Also, there´s the turret issue, that causes the same problem when shooting at npcs. :( I posted every information I have, what happen, and also the code, and (of course) what did I try to fix it (Except Solokiller´s last advices, of course). I saw other people asking for problems like this, but if I did wrong I will delete it ASAP Shepard. ;), thanks for the advice :)
Posted 7 years ago2017-01-26 17:01:44 UTC Post #333186
I saw other people asking for problems like this
Those other people have no idea how GitHub (let alone an "issue tracker") works.

An "issue tracker" (which usually is a component/plug-in offered by VCS hosts) is NOT a forum. Like the name say, it's an "issue management tool". The definition of an "issue" (borrowed from Wikipedia because I'm lazy) :
In computing, the term "issue" is a unit of work to accomplish an improvement in a system. An issue could be a bug, a requested feature, task, missing documentation, and so forth.
What you posted is NOT a bug within Half-Life, nor it's a bug, requested feature, task and missing documentation. GitHub won't allow you to delete the ticket, you can just close it.

Back on the topic, I don't understand what you are trying to accomplish. You want your weapon (FEMP) to control "monstermaker" ?
Posted 7 years ago2017-01-26 17:31:59 UTC Post #333187
No!!, it is just the opposite!!, I don't want it to "destroy" the m_imaxlivechildren flag :( . In the version of the mod I am working now the monstermakers, when their child are killed by the FEMP or the turret's bullets, they create ALL monsters they have assigned by the monstercount flag whithout being affected by the m_imaxlivechildren flag, so they create all 1000 sentinels without stop, filling the map with npcs and thus making the game unplayable.

That's an old problem I had, but I did not know how to fix it or where to start to look into the code so I could ask for help properly. :( I did read Solokiller's mm issue there, but I do not think it is related whith my problem, well, what happens to him is just the oppodite but caused by an entity (oh, probably a bullet is a kind of entity, no?)... :\

I did read the "issue" definition in the Wikipedia, of course, and thought that what is happening to me was a bug indeed, like Solokiller's problem with the npcs created by mm not spawning properly if killed by a killtarget.

I have read here and there that the monstermaker entity is one of the weirdest, pickiest and most buggy entity in half-life, sometimes wrork, sometimes not, and most times act in weird manners.

Anyway I will close it, I don't want to be banned so early!!

Update!: Issue closed.
Posted 7 years ago2017-01-26 17:50:18 UTC Post #333188
You should show us the entire monstermaker class, then we can see if anything looks off. Put it on Pastebin.
Posted 7 years ago2017-01-26 17:52:33 UTC Post #333189
Ok!... errr, what is pastebin? , this days I have the Moron Mode always ON.
Posted 7 years ago2017-01-26 18:12:10 UTC Post #333190
http://pastebin.com/

If you don't want it sticking around forever, set an expire time.
Posted 7 years ago2017-01-26 21:43:31 UTC Post #333191
You see?, I spent the last half hour searching on Github the "pastebin" tag... :( I will post also the full code of the turret and the FEMP.

I have made a last try inspired by Solokiller´s problem...

In monstermaker.cpp

the function

[quote]
//=========================================================
//=========================================================
void CMonsterMaker :: DeathNotice ( entvars_t *pevChild )
{
// ok, we've gotten the deathnotice from our child, now clear out its owner if we don't want it to fade.
m_cLiveChildren--;
if ( !m_fFadeChildren )
{
	pevChild->owner = NULL;
}
}
[/quote]

I did comment the "if ( !m_fFadeChildren )" line and now it seems to work fine... I can not understad anything. Of course I did only three tests-gameplays, but I´m a bit shockd about this. I will do more testings to see if that´s only a glitch, a bug, call it what you want.

Could it be related to this?

[quote]
//=========================================================
// Killed - overrides CFlyingMonster.
//=========================================================
void CIchthyosaur :: Killed( entvars_t *pevAttacker, int iGib )
{
CBaseMonster::Killed( pevAttacker, iGib );
pev->velocity = Vector( 0, 0, 0 );
/////////////////////////////////////////
///// NEWCODE UNDER THIS COMMENT!!!//////
/////////////////////////////////////////
Vector			vecSplatDir;
TraceResult		tr;
CBaseEntity *pOwner = CBaseEntity::Instance(pev->owner);
if (pOwner)
pOwner->DeathNotice(pev);
SetActivity( ACT_DIEVIOLENT );

pev->movetype = MOVETYPE_TOSS;
pev->takedamage = DAMAGE_NO;
pev->spawnflags = SF_MONSTER_FADECORPSE;
DeathSound( ) ;// Descomentado el 2-3-2016
UpdateOnRemove();//NUevo. Sacado de GitHub 19-10-2016 (c)Solokiller
}



void CIchthyosaur::BecomeDead( void )
{

if ( ShouldFadeOnDeath() )
			{
				// this monster was created by a monstermaker... fade the corpse out.
				SUB_StartFadeOut();
			}
//==================================================
//Intento de que no pete el sistema ARM: 26-1-2016
//==================================================
CBaseEntity *pOwner = CBaseEntity::Instance(pev->owner);
if ( pOwner )
{
	pOwner->DeathNotice( pev );
}
UTIL_Remove( this );
	UpdateOnRemove();//NUevo. Sacado de GitHub 19-10-2016 (c)Solokiller
//======================================================
}
[/quote]

I am probably culprit of, after many goofing and trial-eror sessions, having screwing something since the beggining of ZWC development, the code above is the result of YEARS of tries with no luck, the Solokiller part was taken from Github and seemed also to make nothing to prevent the MM behaviour...

Give me a day or two, I will post the results.
Posted 7 years ago2017-01-27 14:15:56 UTC Post #333194
It's probably calling DeathNotice over and over and decrementing m_cLiveChildren too often. Having the child's owner nulled out unconditionally (as you've done) should fix that.

Note that UTIL_Remove will call UpdateOnRemove already (unless your version doesn't) so you don't need to call it manually.
Posted 7 years ago2017-01-27 15:29:13 UTC Post #333195
Like this?
if ( m_fFadeChildren )
{
pevChild->owner = NULL;
}
If so, you are on credits again!! (is like If I have you always on my developing team, haha! :P )
Note that UTIL_Remove will call UpdateOnRemove already (unless your version doesn't) so you don't need to call it manually.
Oh!, see?, I made a redundant code there, I hope it will not cause troube...
Posted 7 years ago2017-01-27 15:44:59 UTC Post #333197
That's still conditional, you shouldn't make it check that boolean. I'm not sure why that's there though. It should really be checking if the monster called DeathNotice before, but that requires the monstermaker to track the children.

If that's needed i can give you some code to create intrusive linked lists of monsters for monstermakers to use, then you can check if the monster has alraedy called DeathNotice before. As a bonus, you'll have a list of all monstermaker children.
Posted 7 years ago2017-01-27 16:39:12 UTC Post #333198
That's still conditional, you shouldn't make it check that boolean. I'm not sure why that's there though. It should really be checking if the monster called DeathNotice before, but that requires the monstermaker to track the children.
the if (m_fFadeChildren) etc. is original code, I did not know why it checks if monsters are fading or not to do the pevChild return NULL.

I found that monsters now spawn properly, but they don´t fade at all making the map be covered with sentinel´s bodies. :(

Checked. If I left the function like that, monsters won´t fade when dead. Any advices?

EDIT:

Think I got it!!, please, fix anything you see it´s bad written or is wrong, please.

[quote]//=================================
//=================================
void CMonsterMaker :: DeathNotice ( entvars_t *pevChild )
{
m_cLiveChildren--;
pevChild->owner = NULL;
}[/quote]

Function now is like that.

In monster´s death code:

[quote]
void CIchthyosaur::BecomeDead( void )
{
// removed conditional "if ( ShouldFadeOnDeath() ) "
SUB_StartFadeOut();
//==========================
// With this game does 
// not crash ARM: 26-1-2016
//===========================
CBaseEntity *pOwner = CBaseEntity::Instance(pev->owner);
if ( pOwner )
{
	pOwner->DeathNotice( pev );
}
UTIL_Remove( this );
UpdateOnRemove();//New. from GitHub 19-10-2016 (c)Solokiller
//========================
}[/quote]

Now the sentinels fade and the monstermakers stop making nonsenses. I have to make several long gameplays and I will post the results. Anyway, tell me if you see something that could be better written and I will do so.

I have also to do firing sessions with the FEMP and see if all woks also.
Posted 7 years ago2017-01-27 21:34:41 UTC Post #333200
This looks good, i think this is a bug in the SDK. I'll have to check that out, see if that's the case. If not, i'll figure out if this is the best solution or if a better one is available.
Posted 7 years ago2017-01-27 21:41:27 UTC Post #333201
This time, in the list of things done by you into the credits video I have added "monstermakers final fix" ;). I will release the credits video as soon as I find a fix for the overheat code (works only at 50%) and find a fix for the bot's aiming and weapon selection routines. :). Thanks Solokiller!
Posted 7 years ago2017-01-28 10:37:11 UTC Post #333206
Checked!!!:

3 Long Plays

1st: 6 minutes. 5 FEMP shot. No changes, all worked fine.
2nd: +7 minutes. 5 FEMP shot. All Ok.
3rd: +7 minutes. 5 FEMP shot. All Ok.

Can´t believe it. A single line of code did all taht mess. :/

Will post the video on Moddb tomorrow...
You must be logged in to post a response.