diff --git a/ABP - Airbase Police/ABP-001 - Caucasus/APL-001 - Caucasus.lua b/ABP - Airbase Police/ABP-001 - Caucasus/APL-001 - Caucasus.lua new file mode 100644 index 0000000000..b6f2fe7747 --- /dev/null +++ b/ABP - Airbase Police/ABP-001 - Caucasus/APL-001 - Caucasus.lua @@ -0,0 +1,3 @@ + +local PlanesClientSet = SET_CLIENT:New():FilterCategories( "plane" ):FilterStart() +local AirbasePolice = AIRBASEPOLICE_CAUCASUS:New( PlanesClientSet ) diff --git a/ABP - Airbase Police/ABP-002 - Nevada/ABP-002 - Nevada.miz b/ABP - Airbase Police/ABP-002 - Nevada/ABP-002 - Nevada.miz index e82f8292fe..1e44a715fc 100644 Binary files a/ABP - Airbase Police/ABP-002 - Nevada/ABP-002 - Nevada.miz and b/ABP - Airbase Police/ABP-002 - Nevada/ABP-002 - Nevada.miz differ diff --git a/ABP - Airbase Police/ABP-002 - Nevada/APL-002 - Nevada.lua b/ABP - Airbase Police/ABP-002 - Nevada/APL-002 - Nevada.lua new file mode 100644 index 0000000000..680bba1dc9 --- /dev/null +++ b/ABP - Airbase Police/ABP-002 - Nevada/APL-002 - Nevada.lua @@ -0,0 +1,3 @@ + +local PlanesClientSet = SET_CLIENT:New():FilterCategories( "plane" ):FilterStart() +local AirbasePolice = AIRBASEPOLICE_NEVADA:New( PlanesClientSet ) diff --git a/AIB - AI Balancing/AIB-007 - All Airports/AIB-007 - AI Balancers For all airports and both coalitions.lua b/AIB - AI Balancing/AIB-007 - All Airports/AIB-007 - AI Balancers For all airports and both coalitions.lua new file mode 100644 index 0000000000..9e3091a6a8 --- /dev/null +++ b/AIB - AI Balancing/AIB-007 - All Airports/AIB-007 - AI Balancers For all airports and both coalitions.lua @@ -0,0 +1,163 @@ +-- Name: AIB-007 - AI Balancers For all airports and both coalitions +-- Author: Delta99 +-- Date Created: 11 Feb 2017 +-- +-- Originally created to solve issues jg7xman (from Moose Slack group) was having in creating +-- AI_BALANCER across multiple airbases. + +-- # Situation: +-- +-- AI_BALANCERS created per airbase for both coalitions. Mutiple patrol zones are created +-- for each side. Each flight that is created by AI_BALANCER will pick a random patrol zone +-- to patrol. + +-- # Test Cases +-- +-- 1. Observe at least 1 flight spawning and taking off from each airbase. +-- 2. Each flight patrols randomly in one of its sides zones. +-- 3. AI will respawn after killed. +-- 4. Additional client slots are available at Sochi. If players don't take a slot there +-- will be more than one AI taking off from Sochi. +-- 5. Batumi contains a flight of 3 units rather than just 1 like most of the rest of the airbases. +-- 6. Watch the coalition AI clash and kill each other. + +-- Create the Red Patrol Zone Array + +-- This zone array will be used in the AI_BALANCER to randomize the patrol +-- zone that each spawned group will patrol + +RedPatrolZone = {} +RedPatrolZone[1] = ZONE:New( "RedPatrolZone1" ) +RedPatrolZone[2] = ZONE:New( "RedPatrolZone2" ) +RedPatrolZone[3] = ZONE:New( "RedPatrolZone3" ) +RedPatrolZone[4] = ZONE:New( "RedPatrolZone4" ) +RedPatrolZone[5] = ZONE:New( "RedPatrolZone5" ) +RedPatrolZone[6] = ZONE:New( "RedPatrolZone6" ) + +-- Russian CAP Aircraft + +-- These are the aircraft created in the mission editor that the AI will spawn +-- with replacing any CLIENT created aircraft in the mission that a human +-- player does not take. + +RU_PlanesSpawn = {} +RU_PlanesSpawn[1] = SPAWN:New( "RU CAP Anapa AB" ):InitCleanUp( 45 ) +RU_PlanesSpawn[2] = SPAWN:New( "RU CAP Beslan AB" ):InitCleanUp( 45 ) +RU_PlanesSpawn[3] = SPAWN:New( "RU CAP Gelendzhik AB" ):InitCleanUp( 45 ) +RU_PlanesSpawn[4] = SPAWN:New( "RU CAP Krasnodar Center AB" ):InitCleanUp( 45 ) +RU_PlanesSpawn[5] = SPAWN:New( "RU CAP Krasnodar Pashkovsky AB" ):InitCleanUp( 45 ) +RU_PlanesSpawn[6] = SPAWN:New( "RU CAP Krymsk AB" ):InitCleanUp( 45 ) +RU_PlanesSpawn[7] = SPAWN:New( "RU CAP Maykop AB" ):InitCleanUp( 45 ) +RU_PlanesSpawn[8] = SPAWN:New( "RU CAP Mineralnye Vody AB" ):InitCleanUp( 45 ) +RU_PlanesSpawn[9] = SPAWN:New( "RU CAP Mozdok AB" ):InitCleanUp( 45 ) +RU_PlanesSpawn[10] = SPAWN:New( "RU CAP Nalchik AB" ):InitCleanUp( 45 ) +RU_PlanesSpawn[11] = SPAWN:New( "RU CAP Novorossiysk AB" ):InitCleanUp( 45 ) + +-- Russian Client Aircraft (via AI_BALANCER, AI will replace these if no human players are in the slot) + +-- If you want more client slots per airbase that you want AI to be able to take control of then +-- name them with the prefixes below and they will be picked up automatically by FilterPrevixes. +-- +-- For example, if you want another Client slot available at Anapa name it "RU CLIENT Anapa AB 2". +-- The code here does not need to be changed. Only an addition in the mission editor. An example +-- of this can be found on the USA side at Sochi AB. + +RU_PlanesClientSet = {} +RU_PlanesClientSet[1] = SET_CLIENT:New():FilterPrefixes("RU CLIENT Anapa AB") +RU_PlanesClientSet[2] = SET_CLIENT:New():FilterPrefixes("RU CLIENT Beslan AB") +RU_PlanesClientSet[3] = SET_CLIENT:New():FilterPrefixes("RU CLIENT Gelendzhik AB") +RU_PlanesClientSet[4] = SET_CLIENT:New():FilterPrefixes("RU CLIENT Krasnodar Center AB") +RU_PlanesClientSet[5] = SET_CLIENT:New():FilterPrefixes("RU CLIENT Krasnodar Pashkovsky AB") +RU_PlanesClientSet[6] = SET_CLIENT:New():FilterPrefixes("RU CLIENT Krymsk AB") +RU_PlanesClientSet[7] = SET_CLIENT:New():FilterPrefixes("RU CLIENT Maykop AB") +RU_PlanesClientSet[8] = SET_CLIENT:New():FilterPrefixes("RU CLIENT Mineralnye Vody AB") +RU_PlanesClientSet[9] = SET_CLIENT:New():FilterPrefixes("RU CLIENT Mozdok AB") +RU_PlanesClientSet[10] = SET_CLIENT:New():FilterPrefixes("RU CLIENT Nalchik AB") +RU_PlanesClientSet[11] = SET_CLIENT:New():FilterPrefixes("RU CLIENT Novorossiysk AB") + +-- We setup an array to store all the AI_BALANCERS that are going to be created. Basically one +-- per airbase. We loop through and create an AI_BALANCER as well as a separate OnAfterSpawned +-- function for each. The Patrol Zone is randomized in the first parameter to AI_PATROL_ZONE:New() +-- call. This is done for each of the AI_BALANCERS. To add more patrol zones, just define them in +-- the mission editor and add into the array above. Code here does not need to be changed. The +-- table.getn(RedPatrolZone) gets the number of elements in the RedPatrolZone array so that all +-- of them are included to pick randomly. + + +RU_AI_Balancer = {} +for i=1, 11 do + RU_AI_Balancer[i] = AI_BALANCER:New(RU_PlanesClientSet[i], RU_PlanesSpawn[i]) + + -- We set a local variable within the for loop to the AI_BALANCER that was just created. + -- I couldn't get RU_AI_BALANCER[i]:OnAfterSpawn to be recognized so this is just pointing + -- curAIBalancer to the relevant RU_AI_BALANCER array item for each loop. + + -- So in this case there are essentially 11 OnAfterSpawned functions defined and handled. + + local curAIBalancer = RU_AI_Balancer[i] + function curAIBalancer:OnAfterSpawned( SetGroup, From, Event, To, AIGroup ) + local Patrol = AI_PATROL_ZONE:New( RedPatrolZone[math.random( 1, table.getn(RedPatrolZone))], 1500, 5500, 700, 1400 ) + Patrol:ManageFuel( 0.2, 60 ) + Patrol:SetControllable( AIGroup ) + Patrol:Start() + end +end + +-- US / Blue side is setup pretty much identically to the RU side above. Same detailed comments +-- above apply here. The main difference here is 10 airbases instead of 11. + +-- Another difference is additional client slots at Sochi and a group defined at Batumi with +-- more than 1 unit per group (flight of 3 units). This is just to show that you can have more +-- client slots per airbase and more units in a single group that the AI will control. I think +-- this will also allow you to fly lead with AI on your wing or you can fly wing with an AI +-- leader. + +-- Create the Blue Patrol Zone Array +BluePatrolZone = {} +BluePatrolZone[1] = ZONE:New( "BluePatrolZone1") +BluePatrolZone[2] = ZONE:New( "BluePatrolZone2") +BluePatrolZone[3] = ZONE:New( "BluePatrolZone3") +BluePatrolZone[4] = ZONE:New( "BluePatrolZone4") +BluePatrolZone[5] = ZONE:New( "BluePatrolZone5") +BluePatrolZone[6] = ZONE:New( "BluePatrolZone6") + +--United States CAP Aircraft (these are used as templates for AI) + +US_PlanesSpawn = {} +US_PlanesSpawn[1] = SPAWN:New( "US CAP Batumi AB" ):InitCleanUp( 45 ) +US_PlanesSpawn[2] = SPAWN:New( "US CAP Gudauta AB" ):InitCleanUp( 45 ) +US_PlanesSpawn[3] = SPAWN:New( "US CAP Kobuleti AB" ):InitCleanUp( 45 ) +US_PlanesSpawn[4] = SPAWN:New( "US CAP Kutaisi AB" ):InitCleanUp( 45 ) +US_PlanesSpawn[5] = SPAWN:New( "US CAP Senaki AB" ):InitCleanUp( 45 ) +US_PlanesSpawn[6] = SPAWN:New( "US CAP Sochi AB" ):InitCleanUp( 45 ) +US_PlanesSpawn[7] = SPAWN:New( "US CAP Soganlug AB" ):InitCleanUp( 45 ) +US_PlanesSpawn[8] = SPAWN:New( "US CAP Sukhumi AB" ):InitCleanUp( 45 ) +US_PlanesSpawn[9] = SPAWN:New( "US CAP Vaziani AB" ):InitCleanUp( 45 ) +US_PlanesSpawn[10] = SPAWN:New( "US CAP Tbilisi AB" ):InitCleanUp( 45 ) + +--United States Client Aircraft (via AI_BALANCER, AI will replace these if no human players are in the slot) + +US_PlanesClientSet = {} +US_PlanesClientSet[1] = SET_CLIENT:New():FilterPrefixes("US CLIENT Batumi AB") +US_PlanesClientSet[2] = SET_CLIENT:New():FilterPrefixes("US CLIENT Gudauta AB") +US_PlanesClientSet[3] = SET_CLIENT:New():FilterPrefixes("US CLIENT Kobuleti AB") +US_PlanesClientSet[4] = SET_CLIENT:New():FilterPrefixes("US CLIENT Kutaisi AB") +US_PlanesClientSet[5] = SET_CLIENT:New():FilterPrefixes("US CLIENT Senaki AB") +US_PlanesClientSet[6] = SET_CLIENT:New():FilterPrefixes("US CLIENT Sochi AB") +US_PlanesClientSet[7] = SET_CLIENT:New():FilterPrefixes("US CLIENT Soganlug AB") +US_PlanesClientSet[8] = SET_CLIENT:New():FilterPrefixes("US CLIENT Sukhumi AB") +US_PlanesClientSet[9] = SET_CLIENT:New():FilterPrefixes("US CLIENT Vaziani AB") +US_PlanesClientSet[10] = SET_CLIENT:New():FilterPrefixes("US CLIENT Tbilisi AB") + +US_AI_Balancer = {} +for i=1, 10 do + US_AI_Balancer[i] = AI_BALANCER:New( US_PlanesClientSet[i], US_PlanesSpawn[i] ) + + local curAIBalancer = US_AI_Balancer[i] + function curAIBalancer:OnAfterSpawned( SetGroup, From, Event, To, AIGroup ) + local Patrol = AI_PATROL_ZONE:New( BluePatrolZone[math.random( 1, table.getn(BluePatrolZone))], 1500, 5500, 700, 1400 ) + Patrol:ManageFuel( 0.2, 60 ) + Patrol:SetControllable( AIGroup ) + Patrol:Start() + end +end diff --git a/AIC - AI Cargo/APC - Armoured Personnel Carrier/AIC-APC-006 - Troops Relocate APC/AIC-APC-001 - Troops Relocate APC.lua b/AIC - AI Cargo/APC - Armoured Personnel Carrier/AIC-APC-006 - Troops Relocate APC/AIC-APC-001 - Troops Relocate APC.lua index 14db08b124..5c40eb57ac 100644 --- a/AIC - AI Cargo/APC - Armoured Personnel Carrier/AIC-APC-006 - Troops Relocate APC/AIC-APC-001 - Troops Relocate APC.lua +++ b/AIC - AI Cargo/APC - Armoured Personnel Carrier/AIC-APC-006 - Troops Relocate APC/AIC-APC-001 - Troops Relocate APC.lua @@ -1,24 +1,24 @@ ---- --- Name: AIC-APC-001 - Troops Relocate APC --- Author: FlightControl --- Date Created: 07 Apr 2018 --- --- Demonstration of troops relocation when carrier is destroyed... --- Carrier will relocate to the rescue carrier. - -local InfantryCargoSet = SET_CARGO:New():FilterTypes( "Infantry" ):FilterStart() - -local CargoCarrier = GROUP:FindByName( "Carrier" ) - -CargoTroops = AI_CARGO_APC:New( CargoCarrier, InfantryCargoSet, 500 ) - - -function CargoTroops:OnAfterDestroyed( CargoCarrier ) - CargoTroops:F( { Destroyed = CargoCarrier } ) - -- The coordinate is passed where the carrier is destroyed. - local NewCarrierGroup = self:FindCarrier( CargoCarrier:GetCoordinate(), 1000 ) -- which returns one Carrier GROUP object or nil. - if NewCarrierGroup then - self:SetCarrier( NewCarrierGroup ) - end -end - +--- +-- Name: AIC-APC-001 - Troops Relocate APC +-- Author: FlightControl +-- Date Created: 07 Apr 2018 +-- +-- Demonstration of troops relocation when carrier is destroyed... +-- Carrier will relocate to the rescue carrier. + +local InfantryCargoSet = SET_CARGO:New():FilterTypes( "Infantry" ):FilterStart() + +local CargoCarrier = GROUP:FindByName( "Carrier" ) + +CargoTroops = AI_CARGO_APC:New( CargoCarrier, InfantryCargoSet, 500 ) + + +function CargoTroops:OnAfterDestroyed( CargoCarrier ) + CargoTroops:F( { Destroyed = CargoCarrier } ) + -- The coordinate is passed where the carrier is destroyed. + local NewCarrierGroup = self:FindCarrier( CargoCarrier:GetCoordinate(), 1000 ) -- which returns one Carrier GROUP object or nil. + if NewCarrierGroup then + self:SetCarrier( NewCarrierGroup ) + end +end + diff --git a/AIC - AI Cargo/HEL - Helicopter/AIC-HEL-010 - Blue Helicopter/AIC-HEL-000 - Helicopter.lua b/AIC - AI Cargo/HEL - Helicopter/AIC-HEL-010 - Blue Helicopter/AIC-HEL-000 - Helicopter.lua new file mode 100644 index 0000000000..eeff770c0e --- /dev/null +++ b/AIC - AI Cargo/HEL - Helicopter/AIC-HEL-010 - Blue Helicopter/AIC-HEL-000 - Helicopter.lua @@ -0,0 +1,38 @@ +--- +-- Name: AIC-HEL-000 - Helicopter +-- Author: FlightControl +-- Date Created: 13 Apr 2018 +-- Date Checked: 01 Jan 2021 +-- Updated Moose, needs fix #1417 to work +-- +BASE:TraceClass("AI_CARGO") +BASE:TraceClass("AI_CARGO_HELICOPTER") +BASE:TraceOn() + +WorkerCargoSet = SET_CARGO:New():FilterTypes( "Workers" ):FilterStart() + + +for i = 1, 5 do + local WorkerGroup = GROUP:FindByName( string.format( "Infantry %03d", i ) ) + local WorkersCargo = CARGO_GROUP:New( WorkerGroup, "Workers", string.format( "Infantry %d", i ), 750, 35 ) +end + +local Helicopter = GROUP:FindByName( "Helicopter" ) + +CargoHelicopter = AI_CARGO_HELICOPTER:New( Helicopter, WorkerCargoSet ) + + +PickupZone = ZONE:New( "PickupZone" ) +DeployZones = { ZONE:New( "DeployZone Alpha" ), ZONE:New( "DeployZone Beta" ), ZONE:New( "DeployZone Gamma" ) } + +CargoHelicopter:Pickup( PickupZone:GetRandomCoordinate( 400, 100 ) ) + +function CargoHelicopter:OnAfterLoaded( Helicopter, From, Event, To, Cargo ) + CargoHelicopter:__Deploy(5,DeployZones[math.random( 1, #DeployZones ) ]:GetRandomCoordinate( 500, 100 ), math.random( 50, 250 ) ) +end + + +function CargoHelicopter:OnAfterUnloaded( Helicopter, From, Event, To, Cargo ) + CargoHelicopter:__Pickup( 5,PickupZone:GetRandomCoordinate( 500, 200 ), math.random( 50, 250 ) ) +end + diff --git a/AIC - AI Cargo/HEL - Helicopter/AIC-HEL-010 - Blue Helicopter/AIC-HEL-010 - Blue Helicopter.miz b/AIC - AI Cargo/HEL - Helicopter/AIC-HEL-010 - Blue Helicopter/AIC-HEL-010 - Blue Helicopter.miz index 0a65a4a385..0e9368fb68 100644 Binary files a/AIC - AI Cargo/HEL - Helicopter/AIC-HEL-010 - Blue Helicopter/AIC-HEL-010 - Blue Helicopter.miz and b/AIC - AI Cargo/HEL - Helicopter/AIC-HEL-010 - Blue Helicopter/AIC-HEL-010 - Blue Helicopter.miz differ diff --git a/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-008 - CAP Grouping Test/AID-008 - AI_A2A - CAP Grouping Test.lua b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-008 - CAP Grouping Test/AID-008 - AI_A2A - CAP Grouping Test.lua new file mode 100644 index 0000000000..759947cc3f --- /dev/null +++ b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-008 - CAP Grouping Test/AID-008 - AI_A2A - CAP Grouping Test.lua @@ -0,0 +1,27 @@ +--- +-- Name: AID-008 - AI_A2A - CAP Grouping Test +-- Author: FlightControl +-- Date Created: 06 Aug 2017 + + +-- Define a SET_GROUP object that builds a collection of groups that define the EWR network. +-- Here we build the network with all the groups that have a name starting with DF CCCP AWACS and DF CCCP EWR. +DetectionSetGroup = SET_GROUP:New() +DetectionSetGroup:FilterPrefixes( { "DF CCCP AWACS", "DF CCCP EWR" } ) +DetectionSetGroup:FilterStart() + +Detection = DETECTION_AREAS:New( DetectionSetGroup, 30000 ) + +-- Setup the A2A dispatcher, and initialize it. +A2ADispatcher = AI_A2A_DISPATCHER:New( Detection ) + + +A2ADispatcher:SetTacticalDisplay( true ) + +-- Setup the squadrons. + +A2ADispatcher:SetSquadron( "Sochi", AIRBASE.Caucasus.Sochi_Adler, { "SQ CCCP SU-27" } ) +CAPZoneWest = ZONE_POLYGON:New( "CAP Zone West", GROUP:FindByName( "CAP Zone West" ) ) +A2ADispatcher:SetSquadronCap( "Sochi", CAPZoneWest, 4000, 8000, 600, 800, 800, 1200 ) +A2ADispatcher:SetSquadronCapInterval( "Sochi", 2, 10, 30, 1 ) +A2ADispatcher:SetSquadronGrouping( "Sochi", 2 ) diff --git a/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-009 - Border Test/AID-009 - AI_A2A - Border Test.lua b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-009 - Border Test/AID-009 - AI_A2A - Border Test.lua new file mode 100644 index 0000000000..3c3088e11a --- /dev/null +++ b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-009 - Border Test/AID-009 - AI_A2A - Border Test.lua @@ -0,0 +1,30 @@ +--- +-- Name: AID-009 - AI_A2A - Border Test +-- Author: FlightControl +-- Date Created: 06 Aug 2017 + + +-- Define a SET_GROUP object that builds a collection of groups that define the EWR network. +-- Here we build the network with all the groups that have a name starting with DF CCCP AWACS and DF CCCP EWR. +DetectionSetGroup = SET_GROUP:New() +DetectionSetGroup:FilterPrefixes( { "DF CCCP AWACS", "DF CCCP EWR" } ) +DetectionSetGroup:FilterStart() + +Detection = DETECTION_AREAS:New( DetectionSetGroup, 30000 ) + +-- Setup the A2A dispatcher, and initialize it. +A2ADispatcher = AI_A2A_DISPATCHER:New( Detection ) + +-- Setup the border zone. +-- In this case the border is a POLYGON, +-- which takes the waypoints of a late activated group with the name CCCP Border as the boundaries of the border area. +-- Any enemy crossing this border will be engaged. +CCCPBorderZone = ZONE_POLYGON:New( "CCCP Border", GROUP:FindByName( "CCCP Border" ) ) +A2ADispatcher:SetBorderZone( CCCPBorderZone ) + +A2ADispatcher:SetTacticalDisplay( true ) + +-- Setup the squadrons. + +A2ADispatcher:SetSquadron( "Sochi", AIRBASE.Caucasus.Sochi_Adler, { "SQ CCCP SU-27" } ) +A2ADispatcher:SetSquadronGci( "Sochi", 1000, 1500 ) diff --git a/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-010 - RTB and ReEngage/AID-010 - AI_A2A - RTB and ReEngage.lua b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-010 - RTB and ReEngage/AID-010 - AI_A2A - RTB and ReEngage.lua new file mode 100644 index 0000000000..1170c6d005 --- /dev/null +++ b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-010 - RTB and ReEngage/AID-010 - AI_A2A - RTB and ReEngage.lua @@ -0,0 +1,50 @@ +--- +-- Name: AID-010 - AI_A2A - RTB and ReEngage +-- Author: FlightControl +-- Date Created: 30 May 2017 + + +-- Define a SET_GROUP object that builds a collection of groups that define the EWR network. +-- Here we build the network with all the groups that have a name starting with DF CCCP AWACS and DF CCCP EWR. +DetectionSetGroup = SET_GROUP:New() +DetectionSetGroup:FilterPrefixes( { "DF CCCP AWACS", "DF CCCP EWR" } ) +DetectionSetGroup:FilterStart() + +Detection = DETECTION_AREAS:New( DetectionSetGroup, 30000 ) + +-- Setup the A2A dispatcher, and initialize it. +A2ADispatcher = AI_A2A_DISPATCHER:New( Detection ) + +-- Initialize the dispatcher, setting up a border zone. This is a polygon, +-- which takes the waypoints of a late activated group with the name CCCP Border as the boundaries of the border area. +-- Any enemy crossing this border will be engaged. +CCCPBorderZone = ZONE_POLYGON:New( "CCCP Border", GROUP:FindByName( "CCCP Border" ) ) +--A2ADispatcher:SetBorderZone( CCCPBorderZone ) + +-- Initialize the dispatcher, setting up a radius of 100km where any airborne friendly +-- without an assignment within 100km radius from a detected target, will engage that target. +A2ADispatcher:SetEngageRadius( 200000 ) + +A2ADispatcher:SetTacticalDisplay( true ) + + +-- Setup the squadrons. + +A2ADispatcher:SetSquadron( "Sochi", AIRBASE.Caucasus.Sochi_Adler, { "SQ CCCP SU-27" }, 20 ) +A2ADispatcher:SetSquadronGci( "Sochi", 900, 1200 ) + +A2ADispatcher:SetDefaultTakeoffFromParkingCold() +A2ADispatcher:SetDefaultLandingAtEngineShutdown() + +-- Blue attack simulation + +local Frequency = 180 + +BlueSpawn2 = SPAWN + :New( "RT NATO 2" ) + :InitLimit( 8, 40 ) + :InitRandomizeTemplate( { "SQ NATO A-10C", "SQ NATO F-15C", "SQ NATO F-16A", "SQ NATO F/A-18", "SQ NATO F-16C" } ) + :InitRandomizeRoute( 0, 0, 30000 ) + :InitDelayOn() + :SpawnScheduled( Frequency, 0.5 ) + diff --git a/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-011 - RTB Fuel Treshold test/AID-011 - AI_A2A - RTB Fuel Treshold test.lua b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-011 - RTB Fuel Treshold test/AID-011 - AI_A2A - RTB Fuel Treshold test.lua new file mode 100644 index 0000000000..b619f66c84 --- /dev/null +++ b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-011 - RTB Fuel Treshold test/AID-011 - AI_A2A - RTB Fuel Treshold test.lua @@ -0,0 +1,51 @@ +--- +-- Name: AID-011 - AI_A2A - RTB Fuel Threshold test +-- Author: FlightControl +-- Date Created: 30 Jul 2017 + + +-- Define a SET_GROUP object that builds a collection of groups that define the EWR network. +-- Here we build the network with all the groups that have a name starting with DF CCCP AWACS and DF CCCP EWR. +DetectionSetGroup = SET_GROUP:New() +DetectionSetGroup:FilterPrefixes( { "DF CCCP AWACS", "DF CCCP EWR" } ) +DetectionSetGroup:FilterStart() + +Detection = DETECTION_AREAS:New( DetectionSetGroup, 30000 ) + +-- Setup the A2A dispatcher, and initialize it. +A2ADispatcher = AI_A2A_DISPATCHER:New( Detection ) + +-- Initialize the dispatcher, setting up a border zone. This is a polygon, +-- which takes the waypoints of a late activated group with the name CCCP Border as the boundaries of the border area. +-- Any enemy crossing this border will be engaged. +CCCPBorderZone = ZONE_POLYGON:New( "CCCP Border", GROUP:FindByName( "CCCP Border" ) ) +--A2ADispatcher:SetBorderZone( CCCPBorderZone ) + +-- Initialize the dispatcher, setting up a radius of 100km where any airborne friendly +-- without an assignment within 100km radius from a detected target, will engage that target. +A2ADispatcher:SetEngageRadius( 200000 ) + + +A2ADispatcher:SetTacticalDisplay( true ) + +-- Set the fuel treshold to 40%. Airplanes will return when only 40% of fuel left in the tank. +A2ADispatcher:SetDefaultFuelThreshold( 0.4 ) + +-- Setup the squadrons. + +A2ADispatcher:SetSquadron( "Sochi", AIRBASE.Caucasus.Sochi_Adler, { "SQ CCCP SU-27" }, 20 ) +A2ADispatcher:SetSquadronOverhead( "Sochi", 1 ) +A2ADispatcher:SetSquadronGrouping( "Sochi", 2 ) + +-- CAP Squadron execution. + +CAPZoneWest = ZONE_POLYGON:New( "CAP Zone West", GROUP:FindByName( "CAP Zone West" ) ) +A2ADispatcher:SetSquadronCap( "Sochi", CAPZoneWest, 4000, 8000, 600, 800, 800, 1200, "BARO" ) +A2ADispatcher:SetSquadronCapInterval( "Sochi", 2, 30, 120, 1 ) + +A2ADispatcher:SetSquadronGci( "Sochi", 900, 1200 ) + +A2ADispatcher:SetSquadronTakeoffFromParkingHot("Sochi") +A2ADispatcher:SetSquadronLandingAtEngineShutdown("Sochi") + + diff --git a/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-012 - CAP Time Interval Test/AID-012 - AI_A2A - CAP Time Interval Test.lua b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-012 - CAP Time Interval Test/AID-012 - AI_A2A - CAP Time Interval Test.lua new file mode 100644 index 0000000000..47005e4104 --- /dev/null +++ b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-012 - CAP Time Interval Test/AID-012 - AI_A2A - CAP Time Interval Test.lua @@ -0,0 +1,51 @@ +--- +-- Name: AID-012 - AI_A2A - CAP Time Interval Test +-- Author: FlightControl +-- Date Created: 30 Jul 2017 + + +-- Define a SET_GROUP object that builds a collection of groups that define the EWR network. +-- Here we build the network with all the groups that have a name starting with DF CCCP AWACS and DF CCCP EWR. +DetectionSetGroup = SET_GROUP:New() +DetectionSetGroup:FilterPrefixes( { "DF CCCP AWACS", "DF CCCP EWR" } ) +DetectionSetGroup:FilterStart() + +Detection = DETECTION_AREAS:New( DetectionSetGroup, 30000 ) + +-- Setup the A2A dispatcher, and initialize it. +A2ADispatcher = AI_A2A_DISPATCHER:New( Detection ) + +-- Initialize the dispatcher, setting up a border zone. This is a polygon, +-- which takes the waypoints of a late activated group with the name CCCP Border as the boundaries of the border area. +-- Any enemy crossing this border will be engaged. +CCCPBorderZone = ZONE_POLYGON:New( "CCCP Border", GROUP:FindByName( "CCCP Border" ) ) +--A2ADispatcher:SetBorderZone( CCCPBorderZone ) + +-- Initialize the dispatcher, setting up a radius of 100km where any airborne friendly +-- without an assignment within 100km radius from a detected target, will engage that target. +A2ADispatcher:SetEngageRadius( 200000 ) + + +A2ADispatcher:SetTacticalDisplay( true ) + +A2ADispatcher:SetDefaultCapLimit( 2 ) +A2ADispatcher:SetDefaultCapTimeInterval( 300, 300 ) -- Spawn each 5 minutes. + +-- Setup the squadrons. + +A2ADispatcher:SetSquadron( "Sochi", AIRBASE.Caucasus.Sochi_Adler, { "SQ CCCP SU-27" }, 20 ) +A2ADispatcher:SetSquadronOverhead( "Sochi", 1 ) +A2ADispatcher:SetSquadronGrouping( "Sochi", 2 ) + +-- CAP Squadron execution. + +CAPZoneWest = ZONE_POLYGON:New( "CAP Zone West", GROUP:FindByName( "CAP Zone West" ) ) +A2ADispatcher:SetSquadronCap( "Sochi", CAPZoneWest, 4000, 8000, 600, 800, 800, 1200, "BARO" ) + + +A2ADispatcher:SetSquadronGci( "Sochi", 900, 1200 ) + +A2ADispatcher:SetSquadronTakeoffFromParkingHot("Sochi") +A2ADispatcher:SetSquadronLandingAtEngineShutdown("Sochi") + + diff --git a/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-014 - DisengageRange Test/AID-014 - AI_A2A - DisengageRange Test.lua b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-014 - DisengageRange Test/AID-014 - AI_A2A - DisengageRange Test.lua new file mode 100644 index 0000000000..86e6d1f4b5 --- /dev/null +++ b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-014 - DisengageRange Test/AID-014 - AI_A2A - DisengageRange Test.lua @@ -0,0 +1,48 @@ +--- +-- Name: AID-014 - AI_A2A - DisengageRange Test +-- Author: FlightControl +-- Date Created: 31 Jul 2017 + + +-- Define a SET_GROUP object that builds a collection of groups that define the EWR network. +-- Here we build the network with all the groups that have a name starting with DF CCCP AWACS and DF CCCP EWR. +DetectionSetGroup = SET_GROUP:New() +DetectionSetGroup:FilterPrefixes( { "DF CCCP AWACS", "DF CCCP EWR" } ) +DetectionSetGroup:FilterStart() + +Detection = DETECTION_AREAS:New( DetectionSetGroup, 30000 ) + +-- Setup the A2A dispatcher, and initialize it. +A2ADispatcher = AI_A2A_DISPATCHER:New( Detection ) + +-- Initialize the dispatcher, setting up a border zone. This is a polygon, +-- which takes the waypoints of a late activated group with the name CCCP Border as the boundaries of the border area. +-- Any enemy crossing this border will be engaged. +CCCPBorderZone = ZONE_POLYGON:New( "CCCP Border", GROUP:FindByName( "CCCP Border" ) ) +--A2ADispatcher:SetBorderZone( CCCPBorderZone ) + +-- Initialize the dispatcher, setting up a radius of 100km where any airborne friendly +-- without an assignment within 100km radius from a detected target, will engage that target. +A2ADispatcher:SetEngageRadius( 200000 ) + + +A2ADispatcher:SetTacticalDisplay( true ) + +-- Test intercept. +A2ADispatcher:SetIntercept( 450 ) + +-- Test an other disengage radius. +A2ADispatcher:SetDisengageRadius( 150000 ) + +-- Setup the squadrons. + +A2ADispatcher:SetSquadron( "Sochi", AIRBASE.Caucasus.Sochi_Adler, { "SQ CCCP MIG-31" }, 20 ) +A2ADispatcher:SetSquadronGci( "Sochi", 900, 1200 ) +A2ADispatcher:SetSquadronTakeoffFromParkingCold( "Sochi" ) + + +A2ADispatcher:SetSquadron( "Gelend", AIRBASE.Caucasus.Gelendzhik, { "SQ CCCP SU-27" }, 20 ) +A2ADispatcher:SetSquadronGci( "Gelend", 800, 1200 ) +A2ADispatcher:SetSquadronTakeoffFromParkingCold( "Gelend" ) + + diff --git a/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-015 - Takeoff Test/AID-015 - AI_A2A - Takeoff Test.lua b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-015 - Takeoff Test/AID-015 - AI_A2A - Takeoff Test.lua new file mode 100644 index 0000000000..cb7aea1b09 --- /dev/null +++ b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-015 - Takeoff Test/AID-015 - AI_A2A - Takeoff Test.lua @@ -0,0 +1,53 @@ +--- +-- Name: AID-015 - AI_A2A - Takeoff Test +-- Author: FlightControl +-- Date Created: 01 Aug 2017 + + +-- Define a SET_GROUP object that builds a collection of groups that define the EWR network. +-- Here we build the network with all the groups that have a name starting with DF CCCP AWACS and DF CCCP EWR. +DetectionSetGroup = SET_GROUP:New() +DetectionSetGroup:FilterPrefixes( { "DF CCCP AWACS", "DF CCCP EWR" } ) +DetectionSetGroup:FilterStart() + +Detection = DETECTION_AREAS:New( DetectionSetGroup, 30000 ) + +-- Setup the A2A dispatcher, and initialize it. +A2ADispatcher = AI_A2A_DISPATCHER:New( Detection ) + +-- Initialize the dispatcher, setting up a border zone. This is a polygon, +-- which takes the waypoints of a late activated group with the name CCCP Border as the boundaries of the border area. +-- Any enemy crossing this border will be engaged. +CCCPBorderZone = ZONE_POLYGON:New( "CCCP Border", GROUP:FindByName( "CCCP Border" ) ) +--A2ADispatcher:SetBorderZone( CCCPBorderZone ) + +-- Initialize the dispatcher, setting up a radius of 100km where any airborne friendly +-- without an assignment within 100km radius from a detected target, will engage that target. +A2ADispatcher:SetEngageRadius( 200000 ) + + +A2ADispatcher:SetTacticalDisplay( true ) + +-- Test intercept. +A2ADispatcher:SetIntercept( 450 ) + +-- Test an other disengage radius. +A2ADispatcher:SetDisengageRadius( 20000 ) + +-- Setup the squadrons. + +A2ADispatcher:SetSquadron( "Sochi", AIRBASE.Caucasus.Sochi_Adler, { "SQ CCCP MIG-31" }, 20 ) +A2ADispatcher:SetSquadronGci( "Sochi", 900, 1200 ) +A2ADispatcher:SetSquadronTakeoffFromParkingCold( "Sochi" ) + +A2ADispatcher:SetSquadron( "Gelend", AIRBASE.Caucasus.Gelendzhik, { "SQ CCCP SU-27" }, 20 ) +A2ADispatcher:SetSquadronGci( "Gelend", 800, 1200 ) +A2ADispatcher:SetSquadronTakeoffFromRunway( "Gelend" ) + +A2ADispatcher:SetSquadron( "Anapa", AIRBASE.Caucasus.Anapa_Vityazevo, { "SQ CCCP SU-27" }, 20 ) +A2ADispatcher:SetSquadronGci( "Anapa", 800, 1200 ) +A2ADispatcher:SetSquadronTakeoffInAir( "Anapa" ) + +A2ADispatcher:SetSquadron( "Novo", AIRBASE.Caucasus.Novorossiysk, { "SQ CCCP SU-27" }, 20 ) +A2ADispatcher:SetSquadronGci( "Novo", 800, 1200 ) +A2ADispatcher:SetSquadronTakeoffFromParkingHot( "Novo" ) diff --git a/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-016 - Refuel Tanker Test/AID-016 - AI_A2A - Refuel Tanker Test.lua b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-016 - Refuel Tanker Test/AID-016 - AI_A2A - Refuel Tanker Test.lua new file mode 100644 index 0000000000..42ceeccfc8 --- /dev/null +++ b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-016 - Refuel Tanker Test/AID-016 - AI_A2A - Refuel Tanker Test.lua @@ -0,0 +1,50 @@ +--- +-- Name: AID-016 - AI_A2A - Refuel Tanker Test +-- Author: FlightControl +-- Date Created: 01 Aug 2017 + + +-- Define a SET_GROUP object that builds a collection of groups that define the EWR network. +-- Here we build the network with all the groups that have a name starting with DF CCCP AWACS and DF CCCP EWR. +DetectionSetGroup = SET_GROUP:New() +DetectionSetGroup:FilterPrefixes( { "DF CCCP AWACS", "DF CCCP EWR" } ) +DetectionSetGroup:FilterStart() + +Detection = DETECTION_AREAS:New( DetectionSetGroup, 30000 ) + +-- Setup the A2A dispatcher, and initialize it. +A2ADispatcher = AI_A2A_DISPATCHER:New( Detection ) + + +-- Initialize the dispatcher, setting up a radius of 100km where any airborne friendly +-- without an assignment within 100km radius from a detected target, will engage that target. +A2ADispatcher:SetEngageRadius( 200000 ) + + +A2ADispatcher:SetTacticalDisplay( true ) + +-- Test intercept. +A2ADispatcher:SetIntercept( 450 ) + + +-- Setup the squadrons. + +A2ADispatcher:SetSquadron( "Sochi", AIRBASE.Caucasus.Sochi_Adler, { "SQ CCCP SU-34" }, 20 ) +A2ADispatcher:SetSquadronCap( "Sochi", ZONE:New( "PatrolZone" ), 4000, 8000, 600, 800, 1000, 1300 ) +A2ADispatcher:SetSquadronCapInterval("Sochi", 2, 30, 600, 1 ) +A2ADispatcher:SetSquadronGci( "Sochi", 900, 1200 ) + + +A2ADispatcher:SetDefaultFuelThreshold( 0.9 ) +A2ADispatcher:SetDefaultTanker( "Tanker" ) + + +A2ADispatcher:SetSquadron( "Gelend", AIRBASE.Caucasus.Gelendzhik, { "SQ CCCP SU-30" }, 20 ) +A2ADispatcher:SetSquadronCap( "Gelend", ZONE:New( "PatrolZoneGelend" ), 4000, 8000, 600, 800, 1000, 1300 ) +A2ADispatcher:SetSquadronCapInterval( "Gelend", 2, 30, 600, 1 ) +A2ADispatcher:SetSquadronGci( "Gelend", 900, 1200 ) + +A2ADispatcher:SetSquadronFuelThreshold( "Gelend", 0.8 ) +A2ADispatcher:SetSquadronTanker( "Gelend", "TankerGelend" ) + + diff --git a/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-017 - Spawn Altitude Test/AID-017 - AI_A2A - Spawn Altitude Test.lua b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-017 - Spawn Altitude Test/AID-017 - AI_A2A - Spawn Altitude Test.lua new file mode 100644 index 0000000000..6f536f82ec --- /dev/null +++ b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-017 - Spawn Altitude Test/AID-017 - AI_A2A - Spawn Altitude Test.lua @@ -0,0 +1,44 @@ +--- +-- Name: AID-017 - AI_A2A - Spawn Altitude Test +-- Author: FlightControl +-- Date Created: 05 Aug 2017 + + +-- Define a SET_GROUP object that builds a collection of groups that define the EWR network. +-- Here we build the network with all the groups that have a name starting with DF CCCP AWACS and DF CCCP EWR. +DetectionSetGroup = SET_GROUP:New() +DetectionSetGroup:FilterPrefixes( { "DF CCCP AWACS", "DF CCCP EWR" } ) +DetectionSetGroup:FilterStart() + +Detection = DETECTION_AREAS:New( DetectionSetGroup, 30000 ) + +-- Setup the A2A dispatcher, and initialize it. +A2ADispatcher = AI_A2A_DISPATCHER:New( Detection ) + +A2ADispatcher:SetTacticalDisplay( true ) + +-- Set the default takeoff method in the air. +A2ADispatcher:SetDefaultTakeoffInAir() + +-- Set the default takeoff altitude at 2000 meters. +A2ADispatcher:SetDefaultTakeoffInAirAltitude( 2000 ) -- Takeoff by default at 2000 meters. + + +-- Spawn for Sochi airbase. +A2ADispatcher:SetSquadron( "Sochi", AIRBASE.Caucasus.Sochi_Adler, { "SQ CCCP SU-34" }, 20 ) +A2ADispatcher:SetSquadronCap( "Sochi", ZONE:New( "PatrolZone" ), 4000, 8000, 600, 800, 1000, 1300 ) +A2ADispatcher:SetSquadronCapInterval("Sochi", 2, 30, 600, 1 ) +A2ADispatcher:SetSquadronGci( "Sochi", 900, 1200 ) + + +-- Spawn for Gelend airbase. +A2ADispatcher:SetSquadron( "Gelend", AIRBASE.Caucasus.Gelendzhik, { "SQ CCCP SU-30" }, 20 ) +A2ADispatcher:SetSquadronCap( "Gelend", ZONE:New( "PatrolZoneGelend" ), 4000, 8000, 600, 800, 1000, 1300 ) +A2ADispatcher:SetSquadronCapInterval( "Gelend", 2, 30, 600, 1 ) +A2ADispatcher:SetSquadronGci( "Gelend", 900, 1200 ) + +-- Let Gelend squadron take off in the air at 4000 meters. +A2ADispatcher:SetSquadronTakeoffInAir( "Gelend", 4000 ) -- Takeoff in Gelend at 4000 meters. + + +-- Run the mission and observe the spawning altitudes. diff --git a/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-018 - Unlimited Resources Test/AID-018 - AI_A2A - Unlimited Resources Test.lua b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-018 - Unlimited Resources Test/AID-018 - AI_A2A - Unlimited Resources Test.lua new file mode 100644 index 0000000000..e1f5e88b02 --- /dev/null +++ b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-018 - Unlimited Resources Test/AID-018 - AI_A2A - Unlimited Resources Test.lua @@ -0,0 +1,45 @@ +--- +-- Name: AID-018 - AI_A2A - Unlimited Resources Test +-- Author: FlightControl +-- Date Created: 05 Aug 2017 + + +-- Define a SET_GROUP object that builds a collection of groups that define the EWR network. +-- Here we build the network with all the groups that have a name starting with DF CCCP AWACS and DF CCCP EWR. +DetectionSetGroup = SET_GROUP:New() +DetectionSetGroup:FilterPrefixes( { "DF CCCP AWACS", "DF CCCP EWR" } ) +DetectionSetGroup:FilterStart() + +Detection = DETECTION_AREAS:New( DetectionSetGroup, 30000 ) + +-- Setup the A2A dispatcher, and initialize it. +A2ADispatcher = AI_A2A_DISPATCHER:New( Detection ) + +-- Initialize the dispatcher, setting up a border zone. This is a polygon, +-- which takes the waypoints of a late activated group with the name CCCP Border as the boundaries of the border area. +-- Any enemy crossing this border will be engaged. +CCCPBorderZone = ZONE_POLYGON:New( "CCCP Border", GROUP:FindByName( "CCCP Border" ) ) +--A2ADispatcher:SetBorderZone( CCCPBorderZone ) + + +A2ADispatcher:SetTacticalDisplay( true ) + +-- Setup the squadrons. +-- Unlimited resources, as the Resources parameter of the :SetSquadron method is not given. + +A2ADispatcher:SetSquadron( "Sochi", AIRBASE.Caucasus.Sochi_Adler, { "SQ CCCP MIG-31" } ) +A2ADispatcher:SetSquadronGci( "Sochi", 900, 1200 ) +A2ADispatcher:SetSquadronTakeoffFromParkingCold( "Sochi" ) + +A2ADispatcher:SetSquadron( "Gelend", AIRBASE.Caucasus.Gelendzhik, { "SQ CCCP SU-27" } ) +A2ADispatcher:SetSquadronGci( "Gelend", 800, 1200 ) +A2ADispatcher:SetSquadronTakeoffFromRunway( "Gelend" ) + +A2ADispatcher:SetSquadron( "Anapa", AIRBASE.Caucasus.Anapa_Vityazevo, { "SQ CCCP SU-27" } ) +A2ADispatcher:SetSquadronGci( "Anapa", 800, 1200 ) +A2ADispatcher:SetSquadronTakeoffFromRunway( "Anapa" ) + +A2ADispatcher:SetSquadron( "Novo", AIRBASE.Caucasus.Novorossiysk, { "SQ CCCP SU-27" } ) +A2ADispatcher:SetSquadronGci( "Novo", 800, 1200 ) +A2ADispatcher:SetSquadronTakeoffFromRunway( "Novo" ) + diff --git a/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-019 - Engage Range Test/AID-019 - AI_A2A - Engage Range Test.lua b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-019 - Engage Range Test/AID-019 - AI_A2A - Engage Range Test.lua new file mode 100644 index 0000000000..5c576b2e18 --- /dev/null +++ b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-019 - Engage Range Test/AID-019 - AI_A2A - Engage Range Test.lua @@ -0,0 +1,31 @@ +--- +-- Name: AID-019 - AI_A2A - Engage Range Test +-- Author: FlightControl +-- Date Created: 06 Aug 2017 + + +-- Define a SET_GROUP object that builds a collection of groups that define the EWR network. +-- Here we build the network with all the groups that have a name starting with DF CCCP AWACS and DF CCCP EWR. +DetectionSetGroup = SET_GROUP:New() +DetectionSetGroup:FilterPrefixes( { "DF CCCP AWACS", "DF CCCP EWR" } ) +DetectionSetGroup:FilterStart() + +Detection = DETECTION_AREAS:New( DetectionSetGroup, 30000 ) + +-- Setup the A2A dispatcher, and initialize it. +A2ADispatcher = AI_A2A_DISPATCHER:New( Detection ) + +-- Initialize the dispatcher, setting up a radius of 50km where any airborne friendly +-- without an assignment within 50km radius from a detected target, will engage that target. +A2ADispatcher:SetEngageRadius( 50000 ) + +A2ADispatcher:SetTacticalDisplay( true ) + + +-- Setup the squadrons. + +A2ADispatcher:SetSquadron( "Sochi", AIRBASE.Caucasus.Sochi_Adler, { "SQ CCCP SU-27" } ) +CAPZoneWest = ZONE_POLYGON:New( "CAP Zone West", GROUP:FindByName( "CAP Zone West" ) ) +A2ADispatcher:SetSquadronCap( "Sochi", CAPZoneWest, 4000, 8000, 600, 800, 800, 1200 ) +A2ADispatcher:SetSquadronCapInterval( "Sochi", 2, 10, 30, 1 ) + diff --git a/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-021 - GCI Radius Test/AID-021 - AI_A2A - GCI Radius Test.lua b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-021 - GCI Radius Test/AID-021 - AI_A2A - GCI Radius Test.lua new file mode 100644 index 0000000000..9f04adff59 --- /dev/null +++ b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-021 - GCI Radius Test/AID-021 - AI_A2A - GCI Radius Test.lua @@ -0,0 +1,42 @@ +--- +-- Name: AID-021 - AI_A2A - GCI Radius Test +-- Author: FlightControl +-- Date Created: 30 May 2017 + + +-- Define a SET_GROUP object that builds a collection of groups that define the EWR network. +-- Here we build the network with all the groups that have a name starting with DF CCCP AWACS and DF CCCP EWR. +DetectionSetGroup = SET_GROUP:New() +DetectionSetGroup:FilterPrefixes( { "DF CCCP AWACS", "DF CCCP EWR" } ) +DetectionSetGroup:FilterStart() + +Detection = DETECTION_AREAS:New( DetectionSetGroup, 30000 ) + +-- Setup the A2A dispatcher, and initialize it. +A2ADispatcher = AI_A2A_DISPATCHER:New( Detection ) + +-- Initialize the dispatcher, setting up a radius of 100km where any airborne friendly +-- without an assignment within 100km radius from a detected target, will engage that target. +A2ADispatcher:SetEngageRadius( 200000 ) + +A2ADispatcher:SetGciRadius( 100000 ) + +A2ADispatcher:SetTacticalDisplay( true ) + + +-- Setup the squadrons. + +A2ADispatcher:SetSquadron( "Kras1", AIRBASE.Caucasus.Krasnodar_Center, { "SQ CCCP SU-27" } ) +A2ADispatcher:SetSquadronGci( "Kras1", 900, 1200 ) + +A2ADispatcher:SetSquadron( "Kras2", AIRBASE.Caucasus.Krasnodar_Pashkovsky, { "SQ CCCP SU-27" } ) +A2ADispatcher:SetSquadronGci( "Kras2", 900, 1200 ) + +A2ADispatcher:SetSquadron( "May", AIRBASE.Caucasus.Maykop_Khanskaya, { "SQ CCCP SU-27" } ) +A2ADispatcher:SetSquadronGci( "May", 900, 1200 ) + + + +A2ADispatcher:SetDefaultTakeoffInAir() +A2ADispatcher:SetDefaultLandingNearAirbase() + diff --git a/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-022 - GCI Overhead/AID-022 - AI_A2A - GCI Overhead.lua b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-022 - GCI Overhead/AID-022 - AI_A2A - GCI Overhead.lua new file mode 100644 index 0000000000..d635243097 --- /dev/null +++ b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-022 - GCI Overhead/AID-022 - AI_A2A - GCI Overhead.lua @@ -0,0 +1,49 @@ +--- +-- Name: AID-022 - AI_A2A - GCI Overhead +-- Author: FlightControl +-- Date Created: 05 Sep 2017 + + +-- Define a SET_GROUP object that builds a collection of groups that define the EWR network. +-- Here we build the network with all the groups that have a name starting with DF CCCP AWACS and DF CCCP EWR. +DetectionSetGroup = SET_GROUP:New() +DetectionSetGroup:FilterPrefixes( { "DF CCCP AWACS", "DF CCCP EWR" } ) +DetectionSetGroup:FilterStart() + +Detection = DETECTION_AREAS:New( DetectionSetGroup, 30000 ) + +-- Setup the A2A dispatcher, and initialize it. +A2ADispatcher = AI_A2A_DISPATCHER:New( Detection ) + +-- Initialize the dispatcher, setting up a radius of 100km where any airborne friendly +-- without an assignment within 100km radius from a detected target, will engage that target. +A2ADispatcher:SetEngageRadius( 200000 ) + +A2ADispatcher:SetTacticalDisplay( true ) + + +-- Setup the squadrons. + +A2ADispatcher:SetSquadron( "May", AIRBASE.Caucasus.Maykop_Khanskaya, { "SQ CCCP SU-27" } ) +A2ADispatcher:SetSquadronGci( "May", 900, 1200 ) +A2ADispatcher:SetSquadronOverhead( "May", 0.25 ) + +A2ADispatcher:SetSquadron( "Kras", AIRBASE.Caucasus.Krasnodar_Center, { "SQ CCCP SU-27" } ) +A2ADispatcher:SetSquadronGci( "Kras", 900, 1200 ) +A2ADispatcher:SetSquadronOverhead( "Kras", 1.5 ) + +A2ADispatcher:SetDefaultTakeoffInAir() +A2ADispatcher:SetDefaultLandingNearAirbase() + +-- Blue attack simulation + +local Frequency = 30 + +BlueSpawn2 = SPAWN + :New( "RT NATO" ) + :InitLimit( 1, 40 ) + :InitRandomizeTemplate( { "SQ NATO A-10C", "SQ NATO F-15C", "SQ NATO F-16A", "SQ NATO F/A-18", "SQ NATO F-16C" } ) + :InitRandomizeRoute( 0, 0, 30000 ) + :InitDelayOn() + :SpawnScheduled( Frequency, 0.5 ) + diff --git a/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-032 - CAP Damage/AID-032 - AI_A2A - CAP Damage.lua b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-032 - CAP Damage/AID-032 - AI_A2A - CAP Damage.lua new file mode 100644 index 0000000000..bc8ac1a207 --- /dev/null +++ b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-032 - CAP Damage/AID-032 - AI_A2A - CAP Damage.lua @@ -0,0 +1,46 @@ +--- +-- Name: AID-032 - AI_A2A - CAP Damage +-- Author: FlightControl +-- Date Created: 29 Oct 2017 + + +-- Define a SET_GROUP object that builds a collection of groups that define the EWR network. +-- Here we build the network with all the groups that have a name starting with DF CCCP AWACS and DF CCCP EWR. +DetectionSetGroup = SET_GROUP:New() +DetectionSetGroup:FilterPrefixes( { "DF CCCP AWACS", "DF CCCP EWR" } ) +DetectionSetGroup:FilterStart() + +Detection = DETECTION_AREAS:New( DetectionSetGroup, 30000 ) + +-- Setup the A2A dispatcher, and initialize it. +A2ADispatcher = AI_A2A_DISPATCHER:New( Detection ) + +A2ADispatcher:SetTacticalDisplay( true ) + + +-- Setup the squadrons. + +A2ADispatcher:SetSquadron( "Kras1", AIRBASE.Caucasus.Krasnodar_Pashkovsky, { "SQ CCCP MIG-31" }, 20 ) +CAPZoneWest = ZONE_POLYGON:New( "CAP Zone West", GROUP:FindByName( "CAP Zone West" ) ) +A2ADispatcher:SetSquadronCap( "Kras1", CAPZoneWest, 4000, 8000, 600, 800, 800, 1200, "BARO" ) +A2ADispatcher:SetSquadronCapInterval( "Kras1", 2, 30, 120, 1 ) + +--A2ADispatcher:SetSquadron( "May", AIRBASE.Caucasus.Maykop_Khanskaya, { "SQ CCCP SU-27" }, 20 ) +--CAPZoneWest = ZONE_POLYGON:New( "CAP Zone West", GROUP:FindByName( "CAP Zone West" ) ) +--A2ADispatcher:SetSquadronCap( "May", CAPZoneWest, 4000, 8000, 600, 800, 800, 1200, "BARO" ) +--A2ADispatcher:SetSquadronCapInterval( "May", 1, 30, 120, 1 ) + +A2ADispatcher:SetDefaultTakeoffInAir() +A2ADispatcher:SetDefaultLandingAtEngineShutdown() + +-- Blue attack simulation + +local Frequency = 300 + +BlueSpawn2 = SPAWN + :New( "RT NATO 2" ) + :InitLimit( 6, 40 ) + :InitRandomizeTemplate( { "SQ NATO A-10C", "SQ NATO F-15C", "SQ NATO F-16A", "SQ NATO F/A-18", "SQ NATO F-16C" } ) + :InitRandomizeRoute( 0, 0, 30000 ) + :InitDelayOn() + :SpawnScheduled( Frequency, 0.5 ) diff --git a/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-040 - CAP Independent Detection in EWR/AID-040 - AI_A2A - CAP Independent Detection in EWR.lua b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-040 - CAP Independent Detection in EWR/AID-040 - AI_A2A - CAP Independent Detection in EWR.lua new file mode 100644 index 0000000000..2446a50124 --- /dev/null +++ b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-040 - CAP Independent Detection in EWR/AID-040 - AI_A2A - CAP Independent Detection in EWR.lua @@ -0,0 +1,47 @@ +--- +-- Name: AID-040 - AI_A2A - CAP Independent Detection in EWR +-- Author: FlightControl +-- Date Created: 30 Aug 2017 + + +-- Define a SET_GROUP object that builds a collection of groups that define the EWR network. +-- Here we build the network with all the groups that have a name starting with DF CCCP AWACS and DF CCCP EWR. +DetectionSetGroup = SET_GROUP:New() +DetectionSetGroup:FilterPrefixes( { "DF CCCP AWACS", "DF CCCP EWR" } ) +DetectionSetGroup:FilterStart() + +Detection = DETECTION_AREAS:New( DetectionSetGroup, 30000 ) + +-- Setup the A2A dispatcher, and initialize it. +A2ADispatcher = AI_A2A_DISPATCHER:New( Detection ) + +A2ADispatcher:SetTacticalDisplay( true ) + + +A2ADispatcher:SetEngageRadius( 90000 ) +-- Setup the squadrons. + +A2ADispatcher:SetSquadron( "Kras1", AIRBASE.Caucasus.Krasnodar_Pashkovsky, { "SQ CCCP SU-27" } ) +CAPZoneWest = ZONE_POLYGON:New( "CAP Zone West", GROUP:FindByName( "CAP Zone West" ) ) +A2ADispatcher:SetSquadronCap( "Kras1", CAPZoneWest, 4000, 8000, 600, 800, 800, 1200, "BARO" ) +A2ADispatcher:SetSquadronCapInterval( "Kras1", 4, 30, 120 ) + +--A2ADispatcher:SetSquadron( "May", AIRBASE.Caucasus.Maykop_Khanskaya, { "SQ CCCP SU-27" }, 20 ) +--CAPZoneWest = ZONE_POLYGON:New( "CAP Zone West", GROUP:FindByName( "CAP Zone West" ) ) +--A2ADispatcher:SetSquadronCap( "May", CAPZoneWest, 4000, 8000, 600, 800, 800, 1200, "BARO" ) +--A2ADispatcher:SetSquadronCapInterval( "May", 1, 30, 120 ) + +A2ADispatcher:SetDefaultTakeoffInAir() +A2ADispatcher:SetDefaultLandingNearAirbase() + +-- Blue attack simulation + +local Frequency = 180 + +BlueSpawn2 = SPAWN + :New( "RT NATO" ) + :InitLimit( 2, 40 ) + :InitRandomizeTemplate( { "SQ NATO A-10C", "SQ NATO F-15C", "SQ NATO F-16A", "SQ NATO F/A-18", "SQ NATO F-16C" } ) + :InitRandomizeRoute( 0, 0, 30000 ) + :InitDelayOn() + :SpawnScheduled( Frequency, 0.5 ) diff --git a/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-041 - CAP Independent Detection in EWR with Clients/AID-040 - AI_A2A - CAP Independent Detection in EWR.lua b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-041 - CAP Independent Detection in EWR with Clients/AID-040 - AI_A2A - CAP Independent Detection in EWR.lua new file mode 100644 index 0000000000..2446a50124 --- /dev/null +++ b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-041 - CAP Independent Detection in EWR with Clients/AID-040 - AI_A2A - CAP Independent Detection in EWR.lua @@ -0,0 +1,47 @@ +--- +-- Name: AID-040 - AI_A2A - CAP Independent Detection in EWR +-- Author: FlightControl +-- Date Created: 30 Aug 2017 + + +-- Define a SET_GROUP object that builds a collection of groups that define the EWR network. +-- Here we build the network with all the groups that have a name starting with DF CCCP AWACS and DF CCCP EWR. +DetectionSetGroup = SET_GROUP:New() +DetectionSetGroup:FilterPrefixes( { "DF CCCP AWACS", "DF CCCP EWR" } ) +DetectionSetGroup:FilterStart() + +Detection = DETECTION_AREAS:New( DetectionSetGroup, 30000 ) + +-- Setup the A2A dispatcher, and initialize it. +A2ADispatcher = AI_A2A_DISPATCHER:New( Detection ) + +A2ADispatcher:SetTacticalDisplay( true ) + + +A2ADispatcher:SetEngageRadius( 90000 ) +-- Setup the squadrons. + +A2ADispatcher:SetSquadron( "Kras1", AIRBASE.Caucasus.Krasnodar_Pashkovsky, { "SQ CCCP SU-27" } ) +CAPZoneWest = ZONE_POLYGON:New( "CAP Zone West", GROUP:FindByName( "CAP Zone West" ) ) +A2ADispatcher:SetSquadronCap( "Kras1", CAPZoneWest, 4000, 8000, 600, 800, 800, 1200, "BARO" ) +A2ADispatcher:SetSquadronCapInterval( "Kras1", 4, 30, 120 ) + +--A2ADispatcher:SetSquadron( "May", AIRBASE.Caucasus.Maykop_Khanskaya, { "SQ CCCP SU-27" }, 20 ) +--CAPZoneWest = ZONE_POLYGON:New( "CAP Zone West", GROUP:FindByName( "CAP Zone West" ) ) +--A2ADispatcher:SetSquadronCap( "May", CAPZoneWest, 4000, 8000, 600, 800, 800, 1200, "BARO" ) +--A2ADispatcher:SetSquadronCapInterval( "May", 1, 30, 120 ) + +A2ADispatcher:SetDefaultTakeoffInAir() +A2ADispatcher:SetDefaultLandingNearAirbase() + +-- Blue attack simulation + +local Frequency = 180 + +BlueSpawn2 = SPAWN + :New( "RT NATO" ) + :InitLimit( 2, 40 ) + :InitRandomizeTemplate( { "SQ NATO A-10C", "SQ NATO F-15C", "SQ NATO F-16A", "SQ NATO F/A-18", "SQ NATO F-16C" } ) + :InitRandomizeRoute( 0, 0, 30000 ) + :InitDelayOn() + :SpawnScheduled( Frequency, 0.5 ) diff --git a/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-041 - CAP Independent Detection in EWR with Clients/AID-041 - AI_A2A - CAP Independent Detection in EWR with Clients.lua b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-041 - CAP Independent Detection in EWR with Clients/AID-041 - AI_A2A - CAP Independent Detection in EWR with Clients.lua new file mode 100644 index 0000000000..2fa9bb138a --- /dev/null +++ b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-041 - CAP Independent Detection in EWR with Clients/AID-041 - AI_A2A - CAP Independent Detection in EWR with Clients.lua @@ -0,0 +1,49 @@ +--- +-- Name: AID-041 - AI_A2A - CAP Independent Detection in EWR with Clients +-- Author: FlightControl +-- Date Created: 01 Sep 2017 + + +-- Define a SET_GROUP object that builds a collection of groups that define the EWR network. +-- Here we build the network with all the groups that have a name starting with DF CCCP AWACS and DF CCCP EWR. +DetectionSetGroup = SET_GROUP:New() +DetectionSetGroup:FilterPrefixes( { "DF CCCP AWACS", "DF CCCP EWR" } ) +DetectionSetGroup:FilterStart() + +Detection = DETECTION_AREAS:New( DetectionSetGroup, 30000 ) +Detection:SetRefreshTimeInterval( 10 ) + +-- Setup the A2A dispatcher, and initialize it. +A2ADispatcher = AI_A2A_DISPATCHER:New( Detection ) + +A2ADispatcher:SetTacticalDisplay( true ) +A2ADispatcher:SetRefreshTimeInterval( 10 ) + + +A2ADispatcher:SetEngageRadius( 90000 ) +-- Setup the squadrons. + +A2ADispatcher:SetSquadron( "Kras1", AIRBASE.Caucasus.Krasnodar_Pashkovsky, { "SQ CCCP SU-27" } ) +CAPZoneWest = ZONE_POLYGON:New( "CAP Zone West", GROUP:FindByName( "CAP Zone West" ) ) +A2ADispatcher:SetSquadronCap( "Kras1", CAPZoneWest, 4000, 8000, 600, 800, 800, 1200, "BARO" ) +A2ADispatcher:SetSquadronCapInterval( "Kras1", 2, 30, 120 ) + +A2ADispatcher:SetSquadron( "May", AIRBASE.Caucasus.Maykop_Khanskaya, { "SQ CCCP SU-27" }, 20 ) +CAPZoneWest = ZONE_POLYGON:New( "CAP Zone West", GROUP:FindByName( "CAP Zone West" ) ) +A2ADispatcher:SetSquadronCap( "May", CAPZoneWest, 4000, 8000, 600, 800, 800, 1200, "BARO" ) +A2ADispatcher:SetSquadronCapInterval( "May", 2, 30, 120 ) + +A2ADispatcher:SetDefaultTakeoffInAir() +A2ADispatcher:SetDefaultLandingNearAirbase() + +-- Blue attack simulation + +--local Frequency = 600 +-- +--BlueSpawn2 = SPAWN +-- :New( "RT NATO" ) +-- :InitLimit( 2, 40 ) +-- :InitRandomizeTemplate( { "SQ NATO A-10C", "SQ NATO F-15C", "SQ NATO F-16A", "SQ NATO F/A-18", "SQ NATO F-16C" } ) +-- :InitRandomizeRoute( 0, 0, 30000 ) +-- :InitDelayOn() +-- :SpawnScheduled( Frequency, 0.5 ) diff --git a/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-060 - Takeoff From Runway Test/AID-060 - AI_A2A - Takeoff From Runway Test.lua b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-060 - Takeoff From Runway Test/AID-060 - AI_A2A - Takeoff From Runway Test.lua new file mode 100644 index 0000000000..f7ffb75693 --- /dev/null +++ b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-060 - Takeoff From Runway Test/AID-060 - AI_A2A - Takeoff From Runway Test.lua @@ -0,0 +1,67 @@ +--- +-- Name: AID-060 - AI_A2A - Takeoff From Runway Test +-- Author: FlightControl +-- Date Created: 21 Sep 2017 + + +-- Define a SET_GROUP object that builds a collection of groups that define the EWR network. +-- Here we build the network with all the groups that have a name starting with DF CCCP AWACS and DF CCCP EWR. +DetectionSetGroup = SET_GROUP:New() +DetectionSetGroup:FilterPrefixes( { "DF CCCP AWACS", "DF CCCP EWR" } ) +DetectionSetGroup:FilterStart() + +Detection = DETECTION_AREAS:New( DetectionSetGroup, 30000 ) + +-- Setup the A2A dispatcher, and initialize it. +A2ADispatcher = AI_A2A_DISPATCHER:New( Detection ) + +-- Enable the tactical display panel. +A2ADispatcher:SetTacticalDisplay( true ) + +-- Initialize the dispatcher, setting up a border zone. This is a polygon, +-- which takes the waypoints of a late activated group with the name CCCP Border as the boundaries of the border area. +-- Any enemy crossing this border will be engaged. +CCCPBorderZone = ZONE_POLYGON:New( "CCCP Border", GROUP:FindByName( "CCCP Border" ) ) +A2ADispatcher:SetBorderZone( CCCPBorderZone ) + +-- Initialize the dispatcher, setting up a radius of 100km where any airborne friendly +-- without an assignment within 100km radius from a detected target, will engage that target. +A2ADispatcher:SetEngageRadius( 250000 ) + +-- Setup the squadrons. +A2ADispatcher:SetSquadron( "Mineralnye", AIRBASE.Caucasus.Mineralnye_Vody, { "SQ CCCP SU-27" }, 20 ) + +-- Setup the overhead +A2ADispatcher:SetSquadronOverhead( "Mineralnye", 1.2 ) + +-- Setup the Grouping +A2ADispatcher:SetSquadronGrouping( "Mineralnye", 1 ) + +-- Setup the Takeoff methods +A2ADispatcher:SetSquadronTakeoff( "Mineralnye", AI_A2A_DISPATCHER.Takeoff.Runway ) + +-- Setup the Landing methods +A2ADispatcher:SetSquadronLandingAtRunway( "Mineralnye" ) + + +-- CAP Squadron execution. +--CAPZoneEast = ZONE_POLYGON:New( "CAP Zone East", GROUP:FindByName( "CAP Zone East" ) ) +--A2ADispatcher:SetSquadronCap( "Mineralnye", CAPZoneEast, 4000, 10000, 500, 600, 800, 900 ) +--A2ADispatcher:SetSquadronCapInterval( "Mineralnye", 2, 30, 60, 1 ) + +-- GCI Squadron execution. +A2ADispatcher:SetSquadronGci( "Mineralnye", 900, 1200 ) + +CleanUp = CLEANUP_AIRBASE:New( { AIRBASE.Caucasus.Novorossiysk } ) + + +-- Blue attack simulation +local Frequency = 60 + +BlueSpawn1 = SPAWN + :New( "RT NATO 1" ) + :InitLimit( 2, 10 ) + :InitRandomizeTemplate( { "SQ NATO A-10C", "SQ NATO F-15C", "SQ NATO F-16A", "SQ NATO F/A-18", "SQ NATO F-16C" } ) + :InitRandomizeRoute( 0, 0, 30000 ) + --:InitDelayOn() + :SpawnScheduled( Frequency, 0.4 ) diff --git a/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-061 - Takeoff From Ship Runway Test/AID-061 - AI_A2A - Takeoff From Ship Runway Test.lua b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-061 - Takeoff From Ship Runway Test/AID-061 - AI_A2A - Takeoff From Ship Runway Test.lua new file mode 100644 index 0000000000..c0bb328de6 --- /dev/null +++ b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-061 - Takeoff From Ship Runway Test/AID-061 - AI_A2A - Takeoff From Ship Runway Test.lua @@ -0,0 +1,61 @@ +--- +-- Name: AID-061 - AI_A2A - Takeoff From Ship Runway Test +-- Author: FlightControl +-- Date Created: 21 Sep 2017 + + +-- Define a SET_GROUP object that builds a collection of groups that define the EWR network. +-- Here we build the network with all the groups that have a name starting with DF CCCP AWACS and DF CCCP EWR. +DetectionSetGroup = SET_GROUP:New() +DetectionSetGroup:FilterPrefixes( { "DF CCCP AWACS", "DF CCCP EWR" } ) +DetectionSetGroup:FilterStart() + +Detection = DETECTION_AREAS:New( DetectionSetGroup, 30000 ) + +-- Setup the A2A dispatcher, and initialize it. +A2ADispatcher = AI_A2A_DISPATCHER:New( Detection ) + +-- Enable the tactical display panel. +A2ADispatcher:SetTacticalDisplay( true ) + +-- Initialize the dispatcher, setting up a radius of 100km where any airborne friendly +-- without an assignment within 100km radius from a detected target, will engage that target. +A2ADispatcher:SetEngageRadius( 250000 ) + +-- Setup the squadrons. +A2ADispatcher:SetSquadron( "Kuznetsov", "Kuznetsov", { "SQ CCCP SU-33" }, 20 ) + +-- Setup the overhead +A2ADispatcher:SetSquadronOverhead( "Kuznetsov", 1.2 ) + +-- Setup the Grouping +A2ADispatcher:SetSquadronGrouping( "Kuznetsov", 1 ) + +-- Setup the Takeoff methods +A2ADispatcher:SetSquadronTakeoff( "Kuznetsov", AI_A2A_DISPATCHER.Takeoff.Runway ) + +-- Setup the Landing methods +A2ADispatcher:SetSquadronLandingAtRunway( "Kuznetsov" ) + + +-- CAP Squadron execution. +--CAPZoneEast = ZONE_POLYGON:New( "CAP Zone East", GROUP:FindByName( "CAP Zone East" ) ) +--A2ADispatcher:SetSquadronCap( "Mineralnye", CAPZoneEast, 4000, 10000, 500, 600, 800, 900 ) +--A2ADispatcher:SetSquadronCapInterval( "Mineralnye", 2, 30, 60, 1 ) + +-- GCI Squadron execution. +A2ADispatcher:SetSquadronGci( "Kuznetsov", 900, 1200 ) + +CleanUp = CLEANUP_AIRBASE:New( { AIRBASE.Caucasus.Novorossiysk } ) + + +-- Blue attack simulation +local Frequency = 60 + +BlueSpawn1 = SPAWN + :New( "RT NATO 1" ) + :InitLimit( 2, 10 ) + :InitRandomizeTemplate( { "SQ NATO A-10C", "SQ NATO F-15C", "SQ NATO F-16A", "SQ NATO F/A-18", "SQ NATO F-16C" } ) + :InitRandomizeRoute( 0, 0, 30000 ) + --:InitDelayOn() + :SpawnScheduled( Frequency, 0.4 ) diff --git a/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-070 - CAP - Player Exit/AID-070 - AI_A2A - CAP - Player Exit.lua b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-070 - CAP - Player Exit/AID-070 - AI_A2A - CAP - Player Exit.lua new file mode 100644 index 0000000000..b5bd26d0f7 --- /dev/null +++ b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-070 - CAP - Player Exit/AID-070 - AI_A2A - CAP - Player Exit.lua @@ -0,0 +1,39 @@ +--- +-- Name: AID-070 - AI_A2A - CAP - Player Exit +-- Author: FlightControl +-- Date Created: 30 Oct 2017 +-- +-- Test Scenario(s): +-- +-- Now take a seat in the client plane as a player. +-- Do the following tests after the plane has been spawned. +-- 1. Immediately exit the plane. +-- 2. Only exit the plane once the defender is engaged. +-- 3. Let the defender shoot you. +-- In all these scenarios, observe if the defender is continuing its patrol. + + +-- Define a SET_GROUP object that builds a collection of groups that define the EWR network. +-- Here we build the network with all the groups that have a name starting with DF CCCP AWACS and DF CCCP EWR. +DetectionSetGroup = SET_GROUP:New() +DetectionSetGroup:FilterPrefixes( { "DF CCCP AWACS", "DF CCCP EWR" } ) +DetectionSetGroup:FilterStart() + +Detection = DETECTION_AREAS:New( DetectionSetGroup, 30000 ) + +-- Setup the A2A dispatcher, and initialize it. +A2ADispatcher = AI_A2A_DISPATCHER:New( Detection ) + +A2ADispatcher:SetTacticalDisplay( true ) + + +-- Setup the squadrons. + +A2ADispatcher:SetSquadron( "Kras1", AIRBASE.Caucasus.Krasnodar_Pashkovsky, { "SQ CCCP SU-27" }, 20 ) +CAPZoneWest = ZONE_POLYGON:New( "CAP Zone West", GROUP:FindByName( "CAP Zone West" ) ) +A2ADispatcher:SetSquadronCap( "Kras1", CAPZoneWest, 4000, 8000, 600, 800, 800, 1200, "BARO" ) +A2ADispatcher:SetSquadronCapInterval( "Kras1", 1, 30, 120, 1 ) + +A2ADispatcher:SetDefaultTakeoffInAir() +A2ADispatcher:SetDefaultLandingNearAirbase() + diff --git a/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-071 - GCI - Player Exit/AID-071 - AI_A2A - GCI - Player Exit.lua b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-071 - GCI - Player Exit/AID-071 - AI_A2A - GCI - Player Exit.lua new file mode 100644 index 0000000000..0cb00283b4 --- /dev/null +++ b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-071 - GCI - Player Exit/AID-071 - AI_A2A - GCI - Player Exit.lua @@ -0,0 +1,37 @@ +--- +-- Name: AID-071 - AI_A2A - GCI - Player Exit +-- Author: FlightControl +-- Date Created: 30 Oct 2017 +-- +-- Test Scenario(s): +-- +-- Now take a seat in the client plane as a player. +-- Do the following tests after the plane has been spawned. +-- 1. Immediately exit the plane. +-- 2. Only exit the plane once the defender is engaged. +-- 3. Let the defender shoot you. +-- In all these scenarios, observe if the defender is returning to base. + + +-- Define a SET_GROUP object that builds a collection of groups that define the EWR network. +-- Here we build the network with all the groups that have a name starting with DF CCCP AWACS and DF CCCP EWR. +DetectionSetGroup = SET_GROUP:New() +DetectionSetGroup:FilterPrefixes( { "DF CCCP AWACS", "DF CCCP EWR" } ) +DetectionSetGroup:FilterStart() + +Detection = DETECTION_AREAS:New( DetectionSetGroup, 30000 ) + +-- Setup the A2A dispatcher, and initialize it. +A2ADispatcher = AI_A2A_DISPATCHER:New( Detection ) + +A2ADispatcher:SetTacticalDisplay( true ) + + +-- Setup the squadrons. + +A2ADispatcher:SetSquadron( "Kras1", AIRBASE.Caucasus.Krasnodar_Pashkovsky, { "SQ CCCP SU-27" }, 20 ) +A2ADispatcher:SetSquadronGci( "Kras1", 800, 1200 ) + +A2ADispatcher:SetDefaultTakeoffInAir() +A2ADispatcher:SetDefaultLandingNearAirbase() + diff --git a/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-210 - GCICAP Demonstration/AID-210 - NTTR AI_A2A_GCICAP Demonstration.lua b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-210 - GCICAP Demonstration/AID-210 - NTTR AI_A2A_GCICAP Demonstration.lua new file mode 100644 index 0000000000..4bf78b201f --- /dev/null +++ b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-210 - GCICAP Demonstration/AID-210 - NTTR AI_A2A_GCICAP Demonstration.lua @@ -0,0 +1,54 @@ + + +-- RED + +--- Setup the Red Coalition A2A GCICAP dispatcher, and initialize it. +A2A_GCICAP_Red = AI_A2A_GCICAP:New( { "RED EWR" }, { "4477th" }, { }, 2 ) + +A2A_GCICAP_Red:SetBorderZone( ZONE_POLYGON:New( "Red Border", GROUP:FindByName( "Red Border" ) ) ) + +-- Enable the tactical display panel. This is to see what this dispatcher is doing. +--A2A_GCICAP_Red:SetTacticalDisplay( true ) + + +-- Initialize the dispatcher, setting up a radius of 150km where any airborne friendly +-- without an assignment within 150km radius from a detected target, will engage that target. +A2A_GCICAP_Red:SetEngageRadius( 150000 ) + +-- The default take-off method is planes takeoff right in the air. +-- Here we specify to take off from a parking space, with engines already running. +A2A_GCICAP_Red:SetSquadronTakeoffFromParkingHot( AIRBASE.Nevada.Tonopah_Test_Range_Airfield ) +--A2A_GCICAP_Red:SetSquadronTakeoffFromParkingHot( "Groom Lake AFB" ) + + +-- BLUE + + +--- Setup the Red Coalition A2A GCICAP dispatcher, and initialize it. +-- EWR network groups start with BLUE EWR. +-- Squadron templates which are placed above the colored airbase, start with 104th or 105th or 106th. +-- Perform CAP in a polygon zone placed near 104th, which is Nellis. +-- Perform 2 CAP. +A2A_GCICAP_Blue = AI_A2A_GCICAP:New( { "BLUE EWR" }, { "104th", "105th", "106th" }, { "104th CAP" }, 2 ) + +A2A_GCICAP_Blue:SetBorderZone( ZONE_POLYGON:New( "Blue Border", GROUP:FindByName( "Blue Border" ) ) ) + +-- Enable the tactical display panel. This is to see what this dispatcher is doing. +--A2A_GCICAP_Blue:SetTacticalDisplay( true ) + + +-- Initialize the dispatcher, setting up a radius of 150km where any airborne friendly +-- without an assignment within 150km radius from a detected target, will engage that target. +A2A_GCICAP_Blue:SetEngageRadius( 150000 ) + +-- The default take-off method is planes takeoff right in the air. +-- Here we specify other take off options. +A2A_GCICAP_Blue:SetSquadronTakeoffFromRunway( AIRBASE.Nevada.Boulder_City_Airport ) -- Takeoff from the runway. +A2A_GCICAP_Blue:SetSquadronTakeoffFromParkingCold( AIRBASE.Nevada.McCarran_International_Airport ) -- Takeoff from parking spot, with engines shut off. +--A2A_GCICAP_Blue:SetSquadronTakeoffFromParkingHot( AIRBASE.Nevada.Nellis_AFB ) -- Takaeoff from parking spot, engines running. + +-- The Nellis airbase contains a squadron that flies an F-5... Less modern airplane. +-- So it needs a stronger "overhead". +A2A_GCICAP_Blue:SetSquadronOverhead( AIRBASE.Nevada.Nellis_AFB, 2 ) -- When 2 airplanes are attacking, we spawn 4 airplanes for defense. +A2A_GCICAP_Blue:SetSquadronGrouping( AIRBASE.Nevada.Nellis_AFB, 2 ) -- We group the spawned defence airplanes per 2 units. + diff --git a/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-210 - GCICAP Demonstration/NTTR AI_A2A_GCICAP Test.lua b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-210 - GCICAP Demonstration/NTTR AI_A2A_GCICAP Test.lua new file mode 100644 index 0000000000..4bf78b201f --- /dev/null +++ b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-210 - GCICAP Demonstration/NTTR AI_A2A_GCICAP Test.lua @@ -0,0 +1,54 @@ + + +-- RED + +--- Setup the Red Coalition A2A GCICAP dispatcher, and initialize it. +A2A_GCICAP_Red = AI_A2A_GCICAP:New( { "RED EWR" }, { "4477th" }, { }, 2 ) + +A2A_GCICAP_Red:SetBorderZone( ZONE_POLYGON:New( "Red Border", GROUP:FindByName( "Red Border" ) ) ) + +-- Enable the tactical display panel. This is to see what this dispatcher is doing. +--A2A_GCICAP_Red:SetTacticalDisplay( true ) + + +-- Initialize the dispatcher, setting up a radius of 150km where any airborne friendly +-- without an assignment within 150km radius from a detected target, will engage that target. +A2A_GCICAP_Red:SetEngageRadius( 150000 ) + +-- The default take-off method is planes takeoff right in the air. +-- Here we specify to take off from a parking space, with engines already running. +A2A_GCICAP_Red:SetSquadronTakeoffFromParkingHot( AIRBASE.Nevada.Tonopah_Test_Range_Airfield ) +--A2A_GCICAP_Red:SetSquadronTakeoffFromParkingHot( "Groom Lake AFB" ) + + +-- BLUE + + +--- Setup the Red Coalition A2A GCICAP dispatcher, and initialize it. +-- EWR network groups start with BLUE EWR. +-- Squadron templates which are placed above the colored airbase, start with 104th or 105th or 106th. +-- Perform CAP in a polygon zone placed near 104th, which is Nellis. +-- Perform 2 CAP. +A2A_GCICAP_Blue = AI_A2A_GCICAP:New( { "BLUE EWR" }, { "104th", "105th", "106th" }, { "104th CAP" }, 2 ) + +A2A_GCICAP_Blue:SetBorderZone( ZONE_POLYGON:New( "Blue Border", GROUP:FindByName( "Blue Border" ) ) ) + +-- Enable the tactical display panel. This is to see what this dispatcher is doing. +--A2A_GCICAP_Blue:SetTacticalDisplay( true ) + + +-- Initialize the dispatcher, setting up a radius of 150km where any airborne friendly +-- without an assignment within 150km radius from a detected target, will engage that target. +A2A_GCICAP_Blue:SetEngageRadius( 150000 ) + +-- The default take-off method is planes takeoff right in the air. +-- Here we specify other take off options. +A2A_GCICAP_Blue:SetSquadronTakeoffFromRunway( AIRBASE.Nevada.Boulder_City_Airport ) -- Takeoff from the runway. +A2A_GCICAP_Blue:SetSquadronTakeoffFromParkingCold( AIRBASE.Nevada.McCarran_International_Airport ) -- Takeoff from parking spot, with engines shut off. +--A2A_GCICAP_Blue:SetSquadronTakeoffFromParkingHot( AIRBASE.Nevada.Nellis_AFB ) -- Takaeoff from parking spot, engines running. + +-- The Nellis airbase contains a squadron that flies an F-5... Less modern airplane. +-- So it needs a stronger "overhead". +A2A_GCICAP_Blue:SetSquadronOverhead( AIRBASE.Nevada.Nellis_AFB, 2 ) -- When 2 airplanes are attacking, we spawn 4 airplanes for defense. +A2A_GCICAP_Blue:SetSquadronGrouping( AIRBASE.Nevada.Nellis_AFB, 2 ) -- We group the spawned defence airplanes per 2 units. + diff --git a/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-210 - GCICAP Demonstration/TAC_NTTR_V.2A_GCICAP_SCRIPT.lua b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-210 - GCICAP Demonstration/TAC_NTTR_V.2A_GCICAP_SCRIPT.lua new file mode 100644 index 0000000000..1e9fb1e07b --- /dev/null +++ b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-210 - GCICAP Demonstration/TAC_NTTR_V.2A_GCICAP_SCRIPT.lua @@ -0,0 +1,1748 @@ +--[[ +Copyright (c) 2016 Snafu, Stonehouse, Rivvern, Chameleon Silk, lukrop. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute copies of the Software, +and to permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software and the Software shall not be +included in whole or part in any sort of paid for software or paid for downloadable +content (DLC) without the express permission of the copyright holders. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +]] + +--[[-- +## Overview +Autonomous GCI and CAP script for DCS: World. +The script provides an autonomous model of combat air patrols and ground controlled +interceptors for use with DCS World by mission builders. + +After minimal setup the script will automatically spawn CAP and GCI flights for two +sides and give them patrol and intercept tasks as well as returning them to base when +threats cease to be detected. + +Originally created by Snafu, enhanced and further modified by Stonehouse, +Rivvern, Chameleon Silk. + +Rewritten by lukrop. + +## Links + +Github repository: + +@script GCICAP +@author Snafu +@author Stonehouse +@author Rivvern +@author Chameleon Silk +@author lukrop +@copyright 2016 Snafu, Stonehouse, Rivvern, Chameleon Silk, lukrop. +@license Modified MIT. See LICENSE file. +]] + +gcicap = {} +gcicap.red = {} +gcicap.red.gci = {} +gcicap.red.cap = {} +gcicap.blue = {} +gcicap.blue.gci = {} +gcicap.blue.cap = {} +gcicap.cap = {} +gcicap.gci = {} + +--- Sets how verbose the log output will be. +-- Possible values are "none", "info", "warning" and "error". +-- I recommend "error" for production. +gcicap.log_level = "error" + +--- Interval, in seconds, of main function. +-- Default 30 seconds. +gcicap.interval = 30 + +--- Interval, in seconds, GCI flights get vectors on targets. +-- AI GCI flights don't use their radar, to be as stealth as +-- possible, relying on those vectors. +-- Default 15 seconds. +gcicap.vector_interval = 15 + +--- How far does a target have to move before an intercept is revectored +gcicap.revector_threshold = 15000 + +--- Initial spawn delay between CAPs +-- Default 30 seconds. +gcicap.initial_spawn_delay = 30 + +--- Enable/disable borders for the red side. +-- CAP units only engage if enemy units intrude their airspace +gcicap.red.borders_enabled = true + +--- Enable/disable borders for the blue side. +-- CAP units only engage if enemy units intrude their airspace +gcicap.blue.borders_enabled = true + +--- CAP minimum altitudes in meters. +-- Default 4500 +gcicap.cap.min_alt = 6100 + +--- CAP maximum altitudes in meters. +-- Default 7500 +gcicap.cap.max_alt = 10500 + +--- Speed for CAP flights on their CAP route. +-- speed is in m/s. Default 220. +gcicap.cap.speed = 220 + +--- Speed for GCI flights on intercept +-- speed is in m/s. Default 300. +gcicap.gci.speed = 300 + +--- Maximum engage distance for CAP flights as long as they are on patrol. +-- this might be overruled by an intercept vector given from +-- ground control (EWR). Default 15000. +gcicap.cap.max_engage_distance = 15000 + +--- Minimum red CAP VUL time in minutes. +-- Minimum time the red CAP flight will orbit on station. +gcicap.red.cap.vul_time_min = 25 + +--- Maximum red CAP VUL time in minutes. +-- Maximum time the red CAP flight will orbit on station. +gcicap.red.cap.vul_time_max = 40 + +--- Minimum blue CAP VUL time in minutes. +gcicap.blue.cap.vul_time_min = 25 + +--- Maximum blue CAP VUL time in minutes. +gcicap.blue.cap.vul_time_max = 30 + +--- Use race-track orbit for CAP flights +-- If true CAPs will use a race-track pattern for orbit +-- between two points in the CAP zone. +gcicap.cap.race_track_orbit = false + +--[[ INOP at the time +--- Minimum leg length for red CAP orbits in meters. +gcicap.red.cap.leg_min = 10000 + +--- Maximum leg length for red CAP orbits in meters. +gcicap.red.cap.leg_min = 20000 + +--- Minimum leg length for blue CAP orbits in meters. +gcicap.blue.cap.leg_min = 10000 + +--- Maximum leg length for blue CAP orbits in meters. +gcicap.blue.cap.leg_min = 20000 +]]-- + +--- Enable/disable red CAP flights airborne start. +-- set to true for CAP flight to start airborne at script initialisation +-- (mission start), false for taking off from the airfield. +-- Default true. +gcicap.red.cap.start_airborne = false + +--- Enable/disable blue CAP flights airborne start. +gcicap.blue.cap.start_airborne = false + +--- Amount of red CAP zones. +-- placed with triggerzones in the ME. +gcicap.red.cap.zones_count = 4 + +--- Amount of blue CAP zones. +gcicap.blue.cap.zones_count = 4 + +--- Amount of red CAP groups concurrently in the air. +gcicap.red.cap.groups_count = 3 + +--- Amount of blue CAP groups concurrently in the air. +gcicap.blue.cap.groups_count = 2 + +--- Group size of red CAP flights. +-- Can be "2", "4" or "randomized" +-- +-- If "2" it consists of 2 planes, if "4" it consists of 4 planes +-- if "randomized", the CAP groups consist of either 2 or 4 planes +gcicap.red.cap.group_size = "randomized" + +--- Group size of blue CAP flights. +-- See @{gcicap.red.cap.group_size} +gcicap.blue.cap.group_size = "4" + +--- Maximum amount of concurrent red intercepts. +gcicap.red.gci.groups_count = 3 + +--- Maximum amount of concurrent blue intercepts. +gcicap.blue.gci.groups_count = 2 + +--- Group size of red GCI flights. +-- Can be "2", "4" or "dynamic" +-- +-- If "2" it consists of 2 planes, if "4" it consists of 4 planes +-- if "dynamic", the GCI groups consist of as much aircrafts +-- as the intruder group. +gcicap.red.gci.group_size = "dynamic" + +--- Group size of blue GCI flights. +-- See @{gcicap.red.gci.group_size} +gcicap.blue.gci.group_size = "dynamic" + +--- Enable/disable GCI messages for red +gcicap.red.gci.messages = false + +--- Enable/disable GCI messages for blue +gcicap.blue.gci.messages = false + +--- How long a GCI message will be shown in seconds. +gcicap.gci.message_time = 5 + +--- Display GCI messages with metric measurment for red. +-- If false the imperial system is used. +gcicap.red.gci.messages_metric = true + +--- Display GCI messages with metric measurment for blue. +-- If false the imperial system is used. +gcicap.blue.gci.messages_metric = false + +--- Names of red groups which will receive GCI messages. +-- Leave blank for all groups of coalition +-- @usage gcicap.red.gci.messages_to = { "my group 1", "GCI Flight" } +gcicap.red.gci.messages_to = {} + +--- Names of blue groups which will receive GCI messages. +-- See @{gcicap.red.gci.messages_to} for format. +gcicap.blue.gci.messages_to = {} + +--- How red CAP flights are spawned. +-- can be "parking", "takeoff" or "air" and defines the way the fighters spawn +-- takeoff is NOT RECOMMENDED currently since their occur timing issues with tasking +-- if a flight is queued for takeoff and not already in the game world while getting tasked +-- +-- Default 'parking' +gcicap.red.cap.spawn_mode = "parking" + +--- How red GCI flights are spawned. +-- @see gcicap.red.cap.spawn_mode +gcicap.red.gci.spawn_mode = "parking" + +--- How blue CAP flights are spawned. +-- @see gcicap.red.cap.spawn_mode +gcicap.blue.cap.spawn_mode = "parking" + +--- How blue GCI flights are spawned. +-- @see gcicap.red.cap.spawn_mode +gcicap.blue.gci.spawn_mode = "parking" + +--- Hide or reveal blue air units in the mission. +gcicap.blue.hide_groups = false + +--- Hide or reveal red air units in the mission. +gcicap.red.hide_groups = false + +--- Enable/disable red CAP flights. +gcicap.red.cap.enabled = true + +--- Enable/disable blue CAP flights. +gcicap.blue.cap.enabled = true + +--- Enable/disable red GCI flights. +gcicap.red.gci.enabled = true + +--- Enable/disable blue GCI flights. +gcicap.blue.gci.enabled = true + +--- Enabel/disable resource limitation for red. +-- If set to true limits the amount of groups a side can spawn. +gcicap.red.limit_resources = false + +--- Enabel/disable resource limitation for blue. +-- @see gcicap.red.limit_resources +gcicap.blue.limit_resources = false + +--- Amount of groups(!) red has at it's disposal. +-- In other words how many Groups of airplanes +-- this side can spawn. +gcicap.red.supply = 24 + +--- Amount of groups(!) red has at it's disposal. +-- @see gcicap.red.supply +gcicap.blue.supply = 24 + +--- Name of the trigger zone which defines red CAP zones. +-- This will be postfixed with the number of +-- the zone. e.g. "redCAPzone3" or "blueCAPzone1". +-- +-- Default: 'redCAPzone'. +gcicap.red.cap.zone_name = 'redCAPzone' + +--- Name of the trigger zone which defines blue CAP zones. +-- Default: 'blueCAPzone'. +-- @see gcicap.red.cap.zone_name +gcicap.blue.cap.zone_name = 'blueCAPzone' + +--- Name of group which waypoints define the red border. +-- Default: 'redborder'. +gcicap.red.border_group = 'redborder' + +--- Name of group which waypoints define the blue border. +-- Default: 'blueborder'. +gcicap.blue.border_group = 'blueborder' + +--- GCI template unit's names prefix. +gcicap.gci.template_prefix = '__GCI__' + +--- CAP template unit's names prefix. +gcicap.cap.template_prefix = '__CAP__' + +--- Count of template units. +-- Remember that this means you need that many +-- template units for each type. E.g. if the template_count is 2 you +-- would need two GCI and two CAP template units for each side. +gcicap.template_count = 4 + +--- Wether red will also acquire targets by AWACS aircraft. +-- This is is currently broken since isTargetDetected doesn't +-- seem to work with AWACS airplanes. Needs a workaround. +-- +-- Default false. +gcicap.red.awacs = false + +--- Wether blue will also acquire targets by AWACS aircraft. +-- @see gcicap.red.awacs +gcicap.blue.awacs = true + +--- Garbage collector move timeout +-- If a unit (aircraft) is on the ground and didn't move +-- since this timeout, in seconds, it will be removed. +-- This applies only to aircraft spawned by GCICAP. +gcicap.move_timeout = 300 + +-- shortcut to the bullseye +gcicap.red.bullseye = coalition.getMainRefPoint(coalition.side.RED) +gcicap.blue.bullseye = coalition.getMainRefPoint(coalition.side.BLUE) + +gcicap.sides = { "red", "blue" } +gcicap.tasks = { "cap", "gci" } + +gcicap.log = mist.Logger:new("GCICAP", gcicap.log_level) + +do + --- Flight class. + -- @type gcicap.Flight + gcicap.Flight = {} + + local function getFlightIndex(group) + if type(group) ~= "string" then + if group:getName() then + group = group:getName() + else + return false + end + end + for i, side in pairs(gcicap.sides) do + for j, task in pairs(gcicap.tasks) do + for n = 1, #gcicap[side][task].flights do + if gcicap[side][task].flights[n].group_name == group then + return {side = side, task = task, index = n} + end + end + end + end + return false + end + + --- Returns the flight for the given group. + -- @tparam string|Group group this can be a Group object + -- or the group name. + -- @treturn gcicap.Flight the flight for the given group. + function gcicap.Flight.getFlight(group) + f = getFlightIndex(group) + if f then + return gcicap[f.side][f.task].flights[f.index] + else + return false + end + end + + --- Creates a new flight. + -- @tparam Group group group of the flight. + -- @tparam Airbase airbase homplate of the new flight. + -- @tparam string task task of the new flight. Can be "cap" or "gci". + -- @param param task parameter. This can be a zone table if it's a + -- CAP flight or it could be a target unit if it's a GCI flight. + function gcicap.Flight:new(group, airbase, task, param) + if group:isExist() then + local side = gcicap.coalitionToSide(group:getCoalition()) + local f = {} + f.side = side + f.give_up = false + f.group = group + f.group_name = group:getName() + f.airbase = airbase + f.task = task + -- is the flight RTB? + f.rtb = false + f.in_zone = false + + if task == "cap" then + f.zone = param + f.zone_name = param.name + f.intercepting = false + f.vul_time = math.random(gcicap[side].cap.vul_time_min, + gcicap[side].cap.vul_time_max) + else -- task should be "gci" + f.target = param + f.target_group = param.group + f.intercepting = true + f.intercept_point = { x = 0, y = 0, z = 0 } + end + + -- get current timestamp + local timestamp = timer.getAbsTime() + f.units_moved = {} + -- set timestamp for each unit + -- this is later used for garbage collection checks + for u, unit in pairs(group:getUnits()) do + f.units_moved[u] = {} + f.units_moved[u].unit = unit + f.units_moved[u].last_moved = timestamp + f.units_moved[u].spawned_at = timestamp + end + + setmetatable(f, self) + self.__index = self + + table.insert(gcicap[side][task].flights, f) + gcicap.log:info("Registered flight: $1", f.group_name) + + return f + else + return nil + end + end + + --- Removes the flight + -- @tparam gcicap.Flight self flight object + function gcicap.Flight:remove() + if self.zone then + -- if we didn't already leave the zone do it now. + self:leaveCAPZone() + end + local f = getFlightIndex(self.group_name) + local r = table.remove(gcicap[f.side][f.task].flights, f.index) + if r then + gcicap.log:info("Removing flight $1 with index $2", r.group_name, f.index) + end + end + + --- Decreases active flights counter in this flights zone. + -- Actually just decreases the active flights + -- counter of a zone. Does NOT task the flight itself. + function gcicap.Flight:leaveCAPZone() + if self.in_zone then + local zone = self.zone + if zone.patrol_count <= 1 then + zone.patrol_count = 0 + else + zone.patrol_count = zone.patrol_count - 1 + end + self.in_zone = false + + -- get current time + local time_now = timer.getAbsTime() + -- get time on station by substracting vul start time from current time + -- and convert it to minutes + local time_on_station = 0 + if self.vul_start then + time_on_station = (time_now - self.vul_start) / 60 + end + local vul_diff = self.vul_time - time_on_station + -- set new vul time only if more than 5 minutes + if vul_diff > 5 then + self.vul_time = vul_diff + else + self.vul_time = 0 + end + end + end + + --- Increases active flights counter in this flights zone. + -- Actually just increases the active flights + -- counter of a zone. Does NOT task the flight itself. + function gcicap.Flight:enterCAPZone() + if not self.in_zone then + self.intercepting = false + self.in_zone = true + local zone = self.zone + zone.patrol_count = zone.patrol_count + 1 + end + end + + --- Tasks the flight to search and engage the target. + -- @tparam Unit intruder target unit. + -- @tparam[opt] boolean cold whether the flight should not destroy + -- the target and just follow it. Default false. + function gcicap.Flight:vectorToTarget(intruder, cold) + local target = nil + if intruder.group then + target = gcicap.getFirstActiveUnit(intruder.group) + end + if target == nil or intruder.group == nil then return end + + -- check if interceptor even still exists + if self.group:isExist() then + if target:isExist() and target:inAir() and self.give_up ~= true then + local target_pos = target:getPoint() + local ctl = self.group:getController() + + local gci_task = { + id = 'Mission', + params = { + route = { + points = { + [1] = { + alt = target_pos.y, + x = target_pos.x, + y = target_pos.z, + speed = gcicap.gci.speed, + action = "Turning Point", + type = "Turning Point", + task = { + id = "ComboTask", + params = { + tasks = { + [1] = { + number = 1, + key = "CAP", + id = "EngageTargets", + enabled = true, + auto = true, + params = { + targetTypes = { [1] = "Air" }, + priority = 0 + } + } + } + } + } + }, + [2] = { + alt = target_pos.y, + x = target_pos.x, + y = target_pos.z, + speed = gcicap.gci.speed, + action = "Turning Point", + type = "Turning Point", + task = { + -- i don't really like this WrappedAction but it's needed in + -- the case the CGI completes this waypoint because of lack/loss + -- of target + id = 'WrappedAction', + params = { + action = { + id = 'Script', + params = { + command = "local group = ...\ + local flight = gcicap.Flight.getFlight(group)\ + if flight then\ + flight.give_up = true\ + if flight.zone then\ + if flight.intercepting then\ + flight:taskWithCAP()\ + end\ + else\ + if not flight.target then\ + flight:taskWithRTB()\ + end\ + end\ + else\ + gcicap.log:error('Could not find flight')\ + end" + } + } + } + } + } + } + } + } + } + + -- checkout of the patrol zone + if self.zone and not self.intercepting then + self:leaveCAPZone() + end + + intruder.intercepted = true + -- only set/reset the task if the target has moved significantly since last GCI update + if mist.utils.get3DDist( target_pos, self.intercept_point ) > gcicap.revector_threshold then + -- if there's still an EWR detecting or we are responding to the initial call + -- then set the target position. do not allow revectoring if no EWR is detecting us now + if (Unit.isExist(intruder.detected_by) and intruder.detected_by:isActive()) then + self.give_up = false + self.intercept_point = mist.utils.deepCopy(target_pos) + ctl:setTask(gci_task) + gcicap.log:info("Vectoring $1 to $2 ($3)", self.group:getName(), + intruder.group:getName(), target:getName()) + + else + gcicap.log:info("Cannot revector $1 to $2 because no longer detecting",self.group:getName(),intruder.group:getName()) + end + end + self.intercepting = true + + -- taskEngageGroup provides omniscient knowledge of where the group to be attacked is, which sucks + if not cold then + --gcicap.taskEngageGroup(self.group, intruder.group) + gcicap.taskEngage(self.group, 15000) + end + + -- reschedule function until either the interceptor or the intruder is dead + mist.scheduleFunction(gcicap.Flight.vectorToTarget, {self, intruder, cold}, + timer.getTime() + gcicap.vector_interval) + + else -- the target is dead or we had to give up, resume CAP or RTB + if self.zone then + -- send CAP back to work only if still intercepting + if self.intercepting then + self:taskWithCAP() + end + else + self.intercepting = false + -- send GCI back to homeplate + self:taskWithRTB() + end + end + else + -- our interceptor group is dead let's see if the + -- intruder is still there and set him to not beeing intercepted anymore + if target:isExist() then + intruder.intercepted = false + end + end + end + + --- Tasks flight with combat air patrol. + -- Creates waypoints inside it's assigned zone and tasks + -- the flight with patroling along the route. + -- @tparam[opt] boolean cold If set to true the flight won't + -- engage any enemy unit's it detects by itself. Default false. + function gcicap.Flight:taskWithCAP(cold) + -- only task with CAP if ther is still vul time left + if self.vul_time == 0 then + -- send flight RTB if no vul time left. + gcicap.log:info("No vul time left for $1", self.group_name) + self:taskWithRTB() + else + local group = self.group + local ctl = group:getController() + local side = gcicap.coalitionToSide(group:getCoalition()) + local start_pos = gcicap.getFirstActiveUnit(group):getPoint() + local leg_dist = math.random(gcicap[side].cap.leg_min, gcicap[side].cap.leg_max) + local cap_route = gcicap.buildCAPRoute(start_pos, self.zone.name, self.vul_time, leg_dist) + local cap_task = { + id = 'Mission', + params = { + route = cap_route + } + } + + self.intercepting = false + self.intercept_point = { x = 0, y = 0, z = 0 } + ctl:setTask(cap_task) + self:enterCAPZone() + ctl:setOption(AI.Option.Air.id.RADAR_USING, AI.Option.Air.val.RADAR_USING.FOR_SEARCH_IF_REQUIRED) + + if not cold then + gcicap.taskEngage(group) + end + gcicap.log:info("Tasking $1 with CAP in zone $2", group:getName(), self.zone.name) + end + end + + --- Tasks the flight to return to it's homeplate. + -- @tparam[opt] Airbase airbase optionally use this as homeplate/airbase + -- to return to. + -- @tparam[opt] boolean cold If set to true the flight won't + -- engage any targets it detects on the way back to base. + -- Default false. + function gcicap.Flight:taskWithRTB(airbase, cold) + if not airbase then + airbase = self.airbase + end + + if self.zone then + self:leaveCAPZone() + local side = self.side + -- let's try to spawn a new CAP flight as soon as the current one is tasked with RTB. + -- never spawn more than 2 x the groups_count, to prevent spam in case something ever goes wrong. + if (not gcicap[side].limit_resources or + (gcicap[side].limit_resources and gcicap[side].supply > 0)) + and #gcicap[side].cap.flights < gcicap[side].cap.groups_count * 2 then + gcicap.spawnCAP(side, self.zone, gcicap[side].cap.spawn_mode) + end + end + self.rtb = true + local group = self.group + local ctl = group:getController() + local af_pos = mist.utils.makeVec2(airbase:getPoint()) + local af_id = airbase:getID() + local rtb_task = { + id = 'Mission', + params = { + route = { + points = { + [1] = { + alt = gcicap.cap.min_alt, + alt_type = "BARO", + speed = gcicap.cap.speed, + x = af_pos.x, + y = af_pos.y, + aerodromeId = af_id, + type = "Land", + action = "Landing", + } + } + } + } + } + + ctl:setTask(rtb_task) + + if not cold then + -- only engage if enemy is inside of 10km of the leg + gcicap.taskEngage(group, 10000) + end + + gcicap.log:info("Tasking $1 with RTB to $2", group:getName(), airbase:getName()) + end + + --- Functions + -- @section gcicap + + --- Clean up inactive/stuck flights. + local function garbageCollector(side) + local timestamp = timer.getAbsTime() + for t, task in pairs(gcicap.tasks) do + for f, flight in pairs(gcicap[side][task].flights) do + if flight.group then + if flight.group:isExist() then + for u = 1, #flight.units_moved do + local unit = flight.units_moved[u].unit + -- check if unit exists + if unit then + if unit:isExist() then + -- if unit is in air we won't do anything + if not unit:inAir() then + -- check if unit is moving + local mag = mist.vec.mag(unit:getVelocity()) + if mag == 0 then + -- get the last time the unit moved + local last_moved = flight.units_moved[u].last_moved + if timestamp - last_moved > gcicap.move_timeout then + gcicap.log:info("Cleaning up $1", flight.group:getName()) + flight.group:destroy() + flight:remove() + end + else + flight.units_moved[u].last_moved = timestamp + end + end + end + end + end + else + flight:remove() + end + else + flight:remove() + end + end + end + end + + local function checkForTemplateUnits(side) + if gcicap[side].gci.enabled then + for i = 1, gcicap.template_count do + local unit = gcicap.gci.template_prefix..side..i + if not Unit.getByName(unit) then + gcicap.log:alert("GCI template unit missing: $1", unit) + return false + end + end + end + if gcicap[side].cap.enabled then + for i = 1, gcicap.template_count do + local unit = gcicap.cap.template_prefix..side..i + if not Unit.getByName(unit) then + gcicap.log:alert("CAP template unit missing: $1", unit) + return false + end + end + end + if gcicap[side].borders_enabled then + if not Group.getByName(gcicap[side].border_group) then + gcicap.log:alert("Border group is missing: $1", gcicap[side].border_group) + return false + end + end + return true + end + + local function checkForTriggerZones(side) + for i = 1, gcicap[side].cap.zones_count do + local zone_name = gcicap[side].cap.zone_name..i + if not trigger.misc.getZone(zone_name) then + gcicap.log:alert("CAP trigger zone is missing: $1", zone_name) + return false + end + end + return true + end + + local function manageCAP(side) + local patroled_zones = 0 + + for i = 1, #gcicap[side].cap.zones do + local zone = gcicap[side].cap.zones[i] + gcicap.log:info("Zone $1 has $2 patrols", zone.name, zone.patrol_count) + + -- see if we can send a new CAP into the zone + if zone.patrol_count <= 0 then + -- first check if we already hit the maximum amounts of routine CAP groups + if #gcicap[side].cap.flights < gcicap[side].cap.groups_count then + -- check if we limit resources and if we have enough supplies + -- if we don't limit resource or have enough supplies we spawn + if not gcicap[side].limit_resources or + (gcicap[side].limit_resources and gcicap[side].supply > 0) then + -- finally spawn it + gcicap.spawnCAP(side, gcicap[side].cap.zones[i], gcicap[side].cap.spawn_mode) + end + end + else + patroled_zones = patroled_zones + 1 + end + end + -- if all zones are patroled and we still have cap groups left + -- send them to a random zone + if #gcicap[side].cap.flights < gcicap[side].cap.groups_count then + if not gcicap[side].limit_resources or + (gcicap[side].limit_resources and gcicap[side].supply > 0) then + local random_zone = math.random(1, #gcicap[side].cap.zones) + gcicap.spawnCAP(side, gcicap[side].cap.zones[random_zone], gcicap[side].cap.spawn_mode) + end + end + gcicap.log:info("$1 patrols in $2/$3 zones with $4 flights", + side, patroled_zones, gcicap[side].cap.zones_count, #gcicap[side].cap.flights) + end + + local function handleIntrusion(side) + for i = 1, #gcicap[side].intruders do + local intruder = gcicap[side].intruders[i] + if intruder.group then + if intruder.group:isExist() then + -- check if we need to do something about him + if not intruder.intercepted then + -- first check if we have something to work with + if #gcicap[side].cap.flights > 0 + or #gcicap[side].gci.flights > 0 + or #gcicap[side].gci.flights < gcicap[side].gci.groups_count then + -- get closest flight to intruder if there is any + local closest = nil + local intruder_unit = gcicap.getFirstActiveUnit(intruder.group) + local closest_flights = gcicap.getClosestFlightsToUnit(side, intruder_unit) + -- we found close flights + local flight_avail = false + if closest_flights then + for j = 1, #closest_flights do + closest = closest_flights[j] + --fligh_avail = (not closest.flight.rtb) and (not closest.flight.intercepting) + flight_avail = (not closest.flight.intercepting) + if flight_avail then + gcicap.log:info("Found flight $1 which is avaliable for tasking.", + closest.flight.group:getName()) + break + end + end + end + if flight_avail then + -- check if we have a airfield which is closer to the unit than the closest flight + -- but add some distance to the airfield since it takes time for a potential spawned + -- flight to take-off + local closest_af, af_distance = gcicap.getClosestAirfieldToUnit(side, intruder_unit) + af_distance = af_distance + 15000 -- add 15km + if closest.distance < af_distance or af_distance == -1 then + -- task flight with intercept + closest.flight.give_up = false + closest.flight:vectorToTarget(intruder) + return + end + if (not gcicap[side].limit_resources + or (gcicap[side].limit_resources and gcicap[side].supply > 0)) + and #gcicap[side].gci.flights < gcicap[side].gci.groups_count + and gcicap[side].gci.enabled then + -- spawn CGI + gcicap.log:info("Airfield closer to intruder than flight or no flight available. Spawning GCI") + local gci = gcicap.spawnGCI(side, intruder) + end + else + if (not gcicap[side].limit_resources + or (gcicap[side].limit_resources and gcicap[side].supply > 0)) + and #gcicap[side].gci.flights < gcicap[side].gci.groups_count + and gcicap[side].gci.enabled then + -- spawn CGI + gcicap.log:info("No CAP flights or already airborne GCI. Spawning GCI") + local gci = gcicap.spawnGCI(side, intruder) + end + end + end + end + end + else + -- the intruder group doesn't exist (anymore) remove it + table.remove(gcicap[side].intruders, i) + end + end + end + + -- returns airfields of given side which are marked with + -- triggerzones (triggerzone name is exactly the same as airfield name). + local function getAirfields(side) + local coal_airfields = coalition.getAirbases(gcicap.sideToCoalition(side)) + local gcicap_airfields = {} + + -- loop over all coalition airfields + for i = 1, #coal_airfields do + -- get name of airfield + local af_name = coal_airfields[i]:getName() + if not string.match(af_name, "FARP") then + -- check if a triggerzone exists with that exact name + if mist.DBs.zonesByName[af_name] then + -- add it to our airfield list for gcicap + gcicap_airfields[#gcicap_airfields + 1] = coal_airfields[i] + end + end + end + + if #gcicap_airfields == 0 then + gcicap.log:warn("No airbase for $1 found", side) + end + return gcicap_airfields + end + + -- returns all currently active aircraft of the given side + -- parameter side has to be "red" or "blue" + local function getAllActiveAircrafts(side) + local filter = { "[" .. side .. "][plane]", "[" .. side .. "][helicopter]"} + local all_aircraft = mist.makeUnitTable(filter) + local active_aircraft = {} + + for i = 1, #all_aircraft do + local ac = Unit.getByName(all_aircraft[i]) + if ac ~= nil then + if Unit.isActive(ac) then + table.insert(active_aircraft, ac) + end + end + end + if #active_aircraft == 0 then + gcicap.log:warn("No active aircraft for $1 found", side) + end + return active_aircraft + end + + -- returns all currently active EWR and AWACS units of the given side + -- parameter side has to be "red" or "blue" + local function getAllActiveEWR(side) + local filter = { "[" .. side .. "][plane]", "[" .. side .. "][vehicle]", "[" .. side .. "][ship]"} + local all_vecs = mist.makeUnitTable(filter) + local active_ewr = {} + + for i = 1, #all_vecs do + local vec = Unit.getByName(all_vecs[i]) + if vec ~= nil then + if Unit.isActive(vec) then + local vec_type = Unit.getTypeName(vec) + if vec_type == "55G6 EWR" + or vec_type == "1L13 EWR" + or vec_type == "Hawk sr" + or vec_type == "Patriot str" then + table.insert(active_ewr, { unit = vec, is_awacs = false} ) + end + -- ED has a bug; the E-2D vehicle has type E-2C + if (vec_type == "A-50" and gcicap[side].awacs) + or (vec_type == "E-2C" and gcicap[side].awacs) + or (vec_type == "E-3A" and gcicap[side].awacs) then + table.insert(active_ewr, { unit = vec, is_awacs = true} ) + end + end + end + end + if #active_ewr == 0 then + gcicap.log:warn("No active EWR for $1 found", side) + end + return active_ewr + end + + local function checkForAirspaceIntrusion(side) + -- init some local vars + local border = gcicap[side].border + local active_ewr = gcicap[side].active_ewr + local intruder_count = 0 + local intruder_side = "" + local toremove = {} + if side == "red" then + -- set the side of the intruder + intruder_side = "blue" + elseif side == "blue" then + intruder_side = "red" + end + local active_ac = gcicap[intruder_side].active_aircraft + + -- only do something if we have active ewr and active aircraft + if #active_ac > 0 and #active_ewr > 0 then + -- loop over all aircraft + for i = 1, #active_ac do + local ac = active_ac[i] + local ac_detected = false + local ac_intruded = false + local ac_pos = {} + local ac_group = nil + local intruder_num = 0 + local ewr = nil + if ac ~= nil then + ac_group = ac:getGroup() + if ac_group:isExist() then + ac_pos = ac:getPoint() + + -- now loop over all ewr units + for n = 1, #active_ewr do + local ewr_controller = nil + if active_ewr[n].is_awacs then + ewr_controller = active_ewr[n].unit:getController() + else + ewr_controller = active_ewr[n].unit:getGroup():getController() + end + -- and check if the EWR detected the aircraft + if ewr_controller:isTargetDetected(ac, RADAR) then + ewr = active_ewr[n].unit + ac_detected = true + -- stop once it was detected by one EWR + break + end + end + + if ac_detected then + -- do we check borders? + if gcicap[side].borders_enabled then + ac_intruded = mist.pointInPolygon(ac_pos, border) + else + -- if not the aircarft is always intruding + ac_intruded = true + end + + if ac_intruded then + local in_list = false + -- check if we already know about the intruder + for j = 1, #gcicap[side].intruders do + if gcicap[side].intruders[j].name == ac_group:getName() then + in_list = true + intruder_num = j + break + end + end + if not in_list then + intruder_count = intruder_count + 1 + + gcicap.log:info("$1 ($2) intruded airspace of $3 detected by $4 ($5)", + ac_group:getName(), ac:getName(), side, + ewr:getGroup():getName(), ewr:getName()) + + intruder = { + name = ac_group:getName(), + --unit = ac, + group = ac_group, + detected_by = ewr, + --groupID = ac_group:getID(), + --unitID = ac:getID(), + --unitType = ac:getTypeName(), + size = ac_group:getSize(), + intercepted = false, + } + table.insert(gcicap[side].intruders, intruder) + intruder_num = #gcicap[side].intruders + end + + -- send message to all units of coalition or some specified groups + -- that we have a intruder + if gcicap[side].gci.messages then + local par = { + units = { ac:getName() }, + ref = gcicap[side].bullseye, + alt = ac_pos.y, + } + -- do we want to display in metric units? + if gcicap[side].gci.messages_metric then + par.metric = true + end + + local msg_for = {} + -- if groups are specified find their units names and add them to the list + if #gcicap[side].gci.messages_to > 0 then + msg_for.units = {} + for g, group_name in pairs(gcicap[side].gci.messages_to) do + group = Group.getByName(group_name) + if group ~= nil then + for u, unit in pairs(group:getUnits()) do + table.insert(msg_for.units, unit:getName()) + end + end + end + else + msg_for.coa = { side } + end + -- get the bearing, range and altitude from bullseye to intruder + local bra = mist.getBRString(par) + local bra_string = "Airpsace intrusion! BRA from bullseye "..bra + local msg = { + text = bra_string, + displayTime = gcicap.gci.message_time, + msgFor = msg_for, + name = "gcicap.gci.msg"..intruder_num, + } + -- finally send the message + mist.message.add(msg) + end + end -- if ac_intruded + else + -- the ac is _not_ intruding so we should remove it from the intruders list + + local in_list = false + local intruder_num = 0 + -- check if we already know about the intruder + for j = 1, #gcicap[side].intruders do + if gcicap[side].intruders[j].name == ac_group:getName() then + in_list = true + intruder_num = j + break + end + end + if in_list then toremove[#toremove + 1] = intruder_num end + end -- if ac_detected + end -- if ac_group is existing + end -- if ac ~= nil + end -- for #active_ac + end -- if active_ac > 0 and active_ewr > 0 + + -- we need to remove intruders from outside the loop + if #toremove > 0 then + for i = 1,#toremove do + intruder_count = intruder_count - 1 + gcicap.log:info("Aircraft "..gcicap[side].intruders[i].name.." no longer intruding") + table.remove(gcicap[side].intruders,i) + end + end + if intruder_count > 0 then + return true + else + return false + end + --return gcicap[side].intruders + end + + -- returns a random airfield for the given side + local function getRandomAirfield(side) + local rand = math.random(1, #gcicap[side].airfields) + return gcicap[side].airfields[rand] + end + + local function buildFirstWp(airbase, spawn_mode) + local airbase_pos = airbase:getPoint() + local airbase_id = airbase:getID() + local wp = mist.fixedWing.buildWP(airbase_pos) + + if spawn_mode == "parking" then -- start from parking area + wp.airdromeId = airbase_id + wp.type = "TakeOffParking" + wp.action = "From Parking Area" + elseif spawn_mode == "takeoff" then -- or start from runway + wp.airdromeId = airbase_id + wp.type = "TakeOff" + wp.action = "From Runway" + elseif spawn_mode == "air" then + -- randomize spawn position a little bit in case of air start + wp.x = wp.x + (50 * math.sin(math.random(10))) + wp.y = wp.y + (50 * math.sin(math.random(10))) + end + + return wp + end + + --- Converts coaltion number to side string. + -- 0 = "neutral", 1 = "red", 2 = "blue" + -- @tparam number coal coaltion number. + -- @treturn string side + function gcicap.coalitionToSide(coal) + if coal == coalition.side.NEUTRAL then return "neutral" + elseif coal == coalition.side.RED then return "red" + elseif coal == coalition.side.BLUE then return "blue" + end + end + + --- Converts side string to coaltion number. + -- 0 = "neutral", 1 = "red", 2 = "blue" + -- @tparam string side side string. + -- @treturn number coalition number. + -- @see coalitionToSide + function gcicap.sideToCoalition(side) + if side == "neutral" then return coalition.side.NEUTRAL + elseif side == "red" then return coalition.side.RED + elseif side == "blue" then return coalition.side.BLUE + end + end + + --- Returns first active unit of a group. + -- @tparam Group group group whose first active + -- unit to return. + -- @treturn Unit first active unit of group. + function gcicap.getFirstActiveUnit(group) + if group ~= nil then + -- engrish mast0r isExistsingsed + if not group:isExist() then return nil end + local units = group:getUnits() + for i = 1, group:getSize() do + if units[i] then + return units[i] + end + end + return nil + else + return nil + end + end + + --- Returns the closest airfield to unit. + -- Returned airfield is controlled by given side. This function + -- also returns the distance to the unit. + -- @tparam string side side string, either "red" or "blue". + -- The airfield returned has to be controlled by this side. + -- @tparam Unit unit unit to use as reference. + -- @treturn table @{closestAirfieldReturn} + function gcicap.getClosestAirfieldToUnit(side, unit) + if not unit then + gcicap.log:error("Couldn't find unit.") + return + end + local airfields = gcicap[side].airfields + + if #airfields == 0 then + gcicap.log:warn("There are no airfields of side $1", side) + return nil + end + + local unit_pos = mist.utils.makeVec2(unit:getPoint()) + local min_distance = -1 + local closest_af = nil + + for i = 1, #airfields do + local af = airfields[i] + local af_pos = mist.utils.makeVec2(af:getPoint()) + local distance = mist.utils.get2DDist(unit_pos, af_pos) + + if distance < min_distance or min_distance == -1 then + min_distance = distance + closest_af = af + end + end + + --- Table returned by getClosestAirfieldToUnit. + -- @table closestAirfieldReturn + -- @tfield Airbase airfield the Airbase object + -- @tfield number distance the distance in meters + -- to the unit. + --return {airfield = closest_af, distance = min_distance} + return closest_af, min_distance + end + + --- Returns the closest flights to the given unit. + -- Flights returned are of given side. This function also returns + -- their distance to the unit. The returned flights are sorted + -- by distance. First is the closest. + -- @tparam string side side whose flights to search. + -- @tparam Unit unit unit object used as reference. + -- @treturn table Array sorted by distance + -- containing @{closestFlightsReturn} tables. + function gcicap.getClosestFlightsToUnit(side, unit) + if not unit then + gcicap.log:error("Couldn't find unit.") + return + end + local closest_flights = {} + if #gcicap[side].cap.flights == 0 and #gcicap[side].gci.flights == 0 then + gcicap.log:info("No CAP or GCI flights of side $1 active", side) + return nil + else + local unit_pos = mist.utils.makeVec2(unit:getPoint()) + local min_distance = -1 + for t, task in pairs(gcicap.tasks) do + local flights = gcicap[side][task].flights + for i = 1, #flights do + if flights[i].group then + local u = gcicap.getFirstActiveUnit(flights[i].group) + if u then + local u_pos = mist.utils.makeVec2(u:getPoint()) + local distance = mist.utils.get2DDist(unit_pos, u_pos) + table.insert(closest_flights, {flight = flights[i], distance = distance }) + else + break + end + end + end + end + + -- sort closest flights + table.sort(closest_flights, function(a,b) + if a.distance < b.distance then + return true + else + return false + end + end) + + --- Table returned by getClosestFlightsToUnit. + -- @table closestFlightsReturn + -- @tfield gcicap.Flight flight object + -- @tfield number distance distance in meters from + -- the unit. + return closest_flights + end + end + + --- Returns a table containting a CAP route. + -- Route originating from given airbase, waypoints + -- are placed randomly inside given zone. Optionally + -- you can specify the amount of waypoints inside the zone. + -- @tparam string zone trigger zone name + -- @tparam number vul_time time on station + -- @tparam number leg_distance leg distance for race-track pattern orbit. + function gcicap.buildCAPRoute(start_pos, zone, vul_time, leg_distance) + local points = {} + -- make altitude consistent for the whole route. + local alt = math.random(gcicap.cap.min_alt, gcicap.cap.max_alt) + + local start_vul_script = "local group = ...\ + local flight = gcicap.Flight.getFlight(group)\ + if flight then\ + gcicap.log:info('$1 starting vul time $2 at $3',\ + flight.group_name, flight.vul_time, flight.zone.name)\ + flight.vul_start = timer.getAbsTime()\ + else\ + gcicap.log:error('Could not find flight')\ + end" + + local end_vul_script = "local group = ...\ + local flight = gcicap.Flight.getFlight(group)\ + if flight then\ + gcicap.log:info('$1 vul time over at $2',\ + flight.group_name, flight.zone.name)\ + flight:taskWithRTB()\ + else\ + gcicap.log:error('Could not find flight')\ + end" + + -- build orbit start waypoint + local orbit_start_point = mist.getRandomPointInZone(zone) + -- add a bogus waypoint so the start vul time script block + -- isn't executed instantly after tasking + points[1] = mist.fixedWing.buildWP(start_pos) + points[2] = mist.fixedWing.buildWP(orbit_start_point) + points[2].task = {} + points[2].task.id = 'ComboTask' + points[2].task.params = {} + points[2].task.params.tasks = {} + points[2].task.params.tasks[1] = { + number = 1, + auto = false, + id = 'WrappedAction', + enabled = true, + params = { + action = { + id = 'Script', + params = { + command = start_vul_script + } + } + } + } + points[2].task.params.tasks[2] = { + number = 2, + auto = false, + id = 'ControlledTask', + enabled = true, + params = { + task = { + id = 'Orbit', + params = { + altitude = alt, + pattern = 'Race-Track', + speed = gcicap.cap.speed + } + }, + stopCondition = { + duration = vul_time * 60 + } + } + } + + -- if we don't use the race-track pattern we'll add the vul end time + -- waypoint right where the start waypoint is and use the 'Circle' pattern. + local orbit_end_point + if not gcicap.cap.race_track_orbit then + points[2].task.params.tasks[2].params.task.params.pattern = 'Circle' + orbit_end_point = start_pos + else + -- build second waypoint (leg end waypoint) + --local orbit_end_point = mist.getRandPointInCircle(orbit_start_point, leg_distance, leg_distance) + orbit_end_point = mist.getRandomPointInZone(zone) + end + + points[3] = mist.fixedWing.buildWP(orbit_end_point) + points[3].task = { + id = 'WrappedAction', + params = { + action = { + id = 'Script', + params = { + command = end_vul_script + } + } + } + } + + for i = 1, 3 do + points[i].speed = gcicap.cap.speed + points[i].alt = alt + end + + -- local ground_level = land.getHeight(point) + -- -- avoid crashing into hills + -- if (alt - 100) < ground_level then + -- alt = alt + ground_level + -- end + + gcicap.log:info("Built CAP route with $1 min vul time at $2 meters in $3", vul_time, alt, zone) + + local route = {} + route.points = points + return route + end + + --- Tasks group to automatically engage any spotted targets. + -- @tparam Group group group to task. + -- @tparam[opt] number max_dist maximum engagment distance. + -- Targets further out (from the route) won't be engaged. + function gcicap.taskEngage(group, max_dist) + if not max_dist then + max_dist = gcicap.cap.max_engage_distance + end + local ctl = group:getController() + local engage = { + id = 'EngageTargets', + params = { + maxDist = max_dist, + maxDistEnabled = true, + targetTypes = { [1] = "Air" }, + priority = 0 + } + } + ctl:pushTask(engage) + end + + --- Tasks group to engage a group. + -- @tparam Group group group to task. + -- @tparam Group target group that should be engaged by + -- given group. + function gcicap.taskEngageGroup(group, target) + local ctl = group:getController() + local engage_group = { + id = 'EngageGroup', + params = { + groupId = target:getID(), + directionEnabled = false, + priority = 0, + altittudeEnabled = false, + } + } + ctl:pushTask(engage_group) + end + + --- Spawns a fighter group. + -- @tparam string side side of the newly created group. + -- Can be "red" or "blue". + -- @tparam string name new group name. + -- @tparam number size count of aircraft in the new group. + -- @tparam Airbase airbase home plate of the new group. + -- @tparam string spawn_mode How the new group will be spawned. + -- Can be 'parking' or 'air'. 'parking' will spawn them at the ramp + -- wit engines turned off. 'air' will spawn them in the air already + -- flying. + -- @tparam string task Task of the new group. Can either be 'cap', + -- for combat air patrol, or 'gci', for ground controlled intercept. + -- @tparam[opt] string zone zone name in which to spawn the unit. This only is + -- taken into account if spawn_mode is "in-zone". + -- @tparam[opt] boolean cold if set to true the newly group won't engage + -- any enemys until tasked otherwise. Default false. + -- @treturn Group|nil newly spawned group or nil on failure. + function gcicap.spawnFighterGroup(side, name, size, airbase, spawn_mode, task, zone, cold) + local template_unit_name = gcicap[task].template_prefix..side..math.random(1, gcicap.template_count) + local template_unit = Unit.getByName(template_unit_name) + if not template_unit then + gcicap.log:error("Can't find template unit $1. This should never happen.\ + Somehow the template unit got deleted.", template_unit_name) + return nil + end + local template_group = mist.getGroupData(template_unit:getGroup():getName()) + local template_unit_data = template_group.units[1] + local airbase_pos = airbase:getPoint() + local group_data = {} + local unit_data = {} + local onboard_num = template_unit_data.onboard_num - 1 + local route = {} + + local rand_point = {} + if spawn_mode == "in-zone" then + rand_point = mist.getRandomPointInZone(zone) + end + + for i = 1, size do + unit_data[i] = {} + unit_data[i].type = template_unit_data.type + unit_data[i].name = name.." Pilot "..i + if spawn_mode == "in-zone" then + unit_data[i].x = rand_point.x + (50 * math.sin(math.random(10))) + unit_data[i].y = rand_point.y + (50 * math.sin(math.random(10))) + else + unit_data[i].x = airbase_pos.x + (50 * math.sin(math.random(10))) + unit_data[i].y = airbase_pos.z + (50 * math.sin(math.random(10))) + end + unit_data[i].alt = gcicap[side].cap.min_alt + unit_data[i].onboard_num = onboard_num + i + unit_data[i].groupName = name + unit_data[i].payload = template_unit_data.payload + unit_data[i].skill = template_unit_data.skill + unit_data[i].livery_id = template_unit_data.livery_id + if side == 'blue' then + unit_data[i].callsign = {} + unit_data[i].callsign[1] = 4 -- Colt + unit_data[i].callsign[2] = gcicap[side].cap.flight_num + unit_data[i].callsign[3] = i + else + unit_data[i].callsign = 600 + gcicap[side].cap.flight_num + i + end + end + + group_data.units = unit_data + group_data.groupName = name + group_data.hidden = gcicap[side].hide_groups + --group_data.country = template_group.country + group_data.country = template_unit:getCountry() + group_data.category = template_group.category + group_data.task = "CAP" + + route.points = {} + if spawn_mode == "in-zone" then + route.points[1] = mist.fixedWing.buildWP(rand_point) + route.points[1].alt = gcicap[side].cap.min_alt + route.points[1].speed = gcicap[side].cap.speed + else + route.points[1] = buildFirstWp(airbase, spawn_mode) + end + group_data.route = route + + if mist.groupTableCheck(group_data) then + local spawn_pos = airbase:getName() + if spawn_mode == "in-zone" then + spawn_pos = zone + end + gcicap.log:info("Spawning fighter group $1 at $2", name, spawn_pos) + mist.dynAdd(group_data) + else + gcicap.log:error("Couldn't spawn group with following groupTable: $1", group_data) + end + + return Group.getByName(name) + end + + --- Spawns a CAP flight. + -- @tparam string side side for the new CAP. + -- @tparam string zone CAP zone (trigger zone) name. + -- @tparam string spawn_mode how the new CAP will be spawned. + -- Can be 'parking' or 'air'. + function gcicap.spawnCAP(side, zone, spawn_mode) + -- increase flight number + gcicap[side].cap.flight_num = gcicap[side].cap.flight_num + 1 + -- select random airbase (for now) TODO: choose closest airfield + local airbase = getRandomAirfield(side) + local group_name = "CAP "..side.." "..gcicap[side].cap.flight_num + -- define size of the flight + local size = gcicap[side].cap.group_size + if size == "randomized" then + size = math.random(1,2)*2 + else + size = tonumber(size) + end + -- actually spawn something + local group = gcicap.spawnFighterGroup(side, group_name, size, airbase, spawn_mode, "cap", zone.name) + --local ctl = group:getController() + --ctl:setOption(AI.Option.Air.id.RADAR_USING, AI.Option.Air.val.RADAR_USING.FOR_ATTACK_ONLY) + gcicap[side].supply = gcicap[side].supply - 1 + -- keep track of the flight + local flight = gcicap.Flight:new(group, airbase, "cap", zone) + -- task the group, for some odd reason we have to wait until we use setTask + -- on a freshly spawned group. + mist.scheduleFunction(gcicap.Flight.taskWithCAP, {flight}, timer.getTime() + 5) + return group + end + + --- Spawns a GCI flight. + -- @tparam string side side for the new GCI. + -- @tparam Unit intruder unit to intercept. + -- @tparam Airbase airbase airbase at which to spawn the GCI flight. + function gcicap.spawnGCI(side, intruder, airbase) + -- increase flight number + gcicap[side].gci.flight_num = gcicap[side].gci.flight_num + 1 + -- select closest airfield to unit + local intruder_unit = gcicap.getFirstActiveUnit(intruder.group) + local closest_af = gcicap.getClosestAirfieldToUnit(side, intruder_unit) + if closest_af then + airbase = closest_af + else + gcicap.log:warn("Couldn't find close airfield for GCI. Choosing one at random.") + airbase = getRandomAirfield(side) + end + local tgt_units = intruder.group:getUnits() + local group_name = "GCI "..side.." "..gcicap[side].gci.flight_num + -- define size of the flight + local size = gcicap[side].gci.group_size + if size == "randomized" then + size = math.random(1,2)*2 + elseif size == "dynamic" then + size = #tgt_units + else + size = tonumber(size) + end + -- actually spawn something + local group = gcicap.spawnFighterGroup(side, group_name, size, airbase, gcicap[side].gci.spawn_mode, "gci") + local ctl = group:getController() + -- make the GCI units only use their radar for attacking + ctl:setOption(AI.Option.Air.id.RADAR_USING, AI.Option.Air.val.RADAR_USING.FOR_ATTACK_ONLY) + gcicap[side].supply = gcicap[side].supply - 1 + -- keep track of the flight + local flight = gcicap.Flight:new(group, airbase, "gci", intruder) + -- vector the interceptor group on the target the first time. + mist.scheduleFunction(gcicap.Flight.vectorToTarget, {flight, intruder}, timer.getTime() + 5) + return group + end + + --- Initialization function + -- Checks if all template units are present. Creates + -- border polygons if borders enabled. + -- @todo complete documentation. + function gcicap.init() + for i, side in pairs(gcicap.sides) do + if not (checkForTemplateUnits(side) and checkForTriggerZones(side)) then + return false + end + if gcicap[side].borders_enabled then + gcicap[side].border = mist.getGroupPoints(gcicap[side].border_group) + end + gcicap[side].intruders = {} + gcicap[side].cap.zones = {} + gcicap[side].cap.flights = {} + gcicap[side].gci.flights = {} + gcicap[side].cap.flight_num = 0 + gcicap[side].gci.flight_num = 0 + gcicap[side].airfields = getAirfields(side) + + if gcicap[side].cap.enabled then + -- loop through all zones + for i = 1, gcicap[side].cap.zones_count do + local zone_name = gcicap[side].cap.zone_name..i + local point = trigger.misc.getZone(zone_name).point + local size = trigger.misc.getZone(zone_name).radius + + -- create zone table + gcicap[side].cap.zones[i] = { + name = zone_name, + pos = point, + radius = size, + patrol_count = 0, + } + end + + for i = 1, gcicap[side].cap.groups_count do + local spawn_mode = "parking" + if gcicap[side].cap.start_airborne then + spawn_mode = "in-zone" + end + -- try to fill all zones + local zone = gcicap[side].cap.zones[i] + -- if we have more flights than zones we select one random zone + if zone == nil then + zone = gcicap[side].cap.zones[math.random(1, gcicap[side].cap.zones_count)] + end + -- actually spawn the group + --local grp = gcicap.spawnCAP(side, zone, spawn_mode) + -- delay the spawn by gcicap interval seconds after one another + local spawn_delay = (i - 1) * gcicap.initial_spawn_delay + mist.scheduleFunction(gcicap.spawnCAP, {side, zone, spawn_mode}, timer.getTime() + spawn_delay) + end + end + end + -- add event handler managing despawns + return true + end + + --- Main function. + -- Run approx. every @{gcicap.interval} sconds. A random amount + -- of 0 to 2 seconds is added for declustering. + -- @todo do the "declustering" at a different level. Probably + -- more efficient. + function gcicap.main() + for i, side in pairs(gcicap.sides) do + -- update list of occupied airfields + gcicap[side].airfields = getAirfields(side) + -- update list of all aircraft + gcicap[side].active_aircraft = getAllActiveAircrafts(side) + -- update list of all EWR + gcicap[side].active_ewr = getAllActiveEWR(side) + end + + -- check for airspace intrusions after updating all the lists + for i, side in pairs(gcicap.sides) do + if gcicap[side].cap.enabled then + manageCAP(side) + end + checkForAirspaceIntrusion(side) + handleIntrusion(side) + garbageCollector(side) + end + end + +end + +if gcicap.init() then + local start_delay = gcicap.initial_spawn_delay * math.max(gcicap.red.cap.groups_count, gcicap.blue.cap.groups_count) + mist.scheduleFunction(gcicap.main, {}, timer.getTime() + start_delay, gcicap.interval) +end + +-- vim: sw=2:ts=2 diff --git a/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-220 - GCICAP Demonstration/AID-220 - NORMANDY AI_A2A_GCICAP Demonstration.lua b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-220 - GCICAP Demonstration/AID-220 - NORMANDY AI_A2A_GCICAP Demonstration.lua new file mode 100644 index 0000000000..7b0f9433d3 --- /dev/null +++ b/AID - AI Dispatching/AID-A2A - AI A2A Dispatching/AID-A2A-220 - GCICAP Demonstration/AID-220 - NORMANDY AI_A2A_GCICAP Demonstration.lua @@ -0,0 +1,27 @@ + + +-- RED + +--- Setup the Red Coalition A2A GCICAP dispatcher, and initialize it. +-- EWR network groups start with RED EWR, which are ships and patrols. +-- Squadron templates which are placed above the colored airbases, start with TR SQ. +-- Perform CAP, the zone for CAP starts with TR CAP, send minimal 10 groups of planes in the air. +A2A_GCICAP_Red = AI_A2A_GCICAP:New( { "TR SQ"}, { "TR SQ" }, { "TR CAP" }, 10 ) + +A2A_GCICAP_Red:SetBorderZone( ZONE_POLYGON:New( "Red Border", GROUP:FindByName( "Red Border" ) ) ) + +-- Enable the tactical display panel. This is to see what this dispatcher is doing. +--A2A_GCICAP_Red:SetTacticalDisplay( true ) + +-- BLUE + +--- Setup the Red Coalition A2A GCICAP dispatcher, and initialize it. +-- EWR network groups start with BLUE EWR. +-- Squadron templates which are placed above the colored airbases, start with UK SQ. +-- Perform no CAP. +A2A_GCICAP_Blue = AI_A2A_GCICAP:New( { "BLUE EWR" }, { "UK SQ" }, { }, 2 ) + +A2A_GCICAP_Blue:SetBorderZone( ZONE_POLYGON:New( "Blue Border", GROUP:FindByName( "Blue Border" ) ) ) + + + diff --git a/AID - AI Dispatching/AID-A2G - AI A2G Dispatching/AID-A2G-004 - Detection and attack close defense point Helicopters/AID-A2G-003 - Detection and Attack one Group Helicopters.lua b/AID - AI Dispatching/AID-A2G - AI A2G Dispatching/AID-A2G-004 - Detection and attack close defense point Helicopters/AID-A2G-003 - Detection and Attack one Group Helicopters.lua new file mode 100644 index 0000000000..c4b7fff895 --- /dev/null +++ b/AID - AI Dispatching/AID-A2G - AI A2G Dispatching/AID-A2G-004 - Detection and attack close defense point Helicopters/AID-A2G-003 - Detection and Attack one Group Helicopters.lua @@ -0,0 +1,52 @@ +--- Detect and attack a set of enemy units using helicopters. +-- Name: AID-A2G-001 - Detection and Attack Helicopters +-- Author: FlightControl +-- Date Created: 02 Nov 2018 + + +CC = COMMANDCENTER:New( GROUP:FindByName("HQ"),"HQ") + +-- Define a SET_GROUP object that builds a collection of groups that define the recce network. +-- Here we build the network with all the groups that have a name starting with CCCP Recce. +DetectionSetGroup = SET_GROUP:New() +DetectionSetGroup:FilterPrefixes( { "CCCP Recce" } ) +DetectionSetGroup:FilterStart() + +Detection = DETECTION_AREAS:New( DetectionSetGroup, 1000 ) + +-- Setup the A2A dispatcher, and initialize it. +A2GDispatcher = AI_A2G_DISPATCHER:New( Detection ) +A2GDispatcher:SetCommandCenter( CC ) + +-- Add defense coordinates. +A2GDispatcher:AddDefenseCoordinate( "HQ", GROUP:FindByName( "HQ" ):GetCoordinate() ) + +A2GDispatcher:SetDefenseReactivityHigh() + +A2GDispatcher:SetDefenseRadius( 200000 ) + +A2GDispatcher:SetTacticalDisplay( true ) + +-- Setup the squadrons. + +A2GDispatcher:SetSquadron( "Maykop SEAD", AIRBASE.Caucasus.Maykop_Khanskaya, { "CCCP SU-25T" }, 10 ) +A2GDispatcher:SetSquadronSead( "Maykop SEAD", 120, 250 ) +A2GDispatcher:SetSquadronTakeoffFromParkingHot( "Maykop SEAD" ) +A2GDispatcher:SetSquadronOverhead( "Maykop SEAD", 0.2 ) + +A2GDispatcher:SetSquadron( "Maykop CAS", "CAS", { "CCCP KA-50" }, 10 ) +A2GDispatcher:SetSquadronCas( "Maykop CAS", 120, 250 ) +A2GDispatcher:SetSquadronTakeoffFromParkingHot( "Maykop CAS" ) +A2GDispatcher:SetSquadronOverhead( "Maykop CAS", 0.25 ) + +A2GDispatcher:SetSquadron( "Maykop BAI", "BAI", { "CCCP KA-50" }, 10 ) +A2GDispatcher:SetSquadronBai( "Maykop BAI", 120, 250 ) +A2GDispatcher:SetSquadronTakeoffFromParkingHot( "Maykop BAI" ) +A2GDispatcher:SetSquadronOverhead( "Maykop BAI", 0.25 ) + +-- We set for each squadron a takeoff interval, as each helicopter will launch from a FARP. +-- This to prevent helicopters to clutter. +-- Each helicopter group is taking off the FARP in hot start. +A2GDispatcher:SetSquadronTakeoffInterval( "Maykop SEAD", 60 ) +A2GDispatcher:SetSquadronTakeoffInterval( "Maykop CAS", 60 ) +A2GDispatcher:SetSquadronTakeoffInterval( "Maykop BAI", 60 ) diff --git a/CAP - Combat Air Patrol/CAP-011 - CAP and Engage within Zone/CAP-010 - CAP and Engage within Zone.lua b/CAP - Combat Air Patrol/CAP-011 - CAP and Engage within Zone/CAP-010 - CAP and Engage within Zone.lua new file mode 100644 index 0000000000..d85726d32c --- /dev/null +++ b/CAP - Combat Air Patrol/CAP-011 - CAP and Engage within Zone/CAP-010 - CAP and Engage within Zone.lua @@ -0,0 +1,23 @@ +-- Name: CAP-001 - Combat Air Patrol +-- Author: FlightControl +-- Date Created: 16 January 2017 +-- +-- # Situation: +-- +-- # Test cases: +-- + +local CapPlane = GROUP:FindByName( "Plane" ) + +local PatrolZone = ZONE:New( "Patrol Zone" ) + +local AICapZone = AI_CAP_ZONE:New( PatrolZone, 500, 1000, 500, 600 ) + +local EngageZoneGroup = GROUP:FindByName( "Engage Zone" ) + +local CapEngageZone = ZONE_POLYGON:New( "Engage Zone", EngageZoneGroup ) + +AICapZone:SetControllable( CapPlane ) +AICapZone:SetEngageZone( CapEngageZone ) -- Set the Engage Zone. The AI will only engage when the bogeys are within the CapEngageZone. + +AICapZone:__Start( 1 ) -- They should statup, and start patrolling in the PatrolZone. diff --git a/CGO - Cargo/CGO-201 - Package Boarding/CGO-201 - Package Boarding.miz b/CGO - Cargo/CGO-201 - Package Boarding/CGO-201 - Package Boarding.miz index 9488e73e80..cc0de1deba 100644 Binary files a/CGO - Cargo/CGO-201 - Package Boarding/CGO-201 - Package Boarding.miz and b/CGO - Cargo/CGO-201 - Package Boarding/CGO-201 - Package Boarding.miz differ diff --git a/DEM - Demo Missions/AUS-Progrressive_SEAD_AB_Attack/Progrressive_SEAD_AB_Attack_Auftrag.lua b/DEM - Demo Missions/AUS-Progrressive_SEAD_AB_Attack/Progrressive_SEAD_AB_Attack_Auftrag.lua new file mode 100644 index 0000000000..da2d7844f4 --- /dev/null +++ b/DEM - Demo Missions/AUS-Progrressive_SEAD_AB_Attack/Progrressive_SEAD_AB_Attack_Auftrag.lua @@ -0,0 +1,244 @@ +--- Mission crated by Marginal +--- Wiht Moase API, Aufraag CLASS +--- Preparped for github by Wingthor +--- 2020-12-15 + + +----------------------------------------------- +--MOOSE SETTINGS, MARKERS and CLEANUP AIRBASE-- +----------------------------------------------- + +-- If you require a MOOSE settings menu, comment out the line below +--_SETTINGS:SetPlayerMenuOff() + +-- If you do not want markers on the F10 Map, comment out the line below +AUFTRAG:SetEnableMarkers() + + -- Cleanup a airbase runway after AI crashes or stops on the runway and wont taxi clear + -- Lookup airbase name in moose.lua + --CleanUpAirports = CLEANUP_AIRBASE:New( AIRBASE.Caucasus.Kutaisi ) + + --Tracing + --BASE:TraceOnOff( true ) + --BASE:TracelLevel( 3 ) + --BASE:TraceAll( true ) + + +---------------- +--SEAD Evasion-- +---------------- + +-- Defends the Russian SA installations from SEAD attacks. +-- Add SAM groups to the list + +SEAD_RU_SAM_Defenses = SEAD:New( {'SAM-SA-10' , 'SAM-SA-15A', 'EWR A' } ) + +------------------------------------------ +--BOMBING - GROUP, UNIT or STATIC object-- +------------------------------------------ + +--In ME: +--create a/c group(s) +--no waypoints reqd +--takeoff from parking cold or hot, runway, or in the air +--check weapons loadout / F15E or B1B GBU31 or 38 JDAM / GBU 31(V)3/B JDAM bunker busters +--for delayed ground starts from ramp cold: check uncontrolled / triggered actions - perform command: start +--for delayed air starts: check late activation + +-- @param Core.Point#COORDINATE Target Target coordinate. Can also be specified as a GROUP, UNIT or STATIC object. +-- @param #number Altitude Engage altitude in feet. Default 25000 ft. + +--4 x GBU31(V)3/B bunker busters +local Target1=STATIC:FindByName("Static Fuel Tank A") +local bomber1=FLIGHTGROUP:New("BOMBER A") +local missionBOMB1=AUFTRAG:NewBOMBING(Target1, 13000) +missionBOMB1:SetTime(60*10, 60*55) +missionBOMB1:SetWeaponExpend(AI.Task.WeaponExpend.ALL) +missionBOMB1:SetPriority(10) +bomber1:AddMission(missionBOMB1) + +--4 x GBU31(V)3/B bunker busters +local Target1=STATIC:FindByName("Static Ammunition Depot B") +local bomber2=FLIGHTGROUP:New("BOMBER B") +local missionBOMB2=AUFTRAG:NewBOMBING(Target1, 13000) +missionBOMB2:SetTime(60*10, 60*55) +missionBOMB2:SetWeaponExpend(AI.Task.WeaponExpend.ALL) +missionBOMB2:SetPriority(10) +bomber2:AddMission(missionBOMB2) + +-- 2 target strike example + +--local Target1=STATIC:FindByName("Static Fuel Tank B") +--local Target2=STATIC:FindByName("Static Ammunition Depot B") +-- local bomber2=FLIGHTGROUP:New("BOMBER B") +-- local mission1=AUFTRAG:NewBOMBING(Target1, nil) +-- mission1:SetWeaponExpend(AI.Task.WeaponExpend.ALL) +-- mission1:SetPriority(10) +-- local mission2=AUFTRAG:NewBOMBING(Target2, nil) +-- mission2:SetWeaponExpend(AI.Task.WeaponExpend.HALF) +-- mission2:SetPriority(20) +-- bomber2:AddMission(mission1) +-- bomber2:AddMission(mission2) + +------------------------------------------ +--BOMBING - GROUP, UNIT or STATIC object-- +------------------------------------------ + +--In ME: +--create a/c group(s) +--no waypoints reqd +--takeoff from parking cold or hot, runway, or in the air +--check weapons loadout / F15E or B1B GBU31 or 38 JDAM / GBU 31(V)3/B JDAM bunker busters +--for delayed ground starts from ramp cold: check uncontrolled / triggered actions - perform command: start +--for delayed air starts: check late activation + +-- @param Core.Point#COORDINATE Target Target coordinate. Can also be specified as a GROUP, UNIT or STATIC object. +-- @param #number Altitude Engage altitude in feet. Default 25000 ft. + +--4 x GBU31(V)3/B bunker busters +local Target1=STATIC:FindByName("Static Fuel Tank A") +local bomber1=FLIGHTGROUP:New("BOMBER A") +local missionBOMB1=AUFTRAG:NewBOMBING(Target1, 13000) +missionBOMB1:SetTime(60*10, 60*55) +missionBOMB1:SetWeaponExpend(AI.Task.WeaponExpend.ALL) +missionBOMB1:SetPriority(10) +bomber1:AddMission(missionBOMB1) + +--4 x GBU31(V)3/B bunker busters +local Target1=STATIC:FindByName("Static Ammunition Depot B") +local bomber2=FLIGHTGROUP:New("BOMBER B") +local missionBOMB2=AUFTRAG:NewBOMBING(Target1, 13000) +missionBOMB2:SetTime(60*10, 60*55) +missionBOMB2:SetWeaponExpend(AI.Task.WeaponExpend.ALL) +missionBOMB2:SetPriority(10) +bomber2:AddMission(missionBOMB2) + +-- 2 target strike example + +--local Target1=STATIC:FindByName("Static Fuel Tank B") +--local Target2=STATIC:FindByName("Static Ammunition Depot B") +-- local bomber2=FLIGHTGROUP:New("BOMBER B") +-- local mission1=AUFTRAG:NewBOMBING(Target1, nil) +-- mission1:SetWeaponExpend(AI.Task.WeaponExpend.ALL) +-- mission1:SetPriority(10) +-- local mission2=AUFTRAG:NewBOMBING(Target2, nil) +-- mission2:SetWeaponExpend(AI.Task.WeaponExpend.HALF) +-- mission2:SetPriority(20) +-- bomber2:AddMission(mission1) +-- bomber2:AddMission(mission2) + + + +---------------------------------- +--STRIKE - BOMBING on Coordinate-- +---------------------------------- + +--In ME: +--create a/c group(s) good for F15E +--no waypoints reqd +--takeoff from parking cold or hot, runway, or in the air +--check weapons loadout / GBU31 or 38 JDAM bridges +-- / GBU 31(V)3/B JDAM bunker busters command centers and fortified ammo dumps +-- / Mk82s for airport fuel and ammo dumps +-- / CBUs dont work well, wind drifts them off target +--for delayed ground starts from ramp cold: check uncontrolled / triggered actions - perform command: start +--for delayed air starts: check late activation + +-- @param Core.Point#COORDINATE Target The target coordinate. Can also be given as a GROUP, UNIT or STATIC object. +-- AUFTRAG:NewSTRIKE(Target, 16000) -- 16000 is engage altitude, higher altitude works well +-- @param #number Altitude Engage altitude in feet. Default 2000 ft. + +-- default altitude 2000 ft +local Target=ZONE:New("Zone Strike A"):GetCoordinate() +local missionSTRIKE1=AUFTRAG:NewSTRIKE(Target, 6000) +local strike1=FLIGHTGROUP:New("STRIKE A") +missionSTRIKE1:SetTime(60*10, 60*55) +strike1:AddMission(missionSTRIKE1) + +local Target=ZONE:New("Zone Strike B"):GetCoordinate() +local missionSTRIKE2=AUFTRAG:NewSTRIKE(Target, 6000) +local strike2=FLIGHTGROUP:New("STRIKE B") +missionSTRIKE2:SetTime(60*10, 60*55) +strike2:AddMission(missionSTRIKE2) + +local Target=ZONE:New("Zone Strike C"):GetCoordinate() +local missionSTRIKE3=AUFTRAG:NewSTRIKE(Target, nil) +local strike3=FLIGHTGROUP:New("STRIKE C") +missionSTRIKE3:SetTime(60*10, 60*55) +strike3:AddMission(missionSTRIKE3) + +local Target=ZONE:New("Zone Strike D"):GetCoordinate() +local missionSTRIKE4=AUFTRAG:NewSTRIKE(Target, nil) +local strike4=FLIGHTGROUP:New("STRIKE D") +missionSTRIKE4:SetTime(60*10, 60*55) +strike4:AddMission(missionSTRIKE4) + +local Target=ZONE:New("Zone Strike E"):GetCoordinate() +local missionSTRIKE5=AUFTRAG:NewSTRIKE(Target, 500) +local strike5=FLIGHTGROUP:New("STRIKE E") +missionSTRIKE5:SetTime(60*10, 60*55) +strike5:AddMission(missionSTRIKE5) + +local Target=ZONE:New("Zone Strike F"):GetCoordinate() +local missionSTRIKE6=AUFTRAG:NewSTRIKE(Target, 500) +local strike6=FLIGHTGROUP:New("STRIKE F") +missionSTRIKE6:SetTime(60*10, 60*55) +strike6:AddMission(missionSTRIKE6) + + +--create zones in ME + +-- Common zones +local Zone={} +Zone.Alpha = ZONE:New("Zone Alpha") --Core.Zone#ZONE --1st SEAD zone +Zone.Bravo = ZONE:New("Zone Bravo") --Core.Zone#ZONE --2nd SEAD zone +--Zone.Charlie = ZONE:New("Zone Charlie") --Core.Zone#ZONE --not used +--Zone.Delta = ZONE:New("Zone Delta") --Core.Zone#ZONE --not used +-- Set of all zones defined in the ME +local AllZones=SET_ZONE:New():FilterOnce() + + +--------------- +--CAS as SEAD-- +--------------- + +--In ME: +--create SEAD a/c groups +--no waypoints reqd but sometimes useful offsetting from departing airport, make it a short leg +--takeoff from parking cold or hot, runway, or in the air +--check weapons loadout +--for delayed ground starts from ramp cold: check uncontrolled / triggered actions - perform command: start +--for delayed air starts: check late activation +--advanced waypoint actions-- +--start enroute task--SEAD +--(Optional)Set option reaction to threat=horizontal AAA fire evade +--Reapers do better with an airstart and altitude of 8000 feet + +-- AUFTRAG:NewCAS(ZoneCAS, Altitude, Speed, Coordinate, Heading, Leg, TargetTypes) +-- @param Core.Zone#ZONE_RADIUS ZoneCAS Circular CAS zone. Detected targets in this zone will be engaged. +-- @param #number Altitude Altitude at which to orbit. Default is 10,000 ft. +-- @param #number Speed Orbit speed in knots. Default 350 KIAS. +-- @param Core.Point#COORDINATE Coordinate Where to orbit. Default is the center of the CAS zone. +-- @param #number Heading Heading of race-track pattern in degrees. If not specified, a simple circular orbit is performed. +-- @param #number Leg Length of race-track in NM. If not specified, a simple circular orbit is performed. +-- @param #table TargetTypes (Optional) Table of target types. Default {"Helicopters", "Ground Units", "Light armed ships"}. + +--make sure your allow for travel time to target area + +--50/50 HARMs AGM 88C IR MAVs AGM65Fs +local cas1=FLIGHTGROUP:New("SEAD A") +local missionSEAD1=AUFTRAG:NewCAS(Zone.Alpha, 15000, nil, nil, nil, nil, nil) +missionSEAD1:SetTime(60, 60*40) +cas1:AddMission(missionSEAD1) + +--50/50 HARMs AGM 88C IR MAVs AGM65Fs +local cas2=FLIGHTGROUP:New("SEAD B") +local missionSEAD2=AUFTRAG:NewCAS(Zone.Alpha, 15000, nil, nil, nil, nil, nil) +missionSEAD2:SetTime(60*2, 60*41) +cas2:AddMission(missionSEAD2) + +--50/50 HARMs AGM 88C IR MAVs AGM65Fs +local cas3=FLIGHTGROUP:New("SEAD C") +local missionSEAD3=AUFTRAG:NewCAS(Zone.Bravo, 15000, nil, nil, nil, nil, nil) +missionSEAD3:SetTime(60*3, 60*42) +cas3:AddMission(missionSEAD3) \ No newline at end of file diff --git a/DES - Designation/DES-020 - Designation of AREAS - Status Menu Flash Activate/DES-010 - Designation of AREAS - Threat Level Prioritization.lua b/DES - Designation/DES-020 - Designation of AREAS - Status Menu Flash Activate/DES-010 - Designation of AREAS - Threat Level Prioritization.lua new file mode 100644 index 0000000000..672f452a8e --- /dev/null +++ b/DES - Designation/DES-020 - Designation of AREAS - Status Menu Flash Activate/DES-010 - Designation of AREAS - Threat Level Prioritization.lua @@ -0,0 +1,40 @@ +--- +-- Name: DES-010 - Designation of AREAS - Threat Level Prioritization +-- Author: FlightControl +-- Date Created: 24 Apr 2017 +-- +-- # Situation: +-- +-- Demonstrates the designation of units, which are grouped in AREAs. +-- +-- A Set of Recce are detecting a large group of units. +-- This test is about the prioritization. First the SAMs should be designated, then the rest. +-- +-- # Test cases: +-- +-- - Check if the SAMs are designated first. + + +RecceSetGroup = SET_GROUP:New():FilterPrefixes( "Recce" ):FilterStart() + +HQ = GROUP:FindByName( "HQ" ) + +CC = COMMANDCENTER:New( HQ, "HQ" ) + +-- Let the RecceSetGroup vehicles in the collection detect targets and group them in AREAS of 1000 meters. +RecceDetection = DETECTION_AREAS:New( RecceSetGroup, 1000 ) + +-- Create a Attack Set, which contains the human player client slots and CA vehicles. +AttackSet = SET_GROUP:New():FilterPrefixes("Attack"):FilterStart() + +RecceDesignation = DESIGNATE:New( CC, RecceDetection, AttackSet ) + +-- This sets the threat level prioritization on +RecceDesignation:SetThreatLevelPrioritization( true ) + +-- Set the possible laser codes. +RecceDesignation:SetLaserCodes({1113,1131,1256}) + +-- Start the detection process in 5 seconds. +RecceDesignation:__Detect( -5 ) + diff --git a/ESC - AI Escort/ESC-100 - Escort Request Menu - kopie/ESC-100 - Escort Request Menu.lua b/ESC - AI Escort/ESC-100 - Escort Request Menu - kopie/ESC-100 - Escort Request Menu.lua new file mode 100644 index 0000000000..e93482903d --- /dev/null +++ b/ESC - AI Escort/ESC-100 - Escort Request Menu - kopie/ESC-100 - Escort Request Menu.lua @@ -0,0 +1,13 @@ +-- At startup of the overall mission, we spawn 10 possible escort planes in "Uncontrolled" state. + +EscortSpawn = SPAWN:NewWithAlias( "Red A2G Escort Template", "Red A2G Escort AI" ):InitLimit( 10, 10 ) +EscortSpawn:ParkAtAirbase( AIRBASE:FindByName( AIRBASE.Caucasus.Sochi_Adler ), AIRBASE.TerminalType.OpenBig ) + + +local EscortUnit = UNIT:FindByName( "Red A2G Pilot" ) + +Escort = AI_ESCORT_REQUEST:New( EscortUnit, EscortSpawn, AIRBASE:FindByName(AIRBASE.Caucasus.Sochi_Adler), "A2G", "Briefing" ) +Escort:FormationTrail( 50, 100, 100 ) +Escort:Menus( 50, 50, 0, 0, 50, 50, 6 ) +Escort:__Start( 5 ) + diff --git a/EVT - Event Handling/EVT-001 - API Demo 1/EVT-001 - API Demo 1.miz b/EVT - Event Handling/EVT-001 - API Demo 1/EVT-001 - API Demo 1.miz index fa22b05f42..0e0018196d 100644 Binary files a/EVT - Event Handling/EVT-001 - API Demo 1/EVT-001 - API Demo 1.miz and b/EVT - Event Handling/EVT-001 - API Demo 1/EVT-001 - API Demo 1.miz differ diff --git a/EVT - Event Handling/EVT-001 - UNIT OnEventShot Stability Test/EVT-001 - UNIT OnEventShot Stability Test.miz b/EVT - Event Handling/EVT-001 - UNIT OnEventShot Stability Test/EVT-001 - UNIT OnEventShot Stability Test.miz index 0dabfad95c..8b08dc443c 100644 Binary files a/EVT - Event Handling/EVT-001 - UNIT OnEventShot Stability Test/EVT-001 - UNIT OnEventShot Stability Test.miz and b/EVT - Event Handling/EVT-001 - UNIT OnEventShot Stability Test/EVT-001 - UNIT OnEventShot Stability Test.miz differ diff --git a/EVT - Event Handling/EVT-001 - UNIT OnEventShot Stability Test/EVT-002 - UNIT OnEventLand ReSpawn Test.lua b/EVT - Event Handling/EVT-001 - UNIT OnEventShot Stability Test/EVT-002 - UNIT OnEventLand ReSpawn Test.lua new file mode 100644 index 0000000000..99c4edd3bf --- /dev/null +++ b/EVT - Event Handling/EVT-001 - UNIT OnEventShot Stability Test/EVT-002 - UNIT OnEventLand ReSpawn Test.lua @@ -0,0 +1,40 @@ +--- +-- Name: EVT-002 - UNIT OnEventLand ReSpawn Test +-- Author: FlightControl +-- Date Created: 9 Apr 2017 +-- +-- # Situation: +-- +-- A couple of planes are taking off from an airbase. +-- When they land, they send out a message that they landed. +-- But! They are automatically respawned upon landing. +-- The 2nd time the same plane lands, they should send the message again!!! +-- +-- # Test cases: +-- +-- 1. Observe in the logging, that the event subscriptions are reset when the respawn happens! +-- 2. Observe the 2nd time the same plane lands, they should send the message again!!! +-- 3. Check the stability of the event handlings. + +PlaneBlueSpawn = SPAWN + :New( "PlaneBlue" ) + :InitLimit(2,0) + :InitRepeatOnEngineShutDown() + :SpawnScheduled(60,0) + :OnSpawnGroup( + --- @param Wrapper.Group#GROUP SpawnGroup + function( SpawnGroup ) + SpawnGroup:HandleEvent( EVENTS.Land ) + --- @param self + -- @param Core.Event#EVENTDATA EventData + function SpawnGroup:OnEventLand(EventData) + EventData.IniGroup:MessageToAll("Landed",15,"Land Event") + end + end + ) + +collectgarbage() +BASE:E( "Collected garbage" ) + + + diff --git a/EVT - Event Handling/EVT-002 - UNIT OnEventLand ReSpawn Test/EVT-001 - UNIT OnEventShot Stability Test.lua b/EVT - Event Handling/EVT-002 - UNIT OnEventLand ReSpawn Test/EVT-001 - UNIT OnEventShot Stability Test.lua new file mode 100644 index 0000000000..45b712876b --- /dev/null +++ b/EVT - Event Handling/EVT-002 - UNIT OnEventLand ReSpawn Test/EVT-001 - UNIT OnEventShot Stability Test.lua @@ -0,0 +1,74 @@ +--- +-- Name: EVT-001 - UNIT OnEventShot Stability Test +-- Author: FlightControl +-- Date Created: 9 Apr 2017 +-- +-- # Situation: +-- +-- A couple of planes are firing to each other. Monitor the shot events. +-- I am doing a collectgarbage to test the stability of the event handling. +-- Also when the planes are destroyed, the event handling should stop etc. +-- The tests are on GROUP level. +-- +-- # Test cases: +-- +-- 1. Observe the planes shooting the missiles. +-- 2. Observe when the plane shoots the missile, a dcs.log entry is written in the logging. +-- 3. Check the stability of the event handlings. + +PlaneGroupsBlue = {} + +PlaneGroupsRed = {} + +PlaneSpawnBlue = SPAWN + :New( "Planes Blue" ) + :InitLimit( 2, 0 ) + :SpawnScheduled( 10,0 ) + :OnSpawnGroup( + function( SpawnGroup ) + SpawnGroupName = SpawnGroup:GetName() + PlaneGroupsBlue[SpawnGroupName] = SpawnGroup + PlaneGroupsBlue[SpawnGroupName]:HandleEvent( EVENTS.Shot ) + PlaneGroupsBlue[SpawnGroupName]:HandleEvent( EVENTS.Hit ) + collectgarbage() + PlaneGroupsBlue[SpawnGroupName].OnEventShot = function( self, EventData ) + self:F( EventData ) + self:MessageToAll( "I just fired a missile!", 15, "Alert!" ) + end + PlaneGroupsBlue[SpawnGroupName].OnEventHit = function( self, EventData ) + self:F( EventData ) + self:MessageToAll( "I just got hit!", 15, "Alert!" ) + end + end + ) + +PlaneSpawnRed = SPAWN + :New( "Planes Red" ) + :InitLimit( 2, 0 ) + :SpawnScheduled(10,0) + :OnSpawnGroup( + function( SpawnGroup ) + SpawnGroupName = SpawnGroup:GetName() + PlaneGroupsRed[SpawnGroupName] = SpawnGroup + PlaneGroupsRed[SpawnGroupName]:HandleEvent( EVENTS.Shot ) + PlaneGroupsRed[SpawnGroupName]:HandleEvent( EVENTS.Hit ) + collectgarbage() + --- @param self + -- @param Core.Event#EVENTDATA EventData + PlaneGroupsRed[SpawnGroupName].OnEventShot = function ( self, EventData ) + self:F( EventData ) + + self:MessageToAll( "I just got hit!", 15, "Alert!" ) + end + PlaneGroupsRed[SpawnGroupName].OnEventHit = function( self, EventData ) + self:F( EventData ) + self:MessageToAll( "I just fired a missile!", 15, "Alert!" ) + end + end + ) + +collectgarbage() +BASE:E( "Collected garbage" ) + + + diff --git a/EVT - Event Handling/EVT-002 - UNIT OnEventLand ReSpawn Test/EVT-002 - UNIT OnEventLand ReSpawn Test.miz b/EVT - Event Handling/EVT-002 - UNIT OnEventLand ReSpawn Test/EVT-002 - UNIT OnEventLand ReSpawn Test.miz index c21e58fc49..51399eda68 100644 Binary files a/EVT - Event Handling/EVT-002 - UNIT OnEventLand ReSpawn Test/EVT-002 - UNIT OnEventLand ReSpawn Test.miz and b/EVT - Event Handling/EVT-002 - UNIT OnEventLand ReSpawn Test/EVT-002 - UNIT OnEventLand ReSpawn Test.miz differ diff --git a/EVT - Event Handling/EVT-100 - UNIT OnEventShot Example/EVT-100 - UNIT OnEventShot Example.miz b/EVT - Event Handling/EVT-100 - UNIT OnEventShot Example/EVT-100 - UNIT OnEventShot Example.miz index 4d42efaddc..2b82297c0a 100644 Binary files a/EVT - Event Handling/EVT-100 - UNIT OnEventShot Example/EVT-100 - UNIT OnEventShot Example.miz and b/EVT - Event Handling/EVT-100 - UNIT OnEventShot Example/EVT-100 - UNIT OnEventShot Example.miz differ diff --git a/EVT - Event Handling/EVT-101 - UNIT OnEventHit Example/EVT-101 - UNIT OnEventHit Example.miz b/EVT - Event Handling/EVT-101 - UNIT OnEventHit Example/EVT-101 - UNIT OnEventHit Example.miz index f346b0db64..c845e80c88 100644 Binary files a/EVT - Event Handling/EVT-101 - UNIT OnEventHit Example/EVT-101 - UNIT OnEventHit Example.miz and b/EVT - Event Handling/EVT-101 - UNIT OnEventHit Example/EVT-101 - UNIT OnEventHit Example.miz differ diff --git a/EVT - Event Handling/EVT-102 - UNIT OnEventTakeoff Example/EVT-102 - UNIT OnEventTakeoff Example.miz b/EVT - Event Handling/EVT-102 - UNIT OnEventTakeoff Example/EVT-102 - UNIT OnEventTakeoff Example.miz index 172ed42b70..8849c3dce7 100644 Binary files a/EVT - Event Handling/EVT-102 - UNIT OnEventTakeoff Example/EVT-102 - UNIT OnEventTakeoff Example.miz and b/EVT - Event Handling/EVT-102 - UNIT OnEventTakeoff Example/EVT-102 - UNIT OnEventTakeoff Example.miz differ diff --git a/EVT - Event Handling/EVT-103 - UNIT OnEventLand Example/EVT-103 - UNIT OnEventLand Example.miz b/EVT - Event Handling/EVT-103 - UNIT OnEventLand Example/EVT-103 - UNIT OnEventLand Example.miz index 3fd35189ed..5847ae66eb 100644 Binary files a/EVT - Event Handling/EVT-103 - UNIT OnEventLand Example/EVT-103 - UNIT OnEventLand Example.miz and b/EVT - Event Handling/EVT-103 - UNIT OnEventLand Example/EVT-103 - UNIT OnEventLand Example.miz differ diff --git a/EVT - Event Handling/EVT-104 - UNIT OnEventCrash Example/EVT-104 - UNIT OnEventCrash Example.miz b/EVT - Event Handling/EVT-104 - UNIT OnEventCrash Example/EVT-104 - UNIT OnEventCrash Example.miz index f2eabd6e70..5728466fbc 100644 Binary files a/EVT - Event Handling/EVT-104 - UNIT OnEventCrash Example/EVT-104 - UNIT OnEventCrash Example.miz and b/EVT - Event Handling/EVT-104 - UNIT OnEventCrash Example/EVT-104 - UNIT OnEventCrash Example.miz differ diff --git a/EVT - Event Handling/EVT-105 - UNIT OnEventPlayerEnterUnit Example/EVT-105 - UNIT OnEventPlayerEnterUnit Example.miz b/EVT - Event Handling/EVT-105 - UNIT OnEventPlayerEnterUnit Example/EVT-105 - UNIT OnEventPlayerEnterUnit Example.miz index aca5afff58..1fb21e3f1b 100644 Binary files a/EVT - Event Handling/EVT-105 - UNIT OnEventPlayerEnterUnit Example/EVT-105 - UNIT OnEventPlayerEnterUnit Example.miz and b/EVT - Event Handling/EVT-105 - UNIT OnEventPlayerEnterUnit Example/EVT-105 - UNIT OnEventPlayerEnterUnit Example.miz differ diff --git a/EVT - Event Handling/EVT-200 - GROUP OnEventShot Example/EVT-200 - GROUP OnEventShot Example.miz b/EVT - Event Handling/EVT-200 - GROUP OnEventShot Example/EVT-200 - GROUP OnEventShot Example.miz index 888c727891..4d5a7c0bb2 100644 Binary files a/EVT - Event Handling/EVT-200 - GROUP OnEventShot Example/EVT-200 - GROUP OnEventShot Example.miz and b/EVT - Event Handling/EVT-200 - GROUP OnEventShot Example/EVT-200 - GROUP OnEventShot Example.miz differ diff --git a/EVT - Event Handling/EVT-201 - GROUP OnEventHit Example/EVT-201 - GROUP OnEventHit Example.miz b/EVT - Event Handling/EVT-201 - GROUP OnEventHit Example/EVT-201 - GROUP OnEventHit Example.miz index 57f35e72cf..0cc1d1971d 100644 Binary files a/EVT - Event Handling/EVT-201 - GROUP OnEventHit Example/EVT-201 - GROUP OnEventHit Example.miz and b/EVT - Event Handling/EVT-201 - GROUP OnEventHit Example/EVT-201 - GROUP OnEventHit Example.miz differ diff --git a/EVT - Event Handling/EVT-204 - GROUP OnEventCrash Example/EVT-201 - GROUP OnEventHit Example.lua b/EVT - Event Handling/EVT-204 - GROUP OnEventCrash Example/EVT-201 - GROUP OnEventHit Example.lua new file mode 100644 index 0000000000..228b24814a --- /dev/null +++ b/EVT - Event Handling/EVT-204 - GROUP OnEventCrash Example/EVT-201 - GROUP OnEventHit Example.lua @@ -0,0 +1,28 @@ +--- +-- Name: EVT-201 - GROUP OnEventHit Example +-- Author: FlightControl +-- Date Created: 08 Mar 2017 +-- +-- # Situation: +-- +-- Two groups of planes are flying in the air and shoot an missile to a multitude of ground targets. +-- +-- # Test cases: +-- +-- 1. Observe the planes shooting the missile. +-- 2. Observe when the planes shoots the missile, and hit the group Tanks A, a dcs.log entry is written in the logging. +-- 3. Check the contents of the fields of the S_EVENT_HIT entry. +-- 4. The tanks of GROUP "Group Tanks A", should only send a message when they get hit. +-- 5. The tanks of GROUP "Group Tanks B", should NOT send a message when they get hit. + +TanksGroup = GROUP:FindByName( "Group Tanks A" ) + +TanksGroup:HandleEvent( EVENTS.Hit ) + +function TanksGroup:OnEventHit( EventData ) + + self:E( "I just got hit and I am part of " .. EventData.TgtGroupName ) + EventData.TgtUnit:MessageToAll( "I just got hit and I am part of " .. EventData.TgtGroupName, 15, "Alert!" ) +end + + diff --git a/EVT - Event Handling/EVT-204 - GROUP OnEventCrash Example/EVT-204 - GROUP OnEventCrash Example.miz b/EVT - Event Handling/EVT-204 - GROUP OnEventCrash Example/EVT-204 - GROUP OnEventCrash Example.miz index d7bc142595..31ecc5d707 100644 Binary files a/EVT - Event Handling/EVT-204 - GROUP OnEventCrash Example/EVT-204 - GROUP OnEventCrash Example.miz and b/EVT - Event Handling/EVT-204 - GROUP OnEventCrash Example/EVT-204 - GROUP OnEventCrash Example.miz differ diff --git a/EVT - Event Handling/EVT-205 - GROUP OnEventDead Example/EVT-205 - GROUP OnEventDead Example.miz b/EVT - Event Handling/EVT-205 - GROUP OnEventDead Example/EVT-205 - GROUP OnEventDead Example.miz index 9ed2c99027..e7affbd665 100644 Binary files a/EVT - Event Handling/EVT-205 - GROUP OnEventDead Example/EVT-205 - GROUP OnEventDead Example.miz and b/EVT - Event Handling/EVT-205 - GROUP OnEventDead Example/EVT-205 - GROUP OnEventDead Example.miz differ diff --git a/EVT - Event Handling/EVT-401 - Generic OnEventHit Example/EVT-401 - Generic OnEventHit Example.miz b/EVT - Event Handling/EVT-401 - Generic OnEventHit Example/EVT-401 - Generic OnEventHit Example.miz index c34b17ab29..08d629a1b6 100644 Binary files a/EVT - Event Handling/EVT-401 - Generic OnEventHit Example/EVT-401 - Generic OnEventHit Example.miz and b/EVT - Event Handling/EVT-401 - Generic OnEventHit Example/EVT-401 - Generic OnEventHit Example.miz differ diff --git a/EVT - Event Handling/EVT-402 - Generic OnEventMissionEnd Example/EVT-402 - Generic OnEventMissionEnd Example.miz b/EVT - Event Handling/EVT-402 - Generic OnEventMissionEnd Example/EVT-402 - Generic OnEventMissionEnd Example.miz index aecc4a1ebe..8fd0395fa7 100644 Binary files a/EVT - Event Handling/EVT-402 - Generic OnEventMissionEnd Example/EVT-402 - Generic OnEventMissionEnd Example.miz and b/EVT - Event Handling/EVT-402 - Generic OnEventMissionEnd Example/EVT-402 - Generic OnEventMissionEnd Example.miz differ diff --git a/EVT - Event Handling/EVT-403 - Generic OnEventBirth Example/EVT-403 - Generic OnEventBirth Example.miz b/EVT - Event Handling/EVT-403 - Generic OnEventBirth Example/EVT-403 - Generic OnEventBirth Example.miz index 9b6bc073a5..87304ffe7c 100644 Binary files a/EVT - Event Handling/EVT-403 - Generic OnEventBirth Example/EVT-403 - Generic OnEventBirth Example.miz and b/EVT - Event Handling/EVT-403 - Generic OnEventBirth Example/EVT-403 - Generic OnEventBirth Example.miz differ diff --git a/EVT - Event Handling/EVT-500 - OnEventLand LandingChallenge/EVT-103 - OnEventLand Example LandingChallenge.lua b/EVT - Event Handling/EVT-500 - OnEventLand LandingChallenge/EVT-103 - OnEventLand Example LandingChallenge.lua new file mode 100644 index 0000000000..a8adb118f7 --- /dev/null +++ b/EVT - Event Handling/EVT-500 - OnEventLand LandingChallenge/EVT-103 - OnEventLand Example LandingChallenge.lua @@ -0,0 +1,63 @@ +--- +-- Name: EVT-103 - OnEventLand Example +-- Author: CraigOwen +-- Date Created: 12 February 2017 +-- +-- # Situation: +-- +-- A client plane is landing on an airfield, trying to pick a rope in the landing zones. +-- When the plane landed in one of the zones, a vehicle flares and a message ist printed out to the client. +-- +-- # Test cases: +-- +-- 1. Land the plane. +-- 2. When the plane landed, observe your message and the signal. +-- 3. Check the contents of the fields of the S_EVENT_LAND entry in the dcs.log file. + +-- Create a unit which signalizes if the client landed good. +signal = UNIT:FindByName("LandingZoneChallenge - Signal") + +-- Create the zones used for the landing check +-- Init Zone +InitZone = ZONE:New("LandingChallange - InitZone") + +-- Ropes +zonegroup1 = GROUP:FindByName("LandingZoneChallenge - RopeGroup 1" ) +zonegroup2 = GROUP:FindByName("LandingZoneChallenge - RopeGroup 2" ) +zonegroup3 = GROUP:FindByName("LandingZoneChallenge - RopeGroup 3" ) +LandZoneRope1 = ZONE_POLYGON:New( "Rope1", zonegroup1) +LandZoneRope2 = ZONE_POLYGON:New( "Rope2", zonegroup2) +LandZoneRope3 = ZONE_POLYGON:New( "Rope3", zonegroup3) + +-- Create a variable Plane that holds a reference to CLIENT object (created by moose at the beginning of the mission) with the name "Plane". +Plane = CLIENT:FindByName( "Plane" ) +-- Subscribe to the event Land. The Land event occurs when a plane lands at an airfield. +Plane:HandleEvent( EVENTS.Land ) + +-- This function will be called whenever the Plane-Object (client) lands! +function Plane:OnEventLand( EventData ) + + -- check wether the client landet at the right airport, where the challenge is located + if not Plane:IsInZone(InitZone) then + return + end + + -- check if the touchdown took place inside of one of the zones + if Plane:IsInZone(LandZoneRope1) then + MESSAGE:New("Great job! You picked the first rope.", 15, "Landing challenge" ):ToClient( Plane ) + signal:FlareGreen() + elseif Plane:IsInZone(LandZoneRope2) then + MESSAGE:New("Good job! You picked the second rope.", 15, "Landing challenge" ):ToClient( Plane ) + signal:FlareYellow() + elseif Plane:IsInZone(LandZoneRope3) then + MESSAGE:New("Close! You picked the last rope.", 15, "Landing challenge" ):ToClient( Plane ) + signal:FlareRed() + else + MESSAGE:New("Too bad, no rope picked! Thrust your engines and try again.", 15, "Landing challenge" ):ToClient( Plane ) + end + + +end + + +MESSAGE:New("Try to land on the runway in between the red trucks.", 15, "Landing challenge"):ToClient(Plane) \ No newline at end of file diff --git a/EVT - Event Handling/EVT-500 - OnEventLand LandingChallenge/EVT-500 - OnEventLand LandingChallenge.miz b/EVT - Event Handling/EVT-500 - OnEventLand LandingChallenge/EVT-500 - OnEventLand LandingChallenge.miz index 85a999ef3b..c65edf641b 100644 Binary files a/EVT - Event Handling/EVT-500 - OnEventLand LandingChallenge/EVT-500 - OnEventLand LandingChallenge.miz and b/EVT - Event Handling/EVT-500 - OnEventLand LandingChallenge/EVT-500 - OnEventLand LandingChallenge.miz differ diff --git a/EVT - Event Handling/EVT-501 - OnEventLand LandingChallengeComplex/EVT-501 - OnEventLand LandingChallengeComplex.miz b/EVT - Event Handling/EVT-501 - OnEventLand LandingChallengeComplex/EVT-501 - OnEventLand LandingChallengeComplex.miz index bc1d81d3ab..06bc0066db 100644 Binary files a/EVT - Event Handling/EVT-501 - OnEventLand LandingChallengeComplex/EVT-501 - OnEventLand LandingChallengeComplex.miz and b/EVT - Event Handling/EVT-501 - OnEventLand LandingChallengeComplex/EVT-501 - OnEventLand LandingChallengeComplex.miz differ diff --git a/EVT - Event Handling/EVT-600 - OnEventHit Example with a Set of Units/EVT-600 - OnEventHit Example with a Set of Units.miz b/EVT - Event Handling/EVT-600 - OnEventHit Example with a Set of Units/EVT-600 - OnEventHit Example with a Set of Units.miz index b034d10074..cfe074f463 100644 Binary files a/EVT - Event Handling/EVT-600 - OnEventHit Example with a Set of Units/EVT-600 - OnEventHit Example with a Set of Units.miz and b/EVT - Event Handling/EVT-600 - OnEventHit Example with a Set of Units/EVT-600 - OnEventHit Example with a Set of Units.miz differ diff --git a/GRP - Group Commands/GRP-300 - Switch WayPoints/GRP-300 - Switch WayPoints.miz b/GRP - Group Commands/GRP-300 - Switch WayPoints/GRP-300 - Switch WayPoints.miz index 70def6cbf0..71fd4ba228 100644 Binary files a/GRP - Group Commands/GRP-300 - Switch WayPoints/GRP-300 - Switch WayPoints.miz and b/GRP - Group Commands/GRP-300 - Switch WayPoints/GRP-300 - Switch WayPoints.miz differ diff --git a/GRP - Group Commands/GRP-504 - Pinpoint Strike Waypooints and Tasking/PinpointStriker.lua b/GRP - Group Commands/GRP-504 - Pinpoint Strike Waypooints and Tasking/PinpointStriker.lua new file mode 100644 index 0000000000..5a73b08f97 --- /dev/null +++ b/GRP - Group Commands/GRP-504 - Pinpoint Strike Waypooints and Tasking/PinpointStriker.lua @@ -0,0 +1,126 @@ +--- +-- Name: GRP-550 - Shows how to make an AI bomb ground targets, both static and scenery. +-- Author: Wingthor +-- Date Created: 22 Aug 2020 +-- +-- Mission illustrates how to make an air GROUP make a bomb run by script. +-- One template group is placed on map by DCS's Mission Editor. +-- Template is set to TASK "Ground Attack", and given proper ordnance in Mission Editor +-- One function handles both attack by give targets coordinates as arguments +-- This also shows how to do a delayed function call using BASE:ScheduleOnce function +-- Mission also feature a helper function which will return a random waypoint between Airbase and Target. +-- +-- Join the Game Master to observe the reaction of the ground units. +-- +-- Blue is attacking. + + +BASE:TraceOnOff(true) +BASE:TraceAll(true) + +--- Help functions --------------------------------------- +--- This function will make a random waypoint between to coordiantes. +--- @param Core.Point#COORDINATE +--- @param Core.Point#COORDINATE +function MakeMiddleWaypoint (TargetCoordinate, InitCoordinate) + BASE:F({TargetCoordinate,InitCoordinate}) + --- If we can not solve this function throw noting back so we dont' break anything. + if TargetCoordinate == nil or InitCoordinate == nil then return nil end + --- @type TargetCoordinate Core.Point#COORDINATE + --- @type InitCoordinate Core.Point#COORDINATE + local _TargetCoordinate = TargetCoordinate + local _InitCoordinate = InitCoordinate + local Distance = TargetCoordinate:Get3DDistance(InitCoordinate) + if Distance < 30000 then + return nil -- To close for us + elseif Distance > 70000 then + Distance = 70000 + else + Distance = math.random(30000,70000) + end -- This is max distance from target we want our Waypoint + local Direction = _TargetCoordinate:GetAngleDegrees(_TargetCoordinate:GetDirectionVec3(_InitCoordinate)) + if Direction > 0 and Direction <=90 then -- North East + return _TargetCoordinate:Translate(Distance, math.random(1,90)) + + elseif Direction > 90 and Direction <= 180 then -- South East + return _TargetCoordinate:Translate(Distance, math.random(91,180)) + elseif Direction > 180 and Direction <= 270 then -- South West then + return _TargetCoordinate:Translate(Distance,math.random(181,270)) + elseif Direction > 270 and Direction <= 360 then -- South West then then + return _TargetCoordinate:Translate(Distance,math.random(271,360)) + else + BASE:E("--- Something wrong in function MakeMiddleWaypoint ---") + return nil + end + +end + + +--- @param #string +--- @param --Core.Point#COORDINATE +--- @param #string AIRBASE +--- @param #string +function PinpointStrike(Group,Target,Base,TargetDescription) + BASE:F({Group,Target,Base}) + -- In case all args is not passed. + if Group == nil or Target == nil or Base == nil then return nil end + -- Make a default description + if TargetDescription == nil then + TargetDescription = "Bomb Target" + end + -- Make a Random heading from the target which will server as an IP + local heading = math.random(90,180) + -- Get targets vevtors + local targetVec = Target:GetVec2() + -- Make a Spawn counter + if SpawnCounter == nil then + SpawnCounter = 0 + else + SpawnCounter = SpawnCounter + 1 + end + -- Spawn the bomber and return a GROUP object + + local SpawnBomber = SPAWN:NewWithAlias( Group, "Bomber" .. "_" .. tostring(SpawnCounter) ) + :OnSpawnGroup(function (Moosegroup) + local message = MESSAGE:New("Launching the Pinpointstrike",40,"Order:",true):ToBlue() + end,{}) + ---@type GROUP + local bomber = SpawnBomber:SpawnAtAirbase(AIRBASE:FindByName( Base ), SPAWN.Takeoff.Cold) + local task = bomber:TaskBombing(targetVec,false,"All",nil,heading,10000) -- WeaponType find this... + local homebasecoords = AIRBASE:FindByName(Base):GetCoordinate() --Core.Point#COORDINATE + + --- Make a waypoint table + local waypoints = {} + + --- Get coordinate for Home Base + local homecoords = AIRBASE:FindByName(Base):GetCoordinate():SetAltitude(8000):Translate(10 * 10000,300) + --- Make an ingrespoint for the bomber + local IngressPoint = MakeMiddleWaypoint( Target, homebasecoords) --Core.Point#COORDINATE + if IngressPoint == nil then -- Its important to handle the edge cases so we don't break anything. Better throw somwthing to log. + BASE:E("--- Error in PinpointStrike target is too close to base ---" ) + return nil + end + + -- Set the coordinate altitude + IngressPoint:SetAltitude(8000) + -- Add coordiantes to table and make Waypoints + waypoints[1] = homebasecoords:WaypointAirTakeOffParking() + waypoints[2] = IngressPoint:WaypointAirTurningPoint(nil,950,{task},TargetDescription) + waypoints[3] = homecoords:WaypointAirTurningPoint() + waypoints[4] = homebasecoords:WaypointAirLanding() + -- Push the waypoint table the bomber + bomber:Route(waypoints) + + end + + -- local targetCoords = ZONE:New("Blue Bridge"):GetCoordinate() --Core.Point#COORDINATE + local CommandCenterCoords = STATIC:FindByName("SAM ControlCenter",false):GetCoordinate() + + -- I have added a small zone over a scenery object in order to grab the coordiantes. + local SceneryTargetCoordiate = ZONE:New("SceneryTarget"):GetCoordinate() + BASE:ScheduleOnce(5,PinpointStrike,"Bloue Owl 1-1",CommandCenterCoords,AIRBASE.Caucasus.Sukhumi_Babushara,"Bomb Command Center") + BASE:ScheduleOnce(10,PinpointStrike,"Bloue Owl 1-1",SceneryTargetCoordiate,AIRBASE.Caucasus.Sukhumi_Babushara,"Bomb Commanders House") + + + + diff --git a/MEN - Menu Options/Caucasus/JDAM Strike.lua b/MEN - Menu Options/Caucasus/JDAM Strike.lua new file mode 100644 index 0000000000..a288dd0d80 --- /dev/null +++ b/MEN - Menu Options/Caucasus/JDAM Strike.lua @@ -0,0 +1,146 @@ + +_SETTINGS:SetPlayerMenuOff() + +local AmmoDumpEast = STATIC:FindByName("EastAmmoDump") +local AmmoDumpEastCOORD = AmmoDumpEast:GetCoordinate() +local AmmoDumpEastHeight = AmmoDumpEastCOORD:GetLandHeight() + +local AmmoDumpWest = STATIC:FindByName("WestAmmoDump") +local AmmoDumpWestCOORD = AmmoDumpWest:GetCoordinate() +local AmmoDumpWestHeight = AmmoDumpWestCOORD:GetLandHeight() + +local AmmoDumpSouth = STATIC:FindByName("SouthAmmoDump") +local AmmoDumpSouthCOORD = AmmoDumpSouth:GetCoordinate() +local AmmoDumpSouthHeight = AmmoDumpSouthCOORD:GetLandHeight() + +local AmmoDumpNorth = STATIC:FindByName("NorthAmmoDump") +local AmmoDumpNorthCOORD = AmmoDumpNorth:GetCoordinate() +local AmmoDumpNorthHeight = AmmoDumpNorthCOORD:GetLandHeight() + +--local AllZones=SET_ZONE:New():FilterOnce()--]] +local Target_1 = ZONE:New("Bridge32") +local T1COORD = Target_1:GetCoordinate() +local T1Height = T1COORD:GetLandHeight() + + +local Target_2 = ZONE:New("Bridge33") +local T2COORD = Target_2:GetCoordinate() +local T2Height = T2COORD:GetLandHeight() + +local Target_3 = ZONE:New("HardenedHanger33") +local T3COORD = Target_3:GetCoordinate() +local T3Height = T3COORD:GetLandHeight() + +local Target_4 = ZONE:New("HardenedHanger34") +local T4COORD = Target_4:GetCoordinate() +local T4Height = T4COORD:GetLandHeight() + +local function TARGET1(T1LLDMS) +local T1LLDMS = T1COORD:ToStringLLDMS() +local coordN1 = string.sub(T1LLDMS,9,10) +local coordN2 = string.sub(T1LLDMS,13,20) +local coordE1 = string.sub(T1LLDMS,26,27) +local coordE2 = string.sub(T1LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(T1Height) +local T1Heightft = UTILS.Round(Heightft) +MESSAGE:New("Bridge 32".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T1Heightft.." ft"), 50):ToAll() +return T1LLDMS +end + +local function TARGET2(T2LLDMS) +local T2LLDMS = T2COORD:ToStringLLDMS() +local coordN1 = string.sub(T2LLDMS,9,10) +local coordN2 = string.sub(T2LLDMS,13,20) +local coordE1 = string.sub(T2LLDMS,26,27) +local coordE2 = string.sub(T2LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(T2Height) +local T2Heightft = UTILS.Round(Heightft) +MESSAGE:New("Bridge 33".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T2Heightft.." ft"), 50):ToAll() +return T2LLDMS +end + +local function TARGET3(T3LLDMS) +local T3LLDMS = T3COORD:ToStringLLDMS() +local coordN1 = string.sub(T3LLDMS,9,10) +local coordN2 = string.sub(T3LLDMS,13,20) +local coordE1 = string.sub(T3LLDMS,26,27) +local coordE2 = string.sub(T3LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(T3Height) +local T3Heightft = UTILS.Round(Heightft) +MESSAGE:New("HardenedHanger 33".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T3Heightft.." ft"), 50):ToAll() +return T3LLDMS +end + +local function TARGET4(T4LLDMS) +local T4LLDMS = T4COORD:ToStringLLDMS() +local coordN1 = string.sub(T4LLDMS,9,10) +local coordN2 = string.sub(T4LLDMS,13,20) +local coordE1 = string.sub(T4LLDMS,26,27) +local coordE2 = string.sub(T4LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(T4Height) +local T4Heightft = UTILS.Round(Heightft) +MESSAGE:New("HardenedHanger 34".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T4Heightft.." ft"), 50):ToAll() +return T4LLDMS +end + +local function TARGET5(T1LLDMS) +local T1LLDMS = AmmoDumpEastCOORD:ToStringLLDMS() +local coordN1 = string.sub(T1LLDMS,9,10) +local coordN2 = string.sub(T1LLDMS,13,20) +local coordE1 = string.sub(T1LLDMS,26,27) +local coordE2 = string.sub(T1LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(AmmoDumpEastHeight) +local T1Heightft = UTILS.Round(Heightft) +MESSAGE:New("EastAmmoDump".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T1Heightft.." ft"), 50):ToAll() +return T1LLDMS +end + +local function TARGET6(T2LLDMS) +local T2LLDMS = AmmoDumpWestCOORD:ToStringLLDMS() +local coordN1 = string.sub(T2LLDMS,9,10) +local coordN2 = string.sub(T2LLDMS,13,20) +local coordE1 = string.sub(T2LLDMS,26,27) +local coordE2 = string.sub(T2LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(AmmoDumpWestHeight) +local T2Heightft = UTILS.Round(Heightft) +MESSAGE:New("WestAmmoDump".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T2Heightft.." ft"), 50):ToAll() +return T2LLDMS +end + +local function TARGET7(T3LLDMS) +local T3LLDMS = AmmoDumpSouthCOORD:ToStringLLDMS() +local coordN1 = string.sub(T3LLDMS,9,10) +local coordN2 = string.sub(T3LLDMS,13,20) +local coordE1 = string.sub(T3LLDMS,26,27) +local coordE2 = string.sub(T3LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(AmmoDumpSouthHeight) +local T3Heightft = UTILS.Round(Heightft) +MESSAGE:New("SouthAmmoDump".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T3Heightft.." ft"), 50):ToAll() +return T3LLDMS +end + +local function TARGET8(T4LLDMS) +local T4LLDMS = AmmoDumpNorthCOORD:ToStringLLDMS() +local coordN1 = string.sub(T4LLDMS,9,10) +local coordN2 = string.sub(T4LLDMS,13,20) +local coordE1 = string.sub(T4LLDMS,26,27) +local coordE2 = string.sub(T4LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(AmmoDumpNorthHeight) +local T4Heightft = UTILS.Round(Heightft) +MESSAGE:New("NorthAmmoDump".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T4Heightft.." ft"), 50):ToAll() +return T4LLDMS +end + +TopMenu1 = MENU_MISSION:New( "TARGETCOORDS" ) + +BridgeMenu = MENU_MISSION:New( "BRIDGE",TopMenu1 ) +AmmoMenu = MENU_MISSION:New( "AMMO DUMP",TopMenu1 ) +ShelterMenu = MENU_MISSION:New( "HARDENED SHELTER",TopMenu1 ) +Menu1 = MENU_MISSION_COMMAND:New("Bridge 32",BridgeMenu, TARGET1) +Menu2 = MENU_MISSION_COMMAND:New("Bridge 33", BridgeMenu, TARGET2) +Menu3 = MENU_MISSION_COMMAND:New("HardenedHanger 33", ShelterMenu, TARGET3) +Menu4 = MENU_MISSION_COMMAND:New("HardenedHanger 34", ShelterMenu, TARGET4) +Menu5 = MENU_MISSION_COMMAND:New("AmmoDumpEast", AmmoMenu, TARGET5) +Menu6 = MENU_MISSION_COMMAND:New("AmmoDumpWest", AmmoMenu, TARGET6) +Menu7 = MENU_MISSION_COMMAND:New("AmmoDumpSouth", AmmoMenu, TARGET7) +Menu8 = MENU_MISSION_COMMAND:New("AmmoDumpNorth", AmmoMenu, TARGET8) diff --git a/MEN - Menu Options/Caucasus/JDAM_Strike.lua b/MEN - Menu Options/Caucasus/JDAM_Strike.lua new file mode 100644 index 0000000000..6ac6319adb --- /dev/null +++ b/MEN - Menu Options/Caucasus/JDAM_Strike.lua @@ -0,0 +1,150 @@ +-- This code pulls the Coordinates for JDAM use, and using the Menu format loads them in game using message system. +-- Mission created by Saint185 +-- 2020-11-21 +_SETTINGS:SetPlayerMenuOff() + + +local AmmoDumpEast = STATIC:FindByName("EastAmmoDump")--Finds the static called EastAmmoDump from the Mission Editor +local AmmoDumpEastCOORD = AmmoDumpEast:GetCoordinate()--contains the LLDMS coordinates for JDAM +local AmmoDumpEastHeight = AmmoDumpEastCOORD:GetLandHeight()--gets the land height Bridge 32 from T1COORD + +local AmmoDumpWest = STATIC:FindByName("WestAmmoDump") +local AmmoDumpWestCOORD = AmmoDumpWest:GetCoordinate() +local AmmoDumpWestHeight = AmmoDumpWestCOORD:GetLandHeight() + +local AmmoDumpSouth = STATIC:FindByName("SouthAmmoDump") +local AmmoDumpSouthCOORD = AmmoDumpSouth:GetCoordinate() +local AmmoDumpSouthHeight = AmmoDumpSouthCOORD:GetLandHeight() + +local AmmoDumpNorth = STATIC:FindByName("NorthAmmoDump") +local AmmoDumpNorthCOORD = AmmoDumpNorth:GetCoordinate() +local AmmoDumpNorthHeight = AmmoDumpNorthCOORD:GetLandHeight() + + +local Target_1 = ZONE:New("Bridge32")--Zone assigned to Bridge 32 in ME +local T1COORD = Target_1:GetCoordinate()--contains the LLDMS coordinates for JDAM +local T1Height = T1COORD:GetLandHeight()--gets the land height Bridge 32 from T1COORD + + +local Target_2 = ZONE:New("Bridge33") +local T2COORD = Target_2:GetCoordinate() +local T2Height = T2COORD:GetLandHeight() + +local Target_3 = ZONE:New("HardenedHanger33") +local T3COORD = Target_3:GetCoordinate() +local T3Height = T3COORD:GetLandHeight() + +local Target_4 = ZONE:New("HardenedHanger34") +local T4COORD = Target_4:GetCoordinate() +local T4Height = T4COORD:GetLandHeight() + +-- Gets LLDMS coord from Target 1(Bridge32p) using T1COORD:ToStringLLDMS() then assigns sections of the string to coordXy +local function TARGET1(T1LLDMS) +local T1LLDMS = T1COORD:ToStringLLDMS() +local coordN1 = string.sub(T1LLDMS,9,10)--extracts a block of text from String T4LLDMS starting at location 9 ending at location 10 +local coordN2 = string.sub(T1LLDMS,13,20)--extracts a block of text from String T4LLDMS starting at location 13 ending at location 20 +local coordE1 = string.sub(T1LLDMS,26,27)--extracts a block of text from String T4LLDMS starting at location 26 ending at location 27 +local coordE2 = string.sub(T1LLDMS,30,37)--extracts a block of text from String T4LLDMS starting at location 30 ending at location 37 +local Heightft = UTILS.MetersToFeet(T1Height)--coverts height in meters to feet +local T1Heightft = UTILS.Round(Heightft)-- rounds the value to a whole number +MESSAGE:New("Bridge 32".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T1Heightft.." ft"), 50):ToAll() +return T1LLDMS--returns the argument for function TARGET1 +end + +local function TARGET2(T2LLDMS) +local T2LLDMS = T2COORD:ToStringLLDMS() +local coordN1 = string.sub(T2LLDMS,9,10) +local coordN2 = string.sub(T2LLDMS,13,20) +local coordE1 = string.sub(T2LLDMS,26,27) +local coordE2 = string.sub(T2LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(T2Height) +local T2Heightft = UTILS.Round(Heightft) +MESSAGE:New("Bridge 33".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T2Heightft.." ft"), 50):ToAll() +return T2LLDMS +end + +local function TARGET3(T3LLDMS) +local T3LLDMS = T3COORD:ToStringLLDMS() +local coordN1 = string.sub(T3LLDMS,9,10) +local coordN2 = string.sub(T3LLDMS,13,20) +local coordE1 = string.sub(T3LLDMS,26,27) +local coordE2 = string.sub(T3LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(T3Height) +local T3Heightft = UTILS.Round(Heightft) +MESSAGE:New("HardenedHanger 33".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T3Heightft.." ft"), 50):ToAll() +return T3LLDMS +end + +local function TARGET4(T4LLDMS) +local T4LLDMS = T4COORD:ToStringLLDMS() +local coordN1 = string.sub(T4LLDMS,9,10) +local coordN2 = string.sub(T4LLDMS,13,20) +local coordE1 = string.sub(T4LLDMS,26,27) +local coordE2 = string.sub(T4LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(T4Height) +local T4Heightft = UTILS.Round(Heightft) +MESSAGE:New("HardenedHanger 34".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T4Heightft.." ft"), 50):ToAll() +return T4LLDMS +end + +local function TARGET5(T1LLDMS) +local T1LLDMS = AmmoDumpEastCOORD:ToStringLLDMS() +local coordN1 = string.sub(T1LLDMS,9,10) +local coordN2 = string.sub(T1LLDMS,13,20) +local coordE1 = string.sub(T1LLDMS,26,27) +local coordE2 = string.sub(T1LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(AmmoDumpEastHeight) +local T1Heightft = UTILS.Round(Heightft) +MESSAGE:New("EastAmmoDump".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T1Heightft.." ft"), 50):ToAll() +return T1LLDMS +end + +local function TARGET6(T2LLDMS) +local T2LLDMS = AmmoDumpWestCOORD:ToStringLLDMS() +local coordN1 = string.sub(T2LLDMS,9,10) +local coordN2 = string.sub(T2LLDMS,13,20) +local coordE1 = string.sub(T2LLDMS,26,27) +local coordE2 = string.sub(T2LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(AmmoDumpWestHeight) +local T2Heightft = UTILS.Round(Heightft) +MESSAGE:New("WestAmmoDump".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T2Heightft.." ft"), 50):ToAll() +return T2LLDMS +end + +local function TARGET7(T3LLDMS) +local T3LLDMS = AmmoDumpSouthCOORD:ToStringLLDMS() +local coordN1 = string.sub(T3LLDMS,9,10) +local coordN2 = string.sub(T3LLDMS,13,20) +local coordE1 = string.sub(T3LLDMS,26,27) +local coordE2 = string.sub(T3LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(AmmoDumpSouthHeight) +local T3Heightft = UTILS.Round(Heightft) +MESSAGE:New("SouthAmmoDump".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T3Heightft.." ft"), 50):ToAll() +return T3LLDMS +end + +local function TARGET8(T4LLDMS) +local T4LLDMS = AmmoDumpNorthCOORD:ToStringLLDMS() +local coordN1 = string.sub(T4LLDMS,9,10)--extracts text from String T4LLDMS at location 9 to 10 +local coordN2 = string.sub(T4LLDMS,13,20)--extracts text from String T4LLDMS at location 13 to 20 +local coordE1 = string.sub(T4LLDMS,26,27)--extracts text from String T4LLDMS at location 26 to 27 +local coordE2 = string.sub(T4LLDMS,30,37)--extracts text from String T4LLDMS at location 30 to 37 +local Heightft = UTILS.MetersToFeet(AmmoDumpNorthHeight)--coverts height in meters to feet +local T4Heightft = UTILS.Round(Heightft)-- rounds the value to a whole number +MESSAGE:New("NorthAmmoDump".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T4Heightft.." ft"), 50):ToAll() +return T4LLDMS +end + +--Coordinates Menu +Level1 = MENU_MISSION:New( "TARGETCOORDS" )--Top level Menu all targets are assigned to this master menu +Level2_1 = MENU_MISSION:New( "BRIDGE",Level1 )--Level 2 Contains Target groups +Level2_2 = MENU_MISSION:New( "AMMO DUMP",Level1 ) +Level2_3 = MENU_MISSION:New( "HARDENED SHELTER",Level1 ) +Menu1 = MENU_MISSION_COMMAND:New("Bridge 32",Level2_1, TARGET1)--Level 3 contains Target group coordinates +Menu2 = MENU_MISSION_COMMAND:New("Bridge 33", Level2_1, TARGET2) +Menu3 = MENU_MISSION_COMMAND:New("HardenedHanger 33", Level2_3, TARGET3)--text displayed HardenedHanger 33, select Menu position, function to call(local function TARGET3(T3LLDMS)) +Menu4 = MENU_MISSION_COMMAND:New("HardenedHanger 34", Level2_3, TARGET4) +Menu5 = MENU_MISSION_COMMAND:New("AmmoDumpEast", Level2_2, TARGET5) +Menu6 = MENU_MISSION_COMMAND:New("AmmoDumpWest", Level2_2, TARGET6) +Menu7 = MENU_MISSION_COMMAND:New("AmmoDumpSouth", Level2_2, TARGET7) +Menu8 = MENU_MISSION_COMMAND:New("AmmoDumpNorth", Level2_2, TARGET8) diff --git a/MEN - Menu Options/Caucasus/MEN-001-MENU_MISSION_COMMAND/JDAM Strike.lua b/MEN - Menu Options/Caucasus/MEN-001-MENU_MISSION_COMMAND/JDAM Strike.lua new file mode 100644 index 0000000000..2319271025 --- /dev/null +++ b/MEN - Menu Options/Caucasus/MEN-001-MENU_MISSION_COMMAND/JDAM Strike.lua @@ -0,0 +1,146 @@ + +_SETTINGS:SetPlayerMenuOff() + +local AmmoDumpEast = STATIC:FindByName("EastAmmoDump") +local AmmoDumpEastCOORD = AmmoDumpEast:GetCoordinate() +local AmmoDumpEastHeight = AmmoDumpEastCOORD:GetLandHeight() + +local AmmoDumpWest = STATIC:FindByName("WestAmmoDump") +local AmmoDumpWestCOORD = AmmoDumpWest:GetCoordinate() +local AmmoDumpWestHeight = AmmoDumpWestCOORD:GetLandHeight() + +local AmmoDumpSouth = STATIC:FindByName("SouthAmmoDump") +local AmmoDumpSouthCOORD = AmmoDumpSouth:GetCoordinate() +local AmmoDumpSouthHeight = AmmoDumpSouthCOORD:GetLandHeight() + +local AmmoDumpNorth = STATIC:FindByName("NorthAmmoDump") +local AmmoDumpNorthCOORD = AmmoDumpNorth:GetCoordinate() +local AmmoDumpNorthHeight = AmmoDumpNorthCOORD:GetLandHeight() + +--local AllZones=SET_ZONE:New():FilterOnce()--]] +local Target_1 = ZONE:New("Bridge32") +local T1COORD = Target_1:GetCoordinate() +local T1Height = T1COORD:GetLandHeight() + + +local Target_2 = ZONE:New("Bridge33") +local T2COORD = Target_2:GetCoordinate() +local T2Height = T2COORD:GetLandHeight() + +local Target_3 = ZONE:New("HardenedHanger33") +local T3COORD = Target_3:GetCoordinate() +local T3Height = T3COORD:GetLandHeight() + +local Target_4 = ZONE:New("HardenedHanger34") +local T4COORD = Target_4:GetCoordinate() +local T4Height = T4COORD:GetLandHeight() + +local function TARGET1(T1LLDMS) +local T1LLDMS = T1COORD:ToStringLLDMS() +local coordN1 = string.sub(T1LLDMS,9,10) +local coordN2 = string.sub(T1LLDMS,13,20) +local coordE1 = string.sub(T1LLDMS,26,27) +local coordE2 = string.sub(T1LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(T1Height) +local T1Heightft = UTILS.Round(Heightft) +MESSAGE:New("Bridge 32".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T1Heightft.." ft"), 50):ToAll() +return T1LLDMS +end + +local function TARGET2(T2LLDMS) +local T2LLDMS = T2COORD:ToStringLLDMS() +local coordN1 = string.sub(T2LLDMS,9,10) +local coordN2 = string.sub(T2LLDMS,13,20) +local coordE1 = string.sub(T2LLDMS,26,27) +local coordE2 = string.sub(T2LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(T2Height) +local T2Heightft = UTILS.Round(Heightft) +MESSAGE:New("Bridge 33".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T2Heightft.." ft"), 50):ToAll() +return T2LLDMS +end + +local function TARGET3(T3LLDMS) +local T3LLDMS = T3COORD:ToStringLLDMS() +local coordN1 = string.sub(T3LLDMS,9,10) +local coordN2 = string.sub(T3LLDMS,13,20) +local coordE1 = string.sub(T3LLDMS,26,27) +local coordE2 = string.sub(T3LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(T3Height) +local T3Heightft = UTILS.Round(Heightft) +MESSAGE:New("HardenedHanger 33".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T3Heightft.." ft"), 50):ToAll() +return T3LLDMS +end + +local function TARGET4(T4LLDMS) +local T4LLDMS = T4COORD:ToStringLLDMS() +local coordN1 = string.sub(T4LLDMS,9,10) +local coordN2 = string.sub(T4LLDMS,13,20) +local coordE1 = string.sub(T4LLDMS,26,27) +local coordE2 = string.sub(T4LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(T4Height) +local T4Heightft = UTILS.Round(Heightft) +MESSAGE:New("HardenedHanger 34".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T4Heightft.." ft"), 50):ToAll() +return T4LLDMS +end + +local function TARGET5(T1LLDMS) +local T1LLDMS = AmmoDumpEastCOORD:ToStringLLDMS() +local coordN1 = string.sub(T1LLDMS,9,10) +local coordN2 = string.sub(T1LLDMS,13,20) +local coordE1 = string.sub(T1LLDMS,26,27) +local coordE2 = string.sub(T1LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(AmmoDumpEastHeight) +local T1Heightft = UTILS.Round(Heightft) +MESSAGE:New("EastAmmoDump".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T1Heightft.." ft"), 50):ToAll() +return T1LLDMS +end + +local function TARGET6(T2LLDMS) +local T2LLDMS = AmmoDumpWestCOORD:ToStringLLDMS() +local coordN1 = string.sub(T2LLDMS,9,10) +local coordN2 = string.sub(T2LLDMS,13,20) +local coordE1 = string.sub(T2LLDMS,26,27) +local coordE2 = string.sub(T2LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(AmmoDumpWestHeight) +local T2Heightft = UTILS.Round(Heightft) +MESSAGE:New("WestAmmoDump".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T2Heightft.." ft"), 50):ToAll() +return T2LLDMS +end + +local function TARGET7(T3LLDMS) +local T3LLDMS = AmmoDumpSouthCOORD:ToStringLLDMS() +local coordN1 = string.sub(T3LLDMS,9,10) +local coordN2 = string.sub(T3LLDMS,13,20) +local coordE1 = string.sub(T3LLDMS,26,27) +local coordE2 = string.sub(T3LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(AmmoDumpSouthHeight) +local T3Heightft = UTILS.Round(Heightft) +MESSAGE:New("SouthAmmoDump".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T3Heightft.." ft"), 50):ToAll() +return T3LLDMS +end + +local function TARGET8(T4LLDMS) +local T4LLDMS = AmmoDumpNorthCOORD:ToStringLLDMS() +local coordN1 = string.sub(T4LLDMS,9,10) +local coordN2 = string.sub(T4LLDMS,13,20) +local coordE1 = string.sub(T4LLDMS,26,27) +local coordE2 = string.sub(T4LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(AmmoDumpNorthHeight) +local T4Heightft = UTILS.Round(Heightft) +MESSAGE:New("NorthAmmoDump".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T4Heightft.." ft"), 50):ToAll() +return T4LLDMS +end + +TopMenu1 = MENU_MISSION:New( "TARGETCOORDS" ) + +BridgeMenu = MENU_MISSION:New( "BRIDGE",TopMenu1 ) +AmmoMenu = MENU_MISSION:New( "AMMO DUMP",TopMenu1 ) +ShelterMenu = MENU_MISSION:New( "HARDENED SHELTER",TopMenu1 ) +Menu1 = MENU_MISSION_COMMAND:New("Bridge 32",BridgeMenu, TARGET1) +Menu2 = MENU_MISSION_COMMAND:New("Bridge 33", BridgeMenu, TARGET2) +Menu3 = MENU_MISSION_COMMAND:New("HardenedHanger 33", ShelterMenu, TARGET3) +Menu4 = MENU_MISSION_COMMAND:New("HardenedHanger 34", ShelterMenu, TARGET4) +Menu5 = MENU_MISSION_COMMAND:New("AmmoDumpEast", AmmoMenu, TARGET5) +Menu6 = MENU_MISSION_COMMAND:New("AmmoDumpWest", AmmoMenu, TARGET6) +Menu7 = MENU_MISSION_COMMAND:New("AmmoDumpSouth", AmmoMenu, TARGET7) +Menu8 = MENU_MISSION_COMMAND:New("AmmoDumpNorth", AmmoMenu, TARGET8) diff --git a/MEN - Menu Options/Caucasus/MEN-001-MENU_MISSION_COMMAND/JDAM_Strike.lua b/MEN - Menu Options/Caucasus/MEN-001-MENU_MISSION_COMMAND/JDAM_Strike.lua new file mode 100644 index 0000000000..c08f71d1d0 --- /dev/null +++ b/MEN - Menu Options/Caucasus/MEN-001-MENU_MISSION_COMMAND/JDAM_Strike.lua @@ -0,0 +1,150 @@ +-- This code pulls the Coordinates for JDAM use, and using the Menu format loads them in game using message system. +-- Mission created by Saint185 +-- 2020-11-21 +_SETTINGS:SetPlayerMenuOff() + + +local AmmoDumpEast = STATIC:FindByName("EastAmmoDump")--Finds the static called EastAmmoDump from the Mission Editor +local AmmoDumpEastCOORD = AmmoDumpEast:GetCoordinate()--contains the LLDMS coordinates for JDAM +local AmmoDumpEastHeight = AmmoDumpEastCOORD:GetLandHeight()--gets the land height Bridge 32 from T1COORD + +local AmmoDumpWest = STATIC:FindByName("WestAmmoDump") +local AmmoDumpWestCOORD = AmmoDumpWest:GetCoordinate() +local AmmoDumpWestHeight = AmmoDumpWestCOORD:GetLandHeight() + +local AmmoDumpSouth = STATIC:FindByName("SouthAmmoDump") +local AmmoDumpSouthCOORD = AmmoDumpSouth:GetCoordinate() +local AmmoDumpSouthHeight = AmmoDumpSouthCOORD:GetLandHeight() + +local AmmoDumpNorth = STATIC:FindByName("NorthAmmoDump") +local AmmoDumpNorthCOORD = AmmoDumpNorth:GetCoordinate() +local AmmoDumpNorthHeight = AmmoDumpNorthCOORD:GetLandHeight() + + +local Target_1 = ZONE:New("Bridge32")--Zone assigned to Bridge 32 in ME +local T1COORD = Target_1:GetCoordinate()--contains the LLDMS coordinates for JDAM +local T1Height = T1COORD:GetLandHeight()--gets the land height Bridge 32 from T1COORD + + +local Target_2 = ZONE:New("Bridge33") +local T2COORD = Target_2:GetCoordinate() +local T2Height = T2COORD:GetLandHeight() + +local Target_3 = ZONE:New("HardenedHanger33") +local T3COORD = Target_3:GetCoordinate() +local T3Height = T3COORD:GetLandHeight() + +local Target_4 = ZONE:New("HardenedHanger34") +local T4COORD = Target_4:GetCoordinate() +local T4Height = T4COORD:GetLandHeight() + +-- Gets LLDMS coord from Target 1(Bridge32p) using T1COORD:ToStringLLDMS() then assigns sections of the string to coordXy +local function TARGET1(T1LLDMS) +local T1LLDMS = T1COORD:ToStringLLDMS() +local coordN1 = string.sub(T1LLDMS,9,10)--extracts a block of text from String T4LLDMS starting at location 9 ending at location 10 +local coordN2 = string.sub(T1LLDMS,13,20)--extracts a block of text from String T4LLDMS starting at location 13 ending at location 20 +local coordE1 = string.sub(T1LLDMS,26,27)--extracts a block of text from String T4LLDMS starting at location 26 ending at location 27 +local coordE2 = string.sub(T1LLDMS,30,37)--extracts a block of text from String T4LLDMS starting at location 30 ending at location 37 +local Heightft = UTILS.MetersToFeet(T1Height)--coverts height in meters to feet +local T1Heightft = UTILS.Round(Heightft)-- rounds the value to a whole number +MESSAGE:New("Bridge 32".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T1Heightft.." ft"), 50):ToAll() +return T1LLDMS--returns the argument for function TARGET1 +end + +local function TARGET2(T2LLDMS) +local T2LLDMS = T2COORD:ToStringLLDMS() +local coordN1 = string.sub(T2LLDMS,9,10) +local coordN2 = string.sub(T2LLDMS,13,20) +local coordE1 = string.sub(T2LLDMS,26,27) +local coordE2 = string.sub(T2LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(T2Height) +local T2Heightft = UTILS.Round(Heightft) +MESSAGE:New("Bridge 33".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T2Heightft.." ft"), 50):ToAll() +return T2LLDMS +end + +local function TARGET3(T3LLDMS) +local T3LLDMS = T3COORD:ToStringLLDMS() +local coordN1 = string.sub(T3LLDMS,9,10) +local coordN2 = string.sub(T3LLDMS,13,20) +local coordE1 = string.sub(T3LLDMS,26,27) +local coordE2 = string.sub(T3LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(T3Height) +local T3Heightft = UTILS.Round(Heightft) +MESSAGE:New("HardenedHanger 33".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T3Heightft.." ft"), 50):ToAll() +return T3LLDMS +end + +local function TARGET4(T4LLDMS) +local T4LLDMS = T4COORD:ToStringLLDMS() +local coordN1 = string.sub(T4LLDMS,9,10) +local coordN2 = string.sub(T4LLDMS,13,20) +local coordE1 = string.sub(T4LLDMS,26,27) +local coordE2 = string.sub(T4LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(T4Height) +local T4Heightft = UTILS.Round(Heightft) +MESSAGE:New("HardenedHanger 34".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T4Heightft.." ft"), 50):ToAll() +return T4LLDMS +end + +local function TARGET5(T1LLDMS) +local T1LLDMS = AmmoDumpEastCOORD:ToStringLLDMS() +local coordN1 = string.sub(T1LLDMS,9,10) +local coordN2 = string.sub(T1LLDMS,13,20) +local coordE1 = string.sub(T1LLDMS,26,27) +local coordE2 = string.sub(T1LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(AmmoDumpEastHeight) +local T1Heightft = UTILS.Round(Heightft) +MESSAGE:New("EastAmmoDump".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T1Heightft.." ft"), 50):ToAll() +return T1LLDMS +end + +local function TARGET6(T2LLDMS) +local T2LLDMS = AmmoDumpWestCOORD:ToStringLLDMS() +local coordN1 = string.sub(T2LLDMS,9,10) +local coordN2 = string.sub(T2LLDMS,13,20) +local coordE1 = string.sub(T2LLDMS,26,27) +local coordE2 = string.sub(T2LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(AmmoDumpWestHeight) +local T2Heightft = UTILS.Round(Heightft) +MESSAGE:New("WestAmmoDump".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T2Heightft.." ft"), 50):ToAll() +return T2LLDMS +end + +local function TARGET7(T3LLDMS) +local T3LLDMS = AmmoDumpSouthCOORD:ToStringLLDMS() +local coordN1 = string.sub(T3LLDMS,9,10) +local coordN2 = string.sub(T3LLDMS,13,20) +local coordE1 = string.sub(T3LLDMS,26,27) +local coordE2 = string.sub(T3LLDMS,30,37) +local Heightft = UTILS.MetersToFeet(AmmoDumpSouthHeight) +local T3Heightft = UTILS.Round(Heightft) +MESSAGE:New("SouthAmmoDump".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T3Heightft.." ft"), 50):ToAll() +return T3LLDMS +end + +local function TARGET8(T4LLDMS) +local T4LLDMS = AmmoDumpNorthCOORD:ToStringLLDMS() +local coordN1 = string.sub(T4LLDMS,9,10)--extracts text from String T4LLDMS at location 9 to 10 +local coordN2 = string.sub(T4LLDMS,13,20)--extracts text from String T4LLDMS at location 13 to 20 +local coordE1 = string.sub(T4LLDMS,26,27)--extracts text from String T4LLDMS at location 26 to 27 +local coordE2 = string.sub(T4LLDMS,30,37)--extracts text from String T4LLDMS at location 30 to 37 +local Heightft = UTILS.MetersToFeet(AmmoDumpNorthHeight)--coverts height in meters to feet +local T4Heightft = UTILS.Round(Heightft)-- rounds the value to a whole number +MESSAGE:New("NorthAmmoDump".."\n".. ("N"..coordN1.."'"..coordN2.."\n".."E"..coordE1.."'"..coordE2.."\n".."ALT "..T4Heightft.." ft"), 50):ToAll() +return T4LLDMS +end + +--Coordinates Menu +Level1 = MENU_MISSION:New( "TARGETCOORDS" )--Top level Menu all targets are assigned to this master menu +Level2_1 = MENU_MISSION:New( "BRIDGE",Level1 )--Level 2 Contains Target groups +Level2_2 = MENU_MISSION:New( "AMMO DUMP",Level1 ) +Level2_3 = MENU_MISSION:New( "HARDENED SHELTER",Level1 ) +Menu1 = MENU_MISSION_COMMAND:New("Bridge 32",Level2_1, TARGET1)--Level 3 contains Target group coordinates +Menu2 = MENU_MISSION_COMMAND:New("Bridge 33", Level2_1, TARGET2) +Menu3 = MENU_MISSION_COMMAND:New("HardenedHanger 33", Level2_3, TARGET3)--text displayed HardenedHanger 33, select Menu position, function to call(local function TARGET3(T3LLDMS)) +Menu4 = MENU_MISSION_COMMAND:New("HardenedHanger 34", Level2_3, TARGET4) +Menu5 = MENU_MISSION_COMMAND:New("AmmoDumpEast", Level2_2, TARGET5) +Menu6 = MENU_MISSION_COMMAND:New("AmmoDumpWest", Level2_2, TARGET6) +Menu7 = MENU_MISSION_COMMAND:New("AmmoDumpSouth", Level2_2, TARGET7) +Menu8 = MENU_MISSION_COMMAND:New("AmmoDumpNorth", Level2_2, TARGET8) diff --git a/MEN - Menu Options/Normandy/MEN-001 - Menu Client/MEN-001 - Menu Client.miz b/MEN - Menu Options/Normandy/MEN-001 - Menu Client/MEN-001 - Menu Client.miz index 9879614019..fd1c019243 100644 Binary files a/MEN - Menu Options/Normandy/MEN-001 - Menu Client/MEN-001 - Menu Client.miz and b/MEN - Menu Options/Normandy/MEN-001 - Menu Client/MEN-001 - Menu Client.miz differ diff --git a/MEN - Menu Options/Normandy/MEN-002 - Menu Coalition/MEN-002 - Menu Coalition.miz b/MEN - Menu Options/Normandy/MEN-002 - Menu Coalition/MEN-002 - Menu Coalition.miz index 518b6e858d..39e14e9217 100644 Binary files a/MEN - Menu Options/Normandy/MEN-002 - Menu Coalition/MEN-002 - Menu Coalition.miz and b/MEN - Menu Options/Normandy/MEN-002 - Menu Coalition/MEN-002 - Menu Coalition.miz differ diff --git a/MIT - Missile Trainer/MIT-001 - Missile Trainer/MIT-001 - Missile Trainer.miz b/MIT - Missile Trainer/MIT-001 - Missile Trainer/MIT-001 - Missile Trainer.miz index 696fb4b95a..2dbff22b8b 100644 Binary files a/MIT - Missile Trainer/MIT-001 - Missile Trainer/MIT-001 - Missile Trainer.miz and b/MIT - Missile Trainer/MIT-001 - Missile Trainer/MIT-001 - Missile Trainer.miz differ diff --git a/MOP - MarkerOps_Base/MOP-100 - MARKEROPS_BASE/MarkerOps_Base_Demo.lua b/MOP - MarkerOps_Base/MOP-100 - MARKEROPS_BASE/MarkerOps_Base_Demo.lua new file mode 100644 index 0000000000..bda9ed35b9 --- /dev/null +++ b/MOP - MarkerOps_Base/MOP-100 - MARKEROPS_BASE/MarkerOps_Base_Demo.lua @@ -0,0 +1,86 @@ +------------------------------------------------------------------------- +-- MOP-100 - MARKEROPS_BASE - Basic Demo +------------------------------------------------------------------------- +-- Documentation +-- +-- MARKEROPS_BASE: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Core.MarkerOps_Base.html +-- +------------------------------------------------------------------------- +-- On the F10, call a tanker to start from the carrier. It will fly to +-- an initial zone. Set a marker on the F10 map with keyword "TankerDemo". +-- The Tanker will fly there. Set a marker on the F10 map with keywords +-- "TankerDemo RTB". The tanke will RTB to the carrier. +------------------------------------------------------------------------- +-- Date: May 2021 +------------------------------------------------------------------------- + +-- globals +mytanker = nil +tankergroup = nil +TankerAuftrag = nil + +function menucalltanker() + + if not mytanker then + -- new MARKEROPS_BASE object + mytanker = MARKEROPS_BASE:New("TankerDemo",{"RTB"}) -- Core.MarkerOps_Base#MARKEROPS_BASE + -- start FlightGroup + tankergroup = FLIGHTGROUP:New("Tanker") + tankergroup:SetHomebase(AIRBASE:FindByName("Truman")) + tankergroup:SetDefaultRadio(245,"AM",false) + tankergroup:SetDespawnAfterLanding() + tankergroup:SwitchTACAN(45, "TKR", 1, "X") + tankergroup:SetDefaultCallsign(CALLSIGN.Tanker.Texaco,1) + -- Mission + local InitialHold = ZONE:New("Initial Hold"):GetCoordinate() + TankerAuftrag = AUFTRAG:NewTANKER(InitialHold,18000,UTILS.KnotsToAltKIAS(220,18000),90,20,0) + TankerAuftrag:SetMissionRange(500) + tankergroup:AddMission(TankerAuftrag) + else + local status = tankergroup:GetState() + local m = MESSAGE:New(string.format("Tanker %s ops in status: %s", mytanker.Tag, status),10,"Info",true):ToAll() + end + + -- Handler function + local function Handler(Keywords,Coord) + + local MustRTB = false + for _,_word in pairs (Keywords) do + if string.lower(_word) == "rtb" then + MustRTB = true + end + end + + -- cancel current Auftrag + TankerAuftrag:Cancel() + + -- check if we need to RTB + if MustRTB then + tankergroup:RTB(AIRBASE:FindByName("Truman")) + else + -- no, fly to coordinate of marker + local auftrag = AUFTRAG:NewTANKER(Coord,18000,UTILS.KnotsToAltKIAS(220,18000),90,20,0) + auftrag:SetMissionRange(500) + tankergroup:AddMission(auftrag) + TankerAuftrag = auftrag + end + end + + -- Event functions + function mytanker:OnAfterMarkAdded(From,Event,To,Text,Keywords,Coord) + local m = MESSAGE:New(string.format("Tanker %s Mark Added.", self.Tag),10,"Info",true):ToAll() + Handler(Keywords,Coord) + end + + function mytanker:OnAfterMarkChanged(From,Event,To,Text,Keywords,Coord) + local m = MESSAGE:New(string.format("Tanker %s Mark Changed.", self.Tag),10,"Info",true):ToAll() + Handler(Keywords,Coord) + end + + function mytanker:OnAfterMarkDeleted(From,Event,To) + local m = MESSAGE:New(string.format("Tanker %s Mark Deleted.", self.Tag),10,"Info",true):ToAll() + end +end + +MenuTop = MENU_COALITION:New( coalition.side.BLUE,"Call Tanker") +MenuTanker = MENU_COALITION_COMMAND:New(coalition.side.BLUE,"Start Tanker",MenuTop,menucalltanker) diff --git a/MOP-100 - MARKEROPS_BASE/MarkerOps_Base_Demo.lua b/MOP-100 - MARKEROPS_BASE/MarkerOps_Base_Demo.lua new file mode 100644 index 0000000000..bda9ed35b9 --- /dev/null +++ b/MOP-100 - MARKEROPS_BASE/MarkerOps_Base_Demo.lua @@ -0,0 +1,86 @@ +------------------------------------------------------------------------- +-- MOP-100 - MARKEROPS_BASE - Basic Demo +------------------------------------------------------------------------- +-- Documentation +-- +-- MARKEROPS_BASE: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Core.MarkerOps_Base.html +-- +------------------------------------------------------------------------- +-- On the F10, call a tanker to start from the carrier. It will fly to +-- an initial zone. Set a marker on the F10 map with keyword "TankerDemo". +-- The Tanker will fly there. Set a marker on the F10 map with keywords +-- "TankerDemo RTB". The tanke will RTB to the carrier. +------------------------------------------------------------------------- +-- Date: May 2021 +------------------------------------------------------------------------- + +-- globals +mytanker = nil +tankergroup = nil +TankerAuftrag = nil + +function menucalltanker() + + if not mytanker then + -- new MARKEROPS_BASE object + mytanker = MARKEROPS_BASE:New("TankerDemo",{"RTB"}) -- Core.MarkerOps_Base#MARKEROPS_BASE + -- start FlightGroup + tankergroup = FLIGHTGROUP:New("Tanker") + tankergroup:SetHomebase(AIRBASE:FindByName("Truman")) + tankergroup:SetDefaultRadio(245,"AM",false) + tankergroup:SetDespawnAfterLanding() + tankergroup:SwitchTACAN(45, "TKR", 1, "X") + tankergroup:SetDefaultCallsign(CALLSIGN.Tanker.Texaco,1) + -- Mission + local InitialHold = ZONE:New("Initial Hold"):GetCoordinate() + TankerAuftrag = AUFTRAG:NewTANKER(InitialHold,18000,UTILS.KnotsToAltKIAS(220,18000),90,20,0) + TankerAuftrag:SetMissionRange(500) + tankergroup:AddMission(TankerAuftrag) + else + local status = tankergroup:GetState() + local m = MESSAGE:New(string.format("Tanker %s ops in status: %s", mytanker.Tag, status),10,"Info",true):ToAll() + end + + -- Handler function + local function Handler(Keywords,Coord) + + local MustRTB = false + for _,_word in pairs (Keywords) do + if string.lower(_word) == "rtb" then + MustRTB = true + end + end + + -- cancel current Auftrag + TankerAuftrag:Cancel() + + -- check if we need to RTB + if MustRTB then + tankergroup:RTB(AIRBASE:FindByName("Truman")) + else + -- no, fly to coordinate of marker + local auftrag = AUFTRAG:NewTANKER(Coord,18000,UTILS.KnotsToAltKIAS(220,18000),90,20,0) + auftrag:SetMissionRange(500) + tankergroup:AddMission(auftrag) + TankerAuftrag = auftrag + end + end + + -- Event functions + function mytanker:OnAfterMarkAdded(From,Event,To,Text,Keywords,Coord) + local m = MESSAGE:New(string.format("Tanker %s Mark Added.", self.Tag),10,"Info",true):ToAll() + Handler(Keywords,Coord) + end + + function mytanker:OnAfterMarkChanged(From,Event,To,Text,Keywords,Coord) + local m = MESSAGE:New(string.format("Tanker %s Mark Changed.", self.Tag),10,"Info",true):ToAll() + Handler(Keywords,Coord) + end + + function mytanker:OnAfterMarkDeleted(From,Event,To) + local m = MESSAGE:New(string.format("Tanker %s Mark Deleted.", self.Tag),10,"Info",true):ToAll() + end +end + +MenuTop = MENU_COALITION:New( coalition.side.BLUE,"Call Tanker") +MenuTanker = MENU_COALITION_COMMAND:New(coalition.side.BLUE,"Start Tanker",MenuTop,menucalltanker) diff --git a/OPS - Airboss/Caucasus/BOS-110 - Airboss launch tanker from ramp/RecoveryTanker - 030 - Uncontrolled_AI.lua b/OPS - Airboss/Caucasus/BOS-110 - Airboss launch tanker from ramp/RecoveryTanker - 030 - Uncontrolled_AI.lua new file mode 100644 index 0000000000..61f35adff2 --- /dev/null +++ b/OPS - Airboss/Caucasus/BOS-110 - Airboss launch tanker from ramp/RecoveryTanker - 030 - Uncontrolled_AI.lua @@ -0,0 +1,52 @@ +--- +-- RECOVERYTANKER: Uncontrolled_AI +-- +-- Created by Azza276. +-- +-- DateTime: 29/12/2020 20:47 +-- +-- Simple Recovery tanker script demonstrating the use of the RECOVERYTANKER.uncontrolledac method. +-- or RECOVERYTANKER:SetUseUncontrolledAircraft(). Both are shown below. +-- You will require an AI skill S-3B tanker group placed in the mission editor, +-- Set to "Takeoff from Ramp" and ensure "Uncontrolled" is ticked. +-- Ensure "Late activation" is not ticked. +-- +-- 2 S-3B Tankers will be spawned on the USS Stennis as a visible objects (not late activation) but without crew. +-- After 30 seconds, the first S-3B will start up go on station overhead at angels 6 with 274 knots TAS (~250 KIAS). +-- After 1 minute, the second S-3B will start up and go on station overhead at angels 12 with 300 knots TAS (~250 KIAS) +-- Radio frequencies, callsign are set below and overrule the settings of the AI group. +--- + +-- S-3B at USS Stennis spawning on deck, Start with Delay in Moose. +local tankerStennis=RECOVERYTANKER:New("USS Stennis", "Texaco Group") + +-- Custom settings for radio frequency, TACAN and callsign. +tankerStennis:SetRadio(261) +tankerStennis:SetTACAN(37, "SHL") +tankerStennis:SetCallsign(CALLSIGN.Tanker.Shell, 3) + +--tankerStennis:SetTakeoffCold() --This is not required as they will always start cold from uncontrolled state. + +--RECOVERYTANKER.uncontrolledac if true, use an uncontrolled tanker group already present in the mission. +tankerStennis.uncontrolledac = true + +-- Start recovery tanker. +-- NOTE: Delay to show Aircraft visible on deck then starts later (30 seconds after mission start). +tankerStennis:__Start(30) + + + +-- S-3B at USS Stennis spawning on deck, Start with Delay in Mission Editor Trigger. +tankerStennis2=RECOVERYTANKER:New( "USS Stennis", "Texaco Group-1") +tankerStennis2:SetRadio(271) +tankerStennis2:SetTACAN(38, "SHE") +tankerStennis2:SetCallsign(3, 2) --First parameter is Callsign name (1=Texaco, 2=Arco, 3=Shell) +tankerStennis2:SetAltitude(12000) --Sets Orbit Altitude +tankerStennis2:SetSpeed(300) --Sets speed to 300 knots TAS (~250 KIAS at 12000ft) + +--RECOVERYTANKER:SetUseUncontrolledAircraft() to use an uncontrolled tanker group already present in the mission. +tankerStennis2:SetUseUncontrolledAircraft() + +-- tankerStennis2:Start() +-- The above without "--" is loaded to the Mission editor trigger "Do Script" action after 60 seconds condition. +-- NOTE: Delay to show Aircraft visible on deck then starts later (60 seconds after mission start).. diff --git a/OPS - Airboss/Normandy/BOS-200 - Fortress Cherbourg/BOS-200 - FA-18C Fortress Cherbourg.lua b/OPS - Airboss/Normandy/BOS-200 - Fortress Cherbourg/BOS-200 - FA-18C Fortress Cherbourg.lua new file mode 100644 index 0000000000..ac13e56cbe --- /dev/null +++ b/OPS - Airboss/Normandy/BOS-200 - Fortress Cherbourg/BOS-200 - FA-18C Fortress Cherbourg.lua @@ -0,0 +1,83 @@ +------------------------- +-- AIRBOSS Test Script -- +------------------------- + +-- Set mission menu. +AIRBOSS.MenuF10Root=MENU_MISSION:New("Airboss").MenuPath + +-- No MOOSE settings menu. +_SETTINGS:SetPlayerMenuOff() + +-- S-3B Recovery Tanker spawning in air. +local tanker=RECOVERYTANKER:New("CVN-74", "- Texaco Tanker") +tanker:SetTakeoffAir() +tanker:SetRadio(256) +tanker:SetModex(511) +tanker:SetTACAN(1, "TKR") +tanker:Start() + +-- E-2D AWACS spawning in air +local awacs=RECOVERYTANKER:New("CVN-74", "AWACS") +awacs:SetAWACS() +awacs:SetTakeoffAir() +awacs:SetRadio(264) +awacs:SetAltitude(20000) +awacs:SetCallsign(CALLSIGN.AWACS.Overloard) +awacs:SetRacetrackDistances(20, 8) +awacs:SetModex(611) +awacs:SetTACAN(2, "OLV") +awacs:Start() + +-- Rescue Helo spawned in air with home base USS Perry. Has to be a global object! +rescuehelo=RESCUEHELO:New("CVN-74", "CV Helo") +rescuehelo:SetHomeBase(AIRBASE:FindByName("CG-67")) +rescuehelo:SetTakeoffAir() +rescuehelo:SetModex(42) +rescuehelo:Start() + +-- Create AIRBOSS object. +local AirbossStennis=AIRBOSS:New("CVN-74") + +-- Add recovery windows: +local window1=AirbossStennis:AddRecoveryWindow("18:30", "21:00", 1, nil, true, 20) + +-- Radio freqs. +AirbossStennis:SetMarshalRadio(305) +AirbossStennis:SetLSORadio(265) + +-- Radio relay units. +AirbossStennis:SetRadioRelayLSO(rescuehelo:GetUnitName()) +AirbossStennis:SetRadioRelayMarshal(tanker:GetUnitName()) + +-- Set folder of airboss sound files within miz file. +AirbossStennis:SetSoundfilesFolder("Airboss Soundfiles/") + +-- Single carrier menu optimization. +AirbossStennis:SetMenuSingleCarrier() + +-- Enable skipper menu. +AirbossStennis:SetMenuRecovery(15, 30, true) + +-- AI groups explicitly excluded from handling by the Airboss +AirbossStennis:SetHandleAIOFF() + +-- Remove landed AI planes from flight deck. +AirbossStennis:SetDespawnOnEngineShutdown() + +-- Load all saved player grades from your "Saved Games\DCS" folder (if lfs was desanitized). +AirbossStennis:Load() + +-- Automatically save player results to your "Saved Games\DCS" folder each time a player get a final grade from the LSO. +AirbossStennis:SetAutoSave() + +-- Enable trap sheet. +AirbossStennis:SetTrapSheet() + +-- Set recovery tanker +AirbossStennis:SetRecoveryTanker(tanker) + +-- Set AWACS. +AirbossStennis:SetAWACS(awacs) + +-- Start airboss class. +AirbossStennis:Start() diff --git a/OPS - Transport/Transport - 023 - HELO Transport Zone To Airbase from Farp/Transport - 023 - HELO Transport Zone to Airbase from Farp.lua b/OPS - Transport/Transport - 023 - HELO Transport Zone To Airbase from Farp/Transport - 023 - HELO Transport Zone to Airbase from Farp.lua index 9202d89bbe..aaf7b2aeac 100644 --- a/OPS - Transport/Transport - 023 - HELO Transport Zone To Airbase from Farp/Transport - 023 - HELO Transport Zone to Airbase from Farp.lua +++ b/OPS - Transport/Transport - 023 - HELO Transport Zone To Airbase from Farp/Transport - 023 - HELO Transport Zone to Airbase from Farp.lua @@ -1,26 +1,26 @@ ---- --- HELO: Zone to Airbase from FARP --- --- Huey group stationed at Farp Berlin picks up cargo in Zone Kobuleti X and delivers them --- to Kobuleti airbase. --- --- Note that the deploy zone is a ZONE_AIRBASE object! ---- - --- Pickup and deploy zones. -local zonePickup=ZONE:New("Zone Kobuleti X"):DrawZone() -local zoneDeploy=ZONE_AIRBASE:New(AIRBASE.Caucasus.Kobuleti):DrawZone() - --- Cargo set. -local infantryset=SET_GROUP:New():FilterPrefixes("Infantry Platoon Alpha-1"):FilterOnce() -infantryset:Activate() - --- Cargo transport assignment. -local opstransport=OPSTRANSPORT:New(infantryset, zonePickup, zoneDeploy) - --- Huey Carrier. -local hueyAlpha1=FLIGHTGROUP:New("UH-1H Alpha-1") -hueyAlpha1:Activate() - --- Cargo transport assignment to the Huey group. +--- +-- HELO: Zone To Airbase from FARP +-- +-- Huey group stationed at Farp Berlin picks up cargo in Zone Kobuleti X and delivers them +-- to Kobuleti airbase. +-- +-- Note that the deploy zone is a ZONE_AIRBASE object! +--- + +-- Pickup and deploy zones. +local zonePickup=ZONE:New("Zone Kobuleti X"):DrawZone() +local zoneDeploy=ZONE_AIRBASE:New(AIRBASE.Caucasus.Kobuleti):DrawZone() + +-- Cargo set. +local infantryset=SET_GROUP:New():FilterPrefixes("Infantry Platoon Alpha-1"):FilterOnce() + infantryset:Activate() + + -- Cargo transport assignment. +local opstransport=OPSTRANSPORT:New(infantryset, zonePickup, zoneDeploy) + +-- Huey Carrier. +local hueyAlpha1=FLIGHTGROUP:New("UH-1H Alpha-1") +hueyAlpha1:Activate() + +-- Cargo transport assignment to first Huey group. hueyAlpha1:AddOpsTransport(opstransport) \ No newline at end of file diff --git a/RAT - Random Air Traffic/Caucasus/RAT-005 - Resticted Coalition/RAT-005 - Restricted Coalition.lua b/RAT - Random Air Traffic/Caucasus/RAT-005 - Resticted Coalition/RAT-005 - Restricted Coalition.lua index 29d5bede63..f79dc761a6 100644 --- a/RAT - Random Air Traffic/Caucasus/RAT-005 - Resticted Coalition/RAT-005 - Restricted Coalition.lua +++ b/RAT - Random Air Traffic/Caucasus/RAT-005 - Resticted Coalition/RAT-005 - Restricted Coalition.lua @@ -1,47 +1,47 @@ --- Name: RAT-005 - Restricted Coalition --- Author: funkyfranky --- Date Created: 24 Sep 2017 --- --- # Situation: --- --- Spawn several aircraft of the same type at airports belonging to a certain coalition. --- In the mission editor, we have set Sochi-Adler, Gelendzhik, Batumi, Senaki-Kolkhi and Kutaisi to red. --- Likewise, Tbilisi-Lochini, Beslan, Nalchik, Mozdok and Mineralnye-Vody were set to blue. --- --- # Test cases: --- --- 1. Observe three Yak-40 aircraft being spawned at red airports only. The will also only get destination airports belonging to that coalition. --- 2. Observe three Yak-40 being spawned at blue airports only. The coalition of the aircraft is changed manually. - --- Create RAT object. Additionally, to the template group name we give the group an alias to be able to distinguish to another group created from this template. -local yak=RAT:New("RAT_Yak", "Yak Red") - --- This restricts the possible departure and destination airports the airports belonging to the red coalition. --- Here it is important that in the mission editor enough (>2) airports have been set to red! Otherwise there will be no possible departure and/or destination airports. -yak:SetCoalition("sameonly") - --- Explicitly exclude Senaki from possible departures and destinations. -yak:ExcludedAirports("Senaki-Kolkhi") - --- Spawn three aircraft. -yak:Spawn(3) - - - --- Create RAT object. Alias is "Yak Blue". If the same template is used multiple times, it is important to give each RAT object an indiviual name! -local yakblue=RAT:New("RAT_Yak", "Yak Blue") - --- Change coalition of Yak to blue. -yakblue:SetCoalitionAircraft("blue") - --- This restricts the possible departure and destination airports the airports belonging to the blue coalition since the coalition is changed manually. -yakblue:SetCoalition("sameonly") - --- We also change the livery of these groups. If a table of liveries is given, each spawned group gets a random livery. -yakblue:Livery({"Georgian Airlines"}) - --- Explicitly exclude Nalchik from possible departures and destinations. -yakblue:ExcludedAirports({"Nalchik", "Mozdok"}) - --- Spawn three aircraft. +-- Name: RAT-005 - Restricted Coalition +-- Author: funkyfranky +-- Date Created: 24 Sep 2017 +-- +-- # Situation: +-- +-- Spawn several aircraft of the same type at airports belonging to a certain coalition. +-- In the mission editor, we have set Sochi-Adler, Gelendzhik, Batumi, Senaki-Kolkhi and Kutaisi to red. +-- Likewise, Tbilisi-Lochini, Beslan, Nalchik, Mozdok and Mineralnye-Vody were set to blue. +-- +-- # Test cases: +-- +-- 1. Observe three Yak-40 aircraft being spawned at red airports only. The will also only get destination airports belonging to that coalition. +-- 2. Observe three Yak-40 being spawned at blue airports only. The coalition of the aircraft is changed manually. + +-- Create RAT object. Additionally, to the template group name we give the group an alias to be able to distinguish to another group created from this template. +local yak=RAT:New("RAT_Yak", "Yak Red") + +-- This restricts the possible departure and destination airports the airports belonging to the red coalition. +-- Here it is important that in the mission editor enough (>2) airports have been set to red! Otherwise there will be no possible departure and/or destination airports. +yak:SetCoalition("sameonly") + +-- Explicitly exclude Senaki from possible departures and destinations. +yak:ExcludedAirports("Senaki-Kolkhi") + +-- Spawn three aircraft. +yak:Spawn(3) + + + +-- Create RAT object. Alias is "Yak Blue". If the same template is used multiple times, it is important to give each RAT object an indiviual name! +local yakblue=RAT:New("RAT_Yak", "Yak Blue") + +-- Change coalition of Yak to blue. +yakblue:SetCoalitionAircraft("blue") + +-- This restricts the possible departure and destination airports the airports belonging to the blue coalition since the coalition is changed manually. +yakblue:SetCoalition("sameonly") + +-- We also change the livery of these groups. If a table of liveries is given, each spawned group gets a random livery. +yakblue:Livery({"Georgian Airlines"}) + +-- Explicitly exclude Nalchik from possible departures and destinations. +yakblue:ExcludedAirports({"Nalchik", "Mozdok"}) + +-- Spawn three aircraft. yakblue:Spawn(3) \ No newline at end of file diff --git a/SET - Data Sets/SET-001 - Airbase Sets/SET-001 - Airbase Sets.miz b/SET - Data Sets/SET-001 - Airbase Sets/SET-001 - Airbase Sets.miz index 03d07366fb..48dcf457d6 100644 Binary files a/SET - Data Sets/SET-001 - Airbase Sets/SET-001 - Airbase Sets.miz and b/SET - Data Sets/SET-001 - Airbase Sets/SET-001 - Airbase Sets.miz differ diff --git a/SET - Data Sets/SET-102 - Test SET_GROUP object against ZONE/ZON-103 - Test if GROUP object is in ZONE.lua b/SET - Data Sets/SET-102 - Test SET_GROUP object against ZONE/ZON-103 - Test if GROUP object is in ZONE.lua new file mode 100644 index 0000000000..8271df5e89 --- /dev/null +++ b/SET - Data Sets/SET-102 - Test SET_GROUP object against ZONE/ZON-103 - Test if GROUP object is in ZONE.lua @@ -0,0 +1,24 @@ +--- +-- Name: ZON-103 - Test if GROUP object is in ZONE +-- Author: FlightControl +-- Date Created: 31 Mar 2017 +-- +-- # Situation: +-- +-- A ZONE has been defined, and it is checked if a GROUP object is within the zone. +-- +-- # Test cases: +-- +-- 1. Observe the zone perimeter, and place the GROUP object in or out of the zone. +-- 2. Observe the results of the functions. + + +GroupObject = GROUP:FindByName( "Group Object" ) + +Zone = ZONE:New( "Zone" ) + + +Zone:E( { "Group is completely in Zone:", GroupObject:IsCompletelyInZone( Zone ) } ) +Zone:E( { "Group is partially in Zone:", GroupObject:IsPartlyInZone( Zone ) } ) +Zone:E( { "Group is not in Zone:", GroupObject:IsNotInZone( Zone ) } ) + diff --git a/SET - Data Sets/SET-GRP/SET-GRP-000 - Add and Remove/SET-101 - Group Sets.lua b/SET - Data Sets/SET-GRP/SET-GRP-000 - Add and Remove/SET-101 - Group Sets.lua new file mode 100644 index 0000000000..ba7685e8e3 --- /dev/null +++ b/SET - Data Sets/SET-GRP/SET-GRP-000 - Add and Remove/SET-101 - Group Sets.lua @@ -0,0 +1,163 @@ + + + + +SetVehicles = SET_GROUP:New() + +SetVehicles:AddGroupsByName( { "Vehicle A", "Vehicle B", "Vehicle C" } ) + +SetVehicles:ForEachGroup( + --- @param Wrapper.Group#GROUP MooseGroup + function( MooseGroup ) + for UnitId, UnitData in pairs( MooseGroup:GetUnits() ) do + local UnitAction = UnitData -- Wrapper.Unit#UNIT + UnitAction:SmokeGreen() + end + end +) + + + +SetBluePlanesGroup = SET_GROUP:New() + :FilterCoalitions( "blue" ) + :FilterCategories( "plane" ) + :FilterStart() + +SetNorthKoreaGroup = SET_GROUP:New() + :FilterCountries( "RUSSIA" ) + :FilterStart() + +SetSAMGroup = SET_GROUP:New() + :FilterPrefixes( "SAM" ) + :FilterStart() + :SetIteratorIntervals( 5, 10 ) + +SetGroundGroup = SET_GROUP:New() + :FilterCategories( "ground" ) + :FilterStart() + +SetGroundGroup:Flush() + +SpawnUS_Plane = SPAWN:New( 'Spawn Test USA Plane') +GroupUS_Plane = SpawnUS_Plane:Spawn() + +SpawnUS_Vehicle = SPAWN:New( 'Spawn Test USA Vehicle') +GroupUS_Vehicle = SpawnUS_Vehicle:Spawn() + +SpawnUS_Ship = SPAWN:New( 'Spawn Test USA Ship') +GroupUS_Ship = SpawnUS_Ship:Spawn() + +SpawnRU_Vehicle = SPAWN:New( 'Spawn Test RUSSIA Vehicle') +GroupRU_Vehicle = SpawnRU_Vehicle:Spawn() + +SpawnRU_Ship = SPAWN:New( 'Spawn Test RUSSIA Ship') +GroupRU_Ship = SpawnRU_Ship:Spawn() + +SpawnM2A2_AttackVehicle = SPAWN:New( 'Spawn Test M2A2 Attack Vehicle' ):InitRandomizeUnits( true, 10, 4 ) +SpawnSAM_AttackVehicle = SPAWN:New( 'Spawn Test SAM Attack Vehicle' ):InitRandomizeUnits( true, 10, 4 ) + +for i = 1, 30 do + GroupM2A2_AttackVehicle = SpawnM2A2_AttackVehicle:SpawnInZone( ZONE:New("Spawn Zone") ) + GroupSAM_AttackVehicle = SpawnSAM_AttackVehicle:SpawnInZone( ZONE:New("Spawn Zone") ) +end + +SetVehicleCompletely = SET_GROUP:New() + :FilterPrefixes( "Spawn Vehicle Zone Completely" ) + :FilterStart() + +SetVehiclePartly = SET_GROUP:New() + :FilterPrefixes( "Spawn Vehicle Zone Partly" ) + :FilterStart() + +SetVehicleNot = SET_GROUP:New() + :FilterPrefixes( "Spawn Vehicle Zone Not" ) + :FilterStart() + +Spawn_Vehicle_Zone_Completely = SPAWN:New( 'Spawn Vehicle Zone Completely' ):InitRandomizeUnits( true, 10, 4) +Spawn_Vehicle_Zone_Partly = SPAWN:New( 'Spawn Vehicle Zone Partly' ):InitRandomizeUnits( true, 10, 4 ) +Spawn_Vehicle_Zone_Not = SPAWN:New( 'Spawn Vehicle Zone Not' ):InitRandomizeUnits( true, 10, 4 ) +for i = 1, 30 do + Spawn_Vehicle_Zone_Completely:SpawnInZone( ZONE:New("Spawn Zone Completely") ) + Spawn_Vehicle_Zone_Partly:SpawnInZone( ZONE:New("Spawn Zone Partly") ) + Spawn_Vehicle_Zone_Not:SpawnInZone( ZONE:New("Spawn Zone Not") ) +end + +--DBBlue:TraceDatabase() +--SCHEDULER:New( DBBluePlanes, DBBluePlanes.Flush, { }, 1 ) +--SCHEDULER:New( DBRedVehicles, DBRedVehicles.Flush, { }, 1 ) +--SCHEDULER:New( DBShips, DBShips.Flush, { }, 1 ) +--SCHEDULER:New( DBBelgium, DBBelgium.Flush, { }, 1 ) +--SCHEDULER:New( DBNorthKorea, DBNorthKorea.Flush, { }, 1 ) +--SCHEDULER:New( DBKA50Vinson, DBKA50Vinson.Flush, { }, 1 ) +-- +--SCHEDULER:New( DBBluePlanesGroup, DBBluePlanesGroup.Flush, { }, 1 ) +--SCHEDULER:New( DBNorthKoreaGroup, DBNorthKoreaGroup.Flush, { }, 1 ) + +SetBluePlanesGroup:ForEachGroup( + --- @param Wrapper.Group#GROUP MooseGroup + function( MooseGroup ) + for UnitId, UnitData in pairs( MooseGroup:GetUnits() ) do + local UnitAction = UnitData -- Wrapper.Unit#UNIT + UnitAction:SmokeBlue() + end + end +) + +SetNorthKoreaGroup:ForEachGroup( + --- @param Wrapper.Group#GROUP MooseGroup + function( MooseGroup ) + for UnitId, UnitData in pairs( MooseGroup:GetUnits() ) do + local UnitAction = UnitData -- Wrapper.Unit#UNIT + UnitAction:SmokeRed() + end + end +) + +SetSAMGroup:ForEachGroup( + --- @param Wrapper.Group#GROUP MooseGroup + function( MooseGroup ) + for UnitId, UnitData in pairs( MooseGroup:GetUnits() ) do + local UnitAction = UnitData -- Wrapper.Unit#UNIT + UnitAction:SmokeOrange() + end + end +) + +GroupZoneCompletely = GROUP:FindByName( "Zone Completely" ) +GroupZonePartly = GROUP:FindByName( "Zone Partly" ) +GroupZoneNot = GROUP:FindByName( "Zone Not" ) + +ZoneCompletely = ZONE_POLYGON:New( "Zone Completely", GroupZoneCompletely ):SmokeZone( SMOKECOLOR.White ) +ZonePartly = ZONE_POLYGON:New( "Zone Partly", GroupZonePartly ):SmokeZone( SMOKECOLOR.White ) +ZoneNot = ZONE_POLYGON:New( "Zone Not", GroupZoneNot ):SmokeZone( SMOKECOLOR.White ) + +SetVehicleCompletely:ForEachGroupCompletelyInZone( ZoneCompletely, + --- @param Wrapper.Group#GROUP MooseGroup + function( MooseGroup ) + for UnitId, UnitData in pairs( MooseGroup:GetUnits() ) do + local UnitAction = UnitData -- Wrapper.Unit#UNIT + UnitAction:SmokeBlue() + end + end +) + +SetVehiclePartly:ForEachGroupPartlyInZone( ZonePartly, + --- @param Wrapper.Group#GROUP MooseGroup + function( MooseGroup ) + for UnitId, UnitData in pairs( MooseGroup:GetUnits() ) do + local UnitAction = UnitData -- Wrapper.Unit#UNIT + UnitAction:SmokeBlue() + end + end +) + +SetVehicleNot:ForEachGroupNotInZone( ZoneNot, + --- @param Wrapper.Group#GROUP MooseGroup + function( MooseGroup ) + for UnitId, UnitData in pairs( MooseGroup:GetUnits() ) do + local UnitAction = UnitData -- Wrapper.Unit#UNIT + UnitAction:SmokeBlue() + end + end +) + \ No newline at end of file diff --git a/SET - Data Sets/SET-GRP/SET-GRP-101 - Group Sets/SET-101 - Group Sets.lua b/SET - Data Sets/SET-GRP/SET-GRP-101 - Group Sets/SET-101 - Group Sets.lua index d15682cbc0..ba7685e8e3 100644 --- a/SET - Data Sets/SET-GRP/SET-GRP-101 - Group Sets/SET-101 - Group Sets.lua +++ b/SET - Data Sets/SET-GRP/SET-GRP-101 - Group Sets/SET-101 - Group Sets.lua @@ -1,159 +1,163 @@ -SetVehicles = SET_GROUP:New() - -SetVehicles:AddGroupsByName( { "Vehicle A", "Vehicle B", "Vehicle C" } ) - -SetVehicles:ForEachGroup( - --- @param Wrapper.Group#GROUP MooseGroup - function( MooseGroup ) - for UnitId, UnitData in pairs( MooseGroup:GetUnits() ) do - local UnitAction = UnitData -- Wrapper.Unit#UNIT - UnitAction:SmokeGreen() - end - end -) - - - -SetBluePlanesGroup = SET_GROUP:New() - :FilterCoalitions( "blue" ) - :FilterCategories( "plane" ) - :FilterStart() - -SetNorthKoreaGroup = SET_GROUP:New() - :FilterCountries( "RUSSIA" ) - :FilterStart() - -SetSAMGroup = SET_GROUP:New() - :FilterPrefixes( "SAM" ) - :FilterStart() - :SetIteratorIntervals( 5, 10 ) - -SetGroundGroup = SET_GROUP:New() - :FilterCategories( "ground" ) - :FilterStart() - -SetGroundGroup:Flush() - -SpawnUS_Plane = SPAWN:New( 'Spawn Test USA Plane') -GroupUS_Plane = SpawnUS_Plane:Spawn() - -SpawnUS_Vehicle = SPAWN:New( 'Spawn Test USA Vehicle') -GroupUS_Vehicle = SpawnUS_Vehicle:Spawn() - -SpawnUS_Ship = SPAWN:New( 'Spawn Test USA Ship') -GroupUS_Ship = SpawnUS_Ship:Spawn() - -SpawnRU_Vehicle = SPAWN:New( 'Spawn Test RUSSIA Vehicle') -GroupRU_Vehicle = SpawnRU_Vehicle:Spawn() - -SpawnRU_Ship = SPAWN:New( 'Spawn Test RUSSIA Ship') -GroupRU_Ship = SpawnRU_Ship:Spawn() - -SpawnM2A2_AttackVehicle = SPAWN:New( 'Spawn Test M2A2 Attack Vehicle' ):InitRandomizeUnits( true, 10, 4 ) -SpawnSAM_AttackVehicle = SPAWN:New( 'Spawn Test SAM Attack Vehicle' ):InitRandomizeUnits( true, 10, 4 ) - -for i = 1, 30 do - GroupM2A2_AttackVehicle = SpawnM2A2_AttackVehicle:SpawnInZone( ZONE:New("Spawn Zone") ) - GroupSAM_AttackVehicle = SpawnSAM_AttackVehicle:SpawnInZone( ZONE:New("Spawn Zone") ) -end - -SetVehicleCompletely = SET_GROUP:New() - :FilterPrefixes( "Spawn Vehicle Zone Completely" ) - :FilterStart() - -SetVehiclePartly = SET_GROUP:New() - :FilterPrefixes( "Spawn Vehicle Zone Partly" ) - :FilterStart() - -SetVehicleNot = SET_GROUP:New() - :FilterPrefixes( "Spawn Vehicle Zone Not" ) - :FilterStart() - -Spawn_Vehicle_Zone_Completely = SPAWN:New( 'Spawn Vehicle Zone Completely' ):InitRandomizeUnits( true, 10, 4) -Spawn_Vehicle_Zone_Partly = SPAWN:New( 'Spawn Vehicle Zone Partly' ):InitRandomizeUnits( true, 10, 4 ) -Spawn_Vehicle_Zone_Not = SPAWN:New( 'Spawn Vehicle Zone Not' ):InitRandomizeUnits( true, 10, 4 ) -for i = 1, 30 do - Spawn_Vehicle_Zone_Completely:SpawnInZone( ZONE:New("Spawn Zone Completely") ) - Spawn_Vehicle_Zone_Partly:SpawnInZone( ZONE:New("Spawn Zone Partly") ) - Spawn_Vehicle_Zone_Not:SpawnInZone( ZONE:New("Spawn Zone Not") ) -end - ---DBBlue:TraceDatabase() ---SCHEDULER:New( DBBluePlanes, DBBluePlanes.Flush, { }, 1 ) ---SCHEDULER:New( DBRedVehicles, DBRedVehicles.Flush, { }, 1 ) ---SCHEDULER:New( DBShips, DBShips.Flush, { }, 1 ) ---SCHEDULER:New( DBBelgium, DBBelgium.Flush, { }, 1 ) ---SCHEDULER:New( DBNorthKorea, DBNorthKorea.Flush, { }, 1 ) ---SCHEDULER:New( DBKA50Vinson, DBKA50Vinson.Flush, { }, 1 ) --- ---SCHEDULER:New( DBBluePlanesGroup, DBBluePlanesGroup.Flush, { }, 1 ) ---SCHEDULER:New( DBNorthKoreaGroup, DBNorthKoreaGroup.Flush, { }, 1 ) - -SetBluePlanesGroup:ForEachGroup( - --- @param Wrapper.Group#GROUP MooseGroup - function( MooseGroup ) - for UnitId, UnitData in pairs( MooseGroup:GetUnits() ) do - local UnitAction = UnitData -- Wrapper.Unit#UNIT - UnitAction:SmokeBlue() - end - end -) - -SetNorthKoreaGroup:ForEachGroup( - --- @param Wrapper.Group#GROUP MooseGroup - function( MooseGroup ) - for UnitId, UnitData in pairs( MooseGroup:GetUnits() ) do - local UnitAction = UnitData -- Wrapper.Unit#UNIT - UnitAction:SmokeRed() - end - end -) - -SetSAMGroup:ForEachGroup( - --- @param Wrapper.Group#GROUP MooseGroup - function( MooseGroup ) - for UnitId, UnitData in pairs( MooseGroup:GetUnits() ) do - local UnitAction = UnitData -- Wrapper.Unit#UNIT - UnitAction:SmokeOrange() - end - end -) - -GroupZoneCompletely = GROUP:FindByName( "Zone Completely" ) -GroupZonePartly = GROUP:FindByName( "Zone Partly" ) -GroupZoneNot = GROUP:FindByName( "Zone Not" ) - -ZoneCompletely = ZONE_POLYGON:New( "Zone Completely", GroupZoneCompletely ):SmokeZone( SMOKECOLOR.White ) -ZonePartly = ZONE_POLYGON:New( "Zone Partly", GroupZonePartly ):SmokeZone( SMOKECOLOR.White ) -ZoneNot = ZONE_POLYGON:New( "Zone Not", GroupZoneNot ):SmokeZone( SMOKECOLOR.White ) - -SetVehicleCompletely:ForEachGroupCompletelyInZone( ZoneCompletely, - --- @param Wrapper.Group#GROUP MooseGroup - function( MooseGroup ) - for UnitId, UnitData in pairs( MooseGroup:GetUnits() ) do - local UnitAction = UnitData -- Wrapper.Unit#UNIT - UnitAction:SmokeBlue() - end - end -) - -SetVehiclePartly:ForEachGroupPartlyInZone( ZonePartly, - --- @param Wrapper.Group#GROUP MooseGroup - function( MooseGroup ) - for UnitId, UnitData in pairs( MooseGroup:GetUnits() ) do - local UnitAction = UnitData -- Wrapper.Unit#UNIT - UnitAction:SmokeBlue() - end - end -) - -SetVehicleNot:ForEachGroupNotInZone( ZoneNot, - --- @param Wrapper.Group#GROUP MooseGroup - function( MooseGroup ) - for UnitId, UnitData in pairs( MooseGroup:GetUnits() ) do - local UnitAction = UnitData -- Wrapper.Unit#UNIT - UnitAction:SmokeBlue() - end - end -) - + + + + +SetVehicles = SET_GROUP:New() + +SetVehicles:AddGroupsByName( { "Vehicle A", "Vehicle B", "Vehicle C" } ) + +SetVehicles:ForEachGroup( + --- @param Wrapper.Group#GROUP MooseGroup + function( MooseGroup ) + for UnitId, UnitData in pairs( MooseGroup:GetUnits() ) do + local UnitAction = UnitData -- Wrapper.Unit#UNIT + UnitAction:SmokeGreen() + end + end +) + + + +SetBluePlanesGroup = SET_GROUP:New() + :FilterCoalitions( "blue" ) + :FilterCategories( "plane" ) + :FilterStart() + +SetNorthKoreaGroup = SET_GROUP:New() + :FilterCountries( "RUSSIA" ) + :FilterStart() + +SetSAMGroup = SET_GROUP:New() + :FilterPrefixes( "SAM" ) + :FilterStart() + :SetIteratorIntervals( 5, 10 ) + +SetGroundGroup = SET_GROUP:New() + :FilterCategories( "ground" ) + :FilterStart() + +SetGroundGroup:Flush() + +SpawnUS_Plane = SPAWN:New( 'Spawn Test USA Plane') +GroupUS_Plane = SpawnUS_Plane:Spawn() + +SpawnUS_Vehicle = SPAWN:New( 'Spawn Test USA Vehicle') +GroupUS_Vehicle = SpawnUS_Vehicle:Spawn() + +SpawnUS_Ship = SPAWN:New( 'Spawn Test USA Ship') +GroupUS_Ship = SpawnUS_Ship:Spawn() + +SpawnRU_Vehicle = SPAWN:New( 'Spawn Test RUSSIA Vehicle') +GroupRU_Vehicle = SpawnRU_Vehicle:Spawn() + +SpawnRU_Ship = SPAWN:New( 'Spawn Test RUSSIA Ship') +GroupRU_Ship = SpawnRU_Ship:Spawn() + +SpawnM2A2_AttackVehicle = SPAWN:New( 'Spawn Test M2A2 Attack Vehicle' ):InitRandomizeUnits( true, 10, 4 ) +SpawnSAM_AttackVehicle = SPAWN:New( 'Spawn Test SAM Attack Vehicle' ):InitRandomizeUnits( true, 10, 4 ) + +for i = 1, 30 do + GroupM2A2_AttackVehicle = SpawnM2A2_AttackVehicle:SpawnInZone( ZONE:New("Spawn Zone") ) + GroupSAM_AttackVehicle = SpawnSAM_AttackVehicle:SpawnInZone( ZONE:New("Spawn Zone") ) +end + +SetVehicleCompletely = SET_GROUP:New() + :FilterPrefixes( "Spawn Vehicle Zone Completely" ) + :FilterStart() + +SetVehiclePartly = SET_GROUP:New() + :FilterPrefixes( "Spawn Vehicle Zone Partly" ) + :FilterStart() + +SetVehicleNot = SET_GROUP:New() + :FilterPrefixes( "Spawn Vehicle Zone Not" ) + :FilterStart() + +Spawn_Vehicle_Zone_Completely = SPAWN:New( 'Spawn Vehicle Zone Completely' ):InitRandomizeUnits( true, 10, 4) +Spawn_Vehicle_Zone_Partly = SPAWN:New( 'Spawn Vehicle Zone Partly' ):InitRandomizeUnits( true, 10, 4 ) +Spawn_Vehicle_Zone_Not = SPAWN:New( 'Spawn Vehicle Zone Not' ):InitRandomizeUnits( true, 10, 4 ) +for i = 1, 30 do + Spawn_Vehicle_Zone_Completely:SpawnInZone( ZONE:New("Spawn Zone Completely") ) + Spawn_Vehicle_Zone_Partly:SpawnInZone( ZONE:New("Spawn Zone Partly") ) + Spawn_Vehicle_Zone_Not:SpawnInZone( ZONE:New("Spawn Zone Not") ) +end + +--DBBlue:TraceDatabase() +--SCHEDULER:New( DBBluePlanes, DBBluePlanes.Flush, { }, 1 ) +--SCHEDULER:New( DBRedVehicles, DBRedVehicles.Flush, { }, 1 ) +--SCHEDULER:New( DBShips, DBShips.Flush, { }, 1 ) +--SCHEDULER:New( DBBelgium, DBBelgium.Flush, { }, 1 ) +--SCHEDULER:New( DBNorthKorea, DBNorthKorea.Flush, { }, 1 ) +--SCHEDULER:New( DBKA50Vinson, DBKA50Vinson.Flush, { }, 1 ) +-- +--SCHEDULER:New( DBBluePlanesGroup, DBBluePlanesGroup.Flush, { }, 1 ) +--SCHEDULER:New( DBNorthKoreaGroup, DBNorthKoreaGroup.Flush, { }, 1 ) + +SetBluePlanesGroup:ForEachGroup( + --- @param Wrapper.Group#GROUP MooseGroup + function( MooseGroup ) + for UnitId, UnitData in pairs( MooseGroup:GetUnits() ) do + local UnitAction = UnitData -- Wrapper.Unit#UNIT + UnitAction:SmokeBlue() + end + end +) + +SetNorthKoreaGroup:ForEachGroup( + --- @param Wrapper.Group#GROUP MooseGroup + function( MooseGroup ) + for UnitId, UnitData in pairs( MooseGroup:GetUnits() ) do + local UnitAction = UnitData -- Wrapper.Unit#UNIT + UnitAction:SmokeRed() + end + end +) + +SetSAMGroup:ForEachGroup( + --- @param Wrapper.Group#GROUP MooseGroup + function( MooseGroup ) + for UnitId, UnitData in pairs( MooseGroup:GetUnits() ) do + local UnitAction = UnitData -- Wrapper.Unit#UNIT + UnitAction:SmokeOrange() + end + end +) + +GroupZoneCompletely = GROUP:FindByName( "Zone Completely" ) +GroupZonePartly = GROUP:FindByName( "Zone Partly" ) +GroupZoneNot = GROUP:FindByName( "Zone Not" ) + +ZoneCompletely = ZONE_POLYGON:New( "Zone Completely", GroupZoneCompletely ):SmokeZone( SMOKECOLOR.White ) +ZonePartly = ZONE_POLYGON:New( "Zone Partly", GroupZonePartly ):SmokeZone( SMOKECOLOR.White ) +ZoneNot = ZONE_POLYGON:New( "Zone Not", GroupZoneNot ):SmokeZone( SMOKECOLOR.White ) + +SetVehicleCompletely:ForEachGroupCompletelyInZone( ZoneCompletely, + --- @param Wrapper.Group#GROUP MooseGroup + function( MooseGroup ) + for UnitId, UnitData in pairs( MooseGroup:GetUnits() ) do + local UnitAction = UnitData -- Wrapper.Unit#UNIT + UnitAction:SmokeBlue() + end + end +) + +SetVehiclePartly:ForEachGroupPartlyInZone( ZonePartly, + --- @param Wrapper.Group#GROUP MooseGroup + function( MooseGroup ) + for UnitId, UnitData in pairs( MooseGroup:GetUnits() ) do + local UnitAction = UnitData -- Wrapper.Unit#UNIT + UnitAction:SmokeBlue() + end + end +) + +SetVehicleNot:ForEachGroupNotInZone( ZoneNot, + --- @param Wrapper.Group#GROUP MooseGroup + function( MooseGroup ) + for UnitId, UnitData in pairs( MooseGroup:GetUnits() ) do + local UnitAction = UnitData -- Wrapper.Unit#UNIT + UnitAction:SmokeBlue() + end + end +) + \ No newline at end of file diff --git a/SET - Data Sets/SET-UNT/SET-UNT-100 - FilterOnce Scenario 1/SET-UNT-100 - Unit Sets.lua b/SET - Data Sets/SET-UNT/SET-UNT-100 - FilterOnce Scenario 1/SET-UNT-100 - Unit Sets.lua index 9b2806f476..ed0518e126 100644 --- a/SET - Data Sets/SET-UNT/SET-UNT-100 - FilterOnce Scenario 1/SET-UNT-100 - Unit Sets.lua +++ b/SET - Data Sets/SET-UNT/SET-UNT-100 - FilterOnce Scenario 1/SET-UNT-100 - Unit Sets.lua @@ -1,7 +1,7 @@ - -SetUnit = SET_UNIT:New():FilterCoalitions("blue"):FilterCategories("ground"):FilterOnce() - -SetUnit:Flush() - -SetUnit:I(SetUnit:Count()) - + +SetUnit = SET_UNIT:New():FilterCoalitions("blue"):FilterCategories("ground"):FilterOnce() + +SetUnit:Flush() + +SetUnit:I(SetUnit:Count()) + diff --git a/SET - Data Sets/SET-UNT/SET-UNT-110 - FilterOnce Scenario 2/SET-UNT-110 - FilterOnce Ground.lua b/SET - Data Sets/SET-UNT/SET-UNT-110 - FilterOnce Scenario 2/SET-UNT-110 - FilterOnce Ground.lua index da158a4dda..1183395618 100644 --- a/SET - Data Sets/SET-UNT/SET-UNT-110 - FilterOnce Scenario 2/SET-UNT-110 - FilterOnce Ground.lua +++ b/SET - Data Sets/SET-UNT/SET-UNT-110 - FilterOnce Scenario 2/SET-UNT-110 - FilterOnce Ground.lua @@ -1,11 +1,12 @@ -SetUnit = SET_UNIT:New():FilterCoalitions("blue"):FilterCategories("ground"):FilterOnce() -SetUnit:Flush() -SetUnit:I( { Count = SetUnit:Count() } ) - -SCHEDULER:New( nil, - function() - SetUnit = SET_UNIT:New():FilterCoalitions("blue"):FilterCategories("ground"):FilterOnce() - SetUnit:Flush() - SetUnit:I( { Count = SetUnit:Count() } ) - end, {}, 60 ) - + +SetUnit = SET_UNIT:New():FilterCoalitions("blue"):FilterCategories("ground"):FilterOnce() +SetUnit:Flush() +SetUnit:I( { Count = SetUnit:Count() } ) + +SCHEDULER:New( nil, + function() + SetUnit = SET_UNIT:New():FilterCoalitions("blue"):FilterCategories("ground"):FilterOnce() + SetUnit:Flush() + SetUnit:I( { Count = SetUnit:Count() } ) + end, {}, 60 ) + diff --git a/SEV - SEAD Evasion/SEV-001 - SEAD Evasion/SEV-001 - SEAD Evasion.miz b/SEV - SEAD Evasion/SEV-001 - SEAD Evasion/SEV-001 - SEAD Evasion.miz index 57f8adcc30..1ba581e4fe 100644 Binary files a/SEV - SEAD Evasion/SEV-001 - SEAD Evasion/SEV-001 - SEAD Evasion.miz and b/SEV - SEAD Evasion/SEV-001 - SEAD Evasion/SEV-001 - SEAD Evasion.miz differ diff --git a/SPA - Spawning/SPA-011 - Ground Ops - Simple Spawning/SPA-011 - Ground Ops - Simple Spawning.miz b/SPA - Spawning/SPA-011 - Ground Ops - Simple Spawning/SPA-011 - Ground Ops - Simple Spawning.miz index 5653280acd..051a771ed8 100644 Binary files a/SPA - Spawning/SPA-011 - Ground Ops - Simple Spawning/SPA-011 - Ground Ops - Simple Spawning.miz and b/SPA - Spawning/SPA-011 - Ground Ops - Simple Spawning/SPA-011 - Ground Ops - Simple Spawning.miz differ diff --git a/SPA - Spawning/SPA-012 - Ground Ops - Multiple Spawns/SPA-012 - Ground Ops - Multiple Spawns.miz b/SPA - Spawning/SPA-012 - Ground Ops - Multiple Spawns/SPA-012 - Ground Ops - Multiple Spawns.miz index ef28971f9c..96fe537341 100644 Binary files a/SPA - Spawning/SPA-012 - Ground Ops - Multiple Spawns/SPA-012 - Ground Ops - Multiple Spawns.miz and b/SPA - Spawning/SPA-012 - Ground Ops - Multiple Spawns/SPA-012 - Ground Ops - Multiple Spawns.miz differ diff --git a/SPA - Spawning/SPA-013 - Ground Ops - Scheduled Spawns/SPA-013 - Ground Ops - Scheduled Spawns.miz b/SPA - Spawning/SPA-013 - Ground Ops - Scheduled Spawns/SPA-013 - Ground Ops - Scheduled Spawns.miz index 045df2896a..1c52a4ff19 100644 Binary files a/SPA - Spawning/SPA-013 - Ground Ops - Scheduled Spawns/SPA-013 - Ground Ops - Scheduled Spawns.miz and b/SPA - Spawning/SPA-013 - Ground Ops - Scheduled Spawns/SPA-013 - Ground Ops - Scheduled Spawns.miz differ diff --git a/SPA - Spawning/SPA-014 - Ground Ops - Scheduled Spawns Limited/SPA-014 - Ground Ops - Scheduled Spawns Limited.miz b/SPA - Spawning/SPA-014 - Ground Ops - Scheduled Spawns Limited/SPA-014 - Ground Ops - Scheduled Spawns Limited.miz index 10feb7059b..4c8f3001be 100644 Binary files a/SPA - Spawning/SPA-014 - Ground Ops - Scheduled Spawns Limited/SPA-014 - Ground Ops - Scheduled Spawns Limited.miz and b/SPA - Spawning/SPA-014 - Ground Ops - Scheduled Spawns Limited/SPA-014 - Ground Ops - Scheduled Spawns Limited.miz differ diff --git a/SPA - Spawning/SPA-015 - Ground Ops - Randomize Route/SPA-015 - Ground Ops - Randomize Route.miz b/SPA - Spawning/SPA-015 - Ground Ops - Randomize Route/SPA-015 - Ground Ops - Randomize Route.miz index f74ab9f12a..7d264bf08a 100644 Binary files a/SPA - Spawning/SPA-015 - Ground Ops - Randomize Route/SPA-015 - Ground Ops - Randomize Route.miz and b/SPA - Spawning/SPA-015 - Ground Ops - Randomize Route/SPA-015 - Ground Ops - Randomize Route.miz differ diff --git a/SPA - Spawning/SPA-016 - Ground Ops - Randomize Zones/SPA-016 - Ground Ops - Randomize Zones.miz b/SPA - Spawning/SPA-016 - Ground Ops - Randomize Zones/SPA-016 - Ground Ops - Randomize Zones.miz index 84e3f14a94..5f467afb1c 100644 Binary files a/SPA - Spawning/SPA-016 - Ground Ops - Randomize Zones/SPA-016 - Ground Ops - Randomize Zones.miz and b/SPA - Spawning/SPA-016 - Ground Ops - Randomize Zones/SPA-016 - Ground Ops - Randomize Zones.miz differ diff --git a/SPA - Spawning/SPA-018 - Ground Ops - Randomize Templates/SPA-018 - Ground Ops - Randomize Templates.miz b/SPA - Spawning/SPA-018 - Ground Ops - Randomize Templates/SPA-018 - Ground Ops - Randomize Templates.miz index e9ec5d9532..2210e06005 100644 Binary files a/SPA - Spawning/SPA-018 - Ground Ops - Randomize Templates/SPA-018 - Ground Ops - Randomize Templates.miz and b/SPA - Spawning/SPA-018 - Ground Ops - Randomize Templates/SPA-018 - Ground Ops - Randomize Templates.miz differ diff --git a/SPA - Spawning/SPA-019 - Ground Ops - Randomize Templates without Waypoints/SPA-019 - Ground Ops - Randomize Templates without Waypoints.miz b/SPA - Spawning/SPA-019 - Ground Ops - Randomize Templates without Waypoints/SPA-019 - Ground Ops - Randomize Templates without Waypoints.miz index cc0d07bbb6..f9219b795a 100644 Binary files a/SPA - Spawning/SPA-019 - Ground Ops - Randomize Templates without Waypoints/SPA-019 - Ground Ops - Randomize Templates without Waypoints.miz and b/SPA - Spawning/SPA-019 - Ground Ops - Randomize Templates without Waypoints/SPA-019 - Ground Ops - Randomize Templates without Waypoints.miz differ diff --git a/SPA - Spawning/SPA-020 - Ground Ops - Randomize Templates in Zones no WP/SPA-020 - Ground Ops - Randomize Templates in Zones no WP.miz b/SPA - Spawning/SPA-020 - Ground Ops - Randomize Templates in Zones no WP/SPA-020 - Ground Ops - Randomize Templates in Zones no WP.miz index d71fb6ba3d..1448630e2f 100644 Binary files a/SPA - Spawning/SPA-020 - Ground Ops - Randomize Templates in Zones no WP/SPA-020 - Ground Ops - Randomize Templates in Zones no WP.miz and b/SPA - Spawning/SPA-020 - Ground Ops - Randomize Templates in Zones no WP/SPA-020 - Ground Ops - Randomize Templates in Zones no WP.miz differ diff --git a/SPA - Spawning/SPA-021 - Ground Ops - Scheduled Spawns Limited Keep Unit Names/SPA-021 - Ground Ops - Scheduled Spawns Limited Keep Unit Names.miz b/SPA - Spawning/SPA-021 - Ground Ops - Scheduled Spawns Limited Keep Unit Names/SPA-021 - Ground Ops - Scheduled Spawns Limited Keep Unit Names.miz index eb34fe7264..e1055ca3dc 100644 Binary files a/SPA - Spawning/SPA-021 - Ground Ops - Scheduled Spawns Limited Keep Unit Names/SPA-021 - Ground Ops - Scheduled Spawns Limited Keep Unit Names.miz and b/SPA - Spawning/SPA-021 - Ground Ops - Scheduled Spawns Limited Keep Unit Names/SPA-021 - Ground Ops - Scheduled Spawns Limited Keep Unit Names.miz differ diff --git a/SPA - Spawning/SPA-022 - Ground Ops - Scheduled Spawns Limited with long interval/SPA-022 - Ground Ops - Scheduled Spawns Limited with long interval.miz b/SPA - Spawning/SPA-022 - Ground Ops - Scheduled Spawns Limited with long interval/SPA-022 - Ground Ops - Scheduled Spawns Limited with long interval.miz index 0968b42f4b..da90b53aae 100644 Binary files a/SPA - Spawning/SPA-022 - Ground Ops - Scheduled Spawns Limited with long interval/SPA-022 - Ground Ops - Scheduled Spawns Limited with long interval.miz and b/SPA - Spawning/SPA-022 - Ground Ops - Scheduled Spawns Limited with long interval/SPA-022 - Ground Ops - Scheduled Spawns Limited with long interval.miz differ diff --git a/SPA - Spawning/SPA-023 - Ground Ops - SpawnStart and SpawnStop/SPA-023 - Ground Ops - SpawnStart and SpawnStop.miz b/SPA - Spawning/SPA-023 - Ground Ops - SpawnStart and SpawnStop/SPA-023 - Ground Ops - SpawnStart and SpawnStop.miz index 7cbf04d277..8bff996454 100644 Binary files a/SPA - Spawning/SPA-023 - Ground Ops - SpawnStart and SpawnStop/SPA-023 - Ground Ops - SpawnStart and SpawnStop.miz and b/SPA - Spawning/SPA-023 - Ground Ops - SpawnStart and SpawnStop/SPA-023 - Ground Ops - SpawnStart and SpawnStop.miz differ diff --git a/SPA - Spawning/SPA-024 - Ground Ops - Arrays Normandy/SPA-024 - Ground Ops - Arrays Normandy.miz b/SPA - Spawning/SPA-024 - Ground Ops - Arrays Normandy/SPA-024 - Ground Ops - Arrays Normandy.miz index deeb146ebd..65740974dd 100644 Binary files a/SPA - Spawning/SPA-024 - Ground Ops - Arrays Normandy/SPA-024 - Ground Ops - Arrays Normandy.miz and b/SPA - Spawning/SPA-024 - Ground Ops - Arrays Normandy/SPA-024 - Ground Ops - Arrays Normandy.miz differ diff --git a/SPA - Spawning/SPA-024 - Ground Ops - Arrays Normandy/SPA-024 - Ground Ops - Arrays.lua b/SPA - Spawning/SPA-024 - Ground Ops - Arrays Normandy/SPA-024 - Ground Ops - Arrays.lua new file mode 100644 index 0000000000..1bdb911081 --- /dev/null +++ b/SPA - Spawning/SPA-024 - Ground Ops - Arrays Normandy/SPA-024 - Ground Ops - Arrays.lua @@ -0,0 +1,27 @@ +--- +-- Name: SPA-024 - Ground Ops - Arrays +-- Author: FlightControl +-- Date Created: 19 Jul 2017 +-- +-- # Situation: +-- +-- At Gudauta spawn multiple ground vehicles, in an array. +-- +-- # Test cases: +-- +-- 1. Observe that the ground vehicles are spawned at the position declared within the mission editor. +-- 2. The vehicles should spawn according the array parameters. + + + +-- Tests Gudauta +-- ------------- +Spawn_Vehicle = SPAWN + :New( "Spawn Vehicles" ) + :InitLimit( 12, 60 ) + :InitArray( 90, 10, 10, 10 ) + + + + + diff --git a/SPA - Spawning/SPA-024 - Ground Ops - Arrays/SPA-024 - Ground Ops - Arrays.miz b/SPA - Spawning/SPA-024 - Ground Ops - Arrays/SPA-024 - Ground Ops - Arrays.miz index deeb146ebd..65740974dd 100644 Binary files a/SPA - Spawning/SPA-024 - Ground Ops - Arrays/SPA-024 - Ground Ops - Arrays.miz and b/SPA - Spawning/SPA-024 - Ground Ops - Arrays/SPA-024 - Ground Ops - Arrays.miz differ diff --git a/SPA - Spawning/SPA-025 - Ground Ops - Spawn Hidden/SPA-025 - Ground Ops - Spawn Hidden.miz b/SPA - Spawning/SPA-025 - Ground Ops - Spawn Hidden/SPA-025 - Ground Ops - Spawn Hidden.miz index 6d3d6a5e5c..2c23d84053 100644 Binary files a/SPA - Spawning/SPA-025 - Ground Ops - Spawn Hidden/SPA-025 - Ground Ops - Spawn Hidden.miz and b/SPA - Spawning/SPA-025 - Ground Ops - Spawn Hidden/SPA-025 - Ground Ops - Spawn Hidden.miz differ diff --git a/SPA - Spawning/SPA-026 - Ground Ops - Spawn RandomizeTemplate Hidden/SPA-026 - Ground Ops - Spawn RandomizeTemplate Hidden.miz b/SPA - Spawning/SPA-026 - Ground Ops - Spawn RandomizeTemplate Hidden/SPA-026 - Ground Ops - Spawn RandomizeTemplate Hidden.miz index bcec48297d..0ba0ab0db9 100644 Binary files a/SPA - Spawning/SPA-026 - Ground Ops - Spawn RandomizeTemplate Hidden/SPA-026 - Ground Ops - Spawn RandomizeTemplate Hidden.miz and b/SPA - Spawning/SPA-026 - Ground Ops - Spawn RandomizeTemplate Hidden/SPA-026 - Ground Ops - Spawn RandomizeTemplate Hidden.miz differ diff --git a/SPA - Spawning/SPA-027 - Ground Ops - Respawning After Destroy/SPA-027 - Ground Ops - Respawning After Destroy.miz b/SPA - Spawning/SPA-027 - Ground Ops - Respawning After Destroy/SPA-027 - Ground Ops - Respawning After Destroy.miz index 6a11edeca2..e8b37add61 100644 Binary files a/SPA - Spawning/SPA-027 - Ground Ops - Respawning After Destroy/SPA-027 - Ground Ops - Respawning After Destroy.miz and b/SPA - Spawning/SPA-027 - Ground Ops - Respawning After Destroy/SPA-027 - Ground Ops - Respawning After Destroy.miz differ diff --git a/SPA - Spawning/SPA-100 - Air Ops - CleanUp of Inactive Units/SPA-100 - Air Ops - Scheduled Spawn Helicopters with CleanUp of Inactive Units.lua b/SPA - Spawning/SPA-100 - Air Ops - CleanUp of Inactive Units/SPA-100 - Air Ops - Scheduled Spawn Helicopters with CleanUp of Inactive Units.lua new file mode 100644 index 0000000000..0d07b33fc1 --- /dev/null +++ b/SPA - Spawning/SPA-100 - Air Ops - CleanUp of Inactive Units/SPA-100 - Air Ops - Scheduled Spawn Helicopters with CleanUp of Inactive Units.lua @@ -0,0 +1,8 @@ +-- Tests Kutaisi +-- ------------- +-- Tests the CleanUp functionality. +-- Limited spawning of groups, scheduled every 10 seconds, who are engaging into combat. Some helicopters may crash land on the ground. +-- Observe when helicopters land but are not dead and are out of the danger zone, that they get removed after a while (+/- 180 seconds) and ReSpawn. +Spawn_Helicopter_Scheduled_CleanUp = SPAWN:New( "Spawn Helicopter Scheduled CleanUp" ):InitLimit( 3, 100 ):InitRandomizeRoute( 1, 1, 1000 ):InitCleanUp( 60 ):SpawnScheduled( 10, 0 ) +Spawn_Vehicle_Scheduled_CleanUp = SPAWN:New( "Spawn Vehicle Scheduled CleanUp" ):InitLimit( 3, 100 ):InitRandomizeRoute( 1, 1, 1000 ):SpawnScheduled( 10, 0 ) + diff --git a/SPA - Spawning/SPA-110 - Limit Spawning/SPA-110 - Limit Spawning.miz b/SPA - Spawning/SPA-110 - Limit Spawning/SPA-110 - Limit Spawning.miz index 1c6240d090..5e75507a13 100644 Binary files a/SPA - Spawning/SPA-110 - Limit Spawning/SPA-110 - Limit Spawning.miz and b/SPA - Spawning/SPA-110 - Limit Spawning/SPA-110 - Limit Spawning.miz differ diff --git a/SPA - Spawning/SPA-124 - Air Ops - Scheduled Spawns with OnSpawnGroup/SPA-124 - Air Ops - Scheduled Spawns with Escort Task.lua b/SPA - Spawning/SPA-124 - Air Ops - Scheduled Spawns with OnSpawnGroup/SPA-124 - Air Ops - Scheduled Spawns with Escort Task.lua new file mode 100644 index 0000000000..74616be005 --- /dev/null +++ b/SPA - Spawning/SPA-124 - Air Ops - Scheduled Spawns with OnSpawnGroup/SPA-124 - Air Ops - Scheduled Spawns with Escort Task.lua @@ -0,0 +1,52 @@ +---------------------------------------------------------------------- +--SPA-124 - Air Ops - Scheduled Spawns with OnSpawnGroup() Escort Task +---------------------------------------------------------------------- + --////////////////////////////////// + --////////////Tankers and awacs v1 + --////////////////////////////////// +--////////// By Targs35 ///////////// +--//////////////// from 62nd Air Wing, Brisbane server.. +--/////////////////////////////////// + ------- With thanks to the guys at MOOSE and in particular Pikes, Nolove, Delta99 and Wingthor + -- Funky Frank is the man.. +-----//////////////////////////////// +--/////////// Spawn Tanker and Escorts /// + + do + + local PointVec1 = POINT_VEC3:New( -100, 20, 80 ) -- This is a Vec3 class - defines the position of the escorts relative to the escorted group + local PointVec2 = POINT_VEC3:New( -100, 20, 150 ) -- This is a Vec3 class - defines the position of the escorts relative to the escorted group + + --Create Spawn Groups, use the OnSpawnGroup() function to spawn two escorts and task them + + local Tanker_Texaco = SPAWN + :New("Tanker_Texaco_Droge") + :InitLimit( 1, 2 ) -- group with one unit, spawn 1 *alive* units max + :InitCleanUp( 240 ) + :OnSpawnGroup(function (tanker) -- tanker contains the GROUP object when the tanker spawns + local Escort_Texaco_1 = SPAWN + :New("Escort_Texaco_F14 001") + :InitLimit( 1, 2 ) + :InitCleanUp( 240 ) + :OnSpawnGroup(function (spawndgroup) -- spawndgrp contains the GROUP object when the escort spawns + local FollowDCSTask1 = spawndgroup:TaskFollow( tanker, PointVec1 ) -- create task + spawndgroup:SetTask( FollowDCSTask1, 1 ) -- push task on the GROUP + end + ) + :SpawnScheduled( 60, 0.5 ) + + local Escort_Texaco_2 = SPAWN + :New("Escort_Texaco_F14 002") + :InitLimit( 1, 2 ) + :InitCleanUp( 240 ) + :OnSpawnGroup(function (spawndgroup) -- spawndgrp contains the GROUP object when the escort spawns + local FollowDCSTask2 = spawndgroup:TaskFollow( tanker, PointVec2 ) + spawndgroup:SetTask( FollowDCSTask2, 1 ) + end + ) + :SpawnScheduled( 60, 0.5 ) + end + ) + :SpawnScheduled( 60, 0.5 ) + +end diff --git a/SPA - Spawning/SPA-131 - Air Ops - SpawnAtAirbase/SPA-131 - Air Ops - Nevada - SpawnAtAirbase.lua b/SPA - Spawning/SPA-131 - Air Ops - SpawnAtAirbase/SPA-131 - Air Ops - Nevada - SpawnAtAirbase.lua index b7b1df3a94..13f670b4ca 100644 --- a/SPA - Spawning/SPA-131 - Air Ops - SpawnAtAirbase/SPA-131 - Air Ops - Nevada - SpawnAtAirbase.lua +++ b/SPA - Spawning/SPA-131 - Air Ops - SpawnAtAirbase/SPA-131 - Air Ops - Nevada - SpawnAtAirbase.lua @@ -1,11 +1,11 @@ --- Name: SPA-131 - Air Ops - SpawnAtAirbase --- Author: FlightControl --- Date Created: 14 Sep 2017 --- -Spawn_Plane = SPAWN:New( "Plane" ) -Spawn_Plane:SpawnAtAirbase( AIRBASE:FindByName( AIRBASE.Nevada.Groom_Lake_AFB ), SPAWN.Takeoff.Cold ) -Spawn_Plane:SpawnAtAirbase( AIRBASE:FindByName( AIRBASE.Nevada.Groom_Lake_AFB ), SPAWN.Takeoff.Hot ) -Spawn_Plane:SpawnAtAirbase( AIRBASE:FindByName( AIRBASE.Nevada.Groom_Lake_AFB ), SPAWN.Takeoff.Runway ) - - - +-- Name: SPA-131 - Air Ops - SpawnAtAirbase +-- Author: FlightControl +-- Date Created: 14 Sep 2017 +-- +Spawn_Plane = SPAWN:New( "Plane" ) +Spawn_Plane:SpawnAtAirbase( AIRBASE:FindByName( AIRBASE.Nevada.Groom_Lake_AFB ), SPAWN.Takeoff.Cold ) +Spawn_Plane:SpawnAtAirbase( AIRBASE:FindByName( AIRBASE.Nevada.Groom_Lake_AFB ), SPAWN.Takeoff.Hot ) +Spawn_Plane:SpawnAtAirbase( AIRBASE:FindByName( AIRBASE.Nevada.Groom_Lake_AFB ), SPAWN.Takeoff.Runway ) + + + diff --git a/SPA - Spawning/SPA-200 - Randomize Unit Types/SPA-200 - Randomize Unit Types.miz b/SPA - Spawning/SPA-200 - Randomize Unit Types/SPA-200 - Randomize Unit Types.miz index e63551eb32..ea85619254 100644 Binary files a/SPA - Spawning/SPA-200 - Randomize Unit Types/SPA-200 - Randomize Unit Types.miz and b/SPA - Spawning/SPA-200 - Randomize Unit Types/SPA-200 - Randomize Unit Types.miz differ diff --git a/SPA - Spawning/SPA-220 - Randomize Zones/SPA-220 - Randomize Zones.miz b/SPA - Spawning/SPA-220 - Randomize Zones/SPA-220 - Randomize Zones.miz index 4a17e8ba64..3407e2af56 100644 Binary files a/SPA - Spawning/SPA-220 - Randomize Zones/SPA-220 - Randomize Zones.miz and b/SPA - Spawning/SPA-220 - Randomize Zones/SPA-220 - Randomize Zones.miz differ diff --git a/SPA - Spawning/SPA-350 - Spawn at Vec3 position RandomizePosition/SPA-350 - Spawn at Vec3 position RandomzePosition.lua b/SPA - Spawning/SPA-350 - Spawn at Vec3 position RandomizePosition/SPA-350 - Spawn at Vec3 position RandomzePosition.lua new file mode 100644 index 0000000000..3122b26dda --- /dev/null +++ b/SPA - Spawning/SPA-350 - Spawn at Vec3 position RandomizePosition/SPA-350 - Spawn at Vec3 position RandomzePosition.lua @@ -0,0 +1,73 @@ +--- +-- Name: SPA-350 - Spawn at Vec3 position RandomzePosition +-- Author: FlightControl +-- Date Created: 14 Mar 2017 +-- +-- # Situation: +-- +-- Ground troops, Airplanes, Helicopters and Ships are spawning from Vec3 points. +-- The API InitRandomizePosition is tested here, ensure that groups are replaced within a 900 to 1000 zone band at random positions. +-- +-- # Test cases: +-- +-- 1. Observe the random positioning of the groups. There should be no scattering of units. +-- + +local Iterations = 10 +local Iteration = 1 + +GroundZones = { "GroundZone1", "GroundZone2", "GroundZone3" } +GroundRandomizeZones = { "GroundRandomizeZone1", "GroundRandomizeZone2", "GroundRandomizeZone3" } +AirplaneZones = { "AirplaneZone1", "AirplaneZone2", "AirplaneZone3" } +HelicopterZones = { "HelicopterZone1", "HelicopterZone2", "HelicopterZone3" } +ShipZones = { "ShipZone1", "ShipZone2", "ShipZone3" } + +HeightLimit = 500 + +SpawnGrounds = SPAWN:New("Ground"):InitLimit( 20, 10 ):InitRandomizePosition( true , 1000, 900 ) +SpawnRandomizeGrounds = SPAWN:New("GroundRandomize"):InitLimit( 20, 10 ):InitRandomizePosition( true , 1000, 900 ) +SpawnAirplanes = SPAWN:New("Airplane"):InitLimit( 20, 10 ):InitRandomizePosition( true , 1000, 900 ) +SpawnHelicopters = SPAWN:New("Helicopter"):InitLimit( 20, 10 ):InitRandomizePosition( true , 1000, 900 ) +SpawnShips = SPAWN:New("Ship"):InitLimit( 20, 10 ):InitRandomizePosition( true , 1000, 900 ) + +--- Spawns these groups slowly. +SCHEDULER:New( nil, + + function( Interation, Iterations ) + do + -- Spawn Ground + local ZoneName = GroundZones[ math.random( 1, 3 ) ] + local SpawnVec3 = POINT_VEC3:NewFromVec3( ZONE:New( ZoneName ):GetVec3() ) + SpawnGrounds:SpawnFromVec3( SpawnVec3:GetVec3() ) + end + + do + -- Spawn Ground Randomize + local ZoneName = GroundRandomizeZones[ math.random( 1, 3 ) ] + local SpawnVec3 = POINT_VEC3:NewFromVec3( ZONE:New( ZoneName ):GetVec3() ) + SpawnRandomizeGrounds:SpawnFromVec3( SpawnVec3:GetVec3() ) + end + + do + -- Spawn Airplanes + local ZoneName = AirplaneZones[ math.random( 1, 3 ) ] + local SpawnVec3 = POINT_VEC3:NewFromVec3( ZONE:New( ZoneName ):GetVec3() ) + SpawnAirplanes:SpawnFromVec3( SpawnVec3:GetVec3() ) + end + + do + -- Spawn Helicopters + local ZoneName = HelicopterZones[ math.random( 1, 3 ) ] + local SpawnVec3 = POINT_VEC3:NewFromVec3( ZONE:New( ZoneName ):GetVec3() ) + SpawnHelicopters:SpawnFromVec3( SpawnVec3:GetVec3() ) + end + + do + -- Spawn Ships + local ZoneName = ShipZones[ math.random( 1, 3 ) ] + local SpawnVec3 = POINT_VEC3:NewFromVec3( ZONE:New( ZoneName ):GetVec3() ) + SpawnShips:SpawnFromVec3( SpawnVec3:GetVec3() ) + end + + end, {}, 0, 15, 0.5 +) diff --git a/SPS - Spawning Statics/SPS-100 - Simple Spawning/SPS-100 - Simple Spawning.miz b/SPS - Spawning Statics/SPS-100 - Simple Spawning/SPS-100 - Simple Spawning.miz index 2b21308d86..de7aedd39c 100644 Binary files a/SPS - Spawning Statics/SPS-100 - Simple Spawning/SPS-100 - Simple Spawning.miz and b/SPS - Spawning Statics/SPS-100 - Simple Spawning/SPS-100 - Simple Spawning.miz differ diff --git a/TAD - Task Dispatching/A2G - Air 2 Ground Task Dispatching/TAD-A2G-100 - TYPES - Detection Test/TAD-A2G-100 - TYPES - Detection test.lua b/TAD - Task Dispatching/A2G - Air 2 Ground Task Dispatching/TAD-A2G-100 - TYPES - Detection Test/TAD-A2G-100 - TYPES - Detection test.lua new file mode 100644 index 0000000000..f3c3bb7f5d --- /dev/null +++ b/TAD - Task Dispatching/A2G - Air 2 Ground Task Dispatching/TAD-A2G-100 - TYPES - Detection Test/TAD-A2G-100 - TYPES - Detection test.lua @@ -0,0 +1,51 @@ + --- +-- Name: TAD-A2G-100 - TYPES - Detection Test +-- Author: FlightControl +-- Date Created: 15 Mar 2018 +-- +-- # Situation: +-- +-- This mission demonstrates the dynamic task dispatching for Air to Ground operations. +-- Reconnassance vehicles are placed at strategic locations, scanning for the enemy locations. +-- The detection method used is the DETECTION_TYPES method, which groups detected targets into Unit Types that were detected. +-- The AttackSet will engage upon the enemy, which is a Set of Groups seated by Players. +-- A2G Tasks are being dispatched to the Players as enemy locations are being detected by the Recce. +-- Observe that A2G Tasks are being dispatched to the player. + + +-- Declare the Command Center +local HQ = GROUP + :FindByName( "HQ", "Bravo HQ" ) + +local CommandCenter = COMMANDCENTER + :New( HQ, "Lima" ) -- Create the CommandCenter. + +-- Declare the Mission for the Command Center. +local Mission = MISSION + :New( CommandCenter, "Overlord", "High", "Attack Detect Mission Briefing", coalition.side.RED ) -- Create the Mission. + +-- Define the RecceSet that will detect the enemy. +local RecceSet = SET_GROUP + :New() -- Create the RecceSet, which is the set of groups detecting the enemy locations. + :FilterPrefixes( "Recce" ) -- All Recce groups start with the name "Recce". + :FilterCoalitions("red") -- only the red coalition. + :FilterStart() -- Start the dynamic building of the set. + +-- Setup the detection. We use DETECTION_AREAS to detect and group the enemies. +local DetectionAreas = DETECTION_TYPES + :New( RecceSet ) -- The RecceSet will detect the enemies, and group them into unit types that were detected. + +-- Setup the AttackSet, which is a SET_GROUP. +-- The SET_GROUP is a dynamic collection of GROUP objects. +local AttackSet = SET_GROUP + :New() -- Create the SET_GROUP object. + :FilterCoalitions( "red" ) -- Only incorporate the RED coalitions. + :FilterPrefixes( "Attack" ) -- Only incorporate groups that start with the name Attack. + :FilterStart() -- Start the dynamic building of the set. + +-- Now we have everything to setup the main A2G TaskDispatcher. +TaskDispatcher = TASK_A2G_DISPATCHER + :New( Mission, AttackSet, DetectionAreas ) -- We assign the TaskDispatcher under Mission. The AttackSet will engage the enemy and will recieve the dispatched Tasks. The DetectionAreas will report any detected enemies to the TaskDispatcher. + +-- We use the MISSILETRAINER for demonstration purposes. +MissileTrainer = MISSILETRAINER:New( 100, "Missiles will be destroyed for training when they reach your plane." ) diff --git a/TAD - Task Dispatching/A2G - Air 2 Ground Task Dispatching/TAD-A2G-110 - TYPES - Detection Test/TAD-110 - A2G Task Dispatching DETECTION_TYPES.lua b/TAD - Task Dispatching/A2G - Air 2 Ground Task Dispatching/TAD-A2G-110 - TYPES - Detection Test/TAD-110 - A2G Task Dispatching DETECTION_TYPES.lua new file mode 100644 index 0000000000..96f1c2f1bc --- /dev/null +++ b/TAD - Task Dispatching/A2G - Air 2 Ground Task Dispatching/TAD-A2G-110 - TYPES - Detection Test/TAD-110 - A2G Task Dispatching DETECTION_TYPES.lua @@ -0,0 +1,35 @@ + --- +-- Name: TAD-100 - A2G Task Dispatching DETECTION_AREAS +-- Author: FlightControl +-- Date Created: 06 Mar 2017 +-- +-- # Situation: +-- +-- This mission demonstrates the dynamic task dispatching for Air to Ground operations. +-- FACA's and FAC's are patrolling around the battle zone, while detecting targets. +-- The detection method used is the DETECTION_AREAS method, which groups detected targets into zones. +-- +-- # Test cases: +-- +-- 1. Observe the FAC(A)'s detecting targets and grouping them. +-- For test, each zone will have a circle of tyres, that are visible on the map too. +-- 2. Check that the HQ provides menus to engage on a task set by the FACs. +-- +local HQ = GROUP:FindByName( "HQ", "Bravo HQ" ) + +local CommandCenter = COMMANDCENTER:New( HQ, "Lima" ) + +local Scoring = SCORING:New( "Detect Demo" ) + +local Mission = MISSION + :New( CommandCenter, "Overlord", "High", "Attack Detect Mission Briefing", coalition.side.RED ) + :AddScoring( Scoring ) + +local FACSet = SET_GROUP:New():FilterPrefixes( "FAC" ):FilterCoalitions("red"):FilterStart() + +local FACAreas = DETECTION_TYPES:New( FACSet ) + + +local AttackGroups = SET_GROUP:New():FilterCoalitions( "red" ):FilterPrefixes( "Attack" ):FilterStart() +TaskDispatcher = TASK_A2G_DISPATCHER:New( Mission, AttackGroups, FACAreas ) + diff --git a/TAD - Task Dispatching/A2G - Air 2 Ground Task Dispatching/TAD-A2G-120 - TYPES - Scoring/TAD-220 - A2G Task Dispatching per TYPE and SCORING.lua b/TAD - Task Dispatching/A2G - Air 2 Ground Task Dispatching/TAD-A2G-120 - TYPES - Scoring/TAD-220 - A2G Task Dispatching per TYPE and SCORING.lua new file mode 100644 index 0000000000..2be6e06deb --- /dev/null +++ b/TAD - Task Dispatching/A2G - Air 2 Ground Task Dispatching/TAD-A2G-120 - TYPES - Scoring/TAD-220 - A2G Task Dispatching per TYPE and SCORING.lua @@ -0,0 +1,64 @@ +--- +-- Name: TAD-220 - A2G Task Dispatching per TYPE and SCORING +-- Author: FlightControl +-- Date Created: 20 Mar 2017 +-- +-- # Situation: +-- +-- This mission demonstrates the scoring of dynamic task dispatching for Air to Ground operations. +-- +-- # Test cases: +-- +-- 1. Observe the FAC(A)'s detecting targets and grouping them. +-- 2. Check that the HQ provides menus to engage on a task set by the FACs. +-- 3. Engage on a task and destroy a target. Check if scoring is given for that target. +-- 4. Engage all targets in the task, and check if mission success is achieved and that a scoring is given. +-- 5. Restart the mission, and crash into the ground, check if you can get penalties. +-- +local HQ = GROUP:FindByName( "HQ", "Bravo HQ" ) + +local CommandCenter = COMMANDCENTER:New( HQ, "Lima" ) + +local Scoring = SCORING:New( "Detect Demo" ) + +local Mission = MISSION + :New( CommandCenter, "Overlord", "High", "Attack Detect Mission Briefing", coalition.side.RED ) + :AddScoring( Scoring ) + +local FACSet = SET_GROUP:New():FilterPrefixes( "FAC" ):FilterCoalitions("red"):FilterStart() + +local DetectionTypes = DETECTION_TYPES:New( FACSet ) + +local AttackGroups = SET_GROUP:New():FilterCoalitions( "red" ):FilterPrefixes( "Attack" ):FilterStart() + +TaskDispatcher = TASK_A2G_DISPATCHER:New( Mission, AttackGroups, DetectionTypes ) + +--- @param #TaskDispatcher self +-- @param From +-- @param Event +-- @param To +-- @param Tasking.Task_A2G#TASK_A2G Task +-- @param Wrapper.Unit#UNIT TaskUnit +-- @param #string PlayerName +function TaskDispatcher:OnAfterAssign( From, Event, To, Task, TaskUnit, PlayerName ) + self:E( "I am in assigned ... " ) + Task:SetScoreOnProgress( "Player " .. PlayerName .. " destroyed a target", 50, TaskUnit ) + Task:SetScoreOnSuccess( "The task has been successfully completed!", 200, TaskUnit ) + Task:SetScoreOnFail( "The task has failed completion!", 100, TaskUnit ) +end + +-- Now this is REALLY neat. I set the goal of the mission to be the destruction of Target #004. +-- This is just an example, but many more examples can follow... + +-- Every time a Task becomes Successful, it will trigger the Complete event in the Mission. +-- The mission designer NEED TO OVERRIDE the OnBeforeComplete to prevent the mission from getting into completion +-- too early! + +function Mission:OnBeforeComplete( From, Event, To ) + local Group004 = GROUP:FindByName( "Target #004" ) + if Group004:IsAlive() == false then + Mission:GetCommandCenter():MessageToCoalition( "Mission Complete!" ) + return true + end + return false +end \ No newline at end of file diff --git a/TAD - Task Dispatching/A2G - Air 2 Ground Task Dispatching/TAD-A2G-210 - UNITS - Detection Test/TAD-120 - A2G Task Dispatching DETECTION_UNITS.lua b/TAD - Task Dispatching/A2G - Air 2 Ground Task Dispatching/TAD-A2G-210 - UNITS - Detection Test/TAD-120 - A2G Task Dispatching DETECTION_UNITS.lua new file mode 100644 index 0000000000..6049e078f5 --- /dev/null +++ b/TAD - Task Dispatching/A2G - Air 2 Ground Task Dispatching/TAD-A2G-210 - UNITS - Detection Test/TAD-120 - A2G Task Dispatching DETECTION_UNITS.lua @@ -0,0 +1,50 @@ +--- +-- Name: TAD-120 - A2G Task Dispatching DETECTION_UNITS +-- Author: FlightControl +-- Date Created: 13 Mar 2017 +-- +-- # Situation: +-- +-- This mission demonstrates the dynamic task dispatching for Air to Ground operations. +-- FACA's and FAC's are patrolling around the battle field, while detecting targets. +-- The detection method used is the DETECTION_UNITS method, which groups detected targets per detected unit. +-- +-- # Test cases: +-- +-- 1. Observe the FAC(A)'s detecting targets and grouping them. +-- 2. Check that the HQ provides menus to engage on a task set by the FACs. +-- +local HQ = GROUP:FindByName( "HQ", "Bravo HQ" ) + +local CommandCenter = COMMANDCENTER:New( HQ, "Lima" ) + +local Scoring = SCORING:New( "Detect Demo" ) + +local Mission = MISSION + :New( CommandCenter, "Overlord", "High", "Attack Detect Mission Briefing", coalition.side.RED ) + :AddScoring( Scoring ) + +local FACSet = SET_GROUP:New():FilterPrefixes( "FAC" ):FilterCoalitions("red"):FilterStart() + +local FACAreas = DETECTION_UNITS:New( FACSet ) + + +local AttackGroups = SET_GROUP:New():FilterCoalitions( "red" ):FilterPrefixes( "Attack" ):FilterStart() + +TaskDispatcher = TASK_A2G_DISPATCHER:New( Mission, AttackGroups, FACAreas ) + +-- Now this is REALLY neat. I set the goal of the mission to be the destruction of Target #004. +-- This is just an example, but many more examples can follow... + +-- Every time a Task becomes Successful, it will trigger the Complete event in the Mission. +-- The mission designer NEED TO OVERRIDE the OnBeforeComplete to prevent the mission from getting into completion +-- too early! + +function Mission:OnBeforeComplete( From, Event, To ) + local Group004 = GROUP:FindByName( "Target #004" ) + if Group004:IsAlive() == false then + Mission:GetCommandCenter():MessageToCoalition( "Mission Complete!" ) + return true + end + return false +end \ No newline at end of file diff --git a/TAD - Task Dispatching/A2G - Air 2 Ground Task Dispatching/TAD-A2G-220 - UNITS - Scoring/TAD-200 - A2G Task Dispatching with SCORING.lua b/TAD - Task Dispatching/A2G - Air 2 Ground Task Dispatching/TAD-A2G-220 - UNITS - Scoring/TAD-200 - A2G Task Dispatching with SCORING.lua new file mode 100644 index 0000000000..b29d3e07f6 --- /dev/null +++ b/TAD - Task Dispatching/A2G - Air 2 Ground Task Dispatching/TAD-A2G-220 - UNITS - Scoring/TAD-200 - A2G Task Dispatching with SCORING.lua @@ -0,0 +1,64 @@ +--- +-- Name: TAD-200 - A2G Task Dispatching with SCORING +-- Author: FlightControl +-- Date Created: 19 Mar 2017 +-- +-- # Situation: +-- +-- This mission demonstrates the scoring of dynamic task dispatching for Air to Ground operations. +-- +-- # Test cases: +-- +-- 1. Observe the FAC(A)'s detecting targets and grouping them. +-- 2. Check that the HQ provides menus to engage on a task set by the FACs. +-- 3. Engage on a task and destroy a target. Check if scoring is given for that target. +-- 4. Engage all targets in the task, and check if mission success is achieved and that a scoring is given. +-- 5. Restart the mission, and crash into the ground, check if you can get penalties. +-- +local HQ = GROUP:FindByName( "HQ", "Bravo HQ" ) + +local CommandCenter = COMMANDCENTER:New( HQ, "Lima" ) + +local Scoring = SCORING:New( "Detect Demo" ) + +local Mission = MISSION + :New( CommandCenter, "Overlord", "High", "Attack Detect Mission Briefing", coalition.side.RED ) + :AddScoring( Scoring ) + +local FACSet = SET_GROUP:New():FilterPrefixes( "FAC" ):FilterCoalitions("red"):FilterStart() + +local FACAreas = DETECTION_UNITS:New( FACSet ) + + +local AttackGroups = SET_GROUP:New():FilterCoalitions( "red" ):FilterPrefixes( "Attack" ):FilterStart() + +TaskDispatcher = TASK_A2G_DISPATCHER:New( Mission, AttackGroups, FACAreas ) + +--- @param #TaskDispatcher self +-- @param From +-- @param Event +-- @param To +-- @param Tasking.Task_A2G#TASK_A2G Task +-- @param Wrapper.Unit#UNIT TaskUnit +-- @param #string PlayerName +function TaskDispatcher:OnAfterAssign( From, Event, To, Task, TaskUnit, PlayerName ) + Task:SetScoreOnProgress( "Player " .. PlayerName .. " destroyed a target", 20, TaskUnit ) + Task:SetScoreOnSuccess( "The task has been successfully completed!", 200, TaskUnit ) + Task:SetScoreOnFail( "The task has failed completion!", -100, TaskUnit ) +end + +-- Now this is REALLY neat. I set the goal of the mission to be the destruction of Target #004. +-- This is just an example, but many more examples can follow... + +-- Every time a Task becomes Successful, it will trigger the Complete event in the Mission. +-- The mission designer NEED TO OVERRIDE the OnBeforeComplete to prevent the mission from getting into completion +-- too early! + +function Mission:OnBeforeComplete( From, Event, To ) + local Group004 = GROUP:FindByName( "Target #004" ) + if Group004:IsAlive() == false then + Mission:GetCommandCenter():MessageToCoalition( "Mission Complete!" ) + return true + end + return false +end \ No newline at end of file diff --git a/TAD - Task Dispatching/A2G - Air 2 Ground Task Dispatching/TAD-A2G-320 - AREAS - Scoring/TAD-210 - A2G Task Dispatching #1 for AREAS and SCORING.lua b/TAD - Task Dispatching/A2G - Air 2 Ground Task Dispatching/TAD-A2G-320 - AREAS - Scoring/TAD-210 - A2G Task Dispatching #1 for AREAS and SCORING.lua new file mode 100644 index 0000000000..74af4620db --- /dev/null +++ b/TAD - Task Dispatching/A2G - Air 2 Ground Task Dispatching/TAD-A2G-320 - AREAS - Scoring/TAD-210 - A2G Task Dispatching #1 for AREAS and SCORING.lua @@ -0,0 +1,65 @@ +--- +-- Name: TAD-210 - A2G Task Dispatching #1 for AREAS and SCORING +-- Author: FlightControl +-- Date Created: 19 Mar 2017 +-- +-- # Situation: +-- +-- This mission demonstrates the scoring of dynamic task dispatching for Air to Ground operations. +-- +-- # Test cases: +-- +-- 1. Observe the FAC(A)'s detecting targets and grouping them. +-- 2. Check that the HQ provides menus to engage on a task set by the FACs. +-- 3. Engage on a task and destroy a target. Check if scoring is given for that target. +-- 4. Engage all targets in the task, and check if mission success is achieved and that a scoring is given. +-- 5. Restart the mission, and crash into the ground, check if you can get penalties. +-- +local HQ = GROUP:FindByName( "HQ", "Bravo HQ" ) + +local CommandCenter = COMMANDCENTER:New( HQ, "Lima" ) + +local Scoring = SCORING:New( "Detect Demo" ) + +local Mission = MISSION + :New( CommandCenter, "Overlord", "High", "Attack Detect Mission Briefing", coalition.side.RED ) + :AddScoring( Scoring ) + +local FACSet = SET_GROUP:New():FilterPrefixes( "FAC" ):FilterCoalitions("red"):FilterStart() + +local FACAreas = DETECTION_AREAS:New( FACSet, 400 ) +FACAreas:BoundDetectedZones() + + +local AttackGroups = SET_GROUP:New():FilterCoalitions( "red" ):FilterPrefixes( "Attack" ):FilterStart() + +TaskDispatcher = TASK_A2G_DISPATCHER:New( Mission, AttackGroups, FACAreas ) + +--- @param #TaskDispatcher self +-- @param From +-- @param Event +-- @param To +-- @param Tasking.Task_A2G#TASK_A2G Task +-- @param Wrapper.Unit#UNIT TaskUnit +-- @param #string PlayerName +function TaskDispatcher:OnAfterAssign( From, Event, To, Task, TaskUnit, PlayerName ) + Task:SetScoreOnDestroy( "Player " .. PlayerName .. " destroyed a target", 20, TaskUnit ) + Task:SetScoreOnSuccess( "The task has been successfully completed!", 200, TaskUnit ) + Task:SetPenaltyOnFailed( "The task has failed completion!", -100, TaskUnit ) +end + +-- Now this is REALLY neat. I set the goal of the mission to be the destruction of Target #004. +-- This is just an example, but many more examples can follow... + +-- Every time a Task becomes Successful, it will trigger the Complete event in the Mission. +-- The mission designer NEED TO OVERRIDE the OnBeforeComplete to prevent the mission from getting into completion +-- too early! + +function Mission:OnBeforeComplete( From, Event, To ) + local Group004 = GROUP:FindByName( "Target #004" ) + if Group004:IsAlive() == false then + Mission:GetCommandCenter():MessageToCoalition( "Mission Complete!" ) + return true + end + return false +end \ No newline at end of file diff --git a/TAD - Task Dispatching/A2G - Air 2 Ground Task Dispatching/TAD-A2G-320 - AREAS - Scoring/TAD-210 - A2G Task Dispatching per AREAS and SCORING.lua b/TAD - Task Dispatching/A2G - Air 2 Ground Task Dispatching/TAD-A2G-320 - AREAS - Scoring/TAD-210 - A2G Task Dispatching per AREAS and SCORING.lua new file mode 100644 index 0000000000..f0f5fa30b3 --- /dev/null +++ b/TAD - Task Dispatching/A2G - Air 2 Ground Task Dispatching/TAD-A2G-320 - AREAS - Scoring/TAD-210 - A2G Task Dispatching per AREAS and SCORING.lua @@ -0,0 +1,65 @@ +--- +-- Name: TAD-210 - A2G Task Dispatching for AREAS and SCORING +-- Author: FlightControl +-- Date Created: 19 Mar 2017 +-- +-- # Situation: +-- +-- This mission demonstrates the scoring of dynamic task dispatching for Air to Ground operations. +-- +-- # Test cases: +-- +-- 1. Observe the FAC(A)'s detecting targets and grouping them. +-- 2. Check that the HQ provides menus to engage on a task set by the FACs. +-- 3. Engage on a task and destroy a target. Check if scoring is given for that target. +-- 4. Engage all targets in the task, and check if mission success is achieved and that a scoring is given. +-- 5. Restart the mission, and crash into the ground, check if you can get penalties. +-- +local HQ = GROUP:FindByName( "HQ", "Bravo HQ" ) + +local CommandCenter = COMMANDCENTER:New( HQ, "Lima" ) + +local Scoring = SCORING:New( "Detect Demo" ) + +local Mission = MISSION + :New( CommandCenter, "Overlord", "High", "Attack Detect Mission Briefing", coalition.side.RED ) + :AddScoring( Scoring ) + +local FACSet = SET_GROUP:New():FilterPrefixes( "FAC" ):FilterCoalitions("red"):FilterStart() + +local FACAreas = DETECTION_AREAS:New( FACSet, 400 ) +FACAreas:BoundDetectedZones() + + +local AttackGroups = SET_GROUP:New():FilterCoalitions( "red" ):FilterPrefixes( "Attack" ):FilterStart() + +TaskDispatcher = TASK_A2G_DISPATCHER:New( Mission, AttackGroups, FACAreas ) + +--- @param #TaskDispatcher self +-- @param From +-- @param Event +-- @param To +-- @param Tasking.Task_A2G#TASK_A2G Task +-- @param Wrapper.Unit#UNIT TaskUnit +-- @param #string PlayerName +function TaskDispatcher:OnAfterAssign( From, Event, To, Task, TaskUnit, PlayerName ) + Task:SetScoreOnProgress( "Player " .. PlayerName .. " destroyed a target", 20, TaskUnit ) + Task:SetScoreOnSuccess( "The task has been successfully completed!", 200, TaskUnit ) + Task:SetScoreOnFail( "The task has failed completion!", -100, TaskUnit ) +end + +-- Now this is REALLY neat. I set the goal of the mission to be the destruction of Target #004. +-- This is just an example, but many more examples can follow... + +-- Every time a Task becomes Successful, it will trigger the Complete event in the Mission. +-- The mission designer NEED TO OVERRIDE the OnBeforeComplete to prevent the mission from getting into completion +-- too early! + +function Mission:OnBeforeComplete( From, Event, To ) + local Group004 = GROUP:FindByName( "Target #004" ) + if Group004:IsAlive() == false then + Mission:GetCommandCenter():MessageToCoalition( "Mission Complete!" ) + return true + end + return false +end \ No newline at end of file diff --git a/TAD - Task Dispatching/A2G - Air 2 Ground Task Dispatching/TAD-A2G-601 - ZONES - Destroy/TAD-A2G-001 - AREAS - Destroy Test.lua b/TAD - Task Dispatching/A2G - Air 2 Ground Task Dispatching/TAD-A2G-601 - ZONES - Destroy/TAD-A2G-001 - AREAS - Destroy Test.lua new file mode 100644 index 0000000000..e727a85123 --- /dev/null +++ b/TAD - Task Dispatching/A2G - Air 2 Ground Task Dispatching/TAD-A2G-601 - ZONES - Destroy/TAD-A2G-001 - AREAS - Destroy Test.lua @@ -0,0 +1,52 @@ + --- +-- Name: TAD-A2G-001 - AREAS - Destroy Test +-- Author: FlightControl +-- Date Created: 15 Mar 2018 +-- +-- This mission demonstrates the dynamic task dispatching for Air to Ground operations. +-- Reconnassance vehicles are placed at strategic locations, scanning for the enemy locations. +-- The detection method used is the DETECTION_AREAS method, which groups detected targets into areas. +-- The AttackSet will engage upon the enemy, which is a Set of Groups seated by Players. +-- A2G Tasks are being dispatched to the Players as enemy locations are being detected by the Recce. +-- Observe that A2G Tasks are being dispatched to the player. +-- Get seated in the Attack Plane, there is also an AI with you, who will attack the ground targets. +-- Join the A2G Task that was dispatched to you. +-- Once the AI in your group destroys the target, you should see that the A2G task got success. + + +-- Declare the Command Center +local HQ = GROUP + :FindByName( "HQ", "Bravo HQ" ) + +local CommandCenter = COMMANDCENTER + :New( HQ, "Lima" ) -- Create the CommandCenter. + +-- Declare the Mission for the Command Center. +local Mission = MISSION + :New( CommandCenter, "Overlord", "High", "Attack Detect Mission Briefing", coalition.side.RED ) -- Create the Mission. + +-- Define the RecceSet that will detect the enemy. +local RecceSet = SET_GROUP + :New() -- Create the RecceSet, which is the set of groups detecting the enemy locations. + :FilterPrefixes( "Recce" ) -- All Recce groups start with the name "Recce". + :FilterCoalitions("red") -- only the red coalition. + :FilterStart() -- Start the dynamic building of the set. + +-- Setup the detection. We use DETECTION_AREAS to detect and group the enemies. +local DetectionAreas = DETECTION_AREAS + :New( RecceSet, 3000 ) -- The RecceSet will detect the enemies, and group them into areas of a 3 km radius. + +-- Setup the AttackSet, which is a SET_GROUP. +-- The SET_GROUP is a dynamic collection of GROUP objects. +local AttackSet = SET_GROUP + :New() -- Create the SET_GROUP object. + :FilterCoalitions( "red" ) -- Only incorporate the RED coalitions. + :FilterPrefixes( "Attack" ) -- Only incorporate groups that start with the name Attack. + :FilterStart() -- Start the dynamic building of the set. + +-- Now we have everything to setup the main A2G TaskDispatcher. +TaskDispatcher = TASK_A2G_DISPATCHER + :New( Mission, AttackSet, DetectionAreas ) -- We assign the TaskDispatcher under Mission. The AttackSet will engage the enemy and will recieve the dispatched Tasks. The DetectionAreas will report any detected enemies to the TaskDispatcher. + +-- We use the MISSILETRAINER for demonstration purposes. +MissileTrainer = MISSILETRAINER:New( 100, "Missiles will be destroyed for training when they reach your plane." ) diff --git a/TSK - Task Modelling/A2G - Air to Ground/TSK-A2A-100 - SEAD/TSK-010 - Task Modelling - SEAD.lua b/TSK - Task Modelling/A2G - Air to Ground/TSK-A2A-100 - SEAD/TSK-010 - Task Modelling - SEAD.lua new file mode 100644 index 0000000000..26ccd154b2 --- /dev/null +++ b/TSK - Task Modelling/A2G - Air to Ground/TSK-A2A-100 - SEAD/TSK-010 - Task Modelling - SEAD.lua @@ -0,0 +1,27 @@ +--- +-- Name: TSK-010 - Task Modelling - SEAD.lua +-- Author: FlightControl +-- Date Created: 31 Mar 2017 +-- +-- # Situation: +-- +-- This mission demonstrates the Task_SEAD. +-- +-- # Test cases: +-- + +HQ = GROUP:FindByName( "HQ", "Bravo HQ" ) + +CommandCenter = COMMANDCENTER:New( HQ, "Lima" ) + +Scoring = SCORING:New( "Detect Demo" ) + +Mission = MISSION + :New( CommandCenter, "Overlord", "High", "SEAD the area!", coalition.side.RED ) + :AddScoring( Scoring ) + +AttackGroups = SET_GROUP:New():FilterCoalitions( "red" ):FilterPrefixes( "Attack" ):FilterStart() + +TargetSetUnit = SET_UNIT:New():FilterCoalitions("blue"):FilterPrefixes("Target"):FilterStart() + +TaskSEAD = TASK_A2G_SEAD:New(Mission,AttackGroups,"SEAD",TargetSetUnit) diff --git a/TSK - Task Modelling/A2G - Air to Ground/TSK-A2A-200 - BAI/TSK-100 - A2G - BAI.lua b/TSK - Task Modelling/A2G - Air to Ground/TSK-A2A-200 - BAI/TSK-100 - A2G - BAI.lua new file mode 100644 index 0000000000..98f2e43a55 --- /dev/null +++ b/TSK - Task Modelling/A2G - Air to Ground/TSK-A2A-200 - BAI/TSK-100 - A2G - BAI.lua @@ -0,0 +1,27 @@ +--- +-- Name: TSK-100 - A2G - BAI +-- Author: FlightControl +-- Date Created: 28 May 2017 +-- +-- # Situation: +-- +-- This mission demonstrates the Task_BAI. +-- +-- # Test cases: +-- + +HQ = GROUP:FindByName( "HQ", "Bravo HQ" ) + +CommandCenter = COMMANDCENTER:New( HQ, "Bravo" ) + +Scoring = SCORING:New( "BAI Demo" ) + +Mission = MISSION + :New( CommandCenter, "Overlord", "Primary", "Perform a Battlefield Air Interdiction in the area!", coalition.side.RED ) + :AddScoring( Scoring ) + +AttackGroups = SET_GROUP:New():FilterCoalitions( "red" ):FilterPrefixes( "Attack" ):FilterStart() + +TargetSetUnit = SET_UNIT:New():FilterCoalitions("blue"):FilterPrefixes( "Target" ):FilterStart() + +TaskBAI = TASK_A2G_BAI:New( Mission, AttackGroups,"BAI", TargetSetUnit ) diff --git a/TSK - Task Modelling/A2G - Air to Ground/TSK-A2G-110 - BAI - WWII Mode/TSK-101 - A2G - BAI - WWII Mode.lua b/TSK - Task Modelling/A2G - Air to Ground/TSK-A2G-110 - BAI - WWII Mode/TSK-101 - A2G - BAI - WWII Mode.lua new file mode 100644 index 0000000000..1aaf6fd36e --- /dev/null +++ b/TSK - Task Modelling/A2G - Air to Ground/TSK-A2G-110 - BAI - WWII Mode/TSK-101 - A2G - BAI - WWII Mode.lua @@ -0,0 +1,29 @@ +--- +-- Name: TSK-101 - A2G - BAI - WWII Mode +-- Author: FlightControl +-- Date Created: 28 May 2017 +-- +-- # Situation: +-- +-- This mission demonstrates the Task_BAI. +-- +-- # Test cases: +-- + +HQ = GROUP:FindByName( "HQ", "Bravo HQ" ) + +CommandCenter = COMMANDCENTER:New( HQ, "Bravo" ) +CommandCenter:SetModeWWII() +CommandCenter:SetReferenceZones( "Airbase" ) + +Scoring = SCORING:New( "BAI Demo" ) + +Mission = MISSION + :New( CommandCenter, "Overlord", "Primary", "Perform a Battlefield Air Interdiction in the area!", coalition.side.RED ) + :AddScoring( Scoring ) + +AttackGroups = SET_GROUP:New():FilterCoalitions( "red" ):FilterPrefixes( "Attack" ):FilterStart() + +TargetSetUnit = SET_UNIT:New():FilterCoalitions("blue"):FilterPrefixes( "Target" ):FilterStart() + +TaskBAI = TASK_A2G_BAI:New( Mission, AttackGroups,"BAI", TargetSetUnit ) diff --git a/WHS - Warehouse/Caucasus/WHS-160 - Resupply/WHS-016 - Resupply.lua b/WHS - Warehouse/Caucasus/WHS-160 - Resupply/WHS-016 - Resupply.lua index eba0be3666..9cd4f5c05a 100644 --- a/WHS - Warehouse/Caucasus/WHS-160 - Resupply/WHS-016 - Resupply.lua +++ b/WHS - Warehouse/Caucasus/WHS-160 - Resupply/WHS-016 - Resupply.lua @@ -1,104 +1,103 @@ ------------------------ --- Test 17: Resupply -- ------------------------ --- Warehouse at FARP Berlin is located at the front line and sends infantry groups to the battle zone. --- Whenever a group dies, a new group is send from the warehouse to the battle zone. --- Additionally, for each dead group, Berlin requests resupply from Batumi. - --- Display mission time every 30 seconds. -SCHEDULER:New(nil, UTILS.DisplayMissionTime, {5}, 30, 30) - -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - --- Define Warehouses. -local warehouse={} - --- Blue warehouses -warehouse.Senaki = WAREHOUSE:New(STATIC:FindByName("Warehouse Senaki"), "Senaki") --Functional.Warehouse#WAREHOUSE -warehouse.Batumi = WAREHOUSE:New(STATIC:FindByName("Warehouse Batumi"), "Batumi") --Functional.Warehouse#WAREHOUSE -warehouse.Kobuleti = WAREHOUSE:New(STATIC:FindByName("Warehouse Kobuleti"), "Kobuleti") --Functional.Warehouse#WAREHOUSE -warehouse.Kutaisi = WAREHOUSE:New(STATIC:FindByName("Warehouse Kutaisi"), "Kutaisi") --Functional.Warehouse#WAREHOUSE -warehouse.Berlin = WAREHOUSE:New(STATIC:FindByName("Warehouse Berlin"), "Berlin") --Functional.Warehouse#WAREHOUSE -warehouse.London = WAREHOUSE:New(STATIC:FindByName("Warehouse London"), "London") --Functional.Warehouse#WAREHOUSE -warehouse.Stennis = WAREHOUSE:New(STATIC:FindByName("Warehouse Stennis"), "Stennis") --Functional.Warehouse#WAREHOUSE -warehouse.Pampa = WAREHOUSE:New(STATIC:FindByName("Warehouse Pampa"), "Pampa") --Functional.Warehouse#WAREHOUSE -warehouse.Pearth = WAREHOUSE:New(STATIC:FindByName("Warehouse Pearth"), "Pearth") --Functional.Warehouse#WAREHOUSE --- Red warehouse -warehouse.Sukhumi = WAREHOUSE:New(STATIC:FindByName("Warehouse Sukhumi"), "Sukhumi") --Functional.Warehouse#WAREHOUSE -warehouse.Gudauta = WAREHOUSE:New(STATIC:FindByName("Warehouse Gudauta"), "Gudauta") --Functional.Warehouse#WAREHOUSE -warehouse.Sochi = WAREHOUSE:New(STATIC:FindByName("Warehouse Sochi"), "Sochi") --Functional.Warehouse#WAREHOUSE - --- Fine tune warehouses if necessary. -warehouse.Batumi:SetSpawnZone(ZONE:New("Warehouse Batumi Spawn Zone")) -warehouse.Senaki:SetSpawnZone(ZONE:New("Warehouse Senaki Spawn Zone")) -warehouse.Kobuleti:SetSpawnZone(ZONE_POLYGON:New("Warehouse Kobuleti Spawn Zone", GROUP:FindByName("Warehouse Kobuleti Spawn Zone"))) - - --- Creat explosion at an object. -local function Explosion(object, power) - power=power or 1000 - if object and object:IsAlive() then - object:GetCoordinate():Explosion(power) - end -end - -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - --- Start warehouses. -warehouse.Batumi:Start() -warehouse.Berlin:Start() - --- Front line warehouse. -warehouse.Berlin:AddAsset("Infantry Platoon Alpha", 6) - --- Resupply warehouse. -warehouse.Batumi:AddAsset("Infantry Platoon Alpha", 50) - --- Battle zone near FARP Berlin. This is where the action is! -local BattleZone=ZONE:New("Virtual Battle Zone") - --- Send infantry groups to the battle zone. Two groups every ~60 seconds. -for i=1,2 do - local time=(i-1)*60+10 - warehouse.Berlin:__AddRequest(time, warehouse.Berlin, WAREHOUSE.Descriptor.ATTRIBUTE, WAREHOUSE.Attribute.GROUND_INFANTRY, 2, nil, nil, nil, "To Battle Zone") -end - --- Take care of the spawned units. -function warehouse.Berlin:OnAfterSelfRequest(From,Event,To,groupset,request) - local groupset=groupset --Core.Set#SET_GROUP - local request=request --Functional.Warehouse#WAREHOUSE.Pendingitem - - -- Get assignment of this request. - local assignment=warehouse.Berlin:GetAssignment(request) - - if assignment=="To Battle Zone" then - - for _,group in pairs(groupset:GetSet()) do - local group=group --Wrapper.Group#GROUP - - -- Route group to Battle zone. - local ToCoord=BattleZone:GetRandomCoordinate() - group:RouteGroundOnRoad(ToCoord, group:GetSpeedMax()*0.8) - - -- After 3-5 minutes we create an explosion to destroy the group. - SCHEDULER:New(nil, Explosion, {group, 50}, math.random(180, 300)) - end - - end - -end - --- An asset has died ==> request resupply for it. -function warehouse.Berlin:OnAfterAssetDead(From, Event, To, asset, request) - local asset=asset --Functional.Warehouse#WAREHOUSE.Assetitem - local request=request --Functional.Warehouse#WAREHOUSE.Pendingitem - - -- Get assignment. - local assignment=warehouse.Berlin:GetAssignment(request) - - -- Request resupply for dead asset from Batumi. - warehouse.Batumi:AddRequest(warehouse.Berlin, WAREHOUSE.Descriptor.ATTRIBUTE, asset.attribute, 1, nil, nil, nil, "Resupply") - - -- Send asset to Battle zone either now or when they arrive. - warehouse.Berlin:AddRequest(warehouse.Berlin, WAREHOUSE.Descriptor.ATTRIBUTE, asset.attribute, 1, nil, nil, nil, assignment) -end +----------------------- +-- Test 17: Resupply -- +----------------------- +-- Warehouse at FARP Berlin is located at the front line and sends infantry groups to the battle zone. +-- Whenever a group dies, a new group is send from the warehouse to the battle zone. +-- Additionally, for each dead group, Berlin requests resupply from Batumi. + +-- Display mission time every 30 seconds. +SCHEDULER:New(nil, UTILS.DisplayMissionTime, {5}, 30, 30) + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +-- Define Warehouses. +local warehouse={} + +-- Blue warehouses +warehouse.Senaki = WAREHOUSE:New(STATIC:FindByName("Warehouse Senaki"), "Senaki") --Functional.Warehouse#WAREHOUSE +warehouse.Batumi = WAREHOUSE:New(STATIC:FindByName("Warehouse Batumi"), "Batumi") --Functional.Warehouse#WAREHOUSE +warehouse.Kobuleti = WAREHOUSE:New(STATIC:FindByName("Warehouse Kobuleti"), "Kobuleti") --Functional.Warehouse#WAREHOUSE +warehouse.Kutaisi = WAREHOUSE:New(STATIC:FindByName("Warehouse Kutaisi"), "Kutaisi") --Functional.Warehouse#WAREHOUSE +warehouse.Berlin = WAREHOUSE:New(STATIC:FindByName("Warehouse Berlin"), "Berlin") --Functional.Warehouse#WAREHOUSE +warehouse.London = WAREHOUSE:New(STATIC:FindByName("Warehouse London"), "London") --Functional.Warehouse#WAREHOUSE +warehouse.Stennis = WAREHOUSE:New(STATIC:FindByName("Warehouse Stennis"), "Stennis") --Functional.Warehouse#WAREHOUSE +warehouse.Pampa = WAREHOUSE:New(STATIC:FindByName("Warehouse Pampa"), "Pampa") --Functional.Warehouse#WAREHOUSE +warehouse.Pearth = WAREHOUSE:New(STATIC:FindByName("Warehouse Pearth"), "Pearth") --Functional.Warehouse#WAREHOUSE +-- Red warehouse +warehouse.Sukhumi = WAREHOUSE:New(STATIC:FindByName("Warehouse Sukhumi"), "Sukhumi") --Functional.Warehouse#WAREHOUSE +warehouse.Gudauta = WAREHOUSE:New(STATIC:FindByName("Warehouse Gudauta"), "Gudauta") --Functional.Warehouse#WAREHOUSE +warehouse.Sochi = WAREHOUSE:New(STATIC:FindByName("Warehouse Sochi"), "Sochi") --Functional.Warehouse#WAREHOUSE + +-- Fine tune warehouses if necessary. +warehouse.Batumi:SetSpawnZone(ZONE:New("Warehouse Batumi Spawn Zone")) +warehouse.Senaki:SetSpawnZone(ZONE:New("Warehouse Senaki Spawn Zone")) +warehouse.Kobuleti:SetSpawnZone(ZONE_POLYGON:New("Warehouse Kobuleti Spawn Zone", GROUP:FindByName("Warehouse Kobuleti Spawn Zone"))) + + +-- Creat explosion at an object. +local function Explosion(object, power) + power=power or 1000 + if object and object:IsAlive() then + object:GetCoordinate():Explosion(power) + end +end + + +-- Start warehouses. +warehouse.Batumi:Start() +warehouse.Berlin:Start() + +-- Front line warehouse. +warehouse.Berlin:AddAsset("Infantry Platoon Alpha", 6) + +-- Resupply warehouse. +warehouse.Batumi:AddAsset("Infantry Platoon Alpha", 50) + +-- Battle zone near FARP Berlin. This is where the action is! +local BattleZone=ZONE:New("Virtual Battle Zone") + +-- Send infantry groups to the battle zone. Two groups every ~60 seconds. +for i=1,2 do + local time=(i-1)*60+10 + warehouse.Berlin:__AddRequest(time, warehouse.Berlin, WAREHOUSE.Descriptor.ATTRIBUTE, WAREHOUSE.Attribute.GROUND_INFANTRY, 2, nil, nil, nil, "To Battle Zone") +end + +-- Take care of the spawned units. +function warehouse.Berlin:OnAfterSelfRequest(From,Event,To,groupset,request) + local groupset=groupset --Core.Set#SET_GROUP + local request=request --Functional.Warehouse#WAREHOUSE.Pendingitem + + -- Get assignment of this request. + local assignment=warehouse.Berlin:GetAssignment(request) + + if assignment=="To Battle Zone" then + + for _,group in pairs(groupset:GetSet()) do + local group=group --Wrapper.Group#GROUP + + -- Route group to Battle zone. + local ToCoord=BattleZone:GetRandomCoordinate() + group:RouteGroundOnRoad(ToCoord, group:GetSpeedMax()*80) + + -- After 3-5 minutes we create an explosion to destroy the group. + SCHEDULER:New(nil, Explosion, {group, 50}, math.random(180, 300)) + end + + end + +end + +-- An asset has died ==> request resupply for it. +function warehouse.Berlin:OnAfterAssetDead(From, Event, To, asset, request) + local asset=asset --Functional.Warehouse#WAREHOUSE.Assetitem + local request=request --Functional.Warehouse#WAREHOUSE.Pendingitem + + -- Get assignment. + local assignment=warehouse.Berlin:GetAssignment(request) + + -- Request resupply for dead asset from Batumi. + warehouse.Batumi:AddRequest(warehouse.Berlin, WAREHOUSE.Descriptor.ATTRIBUTE, asset.attribute, nil, nil, nil, nil, "Resupply") + + -- Send asset to Battle zone either now or when they arrive. + warehouse.Berlin:AddRequest(warehouse.Berlin, WAREHOUSE.Descriptor.ATTRIBUTE, asset.attribute, 1, nil, nil, nil, assignment) +end diff --git a/WHS - Warehouse/Caucasus/WHS-170 - Resupply/WHS-016 - Resupply.lua b/WHS - Warehouse/Caucasus/WHS-170 - Resupply/WHS-016 - Resupply.lua new file mode 100644 index 0000000000..9cd4f5c05a --- /dev/null +++ b/WHS - Warehouse/Caucasus/WHS-170 - Resupply/WHS-016 - Resupply.lua @@ -0,0 +1,103 @@ +----------------------- +-- Test 17: Resupply -- +----------------------- +-- Warehouse at FARP Berlin is located at the front line and sends infantry groups to the battle zone. +-- Whenever a group dies, a new group is send from the warehouse to the battle zone. +-- Additionally, for each dead group, Berlin requests resupply from Batumi. + +-- Display mission time every 30 seconds. +SCHEDULER:New(nil, UTILS.DisplayMissionTime, {5}, 30, 30) + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +-- Define Warehouses. +local warehouse={} + +-- Blue warehouses +warehouse.Senaki = WAREHOUSE:New(STATIC:FindByName("Warehouse Senaki"), "Senaki") --Functional.Warehouse#WAREHOUSE +warehouse.Batumi = WAREHOUSE:New(STATIC:FindByName("Warehouse Batumi"), "Batumi") --Functional.Warehouse#WAREHOUSE +warehouse.Kobuleti = WAREHOUSE:New(STATIC:FindByName("Warehouse Kobuleti"), "Kobuleti") --Functional.Warehouse#WAREHOUSE +warehouse.Kutaisi = WAREHOUSE:New(STATIC:FindByName("Warehouse Kutaisi"), "Kutaisi") --Functional.Warehouse#WAREHOUSE +warehouse.Berlin = WAREHOUSE:New(STATIC:FindByName("Warehouse Berlin"), "Berlin") --Functional.Warehouse#WAREHOUSE +warehouse.London = WAREHOUSE:New(STATIC:FindByName("Warehouse London"), "London") --Functional.Warehouse#WAREHOUSE +warehouse.Stennis = WAREHOUSE:New(STATIC:FindByName("Warehouse Stennis"), "Stennis") --Functional.Warehouse#WAREHOUSE +warehouse.Pampa = WAREHOUSE:New(STATIC:FindByName("Warehouse Pampa"), "Pampa") --Functional.Warehouse#WAREHOUSE +warehouse.Pearth = WAREHOUSE:New(STATIC:FindByName("Warehouse Pearth"), "Pearth") --Functional.Warehouse#WAREHOUSE +-- Red warehouse +warehouse.Sukhumi = WAREHOUSE:New(STATIC:FindByName("Warehouse Sukhumi"), "Sukhumi") --Functional.Warehouse#WAREHOUSE +warehouse.Gudauta = WAREHOUSE:New(STATIC:FindByName("Warehouse Gudauta"), "Gudauta") --Functional.Warehouse#WAREHOUSE +warehouse.Sochi = WAREHOUSE:New(STATIC:FindByName("Warehouse Sochi"), "Sochi") --Functional.Warehouse#WAREHOUSE + +-- Fine tune warehouses if necessary. +warehouse.Batumi:SetSpawnZone(ZONE:New("Warehouse Batumi Spawn Zone")) +warehouse.Senaki:SetSpawnZone(ZONE:New("Warehouse Senaki Spawn Zone")) +warehouse.Kobuleti:SetSpawnZone(ZONE_POLYGON:New("Warehouse Kobuleti Spawn Zone", GROUP:FindByName("Warehouse Kobuleti Spawn Zone"))) + + +-- Creat explosion at an object. +local function Explosion(object, power) + power=power or 1000 + if object and object:IsAlive() then + object:GetCoordinate():Explosion(power) + end +end + + +-- Start warehouses. +warehouse.Batumi:Start() +warehouse.Berlin:Start() + +-- Front line warehouse. +warehouse.Berlin:AddAsset("Infantry Platoon Alpha", 6) + +-- Resupply warehouse. +warehouse.Batumi:AddAsset("Infantry Platoon Alpha", 50) + +-- Battle zone near FARP Berlin. This is where the action is! +local BattleZone=ZONE:New("Virtual Battle Zone") + +-- Send infantry groups to the battle zone. Two groups every ~60 seconds. +for i=1,2 do + local time=(i-1)*60+10 + warehouse.Berlin:__AddRequest(time, warehouse.Berlin, WAREHOUSE.Descriptor.ATTRIBUTE, WAREHOUSE.Attribute.GROUND_INFANTRY, 2, nil, nil, nil, "To Battle Zone") +end + +-- Take care of the spawned units. +function warehouse.Berlin:OnAfterSelfRequest(From,Event,To,groupset,request) + local groupset=groupset --Core.Set#SET_GROUP + local request=request --Functional.Warehouse#WAREHOUSE.Pendingitem + + -- Get assignment of this request. + local assignment=warehouse.Berlin:GetAssignment(request) + + if assignment=="To Battle Zone" then + + for _,group in pairs(groupset:GetSet()) do + local group=group --Wrapper.Group#GROUP + + -- Route group to Battle zone. + local ToCoord=BattleZone:GetRandomCoordinate() + group:RouteGroundOnRoad(ToCoord, group:GetSpeedMax()*80) + + -- After 3-5 minutes we create an explosion to destroy the group. + SCHEDULER:New(nil, Explosion, {group, 50}, math.random(180, 300)) + end + + end + +end + +-- An asset has died ==> request resupply for it. +function warehouse.Berlin:OnAfterAssetDead(From, Event, To, asset, request) + local asset=asset --Functional.Warehouse#WAREHOUSE.Assetitem + local request=request --Functional.Warehouse#WAREHOUSE.Pendingitem + + -- Get assignment. + local assignment=warehouse.Berlin:GetAssignment(request) + + -- Request resupply for dead asset from Batumi. + warehouse.Batumi:AddRequest(warehouse.Berlin, WAREHOUSE.Descriptor.ATTRIBUTE, asset.attribute, nil, nil, nil, nil, "Resupply") + + -- Send asset to Battle zone either now or when they arrive. + warehouse.Berlin:AddRequest(warehouse.Berlin, WAREHOUSE.Descriptor.ATTRIBUTE, asset.attribute, 1, nil, nil, nil, assignment) +end diff --git a/ZON - Zones/ZON-103 - Test if GROUP object is in ZONE/SET-102 - Test SET_GROUP object against ZONE.lua b/ZON - Zones/ZON-103 - Test if GROUP object is in ZONE/SET-102 - Test SET_GROUP object against ZONE.lua new file mode 100644 index 0000000000..db60dc57a0 --- /dev/null +++ b/ZON - Zones/ZON-103 - Test if GROUP object is in ZONE/SET-102 - Test SET_GROUP object against ZONE.lua @@ -0,0 +1,34 @@ +--- +-- Name: SET-102 - Test SET_GROUP object against ZONE +-- Author: FlightControl +-- Date Created: 31 Mar 2017 +-- +-- # Situation: +-- +-- A ZONE has been defined, and the SET_GROUP object is checked against the zone. +-- +-- # Test cases: +-- +-- 1. Observe the zone perimeter, and place the SET_GROUP object in or out of the zone. +-- 2. Observe the results of the functions. + + +SetGroupObject = SET_GROUP:New():FilterCoalitions("blue"):FilterPrefixes("Group Object"):FilterStart() + +Zone = ZONE:New( "Zone" ) + +SetGroupObject:ForEachGroupCompletelyInZone( Zone, + function( GroupObject ) + GroupObject:E( { GroupObject:GetName(), "I am completely in Zone" } ) + end ) + +SetGroupObject:ForEachGroupPartlyInZone( Zone, + function( GroupObject ) + GroupObject:E( { GroupObject:GetName(), "I am partially in Zone" } ) + end ) + +SetGroupObject:ForEachGroupNotInZone( Zone, + function( GroupObject ) + GroupObject:E( { GroupObject:GetName(), "I am not in Zone" } ) + end ) + diff --git a/ZON - Zones/ZON-400 - Radius Zone/ZON-400 - Radius Zone.miz b/ZON - Zones/ZON-400 - Radius Zone/ZON-400 - Radius Zone.miz index dc110c1191..9b5bbfbb8e 100644 Binary files a/ZON - Zones/ZON-400 - Radius Zone/ZON-400 - Radius Zone.miz and b/ZON - Zones/ZON-400 - Radius Zone/ZON-400 - Radius Zone.miz differ diff --git a/ZON - Zones/ZON-500 - Polygon Zone/ZON-500 - Polygon Zone.miz b/ZON - Zones/ZON-500 - Polygon Zone/ZON-500 - Polygon Zone.miz index f99a4c14c8..e1b0af28bf 100644 Binary files a/ZON - Zones/ZON-500 - Polygon Zone/ZON-500 - Polygon Zone.miz and b/ZON - Zones/ZON-500 - Polygon Zone/ZON-500 - Polygon Zone.miz differ