160 lines
6.9 KiB
Lua
160 lines
6.9 KiB
Lua
local core_util = require("__core__/lualib/util.lua")
|
|
local misc = require("__flib__.misc")
|
|
require("scripts.gui")
|
|
require("scripts.milestones_util")
|
|
|
|
local function force_print(force, message)
|
|
for _, player in pairs(force.players) do
|
|
if not settings.get_player_settings(player)["milestones_disable_chat_notifications"].value then
|
|
player.print(message)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function raise_milestone_reached_event(force, milestone, message)
|
|
if On_milestone_reached_event then
|
|
script.raise_event(On_milestone_reached_event, {
|
|
force = force,
|
|
name = milestone.name,
|
|
quantity = milestone.quantity,
|
|
completion_tick = milestone.completion_tick,
|
|
message = message
|
|
})
|
|
end
|
|
end
|
|
|
|
-- Writes to a file named "milestones-<MAP SEED>.txt"
|
|
-- Each milestone reached appends a new line.
|
|
-- Each line is JSON and looks like this:
|
|
-- {"force":"player","name":"iron-ore","quantity":10,"type"="item","completion_tick":5279,"completion_time":"1:27"}
|
|
local function write_milestone_to_file(force, milestone, human_timestamp)
|
|
local file_name = string.format("milestones-%s.txt", game.default_map_gen_settings.seed)
|
|
local table = {
|
|
force = force.name,
|
|
name = milestone.name,
|
|
quantity = milestone.quantity,
|
|
type = milestone.type,
|
|
completion_tick = milestone.completion_tick,
|
|
completion_time = human_timestamp,
|
|
}
|
|
local json = game.table_to_json(table) .. "\n"
|
|
for player_index, player in pairs(force.players) do
|
|
if settings.get_player_settings(player)["milestones_write_file"].value then
|
|
game.write_file(file_name, json, true, player_index)
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
local function print_milestone_reached(force, milestone)
|
|
local human_timestamp = misc.ticks_to_timestring(milestone.completion_tick)
|
|
local sprite_name = sprite_prefix(milestone) .. "." .. milestone.name
|
|
local milestone_localised_name
|
|
local message
|
|
if milestone.type == "technology" then
|
|
milestone_localised_name = game.technology_prototypes[milestone.name].localised_name
|
|
local level_string = (milestone.quantity == 1 and "" or " Level "..milestone.quantity.." ")
|
|
message = {"milestones.message_milestone_reached_technology", sprite_name, milestone_localised_name, level_string, human_timestamp}
|
|
else
|
|
if milestone.type == "item" or milestone.type == "item_consumption" then
|
|
if milestone.name == "se-rocket-launch-pad-silo-dummy-result-item" then
|
|
milestone_localised_name = "Cargo rocket"
|
|
else
|
|
milestone_localised_name = game.item_prototypes[milestone.name].localised_name
|
|
end
|
|
elseif milestone.type == "fluid" or milestone.type == "fluid_consumption" then
|
|
milestone_localised_name = game.fluid_prototypes[milestone.name].localised_name
|
|
elseif milestone.type == "kill" then
|
|
milestone_localised_name = game.entity_prototypes[milestone.name].localised_name
|
|
else
|
|
error("Invalid milestone type! " .. milestone.type)
|
|
end
|
|
|
|
local message_type
|
|
if milestone.type == "kill" then
|
|
message_type = "kill"
|
|
elseif milestone.type == "item_consumption" or milestone.type == "fluid_consumption" then
|
|
message_type = "consumption"
|
|
else
|
|
message_type = "item"
|
|
end
|
|
|
|
local postscript
|
|
if milestone.name == "character" then
|
|
postscript = " (haha! 😁)"
|
|
end
|
|
|
|
if milestone.quantity == 1 then
|
|
message = {"", {"milestones.message_milestone_reached_" ..message_type.. "_first", sprite_name, milestone_localised_name, human_timestamp}, postscript}
|
|
else
|
|
local print_quantity = milestone.quantity
|
|
if milestone.quantity >= 10000 then
|
|
print_quantity = core_util.format_number(milestone.quantity, true)
|
|
end
|
|
message = {"", {"milestones.message_milestone_reached_" ..message_type.. "_more", print_quantity, sprite_name, milestone_localised_name, human_timestamp}, postscript}
|
|
end
|
|
end
|
|
|
|
force_print(force, message)
|
|
raise_milestone_reached_event(force, milestone, message)
|
|
write_milestone_to_file(force, milestone, human_timestamp)
|
|
force.play_sound{path="utility/achievement_unlocked"}
|
|
end
|
|
|
|
function track_item_creation(event)
|
|
for force_name, global_force in pairs(global.forces) do
|
|
local milestones_per_tick = #global_force.incomplete_milestones / global.milestones_check_frequency_setting
|
|
local step_nb = event.tick % global.milestones_check_frequency_setting
|
|
local i = math.floor(milestones_per_tick * step_nb) + 1
|
|
local to_i = math.floor(milestones_per_tick * (step_nb + 1))
|
|
-- log("(per tick: "..milestones_per_tick..") tick " .. event.tick .. " : " .. i .. "-" .. to_i)
|
|
|
|
while i <= to_i do
|
|
local milestone = global_force.incomplete_milestones[i]
|
|
if milestone.type ~= "technology"
|
|
and is_production_milestone_reached(milestone, global_force) then
|
|
if milestone.next then
|
|
local next_milestone = create_next_milestone(force_name, milestone)
|
|
if next_milestone then
|
|
table.insert(global_force.incomplete_milestones, next_milestone)
|
|
table.insert(global_force.milestones_by_group[next_milestone.group], next_milestone)
|
|
end
|
|
end
|
|
local force = game.forces[force_name]
|
|
mark_milestone_reached(global_force, milestone, game.tick, i)
|
|
print_milestone_reached(force, milestone)
|
|
refresh_gui_for_force(force)
|
|
to_i = math.min(to_i, #global_force.incomplete_milestones) -- Don't go past the end of the table
|
|
else
|
|
-- When a milestone is reached, incomplete_milestones loses an element
|
|
-- so we only increment when a milestone is not reached
|
|
i = i + 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
script.on_event(defines.events.on_tick, track_item_creation)
|
|
|
|
function check_technology_milestone_reached(event)
|
|
local technology_researched = event.research
|
|
local force = event.research.force
|
|
local global_force = global.forces[force.name]
|
|
if global_force == nil then return end
|
|
|
|
local i = 1
|
|
while i <= #global_force.incomplete_milestones do
|
|
local milestone = global_force.incomplete_milestones[i]
|
|
if is_tech_milestone_reached(milestone, technology_researched) then
|
|
mark_milestone_reached(global_force, milestone, game.tick, i)
|
|
print_milestone_reached(force, milestone)
|
|
refresh_gui_for_force(force)
|
|
else
|
|
-- I guess you could technically have the same technology in 2 milestones...
|
|
-- so we have to keep iterating
|
|
i = i + 1
|
|
end
|
|
end
|
|
end
|
|
script.on_event(defines.events.on_research_finished, check_technology_milestone_reached)
|
|
|