Anyone who has messed with scripting in Tiberian Dawn, and has done some slightly non-standard things, has probably wondered at some point or another why their triggers did not work as expected. Well, I dove into the code so you wouldn’t have to.
Preface: the Inconsistency of Triggers.
Anyone who has messed with mission scripting in Tiberian Dawn before, and who has done some slightly non-standard things like using more Houses than just GDI, Nod, and Neutral, has probably wondered at some point or another why a trigger they put in the mission did not work as expected.
And, while I dug into triggers before, and in fact have an old document circulating with my name on it that claims to know all about these things, I must admit that I’m still very often wrong in my notions on how they work. Especially the role of the “House” on a trigger has been the subject of much debate.
So, one day, when I got involved in a conversation on Discord where some people were messing with these triggers, and it devolved from experimentation to guessing, philosophizing and generally getting annoyed at them, my good friend Kilkakon pointed out that we were all being silly, and should just look at the one place that explains everything: the source code.
The discoveries that were made that day were baffling, confounding, and occasionally hair-raising.
My previous notion that the House was a restriction on who could activate it turned out to only apply to Celltriggers. The configured House is apparently frequently used for both the Event and the Action, often causing insane conflicts and never-working triggers. Two trigger Actions as similar in effect as Production and Autocreate turn out to be handled completely differently depending on what causes them. And the list goes on…
- The word “House”, in context of C&C scripting, refers to a player side. The name is a leftover of Dune II, where noble families were the involved factions. In TD, they are GoodGuy (GDI), BadGuy (Nod), Neutral (civilians), Special (dinosaurs), and Multi1-Multi6 for multiplayer purposes. All of these can be used in singleplayer missions, though if you try to set anything except GDI or Nod as player faction the game will probably crash when the mission is won.
- In this article, “Player” refers specifically to the current human player’s House. This is important, since trigger handling will sometimes use the linked House, and sometimes use the player’s House.
Events, and Where They Come From
Each Event can come from three different sources:
- Cell: will come from a Celltrigger
- Object: will come from a pre-placed unit or structure on the map that has the trigger linked to it.
- House: will come from neither, and will be seen as owned by the House in the trigger. Will not work if “House” is set to None, since the function that checks these is the one that processes general House-related functions.
Some events can come from multiple of these, depending on how they’re configured and what they are linked to.
- From Cell: a cell is entered by a non-cloaked unit of the trigger’s House.
- From Object: a linked object on the map is captured, regardless of by whom.
In practice, for the second case, the “Object” in question will always be a structure. Units can technically be captured when docked to a Repair Facility, but in reality there’s no way to make an AI unit do that. Some elaborate scenario could be set up to have you deliver a unit to a repair pad and then make an AI capture it, though that sounds pretty convoluted to me. AI Helicopters do go to the Repair Facility to get repaired, but those can’t be put on the map in a way a trigger is attached to them.
- From Object: a linked object on the map owned by a different House than the Player is discovered by the Player.
- From Object: a linked object on the map is attacked, regardless of by whom. The set ‘House’ does not affect this.
- From House: any structure of the House set in the trigger is attacked, regardless of by whom. This works without the trigger being attached to anything.
These are actually treated as two different Events: “Object Attacked” and “House Attacked”. An Object Attacked trigger should never have a House set, and a House Attacked one should never be linked to any map objects, otherwise, strange behaviour will occur.
- From Object: a linked object on the map is destroyed, regardless of by whom.
- From Object: any action is performed on a linked object on the map, regardless of by whom.
This is a special case, normally only used on “Cap=Win/Des=Lose”. If used with any other Action, the Action will trigger from the moment any kind of triggerable event happens to the object.
- From House: any unit or structure belonging to this House is discovered.
- From House: all units of the specified House are destroyed.
This check excludes Gunboats, Transport Helicopters, delivery planes, and airstrike planes.
- From House: All structures of the specified House are destroyed.
- From House: All units and structures of the specified House are destroyed.
Again, this check excludes Gunboats, Transport Helicopters, delivery planes, and airstrike planes.
- From House: credits of the specified House reached a certain amount.
- From House: a certain amount of time has passed. The time unit is 1/10th of a minute on Moderate game speed.
Code exists to trigger this from map objects, but it is never used, since the House AI function is the only place that checks time. This is a pity, since it would’ve been an easy way to make timed triggers that can be cancelled by destroying an object.
# Bldgs Dstr.
- From House: a certain amount of buildings of the specified House are destroyed.
# Units Dstr.
- From House: a certain amount of units of the specified House are destroyed.
- From House: the specified house does not own any Weapons Factories, Airstrips, Barracks or Hands of Nod.
- From House: a non-technician civilian has been evacuated with a Transport Helicopter owned by this House.
This trigger event can only be used once in a mission, since the “IsCivEvacuated” status on the House does not reset.
- From House: the specified House has constructed a specific building, as specified by id.
If set to repeat, this will trigger every time a building of that type is built. Building IDs are basically the index in this list – [github.com] , starting at 0 for the Weapons Factory.
Actions, and What They (Really) Do
Now, on to the real beef: the Actions. A lot are origin-independent, while others act very differently depending on the source of the activation.
Origin-independent. The Player is flagged to win, meaning they will win as soon as any blockages from “Allow Win” triggers are cleared.
Origin-independent. The Player loses.
- From Cell: if Player is Goodguy then Badguy begins production; if Player is any other house, then Goodguy begins production.
- From Object: The House set in the trigger begins Production.
- From House: The House set in the trigger begins Production.
Origin-independent. A Team of the linked Teamtype is produced.
Origin-independent. All active teams of the linked Teamtype will disband, meaning their units will stop acting as team. This does not destroy the units. It also doesn’t prevent the future creation of more teams of this type.
All to Hunt
Origin-independent. All non-Player-owned vehicles and infantry on the map are detached from any teams they’re in, and have their orders set to “Hunt”.
Origin-independent. A Team of the linked Teamtype is reinforced from the map border depending on the Edge setting of the House set in the Teamtype.
DZ at ‘Z’
Origin-independent. A smoke signal is shown at Waypoint 25, and an area with a radius of 4 cells around that spot is revealed to the Player.
- From Cell: The House set in the Trigger gets permanent Airstrike ability. If the linked House is the Player, it is made immediately ready to use.
- From Object: The Player gets permanent Airstrike ability, immediately ready to use.
- From House: The Player gets permanent Airstrike ability. If the linked House is the Player, it is made immediately ready to use.
Somehow, they managed to make this do three slightly different things.
Origin-independent. Enables a one-time nuclear strike for BadGuy, and immediately charges it.
This has no effect if BadGuy does not own a Temple of Nod, since it is required for firing it.
The AI will immediately fire this when it is made available to them. The Player will not receive this if they have already fired a nuke before in this mission, but if they have a Nuke that’s still charging, this will immediately make it ready to use.
Origin-independent. Enables a one-time Ion Cannon strike for GoodGuy, and immediately charges it.
This should have no effect if GoodGuy does not own an Advanced Communications Center, but in the Remaster, the AI seems to ignore this. I have not tested if the same is true for the Player.
The AI will immediately fire this when it is made available to them. If the Player already has the ability, the “one-time” aspect of this is ignored, and it just acts as an instant recharge.
Dstry Trig ‘XXXX’ / ‘YYYY’ / ‘ZZZZ’
Origin-independent. These three triggers have one simple effect: they destroy the trigger with that name. Only triggers with these three specific names can be destroyed with triggers.
- From Cell: All Houses starts randomly creating attack teams.
- From Object: The House the object belongs to starts randomly creating attack teams.
- From House: The House set in the Trigger starts randomly creating attack teams.
- From Object: if the object is destroyed, the player loses. If the object is captured, no matter by whom, the player wins.
This is normally linked to the “Any” event, since it is the only one that can check Events other than itself, and this needs to check two different events. If used with a ‘Player Enters’ or ‘Destroyed’ event, it will just act as the corresponding Win or Lose Action.
Origin-independent. The House set in the trigger is only allowed to win after this is triggered.
Problems, so you can Avoid Them
So, as you can see, there are some really messy things in there. And, invariably, all of them are due to both the Event and the Action using the House set in the trigger. Here’s some examples:
Player Enters (cell) -> Airstrike
Set up a celltrigger setup triggered by an AI that is supposed to give the player the Airstrike, and you see it won’t work. Worse; after a while, the AI will start performing periodic airstrikes. Because in the case of celltriggers, the House set in the trigger gets the Airstrike ability.
So, yes, this little gem will permanently enable the Airstrike ability on an AI House. Since this is actually the Airstrike superweapon, and not the classic reinforced A-10s used in the Nod campaign, it will use a different targeting logic, which only targets structures.
Attacked -> Autocreate
“Attacked” are actually two different triggers; one set on a House, and one set on map objects. If the House is set to anything other than ‘None’ though, and the trigger is also attached to map objects, possibly of different Houses, things start getting understandably weird. It will get triggered both from the linked objects, and from the House having a structure attacked. And depending on the Persistence (the “loop” status, in the map editor), one of three things will happen in terms of the Autocreate:
- Volatile (no loop; 0): One of the linked objects, or a structure of the owning House, must be attacked. The House of the first triggered object will get its Autocreate enabled. The others won’t.
- Semi-persistent (‘And’ loop; 1): The linked objects, and a structure of the owning House, must be attacked. The House of the last triggered object will get its Autocreate enabled. The others won’t.
- Persistent (‘Or’ loop; 2): Whenever one of the linked objects is attacked, or when a structure of the House in the trigger is attacked, its owner will get its Autocreate enabled. All Houses can eventually get activated with this setup.
So, wait, does that mean that one single trigger might actually affect a different House, purely depending on what the player attacks first? Yes, yes indeed. And the others are just left in the dust, trigger spent, never getting their precious Autocreate.
All Destr. -> Allow Win
You might be tempted to use the Multi-Houses or House Special to add extra enemies for your player to destroy, and only let the player win after they are all destroyed. Sadly, “Allow Win” can never do this: because it stores its “win-blockers” in the House that is linked in the trigger, it has to be linked to the Player House, or it won’t function at all.
There is some advanced trigger setup you can do to get around it. Basically, when you reinforce a C17 plane carrying a unit to a House that does not have an Airstrip, they get the cost of the unit refunded. And there is a trigger to check credits. This gives some interesting scripting possibilities akin to the “Globals” system in Red Alert’s triggers.
So instead of the “Allow Win” trigger, you can make the destruction of each House trigger such a C17 reinforcement containing a single minigunner, to some multiplayer-House that is 100% unused on the map. And then, you can make that House have a trigger to check if 300 credits are reached, so that after three enemy Houses are destroyed, you win.
Note, when this kind of trigger setup was done on the original game, it occasionally caused the C17 to rampage around the map like an Airstrike, using a weapon composed of random data in memory (since its weapon is set to “-1”, and it actually tried to read a weapon from index -1 on the weapons list). To avoid that, simply make sure your “money bag” House is allied to all other Houses, so the C17 will never be tempted to attack anything.
Discovered -> Dstry Trig ‘XXXX’
So, you want to make a trigger that deactivates a lose condition on a small squad after you discovered your base? Well, you’re going to have to find a different way than “Discovered”; it only triggers when you discover a building of a different House.
A valid substitute is the “Built it” event, linked to one of the actual building types you will discover; discovering a building you own counts as building it.
There are some interesting things hidden in the game engine, which are not immediately apparent, but which are really handy to use in scripting. This list will be updated as I find more of these.
Preventing AI selling
When the AI fails to repair a damaged building due to lack of funds, it will normally sell that building. However, it will never sell a building that has a trigger attached to it. This means that you can prevent selling of specific structures (like a Construction Yard or Refinery) by attaching a trigger to them, even if the trigger does nothing at all.
A trigger can perfectly be created with Event “None”, to prevent activation, and then used as dummy to prevent selling. (Just don’t make it an “Allow Win” one linked to your House; then you can never win the mission.)
This is all for Command & Conquer™ Remastered Collection Scripting in Tiberian Dawn Information Guide hope you enjoy the post. If you believe we forget or we should update the post please let us know via comment, we will try our best to fix how fast is possible! Have a great day!
- Check All Command & Conquer™ Remastered Collection Posts List