L4D2 EMS/Appendix: Functions

From Valve Developer Community
< L4D2 EMS
Revision as of 13:20, 18 February 2013 by JohnGuthrie (talk | contribs) (Some of the exposed C++ connections)
Jump to: navigation, search

This documents some of the functions provided within the new Mutation system. As you have probably figured out if you've gotten this far, the tools provide a scattered collection of helpers and utilities, not a complete set of accessors. Hopefully the docs below will at least provide some ideas on what sorts of things you can do, and how to do them.

Note there are also plenty of other helper elements - Spawning Objects and Infects, the Simple HUD, Saving and Restoring data tables, and so on. They can be reached from the Appendix sidebar.

Script Utilities

sm_utilities holds utility functions used by scripted mode. Notable functions are:

  • TeleportPlayersToStartPoints( spawnpointName ) : This function takes a targetname of spawn points in a map. The spawn points do not need unique names but there must be four of them. When the function is called the players will move from wherever they are to the spawn points. The function will return false if the spawn points are not found.
  • SpawnStartBox( centerobjname, useFloating, width, depth, barriermodel, min_gap ) : This function creates a bounding rectangle of a specified size that will trigger a callback when touched by players. The only required parameter is centerobjname, which is the targetname of the point to center the start box around. By default the box is visible in game - it appears as a white striped plane. If you pass false for 'usefloating' it will use yellow striped ground markers. Or custom models can be specified with barriermodel. The function will return false if it does not find the startbox origin targetname.
When the first survivor exits the startbox, we look for a function called SurvivorLeftStartBox defined at Map or Mode Scope. If we find it, we call it - otherwise we Director.ForceNextStage. NOTE: if you provide your own callback, you have to ForceNextStage yourself if that is what you want - we do _not_ automatically call it if you add a custom callback.
In either case, we clear the StartBox (i.e. remove the callback checking for leaving, and if it is a floating startbox, we also remove the startbox objects).
  • SanitizeMap( sanitizeTable, sanitizeFlags ) : fires outputs based on contents of sanitize table. The sanitize table is specified in a .nut file in the vscript folders named sanitize_<mapname>.nut. The SanitizeMap function is useful for killing entities on map spawn. This is particularly useful to do when you want to create a game mode for existing L4D maps but the map has a bunch of map entities that would interfere with your custom game mode. Check out sanitize_c3m1_plankcountry.nut for an example of how all the c3m1 entities (choreo entities, coop entities, etc) are killed on map spawn to prepare the map for holdout mode.
  • Timer functions
    • @TODO: Document these!
  • Misc helpers and simple things
    • DeepPrintTable(table): prints out an entire table to the console in an indented/as one would build it kind of way, useful for debugging or for generating something to cut and paste to somewhere else.

Some of the exposed C++ connections

Functions in this section are called directly by the C++ code within Left4Dead2.

  • AllowTakeDamage(damageTable) : If you place a function with this name in your script, C++ will call it on all damage events. The damageTable is actually defined in scriptedmode.nut and filled in as appropriate before each call.
ScriptedDamageInfo <-
	Attacker = null              // hscript of the entity that attacked
	Victim = null                // hscript of the entity that was hit
	DamageDone = 0               // how much damage done
	DamageType = -1              // of what type
	Location = Vector(0,0,0)     // where
	Weapon = null                // by what - often Null (say if attacker was a common)
If you return "false" the damage will be stopped and nothing will be done to the target (though animation/bloodstains/decals will probably still happen, sorry about that). The only field read back by the C++ is DamageDone, so if you want you can use it to change the damage value before it is applied. The Type field is a bitfield, of which several key #def's are exported to script (DMG_HEADSHOT, DMG_BULLET, DMG_BUCKSHOT, DMG_MELEE, DMG_STUMBLE, DMG_BLAST, DMG_BLAST_SURFACE, DMG_BURN ).
  • InterceptChat( str, srcEnt ) : If you put a function with this name in your script, C++ will call it on all chat messages. Passing in the (annotated) chat string and the HSCRIPT of the speaker.
