#PLAYERRECCE

* Added setting of laser distance as camera sight calc is a no-starter
* Added specific laser zone of 20mxlength to catch targets to lase
* Reworked detection of hit on lased target
This commit is contained in:
Applevangelist 2022-10-07 14:29:54 +02:00
parent 6a22e03689
commit ff194b4425
2 changed files with 167 additions and 69 deletions

View File

@ -45,6 +45,9 @@
-- @field #string version -- @field #string version
-- @field #table ViewZone -- @field #table ViewZone
-- @field #table ViewZoneVisual -- @field #table ViewZoneVisual
-- @field #table ViewZoneLaser
-- @field #table LaserFOV
-- @field #table LaserTarget
-- @field Core.Set#SET_CLIENT PlayerSet -- @field Core.Set#SET_CLIENT PlayerSet
-- @field #string Name -- @field #string Name
-- @field #number Coalition -- @field #number Coalition
@ -94,9 +97,12 @@ PLAYERRECCE = {
ClassName = "PLAYERRECCE", ClassName = "PLAYERRECCE",
verbose = true, verbose = true,
lid = nil, lid = nil,
version = "0.0.10", version = "0.0.11",
ViewZone = {}, ViewZone = {},
ViewZoneVisual = {}, ViewZoneVisual = {},
ViewZoneLaser = {},
LaserFOV = {},
LaserTarget = {},
PlayerSet = nil, PlayerSet = nil,
debug = true, debug = true,
LaserSpots = {}, LaserSpots = {},
@ -470,22 +476,20 @@ end
-- @param #PLAYERRECCE self -- @param #PLAYERRECCE self
-- @param Wrapper.Unit#UNIT unit The unit which is looking -- @param Wrapper.Unit#UNIT unit The unit which is looking
-- @param #number vheading Heading where the unit or camera is looking -- @param #number vheading Heading where the unit or camera is looking
-- @param #number vnod Nod down in degrees -- @param #number minview Min line of sight - for lasing
-- @param #number maxview Max line of sight, depending on height -- @param #number maxview Max line of sight
-- @param #number angle Angle left/right to be added to heading to form a triangle -- @param #number angle Angle left/right to be added to heading to form a triangle
-- @param #boolean camon Camera is switched on -- @param #boolean camon Camera is switched on
-- @param #boolean draw Draw the zone on the F10 map -- @param #boolean laser Zone is for lasing
-- @return Core.Zone#ZONE_POLYGON ViewZone or nil if camera is off -- @return Core.Zone#ZONE_POLYGON ViewZone or nil if camera is off
function PLAYERRECCE:_GetViewZone(unit, vheading, vnod, maxview, angle, camon, draw) function PLAYERRECCE:_GetViewZone(unit, vheading, minview, maxview, angle, camon, laser)
self:T(self.lid.."_GetViewZone") self:T(self.lid.."_GetViewZone")
local viewzone = nil local viewzone = nil
if not camon then return nil end --if not camon then return nil end
if unit and unit:IsAlive() then if unit and unit:IsAlive() then
local unitname = unit:GetName() local unitname = unit:GetName()
if self.ViewZone[unitname] then if not laser then
self.ViewZone[unitname]:UndrawZone() -- Triangle
end
--local vheading, vnod, maxview, vivon = self:GetGazelleVivianneSight(unit)
local startpos = unit:GetCoordinate() local startpos = unit:GetCoordinate()
local heading1 = (vheading+angle)%360 local heading1 = (vheading+angle)%360
local heading2 = (vheading-angle)%360 local heading2 = (vheading-angle)%360
@ -496,9 +500,29 @@ function PLAYERRECCE:_GetViewZone(unit, vheading, vnod, maxview, angle, camon, d
table.insert(array,pos1:GetVec2()) table.insert(array,pos1:GetVec2())
table.insert(array,pos2:GetVec2()) table.insert(array,pos2:GetVec2())
viewzone = ZONE_POLYGON:NewFromPointsArray(unitname,array) viewzone = ZONE_POLYGON:NewFromPointsArray(unitname,array)
if draw then else
viewzone:DrawZone(-1,{0,0,1},nil,nil,nil,1) -- Square
self.ViewZone[unitname] = viewzone local startp = unit:GetCoordinate()
local heading1 = (vheading+90)%360
local heading2 = (vheading-90)%360
self:I({heading1,heading2})
local startpos = startp:Translate(minview,vheading)
--startpos:MarkToAll("Startpoint")
local pos1 = startpos:Translate(10,heading1)
local pos2 = startpos:Translate(10,heading2)
local pos3 = pos1:Translate(maxview,vheading)
local pos4 = pos2:Translate(maxview,vheading)
--pos1:MarkToAll("P1")
--pos2:MarkToAll("P2")
--pos3:MarkToAll("P3")
--pos4:MarkToAll("P4")
local array = {}
--table.insert(array,startpos:GetVec2())
table.insert(array,pos1:GetVec2())
table.insert(array,pos2:GetVec2())
table.insert(array,pos4:GetVec2())
table.insert(array,pos3:GetVec2())
viewzone = ZONE_POLYGON:NewFromPointsArray(unitname,array)
end end
end end
return viewzone return viewzone
@ -564,24 +588,43 @@ end
--@param #boolean camera If true, use the unit's camera for targets in sight --@param #boolean camera If true, use the unit's camera for targets in sight
--@return Core.Set#SET_UNIT Set of targets, can be empty! --@return Core.Set#SET_UNIT Set of targets, can be empty!
--@return #number count Count of targets --@return #number count Count of targets
function PLAYERRECCE:_GetTargetSet(unit,camera) function PLAYERRECCE:_GetTargetSet(unit,camera,laser)
self:T(self.lid.."_GetTargetSet") self:T(self.lid.."_GetTargetSet")
local finaltargets = SET_UNIT:New() local finaltargets = SET_UNIT:New()
local finalcount = 0 local finalcount = 0
local minview = 0
local typename = unit:GetTypeName()
local playername = unit:GetPlayerName()
local maxview = self.MaxViewDistance[typename] or 5000
local heading,nod,maxview,angle = 0,30,8000,10 local heading,nod,maxview,angle = 0,30,8000,10
local camon = true local camon = true
local typename = unit:GetTypeName()
local name = unit:GetName() local name = unit:GetName()
if string.find(typename,"SA342") and camera then if string.find(typename,"SA342") and camera then
heading,nod,maxview,camon = self:_GetGazelleVivianneSight(unit) heading,nod,maxview,camon = self:_GetGazelleVivianneSight(unit)
angle=10 angle=10
-- Model nod and actual TV view don't compute
maxview = self.MaxViewDistance[typename] or 5000
else else
-- visual -- visual
heading = unit:GetHeading() heading = unit:GetHeading()
nod,maxview,camon = 10,1000,true nod,maxview,camon = 10,1000,true
angle = 45 angle = 45
end end
local zone = self:_GetViewZone(unit,heading,nod,maxview,angle,camon) if laser then
-- get min/max values
if not self.LaserFOV[playername] then
minview = 100
maxview = 2000
self.LaserFOV[playername] = {
min=100,
max=2000,
}
else
minview = self.LaserFOV[playername].min
maxview = self.LaserFOV[playername].max
end
end
local zone = self:_GetViewZone(unit,heading,minview,maxview,angle,camon,laser)
if zone then if zone then
local redcoalition = "red" local redcoalition = "red"
if self.Coalition == coalition.side.RED then if self.Coalition == coalition.side.RED then
@ -612,13 +655,9 @@ end
---[Internal] ---[Internal]
--@param #PLAYERRECCE self --@param #PLAYERRECCE self
--@param Core.Set#SET_UNIT targetset Set of targets, can be empty! --@param Core.Set#SET_UNIT targetset Set of targets, can be empty!
--@return Wrapper.Unit#UNIT Target --@return Wrapper.Unit#UNIT Target or nil
function PLAYERRECCE:_GetHVTTarget(targetset) function PLAYERRECCE:_GetHVTTarget(targetset)
self:T(self.lid.."_GetHVTTarget") self:T(self.lid.."_GetHVTTarget")
-- get one target
-- local target = targetset:GetRandom() -- Wrapper.Unit#UNIT
-- sort units -- sort units
local unitsbythreat = {} local unitsbythreat = {}
local minthreat = self.minthreatlevel or 0 local minthreat = self.minthreatlevel or 0
@ -642,7 +681,11 @@ function PLAYERRECCE:_GetHVTTarget(targetset)
return aNum > bNum -- Return their comparisons, < for ascending, > for descending return aNum > bNum -- Return their comparisons, < for ascending, > for descending
end) end)
if unitsbythreat[1] and unitsbythreat[1][1] then
return unitsbythreat[1][1] return unitsbythreat[1][1]
else
return nil
end
end end
--- [Internal] --- [Internal]
@ -667,37 +710,32 @@ function PLAYERRECCE:_LaseTarget(client,targetset)
else else
laser = self.LaserSpots[playername] laser = self.LaserSpots[playername]
end end
if not laser:IsLasing() and target then if self.LaserTarget[playername] then
-- still looking at target?
local target=self.LaserTarget[playername] -- Ops.Target#TARGET
local oldtarget = target:GetObject() --or laser.Target
self:I("Targetstate: "..target:GetState())
if not oldtarget or targetset:IsNotInSet(oldtarget) or target:IsDead() or target:IsDestroyed() then
-- lost LOS or dead
laser:LaseOff()
if target:IsDead() or target:IsDestroyed() or target:GetLife() < 2 then
self:__Shack(-1,client,oldtarget)
self.LaserTarget[playername] = nil
else
self:__TargetLOSLost(-1,client,oldtarget)
self.LaserTarget[playername] = nil
end
end
elseif not laser:IsLasing() and target then
local relativecam = self.LaserRelativePos[client:GetTypeName()] local relativecam = self.LaserRelativePos[client:GetTypeName()]
laser:SetRelativeStartPosition(relativecam) laser:SetRelativeStartPosition(relativecam)
local lasercode = self.UnitLaserCodes[playername] or laser.LaserCode or 1688 local lasercode = self.UnitLaserCodes[playername] or laser.LaserCode or 1688
local lasingtime = self.lasingtime or 60 local lasingtime = self.lasingtime or 60
local targettype = target:GetTypeName() local targettype = target:GetTypeName()
laser:LaseOn(target,lasercode,lasingtime) laser:LaseOn(target,lasercode,lasingtime)
self.LaserTarget[playername] = TARGET:New(target)
local function Shack(dT,client,target,targettype) self.LaserTarget[playername].TStatus = 9
self:__Shack(-1,client,target,targettype)
end
function laser:OnAfterDestroyed(From,Event,To)
Shack(-1,client,target,targettype)
end
self:__TargetLasing(-1,client,target,lasercode,lasingtime) self:__TargetLasing(-1,client,target,lasercode,lasingtime)
else
-- still looking at target?
local oldtarget=laser.Target
if targetset:IsNotInSet(oldtarget) or (not oldtarget) or (not oldtarget:IsAlive()) or (oldtarget:GetLife() < 2) then
-- lost LOS or dead
--local targettype = oldtarget:GetTypeName()
laser:LaseOff()
self:I(self.lid.."*** Laser off!")
if (not oldtarget:IsAlive()) or (oldtarget:GetLife() < 2) then
self:__Shack(-1,client,oldtarget)
else
self:__TargetLOSLost(-1,client,oldtarget)
end
end
end end
return self return self
end end
@ -762,6 +800,35 @@ function PLAYERRECCE:_SwitchLasing(client,group,playername)
return self return self
end end
--- [Internal]
-- @param #PLAYERRECCE self
-- @param Wrapper.Client#CLIENT client
-- @param Wrapper.Group#GROUP group
-- @param #string playername
-- @param #number mindist
-- @param #number maxdist
-- @return #PLAYERRECCE self
function PLAYERRECCE:_SwitchLasingDist(client,group,playername,mindist,maxdist)
self:T(self.lid.."_SwitchLasingDist")
local mind = mindist or 100
local maxd = maxdist or 2000
if not self.LaserFOV[playername] then
self.LaserFOV[playername] = {
min=mind,
max=maxd,
}
else
self.LaserFOV[playername].min=mind
self.LaserFOV[playername].max=maxd
end
MESSAGE:New(string.format("Laser distance set to %d-%dm!",mindist,maxdist),10,"FACA"):ToClient(client)
if self.ClientMenus[playername] then
self.ClientMenus[playername]:Remove()
self.ClientMenus[playername]=nil
end
return self
end
--- [Internal] --- [Internal]
-- @param #PLAYERRECCE self -- @param #PLAYERRECCE self
-- @param Wrapper.Client#CLIENT client -- @param Wrapper.Client#CLIENT client
@ -894,7 +961,7 @@ end
-- @return #PLAYERRECCE self -- @return #PLAYERRECCE self
function PLAYERRECCE:_ReportLaserTargets(client,group,playername) function PLAYERRECCE:_ReportLaserTargets(client,group,playername)
self:T(self.lid.."_ReportLaserTargets") self:T(self.lid.."_ReportLaserTargets")
local targetset, number = self:_GetTargetSet(client,true) local targetset, number = self:_GetTargetSet(client,true,true)
if number > 0 and self.AutoLase[playername] then if number > 0 and self.AutoLase[playername] then
local Settings = ( client and _DATABASE:GetPlayerSettings( playername ) ) or _SETTINGS local Settings = ( client and _DATABASE:GetPlayerSettings( playername ) ) or _SETTINGS
local target = self:_GetHVTTarget(targetset) -- the one we're lasing local target = self:_GetHVTTarget(targetset) -- the one we're lasing
@ -1000,6 +1067,23 @@ function PLAYERRECCE:_BuildMenus()
local txtonstation = self.AutoLase[playername] and "ON" or "OFF" local txtonstation = self.AutoLase[playername] and "ON" or "OFF"
local text = string.format("Switch Lasing (%s)",txtonstation) local text = string.format("Switch Lasing (%s)",txtonstation)
local lasemenu = MENU_GROUP_COMMAND:New(group,text,self.ClientMenus[playername],self._SwitchLasing,self,client,group,playername) local lasemenu = MENU_GROUP_COMMAND:New(group,text,self.ClientMenus[playername],self._SwitchLasing,self,client,group,playername)
local lasedist = MENU_GROUP:New(group,"Set Laser Distance",self.ClientMenus[playername])
local mindist = 100
local maxdist = 2000
if self.LaserFOV[playername] and self.LaserFOV[playername].max then
maxdist = self.LaserFOV[playername].max
end
local laselist={}
for i=2,8 do
local dist1 = (i*1000)-1000
local dist2 = i*1000
dist1 = dist1 == 1000 and 100 or dist1
local text = string.format("%d-%dm",dist1,dist2)
if dist2 == maxdist then
text = text .. " (*)"
end
laselist[i] = MENU_GROUP_COMMAND:New(group,text,lasedist,self._SwitchLasingDist,self,client,group,playername,dist1,dist2)
end
end end
local targetmenu = MENU_GROUP:New(group,"Target Report",self.ClientMenus[playername]) local targetmenu = MENU_GROUP:New(group,"Target Report",self.ClientMenus[playername])
if canlase then if canlase then
@ -1216,14 +1300,26 @@ function PLAYERRECCE:onafterStatus(From, Event, To)
end end
end end
self:T({targetcount=targetcount}) self:T({targetcount=targetcount})
-- lase targets on camera
if targetcount > 0 then
if self.CanLase[client:GetTypeName()] and self.AutoLase[playername] then
-- DONE move to lase at will
self:_LaseTarget(client,targetset)
end
end
-- lase targets on camera
if self.AutoLase[playername] then
local laserset, targetcount, lzone = self:_GetTargetSet(client,true,true)
if targetcount > 0 or self.LaserTarget[playername] then
if self.CanLase[client:GetTypeName()] then
-- DONE move to lase at will
self:_LaseTarget(client,laserset)
end
end
if lzone then
if self.ViewZoneLaser[playername] then
self.ViewZoneLaser[playername]:UndrawZone()
end
if self.debug and tzone then
self.ViewZoneLaser[playername]=lzone:DrawZone(self.Coalition,{0,1,0},nil,nil,nil,1)
end
end
self:I({lasercount=targetcount})
end
-- visual targets -- visual targets
local vistargetset, vistargetcount, viszone = self:_GetTargetSet(client,false) local vistargetset, vistargetcount, viszone = self:_GetTargetSet(client,false)
if vistargetset then if vistargetset then
@ -1532,7 +1628,7 @@ function PLAYERRECCE:onafterShack(From, Event, To, Client, Target, Targettype)
if self.ReferencePoint then if self.ReferencePoint then
coordtext = coord:ToStringFromRPShort(self.ReferencePoint,self.RPName,Client,Settings) coordtext = coord:ToStringFromRPShort(self.ReferencePoint,self.RPName,Client,Settings)
end end
local targettype = Targettype local targettype = "target"
if self.AttackSet then if self.AttackSet then
for _,_client in pairs(self.AttackSet.Set) do for _,_client in pairs(self.AttackSet.Set) do
local client = _client --Wrapper.Client#CLIENT local client = _client --Wrapper.Client#CLIENT
@ -1575,7 +1671,7 @@ function PLAYERRECCE:onafterTargetLOSLost(From, Event, To, Client, Target)
if self.ReferencePoint then if self.ReferencePoint then
coordtext = coord:ToStringFromRPShort(self.ReferencePoint,self.RPName,Client,Settings) coordtext = coord:ToStringFromRPShort(self.ReferencePoint,self.RPName,Client,Settings)
end end
local targettype = Target:GetTypeName() local targettype = "target" --Target:GetTypeName()
if self.AttackSet then if self.AttackSet then
for _,_client in pairs(self.AttackSet.Set) do for _,_client in pairs(self.AttackSet.Set) do
local client = _client --Wrapper.Client#CLIENT local client = _client --Wrapper.Client#CLIENT

View File

@ -69,6 +69,7 @@ TARGET = {
casualties = {}, casualties = {},
threatlevel0 = 0, threatlevel0 = 0,
conditionStart = {}, conditionStart = {},
TStatus = 30,
} }
@ -146,7 +147,7 @@ _TARGETID=0
--- TARGET class version. --- TARGET class version.
-- @field #string version -- @field #string version
TARGET.version="0.5.2" TARGET.version="0.5.3"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list -- TODO list
@ -185,6 +186,7 @@ function TARGET:New(TargetObject)
-- Defaults. -- Defaults.
self:SetPriority() self:SetPriority()
self:SetImportance() self:SetImportance()
self.TStatus = 30
-- Log ID. -- Log ID.
self.lid=string.format("TARGET #%03d | ", _TARGETID) self.lid=string.format("TARGET #%03d | ", _TARGETID)
@ -570,7 +572,7 @@ function TARGET:onafterStatus(From, Event, To)
-- Update status again in 30 sec. -- Update status again in 30 sec.
if self:IsAlive() then if self:IsAlive() then
self:__Status(-30) self:__Status(-self.TStatus)
end end
end end