--- **Functional** - Base class that models processes to achieve goals involving a Zone. -- -- === -- -- ZONE_GOAL models processes that have a Goal with a defined achievement involving a Zone. -- Derived classes implement the ways how the achievements can be realized. -- -- === -- -- ### Author: **FlightControl** -- ### Contributions: **funkyfranky**, **Applevangelist** -- -- === -- -- @module Functional.ZoneGoal -- @image MOOSE.JPG 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 --- Models processes that have a Goal with a defined achievement involving a Zone. -- Derived classes implement the ways how the achievements can be realized. -- -- ## 1. ZONE_GOAL constructor -- -- * @{#ZONE_GOAL.New}(): Creates a new ZONE_GOAL object. -- -- ## 2. ZONE_GOAL is a finite state machine (FSM). -- -- ### 2.1 ZONE_GOAL States -- -- * None: Initial State -- -- ### 2.2 ZONE_GOAL Events -- -- * DestroyedUnit: A @{Wrapper.Unit} is destroyed in the Zone. The event will only get triggered if the method @{#ZONE_GOAL.MonitorDestroyedUnits}() is used. -- -- @field #ZONE_GOAL ZONE_GOAL = { ClassName = "ZONE_GOAL", Goal = nil, SmokeTime = nil, SmokeScheduler = nil, SmokeColor = nil, SmokeZone = nil, } --- ZONE_GOAL Constructor. -- @param #ZONE_GOAL self -- @param Core.Zone#ZONE_RADIUS Zone A @{Core.Zone} object with the goal to be achieved. Alternatively, can be handed as the name of late activated group describing a ZONE_POLYGON with its waypoints. -- @return #ZONE_GOAL function ZONE_GOAL:New( Zone ) BASE:I({Zone=Zone}) local self = BASE:Inherit( self, BASE:New()) if type(Zone) == "string" then self = BASE:Inherit( self, ZONE_POLYGON:NewFromGroupName(Zone) ) else self = BASE:Inherit( self, ZONE_RADIUS:New( Zone:GetName(), Zone:GetVec2(), Zone:GetRadius() ) ) -- #ZONE_GOAL self:F( { Zone = Zone } ) end -- 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 -- @param #ZONE_GOAL self -- @param #string From -- @param #string Event -- @param #string To -- @param Wrapper.Unit#UNIT DestroyedUnit The destroyed unit. -- @param #string PlayerName The name of the player. return self end --- Get the Zone. -- @param #ZONE_GOAL self -- @return #ZONE_GOAL function ZONE_GOAL:GetZone() return self end --- Get the name of the Zone. -- @param #ZONE_GOAL self -- @return #string function ZONE_GOAL:GetZoneName() return self:GetName() end --- Activate smoking of zone with the color or the current owner. -- @param #ZONE_GOAL self -- @param #boolean switch If *true* or *nil* activate smoke. If *false* or *nil*, no smoke. -- @return #ZONE_GOAL function ZONE_GOAL:SetSmokeZone(switch) self.SmokeZone=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 zone boundary. -- @param #ZONE_GOAL self -- @param DCS#SMOKECOLOR.Color FlareColor function ZONE_GOAL:Flare( FlareColor ) self:FlareZone( FlareColor, 30) end --- When started, check the Smoke and the Zone status. -- @param #ZONE_GOAL self function ZONE_GOAL:onafterGuard() self:F("Guard") -- Start smoke if self.SmokeZone and not self.SmokeScheduler then self.SmokeScheduler = self:ScheduleRepeat(1, 1, 0.1, nil, self.StatusSmoke, self) end end --- Check status Smoke. -- @param #ZONE_GOAL self function ZONE_GOAL:StatusSmoke() self:F({self.SmokeTime, self.SmokeColor}) 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 Event data table. function ZONE_GOAL:__Destroyed( EventData ) self:F( { "EventDead", EventData } ) self:F( { EventData.IniUnit } ) if EventData.IniDCSUnit 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 --- Activate the event UnitDestroyed to be fired when a unit is destroyed in the zone. -- @param #ZONE_GOAL self function ZONE_GOAL:MonitorDestroyedUnits() self:HandleEvent( EVENTS.Dead, self.__Destroyed ) self:HandleEvent( EVENTS.Crash, self.__Destroyed ) end end