mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2025-12-27 03:25:23 +09:00
Move files to exp_legacy
This commit is contained in:
54
exp_legacy/module/modules/addons/advanced-start.lua
Normal file
54
exp_legacy/module/modules/addons/advanced-start.lua
Normal file
@@ -0,0 +1,54 @@
|
||||
--- Adds a better method of player starting items based on production levels.
|
||||
-- @addon Advanced-Start
|
||||
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
local config = require 'config.advanced_start' --- @dep config.advanced_start
|
||||
local items = config.items
|
||||
|
||||
Event.add(defines.events.on_player_created, function(event)
|
||||
local player = game.players[event.player_index]
|
||||
-- game init settings
|
||||
if event.player_index == 1 then
|
||||
player.force.friendly_fire = config.friendly_fire
|
||||
game.map_settings.enemy_expansion.enabled = config.enemy_expansion
|
||||
local r = config.chart_radius
|
||||
local p = player.position
|
||||
player.force.chart(player.surface, {{p.x-r, p.y-r}, {p.x+r, p.y+r}})
|
||||
end
|
||||
-- spawn items
|
||||
for item, callback in pairs(items) do
|
||||
if type(callback) == 'function' then
|
||||
local stats = player.force.item_production_statistics
|
||||
local made = stats.get_input_count(item)
|
||||
local success, count = pcall(callback, made, stats.get_input_count, player)
|
||||
count = math.floor(count)
|
||||
if success and count > 0 then
|
||||
player.insert{name=item, count=count}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if config.armor.enable then
|
||||
player.insert{name=config.armor.main, count=1}
|
||||
|
||||
for _, item in pairs(config.armor.item) do
|
||||
player.insert{name=item.equipment, count=item.count}
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
Event.on_init(function()
|
||||
remote.call('freeplay', 'set_created_items', {})
|
||||
remote.call('freeplay', 'set_chart_distance', 0)
|
||||
remote.call('freeplay', 'set_skip_intro', config.skip_intro)
|
||||
if config.research_queue_from_start then
|
||||
for _, force in pairs(game.forces) do
|
||||
force.research_queue_enabled = true
|
||||
end
|
||||
end
|
||||
if not config.disable_base_game_silo_script then
|
||||
if config.skip_victory then
|
||||
remote.call('silo_script', 'set_no_victory', true)
|
||||
end
|
||||
end
|
||||
end)
|
||||
66
exp_legacy/module/modules/addons/afk-kick.lua
Normal file
66
exp_legacy/module/modules/addons/afk-kick.lua
Normal file
@@ -0,0 +1,66 @@
|
||||
--- Kicks players when all players on the server are afk
|
||||
-- @addon afk-kick
|
||||
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
local Global = require 'utils.global' --- @dep utils.global
|
||||
local config = require 'config.afk_kick' --- @dep config.afk_kick
|
||||
local Async = require 'expcore.async' --- @dep expcore.async
|
||||
|
||||
--- Optional roles require
|
||||
local Roles
|
||||
if config.active_role then
|
||||
Roles = require 'expcore.roles'
|
||||
end
|
||||
|
||||
--- Globals
|
||||
local primitives = { last_active = 0 }
|
||||
Global.register(primitives, function(tbl)
|
||||
primitives = tbl
|
||||
end)
|
||||
|
||||
--- Kicks an afk player, used to add a delay so the gui has time to appear
|
||||
local kick_player =
|
||||
Async.register(function(player)
|
||||
if game.tick - primitives.last_active < config.kick_time then return end -- Safety Catch
|
||||
game.kick_player(player, 'AFK while no active players on the server')
|
||||
end)
|
||||
|
||||
--- Check for an active player every update_time number of ticks
|
||||
Event.on_nth_tick(config.update_time, function()
|
||||
-- Check for active players
|
||||
for _, player in ipairs(game.connected_players) do
|
||||
if player.afk_time < config.afk_time
|
||||
or config.admin_as_active and player.admin
|
||||
or config.trust_as_active and player.online_time > config.trust_time
|
||||
or config.active_role and (Roles.get_player_highest_role(player).index >= Roles.get_role_from_any(config.active_role).index) then
|
||||
-- Active player was found
|
||||
primitives.last_active = game.tick
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- No active player was found, check if players should be kicked
|
||||
if game.tick - primitives.last_active < config.kick_time then return end
|
||||
|
||||
-- Kick time exceeded, kick all players
|
||||
for _, player in ipairs(game.connected_players) do
|
||||
-- Add a frame to say why the player was kicked
|
||||
local res = player.display_resolution
|
||||
local uis = player.display_scale
|
||||
player.gui.screen.add{
|
||||
type = 'frame',
|
||||
name = 'afk-kick',
|
||||
caption = {'afk-kick.message'},
|
||||
}.location = { x=res.width*(0.5 - 0.11*uis), y=res.height*(0.5 - 0.14*uis) }
|
||||
|
||||
-- Kick the player, some delay needed because network delay
|
||||
Async.wait(10, kick_player, player)
|
||||
end
|
||||
end)
|
||||
|
||||
--- Remove the screen gui if it is present
|
||||
Event.add(defines.events.on_player_joined_game, function(event)
|
||||
local player = game.get_player(event.player_index)
|
||||
local frame = player.gui.screen["afk-kick"]
|
||||
if frame and frame.valid then frame.destroy() end
|
||||
end)
|
||||
38
exp_legacy/module/modules/addons/chat-popups.lua
Normal file
38
exp_legacy/module/modules/addons/chat-popups.lua
Normal file
@@ -0,0 +1,38 @@
|
||||
--- Creates flying text entities when a player sends a message in chat;
|
||||
-- also displays a ping above users who are named in the message
|
||||
-- @addon Chat-Popups
|
||||
|
||||
local Game = require 'utils.game' --- @dep utils.game
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
local config = require 'config.popup_messages' --- @dep config.popup_messages
|
||||
|
||||
local send_text = Game.print_player_floating_text -- (player_index, text, color)
|
||||
|
||||
Event.add(defines.events.on_console_chat, function(event)
|
||||
if not event.player_index or event.player_index < 1 then return end
|
||||
local player = game.players[event.player_index]
|
||||
|
||||
-- Some basic sanity checks
|
||||
if not player then return end
|
||||
if not event.message then return end
|
||||
|
||||
-- Sends the message as text above them
|
||||
if config.show_player_messages then
|
||||
send_text(player.index, {'chat-popup.message', player.name, event.message}, player.chat_color)
|
||||
end
|
||||
|
||||
if not config.show_player_mentions then return end
|
||||
|
||||
-- Makes lower and removes white space from the message
|
||||
local search_string = event.message:lower():gsub("%s+", "")
|
||||
|
||||
-- Loops over online players to see if they name is included
|
||||
for _, mentioned_player in pairs(game.connected_players) do
|
||||
if mentioned_player.index ~= player.index then
|
||||
if search_string:find(mentioned_player.name:lower(), 1, true) then
|
||||
send_text(mentioned_player.index, {'chat-popup.ping', player.name}, player.chat_color)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end)
|
||||
52
exp_legacy/module/modules/addons/chat-reply.lua
Normal file
52
exp_legacy/module/modules/addons/chat-reply.lua
Normal file
@@ -0,0 +1,52 @@
|
||||
--- Adds auto replies to chat messages; as well as chat commands
|
||||
-- @addon Chat-Reply
|
||||
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
local Roles = require 'expcore.roles' --- @dep expcore.roles
|
||||
local config = require 'config.chat_reply' --- @dep config.chat_reply
|
||||
|
||||
Event.add(defines.events.on_console_chat, function(event)
|
||||
local player_index = event.player_index
|
||||
if not player_index or player_index < 1 then return end
|
||||
local player = game.players[player_index]
|
||||
local message = event.message:lower():gsub("%s+", "")
|
||||
local allowed = true
|
||||
if config.command_admin_only and not player.admin then allowed = false end
|
||||
if config.command_permission and not Roles.player_allowed(player, config.command_permission) then allowed = false end
|
||||
|
||||
local prefix = config.command_prefix
|
||||
for key_word, reply in pairs(config.messages) do
|
||||
if message:find(key_word) then
|
||||
local is_command = message:find(prefix..key_word)
|
||||
if type(reply) == 'function' then
|
||||
reply = reply(player, is_command)
|
||||
end
|
||||
|
||||
if is_command and allowed then
|
||||
game.print{'chat-bot.reply', reply}
|
||||
elseif is_command then
|
||||
player.print{'chat-bot.disallow'}
|
||||
elseif not allowed then
|
||||
player.print{'chat-bot.reply', reply}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not allowed then return end
|
||||
|
||||
for key_word, reply in pairs(config.commands) do
|
||||
if message:find(prefix..key_word) then
|
||||
if type(reply) == 'function' then
|
||||
local msg = reply(player, true)
|
||||
|
||||
if reply then
|
||||
game.print{'chat-bot.reply', msg}
|
||||
end
|
||||
|
||||
else
|
||||
game.print{'chat-bot.reply', reply}
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end)
|
||||
106
exp_legacy/module/modules/addons/compilatron.lua
Normal file
106
exp_legacy/module/modules/addons/compilatron.lua
Normal file
@@ -0,0 +1,106 @@
|
||||
--- Adds a compilatron that walks around the spawn area; adapted from redmew code
|
||||
-- @addon Compilatron
|
||||
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
local Global = require 'utils.global' --- @dep utils.global
|
||||
local Task = require 'utils.task' --- @dep utils.task
|
||||
local Token = require 'utils.token' --- @dep utils.token
|
||||
local config = require 'config.compilatron' --- @dep config.compilatron
|
||||
local messages = config.messages
|
||||
local locations = config.locations
|
||||
|
||||
local Public = {
|
||||
compilatrons={},
|
||||
current_messages={}
|
||||
}
|
||||
|
||||
Global.register({
|
||||
compilatrons = Public.compilatrons,
|
||||
current_messages = Public.current_messages
|
||||
}, function(tbl)
|
||||
Public.compilatrons = tbl.compilatrons
|
||||
Public.current_messages = tbl.current_messages
|
||||
end)
|
||||
|
||||
--- This will re-create the speech bubble after it de-spawns called with set_timeout
|
||||
local callback =
|
||||
Token.register(
|
||||
function(data)
|
||||
local ent = data.ent
|
||||
local name = data.name
|
||||
local msg_number = data.msg_number
|
||||
local message =
|
||||
ent.surface.create_entity(
|
||||
{name = 'compi-speech-bubble', text = messages[name][msg_number], position = {0, 0}, source = ent}
|
||||
)
|
||||
Public.current_messages[name] = {message = message, msg_number = msg_number}
|
||||
end
|
||||
)
|
||||
|
||||
--- This will move the messages onto the next message in the loop
|
||||
local function circle_messages()
|
||||
for name, ent in pairs(Public.compilatrons) do
|
||||
if not ent.valid then
|
||||
Public.spawn_compilatron(game.players[1].surface, name)
|
||||
end
|
||||
local current_message = Public.current_messages[name]
|
||||
local msg_number
|
||||
local message
|
||||
if current_message ~= nil then
|
||||
message = current_message.message
|
||||
if message ~= nil then
|
||||
message.destroy()
|
||||
end
|
||||
msg_number = current_message.msg_number
|
||||
msg_number = (msg_number < #messages[name]) and msg_number + 1 or 1
|
||||
else
|
||||
msg_number = 1
|
||||
end
|
||||
-- this calls the callback above to re-spawn the message after some time
|
||||
Task.set_timeout_in_ticks(300, callback, {ent = ent, name = name, msg_number = msg_number})
|
||||
end
|
||||
end
|
||||
|
||||
Event.on_nth_tick(config.message_cycle, circle_messages)
|
||||
|
||||
--- This will add a compilatron to the global and start his message cycle
|
||||
-- @tparam LuaEntity entity the compilatron entity that moves around
|
||||
-- @tparam string name the name of the location that the compilatron is at
|
||||
function Public.add_compilatron(entity, name)
|
||||
if not entity and not entity.valid then
|
||||
return
|
||||
end
|
||||
|
||||
if name == nil then
|
||||
return
|
||||
end
|
||||
|
||||
Public.compilatrons[name] = entity
|
||||
local message =
|
||||
entity.surface.create_entity(
|
||||
{name = 'compi-speech-bubble', text = messages[name][1], position = {0, 0}, source = entity}
|
||||
)
|
||||
Public.current_messages[name] = {message = message, msg_number = 1}
|
||||
end
|
||||
|
||||
--- This spawns a new compilatron on a surface with the given location tag (not a position)
|
||||
-- @tparam LuaSurface surface the surface to spawn the compilatron on
|
||||
-- @tparam string location the location tag that is in the config file
|
||||
function Public.spawn_compilatron(surface, location)
|
||||
local position = locations[location]
|
||||
local pos = surface.find_non_colliding_position('compilatron', position, 1.5, 0.5)
|
||||
local compi = surface.create_entity {name='compilatron', position=pos, force=game.forces.neutral}
|
||||
Public.add_compilatron(compi, location)
|
||||
end
|
||||
|
||||
-- When the first player is created this will create all compilatrons that are resisted in the config
|
||||
Event.add(defines.events.on_player_created, function(event)
|
||||
if event.player_index ~= 1 then return end
|
||||
local player = game.players[event.player_index]
|
||||
|
||||
for location in pairs(locations) do
|
||||
Public.spawn_compilatron(player.surface, location)
|
||||
end
|
||||
end)
|
||||
|
||||
return Public
|
||||
42
exp_legacy/module/modules/addons/damage-popups.lua
Normal file
42
exp_legacy/module/modules/addons/damage-popups.lua
Normal file
@@ -0,0 +1,42 @@
|
||||
--- Displays the amount of dmg that is done by players to entities;
|
||||
-- also shows player health when a player is attacked
|
||||
-- @addon Damage-Popups
|
||||
|
||||
local Game = require 'utils.game' --- @dep utils.game
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
local config = require 'config.popup_messages' --- @dep config.popup_messages
|
||||
|
||||
Event.add(defines.events.on_entity_damaged, function(event)
|
||||
local entity = event.entity
|
||||
local cause = event.cause
|
||||
local damage = math.floor(event.original_damage_amount)
|
||||
local health = math.floor(entity.health)
|
||||
local health_percentage = entity.get_health_ratio()
|
||||
local text_colour = {r=1-health_percentage, g=health_percentage, b=0}
|
||||
|
||||
-- Gets the location of the text
|
||||
local size = entity.get_radius()
|
||||
if size < 1 then size = 1 end
|
||||
local r = (math.random()-0.5)*size*config.damage_location_variance
|
||||
local p = entity.position
|
||||
local position = {x=p.x+r, y=p.y-size}
|
||||
|
||||
-- Sets the message
|
||||
local message
|
||||
if entity.name == 'character' and config.show_player_health then
|
||||
message = {'damage-popup.player-health', health}
|
||||
elseif entity.name ~= 'character' and cause and cause.name == 'character' and config.show_player_damage then
|
||||
message = {'damage-popup.player-damage', damage}
|
||||
end
|
||||
|
||||
-- Outputs the message as floating text
|
||||
if message then
|
||||
Game.print_floating_text(
|
||||
entity.surface,
|
||||
position,
|
||||
message,
|
||||
text_colour
|
||||
)
|
||||
end
|
||||
|
||||
end)
|
||||
149
exp_legacy/module/modules/addons/death-logger.lua
Normal file
149
exp_legacy/module/modules/addons/death-logger.lua
Normal file
@@ -0,0 +1,149 @@
|
||||
--- Makes markers on the map where places have died and reclaims items if not recovered
|
||||
-- @addon Death-Logger
|
||||
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
local Global = require 'utils.global' --- @dep utils.global
|
||||
local config = require 'config.death_logger' --- @dep config.death_logger
|
||||
local format_time, move_items = _C.format_time, _C.move_items_stack --- @dep expcore.common
|
||||
|
||||
-- Max amount of ticks a corpse can be alive
|
||||
local corpse_lifetime = 60*60*15
|
||||
|
||||
local deaths = {
|
||||
archive={} -- deaths moved here after body is gone
|
||||
--{player_name='Cooldude2606', time_of_death='15H 15M', position={x=0, y=0}, corpse=LuaEntity, tag=LuaCustomChartTag}
|
||||
}
|
||||
Global.register(deaths, function(tbl)
|
||||
deaths = tbl
|
||||
end)
|
||||
|
||||
--- Creates a new death marker and saves it to the given death
|
||||
local function create_map_tag(death)
|
||||
local player = game.players[death.player_name]
|
||||
local message = player.name..' died'
|
||||
if config.include_time_of_death then
|
||||
local time = format_time(death.time_of_death, {hours=true, minutes=true, string=true})
|
||||
message = message..' at '..time
|
||||
end
|
||||
death.tag = player.force.add_chart_tag(player.surface, {
|
||||
position=death.position,
|
||||
icon=config.map_icon,
|
||||
text=message
|
||||
})
|
||||
end
|
||||
|
||||
--- Checks that all map tags are present and valid
|
||||
-- adds missing ones, deletes expired ones
|
||||
local function check_map_tags()
|
||||
for index, death in ipairs(deaths) do
|
||||
local map_tag = death.tag
|
||||
local corpse = death.corpse
|
||||
-- Check the corpse is valid
|
||||
if corpse and corpse.valid then
|
||||
-- Corpse is valid check the map tag
|
||||
if not map_tag or not map_tag.valid then
|
||||
-- Map tag is not valid make a new one
|
||||
create_map_tag(death)
|
||||
end
|
||||
else
|
||||
-- Corpse is not valid so remove the map tag
|
||||
if map_tag and map_tag.valid then
|
||||
map_tag.destroy()
|
||||
end
|
||||
-- Move the death to the archive
|
||||
death.corpse = nil
|
||||
death.tag = nil
|
||||
table.insert(deaths.archive, death)
|
||||
table.remove(deaths, index)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- when a player dies a new death is added to the records and a map marker is made
|
||||
Event.add(defines.events.on_player_died, function(event)
|
||||
local player = game.players[event.player_index]
|
||||
local corpse = player.surface.find_entity('character-corpse', player.position)
|
||||
if config.use_chests_as_bodies then
|
||||
local items = corpse.get_inventory(defines.inventory.character_corpse)
|
||||
local chest = move_items(items, corpse.surface, corpse.position)
|
||||
chest.destructible = false
|
||||
corpse.destroy()
|
||||
corpse = chest
|
||||
end
|
||||
local death = {
|
||||
player_name = player.name,
|
||||
time_of_death = event.tick,
|
||||
position = player.position,
|
||||
corpse = corpse
|
||||
}
|
||||
if config.show_map_markers then
|
||||
create_map_tag(death)
|
||||
end
|
||||
table.insert(deaths, death)
|
||||
|
||||
-- Draw a light attached to the corpse with the player color
|
||||
if config.show_light_at_corpse then
|
||||
rendering.draw_light{
|
||||
sprite = 'utility/light_medium',
|
||||
color = player.color,
|
||||
target = corpse,
|
||||
force = player.force,
|
||||
surface = player.surface
|
||||
}
|
||||
end
|
||||
end)
|
||||
|
||||
-- Draw lines to the player corpse
|
||||
if config.show_line_to_corpse then
|
||||
Event.add(defines.events.on_player_respawned, function(event)
|
||||
local player = game.players[event.player_index]
|
||||
|
||||
-- New deaths are added at the end of the deaths array, this is why
|
||||
-- we are itterating over the array in reverse. This saves on the amount
|
||||
-- of itterations we do.
|
||||
for index = #deaths, 1, -1 do
|
||||
local death = deaths[index]
|
||||
|
||||
-- If the corpse has already expired break out of the loop because
|
||||
-- all the deaths that will follow will be expired.
|
||||
if game.tick - death.time_of_death > corpse_lifetime then break end
|
||||
|
||||
-- Check if the death body is from the player
|
||||
-- Check if the corpse entity is still valid
|
||||
if death.player_name == player.name and death.corpse and death.corpse.valid then
|
||||
local line_color = player.color
|
||||
line_color.a = .3
|
||||
rendering.draw_line{
|
||||
color = line_color,
|
||||
from = player.character,
|
||||
to = death.corpse,
|
||||
players = { event.player_index },
|
||||
width = 2,
|
||||
dash_length = 1,
|
||||
gap_length = 1,
|
||||
surface = player.surface,
|
||||
draw_on_ground = true
|
||||
}
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- every 5 min all bodies are checked for valid map tags
|
||||
if config.show_map_markers then
|
||||
local check_period = 60*60*5 -- five minutes
|
||||
Event.on_nth_tick(check_period, function()
|
||||
check_map_tags()
|
||||
end)
|
||||
end
|
||||
|
||||
if config.auto_collect_bodies then
|
||||
Event.add(defines.events.on_character_corpse_expired, function(event)
|
||||
local corpse = event.corpse
|
||||
local items = corpse.get_inventory(defines.inventory.character_corpse)
|
||||
move_items(items, corpse.surface, {x=0, y=0})
|
||||
end)
|
||||
end
|
||||
|
||||
-- this is so other modules can access the logs
|
||||
return deaths
|
||||
141
exp_legacy/module/modules/addons/deconlog.lua
Normal file
141
exp_legacy/module/modules/addons/deconlog.lua
Normal file
@@ -0,0 +1,141 @@
|
||||
--- Log certain actions into a file when events are triggered
|
||||
-- @addon Deconlog
|
||||
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
local Roles = require 'expcore.roles' --- @dep expcore.roles
|
||||
local format_time = _C.format_time --- @dep expcore.common
|
||||
local format_number = require('util').format_number --- @dep util
|
||||
local config = require 'config.deconlog' --- @dep config.deconlog
|
||||
|
||||
local filepath = "log/decon.log"
|
||||
|
||||
local function add_log(data)
|
||||
game.write_file(filepath, data .. "\n", true, 0) -- write data
|
||||
end
|
||||
|
||||
local function get_secs()
|
||||
return format_time(game.tick, { hours = true, minutes = true, seconds = true, string = true })
|
||||
end
|
||||
|
||||
local function pos_to_string(pos)
|
||||
return tostring(pos.x) .. "," .. tostring(pos.y)
|
||||
end
|
||||
|
||||
local function pos_to_gps_string(pos)
|
||||
return '[gps=' .. string.format('%.1f', pos.x) .. ',' .. string.format('%.1f', pos.y) .. ']'
|
||||
end
|
||||
|
||||
--- Print a message to all players who match the value of admin
|
||||
local function print_to_players(admin, message)
|
||||
for _, player in ipairs(game.connected_players) do
|
||||
if player.admin == admin then
|
||||
player.print(message)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Event.on_init(function()
|
||||
game.write_file(filepath, "\n", false, 0) -- write data
|
||||
end)
|
||||
|
||||
if config.decon_area then
|
||||
Event.add(defines.events.on_player_deconstructed_area, function(e)
|
||||
if e.alt then
|
||||
return
|
||||
end
|
||||
|
||||
local player = game.get_player(e.player_index)
|
||||
|
||||
if Roles.player_has_flag(player, 'deconlog-bypass') then
|
||||
return
|
||||
end
|
||||
|
||||
local items = e.surface.find_entities_filtered{area=e.area, force=player.force}
|
||||
|
||||
if #items > 250 then
|
||||
print_to_players(true, {'deconlog.decon', player.name, e.surface.name, pos_to_gps_string(e.area.left_top), pos_to_gps_string(e.area.right_bottom), format_number(#items)})
|
||||
end
|
||||
|
||||
add_log(get_secs() .. ',' .. player.name .. ',decon_area,' .. e.surface.name .. ',' .. pos_to_string(e.area.left_top) .. ',' .. pos_to_string(e.area.right_bottom))
|
||||
end)
|
||||
end
|
||||
|
||||
if config.built_entity then
|
||||
Event.add(defines.events.on_built_entity, function (e)
|
||||
if not e.player_index then return end
|
||||
local player = game.get_player(e.player_index)
|
||||
if Roles.player_has_flag(player, "deconlog-bypass") then
|
||||
return
|
||||
end
|
||||
local ent = e.created_entity
|
||||
add_log(get_secs() .. "," .. player.name .. ",built_entity," .. ent.name .. "," .. pos_to_string(ent.position) .. "," .. tostring(ent.direction) .. "," .. tostring(ent.orientation))
|
||||
end)
|
||||
end
|
||||
|
||||
if config.mined_entity then
|
||||
Event.add(defines.events.on_player_mined_entity, function (e)
|
||||
local player = game.get_player(e.player_index)
|
||||
if Roles.player_has_flag(player, "deconlog-bypass") then
|
||||
return
|
||||
end
|
||||
local ent = e.entity
|
||||
add_log(get_secs() .. "," .. player.name .. ",mined_entity," .. ent.name .. "," .. pos_to_string(ent.position) .. "," .. tostring(ent.direction) .. "," .. tostring(ent.orientation))
|
||||
end)
|
||||
end
|
||||
|
||||
if config.fired_rocket then
|
||||
Event.add(defines.events.on_player_ammo_inventory_changed, function (e)
|
||||
local player = game.get_player(e.player_index)
|
||||
if Roles.player_has_flag(player, "deconlog-bypass") then
|
||||
return
|
||||
end
|
||||
local ammo_inv = player.get_inventory(defines.inventory.character_ammo)
|
||||
local item = ammo_inv[player.character.selected_gun_index]
|
||||
if not item or not item.valid or not item.valid_for_read then
|
||||
return
|
||||
end
|
||||
if item.name == "rocket" then
|
||||
add_log(get_secs() .. "," .. player.name .. ",shot-rocket," .. pos_to_string(player.position) .. "," .. pos_to_string(player.shooting_state.position))
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
if config.fired_explosive_rocket then
|
||||
Event.add(defines.events.on_player_ammo_inventory_changed, function (e)
|
||||
local player = game.get_player(e.player_index)
|
||||
|
||||
if Roles.player_has_flag(player, "deconlog-bypass") then
|
||||
return
|
||||
end
|
||||
local ammo_inv = player.get_inventory(defines.inventory.character_ammo)
|
||||
local item = ammo_inv[player.character.selected_gun_index]
|
||||
|
||||
if not item or not item.valid or not item.valid_for_read then
|
||||
return
|
||||
end
|
||||
if item.name == "explosive-rocket" then
|
||||
add_log(get_secs() .. "," .. player.name .. ",shot-explosive-rocket," .. pos_to_string(player.position) .. "," .. pos_to_string(player.shooting_state.position))
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
if config.fired_nuke then
|
||||
Event.add(defines.events.on_player_ammo_inventory_changed, function (e)
|
||||
local player = game.get_player(e.player_index)
|
||||
|
||||
if Roles.player_has_flag(player, "deconlog-bypass") then
|
||||
return
|
||||
end
|
||||
|
||||
local ammo_inv = player.get_inventory(defines.inventory.character_ammo)
|
||||
local item = ammo_inv[player.character.selected_gun_index]
|
||||
|
||||
if not item or not item.valid or not item.valid_for_read then
|
||||
return
|
||||
end
|
||||
|
||||
if item.name == "atomic-bomb" then
|
||||
add_log(get_secs() .. "," .. player.name .. ",shot-nuke," .. pos_to_string(player.position) .. "," .. pos_to_string(player.shooting_state.position))
|
||||
end
|
||||
end)
|
||||
end
|
||||
303
exp_legacy/module/modules/addons/discord-alerts.lua
Normal file
303
exp_legacy/module/modules/addons/discord-alerts.lua
Normal file
@@ -0,0 +1,303 @@
|
||||
--- Sends alert messages to our discord server when certain events are triggered
|
||||
-- @addon Discord-Alerts
|
||||
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
local Colors = require 'utils.color_presets' --- @dep utils.color_presets
|
||||
local write_json, format_time = _C.write_json, _C.format_time --- @dep expcore.common
|
||||
local config = require 'config.discord_alerts' --- @dep config.discord_alerts
|
||||
|
||||
local playtime_format = {hours = true, minutes = true, short = true, string = true}
|
||||
|
||||
local function append_playtime(player_name)
|
||||
if not config.show_playtime then
|
||||
return player_name
|
||||
end
|
||||
|
||||
local player = game.get_player(player_name)
|
||||
|
||||
if not player then
|
||||
return player_name
|
||||
end
|
||||
|
||||
return player.name ..' (' .. format_time(player.online_time, playtime_format) .. ')'
|
||||
end
|
||||
|
||||
local function get_player_name(event)
|
||||
local player = game.players[event.player_index]
|
||||
return player.name, event.by_player_name
|
||||
end
|
||||
|
||||
local function to_hex(color)
|
||||
local hex_digits = '0123456789ABCDEF'
|
||||
local function hex(bit)
|
||||
local major, minor = math.modf(bit/16)
|
||||
major, minor = major+1, minor*16+1
|
||||
return hex_digits:sub(major, major) .. hex_digits:sub(minor, minor)
|
||||
end
|
||||
|
||||
return '0x' .. hex(color.r) .. hex(color.g) .. hex(color.b)
|
||||
end
|
||||
|
||||
local function emit_event(args)
|
||||
local title = args.title or ''
|
||||
local color = args.color or '0x0'
|
||||
local description = args.description or ''
|
||||
|
||||
if type(color) == 'table' then
|
||||
color = to_hex(color)
|
||||
end
|
||||
|
||||
local tick = args.tick or game.tick
|
||||
local tick_formatted = format_time(tick, {days = false, hours = true, minutes = true, short = true, string = true})
|
||||
|
||||
local players_online = 0
|
||||
local admins_online = 0
|
||||
|
||||
for _, player in pairs(game.connected_players) do
|
||||
players_online = players_online + 1
|
||||
|
||||
if player.admin then
|
||||
admins_online = admins_online + 1
|
||||
end
|
||||
end
|
||||
|
||||
local done = {title=true, color=true, description=true}
|
||||
local fields = {{
|
||||
name='Server Details',
|
||||
value=string.format('Server: ${serverName} Time: %s\nTotal: %d Online: %d Admins: %d', tick_formatted, #game.players, players_online, admins_online)
|
||||
}}
|
||||
|
||||
for key, value in pairs(args) do
|
||||
if not done[key] then
|
||||
done[key] = true
|
||||
local field = {
|
||||
name=key,
|
||||
value=value,
|
||||
inline=false
|
||||
}
|
||||
|
||||
local new_value, inline = value:gsub('<inline>', '', 1)
|
||||
if inline > 0 then
|
||||
field.value = new_value
|
||||
field.inline = true
|
||||
end
|
||||
|
||||
table.insert(fields, field)
|
||||
end
|
||||
end
|
||||
|
||||
write_json('ext/discord.out',{
|
||||
title=title,
|
||||
description=description,
|
||||
color=color,
|
||||
fields=fields
|
||||
})
|
||||
end
|
||||
|
||||
--- Repeated protected entity mining
|
||||
if config.entity_protection then
|
||||
local EntityProtection = require 'modules.control.protection' --- @dep modules.control.protection
|
||||
Event.add(EntityProtection.events.on_repeat_violation, function(event)
|
||||
local player_name = get_player_name(event)
|
||||
emit_event{
|
||||
title='Entity Protection',
|
||||
description='A player removed protected entities',
|
||||
color=Colors.yellow,
|
||||
['Player']='<inline>' .. append_playtime(player_name),
|
||||
['Entity']='<inline>' .. event.entity.name,
|
||||
['Location']='X ' .. event.entity.position.x .. ' Y ' .. event.entity.position.y
|
||||
}
|
||||
end)
|
||||
end
|
||||
|
||||
--- Reports added and removed
|
||||
if config.player_reports then
|
||||
local Reports = require 'modules.control.reports' --- @dep modules.control.reports
|
||||
Event.add(Reports.events.on_player_reported, function(event)
|
||||
local player_name, by_player_name = get_player_name(event)
|
||||
emit_event{
|
||||
title='Report',
|
||||
description='A player was reported',
|
||||
color=Colors.yellow,
|
||||
['Player']='<inline>' .. append_playtime(player_name),
|
||||
['By']='<inline>' .. append_playtime(by_player_name),
|
||||
['Report Count']='<inline>' .. Reports.count_reports(player_name),
|
||||
['Reason']=event.reason
|
||||
}
|
||||
end)
|
||||
Event.add(Reports.events.on_report_removed, function(event)
|
||||
if event.batch ~= 1 then return end
|
||||
local player_name = get_player_name(event)
|
||||
emit_event{
|
||||
title='Reports Removed',
|
||||
description='A player has a report removed',
|
||||
color=Colors.green,
|
||||
['Player']='<inline>' .. player_name,
|
||||
['By']='<inline>' .. event.removed_by_name,
|
||||
['Report Count']='<inline>' .. event.batch_count
|
||||
}
|
||||
end)
|
||||
end
|
||||
|
||||
--- Warnings added and removed
|
||||
if config.player_warnings then
|
||||
local Warnings = require 'modules.control.warnings' --- @dep modules.control.warnings
|
||||
Event.add(Warnings.events.on_warning_added, function(event)
|
||||
local player_name, by_player_name = get_player_name(event)
|
||||
local player = game.get_player(player_name)
|
||||
emit_event{
|
||||
title='Warning',
|
||||
description='A player has been given a warning',
|
||||
color=Colors.yellow,
|
||||
['Player']='<inline>' .. player_name,
|
||||
['By']='<inline>' .. by_player_name,
|
||||
['Warning Count']='<inline>' .. Warnings.count_warnings(player),
|
||||
['Reason']=event.reason
|
||||
}
|
||||
end)
|
||||
Event.add(Warnings.events.on_warning_removed, function(event)
|
||||
if event.batch ~= 1 then return end
|
||||
local player_name = get_player_name(event)
|
||||
emit_event{
|
||||
title='Warnings Removed',
|
||||
description='A player has a warning removed',
|
||||
color=Colors.green,
|
||||
['Player']='<inline>' .. player_name,
|
||||
['By']='<inline>' .. event.removed_by_name,
|
||||
['Warning Count']='<inline>' .. event.batch_count
|
||||
}
|
||||
end)
|
||||
end
|
||||
|
||||
--- When a player is jailed or unjailed
|
||||
if config.player_jail then
|
||||
local Jail = require 'modules.control.jail'
|
||||
Event.add(Jail.events.on_player_jailed, function(event)
|
||||
local player_name, by_player_name = get_player_name(event)
|
||||
emit_event{
|
||||
title='Jail',
|
||||
description='A player has been jailed',
|
||||
color=Colors.yellow,
|
||||
['Player']='<inline>' .. player_name,
|
||||
['By']='<inline>' .. by_player_name,
|
||||
['Reason']=event.reason
|
||||
}
|
||||
end)
|
||||
Event.add(Jail.events.on_player_unjailed, function(event)
|
||||
local player_name, by_player_name = get_player_name(event)
|
||||
emit_event{
|
||||
title='Unjail',
|
||||
description='A player has been unjailed',
|
||||
color=Colors.green,
|
||||
['Player']='<inline>' .. player_name,
|
||||
['By']='<inline>' .. by_player_name
|
||||
}
|
||||
end)
|
||||
end
|
||||
|
||||
--- Ban and unban
|
||||
if config.player_bans then
|
||||
Event.add(defines.events.on_player_banned, function(event)
|
||||
if event.by_player then
|
||||
local by_player = game.players[event.by_player]
|
||||
emit_event{
|
||||
title='Banned',
|
||||
description='A player has been banned',
|
||||
color=Colors.red,
|
||||
['Player']='<inline>' .. event.player_name,
|
||||
['By']='<inline>' .. by_player.name,
|
||||
['Reason']=event.reason
|
||||
}
|
||||
end
|
||||
end)
|
||||
Event.add(defines.events.on_player_unbanned, function(event)
|
||||
if event.by_player then
|
||||
local by_player = game.players[event.by_player]
|
||||
emit_event{
|
||||
title='Un-Banned',
|
||||
description='A player has been un-banned',
|
||||
color=Colors.green,
|
||||
['Player']='<inline>' .. event.player_name,
|
||||
['By']='<inline>' .. by_player.name
|
||||
}
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
--- Mute and unmute
|
||||
if config.player_mutes then
|
||||
Event.add(defines.events.on_player_muted, function(event)
|
||||
local player_name = get_player_name(event)
|
||||
emit_event{
|
||||
title='Muted',
|
||||
description='A player has been muted',
|
||||
color=Colors.yellow,
|
||||
['Player']='<inline>' .. player_name
|
||||
}
|
||||
end)
|
||||
Event.add(defines.events.on_player_unmuted, function(event)
|
||||
local player_name = get_player_name(event)
|
||||
emit_event{
|
||||
title='Un-Muted',
|
||||
description='A player has been un-muted',
|
||||
color=Colors.green,
|
||||
['Player']='<inline>' .. player_name
|
||||
}
|
||||
end)
|
||||
end
|
||||
|
||||
--- Kick
|
||||
if config.player_kicks then
|
||||
Event.add(defines.events.on_player_kicked, function(event)
|
||||
if event.by_player then
|
||||
local player_name = get_player_name(event)
|
||||
local by_player = game.players[event.by_player]
|
||||
emit_event{
|
||||
title='Kick',
|
||||
description='A player has been kicked',
|
||||
color=Colors.orange,
|
||||
['Player']='<inline>' .. player_name,
|
||||
['By']='<inline>' .. by_player.name,
|
||||
['Reason']=event.reason
|
||||
}
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
--- Promote and demote
|
||||
if config.player_promotes then
|
||||
Event.add(defines.events.on_player_promoted, function(event)
|
||||
local player_name = get_player_name(event)
|
||||
emit_event{
|
||||
title='Promote',
|
||||
description='A player has been promoted',
|
||||
color=Colors.green,
|
||||
['Player']='<inline>' .. player_name
|
||||
}
|
||||
end)
|
||||
Event.add(defines.events.on_player_demoted, function(event)
|
||||
local player_name = get_player_name(event)
|
||||
emit_event{
|
||||
title='Demote',
|
||||
description='A player has been demoted',
|
||||
color=Colors.yellow,
|
||||
['Player']='<inline>' .. player_name
|
||||
}
|
||||
end)
|
||||
end
|
||||
|
||||
--- Other commands
|
||||
Event.add(defines.events.on_console_command, function(event)
|
||||
if event.player_index then
|
||||
local player_name = get_player_name(event)
|
||||
if config[event.command] then
|
||||
emit_event{
|
||||
title=event.command:gsub('^%l', string.upper),
|
||||
description='/' .. event.command .. ' was used',
|
||||
color=Colors.grey,
|
||||
['By']='<inline>' .. player_name,
|
||||
['Details'] = event.parameters ~= '' and event.parameters or nil
|
||||
}
|
||||
end
|
||||
end
|
||||
end)
|
||||
19
exp_legacy/module/modules/addons/fagc.lua
Normal file
19
exp_legacy/module/modules/addons/fagc.lua
Normal file
@@ -0,0 +1,19 @@
|
||||
--- Allows the FAGC clientside bot to receive information about bans and unbans and propagate that information to other servers
|
||||
-- @addon FAGC
|
||||
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
|
||||
-- Clear the file on startup to minimize its size
|
||||
Event.on_init(function()
|
||||
game.write_file("fagc-actions.txt", "", false, 0)
|
||||
end)
|
||||
|
||||
Event.add(defines.events.on_player_banned, function(e)
|
||||
local text = "ban;" .. e.player_name .. ";" .. (e.by_player or "") .. ";" .. (e.reason or "") .. "\n"
|
||||
game.write_file("fagc-actions.txt", text, true, 0)
|
||||
end)
|
||||
|
||||
Event.add(defines.events.on_player_unbanned, function(e)
|
||||
local text = "unban;" .. e.player_name .. ";" .. (e.by_player or "") .. ";" .. (e.reason or "") .. "\n"
|
||||
game.write_file("fagc-actions.txt", text, true, 0)
|
||||
end)
|
||||
23
exp_legacy/module/modules/addons/inserter.lua
Normal file
23
exp_legacy/module/modules/addons/inserter.lua
Normal file
@@ -0,0 +1,23 @@
|
||||
local Event = require 'utils.event'
|
||||
|
||||
local controllers_with_inventory = {
|
||||
[defines.controllers.character] = true,
|
||||
[defines.controllers.god] = true,
|
||||
[defines.controllers.editor] = true,
|
||||
}
|
||||
|
||||
Event.add(defines.events.on_player_mined_entity, function(event)
|
||||
if (not event.entity.valid) or (event.entity.type ~= 'inserter') or event.entity.drop_target then
|
||||
return
|
||||
end
|
||||
|
||||
local item_entity = event.entity.surface.find_entity('item-on-ground', event.entity.drop_position)
|
||||
|
||||
if item_entity then
|
||||
local player = game.get_player(event.player_index)
|
||||
|
||||
if controllers_with_inventory[player.controller_type] then
|
||||
player.mine_entity(item_entity)
|
||||
end
|
||||
end
|
||||
end)
|
||||
15
exp_legacy/module/modules/addons/inventory-clear.lua
Normal file
15
exp_legacy/module/modules/addons/inventory-clear.lua
Normal file
@@ -0,0 +1,15 @@
|
||||
--- Will move players items to spawn when they are banned or kicked, option to clear on leave
|
||||
-- @addon Inventory-Clear
|
||||
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
local events = require 'config.inventory_clear' --- @dep config.inventory_clear
|
||||
local move_items_stack = _C.move_items_stack --- @dep expcore.common
|
||||
|
||||
local function clear_items(event)
|
||||
local player = game.players[event.player_index]
|
||||
local inv = player.get_main_inventory()
|
||||
move_items_stack(inv)
|
||||
inv.clear()
|
||||
end
|
||||
|
||||
for _, event_name in ipairs(events) do Event.add(event_name, clear_items) end
|
||||
59
exp_legacy/module/modules/addons/lawnmower.lua
Normal file
59
exp_legacy/module/modules/addons/lawnmower.lua
Normal file
@@ -0,0 +1,59 @@
|
||||
--[[-- Addon Lawnmower
|
||||
- Adds a command that clean up biter corpse and nuclear hole
|
||||
@addon Lawnmower
|
||||
]]
|
||||
|
||||
local Commands = require 'expcore.commands' --- @dep expcore.commands
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
local config = require 'config.lawnmower' --- @dep config.lawnmower
|
||||
require 'config.expcore.command_general_parse'
|
||||
|
||||
Commands.new_command('lawnmower', {'expcom-lawnmower.description'}, 'Clean up biter corpse, decoratives and nuclear hole')
|
||||
:add_param('range', false, 'integer-range', 1, 200)
|
||||
:register(function(player, range)
|
||||
local tile_to_do = {}
|
||||
|
||||
player.surface.destroy_decoratives({position=player.position, radius=range})
|
||||
|
||||
local entities = player.surface.find_entities_filtered{position=player.position, radius=range, type='corpse'}
|
||||
|
||||
for _, entity in pairs(entities) do
|
||||
if (entity.name ~= 'transport-caution-corpse' and entity.name ~= 'invisible-transport-caution-corpse') then
|
||||
entity.destroy()
|
||||
end
|
||||
end
|
||||
|
||||
local tiles = player.surface.find_tiles_filtered{position=player.position, radius=range, name={'nuclear-ground'}}
|
||||
|
||||
for _, tile in pairs(tiles) do
|
||||
table.insert(tile_to_do, {name='grass-1', position=tile.position})
|
||||
end
|
||||
|
||||
player.surface.set_tiles(tile_to_do)
|
||||
|
||||
return Commands.success
|
||||
end)
|
||||
|
||||
local function destroy_decoratives(entity)
|
||||
if entity.type ~= 'entity-ghost' and entity.type ~= 'tile-ghost' and entity.prototype.selectable_in_game then
|
||||
entity.surface.destroy_decoratives{area=entity.selection_box}
|
||||
end
|
||||
end
|
||||
|
||||
if config.destroy_decoratives then
|
||||
Event.add(defines.events.on_built_entity, function(event)
|
||||
destroy_decoratives(event.created_entity)
|
||||
end)
|
||||
|
||||
Event.add(defines.events.on_robot_built_entity, function(event)
|
||||
destroy_decoratives(event.created_entity)
|
||||
end)
|
||||
|
||||
Event.add(defines.events.script_raised_built, function(event)
|
||||
destroy_decoratives(event.entity)
|
||||
end)
|
||||
|
||||
Event.add(defines.events.script_raised_revive, function(event)
|
||||
destroy_decoratives(event.entity)
|
||||
end)
|
||||
end
|
||||
71
exp_legacy/module/modules/addons/logging.lua
Normal file
71
exp_legacy/module/modules/addons/logging.lua
Normal file
@@ -0,0 +1,71 @@
|
||||
--[[-- Addon Logging
|
||||
@addon Logging
|
||||
]]
|
||||
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
local config = require 'config.logging' --- @dep config.logging
|
||||
local config_res = require 'config.research' --- @dep config.research
|
||||
|
||||
local function add_log(data)
|
||||
game.write_file(config.file_name, data, true, 0)
|
||||
game.write_file(config.file_name, '\n', true, 0)
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_rocket_launched, function(event)
|
||||
if event and event.rocket and event.rocket.force and event.rocket.force.rockets_launched then
|
||||
if event.rocket.force.rockets_launched >= config.rocket_launch_display_rate and event.rocket.force.rockets_launched % config.rocket_launch_display_rate == 0 then
|
||||
add_log('[ROCKET] ' .. event.rocket.force.rockets_launched .. ' rockets launched')
|
||||
|
||||
elseif config.rocket_launch_display[event.rocket.force.rockets_launched] then
|
||||
add_log('[ROCKET] ' .. event.rocket.force.rockets_launched .. ' rockets launched')
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
Event.add(defines.events.on_pre_player_died, function(event)
|
||||
if event and event.player_index then
|
||||
if event.cause then
|
||||
if event.cause.type and event.cause.type == 'character' and event.cause.player and event.cause.player.index then
|
||||
add_log('[DEATH] ' .. game.players[event.player_index].name .. ' died because of ' .. (game.players[event.cause.player.index].name or 'unknown reason'))
|
||||
|
||||
else
|
||||
add_log('[DEATH] ' .. game.players[event.player_index].name .. ' died because of ' .. (event.cause.name or 'unknown reason'))
|
||||
end
|
||||
|
||||
else
|
||||
add_log('[DEATH] ' .. game.players[event.player_index].name .. ' died because of unknown reason')
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
Event.add(defines.events.on_research_finished, function(event)
|
||||
if event and event.research then
|
||||
if event.by_script then
|
||||
return
|
||||
end
|
||||
|
||||
if (event.research.level and config_res.inf_res[event.research.name]) and (event.research.level >= config_res.inf_res[event.research.name]) then
|
||||
add_log({'logging.add-l', event.research.prototype.localised_name, event.research.level - 1})
|
||||
|
||||
else
|
||||
add_log({'logging.add-n', event.research.prototype.localised_name})
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
Event.add(defines.events.on_player_joined_game, function(event)
|
||||
if event and event.player_index then
|
||||
add_log('[JOIN] ' .. game.players[event.player_index].name .. ' joined the game')
|
||||
end
|
||||
end)
|
||||
|
||||
Event.add(defines.events.on_player_left_game, function(event)
|
||||
if event and event.player_index then
|
||||
if event.reason then
|
||||
add_log('[LEAVE] ' .. game.players[event.player_index].name .. config.disconnect_reason[event.reason])
|
||||
|
||||
else
|
||||
add_log('[LEAVE] ' .. game.players[event.player_index].name .. config.disconnect_reason[defines.disconnect_reason.quit])
|
||||
end
|
||||
end
|
||||
end)
|
||||
181
exp_legacy/module/modules/addons/miner.lua
Normal file
181
exp_legacy/module/modules/addons/miner.lua
Normal file
@@ -0,0 +1,181 @@
|
||||
local Event = require 'utils.event_core' --- @dep utils.event_core
|
||||
local Global = require 'utils.global' --- @dep utils.global
|
||||
local config = require 'config.miner' --- @dep config.miner
|
||||
|
||||
local miner_data = {}
|
||||
|
||||
Global.register(miner_data, function(tbl)
|
||||
miner_data = tbl
|
||||
end)
|
||||
|
||||
miner_data.queue = {}
|
||||
|
||||
local function drop_target(entity)
|
||||
if entity.drop_target then
|
||||
return entity.drop_target
|
||||
|
||||
else
|
||||
local entities = entity.surface.find_entities_filtered{position=entity.drop_position}
|
||||
|
||||
if #entities > 0 then
|
||||
return entities[1]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function check_entity(entity)
|
||||
if entity.to_be_deconstructed(entity.force) then
|
||||
-- if it is already waiting to be deconstruct
|
||||
return true
|
||||
end
|
||||
|
||||
if next(entity.circuit_connected_entities.red) ~= nil or next(entity.circuit_connected_entities.green) ~= nil then
|
||||
-- connected to circuit network
|
||||
return true
|
||||
end
|
||||
|
||||
if not entity.minable then
|
||||
-- if it is minable
|
||||
return true
|
||||
end
|
||||
|
||||
if not entity.prototype.selectable_in_game then
|
||||
-- if it can select
|
||||
return true
|
||||
end
|
||||
|
||||
if entity.has_flag('not-deconstructable') then
|
||||
-- if it can deconstruct
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
local function chest_check(entity)
|
||||
local target = drop_target(entity)
|
||||
|
||||
if check_entity(entity) then
|
||||
return
|
||||
end
|
||||
|
||||
if target.type ~= 'logistic-container' and target.type ~= 'container' then
|
||||
-- not a chest
|
||||
return
|
||||
end
|
||||
|
||||
local radius = 2
|
||||
local entities = target.surface.find_entities_filtered{area={{target.position.x - radius, target.position.y - radius}, {target.position.x + radius, target.position.y + radius}}, type={'mining-drill', 'inserter'}}
|
||||
|
||||
for _, e in pairs(entities) do
|
||||
if drop_target(e) == target then
|
||||
if not e.to_be_deconstructed(entity.force) and e ~= entity then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if check_entity(target) then
|
||||
table.insert(miner_data.queue, {t=game.tick + 10, e=target})
|
||||
end
|
||||
end
|
||||
|
||||
local function miner_check(entity)
|
||||
local ep = entity.position
|
||||
local es = entity.surface
|
||||
local ef = entity.force
|
||||
local er = entity.prototype.mining_drill_radius
|
||||
|
||||
for _, r in pairs(entity.surface.find_entities_filtered{area={{x=ep.x - er, y=ep.y - er}, {x=ep.x + er, y=ep.y + er}}, type='resource'}) do
|
||||
if r.amount > 0 then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
entity.status ~= defines.entity_status.no_minable_resources
|
||||
]]
|
||||
|
||||
if check_entity(entity) then
|
||||
return
|
||||
end
|
||||
|
||||
local pipe_build = {}
|
||||
|
||||
if config.fluid and entity.fluidbox and #entity.fluidbox > 0 then
|
||||
-- if require fluid to mine
|
||||
table.insert(pipe_build, {x=0, y=0})
|
||||
|
||||
local half = math.floor(entity.get_radius())
|
||||
local r = 1 + er
|
||||
|
||||
local entities = es.find_entities_filtered{area={{ep.x - r, ep.y - r}, {ep.x + r, ep.y + r}}, type={'mining-drill', 'pipe', 'pipe-to-ground'}}
|
||||
local entities_t = es.find_entities_filtered{area={{ep.x - r, ep.y - r}, {ep.x + r, ep.y + r}}, ghost_type={'pipe', 'pipe-to-ground'}}
|
||||
|
||||
table.array_insert(entities, entities_t)
|
||||
|
||||
for _, e in pairs(entities) do
|
||||
if (e.position.x > ep.x) and (e.position.y == ep.y) then
|
||||
for h=1, half do
|
||||
table.insert(pipe_build, {x=h, y=0})
|
||||
end
|
||||
|
||||
elseif (e.position.x < ep.x) and (e.position.y == ep.y) then
|
||||
for h=1, half do
|
||||
table.insert(pipe_build, {x=-h, y=0})
|
||||
end
|
||||
|
||||
elseif (e.position.x == ep.x) and (e.position.y > ep.y) then
|
||||
for h=1, half do
|
||||
table.insert(pipe_build, {x=0, y=h})
|
||||
end
|
||||
|
||||
elseif (e.position.x == ep.x) and (e.position.y < ep.y) then
|
||||
for h=1, half do
|
||||
table.insert(pipe_build, {x=0, y=-h})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if config.chest then
|
||||
chest_check(entity)
|
||||
end
|
||||
|
||||
table.insert(miner_data.queue, {t=game.tick + 5, e=entity})
|
||||
|
||||
for _, pos in ipairs(pipe_build) do
|
||||
es.create_entity{name='entity-ghost', position={x=ep.x + pos.x, y=ep.y + pos.y}, force=ef, inner_name='pipe', raise_built=true}
|
||||
end
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_resource_depleted, function(event)
|
||||
if event.entity.prototype.infinite_resource then
|
||||
return
|
||||
end
|
||||
|
||||
local entities = event.entity.surface.find_entities_filtered{area={{event.entity.position.x - 1, event.entity.position.y - 1}, {event.entity.position.x + 1, event.entity.position.y + 1}}, type='mining-drill'}
|
||||
|
||||
if #entities == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
for _, entity in pairs(entities) do
|
||||
if ((math.abs(entity.position.x - event.entity.position.x) < entity.prototype.mining_drill_radius) and (math.abs(entity.position.y - event.entity.position.y) < entity.prototype.mining_drill_radius)) then
|
||||
miner_check(entity)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
Event.on_nth_tick(10, function(event)
|
||||
for k, q in pairs(miner_data.queue) do
|
||||
if not q.e or not q.e.valid then
|
||||
table.remove(miner_data.queue, k)
|
||||
break
|
||||
|
||||
elseif event.tick >= q.t then
|
||||
q.e.order_deconstruction(q.e.force)
|
||||
table.remove(miner_data.queue, k)
|
||||
end
|
||||
end
|
||||
end)
|
||||
46
exp_legacy/module/modules/addons/nukeprotect.lua
Normal file
46
exp_legacy/module/modules/addons/nukeprotect.lua
Normal file
@@ -0,0 +1,46 @@
|
||||
--- Disable new players from having certain items in their inventory, most commonly nukes
|
||||
-- @addon Nukeprotect
|
||||
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
local Roles = require 'expcore.roles' --- @dep expcore.roles
|
||||
local config = require 'config.nukeprotect' --- @dep config.nukeprotect
|
||||
local move_items_stack = _C.move_items_stack --- @dep expcore.common
|
||||
|
||||
|
||||
local function check_items(player, type)
|
||||
-- if the player has perms to be ignored, then they should be
|
||||
if config.ignore_permisison and Roles.player_allowed(player, config.ignore_permisison) then return end
|
||||
-- if the players
|
||||
if config.ignore_admins and player.admin then return end
|
||||
|
||||
local inventory = player.get_inventory(type)
|
||||
for i = 1, #inventory do
|
||||
local item = inventory[i]
|
||||
if item.valid and item.valid_for_read and config[tostring(type)][item.name] then
|
||||
player.print({ "nukeprotect.found", { "item-name." .. item.name } })
|
||||
-- insert the items into the table so all items are transferred at once
|
||||
move_items_stack({ item })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for _, inventory in ipairs(config.inventories) do
|
||||
if #inventory.items > 0 then
|
||||
Event.add(inventory.event, function(event)
|
||||
local player = game.get_player(event.player_index)
|
||||
if player and player.valid then
|
||||
check_items(player, inventory.inventory)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if config.disable_nuke_research then
|
||||
Event.add(defines.events.on_research_started, function(event)
|
||||
local name = event.research.name
|
||||
if config.disable_nuke_research_names[name] then
|
||||
event.research.force.cancel_current_research()
|
||||
end
|
||||
end)
|
||||
end
|
||||
16
exp_legacy/module/modules/addons/pollution-grading.lua
Normal file
16
exp_legacy/module/modules/addons/pollution-grading.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
--- Makes polution look much nice of the map, ie not one big red mess
|
||||
-- @addon Pollution-Grading
|
||||
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
local config = require 'config.pollution_grading' --- @dep config.pollution_grading
|
||||
|
||||
local delay = config.update_delay * 3600 -- convert from minutes to ticks
|
||||
Event.on_nth_tick(delay, function()
|
||||
local surface = game.surfaces[1]
|
||||
local true_max = surface.get_pollution(config.reference_point)
|
||||
local max = true_max*config.max_scalar
|
||||
local min = max*config.min_scalar
|
||||
local settings = game.map_settings.pollution
|
||||
settings.expected_max_per_chunk = max
|
||||
settings.min_to_show_per_chunk = min
|
||||
end)
|
||||
40
exp_legacy/module/modules/addons/protection-jail.lua
Normal file
40
exp_legacy/module/modules/addons/protection-jail.lua
Normal file
@@ -0,0 +1,40 @@
|
||||
--- When a player triggers protection multiple times they are automatically jailed
|
||||
-- @addon protection-jail
|
||||
|
||||
local Event = require 'utils.event' ---@dep utils.event
|
||||
local Global = require 'utils.global' ---@dep utils.global
|
||||
local Jail = require 'modules.control.jail' ---@dep modules.control.jail
|
||||
local Protection = require 'modules.control.protection' --- @dep modules.control.protection
|
||||
local format_chat_player_name = _C.format_chat_player_name --- @dep expcore.common
|
||||
|
||||
--- Stores how many times the repeat violation was triggered
|
||||
local repeat_count = {}
|
||||
Global.register(repeat_count, function(tbl)
|
||||
repeat_count = tbl
|
||||
end)
|
||||
|
||||
--- When a protection is triggered increment their counter and jail if needed
|
||||
Event.add(Protection.events.on_repeat_violation, function(event)
|
||||
local player = game.get_player(event.player_index)
|
||||
|
||||
-- Increment the counter
|
||||
if repeat_count[player.index] then
|
||||
repeat_count[player.index] = repeat_count[player.index] + 1
|
||||
else
|
||||
repeat_count[player.index] = 1
|
||||
end
|
||||
|
||||
-- Jail if needed
|
||||
if repeat_count[player.index] < 3 then
|
||||
return
|
||||
end
|
||||
|
||||
local player_name_color = format_chat_player_name(player)
|
||||
Jail.jail_player(player, '<protection>', 'Removed too many protected entities, please wait for a moderator.')
|
||||
game.print{'protection-jail.jail', player_name_color}
|
||||
end)
|
||||
|
||||
--- Clear the counter when they leave the game (stops a build up of data)
|
||||
Event.add(defines.events.on_player_left_game, function(event)
|
||||
repeat_count[event.player_index] = nil
|
||||
end)
|
||||
28
exp_legacy/module/modules/addons/report-jail.lua
Normal file
28
exp_legacy/module/modules/addons/report-jail.lua
Normal file
@@ -0,0 +1,28 @@
|
||||
--- When a player is reported, the player is automatically jailed if the combined playtime of the reporters exceeds the reported player
|
||||
-- @addon report-jail
|
||||
|
||||
local Event = require 'utils.event' ---@dep utils.event
|
||||
local Jail = require 'modules.control.jail' ---@dep modules.control.jail
|
||||
local Reports = require 'modules.control.reports' --- @dep modules.control.reports
|
||||
local format_chat_player_name = _C.format_chat_player_name --- @dep expcore.common
|
||||
|
||||
--- Returns the playtime of the reporter. Used when calculating the total playtime of all reporters
|
||||
local function reporter_playtime(_, by_player_name, _)
|
||||
local player = game.get_player(by_player_name)
|
||||
if player == nil then
|
||||
return 0
|
||||
end
|
||||
return player.online_time
|
||||
end
|
||||
|
||||
Event.add(Reports.events.on_player_reported, function(event)
|
||||
local player = game.get_player(event.player_index)
|
||||
local total_playtime = Reports.count_reports(player, reporter_playtime)
|
||||
|
||||
-- player less than 30 min
|
||||
if (Reports.count_reports(player) > 1) and (total_playtime > math.max(player.online_time * 2, 108000)) then
|
||||
local player_name_color = format_chat_player_name(player)
|
||||
Jail.jail_player(player, '<reports>', 'Reported by too many players, please wait for a moderator.')
|
||||
game.print{'report-jail.jail', player_name_color}
|
||||
end
|
||||
end)
|
||||
138
exp_legacy/module/modules/addons/scorched-earth.lua
Normal file
138
exp_legacy/module/modules/addons/scorched-earth.lua
Normal file
@@ -0,0 +1,138 @@
|
||||
--- When a player walks around the tiles under them will degrade over time, the same is true when entites are built
|
||||
-- @addon Scorched-Earth
|
||||
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
local Global = require 'utils.global' --- @dep utils.global
|
||||
local print_grid_value, clear_flying_text = _C.print_grid_value, _C.clear_flying_text --- @dep expcore.common
|
||||
local config = require 'config.scorched_earth' --- @dep config.scorched_earth
|
||||
|
||||
-- Loops over the config and finds the wile which has the highest value for strength
|
||||
local max_strength = 0
|
||||
for _, strength in pairs(config.strengths) do
|
||||
if strength > max_strength then
|
||||
max_strength = strength
|
||||
end
|
||||
end
|
||||
|
||||
-- Used for debugging the degrade chances
|
||||
local debug_players = {}
|
||||
Global.register(debug_players, function(tbl)
|
||||
debug_players = tbl
|
||||
end)
|
||||
|
||||
-- Will degrade a tile down to the next tile when called
|
||||
local function degrade(surface, position)
|
||||
local tile = surface.get_tile(position)
|
||||
local tile_name = tile.name
|
||||
local degrade_tile_name = config.degrade_order[tile_name]
|
||||
if not degrade_tile_name then return end
|
||||
surface.set_tiles{{name=degrade_tile_name, position=position}}
|
||||
end
|
||||
|
||||
-- Same as degrade but will degrade all tiles that are under an entity
|
||||
local function degrade_entity(entity)
|
||||
local surface = entity.surface
|
||||
local position = entity.position
|
||||
local tiles = {}
|
||||
if not config.entities[entity.name] then return end
|
||||
local box = entity.prototype.collision_box
|
||||
local lt = box.left_top
|
||||
local rb = box.right_bottom
|
||||
for x = lt.x, rb.x do -- x loop
|
||||
local px = position.x+x
|
||||
for y = lt.y, rb.y do -- y loop
|
||||
local p = {x=px, y=position.y+y}
|
||||
local tile = surface.get_tile(p)
|
||||
local tile_name = tile.name
|
||||
local degrade_tile_name = config.degrade_order[tile_name]
|
||||
if not degrade_tile_name then return end
|
||||
table.insert(tiles, {name=degrade_tile_name, position=p})
|
||||
end
|
||||
end
|
||||
surface.set_tiles(tiles)
|
||||
end
|
||||
|
||||
-- Turns the strength of a tile into a probability (0 = impossible, 1 = certain)
|
||||
local function get_probability(strength)
|
||||
local v1 = strength/max_strength
|
||||
local dif = 1 - v1
|
||||
local v2 = dif/2
|
||||
return (1-v1+v2)/config.weakness_value
|
||||
end
|
||||
|
||||
-- Gets the mean of the strengths around a tile to give the strength at that position
|
||||
local function get_tile_strength(surface, position)
|
||||
local tile = surface.get_tile(position)
|
||||
local tile_name = tile.name
|
||||
local strength = config.strengths[tile_name]
|
||||
if not strength then return end
|
||||
for x = -1, 1 do -- x loop
|
||||
local px = position.x + x
|
||||
for y = -1, 1 do -- y loop
|
||||
local check_tile = surface.get_tile{x=px, y=position.y+y}
|
||||
local check_tile_name = check_tile.name
|
||||
local check_strength = config.strengths[check_tile_name] or 0
|
||||
strength = strength + check_strength
|
||||
end
|
||||
end
|
||||
return strength/9
|
||||
end
|
||||
|
||||
-- Same as get_tile_strength but returns to a in game text rather than as a value
|
||||
local function debug_get_tile_strength(surface, position)
|
||||
for x = -3, 3 do -- x loop
|
||||
local px = position.x+x
|
||||
for y = -3, 3 do -- y loop
|
||||
local p = {x=px, y=position.y+y}
|
||||
local strength = get_tile_strength(surface, p) or 0
|
||||
local tile = surface.get_tile(p)
|
||||
print_grid_value(get_probability(strength)*config.weakness_value, surface, tile.position)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- When the player changes position the tile will have a chance to downgrade, debug check is here
|
||||
Event.add(defines.events.on_player_changed_position, function(event)
|
||||
local player = game.players[event.player_index]
|
||||
local surface = player.surface
|
||||
local position = player.position
|
||||
local strength = get_tile_strength(surface, position)
|
||||
if not strength then return end
|
||||
if get_probability(strength) > math.random() then
|
||||
degrade(surface, position)
|
||||
end
|
||||
if debug_players[player.name] then
|
||||
debug_get_tile_strength(surface, position)
|
||||
end
|
||||
end)
|
||||
|
||||
-- When an entity is build there is a much higher chance that the tiles will degrade
|
||||
Event.add(defines.events.on_built_entity, function(event)
|
||||
local entity = event.created_entity
|
||||
local surface = entity.surface
|
||||
local position = entity.position
|
||||
local strength = get_tile_strength(surface, position)
|
||||
if not strength then return end
|
||||
if get_probability(strength)*config.weakness_value > math.random() then
|
||||
degrade_entity(entity)
|
||||
end
|
||||
end)
|
||||
|
||||
-- Same as above but with robots
|
||||
Event.add(defines.events.on_robot_built_entity, function(event)
|
||||
local entity = event.created_entity
|
||||
local surface = entity.surface
|
||||
local position = entity.position
|
||||
local strength = get_tile_strength(surface, position)
|
||||
if not strength then return end
|
||||
if get_probability(strength)*config.weakness_value > math.random() then
|
||||
degrade_entity(entity)
|
||||
end
|
||||
end)
|
||||
|
||||
-- Used as a way to access the global table
|
||||
return function(player_name, state)
|
||||
local player = game.players[player_name]
|
||||
clear_flying_text(player.surface)
|
||||
debug_players[player_name] = state
|
||||
end
|
||||
236
exp_legacy/module/modules/addons/spawn-area.lua
Normal file
236
exp_legacy/module/modules/addons/spawn-area.lua
Normal file
@@ -0,0 +1,236 @@
|
||||
--- Adds a custom spawn area with chests and afk turrets
|
||||
-- @addon Spawn-Area
|
||||
|
||||
local Global = require 'utils.global' --- @dep utils.global
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
local config = require 'config.spawn_area' --- @dep config.spawn_area
|
||||
|
||||
local turrets = config.turrets.locations
|
||||
Global.register(turrets, function(tbl)
|
||||
turrets = tbl
|
||||
end)
|
||||
|
||||
-- Apply an offset to a LuaPosition
|
||||
local function apply_offset(position, offset)
|
||||
return {x=position.x + (offset.x or offset[1]), y=position.y + (offset.y or offset[2])}
|
||||
end
|
||||
|
||||
-- Apply the offset to the turrets default position
|
||||
for _, turret in ipairs(turrets) do
|
||||
turret.position = apply_offset(turret.position, config.turrets.offset)
|
||||
end
|
||||
|
||||
-- Get or create the force used for entities in spawn
|
||||
local function get_spawn_force()
|
||||
local force = game.forces['spawn']
|
||||
|
||||
if force and force.valid then
|
||||
return force
|
||||
end
|
||||
|
||||
force = game.create_force('spawn')
|
||||
force.set_cease_fire('player', true)
|
||||
-- force.set_friend('player', true)
|
||||
game.forces['player'].set_cease_fire('spawn', true)
|
||||
-- game.forces['player'].set_friend('spawn', true)
|
||||
|
||||
return force
|
||||
end
|
||||
|
||||
-- Protects an entity
|
||||
-- and sets its force to the spawn force
|
||||
local function protect_entity(entity, set_force)
|
||||
if entity and entity.valid then
|
||||
entity.destructible = false
|
||||
entity.minable = false
|
||||
entity.rotatable = false
|
||||
entity.operable = false
|
||||
|
||||
if set_force then
|
||||
entity.force = get_spawn_force()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Will spawn all infinite ammo turrets and keep them refilled
|
||||
local function spawn_turrets()
|
||||
for _, turret_pos in pairs(turrets) do
|
||||
local surface = game.surfaces[turret_pos.surface]
|
||||
local pos = turret_pos.position
|
||||
local turret = surface.find_entity('gun-turret', pos)
|
||||
|
||||
-- Makes a new turret if it is not found
|
||||
if not turret or not turret.valid then
|
||||
turret = surface.create_entity{name='gun-turret', position=pos, force='spawn'}
|
||||
protect_entity(turret)
|
||||
end
|
||||
|
||||
-- Adds ammo to the turret
|
||||
local inv = turret.get_inventory(defines.inventory.turret_ammo)
|
||||
if inv.can_insert{name=config.turrets.ammo_type, count=10} then
|
||||
inv.insert{name=config.turrets.ammo_type, count=10}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Makes a 2x2 afk belt at the locations in the config
|
||||
local function spawn_belts(surface, position)
|
||||
position = apply_offset(position, config.afk_belts.offset)
|
||||
local belt_type = config.afk_belts.belt_type
|
||||
local belt_details = {{-0.5, -0.5, 2}, {0.5, -0.5, 4}, {-0.5, 0.5, 0}, {0.5, 0.5, 6}} -- x, y,dir
|
||||
|
||||
for _, belt_set in pairs(config.afk_belts.locations) do
|
||||
local set_position = apply_offset(position, belt_set)
|
||||
for _, belt in pairs(belt_details) do
|
||||
local pos = apply_offset(set_position, belt)
|
||||
local belt_entity = surface.create_entity{name=belt_type, position=pos, force='neutral', direction=belt[3]}
|
||||
|
||||
if config.afk_belts.protected then
|
||||
protect_entity(belt_entity)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Generates extra tiles in a set pattern as defined in the config
|
||||
local function spawn_pattern(surface, position)
|
||||
position = apply_offset(position, config.pattern.offset)
|
||||
local tiles_to_make = {}
|
||||
local pattern_tile = config.pattern.pattern_tile
|
||||
|
||||
for _, tile in pairs(config.pattern.locations) do
|
||||
table.insert(tiles_to_make, {name=pattern_tile, position=apply_offset(position, tile)})
|
||||
end
|
||||
|
||||
surface.set_tiles(tiles_to_make)
|
||||
end
|
||||
|
||||
-- Generates extra water as defined in the config
|
||||
local function spawn_water(surface, position)
|
||||
position = apply_offset(position, config.water.offset)
|
||||
local tiles_to_make = {}
|
||||
local water_tile = config.water.water_tile
|
||||
for _, tile in pairs(config.water.locations) do
|
||||
table.insert(tiles_to_make, {name=water_tile, position=apply_offset(position, tile)})
|
||||
end
|
||||
surface.set_tiles(tiles_to_make)
|
||||
end
|
||||
|
||||
-- Generates the entities that are in the config
|
||||
local function spawn_entities(surface, position)
|
||||
position = apply_offset(position, config.entities.offset)
|
||||
for _, entity in pairs(config.entities.locations) do
|
||||
local pos = apply_offset(position, {x=entity[2], y=entity[3]})
|
||||
entity = surface.create_entity{name=entity[1], position=pos, force='neutral'}
|
||||
|
||||
if config.entities.protected then
|
||||
protect_entity(entity)
|
||||
end
|
||||
|
||||
entity.operable = config.entities.operable
|
||||
end
|
||||
end
|
||||
|
||||
-- Generates an area with no water or entities, no water area is larger
|
||||
local function spawn_area(surface, position)
|
||||
local dr = config.spawn_area.deconstruction_radius
|
||||
local tr = config.spawn_area.tile_radius
|
||||
local tr2 = tr^2
|
||||
local decon_tile = config.spawn_area.deconstruction_tile
|
||||
|
||||
local fr = config.spawn_area.landfill_radius
|
||||
local fr2 = fr^2
|
||||
local fill_tile = surface.get_tile(position).name
|
||||
|
||||
-- Make sure a non water tile is used for each tile
|
||||
if surface.get_tile(position).collides_with('player-layer') then fill_tile = 'landfill' end
|
||||
if decon_tile == nil then decon_tile = fill_tile end
|
||||
|
||||
local tiles_to_make = {}
|
||||
for x = -fr, fr do -- loop over x
|
||||
local x2 = (x+0.5)^2
|
||||
for y = -fr, fr do -- loop over y
|
||||
local y2 = (y+0.5)^2
|
||||
local dst = x2+y2
|
||||
local pos = {x=position.x+x, y=position.y+y}
|
||||
if dst < tr2 then
|
||||
-- If it is inside the decon radius always set the tile
|
||||
table.insert(tiles_to_make, {name=decon_tile, position=pos})
|
||||
elseif dst < fr2 and surface.get_tile(pos).collides_with('player-layer') then
|
||||
-- If it is inside the fill radius only set the tile if it is water
|
||||
table.insert(tiles_to_make, {name=fill_tile, position=pos})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Remove entities then set the tiles
|
||||
local entities_to_remove = surface.find_entities_filtered{position=position, radius=dr, name='character', invert=true}
|
||||
for _, entity in pairs(entities_to_remove) do
|
||||
entity.destroy()
|
||||
end
|
||||
surface.set_tiles(tiles_to_make)
|
||||
end
|
||||
|
||||
local function spawn_resource_tiles(surface)
|
||||
for _, v in ipairs(config.resource_tiles.resources) do
|
||||
if v.enabled then
|
||||
for x=v.offset[1], v.offset[1] + v.size[1] do
|
||||
for y=v.offset[2], v.offset[2] + v.size[2] do
|
||||
surface.create_entity({name=v.name, amount=v.amount, position={x, y}})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function spawn_resource_patches(surface)
|
||||
for _, v in ipairs(config.resource_patches.resources) do
|
||||
if v.enabled then
|
||||
for i=1, v.num_patches do
|
||||
surface.create_entity({name=v.name, amount=v.amount, position={v.offset[1] + v.offset_next[1] * (i - 1), v.offset[2] + v.offset_next[2] * (i - 1)}})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Only add a event handler if the turrets are enabled
|
||||
if config.turrets.enabled then
|
||||
Event.on_nth_tick(config.turrets.refill_time, function()
|
||||
if game.tick < 10 then return end
|
||||
spawn_turrets()
|
||||
end)
|
||||
end
|
||||
|
||||
if config.resource_refill_nearby.enabled then
|
||||
-- could have a flag in global that early returns if true, and reset it on_tick
|
||||
Event.on_nth_tick(36000, function()
|
||||
if game.tick < 10 then
|
||||
return
|
||||
end
|
||||
|
||||
for _, ore in pairs(game.players[1].surface.find_entities_filtered{position=game.players[1].force.get_spawn_position(game.players[1].surface), radius=config.resource_refill_nearby.range, name=config.resource_refill_nearby.resources_name}) do
|
||||
ore.amount = ore.amount + math.random(config.resource_refill_nearby.amount[1], config.resource_refill_nearby.amount[2])
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- When the first player joins create the spawn area
|
||||
Event.add(defines.events.on_player_created, function(event)
|
||||
if event.player_index ~= 1 then return end
|
||||
local player = game.players[event.player_index]
|
||||
local p = {x=0, y=0}
|
||||
local s = player.surface
|
||||
get_spawn_force()
|
||||
spawn_area(s, p)
|
||||
if config.pattern.enabled then spawn_pattern(s, p) end
|
||||
if config.water.enabled then spawn_water(s, p) end
|
||||
if config.afk_belts.enabled then spawn_belts(s, p) end
|
||||
if config.turrets.enabled then spawn_turrets() end
|
||||
if config.entities.enabled then spawn_entities(s, p) end
|
||||
if config.resource_tiles.enabled then spawn_resource_tiles(s) end
|
||||
if config.resource_patches.enabled then spawn_resource_patches(s) end
|
||||
player.teleport(p, s)
|
||||
end)
|
||||
|
||||
-- Way to access global table
|
||||
return turrets
|
||||
91
exp_legacy/module/modules/addons/station-auto-name.lua
Normal file
91
exp_legacy/module/modules/addons/station-auto-name.lua
Normal file
@@ -0,0 +1,91 @@
|
||||
---LuaPlayerBuiltEntityEventFilters
|
||||
---Events.set_event_filter(defines.events.on_built_entity, {{filter = "name", name = "fast-inserter"}})
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
local config = require 'config.station_auto_name' --- @dep config.chat_reply
|
||||
|
||||
--Credit to Cooldude2606 for using his lua magic to make this function.
|
||||
local directions = {
|
||||
['W'] = -0.875,
|
||||
['NW'] = -0.625,
|
||||
['N'] = -0.375,
|
||||
['NE'] = -0.125,
|
||||
['E'] = 0.125,
|
||||
['SE'] = 0.375,
|
||||
['S'] = 0.625,
|
||||
['SW'] = 0.875
|
||||
}
|
||||
|
||||
local function Angle(entity)
|
||||
local angle = math.atan2(entity.position.y, entity.position.x)/math.pi
|
||||
for direction, requiredAngle in pairs(directions) do
|
||||
if angle < requiredAngle then
|
||||
return direction
|
||||
end
|
||||
end
|
||||
return 'W'
|
||||
end
|
||||
|
||||
local custom_string = ' *'
|
||||
local custom_string_len = #custom_string
|
||||
|
||||
local function station_name_changer(event)
|
||||
local entity = event.created_entity
|
||||
local name = entity.name
|
||||
if name == "entity-ghost" then
|
||||
if entity.ghost_name ~= "train-stop" then return end
|
||||
local backername = entity.backer_name
|
||||
if backername ~= '' then
|
||||
entity.backer_name = backername..custom_string
|
||||
end
|
||||
|
||||
elseif name == "train-stop" then --only do the event if its a train stop
|
||||
local backername = entity.backer_name
|
||||
if backername:sub(-custom_string_len) == custom_string then
|
||||
entity.backer_name = backername:sub(1, -custom_string_len-1)
|
||||
return
|
||||
end
|
||||
|
||||
local boundingBox = entity.bounding_box
|
||||
-- expanded box for recourse search:
|
||||
local bounding2 = {{boundingBox.left_top.x-100 ,boundingBox.left_top.y-100} , {boundingBox.right_bottom.x+100, boundingBox.right_bottom.y+100 }}
|
||||
-- gets all resources in bounding_box2:
|
||||
local recourses = game.surfaces[1].find_entities_filtered{area = bounding2, type = "resource"}
|
||||
if #recourses > 0 then -- save cpu time if their are no recourses in bounding_box2
|
||||
local closest_distance
|
||||
local px, py = boundingBox.left_top.x, boundingBox.left_top.y
|
||||
local recourse_closed
|
||||
|
||||
--Check which recourse is closest
|
||||
for i, item in ipairs(recourses) do
|
||||
local dx, dy = px - item.bounding_box.left_top.x, py - item.bounding_box.left_top.y
|
||||
local distance = (dx*dx)+(dy*dy)
|
||||
if not closest_distance or distance < closest_distance then
|
||||
recourse_closed = item
|
||||
closest_distance = distance
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local item_name = recourse_closed.name
|
||||
if item_name then -- prevent errors if something went wrong
|
||||
local item_name2 = item_name:gsub("^%l", string.upper):gsub('-', ' ') -- removing the - and making first letter capital
|
||||
|
||||
local item_type = 'item'
|
||||
if item_name == 'crude-oil' then
|
||||
item_type = 'fluid'
|
||||
end
|
||||
|
||||
entity.backer_name = config.station_name:gsub('__icon__', '[img=' .. item_type .. '.' .. item_name .. ']')
|
||||
:gsub('__item_name__', item_name2)
|
||||
:gsub('__backer_name__', entity.backer_name)
|
||||
:gsub('__direction__', Angle(entity))
|
||||
:gsub('__x__', math.floor(entity.position.x))
|
||||
:gsub('__y__', math.floor(entity.position.y))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Add handler to robot and player build entities
|
||||
Event.add(defines.events.on_built_entity, station_name_changer)
|
||||
Event.add(defines.events.on_robot_built_entity, station_name_changer)
|
||||
125
exp_legacy/module/modules/addons/tree-decon.lua
Normal file
125
exp_legacy/module/modules/addons/tree-decon.lua
Normal file
@@ -0,0 +1,125 @@
|
||||
--- Makes trees which are marked for decon "decay" quickly to allow faster building
|
||||
-- @addon Tree-Decon
|
||||
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
local Global = require 'utils.global' --- @dep utils.global
|
||||
local Roles = require 'expcore.roles' --- @dep expcore.roles
|
||||
local Gui = require 'expcore.gui' --- @dep expcore.gui
|
||||
local PlayerData = require 'expcore.player_data' --- @dep expcore.player_data
|
||||
|
||||
-- Global queue used to store trees that need to be removed, also cache for player roles
|
||||
local cache = {}
|
||||
local tree_queue = { _head=0 }
|
||||
Global.register({tree_queue, cache}, function(tbl)
|
||||
tree_queue = tbl[1]
|
||||
cache = tbl[2]
|
||||
end)
|
||||
|
||||
local function get_permission(player_index)
|
||||
if cache[player_index] == nil then
|
||||
local player = game.players[player_index]
|
||||
if Roles.player_allowed(player, 'fast-tree-decon') then cache[player_index] = 'fast'
|
||||
elseif Roles.player_allowed(player, 'standard-decon') then cache[player_index] = 'standard'
|
||||
else cache[player_index] = player.force end
|
||||
end
|
||||
|
||||
return cache[player_index]
|
||||
end
|
||||
|
||||
-- Left menu button to toggle between fast decon and normal decon marking
|
||||
local HasEnabledDecon = PlayerData.Settings:combine('HasEnabledDecon')
|
||||
HasEnabledDecon:set_default(false)
|
||||
|
||||
Gui.toolbar_toggle_button("entity/tree-01", {'tree-decon.main-tooltip'}, function (player)
|
||||
return Roles.player_allowed(player, "fast-tree-decon")
|
||||
end)
|
||||
:on_event(Gui.events.on_toolbar_button_toggled, function(player, _, event)
|
||||
HasEnabledDecon:set(player, event.state)
|
||||
player.print{'tree-decon.toggle-msg', event.state and {'tree-decon.enabled'} or {'tree-decon.disabled'}}
|
||||
end)
|
||||
|
||||
|
||||
-- Add trees to queue when marked, only allows simple entities and for players with role permission
|
||||
Event.add(defines.events.on_marked_for_deconstruction, function(event)
|
||||
-- Check which type of decon a player is allowed
|
||||
local index = event.player_index
|
||||
if not index then return end
|
||||
|
||||
-- Check what should happen to this entity
|
||||
local entity = event.entity
|
||||
if not entity or not entity.valid then return end
|
||||
|
||||
-- Not allowed to decon this entity
|
||||
local last_user = entity.last_user
|
||||
local allow = get_permission(index)
|
||||
if last_user and allow ~= 'standard' and allow ~= 'fast' then
|
||||
entity.cancel_deconstruction(allow)
|
||||
return
|
||||
end
|
||||
|
||||
-- Allowed to decon this entity, but not fast
|
||||
if allow ~= 'fast' then return end
|
||||
|
||||
local player = game.get_player(index)
|
||||
if not HasEnabledDecon:get(player) then return end
|
||||
|
||||
-- Allowed fast decon on this entity, just trees
|
||||
local head = tree_queue._head + 1
|
||||
if not last_user and entity.type ~= 'cliff' then
|
||||
tree_queue[head] = entity
|
||||
tree_queue._head = head
|
||||
end
|
||||
|
||||
end)
|
||||
|
||||
-- Remove trees at random till the queue is empty
|
||||
Event.add(defines.events.on_tick, function()
|
||||
local head = tree_queue._head
|
||||
if head == 0 then return end
|
||||
|
||||
local max_remove = math.floor(head/100)+1
|
||||
local remove_count = math.random(0, max_remove)
|
||||
while remove_count > 0 and head > 0 do
|
||||
local remove_index = math.random(1, head)
|
||||
local entity = tree_queue[remove_index]
|
||||
tree_queue[remove_index] = tree_queue[head]
|
||||
head = head - 1
|
||||
if entity and entity.valid then
|
||||
remove_count = remove_count - 1
|
||||
entity.destroy()
|
||||
end
|
||||
end
|
||||
tree_queue._head = head
|
||||
end)
|
||||
|
||||
-- Clear the cache
|
||||
Event.on_nth_tick(300, function()
|
||||
for key, _ in pairs(cache) do
|
||||
cache[key] = nil
|
||||
end
|
||||
end)
|
||||
|
||||
-- Clear trees when hit with a car
|
||||
Event.add(defines.events.on_entity_damaged, function(event)
|
||||
if not (event.damage_type.name == 'impact' and event.force) then
|
||||
return
|
||||
end
|
||||
|
||||
if not (event.entity.type == 'tree' or event.entity.type == 'simple-entity') then
|
||||
return
|
||||
end
|
||||
|
||||
if (not event.cause) or (event.cause.type ~= 'car')then
|
||||
return
|
||||
end
|
||||
|
||||
local driver = event.cause.get_driver()
|
||||
if not driver then return end
|
||||
|
||||
local allow = get_permission(driver.player.index)
|
||||
if allow == "fast" and HasEnabledDecon:get(driver.player) then
|
||||
event.entity.destroy()
|
||||
else
|
||||
event.entity.order_deconstruction(event.force, driver.player)
|
||||
end
|
||||
end)
|
||||
Reference in New Issue
Block a user