231 lines
8.3 KiB
Lua
231 lines
8.3 KiB
Lua
local events = {
|
|
-- Custom event fired to request all name lists register themselves
|
|
on_list_rebuild = script.generate_event_name()
|
|
}
|
|
|
|
local MOD_SETTINGS = {
|
|
["namelists-backer-roboports"] = true,
|
|
["namelists-backer-labs"] = true,
|
|
["namelists-backer-stations"] = true,
|
|
["namelists-backer-locomotives"] = true,
|
|
["namelists-backer-radars"] = true,
|
|
["namelists-backer-default"] = true
|
|
}
|
|
|
|
function rebuild_lists()
|
|
global.names = {}
|
|
global.types = {}
|
|
global.defaults = {weight = 0, lists = {}}
|
|
if settings.global["namelists-backer-roboports"].value then
|
|
register_list({interface = "base", func = "backer_name", category = "type", target = "roboport", weight = #game.backer_names, backer = true})
|
|
end
|
|
if settings.global["namelists-backer-labs"].value then
|
|
register_list({interface = "base", func = "backer_name", category = "type", target = "lab", weight = #game.backer_names, backer = true})
|
|
end
|
|
if settings.global["namelists-backer-stations"].value then
|
|
register_list({interface = "base", func = "backer_name", category = "type", target = "train-stop", weight = #game.backer_names, backer = true})
|
|
end
|
|
if settings.global["namelists-backer-locomotives"].value then
|
|
register_list({interface = "base", func = "backer_name", category = "type", target = "locomotive", weight = #game.backer_names, backer = true})
|
|
end
|
|
if settings.global["namelists-backer-radars"].value then
|
|
register_list({interface = "base", func = "backer_name", category = "type", target = "radar", weight = #game.backer_names, backer = true})
|
|
end
|
|
if settings.global["namelists-backer-default"].value then
|
|
register_list({interface = "base", func = "backer_name", weight = #game.backer_names, backer = true})
|
|
end
|
|
script.raise_event(events.on_list_rebuild, {})
|
|
log("Interface lists rebuilt")
|
|
end
|
|
|
|
script.on_init(rebuild_lists)
|
|
script.on_configuration_changed(rebuild_lists)
|
|
|
|
script.on_event(defines.events.on_runtime_mod_setting_changed, function(event)
|
|
if MOD_SETTINGS[event.setting] then
|
|
rebuild_lists()
|
|
end
|
|
end)
|
|
|
|
-- Registers a name list for the specified name/type
|
|
-- If name or type isn't specified, register as generic
|
|
-- parameters is a table of {interface = "", func = "", category = "", target = "", weight = ""}
|
|
function register_list(parameters)
|
|
global.names = global.names or {}
|
|
global.types = global.types or {}
|
|
if not (parameters.interface and parameters.func and parameters.weight) then
|
|
log("Error registering: missing parameters")
|
|
return
|
|
end
|
|
if parameters.category and not parameters.target then
|
|
log("Error registering: category specified but no target")
|
|
return
|
|
end
|
|
local id = parameters.interface .. "." .. parameters.func
|
|
if parameters.category == "name" then
|
|
global.names[parameters.target] = global.names[parameters.target] or {weight = 0, lists = {}}
|
|
if not global.names[parameters.target].lists[id] then
|
|
log("Registering interface " .. id .. " for name " .. parameters.target)
|
|
global.names[parameters.target].lists[id] =
|
|
{
|
|
interface = parameters.interface,
|
|
func = parameters.func,
|
|
weight = parameters.weight,
|
|
backer = parameters.backer
|
|
}
|
|
global.names[parameters.target].weight = global.names[parameters.target].weight + parameters.weight
|
|
else
|
|
log("Eror registering interface " .. id .. ": already registered for name " .. parameters.target)
|
|
end
|
|
elseif parameters.category == "type" then
|
|
global.types[parameters.target] = global.types[parameters.target] or {weight = 0, lists = {}}
|
|
if not global.types[parameters.target].lists[id] then
|
|
log("Registering interface " .. id .. " for type " .. parameters.target)
|
|
global.types[parameters.target].lists[id] =
|
|
{
|
|
interface = parameters.interface,
|
|
func = parameters.func,
|
|
weight = parameters.weight,
|
|
backer = parameters.backer
|
|
}
|
|
global.types[parameters.target].weight = global.types[parameters.target].weight + parameters.weight
|
|
else
|
|
log("Eror registering interface " .. id .. ": already registered for type " .. parameters.target)
|
|
end
|
|
else
|
|
if not global.defaults.lists[id] then
|
|
log("Registering interface " .. id .. " as a default")
|
|
global.defaults.lists[id] =
|
|
{
|
|
interface = parameters.interface,
|
|
func = parameters.func,
|
|
weight = parameters.weight,
|
|
backer = parameters.backer
|
|
}
|
|
global.defaults.weight = global.defaults.weight + parameters.weight
|
|
else
|
|
log("Eror registering interface " .. id .. ": already registered as default")
|
|
end
|
|
end
|
|
end
|
|
|
|
-- remove list with id from category, because we've tried to use it and it wasn't there
|
|
function remove_list(category, id)
|
|
category.lists[id] = nil
|
|
category.weight = 0
|
|
for i,list in pairs(category.lists) do
|
|
category.weight = category.weight + list.weight
|
|
end
|
|
end
|
|
|
|
-- Keybind
|
|
script.on_event("random-name", function(event)
|
|
local selection = game.players[event.player_index].selected
|
|
if selection and selection.valid and
|
|
selection.supports_backer_name() then
|
|
selection.backer_name = pick_name(selection)
|
|
end
|
|
end)
|
|
|
|
-- Entity built
|
|
-- We don't catch the robot_built event because the ghost will already have a name chosen
|
|
-- in the player event
|
|
script.on_event(defines.events.on_built_entity, function(event)
|
|
if event.created_entity.supports_backer_name() then
|
|
auto_name(event.created_entity)
|
|
end
|
|
end)
|
|
|
|
-- Pick a name unless this is a station built without a ghost
|
|
-- Don't pick a name for hand-built stations, in case they were built over a ghost
|
|
function auto_name(entity)
|
|
if entity.type == "entity-ghost" then
|
|
if entity.backer_name == "" then
|
|
entity.backer_name = pick_name(entity)
|
|
end
|
|
elseif entity.type ~= "train-stop" then
|
|
entity.backer_name = pick_name(entity)
|
|
end
|
|
end
|
|
|
|
-- Get a pick a name list at random from the given category using the weighting
|
|
-- Request a name from that list
|
|
-- If a list is broken, deregister is and try again
|
|
function get_weighted_name(category, entity)
|
|
::roll::
|
|
if category.weight > 0 then
|
|
local dice_roll = math.random(category.weight) - 1
|
|
for id,list in pairs(category.lists) do
|
|
dice_roll = dice_roll - list.weight
|
|
if dice_roll < 0 then
|
|
if list.backer then
|
|
return game.backer_names[math.random(#game.backer_names)]
|
|
elseif remote.interfaces[list.interface] and remote.interfaces[list.interface][list.func] then
|
|
return remote.call(list.interface, list.func, entity)
|
|
else
|
|
-- if this list has stopped working, remove it and try again
|
|
log("Removing non-functioning interface " .. id)
|
|
remove_list(category, id)
|
|
goto roll
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Make a call to a registered list, preferably by name but otherwise by type
|
|
-- Picks a generic name if no more specific list is available, falls back to a backer name
|
|
function pick_name(entity)
|
|
if not (entity and entity.valid) then
|
|
-- ABORT
|
|
return
|
|
end
|
|
local ent_name = entity.name
|
|
local ent_type = entity.type
|
|
-- is this a ghost? get the inner type
|
|
if entity.type == "entity-ghost" then
|
|
ent_name = entity.ghost_name
|
|
ent_type = entity.ghost_type
|
|
end
|
|
local new_name = nil
|
|
-- try to get a name based on entity name
|
|
if global.names[ent_name] and global.names[ent_name].weight > 0 then
|
|
new_name = get_weighted_name(global.names[ent_name], entity)
|
|
if new_name then
|
|
return new_name
|
|
end
|
|
end
|
|
-- try to get a name based on entity type
|
|
if global.types[ent_type] and global.types[ent_type].weight > 0 then
|
|
new_name = get_weighted_name(global.types[ent_type], entity)
|
|
if new_name then
|
|
return new_name
|
|
end
|
|
end
|
|
-- try to get a name from a default list
|
|
if global.defaults and global.defaults.weight > 0 then
|
|
new_name = get_weighted_name(global.defaults, entity)
|
|
if new_name then
|
|
return new_name
|
|
end
|
|
end
|
|
-- fallback: return a built-in backer name
|
|
return game.backer_names[math.random(#game.backer_names)]
|
|
end
|
|
|
|
-- Does a list exist for this entity, either by name or by type?
|
|
-- Deprecated, Namelists now always returns a name if the entity is valid
|
|
function has_name_list(entity)
|
|
return true
|
|
end
|
|
|
|
-- Add interfaces
|
|
remote.add_interface("Namelists", {
|
|
pick_name = pick_name,
|
|
has_list = has_name_list,
|
|
rebuild = rebuild_lists,
|
|
register = register_list,
|
|
get_events = function()
|
|
return events
|
|
end
|
|
}) |