Left 4 Dead 2/Scripting/Expanded Mutation System/Appendix: Spawning
Spawning Objects
Overview
There are several ways to spawn (create) objects in the Mutation toolkit:
- Place named info_item_position objects (using hammer or the entity placement tool, or hand editing the entity text file if you really want) and then either build a table or make function calls to spawn objects at those positions. This is good when you want to place a lot of the same object, or place very precisely, and place in a data driven way.
- "Just use MapSpawns" - will spawn at all the item positions you placed.
- SpawnMultiple - for more specific control, allowing filtering, sorting, and so on.
- Call SpawnSingle (or SpawnSingleAt or SpawnSingleOn) with an entitygroup reference and a place to spawn. This is often best for dynamic or reactive spawns or other simple ones.
- And, of course, you can just place them in hammer, the old way, and ignore the new systems altogether.
There are also, basically, 2 types of things you can spawn:
- Entity Groups which are basically a group of objects and connections exported from hammer.
- Model and Table where you pick a model name and set of entity creation keys.
All-you-can-eat
Create a MapSpawns table (as described below, if you havent already seen one). If you do this, then on the OnGameplayStart message, that table will be spawned (by which we mean - if the flag is set to spawn and you have info_item_positions with appropriate names, etc)
Or you could, if you want, call your table something else. At which point you need to EntSpawn_DoIncludes( MySpawnTable ) early on (@TODO: OnActivate? Is that early enough?). And then EntSpawns_DoTheSpawns( MySpawnTable ) when you want them spawned. But really, you probably want them spawned at OnGameplayStart, hence the automated approach. If you want to do things piecemeal/individually later, you should probably use one of the a la carte approaches below. You still want a MapSpawns table, but set it to NOSPAWN for your dynamic objects, and then spawn them using the tools listed below.
Spawn Tables
MapSpawns<- [ ["GnomehunterGnome", "gnome_spawn", "gnomehunter_gnome_group", SPAWN_FLAGS.SPAWN] ]
This is an array (hence the []) of arrays. Each line is a spawnable, and each spawnable defines up to four things. At base, you define
group name - "GnomehunterGnome" is the name of the entity group exported from hammer (as it appears in the group.nut file). This name is automatically synthesized from the .vmf filename, which is "gnomehunter_gnome". spawn location - "gnome_spawn" is the the name of the info_item_position to spawn your object file to include - "gnomehunter_gnome_group" is the name of the .nut file on disk spawn flags - SPAWN_FLAGS.SPAWN indicates that the object is to be spawned on map load count - if you want, you can include a # to spawn, and set a SPAWN_FLAGS_TARGETSPAWN
Now, in practice, you dont necessarily need to fill this all in. i.e. things have reasonable defaults
GroupName - You always need this one! spawn location - if you dont pass this, we use entities named group_name_spawn file to include - if you dont pass this, we include the file group_name_group spawn flags - this defaults to SPAWN_FLAGS.SPAWN, so only really needed to NOSPAWN or TARGETSPAWN count - assumes you want all, but you can set a value for # to spawn otherwise
[@TODO: at moment we take a CamelCase GroupName to lower_case group_name for extra fields - change it]
A la Carte
- SpawnSingle( entityGroup) : spawns the group, remember to set an 'origin' key so it spawns somewhere
- SpawnSingleAt( entityGroup, Vector, QAngle ) : spawns the group at the Pos/Ang passed in
- SpawnSingleOn( entityGroup, spawnAtEntity ) : spawns the group at the pos/ang of the entity passed in
- SpawnMultiple( entityGroup, configTable ) : Takes a given entity group and spawns it at all the info_item_positions associated with it, pursuant to the configTable. The configTable can have several fields
- filter - is passed the list of possible spawns, can decide which to do or not do
- sort - if you place one, it is called on the final spawn list
- list - if you want to just pass a spawn list yourself directly
- count - if you want N things spawned, but dont care which
Examples:
SpawnSingleOn( HatGroup, hatPosEnt ) SpawnSingleAt( HatGroup, Vector(2,52,1), QAngle(0,90,90) )
These assume you have a bunch of traffic cone info_item positions
SpawnMultiple( HatGroup ) SpawnMultiple( HatGroup, { filter = @(v) v.GetGroup() == 0 } ) // spawn all group 0 hats SpawnMultiple( HatGroup, { sort = @(a,b) a.GetName() <=> b.GetName() } // spawn all in alphabetical order SpawnMultiple( HatGroup, { count = 8 } // spawn 8 of the hats at random
Or
SpawnMultiple( HatGroup, { list = myListOfEntitiesToSpawnHatsAt } ) // if you want to hand manage it all
Create Helpers
These are functions that let you start with just a single entity KeyValue table and have a full EntityGroup table built for you. Most then directly call SpawnSingle for you. The basic one is
- CreateSingleSimpleEntityFromTable(spawnTable, entityAt = null): takes the key/value pairs in spawnTable and wraps them in an entityGroup data structure and uses them to spawn the requested entity. If you pass the optional 2nd parameter (entityAt) it will be used as the origin of the newly spawned entity. Unlike most spawn stuff, since this only spawns one entity, it returns the spawned entity to you (or null if it fails). You _cannot_ put entity postplace callbacks on this function, but as you get the entity back right after calling it, you can do any callback work on return if you need to. @TODO: Chain the callback
- BuildShell( spawnTable ): This is for putting an EntityGroup shell around a table of KeyValue spawn pairs. This function returns an entityGroup which you can then pass to Spawn Functions or otherwise work with.
There are also a few very specific create helpers
- SpawnMeleeWeapon( weaponname, pos, ang ): As you might expect, spawns a weapon of said name at pos/ang.
- CreateParticleSystemAt( srcEnt, vOffset, particleName, startActive(true), overrideTable(null) ): Creates a particle system named particleName at vOffset relative to srcEnt - by default it starts on with no special keys. You can start it off or pass override keys if you want.
Instructor Hint Helpers
- CreateSimpleInstructorHints( hintTable ): This function will find all entities in the supplied table and create instructor hints and hint targets at their respective positions.
The table follows this format:
table <- { hintEntityName = "<name for this hint entity>", targetEntityName = "<name of target entity>", hintText = "<Actual hint display text>", hintOnScreenIcon = "<name of hint icon>" }
- CreateTrainingHints( hintTable ): This function creates hints on model entities specified in a table. You can see an example of how this function is used to create hints that appear on map spawn and remove themselves at a later time in the Holdout training mutations for c10m3_ranchhouse and c10m5_houseboat.
The table follows this format:
table <- { targetname = "<name to give created hint>", mdl = "<name of model used by hint target>", targetEntName = "<name (or substring) of entity that uses the mdl>", hintText = "<text to display>" }
The MDL and targetEntName are both necessary in order to narrow down the entity for hint attachment. You do not need to provide the exact name of the target entity, just a substring contained by the name.
- EndTrainingHints( delay ): Kills off all the hints created by the CreateTrainingHints function.