Fix for "unused keyvalues" bogus error

MS:C community

Old Skool Apostle
Alpha Tester
Joined
Jul 7, 2011
Messages
504
Reaction score
109
I'm sure most mappers here have seen the following 'problems' in their map:

Code:
Entity (msmonster_skeleton) has unused keyvalues
Entity (ms_player_spawn) has unused keyvalues
Entity (msworlditem_treasure) has unused keyvalues
Entity (env_model) has unused keyvalues
These MS:C entities (and a bunch of others, complete list in a few) can, in some cases, produce the above error, which really isn't an error at all. When you click on the description of the problem, you are treated to something in Crazy Moon Language:
The entity contains keyvalues that are not used in its class. You can fix this error with the Fix button.
Pressing "Fix" has actually deletes the unrecognized keyvalues, ie. it removes data from your entity that you assigned and the result will most likely be that your entity will no longer function properly.

You can ignore the problem because it doesn't cause anything to go wrong anyway, but it sure is annoying to see the Problems window spammed with bogus errors. Not to mention that "Fix" is useless here...

So here's what causes it: The "angles" keyvalue (this is the three-number property that defines how an entity is rotated, example "angles" = "30 0 45") isn't defined explicitely for all MS:C entities that need it.

The fix is easy, though: Just copy the Angles BaseClass from halflife.fgd...

Code:
@BaseClass = Angles
[
	angles(string) : "Pitch Yaw Roll (Y Z X)" : "0 0 0"
]
...and paste it somewhere near the top in ms1.4.fgd

Now close halflife.fgd and in ms1.4.fgd go to all of the following entities:

ms_player_spawn
ms_player_begin
ms_player_spec
msitem_spawn
ms_npc
msmonster_boar
msmonster_hawk
msmonster_giantrat
msmonster_bat
msmonster_giantbat
msmonster_skeleton
msmonster_orcwarrior
msmonster_orcberserker
msmonster_orcarcher
msmonster_orcranger
msmonster_troll
msnpc_human1
msworlditem_treasure
env_model


...and add "Angles" in the base() header (separate BaseClasses by commas ","). If you don't know how to do that, here's an example.

BEFORE
Code:
@PointClass base(ms_basenpc) color(128 0 0) studio("models/monsters/Boar.mdl") = msmonster_boar : "Boar"
[
	defscriptfile(string) : "Default Script (do not change)" : "monsters/boar"
]
AFTER
Code:
@PointClass base(Angles, ms_basenpc) color(128 0 0) studio("models/monsters/Boar.mdl") = msmonster_boar : "Boar"
[
	defscriptfile(string) : "Default Script (do not change)" : "monsters/boar"
]
As you can see, I only changed base(ms_basenpc) to base(Angles, ms_basenpc)

Another example:

BEFORE
Code:
@PointClass base(spawnspot) studio("models/human/male1/male1.mdl") = ms_player_spawn : "Generic spawn point" 
[
	message(string) : "Link to Transition"
]
AFTER
Code:
@PointClass base(Angles, spawnspot) studio("models/human/male1/male1.mdl") = ms_player_spawn : "Generic spawn point" 
[
	message(string) : "Link to Transition"
]
Here I only changed base(spawnspot) to base(Angles, spawnspot)

So just add "Angles" (and a comma, if necessary) to the base() header of the nineteen entities listed above, and most "unused keyvalues" problems will be gone.

Some more exotic keyvalue problems
If you want to have a func_button remove an entity upon press, you will have to define the "killtarget" keyvalue for it. Do this by adding, in halflife.fgd, the following line to the func_button keyvalue list:
Code:
	killtarget(target_destination) : "KillTarget"