TODO: Add "annotation parser" to sm_utilities, figure out what happens if chat is from spectator/server.
  • Say( srcScript, string, bTeamOnly ) : Calling this will have player srcScript send string to chat, either to teamonly (true) or to everyone.
TODO: A bad srcScript should "just work" by coming from NULL, but not yet thoroughly tested.
  • Physics Stuff: There are several gets and sets you can do with physics. Remember the Apply's are impulses, not setting an absolute new value.
 vVel = GetPhysVelocity( CurEnt )
 vAng = GetPhysAngularVelocity( CurEnt )
 CurEnt.ApplyAbsVelocityImpulse( throwImp )
 CurEnt.ApplyLocalAngularVelocityImpulse( angImp )
  • GetInvTable( playerScript, invTable ) : Fills invTable with the player's inventory. The table has
 key: SlotX      value: Entity in slot (0-4, i think? Main Weap/Hand/Thrown/HealthPack/Pills)
 key: Held       value: Entity being carried, otherwise Held will not be in the table
  • GetInfectedStats( statTable ) : Fills statTable with some infected counts/etc... Right now the list is Witches, Tanks, Specials, Commons, though we may add more as requested going forward.
  • PickupObject( playerScript, entity ) : Object from world is put into the "Held" slot of the player. Warning: it will smoothly interpolate from where it is to the players hand - which is a bit goofy if it is on other side of level.
TODO: Add helper for "move object near me and pickup", better testing on bad/immobile objects
  • UserConsoleCommand( playerScript, arg ) : when a user does a <scripted_user_func argument> at console (or bound to a key) this function is called (if it exists). The playerscript is which players console it came from. You can pass strings or whatever, of course. So could do a switch statement off <arg> to give players special controls, etc.
  • AddThinkToEnt( ent, FuncName ) : this will put a think function onto an entity, or pass null to remove it. This is NOT chained, so be careful. Mostly used when you want to Inject a set of functions onto a spawned entity without putting a script on it yourself. Adding a "Think" pre-spawn will have it auto-connect, but post-spawn you need to by hand attach it. i.e. you might do something like the following (note in this case you could have one actual think func that all your spawned objects used, in practice.
function InjectThink( scrEnt, thinkFunc )
   local scrScope = scrEnt.GetScriptScope()
   scrScope["InjectedThink"] <- thinkFunc
   AddThinkToEnt( scrEnt, "InjectedThink" )
// and then you could call it like so to have a spawned entity call a common think passing itself as an argument
   InjectThink( myEnt, @() g_MapScript.InjectedThink(self))
// or of course whatever function you want/local thing, etc
TODO: Just put a set of these in sm_utilities so people dont mess them up/etc
  • CanPickupObject( object ) : This lets you decide whether a given object should be pickupable. Right now this is a single function in the Options Table - however we have a TODO to move it to MapScript and perhaps later to make it a table you can create with a callback so you can just list pickupable model names, plus have a fancier callback, plus have entries for both mode and map.
  • ZSpawn( spawnTable ) : This is essentially the z_spawn console command, except (a) you pass a table and (b) no raycast, you give it the position vector. The table entries used are:
   key: type       value: ZOMBIE_WITCH, etc - or the special ZSPAWN_MOB, or WITCHBRIDE, etc
   key: pos        value: Vector position at which to spawn
   key: ang        value: QAngle for spawn, optional (defaults to 0,0,0)
  • TraceLine(traceTable) – uses a configuration table to do a raytrace, puts return information into the table for return usage

Inputs: .start - start vector for the trace .end – end vector for the trace .ignore – entity handle to ignore as part of the trace .mask – optional masks: TRACE_MASK TRACE_ALL, TRACE_SHOT, TRACE_PLAYER_SOLID, TRACE_NPC_SOLID, TRACE_SHOT, TRACE_VISIBLE_AND_NPCS

Outputs: .hit – did we hit something .pos – where the traceline ended .fraction – where the hit occurred .enthit – handle for entity hit if there is one .startsolid – did we start in solid

The only required information to make the trace is providing the start and end point.


	traceTable <-
		start = Vector( 0,0,0 )
		end =  Vector( 0,0,256 )