1
0
mirror of https://github.com/Refactorio/RedMew.git synced 2024-12-14 10:13:13 +02:00
RedMew/utils/score_tracker.lua

157 lines
4.2 KiB
Lua

local Global = require 'utils.global'
local Event = require 'utils.event'
local error = error
local format = string.format
local raise_event = script.raise_event
local score_metadata = {}
local memory = {
players = {},
global = {}
}
Global.register(memory, function (tbl) memory = tbl end)
local Public = {}
Public.events = {
-- Event {
-- score_name = score_name
-- old_value = old_value
-- new_value = new_value
-- player_index = player_index
-- value_changed = value_changed
-- }
on_player_score_changed = Event.generate_event_name('on_player_score_changed'),
-- Event {
-- score_name = score_name
-- old_value = old_value
-- new_value = new_value
-- value_changed = value_changed
-- }
on_global_score_changed = Event.generate_event_name('on_global_score_changed'),
}
---Register a specific score.
---
--- This function must be called in the control stage, i.e. not inside an event.
---
---@param name string
---@param localisation_string table
---@param icon string
function Public.register(name, localisation_string, icon)
if _LIFECYCLE ~= _STAGE.control then
error(format('You can only register score types in the control stage, i.e. not inside events. Tried setting "%s".', name), 2)
end
if score_metadata[name] then
error(format('Trying to register score type for "%s" while it has already been registered.', name), 2)
end
local score = {
name = name,
icon = icon,
localised_string = localisation_string
}
score_metadata[name] = score
return score
end
---Sets a setting to a specific value for a player.
---
---@param player_index number
---@param score_name string
---@param value number|nil number to subtract or add
function Public.change_for_player(player_index, score_name, value)
local setting = score_metadata[score_name]
if not setting then
if _DEBUG then
error(format('Trying to change score "%s" while it has was never registered.', score_name), 2)
end
return
end
local player_score = memory.players[player_index]
if not player_score then
player_score = {}
memory.players[player_index] = player_score
end
local old_value = player_score[score_name] or 0
local new_value = old_value + value
player_score[score_name] = new_value
raise_event(Public.events.on_player_score_changed, {
score_name = score_name,
old_value = old_value,
new_value = new_value,
player_index = player_index,
value_changed = old_value ~= new_value
})
end
---Sets a setting to a specific value for a player.
---
---@param score_name string
---@param value number|nil number to subtract or add
function Public.change_for_global(score_name, value)
local setting = score_metadata[score_name]
if not setting then
if _DEBUG then
error(format('Trying to change score "%s" while it has was never registered.', score_name), 2)
end
return
end
local old_value = memory.global[score_name] or 0
local new_value = old_value + value
memory.global[score_name] = new_value
raise_event(Public.events.on_global_score_changed, {
score_name = score_name,
old_value = old_value,
new_value = new_value,
value_changed = old_value ~= new_value
})
end
---Returns the value for this player of a specific score.
---
---@param player_index number
---@param score_name string
function Public.get_for_player(player_index, score_name)
local setting = score_metadata[score_name]
if not setting then
return nil
end
local player_scores = memory.players[player_index]
if not player_scores then
return 0
end
return player_scores[score_name] or 0
end
---Returns the value of the game score.
---
---@param score_name string
function Public.get_for_global(score_name)
local setting = score_metadata[score_name]
if not setting then
return 0
end
return memory.global[score_name] or 0
end
---Returns the full score metadata, note that this is a reference, do not modify
---this data unless you know what you're doing!
function Public.get_score_metadata()
return score_metadata
end
return Public