This first part is intended to be executed on scenario load. It defines the IADS hierarchy and initializes the state table for its components.
Code: Select all
-- initialization
asvRadarGuid = 'GWKW9V-0HME4FG8F0I72'
bgdCPguid = 'GWKW9V-0HME4FGAIAD73'
sa10rgtCPguid = 'GWKW9V-0HME4FG8F0HPC'
sa10bnCPguid = 'GWKW9V-0HME4FG95CU8I'
sa10bmRadarGuid = 'GWKW9V-0HME4FG8F0HPJ'
sa10Bn1Guid='GWKW9V-0HME4FG8F0I36'
sa10Bn2Guid='GWKW9V-0HME4FG8F0I0B'
sa10Bn3Guid='GWKW9V-0HME4FG8F0HPO'
sa21rgtCPguid = 'GWKW9V-0HME4FGAI6D4S'
sa21bnCPguid = 'GWKW9V-0HME4FGAHSGSH'
sa21bmRadarGuid = 'GWKW9V-0HME4FGAHTDR6'
sa21Bn1Guid= 'GWKW9V-0HME4FGAHRUG7'
sa21Bn2Guid= 'GWKW9V-0HME4FGAHS03V'
sa21Bn3Guid= 'GWKW9V-0HME4FGAHS15G'
pantsirCpyCP = 'GWKW9V-0HME4FGBBM6A5'
pantsirCpyBMRadr = 'GWKW9V-0HME4FGBBPDRI'
pantsirPlt1 = 'GWKW9V-0HME4FGBBM05M'
pantsirPlt2 = 'GWKW9V-0HME4FGBBM1RT'
pantsirPlt3 = 'GWKW9V-0HME4FGBBM2I5'
Code: Select all
pantsirBMMaxRange = 135 -- Max launch range of a FLATFACE-E Radar
pantsirRange = 10 -- Max launch range of an SA-22
sa10BMRMaxRange = 325 -- Max range for a BIG BIRD B
sa10Range = 40 -- Max launch range of an SA-10
sa21BMRMaxRange = 325 -- Max range for a BIG BIRD D
sa21Range = 215 -- Max launch range of an SA-21
-- weapons control states
wcsFree = 0
wcsTight = 1
wcsHold = 2
Code: Select all
sa10AirDefenseRgt = {
commandPost=sa10rgtCPguid,
equipment={sa10bmRadarGuid},
rdrRng=0.5*sa10BMRMaxRange,
emitTime = 8,
tearDownTime = 2,
repositionTime = 2,
setUpTime = 2,
standByTime = 2,
subordinates={ sa10AirDefenseBns }}
Code: Select all
sa10AirDefenseBns = {
commandPost=sa10bnCPguid,
equipment={sa10Bn1Guid,
sa10Bn2Guid, sa10Bn3Guid},
rdrRng=0.8*sa10Range,
emitTime = 8,
tearDownTime = 2,
repositionTime = 2,
setUpTime = 2,
standByTime = 2,
subordinates={}}
Code: Select all
sa21AirDefenseRgt = {
commandPost=sa21rgtCPguid,
equipment={sa21bmRadarGuid },
rdrRng=0.75*sa21BMRMaxRange,
emitTime = 8,
tearDownTime = 2,
repositionTime = 2,
setUpTime = 2,
standByTime = 2,
subordinates={ sa21AirDefenseBns }}
Code: Select all
sa21AirDefenseBns = {
commandPost=sa21bnCPguid,
equipment={sa21Bn1Guid, sa21Bn2Guid, sa21Bn3Guid},
rdrRng=0.8*sa21Range,
emitTime = 8,
tearDownTime = 2,
repositionTime = 2,
setUpTime = 2,
standByTime = 2,
subordinates={}}
Code: Select all
pansirAirDefenseCpy = {
commandPost=pantsirCpyCP,
equipment={pantsirCpyBMRadr},
rdrRng=0.8*pantsirBMMaxRange,
emitTime = 8,
tearDownTime = 2,
repositionTime = 2,
setUpTime = 2,
standByTime = 2,
subordinates={ pantsirAirDefensePlts }}
Code: Select all
pantsirAirDefensePlts = {
commandPost=pantsirCpyCP,
equipment={pantsirPlt1, pantsirPlt2, pantsirPlt3},
rdrRng=0.8*pantsirRange,
emitTime = 8,
tearDownTime = 2,
repositionTime = 2,
setUpTime = 2,
standByTime = 2,
subordinates={}}
Code: Select all
airDefenseBrigade = {
commandPost=bgdCPguid ,
equipment={},
rdrRng=0,
emitTime = 8,
tearDownTime = 2,
repositionTime = 2,
setUpTime = 2,
standByTime = 2,
subordinates={ sa21AirDefenseRgt, sa10AirDefenseRgt }}
unitStates = {}
Code: Select all
function initializeUnitStates(unit, thisSide)
initialized = false
if(ScenEdit_GetUnit({side=mySide, guid=unit.commandPost}) ~= nil) then
if(unit.subordinates ~= nil) then
for s, sub in ipairs(unit.subordinates) do
initializeUnitStates(sub, thisSide)
end
end
if(unit.equipment ~= {}) then
for e, eqp in ipairs(unit.equipment) do
timeToCompleteEvolution = unit.emitTime + unit.tearDownTime + unit.repositionTime + unit.setUpTime + unit.standByTime
Code: Select all
timeToCeaseEmission = unit.emitTime
timeToCompleteTearDown = timeToCeaseEmission + unit.tearDownTime
timeToCompleteRelocation = timeToCompleteTearDown + unit.repositionTime
timeToCompleteSetUp = timeToCompleteRelocation + unit.setUpTime
timeToStandBy = timeToCompleteSetUp + unit.standByTime
Code: Select all
time = math.random(0, timeToCompleteEvolution )
if time < timeToCeaseEmission then
unitStates[eqp] = { state="canEmit", minutesInState = time }
elseif ( (time >= timeToCeaseEmission) and ( time < timeToCompleteTearDown )) then
unitStates[eqp] = { state="tearingDown", minutesInState = (time - timeToCeaseEmission) }
elseif ( ( time >= timeToCompleteTearDown ) and (time < timeToCompleteRelocation )) then
unitStates[eqp] = { state="repositioning", minutesInState = (time - timeToCompleteTearDown) }
elseif ( (time >= timeToCompleteRelocation ) and ( time < timeToCompleteSetUp )) then
unitStates[eqp] = { state="settingUp", minutesInState = (time - timeToCompleteRelocation) }
else
unitStates[eqp] = { state="standingBy", minutesInState = (time - timeToCompleteSetUp ) }
end
end
end
return true
else
return false -- return false if unit is improperly defined
end
end
initializeUnitStates(airDefenseBrigade)
The next bit of code is intended to executed every minute. It manages whether whether the IADS components are setting up, tearing down, moving, or whether they could emit should a worthwhile target come close enough to make it worth lighting up one's organic radars.
Code: Select all
-- execute every minute
function randomWaypoint(currentPosition, dist)
math.randomseed( os.time() ) -- removes correlations (not)
r = math.random(0, 359)
print(r)
newpos=World_GetPointFromBearing( {latitude=tostring(currentPosition.latitude), longitude=tostring(currentPosition.longitude), distance = dist, bearing = r} )
print(newpos)
--wpt = {latitude = newpos.latitude, longitude = newpos.longitude}
wpt = {TypeOf = 'ManualPlottedCourseWaypoint', latitude = newpos.latitude, longitude = newpos.longitude}
return wpt
end
Code: Select all
function manageUnitEMCONandMobilityStates(unit, thisSide)
if(ScenEdit_GetUnit({side=thisSide, guid=unit.commandPost}) ~= nil) then
if(unit.subordinates ~= nil) then
for s, sub in ipairs(unit.subordinates) do
manageUnitEMCONandMobilityStates(sub, thisSide)
end
end
if(next(unit.equipment) ~= nil) then
timeToCompleteEvolution = unit.emitTime + unit.tearDownTime + unit.repositionTime + unit.setUpTime + unit.standByTime
for e, eqp in ipairs(unit.equipment) do
if( unitStates[eqp] ~= nil) then
unitStates[eqp].minutesInState = unitStates[eqp].minutesInState + 1
print(eqp..": state = "..unitStates[eqp].state..", minutesinstate = "..unitStates[eqp].minutesInState)
if unitStates[eqp].state == 'canEmit' then
ScenEdit_SetUnit({side=thisSide, guid=eqp, course={}, speed = 0, holdposition=true })
if unitStates[eqp].minutesInState >= unit.emitTime then
unitStates[eqp].state = 'tearingDown'
unitStates[eqp].minutesInState = 0
break
end
Code: Select all
elseif unitStates[eqp].state == 'tearingDown' then
ScenEdit_SetUnit({side=thisSide, guid=eqp, course={}, speed = 0, holdposition=true })
if unitStates[eqp].minutesInState >= unit.tearDownTime then
unitStates[eqp].state = 'repositioning'
unitStates[eqp].minutesInState = 0
break
end
elseif unitStates[eqp].state == 'repositioning' then
repositionSpeed = 35 -- NM/hr
u = ScenEdit_GetUnit({side=thisside, guid=eqp})
if ( unitStates[eqp].minutesInState < unit.repositionTime) then
newPosition = randomWaypoint( {latitude=u.latitude, longitude=u.longitude}, (repositionSpeed * unit.repositionTime / 60) )
--print(u.name..": latitude= "..newPosition.latitude..", longitude= "..newPosition.longitude)
ScenEdit_SetUnit({side=thisSide, guid=eqp, course={newPosition}, speed = repositionSpeed, holdposition=false })
print(u.course)
Code: Select all
else
if unitStates[eqp].minutesInState >= unit.repositionTime then
unitStates[eqp].state = 'settingUp'
unitStates[eqp].minutesInState = 0
break
end
end
elseif unitStates[eqp].state == 'settingUp' then
ScenEdit_SetUnit({side=thisSide, guid=eqp, course={}, speed = 0, holdposition=true })
if unitStates[eqp].minutesInState >= unit.setUpTime then
unitStates[eqp].state = 'standingBy'
unitStates[eqp].minutesInState = 0
break
end
elseif unitStates[eqp].state == 'standingBy' then
ScenEdit_SetUnit({side=thisSide, guid=eqp, course={}, speed = 0, holdposition=true })
if unitStates[eqp].minutesInState >= timeToCompleteEvolution then
unitStates[eqp].state = 'canEmit'
unitStates[eqp].minutesInState = 0
break
end
end
end
end
end
end
return true
end
manageUnitEMCONandMobilityStates( airDefenseBrigade )
This third part is intended to execute every 15 seconds. It recursively descends the hierarchy tree and determines if a unit component is in a state where it could emit, then adjusts its WCS and EMCON appropriately.
Code: Select all
-- execute every 15 seconds
function equipmentCanEmit(elementGuid)
canEmit = false
if(unitStates[elementGuid] ~= nil) then
if( unitStates[elementGuid].state == "canEmit" ) then
canEmit = true
end
end
return canEmit
end
Code: Select all
function atLeastOneContactIsInRangeOfEquipment(list, unitGuid, range)
cntctInRng = false
for c, cntc in ipairs(contactList) do
trk = ScenEdit_GetContact({side=mySide, guid=cntc.guid})
trkRng = Tool_Range(unitGuid, {latitude=trk.latitude, longitude=trk.longitude})
print(trkRng..", "..range)
if (trkRng <= range) then
cntctInRng = true;
end
end
return cntctInRng
end
Code: Select all
function manageIADSEchelonEmconAndWCS(unit, thisSide)
if(ScenEdit_GetUnit({side=mySide, guid=unit.commandPost}) ~= nil) then
if(unit.subordinates ~= nil) then
for s, sub in ipairs(unit.subordinates) do
manageIADSEchelonEmconAndWCS(sub, thisSide)
end
end
contactList = ScenEdit_GetContacts(thisSide)
if(unit.equipment ~= {}) then
for e, eqp in ipairs(unit.equipment) do
if( ScenEdit_GetUnit({side=thisSide, guid=eqp}) ~= nil ) then
u=ScenEdit_GetUnit({side=thisSide, guid=eqp})
if( atLeastOneContactIsInRangeOfEquipment(contactList, eqp, unit.rdrRng) and equipmentCanEmit(eqp) ) then
print("Turning on radar.")
ScenEdit_SetEMCON('Unit', eqp, "Radar=Active;Sonar=Passive;OECM=Passive")
ScenEdit_SetDoctrine({side = thisSide, unitname=u.name }, { weapon_control_status_air = wcsTight })
else
print("Turning off radar.")
ScenEdit_SetEMCON('Unit', eqp, "Radar=Passive;Sonar=Passive;OECM=Passive")
ScenEdit_SetDoctrine({side = thisSide, unitname=u.name }, { weapon_control_status_air = wcsHold })
end
end
end
end
return true
Code: Select all
else
-- execute alternative emcon/wcs management plan (currently none)
return false -- return false if echelon command post is destroyed
end
end
manageIADSEchelonEmconAndWCS(airDefenseBrigade, "RUS")
Merry Christmas!
