-- ***************************************************************************** -- ** CAPZone War ** -- ********************************************************* --region CAPZoneWarConfigFunctions -- @type CAPPArameterConfig -- @field #number patrolFloor Patrol floor in feet. -- @field #number patrolCeiling Patrol ceiling in feet. -- @field #number minPatrolSpeed Minimum patrol speed in knots. -- @field #number maxPatrolSpeed Maximum patrol speed in knots. -- @field #number minEngageSpeed Minimum engage speed in knots. -- @field #number maxEngageSpeed Maximum engage speed in knots. -- @field #number engageFloor Engage floor in feet. -- @field #number engageCeiling Engage ceiling in feet. -- @type GCICAPSquadronConfig -- @field #string name Squadron Name -- @field #string template Template name -- @field #number skill Skill -- @field #number nb_aircrafts Number of aircrafts -- @field #string role Role of the squadron -- @field #RadioConfig radio Radio configuration -- @field #TacanConfig tacan TACAN configuration -- @field #string modex ModeX configuration -- @field #string livery Livery configuration -- @type CAPZoneWarConfig -- @field #boolean enable Enable CAP Zone creation. -- @field #string name Name of the CAP Zone. -- @field #boolean debug Debug mode for the CAP Zone. -- @field #string borderZoneName Name of the border zone group. -- @field #number detectionGroupingRadius Detection grouping radius in NM. -- @field #number engageRadius Engage radius in NM. -- @field #number fuelLowThreshold Fuel low threshold -- @field #number fuelCriticalThreshold Fuel critical threshold -- @field #boolean supportInvisible Support invisible for the CAP Zone. -- @field #number maxAliveMissions Maximum number of alive missions -- @field #number defaultGrouping Default grouping -- @field #number turnoverTime Turnover time -- @field #number repairTime Repair time -- @field #number numberAlert5Standby Number of alert 5 standby -- @field #number overhead Overhead coefficient -- @field #string[] ewrPrefixes EWR prefixes to use for the CAP Zone. -- @field #CAPZoneWarAirbaseConfig[] capZoneWarAirbases CAPZoneWar Airbases configuration. -- @field #CAPPArameterConfig capParameters CAP parameters. -- @type CAPZoneWarAirbaseConfig -- @field #string name AirBase Name -- @field #boolean enable Enable AirBase for the CAP Zone. -- @field #GCICAPSquadronConfig[] squadrons Squadrons configuration. -- @field #string patrolZoneName Name of the WRAPPER.GROUP or CORE.ZONE defining the patrol Zone --- Parse CAPWarZone config Object. -- @param #JsonObject config Config object to parse -- @return #CAPZoneWarConfig capWarZoneConfigJson Parsed CAPZoneWarConfig object function ParseCAPWarZoneConfigJson(config) local json = require('Scripts/json') local parser_name = "CAP_WAR_ZONE" -- ************************************************************************** -- enable -- ************************************************************************** local capWarZoneConfigJson if config.enable == true then capWarZoneConfigJson = config else capWarZoneConfigJson = { enable = false, } end Jtff_log.debug( string.format( "parsed CAP WarZone config for %s Zone, resulting config :\n%s", config.type or "", json:encode( capWarZoneConfigJson, { indent = true } ) ), parser_name ) return capWarZoneConfigJson end -- endregion CAPZoneWarConfigFunctions -- region CAPZoneWarFunctions function toggleDebugCapWarZone(objCapWarZone) objCapWarZone.Monitor = not(objCapWarZone.Monitor) end function WipeCapWarZone(objCapWarZone) Jtff_log.info( string.format( "%s Zone Stopping...", objCapWarZone.customconfig.name ), "CAP_WAR_ZONE" ) --TODO: remove all drawings generated by CAPSquadrons objCapWarZone.Monitor = false objCapWarZone.debug = false for _airbase, _wing in pairs(objCapWarZone.wings or {}) do Jtff_log.debug( string.format( "%s Airwing Stopping...", objCapWarZone.wings[_airbase][1].alias ), "CAP_WAR_ZONE" ) for _indexMission, _mission in pairs(objCapWarZone.wings[_airbase][1].missionqueue or {}) do Jtff_log.debug( string.format( "Airwings %s mission %s cancelling...", objCapWarZone.wings[_airbase][1].alias, _mission:GetName() ), "CAP_WAR_ZONE" ) for _index,opsGroup in pairs(_mission:GetOpsGroups()) do opsGroup:RTB(opsGroup.legion.airbase) end _mission:Cancel() end for _indexSquadron, _squadron in pairs(objCapWarZone.wings[_airbase][1].cohorts or {}) do Jtff_log.debug( string.format( "%s Squadron Stopping...", _squadron.name ), "CAP_WAR_ZONE" ) _squadron:Stop() for _index,v in pairs(_COHORTNAMES) do if v == _squadron.name then table.remove(_COHORTNAMES, _index) break end end end _wing[1]:Stop() end objCapWarZone:Stop() objCapWarZone.objMenu:RemoveSubMenus() MENU_MISSION_COMMAND:New( "Start ".. objCapWarZone.customconfig.name .. " CAP War Zone", objCapWarZone.objMenu, StartCapWarZone, objCapWarZone) trigger.action.outText('CAP War Zone '..(objCapWarZone.customconfig.name)..' disabled !!', 30) end function StartCapWarZone(objCapWarZone) Jtff_log.info( string.format( "%s Zone Starting...", objCapWarZone.customconfig.name ), "CAP_WAR_ZONE" ) local capwarzoneconfig = objCapWarZone.customconfig local borderZone = objCapWarZone.jtff_borderZone local patrolZones = objCapWarZone.jtff_patrolZones local objMenu = objCapWarZone.objMenu objCapWarZone = EASYGCICAP:New( string.format("CAP War Zone %s",capwarzoneconfig.name), capwarzoneconfig.capZoneWarAirbases[1].name, STATIC:FindByName(capwarzoneconfig.capZoneWarAirbases[1].name):GetCoalitionName(), capwarzoneconfig.ewrPrefixes ) objCapWarZone.jtff_borderZone = borderZone objCapWarZone.jtff_patrolZones = patrolZones objCapWarZone.objMenu = objMenu objCapWarZone.customconfig = capwarzoneconfig objCapWarZone:SetFuelLow(capwarzoneconfig.fuelLowThreshold or 25) objCapWarZone:SetFuelCritical(capwarzoneconfig.fuelCriticalThreshold or 15) objCapWarZone:SetCAPFormation(ENUMS.Formation.FixedWing.FingerFour.Group) objCapWarZone:SetTankerAndAWACSInvisible(capwarzoneconfig.supportInvisible or false) objCapWarZone:SetMaxAliveMissions(capwarzoneconfig.maxAliveMissions or 6) objCapWarZone:SetDefaultResurrection(900) objCapWarZone:SetDefaultRepeatOnFailure(3) objCapWarZone:SetDefaultTakeOffType('hot') objCapWarZone:SetDefaultCAPSpeed(math.random(capwarzoneconfig.capParameters.minPatrolSpeed, capwarzoneconfig.capParameters.maxPatrolSpeed)) objCapWarZone:SetDefaultCAPAlt(math.random(capwarzoneconfig.capParameters.patrolFloor, capwarzoneconfig.capParameters.patrolCeiling)) objCapWarZone:SetDefaultCAPLeg(20) objCapWarZone:SetDefaultCAPGrouping(capwarzoneconfig.defaultGrouping or 2) objCapWarZone:SetDefaultMissionRange(120) objCapWarZone:SetDefaultDespawnAfterLanding() objCapWarZone:SetDefaultTurnoverTime(capwarzoneconfig.turnoverTime or 10, capwarzoneconfig.repairTime or 20) objCapWarZone:SetDefaultNumberAlert5Standby(capwarzoneconfig.numberAlert5Standby or 2) objCapWarZone:SetDefaultEngageRange(capwarzoneconfig.engageRadius or 50) objCapWarZone:SetDefaultOverhead(capwarzoneconfig.overhead or 1) objCapWarZone.debug = capwarzoneconfig.debug or false objCapWarZone.Monitor = capwarzoneconfig.debug or false if type(GROUP:FindByName( capwarzoneconfig.borderZoneName )) ~= 'nil' then objCapWarZone:AddAcceptZone(ZONE_POLYGON:FindByName(capwarzoneconfig.borderZoneName)) elseif type(ZONE:New(capwarzoneconfig.borderZoneName)) ~= 'nil' then objCapWarZone:AddAcceptZone(ZONE:FindByName(capwarzoneconfig.borderZoneName)) end for _indexAirbase, _czwAirbaseconfig in ipairs(capwarzoneconfig.capZoneWarAirbases) do local airbaseconfig = _czwAirbaseconfig if airbaseconfig.enable == true then Jtff_log.info( string.format( 'creation Airbase %s: ...', airbaseconfig.name ), "CAP_WAR_ZONE" ) if _indexAirbase ~= 1 then objCapWarZone:AddAirwing( airbaseconfig.name, airbaseconfig.name ) end local patrolZone = {} local patrolZoneVisibility if objCapWarZone.debug == true then patrolZoneVisibility = -1 else patrolZoneVisibility = objCapWarZone.coalition end if type(GROUP:FindByName( airbaseconfig.patrolZoneName )) ~= 'nil' then patrolZone = ZONE_POLYGON:FindByName(airbaseconfig.patrolZoneName) if type(patrolZone) == 'nil' then patrolZone = ZONE_POLYGON:New( airbaseconfig.patrolZoneName, GROUP:FindByName( airbaseconfig.patrolZoneName ) ):DrawZone( patrolZoneVisibility, {1,0,0}, 1, {1,1,0}, 0.10, 4, true, nil ) end table.insert( objCapWarZone.jtff_patrolZones, patrolZone ) objCapWarZone:AddConflictZone(ZONE_POLYGON:FindByName(airbaseconfig.patrolZoneName)) elseif type(ZONE:FindByName(airbaseconfig.patrolZoneName)) ~= 'nil' then patrolZone = ZONE:FindByName(airbaseconfig.patrolZoneName):DrawZone( patrolZoneVisibility, {1,0,0}, 1, {1,1,0}, 0.10, 4, true, nil ) table.insert( objCapWarZone.jtff_patrolZones, patrolZone ) objCapWarZone:AddConflictZone(ZONE:FindByName(airbaseconfig.patrolZoneName)) else patrolZone = ZONE:New(airbaseconfig.patrolZoneName):DrawZone( patrolZoneVisibility, {1,0,0}, 1, {1,1,0}, 0.10, 4, true, nil ) table.insert( objCapWarZone.jtff_patrolZones, patrolZone ) objCapWarZone:AddConflictZone(ZONE:FindByName(airbaseconfig.patrolZoneName)) end for _, _squadronconfig in ipairs(airbaseconfig.squadrons) do if _squadronconfig.role == 'fighter' then objCapWarZone:AddSquadron( _squadronconfig.template, _squadronconfig.name, airbaseconfig.name, _squadronconfig.nb_aircrafts, _squadronconfig.skill, _squadronconfig.modex or nil, _squadronconfig.livery or nil ) elseif _squadronconfig.role == 'awacs' then objCapWarZone:AddAWACSSquadron( _squadronconfig.template, _squadronconfig.name, airbaseconfig.name, _squadronconfig.nb_aircrafts, _squadronconfig.skill, _squadronconfig.modex or nil, _squadronconfig.livery or nil, _squadronconfig.radio.frequency or 251.000, _squadronconfig.radio.modulation or radio.modulation.AM ) objCapWarZone:AddPatrolPointAwacs( airbaseconfig.name, objCapWarZone.jtff_borderZone:GetRandomCoordinate(), 28000, 320, math.random(0, 359), 20 ) elseif _squadronconfig.role == 'tanker' then objCapWarZone:AddTankerSquadron( _squadronconfig.template, _squadronconfig.name, airbaseconfig.name, _squadronconfig.nb_aircrafts, _squadronconfig.skill, _squadronconfig.modex or nil, _squadronconfig.livery or nil, _squadronconfig.radio.frequency or 251.000, _squadronconfig.radio.modulation or radio.modulation.AM, _squadronconfig.tacan.channel or nil ) objCapWarZone:AddPatrolPointTanker( airbaseconfig.name, objCapWarZone.jtff_borderZone:GetRandomCoordinate(), 25000, 320, math.random(0, 359), 20 ) end end if airbaseconfig.nbMaxPatrols > 0 then for _i = 1,math.max(1,math.random(airbaseconfig.nbMinPatrols, airbaseconfig.nbMaxPatrols)), 1 do objCapWarZone:AddPatrolPointCAP( airbaseconfig.name, ZONE_POLYGON:FindByName(airbaseconfig.patrolZoneName):GetRandomCoordinate() or ZONE:FindByName(airbaseconfig.patrolZoneName):GetRandomCoordinate(), math.random( capwarzoneconfig.capParameters.patrolFloor, capwarzoneconfig.capParameters.patrolCeiling ), math.random( capwarzoneconfig.capParameters.minPatrolSpeed, capwarzoneconfig.capParameters.maxPatrolSpeed ), math.random(0, 359), 20 ) end end end end objCapWarZone.objMenu:RemoveSubMenus() MENU_MISSION_COMMAND:New( "Stop ".. capwarzoneconfig.name .. " CAP War Zone", objCapWarZone.objMenu, WipeCapWarZone, objCapWarZone ) MENU_MISSION_COMMAND:New( "Toggle Display Status ".. capwarzoneconfig.name .. " CAP War Zone", objCapWarZone.objMenu, toggleDebugCapWarZone, objCapWarZone ) end -- endregion CAPZoneWarFunctions CAPWarZoneArray = {} local compteur = #CAPWarZoneArray MenuMissionCAPWarZone = MENU_MISSION:New("CAP War Zones", nil) for _index, currentCAPWarZoneConfigObject in ipairs(CAPWarZoneConfig) do local capwarzoneconfig = ParseCAPWarZoneConfigJson(currentCAPWarZoneConfigObject) if capwarzoneconfig.enable == true and #(capwarzoneconfig.ewrPrefixes) > 0 then compteur = compteur + 1 -- region CAPZoneWarSetUp Jtff_log.info( string.format( "%s Zone creation...", capwarzoneconfig.name ), "CAP_WAR_ZONE" ) local objCapWarZone = { customconfig = capwarzoneconfig, jtff_patrolZones = {}, jtff_borderZone = {}, objMenu = {}, } if type(GROUP:FindByName( capwarzoneconfig.borderZoneName )) ~= 'nil' then if type(ZONE_POLYGON:FindByName(capwarzoneconfig.borderZoneName)) ~= 'nil' then objCapWarZone.jtff_borderZone = ZONE_POLYGON:FindByName(capwarzoneconfig.borderZoneName) else objCapWarZone.jtff_borderZone = ZONE_POLYGON:New( capwarzoneconfig.borderZoneName, GROUP:FindByName( capwarzoneconfig.borderZoneName ) ):DrawZone( -1, -- All coalitions {1,0,0}, 1, {1,0,0}, 0.10, 3, true, nil ) end elseif type(ZONE:New(capwarzoneconfig.borderZoneName)) ~= 'nil' then objCapWarZone.jtff_borderZone = ZONE:FindByName(capwarzoneconfig.borderZoneName):DrawZone( -1, -- All coalitions {1,0,0}, 1, {1,0,0}, 0.10, 3, true, nil ) else objCapWarZone.jtff_borderZone = nil end objCapWarZone.objMenu = MENU_MISSION:New(capwarzoneconfig.name, MenuMissionCAPWarZone) objCapWarZone.objMenu:RemoveSubMenus() objCapWarZone.customconfig = capwarzoneconfig CAPWarZoneArray[compteur] = objCapWarZone MENU_MISSION_COMMAND:New( string.format("Start %s CAP War Zone", capwarzoneconfig.name), CAPWarZoneArray[compteur].objMenu, StartCapWarZone, CAPWarZoneArray[compteur] ) -- endregion CAPZoneWarSetUp end end