Combined light entities
Introduction
Many complex objects in game are build from more than one entity. Others consist of only one entity, but represent different things at the same time.
For instance, a candle consists of two entity: the candle stub, and an attached flame object.
The flame object itself consists of only one entity, but this entity both emits light, sound and particles as well as reacts to stimuli like fire and water.
This article deals with the complex entities consisting of more than one entity.
Two ways
There are two ways to attach two entities together:
- the entityDef (inside a .def file) can specify to spawn and attach a new entity when the first entity is spawned. This typical happens at map loading time, but can also happen later in game when a new base entity is spawned. This is from here one called "def_attached" due to the spawnarg being responsible: def_attach.
- the mapper can manually add both entities in the map, and then arrange them in the editor so they look bound together. We refer to this from here on as "the manual way".
The second way has several disadvantages but also advantages:
Disadvantages:
- manually arranging the entities is error prone, f.i. often candle flames would hover over the candle, or be slightly offset
- Moving the entities in the map must always move both in sync, or #1 happens.
- when creating a moveable entity, the mapper must also take care that the second entity moves with the first by binding them together manually
Advantages:
- Both entities are present in the editor, and can thus be seen. (For combined entities, DR will hopefully later automatically show a dashed outline for any automatically attached entities, making this point mood).
- Since the attached entity is already in the editor, its name is known, so it can be easily targeted by scripts. This is the main disadvantage of def_attaching entities and we see later how we can overcome it.
This article, however, deals primarily with the first way.
Example entities
Candle and Flame
Here is an example entity attaching a flame to a candle:
entityDef atdm:moveable_candle_01_lit { "inherit" "atdm:moveable_lit_candle_base" "model" "models/darkmod/lights/extinguishable/candle_01.ase" "mass" "0.4" "editor_usage" "A lit yellowish candle stump." "attach_pos_origin_1" "0 0 5.5" // Offset the flame X units in the Z direction }
Holder and Candle (and Flame)
Here is an example entity attaching a candle (which itself has an attached flame) to a candle holder:
/* skinny tall */ entityDef atdm:moveable_candle_holder_plus_skinny_tall_candle { "inherit" "atdm:moveable_candle_holder_base" "mass" "1.5" "editor_usage" "A candle holder with an unlit tall & skinny candle." // attach the candle "def_attach" "atdm:moveable_candle_skinny_tall" "pos_attach" "candle" // At the attach point called "candle"... "attach_pos_name_1" "candle" // ... which is defined here. "name_attach" "candle" // Set a name to pass along spawnargs "attach_pos_origin_1" "0 0 17.5" // Offset the candle X units in the Z direction }
Modifying the attached entity/entities
When you place a combined entity (f.i. candle+flame) in your map, you only see the base entity, in this case the candle. However, to switch the candle off or on, you would need to link some entity (like a switch or trigger) to the candle flame entity. Likewise, if you want to change the color of the flame, you would need to set the "_color" spawnarg on the flame.
But since the candle flame does not exist yet, you can't. Here is how you can overcome this:
Targeting the (invisible) entity
Simple target the base entity, like the holder or the candle. When triggered, these know how to extingusish or light all attached flames (even tho they don't exist at map load).
Note: sombody please test that that actually works!
Using a script to turn lights off/on
There are three special global script functions that you can use to manipulate attached light entities when you only know the base entity:
frob_light_holder_light( holder ); # turn the light on frob_light_holder_ext( holder ); # turn the light off frob_light_holder_toggle_light( holder ); # toggle light (if on => off, if off => on)
Note: These functions are called without an object and take as first argument the base entity.
Example:
void light_on( entity zone ) { entity holder = sys.getEntity( "stone_room_light" ); if (holder) { // We need to tell the holder to turn off the bound light (as we do // not know what the bound light entity is named) frob_light_holder_light( holder ); } }
Note: Don't call these functions this way:
holder.frob_light_holder_light(); # WRONG!
Setting spawnargs
To be written in a moment.