Files
bbassieandClaude Opus 5.5 a6c453a88e Add a community_details feature for the community name and links
The community name, Discord, website, status, GitHub, and Patreon links
lived in exp_legacy/config/server_detail.lua, so changing them meant
editing the scenario. They are now the community_details feature and can
be edited from the Scenario Features page.

Chat auto reply, help bubbles, and the readme read the live config
instead of copying the values when the file loads, so an edit shows up
without a restart. Help bubbles store the location name in their task
and build the messages each cycle; the readme tab tooltip can be a
function which is called when the readme opens.

Every feature gets an enabled switch from the framework. There is no
sensible meaning for a disabled community name, so the values are
always used and the feature description says the switch does nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:10:22 +00:00

146 lines
7.1 KiB
Lua

--- This file defines the different triggers for the chat bot
-- @config Chat-Auto-Reply
local ExpUtil = require("modules/exp_util")
local Feature = require("modules/exp_scenario/features")
local Async = require("modules/exp_util/async")
local community_details = require("modules/exp_scenario/config/community_details").config
local floor = math.floor
local random = math.random
local format_string = string.format
local locale_reply = "exp_chat-auto-reply.chat-reply"
local send_message_async =
Async.register(function(player, message)
if player == nil then
game.print(message)
else
player.print(message)
end
end)
--- Reply with a link from community_details, read when the reply is sent
--- @param key string
--- @return fun(): LocalisedString
local function server_link(key)
return function()
return { "info." .. key, community_details[key] }
end
end
local afk_time_units = {
minutes = true,
seconds = true,
}
return Feature.register("chat_auto_reply", {
--- @type table<string, LocalisedString | fun(player: LuaPlayer, is_command: boolean): LocalisedString>
messages = { -- will trigger when ever the word is said
["discord"] = server_link("discord"),
["expgaming"] = server_link("website"),
["website"] = server_link("website"),
["status"] = server_link("status"),
["github"] = server_link("github"),
["patreon"] = server_link("patreon"),
["donate"] = server_link("patreon"),
["command"] = { "info.custom-commands" },
["commands"] = { "info.custom-commands" },
["softmod"] = { "info.softmod" },
["plugin"] = { "info.softmod" },
["script"] = { "info.softmod" },
["redmew"] = { "info.redmew" },
["comfy"] = { "info.redmew" },
["rhd"] = { "info.lhd" },
["lhd"] = { "info.lhd" },
["loop"] = { "exp_chat-auto-reply.reply-loops" },
["roundabout"] = { "exp_chat-auto-reply.reply-loops" },
["roundabouts"] = { "exp_chat-auto-reply.reply-loops" },
["clusterio"] = { "exp_chat-auto-reply.reply-clusterio" },
["players"] = function()
return { "exp_chat-auto-reply.reply-players", #game.players }
end,
["online"] = function()
return { "exp_chat-auto-reply.reply-online", #game.connected_players }
end,
["afk"] = function(player)
local max = player
for _, next_player in pairs(game.connected_players) do
if max.afk_time < next_player.afk_time then
max = next_player
end
end
return { "exp_chat-auto-reply.reply-afk", max.name, ExpUtil.format_time_locale(max.afk_time, "long", afk_time_units) }
end,
},
allow_command_prefix_for_messages = true, -- when true any message trigger will print to all player when prefixed
command_prefix = "!", -- prefix used for commands below and to print to all players (if enabled above)
--- @type table<string, LocalisedString | fun(player: LuaPlayer, is_command: boolean): LocalisedString>
commands = { -- will trigger only when command prefix is given
["dev"] = { "exp_chat-auto-reply.reply-dev" },
["magic"] = { "exp_chat-auto-reply.reply-magic" },
["aids"] = { "exp_chat-auto-reply.reply-aids" },
["riot"] = { "exp_chat-auto-reply.reply-riot" },
["lenny"] = { "exp_chat-auto-reply.reply-lenny" },
["blame"] = function(player)
local names = { "Cooldude2606", "arty714", "badgamernl", "mark9064", "aldldl", "Drahc_pro", player.name }
for _, next_player in pairs(game.connected_players) do
names[#names + 1] = next_player.name
end
return { "exp_chat-auto-reply.reply-blame", table.get_random(names) }
end,
["hodor"] = function()
local options = { "?", ".", "!", "!!!" }
return { "exp_chat-auto-reply.reply-hodor", table.get_random(options) }
end,
["evolution"] = function(player)
return { "exp_chat-auto-reply.reply-evolution", format_string("%.2f", game.forces["enemy"].get_evolution_factor(player.surface)) }
end,
["makepopcorn"] = function(player)
local timeout = floor(180 * (random() + 0.5))
send_message_async:start_after(timeout, nil, { locale_reply, { "exp_chat-auto-reply.reply-popcorn-2", player.name } })
return { locale_reply, { "exp_chat-auto-reply.reply-popcorn-1" } }
end,
["passsomesnaps"] = function(player)
local timeout = floor(180 * (random() + 0.5))
send_message_async:start_after(timeout, nil, { locale_reply, { "exp_chat-auto-reply.reply-snaps-2", player.name } })
send_message_async:start_after(timeout * (random() + 0.5), nil, { locale_reply, { "exp_chat-auto-reply.reply-snaps-3", player.name } })
return { locale_reply, { "exp_chat-auto-reply.reply-snaps-1" } }
end,
["makecocktail"] = function(player)
local timeout = floor(180 * (random() + 0.5))
send_message_async:start_after(timeout, nil, { locale_reply, { "exp_chat-auto-reply.reply-cocktail-2", player.name } })
send_message_async:start_after(timeout * (random() + 0.5), nil, { locale_reply, { "exp_chat-auto-reply.reply-cocktail-3", player.name } })
return { locale_reply, { "exp_chat-auto-reply.reply-cocktail-1" } }
end,
["makecoffee"] = function(player)
local timeout = floor(180 * (random() + 0.5))
send_message_async:start_after(timeout, nil, { locale_reply, { "exp_chat-auto-reply.reply-coffee-2", player.name } })
return { locale_reply, { "exp_chat-auto-reply.reply-coffee-1" } }
end,
["orderpizza"] = function(player)
local timeout = floor(180 * (random() + 0.5))
send_message_async:start_after(timeout, nil, { locale_reply, { "exp_chat-auto-reply.reply-pizza-2", player.name } })
send_message_async:start_after(timeout * (random() + 0.5), nil, { locale_reply, { "exp_chat-auto-reply.reply-pizza-3", player.name } })
return { locale_reply, { "exp_chat-auto-reply.reply-pizza-1" } }
end,
["maketea"] = function(player)
local timeout = floor(180 * (random() + 0.5))
send_message_async:start_after(timeout, nil, { locale_reply, { "exp_chat-auto-reply.reply-tea-2", player.name } })
return { locale_reply, { "exp_chat-auto-reply.reply-tea-1" } }
end,
["meadplease"] = function(player)
local timeout = floor(180 * (random() + 0.5))
send_message_async:start_after(timeout, nil, { locale_reply, { "exp_chat-auto-reply.reply-mead-2", player.name } })
return { locale_reply, { "exp_chat-auto-reply.reply-mead-1" } }
end,
["passabeer"] = function(player)
local timeout = floor(180 * (random() + 0.5))
send_message_async:start_after(timeout, nil, { locale_reply, { "exp_chat-auto-reply.reply-beer-2", player.name } })
return { locale_reply, { "exp_chat-auto-reply.reply-beer-1" } }
end,
},
})