Matrix Games Forums

Forums  Register  Login  Photo Gallery  Member List  Search  Calendars  FAQ 

My Profile  Inbox  Address Book  My Subscription  My Forums  Log Out

Hierarchical IADS Code w/Shoot and Scoot Logic

 
View related threads: (in this forum | in all forums)

Logged in as: Guest
Users viewing this topic: none
  Printable Version
All Forums >> [New Releases from Matrix Games] >> Command: Modern Operations series >> Mods and Scenarios >> Lua Legion >> Hierarchical IADS Code w/Shoot and Scoot Logic Page: [1]
Login
Message << Older Topic   Newer Topic >>
Hierarchical IADS Code w/Shoot and Scoot Logic - 12/24/2021 4:56:12 PM   
SeaQueen


Posts: 1451
Joined: 4/14/2007
From: Washington D.C.
Status: offline
I wrote this code to allow scenario designers to build a flexible model of a hierarchical IADS that would include the possibility of clipping the kill chain by striking various echelon command posts. IADS elements will move periodically, following their emission period.

This first part is intended to be executed on scenario load. It defines the IADS hierarchy and initializes the state table for its components.

-- 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'

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

sa10AirDefenseRgt = {
commandPost=sa10rgtCPguid, 
equipment={sa10bmRadarGuid}, 
rdrRng=0.5*sa10BMRMaxRange, 
emitTime = 8, 
tearDownTime = 2, 
repositionTime = 2, 
setUpTime = 2, 
standByTime = 2, 
subordinates={ sa10AirDefenseBns }}

sa10AirDefenseBns = {
commandPost=sa10bnCPguid, 
equipment={sa10Bn1Guid, 
sa10Bn2Guid, sa10Bn3Guid}, 
rdrRng=0.8*sa10Range, 
emitTime = 8, 
tearDownTime = 2, 
repositionTime = 2, 
setUpTime = 2, 
standByTime = 2, 
subordinates={}}

sa21AirDefenseRgt = {
commandPost=sa21rgtCPguid, 
equipment={sa21bmRadarGuid }, 
rdrRng=0.75*sa21BMRMaxRange, 
emitTime = 8, 
tearDownTime = 2, 
repositionTime = 2, 
setUpTime = 2, 
standByTime = 2, 
subordinates={ sa21AirDefenseBns }}

sa21AirDefenseBns = {
commandPost=sa21bnCPguid, 
equipment={sa21Bn1Guid, sa21Bn2Guid, sa21Bn3Guid}, 
rdrRng=0.8*sa21Range, 
emitTime = 8, 
tearDownTime = 2, 
repositionTime = 2, 
setUpTime = 2, 
standByTime = 2, 
subordinates={}}

pansirAirDefenseCpy = {
commandPost=pantsirCpyCP, 
equipment={pantsirCpyBMRadr}, 
rdrRng=0.8*pantsirBMMaxRange, 
emitTime = 8, 
tearDownTime = 2, 
repositionTime = 2, 
setUpTime = 2, 
standByTime = 2, 
subordinates={ pantsirAirDefensePlts }}

pantsirAirDefensePlts =  {
commandPost=pantsirCpyCP, 
equipment={pantsirPlt1, pantsirPlt2, pantsirPlt3}, 
rdrRng=0.8*pantsirRange, 
emitTime = 8, 
tearDownTime = 2, 
repositionTime = 2, 
setUpTime = 2, 
standByTime = 2, 
subordinates={}}

airDefenseBrigade = {
commandPost=bgdCPguid , 
equipment={}, 
rdrRng=0,
emitTime = 8, 
tearDownTime = 2, 
repositionTime = 2, 
setUpTime = 2, 
standByTime = 2, 
subordinates={ sa21AirDefenseRgt, sa10AirDefenseRgt }}

unitStates = {}

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

                timeToCeaseEmission = unit.emitTime
                timeToCompleteTearDown = timeToCeaseEmission + unit.tearDownTime
                timeToCompleteRelocation = timeToCompleteTearDown + unit.repositionTime
                timeToCompleteSetUp = timeToCompleteRelocation + unit.setUpTime
                timeToStandBy = timeToCompleteSetUp + unit.standByTime

                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.

-- 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

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                

                    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)

                        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.
-- 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

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

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

    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!

< Message edited by SeaQueen -- 12/24/2021 5:59:58 PM >
Post #: 1
RE: Hierarchical IADS Code w/Shoot and Scoot Logic - 12/24/2021 9:46:52 PM   
KLAB


