Page 1 of 1
Missile Raid function
Posted: Fri Oct 11, 2019 9:20 pm
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
RE: Missile Raid function
Posted: Sat Oct 12, 2019 8:29 am
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.
RE: Missile Raid function
Posted: Sat Oct 12, 2019 8:39 am
by SeaQueen
Not displaying correctly...
RE: Missile Raid function
Posted: Sat Oct 12, 2019 8:40 am
by SeaQueen
Definitely not displayed correctly...
RE: Missile Raid function
Posted: Sat Oct 12, 2019 10:01 am
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)
RE: Missile Raid function
Posted: Sat Oct 12, 2019 11:19 am
by KnightHawk75
Good stuff.
RE: Missile Raid function
Posted: Sat Oct 12, 2019 11:54 am
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)})
RE: Missile Raid function
Posted: Sat Oct 12, 2019 12:18 pm
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.
RE: Missile Raid function
Posted: Sat Oct 12, 2019 12:21 pm
by SeaQueen
Fixed it.