diff --git a/Moose Development/Moose/Functional/Fox2.lua b/Moose Development/Moose/Functional/Fox2.lua index c1af51467..b5e9f5642 100644 --- a/Moose Development/Moose/Functional/Fox2.lua +++ b/Moose Development/Moose/Functional/Fox2.lua @@ -367,7 +367,7 @@ function FOX2:_CheckMissileStatus() end ---- Missle +--- Missle launch. -- @param #FOX2 self -- @param #string From From state. -- @param #string Event Event. @@ -464,7 +464,9 @@ function FOX2:onafterMissileLaunch(From, Event, To, missile) if missile.targetPlayer then -- Target is a player. - target=missile.targetUnit + if missile.targetPlayer.destroy==true then + target=missile.targetUnit + end else --TODO: Check if unit is protected. end @@ -482,19 +484,23 @@ function FOX2:onafterMissileLaunch(From, Event, To, missile) for _,_player in pairs(self.players) do local player=_player --#FOX2.PlayerData - -- Player position. - local playerCoord=player.unit:GetCoordinate() + -- Check that player was not the one who launched the missile. + if player.unitname~=missile.shooterName then - -- Distance. - local dist=missileCoord:Get3DDistance(playerCoord) - - -- Maxrange from launch point to player. - local maxrange=playerCoord:Get3DDistance(missile.shotCoord) - - -- Update mindist if necessary. Only include players in range of missile. - if (mindist==nil or dist Event --> To State + self:AddTransition("Stopped", "Start", "Running") -- Start RANGE script. + self:AddTransition("*", "Status", "*") -- Status of RANGE script. + self:AddTransition("*", "Impact", "*") -- Impact of bomb/rocket/missile. + + ------------------------ + --- Pseudo Functions --- + ------------------------ + + --- Triggers the FSM event "Start". Starts the RANGE. Initializes parameters and starts event handlers. + -- @function [parent=#RANGE] Start + -- @param #RANGE self + + --- Triggers the FSM event "Start" after a delay. Starts the RANGE. Initializes parameters and starts event handlers. + -- @function [parent=#RANGE] __Start + -- @param #RANGE self + -- @param #number delay Delay in seconds. + + --- Triggers the FSM event "Stop". Stops the RANGE and all its event handlers. + -- @param #RANGE self + + --- Triggers the FSM event "Stop" after a delay. Stops the RANGE and all its event handlers. + -- @function [parent=#RANGE] __Stop + -- @param #RANGE self + -- @param #number delay Delay in seconds. + + --- Triggers the FSM event "Status". + -- @function [parent=#RANGE] Status + -- @param #RANGE self + + --- Triggers the FSM event "Status" after a delay. + -- @function [parent=#RANGE] __Status + -- @param #RANGE self + -- @param #number delay Delay in seconds. + + --- Triggers the FSM event "Impact". + -- @function [parent=#RANGE] Impact + -- @param #RANGE self + -- @param #RANGE.BombResult result Data of bombing run. + + --- Triggers the FSM delayed event "Impact". + -- @function [parent=#RANGE] __Impact + -- @param #RANGE self + -- @param #number delay Delay in seconds before the function is called. + -- @param #RANGE.BombResult result Data of the bombing run. + + --- On after "Impact" event user function. Called when a bomb/rocket/missile impacted. + -- @function [parent=#RANGE] OnAfterImpact + -- @param #RANGE self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + -- @param #RANGE.BombResult result Data of the bombing run. -- Return object. return self @@ -336,106 +439,101 @@ end --- Initializes number of targets and location of the range. Starts the event handlers. -- @param #RANGE self --- @param #number delay Delay in seconds, before the RANGE is started. Default immediately. --- @return self -function RANGE:Start(delay) - self:F() +-- @param #string From From state. +-- @param #string Event Event. +-- @param #string To To state. +function RANGE:onafterStart() - if delay and delay>0 then - SCHEDULER:New(nil, self.Start, {self}, delay) - else + -- Location/coordinate of range. + local _location=nil - -- Location/coordinate of range. - local _location=nil + -- Count bomb targets. + local _count=0 + for _,_target in pairs(self.bombingTargets) do + _count=_count+1 - -- Count bomb targets. - local _count=0 - for _,_target in pairs(self.bombingTargets) do - _count=_count+1 - - -- Get range location. + -- Get range location. + if _location==nil then + _location=self:_GetBombTargetCoordinate(_target) + end + end + self.nbombtargets=_count + + -- Count strafing targets. + _count=0 + for _,_target in pairs(self.strafeTargets) do + _count=_count+1 + + for _,_unit in pairs(_target.targets) do if _location==nil then - _location=_target.target:GetCoordinate() --Core.Point#COORDINATE + _location=_unit:GetCoordinate() end end - self.nbombtargets=_count - - -- Count strafing targets. - _count=0 - for _,_target in pairs(self.strafeTargets) do - _count=_count+1 - - for _,_unit in pairs(_target.targets) do - if _location==nil then - _location=_unit:GetCoordinate() - end - end - end - self.nstrafetargets=_count - - -- Location of the range. We simply take the first unit/target we find if it was not explicitly specified by the user. - if self.location==nil then - self.location=_location - end - - if self.location==nil then - local text=string.format("ERROR! No range location found. Number of strafe targets = %d. Number of bomb targets = %d.", self.rangename, self.nstrafetargets, self.nbombtargets) - self:E(RANGE.id..text) - return - end - - -- Define a MOOSE zone of the range. - if self.rangezone==nil then - self.rangezone=ZONE_RADIUS:New(self.rangename, {x=self.location.x, y=self.location.z}, self.rangeradius) - end - - -- Starting range. - local text=string.format("Starting RANGE %s. Number of strafe targets = %d. Number of bomb targets = %d.", self.rangename, self.nstrafetargets, self.nbombtargets) - self:I(RANGE.id..text) - MESSAGE:New(text,10):ToAllIf(self.Debug) - - -- Event handling. - if self.eventmoose then - -- Events are handled my MOOSE. - self:T(RANGE.id.."Events are handled by MOOSE.") - self:HandleEvent(EVENTS.Birth) - self:HandleEvent(EVENTS.Hit) - self:HandleEvent(EVENTS.Shot) - else - -- Events are handled directly by DCS. - self:T(RANGE.id.."Events are handled directly by DCS.") - world.addEventHandler(self) - end - - -- Make bomb target move randomly within the range zone. - for _,_target in pairs(self.bombingTargets) do + end + self.nstrafetargets=_count - -- Check if it is a static object. - local _static=self:_CheckStatic(_target.target:GetName()) - - if _target.move and _static==false and _target.speed>1 then - local unit=_target.target --Wrapper.Unit#UNIT - _target.target:PatrolZones({self.rangezone}, _target.speed*0.75, "Off road") - end - - end + -- Location of the range. We simply take the first unit/target we find if it was not explicitly specified by the user. + if self.location==nil then + self.location=_location + end + + if self.location==nil then + local text=string.format("ERROR! No range location found. Number of strafe targets = %d. Number of bomb targets = %d.", self.rangename, self.nstrafetargets, self.nbombtargets) + self:E(RANGE.id..text) + return + end + + -- Define a MOOSE zone of the range. + if self.rangezone==nil then + self.rangezone=ZONE_RADIUS:New(self.rangename, {x=self.location.x, y=self.location.z}, self.rangeradius) + end + + -- Starting range. + local text=string.format("Starting RANGE %s. Number of strafe targets = %d. Number of bomb targets = %d.", self.rangename, self.nstrafetargets, self.nbombtargets) + self:I(RANGE.id..text) + MESSAGE:New(text,10):ToAllIf(self.Debug) + + -- Event handling. + if self.eventmoose then + -- Events are handled my MOOSE. + self:T(RANGE.id.."Events are handled by MOOSE.") + self:HandleEvent(EVENTS.Birth) + self:HandleEvent(EVENTS.Hit) + self:HandleEvent(EVENTS.Shot) + else + -- Events are handled directly by DCS. + self:T(RANGE.id.."Events are handled directly by DCS.") + world.addEventHandler(self) + end + + -- Make bomb target move randomly within the range zone. + for _,_target in pairs(self.bombingTargets) do + + -- Check if it is a static object. + --local _static=self:_CheckStatic(_target.target:GetName()) + local _static=_target.type==RANGE.TargetType.STATIC - -- Debug mode: smoke all targets and range zone. - if self.Debug then - self:_MarkTargetsOnMap() - self:_SmokeBombTargets() - self:_SmokeStrafeTargets() - self:_SmokeStrafeTargetBoxes() - self.rangezone:SmokeZone(SMOKECOLOR.White) + if _target.move and _static==false and _target.speed>1 then + local unit=_target.target --Wrapper.Unit#UNIT + _target.target:PatrolZones({self.rangezone}, _target.speed*0.75, "Off road") end end - return self + -- Debug mode: smoke all targets and range zone. + if self.Debug then + self:_MarkTargetsOnMap() + self:_SmokeBombTargets() + self:_SmokeStrafeTargets() + self:_SmokeStrafeTargetBoxes() + self.rangezone:SmokeZone(SMOKECOLOR.White) + end + end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- User Functions +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- Set maximal strafing altitude. Player entering a strafe pit above that altitude are not registered for a valid pass. -- @param #RANGE self @@ -495,7 +593,7 @@ end --- Set player setting whether bomb impact points are smoked or not -- @param #RANGE self --- @param #boolean If true nor nil default is to smoke impact points of bombs. +-- @param #boolean switch If true nor nil default is to smoke impact points of bombs. -- @return #RANGE self function RANGE:SetDefaultPlayerSmokeBomb(switch) if switch==true or switch==nil then @@ -511,7 +609,7 @@ end -- @param #number distance Threshold distance in km. Default 25 km. -- @return #RANGE self function RANGE:SetBombtrackThreshold(distance) - self.BombtrackThreshold=distance*1000 or 25*1000 + self.BombtrackThreshold=(distance or 25)*1000 return self end @@ -544,6 +642,15 @@ function RANGE:SetBombTargetSmokeColor(colorid) return self end +--- Set score bomb distance. +-- @param #RANGE self +-- @param #number distance Distance in meters. Default 1000 m. +-- @return #RANGE self +function RANGE:SetScoreBombDistance(distance) + self.scorebombdistance=distance or 1000 + return self +end + --- Set smoke color for marking strafe targets. By default strafe targets are marked by green smoke. -- @param #RANGE self -- @param Utilities.Utils#SMOKECOLOR colorid Color id. Default SMOKECOLOR.Green. @@ -757,9 +864,19 @@ function RANGE:AddStrafePit(targetnames, boxlength, boxwidth, heading, inversehe -- Create tires --_polygon:BoundZone() + + local st={} --#RANGE.StrafeTarget + st.name=_name + st.polygon=_polygon + st.coordinate=Ccenter + st.goodPass=goodpass + st.targets=_targets + st.foulline=foulline + st.smokepoints=p + st.heading=heading -- Add zone to table. - table.insert(self.strafeTargets, {name=_name, polygon=_polygon, coordinate= Ccenter, goodPass=goodpass, targets=_targets, foulline=foulline, smokepoints=p, heading=heading}) + table.insert(self.strafeTargets, st) -- Debug info local text=string.format("Adding new strafe target %s with %d targets: heading = %03d, box_L = %.1f, box_W = %.1f, goodpass = %d, foul line = %.1f", _name, ntargets, heading, l, w, goodpass, foulline) @@ -888,9 +1005,46 @@ function RANGE:AddBombingTargetUnit(unit, goodhitrange, randommove) speed=self:_GetSpeed(unit) end - -- Insert target to table. - table.insert(self.bombingTargets, {name=name, target=unit, goodhitrange=goodhitrange, move=randommove, speed=speed}) + local target={} --#RANGE.BombTarget + target.name=name + target.target=target + target.goodhitrange=goodhitrange + target.move=randommove + target.speed=speed + target.coordinate=unit:GetCoordinate() + if _isstatic then + target.type=RANGE.TargetType.STATIC + else + target.type=RANGE.TargetType.UNIT + end + -- Insert target to table. + table.insert(self.bombingTargets, target) + + return self +end + + +--- Add a coordinate of a bombing target. This +-- @param #RANGE self +-- @param Core.Point#COORDINATE coord The coordinate. +-- @param #string name Name of target. +-- @param #number goodhitrange Max distance from unit which is considered as a good hit. +-- @return #RANGE self +function RANGE:AddBombingTargetCoordinate(coord, name, goodhitrange) + + local target={} --#RANGE.BombTarget + target.name=name or "Bomb Target" + target.target=nil + target.goodhitrange=goodhitrange or RANGE.Defaults.goodhitrange + target.move=false + target.speed=0 + target.coordinate=coord + target.type=RANGE.TargetType.COORD + + -- Insert target to table. + table.insert(self.bombingTargets, target) + return self end @@ -963,6 +1117,7 @@ end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- Event Handling +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- General event handler. -- @param #RANGE self @@ -1054,26 +1209,25 @@ function RANGE:OnEventBirth(EventData) -- Debug output. local text=string.format("Player %s, callsign %s entered unit %s (UID %d) of group %s (GID %d)", _playername, _callsign, _unitName, _uid, _group:GetName(), _gid) - self:T(RANGE.id..text) + self:E(RANGE.id..text) MESSAGE:New(text, 5):ToAllIf(self.Debug) - self:_GetAmmo(_unitName) - -- Reset current strafe status. self.strafeStatus[_uid] = nil -- Add Menu commands after a delay of 0.1 seconds. - --self:_AddF10Commands(_unitName) SCHEDULER:New(nil, self._AddF10Commands, {self,_unitName}, 0.1) -- By default, some bomb impact points and do not flare each hit on target. - self.PlayerSettings[_playername]={} + self.PlayerSettings[_playername]={} --#RANGE.PlayerData self.PlayerSettings[_playername].smokebombimpact=self.defaultsmokebomb self.PlayerSettings[_playername].flaredirecthits=false self.PlayerSettings[_playername].smokecolor=SMOKECOLOR.Blue self.PlayerSettings[_playername].flarecolor=FLARECOLOR.Red self.PlayerSettings[_playername].delaysmoke=true self.PlayerSettings[_playername].messages=true + self.PlayerSettings[_playername].unitname=_unitName + self.PlayerSettings[_playername].playername=_playername -- Start check in zone timer. if self.planes[_uid] ~= true then @@ -1209,6 +1363,7 @@ function RANGE:OnEventShot(EventData) self:T(RANGE.id.."EVENT SHOT: Weapon type = ".._weapon) self:T(RANGE.id.."EVENT SHOT: Weapon name = ".._weaponName) self:T(RANGE.id.."EVENT SHOT: Weapon cate = "..weaponcategory) + -- Special cases: --local _viggen=string.match(_weapon, "ROBOT") or string.match(_weapon, "RB75") or string.match(_weapon, "BK90") or string.match(_weapon, "RB15") or string.match(_weapon, "RB04") @@ -1237,6 +1392,9 @@ function RANGE:OnEventShot(EventData) -- Only track if distance player to range is < 25 km. Also check that a player shot. No need to track AI weapons. if _track and dPR<=self.BombtrackThreshold and _unit and _playername then + + -- Player data. + local playerData=self.PlayerSettings[_playername] --#RANGE.PlayerData -- Tracking info and init of last bomb position. self:T(RANGE.id..string.format("RANGE %s: Tracking %s - %s.", self.rangename, _weapon, EventData.weapon:getName())) @@ -1253,22 +1411,30 @@ function RANGE:OnEventShot(EventData) return _ordnance:getPoint() end) - self:T3(RANGE.id..string.format("Range %s: Bomb still in air: %s", self.rangename, tostring(_status))) + self:T2(RANGE.id..string.format("Range %s: Bomb still in air: %s", self.rangename, tostring(_status))) if _status then - -- Still in the air. Remember this position. + ---------------------------- + -- Weapon is still in air -- + ---------------------------- + + -- Remember this position. _lastBombPos = {x = _bombPos.x, y = _bombPos.y, z= _bombPos.z } - -- Check again in 0.005 seconds. + -- Check again in ~0.005 seconds ==> 200 checks per second. return timer.getTime() + self.dtBombtrack else - -- Bomb did hit the ground. + ----------------------------- + -- Bomb did hit the ground -- + ----------------------------- + -- Get closet target to last position. - local _closetTarget = nil - local _distance = nil - local _hitquality = "POOR" + local _closetTarget=nil --#RANGE.BombTarget + local _distance=nil + local _closeCoord=nil + local _hitquality="POOR" -- Get callsign. local _callsign=self:_myname(_unitName) @@ -1276,42 +1442,39 @@ function RANGE:OnEventShot(EventData) -- Coordinate of impact point. local impactcoord=COORDINATE:NewFromVec3(_lastBombPos) - -- Check if impact happend in range zone. + -- Check if impact happened in range zone. local insidezone=self.rangezone:IsCoordinateInZone(impactcoord) - -- Distance from range. We dont want to smoke targets outside of the range. - local impactdist=impactcoord:Get2DDistance(self.location) - -- Impact point of bomb. if self.Debug then impactcoord:MarkToAll("Bomb impact point") end -- Smoke impact point of bomb. - if self.PlayerSettings[_playername].smokebombimpact and insidezone then - if self.PlayerSettings[_playername].delaysmoke then - timer.scheduleFunction(self._DelayedSmoke, {coord=impactcoord, color=self.PlayerSettings[_playername].smokecolor}, timer.getTime() + self.TdelaySmoke) + if playerData.smokebombimpact and insidezone then + if playerData.delaysmoke then + timer.scheduleFunction(self._DelayedSmoke, {coord=impactcoord, color=playerData.smokecolor}, timer.getTime() + self.TdelaySmoke) else - impactcoord:Smoke(self.PlayerSettings[_playername].smokecolor) + impactcoord:Smoke(playerData.smokecolor) end end -- Loop over defined bombing targets. for _,_bombtarget in pairs(self.bombingTargets) do - local _target=_bombtarget.target --Wrapper.Positionable#POSITIONABLE + -- Get target coordinate. + local targetcoord=self:_GetBombTargetCoordinate(_bombtarget) - if _target and _target:IsAlive() then + if targetcoord then -- Distance between bomb and target. - local _temp = impactcoord:Get2DDistance(_target:GetCoordinate()) - - --env.info(string.format("FF target = %s dist = %d m", _target:GetName(), _temp)) + local _temp = impactcoord:Get2DDistance(targetcoord) -- Find closest target to last known position of the bomb. if _distance == nil or _temp < _distance then _distance = _temp _closetTarget = _bombtarget + _closeCoord=targetcoord if _distance <= 0.5*_bombtarget.goodhitrange then _hitquality = "EXCELLENT" elseif _distance <= _bombtarget.goodhitrange then @@ -1327,28 +1490,38 @@ function RANGE:OnEventShot(EventData) end -- Count if bomb fell less than ~1 km away from the target. - if _distance <= self.scorebombdistance then - + if _distance and _distance <= self.scorebombdistance then -- Init bomb player results. if not self.bombPlayerResults[_playername] then - self.bombPlayerResults[_playername] = {} + self.bombPlayerResults[_playername]={} end -- Local results. - local _results = self.bombPlayerResults[_playername] + local _results=self.bombPlayerResults[_playername] + + local result={} --#RANGE.BombResult + result.name=_closetTarget.name + result.distance=_distance + result.radial=_closeCoord:HeadingTo(impactcoord) + result.weapon=_weaponName + result.quality=_hitquality + result.player=playerData + result.time=timer.getAbsTime() -- Add to table. - table.insert(_results, {name=_closetTarget.name, distance =_distance, weapon = _weaponName, quality=_hitquality }) + table.insert(_results, result) + + -- Call impact. + self:Impact(result) - -- Send message to player. - local _message = string.format("%s, impact %d m from bullseye of target %s. %s hit.", _callsign, _distance, _closetTarget.name, _hitquality) - - -- Send message. - self:_DisplayMessageToGroup(_unit, _message, nil, true) elseif insidezone then - -- Send message + + -- Send message. local _message=string.format("%s, weapon fell more than %.1f km away from nearest range target. No score!", _callsign, self.scorebombdistance/1000) self:_DisplayMessageToGroup(_unit, _message, nil, false) + + else + self:T(self.id.."Weapon impacted outside range zone.") end --Terminate the timer @@ -1367,8 +1540,46 @@ function RANGE:OnEventShot(EventData) end +----------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- FSM Functions +----------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +--- Function called after bomb impact on range. +-- @param #RANGE self +-- @param #string From From state. +-- @param #string Event Event. +-- @param #string To To state. +-- @param #RANGE.BombResult result Result of bomb impact. +function RANGE:onafterImpact(From, Event, To, result) + + -- Only display target name if there is more than one bomb target. + local targetname=nil + if #self.bombingTargets>1 then + local targetname=result.name + end + + -- Send message to player. + local text=string.format("%s, impact %03d° for %d ft", result.player.playername, result.radial, UTILS.MetersToFeet(result.distance)) + if targetname then + text=text..string.format(" from bulls of target %s.") + else + text=text.."." + end + text=text..string.format(" %s hit.", result.quality) + + -- Unit. + local unit=UNIT:FindByName(result.player.unitname) + + -- Send message. + self:_DisplayMessageToGroup(unit, text, nil, true) + self:T(self.id..text) + +end + + ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- Display Messages +----------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- Start smoking a coordinate with a delay. -- @param #table _args Argements passed. @@ -1625,8 +1836,12 @@ function RANGE:_DisplayRangeInfo(_unitname) if self.location then + local settings=_DATABASE:GetPlayerSettings(playername) or _SETTINGS --Core.Settings#SETTINGS + -- Direction vector from current position (coord) to target (position). local position=self.location --Core.Point#COORDINATE + local bulls=position:ToStringBULLS(unit:GetCoalition(), settings) + local lldms=position:ToStringLLDMS(settings) local rangealt=position:GetLandHeight() local vec3=coord:GetDirectionVec3(position) local angle=coord:GetAngleDegrees(vec3) @@ -1654,8 +1869,7 @@ function RANGE:_DisplayRangeInfo(_unitname) textdelay=string.format("Smoke bomb delay: OFF") end - -- Player unit settings. - local settings=_DATABASE:GetPlayerSettings(playername) or _SETTINGS --Core.Settings#SETTINGS + -- Player unit settings. local trange=string.format("%.1f km", range/1000) local trangealt=string.format("%d m", rangealt) local tstrafemaxalt=string.format("%d m", self.strafemaxalt) @@ -1669,6 +1883,8 @@ function RANGE:_DisplayRangeInfo(_unitname) text=text..string.format("Information on %s:\n", self.rangename) text=text..string.format("-------------------------------------------------------\n") text=text..string.format("Bearing %s, Range %s\n", Bs, trange) + text=text..string.format("%s\n", bulls) + text=text..string.format("%s\n", lldms) text=text..string.format("Altitude ASL: %s\n", trangealt) text=text..string.format("Max strafing alt AGL: %s\n", tstrafemaxalt) text=text..string.format("# of strafe targets: %d\n", self.nstrafetargets) @@ -1706,12 +1922,14 @@ function RANGE:_DisplayBombTargets(_unitname) for _,_bombtarget in pairs(self.bombingTargets) do local _target=_bombtarget.target --Wrapper.Positionable#POSITIONABLE - if _target and _target:IsAlive() then - -- Core.Point#COORDINATE - local coord=_target:GetCoordinate() --Core.Point#COORDINATE + -- Coordinate of bombtarget. + local coord=self:_GetBombTargetCoordinate(_bombtarget) + + if coord then + local mycoord=coord:ToStringA2G(_unit, _settings) - _text=_text..string.format("\n- %s: %s",_bombtarget.name, mycoord) + _text=_text..string.format("\n- %s: %s",_bombtarget.name or "unknown", mycoord) end end @@ -1983,6 +2201,7 @@ end ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- Menu Functions +----------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- Add menu commands for player. -- @param #RANGE self @@ -2087,6 +2306,45 @@ end ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- Helper Functions +----------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +--- Get the number of shells a unit currently has. +-- @param #RANGE self +-- @param #RANGE.BombTarget target Bomb target data. +-- @return Core.Point#COORDINATE Target coordinate. +function RANGE:_GetBombTargetCoordinate(target) + + local coord=nil --Core.Point#COORDINATE + + if target.type==RANGE.TargetType.UNIT then + + if not target.move then + -- Target should not move. + coord=target.coordinate + else + -- Moving target. Check if alive and get current position + if target.target and target.target:IsAlive() then + coord=target.target:GetCoordinate() + end + end + + elseif target.type==RANGE.TargetType.STATIC then + + -- Static targets dont move. + coord=target.coordinate + + elseif target.type==RANGE.TargetType.COORD then + + -- Coordinates dont move. + coord=target.coordinate + + else + self:E(self.id.."ERROR: Unknown target type.") + end + + return coord +end + --- Get the number of shells a unit currently has. -- @param #RANGE self @@ -2197,8 +2455,8 @@ function RANGE:_IlluminateBombTargets(_unitName) for _,_bombtarget in pairs(self.bombingTargets) do local _target=_bombtarget.target --Wrapper.Positionable#POSITIONABLE - if _target and _target:IsAlive() then - local coord=_target:GetCoordinate() --Core.Point#COORDINATE + local coord=self:_GetBombTargetCoordinate(_bombtarget) + if coord then table.insert(bomb, coord) end end @@ -2271,26 +2529,30 @@ function RANGE:_DisplayMessageToGroup(_unit, _text, _time, _clear, display) _clear=true end - -- Group ID. - local _gid=_unit:GetGroup():GetID() + -- Check if unit is alive. + if _unit and _unit:IsAlive() then - -- Get playername and player settings - local _, playername=self:_GetPlayerUnitAndName(_unit:GetName()) - local playermessage=self.PlayerSettings[playername].messages + -- Group ID. + local _gid=_unit:GetGroup():GetID() + + -- Get playername and player settings + local _, playername=self:_GetPlayerUnitAndName(_unit:GetName()) + local playermessage=self.PlayerSettings[playername].messages + + -- Send message to player if messages enabled and not only for the examiner. + if _gid and (playermessage==true or display) and (not self.examinerexclusive) then + trigger.action.outTextForGroup(_gid, _text, _time, _clear) + end - -- Send message to player if messages enabled and not only for the examiner. - if _gid and (playermessage==true or display) and (not self.examinerexclusive) then - trigger.action.outTextForGroup(_gid, _text, _time, _clear) + -- Send message to examiner. + if self.examinergroupname~=nil then + local _examinerid=GROUP:FindByName(self.examinergroupname):GetID() + if _examinerid then + trigger.action.outTextForGroup(_examinerid, _text, _time, _clear) + end + end end - - -- Send message to examiner. - if self.examinergroupname~=nil then - local _examinerid=GROUP:FindByName(self.examinergroupname):GetID() - if _examinerid then - trigger.action.outTextForGroup(_examinerid, _text, _time, _clear) - end - end - + end --- Toggle status of smoking bomb impact points. @@ -2384,8 +2646,8 @@ function RANGE:_SmokeBombTargets(unitname) for _,_bombtarget in pairs(self.bombingTargets) do local _target=_bombtarget.target --Wrapper.Positionable#POSITIONABLE - if _target and _target:IsAlive() then - local coord = _target:GetCoordinate() --Core.Point#COORDINATE + local coord=self:_GetBombTargetCoordinate(_bombtarget) + if coord then coord:Smoke(self.BombSmokeColor) end end @@ -2620,21 +2882,4 @@ function RANGE:_myname(unitname) return string.format("%s (%s)", csign, pname) end ---- Split string. Cf http://stackoverflow.com/questions/1426954/split-string-in-lua --- @param #RANGE self --- @param #string str Sting to split. --- @param #string sep Speparator for split. --- @return #table Split text. -function RANGE:_split(str, sep) - self:F2({str=str, sep=sep}) - - local result = {} - local regex = ("([^%s]+)"):format(sep) - for each in str:gmatch(regex) do - table.insert(result, each) - end - - return result -end - ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/Moose Development/Moose/Functional/Warehouse.lua b/Moose Development/Moose/Functional/Warehouse.lua index 3537c42d5..8395172bf 100644 --- a/Moose Development/Moose/Functional/Warehouse.lua +++ b/Moose Development/Moose/Functional/Warehouse.lua @@ -7669,7 +7669,13 @@ function WAREHOUSE:_PrintQueue(queue, name) end - self:I(self.wid..text) + if #queue==0 then + self:T(self.wid..text) + else + if total~="Empty" then + self:I(self.wid..text) + end + end end --- Display status of warehouse. diff --git a/Moose Development/Moose/Wrapper/Positionable.lua b/Moose Development/Moose/Wrapper/Positionable.lua index 950218de5..443192ed8 100644 --- a/Moose Development/Moose/Wrapper/Positionable.lua +++ b/Moose Development/Moose/Wrapper/Positionable.lua @@ -1163,9 +1163,9 @@ end --- Start Lasing a POSITIONABLE -- @param #POSITIONABLE self --- @param #POSITIONABLE Target --- @param #number LaserCode --- @param #number Duration +-- @param #POSITIONABLE Target The target to lase. +-- @param #number LaserCode Laser code or random number in [1000, 9999]. +-- @param #number Duration Duration of lasing in seconds. -- @return Core.Spot#SPOT function POSITIONABLE:LaseUnit( Target, LaserCode, Duration ) --R2.1 self:F2()