How would you find if a monster had died?

greatguys1

Epic Adventurer
MSC Developer
Warriors of the North
MSC Archivist
Joined
Apr 20, 2013
Messages
339
Reaction score
61
Age
26
Location
Yes
Lets say I've got a bunch'o orcs spawning around. How would a script find if I were to kill them?
 

Thothie

Administrator
Staff member
Administrator
Moderator
MSC Archivist
Joined
Apr 8, 2005
Messages
16,342
Reaction score
326
Location
lost
Usually it's handled map side via the ms_counter entity targeted by the monsters on the map when they die, but to capture it script side, for a specific script, or set of scripts, you'd need to add something to a script they all share.

Usually things such as this are added to monsters\externals (or test_scripts\npc_externals.script). You then use the "Additional Parameters" (params) property on the msmonster_xxx entity to trigger the external. For example:

Code:
{ set_count_orc_death //addparam
	setvard NPC_COUNT_ORC_DEATH 1
}

{ game_death
	if NPC_COUNT_ORC_DEATH
	callexternal GAME_MASTER gm_dead_orc_count
}

Then, in \game_master.script (or test_scripts\game_master.script):
Code:
{ gm_dead_orc_count
	if !GM_DID_DEAD_ORC_TRIGGER
	add GM_DEAD_ORC_COUNTER 1
	if GM_DEAD_ORC_COUNTER >= GM_DEAD_ORC_MAX
	setvard GM_DID_DEAD_ORC_TRIGGER 1 //flag so we don't repeat this final event
	callevent gm_dead_orc_trigger
}

{ gm_dead_orc_trigger

	[ whatever you want to happen when the requisite number of orcs defined in GM_DEAD_ORC_MAX are dead ]

}

You want to externalize the trigger event to the Game Master, as on any individual mob, script execution stops after game_death is fired, lest you use "setalive 1" in that event (which causes all sorts of fun), and there's always the risk of multiple mobs being slain in the same frame (particularly if you're running about with slayall).

