Missile Raid function

All discussions & material related to Command's Lua interface

Moderators: RoryAndersonCDT, michaelm75au, angster, MOD_Command

Post Reply
User avatar
SeaQueen
Posts: 1436
Joined: Sat Apr 14, 2007 4:20 am
Location: Washington D.C.

Missile Raid function

Post by SeaQueen »

I've often been frustrated with how using missions on the computer controlled side for GLCMs and TBMs tends to result in overly conservative raids, because the AI tends to try to allocate weapons efficiently. The problem with this is that in order for a raid to be successful, you often want to build a certain amount of overkill in to account for interceptors. In order to solve that problem, I wrote this code. It allows the computer controlled side to easily follow a specific raid schedule (e.g. at time X fire Y at Z). The rest of the code I posted in this thread is an example of how I might use it notionally to model a coordinated strike by PLAAF/PLARF forces on Guam. In practice, it would have to be customized to your particular scenario. The important take away is less the specific code and more the technique.

Code: Select all

 -- returns the contact id of a unit whose guid is known
 -- use of this function avoids the need to shoot work off the contact list which is dynamic and makes it 
 -- hard to bake in fire plans
 function getContactIdOfUnit( sd, unitId )
   local contactList = ScenEdit_GetContacts(sd)
   local unitContactId
   for i, con in ipairs( contactList ) do
     local cnt = ScenEdit_GetContact({side=sd, guid=con.guid})
     if (cnt.actualunitid == unitId) then
         unitContactId = cnt.guid
       break
     end
   end
   return unitContactId 
 end
 

Code: Select all

 -- launches a raid with the "participatingUnits" firing a defined salvo size at "targetList."
 -- "participatingUnits" and "targetList" are just lists of guids for the shooters and targets, respectively
 function missileRaid( side, participatingUnits, targetList, wpnId, salvoSize )
   local tgtContactId 
   for i, u in ipairs( participatingUnits ) do
     local attacker = ScenEdit_GetUnit( {guid=u} )
     for j, tgt in ipairs( targetList ) do
       tgtContactId =  getContactIdOfUnit(side, tgt)
       if ( tgtContactId  ~= nil ) then   -- accounts for targets not on the contact list
         for k, mnt in ipairs( attacker.mounts ) do        
           for l, wpn in ipairs( mnt.mount_weapons ) do           
              if ( wpn.wpn_dbid == wpnId ) then 
                if ( wpn.wpn_current > 0 ) then 
                   ScenEdit_AttackContact(attacker.guid, tgtContactId, {mode='ManualWeaponAlloc', mount=mnt.mount_dbid, weapon=wpnId, qty=salvoSize  })
                end
             end
           end
         end
       end
     end
   end
 end
 
User avatar
SeaQueen
Posts: 1436
Joined: Sat Apr 14, 2007 4:20 am
Location: Washington D.C.

RE: Missile Raid function

Post by SeaQueen »

To be used with the above functions, I wrote this code which sets the firing time for Time Triggers. I'd run this at scenario load in order to ensures that the right number of TBM/GLCMs get fired at the right time:

I could probably modify the code to use for ALCMs/SLCMs but I'd have to take into account the position of the launch platform somehow since they move. If I did it that way, then I could have them fly or sail out to their launch baskets and fire at a specific time for coordination purposes. I need to think about that one more. I also included a "rolex" variable to add an arbitrary time offset to the whole war. I don't use it at this point, but someday I might.

Code: Select all

 -- scenario timing constants
 
 oneMinute = 60
 fiveMinutes = 5 * oneMinute
 fifteenMinutes = 15 * oneMinute
 oneHour = 60*oneMinute 
 threeHours = 3 * oneHour
 sixHours = 6 * oneHour
 oneDay = 24*oneHour 
 
 -- randomizes time on target so that I don't know exactly when the raid will come
 mainStrikeMedianTimeOnTarget = os.time{ year=2020, month=6, day=21, hour=14, min= 00, sec=0 }
 rolex = 0
 
 
 -- the +/- three hours ensures the strike will occur within a 6 hour launch window.  It could be whatever you want.
 mainStrikeTimeOnTarget = mainStrikeMedianTimeOnTarget  + math.random( (-1*threeHours) , threeHours ) + rolex
 
 -- typically I'll put this code in a separate LUA action, just for modularity, but there's no reason it can't
 -- be in the same as the above code it just depends on how you roll.
 
 -- SEAD dedicated strikes will arrive on target five minutes prior to the main strike (480 kts * 5 min = 40 Nmi)
 
 local seadTimeOnTarget = mainStrikeTimeOnTarget - fiveMinutes 
 

