TwitterFacebook

Random Lua Elements-How, When, and Why

When I saw the Lua tutorial video showing how it could be used to make random elements in Command, I was excited. My excitement diminished as I started making an overambitious scenario involving random Lua and recognized both the limitations and difficulty. But with that lesson in mind, I continued using random Lua.

While still frustrating at times, in part due to me not being a programmer, I found the benefits to be worth it. (Ckfinite, who is a programmer, has been a great help in getting my Lua efforts to work, and has provided many necessary technical corrections to this post. )

Event Editor vs. Lua.

So, in layman’s terms, the existing event editor allowed for an “either or” option. Operation Square Peg: Syrian MiG-29s are sitting at Damascus International, and a probability event fires to see if they’re dumb enough to mess with F-22s. The “attempted intercept” mission switches from inactive to active, and that’s all it can do.

Lua would allow that same group of MiG-29s to either all take off,  none of them take off, have a portion of them take off, or have them take off to fly to another airbase rather than engaging the attackers.

How To Make Random Lua Events

First, a necessary warning is in order. Even with the best scripting available, the random elements will still not be as random as you’d probably think they’d be-and the effectiveness of a simple “math.random” can vary a lot by computer.  Thus, one should have modest expectations.

That being said, now onto the detail of the scripts.

-First, use the event editor. The script will be typed/copied into the “action”, and the trigger will be at the start of the scenario. You can either do the more recently added “scenario loaded” trigger or a classic “scenario start + 1 second time” one. I’ve used both and personally find the latter a little easier to handle.

To help prevent a “stuck” result, one can use a random seed generation. The example is math.randomseed( os.time() )

However, it is vital not to overseed. Only make sure the randomseed activates once at the beginning of the scenario. (For my existing scenarios, which have only one random script at the beginning anyway, it’s not such a big deal, but for a scenario with, for instance, repeated random spawns, do not use a randomseed in each spawn event)

Now for the random elements themselves. I’ll begin with the sub generation event from Best of the West, Worst of the East, touched up a bit:

 

math.randomseed( os.time() )
a = math.random(1,2)
if a == 1 then
  ScenEdit_AddUnit({type='Sub', side='USSR', name='B-23', dbid='187', latitude='49.3812997111192', longitude='-36.8903957715054'})
elseif a == 2 then
  ScenEdit_AddUnit({type='Sub', side='USSR', name='B-25', dbid='147', latitude='49.3812997111192', longitude='-36.8903957715054'})
end
a = math.random(1,3)
if a == 1 then
  ScenEdit_AddUnit({type='Sub', side='USSR',name='B-10', dbid='278', latitude='50.52351341355', longitude='-37.177899984719'})
elseif a == 2 then
  ScenEdit_AddUnit({type='Sub', side='USSR',name='B-15', dbid='278', latitude='50.52351341355', longitude='-37.177899984719'})
elseif a == 3 then
  ScenEdit_AddUnit({type='Sub', side='USSR',name='K-115', dbid='391', latitude='50.52351341355', longitude='-37.177899984719'})
end

a = math.random(1,3)

if a == 1 then
  ScenEdit_AddUnit({type='Sub', side='USSR', name='K-18', dbid='159', latitude='49.8531552461574', longitude='-36.2143146634912'})
end
a=math.random(1,2)
if a == 1 then
  ScenEdit_AddUnit({type='Sub', side='USSR', name='K-16', dbid='363', latitude='50.1531552461574', longitude='-36.3143146634912'})
elseif a == 2 then
  ScenEdit_AddUnit({type='Sub', side='USSR', name='K-5', dbid='363', latitude='50.1531552461574', longitude='-36.3143146634912'})
end
ScenEdit_AddUnit({type='Sub', side='USSR', name='B-8', dbid='287', latitude='48.9941488964394', longitude='-35.8765853708755'})
a= math.random(1,2)
if a == 1 then
  ScenEdit_AddUnit({type='Sub', side='USSR', name='B-7', dbid='287', latitude='50.051014008713', longitude='-41.5623833495527'})
end
a= math.random(1,50)
if a <40 then
  ScenEdit_AddUnit({type='Sub', side='USSR', name='B-104', dbid='187', latitude='49.4764836877471', longitude='-38.8365478377241'})
elseif a>=40 then
  ScenEdit_AddUnit({type='Sub', side='USSR', name='K-474', dbid='117', latitude='49.4764836877471', longitude='-38.8365478377241'})
end

 

What all that code represents is the following (on-paper) formula:

-50% chance of either a weak Foxtrot or much stronger Kilo being included.

-2/3rds chance of a Juliett, 1/3 chance of an Echo II.

-1/3 chance of a low-tech but fast November

-A Hotel II SSN mod will always appear, but its name will be different.

-A Whiskey named B-8 will always appear.

-A Whiskey named B-7 has a 50% chance of appearing.

-A Foxtrot has a 4/5ths chance of appearing, and a Charlie II a 1/5th chance.

 

You can try this in the console-all you need is the DB3K and a side named “USSR”. Go and see what subs come up. As you can see, this is a large series of Math.random commands, accompanying basic Scenedit-addunit scripts.

Remember to:

-Make sure each math.random is “contained” with its own end line.

Changing AI Missions:

Now for the Lua script in They Came From The Museum.

 

math.randomseed( os.time() )

a = math.random(1,10)

if a<5 then

