diff --git a/Moose Development/Moose/Core/F10Menu.lua b/Moose Development/Moose/Core/F10Menu.lua new file mode 100644 index 000000000..de8a04314 --- /dev/null +++ b/Moose Development/Moose/Core/F10Menu.lua @@ -0,0 +1,212 @@ +---- **Core** - F10 Other Menu. +-- +-- **Main Features:** +-- +-- * Add Menus and Commands to the "F10 Other" Menu +-- * Create menus and commands at specific locations within the parent menu +-- * Events when command functions are executed +-- +-- +-- === +-- +-- ### Author: **funkyfranky** +-- @module Ops.F10Menu +-- @image OPS_F10Menu.png + +--- F10Menu class. +-- @type F10MENU +-- @field #string ClassName Name of the class. +-- @field #number verbose Verbosity level. +-- @field #string lid Class id string for output to DCS log file. +-- @field #string text Text of the menu item. +-- @field #table path Path of the menu. +-- @field #F10MENU parent Parent menu or `nil`. +-- @field #table commands Commands within this menu. +-- @field #table submenues Sub menues withing this menu. +-- @extends Core.Fsm#FSM + +--- *In preparing for battle I have always found that plans are useless, but planning is indispensable* -- Dwight D Eisenhower +-- +-- === +-- +-- # The CHIEF Concept +-- +-- +-- @field #F10MENU +F10MENU = { + ClassName = "F10MENU", + verbose = 0, + lid = nil, + commands = {}, + submenues = {}, +} + +--- Command executing a function. +-- @type F10MENU.Command +-- @field #number uid Unique ID. +-- @field #string text Description. +-- @field #function func Function. +-- @field #table args Arguments. +-- @field #table path Path. + +--- F10 menu class version. +-- @field #string version +F10MENU.version="0.0.1" + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- TODO list +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +-- TODO: A lot. + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- Constructors +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +--- Create a new F10 menu entry. +-- @param #F10MENU self +-- @return #F10MENU self +function F10MENU:_New() + + -- Inherit everything from INTEL class. + local self=BASE:Inherit(self, FSM:New()) --#F10MENU + + -- Add FSM transitions. + -- From State --> Event --> To State + self:AddTransition("*", "MissionAssign", "*") -- Assign mission to a COMMANDER. + + ------------------------ + --- Pseudo Functions --- + ------------------------ + + + return self +end + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- User functions +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +--- Create a new F10 menu for all players. +-- @param #F10MENU self +-- @param #string Text Description of menu. +-- @param #F10MENU ParentMenu Parent menu to which this menu is added. If not specified, the menu is added to the root menu. +-- @return #F10MENU self +function F10MENU:NewForAll(Text, ParentMenu) + + -- Inherit everything from INTEL class. + local self=self:_New() + + self.text=Text + + self.parent=ParentMenu + + if self.parent then + self.parent:_AddSubmenu(self) + end + + local path=self.parent and self.parent:GetPath() or nil + + self.path=missionCommands.addSubMenu(self.text, path) + + return self +end + +--- Removes the F10 menu and its entire contents. +-- @param #F10MENU self +-- @return #F10MENU self +function F10MENU:Remove() + + for path,_submenu in pairs(self.submenues) do + local submenu=_submenu --#F10MENU + submenu:Remove() + end + +end + +--- Get path. +-- @param #F10MENU self +-- @return #table Path. +function F10MENU:GetPath() + return self.path +end + +--- Get commands +-- @param #F10MENU self +-- @return #table Path. +function F10MENU:GetCommands() + return self.commands +end + +--- Get submenues. +-- @param #F10MENU self +-- @return #table Path. +function F10MENU:GetSubmenues() + return self.submenues +end + + +--- Add a command for all players. +-- @param #F10MENU self +-- @param #string Text Description. +-- @param #function CommandFunction Function to call. +-- @param ... Function arguments. +-- @return #F10MENU.Command Command. +function F10MENU:AddCommandForAll(Text, CommandFunction, ...) + + local command={} --#F10MENU.Command + command.uid=1 + command.text=Text + command.func=CommandFunction + command.args=... + command.path=missionCommands.addCommand(command.text, self.path, command.func, command.args) + + table.insert(self.commands, command) + + return command +end + +--- Add a command for players of a specific coalition. +-- @param #F10MENU self +-- @return #F10MENU self +function F10MENU:AddCommandForCoalition() + +end + + +--- Add a command for players of a specific group. +-- @param #F10MENU self +-- @return #F10MENU self +function F10MENU:AddCommandForGroup() + +end + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- Private functions +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +--- Add a command for players of a specific group. +-- @param #F10MENU self +-- @param #F10MENU Submenu The submenu to add. +-- @return #F10MENU self +function F10MENU:_AddSubmenu(Submenu) + + self.submenues[Submenu.path]=Submenu + +end + +--- Add a command for players of a specific group. +-- @param #F10MENU self +-- @return #F10MENU self +function F10MENU:_Refresh() + + + + for _,_submenu in pairs(self.submenues) do + local submenu=_submenu --#F10MENU + + + end + +end + diff --git a/Moose Development/Moose/Modules.lua b/Moose Development/Moose/Modules.lua index 7d47cbba1..0f2b6d565 100644 --- a/Moose Development/Moose/Modules.lua +++ b/Moose Development/Moose/Modules.lua @@ -29,6 +29,7 @@ __Moose.Include( 'Scripts/Moose/Core/Goal.lua' ) __Moose.Include( 'Scripts/Moose/Core/Spot.lua' ) __Moose.Include( 'Scripts/Moose/Core/Astar.lua' ) __Moose.Include( 'Scripts/Moose/Core/MarkerOps_Base.lua' ) +__Moose.Include( 'Scripts/Moose/Core/F10Menu.lua' ) __Moose.Include( 'Scripts/Moose/Wrapper/Object.lua' ) __Moose.Include( 'Scripts/Moose/Wrapper/Identifiable.lua' ) diff --git a/Moose Development/Moose/Ops/ArmyGroup.lua b/Moose Development/Moose/Ops/ArmyGroup.lua index 30bb2f75e..613e53b5a 100644 --- a/Moose Development/Moose/Ops/ArmyGroup.lua +++ b/Moose Development/Moose/Ops/ArmyGroup.lua @@ -849,7 +849,8 @@ function ARMYGROUP:onbeforeUpdateRoute(From, Event, To, n, N, Speed, Formation) self:E(self.lid.."Update route denied. Group is STOPPED!") return false elseif self:IsHolding() then - self:E(self.lid.."Update route denied. Group is holding position! Use Cruise()") + self:T(self.lid.."Update route denied. Group is holding position!") + return false end return true end diff --git a/Moose Development/Moose/Ops/Auftrag.lua b/Moose Development/Moose/Ops/Auftrag.lua index 10b1b7e2c..a4a85841e 100644 --- a/Moose Development/Moose/Ops/Auftrag.lua +++ b/Moose Development/Moose/Ops/Auftrag.lua @@ -46,6 +46,8 @@ -- @field #number Tstart Mission start time in abs. seconds. -- @field #number Tstop Mission stop time in abs. seconds. -- @field #number duration Mission duration in seconds. +-- @field #number durationExe Mission execution time in seconds. +-- @field #number Texecuting Mission time stamp (abs) when it started to execute. Is #nil on start. -- @field #number Tpush Mission push/execute time in abs. seconds. -- @field Wrapper.Marker#MARKER marker F10 map marker. -- @field #boolean markerOn If true, display marker on F10 map with the AUFTRAG status. @@ -2703,7 +2705,7 @@ function AUFTRAG:AddOpsGroup(OpsGroup) return self end ---- Remove an Ops group from the mission. +--- Remove an Ops group from the mission. -- @param #AUFTRAG self -- @param Ops.OpsGroup#OPSGROUP OpsGroup The OPSGROUP object. -- @return #AUFTRAG self @@ -3061,9 +3063,18 @@ function AUFTRAG:onafterStatus(From, Event, To) self:Cancel() elseif self.durationExe and self.Texecuting and Tnow-self.Texecuting>self.durationExe then + + -- Backup repeat values + local Nrepeat=self.Nrepeat + local NrepeatS=self.NrepeatSuccess + local NrepeatF=self.NrepeatFailure -- Cancel mission if stop time passed. self:Cancel() + + self.Nrepeat=Nrepeat + self.NrepeatSuccess=NrepeatS + self.NrepeatFailure=NrepeatF elseif (Ntargets0>0 and Ntargets==0) then @@ -3811,6 +3822,9 @@ function AUFTRAG:onafterDone(From, Event, To) -- Set time stamp. self.Tover=timer.getAbsTime() + -- Not executing any more. + self.Texecuting=nil + -- Set status for CHIEF, COMMANDER and LEGIONs self.statusChief=AUFTRAG.Status.DONE self.statusCommander=AUFTRAG.Status.DONE @@ -3983,7 +3997,7 @@ function AUFTRAG:onafterRepeat(From, Event, To) end else - self:E(self.lid.."ERROR: Mission can only be repeated by a CHIEF, WINGCOMMANDER or AIRWING! Stopping AUFTRAG") + self:E(self.lid.."ERROR: Mission can only be repeated by a CHIEF, COMMANDER or LEGION! Stopping AUFTRAG") self:Stop() return end @@ -3992,7 +4006,9 @@ function AUFTRAG:onafterRepeat(From, Event, To) -- No mission assets. self.assets={} - for _,_groupdata in pairs(self.groupdata) do + + -- Remove OPS groups. This also removes the mission from the OPSGROUP mission queue. + for groupname,_groupdata in pairs(self.groupdata) do local groupdata=_groupdata --#AUFTRAG.GroupData local opsgroup=groupdata.opsgroup if opsgroup then diff --git a/Moose Development/Moose/Ops/Brigade.lua b/Moose Development/Moose/Ops/Brigade.lua index 9d77f24ed..be530f2e5 100644 --- a/Moose Development/Moose/Ops/Brigade.lua +++ b/Moose Development/Moose/Ops/Brigade.lua @@ -384,7 +384,7 @@ function BRIGADE:onafterStatus(From, Event, To) local mission=_mission --Ops.Auftrag#AUFTRAG local prio=string.format("%d/%s", mission.prio, tostring(mission.importance)) ; if mission.urgent then prio=prio.." (!)" end - local assets=string.format("%d/%d", mission:CountOpsGroups(), mission.nassets) + local assets=string.format("%d/%d", mission:CountOpsGroups(), mission.Nassets or 0) local target=string.format("%d/%d Damage=%.1f", mission:CountMissionTargets(), mission:GetTargetInitialNumber(), mission:GetTargetDamage()) text=text..string.format("\n[%d] %s %s: Status=%s, Prio=%s, Assets=%s, Targets=%s", i, mission.name, mission.type, mission.status, prio, assets, target) diff --git a/Moose Development/Moose/Ops/NavyGroup.lua b/Moose Development/Moose/Ops/NavyGroup.lua index 77adc930b..79a3ef082 100644 --- a/Moose Development/Moose/Ops/NavyGroup.lua +++ b/Moose Development/Moose/Ops/NavyGroup.lua @@ -940,6 +940,9 @@ function NAVYGROUP:onbeforeUpdateRoute(From, Event, To, n, Speed, Depth) elseif self:IsStopped() then self:E(self.lid.."Update route denied. Group is STOPPED!") return false + elseif self:IsHolding() then + self:T(self.lid.."Update route denied. Group is holding position!") + return false end return true end diff --git a/Moose Development/Moose/Ops/OpsGroup.lua b/Moose Development/Moose/Ops/OpsGroup.lua index a5f0a5ee8..414ddf409 100644 --- a/Moose Development/Moose/Ops/OpsGroup.lua +++ b/Moose Development/Moose/Ops/OpsGroup.lua @@ -684,12 +684,13 @@ function OPSGROUP:New(group) self:AddTransition("*", "Pickup", "*") -- Carrier and is on route to pick up cargo. self:AddTransition("*", "Loading", "*") -- Carrier is loading cargo. self:AddTransition("*", "Load", "*") -- Carrier loads cargo into carrier. - self:AddTransition("*", "Loaded", "*") -- Carrier loaded all assigned/possible cargo into carrier. + self:AddTransition("*", "Loaded", "*") -- Carrier loaded cargo into carrier. + self:AddTransition("*", "LoadingDone", "*") -- Carrier loaded all assigned/possible cargo into carrier. self:AddTransition("*", "Transport", "*") -- Carrier is transporting cargo. self:AddTransition("*", "Unloading", "*") -- Carrier is unloading the cargo. - self:AddTransition("*", "Unload", "*") -- Carrier unload a cargo group. - self:AddTransition("*", "Unloaded", "*") -- Carrier unloaded all its current cargo. - self:AddTransition("*", "UnloadingDone", "*") -- Carrier is unloading the cargo. + self:AddTransition("*", "Unload", "*") -- Carrier unloads a cargo group. + self:AddTransition("*", "Unloaded", "*") -- Carrier unloaded a cargo group. + self:AddTransition("*", "UnloadingDone", "*") -- Carrier unloaded all its current cargo. self:AddTransition("*", "Delivered", "*") -- Carrier delivered ALL cargo of the transport assignment. self:AddTransition("*", "TransportCancel", "*") -- Cancel (current) transport. @@ -904,7 +905,7 @@ end --- Set default cruise altitude. -- @param #OPSGROUP self --- @param #number Altitude Altitude in feet. Default is 10,000 ft for airplanes and 1,000 feet for helicopters. +-- @param #number Altitude Altitude in feet. Default is 10,000 ft for airplanes and 1,500 feet for helicopters. -- @return #OPSGROUP self function OPSGROUP:SetDefaultAltitude(Altitude) if Altitude then @@ -912,7 +913,7 @@ function OPSGROUP:SetDefaultAltitude(Altitude) else if self:IsFlightgroup() then if self.isHelo then - self.altitudeCruise=UTILS.FeetToMeters(1000) + self.altitudeCruise=UTILS.FeetToMeters(1500) else self.altitudeCruise=UTILS.FeetToMeters(10000) end @@ -6235,7 +6236,7 @@ function OPSGROUP:_CheckCargoTransport() -- Boarding finished ==> Transport cargo. if gotcargo and self.cargoTransport:_CheckRequiredCargos(self.cargoTZC) and not boarding then self:T(self.lid.."Boarding finished ==> Loaded") - self:Loaded() + self:LoadingDone() else -- No cargo and no one is boarding ==> check again if we can make anyone board. self:Loading() @@ -7301,6 +7302,9 @@ function OPSGROUP:onafterLoad(From, Event, To, CargoGroup, Carrier) -- Trigger embarked event for cargo group. CargoGroup:Embarked(self, carrier) + -- Trigger Loaded event. + self:Loaded(CargoGroup) + -- Trigger "Loaded" event for current cargo transport. if self.cargoTransport then CargoGroup:_DelMyLift(self.cargoTransport) @@ -7315,15 +7319,15 @@ function OPSGROUP:onafterLoad(From, Event, To, CargoGroup, Carrier) end ---- On after "Loaded" event. Carrier has loaded all (possible) cargo at the pickup zone. +--- On after "LoadingDone" event. Carrier has loaded all (possible) cargo at the pickup zone. -- @param #OPSGROUP self -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. -function OPSGROUP:onafterLoaded(From, Event, To) +function OPSGROUP:onafterLoadingDone(From, Event, To) -- Debug info. - self:T(self.lid.."Carrier Loaded ==> Transport") + self:T(self.lid.."Carrier Loading Done ==> Transport") -- Order group to transport. self:__Transport(1) diff --git a/Moose Development/Moose/Wrapper/Positionable.lua b/Moose Development/Moose/Wrapper/Positionable.lua index bc0a82dd4..49172b5a9 100644 --- a/Moose Development/Moose/Wrapper/Positionable.lua +++ b/Moose Development/Moose/Wrapper/Positionable.lua @@ -1452,8 +1452,20 @@ do -- Cargo ["C-17A"] = 35000, --77519 cannot be used, because it loads way too much apcs and infantry. ["C-130"] = 22000 --The real value cannot be used, because it loads way too much apcs and infantry. } + + local Weight=Weights[Desc.typeName] + + if not Weight then + local fuelrel=self:GetFuel() or 1.0 + local Mmax=Desc.massMax or 0 + local Mempty=Desc.massEmpty or 0 + local Mfuel=Desc.fuelMassMax and Desc.fuelMassMax*fuelrel or 0 + Weight=Mmax-(Mempty+Mfuel) + self:I(string.format("Setting Cargo bay weight limit [%s]=%d kg (Mass max=%d, empty=%d, fuel=%d kg, fuelrel=%.3f)", Desc.typeName or "unknown type", Weight, Mmax, Mempty, Mfuel, fuelrel)) + end - self.__.CargoBayWeightLimit = Weights[Desc.typeName] or ( Desc.massMax - ( Desc.massEmpty + Desc.fuelMassMax ) ) + self.__.CargoBayWeightLimit = Weight + elseif self:IsShip() then local Desc = self:GetDesc() self:F({Desc=Desc}) diff --git a/Moose Setup/Moose.files b/Moose Setup/Moose.files index 9608179cf..7a1553aff 100644 --- a/Moose Setup/Moose.files +++ b/Moose Setup/Moose.files @@ -28,6 +28,7 @@ Core/SpawnStatic.lua Core/Timer.lua Core/Goal.lua Core/Spot.lua +Core/F10Menu.lua Wrapper/Object.lua Wrapper/Identifiable.lua