From 0166b53e21a1fdb3427481bebe5278c8f4284f78 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Tue, 16 Aug 2022 16:48:13 +0200 Subject: [PATCH] #PLAYERTASKCONTROLLER * Added option to suppress screen output * Added target information via SRS * Added target radius for BAI vs CAS and target type COORDINATE to be configureable * Refined SRS output * Added STATIC targets to get task type BOMBING * Added solution to detect bombing runways (kind of, bombing occuring in AFB zone) * Added solution for COORDINATE and ZONE type TARGETs (find enemy GROUP and/or STATIC objects in target radius) * Refined documentation --- Moose Development/Moose/Ops/PlayerTask.lua | 234 ++++++++++++++++----- 1 file changed, 180 insertions(+), 54 deletions(-) diff --git a/Moose Development/Moose/Ops/PlayerTask.lua b/Moose Development/Moose/Ops/PlayerTask.lua index bc0201567..219d353ea 100644 --- a/Moose Development/Moose/Ops/PlayerTask.lua +++ b/Moose Development/Moose/Ops/PlayerTask.lua @@ -577,7 +577,7 @@ end function PLAYERTASK:onafterClientAdded(From, Event, To, Client) self:T({From, Event, To}) if Client and self.verbose then - local text = string.format("Player %s joined task %d!",Client:GetPlayerName() or "Generic",self.PlayerTaskNr) + local text = string.format("Player %s joined task %03d!",Client:GetPlayerName() or "Generic",self.PlayerTaskNr) self:I(self.lid..text) end return self @@ -681,6 +681,8 @@ end -- @field #boolean usecluster -- @field #number ClusterRadius -- @field #string MenuName +-- @field #boolean NoScreenOutput +-- @field #number TargetRadius -- @@ -697,19 +699,21 @@ PLAYERTASKCONTROLLER = { usecluster = false, MenuName = nil, ClusterRadius = 1250, + NoScreenOutput = false, + TargetRadius = 500, } --- -- @field Type PLAYERTASKCONTROLLER.Type = { - A2A = "Air-To-Air", - A2G = "Air-To-Ground", - A2S = "Air-To-Sea", + ["A2A"] = "Air-To-Air", + ["A2G"] = "Air-To-Ground", + ["A2S"] = "Air-To-Sea", } --- PLAYERTASK class version. -- @field #string version -PLAYERTASKCONTROLLER.version="0.0.11" +PLAYERTASKCONTROLLER.version="0.0.12" --- Constructor -- @param #PLAYERTASKCONTROLLER self @@ -734,6 +738,7 @@ function PLAYERTASKCONTROLLER:New(Name, Coalition, Type, ClientFilter) end self.ClusterRadius = 1250 + self.TargetRadius = 500 self.ClientFilter = ClientFilter or "" @@ -867,12 +872,16 @@ function PLAYERTASKCONTROLLER:_EventHandler(EventData) if EventData.IniPlayerName and EventData.IniGroup and self.UseSRS then self:T(self.lid.."Event for player: "..EventData.IniPlayerName) local frequency = self.Frequency - if type(frequency) == "table" then frequency = frequency[1] end + local freqtext = "" + if type(frequency) == "table" then + freqtext = "frequencies "..table.concat(frequency,", ") + else + freqtext = string.format("frequency %.3f",frequency) + end local modulation = self.Modulation if type(modulation) == "table" then modulation = modulation[1] end modulation = UTILS.GetModulationName(modulation) - local text = string.format("%s, %s, switch to frequency %.3f for task assignment!",EventData.IniPlayerName,self.MenuName or self.Name,frequency) - --local m = MESSAGE:New(text,30,"Tasking",true):ToGroup(EventData.IniGroup) + local text = string.format("%s, %s, switch to %s for task assignment!",EventData.IniPlayerName,self.MenuName or self.Name,freqtext) self.SRSQueue:NewTransmission(text,nil,self.SRS,timer.getAbsTime()+60,2,{EventData.IniGroup},text,30,self.BCFrequency,self.BCModulation) end end @@ -884,6 +893,26 @@ function PLAYERTASKCONTROLLER:_DummyMenu(group) return self end +--- [User] Switch screen output. +-- @param #PLAYERTASKCONTROLLER self +-- @param #boolean OnOff. Switch screen output off (true) or on (false) +-- @return #PLAYERTASKCONTROLLER self +function PLAYERTASKCONTROLLER:SuppressScreenOutput(OnOff) + self:T(self.lid.."SuppressScreenOutput") + self.NoScreenOutput = OnOff or false + return self +end + +--- [User] Set target radius. Determines the zone radius to distinguish CAS from BAI tasks and to find enemies if the TARGET object is a COORDINATE. +-- @param #PLAYERTASKCONTROLLER self +-- @param #number Radius Radius to use in meters. Defaults to 500 meters. +-- @return #PLAYERTASKCONTROLLER self +function PLAYERTASKCONTROLLER:SetTargetRadius(Radius) + self:T(self.lid.."SetTargetRadius") + self.TargetRadius = Radius or 500 + return self +end + --- [User] Set the cluster radius if you want to use target clusters rather than single group detection. -- Note that for a controller type A2A target clustering is on by default. Also remember that the diameter of the resulting zone is double the radius. -- @param #PLAYERTASKCONTROLLER self @@ -1019,7 +1048,7 @@ end --- [User] Add a target object to the target queue -- @param #PLAYERTASKCONTROLLER self --- @param Wrapper.Positionable#POSITIONABLE Target The target GROUP, SET\_GROUP, UNIT, SET\_UNIT, STATIC, SET\_STATIC, AIRBASE or COORDINATE. +-- @param Wrapper.Positionable#POSITIONABLE Target The target GROUP, SET\_GROUP, UNIT, SET\_UNIT, STATIC, SET\_STATIC, AIRBASE, ZONE or COORDINATE. -- @return #PLAYERTASKCONTROLLER self function PLAYERTASKCONTROLLER:AddTarget(Target) self:T(self.lid.."AddTarget") @@ -1075,18 +1104,22 @@ function PLAYERTASKCONTROLLER:_AddTask(Target) end end ) + elseif targetobject:IsInstanceOf("SET_STATIC") or targetobject:IsInstanceOf("STATIC") then + self:T("BOMBING SET_STATIC or STATIC") + type = AUFTRAG.Type.BOMBING + ttstype = "bombing" end - -- if there are no friendlies nearby ~2km and task isn't SEAD, then it's BAI + -- if there are no friendlies nearby ~0.5km and task isn't SEAD, then it's BAI local targetcoord = Target:GetCoordinate() local targetvec2 = targetcoord:GetVec2() - local targetzone = ZONE_RADIUS:New(self.Name,targetvec2,2000) + local targetzone = ZONE_RADIUS:New(self.Name,targetvec2,self.TargetRadius) local coalition = targetobject:GetCoalitionName() or "Blue" coalition = string.lower(coalition) self:T("Target coalition is "..tostring(coalition)) local filtercoalition = "blue" if coalition == "blue" then filtercoalition = "red" end local friendlyset = SET_GROUP:New():FilterCategoryGround():FilterCoalitions(filtercoalition):FilterZones({targetzone}):FilterOnce() - if friendlyset:Count() == 0 and type ~= AUFTRAG.Type.SEAD then + if friendlyset:Count() == 0 and type == AUFTRAG.Type.CAS then type = AUFTRAG.Type.BAI ttstype = "battle field air interdiction" end @@ -1097,19 +1130,57 @@ function PLAYERTASKCONTROLLER:_AddTask(Target) type = AUFTRAG.Type.INTERCEPT ttstype = "intercept" elseif cat == TARGET.Category.AIRBASE then - --TODO: Define Success Criteria, AB hit? Runway blocked, how to determine? change of coalition? + --TODO: Define Success Criteria, AB hit? Runway blocked, how to determine? change of coalition? Void of enemies? + -- Current implementation - bombing in AFB zone (EVENTS.Shot) type = AUFTRAG.Type.BOMBRUNWAY ttstype = "bomb runway" elseif cat == TARGET.Category.COORDINATE or cat == TARGET.Category.ZONE then --TODO: Define Success Criteria, void of enemies? - type = AUFTRAG.Type.BOMBING - ttstype = "bombing" + -- Current implementation - find SET of enemies in ZONE or 500m radius around coordinate, and assign as targets + local zone = Target:GetObject() + if cat == TARGET.Category.COORDINATE then + zone = ZONE_RADIUS:New("TargetZone-"..math.random(1,10000),Target:GetVec2(),self.TargetRadius) + end + -- find some enemies around there... + local enemies = self.CoalitionName == "Blue" and "red" or "blue" + local enemysetg = SET_GROUP:New():FilterCoalitions(enemies):FilterCategoryGround():FilterActive(true):FilterZones({zone}):FilterOnce() + local enemysets = SET_STATIC:New():FilterCoalitions(enemies):FilterZones({zone}):FilterOnce() + local countg = enemysetg:Count() + local counts = enemysets:Count() + if countg > 0 then + self:AddTarget(enemysetg) + end + if counts > 0 then + self:AddTarget(enemysets) + end + return self end local task = PLAYERTASK:New(type,Target,self.repeatonfailed,self.repeattimes,ttstype) + + task.coalition = self.Coalition + + if type == AUFTRAG.Type.BOMBRUNWAY then + -- task to handle event shot + task:HandleEvent(EVENTS.Shot) + function task:OnEventShot(EventData) + local data = EventData -- Core.Event#EVENTDATA EventData + local wcat = data.Weapon:getCategory() -- cat 2 or 3 + local coord = data.IniUnit:GetCoordinate() or data.IniGroup:GetCoordinate() + local coal = data.IniCoalition + local afbzone = AIRBASE:FindByName(Target:GetName()):GetZone() + local inzone = afbzone:IsVec2InZone(coord:GetVec2() or {x=0, y=0}) + if coal == task.coalition and (wcat == 2 or wcat == 3) and inzone then + -- bombing/rockets inside target AFB zone - well done! + task:__Success(-20) + end + end + end + task:_SetController(self) self.TaskQueue:Push(task) self:__TaskAdded(-1,task) + return self end @@ -1124,7 +1195,9 @@ function PLAYERTASKCONTROLLER:_JoinTask(Group, Client, Task) local playername = Client:GetPlayerName() if self.TasksPerPlayer:HasUniqueID(playername) then -- Player already has a task - local m=MESSAGE:New("You already have one active task! Complete it first!","10","Info"):ToGroup(Group) + if not self.NoScreenOutput then + local m=MESSAGE:New("You already have one active task! Complete it first!","10","Tasking"):ToGroup(Group) + end return self end Task:AddClient(Client) @@ -1133,20 +1206,17 @@ function PLAYERTASKCONTROLLER:_JoinTask(Group, Client, Task) if taskstate ~= "Executing" and taskstate ~= "Done" then Task:__Requested(-1) Task:__Executing(-2) - local text = string.format("Pilot %s joined task %d", playername, Task.PlayerTaskNr) + local text = string.format("%s, pilot %s joined task %03d", self.MenuName or self.Name, playername, Task.PlayerTaskNr) self:T(self.lid..text) - local m=MESSAGE:New(text,"10","Info"):ToAll() + if not self.NoScreenOutput then + local m=MESSAGE:New(text,"10","Tasking"):ToAll() + end if self.UseSRS then self.SRSQueue:NewTransmission(text,nil,self.SRS,nil,2) end self.TasksPerPlayer:Push(Task,playername) -- clear menu self:_BuildMenus(Client) - --[[ - if self.PlayerMenu[playername] then - self.PlayerMenu[playername]:RemoveSubMenus() - end - --]] end return self end @@ -1162,12 +1232,24 @@ function PLAYERTASKCONTROLLER:_ActiveTaskInfo(Group, Client) local text = "" if self.TasksPerPlayer:HasUniqueID(playername) then -- TODO: Show multiple? - local task = self.TasksPerPlayer:GetIDStack() + --local task = self.TasksPerPlayer:GetIDStack() local task = self.TasksPerPlayer:ReadByID(playername) -- Ops.PlayerTask#PLAYERTASK - local taskname = string.format("%s Task ID %02d",task.Type,task.PlayerTaskNr) + local taskname = string.format("%s Task ID %03d",task.Type,task.PlayerTaskNr) + local ttstaskname = string.format("%s Task ID %03d",task.TTSType,task.PlayerTaskNr) local Coordinate = task.Target:GetCoordinate() - local CoordText = Coordinate:ToStringA2G(Client) + local CoordText = "" + if self.Type ~= PLAYERTASKCONTROLLER.Type.A2A then + CoordText = Coordinate:ToStringA2G(Client) + else + CoordText = Coordinate:ToStringA2A(Client) + end local ThreatLevel = task.Target:GetThreatLevelMax() + local ThreatLevelText = "high" + if ThreatLevel > 3 and ThreatLevel < 8 then + ThreatLevelText = "medium" + elseif ThreatLevel <= 3 then + ThreatLevelText = "low" + end local targets = task.Target:CountTargets() or 0 local clientlist = task:GetClients() local ThreatGraph = "[" .. string.rep( "■", ThreatLevel ) .. string.rep( "□", 10 - ThreatLevel ) .. "]: "..ThreatLevel @@ -1177,11 +1259,17 @@ function PLAYERTASKCONTROLLER:_ActiveTaskInfo(Group, Client) clienttxt = clienttxt .. _name .. ", " end clienttxt=string.gsub(clienttxt,", $",".") - text = text .. clienttxt + text = text .. clienttxt + if self.UseSRS then + local ttstext = string.format("%s, %s. Target information for %s. Threat level %s. Targets left %d. Target location %s.",self.MenuName or self.Name,playername,ttstaskname,ThreatLevelText, targets, CoordText) + self.SRSQueue:NewTransmission(ttstext,nil,self.SRS,nil,2) + end else text = "No active task!" end - local m=MESSAGE:New(text,15,"Tasking"):ToGroup(Group) + if not self.NoScreenOutput then + local m=MESSAGE:New(text,15,"Tasking"):ToGroup(Group) + end return self end @@ -1197,11 +1285,17 @@ function PLAYERTASKCONTROLLER:_MarkTask(Group, Client) if self.TasksPerPlayer:HasUniqueID(playername) then local task = self.TasksPerPlayer:ReadByID(playername) -- Ops.PlayerTask#PLAYERTASK task:MarkTargetOnF10Map() - text = "Task location marked!" + text = string.format("%s, copy pilot %s, task %03d location marked on map!", self.MenuName or self.Name, playername, task.PlayerTaskNr) + self:T(self.lid..text) + if self.UseSRS then + self.SRSQueue:NewTransmission(text,nil,self.SRS,nil,2) + end else text = "No active task!" end - local m=MESSAGE:New(text,15,"Info"):ToGroup(Group) + if not self.NoScreenOutput then + local m=MESSAGE:New(text,"10","Tasking"):ToGroup(Group) + end return self end @@ -1217,11 +1311,18 @@ function PLAYERTASKCONTROLLER:_SmokeTask(Group, Client) if self.TasksPerPlayer:HasUniqueID(playername) then local task = self.TasksPerPlayer:ReadByID(playername) -- Ops.PlayerTask#PLAYERTASK task:SmokeTarget() - text = "Task location smoked!" + text = string.format("%s, copy pilot %s, task %03d location smoked!", self.MenuName or self.Name, playername, task.PlayerTaskNr) + self:T(self.lid..text) + --local m=MESSAGE:New(text,"10","Tasking"):ToAll() + if self.UseSRS then + self.SRSQueue:NewTransmission(text,nil,self.SRS,nil,2) + end else text = "No active task!" end - local m=MESSAGE:New(text,15,"Info"):ToGroup(Group) + if not self.NoScreenOutput then + local m=MESSAGE:New(text,15,"Tasking"):ToGroup(Group) + end return self end @@ -1237,11 +1338,18 @@ function PLAYERTASKCONTROLLER:_FlareTask(Group, Client) if self.TasksPerPlayer:HasUniqueID(playername) then local task = self.TasksPerPlayer:ReadByID(playername) -- Ops.PlayerTask#PLAYERTASK task:FlareTarget() - text = "Task location illuminated!" + text = string.format("%s, copy pilot %s, task %03d location illuminated!", self.MenuName or self.Name, playername, task.PlayerTaskNr) + self:T(self.lid..text) + --local m=MESSAGE:New(text,"10","Tasking"):ToAll() + if self.UseSRS then + self.SRSQueue:NewTransmission(text,nil,self.SRS,nil,2) + end else text = "No active task!" end - local m=MESSAGE:New(text,15,"Info"):ToGroup(Group) + if not self.NoScreenOutput then + local m=MESSAGE:New(text,15,"Tasking"):ToGroup(Group) + end return self end @@ -1257,11 +1365,18 @@ function PLAYERTASKCONTROLLER:_AbortTask(Group, Client) if self.TasksPerPlayer:HasUniqueID(playername) then local task = self.TasksPerPlayer:PullByID(playername) -- Ops.PlayerTask#PLAYERTASK task:ClientAbort(Client) - text = "Task aborted!" + text = string.format("%s, all stations, pilot %s aborted task %03d", self.MenuName or self.Name, playername, task.PlayerTaskNr) + self:T(self.lid..text) + --local m=MESSAGE:New(text,"10","Tasking"):ToAll() + if self.UseSRS then + self.SRSQueue:NewTransmission(text,nil,self.SRS,nil,2) + end else text = "No active task!" end - local m=MESSAGE:New(text,15,"Info"):ToGroup(Group) + if not self.NoScreenOutput then + local m=MESSAGE:New(text,15,"Tasking"):ToGroup(Group) + end self:_BuildMenus(Client) return self end @@ -1518,8 +1633,8 @@ end --- [User] Set SRS TTS details - see @{Sound.SRS} for details -- @param #PLAYERTASKCONTROLLER self --- @param #number Frequency Frequency to be used. Can also be given as a table of multiple frequencies, e.g. 271 or {127,251} --- @param #number Modulation Modulation to be used. Can also be given as a table of multiple modulations, e.g. radio.modulation.AM or {radio.modulation.FM,radio.modulation.AM} +-- @param #number Frequency Frequency to be used. Can also be given as a table of multiple frequencies, e.g. 271 or {127,251}. There needs to be exactly the same number of modulations! +-- @param #number Modulation Modulation to be used. Can also be given as a table of multiple modulations, e.g. radio.modulation.AM or {radio.modulation.FM,radio.modulation.AM}. There needs to be exactly the same number of frequencies! -- @param #string PathToSRS Defaults to "C:\\Program Files\\DCS-SimpleRadio-Standalone" -- @param #string Gender Defaults to "male" -- @param #string Culture Defaults to "en-US" @@ -1541,7 +1656,7 @@ function PLAYERTASKCONTROLLER:SetSRS(Frequency,Modulation,PathToSRS,Gender,Cultu self.UseSRS = true self.Frequency = Frequency or {127,251} self.BCFrequency = self.Frequency - self.Modulation = Modulation or {radio.modulationFM,radio.modulation.AM} + self.Modulation = Modulation or {radio.modulation.FM,radio.modulation.AM} self.BCModulation = self.Modulation self.SRS=MSRS:New(self.PathToSRS,self.Frequency,self.Modulation,self.Volume) self.SRS:SetCoalition(self.Coalition) @@ -1555,8 +1670,8 @@ end --- [User] Set SRS Broadcast - for the announcement to joining players which SRS frequency, modulation to use. Use in case you want to set this differently to the standard SRS. -- @param #PLAYERTASKCONTROLLER self --- @param #number Frequency Frequency to be used. Can also be given as a table of multiple frequencies, e.g. 271 or {127,251} --- @param #number Modulation Modulation to be used. Can also be given as a table of multiple modulations, e.g. radio.modulation.AM or {radio.modulation.FM,radio.modulation.AM} +-- @param #number Frequency Frequency to be used. Can also be given as a table of multiple frequencies, e.g. 271 or {127,251}. There needs to be exactly the same number of modulations! +-- @param #number Modulation Modulation to be used. Can also be given as a table of multiple modulations, e.g. radio.modulation.AM or {radio.modulation.FM,radio.modulation.AM}. There needs to be exactly the same number of frequencies! -- @return #PLAYERTASKCONTROLLER self function PLAYERTASKCONTROLLER:SetSRSBroadcast(Frequency,Modulation) self:T(self.lid.."SetSRSBroadcast") @@ -1623,10 +1738,12 @@ end function PLAYERTASKCONTROLLER:onafterTaskCancelled(From, Event, To, Task) self:T({From, Event, To}) self:T(self.lid.."TaskCancelled") - local taskname = string.format("Task #%d %s is ancelled!", Task.PlayerTaskNr, tostring(Task.Type)) - local m = MESSAGE:New(taskname,15,"Tasking"):ToCoalition(self.Coalition) + local taskname = string.format("Task #%03d %s is cancelled!", Task.PlayerTaskNr, tostring(Task.Type)) + if not self.NoScreenOutput then + local m = MESSAGE:New(taskname,15,"Tasking"):ToCoalition(self.Coalition) + end if self.UseSRS then - taskname = string.format("Task %d %s is cancelled!", Task.PlayerTaskNr, tostring(Task.TTSType)) + taskname = string.format("%s, task %03d %s is cancelled!", self.MenuName or self.Name, Task.PlayerTaskNr, tostring(Task.TTSType)) self.SRSQueue:NewTransmission(taskname,nil,self.SRS,nil,2) end return self @@ -1642,10 +1759,12 @@ end function PLAYERTASKCONTROLLER:onafterTaskSuccess(From, Event, To, Task) self:T({From, Event, To}) self:T(self.lid.."TaskSuccess") - local taskname = string.format("Task #%d %s completed successfully!", Task.PlayerTaskNr, tostring(Task.Type)) - local m = MESSAGE:New(taskname,15,"Tasking"):ToCoalition(self.Coalition) + local taskname = string.format("Task #%03d %s completed successfully!", Task.PlayerTaskNr, tostring(Task.Type)) + if not self.NoScreenOutput then + local m = MESSAGE:New(taskname,15,"Tasking"):ToCoalition(self.Coalition) + end if self.UseSRS then - taskname = string.format("Task %d %s completed successfully!", Task.PlayerTaskNr, tostring(Task.TTSType)) + taskname = string.format("%s, task %03d %s completed successfully!", self.MenuName or self.Name, Task.PlayerTaskNr, tostring(Task.TTSType)) self.SRSQueue:NewTransmission(taskname,nil,self.SRS,nil,2) end return self @@ -1661,10 +1780,12 @@ end function PLAYERTASKCONTROLLER:onafterTaskFailed(From, Event, To, Task) self:T({From, Event, To}) self:T(self.lid.."TaskFailed") - local taskname = string.format("Task #%d %s was a failure!", Task.PlayerTaskNr, tostring(Task.Type)) - local m = MESSAGE:New(taskname,15,"Tasking"):ToCoalition(self.Coalition) + local taskname = string.format("Task #%03d %s was a failure!", Task.PlayerTaskNr, tostring(Task.Type)) + if not self.NoScreenOutput then + local m = MESSAGE:New(taskname,15,"Tasking"):ToCoalition(self.Coalition) + end if self.UseSRS then - taskname = string.format("Task %d %s was a failure!", Task.PlayerTaskNr, tostring(Task.TTSType)) + taskname = string.format("%s, task %03d %s was a failure!", self.MenuName or self.Name, Task.PlayerTaskNr, tostring(Task.TTSType)) self.SRSQueue:NewTransmission(taskname,nil,self.SRS,nil,2) end return self @@ -1680,10 +1801,12 @@ end function PLAYERTASKCONTROLLER:onafterTaskRepeatOnFailed(From, Event, To, Task) self:T({From, Event, To}) self:T(self.lid.."RepeatOnFailed") - local taskname = string.format("Task #%d %s was a failure! Replanning!", Task.PlayerTaskNr, tostring(Task.Type)) - local m = MESSAGE:New(taskname,15,"Tasking"):ToCoalition(self.Coalition) + local taskname = string.format("Task #%03d %s was a failure! Replanning!", Task.PlayerTaskNr, tostring(Task.Type)) + if not self.NoScreenOutput then + local m = MESSAGE:New(taskname,15,"Tasking"):ToCoalition(self.Coalition) + end if self.UseSRS then - taskname = string.format("Task %d %s was a failure! Replanning!", Task.PlayerTaskNr, tostring(Task.TTSType)) + taskname = string.format("%s, task %03d %s was a failure! Replanning!", self.MenuName or self.Name, Task.PlayerTaskNr, tostring(Task.TTSType)) self.SRSQueue:NewTransmission(taskname,nil,self.SRS,nil,2) end return self @@ -1700,7 +1823,9 @@ function PLAYERTASKCONTROLLER:onafterTaskAdded(From, Event, To, Task) self:T({From, Event, To}) self:T(self.lid.."TaskAdded") local taskname = string.format("%s has a new task %s", self.MenuName or self.Name, tostring(Task.Type)) - local m = MESSAGE:New(taskname,15,"Tasking"):ToCoalition(self.Coalition) + if not self.NoScreenOutput then + local m = MESSAGE:New(taskname,15,"Tasking"):ToCoalition(self.Coalition) + end if self.UseSRS then taskname = string.format("%s has a new task %s", self.MenuName or self.Name, tostring(Task.TTSType)) self.SRSQueue:NewTransmission(taskname,nil,self.SRS,nil,2) @@ -1722,6 +1847,7 @@ function PLAYERTASKCONTROLLER:onafterStop(From, Event, To) self:UnHandleEvent(EVENTS.Ejection) self:UnHandleEvent(EVENTS.Crash) self:UnHandleEvent(EVENTS.PilotDead) + self:UnHandleEvent(EVENTS.PlayerEnterAircraft) return self end