If you want to assign an MS:C script to a func_rotating (the only case where you'd actually want to do this is to make 'clock hands' like those in edana), add the following line to func_rotating:
Code:
	scriptname(string) : "Use scriptfile (for clock hands)"
Some really exotic keyvalue problems
For those handsome VHLT users out there who use zhlt_usemodel and zhlt_copylight, I have two useful BaseClasses that can be added to halflife.fgd and/or ms1.4.fgd
Code:
@BaseClass = VHLTcopylight
[
	zhlt_copylight(string) : "Use light data from this entity"
]
Code:
@BaseClass = VHLTcopymodel
[
	zhlt_usemodel(string) : "Use model (appearance) from this entity"
]
Which entity or entities you now add one or both of these BaseClasses to is of course entirely up to you. I myself added VHLTcopylight to MS:C's env_model, just to give an example.
 

Thothie

Administrator
Staff member
Administrator
Moderator
MSC Archivist
Joined
Apr 8, 2005
Messages
16,342
Reaction score
326
Location
lost
Well damn, been wondering how to fix this BS...

I can add these changes to the betapack...

Few things:
Likely simpler to just add Angles to ms_basenpc:
Code:
 @BaseClass base(Targetname,Angles) size(-16 -16 0, 16 16 72) = ms_basenpc

Thus you won't have to track down all the msmonster_xxx's, ms_npc, msworlditem_treasure...

...and I'm still getting a few of these bogus unused key values... So something else be missing still...

MS:C community said:
If you want to assign an MS:C script to a func_rotating (the only case where you'd actually want to do this is to make 'clock hands' like those in edana), add the following line to func_rotating:
Code:
   scriptname(string) : "Use scriptfile (for clock hands)"
Actually, that property is for more than just the clock, rarely used though it is. It can be added to, literally, any entity. The functionality changes, but any entity, solid or point, can be scripted, by adding that property. Generally, however, if you want a solid brush to be scripted, you're better off using the msarea_scripted entity, coupled with an origin brush.

Thus, rather than making a new base attrib for every entity that's almost never used, we've just left it as a manual addition.

And yes, you can make entity brushes that get up, chase you around, and can attack and be killed.


MS:C community said:
Which entity or entities you now add one or both of these BaseClasses to is of course entirely up to you. I myself added VHLTcopylight to MS:C's env_model, just to give an example.
I think that's for solid brushes (brush models) rather than point-entity models... Not sure if that'll work... :\ Might... :/
 

MS:C community

Old Skool Apostle
Alpha Tester
Joined
Jul 7, 2011
Messages
504
Reaction score
109
Thothie said:
Few things:
Likely simpler to just add Angles to ms_basenpc
...and I'm still getting a few of these bogus unused key values... So something else be missing still...
D'oh, how did I miss that...

As for the additional unused key value problems you're getting... The ms_basenpc BaseClass is only used by ms_npc, msnpc_human1, msworlditem_treasure and the msmonster_[name] series.
You'll also need to add Angles to the base() headers of:
  • the spawnspot BaseClass (for ms_player_spawn, ms_player_begin and ms_player_spec)
  • the ms_baseitem BaseClass (for msitem_spawn)
  • env_model
...but you probably already know that.

If you're still getting "unused keyvalues" problems, copy+paste the entity data (as you'd find it in the map's entity table) or a screenshot of the offending entity's Object Properties window in Hammer (with SmartEdit disabled of course) and I'll try to help you out.

Thothie said:
Actually, [the scriptname] property is for more than just the clock, rarely used though it is. It can be added to, literally, any entity.
I'm aware that there's stuff like triggers/glow_block (for trigger_multiple) and triggers/trigger_web (for func_wall_toggle); I was referring to func_rotating specifically here. I don't see at this point why anyone would ever want to add a scriptname to a func_rotating, unless it's either edana/clock_minutehand or edana/clock_hourhand.

Thothie said:
I think [zhlt_copylight is] for solid brushes (brush models) rather than point-entity models... Not sure if that'll work... :\ Might... :/
More on this in a few...
 

Thothie

Administrator
Staff member
Administrator
Moderator
MSC Archivist
Joined
Apr 8, 2005
Messages
16,342
Reaction score
326
Location
lost
MS:C community said:
I don't see at this point why anyone would ever want to add a scriptname to a func_rotating, unless it's either edana/clock_minutehand or edana/clock_hourhand.
Once or twice we've used to change the location of a func_rotating for a moving cage like effect (though maybe it was a rotating door). True, I dun think we kept the idea... We've also used it on func_breakables to convert them into lures. You can try using the scriptname "other/make_glow" for loads of fun, if it'll work... Tip: doesn't do what the name suggests - and you may have to click +use on the brush before the fun starts.

MS:C community said:
[zhlt_copylight on env_model]
That's... Very odd... As env_model is not a default Half-Life entity - it's unique to MSC. I dunno how/why VHLT would be able to pick up on it. Normally, in Half-Life, the only way to place models is with env_sprite (and that's a bit half-assed).
 

MS:C community

Old Skool Apostle
Alpha Tester
Joined
Jul 7, 2011
Messages
504
Reaction score
109
Looks like you saw my half-assed spam about zhlt_copylight before I edited it out :razz:

By now I did some real testing with it, and you pretty much underestimate the power of zhlt_copylight!

I'll abbrevate the entity-that-you-give-a-name-so-other-entities-can-use-its-light-data as the sample, the entity-that-you-wish-to-use-zhlt_copylight-on as the target, a point-based entity as a point and a brush-based entity as a brush so this will be easier to read:

With zhlt_copylight you can do... Everything! You can have:
  • a point-sample light a point-target
  • a point-sample light a brush-target
  • a brush-sample light a point-target
  • a brush-sample light a brush-target

Post is worthless without pics, so here goes:

My point-sample is a simple env_model, a chair to be precise:
2ZKjO00.png
It's being lit from above by a pure blue light (brightness: 1500) and the name of the point-sample is "sample_point" (how creative). Apart from some rotation, none of the keyvalues of this env_model have been altered.

And here is my brush-sample:
21ek31e.png
This is a func_illusionary (standard render properties) named "sample_brush". What you don't see, however, is that there's an ORIGIN brush tied to it. I placed it in front of the brush (so it gets lit). A brush-sample must have an ORIGIN brush tied to it in order to tell RAD at which coordinates the light information must be sampled.
This brush-sample is being lit from the front by a pure red light (brightness: 1500).

The results (click to enlarge):
4mHaKPm.png

Yes, I did have to cheat a bit with the render properties for the brush-targets (otherwise they'd just show up in the colour of the texture I used) but at least they're emitting light because of zhlt_copylight.
Important: The brush-targets need an ORIGIN brush attached to them as well!

Models will emit light and be lit properly by zhlt_copylight, without you having to change render options and such.

Also, about env_model... I'm quite sure I've seen that in The Ship as well. Are you sure it's MS:C-exclusive?

Edit:
Thothie said:
You can try using the scriptname "other/make_glow" for loads of fun, if it'll work...
Curiosity ignited...! I'll try that later.

Also, do you still have "unused keyvalues" problems that I can take a look at, if you want?

Edit 2:
Download the BSP + source of the test map I used here
 

MS:C community

Old Skool Apostle
Alpha Tester
Joined
Jul 7, 2011
Messages
504
Reaction score
109
Thothie said:
You can try using the scriptname "other/make_glow" for loads of fun, if it'll work... Tip: doesn't do what the name suggests - and you may have to click +use on the brush before the fun starts.
I tried other/make_glow on a func_wall, func_breakable and a func_rotating but nothing ever happened (not even after +use). What is supposed to happen...?

Also, does anyone know how zhlt_transform works? I haven't even tried yet though, but if anyone knows I can save some time here.
 

Thothie

Administrator
Staff member
Administrator
Moderator
MSC Archivist
Joined
Apr 8, 2005
Messages
16,342
Reaction score
326
Location
lost
MS:C community said:
I tried other/make_glow on a func_wall, func_breakable and a func_rotating but nothing ever happened (not even after +use). What is supposed to happen...?
Darn... Ya might have to put it on an msarea_scripted instead, or some other entity that has a +use input - I guess func_rotating doesn't. :\

If it works, it'll have an interaction menu, and should be obvious from there. Unlike some of the other brush scripts (such as the boom block) it's user friendly.

MS:C community said:
Also, does anyone know how zhlt_transform works? I haven't even tried yet though, but if anyone knows I can save some time here.
Not fiddled with it, or even the basic scale function. Doesn't seem it would be particularly useful by itself though.

What I am more curious about, that I've also not fiddled with, is the info_hullzone entity - that lets you define the area a player can move in, and thus skip clip nodes for large portions of the map (though seems to have potential issues)... And fiddling with the results of the -smooth2 # feature on the VHLRAD.

MS:C community said:
zhlt_copylight
For brush entities, it'd probably be simpler to use the classic ZHLT "Light Origin Target" (light_origin) property, common to most all solid brushes, which will cause the model to be lit as if its center were at the defined info_target. (ie. make info_target named "red_light_district" in a red-lit room, and set the light_origin to "red_light_district" on any brushes you want to be red.)

Unlike copylight, dun think it works with models though.
 

MS:C community

Old Skool Apostle
Alpha Tester
Joined
Jul 7, 2011
Messages
504
Reaction score
109
Thothie said:
Darn... Ya might have to put it on an msarea_scripted instead, or some other entity that has a +use input - I guess func_rotating doesn't. :\
I followed your advice and got it to work on an msarea_scripted -- after adding an ORIGIN brush and setting "zhlt_invisible" = "0", that is.

It works pretty good: click
Menu option 'Spin' doesn't appear to function though, and if you hit the brush, it stops moving and the render properties change, but I gather this entity is only for messing around so it's probably no big deal. Fun though :razz:

I did notice that msarea_scripted makes use of the "scriptfile" keyvalue (and not "scriptname"). I tried making a func_rotating with "scriptfile" = "other/make_glow" instead of "scriptname" = "other/make_glow" this time, but it still didn't work.

That being said... If you have time, could you please explain the difference between "scriptfile", "scriptname" and "scriptevent" and maybe give some examples?
 

Thothie

Administrator
Staff member
Administrator
Moderator
MSC Archivist
Joined
Apr 8, 2005
Messages
16,342
Reaction score
326
Location
lost
Scriptname and Scriptfile I suspect are just inconsistencies in the naming when the original entities were made. I do believe "scriptname" is used when attaching a script to a normally unscripted brush, while "scriptfile" tends to be the name used for things that are always intended to be scripted (such as msarea_scripted, ms_npc, msmonster_xxx, etc.)

Scriptevent is different... It runs an event within the script that touches it. So, if you make a trigger_once with the scriptevent "demon_blood" it'll activate the demon blood effect when a player or mob crosses it (assuming it's flagged to detect mobs). "npc_suicide" will, well, do what the name suggests when an NPC crosses it. (The NPC in question has to have the AI though - so it won't apply to your playmate there.)

Most Additional Parameters work at this point too. You can (possibly, not tested), use "ext_scale;2.0" on a scriptevent brush, and watch NPC's grow as they cross them.

If the scriptevent is prefixed with gm_ - the event is called on the special Game Master npc, instead of the entity that touched it, which is useful for global events.

Additional parameters can be passed through the script event by adding semi-colons (eg. "ext_darkenbloom;6" - nerfs the bloom six levels for the player that touched it -
"ext_weather_force_change;fog_red" would set red fog for said player). If it's a gm_ event, the first parameter will always be the ent_id of the entity that touched the brush, and additional semi-colon parsed parameters show up as the second, third, etc. (eg. "gm_crys_key_activate;1" - on Nasharlwhatizt, tells the game that the player picked up the first crystal.)... This can be tied to buttons as well, such as the buttons that spawn the soccer ball teams on ms_soccer, and alerts the players as to who added or removed the team. (ie. "gm_soccer_blue_toggle")

It's more or less impossible to make an exhaustive list of all the events that can be triggered - as there are thousands of events in the scripts. In the test_scripts system, you can add custom ones, by editing test_scripts/game_master.script, test_scripts/npc_externals.script, or test_scripts/player_externals.script, accordingly, and they can be used to do nearly anything.

MS:C community said:
and setting "zhlt_invisible" = "0", that is.
Wups... Will fix... It is the only msarea that should render, I believe...

PS. If you're curious about your playmate's code:
Code:
#include monsters/base_flyer_grav
#include monsters/externals

{ game_spawn
	name a|Killer Map Brush
	race hated
	hp 1000
	hearingsensitivity 11
	setvard NPCATK_TARGET unset
	menu.autoopen 1
	setvard SUSPEND_AI 1
	gravity 0
	setvard CYCLE_RATE 1.0
	callevent 1.0 npcatk_hunt
}

{ game_heardsound
	local HEARD_ID $get(ent_lastheard,id)
	if $get(ent_me,relationship,HEARD_ID) equals enemy
	setvard NPCATK_TARGET HEARD_ID
}

{ game_damaged
	if $get(PARAM1,relationship,ent_me) equals enemy
	setvard NPCATK_TARGET HEARD_ID
	effect glow ent_me (255,0,0) 64 30 30 //no work
}

{ game_death
	playsound 0 10 voices/human/male_die.wav
	deleteent ent_me fade
}

{ npcatk_hunt
	callevent CYCLE_RATE npcatk_hunt
	if !SUSPEND_AI
	dbg Hunting $get(NPCATK_TARGET,name) [ $get(NPCATK_TARGET,range) ]

	playsound 2 10 magic/energy1.wav

	if ( !$get(NPCATK_TARGET,isalive) ) setvard NPCATK_TARGET unset
	if NPCATK_TARGET isnot unset
	setmovedest NPCATK_TARGET 32
	if ( $cansee(NPCATK_TARGET) ) addvelocity ent_me $relvel(0,50,0)

	if ( $get(NPCATK_TARGET,range) < 64 ) dodamage NPCATK_TARGET 64 5 50 slash
}

//this works, btw
//{ game_playerused
//	setprop ent_me rendermode 5
//	setprop ent_me renderamt 255
//}

{ npcatk_resume_ai
	setvard CYCLE_RATE 0.1
	setvard NPCATK_TARGET PARAM1
	setvard SUSPEND_AI 0
}

{ npcatk_suspend_ai
	setvard CYCLE_RATE 1.0
	setvard SUSPEND_AI 1
}

{ menu_hunt
	callevent npcatk_resume_ai $get(PARAM1,id)
}

{ menu_stop
	callevent npcatk_suspend_ai
}

{ menu_glow
	clientevent new all effects/sfx_follow_glow_cl $get(ent_me,index) (255,255,0) 128 30.0
}

{ game_menu_getoptions
	if ( SUSPEND_AI )
	{
		local reg.mitem.title "Hunt"
		local reg.mitem.type callback
		local reg.mitem.callback menu_hunt
		menuitem.register
	}
	else
	{
		local reg.mitem.title "Stop"
		local reg.mitem.type callback
		local reg.mitem.callback menu_stop
		menuitem.register
	}

	local reg.mitem.title "Glow"
	local reg.mitem.type callback
	local reg.mitem.callback menu_glow
	menuitem.register


	local reg.mitem.title "Additive"
	local reg.mitem.type callback
	local reg.mitem.callback menu_additive
	menuitem.register

	local reg.mitem.title "Spin"
	local reg.mitem.type callback
	local reg.mitem.callback menu_spin
	menuitem.register


//	local reg.mitem.title "Fly Baby! Fly!"
//	local reg.mitem.type callback
//	local reg.mitem.callback menu_fly
//	menuitem.register
}

{ menu_fly
	//fly 1 //CRASHES
	gravity 0
	saytextrange 1024
	saytext Weeee!
}

{ menu_additive
	setprop ent_me rendermode 5
	setprop ent_me renderamt 255
}

{ menu_spin
	setprop ent_me avelocity $vec(50,50,0)
	callevent 0.1 menu_spin
}
Might be useful for creating your own, more functional scripted brush.

The "Boom Block" in the video I put up earlier, requires a developer command to activate (". eventall do_boom ME")
other/boom_block
Code:
{
	const EFFECT_DIST 1024
}

{ game_spawn
	invincible 1
	race beloved
	setvard PLAYING_DEAD 1
	setsolid none
	nopush 1
	callevent 0.1 get_home_loc
}

{ get_home_loc
	setvard NPC_HOME_LOC $get(ent_me,origin)
}

{ do_boom //<ent>
	local BOOM_SOURCE PARAM1

	dbg do_boom $get(BOOM_SOURCE,range)
	if $get(BOOM_SOURCE,range) < EFFECT_DIST

	local DIST_RATIO $get(BOOM_SOURCE,range)
	divide DIST_RATIO EFFECT_DIST
	local BOOM_DELAY $ratio(DIST_RATIO,0.1,1.0)
	dbg do_boom BOOM_DELAY
	callevent BOOM_DELAY do_bob
}

{ do_bob
	addvelocity ent_me $relvel(0,0,200)
	//callevent 0.5 reset_block
}

{ reset_block
	setvelocity ent_me $vec(0,0,0)
	setorigin ent_me NPC_HOME_LOC
}

{ bury_block
	setsolid none
	local DOWN_SOME NPC_HOME_LOC
	vectoradd DOWN_SOME z -30
	setorigin ent_me DOWN_SOME 
}
The idea behind that one was to have a big chained warping of the floor when our new dragon friend stomped or died, but as the commentary in the video suggests, it turned out to be too resource intensive to pull off.
 

MS:C community

Old Skool Apostle
Alpha Tester
Joined
Jul 7, 2011
Messages
504
Reaction score
109
I was toying around with the boom block a bit and ". eventall do_boom ME" didn't work... ". eventall do_boom" did work though, but all blocks went up in the air at the same time.

Using "ext_scale;2.0" on a monster-only trigger_multiple works (very impressive) but the skeleton I had as test subject got stuck in the floor at first and then miraculously got out when I wasn't paying attention o_O
 

Thothie

Administrator
Staff member
Administrator
Moderator
MSC Archivist
Joined
Apr 8, 2005
Messages
16,342
Reaction score
326
Location
lost
Yeah, I thought it might have "issues". ;) It might actually be possible to make a smoother working variant, if you really wanted to use such a thing - maybe make them slowly grow after crossing as well.

MS:C community said:
I was toying around with the boom block a bit and ". eventall do_boom ME" didn't work... ". eventall do_boom" did work though, but all blocks went up in the air at the same time.
That's... Odd... Maybe sans quotes (or as a bind and with them)? Without the ME (uses the player as a parameter), it doesn't know where the center of the effect is, so yeah, they'll all just go up at the same time, if at all.

Obviously, to be of any use, an entity would have to "callexternal all do_boom $get(ent_me,id)" scriptisde, or some similar such, although variants that moved based on touch or sound from nearby ents would be possible.
 

MS:C community

Old Skool Apostle
Alpha Tester
Joined
Jul 7, 2011
Messages
504
Reaction score
109
D'oh, I forgot to add ORIGIN brushes to all my boom blocks. No wonder they couldn't determine where I was...
INoGT8z.jpg

I also managed to make a monster immune to lightning and change its race with monster-only trigger_multiple entities -- awesome! And there's so many things I haven't even tried yet :oldshock:
 

Thothie

Administrator
Staff member
Administrator
Moderator
MSC Archivist
Joined
Apr 8, 2005
Messages
16,342
Reaction score
326
Location
lost
Have a blast:
monsters/externals
Code:
//Called against montsters exernally or via ms_npcscript

{
	setvard SCARABS_ATTACHED 0
	const NPC_FADE_IN_SPEED 0.1
	const EXT_DEMON_BLOOD_RATIO 5.0
}

{ effect_damage

	//this is not used by very many scripts anymore, hoping to remove entirely
	//now instead we send damage to targets via player/monsters external send_damage (player_main on player)

	//Effect Damage	PARAM1=Dmg PARAM2=Attacker PARAM3=Duration PARAM4=Type
	//- Called from external damaging effects in hopes of reducing crash / making XP pass proper

	////dbg Effect_damage Delay EFFECT_DAMAGE_DELAY Dmg PARAM1 Src PARAM2 Durat PARAM3 Type PARAM4

	if !EFFECT_DAMAGE_DELAY
	setvard EFFECT_DAMAGE_DELAY 1
	callevent 0.9 reset_effect_damage
	//dbg standard_effect_damage
	dodamage ent_me direct PARAM1 100% PARAM2 PARAM4 PARAM5 PARAM6 PARAM7 PARAM9
}


//FEB2009_19 - defunct - use xdodamage instead
//{ effect_skilldamage
//
//	if !EFFECT_DAMAGE_DELAY
//	setvard EFFECT_DAMAGE_DELAY 1
//	callevent 0.9 reset_effect_damage
//
//	//dbg effect_skilldamage: doskilldamage PARAM1 ent_me direct PARAM2 100% PARAM3 PARAM4
//	doskilldamage PARAM1 ent_me direct PARAM2 100% PARAM3 PARAM4
//}

{ reset_effect_damage

	setvard EFFECT_DAMAGE_DELAY 0
}

//Race changes, to be called from ms_npcscript
{ orc_race

	//dbg Got PARAM1
	race orc
}
{ demon_race

	//dbg Got PARAM1
	race demon
}
{ undead_race

	//dbg Got PARAM1
	race undead
}
{ human_race

	//dbg Got PARAM1
	race human
}
{ spider_race

	//dbg Got PARAM1
	race spider
}
{ wildanimal_race

	//dbg Got PARAM1
	race wildanimal
}
{ hated_race

	//dbg Got PARAM1
	race hated
}
{ beloved_race

	//dbg Got PARAM1
	race beloved
}
{ evil_race

	//dbg Got PARAM1
	race evil
}
{ good_race

	//dbg Got PARAM1
	race good
}
{ vermin_race

	race vermin
}
{ rogue_race

	race rogue
}
{ hguard_race

	race hguard
}


//Immune changes, to be used from ms_npcscript, item, or spell
{ lightning_immune

	takedmg lightning 0.0
	setvard IMMUNE_LIGHTNING 1
}
{ fire_immune

	takedmg fire 0.0
	setvard IMMUNE_FIRE 1
}
{ poison_immune

	takedmg poison 0.0
	setvard IMMUNE_POISON 1
}
{ cold_immune

	takedmg cold 0.0
	takedmg ice 0.0
	setvard IMMUNE_COLD 1
}
{ normal_immune

	setvard IMMUNE_COLD 0
	setvard IMMUNE_FIRE 0
	setvard IMMUNE_LIGHTNING 0
	setvard IMMUNE_POISON 0
	takedmg cold 1.0
	takedmg fire 1.0
	takedmg lightning 1.0
	takedmg poison 1.0
	takedmg ice 1.0
}


//Armor Changes (to be used by ms_npcscript)
{ fifty_armor
	takedmg all 0.5
}
{ eighty_armor
	takedmg all 0.2
}
{ no_armor
	takedmg all 1.0
}
{ weakened_armor
	takedmg all 2.0
}

//Invincible Toggle (to be used by ms_npcscript)
{ make_invulnerable
   	setvard MY_OLD_NAME $get(ent_me,name)
	local MY_NEW_NAME "Invincible "
  	stradd MY_NEW_NAME MY_OLD_NAME
	name MY_NEW_NAME
	effect glow ent_me (255,255,255) 64 -1 0
	setvard NPC_GLOW (255,255,255)
	invincible 1
}
{ make_vulnerable
	if ( MY_OLD_NAME isnot 'MY_OLD_NAME' ) name MY_OLD_NAME
	invincible 0
	effect glow ent_me (255,255,255) 128 1 1
	setvard NPC_GLOW 'NPC_GLOW'
}

//Add HP (to be used by ms_npcscript)
{ add_10_health 

	local CURRENT_HP $get(ent_me,hp)
	add CURRENT_HP 10
	hp CURRENT_HP
}
{ add_100_health 

	local CURRENT_HP $get(ent_me,hp)
	add CURRENT_HP 100
	hp CURRENT_HP
}
{ add_500_health 

	local CURRENT_HP $get(ent_me,hp)
	add CURRENT_HP 500
	hp CURRENT_HP
}
{ add_1000_health 

	local CURRENT_HP $get(ent_me,hp)
	add CURRENT_HP 1000
	hp CURRENT_HP
}

{ double_health 
   	local MY_OLDHP_NAME $get(ent_me,name)
	local MY_NEWHP_NAME "Strong "
  	stradd MY_NEWHP_NAME MY_OLDHP_NAME
	name MY_NEWHP_NAME

	local CURRENT_HP $get(ent_me,hp)
	multiply CURRENT_HP 2.0
	hp CURRENT_HP
}

{ quad_health 
   	local MY_OLDHP_NAME $get(ent_me,name)
	local MY_NEWHP_NAME "Very Strong "
  	stradd MY_NEWHP_NAME MY_OLDHP_NAME
	name MY_NEWHP_NAME

	local CURRENT_HP $get(ent_me,hp)
	multiply CURRENT_HP 4.0
	hp CURRENT_HP
}

{ half_health 
   	local MY_OLDHP_NAME $get(ent_me,name)
	local MY_NEWHP_NAME "Weakened "
  	stradd MY_NEWHP_NAME MY_OLDHP_NAME
	name MY_NEWHP_NAME

	divide NPC_GIVE_EXP 2 //Thothie FEB2009 - reduce XP value for nerfed monster
	skilllevel NPC_GIVE_EXP

	local CURRENT_HP $get(ent_me,hp)
	multiply CURRENT_HP 0.5
	hp CURRENT_HP
}

{ ice_shield_on
	//dbg Ice Shield Applied
	setvard ICE_SHIELDED 1
}

{ ice_shield_off
	//dbg Ice Shield Removed
	setvard ICE_SHIELDED 0
}

{ ice_shield_check

	if ( ICE_SHIELDED ) setvarg ICE_SHIELD_CHECK 1
	if ( !ICE_SHIELDED ) setvarg ICE_SHIELD_CHECK 0
	//dbg Ice Shield is now ( ICE_SHIELD_CHECK ) ( Was ICE_SHIELDED )
}

{ npc_fade_away

	//not always monster spawn friendly
	setalive 0
	deleteent ent_me fade
}

{ go_roam
	roam 1
}

{ no_roam
	roam 0
}

{ set_stun_prot

	setvard IMMUNE_STUN PARAM1
}

{ npc_suicide

	if $get(ent_me,isalive)

	if !I_R_COMPANION //never, ever, slay companions (if you need to, make new external)

	local SINCE_SPAWN game.time
	subtract SINCE_SPAWN NPC_SPAWN_TIME

	//if ( NPC_QUED_FOR_DEATH ) local PARAM1 dienow

	if ( SINCE_SPAWN < 2.0 )
	{
		if ( PARAM1	equals dienow )
		{
			setanim.framerate 0
			setanim.movespeed 0
			setvard NPC_OVERRIDE_DEATH 1
			deleteent ent_me fade
			local EXIT_SUB 1
		}
		else
		{
			setvard NPC_QUED_FOR_DEATH 1
			callevent 2.1 npc_suicide
			dbg npc_suicide - not_ready_to_die - qued for death
			local EXIT_SUB 1
		}
	}
	if !EXIT_SUB

	if ( PARAM1 equals no_pets )
	{
		if I_R_PET
		local EXIT_SUB 1
	}

	if ( PARAM1 equals only_bad )
	{
		if ( $get(ent_me,race) equals human ) local EXIT_SUB 1
		if ( $get(ent_me,race) equals hguard ) local EXIT_SUB 1
		if ( $get(ent_me,race) equals beloved ) local EXIT_SUB 1
	}
	if !EXIT_SUB

	invincible 0
	race hated
	setvard SKEL_RESPAWN_TIMES 99
	dodamage ent_me direct 99999 100 GAME_MASTER target
}

//Older convention
{ freeze_solid //PARAM1=Duration PARAM2= ATKER ID PARAM3=Dmg (optional)

	//note this is called normally by effects/freeze_solid
	//if that effect does damage, it is handled on that effect's side
	//it might be useful to make frozen state a universal flag and handle it code side
	//as this methodology has issues
	//meanwhile, use I_R_FROZEN to determine if a monster is in a frozen state or not
	//and thus disallow pushing himself via addvelocity or other types of movement
	//(seetting nopush to 1 has no affect on a monsters ability to push itself)

	if !IN_ICECAGE

	if game.monster.hp > 0
	if game.monster.alive

	//SEP2009 - resistance to freezing sphere for monsters, since they don't use the apply effect, for some reason that I've forgotten
	local MY_RESIST $get_takedmg(ent_me,cold)
	dbg freeze_solid MY_RESIST
	if ( MY_RESIST == 0 )
	{
		playermessage PARAM2 $get(ent_me,name) is immune to ice magic!
		local EXIT_SUB 1
	}
	if ( MY_RESIST > 0 )
	{
		local RESIST_ROLL $randf(0.0,0.99)
		if RESIST_ROLL > MY_RESIST
		local RESIST_PERC MY_RESIST
		multiply RESIST_PERC 100
		local RESIST_PERC_REPORT 100
		subtract RESIST_PERC_REPORT RESIST_PERC
		local RESIST_PERC_REPORT $int(RESIST_PERC_REPORT)
		stradd RESIST_PERC_REPORT '%%'
		playermessage PARAM2 $get(ent_me,name) resists the ice magic ( RESIST_PERC_REPORT )
		local EXIT_SUB 1
	}
	if !EXIT_SUB

	setvard OLD_FRAMERATE $get(ent_me,framerate)
	setvard OLD_MOVESPEED  $get(ent_me,movespeed)
	//dbg temp framerate game.monster.framerate setframe setanim.framerate ( OLD_FRAMERATE )

	setanim.framerate 0.0001
	setanim.movespeed 0
	setvard CANT_TURN 1

	setvard I_R_FROZEN 1

	if ( FX_SPAMMERS < MAX_FX_SPAMMERS )
	{
		//createnpc effects/sfx_icecage (0,0,-48) $get(ent_me,id) PARAM1
		//setvard SCRIPT_ICECAGE $get(ent_lastcreated,id)
		clientevent new all effects/sfx_icecage $get(ent_me,index) PARAM1
		setvard SCRIPT_ICECAGE game.script.last_sent_id
	}

	if ( PARAM3 )
	{
		applyeffect ent_me effect/effect_frostbite_dmg PARAM1 PARAM2 PARAM3
	}

	setvard IN_ICECAGE 1
	callevent PARAM1 unfreeze_solid
}

{ unfreeze_solid

	if IN_ICECAGE
	setvard CANT_TURN 0
	setvard I_R_FROZEN 0
	setvard SCRIPT_ICECAGE 'SCRIPT_ICECAGE'
	//playsound 0 5 debris/bustglass2.wav
	//if ( FX_SPAMMERS < MAX_FX_SPAMMERS ) effect tempent gibs glassgibs.mdl $relpos(0,0,0) 1.0 30 10 10 1.0
	setvard IN_ICECAGE 0
	if ( BASE_FRAMERATE equals 'BASE_FRAMERATE' ) local BASE_FRAMERATE OLD_FRAMERATE
	if ( BASE_MOVESPEED equals 'BASE_MOVESPEED' ) local BASE_MOVESPEED OLD_MOVESPEED
	setanim.framerate BASE_FRAMERATE
	setanim.movespeed BASE_MOVESPEED
}

//newer
{ freeze_solid_start //PARAM1 = duration to freeze
	//this is to tell monsters that change their move/anim speeds not to do so while frozen

	local ICE_CAGE_DURATION PARAM1

	setvard ICE_CAGE_OLD_CANT_TURN CANT_TURN
	setvard ICE_CAGE_OLD_STUCK_CHECK NO_STUCK_CHECKS
	setvard ICE_CAGE_OLD_ROAM $get(ent_me,roam)
	dbg freeze_solid_start roamstate ICE_CAGE_OLD_ROAM
	
	if ( !SUSPEND_AI ) callevent npcatk_suspend_ai ICE_CAGE_DURATION

	setvard I_R_FROZEN 1
	setvard IN_ICECAGE 1
	setvard CANT_TURN 1
	setvard NO_STUCK_CHECKS 1
	roam 0

	setanim.framerate 0.0001
	//setanim.movespeed 0

	callevent ICE_CAGE_DURATION freeze_solid_end
}

{ freeze_solid_end
	//dbg thaw
	setvard I_R_FROZEN 0
	setvard IN_ICECAGE 0
	setvard CANT_TURN ICE_CAGE_OLD_CANT_TURN
	setvard NO_STUCK_CHECKS ICE_CAGE_OLD_STUCK_CHECK
	roam ICE_CAGE_OLD_ROAM
	setanim.framerate BASE_FRAMERATE
	//setanim.movespeed BASE_MOVESPEED
	if ( CAN_HUNT ) playanim once ANIM_RUN
}

{ tally_race //PARAM1 = race to check (set all these G_'s 0 before calling)

	if ( game.monster.race equals orc ) add G_ORC_TALLY 1
	if ( game.monster.race equals rogue ) add G_ROGUE_TALLY 1
	if ( game.monster.race equals demon ) add G_DEMON_TALLY 1
	if ( game.monster.race equals undead ) add G_UNDEAD_TALLY 1
	if ( game.monster.race equals spider ) add G_SPIDER_TALLY 1
	if ( game.monster.race equals human ) add G_HUMAN_TALLY 1
	if ( game.monster.race equals hguard ) add G_HGUARD_TALLY 1
}

{ tally_enemy //PARAM1 = npc to check (setvarg G_ENEMY_TALLY 0 before calling)

	if $get(ent_me,relationship,PARAM1) equals enemy
	add G_ENEMY_TALLY 1
}


{ [server] send_damage //same params as do damage

	//temporary debug
//	if ( !$get(PARAM1,isalive) )
//	{
//		local OUT_PAR1 PARAM1
//		callevent debug_beam OUT_PAR1 PARAM2 (255,0,0)
//	}
	
	//if !SEND_DMG_DELAY
	//setvard SEND_DMG_DELAY 1
	//callevent 0.2 reset_send_dmg_delay
	////dbg send_damage PARAM1 PARAM2 PARAM3 PARAM4 PARAM5 PARAM6 PARAM7
	dodamage PARAM1 PARAM2 PARAM3 PARAM4 PARAM5 PARAM6 PARAM7
}

{ demon_blood //PARAM1 = effecitve SC level, or set via DEMON_LEVEL if delay needed

	playsound 0 10 monsters/troll/trollidle2.wav //precache?

	setvard MAKE_NOISE 2
	setvard DEMON_BLOOD 1

	if ( NPC_ADJ_FLAGS equals 'NPC_ADJ_FLAGS' ) setvard NPC_ADJ_FLAGS ''
	token.add NPC_ADJ_FLAGS demon_blood

	callevent 1.0 demon_blood_loop
}

{ demon_blood_loop

	if DEMON_BLOOD

	if ( FX_SPAMMERS < MAX_FX_SPAMMERS ) effect glow ent_me (255,0,0) 256 1.9 1.9

	if game.monster.hp > 11

	callevent 2.0 demon_blood_loop

	add MAKE_NOISE 1	
	if ( MAKE_NOISE > 5 )
	{
		playrandomsound 0 10 monsters/troll/trollidle2.wav monsters/troll/trollidle.wav
		setvard MAKE_NOISE 0
	}

	if ( !DEMON_NOHP_LOSS ) givehp DEMON_BLOOD_LOSS
    effect screenshake $relpos(0,0,0) 32 10 1 32
	if ( MAKE_NOISE > 0 ) playsound 0 10 player/heartbeat_noloop.wav
	setvard DEMON_BLOOD 1
}

{ game_damaged_other //PARAM1=target_hit PARAM2=dmg

	if DEMON_BLOOD
	if $get(PARAM1,relationship,ent_me) equals enemy

	returndata EXT_DEMON_BLOOD_RATIO

	//applyeffect ent_laststruck effects/generic_damage DEMON_LEVEL $get(ent_me,id) 1 magic
	//setdmg does not work here
	//local IN_DMG PARAM2
	//add IN_DMG DEMON_LEVEL
	//setdmg dmg IN_DMG
	//dbg game_damaged_other DEMON_LEVEL
	playrandomsound 0 10 monsters/troll/trollpain.wav monsters/troll/trollattack.wav
}

{ ext_hit_manaball
	//stop rapid damage stack from player manaballs

	if !HIT_BY_MANABALL
	setvard HIT_BY_MANABALL 1
	callevent 1.0 reset_hit_by_manaball
}

{ reset_hit_by_manaball
	setvard HIT_BY_MANABALL 0
}

{ ext_playsound_kiss
	playsound PARAM1 PARAM2 PARAM3
}

{ ext_svplaysound_kiss
	dbg ext_svplaysound_kiss PARAM1 PARAM2 PARAM3 PARAM4 PARAM5
	svplaysound PARAM1 PARAM2 PARAM3 PARAM4 PARAM5
}

{ ext_mon_playsound //<WAV> <(source)> [MaxRange] //sound must be precached

	if ( PARAM3 isnot 'PARAM3' )
	{
		local SOURCE_ORG PARAM2
		//dbg temp $dist(game.monster.origin,SOURCE_ORG) 
		if $dist(game.monster.origin,SOURCE_ORG) > PARAM3
		local EXIT_SUB 1
	}
	if !EXIT_SUB

	setvard EXTPLAY_SOUND PARAM1
	callevent 0.1 ext_playsound2 //delay 0.1 seconds to stop flood
}

{ turn_undead //PARAM1=Dmg PARAM2=Exorcist

	//if !AM_SKELETON //base_skeleton users handle this different, should migrate

	if game.monster.isalive

	if !CUSTOM_TURN_UNDEAD

	//dbg temp got rebuke PARAM1 PARAM2

	if IMMUNE_HOLY != 1

	local EXT_INC_HOLY_DMG PARAM1
	local EXT_THE_EXCORCIST PARAM2

	effect glow ent_me (255,255,0) 512 1 1

	setvard STRUCK_BY_HOLY 1
	setvard SKELE_TURNED 1
	setvard STRUCK_HOLY 1

	//callexternal EXT_THE_EXCORCIST send_damage $get(ent_me,id) direct EXT_INC_HOLY_DMG 100 EXT_THE_EXCORCIST holy

	xdodamage $get(ent_me,id) direct EXT_INC_HOLY_DMG 100 EXT_THE_EXCORCIST EXT_THE_EXCORCIST spellcasting.divination holy

	//something about the external damage on this fubars things sometimes (causes death anim to lock)
	//fade monsters killed by this as work around:
	if ( EXT_INC_HOLY_DMG > game.monster.hp ) setvard EXT_FADE_ON_DEATH 1

	if I_AM_TURNABLE

	//determined turned

	multiply TURN_STRENGTH 7

	If ( TURN_STRENGTH > 1000 ) local TURN_STRENGTH 1000 	//cap at 1000 (no turning bosses)
	
	if !IS_FLEEING			//can't turn already turned

	if TURN_STRENGTH > MY_CURRENT_HP

	local TURN_RESISTANCE MY_MAX_HP
	divide TURN_RESISTANCE 25
	local TURN_RESISTANCE $int(TURN_RESISTANCE)

	if ( TURN_RESISTANCE < 2 ) local TURN_RESISTANCE 2

	local TURNCHANCE $rand(1,TURN_RESISTANCE)

	//dbg MyTurnResistance TURN_RESISTANCE mymaxhp MY_MAX_HP Rolled TURNCHANCE
	if TURNCHANCE == 1

	//Minimum Turn Duration 5 seconds, max 20
	local TURN_DURATION $get(THE_EXCORCIST,skill.spellcasting.divination)
	if ( TURN_DURATION < 5 ) local TURN_DURATION 5
	if ( TURN_DURATION > 15 ) local TURN_DURATION 15

	//Thothie - RUN AWAY!
	setvard FLEE_DISTANCE 2048

	volume 10
	playrandomsound 2 SOUND_TURNED1 SOUND_TURNED2 SOUND_TURNED3 SOUND_TURNED4

	setvard CAN_FLEE 1
	callevent npcatk_flee THE_EXCORCIST FLEE_DISTANCE TURN_DURATION
}

{ [server] bd_debug  //<print_var> <property_printvar> <extra> <extra> <caller_id>
	//tdebug/tdebugt
	saytextrange 2048
	saytext var PARAM1 prop PARAM2 = $get(PARAM1,PARAM2)
	consolemsg PARAM5 $get(ent_me,name) reports: var PARAM1 pvar $get(PARAM1,PARAM2)
	dbg PARAM5 $get(ent_me,name) reports: var PARAM1 pvar $get(PARAM1,PARAM2)
}

{ [server] ext_speak //<"text">
	saytextrange 2048
	saytext PARAM1
}

{ [server] give_hp //PARAM1 = amont to give, can be negative
	givehp PARAM1
}

//{ [server] ext_return_relpos //used to return position relative to others
//	local MY_ORG game.monster.origin
//	vectoradd MY_ORG $relpos(PARAM1,PARAM2)
//	setvarg G_RELPOS MY_ORG
//}

{ [server] ext_invalidate //<PARAM1> 1|0 - marks target as invalid
	setvard PLAYING_DEAD PARAM1	
}

{ [server] ext_dodamage //same params as do damage

	dodamage PARAM1 PARAM2 PARAM3 PARAM4 PARAM5 PARAM6 PARAM7
}

{ [server] ext_set_freeze_amt
	//this is used to determine the current amount of freeze magic on the target
	setvard EFFECT_FREEZE_AMT PARAM1
}

{ ext_flash_bang //PARAM1 = origin PARAM2 = radius PARAM3 = source_owner
	if $dist(game.monster.origin,PARAM1) < PARAM2
	callevent npcatk_flee $get(PARAM3,id) 1024 5.0
}

{ speed_x2

	//increase move and atk speeds
	movespeed 1.5
	setanim.movespeed 1.5
	setanim.framerate 1.5
	setvard BASE_MOVESPEED 1.5
	setvard BASE_FRAMERATE 1.5
	if ( NPC_ADJ_FLAGS equals 'NPC_ADJ_FLAGS' ) setvard NPC_ADJ_FLAGS ''
	token.add NPC_ADJ_FLAGS speed_x2
}

{ speed_x2_5

	//increase move and atk speeds
	movespeed 1.75
	setanim.movespeed 1.75
	setanim.framerate 1.75
	setvard BASE_MOVESPEED 1.75
	setvard BASE_FRAMERATE 1.75
	if ( NPC_ADJ_FLAGS equals 'NPC_ADJ_FLAGS' ) setvard NPC_ADJ_FLAGS ''
	token.add NPC_ADJ_FLAGS speed_x2
}

{ speed_x3

	//increase move and atk speeds
	movespeed 2.0
	setanim.movespeed 2.0
	setanim.framerate 2.0
	setvard BASE_MOVESPEED 2.0
	setvard BASE_FRAMERATE 2.0
	if ( NPC_ADJ_FLAGS equals 'NPC_ADJ_FLAGS' ) setvard NPC_ADJ_FLAGS ''
	token.add NPC_ADJ_FLAGS speed_x3
}

{ speed_x4

	//increase move and atk speeds
	movespeed 3.0
	setanim.movespeed 3.0
	setanim.framerate 3.0
	setvard BASE_MOVESPEED 3.0
	setvard BASE_FRAMERATE 3.0

	if ( NPC_ADJ_FLAGS equals 'NPC_ADJ_FLAGS' ) setvard NPC_ADJ_FLAGS ''
	token.add NPC_ADJ_FLAGS speed_x4
}

{ critical_npc

	//for siege mode maps
	invincible 0
	setvard NPC_CRITICAL 1
	token.add G_CRITICAL_NPCS $get(ent_me,id)
	setvarg G_SIEGE_MAP 1
	local FIRST_TOKEN $get_token(G_CRITICAL_NPCS,0)
	if ( !$get(FIRST_TOKEN,isalive) ) token.del G_CRITICAL_NPCS 0 //fix buggy token creation
}

//prevents DOT effects from stacking into crash (see effects/effect_base)
{ ext_set_effect_lastdmg
	setvard EXT_LAST_EFFECT_DMG game.time
}

//No longer required, but still called, in case you want script to do something about it
{ ext_monsterspawn_removed
	if $get(ent_me,spawner) equals PARAM1
	local L_MAP_NAME $lcase(game.map.name)
	if ( L_MAP_NAME contains helena ) callevent npc_suicide dienow
	//if ( L_MAP_NAME equals walltest ) callevent npc_suicide dienow
	if ( L_MAP_NAME equals aleyesu ) callevent npc_suicide dienow
	if ( L_MAP_NAME equals b_castle ) callevent npc_suicide dienow
	if ( L_MAP_NAME equals bloodrose ) callevent npc_suicide dienow
	if ( L_MAP_NAME equals calruin2 ) callevent npc_suicide dienow
	if ( L_MAP_NAME equals cleicert ) callevent npc_suicide dienow
	if ( L_MAP_NAME equals bloodrose ) callevent npc_suicide dienow
	if ( L_MAP_NAME equals demontemple ) callevent npc_suicide dienow
	if ( L_MAP_NAME equals foutpost ) callevent npc_suicide dienow
	if ( L_MAP_NAME equals gatecity ) callevent npc_suicide dienow
	if ( L_MAP_NAME contains gertenheld ) callevent npc_suicide dienow
	if ( L_MAP_NAME equals keledrosruins ) callevent npc_suicide dienow
	if ( L_MAP_NAME equals kfortress ) callevent npc_suicide dienow
	if ( L_MAP_NAME contains lodagond ) callevent npc_suicide dienow
	if ( L_MAP_NAME equals ms_wicardoven ) callevent npc_suicide dienow
	if ( L_MAP_NAME equals mscave ) callevent npc_suicide dienow
	if ( L_MAP_NAME equals shad_palace ) callevent npc_suicide dienow
	if ( L_MAP_NAME equals sorc_villa ) callevent npc_suicide dienow
	if ( L_MAP_NAME equals the_keep ) callevent npc_suicide dienow
	if ( L_MAP_NAME contains islesofdread ) callevent npc_suicide dienow
	if ( L_MAP_NAME equals the_wall ) callevent npc_suicide dienow
	if ( L_MAP_NAME equals umulak ) callevent npc_suicide dienow
	if ( L_MAP_NAME equals ww1 ) callevent npc_suicide dienow
	if ( L_MAP_NAME equals ww2b ) callevent npc_suicide dienow
	if ( L_MAP_NAME equals ww3d ) callevent npc_suicide dienow

	if ( NPC_DIE_ON_SPAWN_REMOVAL ) callevent npc_suicide dienow
	
	callevent npc_monsterspawn_removed
	//deleteent ent_me fade
	//callevent npc_suicide override
}

{ glow_red
	setvard NPC_GLOW (255,0,0)
}

{ glow_green
	setvard NPC_GLOW (0,255,0)
}

{ glow_blue
	setvard NPC_GLOW (0,0,255)
}

{ glow_yellow
	setvard NPC_GLOW (255,255,0)
}

{ glow_purple
	setvard NPC_GLOW (255,0,255)
}

{ glow_custom
	setvard NPC_GLOW PARAM1
}

{ glow_remove
	setvard NPC_GLOW 'NPC_GLOW'
}

{ remove_ghost
	setvard NPC_GHOST 0
}

{ make_ghost
	setvard NPC_GHOST 1
}

{ npc_post_spawn

	if ( NPC_GHOST )
	{
		setprop ent_me rendermode 5
		setprop ent_me renderamt 255
		callevent 10.1 npcatk_reset_ghost
	}


	if ( NPC_GLOW isnot 'NPC_GLOW' )
	{
		effect glow ent_me NPC_GLOW 64 20 0	
		callevent 20.1 npcatk_reset_glow
	}
}

//These render effects are reset priodically as some effects can remove or conflict with them
{ npcatk_reset_glow

	if NPC_GLOW isnot 'NPC_GLOW'
	effect glow ent_me NPC_GLOW 64 20 0	
	callevent 20.1 npcatk_reset_glow
}

{ npcatk_reset_ghost
	
	if NPC_GHOST
	setprop ent_me rendermode 5
	setprop ent_me renderamt 255
	callevent 10.1 npcatk_reset_ghost
}

{ set_race
	race PARAM1
}

{ set_model
	setmodel PARAM1
	setsolid box
	setbbox npcsize
}

{ ext_report_armor
	consolemsg PARAM2 $get(ent_me,name) Armor: MSC_ARMOR_ALL PARAM1 : $get_takedmg(ent_me,PARAM1)
}

{ ext_set_parry //add param SEP2009_17 - set a monster's parry skill
	setstat parry PARAM1
}

{ ext_blind
	blind 1
}

{ ext_unblind
	blind 0
}

{ game_drain_death //PARAM1 = drainer
	//dbg DRAIN DEATH
	dodamage ent_me direct PARAM1 100 100% PARAM1 target
}

//{ ext_nopush
//
//	scriptflags ent_me add ext_nopush nopush PARAM1
//	//dbg nopush set to PARAM1
//}
//
//{ ext_nopush_on
//	scriptflags ent_me add ext_nopush nopush 1 PARAM2 none
//	//if ( PARAM2 > 0 ) callevent PARAM2 ext_nopush_off //seems this should be PARAM1 though
//}
//
//{ ext_nopush_off
//	nopush 0
//}

{ ext_wink_out
	//teleport off map, return to point PARAM1 in PARAM2 seconds
	setorigin ent_me (20000,10000,-20000)
	setvard NPC_WINK_IN_POINT PARAM1
	setvard NPC_WINKED_OUT 1
	callevent PARAM2 ext_wink_in
}

{ ext_wink_in
	//return from ext_wink_out
	setorigin ent_me NPC_WINK_IN_POINT
	setvard NPC_WINKED_OUT 0
}

{ ext_set_slowed
	setvard I_R_SLOWED PARAM1
}


{ make_boss
	setvard NPC_IS_BOSS 1
	setvard NPC_BOSS_KNOWS ''
	setvard NPC_BOSS_KNOWS_AMTS ''
}

{ ext_makepet
	setprop ent_me rendermode 5
	setprop ent_me renderamt 0
	setvard NPC_SILENT_DEATH 1
	callevent 0.01 npc_suicide
	createnpc NPC_PET_SCRIPT $relpos(0,0,0) $get(PARAM1,id) 1
}

{ ext_set_health
	hp PARAM1 PARAM2
}

//{ ext_return_relpos_vec //return an adjusted self-relative position SEP2009_17 - fixed, was useless old way as was using coord type $relpos()
//	setvard EXT_RELPOS $relpos(PARAM1,PARAM2,PARAM3)
//}

//Thothie FEB2009 - external addparam to flag monster not to hunt for critical NPCs
{ ignore_critical_npc
	setvard NPC_NO_SIEGE_HUNT 1
}

//Thothie FEB2009_18 - external for setting hit chance penalties
{ ext_hit_chance
	hitmulti ent_me PARAM1
}

//Thothie FEB2009_19 - allow frozen status from things other than freeze_solid
{ ext_set_frozen
	setvard I_R_FROZEN 1
//	setvard ORIG_NOPUSH $get(ent_me,nopush)
//	nopush 1
	scriptflags ent_me add ext_set_frozen nopush 1 PARAM1 none
	callevent PARAM1 ext_set_unfrozen
}

{ ext_set_unfrozen
	setvard I_R_FROZEN 0
	//nopush ORIG_NOPUSH
}

//Thothie APR2009 - allow unsommoning of all NPC's summons, globally
{ ext_unsummon
	if AM_SUMMONED
	setalive 0
	deleteent ent_me fade
}

{ ext_sphere_token_x //TYPE_SCAN SCAN_RANGE
	setvard PLR_SCAN_TOKEN $get_tsphere(PARAM1,PARAM2)
	//dbg ext_sphere_token_x PLR_SCAN_TOKEN
}

{ ext_sphere_token //TYPE_SCAN SCAN_RANGE SCAN_ORIGIN
	setvard PLR_SCAN_TOKEN $get_tsphere(PARAM1,PARAM2,PARAM3)
	//dbg ext_sphere_token PLR_SCAN_TOKEN
}

{ ext_box_token //TYPE_SCAN SCAN_RANGE SCAN_ORIGIN
	setvard PLR_SCAN_TOKEN $get_tbox(PARAM1,PARAM2,PARAM3)
	//dbg ext_box_token PLR_SCAN_TOKEN
}

{ ext_reduct_xp //add param for monster placements that are exploitable, etc
	if PARAM1 < 1
	setvard NPC_EXP_REDUCT PARAM1
	//callevent 1.5 ext_reduct_xp2 //delay to give chance for monsters to set base XP
}
//
//{ ext_reduct_xp2
//	if NPC_EXP_REDUCT < 1.0
//	multiply NPC_GIVE_EXP NPC_EXP_REDUCT
//	if ( DROP_GOLD ) multiply DROP_GOLD_AMT NPC_EXP_REDUCT
//	skilllevel NPC_GIVE_EXP
//	dbg ext_reduct_xp NPC_EXP_REDUCT NPC_GIVE_EXP
//}

{ ext_no_drops //add param to remove drops for exploitable monsters
	callevent 1.5 ext_no_drops2 //delay to give chance for monsters to set treasure
}

{ ext_no_drops2
	setvard NPC_NO_DROPS 1
	gold 0
	setvard DROP_GOLD 0
	setvard DROP_ITEM1_CHANCE 0%
	setvard DROP_ITEM2_CHANCE 0%
	setvard DROP_ITEM3_CHANCE 0%
	setvard DROP_ITEM4_CHANCE 0%
	setvard CONTAINER_DROP_CHANCE 0%
}

//Jelly's external scan+sort
{ ext_ent_list_sort //SCAN_TYPE SCAN_RANGE SCAN_ORIGIN SORT_TYPE:range|hp|maxhp|mp|maxmp
   local SCAN_TYPE PARAM1
   local SCAN_RANGE PARAM2
   local SCAN_ORIGIN PARAM3
   local SORT_TYPE PARAM4
   callevent ext_sphere_token SCAN_TYPE SCAN_RANGE SCAN_ORIGIN
   setvard PLR_SCAN_TOKEN_SORTED $sort_entlist(PLR_SCAN_TOKEN,SORT_TYPE)
}

//OCT2009 - Giving monsters resist hold over time too (also helps prevent stack crashes)
{ ext_set_last_resist
	setvard PLR_LAST_RESIST_TIME game.time
	setvard PLR_LAST_RESIST_ELM PARAM1
}

//DEC2009 - Option to make monster invulnerable to player damage (good for guards / crit NPCs)
{ ext_no_player_damage
	setvard NPC_NO_PLAYER_DMG 1
}

//Failed JAN2010 spariment
{ ext_setrender
	dbg got ext_setrender PARAM1
	setrender PARAM1
}

//JAN2010_29 spariment
{ ext_scale //<ratio>

	local MY_WIDTH $get(ent_me,width)
	local MY_HEIGHT $get(ent_me,height)
	setprop ent_me scale PARAM1
	multiply MY_WIDTH PARAM1
	multiply MY_HEIGHT PARAM1
	width MY_WIDTH
	height MY_WIDTH
	setvard MONSTER_WIDTH MY_WIDTH

	setbbox npcsize

	if PARAM1 > 1

	if ( BASE_MOVESPEED equals 'BASE_MOVESPEED' )
	{
		setvard BASE_MOVESPEED PARAM1
	}
	else
	{
		add BASE_MOVESPEED PARAM1
	}
	setanim.movespeed BASE_MOVESPEED
	movespeed BASE_MOVESPEED

	setvard NPC_SCALED PARAM1

	if ( !NPC_RANGED )
	{
		callevent 1.9 ext_adjust_scale_range
	}
}

{ set_scale
	callevent ext_scale PARAM1
}

{ ext_adjust_scale_range
	local RANGE_ADJ_RATIO NPC_SCALED
	if PARAM1 > 0
	multiply ATTACK_RANGE RANGE_ADJ_RATIO
	multiply ATTACK_HITRANGE RANGE_ADJ_RATIO
	//multiply MOVE_RANGE RANGE_ADJ_RATIO
	//multiply ATTACK_MOVERANGE RANGE_ADJ_RATIO
}

{ set_attack_until_spotted
	//simulates hacking on an object until spots or spotted by player
	setvard NPC_ATTACK_UNTIL_SPOTTED 1
}

{ npc_post_spawn
	if NPC_ATTACK_UNTIL_SPOTTED
	callevent npcatk_attack_till_spotted
}

{ npcatk_attack_till_spotted
	if NPCATK_TARGET equals unset
	callevent 0.25 npcatk_attack_till_spotted
	playanim once ANIM_ATTACK
	setvard AS_ATTACKING game.time
	add AS_ATTACKING 5.0
	local FACE_SPOT NPC_HOME_LOC
	local FACE_DIR $vec.yaw(NPC_HOME_ANG)
	vectoradd FACE_SPOT $relpos($vec(0,FACE_DIR,0),$vec(0,256,0))
	setvard NPC_FORCED_MOVEDEST 1
	setmovedest FACE_SPOT 9999
}

{ set_fade_in //thought I had this, guess not
	setvard NPC_RENDER_AMT 0
	setvard NPC_RENDER_MODE 2
	setprop ent_me renderamt NPC_RENDER_AMT
	setprop ent_me rendermode NPC_RENDER_MODE
	
	local L_FADE_DELAY PARAM1
	if ( L_FADE_DELAY == 0 ) local L_FADE_DELAY 0.1

	setvard NPC_FADEIN_RATE PARAM1
	if ( NPC_FADEIN_RATE < 10 ) setvard NPC_FADEIN_RATE 10
	callevent L_FADE_DELAY set_fade_in_loop
}

{ set_fade_in_loop
	add NPC_RENDER_AMT 10

	if ( NPC_RENDER_AMT < 255 )
	{
		setprop ent_me renderamt NPC_RENDER_AMT
		callevent NPC_FADE_IN_SPEED set_fade_in_loop
	}
	else
	{
		setprop ent_me renderamt 255
		setprop ent_me rendermode 0
		setvard NPC_RENDER_AMT 255
		setvard NPC_RENDER_MODE 0
		callevent npc_fadein_done
	}
}

//FEB2010_06 toggle step adj on individual monsters
{ set_no_step_adj
	setvard NO_STEP_ADJ 1
}

//FEB2010_06 global set turret function
{ set_npc_turret
	movespeed 0.0
	setvard BASE_MOVESPEED 0.0
	setmoveanim ANIM_IDLE
	roam 0
	setvard NO_STUCK_CHECKS 1
	setvard ANIM_RUN ANIM_IDLE
	setvard ANIM_WALK ANIM_IDLE
	setvard NPC_IS_TURRET 1
	callevent 0.1 set_npc_turret2
}

{ set_npc_turret2
	//enforcer - it's either the weirdness of xetvar or something getting reset somewhere
	setvard ANIM_RUN ANIM_IDLE
	setvard ANIM_WALK ANIM_IDLE
	setmoveanim ANIM_IDLE
}

{ set_summon_circle

	callevent set_fade_in 1.0
	if ( !NPC_HANDLES_SUMMON_CIRCLES ) setanim.framerate 0
	callevent 0.1 set_summon_circle2
}

{ set_summon_circle2
	if ( !NPC_HANDLES_SUMMON_CIRCLES )
	{
		callevent npcatk_suspend_ai
		setanim.framerate 0 //case variant in npc_spawn
	}
	local CIRCLE_ORG $get(ent_me,origin)
	vectorset CIRCLE_ORG z $get_ground_height(CIRCLE_ORG)
	if ( $get(ent_me,height) < 90 )
	{
		clientevent new all effects/sfx_summon_circle CIRCLE_ORG 3
	}
	else
	{
		clientevent new all effects/sfx_summon_circle CIRCLE_ORG 5
	}
	callevent 1.0 set_summon_circle3
}

{ set_summon_circle3
	setvard AS_ATTACKING game.time
	add AS_ATTACKING 5.0
	if !NPC_HANDLES_SUMMON_CIRCLES
	callevent npcatk_resume_ai
	if ( BASE_FRAMERATE equals 'BASE_FRAMERATE' )
	{
		setanim.framerate 1.0
	}
	else
	{
		setanim.framerate BASE_FRAMERATE
	}
}

{ set_takedmg_holy //add param
	takedmg holy PARAM1
}

{ set_stepsize
	stepsize PARAM1
}

{ ext_scarab_latch
	add SCARABS_ATTACHED PARAM1
	if ( SCARABS_ATTACHED < 0 ) setvard SCARABS_ATTACHED 0
}

{ ext_hold_person //<duration>
	setvard I_R_HELD 1
	local L_HOLD_TIME PARAM1
	scriptflags ent_me add hold_person nopush 1 PARAM1 none
	callevent PARAM1 hold_person_end
}

{ hold_person_end
	setvard I_R_HELD 0
}

{ ext_playanim
	dbg ext_playanim PARAM1
	playanim critical PARAM1
}

//{ ext_sethp
//	hp PARAM1
//}

{ bs_global_command //<param1> - called globally when player dies

	//clear XP from player who died
	dbg bs_global_command clearplayerhits $get(PARAM1,name)
	if !NPC_IS_BOSS
	clearplayerhits ent_me PARAM1
}

{ ext_dbg
	if ( PARAM1 isnot off )
	{
		setvard EXT_DEBUG_PARAM PARAM1
		setvard EXT_DBG_LOOP_ON 1
		callevent ext_dbg_loop
	}
	else
	{
		setvard EXT_DBG_LOOP_ON 0
	}
}

{ ext_dbg_loop
	if EXT_DBG_LOOP_ON
	callevent 0.1 ext_dbg_loop
	dbg $get(ent_me,EXT_DEBUG_PARAM)
}

{ set_blind_attack
	setvard NPC_MUST_SEE_TARGET 0
}

{ ext_spawn_sound
	setvard NPC_USES_HANDLE_EVENTS 1
	setvard NPC_DO_SPAWN_SOUND 1
}

{ setfx_spawn_sound
	//convention alias
	callevent ext_spawn_sound
}

{ setfx_summon_circle
	//convention alias
	callevent set_summon_circle
}

{ setfx_fade_in
	//convention alias
	callevent set_fade_in
}

{ setfx_tele_in

	callevent set_fade_in 20
	callevent 0.01 setfx_tele_in2
}

{ setfx_tele_in2
	local MY_POS_GROUND $get(ent_me,origin)
	vectorset MY_POS_GROUND z $get_ground_height(MY_POS_GROUND)
	clientevent new all effects/sfx_repulse_burst MY_POS_GROUND 128 1.0
}

{ set_no_player_damage
	///alias for ext_no_player_damage
	setvard NPC_NO_PLAYER_DMG 1
}

{ ext_setmodelbody
	setmodelbody PARAM1 PARAM2
}

//{ ext_anim_exists
//	dbg ext_animexists $anim_exists(PARAM1)
//}

{ set_die_on_spawn_removed
	setvard NPC_DIE_ON_SPAWN_REMOVAL 1
}

{ set_dosr
	setvard NPC_DIE_ON_SPAWN_REMOVAL 1
}

{ set_no_roam
	setvard NPC_NO_ROAM 1
	roam 0
}

{ set_roam
	setvard NPC_FORCE_ROAM 1
	roam 0
}

{ trig_damage //<name>;<dmg>;<dmg_type> - called by a map brush with scriptevent
	//local TRIG_NAME PARAM1
	local TRIG_DMG PARAM2
	local TRIG_DMG_TYPE PARAM3
	stradd TRIG_DMG_TYPE _effect
	xdodamage ent_me direct TRIG_DMG 100% GAME_MASTER GAME_MASTER none TRIG_DMG_TYPE
}

{ ext_webbed
	if ( WEBS_ATTACHED == 0 )
	{
		setvard WEBS_ATTACHED 0
		callevent 10.0 ext_webs_decay
	}
	add WEBS_ATTACHED 1
}

{ ext_webs_decay
	subtract WEBS_ATTACHED 1
	if ( WEBS_ATTACHED > 0 ) callevent 10.0 webs_decay
}

{ ext_set_cocooned
	setvard COCOON_ATTACHED PARAM1
	if ( COCOON_ATTACHED ) setvard WEBS_ATTACHED 0
}

{ set_self_adj //[adj_down]
	dbg set_self_adj PARAM1

	setvard NPC_SELF_ADJUST 1
	if ( PARAM1 startswith 'PARAM' ) local NO_ADJ 1
	if !NO_ADJ
	if PARAM1 > 0
	//used to cap out adjustment on higher level beasties
	setvard NPC_ADJ_DOWN PARAM1
}

{ set_no_avg
	//don't add this monster to the level averages (good for monsters encountered early in map, where not everyone may have joined yet)
	setvard NPC_SELF_ADJUST_NOAVG 1
}


{ set_poisonous
	setvard NPC_POISONOUS 1
	setvard NPC_GLOW (0,255,0)
}

{ set_no_auto_activate //don't cycle up instantly based on player prox on spawn
	setvard NPC_NO_AUTO_ACTIVATE 1
}

{ set_non_agro
	setvard NPC_NO_AGRO 1
	callevent npcatk_suspend_ai
}

{ ext_set_goblin_latched
	setvard I_R_GOBLIN_LATCHED PARAM1
}

{ setfx_sprite_in
	//make sure c-tele1.spr is precached somewhere on the map or scripts - it isn't precached by default
	setvard NPC_USES_HANDLE_EVENTS 1
	setvard NPC_SPRITE_IN 1
	callevent set_fade_in
}

{ setfx_sprite_inx
	//uses xflare1.spr as it's already cached
	setvard NPC_USES_HANDLE_EVENTS 1
	setvard NPC_SPRITE_IN 2
	callevent set_fade_in
}

{ set_summon
	//for global npc summon counting
	setvard NPC_SUMMON 1
	add G_NPC_SUMMON_COUNT 1
	dbg set_summon G_NPC_SUMMON_COUNT
}

{ ext_summon_fade
	if NPC_SUMMON
	subtract G_NPC_SUMMON_COUNT 1
	dbg ext_summon_fade G_NPC_SUMMON_COUNT
	setanim.framerate 0
	setanim.movespeed 0
	gravity 0
	setvelocity ent_me (0,0,0)
	setvard NPC_DID_DEATH 1
	setvard NPC_OVERRIDE_DEATH 1
	setvard SKEL_RESPAWN_TIMES 99
	dodamage ent_me direct 99999 100 GAME_MASTER target
	deleteent ent_me fade
}

{ set_fadein_delayed
	callevent set_fade_in 1.0
}

{ setfx_beam_in
	callevent set_fade_in
	local BEAM_START $get(ent_me,origin)
	vectorset BEAM_START z $get_ground_height(BEAM_START)
	local BEAM_END BEAM_START
	vectoradd BEAM_END z 512
	effect beam point lgtning.spr 90 BEAM_START BEAM_END (64,128,255) 200 20 2.0
	playsound 0 10 weather/Storm_exclamation.wav
}

{ set_push_resist
	setvard MSC_PUSH_RESIST PARAM1
}

//nerf powers monster's XP to reach max over time (case big xp mob close to start) [cals from map start]
//ie. if you attack this mob 10 minutes in, and <minstomax> is set to 20, you'll get 50% xp
{ set_xp_tr //<minutes to max XP>
	setvard NPC_XPTR 1
	setvard NPC_XPTR_TIME PARAM1
	multiply NPC_XPTR_TIME 60.0
	if NPC_XPTR_TIME > game.time
	callevent 2.0 set_xp_timeramp_start
}

{ set_xp_timeramp_start
	setvard NPC_XPTR_MAXXP NPC_GIVE_EXP //all XP mods should be done by now
	callevent 1.0 set_xp_timeramp_loop
	dbg set_xp_timeramp_start TIME_RATIO NEW_XP [ NPC_XPTR_TIME ]
}

{ set_xp_timeramp_loop
	if NPC_XPTR
	callevent 60.0 set_xp_timeramp_loop
	local L_TIME_RATIO game.time
	divide L_TIME_RATIO NPC_XPTR_TIME
	if ( L_TIME_RATIO > 1 )
	{
		setvard NPC_XPTR 0
		local EXIT_SUB 1
	}
	if !EXIT_SUB
	local NEW_XP $ratio(L_TIME_RATIO,0,NPC_XPTR_MAXXP)
	skilllevel NEW_XP
	dbg set_xp_timeramp_loop L_TIME_RATIO = NEW_XP / NPC_XPTR_MAXXP [ NPC_XPTR_TIME ]
}

{ game_scriptflag_update //<action> <name> <type> <value> <base_expire_time>

	//handle flags
	if ( $get_scriptflag(ent_me,nopush,exists) )
	{
		nopush 1
	}
	else
	{
		nopush 0
	}

	//handle check for expire
	if PARAM1 equals add

	local L_CHECK_EXPTIME PARAM5

	if ( L_CHECK_EXPTIME > -1 )
	{
		add L_CHECK_EXPTIME 0.1
		callevent L_CHECK_EXPTIME check_flags_expired
	}
}

{ check_flags_expired
	scriptflags ent_me remove_expired
}

//in case nopush was set at spawn
{ npc_post_spawn
	if $get(ent_me,nopush)
	scriptflags ent_me add npspawn nopush
}

//map side npc addparams can only get one param at a time, so we have to break this in two
{ set_cbm_file
	setvard NPC_CUSTOM_COMBAT_MUSIC 1
	setvard NPC_CMUSIC_LENGTH 5.0
	setvard NPC_CMUSIC_FILE PARAM1
}

{ set_cbm_length
	setvard NPC_CMUSIC_LENGTH PARAM1
}

{ ext_conflict
	conflictcheck
}

{ ext_showflags
	local L_TEST $get_scriptflag(ent_me,listall)
}

{ ext_dumpvars
	conflictcheck dumpvars noglobals
}

{ set_mclip
	setmonsterclip PARAM1
}

Granted, most of those aren't going to be real useful... Changing a mob's race mid-combat can be dangerous, btw (sometimes crashes).

One that might actually be pretty useful, that I've not yet seen used, is ext_say - but I think you'd have to enclose the text in single quotes. eg. ext_say;'Yo, I has crossed the line!' - would let you give monster's one-liners without the need to edit scripts.
 

MS:C community

Old Skool Apostle
Alpha Tester
Joined
Jul 7, 2011
Messages
504
Reaction score
109
Thanks!

I noticed you mentioned info_hullzone. That entity doesn't exist anymore in the latest zhlt.fgd and I figured it got removed for a reason. I stumbled across a Chinese thread with VHLT changelogs and on page 2 it says (after Google Translate):
---- Delete the previous version info_hullzone
Only to find that this thing is useless, directly put the clip is not on the line.
So I guess info_hullzone is useless, but I can't really 'decipher' the reason.

On the same page it also says:
---- Bsp increase the-nohull2 parameters help solve MAX_MAP_CLIPNODES error
Can be through not generate collisions housing 2 to reduce the number of 1/3 of CLIPNODES
Collision shell 2 is a role for large objects (some pushable and monster)
I tried using this BSP parameter for my current WIP version of msc_vow and it appears to work:
Code:
SolidBSP [hull 2] 1 (0.00 seconds)
The clipnode count went from 50.9% to 35.8% which is pretty significant. I didn't test the map in-game because hull 2 isn't for players anyway but that's also what kind of worries me... Since hull 2 is for some pushables and monsters, usage of this parameter is probably a no-go for maps that have pushables in it. Also, I'm not sure which monsters (if any) 'use' hull 2, but I fear this -nohull2 parameter, awesome as it is, won't be useful here...

I also messed around with zhlt_transform, incase anyone cares. It requires an input of four numbers in the format "SCALE Xmove Ymove Zmove". So if you want to double a brush in size and then move it 16 units down, you'd use:
Code:
"zhlt_transform" = "2 0 0 -16"
But the downsides are plenty... Whatever you're scaling needs to have an ORIGIN brush attached to it, otherwise the brush will scale using (0,0,0) as its origin which leads to unwanted results. And you can't scale in just one direction, ie. you can't (for example) 'stretch' along the x direction.
And since this zhlt_transform thing is not dynamic (CSG parses the keyvalue, scales and/or moves the brush and then deletes the keyvalue), it's kind of useless. Manually adding zhlt_transform to a brush-based entity after compile does nothing. I don't see the point because there's already tools for scaling and moving brushes in Hammer...

I tried ext_say;'Hello I am from the Internet' and ext_say;(Hello I am from the Internet) but neither worked.

Also, I have three more questions (and then I'm really done bugging you for now :razz: )
  • What does "Spawn with Partner" ("spawnwith") do and how does it work? I tried spawning a monsters/orcflayer as partner of a monsters/skeleton_once, but the flayer never showed up...
  • What does "Req. Else Target" ("reqelsetarget") do?
  • How can you enable gl_wireframe "2" in MS:C? My console keeps telling me I can't use wireframe in a multiplayer game, yet in some other thread you posted this.
 

Thothie

Administrator
Staff member
Administrator
Moderator
MSC Archivist
Joined
Apr 8, 2005
Messages
16,342
Reaction score
326
Location
lost
MS:C community said:
And since this zhlt_transform thing is not dynamic (CSG parses the keyvalue, scales and/or moves the brush and then deletes the keyvalue), it's kind of useless. Manually adding zhlt_transform to a brush-based entity after compile does nothing. I don't see the point because there's already tools for scaling and moving brushes in Hammer...
Yeah, I didn't see much point to it, unless it was dynamic...

I dunno if setprop ent_me scale <ratio> would have an effect on an msarea_scripted brush. That might be more useful, for a visual effect, at least (maybe even just fancy doors that shrink out of existence). If it worked, it'd be dynamic - but somehow doubt it'll cooperate.

MS:C community said:
What does "Spawn with Partner" ("spawnwith") do and how does it work? I tried spawning a monsters/orcflayer as partner of a monsters/skeleton_once, but the flayer never showed up...
I dun rightly know, as I've never seen it used...

...and looking at the code... I don't even see "spawnwith" among the map entities... Hrmm... It maybe some legacy thing that no longer works - perhaps it should be axed from the FGD. (Got too many properties for ms npc's as it is.)

Generally, if you want a mob to have an escort on a separate tracker (common with boss escorts), you want him to target another ms_monsterspawn when he spawns, via the target ("Trigger on spawn") property. This is also useful if you need to ensure that two mobs in same area spawn in a certain order (for instance, if one is a controlling or targeting utility npc, and it needs to spawn before the mob that uses it.)

MS:C community said:
What does "Req. Else Target" ("reqelsetarget") do?
If you have a trigger with reqhp, reqavghp, or reqplayers (requires hp/average hp/X# players), and it is crossed, but fails to trigger due to not meeting the defined requirements, it can be made to fire reqelsetarget instead. (As described in changelog) Useful if you want to spawn one set of things if the server population meets the requirements, and another if it doesn't, for instance.

MS:C community said:
How can you enable gl_wireframe "2" in MS:C? My console keeps telling me I can't use wireframe in a multiplayer game, yet in some other thread you posted this.
Ruh oh... It maybe a Half-Life update messed this up, but, at least under my current build I can still use it. (I can't play under the newer builds). If you launch a map, via map <mapname> at console, rather than through the menu, that may help prevent the anti-cheat from kicking in. (Gimme a heads up if that doesn't cut it... I may have to look into hacks...)
 

MS:C community

Old Skool Apostle
Alpha Tester
Joined
Jul 7, 2011
Messages
504
Reaction score
109
I tried everything but gl_wireframe "2" still doesn't work.

Also tried triggering a separate monster (which I named "dude") and a separate ms_monsterspawn (also named "dude") with the "spawnwith" keyvalue but it didn't work. So yeah, I guess it can be removed from the FGD.
 

Thothie

Administrator
Staff member
Administrator
Moderator
MSC Archivist
Joined
Apr 8, 2005
Messages
16,342
Reaction score
326
Location
lost
Yeah, I don't see it in the code, so it's likely not connected to anything... I'll have to double check with an external search, as Visual Studio has a habit of missing files when it searches - but I'm sure the map entity files are all included in its standard search.

As for gl_wireframe not working, I'll have to ask again - are you using the latest Half-Life update, or the fixed rollback? I know it works under the rollback (and has for years), but the latest updates may have fubar'd it again. Seems there was another update today, so I suppose I should take another shot at the newer version.
 

MS:C community

Old Skool Apostle
Alpha Tester
Joined
Jul 7, 2011
Messages
504
Reaction score
109
Kind of hard to tell... I did roll back using franky200's fix but if I right-click on the Steam icon, I see the new "Friend Activity" thing... I don't really know what kind of Steam version I'm running.
 

Thothie

Administrator
Staff member
Administrator
Moderator
MSC Archivist
Joined
Apr 8, 2005
Messages
16,342
Reaction score
326
Location
lost
It wouldn't affect the Steam client, only Half-Life... I suppose, if you used the rollback, there's a reason for it, and whatever reason that is would have re-asserted itself, if it updated unexpectedly, as it so often does...

You can close Steam, and try applying this:
http://www.thothie.com/msc_dev4/half-li ... EB2013.exe

And if it still doesn't work... Meh, I'm not sure waddup... Maybe would need to see your listenserver.cfg or some such.

Only other alternative is to toss the BSP into Half-Life (valve/maps) and try it there... Should work, so long as any wad dependencies are provided - may need to add an info_player_start, but failing that, I think Freeman will just spawn at 0x0x0, and you'll need to sv_cheats 1 and noclip your way out. (sv_cheats - might be another thing to try - but shouldn't be required.)
 

MS:C community

Old Skool Apostle
Alpha Tester
Joined
Jul 7, 2011
Messages
504
Reaction score
109
Thothie, I was kind of wondering what you think: Is -nohull2 viable or not?
 
Top