mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2026-07-16 22:22:25 +00:00
Compare commits
41 Commits
2.9.14
...
FF/MasterDev
| Author | SHA1 | Date | |
|---|---|---|---|
| a0c5466f7f | |||
| 2f002703ee | |||
| b0c6ed1d59 | |||
| 950e97b6d7 | |||
| 6d54e5a47f | |||
| 35c8803f8b | |||
| d9c8542993 | |||
| f3c38a4288 | |||
| 626b03c93a | |||
| cf5c55209a | |||
| 19921414cf | |||
| c4de2b6990 | |||
| 7907e4b830 | |||
| 5955c2d61f | |||
| 26fbae8672 | |||
| 5089e7df25 | |||
| 0c0d1cc794 | |||
| 21b968a9c6 | |||
| 704bb8668f | |||
| 763bfb4bb1 | |||
| 046bd37fd5 | |||
| fbf83b3aed | |||
| 22097987dc | |||
| 98d02d7532 | |||
| 7b44e7a3f6 | |||
| aa4cf37aed | |||
| caf2b4e736 | |||
| da516a0167 | |||
| 17d1cf673d | |||
| 1fcd70b0d0 | |||
| 832941494b | |||
| 0e82cb977e | |||
| e9237146a3 | |||
| b72899b500 | |||
| 2f39e38264 | |||
| db54672fbd | |||
| 30d9a7d703 | |||
| 5a088a740e | |||
| be220b6c1d | |||
| 645c4a4dbc | |||
| c2a630dabd |
@@ -1475,7 +1475,7 @@ function EVENT:onEvent( Event )
|
||||
-- SCENERY
|
||||
---
|
||||
Event.TgtDCSUnit = Event.target
|
||||
Event.TgtDCSUnitName = Event.TgtDCSUnit.getName and Event.TgtDCSUnit.getName() or nil
|
||||
Event.TgtDCSUnitName = Event.TgtDCSUnit.getName and Event.TgtDCSUnit:getName() or nil
|
||||
if Event.TgtDCSUnitName~=nil then
|
||||
Event.TgtUnitName = Event.TgtDCSUnitName
|
||||
Event.TgtUnit = SCENERY:Register( Event.TgtDCSUnitName, Event.target )
|
||||
|
||||
+1248
-1345
File diff suppressed because it is too large
Load Diff
@@ -1165,7 +1165,7 @@ function ZONE_RADIUS:Scan( ObjectCategories, UnitCategories )
|
||||
self.ScanData.SceneryTable = {}
|
||||
self.ScanData.Units = {}
|
||||
|
||||
local ZoneCoord = self:GetCoordinate()
|
||||
local ZoneCoord = self:GetCoordinate():SetAlt()
|
||||
local ZoneRadius = self:GetRadius()
|
||||
|
||||
--self:F({ZoneCoord = ZoneCoord, ZoneRadius = ZoneRadius, ZoneCoordLL = ZoneCoord:ToStringLLDMS()})
|
||||
|
||||
@@ -90,7 +90,8 @@
|
||||
-- @image Scoring.JPG
|
||||
|
||||
--- @type SCORING
|
||||
-- @field Players A collection of the current players that have joined the game.
|
||||
-- @field #table Players A collection of the current players that have joined the game.
|
||||
-- @field Core.Set#SET_SCENERY ScoringScenery
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
--- SCORING class
|
||||
@@ -229,7 +230,8 @@ SCORING = {
|
||||
ClassID = 0,
|
||||
Players = {},
|
||||
AutoSave = true,
|
||||
version = "1.18.4"
|
||||
version = "1.18.4",
|
||||
ScoringScenery = nil, -- Core.Set#SET_SCENERY
|
||||
}
|
||||
|
||||
local _SCORINGCoalition = {
|
||||
@@ -325,6 +327,8 @@ function SCORING:New( GameName, SavePath, AutoSave )
|
||||
self:OpenCSV( GameName )
|
||||
end
|
||||
|
||||
self:I("SCORING "..tostring(GameName).." started! v"..self.version)
|
||||
|
||||
return self
|
||||
|
||||
end
|
||||
@@ -377,7 +381,7 @@ function SCORING:AddUnitScore( ScoreUnit, Score )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Removes a @{Wrapper.Unit} for additional scoring when the @{Wrapper.Unit} is destroyed.
|
||||
--- Removes a @{Wrapper.Unit} for scoring when the @{Wrapper.Unit} is destroyed.
|
||||
-- @param #SCORING self
|
||||
-- @param Wrapper.Unit#UNIT ScoreUnit The @{Wrapper.Unit} for which the Score needs to be given.
|
||||
-- @return #SCORING
|
||||
@@ -394,10 +398,26 @@ end
|
||||
-- Note that if there was already a @{Wrapper.Static} declared within the scoring with the same name,
|
||||
-- then the old @{Wrapper.Static} will be replaced with the new @{Wrapper.Static}.
|
||||
-- @param #SCORING self
|
||||
-- @param Wrapper.Static#UNIT ScoreStatic The @{Wrapper.Static} for which the Score needs to be given.
|
||||
-- @param Wrapper.Static#STATIC ScoreStatic The @{Wrapper.Static} for which the Score needs to be given.
|
||||
-- @param #number Score The Score value.
|
||||
-- @return #SCORING
|
||||
function SCORING:AddStaticScore( ScoreStatic, Score )
|
||||
return self:AddScoreStatic( ScoreStatic, Score )
|
||||
end
|
||||
|
||||
--- Add a @{Wrapper.Static} for additional scoring when the @{Wrapper.Static} is destroyed.
|
||||
-- Note that if there was already a @{Wrapper.Static} declared within the scoring with the same name,
|
||||
-- then the old @{Wrapper.Static} will be replaced with the new @{Wrapper.Static}.
|
||||
-- @param #SCORING self
|
||||
-- @param Wrapper.Static#STATIC ScoreStatic The @{Wrapper.Static} for which the Score needs to be given.
|
||||
-- @param #number Score The Score value.
|
||||
-- @return #SCORING
|
||||
function SCORING:AddScoreStatic( ScoreStatic, Score )
|
||||
|
||||
if ScoreStatic == nil then
|
||||
BASE:E("SCORING.AddStaticScore: Parameter ScoreStatic is nil!")
|
||||
return self
|
||||
end
|
||||
|
||||
local StaticName = ScoreStatic:GetName()
|
||||
|
||||
@@ -406,7 +426,61 @@ function SCORING:AddStaticScore( ScoreStatic, Score )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Removes a @{Wrapper.Static} for additional scoring when the @{Wrapper.Static} is destroyed.
|
||||
--- Add a @{Wrapper.Scenery} for additional scoring when the @{Wrapper.Scenery} is destroyed.
|
||||
-- @param #SCORING self
|
||||
-- @param Wrapper.Scenery#SCENERY ScoreScenery The @{Wrapper.Scenery} for which the Score needs to be given.
|
||||
-- @param #number Score The Score value.
|
||||
-- @return #SCORING
|
||||
function SCORING:AddScoreScenery( ScoreScenery, Score )
|
||||
|
||||
if ScoreScenery == nil then
|
||||
self:E("SCORING.ScoreScenery: Parameter ScoreScenery is nil!")
|
||||
return self
|
||||
end
|
||||
|
||||
if not self.ScoringScenery then
|
||||
self.ScoringScenery = SET_SCENERY:New() -- Core.Set#SET_SCENERY
|
||||
end
|
||||
|
||||
local StaticName = ScoreScenery:GetName()
|
||||
self:T("Scenery name = ".. StaticName)
|
||||
|
||||
self.ScoringScenery:AddScenery(ScoreScenery)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Removes a @{Wrapper.Scenery} for scoring when the @{Wrapper.Scenery} is destroyed.
|
||||
-- @param #SCORING self
|
||||
-- @param Wrapper.Scenery#SCENERY ScoreStatic The @{Wrapper.Scenery} for which the Score needs to be given.
|
||||
-- @return #SCORING
|
||||
function SCORING:RemoveSceneryScore( ScoreScenery )
|
||||
|
||||
local StaticName = ScoreScenery:GetName()
|
||||
|
||||
self.ScoringObjects[StaticName] = nil
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Specify a special additional score for a @{Core.Set#SET_SCENERY}.
|
||||
-- @param #SCORING self
|
||||
-- @param Core.Set#SET_SCENERY Set The @{Core.Set#SET_SCENERY} for which each @{Wrapper.Scenery} in the SET a Score is given.
|
||||
-- @param #number Score The Score value.
|
||||
-- @return #SCORING
|
||||
function SCORING:AddScoreSetScenery(Set, Score)
|
||||
local set = Set.Set
|
||||
|
||||
for _,_static in pairs (set) do
|
||||
if _static ~= nil then
|
||||
self:AddScoreScenery(_static,Score)
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Removes a @{Wrapper.Static} for scoring when the @{Wrapper.Static} is destroyed.
|
||||
-- @param #SCORING self
|
||||
-- @param Wrapper.Static#UNIT ScoreStatic The @{Wrapper.Static} for which the Score needs to be given.
|
||||
-- @return #SCORING
|
||||
@@ -461,6 +535,31 @@ function SCORING:AddScoreSetGroup(Set, Score)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Specify a special additional score for a @{Core.Set#SET_STATIC}.
|
||||
-- @param #SCORING self
|
||||
-- @param Core.Set#SET_STATIC Set The @{Core.Set#SET_STATIC} for which each @{Wrapper.Static} in the SET a Score is given.
|
||||
-- @param #number Score The Score value.
|
||||
-- @return #SCORING
|
||||
function SCORING:AddScoreSetStatic(Set, Score)
|
||||
local set = Set:GetSetObjects()
|
||||
|
||||
for _,_static in pairs (set) do
|
||||
if _static and _static:IsAlive() then
|
||||
self:AddStaticScore(_static,Score)
|
||||
end
|
||||
end
|
||||
|
||||
local function AddScore(static)
|
||||
self:AddStaticScore(static,Score)
|
||||
end
|
||||
|
||||
function Set:OnAfterAdded(From,Event,To,ObjectName,Object)
|
||||
AddScore(Object)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Add a @{Core.Zone} to define additional scoring when any object is destroyed in that zone.
|
||||
-- Note that if a @{Core.Zone} with the same name is already within the scoring added, the @{Core.Zone} (type) and Score will be replaced!
|
||||
-- This allows for a dynamic destruction zone evolution within your mission.
|
||||
@@ -480,7 +579,24 @@ function SCORING:AddZoneScore( ScoreZone, Score )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove a @{Core.Zone} for additional scoring.
|
||||
--- Add a @{Core.Set#SET_ZONE} to define additional scoring when any object is destroyed in that zone.
|
||||
-- Note that if a @{Core.Zone} with the same name is already within the scoring added, the @{Core.Zone} (type) and Score will be replaced!
|
||||
-- This allows for a dynamic destruction zone evolution within your mission.
|
||||
-- @param #SCORING self
|
||||
-- @param Core.Set#SET_ZONE ScoreZoneSet The @{Core.Set#SET_ZONE} which defines the destruction score perimeters.
|
||||
-- Note that a zone can be a polygon or a moving zone.
|
||||
-- @param #number Score The Score value.
|
||||
-- @return #SCORING
|
||||
function SCORING:AddZoneScoreSet( ScoreZoneSet, Score )
|
||||
|
||||
for _,_zone in pairs(ScoreZoneSet.Set or {}) do
|
||||
self:AddZoneScore(_zone,Score)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove a @{Core.Zone} for scoring.
|
||||
-- The scoring will search if any @{Core.Zone} is added with the given name, and will remove that zone from the scoring.
|
||||
-- This allows for a dynamic destruction zone evolution within your mission.
|
||||
-- @param #SCORING self
|
||||
@@ -958,7 +1074,7 @@ end
|
||||
-- @param #SCORING self
|
||||
-- @param Core.Event#EVENTDATA Event
|
||||
function SCORING:_EventOnHit( Event )
|
||||
self:F( { Event } )
|
||||
--self:F( { Event } )
|
||||
|
||||
local InitUnit = nil
|
||||
local InitUNIT = nil
|
||||
@@ -988,6 +1104,7 @@ function SCORING:_EventOnHit( Event )
|
||||
local TargetUnitCategory = nil
|
||||
local TargetUnitType = nil
|
||||
local TargetIsScenery = false
|
||||
local TargetSceneryObject = nil
|
||||
|
||||
if Event.IniDCSUnit then
|
||||
|
||||
@@ -1009,7 +1126,7 @@ function SCORING:_EventOnHit( Event )
|
||||
InitUnitCategory = _SCORINGCategory[InitCategory]
|
||||
InitUnitType = InitType
|
||||
|
||||
self:T( { InitUnitName, InitGroupName, InitPlayerName, InitCoalition, InitCategory, InitType, InitUnitCoalition, InitUnitCategory, InitUnitType } )
|
||||
--self:T( { InitUnitName, InitGroupName, InitPlayerName, InitCoalition, InitCategory, InitType, InitUnitCoalition, InitUnitCategory, InitUnitType } )
|
||||
end
|
||||
|
||||
if Event.TgtDCSUnit then
|
||||
@@ -1027,18 +1144,23 @@ function SCORING:_EventOnHit( Event )
|
||||
-- TargetCategory = TargetUnit:getDesc().category
|
||||
TargetCategory = Event.TgtCategory
|
||||
TargetType = Event.TgtTypeName
|
||||
|
||||
|
||||
-- Scenery hit
|
||||
if (not TargetCategory) and TargetUNIT ~= nil and TargetUnit:IsInstanceOf("SCENERY") then
|
||||
if TargetUNIT ~= nil and TargetUNIT:IsInstanceOf("SCENERY") then
|
||||
TargetCategory = Unit.Category.STRUCTURE
|
||||
TargetIsScenery = true
|
||||
TargetType = "Scenery"
|
||||
TargetSceneryObject = TargetUNIT
|
||||
self:T("***** Target is Scenery and TargetUNIT is SCENERY object!")
|
||||
UTILS.PrintTableToLog(TargetSceneryObject)
|
||||
end
|
||||
|
||||
TargetUnitCoalition = _SCORINGCoalition[TargetCoalition]
|
||||
TargetUnitCategory = _SCORINGCategory[TargetCategory]
|
||||
TargetUnitType = TargetType
|
||||
|
||||
self:T( { TargetUnitName, TargetGroupName, TargetPlayerName, TargetCoalition, TargetCategory, TargetType, TargetUnitCoalition, TargetUnitCategory, TargetUnitType } )
|
||||
--self:T( { TargetUnitName=TargetUnitName, TargetGroupName=TargetGroupName, TargetPlayerName=TargetPlayerName, TargetCoalition=TargetCoalition, TargetCategory=TargetCategory, TargetType=TargetType, TargetUnitCoalition=TargetUnitCoalition, TargetUnitCategory=TargetUnitCategory, TargetUnitType=TargetUnitType } )
|
||||
end
|
||||
|
||||
if InitPlayerName ~= nil then -- It is a player that is hitting something
|
||||
@@ -1051,7 +1173,7 @@ function SCORING:_EventOnHit( Event )
|
||||
self:T( "Hitting Something" )
|
||||
|
||||
-- What is he hitting?
|
||||
if TargetCategory then
|
||||
if (TargetCategory ~=nil) and (TargetIsScenery == false) then
|
||||
|
||||
-- A target got hit, score it.
|
||||
-- Player contains the score data from self.Players[InitPlayerName]
|
||||
@@ -1071,7 +1193,7 @@ function SCORING:_EventOnHit( Event )
|
||||
PlayerHit.TimeStamp = PlayerHit.TimeStamp or 0
|
||||
PlayerHit.UNIT = PlayerHit.UNIT or TargetUNIT
|
||||
-- After an instant kill we can't compute the threat level anymore. To fix this we compute at OnEventBirth
|
||||
if PlayerHit.UNIT.ThreatType == nil then
|
||||
if PlayerHit.UNIT and PlayerHit.UNIT.ThreatType == nil then
|
||||
PlayerHit.ThreatLevel, PlayerHit.ThreatType = PlayerHit.UNIT:GetThreatLevel()
|
||||
-- if this fails for some reason, set a good default value
|
||||
if PlayerHit.ThreatType == nil or PlayerHit.ThreatType == "" then
|
||||
@@ -1157,21 +1279,21 @@ function SCORING:_EventOnHit( Event )
|
||||
|
||||
-- It is a weapon initiated by a player, that is hitting something
|
||||
-- This seems to occur only with scenery and static objects.
|
||||
if Event.WeaponPlayerName ~= nil then
|
||||
self:_AddPlayerFromUnit( Event.WeaponUNIT )
|
||||
if self.Players[Event.WeaponPlayerName] then -- This should normally not happen, but i'll test it anyway.
|
||||
if TargetPlayerName ~= nil then -- It is a player hitting another player ...
|
||||
self:_AddPlayerFromUnit( TargetUNIT )
|
||||
end
|
||||
if Event.WeaponPlayerName ~= nil or TargetIsScenery == true then
|
||||
|
||||
local playername = Event.WeaponPlayerName or Event.IniPlayerName or "Ghost"
|
||||
|
||||
--self:_AddPlayerFromUnit( Event.WeaponUNIT )
|
||||
if self.Players[playername] then -- This should normally not happen, but i'll test it anyway.
|
||||
|
||||
self:T( "Hitting Scenery" )
|
||||
self:T( "Hitting Scenery or Static" )
|
||||
|
||||
-- What is he hitting?
|
||||
if TargetCategory then
|
||||
if Event.TgtObjectCategory then
|
||||
|
||||
-- A scenery or static got hit, score it.
|
||||
-- Player contains the score data from self.Players[WeaponPlayerName]
|
||||
local Player = self.Players[Event.WeaponPlayerName]
|
||||
local Player = self.Players[playername]
|
||||
|
||||
-- Ensure there is a hit table per TargetCategory and TargetUnitName.
|
||||
Player.Hit[TargetCategory] = Player.Hit[TargetCategory] or {}
|
||||
@@ -1179,15 +1301,17 @@ function SCORING:_EventOnHit( Event )
|
||||
|
||||
-- PlayerHit contains the score counters and data per unit that was hit.
|
||||
local PlayerHit = Player.Hit[TargetCategory][TargetUnitName]
|
||||
|
||||
|
||||
-- Init player scores
|
||||
PlayerHit.Score = PlayerHit.Score or 0
|
||||
PlayerHit.Penalty = PlayerHit.Penalty or 0
|
||||
PlayerHit.ScoreHit = PlayerHit.ScoreHit or 0
|
||||
PlayerHit.PenaltyHit = PlayerHit.PenaltyHit or 0
|
||||
PlayerHit.TimeStamp = PlayerHit.TimeStamp or 0
|
||||
PlayerHit.UNIT = PlayerHit.UNIT or TargetUNIT
|
||||
|
||||
-- After an instant kill we can't compute the threat level anymore. To fix this we compute at OnEventBirth
|
||||
if PlayerHit.UNIT.ThreatType == nil then
|
||||
if PlayerHit.UNIT and PlayerHit.UNIT.ThreatType == nil then
|
||||
PlayerHit.ThreatLevel, PlayerHit.ThreatType = PlayerHit.UNIT:GetThreatLevel()
|
||||
-- if this fails for some reason, set a good default value
|
||||
if PlayerHit.ThreatType == nil then
|
||||
@@ -1195,8 +1319,8 @@ function SCORING:_EventOnHit( Event )
|
||||
PlayerHit.ThreatType = "Unknown"
|
||||
end
|
||||
else
|
||||
PlayerHit.ThreatLevel = PlayerHit.UNIT.ThreatLevel
|
||||
PlayerHit.ThreatType = PlayerHit.UNIT.ThreatType
|
||||
PlayerHit.ThreatLevel = PlayerHit.UNIT and PlayerHit.UNIT.ThreatLevel or 1
|
||||
PlayerHit.ThreatType = PlayerHit.UNIT and PlayerHit.UNIT.ThreatType or "Unknown"
|
||||
end
|
||||
|
||||
-- Only grant hit scores if there was more than one second between the last hit.
|
||||
@@ -1204,50 +1328,68 @@ function SCORING:_EventOnHit( Event )
|
||||
PlayerHit.TimeStamp = timer.getTime()
|
||||
|
||||
local Score = 0
|
||||
|
||||
if InitCoalition then -- A coalition object was hit, probably a static.
|
||||
if InitCoalition == TargetCoalition then
|
||||
-- TODO: Penalty according scale
|
||||
local Penalty = 10
|
||||
Player.Penalty = Player.Penalty + Penalty --* self.ScaleDestroyPenalty
|
||||
PlayerHit.Penalty = PlayerHit.Penalty + Penalty --* self.ScaleDestroyPenalty
|
||||
PlayerHit.PenaltyHit = PlayerHit.PenaltyHit + 1 * self.ScaleDestroyPenalty
|
||||
|
||||
MESSAGE
|
||||
:NewType( self.DisplayMessagePrefix .. "Player '" .. Event.WeaponPlayerName .. "' hit friendly target " ..
|
||||
TargetUnitCategory .. " ( " .. TargetType .. " ) " ..
|
||||
"Penalty: -" .. Penalty .. " = " .. Player.Score - Player.Penalty,
|
||||
MESSAGE.Type.Update
|
||||
)
|
||||
:ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() )
|
||||
:ToCoalitionIf( Event.WeaponCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
|
||||
self:ScoreCSV( Event.WeaponPlayerName, TargetPlayerName, "HIT_PENALTY", 1, -10, Event.WeaponName, Event.WeaponCoalition, Event.WeaponCategory, Event.WeaponTypeName, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
|
||||
else
|
||||
|
||||
local TgtName = Event.TgtDCSUnit and Event.TgtDCSUnit.getName and Event.TgtDCSUnit:getName() or "Unknown"
|
||||
|
||||
--if InitCoalition then -- A coalition object was hit, probably a static.
|
||||
if TargetIsScenery == true and self.ScoringScenery:IsInSet(TargetSceneryObject) then
|
||||
Player.Score = Player.Score + self.ScoreIncrementOnHit
|
||||
PlayerHit.Score = PlayerHit.Score + self.ScoreIncrementOnHit
|
||||
PlayerHit.ScoreHit = PlayerHit.ScoreHit + 1
|
||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. Event.WeaponPlayerName .. "' hit enemy target " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " ..
|
||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. playername .. "' hit scenery target " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " ..
|
||||
"Score: " .. PlayerHit.Score .. ". Score Total:" .. Player.Score - Player.Penalty,
|
||||
MESSAGE.Type.Update )
|
||||
:ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() )
|
||||
:ToCoalitionIf( Event.WeaponCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
|
||||
|
||||
self:ScoreCSV( Event.WeaponPlayerName, TargetPlayerName, "HIT_SCORE", 1, 1, Event.WeaponName, Event.WeaponCoalition, Event.WeaponCategory, Event.WeaponTypeName, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
|
||||
end
|
||||
else -- A scenery object was hit.
|
||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. Event.WeaponPlayerName .. "' hit scenery object.",
|
||||
MESSAGE.Type.Update )
|
||||
:ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() )
|
||||
:ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
|
||||
self:ScoreCSV( playername, TargetPlayerName, "HIT_SCORE", 1, 1, Event.WeaponName, Event.WeaponCoalition, Event.WeaponCategory, Event.WeaponTypeName, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
|
||||
elseif TargetIsScenery == false and Event.TgtObjectCategory == Object.Category.STATIC and self.ScoringObjects[TgtName] then
|
||||
Player.Score = Player.Score + self.ScoreIncrementOnHit
|
||||
PlayerHit.Score = PlayerHit.Score + self.ScoreIncrementOnHit
|
||||
PlayerHit.ScoreHit = PlayerHit.ScoreHit + 1
|
||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. playername .. "' hit static target " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " ..
|
||||
"Score: " .. PlayerHit.Score .. ". Score Total:" .. Player.Score - Player.Penalty,
|
||||
MESSAGE.Type.Update )
|
||||
:ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() )
|
||||
:ToCoalitionIf( Event.WeaponCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
|
||||
|
||||
self:ScoreCSV( Event.WeaponPlayerName, "", "HIT_SCORE", 1, 0, Event.WeaponName, Event.WeaponCoalition, Event.WeaponCategory, Event.WeaponTypeName, TargetUnitName, "", "Scenery", TargetUnitType )
|
||||
end
|
||||
self:ScoreCSV( playername, TargetPlayerName, "HIT_SCORE", 1, 1, Event.WeaponName, Event.WeaponCoalition, Event.WeaponCategory, Event.WeaponTypeName, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
|
||||
|
||||
else
|
||||
self:E("Hit unregistered scenery or static object - NO target! ("..TgtName..")")
|
||||
end
|
||||
--end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Check if there are Zones where the destruction happened.
|
||||
for ZoneName, ScoreZoneData in pairs( self.ScoringZones ) do
|
||||
self:F( { ScoringZone = ScoreZoneData } )
|
||||
local hit=Event.TgtUnit
|
||||
local ScoreZone = ScoreZoneData.ScoreZone -- Core.Zone#ZONE_BASE
|
||||
local Score = ScoreZoneData.Score
|
||||
if TargetUNIT and ScoreZone:IsVec2InZone( TargetUNIT:GetVec2() ) then
|
||||
-- A scenery or static got hit, score it.
|
||||
-- Player contains the score data from self.Players[WeaponPlayerName]
|
||||
local PlayerName = Event.IniPlayerName or "Ghost"
|
||||
local Player = self.Players[PlayerName]
|
||||
|
||||
Player.Score = Player.Score + Score
|
||||
Player.Score = Player.Score + self.ScoreIncrementOnHit
|
||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "hit in zone '" .. ScoreZone:GetName() .. "'." ..
|
||||
"Player '" .. PlayerName .. "' receives an extra " .. Score .. " points! " .. "Total: " .. Player.Score - Player.Penalty,
|
||||
MESSAGE.Type.Information )
|
||||
:ToAllIf( self:IfMessagesZone() and self:IfMessagesToAll() )
|
||||
:ToCoalitionIf( InitCoalition, self:IfMessagesZone() and self:IfMessagesToCoalition() )
|
||||
|
||||
self:ScoreCSV( PlayerName, "", "HIT_SCORE", 1, Score, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, "", "Zone", TargetUnitType )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
--- Track DEAD or CRASH events for the scoring.
|
||||
-- @param #SCORING self
|
||||
-- @param Core.Event#EVENTDATA Event
|
||||
@@ -1305,7 +1447,7 @@ function SCORING:_EventOnDeadOrCrash( Event )
|
||||
local Destroyed = false
|
||||
|
||||
-- What is the player destroying?
|
||||
if Player and Player.Hit and Player.Hit[TargetCategory] and Player.Hit[TargetCategory][TargetUnitName] and Player.Hit[TargetCategory][TargetUnitName].TimeStamp ~= 0 and (TargetUnit.BirthTime == nil or Player.Hit[TargetCategory][TargetUnitName].TimeStamp > TargetUnit.BirthTime) then -- Was there a hit for this unit for this player before registered???
|
||||
if Player and Player.Hit and Player.Hit[TargetCategory] and Player.Hit[TargetCategory][TargetUnitName] and Player.Hit[TargetCategory][TargetUnitName].TimeStamp ~= 0 and TargetUnit and (TargetUnit.BirthTime == nil or Player.Hit[TargetCategory][TargetUnitName].TimeStamp > TargetUnit.BirthTime) then -- Was there a hit for this unit for this player before registered???
|
||||
|
||||
local TargetThreatLevel = Player.Hit[TargetCategory][TargetUnitName].ThreatLevel
|
||||
local TargetThreatType = Player.Hit[TargetCategory][TargetUnitName].ThreatType
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
-- **Supported Aircraft:**
|
||||
--
|
||||
-- * [F/A-18C Hornet Lot 20](https://forums.eagle.ru/forumdisplay.php?f=557) (Player & AI)
|
||||
-- * [F-14A/B Tomcat](https://forums.eagle.ru/forumdisplay.php?f=395) (Player & AI)
|
||||
-- * [F-14A/B/A Early Tomcat](https://forums.eagle.ru/forumdisplay.php?f=395) (Player & AI)
|
||||
-- * [A-4E Skyhawk Community Mod](https://forums.eagle.ru/showthread.php?t=224989) (Player & AI)
|
||||
-- * [AV-8B N/A Harrier](https://forums.eagle.ru/forumdisplay.php?f=555) (Player & AI)
|
||||
-- * [T-45C Goshawk](https://forum.dcs.world/topic/203816-vnao-t-45-goshawk/) (VNAO mod) (Player & AI)
|
||||
@@ -63,7 +63,7 @@
|
||||
-- no other fixed wing aircraft (human or AI controlled) are supposed to land on these ships. Currently only Case I is supported. Case II/III take slightly different steps from the CVN carrier.
|
||||
-- However, if no offset is used for the holding radial this provides a very close representation of the V/STOL Case III, allowing for an approach to over the deck and a vertical landing.
|
||||
--
|
||||
-- Heatblur's mighty F-14B Tomcat has been added (March 13th 2019) as well. Same goes for the A version.
|
||||
-- Heatblur's mighty F-14A/B/A Early Tomcat has been added as well.
|
||||
--
|
||||
-- The [DCS Supercarriers](https://www.digitalcombatsimulator.com/de/shop/modules/supercarrier/) are also supported.
|
||||
--
|
||||
@@ -1276,6 +1276,7 @@ AIRBOSS = {
|
||||
-- @field #string A4EC A-4E Community mod.
|
||||
-- @field #string HORNET F/A-18C Lot 20 Hornet by Eagle Dynamics.
|
||||
-- @field #string F14A F-14A by Heatblur.
|
||||
-- @field #string F14A_Early F-14A-135-GR-Early by Heatblur.
|
||||
-- @field #string F14B F-14B by Heatblur.
|
||||
-- @field #string F14A_AI F-14A Tomcat (AI).
|
||||
-- @field #string FA18C F/A-18C Hornet (AI).
|
||||
@@ -1294,6 +1295,7 @@ AIRBOSS.AircraftCarrier={
|
||||
HORNET="FA-18C_hornet",
|
||||
A4EC="A-4E-C",
|
||||
F14A="F-14A-135-GR",
|
||||
F14A_Early="F-14A-135-GR-Early",
|
||||
F14B="F-14B",
|
||||
F14A_AI="F-14A",
|
||||
FA18C="F/A-18C",
|
||||
@@ -5473,7 +5475,7 @@ function AIRBOSS:_GetAircraftAoA( playerData )
|
||||
local goshawk = playerData.actype == AIRBOSS.AircraftCarrier.T45C
|
||||
local skyhawk = playerData.actype == AIRBOSS.AircraftCarrier.A4EC
|
||||
local harrier = playerData.actype == AIRBOSS.AircraftCarrier.AV8B
|
||||
local tomcat = playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B
|
||||
local tomcat = playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B or playerData.actype == AIRBOSS.AircraftCarrier.F14A_Early
|
||||
local corsair = playerData.actype == AIRBOSS.AircraftCarrier.CORSAIR or playerData.actype == AIRBOSS.AircraftCarrier.CORSAIR_CW
|
||||
|
||||
-- Table with AoA values.
|
||||
@@ -5498,11 +5500,15 @@ function AIRBOSS:_GetAircraftAoA( playerData )
|
||||
aoa.OnSpeedMin = self:_AoAUnit2Deg( playerData, 14.0 ) -- 14.17 --14.5 units -- VNAO Edit - Original value 14.5
|
||||
aoa.Fast = self:_AoAUnit2Deg( playerData, 13.5 ) -- 13.33 --14.0 units -- VNAO Edit - Original value 14
|
||||
aoa.FAST = self:_AoAUnit2Deg( playerData, 12.5 ) -- 11.67 --13.0 units -- VNAO Edit - Original value 13
|
||||
local hornet = playerData.actype == AIRBOSS.AircraftCarrier.HORNET
|
||||
or playerData.actype == AIRBOSS.AircraftCarrier.RHINOE
|
||||
or playerData.actype == AIRBOSS.AircraftCarrier.RHINOF
|
||||
or playerData.actype == AIRBOSS.AircraftCarrier.GROWLER
|
||||
local tomcat = playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B
|
||||
elseif goshawk then --These parameters edited by CIRCUIT to support new VNAO flight model
|
||||
-- T-45C Goshawk parameters.
|
||||
aoa.SLOW = 9.5 -- 8.00 -- 19
|
||||
aoa.Slow = 9.25 -- 7.75 -- 18
|
||||
aoa.OnSpeedMax = 9.0 --7.25 -- 17.5
|
||||
aoa.OnSpeed = 8.5 -- 7.00 -- 17
|
||||
aoa.OnSpeedMin = 8.25 -- 6.75 -- 16.5
|
||||
aoa.Fast = 7.75 -- 6.25 -- 16
|
||||
aoa.FAST = 5.5 -- 6.00 -- 15
|
||||
elseif skyhawk then
|
||||
-- A-4E-C Skyhawk parameters from https://forums.eagle.ru/showpost.php?p=3703467&postcount=390
|
||||
-- Note that these are arbitrary UNITS and not degrees. We need a conversion formula!
|
||||
@@ -5548,7 +5554,7 @@ function AIRBOSS:_AoAUnit2Deg( playerData, aoaunits )
|
||||
local degrees = aoaunits
|
||||
|
||||
-- Check aircraft type of player.
|
||||
if playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B then
|
||||
if playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B or playerData.actype == AIRBOSS.AircraftCarrier.F14A_Early then
|
||||
|
||||
-------------
|
||||
-- F-14A/B --
|
||||
@@ -5591,7 +5597,7 @@ function AIRBOSS:_AoADeg2Units( playerData, degrees )
|
||||
local aoaunits = degrees
|
||||
|
||||
-- Check aircraft type of player.
|
||||
if playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B then
|
||||
if playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B or playerData.actype == AIRBOSS.AircraftCarrier.F14A_Early then
|
||||
|
||||
-------------
|
||||
-- F-14A/B --
|
||||
@@ -11589,7 +11595,7 @@ function AIRBOSS:_AttitudeMonitor( playerData )
|
||||
|
||||
local unitClient = Unit.getByName(unit:GetName()) -- VNAO Edit - Added
|
||||
local hornet = playerData.actype == AIRBOSS.AircraftCarrier.HORNET -- VNAO Edit - Added
|
||||
local tomcat = playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B -- VNAO Edit - Added
|
||||
local tomcat = playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B or playerData.actype == AIRBOSS.AircraftCarrier.F14A_Early -- VNAO Edit - Added
|
||||
|
||||
if hornet then -- VNAO Edit - Added
|
||||
local nozzlePosL = 0 -- VNAO Edit - Added
|
||||
@@ -11822,7 +11828,7 @@ function AIRBOSS:_NozzleArgumentLeft( unit ) -- VNAO Edit - Added
|
||||
else -- VNAO Edit - Added
|
||||
nozzlePosL = 0 -- VNAO Edit - Added
|
||||
end -- VNAO Edit - Added
|
||||
elseif typeName == "F-14A-135-GR" or typeName == "F-14B" then -- VNAO Edit - Added
|
||||
elseif typeName == "F-14A-135-GR" or typeName == "F-14B" or typeName == "F-14A-135-GR-Early" then -- VNAO Edit - Added
|
||||
nozzlePosL = unitClient:getDrawArgumentValue(434) -- VNAO Edit - Added
|
||||
end -- VNAO Edit - Added
|
||||
|
||||
@@ -11847,7 +11853,7 @@ function AIRBOSS:_NozzleArgumentRight( unit ) -- VNAO Edit - Added
|
||||
else -- VNAO Edit - Added
|
||||
nozzlePosR = 0 -- VNAO Edit - Added
|
||||
end -- VNAO Edit - Added
|
||||
elseif typeName == "F-14A-135-GR" or typeName == "F-14B" then -- VNAO Edit - Added
|
||||
elseif typeName == "F-14A-135-GR" or typeName == "F-14B" or typeName == "F-14A-135-GR-Early" then -- VNAO Edit - Added
|
||||
nozzlePosR = unitClient:getDrawArgumentValue(433) -- VNAO Edit - Added
|
||||
end -- VNAO Edit - Added
|
||||
return nozzlePosR -- VNAO Edit - Added
|
||||
@@ -15062,7 +15068,7 @@ function AIRBOSS:_GetACNickname( actype )
|
||||
nickname = "Hawkeye"
|
||||
elseif actype == AIRBOSS.AircraftCarrier.C2A then
|
||||
nickname = "Greyhound"
|
||||
elseif actype == AIRBOSS.AircraftCarrier.F14A_AI or actype == AIRBOSS.AircraftCarrier.F14A or actype == AIRBOSS.AircraftCarrier.F14B then
|
||||
elseif actype == AIRBOSS.AircraftCarrier.F14A_AI or actype == AIRBOSS.AircraftCarrier.F14A or actype == AIRBOSS.AircraftCarrier.F14B or actype == AIRBOSS.AircraftCarrier.F14A_Early then
|
||||
nickname = "Tomcat"
|
||||
elseif actype == AIRBOSS.AircraftCarrier.FA18C or actype == AIRBOSS.AircraftCarrier.HORNET then
|
||||
nickname = "Hornet"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -5145,3 +5145,116 @@ function UTILS.ValidateAndRepositionStatic(Country, Category, Type, Position, Sh
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
---
|
||||
-- This function can be used to scan all airdromes of a map and write the Moose enums to a file.
|
||||
function UTILS.CreateAirbaseEnum()
|
||||
|
||||
-- Save file function
|
||||
local function _savefile( filename, data )
|
||||
local file=lfs.writedir() .. filename
|
||||
local f = io.open(file , "wb")
|
||||
if f then
|
||||
f:write( data )
|
||||
f:close()
|
||||
env.info(string.format("Saving to file %s", tostring(file) ))
|
||||
else
|
||||
env.info(string.format("ERROR: Could not save results to file %s", tostring(file) ))
|
||||
end
|
||||
end
|
||||
|
||||
-- Get all airbases
|
||||
local airbases=world.getAirbases()
|
||||
|
||||
-- Get map name
|
||||
local mapname=env.mission.theatre
|
||||
|
||||
-- Put airbases in a table
|
||||
local myab={}
|
||||
for i,_airbase in pairs(airbases) do
|
||||
local airbase=_airbase --DCS#Airbase
|
||||
|
||||
|
||||
local cat=airbase:getDesc().category
|
||||
|
||||
if cat==Airbase.Category.AIRDROME then
|
||||
|
||||
-- Get airbase name
|
||||
local name=airbase:getName()
|
||||
|
||||
-- Key is the name with illigal characters replaced
|
||||
local key=name
|
||||
|
||||
-- Germany map specifics
|
||||
if name=="Airracing Lubeck" then
|
||||
key="Airracing_Luebeck"
|
||||
elseif name=="Bad Durkheim" then
|
||||
key="Bad_Duerkheim"
|
||||
elseif name=="Buchel" then
|
||||
key="Buechel"
|
||||
elseif name=="Buckeburg" then
|
||||
key="Bueckeburg"
|
||||
elseif name=="Dusseldorf" then
|
||||
key="Duesseldorf"
|
||||
elseif name=="Gutersloh" then
|
||||
key="Guetersloh"
|
||||
elseif name=="Kothen" then
|
||||
key="Koethen"
|
||||
elseif name=="Larz" then
|
||||
key="Laerz"
|
||||
elseif name=="Lubeck" then
|
||||
key="Luebeck"
|
||||
elseif name=="Luneburg" then
|
||||
key="Lueneburg"
|
||||
elseif name=="Norvenich" then
|
||||
key="Noervenich"
|
||||
elseif name=="Ober-Morlen" then
|
||||
key="Ober_Moerlen"
|
||||
elseif name=="Peenemunde" then
|
||||
key="Peenemuende"
|
||||
elseif name=="Pottschutthohe" then
|
||||
key="Pottschutthoehe"
|
||||
elseif name=="Schonefeld" then
|
||||
key="Schoenefeld"
|
||||
elseif name=="Weser Wumme" then
|
||||
key="Weser_Wuemme"
|
||||
elseif name=="Zollschen" then
|
||||
key="Zoellschen"
|
||||
elseif name=="Zweibrucken" then
|
||||
key="Zweibruecken"
|
||||
end
|
||||
|
||||
-- Replace blanks, hyphens by underscores
|
||||
key=key:gsub(" ", "_")
|
||||
key=key:gsub("-", "_")
|
||||
key=key:gsub("'", "_")
|
||||
key=UTILS.ReplaceIllegalCharacters(key, "_")
|
||||
|
||||
local entry={}
|
||||
entry.key=key
|
||||
entry.name=name
|
||||
table.insert(myab, entry)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Sort by name
|
||||
table.sort(myab, function(a,b) return a.name < b.name end)
|
||||
|
||||
local text=string.format("\n--- Airbases of the %s map", mapname)
|
||||
text=text.."\n--"
|
||||
for _,ab in pairs(myab) do
|
||||
text=text..string.format("\n-- * `AIRBASE.%s.%s` %s", mapname, ab.key, ab.name)
|
||||
end
|
||||
text=text.."\n--"
|
||||
text=text..string.format("\n-- @field %s", mapname)
|
||||
text=text..string.format("\nAIRBASE.%s = {", mapname)
|
||||
for _,ab in pairs(myab) do
|
||||
text=text..string.format('\n\t["%s"] = "%s",', ab.key, ab.name)
|
||||
end
|
||||
text=text.."\n}"
|
||||
|
||||
_savefile(string.format("%s-enums.txt", env.mission.theatre), text)
|
||||
--env.info(text)
|
||||
end
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2855,7 +2855,7 @@ do -- Route methods
|
||||
-- @param Core.Zone#ZONE Zone The zone where to route to.
|
||||
-- @param #boolean Randomize Defines whether to target point gets randomized within the Zone.
|
||||
-- @param #number Speed The speed in m/s. Default is 5.555 m/s = 20 km/h.
|
||||
-- @param Core.Base#FORMATION Formation The formation string.
|
||||
-- @param DCS#FORMATION Formation The formation string.
|
||||
function CONTROLLABLE:TaskRouteToZone( Zone, Randomize, Speed, Formation )
|
||||
self:F2( Zone )
|
||||
|
||||
@@ -2915,7 +2915,7 @@ do -- Route methods
|
||||
-- @param #CONTROLLABLE self
|
||||
-- @param DCS#Vec2 Vec2 The Vec2 where to route to.
|
||||
-- @param #number Speed The speed in m/s. Default is 5.555 m/s = 20 km/h.
|
||||
-- @param Core.Base#FORMATION Formation The formation string.
|
||||
-- @param DCS#FORMATION Formation The formation string.
|
||||
function CONTROLLABLE:TaskRouteToVec2( Vec2, Speed, Formation )
|
||||
|
||||
local DCSControllable = self:GetDCSObject()
|
||||
|
||||
@@ -108,8 +108,9 @@ DYNAMICCARGO.State = {
|
||||
-- @type DYNAMICCARGO.AircraftTypes
|
||||
DYNAMICCARGO.AircraftTypes = {
|
||||
["CH-47Fbl1"] = "CH-47Fbl1",
|
||||
["Mi-8MTV2"] = "CH-47Fbl1",
|
||||
["Mi-8MT"] = "CH-47Fbl1",
|
||||
["Mi-8MTV2"] = "Mi-8MTV2",
|
||||
["Mi-8MT"] = "Mi-8MT",
|
||||
["C-130J-30"] = "C-130J-30",
|
||||
}
|
||||
|
||||
--- Helo types possible.
|
||||
@@ -122,23 +123,29 @@ DYNAMICCARGO.AircraftDimensions = {
|
||||
["length"] = 11,
|
||||
["ropelength"] = 30,
|
||||
},
|
||||
["Mi-8MTV2"] = {
|
||||
["Mi-8MTV2"] = {
|
||||
["width"] = 6,
|
||||
["height"] = 6,
|
||||
["length"] = 15,
|
||||
["ropelength"] = 30,
|
||||
},
|
||||
["Mi-8MT"] = {
|
||||
["Mi-8MT"] = {
|
||||
["width"] = 6,
|
||||
["height"] = 6,
|
||||
["length"] = 15,
|
||||
["ropelength"] = 30,
|
||||
},
|
||||
["C-130J-30"] = {
|
||||
["width"] = 4,
|
||||
["height"] = 12,
|
||||
["length"] = 35,
|
||||
["ropelength"] = 0,
|
||||
},
|
||||
}
|
||||
|
||||
--- DYNAMICCARGO class version.
|
||||
-- @field #string version
|
||||
DYNAMICCARGO.version="0.0.9"
|
||||
DYNAMICCARGO.version="0.1.0"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
@@ -527,7 +534,10 @@ function DYNAMICCARGO:_UpdatePosition()
|
||||
---------------
|
||||
-- REMOVED Cargo
|
||||
---------------
|
||||
if self.timer and self.timer:IsRunning() then self.timer:Stop() end
|
||||
if self.timer and self.timer:IsRunning() then
|
||||
self.timer:Stop()
|
||||
self.timer=nil
|
||||
end
|
||||
self:T(self.lid.." dead! " ..self.CargoState.."-> REMOVED")
|
||||
self.CargoState = DYNAMICCARGO.State.REMOVED
|
||||
_DATABASE:CreateEventDynamicCargoRemoved(self)
|
||||
@@ -535,6 +545,24 @@ function DYNAMICCARGO:_UpdatePosition()
|
||||
return self
|
||||
end
|
||||
|
||||
--- [USER] Destroy a DYNAMICCARGO object.
|
||||
-- @param #DYNAMICCARGO self
|
||||
-- @param #boolean GenerateEvent Set to false to remove an item silently. Defaults to true.
|
||||
-- @return #boolean Return Returns nil if the object could not be found, else returns true.
|
||||
function DYNAMICCARGO:Destroy(GenerateEvent)
|
||||
local DCSObject = self:GetDCSObject()
|
||||
if DCSObject then
|
||||
local GenerateEvent = (GenerateEvent ~= nil and GenerateEvent == false) and false or true
|
||||
if GenerateEvent and GenerateEvent == true then
|
||||
self:CreateEventDead( timer.getTime(), DCSObject )
|
||||
end
|
||||
DCSObject:destroy()
|
||||
self:_UpdatePosition()
|
||||
return true
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
--- [Internal] Track helos for loaded/unloaded decision making.
|
||||
-- @param Wrapper.Client#CLIENT client
|
||||
-- @return #boolean IsIn
|
||||
|
||||
@@ -1058,9 +1058,12 @@ function GROUP:GetTypeName()
|
||||
local DCSGroup = self:GetDCSObject()
|
||||
|
||||
if DCSGroup then
|
||||
local GroupTypeName = DCSGroup:getUnit(1):getTypeName()
|
||||
--self:T3( GroupTypeName )
|
||||
return( GroupTypeName )
|
||||
local unit = DCSGroup:getUnit(1)
|
||||
if unit then
|
||||
local GroupTypeName = unit:getTypeName()
|
||||
--self:T3( GroupTypeName )
|
||||
return( GroupTypeName )
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
@@ -1075,9 +1078,12 @@ function GROUP:GetNatoReportingName()
|
||||
local DCSGroup = self:GetDCSObject()
|
||||
|
||||
if DCSGroup then
|
||||
local GroupTypeName = DCSGroup:getUnit(1):getTypeName()
|
||||
--self:T3( GroupTypeName )
|
||||
return UTILS.GetReportingName(GroupTypeName)
|
||||
local unit = DCSGroup:getUnit(1)
|
||||
if unit then
|
||||
local GroupTypeName = unit:getTypeName()
|
||||
--self:T3( GroupTypeName )
|
||||
return UTILS.GetReportingName(GroupTypeName)
|
||||
end
|
||||
end
|
||||
|
||||
return "Bogey"
|
||||
@@ -1093,9 +1099,12 @@ function GROUP:GetPlayerName()
|
||||
local DCSGroup = self:GetDCSObject()
|
||||
|
||||
if DCSGroup then
|
||||
local PlayerName = DCSGroup:getUnit(1):getPlayerName()
|
||||
--self:T3( PlayerName )
|
||||
return( PlayerName )
|
||||
local unit = DCSGroup:getUnit(1)
|
||||
if unit then
|
||||
local PlayerName = unit:getPlayerName()
|
||||
--self:T3( PlayerName )
|
||||
return( PlayerName )
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
@@ -1111,9 +1120,12 @@ function GROUP:GetCallsign()
|
||||
local DCSGroup = self:GetDCSObject()
|
||||
|
||||
if DCSGroup then
|
||||
local GroupCallSign = DCSGroup:getUnit(1):getCallsign()
|
||||
--self:T3( GroupCallSign )
|
||||
return GroupCallSign
|
||||
local unit = DCSGroup:getUnit(1)
|
||||
if unit then
|
||||
local GroupCallSign = unit:getCallsign()
|
||||
--self:T3( GroupCallSign )
|
||||
return GroupCallSign
|
||||
end
|
||||
end
|
||||
|
||||
BASE:E( { "Cannot GetCallsign", Positionable = self, Alive = self:IsAlive() } )
|
||||
|
||||
@@ -170,6 +170,27 @@ function IDENTIFIABLE:GetCoalition()
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Returns true if identifiable is of RED coalition.
|
||||
-- @param #IDENTIFIABLE self
|
||||
-- @return #boolean If the identifiable is red.
|
||||
function IDENTIFIABLE:IsRed()
|
||||
return self:GetCoalition() == coalition.side.RED
|
||||
end
|
||||
|
||||
--- Returns true if identifiable is of BLUE coalition.
|
||||
-- @param #IDENTIFIABLE self
|
||||
-- @return #boolean If the identifiable is blue.
|
||||
function IDENTIFIABLE:IsBlue()
|
||||
return self:GetCoalition() == coalition.side.BLUE
|
||||
end
|
||||
|
||||
--- Returns true if identifiable is of NEUTRAL coalition.
|
||||
-- @param #IDENTIFIABLE self
|
||||
-- @return #boolean If the identifiable is neutral.
|
||||
function IDENTIFIABLE:IsNeutral()
|
||||
return self:GetCoalition() == coalition.side.NEUTRAL
|
||||
end
|
||||
|
||||
--- Returns the name of the coalition of the Identifiable.
|
||||
-- @param #IDENTIFIABLE self
|
||||
-- @return #string The name of the coalition.
|
||||
|
||||
@@ -18,7 +18,13 @@
|
||||
-- @field #string SceneryName Name of the scenery object.
|
||||
-- @field DCS#Object SceneryObject DCS scenery object.
|
||||
-- @field #number Life0 Initial life points.
|
||||
-- @field #table Properties
|
||||
-- @field #table Properties.
|
||||
-- @field #number ID.
|
||||
-- @field Core.Zone#ZONE_POLYGON SceneryZone.
|
||||
-- @field Core.Point#COORDINATE Coordinate.
|
||||
-- @field DCS#Vec2 Vec2.
|
||||
-- @field DCS#Vec3 Vec3.
|
||||
-- @field Core.Vector#VECTOR Vector.
|
||||
-- @extends Wrapper.Positionable#POSITIONABLE
|
||||
|
||||
|
||||
@@ -35,27 +41,72 @@ SCENERY = {
|
||||
ClassName = "SCENERY",
|
||||
}
|
||||
|
||||
_SCENERY = {}
|
||||
|
||||
--- Register scenery object as POSITIONABLE.
|
||||
--@param #SCENERY self
|
||||
--@param #string SceneryName Scenery name.
|
||||
--@param DCS#Object SceneryObject DCS scenery object.
|
||||
--@param Core.Zone#ZONE_POLYGON SceneryZone (optional) The zone object.
|
||||
--@return #SCENERY Scenery object.
|
||||
function SCENERY:Register( SceneryName, SceneryObject )
|
||||
|
||||
function SCENERY:Register( SceneryName, SceneryObject, SceneryZone )
|
||||
|
||||
local ID = (SceneryObject and SceneryObject.getID) and SceneryObject:getID() or SceneryName
|
||||
|
||||
if _SCENERY[ID] and _SCENERY[ID].SceneryObject == nil then
|
||||
|
||||
_SCENERY[ID].SceneryObject=SceneryObject
|
||||
SCENERY._UpdateFromDCSObject(_SCENERY[ID])
|
||||
|
||||
end
|
||||
|
||||
if _SCENERY[ID] then return _SCENERY[ID] end
|
||||
|
||||
local self = BASE:Inherit( self, POSITIONABLE:New( SceneryName ) )
|
||||
|
||||
self.SceneryName = tostring(SceneryName)
|
||||
|
||||
self.ID = ID
|
||||
self.SceneryObject = SceneryObject
|
||||
self.SceneryZone = SceneryZone
|
||||
|
||||
if SceneryZone then
|
||||
self.Vec3 = SceneryZone:GetVec3()
|
||||
self.Vec2 = SceneryZone:GetVec2()
|
||||
self.Vector = (self.Vec3 and VECTOR) and VECTOR:NewFromVec(self.Vec3) or nil
|
||||
end
|
||||
|
||||
if self.SceneryObject and self.SceneryObject.getLife then -- fix some objects do not have all functions
|
||||
self.Life0 = self.SceneryObject:getLife() or 0
|
||||
self.Life0 = self.SceneryObject:getLife() or 1
|
||||
else
|
||||
self.Life0 = 0
|
||||
self.Life0 = 1
|
||||
end
|
||||
|
||||
self.Properties = {}
|
||||
|
||||
_SCENERY[self.ID] = self
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- [INTERNAL] Update data
|
||||
-- @param Wrapper.Scenery#SCENERY Scenery The object to update.
|
||||
function SCENERY._UpdateFromDCSObject(Scenery)
|
||||
env.info("APPLE _UpdateFromDCSObject "..tostring(Scenery.SceneryName))
|
||||
local self=Scenery
|
||||
if self.Vec2 == nil and self.SceneryObject ~= nil then
|
||||
self.Vec3 = self.SceneryObject:getPoint()
|
||||
if self.Vec3 then
|
||||
self.Vec2 = {x=self.Vec3.x,y=self.Vec3.z}
|
||||
self.Vector = VECTOR:NewFromVec(self.Vec3)
|
||||
end
|
||||
end
|
||||
if not self.Life0 or self.Life0 == 1 then
|
||||
if self.SceneryObject and self.SceneryObject.getLife() then
|
||||
self.Life = self.SceneryObject:getLife() or 1
|
||||
self.Life0 = self.Life
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -99,6 +150,39 @@ function SCENERY:GetName()
|
||||
return self.SceneryName
|
||||
end
|
||||
|
||||
--- Obtain object coordinate.
|
||||
--@param #SCENERY self
|
||||
--@return Core.Point#COORDINATE Coordinate
|
||||
function SCENERY:GetCoordinate()
|
||||
if self.Coordinate then
|
||||
return self.Coordinate
|
||||
elseif self.Vec3 then
|
||||
self.Coordinate = COORDINATE:NewFromVec3(self.Vec3):SetAlt()
|
||||
end
|
||||
return self.Coordinate
|
||||
end
|
||||
|
||||
--- Obtain object coordinate.
|
||||
--@param #SCENERY self
|
||||
--@return DCS#Vec3 Vec3
|
||||
function SCENERY:GetVec3()
|
||||
return self.Vec3
|
||||
end
|
||||
|
||||
--- Obtain object coordinate.
|
||||
--@param #SCENERY self
|
||||
--@return DCS#Vec2 Vec2
|
||||
function SCENERY:GetVec2()
|
||||
return self.Vec2
|
||||
end
|
||||
|
||||
--- Obtain object coordinate.
|
||||
--@param #SCENERY self
|
||||
--@return Core.Vector#VECTOR Vector
|
||||
function SCENERY:GetVector()
|
||||
return self.Vector
|
||||
end
|
||||
|
||||
--- Obtain DCS Object from the SCENERY Object.
|
||||
--@param #SCENERY self
|
||||
--@return DCS#Object DCS scenery object.
|
||||
@@ -106,6 +190,13 @@ function SCENERY:GetDCSObject()
|
||||
return self.SceneryObject
|
||||
end
|
||||
|
||||
--- Obtain object ID.
|
||||
--@param #SCENERY self
|
||||
--@return #string Name
|
||||
function SCENERY:GetID()
|
||||
return self.ID
|
||||
end
|
||||
|
||||
--- Get current life points from the SCENERY Object. Note - Some scenery objects always have 0 life points.
|
||||
-- **CAVEAT**: Some objects change their life value or "hitpoints" **after** the first hit. Hence we will adjust the life0 value to 120%
|
||||
-- of the last life value if life exceeds life0 (initial life) at any point. Thus will will get a smooth percentage decrease, if you use this e.g. as success
|
||||
@@ -113,12 +204,14 @@ end
|
||||
--@param #SCENERY self
|
||||
--@return #number life
|
||||
function SCENERY:GetLife()
|
||||
local life = 0
|
||||
local life = 1
|
||||
if self.SceneryObject and self.SceneryObject.getLife then
|
||||
life = self.SceneryObject:getLife()
|
||||
if life > self.Life0 then
|
||||
self.Life0 = math.floor(life * 1.2)
|
||||
end
|
||||
elseif self.Life then
|
||||
life = self.Life
|
||||
end
|
||||
return life
|
||||
end
|
||||
@@ -176,12 +269,19 @@ end
|
||||
--- Find a SCENERY object from its name or id. Since SCENERY isn't registered in the Moose database (just too many objects per map), we need to do a scan first
|
||||
-- to find the correct object.
|
||||
--@param #SCENERY self
|
||||
--@param #string Name The name/id of the scenery object as taken from the ME. Ex. '595785449'
|
||||
--@param Core.Point#COORDINATE Coordinate Where to find the scenery object
|
||||
--@param #number Radius (optional) Search radius around coordinate, defaults to 100
|
||||
--@return #SCENERY Scenery Object or `nil` if it cannot be found
|
||||
function SCENERY:FindByName(Name, Coordinate, Radius, Role)
|
||||
|
||||
--@param #string Name The name/id of the scenery object as taken from the ME. Ex. '595785449'.
|
||||
--@param Core.Point#COORDINATE Coordinate Where to find the scenery object.
|
||||
--@param #number Radius (optional) Search radius around coordinate, defaults to 100.
|
||||
--@param #string Role (optional) The role if set on the zone object.
|
||||
--@param Core.Zone#ZONE_POLYGON Zone (optional) The Zone where the scenery is located.
|
||||
--@return #SCENERY Scenery Object or `nil` if it cannot be found.
|
||||
function SCENERY:FindByName(Name, Coordinate, Radius, Role, Zone)
|
||||
|
||||
--BASE:I("Coordinate x = "..Coordinate.x .. " y = "..Coordinate.y.." z = "..Coordinate.z)
|
||||
|
||||
local findme = self:_FindByName(Name)
|
||||
if findme then return findme end
|
||||
|
||||
local radius = Radius or 100
|
||||
local name = Name or "unknown"
|
||||
local scenery = nil
|
||||
@@ -193,12 +293,13 @@ function SCENERY:FindByName(Name, Coordinate, Radius, Role)
|
||||
local function SceneryScan(scoordinate, sradius, sname)
|
||||
if scoordinate ~= nil then
|
||||
local Vec2 = scoordinate:GetVec2()
|
||||
local scanzone = ZONE_RADIUS:New("Zone-"..sname,Vec2,sradius,true)
|
||||
local scanzone = ZONE_RADIUS:New("Zone-"..sname,Vec2,sradius)
|
||||
scanzone:Scan({Object.Category.SCENERY})
|
||||
local scanned = scanzone:GetScannedSceneryObjects()
|
||||
local rscenery = nil -- Wrapper.Scenery#SCENERY
|
||||
for _,_scenery in pairs(scanned) do
|
||||
local scenery = _scenery -- Wrapper.Scenery#SCENERY
|
||||
--BASE:I({tostring(scenery.SceneryName),tostring(sname)})
|
||||
if tostring(scenery.SceneryName) == tostring(sname) then
|
||||
rscenery = scenery
|
||||
if Role then rscenery:SetProperty("ROLE",Role) end
|
||||
@@ -211,13 +312,36 @@ function SCENERY:FindByName(Name, Coordinate, Radius, Role)
|
||||
end
|
||||
|
||||
if Coordinate then
|
||||
--BASE:I("Coordinate Scenery Scan")
|
||||
scenery = SceneryScan(Coordinate, radius, name)
|
||||
end
|
||||
|
||||
|
||||
if not scenery then scenery = SCENERY:Register(Name,nil,Zone) end
|
||||
|
||||
return scenery
|
||||
end
|
||||
|
||||
--- Find a SCENERY object that was previously registered(!) by it's ID.
|
||||
-- @param #SCENERY self
|
||||
-- @param #number ID
|
||||
-- @return Wrapper.Scenery#SCENERY Scenery or nil if it could not be found
|
||||
function SCENERY:FindByID(ID)
|
||||
return _SCENERY[ID]
|
||||
end
|
||||
|
||||
--- Find a SCENERY object that was previously registered(!) by it's name.
|
||||
-- @param #SCENERY self
|
||||
-- @param #string Name
|
||||
-- @return Wrapper.Scenery#SCENERY Scenery or nil if it could not be found
|
||||
function SCENERY:_FindByName(Name)
|
||||
for _id,_object in pairs(_SCENERY) do
|
||||
if _object and _object.GetName and _object:GetName() then
|
||||
local name = _object:GetName()
|
||||
if Name == name then return _object end
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Find a SCENERY object from its name or id. Since SCENERY isn't registered in the Moose database (just too many objects per map), we need to do a scan first
|
||||
-- to find the correct object.
|
||||
--@param #SCENERY self
|
||||
@@ -231,8 +355,8 @@ function SCENERY:FindByNameInZone(Name, Zone, Radius)
|
||||
if type(Zone) == "string" then
|
||||
Zone = ZONE:FindByName(Zone)
|
||||
end
|
||||
local coordinate = Zone:GetCoordinate()
|
||||
return self:FindByName(Name,coordinate,Radius,Zone:GetProperty("ROLE"))
|
||||
local coordinate = Zone:GetCoordinate():SetAlt()
|
||||
return self:FindByName(Name,coordinate,Radius,Zone:GetProperty("ROLE"),Zone)
|
||||
end
|
||||
|
||||
--- Find a SCENERY object from its zone name. Since SCENERY isn't registered in the Moose database (just too many objects per map), we need to do a scan first
|
||||
@@ -241,14 +365,18 @@ end
|
||||
--@param #string ZoneName The name of the scenery zone as created with a right-click on the map in the mission editor and select "assigned to...". Can be handed over as ZONE object.
|
||||
--@return #SCENERY First found Scenery Object or `nil` if it cannot be found
|
||||
function SCENERY:FindByZoneName( ZoneName )
|
||||
--BASE:I(ZoneName)
|
||||
|
||||
local zone = ZoneName -- Core.Zone#ZONE_BASE
|
||||
|
||||
if type(ZoneName) == "string" then
|
||||
zone = ZONE:FindByName(ZoneName) -- Core.Zone#ZONE_POLYGON
|
||||
end
|
||||
|
||||
local _id = zone:GetProperty('OBJECT ID')
|
||||
--local properties = zone:GetAllProperties() or {}
|
||||
--BASE:I(string.format("Object ID is: %s",_id or "none"))
|
||||
--BASE:T("Object ID ".._id)
|
||||
|
||||
--BASE:I("Object ID ".._id)
|
||||
|
||||
if not _id then
|
||||
-- this zone has no object ID
|
||||
BASE:E("**** Zone without object ID: "..ZoneName.." | Type: "..tostring(zone.ClassName))
|
||||
@@ -257,23 +385,27 @@ function SCENERY:FindByZoneName( ZoneName )
|
||||
local scanned = zone:GetScannedSceneryObjects()
|
||||
for _,_scenery in (scanned) do
|
||||
local scenery = _scenery -- Wrapper.Scenery#SCENERY
|
||||
if scenery:IsAlive() then
|
||||
--if scenery:IsAlive() then
|
||||
local role = zone:GetProperty("ROLE")
|
||||
if role then scenery:SetProperty("ROLE",role) end
|
||||
return scenery
|
||||
end
|
||||
--end
|
||||
end
|
||||
return nil
|
||||
else
|
||||
return self:FindByName(_id, zone:GetCoordinate(),nil,zone:GetProperty("ROLE"))
|
||||
local coordinate = zone:GetCoordinate()
|
||||
coordinate:SetAlt()
|
||||
return self:FindByName(_id, coordinate,nil,zone:GetProperty("ROLE"),zone)
|
||||
end
|
||||
else
|
||||
return self:FindByName(_id, zone:GetCoordinate(),nil,zone:GetProperty("ROLE"))
|
||||
local coordinate = zone:GetCoordinate()
|
||||
coordinate:SetAlt()
|
||||
return self:FindByName(_id, coordinate,nil,zone:GetProperty("ROLE"),zone)
|
||||
end
|
||||
end
|
||||
|
||||
--- Scan and find all SCENERY objects from a zone by zone-name. Since SCENERY isn't registered in the Moose database (just too many objects per map), we need to do a scan first
|
||||
-- to find the correct object.
|
||||
-- to find the correct object. Might return nil!
|
||||
--@param #SCENERY self
|
||||
--@param #string ZoneName The name of the zone, can be handed as ZONE_RADIUS or ZONE_POLYGON object
|
||||
--@return #table of SCENERY Objects, or `nil` if nothing found
|
||||
@@ -295,7 +427,7 @@ function SCENERY:FindAllByZoneName( ZoneName )
|
||||
return nil
|
||||
end
|
||||
else
|
||||
local obj = self:FindByName(_id, zone:GetCoordinate(),nil,zone:GetProperty("ROLE"))
|
||||
local obj = self:FindByName(_id, zone:GetCoordinate():SetAlt(),nil,zone:GetProperty("ROLE"), zone)
|
||||
if obj then
|
||||
return {obj}
|
||||
else
|
||||
|
||||
@@ -64,6 +64,9 @@ function STATIC:Register( StaticName )
|
||||
else
|
||||
self:E(string.format("Static object %s does not exist!", tostring(self.StaticName)))
|
||||
end
|
||||
|
||||
-- Cache position
|
||||
self._vec3 = self:GetVec3()
|
||||
|
||||
return self
|
||||
end
|
||||
@@ -86,6 +89,30 @@ function STATIC:GetLife()
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Get the position of the STATIC even if it is not alive.
|
||||
-- @param #STATIC self
|
||||
-- @return DCS#Vec2 The 2D point vector of the POSITIONABLE.
|
||||
-- @return #nil The position was not cached.
|
||||
function STATIC:GetVec2Cached()
|
||||
local vec2 = self:GetVec2()
|
||||
if not vec2 and self._vec3 then
|
||||
vec2 = {x = self._vec3.x, y = self._vec3.z }
|
||||
end
|
||||
return vec2
|
||||
end
|
||||
|
||||
--- Get the position of the STATIC even if it is not alive.
|
||||
-- @param #STATIC self
|
||||
-- @return DCS#Vec3 The 3D point vector of the POSITIONABLE.
|
||||
-- @return #nil The position was not cached.
|
||||
function STATIC:GetVec3Cached()
|
||||
local vec3 = self:GetVec3()
|
||||
if not vec3 and self._vec3 then
|
||||
vec3 = self._vec3
|
||||
end
|
||||
return vec3
|
||||
end
|
||||
|
||||
--- Finds a STATIC from the _DATABASE using a DCSStatic object.
|
||||
-- @param #STATIC self
|
||||
-- @param DCS#StaticObject DCSStatic An existing DCS Static object reference.
|
||||
@@ -232,6 +259,8 @@ function STATIC:SpawnAt(Coordinate, Heading, Delay)
|
||||
local SpawnStatic=SPAWNSTATIC:NewFromStatic(self.StaticName)
|
||||
|
||||
SpawnStatic:SpawnFromPointVec2( Coordinate, Heading, self.StaticName )
|
||||
-- Cache position
|
||||
self._vec3 = self:GetVec3()
|
||||
|
||||
end
|
||||
|
||||
@@ -255,6 +284,8 @@ function STATIC:ReSpawn(CountryID, Delay)
|
||||
local SpawnStatic=SPAWNSTATIC:NewFromStatic(self.StaticName, CountryID)
|
||||
|
||||
SpawnStatic:Spawn(nil, self.StaticName)
|
||||
-- Cache position
|
||||
self._vec3 = self:GetVec3()
|
||||
|
||||
end
|
||||
|
||||
@@ -278,6 +309,8 @@ function STATIC:ReSpawnAt(Coordinate, Heading, Delay)
|
||||
local SpawnStatic=SPAWNSTATIC:NewFromStatic(self.StaticName, self:GetCountry())
|
||||
|
||||
SpawnStatic:SpawnFromCoordinate(Coordinate, Heading, self.StaticName)
|
||||
-- Cache position
|
||||
self._vec3 = self:GetVec3()
|
||||
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user