Files
factorio-expcluster/exp_scenario/module/control/help_bubbles.lua
T
Bastiaan 757a36fc03 Merge pull request #486 from bbassie/feature/convert-configs
Convert the remaining scenario configs into features
2026-10-05 00:33:36 +01:00

128 lines
4.0 KiB
Lua

--[[-- Control - Help Bubbles
Adds friendly biters that walk around and give helpful messages
]]
local Async = require("modules/exp_util/async")
local Storage = require("modules/exp_util/storage")
local Feature = require("modules/exp_scenario/features")
local config_server_detail = require("modules.exp_legacy.config.server_detail")
local feature = Feature.register("help_bubbles")
--- Ticks between message changes
local message_cycle = 60 * 15
local locations = {
["Spawn"] = {
spawn_position = { x = 0, y = 0 },
spawn_surface = "nauvis",
entity_name = "small-biter",
messages = {
{ "info.website", config_server_detail["website"] },
{ "info.read-readme" },
{ "info.discord", config_server_detail["discord"] },
{ "info.softmod" },
{ "info.redmew" },
{ "info.custom-commands" },
{ "info.status", config_server_detail["status"] },
{ "info.lhd" },
{ "info.github", config_server_detail["github"] },
{ "info.patreon", config_server_detail["patreon"] },
},
}
}
--- @type table<string, Async.AsyncReturn<any>>
local persistent_locations = {}
Storage.register(persistent_locations, function(tbl)
persistent_locations = tbl
end)
--- @class speech_bubble_task_param
--- @field entity LuaEntity
--- @field messages LocalisedString[]
--- @field previous_message LuaEntity?
--- @field current_message_index number
--- Used by create_entity within speech_bubble_async
local speech_bubble_param = {
name = "compi-speech-bubble",
position = { 0, 0 },
}
--- Cycle between a set category of messages above an entity
local speech_bubble_task =
Async.register(function(task)
--- @cast task speech_bubble_task_param
local entity = task.entity
if not entity.valid then
return Async.status.complete()
end
local index = task.current_message_index
if index > #task.messages then
index = 1
end
local previous_message = task.previous_message
if previous_message and previous_message.valid then
previous_message.destroy()
end
speech_bubble_param.source = entity
speech_bubble_param.text = task.messages[index]
task.previous_message = entity.surface.create_entity(speech_bubble_param)
task.current_message_index = index + 1
return Async.status.delay(message_cycle, task)
end)
--- Register an entity to start spawning speech bubbles
--- @param entity LuaEntity the entity which will have messages spawn from it
--- @param messages LocalisedString[] the messages which should be shown
--- @param starting_index number? the message index to start at, default 1
--- @return Async.AsyncReturn<any>
local function register_entity(entity, messages, starting_index)
return speech_bubble_task{
entity = entity,
messages = messages,
current_message_index = starting_index or 1,
}
end
--- Check all persistent locations from the config are active
local function check_persistent_locations()
for name, location in pairs(locations) do
local task = persistent_locations[name]
if task and not task.completed then
goto continue
end
local surface = game.get_surface(location.spawn_surface)
if not surface then
goto continue
end
local position = surface.find_non_colliding_position(location.entity_name, location.spawn_position, 1.5, 0.5)
if not position then
goto continue
end
local entity = surface.create_entity{ name = location.entity_name, position = position, force = game.forces.neutral }
if not entity then
goto continue
end
persistent_locations[name] = register_entity(entity, location.messages)
::continue::
end
end
return feature:guard{
on_nth_tick = {
[message_cycle] = check_persistent_locations,
},
register_entity = register_entity,
}