Code: Select all

 -- andersenAFB is just the guid of the target for that portion of the raid, it could be anywhere.  I just used
 -- andersen because I developed the code for a Guam raid scenario.  Change as it suits your purposes.  
 -- Similarly, "firstBnFirstBgd," "secondBnFirstBgd," etc. are set to guids of TBM battalions
 
 local distanceFromFirstBnFirstBgdToAndersen = Tool_Range( firstBnFirstBgd , andersenAFB)
 local distanceFromFirstBnSecondBgdToAndersen = Tool_Range( firstBnSecondBgd , andersenAFB)
 
 local distanceFromSecondBnFirstBgdToAndersen = Tool_Range( secondBnFirstBgd , andersenAFB)
 local distanceFromSecondBnSecondBgdToAndersen = Tool_Range( secondBnSecondBgd , andersenAFB)
 
 local missileSpeed = 7500 
 
 local missileFirstBnFirstBgdFlyoutTime = (distanceFromFirstBnFirstBgdToAndersen / missileSpeed ) * oneHour
 local missileFirstBnSecondBgdFlyoutTime = (distanceFromFirstBnSecondBgdToAndersen / missileSpeed) * oneHour
 
 local missileSecondBnFirstBgdFlyoutTime = ( distanceFromSecondBnFirstBgdToAndersen / missileSpeed ) * oneHour
 local missileSecondBnSecondBgdFlyoutTime = ( distanceFromSecondBnSecondBgdToAndersen / missileSpeed) * oneHour
 
 local tbmFirstBnFirstBgdSeadMissionStartTime = seadTimeOnTarget - missileFirstBnFirstBgdFlyoutTime 
 local tbmFirstBnSecondBgdSeadMissionStartTime = seadTimeOnTarget - missileFirstBnSecondBgdFlyoutTime
 

Code: Select all

 local tbmSecondBnFirstBgdMainStrikeMissionStartTime = mainStrikeTimeOnTarget - missileSecondBnFirstBgdFlyoutTime 
 local tbmSecondBnSecondBgdMainStrikeMissionStartTime = mainStrikeTimeOnTarget - missileSecondBnSecondBgdFlyoutTime
 
 local tbmFirstBnFirstBgdSEADMissionTrigger = ScenEdit_GetEvent('Launch Northern TBM SEAD Raid', 2)
 local tbmFirstBnSecondBgdSEADMissionTrigger = ScenEdit_GetEvent('Time For Southern TBM Raid - SEAD Wave', 2)
 
 local tbmFirstBnFirstBgdSEADMissionEvent = ScenEdit_GetEvent('Launch Southern TBM SEAD Raid', 1)
 local tbmFirstBnSecondBgdSEADMissionEvent = ScenEdit_GetEvent('Launch Northern TBM SEAD Raid', 1)
 
 local tbmSecondBnFirstBgdMainMissionEvent = ScenEdit_GetEvent('Launch Southern TBM Main Raid', 1)
 local tbmSecondBnSecondBgdMainMissionEvent = ScenEdit_GetEvent('Launch Northern TBM Main Raid', 1)
 
 local tbmFirstBnFirstBgdSEADMissionTriggerID =  tbmFirstBnFirstBgdSEADMissionEvent.details.triggers[1].Time.ID
 local tbmFirstBnSecondBgdSEADMissionTriggerID =  tbmFirstBnSecondBgdSEADMissionEvent.details.triggers[1].Time.ID
 local tbmSecondBnFirstBgdMainMissionTriggerID =  tbmSecondBnFirstBgdMainMissionEvent.details.triggers[1].Time.ID
 local tbmSecondBnSecondBgdMainMissionTriggerID = tbmSecondBnSecondBgdMainMissionEvent.details.triggers[1].Time.ID
 
 ScenEdit_SetTrigger( {Description=tbmFirstBnFirstBgdSEADMissionTriggerID,  Time=os.date('%m/%d/%Y %I:%M:%S %p', tbmFirstBnFirstBgdSeadMissionStartTime )    } )
 ScenEdit_SetTrigger( {Description=tbmFirstBnSecondBgdSEADMissionTriggerID ,  Time=os.date('%m/%d/%Y %I:%M:%S %p', tbmFirstBnSecondBgdSeadMissionStartTime )    } )
 
 ScenEdit_SetTrigger( {Description=tbmSecondBnFirstBgdMainMissionTriggerID  ,  Time=os.date('%m/%d/%Y %I:%M:%S %p', tbmSecondBnFirstBgdMainStrikeMissionStartTime )    } )
 ScenEdit_SetTrigger( {Description= tbmSecondBnSecondBgdMainMissionTriggerID ,  Time=os.date('%m/%d/%Y %I:%M:%S %p', tbmSecondBnSecondBgdMainStrikeMissionStartTime )    } )
 

