Merge branch 'develop' into FF/Ops
2
.github/workflows/gh-pages.yml
vendored
@ -75,4 +75,4 @@ jobs:
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v3
|
||||
- run: npm install linkinator
|
||||
- run: npx linkinator https://flightcontrol-master.github.io/MOOSE/ --verbosity error --timeout 5000 --recurse --skip "(java.com)"
|
||||
- run: npx linkinator https://flightcontrol-master.github.io/MOOSE/ --verbosity error --timeout 5000 --recurse --skip "(java.com)" --retry-errors --retry-errors-count 3 --retry-errors-jitter
|
||||
|
||||
@ -261,6 +261,15 @@ EVENTS = {
|
||||
SimulationStart = world.event.S_EVENT_SIMULATION_START or -1,
|
||||
WeaponRearm = world.event.S_EVENT_WEAPON_REARM or -1,
|
||||
WeaponDrop = world.event.S_EVENT_WEAPON_DROP or -1,
|
||||
-- Added with DCS 2.9.0
|
||||
UnitTaskTimeout = world.event.S_EVENT_UNIT_TASK_TIMEOUT or -1,
|
||||
UnitTaskStage = world.event.S_EVENT_UNIT_TASK_STAGE or -1,
|
||||
MacSubtaskScore = world.event.S_EVENT_MAC_SUBTASK_SCORE or -1,
|
||||
MacExtraScore = world.event.S_EVENT_MAC_EXTRA_SCORE or -1,
|
||||
MissionRestart = world.event.S_EVENT_MISSION_RESTART or -1,
|
||||
MissionWinner = world.event.S_EVENT_MISSION_WINNER or -1,
|
||||
PostponedTakeoff = world.event.S_EVENT_POSTPONED_TAKEOFF or -1,
|
||||
PostponedLand = world.event.S_EVENT_POSTPONED_LAND or -1,
|
||||
}
|
||||
|
||||
--- The Event structure
|
||||
@ -636,6 +645,55 @@ local _EVENTMETA = {
|
||||
Event = "OnEventWeaponDrop",
|
||||
Text = "S_EVENT_WEAPON_DROP"
|
||||
},
|
||||
-- DCS 2.9
|
||||
[EVENTS.UnitTaskTimeout] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventUnitTaskTimeout",
|
||||
Text = "S_EVENT_UNIT_TASK_TIMEOUT "
|
||||
},
|
||||
[EVENTS.UnitTaskStage] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventUnitTaskStage",
|
||||
Text = "S_EVENT_UNIT_TASK_STAGE "
|
||||
},
|
||||
[EVENTS.MacSubtaskScore] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventMacSubtaskScore",
|
||||
Text = "S_EVENT_MAC_SUBTASK_SCORE"
|
||||
},
|
||||
[EVENTS.MacExtraScore] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventMacExtraScore",
|
||||
Text = "S_EVENT_MAC_EXTRA_SCOREP"
|
||||
},
|
||||
[EVENTS.MissionRestart] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventMissionRestart",
|
||||
Text = "S_EVENT_MISSION_RESTART"
|
||||
},
|
||||
[EVENTS.MissionWinner] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventMissionWinner",
|
||||
Text = "S_EVENT_MISSION_WINNER"
|
||||
},
|
||||
[EVENTS.PostponedTakeoff] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventPostponedTakeoff",
|
||||
Text = "S_EVENT_POSTPONED_TAKEOFF"
|
||||
},
|
||||
[EVENTS.PostponedLand] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventPostponedLand",
|
||||
Text = "S_EVENT_POSTPONED_LAND"
|
||||
},
|
||||
}
|
||||
|
||||
--- The Events structure
|
||||
@ -1245,11 +1303,14 @@ function EVENT:onEvent( Event )
|
||||
Event.TgtDCSUnit = Event.target
|
||||
if Event.target:isExist() and Event.id ~= 33 then -- leave out ejected seat object
|
||||
Event.TgtDCSUnitName = Event.TgtDCSUnit:getName()
|
||||
Event.TgtUnitName = Event.TgtDCSUnitName
|
||||
Event.TgtUnit = STATIC:FindByName( Event.TgtDCSUnitName, false )
|
||||
Event.TgtCoalition = Event.TgtDCSUnit:getCoalition()
|
||||
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category
|
||||
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName()
|
||||
-- Workaround for borked target info on cruise missiles
|
||||
if Event.TgtDCSUnitName and Event.TgtDCSUnitName ~= "" then
|
||||
Event.TgtUnitName = Event.TgtDCSUnitName
|
||||
Event.TgtUnit = STATIC:FindByName( Event.TgtDCSUnitName, false )
|
||||
Event.TgtCoalition = Event.TgtDCSUnit:getCoalition()
|
||||
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category
|
||||
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName()
|
||||
end
|
||||
else
|
||||
Event.TgtDCSUnitName = string.format("No target object for Event ID %s", tostring(Event.id))
|
||||
Event.TgtUnitName = Event.TgtDCSUnitName
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
-- @module Functional.Mantis
|
||||
-- @image Functional.Mantis.jpg
|
||||
--
|
||||
-- Last Update: Oct 2023
|
||||
-- Last Update: Nov 2023
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
--- **MANTIS** class, extends Core.Base#BASE
|
||||
@ -799,12 +799,16 @@ do
|
||||
-- @param #MANTIS self
|
||||
-- @param Core.Set#SET_ZONE ZoneSet Set of zones to be used. Units will move around to the next (random) zone between 100m and 3000m away.
|
||||
-- @param #number Number Number of closest zones to be considered, defaults to 3.
|
||||
-- @param #boolean Random If true, use a random coordinate inside the next zone to scoot to.
|
||||
-- @param #string Formation Formation to use, defaults to "Cone". See mission editor dropdown for options.
|
||||
-- @return #MANTIS self
|
||||
function MANTIS:AddScootZones(ZoneSet, Number)
|
||||
function MANTIS:AddScootZones(ZoneSet, Number, Random, Formation)
|
||||
self:T(self.lid .. " AddScootZones")
|
||||
self.SkateZones = ZoneSet
|
||||
self.SkateNumber = Number or 3
|
||||
self.shootandscoot = true
|
||||
self.shootandscoot = true
|
||||
self.ScootRandom = Random
|
||||
self.ScootFormation = Formation or "Cone"
|
||||
return self
|
||||
end
|
||||
|
||||
@ -1809,8 +1813,8 @@ do
|
||||
self.Shorad.Groupset=self.ShoradGroupSet
|
||||
self.Shorad.debug = self.debug
|
||||
end
|
||||
if self.shootandscoot and self.SkateZones then
|
||||
self.Shorad:AddScootZones(self.SkateZones,self.SkateNumber or 3)
|
||||
if self.shootandscoot and self.SkateZones and self.Shorad then
|
||||
self.Shorad:AddScootZones(self.SkateZones,self.SkateNumber or 3,self.ScootRandom,self.ScootFormation)
|
||||
end
|
||||
self:__Status(-math.random(1,10))
|
||||
return self
|
||||
|
||||
@ -41,10 +41,14 @@
|
||||
-- @field #boolean DefendMavs Default true, intercept incoming AG-Missiles
|
||||
-- @field #number DefenseLowProb Default 70, minimum detection limit
|
||||
-- @field #number DefenseHighProb Default 90, maximum detection limit
|
||||
-- @field #boolean UseEmOnOff Decide if we are using Emission on/off (default) or AlarmState red/green.
|
||||
-- @field #boolean shootandscoot
|
||||
-- @field #number SkateNumber
|
||||
-- @field Core.Set#SET_ZONE SkateZones
|
||||
-- @field #boolean UseEmOnOff Decide if we are using Emission on/off (default) or AlarmState red/green
|
||||
-- @field #boolean shootandscoot If true, shoot and scoot between zones
|
||||
-- @field #number SkateNumber Number of zones to consider
|
||||
-- @field Core.Set#SET_ZONE SkateZones Zones in this set are considered
|
||||
-- @field #number minscootdist Min distance of the next zone
|
||||
-- @field #number maxscootdist Max distance of the next zone
|
||||
-- @field #boolean scootrandomcoord If true, use a random coordinate in the zone and not the center
|
||||
-- @field #string scootformation Formation to take for scooting, e.g. "Vee" or "Cone"
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
|
||||
@ -77,14 +81,15 @@
|
||||
--
|
||||
-- `myshorad = SHORAD:New("RedShorad", "Red SHORAD", SamSet, 25000, 600, "red")`
|
||||
--
|
||||
-- ## Customize options
|
||||
-- ## Customization options
|
||||
--
|
||||
-- * SHORAD:SwitchDebug(debug)
|
||||
-- * SHORAD:SwitchHARMDefense(onoff)
|
||||
-- * SHORAD:SwitchAGMDefense(onoff)
|
||||
-- * SHORAD:SetDefenseLimits(low,high)
|
||||
-- * SHORAD:SetActiveTimer(seconds)
|
||||
-- * SHORAD:SetDefenseRadius(meters)
|
||||
-- * myshorad:SwitchDebug(debug)
|
||||
-- * myshorad:SwitchHARMDefense(onoff)
|
||||
-- * myshorad:SwitchAGMDefense(onoff)
|
||||
-- * myshorad:SetDefenseLimits(low,high)
|
||||
-- * myshorad:SetActiveTimer(seconds)
|
||||
-- * myshorad:SetDefenseRadius(meters)
|
||||
-- * myshorad:AddScootZones(ZoneSet,Number,Random,Formation)
|
||||
--
|
||||
-- @field #SHORAD
|
||||
SHORAD = {
|
||||
@ -107,6 +112,9 @@ SHORAD = {
|
||||
shootandscoot = false,
|
||||
SkateNumber = 3,
|
||||
SkateZones = nil,
|
||||
minscootdist = 100,
|
||||
minscootdist = 3000,
|
||||
scootrandomcoord = false,
|
||||
}
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
@ -174,7 +182,7 @@ do
|
||||
self.DefenseHighProb = 90 -- probability to detect a missile shot, high margin
|
||||
self.UseEmOnOff = true -- Decide if we are using Emission on/off (default) or AlarmState red/green
|
||||
if UseEmOnOff == false then self.UseEmOnOff = UseEmOnOff end
|
||||
self:I("*** SHORAD - Started Version 0.3.2")
|
||||
self:I("*** SHORAD - Started Version 0.3.4")
|
||||
-- Set the string id for output to DCS.log file.
|
||||
self.lid=string.format("SHORAD %s | ", self.name)
|
||||
self:_InitState()
|
||||
@ -219,12 +227,16 @@ do
|
||||
-- @param #SHORAD self
|
||||
-- @param Core.Set#SET_ZONE ZoneSet Set of zones to be used. Units will move around to the next (random) zone between 100m and 3000m away.
|
||||
-- @param #number Number Number of closest zones to be considered, defaults to 3.
|
||||
-- @param #boolean Random If true, use a random coordinate inside the next zone to scoot to.
|
||||
-- @param #string Formation Formation to use, defaults to "Cone". See mission editor dropdown for options.
|
||||
-- @return #SHORAD self
|
||||
function SHORAD:AddScootZones(ZoneSet, Number)
|
||||
function SHORAD:AddScootZones(ZoneSet, Number, Random, Formation)
|
||||
self:T(self.lid .. " AddScootZones")
|
||||
self.SkateZones = ZoneSet
|
||||
self.SkateNumber = Number or 3
|
||||
self.shootandscoot = true
|
||||
self.shootandscoot = true
|
||||
self.scootrandomcoord = Random
|
||||
self.scootformation = Formation or "Cone"
|
||||
return self
|
||||
end
|
||||
|
||||
@ -613,8 +625,8 @@ do
|
||||
function SHORAD:onafterShootAndScoot(From,Event,To,Shorad)
|
||||
self:T( { From,Event,To } )
|
||||
local possibleZones = {}
|
||||
local mindist = 100
|
||||
local maxdist = 3000
|
||||
local mindist = self.minscootdist or 100
|
||||
local maxdist = self.maxscootdist or 3000
|
||||
if Shorad and Shorad:IsAlive() then
|
||||
local NowCoord = Shorad:GetCoordinate()
|
||||
for _,_zone in pairs(self.SkateZones.Set) do
|
||||
@ -630,7 +642,11 @@ do
|
||||
if rand == 0 then rand = 1 end
|
||||
self:T(self.lid .. " ShootAndScoot to zone "..rand)
|
||||
local ToCoordinate = possibleZones[rand]:GetCoordinate()
|
||||
Shorad:RouteGroundTo(ToCoordinate,20,"Cone",1)
|
||||
if self.scootrandomcoord then
|
||||
ToCoordinate = possibleZones[rand]:GetRandomCoordinate(nil,nil,{land.SurfaceType.LAND,land.SurfaceType.ROAD})
|
||||
end
|
||||
local formation = self.scootformation or "Cone"
|
||||
Shorad:RouteGroundTo(ToCoordinate,20,formation,1)
|
||||
end
|
||||
end
|
||||
return self
|
||||
@ -731,4 +747,4 @@ do
|
||||
end
|
||||
-----------------------------------------------------------------------
|
||||
-- SHORAD end
|
||||
-----------------------------------------------------------------------
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
-- @module Ops.CTLD
|
||||
-- @image OPS_CTLD.jpg
|
||||
|
||||
-- Last Update October 2023
|
||||
-- Last Update November 2023
|
||||
|
||||
do
|
||||
|
||||
@ -741,7 +741,7 @@ do
|
||||
--
|
||||
-- -- E.g. update unit capabilities for testing. Please stay realistic in your mission design.
|
||||
-- -- Make a Gazelle into a heavy truck, this type can load both crates and troops and eight of each type, up to 4000 kgs:
|
||||
-- my_ctld:UnitCapabilities("SA342L", true, true, 8, 8, 12, 4000)
|
||||
-- my_ctld:SetUnitCapabilities("SA342L", true, true, 8, 8, 12, 4000)
|
||||
--
|
||||
-- -- Default unit type capabilities are:
|
||||
-- ["SA342Mistral"] = {type="SA342Mistral", crates=false, troops=true, cratelimit = 0, trooplimit = 4, length = 12, cargoweightlimit = 400},
|
||||
@ -1200,14 +1200,14 @@ CTLD.CargoZoneType = {
|
||||
-- @field #CTLD_CARGO.Enum Type Type enumerator (for moves).
|
||||
|
||||
--- Unit capabilities.
|
||||
-- @type CTLD.UnitCapabilities
|
||||
-- @type CTLD.UnitTypeCapabilities
|
||||
-- @field #string type Unit type.
|
||||
-- @field #boolean crates Can transport crate.
|
||||
-- @field #boolean troops Can transport troops.
|
||||
-- @field #number cratelimit Number of crates transportable.
|
||||
-- @field #number trooplimit Number of troop units transportable.
|
||||
-- @field #number cargoweightlimit Max loadable kgs of cargo.
|
||||
CTLD.UnitTypes = {
|
||||
CTLD.UnitTypeCapabilities = {
|
||||
["SA342Mistral"] = {type="SA342Mistral", crates=false, troops=true, cratelimit = 0, trooplimit = 4, length = 12, cargoweightlimit = 400},
|
||||
["SA342L"] = {type="SA342L", crates=false, troops=true, cratelimit = 0, trooplimit = 2, length = 12, cargoweightlimit = 400},
|
||||
["SA342M"] = {type="SA342M", crates=false, troops=true, cratelimit = 0, trooplimit = 4, length = 12, cargoweightlimit = 400},
|
||||
@ -1228,7 +1228,7 @@ CTLD.UnitTypes = {
|
||||
|
||||
--- CTLD class version.
|
||||
-- @field #string version
|
||||
CTLD.version="1.0.41"
|
||||
CTLD.version="1.0.43"
|
||||
|
||||
--- Instantiate a new CTLD.
|
||||
-- @param #CTLD self
|
||||
@ -1293,6 +1293,8 @@ function CTLD:New(Coalition, Prefixes, Alias)
|
||||
self:AddTransition("*", "CratesDropped", "*") -- CTLD deploy event.
|
||||
self:AddTransition("*", "CratesBuild", "*") -- CTLD build event.
|
||||
self:AddTransition("*", "CratesRepaired", "*") -- CTLD repair event.
|
||||
self:AddTransition("*", "CratesBuildStarted", "*") -- CTLD build event.
|
||||
self:AddTransition("*", "CratesRepairStarted", "*") -- CTLD repair event.
|
||||
self:AddTransition("*", "Load", "*") -- CTLD load event.
|
||||
self:AddTransition("*", "Save", "*") -- CTLD save event.
|
||||
self:AddTransition("*", "Stop", "Stopped") -- Stop FSM.
|
||||
@ -1475,7 +1477,7 @@ function CTLD:New(Coalition, Prefixes, Alias)
|
||||
-- @param #CTLD self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
--- FSM Function OnBeforeTroopsPickedUp.
|
||||
--- FSM Function OnBeforeTroopsPickedUp.
|
||||
-- @function [parent=#CTLD] OnBeforeTroopsPickedUp
|
||||
-- @param #CTLD self
|
||||
-- @param #string From State.
|
||||
@ -1627,6 +1629,46 @@ function CTLD:New(Coalition, Prefixes, Alias)
|
||||
-- @param Wrapper.Group#GROUP Vehicle The #GROUP object of the vehicle or FOB build.
|
||||
-- @return #CTLD self
|
||||
|
||||
--- FSM Function OnAfterCratesBuildStarted. Info event that a build has been started.
|
||||
-- @function [parent=#CTLD] OnAfterCratesBuildStarted
|
||||
-- @param #CTLD self
|
||||
-- @param #string From State.
|
||||
-- @param #string Event Trigger.
|
||||
-- @param #string To State.
|
||||
-- @param Wrapper.Group#GROUP Group Group Object.
|
||||
-- @param Wrapper.Unit#UNIT Unit Unit Object.
|
||||
-- @return #CTLD self
|
||||
|
||||
--- FSM Function OnAfterCratesRepairStarted. Info event that a repair has been started.
|
||||
-- @function [parent=#CTLD] OnAfterCratesRepairStarted
|
||||
-- @param #CTLD self
|
||||
-- @param #string From State.
|
||||
-- @param #string Event Trigger.
|
||||
-- @param #string To State.
|
||||
-- @param Wrapper.Group#GROUP Group Group Object.
|
||||
-- @param Wrapper.Unit#UNIT Unit Unit Object.
|
||||
-- @return #CTLD self
|
||||
|
||||
--- FSM Function OnBeforeCratesBuildStarted. Info event that a build has been started.
|
||||
-- @function [parent=#CTLD] OnBeforeCratesBuildStarted
|
||||
-- @param #CTLD self
|
||||
-- @param #string From State.
|
||||
-- @param #string Event Trigger.
|
||||
-- @param #string To State.
|
||||
-- @param Wrapper.Group#GROUP Group Group Object.
|
||||
-- @param Wrapper.Unit#UNIT Unit Unit Object.
|
||||
-- @return #CTLD self
|
||||
|
||||
--- FSM Function OnBeforeCratesRepairStarted. Info event that a repair has been started.
|
||||
-- @function [parent=#CTLD] OnBeforeCratesRepairStarted
|
||||
-- @param #CTLD self
|
||||
-- @param #string From State.
|
||||
-- @param #string Event Trigger.
|
||||
-- @param #string To State.
|
||||
-- @param Wrapper.Group#GROUP Group Group Object.
|
||||
-- @param Wrapper.Unit#UNIT Unit Unit Object.
|
||||
-- @return #CTLD self
|
||||
|
||||
--- FSM Function OnAfterCratesRepaired.
|
||||
-- @function [parent=#CTLD] OnAfterCratesRepaired
|
||||
-- @param #CTLD self
|
||||
@ -1680,7 +1722,7 @@ function CTLD:_GetUnitCapabilities(Unit)
|
||||
self:T(self.lid .. " _GetUnitCapabilities")
|
||||
local _unit = Unit -- Wrapper.Unit#UNIT
|
||||
local unittype = _unit:GetTypeName()
|
||||
local capabilities = self.UnitTypes[unittype] -- #CTLD.UnitCapabilities
|
||||
local capabilities = self.UnitTypeCapabilities[unittype] -- #CTLD.UnitTypeCapabilities
|
||||
if not capabilities or capabilities == {} then
|
||||
-- e.g. ["Ka-50"] = {type="Ka-50", crates=false, troops=false, cratelimit = 0, trooplimit = 0},
|
||||
capabilities = {}
|
||||
@ -1871,7 +1913,7 @@ function CTLD:_PreloadCrates(Group, Unit, Cargo, NumberOfCrates)
|
||||
local unitname = unit:GetName()
|
||||
-- see if this heli can load crates
|
||||
local unittype = unit:GetTypeName()
|
||||
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitCapabilities
|
||||
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitTypeCapabilities
|
||||
local cancrates = capabilities.crates -- #boolean
|
||||
local cratelimit = capabilities.cratelimit -- #number
|
||||
if not cancrates then
|
||||
@ -2124,6 +2166,7 @@ function CTLD:_RepairObjectFromCrates(Group,Unit,Crates,Build,Number,Engineering
|
||||
desttimer:Start(self.repairtime - 1)
|
||||
local buildtimer = TIMER:New(self._BuildObjectFromCrates,self,Group,Unit,object,true,NearestGroup:GetCoordinate())
|
||||
buildtimer:Start(self.repairtime)
|
||||
self:__CratesRepairStarted(1,Group,Unit)
|
||||
else
|
||||
if not Engineering then
|
||||
self:_SendMessage("Can't repair this unit with " .. build.Name, 10, false, Group)
|
||||
@ -2308,7 +2351,7 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack)
|
||||
end
|
||||
|
||||
-- avoid crate spam
|
||||
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitCapabilities
|
||||
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitTypeCapabilities
|
||||
local canloadcratesno = capabilities.cratelimit
|
||||
local loaddist = self.CrateDistance or 35
|
||||
local nearcrates, numbernearby = self:_FindCratesNearby(Group,Unit,loaddist,true)
|
||||
@ -2601,8 +2644,8 @@ function CTLD:_LoadCratesNearby(Group, Unit)
|
||||
local unitname = unit:GetName()
|
||||
-- see if this heli can load crates
|
||||
local unittype = unit:GetTypeName()
|
||||
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitCapabilities
|
||||
--local capabilities = self.UnitTypes[unittype] -- #CTLD.UnitCapabilities
|
||||
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitTypeCapabilities
|
||||
--local capabilities = self.UnitTypeCapabilities[unittype] -- #CTLD.UnitTypeCapabilities
|
||||
local cancrates = capabilities.crates -- #boolean
|
||||
local cratelimit = capabilities.cratelimit -- #number
|
||||
local grounded = not self:IsUnitInAir(Unit)
|
||||
@ -2753,7 +2796,7 @@ function CTLD:_GetMaxLoadableMass(Unit)
|
||||
if not Unit then return 0 end
|
||||
local loadable = 0
|
||||
local loadedmass = self:_GetUnitCargoMass(Unit)
|
||||
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitCapabilities
|
||||
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitTypeCapabilities
|
||||
local maxmass = capabilities.cargoweightlimit or 2000 -- max 2 tons
|
||||
loadable = maxmass - loadedmass
|
||||
return loadable
|
||||
@ -2778,7 +2821,7 @@ function CTLD:_ListCargo(Group, Unit)
|
||||
self:T(self.lid .. " _ListCargo")
|
||||
local unitname = Unit:GetName()
|
||||
local unittype = Unit:GetTypeName()
|
||||
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitCapabilities
|
||||
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitTypeCapabilities
|
||||
local trooplimit = capabilities.trooplimit -- #boolean
|
||||
local cratelimit = capabilities.cratelimit -- #number
|
||||
local loadedcargo = self.Loaded_Cargo[unitname] or {} -- #CTLD.LoadedCargo
|
||||
@ -3226,6 +3269,7 @@ function CTLD:_BuildCrates(Group, Unit,Engineering)
|
||||
local buildtimer = TIMER:New(self._BuildObjectFromCrates,self,Group,Unit,build,false,Group:GetCoordinate())
|
||||
buildtimer:Start(self.buildtime)
|
||||
self:_SendMessage(string.format("Build started, ready in %d seconds!",self.buildtime),15,false,Group)
|
||||
self:__CratesBuildStarted(1,Group,Unit)
|
||||
else
|
||||
self:_BuildObjectFromCrates(Group,Unit,build)
|
||||
end
|
||||
@ -3536,13 +3580,19 @@ function CTLD:_RefreshF10Menus()
|
||||
if _group then
|
||||
-- get chopper capabilities
|
||||
local unittype = _unit:GetTypeName()
|
||||
local capabilities = self:_GetUnitCapabilities(_unit) -- #CTLD.UnitCapabilities
|
||||
local capabilities = self:_GetUnitCapabilities(_unit) -- #CTLD.UnitTypeCapabilities
|
||||
local cantroops = capabilities.troops
|
||||
local cancrates = capabilities.crates
|
||||
-- top menu
|
||||
local topmenu = MENU_GROUP:New(_group,"CTLD",nil)
|
||||
local toptroops = MENU_GROUP:New(_group,"Manage Troops",topmenu)
|
||||
local topcrates = MENU_GROUP:New(_group,"Manage Crates",topmenu)
|
||||
local toptroops = nil
|
||||
local topcrates = nil
|
||||
if cantroops then
|
||||
toptroops = MENU_GROUP:New(_group,"Manage Troops",topmenu)
|
||||
end
|
||||
if cancrates then
|
||||
topcrates = MENU_GROUP:New(_group,"Manage Crates",topmenu)
|
||||
end
|
||||
local listmenu = MENU_GROUP_COMMAND:New(_group,"List boarded cargo",topmenu, self._ListCargo, self, _group, _unit)
|
||||
local invtry = MENU_GROUP_COMMAND:New(_group,"Inventory",topmenu, self._ListInventory, self, _group, _unit)
|
||||
local rbcns = MENU_GROUP_COMMAND:New(_group,"List active zone beacons",topmenu, self._ListRadioBeacons, self, _group, _unit)
|
||||
@ -4339,7 +4389,7 @@ end
|
||||
-- @param #number Trooplimit Unit can carry number of troops. Default 0.
|
||||
-- @param #number Length Unit lenght (in metres) for the load radius. Default 20.
|
||||
-- @param #number Maxcargoweight Maxmimum weight in kgs this helo can carry. Default 500.
|
||||
function CTLD:UnitCapabilities(Unittype, Cancrates, Cantroops, Cratelimit, Trooplimit, Length, Maxcargoweight)
|
||||
function CTLD:SetUnitCapabilities(Unittype, Cancrates, Cantroops, Cratelimit, Trooplimit, Length, Maxcargoweight)
|
||||
self:T(self.lid .. " UnitCapabilities")
|
||||
local unittype = nil
|
||||
local unit = nil
|
||||
@ -4353,13 +4403,13 @@ end
|
||||
end
|
||||
local length = 20
|
||||
local maxcargo = 500
|
||||
local existingcaps = self.UnitTypes[unittype] -- #CTLD.UnitCapabilities
|
||||
local existingcaps = self.UnitTypeCapabilities[unittype] -- #CTLD.UnitTypeCapabilities
|
||||
if existingcaps then
|
||||
length = existingcaps.length or 20
|
||||
maxcargo = existingcaps.cargoweightlimit or 500
|
||||
end
|
||||
-- set capabilities
|
||||
local capabilities = {} -- #CTLD.UnitCapabilities
|
||||
local capabilities = {} -- #CTLD.UnitTypeCapabilities
|
||||
capabilities.type = unittype
|
||||
capabilities.crates = Cancrates or false
|
||||
capabilities.troops = Cantroops or false
|
||||
@ -4367,10 +4417,26 @@ end
|
||||
capabilities.trooplimit = Trooplimit or 0
|
||||
capabilities.length = Length or length
|
||||
capabilities.cargoweightlimit = Maxcargoweight or maxcargo
|
||||
self.UnitTypes[unittype] = capabilities
|
||||
self.UnitTypeCapabilities[unittype] = capabilities
|
||||
return self
|
||||
end
|
||||
|
||||
--- [Deprecated] - Function to add/adjust unittype capabilities. Has been replaced with `SetUnitCapabilities()` - pls use the new one going forward!
|
||||
-- @param #CTLD self
|
||||
-- @param #string Unittype The unittype to adjust. If passed as Wrapper.Unit#UNIT, it will search for the unit in the mission.
|
||||
-- @param #boolean Cancrates Unit can load crates. Default false.
|
||||
-- @param #boolean Cantroops Unit can load troops. Default false.
|
||||
-- @param #number Cratelimit Unit can carry number of crates. Default 0.
|
||||
-- @param #number Trooplimit Unit can carry number of troops. Default 0.
|
||||
-- @param #number Length Unit lenght (in metres) for the load radius. Default 20.
|
||||
-- @param #number Maxcargoweight Maxmimum weight in kgs this helo can carry. Default 500.
|
||||
function CTLD:UnitCapabilities(Unittype, Cancrates, Cantroops, Cratelimit, Trooplimit, Length, Maxcargoweight)
|
||||
self:I(self.lid.."This function been replaced with `SetUnitCapabilities()` - pls use the new one going forward!")
|
||||
self:SetUnitCapabilities(Unittype, Cancrates, Cantroops, Cratelimit, Trooplimit, Length, Maxcargoweight)
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- (Internal) Check if a unit is hovering *in parameters*.
|
||||
-- @param #CTLD self
|
||||
-- @param Wrapper.Unit#UNIT Unit
|
||||
@ -4523,7 +4589,7 @@ end
|
||||
local unittype = Unit:GetTypeName()
|
||||
local unitname = Unit:GetName()
|
||||
local Group = Unit:GetGroup()
|
||||
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitCapabilities
|
||||
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitTypeCapabilities
|
||||
local cancrates = capabilities.crates -- #boolean
|
||||
local cratelimit = capabilities.cratelimit -- #number
|
||||
if cancrates then
|
||||
|
||||
9
docs/beginner/hello-world-build.md
Normal file
@ -0,0 +1,9 @@
|
||||
---
|
||||
parent: Beginner
|
||||
nav_order: 03
|
||||
---
|
||||
|
||||
# Create your own Hello world
|
||||
|
||||
{: .warning }
|
||||
> THIS DOCUMENT IS STILL WORK IN PROGRESS!
|
||||
178
docs/beginner/hello-world.md
Normal file
@ -0,0 +1,178 @@
|
||||
---
|
||||
parent: Beginner
|
||||
nav_order: 02
|
||||
---
|
||||
|
||||
# Hello world mission
|
||||
{: .no_toc }
|
||||
|
||||
1. Table of contents
|
||||
{:toc}
|
||||
|
||||
## Let's see MOOSE in action
|
||||
|
||||
It is tradition that the first piece of code is a very simple example on showing
|
||||
a "Hello world!" to the user. We have prepared this example mission for you. So
|
||||
you can download and run it. Later on we will analyze it to explain the basics
|
||||
on how to add MOOSE to your own missions.
|
||||
|
||||
- Download the demo mission [001-hello-world.miz] by clicking on the link.
|
||||
- Put the .miz file into your Missions subfolder of your [Saved Games folder].
|
||||
- Start DCS, choose `MISSION` in the menu on the right side:
|
||||
|
||||

|
||||
|
||||
- Click on `My Missions`, choose the `hello-world` mission and click on `OK`.
|
||||
|
||||

|
||||
|
||||
- It is an empty mission, so skip `BRIEFING` with `START` and then `FLY`.
|
||||
- You spawn as a spectator. After some seconds you will see this message in
|
||||
the upper right corner:
|
||||
|
||||

|
||||
|
||||
Ok, that's all. There is nothing more to see in this mission. This is not
|
||||
particularly impressive and can also be achieved using standard Lua in DCS
|
||||
(i.e. without MOOSE), but we want to keep it simple at the beginning.
|
||||
|
||||
{: .note }
|
||||
> If the text don't show up, the mission might be corrupted. Please contact the
|
||||
> team on Discord for futher instructions.
|
||||
|
||||
## Let's take a look under the hood
|
||||
|
||||
- Go back to the main window and open the `MISSION EDITOR`.
|
||||
- Choose `open mission` navigate to `My Missions` and open 001-hello-world.miz.
|
||||
- On the left side activate `TRIGGERS`:
|
||||
|
||||

|
||||
|
||||
- On the right side the `TRIGGERS` dialog opens with a lot of options.
|
||||
- First take a look at the available triggers:
|
||||
|
||||

|
||||
|
||||
- You will see two:
|
||||
- One in yellow with type `4 MISSION START` and name `Load MOOSE` and
|
||||
- one in green with type `1 ONCE` and name `Load Mission Script`.
|
||||
|
||||
### Execution of Moose
|
||||
|
||||
- Click on the yellow one to show all of it options.
|
||||
|
||||
- In the middle part the `CONDITIONS` will be shown.
|
||||
For this trigger there are no conditions configured.
|
||||
|
||||

|
||||
|
||||
{: .important }
|
||||
> The trigger type `4 MISSION START` does not support `CONDITIONS`. <br />
|
||||
> So `CONDITIONS` must left blank when using it. <br />
|
||||
> **If you add a condition the trigger will never be executed!**
|
||||
|
||||
- On the right side the `ACTIONS` will be shown:
|
||||
|
||||

|
||||
|
||||
- A `DO SCRIPT FILE` is configured, which executes the file `Moose_.lua`
|
||||
|
||||
{: .highlight }
|
||||
> This is the execution of the Moose framework included in the mission as one single file. <br />
|
||||
> The difference between `Moose_.lua` and `Moose.lua` will be explained later. <br />
|
||||
> This doesn't matter at this time.
|
||||
|
||||
{: .important }
|
||||
> The trigger `4 MISSION START` will be executed **before** the mission is started! <br />
|
||||
> This is important, because Moose **must** be executed before other scripts, that want to use Moose!
|
||||
|
||||
### Execution of the mission script
|
||||
|
||||
- Now move back to the left `TRIGGERS` area and click on the green trigger <br />
|
||||
`1 ONCE (Load Mission Script ...)`
|
||||
|
||||

|
||||
|
||||
- The configured options will be shown. <br />
|
||||
In the middle part the `CONDITIONS` will be shown. <br />
|
||||
For this trigger there is one condition configured:
|
||||
|
||||

|
||||
|
||||
- The combination of `1 ONCE` with `TIME MORE(1)` will ensure, that the mission
|
||||
script is executed 1 second after the mission is started.
|
||||
|
||||
- On the right side the `ACTIONS` will be shown:
|
||||
|
||||

|
||||
|
||||
- A `DO SCRIPT FILE` is configured, which executes the file `001-hello-world.lua`.
|
||||
|
||||
{: .highlight }
|
||||
> This is the execution of the mission script, which you will create in the future.
|
||||
|
||||
{: .important }
|
||||
> Most important is the fact, that the mission script (`001-hello-world.lua`)
|
||||
> is executed **after** `Moose_.lua`, because the mission script needs the
|
||||
> classes defined in `Moose_.lua`. And they are only available when `Moose_.lua`
|
||||
> is executed before the mission script.
|
||||
|
||||
### Inspect the code of the mission script
|
||||
|
||||
The file `001-hello-world.lua` consists of following code:
|
||||
|
||||
```lua
|
||||
--
|
||||
-- Simple example mission to show the very basics of MOOSE
|
||||
--
|
||||
MESSAGE:New( "Hello World! This messages is printed by MOOSE", 35, "INFO" ):ToAll()
|
||||
```
|
||||
|
||||
- The first three lines starting with `--` are comments and will be ignored.
|
||||
|
||||
- Line 4 is the one with the "magic":
|
||||
|
||||
- With `MESSAGE` we use the class [Core.Message].
|
||||
|
||||
The part before the dot (Core) is the section where the class is placed.
|
||||
It is important for the Moose programmes to have a structure where the classes
|
||||
are placed. But in the code itself it is not used.
|
||||
|
||||
#### What is a class?
|
||||
|
||||
{: .highlight }
|
||||
> In object-oriented programming, a class is an extensible program-code-template
|
||||
> for creating objects, providing initial values for state (member variables)
|
||||
> and implementations of behavior (member functions or methods). <br />
|
||||
> *Source [Wikipedia:Class]{:target="_blank"}*
|
||||
|
||||
After the class name we call a method of that class. We do this with semicolon
|
||||
followed by the name of the method and a pair of round brackets.
|
||||
Here we call the method `New`, which creates a new MESSAGE object.
|
||||
|
||||
We give it three parameters within the round brackets, which are divided by commas:
|
||||
1. The text we want to show: `"Hello World! ..."`
|
||||
1. The time in seconds the messages should be visible: `35`
|
||||
1. And the type of message: `"INFO"`
|
||||
|
||||
- With `New` the MESSAGE object is created, but the message is still not printed
|
||||
to the screen.
|
||||
- This is done by `:ToAll()`. Another method of [Core.Message] which sends the
|
||||
message to all players, no matter if they belong to the RED or BLUE coalition.
|
||||
|
||||
If you you want to read more about [Core.Message] click on the link.
|
||||
The page with all the Methods and Fields is very long and this might be
|
||||
daunting, but for the copy and paste approach, you won't need it often.
|
||||
|
||||
And if you want to learn how to use more of that stuff, you will become
|
||||
compftable in filtering these informations fast.
|
||||
|
||||
## Next step
|
||||
|
||||
Now it is time to [create your own Hello world] mission.
|
||||
|
||||
[Saved Games folder]: ../beginner/tipps-and-tricks.md#find-the-saved-games-folder
|
||||
[hello-world demo mission]: https://raw.githubusercontent.com/FlightControl-Master/MOOSE_MISSIONS/master/Core/Message/001-hello-world.miz
|
||||
[Core.Message]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Core.Message.html
|
||||
[Wikipedia:Class]: https://en.wikipedia.org/wiki/Class_(computer_programming)
|
||||
[create your own Hello world]: hello-world-build.md
|
||||
106
docs/beginner/introduction.md
Normal file
@ -0,0 +1,106 @@
|
||||
---
|
||||
parent: Beginner
|
||||
nav_order: 01
|
||||
---
|
||||
# Introduction
|
||||
{: .no_toc }
|
||||
|
||||
1. Table of contents
|
||||
{:toc}
|
||||
|
||||
This very short chapter is for people identifying as a consumer of MOOSE and not
|
||||
wishing to learn to script. This is a condensed FAQ and set of links to get you
|
||||
up and running. It specifically avoids any complexity.
|
||||
|
||||
## What is MOOSE?
|
||||
|
||||
[DCS] has included a [Simulator Scripting Engine] (short SSE). This SSE gives
|
||||
mission designers access to objects in the game using [Lua] scripts.
|
||||
|
||||
**M**ission **O**bject **O**riented **S**cripting **E**nvironment, is a
|
||||
scripting framework written in [Lua] that attempts to make the scripting of
|
||||
missions within DCS easier, simpler and shorter than with the standard methods.
|
||||
|
||||
MOOSE is over 5 MB of code, with as many words as the Bible and the core of it
|
||||
was written over several years by one person.
|
||||
|
||||
MOOSE is the brain-child of an talented programmer with the alias FlightControl.
|
||||
If you want to know more about this topic, check out FC’s [MOOSE for Dummies]
|
||||
videos on YouTube.
|
||||
|
||||
{: .note }
|
||||
> We recommend video playback at 1.5x speed, as FC speaks slowly and distinctly.
|
||||
|
||||
## What is Lua?
|
||||
|
||||
[Lua] is a lightweight, programming language designed primarily to be embedded
|
||||
in applications. It's main advantages are:
|
||||
|
||||
- It is fast,
|
||||
- it is portabel (Windows, Linux, MacOS),
|
||||
- it is easy to use.
|
||||
|
||||
[Lua] is embedded in DCS, so we can use it without any modifacation to the game.
|
||||
|
||||
## What is are scripts, frameworks and classes?
|
||||
|
||||
A script is a set of instructions in plain text read by a computer and processed
|
||||
on the fly. Scripts do not need to be compiled before execution, unlike exe
|
||||
files.
|
||||
|
||||
A framework is a structure that you can build software (or in this case missions)
|
||||
on. It serves as a foundation, so you're not starting entirely from scratch.
|
||||
It takes a lot of work off your hands because someone else has thought about it
|
||||
and provides ready-made building blocks for many situations.
|
||||
|
||||
These building blocks are called classes in object oriented programming.
|
||||
|
||||
## What can MOOSE do for me?
|
||||
|
||||
Whilst MOOSE can be used to write customised [Lua] scripts, you are probably not
|
||||
caring for learning [Lua] right now. Instead you can use a MOOSE script written
|
||||
by someone else by just copy and paste it. You can configure the basic settings
|
||||
of the classes to fit your needs in your mission.
|
||||
|
||||
Here are a few suggestions for well-known and popular classes:
|
||||
|
||||
- [Ops.Airboss] manages recoveries of human pilots and AI aircraft on aircraft
|
||||
carriers.
|
||||
- [Functional.RAT] creates random airtraffic in your missions.
|
||||
- [Functional.Range] (which counts hits on targets so you can practice),
|
||||
- [Functional.Fox] to practice to evade missiles without being destroyed.
|
||||
- and many more!
|
||||
|
||||
You will need to look through examples to know what functionallity you want to
|
||||
add to your missions.
|
||||
|
||||
## What if I don’t want to learn scripting?
|
||||
|
||||
The good news for you: You don't need to become a professional [Lua] programmer
|
||||
to use MOOSE. As explained already, you can copy and paste the code from example
|
||||
missions. You need some basics how to add triggers in the mission editor. But we
|
||||
will cover this later.
|
||||
|
||||
If you want to modify the behaviour of the classes slightly, some basics about
|
||||
the [Lua] synthax (the rules how to write the code) will help you to avoid
|
||||
errors.
|
||||
|
||||
The more customizations you want to make, the more knowledge about [Lua] you
|
||||
will need. But you can learn this step by step.
|
||||
|
||||
## Next step
|
||||
|
||||
We will start with a very simple demonstartion of MOOSE in the next section
|
||||
[Hello world mission].
|
||||
|
||||
[DCS]: https://www.digitalcombatsimulator.com/en/
|
||||
[Simulator Scripting Engine]: https://wiki.hoggitworld.com/view/Simulator_Scripting_Engine_Documentation
|
||||
[Lua]: https://www.lua.org/
|
||||
[MOOSE for Dummies]: https://www.youtube.com/watch?v=ZqvdUFhKX4o&list=PL7ZUrU4zZUl04jBoOSX_rmqE6cArquhM4&index=2&t=618s
|
||||
|
||||
[Ops.Airboss]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Ops.Airboss.html
|
||||
[Functional.RAT]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.RAT.html
|
||||
[Functional.Range]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.Range.html
|
||||
[Functional.Fox]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.Fox.html
|
||||
|
||||
[Hello world mission]: hello-world.md
|
||||
@ -25,5 +25,30 @@ It depends on the platform and the version you choosed to install:
|
||||
- If you changed the installation folder of the Standalone version, right
|
||||
click on the game icon, open Properties and click on `Open File Location`.
|
||||
|
||||
## Find the Saved Games folder
|
||||
|
||||
DCS creates a folder to store all user specific configuration and data.
|
||||
This folder can be found in your userprofile as subfolder of `Saved Games`.
|
||||
|
||||
The easiest way to find it, is to open search and paste the text below into it
|
||||
and press Enter:
|
||||
|
||||
```%userprofile%\Saved Games```
|
||||
|
||||
{: .note }
|
||||
> The text will work even if your Windows is installed with another language,
|
||||
> e.g. German. This is really usefull.
|
||||
|
||||
Depending on the DCS version you will find one of the following folders:
|
||||
|
||||
- DCS
|
||||
- DCS.openbeta
|
||||
|
||||
{: .note }
|
||||
> It is good idea to add the folder to the quick access area in the windows
|
||||
> explorer. You will use it very often!
|
||||
|
||||
For MOOSE users the folders `Missions`, `Logs` and `Config` are most important!
|
||||
|
||||
[DCS World Steam Edition]: https://store.steampowered.com/app/223750/DCS_World_Steam_Edition/
|
||||
[DCS World Standalone installer]: https://www.digitalcombatsimulator.com/en/downloads/world/
|
||||
|
||||
BIN
docs/images/beginner/dcs-menu-mission.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
docs/images/beginner/dcs-message.jpg
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
docs/images/beginner/dcs-my-missions.png
Normal file
|
After Width: | Height: | Size: 117 KiB |
BIN
docs/images/beginner/dcs-triggers-mission-start-actions-conf.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
docs/images/beginner/dcs-triggers-mission-start-actions.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
docs/images/beginner/dcs-triggers-mission-start-conditions.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
docs/images/beginner/dcs-triggers-mission-start-conf.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
docs/images/beginner/dcs-triggers-mission-start.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
docs/images/beginner/dcs-triggers-once-actions.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
docs/images/beginner/dcs-triggers-once-conditions.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
docs/images/beginner/dcs-triggers-once-conf.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
docs/images/beginner/dcs-triggers-once.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
docs/images/beginner/dcs-triggers-toolbar.png
Normal file
|
After Width: | Height: | Size: 14 KiB |