diff --git a/Moose Development/Moose/Core/Point.lua b/Moose Development/Moose/Core/Point.lua index de6378a22..25c4c9275 100644 --- a/Moose Development/Moose/Core/Point.lua +++ b/Moose Development/Moose/Core/Point.lua @@ -540,7 +540,7 @@ do -- COORDINATE local gotscenery=false local function EvaluateZone(ZoneObject) - + BASE:T({ZoneObject}) if ZoneObject then -- Get category of scanned object. @@ -1324,7 +1324,15 @@ do -- COORDINATE self.y=alt return self end - + + --- Set altitude to be at land height (i.e. on the ground!) + -- @param #COORDINATE self + function COORDINATE:SetAtLandheight() + local alt=self:GetLandHeight() + self.y=alt + return self + end + --- Build an air type route point. -- @param #COORDINATE self -- @param #COORDINATE.WaypointAltType AltType The altitude type. @@ -1950,7 +1958,6 @@ do -- COORDINATE -- @param #COORDINATE self -- @param #string name (Optional) Name of the fire to stop it, if not using the same COORDINATE object. function COORDINATE:StopBigSmokeAndFire( name ) - self:F2( { name = name } ) name = name or self.firename trigger.action.effectSmokeStop( name ) end diff --git a/Moose Development/Moose/Functional/Scoring.lua b/Moose Development/Moose/Functional/Scoring.lua index 24085edf3..92fe5f16a 100644 --- a/Moose Development/Moose/Functional/Scoring.lua +++ b/Moose Development/Moose/Functional/Scoring.lua @@ -873,8 +873,10 @@ end function SCORING:OnEventBirth( Event ) if Event.IniUnit then + Event.IniUnit.ThreatLevel, Event.IniUnit.ThreatType = Event.IniUnit:GetThreatLevel() if Event.IniObjectCategory == 1 then local PlayerName = Event.IniUnit:GetPlayerName() + Event.IniUnit.BirthTime = timer.getTime() if PlayerName then self:_AddPlayerFromUnit( Event.IniUnit ) self:SetScoringMenu( Event.IniGroup ) @@ -1005,7 +1007,18 @@ function SCORING:_EventOnHit( Event ) PlayerHit.PenaltyHit = PlayerHit.PenaltyHit or 0 PlayerHit.TimeStamp = PlayerHit.TimeStamp or 0 PlayerHit.UNIT = PlayerHit.UNIT or TargetUNIT + -- After an instant kill we can't compute the thread level anymore. To fix this we compute at OnEventBirth + if PlayerHit.UNIT.ThreatType == nil then PlayerHit.ThreatLevel, PlayerHit.ThreatType = PlayerHit.UNIT:GetThreatLevel() + -- if this fails for some reason, set a good default value + if PlayerHit.ThreatType == nil then + PlayerHit.ThreatLevel = 1 + PlayerHit.ThreatType = "Unknown" + end + else + PlayerHit.ThreatLevel = PlayerHit.UNIT.ThreatLevel + PlayerHit.ThreatType = PlayerHit.UNIT.ThreatType + end -- Only grant hit scores if there was more than one second between the last hit. if timer.getTime() - PlayerHit.TimeStamp > 1 then @@ -1021,19 +1034,20 @@ function SCORING:_EventOnHit( Event ) if InitCoalition then -- A coalition object was hit. if InitCoalition == TargetCoalition then - Player.Penalty = Player.Penalty + 10 - PlayerHit.Penalty = PlayerHit.Penalty + 10 + local Penalty = 10 + Player.Penalty = Player.Penalty + Penalty + PlayerHit.Penalty = PlayerHit.Penalty + Penalty PlayerHit.PenaltyHit = PlayerHit.PenaltyHit + 1 if TargetPlayerName ~= nil then -- It is a player hitting another player ... MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. InitPlayerName .. "' hit friendly player '" .. TargetPlayerName .. "' " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " .. PlayerHit.PenaltyHit .. " times. " .. - "Penalty: -" .. PlayerHit.Penalty .. ". Score Total:" .. Player.Score - Player.Penalty, + "Penalty: -" .. Penalty .. ". Score Total:" .. Player.Score - Player.Penalty, MESSAGE.Type.Update ) :ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() ) :ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() ) else MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. InitPlayerName .. "' hit friendly target " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " .. PlayerHit.PenaltyHit .. " times. " .. - "Penalty: -" .. PlayerHit.Penalty .. ". Score Total:" .. Player.Score - Player.Penalty, + "Penalty: -" .. Penalty .. ". Score Total:" .. Player.Score - Player.Penalty, MESSAGE.Type.Update ) :ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() ) :ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() ) @@ -1104,7 +1118,18 @@ function SCORING:_EventOnHit( Event ) PlayerHit.PenaltyHit = PlayerHit.PenaltyHit or 0 PlayerHit.TimeStamp = PlayerHit.TimeStamp or 0 PlayerHit.UNIT = PlayerHit.UNIT or TargetUNIT + -- After an instant kill we can't compute the thread level anymore. To fix this we compute at OnEventBirth + if PlayerHit.UNIT.ThreatType == nil then PlayerHit.ThreatLevel, PlayerHit.ThreatType = PlayerHit.UNIT:GetThreatLevel() + -- if this fails for some reason, set a good default value + if PlayerHit.ThreatType == nil then + PlayerHit.ThreatLevel = 1 + PlayerHit.ThreatType = "Unknown" + end + else + PlayerHit.ThreatLevel = PlayerHit.UNIT.ThreatLevel + PlayerHit.ThreatType = PlayerHit.UNIT.ThreatType + end -- Only grant hit scores if there was more than one second between the last hit. if timer.getTime() - PlayerHit.TimeStamp > 1 then @@ -1115,14 +1140,15 @@ function SCORING:_EventOnHit( Event ) if InitCoalition then -- A coalition object was hit, probably a static. if InitCoalition == TargetCoalition then -- TODO: Penalty according scale - Player.Penalty = Player.Penalty + 10 --* self.ScaleDestroyPenalty - PlayerHit.Penalty = PlayerHit.Penalty + 10 --* self.ScaleDestroyPenalty + local Penalty = 10 + Player.Penalty = Player.Penalty + Penalty --* self.ScaleDestroyPenalty + PlayerHit.Penalty = PlayerHit.Penalty + Penalty --* self.ScaleDestroyPenalty PlayerHit.PenaltyHit = PlayerHit.PenaltyHit + 1 * self.ScaleDestroyPenalty MESSAGE :NewType( self.DisplayMessagePrefix .. "Player '" .. Event.WeaponPlayerName .. "' hit friendly target " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " .. - "Penalty: -" .. PlayerHit.Penalty .. " = " .. Player.Score - Player.Penalty, + "Penalty: -" .. Penalty .. " = " .. Player.Score - Player.Penalty, MESSAGE.Type.Update ) :ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() ) @@ -1133,7 +1159,7 @@ function SCORING:_EventOnHit( Event ) PlayerHit.Score = PlayerHit.Score + 1 PlayerHit.ScoreHit = PlayerHit.ScoreHit + 1 MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. Event.WeaponPlayerName .. "' hit enemy target " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " .. - "Score: +" .. PlayerHit.Score .. " = " .. Player.Score - Player.Penalty, + "Score: " .. PlayerHit.Score .. ". Score Total:" .. Player.Score - Player.Penalty, MESSAGE.Type.Update ) :ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() ) :ToCoalitionIf( Event.WeaponCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() ) @@ -1211,7 +1237,7 @@ function SCORING:_EventOnDeadOrCrash( Event ) local Destroyed = false -- What is the player destroying? - if Player and Player.Hit and Player.Hit[TargetCategory] and Player.Hit[TargetCategory][TargetUnitName] and Player.Hit[TargetCategory][TargetUnitName].TimeStamp ~= 0 then -- Was there a hit for this unit for this player before registered??? + if Player and Player.Hit and Player.Hit[TargetCategory] and Player.Hit[TargetCategory][TargetUnitName] and Player.Hit[TargetCategory][TargetUnitName].TimeStamp ~= 0 and (TargetUnit.BirthTime == nil or Player.Hit[TargetCategory][TargetUnitName].TimeStamp > TargetUnit.BirthTime) then -- Was there a hit for this unit for this player before registered??? local TargetThreatLevel = Player.Hit[TargetCategory][TargetUnitName].ThreatLevel local TargetThreatType = Player.Hit[TargetCategory][TargetUnitName].ThreatType @@ -1240,13 +1266,13 @@ function SCORING:_EventOnDeadOrCrash( Event ) if Player.HitPlayers[TargetPlayerName] then -- A player destroyed another player MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' destroyed friendly player '" .. TargetPlayerName .. "' " .. TargetUnitCategory .. " ( " .. ThreatTypeTarget .. " ) " .. - "Penalty: -" .. TargetDestroy.Penalty .. " = " .. Player.Score - Player.Penalty, + "Penalty: -" .. ThreatPenalty .. " = " .. Player.Score - Player.Penalty, MESSAGE.Type.Information ) :ToAllIf( self:IfMessagesDestroy() and self:IfMessagesToAll() ) :ToCoalitionIf( InitCoalition, self:IfMessagesDestroy() and self:IfMessagesToCoalition() ) else MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' destroyed friendly target " .. TargetUnitCategory .. " ( " .. ThreatTypeTarget .. " ) " .. - "Penalty: -" .. TargetDestroy.Penalty .. " = " .. Player.Score - Player.Penalty, + "Penalty: -" .. ThreatPenalty .. " = " .. Player.Score - Player.Penalty, MESSAGE.Type.Information ) :ToAllIf( self:IfMessagesDestroy() and self:IfMessagesToAll() ) :ToCoalitionIf( InitCoalition, self:IfMessagesDestroy() and self:IfMessagesToCoalition() ) @@ -1268,13 +1294,13 @@ function SCORING:_EventOnDeadOrCrash( Event ) TargetDestroy.ScoreDestroy = TargetDestroy.ScoreDestroy + 1 if Player.HitPlayers[TargetPlayerName] then -- A player destroyed another player MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' destroyed enemy player '" .. TargetPlayerName .. "' " .. TargetUnitCategory .. " ( " .. ThreatTypeTarget .. " ) " .. - "Score: +" .. TargetDestroy.Score .. " = " .. Player.Score - Player.Penalty, + "Score: +" .. ThreatScore .. " = " .. Player.Score - Player.Penalty, MESSAGE.Type.Information ) :ToAllIf( self:IfMessagesDestroy() and self:IfMessagesToAll() ) :ToCoalitionIf( InitCoalition, self:IfMessagesDestroy() and self:IfMessagesToCoalition() ) else MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' destroyed enemy " .. TargetUnitCategory .. " ( " .. ThreatTypeTarget .. " ) " .. - "Score: +" .. TargetDestroy.Score .. " = " .. Player.Score - Player.Penalty, + "Score: +" .. ThreatScore .. " = " .. Player.Score - Player.Penalty, MESSAGE.Type.Information ) :ToAllIf( self:IfMessagesDestroy() and self:IfMessagesToAll() ) :ToCoalitionIf( InitCoalition, self:IfMessagesDestroy() and self:IfMessagesToCoalition() ) diff --git a/Moose Development/Moose/Functional/ZoneCaptureCoalition.lua b/Moose Development/Moose/Functional/ZoneCaptureCoalition.lua index 2439029f9..3215b9a12 100644 --- a/Moose Development/Moose/Functional/ZoneCaptureCoalition.lua +++ b/Moose Development/Moose/Functional/ZoneCaptureCoalition.lua @@ -715,7 +715,7 @@ do -- ZONE_CAPTURE_COALITION local UnitHit = EventData.TgtUnit - if UnitHit.ClassName ~= "SCENERY" then + if UnitHit and UnitHit.ClassName ~= "SCENERY" then -- Check if unit is inside the capture zone and that it is of the defending coalition. if UnitHit and UnitHit:IsInZone(self) and UnitHit:GetCoalition()==self.Coalition then diff --git a/Moose Development/Moose/Ops/AirWing.lua b/Moose Development/Moose/Ops/AirWing.lua index fe0d22de5..4cfbe36a7 100644 --- a/Moose Development/Moose/Ops/AirWing.lua +++ b/Moose Development/Moose/Ops/AirWing.lua @@ -524,7 +524,7 @@ function AIRWING:FetchPayloadFromStock(UnitType, MissionType, Payloads) if a and b then -- I had the case that a or b were nil even though the self.payloads table was looking okay. Very strange! Seems to be solved by pre-selecting valid payloads. local performanceA=self:GetPayloadPeformance(a, MissionType) local performanceB=self:GetPayloadPeformance(b, MissionType) - return (performanceA>performanceB) or (performanceA==performanceB and a.unlimited==true) or (performanceA==performanceB and a.unlimited==true and b.unlimited==true and a.navail>b.navail) + return (performanceA>performanceB) or (performanceA==performanceB and a.unlimited==true and b.unlimited~=true) or (performanceA==performanceB and a.unlimited==true and b.unlimited==true and a.navail>b.navail) elseif not a then self:I(self.lid..string.format("FF ERROR in sortpayloads: a is nil")) return false diff --git a/Moose Development/Moose/Ops/CTLD.lua b/Moose Development/Moose/Ops/CTLD.lua index e4e2fd1ed..db2afa9c0 100644 --- a/Moose Development/Moose/Ops/CTLD.lua +++ b/Moose Development/Moose/Ops/CTLD.lua @@ -713,8 +713,9 @@ do -- my_ctld.placeCratesAhead = false -- place crates straight ahead of the helicopter, in a random way. If true, crates are more neatly sorted. -- my_ctld.nobuildinloadzones = true -- forbid players to build stuff in LOAD zones if set to `true` -- my_ctld.movecratesbeforebuild = true -- crates must be moved once before they can be build. Set to false for direct builds. --- my_ctld.surfacetypes = {land.SurfaceType.LAND,land.SurfaceType.ROAD,land.SurfaceType.RUNWAY,land.SurfaceType.SHALLOW_WATER} -- surfaces for loading back objects --- +-- my_ctld.surfacetypes = {land.SurfaceType.LAND,land.SurfaceType.ROAD,land.SurfaceType.RUNWAY,land.SurfaceType.SHALLOW_WATER} -- surfaces for loading back objects. +-- my_ctld.nobuildmenu = false -- if set to true effectively enforces to have engineers build/repair stuff for you. +-- -- ## 2.1 User functions -- -- ### 2.1.1 Adjust or add chopper unit-type capabilities @@ -732,6 +733,7 @@ do -- ["SA342Minigun"] = {type="SA342Minigun", crates=false, troops=true, cratelimit = 0, trooplimit = 2, length = 12, cargoweightlimit = 400}, -- ["UH-1H"] = {type="UH-1H", crates=true, troops=true, cratelimit = 1, trooplimit = 8, length = 15, cargoweightlimit = 700}, -- ["Mi-8MT"] = {type="Mi-8MT", crates=true, troops=true, cratelimit = 2, trooplimit = 12, length = 15, cargoweightlimit = 3000}, +-- ["Mi-8MTV2"] = {type="Mi-8MTV2", crates=true, troops=true, cratelimit = 2, trooplimit = 12, length = 15, cargoweightlimit = 3000}, -- ["Ka-50"] = {type="Ka-50", crates=false, troops=false, cratelimit = 0, trooplimit = 0, length = 15, cargoweightlimit = 0}, -- ["Mi-24P"] = {type="Mi-24P", crates=true, troops=true, cratelimit = 2, trooplimit = 8, length = 18, cargoweightlimit = 700}, -- ["Mi-24V"] = {type="Mi-24V", crates=true, troops=true, cratelimit = 2, trooplimit = 8, length = 18, cargoweightlimit = 700}, @@ -1180,7 +1182,7 @@ CTLD.UnitTypes = { ["SA342Minigun"] = {type="SA342Minigun", crates=false, troops=true, cratelimit = 0, trooplimit = 2, length = 12, cargoweightlimit = 400}, ["UH-1H"] = {type="UH-1H", crates=true, troops=true, cratelimit = 1, trooplimit = 8, length = 15, cargoweightlimit = 700}, ["Mi-8MTV2"] = {type="Mi-8MTV2", crates=true, troops=true, cratelimit = 2, trooplimit = 12, length = 15, cargoweightlimit = 3000}, - ["Mi-8MT"] = {type="Mi-8MTV2", crates=true, troops=true, cratelimit = 2, trooplimit = 12, length = 15, cargoweightlimit = 3000}, + ["Mi-8MT"] = {type="Mi-8MT", crates=true, troops=true, cratelimit = 2, trooplimit = 12, length = 15, cargoweightlimit = 3000}, ["Ka-50"] = {type="Ka-50", crates=false, troops=false, cratelimit = 0, trooplimit = 0, length = 15, cargoweightlimit = 0}, ["Ka-50_3"] = {type="Ka-50_3", crates=false, troops=false, cratelimit = 0, trooplimit = 0, length = 15, cargoweightlimit = 0}, ["Mi-24P"] = {type="Mi-24P", crates=true, troops=true, cratelimit = 2, trooplimit = 8, length = 18, cargoweightlimit = 700}, @@ -1194,7 +1196,7 @@ CTLD.UnitTypes = { --- CTLD class version. -- @field #string version -CTLD.version="1.0.27" +CTLD.version="1.0.30" --- Instantiate a new CTLD. -- @param #CTLD self @@ -1306,6 +1308,7 @@ function CTLD:New(Coalition, Prefixes, Alias) self.Engineers = 0 -- #number use as counter self.EngineersInField = {} -- #table holds #CTLD_ENGINEERING objects self.EngineerSearch = 2000 -- #number search distance for crates to build or repair + self.nobuildmenu = false -- enfore engineer build only? -- setup self.CrateDistance = 35 -- list/load crates in this radius @@ -1773,6 +1776,22 @@ function CTLD:_FindTroopsCargoObject(Name) return nil end +--- (Internal) Find a crates CTLD_CARGO object in stock +-- @param #CTLD self +-- @param #string Name of the object +-- @return #CTLD_CARGO Cargo object, nil if it cannot be found +function CTLD:_FindCratesCargoObject(Name) + self:T(self.lid .. " _FindCratesCargoObject") + local cargo = nil + for _,_cargo in pairs(self.Cargo_Crates)do + local cargo = _cargo -- #CTLD_CARGO + if cargo.Name == Name then + return cargo + end + end + return nil +end + --- (User) Pre-load troops into a helo, e.g. for airstart. Unit **must** be alive in-game, i.e. player has taken the slot! -- @param #CTLD self -- @param Wrapper.Unit#UNIT Unit The unit to load into, can be handed as Wrapper.Client#CLIENT object @@ -1798,6 +1817,84 @@ function CTLD:PreloadTroops(Unit,Troopname) return self end +--- (Internal) Pre-load crates into a helo. Do not use standalone! +-- @param #CTLD self +-- @param Wrapper.Group#GROUP Group The group to load into, can be handed as Wrapper.Client#CLIENT object +-- @param Wrapper.Unit#UNIT Unit The unit to load into, can be handed as Wrapper.Client#CLIENT object +-- @param #CTLD_CARGO Cargo The Cargo crate object to load +-- @param #number NumberOfCrates (Optional) Number of crates to be loaded. Default - all necessary to build this object. Might overload the helo! +-- @return #CTLD self +function CTLD:_PreloadCrates(Group, Unit, Cargo, NumberOfCrates) + -- load crate into heli + local group = Group -- Wrapper.Group#GROUP + local unit = Unit -- Wrapper.Unit#UNIT + local unitname = unit:GetName() + -- see if this heli can load crates + local unittype = unit:GetTypeName() + local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitCapabilities + local cancrates = capabilities.crates -- #boolean + local cratelimit = capabilities.cratelimit -- #number + if not cancrates then + self:_SendMessage("Sorry this chopper cannot carry crates!", 10, false, Group) + return self + else + -- have we loaded stuff already? + local numberonboard = 0 + local massonboard = 0 + local loaded = {} + if self.Loaded_Cargo[unitname] then + loaded = self.Loaded_Cargo[unitname] -- #CTLD.LoadedCargo + numberonboard = loaded.Cratesloaded or 0 + massonboard = self:_GetUnitCargoMass(Unit) + else + loaded = {} -- #CTLD.LoadedCargo + loaded.Troopsloaded = 0 + loaded.Cratesloaded = 0 + loaded.Cargo = {} + end + local crate = Cargo -- #CTLD_CARGO + local numbercrates = NumberOfCrates or crate:GetCratesNeeded() + for i=1,numbercrates do + loaded.Cratesloaded = loaded.Cratesloaded + 1 + crate:SetHasMoved(true) + crate:SetWasDropped(false) + table.insert(loaded.Cargo, crate) + crate.Positionable = nil + self:_SendMessage(string.format("Crate ID %d for %s loaded!",crate:GetID(),crate:GetName()), 10, false, Group) + --self:__CratesPickedUp(1, Group, Unit, crate) + self.Loaded_Cargo[unitname] = loaded + self:_UpdateUnitCargoMass(Unit) + end + end + return self +end + +--- (User) Pre-load crates into a helo, e.g. for airstart. Unit **must** be alive in-game, i.e. player has taken the slot! +-- @param #CTLD self +-- @param Wrapper.Unit#UNIT Unit The unit to load into, can be handed as Wrapper.Client#CLIENT object +-- @param #string Cratesname The name of the cargo to be loaded. Must be created prior in the CTLD setup! +-- @param #number NumberOfCrates (Optional) Number of crates to be loaded. Default - all necessary to build this object. Might overload the helo! +-- @return #CTLD self +-- @usage +-- local client = UNIT:FindByName("Helo-1-1") +-- if client and client:IsAlive() then +-- myctld:PreloadCrates(client,"Humvee") +-- end +function CTLD:PreloadCrates(Unit,Cratesname,NumberOfCrates) + self:T(self.lid .. " PreloadCrates") + local name = Cratesname or "Unknown" + if Unit and Unit:IsAlive() then + local cargo = self:_FindCratesCargoObject(name) + local group = Unit:GetGroup() + if cargo then + self:_PreloadCrates(group,Unit,cargo,NumberOfCrates) + else + self:E(self.lid.." Crates preload - Cargo Object "..name.." not found!") + end + end + return self +end + --- (Internal) Function to load troops into a heli. -- @param #CTLD self -- @param Wrapper.Group#GROUP Group @@ -3323,6 +3420,12 @@ function CTLD:_RefreshF10Menus() self.subcats[entry.Subcategory] = entry.Subcategory end end + for _id,_cargo in pairs(self.Cargo_Statics) do + local entry = _cargo -- #CTLD_CARGO + if not self.subcats[entry.Subcategory] then + self.subcats[entry.Subcategory] = entry.Subcategory + end + end end -- build unit menus @@ -3386,6 +3489,13 @@ function CTLD:_RefreshF10Menus() local menutext = string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0) menus[menucount] = MENU_GROUP_COMMAND:New(_group,menutext,subcatmenus[subcat],self._GetCrates, self, _group, _unit, entry) end + for _,_entry in pairs(self.Cargo_Statics) do + local entry = _entry -- #CTLD_CARGO + local subcat = entry.Subcategory + menucount = menucount + 1 + local menutext = string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0) + menus[menucount] = MENU_GROUP_COMMAND:New(_group,menutext,subcatmenus[subcat],self._GetCrates, self, _group, _unit, entry) + end else for _,_entry in pairs(self.Cargo_Crates) do local entry = _entry -- #CTLD_CARGO @@ -3393,17 +3503,21 @@ function CTLD:_RefreshF10Menus() local menutext = string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0) menus[menucount] = MENU_GROUP_COMMAND:New(_group,menutext,cratesmenu,self._GetCrates, self, _group, _unit, entry) end - end - for _,_entry in pairs(self.Cargo_Statics) do - local entry = _entry -- #CTLD_CARGO - menucount = menucount + 1 - local menutext = string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0) - menus[menucount] = MENU_GROUP_COMMAND:New(_group,menutext,cratesmenu,self._GetCrates, self, _group, _unit, entry) + for _,_entry in pairs(self.Cargo_Statics) do + local entry = _entry -- #CTLD_CARGO + menucount = menucount + 1 + local menutext = string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0) + menus[menucount] = MENU_GROUP_COMMAND:New(_group,menutext,cratesmenu,self._GetCrates, self, _group, _unit, entry) + end end listmenu = MENU_GROUP_COMMAND:New(_group,"List crates nearby",topcrates, self._ListCratesNearby, self, _group, _unit) local unloadmenu = MENU_GROUP_COMMAND:New(_group,"Drop crates",topcrates, self._UnloadCrates, self, _group, _unit) - local buildmenu = MENU_GROUP_COMMAND:New(_group,"Build crates",topcrates, self._BuildCrates, self, _group, _unit) - local repairmenu = MENU_GROUP_COMMAND:New(_group,"Repair",topcrates, self._RepairCrates, self, _group, _unit):Refresh() + if not self.nobuildmenu then + local buildmenu = MENU_GROUP_COMMAND:New(_group,"Build crates",topcrates, self._BuildCrates, self, _group, _unit) + local repairmenu = MENU_GROUP_COMMAND:New(_group,"Repair",topcrates, self._RepairCrates, self, _group, _unit):Refresh() + else + unloadmenu:Refresh() + end end if self:IsHercules(_unit) then local hoverpars = MENU_GROUP_COMMAND:New(_group,"Show flight parameters",topmenu, self._ShowFlightParams, self, _group, _unit):Refresh() @@ -3488,13 +3602,14 @@ end -- @param #string Name Unique name of this type of cargo as set in the mission editor (note: UNIT name!), e.g. "Ammunition-1". -- @param #number Mass Mass in kg of each static in kg, e.g. 100. -- @param #number Stock Number of groups in stock. Nil for unlimited. -function CTLD:AddStaticsCargo(Name,Mass,Stock) +-- @param #string SubCategory Name of sub-category (optional). +function CTLD:AddStaticsCargo(Name,Mass,Stock,SubCategory) self:T(self.lid .. " AddStaticsCargo") self.CargoCounter = self.CargoCounter + 1 local type = CTLD_CARGO.Enum.STATIC local template = STATIC:FindByName(Name,true):GetTypeName() -- Crates are not directly loadable - local cargo = CTLD_CARGO:New(self.CargoCounter,Name,template,type,false,false,1,nil,nil,Mass,Stock) + local cargo = CTLD_CARGO:New(self.CargoCounter,Name,template,type,false,false,1,nil,nil,Mass,Stock,SubCategory) table.insert(self.Cargo_Statics,cargo) return self end @@ -5252,7 +5367,7 @@ CTLD_HERCULES = { ClassName = "CTLD_HERCULES", lid = "", Name = "", - Version = "0.0.2", + Version = "0.0.3", } --- Define cargo types. @@ -5570,8 +5685,8 @@ function CTLD_HERCULES:Cargo_SpawnObjects(Cargo_Drop_initiator,Cargo_Drop_Direct if offload_cargo == true or ParatrooperGroupSpawn == true then if ParatrooperGroupSpawn == true then - self:Soldier_SpawnGroup(Cargo_Drop_initiator,Cargo_Content_position, Cargo_Type_name, CargoHeading, Cargo_Country, 0) - self:Soldier_SpawnGroup(Cargo_Drop_initiator,Cargo_Content_position, Cargo_Type_name, CargoHeading, Cargo_Country, 5) + --self:Soldier_SpawnGroup(Cargo_Drop_initiator,Cargo_Content_position, Cargo_Type_name, CargoHeading, Cargo_Country, 0) + --self:Soldier_SpawnGroup(Cargo_Drop_initiator,Cargo_Content_position, Cargo_Type_name, CargoHeading, Cargo_Country, 5) self:Soldier_SpawnGroup(Cargo_Drop_initiator,Cargo_Content_position, Cargo_Type_name, CargoHeading, Cargo_Country, 10) else self:Cargo_SpawnGroup(Cargo_Drop_initiator,Cargo_Content_position, Cargo_Type_name, CargoHeading, Cargo_Country) diff --git a/Moose Development/Moose/Ops/PlayerRecce.lua b/Moose Development/Moose/Ops/PlayerRecce.lua index 746fff5e3..df55a88d4 100644 --- a/Moose Development/Moose/Ops/PlayerRecce.lua +++ b/Moose Development/Moose/Ops/PlayerRecce.lua @@ -104,7 +104,7 @@ PLAYERRECCE = { ClassName = "PLAYERRECCE", verbose = true, lid = nil, - version = "0.0.16", + version = "0.0.17", ViewZone = {}, ViewZoneVisual = {}, ViewZoneLaser = {}, @@ -149,7 +149,8 @@ PLAYERRECCE.LaserRelativePos = { ["SA342Mistral"] = { x = 1.7, y = 1.2, z = 0 }, ["SA342Minigun"] = { x = 1.7, y = 1.2, z = 0 }, ["SA342L"] = { x = 1.7, y = 1.2, z = 0 }, - ["Ka-50"] = { x = 6.1, y = -0.85 , z = 0 } + ["Ka-50"] = { x = 6.1, y = -0.85 , z = 0 }, + ["Ka-50_3"] = { x = 6.1, y = -0.85 , z = 0 } } --- @@ -161,6 +162,7 @@ PLAYERRECCE.MaxViewDistance = { ["SA342Minigun"] = 8000, ["SA342L"] = 8000, ["Ka-50"] = 8000, + ["Ka-50_3"] = 8000, } --- @@ -172,6 +174,7 @@ PLAYERRECCE.Cameraheight = { ["SA342Minigun"] = 2.85, ["SA342L"] = 2.85, ["Ka-50"] = 0.5, + ["Ka-50_3"] = 0.5, } --- @@ -182,7 +185,8 @@ PLAYERRECCE.CanLase = { ["SA342Mistral"] = true, ["SA342Minigun"] = false, -- no optics ["SA342L"] = true, - ["Ka-50"] = true, + ["Ka-50"] = true, + ["Ka-50_3"] = true, } --- @@ -337,11 +341,7 @@ function PLAYERRECCE:_GetClockDirection(unit, target) clock = 12+hours clock = UTILS.Round(clock,0) if clock > 12 then clock = clock-12 end - end - --if self.debug then - --local text = string.format("Heading = %d, Angle = %d, Hours= %d, Clock = %d",_heading,Angle,hours,clock) - --self:I(self.lid .. text) - --end + end return clock end @@ -411,7 +411,7 @@ function PLAYERRECCE:_CameraOn(client,playername) if vivihorizontal < -0.7 or vivihorizontal > 0.7 then camera = false end - elseif typename == "Ka-50" then + elseif string.find(typename,"Ka-50") then camera = true end end @@ -653,7 +653,7 @@ function PLAYERRECCE:_GetTargetSet(unit,camera,laser) angle=10 -- Model nod and actual TV view don't compute maxview = self.MaxViewDistance[typename] or 5000 - elseif typename == "Ka-50" and camera then + elseif string.find(typename,"Ka-50") and camera then heading = unit:GetHeading() nod,maxview,camon = 10,1000,true angle = 10 diff --git a/Moose Setup/Moose.files b/Moose Setup/Moose.files index ae26fe81f..6cd862e94 100644 --- a/Moose Setup/Moose.files +++ b/Moose Setup/Moose.files @@ -43,6 +43,7 @@ Wrapper/Static.lua Wrapper/Airbase.lua Wrapper/Scenery.lua Wrapper/Marker.lua +Wrapper/Weapon.lua Cargo/Cargo.lua Cargo/CargoUnit.lua