ScenEdit_AssignUnitToMission(‘Ukrainian Flanker #1’, ‘NONE’)

ScenEdit_AssignUnitToMission(‘Ukrainian Flanker #2’, ‘NONE’)

ScenEdit_AssignUnitToMission(‘Ukrainian Flanker #3’, ‘NONE’)

ScenEdit_AssignUnitToMission(‘Ukrainian Flanker #4’, ‘NONE’)

ScenEdit_AssignUnitToMission(‘Ukrainian Flanker #5’, ‘NONE’)

ScenEdit_AssignUnitToMission(‘Ukrainian Flanker #6’, ‘NONE’)

elseif a>=5  and a<8 then

ScenEdit_AssignUnitToMission(‘Ukrainian Flanker #1’, ‘Close Patrol’)

ScenEdit_AssignUnitToMission(‘Ukrainian Flanker #2’, ‘Close Patrol’)

ScenEdit_AssignUnitToMission(‘Ukrainian Flanker #3’, ‘Close Patrol’)

ScenEdit_AssignUnitToMission(‘Ukrainian Flanker #4’, ‘Close Patrol’)

ScenEdit_AssignUnitToMission(‘Ukrainian Flanker #5’, ‘Close Patrol’)

ScenEdit_AssignUnitToMission(‘Ukrainian Flanker #6’, ‘Close Patrol’)

elseif a>=8 then

ScenEdit_AssignUnitToMission(‘Ukrainian Flanker #1’, ‘Aggressive Patrol’)

ScenEdit_AssignUnitToMission(‘Ukrainian Flanker #2’, ‘Aggressive Patrol’)

ScenEdit_AssignUnitToMission(‘Ukrainian Flanker #3’, ‘Aggressive Patrol’)

ScenEdit_AssignUnitToMission(‘Ukrainian Flanker #4’, ‘Aggressive Patrol’)

ScenEdit_AssignUnitToMission(‘Ukrainian Flanker #5’, ‘Aggressive Patrol’)

ScenEdit_AssignUnitToMission(‘Ukrainian Flanker #6’, ‘Aggressive Patrol’)

end

 

This is all part of a single “math.random” element, so unlike the submarine example, there’s no need to punctuate it with “Math.random (_,_), ends. If A is 4 or less, the Ukrainian Su-27s just stay at their base and don’t participate in the battle at all. If it’s 5 to 7, they launch, but do so as part of a timid patrol over their own heartland. If it’s 8 to 10, they are assigned to a patrol which has a large prosecution area.

Note that, for the extra work, making sure there’s an option to explicitly remove the units from the missions is essential-especially if you’re using a “scenario loaded” startup event. Otherwise, if it activates “Close Patrol” and the scenario developer saves, and it rolls a 3 next time, rather than cancel the mission, it will just stick with the status quo (in this case, ‘Close Patrol’)-so include a “Assign to none” option.

Also, I got tripped up by the numbers when making the script. Make sure there’s no overlapping values.

For both, you can accomplish this with a ScenEdit_Addunit(Name1) and a Scenedit_AssignunitToMission (Name1), (Mission1) command in the same script. A simple version involves going to the Bering Sea, making a patrol with the exact name NorthPatrol (no spaces), and running the following.

ScenEdit_AddUnit({type=’Ship’, side=’USN’, name=’USS Joachim Pease’, dbid=’562′, latitude=’57.9134536696492′, longitude=’-165.17805145352′})
ScenEdit_AssignUnitToMission(‘USS Joachim Pease’, ‘NorthPatrol’)

This should create a Bainbridge-class cruiser called the “USS Joachim Pease”, and immediatley assign it to the “NorthPatrol” mission (whatever that is)

Pitfalls and Promise

Best of the West, Worst of the East was a sour first start-not unplayable or unreleasable, but a learning experience. There were technical issues (the earliest Lua release had a tendency to get “stuck” on certain combinations, since fixed, especially with randomseeds added), and gameplay ones (I’ve felt I was so obsessed with the random Lua part of the scenario that I neglected the actual playtesting of it.)

Beyond that, there were issues where I felt wrong. First, in my quest to make as random and diverse a fleet as possible, I went too far from the original concept of seeing how capable the older submarines of the USSR were. A Kilo is not anyone’s idea of the “worst” sub, and neither is an Echo with heavy ASMs.

While specific details like those could be easily fixed with changes to the spawning script, I felt the issues went deeper than that. Simply making the random units happen on the player’s side at the very beginning of the scenario had its issues. This is double the case if the random units are extremely varied, as was the case in that scenario. A win-at-all-costs player could easily reload the scenario until they got the best units, and even someone who took what the scenario gave them would have the experience differ drastically based on nothing they did.

So when I next turned to Lua, I chose to limit it. Only a small portion of the scenario was actually affected by the random script, it occurred on the opponents side rather than the players, and two out of the three outcomes were not immediately obvious.

Such an experience was a lot more satisfying-adding just enough variance to a scenario without consuming it. While there are of course exceptions to every rule, my general principle after the Lua scenarios-and by seeing variance in other games-is that they should alter the difficulty or direct experience but not fundamentally change it so that its outcome becomes more determined by the random changes than by the player’s actions.

Another advantage a Lua script has over a conventional event is that it’s more easily hidden without the need to change message settings. “Event A was triggered but not fire-failed probability check” is displayed right there, but Lua just gives “Event A has been fired”, while the real roll is not noticeable (right away).

One should start small with Lua and not get discouraged, for it can do so much.