Campaign Series Event Engine in Vietnam 1.0: Triggering Events
Campaign Series Event Engine (CSEE) is a new system that allows scenario designers to script events in their scenarios to add more capabilities not seen before in the Campaign Series games. This system uses programmed Lua files to determine what the events are and how they interact with the scenario.

Triggering Events with CSEE
All of the scenarios that are included with Vietnam have a large component of the AI using the Campaign Series Event Engine where one side is fully scripted, providing an exciting opponent to play against. For the purposes of this Developer Diary series, I will look at what CSEE brings to Campaign Series from three viewpoints:
- How Events are triggered in scenario Lua file
- How Lua provides an easy to Adaptive AI settings, and
- How the computer player with Scripted AI is a new kind of a foe.
In this post, I cover the first capability: how events are triggered and what you can do when that happens. Before that, a few words on the anatomy of CSEE itself.
Note: This is meant as an introductory blog about the coming features. There will be a complete CS Event Engine manual shipping out together with the game install.
Campaign Series Modern Wars game engine vs. Campaign Series Event Engine
While there has been quite a few additions and enhancements built to Campaign Series game engine itself, none of them has been as exciting as the ability to react to anything happening in game – ie. having an event to taking place – in a scenario specific manner. And even though we combine the CS Lua Event engine with the game engine into one integrated game executable, on game launch, it is useful to think of the two engines as two separate programs running side by side. As an event takes place in the Campaign Series “Modern Wars engine” (built with MS Visual C++) it forks out a call to Campaign Series Event Engine “Lua engine”, running in parallel in the same process space. This is very efficient, too: you’d expect to see a little delay perhaps but no, it all plays together very smoothly.
Specifically, there’s a scenario specific Lua file available to catch these game event calls, in any and all of the event functions now available. Once said event function has been processed in Lua engine, the control then returns to CS Modern Wars engine to continue with the game play there.
As with previous Campaign Series games, CS Vietnam 1948-1967 comes with a full set of editors. You can create your own scenario just like you did with previous games and their editors. Only now – it is an option – you can add a Lua programme file to the scenario you have designed. In that Lua file you can handle any game event in a manner that is relevant in the battle you are depicting.
Reacting to game events
Triggers available
Once an event takes place in the game, the game triggers an event function in the scenario specific lua code. Here are the event functions available at the time of writing this post. It is rather lengthy, but that’s the whole point, so here they are in all their glory:
- on_air_attack (hc, pid, name, side, nation, points, strength)
- on_arty_attack (hc, trackid, pid, name, side, nation, oid, orgname, points, strength, HQ, Leader)
- on_build_barrier (hc, trackid, pid, name, side, nation, oid, orgname)
- on_build_light_bridge (hc, dir, trackid, pid, name, side, nation, oid, orgname)
- on_build_vehicle_bridge (hc, dir, trackid, pid, name, side, nation, oid, orgname)
- on_clear_hex (hc)
- on_clear_lz (hc, trackid, pid, name, side, nation, oid, orgname)
- on_damage (hc, trackid, pid, name, side, nation, oid, orgname)
- on_entrench_hex (hc, trackid, pid, name, side, nation, oid, orgname)
- on_hex_assault (hc, side)
- on_hex_attack (hc, side, nation, attype)
- on_ied_attack (hc, trackid, pid, name, side, nation, oid, orgname, points, strength, HQ, Leader)
- on_improve_hex (hc, trackid, pid, name, side, nation, oid, orgname)
- on_lay_mine_field (hc, trackid, pid, name, side, nation, oid, orgname)
- on_mine_attack (hc, trackid, pid, name, side, nation, oid, orgname, points, strength, HQ, Leader)
- on_next_phase (turn, side)
- on_next_turn (turn)
- on_objective_capture (hc, values, side)
- on_resume ()
- on_set_ied (hc, trackid, pid, name, side, nation, oid, orgname)
- on_shutdown ()
- on_startup ()
- on_unit_arty_fire (hc, trackid, pid, name, side, nation, oid, orgname, strength)
- on_unit_attack (hc, trackid, pid, name, side, nation, oid, orgname, points, strength, HQ, Leader, attype)
- on_unit_clockwise (hc, trackid, pid, name, side, nation, oid, orgname, points, strength, HQ, Leader)
- on_unit_counterclockwise (hc, trackid, pid, name, side, nation, oid, orgname, points, strength, HQ, Leader)
- on_unit_fire (hc, trackid, pid, name, side, nation, oid, orgname, strength)
- on_unit_kill (hc, trackid, pid, name, side, nation, oid, orgname, points, strength, HQ, Leader)
- on_unit_merge (hc, trackid0, pid0, name0, side0, nation0, oid0, orgname0, points0, strength0, HQ0, Leader0, trackid1, pid1, name1, side1, nation1, oid1, orgname1, points1, strength1, HQ1, Leader1)
- on_unit_move (hc_from, hc_to, trackid)
- on_unit_reduce (hc, trackid, pid, name, side, nation, oid, orgname, points, strength, HQ, Leader, loss)
- on_unit_reinforce (hc, trackid, pid, name, side, nation, oid, orgname, points, strength, HQ, Leader)
- on_unit_release (trackid, pid, name, side, nation, oid, orgname, points, strength, HQ, Leader)
- on_unit_remove (hc, trackid, pid, name, side, nation, oid, orgname, points, strength, HQ, Leader)
- on_unit_to_top (hc, trackid, pid, name, side, nation, oid, orgname, points, strength, HQ, Leader)
- on_unit_to_bottom (hc, trackid, pid, name, side, nation, oid, orgname, points, strength, HQ, Leader)
Compare this to how it was with Campaign Series: Middle East 2.0 and you’ll find there’s approximately three times the events now as compared to CSEE’s first iteration back in the day!
On Objective Capture
Let us pick perhaps an obvious one: on_objective_capture (hc, values, side). Here’s how it looks in the scenario lua file:
So what happens is that each and every time an objective changes hands in the scenario played, there’s – in this particular implementation – a 2-in-3 chance the player would get an encouragement for his brave deed. See here:

Objective taken – commendations!
Also, note the parameters you receive in this particular event to have a look at:
- What were the hex co-ordinates of the objective (“hc”)
- What was the value, in Victory Points, of said objective (“value”)
- Which side captured said objective (“side”)
With that knowledge, what else could take place? Well, anything!
- Loss of an important objective might lower everyone’s Morale by 1 step,
- Certain reserves might receive an order to counter attack the objective viciously to win it back, or
- This might actually trigger the Scripted AI to revert from battle plan “A” to plan “B”, what ever that plan then is.
On Unit Kill
Another example: on_unit_kill (hc, trackid, pid, name, side, nation, oid, orgname, points, strength, HQ, Leader)
A more complex example, yet nothing too complex right? With HQ units in Campaign Series representing bot the C3 (command, control, communications) capabilities as well as logistics (logistic chain as well as handling the rate of consumption), it might be prudent that a loss of any of your HQs triggers an penalty. It could be an Event Points penalty, as the standard code snippet suggests, or in this case, depending how important your HQ was there’s loss to logistics in that the base ammo levels go down. Supply does not flow to your troops as efficiently anymore!

HQ lost – logistics take a hit!
Stay tuned for more CSEE under the covers!
To summarise, with all those event functions available to be triggered, as that particular event takes place in the game play, sky’s the limit to enrich the playing experience.
In my next blog, then, I will talk about how to access the Adaptive AI parameters from CSEE Lua code. Here’s how it was available in its first iteration with Campaign Series: Middle East 2.0. Effective, but quite cumbersome. Now: way much easier, and, adaptive to game events to top it off!