Posts: 355
Joined: 2/27/2007
Status: offline
Wow! Thanks. Merry Christmas.

(in reply to SeaQueen)
Post #: 2
RE: Hierarchical IADS Code w/Shoot and Scoot Logic - 12/25/2021 11:38:57 AM   
Parel803

 

Posts: 579
Joined: 10/10/2019
From: Netherlands
Status: offline
looks impressive, will try to learn from it.
merry Christmas

(in reply to KLAB)
Post #: 3
RE: Hierarchical IADS Code w/Shoot and Scoot Logic - 12/25/2021 2:20:39 PM   
SeaQueen


Posts: 1451
Joined: 4/14/2007
From: Washington D.C.
Status: offline
If you have any questions, please ask. I created a tree data structure that is intended to reflect the various echelons of the IADS network. It should be very flexible, and can reflect a wide variety of network topologies. On initialization or at regular intervals, it recursively descends the tree and performs various administrative actions (changing the values of variables) and then asks the SAM site to move or emit based on the administrative actions and the current picture. It's very simple, and it should be easy to customize to many different IADS behaviors.

< Message edited by SeaQueen -- 12/25/2021 2:54:00 PM >

(in reply to Parel803)
Post #: 4
RE: Hierarchical IADS Code w/Shoot and Scoot Logic - 12/26/2021 9:42:16 PM   
BDukes

 

Posts: 1695
Joined: 12/27/2017
Status: offline
Very impressive. Thank you!

Mike

_____________________________

Don't call it a comeback...

(in reply to SeaQueen)
Post #: 5
RE: Hierarchical IADS Code w/Shoot and Scoot Logic - 12/27/2021 9:28:59 AM   
SeaQueen


Posts: 1451
Joined: 4/14/2007
From: Washington D.C.
Status: offline
Be advised, I have found some bugs in this during subsequent testing. I'll probably put out a revised version soon.

(in reply to BDukes)
Post #: 6
RE: Hierarchical IADS Code w/Shoot and Scoot Logic - 12/27/2021 3:10:03 PM   
BDukes

 

Posts: 1695
Joined: 12/27/2017
Status: offline

quote:

ORIGINAL: SeaQueen

Be advised, I have found some bugs in this during subsequent testing. I'll probably put out a revised version soon.


Waa I want my money back

_____________________________

Don't call it a comeback...

(in reply to SeaQueen)
Post #: 7
RE: Hierarchical IADS Code w/Shoot and Scoot Logic - 12/27/2021 11:33:11 PM   
SeaQueen


Posts: 1451
Joined: 4/14/2007
From: Washington D.C.
Status: offline
You’re welcome to fix it yourself. I don’t generally post code with the idea that it could be used without substantial customization.

(in reply to BDukes)
Post #: 8
RE: Hierarchical IADS Code w/Shoot and Scoot Logic - 12/28/2021 1:04:46 PM   
BDukes

 

Posts: 1695
Joined: 12/27/2017
Status: offline
quote:

ORIGINAL: SeaQueen

You’re welcome to fix it yourself. I don’t generally post code with the idea that it could be used without substantial customization.


SQ its free code. I can't complain and you're awesome!

Probably should have started with that. Internet don't do tone well


< Message edited by BDukes -- 12/28/2021 1:18:48 PM >


_____________________________

Don't call it a comeback...

(in reply to SeaQueen)
Post #: 9
RE: Hierarchical IADS Code w/Shoot and Scoot Logic - 12/30/2021 12:30:09 PM   
SeaQueen


Posts: 1451
Joined: 4/14/2007
From: Washington D.C.
Status: offline
Thank you. Hopefully you've put it to good use by now. ;-)

(in reply to BDukes)
Post #: 10
Page:   [1]
All Forums >> [New Releases from Matrix Games] >> Command: Modern Operations series >> Mods and Scenarios >> Lua Legion >> Hierarchical IADS Code w/Shoot and Scoot Logic Page: [1]
Jump to:





New Messages No New Messages
Hot Topic w/ New Messages Hot Topic w/o New Messages
Locked w/ New Messages Locked w/o New Messages
 Post New Thread
 Reply to Message
 Post New Poll
 Submit Vote
 Delete My Own Post
 Delete My Own Thread
 Rate Posts


Forum Software © ASPPlayground.NET Advanced Edition 2.4.5 ANSI

6.719