From 70386811e6a9788bd7e70bedc81c9789f86f44e6 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Sun, 19 Feb 2023 12:31:57 +0100 Subject: [PATCH] AICSAR --- Moose Development/Moose/Functional/AICSAR.lua | 95 ++++++++++++++++++- Moose Development/Moose/Wrapper/Client.lua | 16 ++++ Moose Development/Moose/Wrapper/Net.lua | 31 +++--- 3 files changed, 126 insertions(+), 16 deletions(-) diff --git a/Moose Development/Moose/Functional/AICSAR.lua b/Moose Development/Moose/Functional/AICSAR.lua index a09d0e1bd..c9ec13298 100644 --- a/Moose Development/Moose/Functional/AICSAR.lua +++ b/Moose Development/Moose/Functional/AICSAR.lua @@ -55,6 +55,8 @@ -- @field Utilities.FiFo#FIFO PilotStore -- @field #number Altitude Default altitude setting for the helicopter FLIGHTGROUP 1500ft. -- @field #number Speed Default speed setting for the helicopter FLIGHTGROUP is 100kn. +-- @field #boolean UseEventEject In case Event LandingAfterEjection isn't working, use set this to true. +-- @field #number Delay In case of UseEventEject wait this long until we spawn a landed pilot. -- @extends Core.Fsm#FSM @@ -189,7 +191,7 @@ -- @field #AICSAR AICSAR = { ClassName = "AICSAR", - version = "0.1.12", + version = "0.1.14", lid = "", coalition = coalition.side.BLUE, template = "", @@ -232,6 +234,8 @@ AICSAR = { PilotStore = nil, Speed = 100, Altitude = 1500, + UseEventEject = false, + Delay = 100, } -- TODO Messages @@ -343,6 +347,8 @@ function AICSAR:New(Alias,Coalition,Pilottemplate,Helotemplate,FARP,MASHZone) self.farp = FARP self.farpzone = MASHZone self.playerset = SET_CLIENT:New():FilterActive(true):FilterCategories("helicopter"):FilterStart() + self.UseEventEject = false + self.Delay = 300 -- Radio self.SRS = nil @@ -394,7 +400,7 @@ function AICSAR:New(Alias,Coalition,Pilottemplate,Helotemplate,FARP,MASHZone) self:AddTransition("*", "Stop", "Stopped") -- Stop FSM. self:HandleEvent(EVENTS.LandingAfterEjection,self._EventHandler) - self:HandleEvent(EVENTS.Ejection,self._EventHandlerEject) + self:HandleEvent(EVENTS.Ejection,self._EjectEventHandler) self:__Start(math.random(2,5)) @@ -663,20 +669,99 @@ end -- @param #AICSAR self -- @param Core.Event#EVENTDATA EventData -- @return #AICSAR self -function AICSAR:_EventHandlerEject(EventData) +function AICSAR:_EjectEventHandler(EventData) local _event = EventData -- Core.Event#EVENTDATA if _event.IniPlayerName then self.PilotStore:Push(_event.IniPlayerName) self:T(self.lid.."Pilot Ejected: ".._event.IniPlayerName) + if self.UseEventEject then + -- get position and spawn in a template pilot + local _LandingPos = COORDINATE:NewFromVec3(_event.initiator:getPosition().p) + local _country = _event.initiator:getCountry() + local _coalition = coalition.getCountryCoalition( _country ) + local data = UTILS.DeepCopy(EventData) + Unit.destroy(_event.initiator) -- shagrat remove static Pilot model + self:ScheduleOnce(self.Delay,self._DelayedSpawnPilot,self,_LandingPos,_coalition) + end end return self end +--- [Internal] Spawn a pilot +-- @param #AICSAR self +-- @param Core.Point#COORDINATE _LandingPos Landing Postion +-- @param #number _coalition Coalition side +-- @return #AICSAR self +function AICSAR:_DelayedSpawnPilot(_LandingPos,_coalition) + + local distancetofarp = _LandingPos:Get2DDistance(self.farp:GetCoordinate()) + -- Mayday Message + local Text,Soundfile,Soundlength,Subtitle = self.gettext:GetEntry("PILOTDOWN",self.locale) + local text = "" + local setting = {} + setting.MGRS_Accuracy = self.MGRS_Accuracy + local location = _LandingPos:ToStringMGRS(setting) + local msgtxt = Text..location.."!" + location = string.gsub(location,"MGRS ","") + location = string.gsub(location,"%s+","") + location = string.gsub(location,"([%a%d])","%1;") -- "0 5 1 " + location = string.gsub(location,"0","zero") + location = string.gsub(location,"9","niner") + location = "MGRS;"..location + if self.SRSGoogle then + location = string.format("%s",location) + end + text = Text .. location .. "!" + local ttstext = Text .. location .. "! Repeat! "..location + if _coalition == self.coalition then + if self.verbose then + MESSAGE:New(msgtxt,15,"AICSAR"):ToCoalition(self.coalition) + -- MESSAGE:New(msgtxt,15,"AICSAR"):ToLog() + end + if self.SRSRadio then + local sound = SOUNDFILE:New(Soundfile,self.SRSSoundPath,Soundlength) + sound:SetPlayWithSRS(true) + self.SRS:PlaySoundFile(sound,2) + elseif self.DCSRadio then + self:DCSRadioBroadcast(Soundfile,Soundlength,text) + elseif self.SRSTTSRadio then + if self.SRSPilotVoice then + self.SRSQ:NewTransmission(ttstext,nil,self.SRSPilot,nil,1) + else + self.SRSQ:NewTransmission(ttstext,nil,self.SRS,nil,1) + end + end + end + + -- further processing + if _coalition == self.coalition and distancetofarp <= self.maxdistance then + -- in reach + self:T(self.lid .. "Spawning new Pilot") + self.pilotindex = self.pilotindex + 1 + local newpilot = SPAWN:NewWithAlias(self.template,string.format("%s-AICSAR-%d",self.template, self.pilotindex)) + newpilot:InitDelayOff() + newpilot:OnSpawnGroup( + function (grp) + self.pilotqueue[self.pilotindex] = grp + end + ) + newpilot:SpawnFromCoordinate(_LandingPos) + + self:__PilotDown(2,_LandingPos,true) + elseif _coalition == self.coalition and distancetofarp > self.maxdistance then + -- out of reach, apologies, too far off + self:T(self.lid .. "Pilot out of reach") + self:__PilotDown(2,_LandingPos,false) + end + return self +end + --- [Internal] Catch the landing after ejection and spawn a pilot in situ. -- @param #AICSAR self -- @param Core.Event#EVENTDATA EventData +-- @param #boolean FromEject -- @return #AICSAR self -function AICSAR:_EventHandler(EventData) +function AICSAR:_EventHandler(EventData, FromEject) self:T(self.lid .. "OnEventLandingAfterEjection ID=" .. EventData.id) -- autorescue on off? @@ -686,6 +771,8 @@ function AICSAR:_EventHandler(EventData) end end + if self.UseEventEject and (not FromEject) then return self end + local _event = EventData -- Core.Event#EVENTDATA -- get position and spawn in a template pilot local _LandingPos = COORDINATE:NewFromVec3(_event.initiator:getPosition().p) diff --git a/Moose Development/Moose/Wrapper/Client.lua b/Moose Development/Moose/Wrapper/Client.lua index 12f2baa13..576e61db8 100644 --- a/Moose Development/Moose/Wrapper/Client.lua +++ b/Moose Development/Moose/Wrapper/Client.lua @@ -95,6 +95,22 @@ function CLIENT:Find(DCSUnit, Error) end end +--- Finds a CLIENT from the _DATABASE using the relevant player name. +-- @param #CLIENT self +-- @param #string Name Name of the player +-- @return #CLIENT or nil if not found +function CLIENT:FindByPlayerName(Name) + + local foundclient = nil + _DATABASE:ForEachClient( + function(client) + if client:GetPlayerName() == Name then + foundclient = client + end + end + ) + return foundclient +end --- Finds a CLIENT from the _DATABASE using the relevant Client Unit Name. -- As an optional parameter, a briefing text can be given also. diff --git a/Moose Development/Moose/Wrapper/Net.lua b/Moose Development/Moose/Wrapper/Net.lua index 300775eb9..4f28e8a6d 100644 --- a/Moose Development/Moose/Wrapper/Net.lua +++ b/Moose Development/Moose/Wrapper/Net.lua @@ -31,7 +31,7 @@ do -- @field #NET NET = { ClassName = "NET", - Version = "0.0.6", + Version = "0.0.7", BlockTime = 600, BlockedPilots = {}, BlockedUCIDs = {}, @@ -154,17 +154,18 @@ function NET:_EventHandler(EventData) local name = data.IniPlayerName and data.IniPlayerName or data.IniUnit:GetPlayerName() local ucid = self:GetPlayerUCID(nil,name) local PlayerID = self:GetPlayerIDByName(name) or "none" + local PlayerSide, PlayerSlot = self:GetSlot(data.IniUnit) local TNow = timer.getTime() - self:I(self.lid.."Event for: "..name.." | UCID: "..ucid) + self:T(self.lid.."Event for: "..name.." | UCID: "..ucid) if self.BlockedPilots[name] then - self:I(self.lid.."Pilot "..name.." ID "..PlayerID.." Blocked for another "..self.BlockedPilots[name]-timer.getTime().." seconds!") + self:T(self.lid.."Pilot "..name.." ID "..PlayerID.." Blocked for another "..self.BlockedPilots[name]-timer.getTime().." seconds!") end if self.BlockedUCIDs[ucid] then - self:I(self.lid.."Pilot "..name.." ID "..PlayerID.." Blocked for another "..self.BlockedUCIDs[ucid]-timer.getTime().." seconds!") + self:T(self.lid.."Pilot "..name.." ID "..PlayerID.." Blocked for another "..self.BlockedUCIDs[ucid]-timer.getTime().." seconds!") end -- Joining if data.id == EVENTS.PlayerEnterUnit or data.id == EVENTS.PlayerEnterAircraft then - self:I(self.lid.."Pilot Joining: "..name.." | UCID: "..ucid) + self:T(self.lid.."Pilot Joining: "..name.." | UCID: "..ucid) -- Check for known pilots if self.BlockedPilots[name] and TNow < self.BlockedPilots[name] then -- block pilot by name @@ -177,7 +178,13 @@ function NET:_EventHandler(EventData) local outcome = net.force_player_slot(tonumber(PlayerID), 0, '' ) end else - self.KnownPilots[name] = true + self.KnownPilots[name] = { + name = name, + ucid = ucid, + id = PlayerID, + side = PlayerSide, + slot = PlayerSlot, + } if (self.BlockedUCIDs[ucid] and TNow >= self.BlockedUCIDs[ucid]) or (self.BlockedPilots[name] and TNow >= self.BlockedPilots[name]) then self.BlockedPilots[name] = nil self.BlockedUCIDs[ucid] = nil @@ -188,21 +195,21 @@ function NET:_EventHandler(EventData) end -- Leaving if data.id == EVENTS.PlayerLeaveUnit and self.KnownPilots[name] then - self:I(self.lid.."Pilot Leaving: "..name.." | UCID: "..ucid) + self:T(self.lid.."Pilot Leaving: "..name.." | UCID: "..ucid) self:__PlayerLeft(1,data.IniUnit,name) self.KnownPilots[name] = false return self end -- Ejected if data.id == EVENTS.Ejection and self.KnownPilots[name] then - self:I(self.lid.."Pilot Ejecting: "..name.." | UCID: "..ucid) + self:T(self.lid.."Pilot Ejecting: "..name.." | UCID: "..ucid) self:__PlayerEjected(1,data.IniUnit,name) self.KnownPilots[name] = false return self end -- Dead, Crash, Suicide if (data.id == EVENTS.PilotDead or data.id == EVENTS.SelfKillPilot or data.id == EVENTS.Crash) and self.KnownPilots[name] then - self:I(self.lid.."Pilot Dead: "..name.." | UCID: "..ucid) + self:T(self.lid.."Pilot Dead: "..name.." | UCID: "..ucid) self:__PlayerDied(1,data.IniUnit,name) self.KnownPilots[name] = false return self @@ -219,7 +226,7 @@ end -- @param #string Message (optional) Message to be sent via chat. -- @return #NET self function NET:BlockPlayer(Client,PlayerName,Seconds,Message) - self:I({PlayerName,Seconds,Message}) + self:T({PlayerName,Seconds,Message}) local name = PlayerName if Client and (not PlayerName) then name = Client:GetPlayerName() @@ -322,10 +329,10 @@ end function NET:GetPlayerIDByName(Name) if not Name then return nil end local playerList = self:GetPlayerList() - self:I({playerList}) + self:T({playerList}) for i=1,#playerList do local playerName = net.get_name(i) - self:I({playerName}) + self:T({playerName}) if playerName == Name then return playerList[i] end