diff --git a/Moose Development/Moose/Core/Zone.lua b/Moose Development/Moose/Core/Zone.lua index 07c93f7b9..a1db93d70 100644 --- a/Moose Development/Moose/Core/Zone.lua +++ b/Moose Development/Moose/Core/Zone.lua @@ -56,7 +56,7 @@ --- @type ZONE_BASE -- @field #string ZoneName Name of the zone. -- @field #number ZoneProbability A value between 0 and 1. 0 = 0% and 1 = 100% probability. --- @extends Core.Base#BASE +-- @extends Core.Fsm#FSM --- This class is an abstract BASE class for derived classes, and is not meant to be instantiated. diff --git a/Moose Development/Moose/Functional/Range.lua b/Moose Development/Moose/Functional/Range.lua index d3fc4d1aa..d181ebbec 100644 --- a/Moose Development/Moose/Functional/Range.lua +++ b/Moose Development/Moose/Functional/Range.lua @@ -516,7 +516,7 @@ RANGE.MenuF10Root=nil --- Range script version. -- @field #string version -RANGE.version="2.2.0" +RANGE.version="2.2.1" --TODO list: --TODO: Verbosity level for messages. @@ -2521,10 +2521,17 @@ function RANGE:_DisplayBombTargets(_unitname) local coord=self:_GetBombTargetCoordinate(bombtarget) if coord then + + -- Get elevation + local elevation=coord:GetLandHeight() + local eltxt=string.format("%d m", elevation) + if _settings:IsImperial() then + elevation=UTILS.MetersToFeet(elevation) + eltxt=string.format("%d ft", elevation) + end local ca2g=coord:ToStringA2G(_unit,_settings) - --local lldms=coord:ToStringLLDMS(_settings) - _text=_text..string.format("\n- %s:\n%s", bombtarget.name or "unknown", ca2g) + _text=_text..string.format("\n- %s:\n%s @ %s", bombtarget.name or "unknown", ca2g, eltxt) end end diff --git a/Moose Development/Moose/Functional/ZoneCaptureCoalition.lua b/Moose Development/Moose/Functional/ZoneCaptureCoalition.lua index 2cd1f7ac2..fbca12fae 100644 --- a/Moose Development/Moose/Functional/ZoneCaptureCoalition.lua +++ b/Moose Development/Moose/Functional/ZoneCaptureCoalition.lua @@ -347,6 +347,8 @@ do -- ZONE_CAPTURE_COALITION -- @param #ZONE_CAPTURE_COALITION self -- @param Core.Zone#ZONE Zone A @{Zone} object with the goal to be achieved. -- @param DCSCoalition.DCSCoalition#coalition Coalition The initial coalition owning the zone. + -- @param #table UnitCategories Table of unit categories. See [DCS Class Unit](https://wiki.hoggitworld.com/view/DCS_Class_Unit). Default {Unit.Category.GROUND_UNIT}. + -- @param #table ObjectCategories Table of unit categories. See [DCS Class Object](https://wiki.hoggitworld.com/view/DCS_Class_Object). Default {Object.Category.UNIT, Object.Category.STATIC}, i.e. all UNITS and STATICS. -- @return #ZONE_CAPTURE_COALITION -- @usage -- @@ -355,11 +357,13 @@ do -- ZONE_CAPTURE_COALITION -- ZoneCaptureCoalition = ZONE_CAPTURE_COALITION:New( AttackZone, coalition.side.RED ) -- Create a new ZONE_CAPTURE_COALITION object of zone AttackZone with ownership RED coalition. -- ZoneCaptureCoalition:__Guard( 1 ) -- Start the Guarding of the AttackZone. -- - function ZONE_CAPTURE_COALITION:New( Zone, Coalition, UnitCategories ) + function ZONE_CAPTURE_COALITION:New( Zone, Coalition, UnitCategories, ObjectCategories ) local self = BASE:Inherit( self, ZONE_GOAL_COALITION:New( Zone, Coalition, UnitCategories ) ) -- #ZONE_CAPTURE_COALITION - self:F( { Zone = Zone, Coalition = Coalition, UnitCategories = UnitCategories } ) + self:F( { Zone = Zone, Coalition = Coalition, UnitCategories = UnitCategories, ObjectCategories = ObjectCategories } ) + + self:SetObjectCategories(ObjectCategories) do @@ -613,16 +617,15 @@ do -- ZONE_CAPTURE_COALITION -- function ZONE_CAPTURE_COALITION:Start( StartInterval, RepeatInterval ) - self.StartInterval = StartInterval or 15 + self.StartInterval = StartInterval or 1 self.RepeatInterval = RepeatInterval or 15 if self.ScheduleStatusZone then self:ScheduleStop( self.ScheduleStatusZone ) end - self.ScheduleStatusZone = self:ScheduleRepeat( self.StartInterval, self.RepeatInterval, 1.5, nil, self.StatusZone, self ) - - self:StatusZone() + -- Start Status scheduler. + self.ScheduleStatusZone = self:ScheduleRepeat( self.StartInterval, self.RepeatInterval, 0.1, nil, self.StatusZone, self ) end @@ -696,12 +699,14 @@ do -- ZONE_CAPTURE_COALITION --- On enter "Guarded" state. -- @param #ZONE_CAPTURE_COALITION self function ZONE_CAPTURE_COALITION:onenterGuarded() + env.info("FF enter Guarded") self:Mark() end --- On enter "Captured" state. -- @param #ZONE_CAPTURE_COALITION self function ZONE_CAPTURE_COALITION:onenterCaptured() + env.info("FF enter Captured") -- Get new coalition. local NewCoalition = self:GetScannedCoalition() @@ -720,18 +725,21 @@ do -- ZONE_CAPTURE_COALITION --- On after "ChangeCoalition" state. -- @param #ZONE_CAPTURE_COALITION self function ZONE_CAPTURE_COALITION:onafterChangeCoalition(From, Event, To, NewCoalition, OldCoalition) + env.info("FF after ChangeCoalition") self:SetCoalition(NewCoalition) end --- On enter "Empty" state. -- @param #ZONE_CAPTURE_COALITION self function ZONE_CAPTURE_COALITION:onenterEmpty() + env.info("FF enter Empty") self:Mark() end --- On enter "Attacked" state. -- @param #ZONE_CAPTURE_COALITION self function ZONE_CAPTURE_COALITION:onenterAttacked() + env.info("FF enter Attacked") self:Mark() end diff --git a/Moose Development/Moose/Functional/ZoneGoal.lua b/Moose Development/Moose/Functional/ZoneGoal.lua index 5a7e85397..f3ba834dd 100644 --- a/Moose Development/Moose/Functional/ZoneGoal.lua +++ b/Moose Development/Moose/Functional/ZoneGoal.lua @@ -17,6 +17,12 @@ do -- Zone --- @type ZONE_GOAL + -- @field #string ClassName Name of the class. + -- @field Core.Goal#GOAL Goal The goal object. + -- @field #number SmokeTime Time stamp in seconds when the last smoke of the zone was triggered. + -- @field Core.Scheduler#SCHEDULER SmokeScheduler Scheduler responsible for smoking the zone. + -- @field #number SmokeColor Color of the smoke. + -- @field #boolean SmokeZone If true, smoke zone. -- @extends Core.Zone#ZONE_RADIUS @@ -43,6 +49,8 @@ do -- Zone Goal = nil, SmokeTime = nil, SmokeScheduler = nil, + SmokeColor = nil, + SmokeZone = nil, } --- ZONE_GOAL Constructor. @@ -54,11 +62,24 @@ do -- Zone local self = BASE:Inherit( self, ZONE_RADIUS:New( Zone:GetName(), Zone:GetVec2(), Zone:GetRadius() ) ) -- #ZONE_GOAL self:F( { Zone = Zone } ) + -- Goal object. self.Goal = GOAL:New() self.SmokeTime = nil + + -- Set smoke ON. + self:SetSmokeZone(true) self:AddTransition( "*", "DestroyedUnit", "*" ) + + --- DestroyedUnit event. + -- @function [parent=#ZONE_GOAL] DestroyedUnit + -- @param #ZONE_GOAL self + + --- DestroyedUnit delayed event + -- @function [parent=#ZONE_GOAL] __DestroyedUnit + -- @param #ZONE_GOAL self + -- @param #number delay Delay in seconds. --- DestroyedUnit Handler OnAfter for ZONE_GOAL -- @function [parent=#ZONE_GOAL] OnAfterDestroyedUnit @@ -69,19 +90,18 @@ do -- Zone -- @param Wrapper.Unit#UNIT DestroyedUnit The destroyed unit. -- @param #string PlayerName The name of the player. - return self end - --- Get the Zone + --- Get the Zone. -- @param #ZONE_GOAL self - -- @return Core.Zone#ZONE_BASE + -- @return #ZONE_GOAL function ZONE_GOAL:GetZone() return self end - --- Get the name of the ProtectZone + --- Get the name of the Zone. -- @param #ZONE_GOAL self -- @return #string function ZONE_GOAL:GetZoneName() @@ -89,35 +109,43 @@ do -- Zone end - --- Smoke the center of theh zone. + --- Activate smoking of zone with the color or the current owner. -- @param #ZONE_GOAL self - -- @param #SMOKECOLOR.Color SmokeColor - function ZONE_GOAL:Smoke( SmokeColor ) - + -- @param #boolean switch If *true* or *nil* activate smoke. If false, no smoke. + -- @return #ZONE_GOAL + function ZONE_GOAL:SetSmokeZone(switch) + if switch==nil or switch==true then + self.SmokeZone=true + else + self.SmokeZone=false + end + return self + end + + --- Set the smoke color. + -- @param #ZONE_GOAL self + -- @param DCS#SMOKECOLOR.Color SmokeColor + function ZONE_GOAL:Smoke( SmokeColor ) self:F( { SmokeColor = SmokeColor} ) self.SmokeColor = SmokeColor end - --- Flare the center of the zone. + --- Flare the zone boundary. -- @param #ZONE_GOAL self - -- @param #SMOKECOLOR.Color FlareColor + -- @param DCS#SMOKECOLOR.Color FlareColor function ZONE_GOAL:Flare( FlareColor ) - self:FlareZone( FlareColor, math.random( 1, 360 ) ) + self:FlareZone( FlareColor, 30) end --- When started, check the Smoke and the Zone status. -- @param #ZONE_GOAL self function ZONE_GOAL:onafterGuard() - - --self:GetParent( self ):onafterStart() - self:F("Guard") - - --self:ScheduleRepeat( 15, 15, 0.1, nil, self.StatusZone, self ) - if not self.SmokeScheduler then + + if self.SmokeZone and not self.SmokeScheduler then self.SmokeScheduler = self:ScheduleRepeat( 1, 1, 0.1, nil, self.StatusSmoke, self ) end end @@ -126,42 +154,54 @@ do -- Zone --- Check status Smoke. -- @param #ZONE_GOAL self function ZONE_GOAL:StatusSmoke() - self:F({self.SmokeTime, self.SmokeColor}) - local CurrentTime = timer.getTime() - - if self.SmokeTime == nil or self.SmokeTime + 300 <= CurrentTime then - if self.SmokeColor then - self:GetCoordinate():Smoke( self.SmokeColor ) - --self.SmokeColor = nil - self.SmokeTime = CurrentTime + if self.SmokeZone then + + -- Current time. + local CurrentTime = timer.getTime() + + -- Restart smoke every 5 min. + if self.SmokeTime == nil or self.SmokeTime + 300 <= CurrentTime then + if self.SmokeColor then + self:GetCoordinate():Smoke( self.SmokeColor ) + self.SmokeTime = CurrentTime + end end + end + end --- @param #ZONE_GOAL self - -- @param Core.Event#EVENTDATA EventData + -- @param Core.Event#EVENTDATA EventData Event data table. function ZONE_GOAL:__Destroyed( EventData ) self:F( { "EventDead", EventData } ) self:F( { EventData.IniUnit } ) - local Vec3 = EventData.IniDCSUnit:getPosition().p - self:F( { Vec3 = Vec3 } ) - if EventData.IniDCSUnit then - if self:IsVec3InZone(Vec3) then + + local Vec3 = EventData.IniDCSUnit:getPosition().p + self:F( { Vec3 = Vec3 } ) + + if Vec3 and self:IsVec3InZone(Vec3) then + local PlayerHits = _DATABASE.HITS[EventData.IniUnitName] + if PlayerHits then + for PlayerName, PlayerHit in pairs( PlayerHits.Players or {} ) do self.Goal:AddPlayerContribution( PlayerName ) self:DestroyedUnit( EventData.IniUnitName, PlayerName ) end + end + end end + end diff --git a/Moose Development/Moose/Functional/ZoneGoalCoalition.lua b/Moose Development/Moose/Functional/ZoneGoalCoalition.lua index 0625aaae1..a25d4e534 100644 --- a/Moose Development/Moose/Functional/ZoneGoalCoalition.lua +++ b/Moose Development/Moose/Functional/ZoneGoalCoalition.lua @@ -17,6 +17,10 @@ do -- ZoneGoal --- @type ZONE_GOAL_COALITION + -- @field #string ClassName Name of the Class. + -- @field #number Coalition The current coalition ID of the zone owner. + -- @field #table UnitCategories Table of unit categories that are able to capture and hold the zone. Default is only GROUND units. + -- @field #table ObjectCategories Table of object categories that are able to hold a zone. Default is UNITS and STATICS. -- @extends Functional.ZoneGoal#ZONE_GOAL @@ -37,9 +41,10 @@ do -- ZoneGoal -- -- @field #ZONE_GOAL_COALITION ZONE_GOAL_COALITION = { - ClassName = "ZONE_GOAL_COALITION", - Coalition = nil, - + ClassName = "ZONE_GOAL_COALITION", + Coalition = nil, + UnitCategories = nil, + ObjectCategories = nil, } --- @field #table ZONE_GOAL_COALITION.States @@ -48,27 +53,69 @@ do -- ZoneGoal --- ZONE_GOAL_COALITION Constructor. -- @param #ZONE_GOAL_COALITION self -- @param Core.Zone#ZONE Zone A @{Zone} object with the goal to be achieved. - -- @param DCSCoalition.DCSCoalition#coalition Coalition The initial coalition owning the zone. + -- @param DCSCoalition.DCSCoalition#coalition Coalition The initial coalition owning the zone. Default coalition.side.NEUTRAL. + -- @param #table UnitCategories Table of unit categories. See [DCS Class Unit](https://wiki.hoggitworld.com/view/DCS_Class_Unit). Default {Unit.Category.GROUND_UNIT}. -- @return #ZONE_GOAL_COALITION - function ZONE_GOAL_COALITION:New( Zone, Coalition ) + function ZONE_GOAL_COALITION:New( Zone, Coalition, UnitCategories ) + if not Zone then + BASE:E("ERROR: No Zone specified in ZONE_GOAL_COALITON!") + return nil + end + + -- Inherit ZONE_GOAL. local self = BASE:Inherit( self, ZONE_GOAL:New( Zone ) ) -- #ZONE_GOAL_COALITION self:F( { Zone = Zone, Coalition = Coalition } ) - self:SetCoalition( Coalition ) - - + -- Set initial owner. + self:SetCoalition( Coalition or coalition.side.NEUTRAL) + + -- Set default unit and object categories for the zone scan. + self:SetUnitCategories(UnitCategories) + self:SetObjectCategories() + return self end --- Set the owning coalition of the zone. -- @param #ZONE_GOAL_COALITION self - -- @param DCSCoalition.DCSCoalition#coalition Coalition + -- @param DCSCoalition.DCSCoalition#coalition Coalition The coalition ID, e.g. *coalition.side.RED*. + -- @return #ZONE_GOAL_COALITION function ZONE_GOAL_COALITION:SetCoalition( Coalition ) self.Coalition = Coalition + return self + end + + --- Set the owning coalition of the zone. + -- @param #ZONE_GOAL_COALITION self + -- @param #table UnitCategories Table of unit categories. See [DCS Class Unit](https://wiki.hoggitworld.com/view/DCS_Class_Unit). Default {Unit.Category.GROUND_UNIT}. + -- @return #ZONE_GOAL_COALITION + function ZONE_GOAL_COALITION:SetUnitCategories( UnitCategories ) + + if UnitCategories and type(UnitCategories)~="table" then + UnitCategories={UnitCategories} + end + + self.UnitCategories=UnitCategories or {Unit.Category.GROUND_UNIT} + + return self end + --- Set the owning coalition of the zone. + -- @param #ZONE_GOAL_COALITION self + -- @param #table ObjectCategories Table of unit categories. See [DCS Class Object](https://wiki.hoggitworld.com/view/DCS_Class_Object). Default {Object.Category.UNIT, Object.Category.STATIC}, i.e. all UNITS and STATICS. + -- @return #ZONE_GOAL_COALITION + function ZONE_GOAL_COALITION:SetObjectCategories( ObjectCategories ) + + if ObjectCategories and type(ObjectCategories)~="table" then + ObjectCategories={ObjectCategories} + end + + self.ObjectCategories=ObjectCategories or {Object.Category.UNIT, Object.Category.STATIC} + + return self + end --- Get the owning coalition of the zone. -- @param #ZONE_GOAL_COALITION self @@ -95,20 +142,25 @@ do -- ZoneGoal return "Neutral" end - return "" + return "Unknown" end --- Check status Coalition ownership. -- @param #ZONE_GOAL_COALITION self + -- @return #ZONE_GOAL_COALITION function ZONE_GOAL_COALITION:StatusZone() local State = self:GetState() self:F( { State = self:GetState() } ) - env.info("scanning") - self:Scan( { Object.Category.UNIT, Object.Category.STATIC } ) + -- Debug text. + local text=string.format("Zone state=%s, Owner=%s, Scanning...", State, self:GetCoalitionName()) + env.info(text) + + self:Scan( self.ObjectCategories, self.UnitCategories ) + return self end end