mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2026-08-18 13:16:03 +00:00
xx
This commit is contained in:
@@ -230,8 +230,10 @@ SCORING = {
|
|||||||
ClassID = 0,
|
ClassID = 0,
|
||||||
Players = {},
|
Players = {},
|
||||||
AutoSave = true,
|
AutoSave = true,
|
||||||
version = "1.18.4",
|
version = "1.18.5",
|
||||||
ScoringScenery = nil, -- Core.Set#SET_SCENERY
|
ScoringScenery = nil, -- Core.Set#SET_SCENERY
|
||||||
|
SceneryHitsInZone = false,
|
||||||
|
LoadSave = false,
|
||||||
}
|
}
|
||||||
|
|
||||||
local _SCORINGCoalition = {
|
local _SCORINGCoalition = {
|
||||||
@@ -250,15 +252,16 @@ local _SCORINGCategory = {
|
|||||||
--- Creates a new SCORING object to administer the scoring achieved by players.
|
--- Creates a new SCORING object to administer the scoring achieved by players.
|
||||||
-- @param #SCORING self
|
-- @param #SCORING self
|
||||||
-- @param #string GameName The name of the game. This name is also logged in the CSV score file.
|
-- @param #string GameName The name of the game. This name is also logged in the CSV score file.
|
||||||
-- @param #string SavePath (Optional) Path where to save the CSV file, defaults to your **<User>\\Saved Games\\DCS\\Logs** folder.
|
-- @param #string SavePath (Optional) Path where to save the CSV files, defaults to your **<User>\\Saved Games\\DCS\\Logs** folder. See next two options.
|
||||||
-- @param #boolean AutoSave (Optional) If passed as `false`, then swith autosave off.
|
-- @param #boolean AutoSave (Optional) If passed as `false`, then swith autosave off. This stores a detailed table which will never be loaded again by SCORING (for e.g. Discord purposes).
|
||||||
|
-- @param #boolean LoadSave (Optional) If passed as `true` save summary scores per player, and load at restart of the mission.
|
||||||
-- @return #SCORING self
|
-- @return #SCORING self
|
||||||
-- @usage
|
-- @usage
|
||||||
--
|
--
|
||||||
-- -- Define a new scoring object for the mission Gori Valley.
|
-- -- Define a new scoring object for the mission Gori Valley.
|
||||||
-- ScoringObject = SCORING:New( "Gori Valley" )
|
-- ScoringObject = SCORING:New( "Gori Valley" )
|
||||||
--
|
--
|
||||||
function SCORING:New( GameName, SavePath, AutoSave )
|
function SCORING:New( GameName, SavePath, AutoSave, LoadSave )
|
||||||
|
|
||||||
-- Inherits from BASE
|
-- Inherits from BASE
|
||||||
local self = BASE:Inherit( self, BASE:New() ) -- #SCORING
|
local self = BASE:Inherit( self, BASE:New() ) -- #SCORING
|
||||||
@@ -266,7 +269,7 @@ function SCORING:New( GameName, SavePath, AutoSave )
|
|||||||
if GameName then
|
if GameName then
|
||||||
self.GameName = GameName
|
self.GameName = GameName
|
||||||
else
|
else
|
||||||
error( "A game name must be given to register the scoring results" )
|
error( "A game name must be given to register the scoring results!" )
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Additional Object scores
|
-- Additional Object scores
|
||||||
@@ -301,6 +304,12 @@ function SCORING:New( GameName, SavePath, AutoSave )
|
|||||||
self.penaltyoncoalitionchange = true
|
self.penaltyoncoalitionchange = true
|
||||||
|
|
||||||
self:SetDisplayMessagePrefix()
|
self:SetDisplayMessagePrefix()
|
||||||
|
|
||||||
|
self.SceneryHitsInZone = false
|
||||||
|
|
||||||
|
if LoadSave then
|
||||||
|
self.LoadSave = LoadSave
|
||||||
|
end
|
||||||
|
|
||||||
-- Event handlers
|
-- Event handlers
|
||||||
self:HandleEvent( EVENTS.Dead, self._EventOnDeadOrCrash )
|
self:HandleEvent( EVENTS.Dead, self._EventOnDeadOrCrash )
|
||||||
@@ -328,11 +337,61 @@ function SCORING:New( GameName, SavePath, AutoSave )
|
|||||||
end
|
end
|
||||||
|
|
||||||
self:I("SCORING "..tostring(GameName).." started! v"..self.version)
|
self:I("SCORING "..tostring(GameName).." started! v"..self.version)
|
||||||
|
|
||||||
|
if LoadSave == true then
|
||||||
|
self:_LoadPlayerSummaryScore()
|
||||||
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [Internal] Helper to load scores from disk at scoring start
|
||||||
|
-- @param #SCORING self
|
||||||
|
-- @return #SCORING self
|
||||||
|
function SCORING:_LoadPlayerSummaryScore()
|
||||||
|
|
||||||
|
if lfs and io and self.LoadSave == true then
|
||||||
|
local path = self.AutoSavePath or lfs.writedir() .. [[Logs\]]
|
||||||
|
local filename = self.GameName or "PlayerScoresSummary"
|
||||||
|
filename = filename..".csv"
|
||||||
|
if UTILS.CheckFileExists(path,filename) then
|
||||||
|
local ok, data = UTILS.LoadFromFile(path,filename)
|
||||||
|
-- Playername;;Score;;Penalty
|
||||||
|
table.remove(data,1)
|
||||||
|
for _,_data in pairs(data) do
|
||||||
|
local line = UTILS.Split(_data,";;")
|
||||||
|
local playername = tostring(line[1])
|
||||||
|
local score = tonumber(line[2])
|
||||||
|
local penalty = tonumber(line[3])
|
||||||
|
self:I(string.format("Player %s Score %d Penalty %d",playername,score,penalty))
|
||||||
|
local PlayerData = self.Players[playername]
|
||||||
|
if not PlayerData then
|
||||||
|
PlayerData = {}
|
||||||
|
PlayerData.Hit = {}
|
||||||
|
PlayerData.Destroy = {}
|
||||||
|
PlayerData.Goals = {}
|
||||||
|
PlayerData.Goals[self.GameName] = {Score = score, Penalty = penalty}
|
||||||
|
PlayerData.Mission = {}
|
||||||
|
PlayerData.HitPlayers = {}
|
||||||
|
PlayerData.Score = score
|
||||||
|
PlayerData.Penalty = penalty
|
||||||
|
PlayerData.PenaltyCoalition = 0
|
||||||
|
PlayerData.PenaltyWarning = 0
|
||||||
|
self.Players[playername] = PlayerData
|
||||||
|
else
|
||||||
|
PlayerData.Score = score
|
||||||
|
PlayerData.Penalty =penalty
|
||||||
|
self.Players[playername] = PlayerData
|
||||||
|
PlayerData.Goals[self.GameName] = {Score = score, Penalty = penalty}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Set a prefix string that will be displayed at each scoring message sent.
|
--- Set a prefix string that will be displayed at each scoring message sent.
|
||||||
-- @param #SCORING self
|
-- @param #SCORING self
|
||||||
-- @param #string DisplayMessagePrefix (Default="Scoring: ") The scoring prefix string.
|
-- @param #string DisplayMessagePrefix (Default="Scoring: ") The scoring prefix string.
|
||||||
@@ -579,6 +638,22 @@ function SCORING:AddZoneScore( ScoreZone, Score )
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Allow Scenery hits in Zones to count (no specific(!) scenery targets). NOTE - Allowing this can spam your scoring display!
|
||||||
|
-- @param #SCORING self
|
||||||
|
-- @return #SCORING self
|
||||||
|
function SCORING:EnableSceneryHitsinZones()
|
||||||
|
self.SceneryHitsInZone = true
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Disallow Scenery hits in Zones to count (no specific(!) scenery targets).
|
||||||
|
-- @param #SCORING self
|
||||||
|
-- @return #SCORING self
|
||||||
|
function SCORING:DisableSceneryHitsinZones()
|
||||||
|
self.SceneryHitsInZone = false
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Add a @{Core.Set#SET_ZONE} to define additional scoring when any object is destroyed in that zone.
|
--- 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!
|
-- 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.
|
-- This allows for a dynamic destruction zone evolution within your mission.
|
||||||
@@ -877,6 +952,20 @@ function SCORING:AddGoalScorePlayer( PlayerName, GoalTag, Text, Score )
|
|||||||
-- PlayerName can be nil, if the Unit with the player crashed or due to another reason.
|
-- PlayerName can be nil, if the Unit with the player crashed or due to another reason.
|
||||||
if PlayerName then
|
if PlayerName then
|
||||||
local PlayerData = self.Players[PlayerName]
|
local PlayerData = self.Players[PlayerName]
|
||||||
|
if not PlayerData then
|
||||||
|
PlayerData = {}
|
||||||
|
PlayerData.Goals = {}
|
||||||
|
PlayerData.Hit = {}
|
||||||
|
PlayerData.Destroy = {}
|
||||||
|
PlayerData.Goals = {}
|
||||||
|
PlayerData.Mission = {}
|
||||||
|
PlayerData.HitPlayers = {}
|
||||||
|
PlayerData.Score = 0
|
||||||
|
PlayerData.Penalty = 0
|
||||||
|
PlayerData.PenaltyCoalition = 0
|
||||||
|
PlayerData.PenaltyWarning = 0
|
||||||
|
self.Players[PlayerName] = PlayerData
|
||||||
|
end
|
||||||
|
|
||||||
PlayerData.Goals[GoalTag] = PlayerData.Goals[GoalTag] or { Score = 0 }
|
PlayerData.Goals[GoalTag] = PlayerData.Goals[GoalTag] or { Score = 0 }
|
||||||
PlayerData.Goals[GoalTag].Score = PlayerData.Goals[GoalTag].Score + Score
|
PlayerData.Goals[GoalTag].Score = PlayerData.Goals[GoalTag].Score + Score
|
||||||
@@ -1568,22 +1657,24 @@ function SCORING:_EventOnDeadOrCrash( Event )
|
|||||||
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
-- Check if there are Zones where the destruction happened.
|
if self.SceneryHitsInZone == true then
|
||||||
for ZoneName, ScoreZoneData in pairs( self.ScoringZones ) do
|
-- Check if there are Zones where the destruction happened.
|
||||||
self:F( { ScoringZone = ScoreZoneData } )
|
for ZoneName, ScoreZoneData in pairs( self.ScoringZones ) do
|
||||||
local ScoreZone = ScoreZoneData.ScoreZone -- Core.Zone#ZONE_BASE
|
self:F( { ScoringZone = ScoreZoneData } )
|
||||||
local Score = ScoreZoneData.Score
|
local ScoreZone = ScoreZoneData.ScoreZone -- Core.Zone#ZONE_BASE
|
||||||
if ScoreZone:IsVec2InZone( TargetUnit:GetVec2() ) then
|
local Score = ScoreZoneData.Score
|
||||||
Player.Score = Player.Score + Score
|
if ScoreZone:IsVec2InZone( TargetUnit:GetVec2() ) then
|
||||||
TargetDestroy.Score = TargetDestroy.Score + Score
|
Player.Score = Player.Score + Score
|
||||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Scenery destroyed in zone '" .. ScoreZone:GetName() .. "'." ..
|
TargetDestroy.Score = TargetDestroy.Score + Score
|
||||||
"Player '" .. PlayerName .. "' receives an extra " .. Score .. " points! " .. "Total: " .. Player.Score - Player.Penalty,
|
MESSAGE:NewType( self.DisplayMessagePrefix .. "Scenery destroyed in zone '" .. ScoreZone:GetName() .. "'." ..
|
||||||
MESSAGE.Type.Information )
|
"Player '" .. PlayerName .. "' receives an extra " .. Score .. " points! " .. "Total: " .. Player.Score - Player.Penalty,
|
||||||
:ToAllIf( self:IfMessagesZone() and self:IfMessagesToAll() )
|
MESSAGE.Type.Information )
|
||||||
:ToCoalitionIf( InitCoalition, self:IfMessagesZone() and self:IfMessagesToCoalition() )
|
:ToAllIf( self:IfMessagesZone() and self:IfMessagesToAll() )
|
||||||
|
:ToCoalitionIf( InitCoalition, self:IfMessagesZone() and self:IfMessagesToCoalition() )
|
||||||
self:ScoreCSV( PlayerName, "", "DESTROY_SCORE", 1, Score, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, "", "Scenery", TargetUnitType )
|
|
||||||
Destroyed = true
|
self:ScoreCSV( PlayerName, "", "DESTROY_SCORE", 1, Score, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, "", "Scenery", TargetUnitType )
|
||||||
|
Destroyed = true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1927,9 +2018,12 @@ end
|
|||||||
--- Report all players score
|
--- Report all players score
|
||||||
-- @param #SCORING self
|
-- @param #SCORING self
|
||||||
-- @param Wrapper.Group#GROUP PlayerGroup The player group.
|
-- @param Wrapper.Group#GROUP PlayerGroup The player group.
|
||||||
function SCORING:ReportScoreAllSummary( PlayerGroup )
|
-- @param #boolean JustScore If this is true, return just a table with playernames and overall scores.
|
||||||
|
-- @return #table ReportTable Table returned if JustScore is true.
|
||||||
|
function SCORING:ReportScoreAllSummary( PlayerGroup, JustScore )
|
||||||
|
|
||||||
local PlayerMessage = ""
|
local PlayerMessage = ""
|
||||||
|
local ReportTable = {}
|
||||||
|
|
||||||
self:T( { "Summary Score Report of All Players", Players = self.Players } )
|
self:T( { "Summary Score Report of All Players", Players = self.Players } )
|
||||||
|
|
||||||
@@ -1961,20 +2055,28 @@ function SCORING:ReportScoreAllSummary( PlayerGroup )
|
|||||||
|
|
||||||
local PlayerScore = ScoreHits + ScoreDestroys + ScoreCoalitionChanges + ScoreGoals + ScoreMissions
|
local PlayerScore = ScoreHits + ScoreDestroys + ScoreCoalitionChanges + ScoreGoals + ScoreMissions
|
||||||
local PlayerPenalty = PenaltyHits + PenaltyDestroys + PenaltyCoalitionChanges + PenaltyGoals + PenaltyMissions
|
local PlayerPenalty = PenaltyHits + PenaltyDestroys + PenaltyCoalitionChanges + PenaltyGoals + PenaltyMissions
|
||||||
|
|
||||||
PlayerMessage =
|
if JustScore~=true then
|
||||||
string.format( "Player '%s' Score = %d ( %d Score, -%d Penalties )",
|
PlayerMessage =
|
||||||
PlayerName,
|
string.format( "Player '%s' Score = %d ( %d Score, -%d Penalties )",
|
||||||
PlayerScore - PlayerPenalty,
|
PlayerName,
|
||||||
PlayerScore,
|
PlayerScore - PlayerPenalty,
|
||||||
PlayerPenalty
|
PlayerScore,
|
||||||
)
|
PlayerPenalty
|
||||||
MESSAGE:NewType( PlayerMessage, MESSAGE.Type.Overview ):ToGroup( PlayerGroup )
|
)
|
||||||
|
MESSAGE:NewType( PlayerMessage, MESSAGE.Type.Overview ):ToGroup( PlayerGroup )
|
||||||
|
else
|
||||||
|
ReportTable[PlayerName] = {["Score"]=PlayerScore,["Penalty"]=PlayerPenalty}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return ReportTable
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Opens a score CSV file to log the scores.
|
||||||
|
-- @param #SCORING self
|
||||||
|
-- @param #number sSeconds
|
||||||
|
-- @return #string ClockString
|
||||||
function SCORING:SecondsToClock( sSeconds )
|
function SCORING:SecondsToClock( sSeconds )
|
||||||
local nSeconds = sSeconds
|
local nSeconds = sSeconds
|
||||||
if nSeconds == 0 then
|
if nSeconds == 0 then
|
||||||
@@ -2102,6 +2204,19 @@ function SCORING:ScoreCSV( PlayerName, TargetPlayerName, ScoreType, ScoreTimes,
|
|||||||
|
|
||||||
self.CSVFile:write( "\n" )
|
self.CSVFile:write( "\n" )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if lfs and io and self.LoadSave == true then
|
||||||
|
local path = self.AutoSavePath or lfs.writedir() .. [[Logs\]]
|
||||||
|
local filename = self.GameName or "PlayerScoresSummary"
|
||||||
|
filename = filename..".csv"
|
||||||
|
local data = self:ReportScoreAllSummary("",true)
|
||||||
|
local text = "-- Playername;;Score;;Penalty\n"
|
||||||
|
for _playername,_data in pairs(data or {}) do
|
||||||
|
text = text..string.format("%s;;%d;;%d\n")
|
||||||
|
end
|
||||||
|
UTILS.SaveToFile(path,filename,text)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Close CSV file
|
--- Close CSV file
|
||||||
|
|||||||
Reference in New Issue
Block a user