If you are creating the orcs dynamically (and thus can't define addparams on the map entity), you can add to your createnpc command:
Code:
createnpc <some_script> <some_loc> addparams "set_count_orc_death"
Which will stick in additional parameters to be processed at spawn time (parsed by semi-colons in the same fashion the msmonster_xxx entity's "params" property uses).

You can also hybridize the methods, by having an ms_counter on the map, and giving it a "scriptevent" property prefixed with gm_ - which will then call the event on the game_master when the entity reaches its count.
 

greatguys1

Epic Adventurer
MSC Developer
Warriors of the North
MSC Archivist
Joined
Apr 20, 2013
Messages
339
Reaction score
61
Age
26
Location
Yes
Thanks for your help. I took some liberties with your example. Here's what I did:
I added an #include into the game master for my own dynamic quest functions so they don't get jumbled into the code that's already there:
Code:
{ gm_dq_death_counter //PARAM1 = name of monster to count, or partial name. All for counting all of 'em. Not scriptname!  PARAM2 = 1 or 0	greatguys1 July2016

	setvard DQ_DEATHS 0
	setvard DQ_COUNT_WHO PARAM1
	setvard DQ_COUNT_DEATHS PARAM2
}

{ gm_dq_add_death //PARAM1 = name of monster	greatguys1 July2016

	if ( PARAM1 contains DQ_COUNT_WHO )
	{
		setvard DQ_DEATHS $math(add,DQ_DEATHS,1)
	}
	else if ( PARAM1 equals 'all' )
	{
		setvard DQ_DEATHS $math(add,DQ_DEATHS,1)
	}
}
The gm_dq_death_counter takes 2 parameters. The first one takes the name, or partial name of a monster, to check the deaths of if it's the one you wanted to count. Putting in "all" will count all of the monster deaths. The second parameter is to turn it on or off. 1/0. This function also serves as a "reset" to the counter, if you need to count again in the same map.
The gm_dq_add_death is called from another include I have in monsters/extermals.
Code:
{ game_death
	if ( $get(GAME_MASTER,scriptvar,'DQ_COUNT_DEATHS') == 1 ) //greatguys1 July2016
	{
		callexternal GAME_MASTER gm_dq_add_death $get($get(ent_me,id),name)
	}
}
The game_death function is called when the monster dies. This checks if we're supposed to be counting deaths, and if we are, call the game master function gm_dq_add_death. The second function from earlier. It sends the name of the monster that died through it, so it can compare with what we want to count. If the monsters name contains the name we're looking for, add it to the counter. If it doesn't, then do nothing. The counted deaths can then be gotten by:
Code:
if ( $get(GAME_MASTER,scriptvar,'DQ_DEATHS') >= DQ_KILL_NUM )
{
	setvard QUEST_MODE "complete"
}
In which DQ_KILL_NUM is the amount of things that we want to kill.
 

Thothie

Administrator
Staff member
Administrator
Moderator
MSC Archivist
Joined
Apr 8, 2005
Messages
16,342
Reaction score
326
Location
lost
Should work...
Code:
{ game_death
   if ( $get(GAME_MASTER,scriptvar,'DQ_COUNT_DEATHS') ) //greatguys1 July2016
   {
      callexternal GAME_MASTER gm_dq_add_death $get(ent_me,name)
   }
}
Might be a bit cleaner though.

Ya can't pass just "ent_me" but you can pass any $get or other function.

Mind that you can only send one param to an event via addparam, but shouldn't be an issue, if you're calling this from within the scripts rather than through a map entity.
 

greatguys1

Epic Adventurer
MSC Developer
Warriors of the North
MSC Archivist
Joined
Apr 20, 2013
Messages
339
Reaction score
61
Age
26
Location
Yes
I changed how it works a bit so multiple scripts can use the same function.

In the monsters/externals include:
Code:
//By greatguys1
//Best viewed in EditPlus with the ms.stx applied
//This is meant to be included into the monsters\externals.script!!! This doesn't work on its own!

{ game_death

	callexternal GAME_MASTER gm_dq_add_death $get(ent_me,name) $get(ent_me,origin)	//Various params passed are stored on the game_master so other scripts can look at them later if they need to. Add more as needed
}
I removed the check to see if the monster counter is on. It will check in the game_master if there's anything to call anywhere. All this does is call the game_master and pass some params that other scripts might need.

In the game_master include:
Code:
//By greatguys1
//Best viewed in EditPlus with the ms.stx applied
//This is supposed to be included into the game master! This does not work on its own!

{ gm_dq_add_counter //PARAM1 = ID that you wanna call back	greatguys1 July2016
	
	if ( !$get_array(DQ_DEATH_CALLBACK_IDS,exists) )
	{
		array.create DQ_DEATH_CALLBACK_IDS
	}
	array.add DQ_DEATH_CALLBACK_IDS PARAM1
}

{ gm_dq_perish_counter //PARAM1 = ID that you want to perish the counter with

	local L_DEL_IDX $get_arrayfind(DQ_DEATH_CALLBACK_IDS,PARAM1)
	
	if ( L_DEL_IDX != -1 )
	{
		array.del DQ_DEATH_CALLBACK_IDS L_DEL_IDX 
	}
}

{ gm_dq_add_death //PARAM1 = name of monster PARAM2 = MonsterOrigin	greatguys1 July2016

	setvard DQ_KILLED_MONSTER_NAME PARAM1
	setvard DQ_KILLED_MONSTER_ORIGIN PARAM2

	calleventloop $get_array_amt(DQ_DEATH_CALLBACK_IDS) gm_dq_monster_death_callbacks
}

{ gm_dq_monster_death_callbacks

	callexternal $get_array(DQ_DEATH_CALLBACK_IDS,game.script.iteration) ext_quest_monster_killed
}
I added a few new functions, and changed the others. gm_dq_add_counter would be called while passing the id of the script that called it when you want the game_master to report back when a monster is killed. From there, you could do $get(GAME_MASTER,scriptvar,'somevarthatyouwant') once its called back to check conditions. Use gm_dq_perish_counter while passing an id to remove it from the monster counter. gm_dq_add_death is called from the monsters/externals while passing some vars that you might want. gm_dq_monster_death_callbacks actually calls all the ids that you prepped with gm_dq_add_counter.
 
Top