From ae2e99a5609497b1a7679320c565208a196b1ff4 Mon Sep 17 00:00:00 2001 From: FlightControl_Master Date: Sat, 10 Mar 2018 07:00:09 +0100 Subject: [PATCH 1/7] Updating loader so that it allows to load complete mission scripts for mission designers from other paths. --- Moose Setup/Moose Templates/Moose_Dynamic_Loader.lua | 4 +--- Moose Setup/Moose_Create.lua | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Moose Setup/Moose Templates/Moose_Dynamic_Loader.lua b/Moose Setup/Moose Templates/Moose_Dynamic_Loader.lua index 87044ad51..70371bf3a 100644 --- a/Moose Setup/Moose Templates/Moose_Dynamic_Loader.lua +++ b/Moose Setup/Moose Templates/Moose_Dynamic_Loader.lua @@ -7,7 +7,7 @@ __Moose = {} __Moose.Include = function( IncludeFile ) if not __Moose.Includes[ IncludeFile ] then __Moose.Includes[IncludeFile] = IncludeFile - local f = assert( base.loadfile( __Moose.ProgramPath .. IncludeFile ) ) + local f = assert( base.loadfile( IncludeFile ) ) if f == nil then error ("Moose: Could not load Moose file " .. IncludeFile ) else @@ -17,6 +17,4 @@ __Moose.Include = function( IncludeFile ) end end -__Moose.ProgramPath = "Scripts/Moose/" - __Moose.Includes = {} diff --git a/Moose Setup/Moose_Create.lua b/Moose Setup/Moose_Create.lua index c15f3f5e2..500a56965 100644 --- a/Moose Setup/Moose_Create.lua +++ b/Moose Setup/Moose_Create.lua @@ -47,7 +47,7 @@ while( MooseSource ) do local MooseFilePath = MooseDevelopmentPath .. "/" .. MooseSource if MooseDynamicStatic == "D" then print( "Load dynamic: " .. MooseSource ) - MooseFile:write( "__Moose.Include( '" .. MooseSource .. "' )\n" ) + MooseFile:write( "__Moose.Include( 'Scripts/Moose/" .. MooseSource .. "' )\n" ) end if MooseDynamicStatic == "S" then print( "Load static: " .. MooseSource ) From 3544f071696eb4ede722c252cef5e73ff0940292 Mon Sep 17 00:00:00 2001 From: FlightControl_Master Date: Sat, 10 Mar 2018 08:44:33 +0100 Subject: [PATCH 2/7] If one or more units of a group defined as CARGO_GROUP died, the CARGO_GROUP:Board() command does not trigger the CARGO_GRUOP:OnEnterLoaded() function. --- Moose Development/Moose/Core/Cargo.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Moose Development/Moose/Core/Cargo.lua b/Moose Development/Moose/Core/Cargo.lua index 8bdbbd205..de62c73e2 100644 --- a/Moose Development/Moose/Core/Cargo.lua +++ b/Moose Development/Moose/Core/Cargo.lua @@ -1289,7 +1289,10 @@ function CARGO_GROUP:onafterBoarding( From, Event, To, CargoCarrier, NearRadius, -- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2 for CargoID, Cargo in pairs( self.CargoSet:GetSet() ) do self:T( { Cargo:GetName(), Cargo.current } ) - if not Cargo:is( "Loaded" ) then + + + if not Cargo:is( "Loaded" ) + and (not Cargo:is( "Destroyed" )) then -- If one or more units of a group defined as CARGO_GROUP died, the CARGO_GROUP:Board() command does not trigger the CARGO_GRUOP:OnEnterLoaded() function. Boarded = false end From f2cb750aa21e250ca0deda2787f38a77721573c3 Mon Sep 17 00:00:00 2001 From: funkyfranky Date: Sat, 10 Mar 2018 23:57:49 +0100 Subject: [PATCH 3/7] RAT v2.2 RAT: - Added possibility to activate uncontrolled aircraft. - Added immortal option (untested). - Added invisible option (untested). - Added check that when aircraft are spawned on the runway, that they get despawned immediately. - Added RATMANAGER class. ZONE: Fix/workaround for isExist() always returning false for scenery objects. --- Moose Development/Moose/Core/Zone.lua | 7 +- Moose Development/Moose/Functional/RAT.lua | 1279 +++++++++++++++----- 2 files changed, 1006 insertions(+), 280 deletions(-) diff --git a/Moose Development/Moose/Core/Zone.lua b/Moose Development/Moose/Core/Zone.lua index 4d5512147..9e0ab175f 100644 --- a/Moose Development/Moose/Core/Zone.lua +++ b/Moose Development/Moose/Core/Zone.lua @@ -618,10 +618,11 @@ function ZONE_RADIUS:Scan( ObjectCategories ) } local function EvaluateZone( ZoneObject ) - if ZoneObject:isExist() then + --if ZoneObject:isExist() then --FF: isExist always returns false for SCENERY objects since DCS 2.2 and still in DCS 2.5 + if ZoneObject then local ObjectCategory = ZoneObject:getCategory() - if ( ObjectCategory == Object.Category.UNIT and ZoneObject:isActive() ) or - ObjectCategory == Object.Category.STATIC then + if ( ObjectCategory == Object.Category.UNIT and ZoneObject:isExist() and ZoneObject:isActive() ) or + (ObjectCategory == Object.Category.STATIC and ZoneObject:isExist()) then local CoalitionDCSUnit = ZoneObject:getCoalition() self.ScanData.Coalitions[CoalitionDCSUnit] = true self:E( { Name = ZoneObject:getName(), Coalition = CoalitionDCSUnit } ) diff --git a/Moose Development/Moose/Functional/RAT.lua b/Moose Development/Moose/Functional/RAT.lua index 2198ea8d0..1693f938f 100644 --- a/Moose Development/Moose/Functional/RAT.lua +++ b/Moose Development/Moose/Functional/RAT.lua @@ -132,9 +132,17 @@ -- @field #boolean radio If true/false disables radio messages from the RAT groups. -- @field #number frequency Radio frequency used by the RAT groups. -- @field #string modulation Ratio modulation. Either "FM" or "AM". --- @field #boolean uncontrolled If true aircraft are spawned in uncontrolled state and will only sit on their parking spots. +-- @field #boolean uncontrolled If true aircraft are spawned in uncontrolled state and will only sit on their parking spots. They can later be activated. +-- @field #boolean invisible If true aircraft are set to invisible for other AI forces. +-- @field #boolean immortal If true, aircraft are spawned as immortal. +-- @field #boolean activate_uncontrolled If true, uncontrolled are activated randomly after certain time intervals. +-- @field #number activate_delay Delay in seconds before first uncontrolled group is activated. Default is 5 seconds. +-- @field #number activate_delta Time interval in seconds between activation of uncontrolled groups. Default is 5 seconds. +-- @field #number activate_frand Randomization factor of time interval (activate_delta) between activating uncontrolled groups. Default is 0. +-- @field #number activate_max=0 Maximal number of uncontrolle aircraft, which will be activated at a time. Default is 0 -- @field #string onboardnum Sets the onboard number prefix. Same as setting "TAIL #" in the mission editor. -- @field #number onboardnum0 (Optional) Starting value of the automatically appended numbering of aircraft within a flight. Default is one. +-- @field #number rbug_maxretry Number of respawn retries (on ground) at other airports if a group gets accidentally spawned on the runway. Default is 3. -- @extends Core.Spawn#SPAWN ---# RAT class, extends @{Spawn#SPAWN} @@ -355,8 +363,16 @@ RAT={ modulation=nil, -- Ratio modulation. Either "FM" or "AM". actype=nil, -- Aircraft type set by user. Changes the type of the template group. uncontrolled=false, -- Spawn uncontrolled aircraft. + invisible=false, -- Spawn aircraft as invisible. + immortal=false, -- Spawn aircraft as indestructible. + activate_uncontrolled=false, -- Activate uncontrolled aircraft (randomly). + activate_delay=5, -- Delay in seconds before first uncontrolled group is activated. + activate_delta=5, -- Time interval in seconds between activation of uncontrolled groups. + activate_frand=0, -- Randomization factor of time interval (activate_delta) between activating uncontrolled groups. + activate_max=0, -- Max number of uncontrolle aircraft, which will be activated at a time. onboardnum=nil, -- Tail number. onboardnum0=1, -- (Optional) Starting value of the automatically appended numbering of aircraft within a flight. Default is one. + rbug_maxretry=3, -- Number of respawn retries (on ground) at other airports if a group gets accidentally spawned on the runway. } ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -398,6 +414,9 @@ RAT.status={ DescentHolding="Descend to holding point", Holding="Holding", Destination="Arrived at destination", + -- Spawn states. + Uncontrolled="Uncontrolled", + Spawned="Spawned", -- Event states. EventBirthAir="Born in air", EventBirth="Ready and starting engines", @@ -472,7 +491,7 @@ RAT.id="RAT | " --- RAT version. -- @field #list RAT.version={ - version = "2.1.0", + version = "2.2.0", print = true, } @@ -508,9 +527,9 @@ RAT.version={ --DONE: Check cases where aircraft get shot down. --DONE: Handle the case where more than 10 RAT objects are spawned. Likewise, more than 10 groups of one object. Causes problems with the number of menu items! ==> not now! --DONE: Add custom livery choice if possible. ---TODO: When only a destination is set, it should be checked that the departure is within range. Also, that departure and destination are not the same. ---TODO: Add function to include all airports to selected destinations/departures. +--DONE: Add function to include all airports to selected destinations/departures. --DONE: Find way to respawn aircraft at same position where the last was despawned for commute and journey. +--TODO: Check that same alias is not given twice. Need to store previous ones and compare. ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -523,6 +542,7 @@ RAT.version={ -- @usage yak1:RAT("RAT_YAK") will create a RAT object called "yak1". The template group in the mission editor must have the name "RAT_YAK". -- @usage yak2:RAT("RAT_YAK", "Yak2") will create a RAT object "yak2". The template group in the mission editor must have the name "RAT_YAK" but the group will be called "Yak2" in e.g. the F10 menu. function RAT:New(groupname, alias) + BASE:F({groupname=groupname, alias=alias}) -- Inherit SPAWN class. self=BASE:Inherit(self, SPAWN:NewWithAlias(groupname, alias)) -- #RAT @@ -665,7 +685,6 @@ function RAT:Spawn(naircraft) text=text..string.format("Journey: %s\n", tostring(self.continuejourney)) text=text..string.format("Destination Zone: %s\n", tostring(self.destinationzone)) text=text..string.format("Return Zone: %s\n", tostring(self.returnzone)) - text=text..string.format("Uncontrolled: %s\n", tostring(self.uncontrolled)) text=text..string.format("Spawn delay: %4.1f\n", self.spawndelay) text=text..string.format("Spawn interval: %4.1f\n", self.spawninterval) text=text..string.format("Respawn after landing: %s\n", tostring(self.respawn_at_landing)) @@ -692,6 +711,13 @@ function RAT:Spawn(naircraft) text=text..string.format("Radio frequency : %s\n", tostring(self.frequency)) text=text..string.format("Radio modulation : %s\n", tostring(self.frequency)) text=text..string.format("Tail # prefix : %s\n", tostring(self.onboardnum)) + text=text..string.format("Uncontrolled: %s\n", tostring(self.uncontrolled)) + if self.uncontrolled and self.activate_uncontrolled then + text=text..string.format("Uncontrolled delay: %4.1f\n", self.activate_delay) + text=text..string.format("Uncontrolled delta: %4.1f\n", self.activate_delta) + text=text..string.format("Uncontrolled frand: %4.1f\n", self.activate_frand) + text=text..string.format("Uncontrolled max : %4.1f\n", self.activate_max) + end if self.livery then text=text..string.format("Available liveries:\n") for _,livery in pairs(self.livery) do @@ -718,8 +744,7 @@ function RAT:Spawn(naircraft) dt=math.max(dt, 180) end local Tstop=Tstart+dt*(self.ngroups-1) - SCHEDULER:New(nil, self._SpawnWithRoute, {self}, Tstart, dt, 0.0, Tstop) - + -- Status check and report scheduler. SCHEDULER:New(nil, self.Status, {self}, Tstart+1, self.statusinterval) @@ -732,11 +757,132 @@ function RAT:Spawn(naircraft) self:HandleEvent(EVENTS.Dead, self._OnDead) self:HandleEvent(EVENTS.Crash, self._OnCrash) -- TODO: add hit event? + + if self.ngroups==0 then + return nil + elseif self.uncontrolled then + for i=1,self.ngroups do + self:_SpawnWithRoute() + end + if self.activate_uncontrolled then + SCHEDULER:New(nil, self._ActivateUncontrolled, {self}, self.activate_delay, self.activate_delta, self.activate_frand) + end + else + SCHEDULER:New(nil, self._SpawnWithRoute, {self}, Tstart, dt, 0.0, Tstop) + end end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +--- Randomly activates an uncontrolled aircraft. +-- @param #RAT self +function RAT:_ActivateUncontrolled() + if self.Debug then + env.info(RAT.id.."_ActivateUncontrolled") + end + + -- Spawn indices of uncontrolled inactive aircraft. + local idx={} + local rat={} + + -- Number of active aircraft. + local nactive=0 + + -- Loop over RAT groups and count the active ones. + for spawnindex,ratcraft in pairs(self.ratcraft) do + + local group=ratcraft.group --Wrapper.Group#GROUP + + if group and group:IsAlive() then + + if self.Debug then + local text=string.format("Spawnindex = %d, group name = %s, active = %s", spawnindex, ratcraft.group:GetName(), tostring(ratcraft.active)) + env.info(RAT.id..text) + end + + if ratcraft.active then + nactive=nactive+1 + else + table.insert(idx, spawnindex) + end + + end + end + + if self.Debug then + local text=string.format("Nactive = %d, Ninactive = %d, max active=%d", nactive, #idx, self.activate_max) + env.info(RAT.id..text) + end + + if #idx>0 and nactive Zone --> Zone --> Zone @@ -1700,6 +1927,13 @@ function RAT:_Respawn(group) -- Use the same livery for next aircraft. _livery=livery + -- Last known position of the aircraft, which should be the sparking spot location. + -- Note: we have to check that it was supposed to land and not respawned directly after landing or after takeoff. + -- TODO: Need to think if commute with respawn_after_takeoff actually makes sense. + if landing==RAT.wp.landing and lastpos and not (self.respawn_at_landing or self.respawn_after_takeoff) then + _lastpos=lastpos + end + -- Handle takeoff type. if self.destinationzone then -- self.takeoff is either RAT.wp.air or RAT.wp.cold @@ -1745,21 +1979,30 @@ function RAT:_Respawn(group) _lastwp=lastwp end - if self.Debug then - local text=string.format("self.takeoff, takeoff, _takeoff = %s, %s, %s", tostring(self.takeoff), tostring(takeoff), tostring(_takeoff)) - text=text.."\n"..string.format("self.landing, landing, _landing = %s, %s, %s", tostring(self.landing), tostring(landing), tostring(_landing)) - self:T(RAT.id..text) - end + -- Debug + self:F({departure=_departure, destination=_destination, takeoff=_takeoff, landing=_landing, livery=_livery, lastwp=_lastwp}) -- Spawn new group. - if self.respawn_delay then - SCHEDULER:New(nil, self._SpawnWithRoute, {self, _departure, _destination, _takeoff, _landing, _livery, _lastwp}, self.respawn_delay) - else - self:_SpawnWithRoute(_departure, _destination, _takeoff, _landing, _livery, _lastwp) - end + local arg={} + arg.self=self + arg.departure=_departure + arg.destination=_destination + arg.takeoff=_takeoff + arg.landing=_landing + arg.livery=_livery + arg.lastwp=_lastwp + arg.lastpos=_lastpos + SCHEDULER:New(nil, self._SpawnWithRouteTimer, {arg}, self.respawn_delay or 1) end +--- Delayed spawn function called by scheduler. +-- @param #RAT self +-- @param #table arg Parameters: arg.self, arg.departure, arg.destination, arg.takeoff, arg.landing, arg.livery, arg.lastwp, arg.lastpos +function RAT._SpawnWithRouteTimer(arg) + RAT._SpawnWithRoute(arg.self, arg.departure, arg.destination, arg.takeoff, arg.landing, arg.livery, arg.lastwp, arg.lastpos) +end + ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- Set the route of the AI plane. Due to DCS landing bug, this has to be done before the unit is spawned. @@ -2428,7 +2671,7 @@ function RAT:_PickDeparture(takeoff) end -- Info message. - self:T(RAT.id.."Number of possible departures = "..#departures) + self:T(RAT.id..string.format("Number of possible departures for %s= %d", self.alias, #departures)) -- Select departure airport or zone. local departure=departures[math.random(#departures)] @@ -2436,16 +2679,14 @@ function RAT:_PickDeparture(takeoff) local text if departure and departure:GetName() then if takeoff==RAT.wp.air then - text="Chosen departure zone: "..departure:GetName() + text=string.format("%s: Chosen departure zone: %s", self.alias, departure:GetName()) else - text="Chosen departure airport: "..departure:GetName().." (ID "..departure:GetID()..")" + text=string.format("%s: Chosen departure airport: %s (ID %d)", self.alias, departure:GetName(), departure:GetID()) end + MESSAGE:New(text, 30):ToAllIf(self.Debug) self:T(RAT.id..text) - if self.Debug then - MESSAGE:New(text, 30):ToAll() - end else - self:E(RAT.id.."ERROR: No departure airport or zone found.") + self:E(RAT.id..string.format("ERROR: No departure airport or zone found for %s!", self.alias)) departure=nil end @@ -2562,14 +2803,12 @@ function RAT:_PickDestination(departure, q, minrange, maxrange, random, landing) -- Debug message. local text if landing==RAT.wp.air then - text=string.format("Chosen destination zone: %s.", destination:GetName()) + text=string.format("%s: Chosen destination zone: %s.", self.alias, destination:GetName()) else - text=string.format("Chosen destination airport: %s (ID %d).", destination:GetName(), destination:GetID()) + text=string.format("%s Chosen destination airport: %s (ID %d).", self.alias, destination:GetName(), destination:GetID()) end self:T(RAT.id..text) - if self.Debug then - MESSAGE:New(text, 30):ToAll() - end + MESSAGE:New(text, 30):ToAllIf(self.Debug) else self:E(RAT.id.."ERROR: No destination airport or zone found.") @@ -2657,13 +2896,8 @@ function RAT:_GetAirportsOfMap() -- Add airport to table. table.insert(self.airports_map, _myab) - if self.Debug then - local text1="MOOSE: Airport ID = ".._myab:GetID().." and Name = ".._myab:GetName()..", Category = ".._myab:GetCategory()..", TypeName = ".._myab:GetTypeName() - --local text2="DCS : Airport ID = "..airbase:getID().." and Name = "..airbase:getName()..", Category = "..airbase:getCategory()..", TypeName = "..airbase:getTypeName() - self:T(RAT.id..text1) - --self:T(RAT.id..text2) - end - + local text="MOOSE: Airport ID = ".._myab:GetID().." and Name = ".._myab:GetName()..", Category = ".._myab:GetCategory()..", TypeName = ".._myab:GetTypeName() + self:T2(RAT.id..text) end end @@ -2701,162 +2935,160 @@ end -- @param #number forID (Optional) Send message only for this ID. function RAT:Status(message, forID) - message=message or false - forID=forID or false + --message=message or false + --forID=forID or false - -- number of ratcraft spawned. - local ngroups=#self.ratcraft + if message==nil then + message=false + end + if forID==nil then + forID=false + end -- Current time. local Tnow=timer.getTime() - for i=1, ngroups do + -- Loop over all ratcraft. + for spawnindex,ratcraft in ipairs(self.ratcraft) do - if self.ratcraft[i].group then - if self.ratcraft[i].group:IsAlive() then - - -- Gather some information. - local group=self.ratcraft[i].group --Wrapper.Group#GROUP - local prefix=self:_GetPrefixFromGroup(group) - local life=self:_GetLife(group) - local fuel=group:GetFuel()*100.0 - local airborne=group:InAir() - local coords=group:GetCoordinate() - local alt=coords.y - --local vel=group:GetVelocityKMH() - local departure=self.ratcraft[i].departure:GetName() - local destination=self.ratcraft[i].destination:GetName() - local type=self.aircraft.type - - - -- Monitor time and distance on ground. - local Tg=0 - local Dg=0 - local dTlast=0 - local stationary=false --lets assume, we did move - if airborne then - -- Aircraft is airborne. - self.ratcraft[i]["Tground"]=nil - self.ratcraft[i]["Pground"]=nil - self.ratcraft[i]["Tlastcheck"]=nil - else - --Aircraft is on ground. - if self.ratcraft[i]["Tground"] then - -- Aircraft was already on ground. Calculate total time on ground. - Tg=Tnow-self.ratcraft[i]["Tground"] + -- Get group. + local group=ratcraft.group --Wrapper.Group#GROUP + + if group and group:IsAlive() then - -- Distance on ground since last check. - Dg=coords:Get2DDistance(self.ratcraft[i]["Pground"]) - - -- Time interval since last check. - dTlast=Tnow-self.ratcraft[i]["Tlastcheck"] - - -- If more than Tinactive seconds passed since last check ==> check how much we moved meanwhile. - if dTlast > self.Tinactive then - - -- If aircraft did not move more than 50 m since last check, we call it stationary and despawn it. - --TODO: add case that the aircraft are currently starting their engines. This should not count as being stationary. - --local starting_engines=self.ratcraft[i].status=="" - if Dg<50 and not self.uncontrolled then - stationary=true - end - - -- Set the current time to know when the next check is necessary. - self.ratcraft[i]["Tlastcheck"]=Tnow - self.ratcraft[i]["Pground"]=coords + -- Gather some information. + local prefix=self:_GetPrefixFromGroup(group) + local life=self:_GetLife(group) + local fuel=group:GetFuel()*100.0 + local airborne=group:InAir() + local coords=group:GetCoordinate() + local alt=coords.y + --local vel=group:GetVelocityKMH() + local departure=ratcraft.departure:GetName() + local destination=ratcraft.destination:GetName() + local type=self.aircraft.type + local status=ratcraft.status + local active=ratcraft.active + + -- Monitor time and distance on ground. + local Tg=0 + local Dg=0 + local dTlast=0 + local stationary=false --lets assume, we did move + if airborne then + -- Aircraft is airborne. + ratcraft["Tground"]=nil + ratcraft["Pground"]=nil + ratcraft["Tlastcheck"]=nil + else + --Aircraft is on ground. + if ratcraft["Tground"] then + -- Aircraft was already on ground. Calculate total time on ground. + Tg=Tnow-ratcraft["Tground"] + + -- Distance on ground since last check. + Dg=coords:Get2DDistance(ratcraft["Pground"]) + + -- Time interval since last check. + dTlast=Tnow-ratcraft["Tlastcheck"] + + -- If more than Tinactive seconds passed since last check ==> check how much we moved meanwhile. + if dTlast > self.Tinactive then + + -- If aircraft did not move more than 50 m since last check, we call it stationary and despawn it. + -- Aircraft which are spawned uncontrolled or starting their engines are not counted. + if Dg<50 and active and not status==RAT.status.EventBirth then + stationary=true end - else - -- First time we see that the aircraft is on ground. Initialize the times and position. - self.ratcraft[i]["Tground"]=Tnow - self.ratcraft[i]["Tlastcheck"]=Tnow - self.ratcraft[i]["Pground"]=coords + -- Set the current time to know when the next check is necessary. + ratcraft["Tlastcheck"]=Tnow + ratcraft["Pground"]=coords end + + else + -- First time we see that the aircraft is on ground. Initialize the times and position. + ratcraft["Tground"]=Tnow + ratcraft["Tlastcheck"]=Tnow + ratcraft["Pground"]=coords end - - -- Monitor travelled distance since last check. - local Pn=coords - local Dtravel=Pn:Get2DDistance(self.ratcraft[i]["Pnow"]) - self.ratcraft[i]["Pnow"]=Pn - - -- Add up the travelled distance. - self.ratcraft[i]["Distance"]=self.ratcraft[i]["Distance"]+Dtravel - - -- Distance remaining to destination. - local Ddestination=Pn:Get2DDistance(self.ratcraft[i].destination:GetCoordinate()) - - -- Status shortcut. - local status=self.ratcraft[i].status - - -- Uncontrolled aircraft. - if self.uncontrolled then - status="Uncontrolled" - end - - -- Status report. - if (forID and i==forID) or (not forID) then - local text=string.format("ID %i of group %s\n", i, prefix) - if self.commute then - text=text..string.format("%s commuting between %s and %s\n", type, departure, destination) - elseif self.continuejourney then - text=text..string.format("%s travelling from %s to %s (and continueing form there)\n", type, departure, destination) - else - text=text..string.format("%s travelling from %s to %s\n", type, departure, destination) - end - text=text..string.format("Status: %s", status) - if airborne then - text=text.." [airborne]\n" - else - text=text.." [on ground]\n" - end - text=text..string.format("Fuel = %3.0f %%\n", fuel) - text=text..string.format("Life = %3.0f %%\n", life) - text=text..string.format("FL%03d = %i m ASL\n", alt/RAT.unit.FL2m, alt) - --text=text..string.format("Speed = %i km/h\n", vel) - text=text..string.format("Distance travelled = %6.1f km\n", self.ratcraft[i]["Distance"]/1000) - text=text..string.format("Distance to destination = %6.1f km", Ddestination/1000) - if not airborne then - text=text..string.format("\nTime on ground = %6.0f seconds\n", Tg) - text=text..string.format("Position change = %8.1f m since %3.0f seconds.", Dg, dTlast) - end - if self.Debug then - self:T(RAT.id..text) - end - if message then - MESSAGE:New(text, 20):ToAll() - end - end - - -- Despawn groups if they are on ground and don't move or are damaged. - if not airborne then - - -- Despawn unit if it did not move more then 50 m in the last 180 seconds. - if stationary then - local text=string.format("Group %s is despawned after being %4.0f seconds inaktive on ground.", self.alias, dTlast) - self:T(RAT.id..text) - self:_Despawn(group) - end - -- Despawn group if life is < 10% and distance travelled < 100 m. - if life<10 and Dtravel<100 then - local text=string.format("Damaged group %s is despawned. Life = %3.0f", self.alias, life) - self:_Despawn(group) - end - end - - if self.ratcraft[i].despawnme then - local text=string.format("Flight %s will be despawned NOW!", self.alias) - self:T(RAT.id..text) - -- Despawn old group. - self:_Respawn(self.ratcraft[i].group) - self:_Despawn(self.ratcraft[i].group) - end - end - else - if self.Debug then - local text=string.format("Group %i does not exist.", i) - self:T(RAT.id..text) end - end + + -- Monitor travelled distance since last check. + local Pn=coords + local Dtravel=Pn:Get2DDistance(ratcraft["Pnow"]) + ratcraft["Pnow"]=Pn + + -- Add up the travelled distance. + ratcraft["Distance"]=ratcraft["Distance"]+Dtravel + + -- Distance remaining to destination. + local Ddestination=Pn:Get2DDistance(ratcraft.destination:GetCoordinate()) + + -- Status report. + if (forID and spawnindex==forID) or (not forID) then + local text=string.format("ID %i of group %s\n", spawnindex, prefix) + if self.commute then + text=text..string.format("%s commuting between %s and %s\n", type, departure, destination) + elseif self.continuejourney then + text=text..string.format("%s travelling from %s to %s (and continueing form there)\n", type, departure, destination) + else + text=text..string.format("%s travelling from %s to %s\n", type, departure, destination) + end + text=text..string.format("Status: %s", status) + if airborne then + text=text.." [airborne]\n" + else + text=text.." [on ground]\n" + end + text=text..string.format("Fuel = %3.0f %%\n", fuel) + text=text..string.format("Life = %3.0f %%\n", life) + text=text..string.format("FL%03d = %i m ASL\n", alt/RAT.unit.FL2m, alt) + --text=text..string.format("Speed = %i km/h\n", vel) + text=text..string.format("Distance travelled = %6.1f km\n", ratcraft["Distance"]/1000) + text=text..string.format("Distance to destination = %6.1f km", Ddestination/1000) + if not airborne then + text=text..string.format("\nTime on ground = %6.0f seconds\n", Tg) + text=text..string.format("Position change = %8.1f m since %3.0f seconds.", Dg, dTlast) + end + self:T2(RAT.id..text) + if message then + MESSAGE:New(text, 20):ToAll() + end + end + + -- Despawn groups if they are on ground and don't move or are damaged. + if not airborne then + + -- Despawn unit if it did not move more then 50 m in the last 180 seconds. + if stationary then + local text=string.format("Group %s is despawned after being %4.0f seconds inaktive on ground.", self.alias, dTlast) + self:T(RAT.id..text) + self:_Despawn(group) + end + -- Despawn group if life is < 10% and distance travelled < 100 m. + if life<10 and Dtravel<100 then + local text=string.format("Damaged group %s is despawned. Life = %3.0f", self.alias, life) + self:_Despawn(group) + end + end + + if ratcraft.despawnme then + local text=string.format("Flight %s will be despawned NOW!", self.alias) + self:T(RAT.id..text) + -- Despawn old group. + if not self.norespawn then + self:_Respawn(group) + end + self:_Despawn(group) + end + + else + -- Group does not exist. + local text=string.format("Group does not exist in loop ratcraft status.") + self:T2(RAT.id..text) + end + end if (message and not forID) then @@ -2878,40 +3110,49 @@ function RAT:_GetLife(group) if unit then life=unit:GetLife()/unit:GetLife0()*100 else - if self.Debug then - self:E(RAT.id.."ERROR: Unit does not exist in RAT_Getlife(). Returning zero.") - end + self:T2(RAT.id.."ERROR: Unit does not exist in RAT_Getlife(). Returning zero.") end else - if self.Debug then - self:E(RAT.id.."ERROR: Group does not exist in RAT_Getlife(). Returning zero.") - end + self:T2(RAT.id.."ERROR: Group does not exist in RAT_Getlife(). Returning zero.") end return life end --- Set status of group. -- @param #RAT self +-- @param Wrapper.Group#GROUP group Group. +-- @param #string status Status of group. function RAT:_SetStatus(group, status) - -- Get index from groupname. - local index=self:GetSpawnIndexFromGroup(group) - - -- Set new status. - self.ratcraft[index].status=status - - -- No status update message for "first waypoint", "holding" - local no1 = status==RAT.status.Departure - local no2 = status==RAT.status.EventBirthAir - local no3 = status==RAT.status.Holding - - local text=string.format("Flight %s: %s.", group:GetName(), status) - self:T(RAT.id..text) - - if (not (no1 or no2 or no3)) then - MESSAGE:New(text, 10):ToAllIf(self.reportstatus) + if group and group:IsAlive() then + + -- Get index from groupname. + local index=self:GetSpawnIndexFromGroup(group) + + if self.Debug or self.reportstatus then + env.info(RAT.id..string.format("Group %s has status %s, spawnindex = %d", group:GetName(), status, index)) + end + + if self.ratcraft[index] then + + -- Set new status. + self.ratcraft[index].status=status + + -- No status update message for "first waypoint", "holding" + local no1 = status==RAT.status.Departure + local no2 = status==RAT.status.EventBirthAir + local no3 = status==RAT.status.Holding + + local text=string.format("Flight %s: %s.", group:GetName(), status) + self:T(RAT.id..text) + + if (not (no1 or no2 or no3)) then + MESSAGE:New(text, 10):ToAllIf(self.reportstatus) + end + + end + end - end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -2934,25 +3175,147 @@ function RAT:_OnBirth(EventData) local text="Event: Group "..SpawnGroup:GetName().." was born." self:T(RAT.id..text) + + -- Increase counter of alive groups (also uncontrolled ones). + self.alive=self.alive+1 -- Set status. - local status + local status="unknown in birth" if SpawnGroup:InAir() then - status="Just born (after air start)" status=RAT.status.EventBirthAir + elseif self.uncontrolled then + status=RAT.status.Uncontrolled else - status="Starting engines (after birth)" status=RAT.status.EventBirth end self:_SetStatus(SpawnGroup, status) + + -- Get some info ablout this flight. + local i=self:GetSpawnIndexFromGroup(SpawnGroup) + local _departure=self.ratcraft[i].departure:GetName() + local _destination=self.ratcraft[i].destination:GetName() + local _nrespawn=self.ratcraft[i].nrespawn + local _takeoff=self.ratcraft[i].takeoff + local _landing=self.ratcraft[i].landing + local _livery=self.ratcraft[i].livery + + -- Check if aircraft group was accidentally spawned on the runway. + -- This can happen due to no parking slots available and other DCS bugs. + local onrunway=false + if _takeoff ~= RAT.wp.runway then + onrunway=self:_CheckOnRunway(SpawnGroup, _departure) + end + + -- Workaround if group was spawned on runway. + if onrunway then + + -- Error message. + local text=string.format("ERROR: RAT group of %s was spawned on runway (DCS bug). Group #%d will be despawned immediately!", self.alias, i) + MESSAGE:New(text,30):ToAllIf(self.Debug) + env.info(RAT.id..text) + if self.Debug then + SpawnGroup:FlareRed() + end + + -- Despawn the group. + self:_Despawn(SpawnGroup) + + -- Try to respawn the group if there is at least another airport or random airport selection is used. + if (self.Ndeparture_Airports>=2 or self.random_departure) and _nrespawn= mini[j] then + N[j]=math.random(mini[j], maxi[j]) + else + N[j]=0 + end + + -- Debug info + --env.info(string.format("RATMANAGER: i=%d, alive=%d, min=%d, mini=%d, maxi=%d, add=%d, sumN=%d, sumP=%d", j, alive[j], min[j], mini[j], maxi[j], N[j],sN, sP)) + + end + + -- Last RAT object, number of groups is determined from number of already distributed groups and nnew. + local j=rattab[1] + N[j]=nnew-sum(N, done) + mini[j]=nnew-sum(N, done) + maxi[j]=nnew-sum(N, done) + table.remove(rattab, 1) + table.insert(done,j) + + -- Debug info + if self.Debug then + local text=RATMANAGER.id.."\n" + for i=1,nrat do + text=text..string.format("%s: i=%d, alive=%d, min=%d, mini=%d, maxi=%d, add=%d\n", self.name[i], i, alive[i], min[i], mini[i], maxi[i], N[i]) + end + text=text..string.format("Total # of groups to add = %d", sum(N, done)) + self:T2(text) + end + + -- Return number of groups to be spawned. + return N +end + From 96ca3eeb440509e05505c748a35ac9ca32310b88 Mon Sep 17 00:00:00 2001 From: funkyfranky Date: Sun, 11 Mar 2018 19:12:07 +0100 Subject: [PATCH 4/7] RATMANAGER documentation Fixes/added brief documentation for RATMANAGER class. --- Moose Development/Moose/Functional/RAT.lua | 52 +++++++++++++++------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/Moose Development/Moose/Functional/RAT.lua b/Moose Development/Moose/Functional/RAT.lua index 1693f938f..b73c53820 100644 --- a/Moose Development/Moose/Functional/RAT.lua +++ b/Moose Development/Moose/Functional/RAT.lua @@ -489,7 +489,7 @@ RAT.MenuF10=nil RAT.id="RAT | " --- RAT version. --- @field #list +-- @list version RAT.version={ version = "2.2.0", print = true, @@ -4699,21 +4699,6 @@ function RAT:_ATCQueue() end end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---- **Functional** - Manage multiple RAT objects. --- --- ![Banner Image](..\Presentations\RAT\RAT.png) --- --- ==== --- --- The aim of the RAT class is to fill the empty DCS world with randomized air traffic and bring more life to your airports. --- --- In particular, it is designed to spawn AI air units at random airports. These units will be assigned a random flight path to another random airport on the map. --- --- Even the mission designer will not know where aircraft will be spawned and which route they follow. --- --- @module Ratmanager - ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- RATMANAGER class -- @type RATMANAGER @@ -4731,7 +4716,40 @@ end -- @extends Core.Base#BASE ---# RATMANAGER class, extends @{Base#BASE} --- The RATMANAGER class manages spawning of multiple RAT objects. +-- The RATMANAGER class manages spawning of multiple RAT objects in a very simple way. It is created by the @{#RATMANAGER.New}() contructor. +-- RAT objects with different "tasks" can be defined as usual. However, they **must not** be spawned via the @{#RAT.Spawn}() function. +-- +-- Instead, these objects can be added to the manager via the @{#RATMANAGER.Add}(ratobject, min) function, where the first parameter "ratobject" is the @{#RAT} object, while the second parameter "min" defines the +-- minimum number of RAT aircraft of that object, which are alive at all time. +-- +-- The @{#RATMANAGER} must be started by the @{#RATMANAGER.Start}(startime) function, where the optional argument "startime" specifies the delay time in seconds after which the manager is started and the spawning beginns. +-- If desired, the @{#RATMANAGER} can be stopped by the @{#RATMANAGER.Stop}(stoptime) function. The parameter "stoptime" specifies the time delay in seconds after which the manager stops. +-- When this happens, no new aircraft will be spawned and the population will eventually decrease to zero. +-- +-- ## Example +-- In this example, three different @{#RAT} objects are created (but not spawned manually). The @{#RATMANAGER} takes care that at least five aircraft of each type are alive and that the total number of aircraft +-- spawned is 25. The @{#RATMANAGER} is started after 30 seconds and stopped after two hours. +-- +-- local a10c=RAT:New("RAT_A10C", "A-10C managed") +-- a10c:SetDeparture({"Batumi"}) +-- +-- local f15c=RAT:New("RAT_F15C", "F15C managed") +-- f15c:SetDeparture({"Sochi-Adler"}) +-- f15c:DestinationZone() +-- f15c:SetDestination({"Zone C"}) +-- +-- local av8b=RAT:New("RAT_AV8B", "AV8B managed") +-- av8b:SetDeparture({"Zone C"}) +-- av8b:SetTakeoff("air") +-- av8b:DestinationZone() +-- av8b:SetDestination({"Zone A"}) +-- +-- local manager=RATMANAGER:New(25) +-- manager:Add(a10c, 5) +-- manager:Add(f15c, 5) +-- manager:Add(av8b, 5) +-- manager:Start(30) +-- manager:Stop(7200) -- -- @field #RATMANAGER RATMANAGER={ From 53980423a921e90b26632de53788098659bc592d Mon Sep 17 00:00:00 2001 From: FlightControl_Master Date: Mon, 12 Mar 2018 10:43:25 +0100 Subject: [PATCH 5/7] Rework documentation of DESIGNATE --- .../Moose/Functional/Designate.lua | 126 ++++++++++++++---- 1 file changed, 103 insertions(+), 23 deletions(-) diff --git a/Moose Development/Moose/Functional/Designate.lua b/Moose Development/Moose/Functional/Designate.lua index 13c174ebc..dfc42c136 100644 --- a/Moose Development/Moose/Functional/Designate.lua +++ b/Moose Development/Moose/Functional/Designate.lua @@ -1,6 +1,6 @@ --- **Functional** -- Management of target **Designation**. Lase, smoke and illuminate targets. -- --- --![Banner Image](..\Presentations\DESIGNATE\Dia1.JPG) +-- ![Banner Image](..\Presentations\DESIGNATE\Dia1.JPG) -- -- === -- @@ -40,12 +40,9 @@ do -- DESIGNATE --- # DESIGNATE class, extends @{Fsm#FSM} -- - -- DESIGNATE is orchestrating the designation of potential targets executed by a Recce group, - -- and communicates these to a dedicated attacking group of players, - -- so that following a dynamically generated menu system, - -- each detected set of potential targets can be lased or smoked... - -- - -- Targets can be: + -- DESIGNATE is managing the designation of detected targets. + -- Targets detected by recce will be communicated to a group of attacking players. + -- A menu system is made available that allows to: -- -- * **Lased** for a period of time. -- * **Smoked**. Artillery or airplanes with Illuminatino ordonance need to be present. (WIP, but early demo ready.) @@ -55,8 +52,8 @@ do -- DESIGNATE -- -- * The **DesignateObject** is the object of the DESIGNATE class, which is this class explained in the document. -- * The **DetectionObject** is the object of a DETECTION_ class (DETECTION_TYPES, DETECTION_AREAS, DETECTION_UNITS), which is executing the detection and grouping of Targets into _DetectionItems_. - -- * **DetectionItems** is the list of detected target groupings by the _DetectionObject_. Each _DetectionItem_ contains a _TargetSet_. - -- * **DetectionItem** is one element of the _DetectionItems_ list, and contains a _TargetSet_. + -- * **TargetGroups** is the list of detected target groupings by the _DetectionObject_. Each _TargetGroup_ contains a _TargetSet_. + -- * **TargetGroup** is one element of the __TargetGroups__ list, and contains a _TargetSet_. -- * The **TargetSet** is a SET_UNITS collection of _Targets_, that have been detected by the _DetectionObject_. -- * A **Target** is a detected UNIT object by the _DetectionObject_. -- * A **Threat Level** is a number from 0 to 10 that is calculated based on the threat of the Target in an Air to Ground battle scenario. @@ -67,39 +64,122 @@ do -- DESIGNATE -- * A **Player** is an active CLIENT object containing a human player. -- * A **Designate Menu** is the menu that is dynamically created during the designation process for each _AttackGroup_. -- - -- The RecceSet is continuously detecting for potential Targets, executing its task as part of the DetectionObject. + -- ## 0. Player Manual + -- + -- ![Banner Image](..\Presentations\DESIGNATE\Dia3.JPG) + -- + -- A typical mission setup would require Recce (a @{Set} of Recce) to be detecting potential targets. + -- The DetectionObject will group the detected targets based on the detection method being used. + -- Possible detection methods could be by Area, by Type or by Unit. + -- Each grouping will result in a **TargetGroup**, for terminology and clarity we will use this term throughout the document. + -- + -- **Recce** require to have Line of Sight (LOS) towards the targets. + -- The **Recce** will report any detected targets to the Players (on the picture Observers). + -- When targets are detected, a menu will be made available that allows those **TargetGroups** to be designated. + -- Designation can be done by Lasing, Smoking and Illumination. + -- Smoking is useful during the day, while illumination is recommended to be used during the night. + -- Smoking can designate specific targets, but not very precise, while lasing is very accurate and allows to + -- players to attack the targets using laser guided bombs or rockets. + -- Illumination will lighten up the Target Area. + -- + -- **Recce** can be ground based or airborne. Airborne **Recce** (AFAC) can be really useful to designate a large amount of targets + -- in a wide open area, as airborne **Recce** has a large LOS. + -- However, ground based **Recce** are very useful to smoke or illuminate targets, as they can be much closer + -- to the Target Area. + -- + -- It is recommended to make the **Recce** invisible and immortal using the Mission Editor in DCS World. + -- This will ensure that the detection process won't be interrupted and that targets can be designated. + -- However, you don't have to, so to simulate a more real-word situation or simulation, **Recce can also be destroyed**! + -- + -- ### 0.1. Player View (Observer) + -- + -- ![Banner Image](..\Presentations\DESIGNATE\Dia4.JPG) + -- + -- The RecceSet is continuously detecting for potential Targets, + -- executing its task as part of the DetectionObject. -- Once Targets have been detected, the DesignateObject will trigger the **Detect Event**. -- - -- In order to prevent an overflow in the DesignateObject of detected targets, there is a maximum - -- amount of DetectionItems that can be put in **scope** of the DesignateObject. + -- In order to prevent an overflow in the DesignateObject of detected targets, + -- there is a maximum amount of TargetGroups + -- that can be put in **scope** of the DesignateObject. -- We call this the **MaximumDesignations** term. -- - -- As part of the Detect Event, the DetectionItems list is used by the DesignateObject to provide the Players with: + -- ### 0.2. Designate Menu -- + -- ![Banner Image](..\Presentations\DESIGNATE\Dia5.JPG) + -- + -- For each detected TargetGroup, there is: + -- + -- * A **Designate Menu** are created and continuously refreshed, containing the **DesignationID** and the **Designation Status**. -- * The RecceGroups are reporting to each AttackGroup, sending **Messages** containing the Threat Level and the TargetSet composition. - -- * **Menu options** are created and updated for each AttackGroup, containing the Detection ID and the Coordinates. -- - -- A Player can then select an action from the Designate Menu. + -- A Player can then select an action from the **Designate Menu**. + -- The Designation Status is shown between the ( ). -- - -- **Note that each selected action will be executed for a TargetSet, thus the Target grouping done by the DetectionObject.** + -- It indicates for each TargetGroup the current active designation action applied: -- - -- Each **Menu Option** in the Designate Menu has two modes: + -- * An "I" for Illumnation designation. + -- * An "S" for Smoking designation. + -- * An "L" for Lasing designation. + -- + -- Note that multiple designation methods can be active at the same time! + -- Note the **Auto Lase** option. When switched on, the available **Recce** will lase + -- Targets when detected. -- - -- 1. If the TargetSet **is not being designated**, then the **Designate Menu** option for the target Set will provide options to **Lase** or **Smoke** the targets. - -- 2. If the Target Set **is being designated**, then the **Designate Menu** option will provide an option to stop or cancel the designation. + -- Targets are designated per **Threat Level**. + -- The most threatening targets from an Air to Ground perspective, are designated first! + -- This is for all designation methods. -- - -- While designating, the RecceGroups will report any change in TargetSet composition or Target presence. + -- ![Banner Image](..\Presentations\DESIGNATE\Dia6.JPG) -- - -- The following logic is executed when a TargetSet is selected to be *lased* from the Designation Menu: + -- Each Designate Menu has a sub menu structure, which allows specific actions to be triggered: -- - -- * The RecceSet is searched for any Recce that is within *designation distance* from a Target in the TargetSet that is currently not being designated. + -- * Lase Targets using a specific laser code. + -- * Smoke Targets using a specific smoke color. + -- * Illuminate areas. + -- + -- ### 0.3. Lasing Targets + -- + -- ![Banner Image](..\Presentations\DESIGNATE\Dia7.JPG) + -- + -- Lasing targets is done as expected. Each available Recce can lase only ONE target through! + -- + -- ![Banner Image](..\Presentations\DESIGNATE\Dia8.JPG) + -- + -- Lasing can be done for specific laser codes. The Su-25T requires laser code 1113, while the A-10A requires laser code 1680. + -- For those, specific menu options can be made available for players to lase with these codes. + -- Auto Lase (as explained above), will ensure continuous lasing of available targets. + -- The status report shows which targets are being designated. + -- + -- The following logic is executed when a TargetGroup is selected to be *lased* from the Designation Menu: + -- + -- * The RecceSet is searched for any Recce that is within *designation distance* from a Target in the TargetGroup that is currently not being designated. -- * If there is a Recce found that is currently no designating a target, and is within designation distance from the Target, then that Target will be designated. -- * During designation, any Recce that does not have Line of Sight (LOS) and is not within disignation distance from the Target, will stop designating the Target, and a report is given. -- * When a Recce is designating a Target, and that Target is destroyed, then the Recce will stop designating the Target, and will report the event. -- * When a Recce is designating a Target, and that Recce is destroyed, then the Recce will be removed from the RecceSet and designation will stop without reporting. -- * When all RecceGroups are destroyed from the RecceSet, then the DesignationObject will stop functioning, and nothing will be reported. -- - -- In this way, the DesignationObject assists players to designate ground targets for a coordinated attack! + -- In this way, DESIGNATE assists players to designate ground targets for a coordinated attack! + -- + -- ### 0.4. Illuminating Targets + -- + -- ![Banner Image](..\Presentations\DESIGNATE\Dia8.JPG) + -- + -- Illumination bombs are fired between 500 and 700 meters altitude and will burn about 2 minutes, while slowly decending. + -- Each available recce within range will fire an illumination bomb. + -- Illumination bombs can be fired in while lasing targets. + -- When illumination bombs are fired, it will take about 2 minutes until a sequent bomb run can be requested using the menus. + -- + -- ### 0.5. Smoking Targets + -- + -- ![Banner Image](..\Presentations\DESIGNATE\Dia9.JPG) + -- + -- Smoke will fire for 5 minutes. + -- Each available recce within range will smoke a target. + -- Smoking can be requested while lasing targets. + -- Smoke will appear “around” the targets, because of accuracy limitations. + -- -- -- Have FUN! -- From 296d1dbc2bcd1288843984386c779511ecb9b7f6 Mon Sep 17 00:00:00 2001 From: FlightControl_Master Date: Mon, 12 Mar 2018 10:48:38 +0100 Subject: [PATCH 6/7] Rework of missions --- Moose Development/Moose/Functional/Designate.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Moose Development/Moose/Functional/Designate.lua b/Moose Development/Moose/Functional/Designate.lua index dfc42c136..37e28ba58 100644 --- a/Moose Development/Moose/Functional/Designate.lua +++ b/Moose Development/Moose/Functional/Designate.lua @@ -189,7 +189,7 @@ do -- DESIGNATE -- -- ## 2. DESIGNATE is a FSM -- - -- ![Process](..\Presentations\DESIGNATE\Dia2.JPG) + -- Designate is a finite state machine, which allows for controlled transitions of states. -- -- ### 2.1 DESIGNATE States -- From f82a0c092a59a8241771bc423c349ecd01243209 Mon Sep 17 00:00:00 2001 From: FlightControl_Master Date: Mon, 12 Mar 2018 10:57:18 +0100 Subject: [PATCH 7/7] Fix of picture in docs. --- Moose Development/Moose/Functional/Designate.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Moose Development/Moose/Functional/Designate.lua b/Moose Development/Moose/Functional/Designate.lua index 37e28ba58..ba258dc8b 100644 --- a/Moose Development/Moose/Functional/Designate.lua +++ b/Moose Development/Moose/Functional/Designate.lua @@ -164,7 +164,7 @@ do -- DESIGNATE -- -- ### 0.4. Illuminating Targets -- - -- ![Banner Image](..\Presentations\DESIGNATE\Dia8.JPG) + -- ![Banner Image](..\Presentations\DESIGNATE\Dia9.JPG) -- -- Illumination bombs are fired between 500 and 700 meters altitude and will burn about 2 minutes, while slowly decending. -- Each available recce within range will fire an illumination bomb. @@ -173,7 +173,7 @@ do -- DESIGNATE -- -- ### 0.5. Smoking Targets -- - -- ![Banner Image](..\Presentations\DESIGNATE\Dia9.JPG) + -- ![Banner Image](..\Presentations\DESIGNATE\Dia10.JPG) -- -- Smoke will fire for 5 minutes. -- Each available recce within range will smoke a target.