Not sure this is displayed correctly.
User avatar
SeaQueen
Posts: 1436
Joined: Sat Apr 14, 2007 4:20 am
Location: Washington D.C.

RE: Missile Raid function

Post by SeaQueen »

Not displaying correctly...
User avatar
SeaQueen
Posts: 1436
Joined: Sat Apr 14, 2007 4:20 am
Location: Washington D.C.

RE: Missile Raid function

Post by SeaQueen »

Definitely not displayed correctly...
User avatar
SeaQueen
Posts: 1436
Joined: Sat Apr 14, 2007 4:20 am
Location: Washington D.C.

RE: Missile Raid function

Post by SeaQueen »

Finally, the Time trigger (in this case 'Launch Southern TBM Main Raid') fires a LUA action similar to this:

"andersenRnwys" and "andersenFuel" are just arrays of guids containing the target set.

Code: Select all

 local mainStkRnwyShooters = { secondBnSecondBgd }  
 local mainStkFuelShooters = { thirdBnSecondBgd,  fourthBnSecondBgd}  
 
 -- shoots a salvo of 2 per target at the runways
 missileRaid('CHN', mainStkRnwyShooters, andersenRnwys, df26Id, 2)
 
 -- shoots a salvo of 1 per target at the POL storage facilities
 missileRaid('CHN', mainStkFuelShooters, andersenFuel, df26Id, 1)
 
KnightHawk75
Posts: 1850
Joined: Thu Nov 15, 2018 7:24 pm

RE: Missile Raid function

Post by KnightHawk75 »

Good stuff.
User avatar
SeaQueen
Posts: 1436
Joined: Sat Apr 14, 2007 4:20 am
Location: Washington D.C.

RE: Missile Raid function

Post by SeaQueen »

This code sets the mission start times for the ALCM equipped bombers so that it's automatically coordinated with the TBM raid. Typically I would run this at scenario load as well, so that everything gets aligned from the start.

Code: Select all

 -- SEAD dedicated strikes will arrive on target five minutes prior to the main strike (480 kts * 5 min = 40 Nmi)
 -- note these mission start times hang off the mainStrikeTimeOnTarget calculated in the earlier code
 
 local seadTimeOnTarget = mainStrikeTimeOnTarget - fiveMinutes 
 
 local distanceFromLeiyangToAndersen = Tool_Range(leiyangAB, andersenAFB)
 local distanceFromLeiyangToKD20LaunchBasket = distanceFromLeiyangToAndersen - kd20Range
 
 local aircraftSpeed = 420 -- knots
 local kd20speed = 500 -- knots
 local aircraftFlyoutTime = ( distanceFromLeiyangToKD20LaunchBasket / aircraftSpeed ) * oneHour -- conversion factor applied (hours to seconds)
 local kd20FlyoutTime = ( kd20Range / kd20speed ) * oneHour -- conversion factor applied (hours to seconds)
 
 local H6KSeadMissionStartTime = seadTimeOnTarget - ( aircraftFlyoutTime + kd20FlyoutTime )
 local H6KMainStrikeMissionStartTime = mainStrikeTimeOnTarget -  ( aircraftFlyoutTime + kd20FlyoutTime )
 
 local H6KSeadMission = ScenEdit_GetMission('CHN', 'SEAD Strike (H6K)')
 ScenEdit_SetMission('CHN', H6KSeadMission.guid,  {starttime=os.date('%m/%d/%Y %I:%M:%S %p',H6KSeadMissionStartTime)})
 
 local H6KOpenedParkingStrikeMission = ScenEdit_GetMission('CHN', 'Strike - Opened Parking (H6K)')
 ScenEdit_SetMission('CHN', H6KOpenedParkingStrikeMission.guid,  {starttime=os.date('%m/%d/%Y %I:%M:%S %p',H6KMainStrikeMissionStartTime)})
 
Whicker
Posts: 665
Joined: Tue Jun 19, 2018 9:54 pm

RE: Missile Raid function

Post by Whicker »

if you put it in a quote it will work - for some reason the code tag has max height so it gets screwed up like that.
User avatar
SeaQueen
Posts: 1436
Joined: Sat Apr 14, 2007 4:20 am
Location: Washington D.C.

RE: Missile Raid function

Post by SeaQueen »

Fixed it.
Post Reply

Return to “Lua Legion”