You've already forked ComfyFactorio
mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2025-11-27 22:38:18 +02:00
More refactor and performance fixes
This commit is contained in:
@@ -3,55 +3,9 @@ local Public = require 'maps.infestation_islands.table'
|
||||
local BiterHealthBooster = require 'modules.biter_health_booster_v2'
|
||||
local Server = require 'utils.server'
|
||||
|
||||
local scale_units_by_health =
|
||||
{
|
||||
['small-biter'] = 1,
|
||||
['medium-biter'] = 0.75,
|
||||
['big-biter'] = 0.5,
|
||||
['behemoth-biter'] = 0.25,
|
||||
['small-spitter'] = 1,
|
||||
['medium-spitter'] = 0.75,
|
||||
['big-spitter'] = 0.5,
|
||||
['behemoth-spitter'] = 0.25,
|
||||
|
||||
['small-wriggler-pentapod'] = 1,
|
||||
['medium-wriggler-pentapod'] = 0.75,
|
||||
['big-wriggler-pentapod'] = 0.5,
|
||||
['small-strafer-pentapod'] = 1,
|
||||
['medium-strafer-pentapod'] = 0.75,
|
||||
['big-strafer-pentapod'] = 0.5,
|
||||
|
||||
}
|
||||
|
||||
local scale_spawners_by_health =
|
||||
{
|
||||
['biter-spawner'] = 0.5,
|
||||
['spitter-spawner'] = 0.5,
|
||||
['gleba-spawner-small'] = 0.5,
|
||||
['gleba-spawner'] = 0.5,
|
||||
}
|
||||
|
||||
local scale_worms_by_health =
|
||||
{
|
||||
['land-mine'] = 0.5, -- not active as of now
|
||||
['gun-turret'] = 0.5, -- not active as of now
|
||||
['flamethrower-turret'] = 0.4, -- not active as of now
|
||||
['artillery-turret'] = 0.25, -- not active as of now
|
||||
['small-worm-turret'] = 0.8,
|
||||
['medium-worm-turret'] = 0.6,
|
||||
['big-worm-turret'] = 0.3,
|
||||
['behemoth-worm-turret'] = 0.3
|
||||
}
|
||||
|
||||
local round = math.round
|
||||
local floor = math.floor
|
||||
local random = math.random
|
||||
|
||||
local spawn_amount_rolls = {}
|
||||
for a = 48, 1, -1 do
|
||||
spawn_amount_rolls[#spawn_amount_rolls + 1] = floor(a ^ 5)
|
||||
end
|
||||
|
||||
local random_particles =
|
||||
{
|
||||
'dirt-2-stone-particle-medium',
|
||||
@@ -143,17 +97,13 @@ local function roll_spawner(level)
|
||||
end
|
||||
|
||||
local function roll_health_boost(level)
|
||||
if not level or level <= 3 then
|
||||
if not level or level <= 1 then
|
||||
return 1
|
||||
elseif level <= 6 then
|
||||
return 1.5
|
||||
elseif level <= 10 then
|
||||
return 2
|
||||
elseif level > 10 then
|
||||
return 3
|
||||
end
|
||||
return 1 + (level ^ 1.25) * 0.15
|
||||
end
|
||||
|
||||
|
||||
local function spawn_spawner(data)
|
||||
local alive_enemies = Public.get('alive_enemies')
|
||||
local max_biters_per_island = Public.get('max_biters_per_island')
|
||||
@@ -185,20 +135,10 @@ local function spawn_spawner(data)
|
||||
return
|
||||
end
|
||||
|
||||
alive_enemies = Public.get('alive_enemies')
|
||||
|
||||
Public.set('alive_enemies', alive_enemies + 1)
|
||||
|
||||
local health_boost = roll_health_boost(current_level) or 1
|
||||
local health_boost = roll_health_boost(current_level + 5) or 1
|
||||
|
||||
if random(1, 30) == 1 then
|
||||
BiterHealthBooster.add_boss_unit(unit, health_boost, 0.38)
|
||||
else
|
||||
local final_health = round(health_boost * scale_spawners_by_health[unit.name], 3)
|
||||
if final_health < 1 then
|
||||
final_health = 1
|
||||
end
|
||||
BiterHealthBooster.add_unit(unit, final_health)
|
||||
end
|
||||
return true
|
||||
end
|
||||
@@ -234,20 +174,10 @@ local function spawn_biters(data)
|
||||
return
|
||||
end
|
||||
|
||||
alive_enemies = Public.get('alive_enemies')
|
||||
|
||||
Public.set('alive_enemies', alive_enemies + 1)
|
||||
|
||||
local health_boost = roll_health_boost(current_level) or 1
|
||||
local health_boost = roll_health_boost(current_level + 5) or 1
|
||||
|
||||
if random(1, 30) == 1 then
|
||||
BiterHealthBooster.add_boss_unit(unit, health_boost, 0.38)
|
||||
else
|
||||
local final_health = round(health_boost * scale_units_by_health[unit.name], 3)
|
||||
if final_health < 1 then
|
||||
final_health = 1
|
||||
end
|
||||
BiterHealthBooster.add_unit(unit, final_health)
|
||||
end
|
||||
|
||||
local market_target = Public.get('market_target')
|
||||
@@ -302,7 +232,7 @@ local function spawn_tech(data)
|
||||
return
|
||||
end
|
||||
|
||||
local health_boost = roll_health_boost(current_level) or 1
|
||||
local health_boost = roll_health_boost(current_level + 5) or 1
|
||||
|
||||
|
||||
local unit = surface.create_entity({ name = unit_to_create, position = position, force = data.force or 'enemy', quality = data.quality or 'normal' })
|
||||
@@ -312,12 +242,6 @@ local function spawn_tech(data)
|
||||
|
||||
if random(1, 30) == 1 then
|
||||
BiterHealthBooster.add_boss_unit(unit, health_boost, 0.38)
|
||||
else
|
||||
local final_health = round(health_boost * 0.5, 3)
|
||||
if final_health < 1 then
|
||||
final_health = 1
|
||||
end
|
||||
BiterHealthBooster.add_unit(unit, final_health)
|
||||
end
|
||||
return true
|
||||
end
|
||||
@@ -349,23 +273,18 @@ local function spawn_worms(data)
|
||||
if not unit or not unit.valid then
|
||||
return
|
||||
end
|
||||
alive_enemies = Public.get('alive_enemies')
|
||||
Public.set('alive_enemies', alive_enemies + 1)
|
||||
|
||||
local health_boost = roll_health_boost(current_level) or 1
|
||||
local health_boost = roll_health_boost(current_level + 5) or 1
|
||||
|
||||
if random(1, 30) == 1 then
|
||||
BiterHealthBooster.add_boss_unit(unit, health_boost, 0.38)
|
||||
else
|
||||
local final_health = round(health_boost * scale_worms_by_health[unit.name], 3)
|
||||
if final_health < 1 then
|
||||
final_health = 1
|
||||
end
|
||||
|
||||
BiterHealthBooster.add_unit(unit, final_health)
|
||||
end
|
||||
end
|
||||
|
||||
---@param surface LuaSurface
|
||||
---@param position MapPosition
|
||||
---@param count number
|
||||
---@param force string
|
||||
function Public.buried_spawner(surface, position, count, force)
|
||||
if not (surface and surface.valid) then
|
||||
return
|
||||
@@ -386,7 +305,7 @@ function Public.buried_spawner(surface, position, count, force)
|
||||
|
||||
local buried_biters = Public.get('buried_biters')
|
||||
|
||||
for t = 1, 60, 1 do
|
||||
for t = 1, 220, 1 do
|
||||
if not buried_biters[game.tick + t] then
|
||||
buried_biters[game.tick + t] = {}
|
||||
end
|
||||
@@ -397,7 +316,7 @@ function Public.buried_spawner(surface, position, count, force)
|
||||
data = { surface = surface, position = { x = position.x, y = position.y }, amount = math.ceil(t * 0.05) }
|
||||
}
|
||||
|
||||
if t == 60 then
|
||||
if t == 220 then
|
||||
if count == 1 then
|
||||
buried_biters[game.tick + t][#buried_biters[game.tick + t] + 1] =
|
||||
{
|
||||
@@ -419,6 +338,11 @@ function Public.buried_spawner(surface, position, count, force)
|
||||
end
|
||||
end
|
||||
|
||||
---@param surface LuaSurface
|
||||
---@param position MapPosition
|
||||
---@param count number
|
||||
---@param force string
|
||||
---@param quality string
|
||||
function Public.buried_biter(surface, position, count, force, quality)
|
||||
if not (surface and surface.valid) then
|
||||
return
|
||||
@@ -439,7 +363,7 @@ function Public.buried_biter(surface, position, count, force, quality)
|
||||
|
||||
local buried_biters = Public.get('buried_biters')
|
||||
|
||||
for t = 1, 60, 1 do
|
||||
for t = 1, 220, 1 do
|
||||
if not buried_biters[game.tick + t] then
|
||||
buried_biters[game.tick + t] = {}
|
||||
end
|
||||
@@ -450,7 +374,7 @@ function Public.buried_biter(surface, position, count, force, quality)
|
||||
data = { surface = surface, position = { x = position.x, y = position.y }, amount = math.ceil(t * 0.05) }
|
||||
}
|
||||
|
||||
if t == 60 then
|
||||
if t == 220 then
|
||||
if count == 1 then
|
||||
buried_biters[game.tick + t][#buried_biters[game.tick + t] + 1] =
|
||||
{
|
||||
@@ -472,6 +396,11 @@ function Public.buried_biter(surface, position, count, force, quality)
|
||||
end
|
||||
end
|
||||
|
||||
---@param surface LuaSurface
|
||||
---@param position MapPosition
|
||||
---@param count number
|
||||
---@param force string
|
||||
---@param quality string
|
||||
function Public.buried_tech(surface, position, count, force, quality)
|
||||
if not (surface and surface.valid) then
|
||||
return
|
||||
@@ -492,7 +421,7 @@ function Public.buried_tech(surface, position, count, force, quality)
|
||||
|
||||
local buried_biters = Public.get('buried_biters')
|
||||
|
||||
for t = 1, 60, 1 do
|
||||
for t = 1, 220, 1 do
|
||||
if not buried_biters[game.tick + t] then
|
||||
buried_biters[game.tick + t] = {}
|
||||
end
|
||||
@@ -503,7 +432,7 @@ function Public.buried_tech(surface, position, count, force, quality)
|
||||
data = { surface = surface, position = { x = position.x, y = position.y }, amount = math.ceil(t * 0.05) }
|
||||
}
|
||||
|
||||
if t == 60 then
|
||||
if t == 220 then
|
||||
if count == 1 then
|
||||
buried_biters[game.tick + t][#buried_biters[game.tick + t] + 1] =
|
||||
{
|
||||
@@ -525,6 +454,9 @@ function Public.buried_tech(surface, position, count, force, quality)
|
||||
end
|
||||
end
|
||||
|
||||
---@param surface LuaSurface
|
||||
---@param position MapPosition
|
||||
---@param quality string
|
||||
function Public.buried_worm(surface, position, quality)
|
||||
if not (surface and surface.valid) then
|
||||
return
|
||||
@@ -541,7 +473,7 @@ function Public.buried_worm(surface, position, quality)
|
||||
|
||||
local buried_biters = Public.get('buried_biters')
|
||||
|
||||
for t = 1, 60, 1 do
|
||||
for t = 1, 220, 1 do
|
||||
if not buried_biters[game.tick + t] then
|
||||
buried_biters[game.tick + t] = {}
|
||||
end
|
||||
@@ -552,7 +484,7 @@ function Public.buried_worm(surface, position, quality)
|
||||
data = { surface = surface, position = { x = position.x, y = position.y }, amount = math.ceil(t * 0.05) }
|
||||
}
|
||||
|
||||
if t == 60 then
|
||||
if t == 220 then
|
||||
buried_biters[game.tick + t][#buried_biters[game.tick + t] + 1] =
|
||||
{
|
||||
callback = 'spawn_worms',
|
||||
|
||||
1159
maps/infestation_islands/callbacks.lua
Normal file
1159
maps/infestation_islands/callbacks.lua
Normal file
File diff suppressed because it is too large
Load Diff
425
maps/infestation_islands/commands.lua
Normal file
425
maps/infestation_islands/commands.lua
Normal file
@@ -0,0 +1,425 @@
|
||||
local Public = require 'maps.infestation_islands.table'
|
||||
local Server = require 'utils.server'
|
||||
local Color = require 'utils.color_presets'
|
||||
local Difficulty = require 'modules.difficulty_vote_by_amount'
|
||||
local Scheduler = require 'utils.scheduler'
|
||||
local Commands = require 'utils.commands'
|
||||
local Discord = require 'utils.discord_handler'
|
||||
|
||||
Commands.new('toggle_auto_create_islands', 'Toggles the autogenerate islands.')
|
||||
:require_admin()
|
||||
:require_validation('Utilize this only when testing the map generation!')
|
||||
:add_parameter('state', false, 'boolean')
|
||||
:callback(
|
||||
function (player, state)
|
||||
if not state then
|
||||
Public.set('auto_create_islands', false)
|
||||
player.print('The autogenerate islands has been disabled!', { color = Color.warning })
|
||||
return
|
||||
end
|
||||
|
||||
Public.set('auto_create_islands', true)
|
||||
player.print('The autogenerate islands has been enabled!', { color = Color.warning })
|
||||
local this = Public.get()
|
||||
if this.market_target then
|
||||
this.position = this.market_target.position
|
||||
else
|
||||
this.position = { x = 0, y = 0 }
|
||||
end
|
||||
this.current_level = this.current_level + 1
|
||||
this.attack_grace_period = game.tick + 54000
|
||||
this.cooldown_complete_level = game.tick + (60 * 60)
|
||||
this.alive_enemies = 999
|
||||
Scheduler.new(1, Public.init_next_island_token)
|
||||
:set_data({ surface = game.surfaces[1], position = this.position })
|
||||
end
|
||||
)
|
||||
|
||||
|
||||
Commands.new('show_centered_gps', 'Shows the centered points of the map.')
|
||||
:require_admin()
|
||||
:callback(
|
||||
function (player)
|
||||
local this = Public.get()
|
||||
for level, point in pairs(this.islands_data) do
|
||||
player.print('Level ' .. level .. ':')
|
||||
player.print('[gps=' .. point.position.x .. ',' .. point.position.y .. ',' .. player.surface.name .. ']')
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
Commands.new('set_biter_count', 'Sets the biter count.')
|
||||
:require_admin()
|
||||
:add_parameter('count', false, 'number')
|
||||
:callback(
|
||||
function (player, count)
|
||||
local this = Public.get()
|
||||
this.max_biters_per_island = count
|
||||
player.print('The biter count has been set to ' .. count .. '!', { color = Color.warning })
|
||||
end
|
||||
)
|
||||
|
||||
Commands.new('send_enemies', 'Sends enemies to the market.')
|
||||
:require_admin()
|
||||
:callback(
|
||||
function (player)
|
||||
Public.set_multi_command()
|
||||
player.print('Enemies have been sent to the market!', { color = Color.warning })
|
||||
return true
|
||||
end
|
||||
)
|
||||
|
||||
Commands.new('toggle_drift_corpses_toward_beach', 'Toggles the drift corpses toward beach.')
|
||||
:require_admin()
|
||||
:add_parameter('state', false, 'boolean')
|
||||
:callback(
|
||||
function (player, state)
|
||||
Public.set('drift_corpses_toward_beach_enabled', state)
|
||||
player.print('The drift corpses toward beach has been ' .. (state and 'enabled' or 'disabled') .. '!', { color = Color.warning })
|
||||
end
|
||||
)
|
||||
|
||||
Commands.new('set_infinite_ammo_tick', 'Sets the infinite ammo tick.')
|
||||
:require_admin()
|
||||
:add_parameter('tick', false, 'number')
|
||||
:callback(
|
||||
function (player, tick)
|
||||
if tick < 10 then
|
||||
return player.print('The infinite ammo tick must be at least 10 ticks!', { color = Color.warning })
|
||||
end
|
||||
if tick > 100 then
|
||||
return player.print('The infinite ammo tick must be less than 100 ticks!', { color = Color.warning })
|
||||
end
|
||||
Public.set('infinite_ammo_tick', tick)
|
||||
player.print('The infinite ammo tick has been set to ' .. tick .. '!', { color = Color.warning })
|
||||
end
|
||||
)
|
||||
|
||||
Commands.new('skip_difficulty_vote', 'Skips the difficulty vote.')
|
||||
:require_admin()
|
||||
:callback(
|
||||
function (player)
|
||||
Difficulty.set_poll_closing_timeout(game.tick)
|
||||
player.print('The difficulty vote has been skipped!', { color = Color.warning })
|
||||
end
|
||||
)
|
||||
|
||||
Commands.new('skip_voting_to_progress', 'Toggles the voting to progress.')
|
||||
:require_admin()
|
||||
:add_parameter('state', false, 'boolean')
|
||||
:callback(
|
||||
function (player, state)
|
||||
if not state then
|
||||
Public.set('voting_to_progress_enabled', true)
|
||||
player.print('The voting to progress has been enabled!', { color = Color.warning })
|
||||
return
|
||||
end
|
||||
|
||||
Public.set('voting_to_progress_enabled', false)
|
||||
player.print('The voting to progress has been disabled!', { color = Color.warning })
|
||||
end
|
||||
)
|
||||
|
||||
Commands.new('reward_level', 'Rewards the level.')
|
||||
:require_admin()
|
||||
:callback(
|
||||
function (player)
|
||||
local level = Public.get('current_level')
|
||||
local center_position = Public.get('islands_data')[level]
|
||||
if not center_position then
|
||||
center_position =
|
||||
{
|
||||
position = { x = 0, y = 0 }
|
||||
}
|
||||
end
|
||||
Public.reward_level(game.surfaces[1], center_position)
|
||||
player.print('Level ' .. level .. ' has been rewarded!', { color = Color.warning })
|
||||
end
|
||||
)
|
||||
|
||||
Commands.new('set_clear_items_on_ground', 'Sets the clear items on ground state.')
|
||||
:require_admin()
|
||||
:add_parameter('state', false, 'boolean')
|
||||
:callback(
|
||||
function (player, state)
|
||||
Public.set('clear_items_on_ground_state', state)
|
||||
player.print('Clear items on ground has been ' .. (state and 'enabled' or 'disabled') .. '!', { color = Color.warning })
|
||||
end
|
||||
)
|
||||
|
||||
Commands.new('toggle_check_surface_daytime', 'Checks the surface daytime if an attack towards the market should be sent.')
|
||||
:require_admin()
|
||||
:add_parameter('state', false, 'boolean')
|
||||
:callback(
|
||||
function (player, state)
|
||||
Public.set('check_surface_daytime_for_attacks', state)
|
||||
player.print('The check surface daytime has been ' .. (state and 'enabled' or 'disabled') .. '!', { color = Color.warning })
|
||||
end
|
||||
)
|
||||
|
||||
Commands.new('toggle_disable_multi_command_attack', 'Disables waves of enemies from being sent to the market.')
|
||||
:require_admin()
|
||||
:add_parameter('state', false, 'boolean')
|
||||
:callback(
|
||||
function (player, state)
|
||||
Public.set('disable_multi_command_attack', state)
|
||||
player.print('The disable multi command attack has been ' .. (state and 'enabled' or 'disabled') .. '!', { color = Color.warning })
|
||||
end
|
||||
)
|
||||
|
||||
Commands.new('scenario', 'Usable only for admins - controls the scenario!')
|
||||
:require_admin()
|
||||
:require_validation()
|
||||
:add_parameter('reset', false, 'string')
|
||||
:callback(
|
||||
function (player, action)
|
||||
local this = Public.get()
|
||||
|
||||
if action == 'reset' then
|
||||
goto continue
|
||||
else
|
||||
player.print('Invalid action.')
|
||||
return false
|
||||
end
|
||||
|
||||
::continue::
|
||||
|
||||
if action == 'reset' then
|
||||
this.reset_are_you_sure = nil
|
||||
if player and player.valid then
|
||||
game.print(Public.island_keeper .. player.name .. ', has reset the game!',
|
||||
{ color = Public.command_color })
|
||||
Discord.send_notification(
|
||||
{
|
||||
title = "Game reset",
|
||||
description = player.name .. ' has reset the game!',
|
||||
color = "success",
|
||||
fields =
|
||||
{
|
||||
{
|
||||
title = "Server",
|
||||
description = Public.discord_name,
|
||||
inline = "false"
|
||||
}
|
||||
}
|
||||
})
|
||||
else
|
||||
game.print(Public.island_keeper .. 'server, has reset the game!', { color = Public.command_color })
|
||||
Discord.send_notification(
|
||||
{
|
||||
title = "Game reset",
|
||||
description = 'Server has reset the game!',
|
||||
color = "success",
|
||||
fields =
|
||||
{
|
||||
{
|
||||
title = "Server",
|
||||
description = Public.discord_name,
|
||||
inline = "false"
|
||||
}
|
||||
}
|
||||
})
|
||||
end
|
||||
this.game_lost = true
|
||||
this.game_reset_tick = 1
|
||||
player.print('Game has been reset!')
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
Commands.new('server', 'Usable only for admins - controls the server!')
|
||||
:require_admin()
|
||||
:require_validation()
|
||||
:add_parameter('restart/shutdown/restart-now', false, 'string')
|
||||
:callback(
|
||||
function (player, action)
|
||||
local this = Public.get()
|
||||
|
||||
if action == 'restart' or action == 'shutdown' or action == 'restart-now' then
|
||||
goto continue
|
||||
else
|
||||
player.print('Invalid action.')
|
||||
return false
|
||||
end
|
||||
|
||||
::continue::
|
||||
|
||||
if action == 'restart' then
|
||||
if this.restart then
|
||||
this.reset_are_you_sure = nil
|
||||
this.restart = false
|
||||
this.soft_reset = true
|
||||
Discord.send_notification(
|
||||
{
|
||||
title = "Soft-reset enabled",
|
||||
description = player.name .. ' has enabled soft-reset!',
|
||||
color = "info",
|
||||
fields =
|
||||
{
|
||||
{
|
||||
title = "Server",
|
||||
description = Public.discord_name,
|
||||
inline = "false"
|
||||
}
|
||||
}
|
||||
})
|
||||
player.print('Soft-reset is enabled.')
|
||||
else
|
||||
this.reset_are_you_sure = nil
|
||||
this.restart = true
|
||||
this.soft_reset = false
|
||||
if this.shutdown then
|
||||
this.shutdown = false
|
||||
end
|
||||
Discord.send_notification(
|
||||
{
|
||||
title = "Soft-reset disabled",
|
||||
description = player.name .. ' has disabled soft-reset! Restart will happen from scenario.',
|
||||
color = "warning",
|
||||
fields =
|
||||
{
|
||||
{
|
||||
title = "Server",
|
||||
description = Public.discord_name,
|
||||
inline = "false"
|
||||
}
|
||||
}
|
||||
})
|
||||
player.print('Soft-reset is disabled! Server will restart from scenario to load new changes.')
|
||||
end
|
||||
elseif action == 'restart-now' then
|
||||
this.reset_are_you_sure = nil
|
||||
Server.start_scenario('Infestation_Islands')
|
||||
Discord.send_notification(
|
||||
{
|
||||
title = "Server restarted",
|
||||
description = player.name .. ' restarted the server.',
|
||||
color = "success",
|
||||
fields =
|
||||
{
|
||||
{
|
||||
title = "Server",
|
||||
description = Public.discord_name,
|
||||
inline = "false"
|
||||
}
|
||||
}
|
||||
})
|
||||
player.print('Restarted the server.')
|
||||
elseif action == 'shutdown' then
|
||||
if this.shutdown then
|
||||
this.reset_are_you_sure = nil
|
||||
this.shutdown = false
|
||||
this.soft_reset = true
|
||||
Discord.send_notification(
|
||||
{
|
||||
title = "Soft-reset enabled",
|
||||
description = player.name .. ' has enabled soft-reset. Server will NOT shutdown!',
|
||||
color = "success",
|
||||
fields =
|
||||
{
|
||||
{
|
||||
title = "Server",
|
||||
description = Public.discord_name,
|
||||
inline = "false"
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
player.print('Soft-reset is enabled.')
|
||||
else
|
||||
this.reset_are_you_sure = nil
|
||||
this.shutdown = true
|
||||
this.soft_reset = false
|
||||
if this.restart then
|
||||
this.restart = false
|
||||
end
|
||||
|
||||
Discord.send_notification(
|
||||
{
|
||||
title = "Soft-reset disabled",
|
||||
description = player.name .. ' has disabled soft-reset. Server will shutdown!',
|
||||
color = "warning",
|
||||
fields =
|
||||
{
|
||||
{
|
||||
title = "Server",
|
||||
description = Public.discord_name,
|
||||
inline = "false"
|
||||
}
|
||||
}
|
||||
})
|
||||
player.print('Soft-reset is disabled! Server will shutdown.')
|
||||
end
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
Commands.new('switch_game_mode', 'Switches the game mode - for admins.')
|
||||
:require_admin()
|
||||
:add_parameter('state', false, 'boolean')
|
||||
:callback(
|
||||
function (player, state)
|
||||
if state then
|
||||
Public.set('game_over_if_market_dies', true)
|
||||
player.print('Game mode switched!')
|
||||
player.print('The game will be over if any market dies!', { color = Color.warning })
|
||||
else
|
||||
Public.set('game_over_if_market_dies', false)
|
||||
player.print('Game mode switched!')
|
||||
player.print('The biters will try to conquer islands, but the game will not be over if any market dies unless it\'s the last one!', { color = Color.warning })
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
Commands.new('do_buried_biters', 'Spawns some biters at a given explored level!')
|
||||
:require_admin()
|
||||
:add_parameter('level', false, 'number')
|
||||
:add_parameter('count', false, 'number')
|
||||
:callback(
|
||||
function (player, level, count)
|
||||
Public.do_buried_biters(level)
|
||||
local islands_data = Public.get('islands_data')
|
||||
local last_level = Public.get('current_level')
|
||||
local position = islands_data[level] and islands_data[level].position
|
||||
if not position then
|
||||
return player.print('Level ' .. level .. ' has not been explored yet!', { color = Color.warning })
|
||||
end
|
||||
|
||||
if level > last_level then
|
||||
return player.print('Level ' .. level .. ' is not the last level!', { color = Color.warning })
|
||||
end
|
||||
|
||||
Public.buried_biter(game.surfaces[1], position, count, 'enemy', Public.qualities[math.random(1, #Public.qualities)])
|
||||
player.print('Buried biters have been spawned at level ' .. level .. '!', { color = Color.warning })
|
||||
end
|
||||
)
|
||||
|
||||
|
||||
Commands.new('reverse_start_position', 'Reverses the start position from where the snake should start at.')
|
||||
:require_admin()
|
||||
:add_parameter('state', false, 'boolean')
|
||||
:callback(
|
||||
function (player, state)
|
||||
Public.set('reverse_start_position', state)
|
||||
if not state then
|
||||
return player.print('The snake will start from the parent island and move towards the new island!', { color = Color.warning })
|
||||
else
|
||||
return player.print('The snake will start from the new island and move towards the parent island!', { color = Color.warning })
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
Commands.new('set_auto_generate_upon_idle', 'Sets whether the next island should be automatically generated upon idle.')
|
||||
:require_admin()
|
||||
:add_parameter('state', false, 'boolean')
|
||||
:callback(
|
||||
function (player, state)
|
||||
if not state then
|
||||
Public.set('auto_generate_upon_idle', false)
|
||||
player.print('New islands will not be automatically generated upon idle!', { color = Color.warning })
|
||||
else
|
||||
Public.set('auto_generate_upon_idle', true)
|
||||
player.print('New islands will be automatically generated upon idle!', { color = Color.warning })
|
||||
end
|
||||
end
|
||||
)
|
||||
@@ -1,8 +1,10 @@
|
||||
local Public = require 'maps.infestation_islands.table'
|
||||
Public.func = require 'maps.infestation_islands.func'
|
||||
Public.functions = require 'maps.infestation_islands.functions'
|
||||
Public.callbacks = require 'maps.infestation_islands.callbacks'
|
||||
Public.basic_markets = require 'maps.infestation_islands.basic_markets'
|
||||
Public.island_settings = require 'maps.infestation_islands.island_settings'
|
||||
Public.loot = require 'maps.infestation_islands.loot'
|
||||
Public.buried_biters = require 'maps.infestation_islands.buried_biters'
|
||||
Public.commands = require 'maps.infestation_islands.commands'
|
||||
|
||||
return Public
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
1719
maps/infestation_islands/functions.lua
Normal file
1719
maps/infestation_islands/functions.lua
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,14 +1,14 @@
|
||||
--created by Gerkiz
|
||||
local Public = require 'maps.infestation_islands.core'
|
||||
local Event = require 'utils.event'
|
||||
local Func = Public.func
|
||||
local Task = require 'utils.task_token'
|
||||
local Func = Public.functions
|
||||
local Scheduler = require 'utils.scheduler'
|
||||
local Difficulty = require 'modules.difficulty_vote_by_amount'
|
||||
local Server = require 'utils.server'
|
||||
local Gui = require 'utils.gui'
|
||||
|
||||
local stage_gui_name = Gui.uid()
|
||||
local random = math.random
|
||||
|
||||
if not script.active_mods.quality then
|
||||
error('Quality mod is not enabled!')
|
||||
@@ -48,7 +48,8 @@ local function reset_player(player)
|
||||
end
|
||||
|
||||
local reset_players_token =
|
||||
Task.register(
|
||||
Scheduler.register_function(
|
||||
'reset_players_token',
|
||||
function ()
|
||||
local surface = game.get_surface(1)
|
||||
|
||||
@@ -82,69 +83,82 @@ end
|
||||
|
||||
local function create_stage_gui(player)
|
||||
local button = get_top_frame(player, stage_gui_name)
|
||||
if button then
|
||||
return
|
||||
end
|
||||
if button and button.valid then button.destroy() end
|
||||
|
||||
if Gui.get_mod_gui_top_frame() then
|
||||
local frame =
|
||||
local element =
|
||||
Gui.add_mod_button(
|
||||
player,
|
||||
{
|
||||
type = 'frame',
|
||||
name = stage_gui_name,
|
||||
caption = ' '
|
||||
}
|
||||
)
|
||||
if frame then
|
||||
frame.style.minimal_height = 36
|
||||
frame.style.maximal_height = 36
|
||||
frame.style.minimal_width = 140
|
||||
frame.style.maximal_width = 420
|
||||
frame.style.font_color = { r = 155, g = 85, b = 25 }
|
||||
frame.style.font = 'heading-2'
|
||||
if element and element.valid then
|
||||
local style = element.style
|
||||
|
||||
style.minimal_height = 36
|
||||
style.maximal_height = 36
|
||||
style.padding = 0
|
||||
local label = element.add({ type = 'label', caption = ' ', name = 'label' })
|
||||
label.style.font_color = { r = 0.88, g = 0.88, b = 0.88 }
|
||||
label.style.font = 'heading-1'
|
||||
end
|
||||
else
|
||||
local element = player.gui.top.add({ type = 'frame', name = stage_gui_name, caption = ' ' })
|
||||
if element and element.valid then
|
||||
local style = element.style
|
||||
style.minimal_height = 54
|
||||
style.maximal_height = 54
|
||||
style.minimal_width = 140
|
||||
style.maximal_width = 420
|
||||
style.top_padding = 12
|
||||
style.left_padding = 4
|
||||
style.right_padding = 4
|
||||
style.bottom_padding = 2
|
||||
style.font_color = { r = 155, g = 85, b = 25 }
|
||||
style.font = 'default-large-bold'
|
||||
style.padding = 0
|
||||
|
||||
local label = element.add({ type = 'label', caption = ' ', name = 'label' })
|
||||
label.style.font_color = { r = 0.88, g = 0.88, b = 0.88 }
|
||||
label.style.font = 'heading-1'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function update_stage_gui(caption_override)
|
||||
local function update_stage_gui()
|
||||
local this = Public.get()
|
||||
if not this.stages then
|
||||
return
|
||||
end
|
||||
local caption = 'Level: ' .. this.current_level
|
||||
caption = caption .. ' | Stage: '
|
||||
local stage = this.current_stage
|
||||
local caption = 'Level: '
|
||||
local stage = this.current_level
|
||||
if stage > #this.stages - 1 then
|
||||
stage = #this.stages - 1
|
||||
end
|
||||
local islands_data = Public.get('islands_data')
|
||||
local island_data = islands_data[stage]
|
||||
caption = caption .. stage
|
||||
caption = caption .. '/'
|
||||
caption = caption .. #this.stages - 1
|
||||
if this.alive_enemies == 0 then
|
||||
local tooltip
|
||||
if not (island_data and island_data.spawned_biters) then
|
||||
caption = caption .. ' | Generating...'
|
||||
tooltip = 'The biters are still generating on the island. Please wait for them to finish.'
|
||||
elseif (this.auto_generate_upon_idle and island_data and island_data.spawned_biters and island_data.completed and this.time_until_next_island_is_created and this.time_until_next_island_is_created > game.tick and Difficulty.has_votes_ended()) then
|
||||
caption = caption .. ' | Level cleared!'
|
||||
caption = caption .. ' | [entity=small-biter,quality=' .. Public.qualities[random(1, #Public.qualities)] .. ']: ' .. Public.normalize_time_until_next_island_is_created()
|
||||
tooltip = 'The next island will be generated in ' .. Public.normalize_time_until_next_island_is_created() .. '.\nUnless you progress to the next island, it will be generated automatically.\nIf you do not progress to the next island, you will not be able to reroll the next island market.\nMarket rerolls are unlocked when you manually progress to the next island.'
|
||||
elseif (island_data and island_data.spawned_biters and island_data.completed) then
|
||||
caption = caption .. ' | Level cleared!'
|
||||
tooltip = 'Defenses would sure be helpful right now.\nVotes close in ' .. Difficulty.get_closing_timeout() .. ' seconds.'
|
||||
elseif (this.auto_generate_upon_idle and island_data and island_data.auto_generated_bridge == false) then
|
||||
caption = caption .. ' | Bugs remaining: '
|
||||
caption = caption .. this.alive_enemies
|
||||
caption = caption .. ' | [entity=small-biter,quality=' .. Public.qualities[random(1, #Public.qualities)] .. ']: ' .. Public.normalize_time_until_next_island_is_created()
|
||||
tooltip = 'The bridge to the next island will be generated in ' .. Public.normalize_time_until_next_island_is_created() .. '.\nUnless you progress to the next island, it will be generated automatically.\nMarket rerolls have been removed for the next island.\nMarket rerolls are unlocked when you manually progress to the next island.'
|
||||
else
|
||||
caption = caption .. ' | Bugs remaining: '
|
||||
caption = caption .. this.alive_enemies
|
||||
tooltip = 'Vanquish the biters to capture the island. ' .. this.alive_enemies .. ' biters remaining.'
|
||||
end
|
||||
|
||||
for _, player in pairs(game.connected_players) do
|
||||
local frame = get_top_frame(player, stage_gui_name)
|
||||
if frame then
|
||||
frame.caption = caption_override or caption
|
||||
if frame and frame.valid and frame.label and frame.label.valid then
|
||||
frame.label.caption = this.top_label_caption_override or caption
|
||||
frame.label.tooltip = tooltip
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -172,6 +186,16 @@ end
|
||||
local function clear_surface()
|
||||
local surface = game.get_surface(1)
|
||||
surface.clear()
|
||||
|
||||
local planet = game.planets['nauvis']
|
||||
local platforms = planet.get_space_platforms('player')
|
||||
if platforms then
|
||||
for _, platform in pairs(platforms) do
|
||||
if platform and platform.valid then
|
||||
platform.destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function on_player_joined_game(event)
|
||||
@@ -195,7 +219,9 @@ local function has_the_game_ended(this)
|
||||
end
|
||||
|
||||
game.forces.enemy.set_friend('player', true)
|
||||
game.forces.enemy.set_cease_fire('player', true)
|
||||
game.forces.player.set_friend('enemy', true)
|
||||
game.forces.player.set_cease_fire('enemy', true)
|
||||
|
||||
this.game_reset_tick = this.game_reset_tick - 1
|
||||
if this.game_reset_tick % 600 == 0 then
|
||||
@@ -224,7 +250,7 @@ local function has_the_game_ended(this)
|
||||
this.ammo_chest = nil
|
||||
end
|
||||
|
||||
for _, market_data in pairs(this.spawned_markets) do
|
||||
for _, market_data in pairs(this.islands_data) do
|
||||
if market_data and market_data.market and market_data.market.valid then
|
||||
if market_data.render_protect_text then
|
||||
market_data.render_protect_text.destroy()
|
||||
@@ -235,16 +261,17 @@ local function has_the_game_ended(this)
|
||||
market_data.render_checkpoint_text = nil
|
||||
end
|
||||
market_data.market.destroy()
|
||||
market_data.market = nil
|
||||
end
|
||||
end
|
||||
|
||||
this.game_reset_tick = nil
|
||||
this.game_lost = false
|
||||
this.game_won = false
|
||||
Scheduler.can_run_scheduler(false)
|
||||
Scheduler.clear_tasks()
|
||||
clear_surface()
|
||||
Public.on_init()
|
||||
Task.set_timeout_in_ticks(500, reset_players_token)
|
||||
Scheduler.new(500, reset_players_token)
|
||||
return
|
||||
end
|
||||
|
||||
@@ -274,27 +301,83 @@ end
|
||||
|
||||
local function on_tick()
|
||||
local this = Public.get()
|
||||
if game.tick % 25 == 0 then
|
||||
if this.alive_enemies < 0 then this.alive_enemies = 0 end
|
||||
if this.game_lost then
|
||||
local message = this.nomed_marked and 'The bugs had a feast on the marked at level ' .. this.nomed_marked .. '!' or 'The bugs had a feast on the marked!'
|
||||
update_stage_gui(message)
|
||||
else
|
||||
update_stage_gui()
|
||||
local island_data = this.islands_data[this.current_level]
|
||||
local tick = game.tick
|
||||
|
||||
if this.delayed_messages[tick] then
|
||||
game.print(this.delayed_messages[tick])
|
||||
this.delayed_messages[tick] = nil
|
||||
end
|
||||
|
||||
if tick % 25 == 0 then
|
||||
Func.check_alive_enemies()
|
||||
end
|
||||
|
||||
has_the_game_ended(this)
|
||||
|
||||
if tick % 40 == 0 and this.auto_generate_upon_idle then
|
||||
if island_data and Difficulty.has_votes_ended() then
|
||||
local _, time = Public.normalize_time_until_next_island_is_created()
|
||||
|
||||
if island_data.completed then
|
||||
if not this.time_until_next_island_is_created then
|
||||
local difficulty_index = Difficulty.get('index')
|
||||
local hour
|
||||
if difficulty_index == 1 then
|
||||
hour = random(60, 120)
|
||||
elseif difficulty_index == 2 then
|
||||
hour = random(30, 60)
|
||||
elseif difficulty_index == 3 then
|
||||
hour = random(15, 30)
|
||||
end
|
||||
|
||||
this.time_until_next_island_is_created = tick + (60 * 60 * hour * this.current_level)
|
||||
this.time_until_next_island_is_created_static = math.round((this.time_until_next_island_is_created - tick) / 60 / 60, 0)
|
||||
|
||||
if _DEBUG then
|
||||
this.time_until_next_island_is_created = tick + (60 * 60 * 10)
|
||||
this.time_until_next_island_is_created_static = math.round((this.time_until_next_island_is_created - tick) / 60 / 60, 0)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
local time_limit = this.time_until_next_island_is_created_static / 2
|
||||
|
||||
-- spawn the island before the time limit is reached
|
||||
if time <= time_limit then
|
||||
if not island_data.auto_generated_island then
|
||||
island_data.auto_generated_island = true
|
||||
game.print('The biters are getting hungry!!!', { color = { r = 0.88, g = 0.22, b = 0.22 } })
|
||||
Scheduler.new(1, Public.init_next_island_without_bridge_token):set_data({ surface = game.surfaces[1] })
|
||||
end
|
||||
end
|
||||
else
|
||||
-- spawn the island after the time limit is reached
|
||||
if time <= 0 then
|
||||
if not (island_data and island_data.auto_generated_bridge) then
|
||||
island_data.auto_generated_bridge = true
|
||||
game.print('The biters are forming a bridge to our island! They are coming!!!', { color = { r = 0.88, g = 0.22, b = 0.22 } })
|
||||
Scheduler.new(1, Public.do_generate_bridge_token):set_data({ surface = game.surfaces[1] })
|
||||
this.time_until_next_island_is_created = nil
|
||||
end
|
||||
end
|
||||
if not this.game_lost then
|
||||
if Difficulty.has_votes_ended() and not this.difficulty_vote_ended then
|
||||
this.difficulty_vote_ended = true
|
||||
game.print('The difficulty vote has ended! You may now progress to the next island!', { color = { r = 0.22, g = 0.88, b = 0.22 } })
|
||||
Server.to_discord_embed('** The difficulty vote has ended! You may now progress to the next island! **')
|
||||
game.print('The difficulty is ' .. Difficulty.get('name') .. '!', { color = Difficulty.get('print_color') })
|
||||
Server.to_discord_embed('** The difficulty is ' .. Difficulty.get('name') .. '! **')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local infinite_ammo_tick = Public.get('infinite_ammo_tick')
|
||||
if game.tick % infinite_ammo_tick == 0 then
|
||||
if tick % 50 == 0 then
|
||||
update_stage_gui()
|
||||
if this.game_lost then return end
|
||||
|
||||
local position = island_data and island_data.position or { x = 0, y = 0 }
|
||||
local radius = island_data and island_data.radius or 0
|
||||
|
||||
game.forces.player.chart(game.surfaces[1], { { position.x - radius, position.y - radius }, { position.x + radius, position.y + radius } })
|
||||
|
||||
Func.is_rocket_silo_alive()
|
||||
end
|
||||
|
||||
if tick % this.infinite_ammo_tick == 0 then
|
||||
drift_corpses_toward_beach()
|
||||
if this.ammo_chest and this.ammo_chest.valid then
|
||||
local magazine_name = 'firearm-magazine'
|
||||
@@ -309,60 +392,45 @@ local function on_tick()
|
||||
end
|
||||
end
|
||||
|
||||
if game.tick % 150 == 0 then
|
||||
if this.game_lost then return end
|
||||
|
||||
Func.is_rocket_silo_alive()
|
||||
|
||||
local center_position = this.centered_points[this.current_level]
|
||||
if not center_position then
|
||||
center_position =
|
||||
{
|
||||
position = { x = 0, y = 0 }
|
||||
}
|
||||
if tick % 100 == 0 then
|
||||
if not this.game_lost then
|
||||
if Difficulty.has_votes_ended() and not this.difficulty_vote_ended then
|
||||
this.difficulty_vote_ended = true
|
||||
game.print('The difficulty vote has ended! You may now progress to the next island!', { color = { r = 0.22, g = 0.88, b = 0.22 } })
|
||||
Server.to_discord_embed('** The difficulty vote has ended! You may now progress to the next island! **')
|
||||
game.print('The difficulty is ' .. Difficulty.get('name') .. '!', { color = Difficulty.get('print_color') })
|
||||
Server.to_discord_embed('** The difficulty is ' .. Difficulty.get('name') .. '! **')
|
||||
end
|
||||
end
|
||||
end
|
||||
game.forces.player.chart(game.surfaces[1], { { center_position.position.x - 124, center_position.position.y - 124 }, { center_position.position.x + 124, center_position.position.y + 124 } })
|
||||
|
||||
Func.check_alive_enemies()
|
||||
if not this.completed_levels[this.current_level] then
|
||||
if tick % 150 == 0 then
|
||||
if not this.game_lost then
|
||||
if not island_data.completed then
|
||||
if not this.disable_multi_command_attack then
|
||||
Func.do_buried_biters()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if game.tick % 400 == 0 then
|
||||
if tick % 400 == 0 then
|
||||
Func.set_multi_command()
|
||||
end
|
||||
|
||||
if game.tick % 500 == 0 then
|
||||
if this.completed_levels[this.current_level] then
|
||||
if not this.disable_multi_command_attack then
|
||||
Func.do_buried_biters_on_completed_levels()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if this.delayed_messages[game.tick] then
|
||||
game.print(this.delayed_messages[game.tick])
|
||||
this.delayed_messages[game.tick] = nil
|
||||
end
|
||||
|
||||
if game.tick % 500 == 0 then
|
||||
if tick % 500 == 0 then
|
||||
Func.update_evolution_static()
|
||||
end
|
||||
|
||||
if this.clear_items_on_ground_state then
|
||||
if game.tick % 450 == 0 then
|
||||
if tick % 450 == 0 then
|
||||
Func.do_clear_items_on_ground_slowly()
|
||||
end
|
||||
|
||||
if game.tick % 4500 == 0 then
|
||||
if tick % 4500 == 0 then
|
||||
Func.run_clear_items_on_ground()
|
||||
end
|
||||
end
|
||||
|
||||
has_the_game_ended(this)
|
||||
end
|
||||
|
||||
local handle_changes = function ()
|
||||
|
||||
@@ -5,7 +5,6 @@ local Autostash = require 'modules.autostash'
|
||||
local BottomFrame = require 'utils.gui.bottom_frame'
|
||||
local Misc = require 'utils.commands.misc'
|
||||
local Map = require 'modules.map_info'
|
||||
local Scheduler = require 'utils.scheduler'
|
||||
local Task = require 'utils.task_token'
|
||||
local Difficulty = require 'modules.difficulty_vote_by_amount'
|
||||
local Server = require 'utils.server'
|
||||
@@ -22,11 +21,115 @@ Global.register(
|
||||
end
|
||||
)
|
||||
|
||||
local set_tech_limit_token = Task.register(
|
||||
function ()
|
||||
Public.func.disable_tech()
|
||||
Public.island_keeper = '[color=blue]Island Keeper: [/color]'
|
||||
|
||||
Public.command_color = { r = 0.98, g = 0.66, b = 0.22 }
|
||||
|
||||
Public.island_radius_param = 6
|
||||
|
||||
Public.decoratives =
|
||||
{
|
||||
'red-croton',
|
||||
'brown-hairy-grass',
|
||||
'muddy-stump',
|
||||
'green-bush-mini',
|
||||
'nuclear-ground-patch',
|
||||
}
|
||||
|
||||
Public.spooky_lines =
|
||||
{
|
||||
"The market does not feel as safe as before...",
|
||||
"Something feels… off around the market.",
|
||||
"The guards whisper of strange noises beneath the ground.",
|
||||
"The calm around the market feels forced — too quiet.",
|
||||
"The soil near the market seems to move when no one is looking."
|
||||
}
|
||||
|
||||
Public.overrun_messages =
|
||||
{
|
||||
"[color=red]The ground trembles where the market once stood.[/color]",
|
||||
"[color=red]Something vast is crawling out from beneath the ruins.[/color]",
|
||||
"[color=red]The earth splits open — a tide of biters surges forth.[/color]",
|
||||
"[color=red]The market’s ashes stir… the hive awakens.[/color]",
|
||||
"[color=red]A dark roar echoes from the crater — they’re not done yet.[/color]",
|
||||
"[color=red]The air thickens with the sound of chittering and claws.[/color]",
|
||||
"[color=red]The soil itself seems alive where the market once stood.[/color]",
|
||||
"[color=red]Smoke rises… and with it, the swarm.[/color]",
|
||||
"[color=red]The silence breaks — and the ground moves.[/color]",
|
||||
"[color=red]Biters are pouring out of the ruins![/color]",
|
||||
"[color=red]The island is being overrun — the swarm is spreading fast![/color]",
|
||||
"[color=red]A massive horde erupts from the fallen market![/color]",
|
||||
"[color=red]The market’s collapse has unleashed the swarm![/color]",
|
||||
"[color=red]The ground bursts open — enemies everywhere![/color]",
|
||||
"[color=red]The swarm is reclaiming the island![/color]",
|
||||
"[color=red]The defenders are gone — the biters take everything.[/color]",
|
||||
"[color=red]They’re coming from below! The island is lost![/color]",
|
||||
"[color=red]The market is gone… and the swarm claims what’s left.[/color]",
|
||||
"[color=red]Only ruin remains — the swarm feasts in silence.[/color]",
|
||||
"[color=red]The island falls quiet, except for the sound of wings and claws.[/color]",
|
||||
"[color=red]The market’s fall has awakened something unstoppable.[/color]",
|
||||
}
|
||||
|
||||
Public.quality_per_level = {}
|
||||
for i = 0, 50 do
|
||||
local n = i / 50
|
||||
local w_normal, w_uncommon, w_rare, w_epic, w_legendary = 100, 0, 0, 0, 0
|
||||
|
||||
if n > 0.2 then
|
||||
w_normal, w_uncommon = 70, 30
|
||||
end
|
||||
)
|
||||
if n > 0.4 then
|
||||
w_normal, w_uncommon, w_rare = 65, 25, 10
|
||||
end
|
||||
if n > 0.6 then
|
||||
w_normal, w_uncommon, w_rare, w_epic = 50, 30, 15, 5
|
||||
end
|
||||
if n > 0.8 then
|
||||
w_normal, w_uncommon, w_rare, w_epic, w_legendary = 40, 30, 20, 8, 2
|
||||
end
|
||||
|
||||
local total = w_normal + w_uncommon + w_rare + w_epic + w_legendary
|
||||
Public.quality_per_level[i] =
|
||||
{
|
||||
thresholds =
|
||||
{
|
||||
w_normal / total,
|
||||
(w_normal + w_uncommon) / total,
|
||||
(w_normal + w_uncommon + w_rare) / total,
|
||||
(w_normal + w_uncommon + w_rare + w_epic) / total,
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
Public.valid_enemy_types =
|
||||
{
|
||||
['unit'] = true,
|
||||
['turret'] = true,
|
||||
['unit-spawner'] = true
|
||||
}
|
||||
|
||||
Public.rock_raffle =
|
||||
{
|
||||
'big-sand-rock',
|
||||
'big-sand-rock',
|
||||
'big-rock',
|
||||
'big-rock',
|
||||
'big-rock',
|
||||
'big-rock',
|
||||
'big-rock',
|
||||
'huge-rock',
|
||||
'huge-rock'
|
||||
}
|
||||
|
||||
Public.plantable_soil =
|
||||
{
|
||||
'natural-jellynut-soil',
|
||||
'artificial-jellynut-soil',
|
||||
'natural-yumako-soil',
|
||||
'artificial-yumako-soil',
|
||||
'wetland-yumako',
|
||||
'wetland-jellynut',
|
||||
}
|
||||
|
||||
Public.qualities =
|
||||
{
|
||||
@@ -37,6 +140,175 @@ Public.qualities =
|
||||
'legendary'
|
||||
}
|
||||
|
||||
Public.mining_chances_ores =
|
||||
{
|
||||
{ name = 'coal', chance = 26 },
|
||||
{ name = 'copper-ore', chance = 21 },
|
||||
{ name = 'iron-ore', chance = 20 },
|
||||
{ name = 'stone', chance = 15 },
|
||||
{ name = 'uranium-ore', chance = 10 },
|
||||
{ name = 'spoilage', chance = 10 },
|
||||
{ name = 'tungsten-ore', chance = 5 },
|
||||
{ name = 'holmium-ore', chance = 5 },
|
||||
{ name = 'calcite', chance = 10 },
|
||||
{ name = 'lithium', chance = 5 },
|
||||
{ name = 'jellynut', chance = 5 },
|
||||
{ name = 'yumako', chance = 5 },
|
||||
{ name = 'carbon', chance = 5 },
|
||||
{ name = 'scrap', chance = 5 },
|
||||
{ name = 'ice', chance = 5 },
|
||||
}
|
||||
|
||||
Public.harvest_raffle_ores = {}
|
||||
for _, data in pairs(Public.mining_chances_ores) do
|
||||
for _ = 1, data.chance, 1 do
|
||||
Public.harvest_raffle_ores[#Public.harvest_raffle_ores + 1] = data.name
|
||||
end
|
||||
end
|
||||
Public.size_of_ore_raffle = #Public.harvest_raffle_ores
|
||||
|
||||
Public.raw_ores =
|
||||
{
|
||||
'copper-ore',
|
||||
'iron-ore',
|
||||
'coal',
|
||||
'stone',
|
||||
'uranium-ore',
|
||||
'calcite',
|
||||
'tungsten-ore',
|
||||
'scrap',
|
||||
}
|
||||
|
||||
Public.oil_raffle =
|
||||
{
|
||||
'sulfuric-acid-geyser',
|
||||
'lithium-brine',
|
||||
'fluorine-vent',
|
||||
'crude-oil',
|
||||
}
|
||||
|
||||
Public.draw_path_tile_whitelist =
|
||||
{
|
||||
['water'] = true,
|
||||
['deepwater'] = true,
|
||||
['brash-ice'] = true,
|
||||
['lava-hot'] = true,
|
||||
}
|
||||
|
||||
Public.path_tile_names =
|
||||
{
|
||||
'highland-yellow-rock',
|
||||
'highland-yellow-rock',
|
||||
'highland-dark-rock-2',
|
||||
'highland-dark-rock-2',
|
||||
'highland-dark-rock',
|
||||
'highland-dark-rock',
|
||||
'midland-cracked-lichen-dull',
|
||||
'midland-cracked-lichen-dull',
|
||||
'midland-cracked-lichen-dark',
|
||||
'midland-cracked-lichen-dark',
|
||||
'midland-turquoise-bark-2',
|
||||
'midland-turquoise-bark-2',
|
||||
'midland-turquoise-bark',
|
||||
'midland-turquoise-bark',
|
||||
'lowland-dead-skin',
|
||||
'lowland-dead-skin',
|
||||
'lowland-dead-skin-2',
|
||||
'lowland-dead-skin-2',
|
||||
'lowland-red-vein-dead',
|
||||
'lowland-red-vein-dead',
|
||||
}
|
||||
|
||||
Public.path_tile_names_dict =
|
||||
{
|
||||
['highland-yellow-rock'] = true,
|
||||
['highland-dark-rock-2'] = true,
|
||||
['highland-dark-rock'] = true,
|
||||
['midland-cracked-lichen-dull'] = true,
|
||||
['midland-cracked-lichen-dark'] = true,
|
||||
['midland-turquoise-bark-2'] = true,
|
||||
['midland-turquoise-bark'] = true,
|
||||
['lowland-dead-skin'] = true,
|
||||
['lowland-dead-skin-2'] = true,
|
||||
['lowland-red-vein-dead'] = true,
|
||||
}
|
||||
|
||||
Public.messages =
|
||||
{
|
||||
"The infestation spreads its reach...",
|
||||
"Extending the corruption — please stand by...",
|
||||
"Creeping tendrils are forming new islands...",
|
||||
"Nature’s wrath forges a new connection...",
|
||||
"The island keeper senses movement beneath the waters...",
|
||||
"Roots dig deep — a new island awakens...",
|
||||
"The corruption coils ever closer...",
|
||||
"Spawning path tiles... and probably a few regrets...",
|
||||
"The ground trembles as the next path takes shape...",
|
||||
"Building a new route for our doom — hang tight...",
|
||||
"The infestation hums... something new emerges...",
|
||||
"Path formation in progress — please don’t fall in...",
|
||||
"The snake slithers onward... destination unknown...",
|
||||
"Twisting and turning — the way forward is being formed...",
|
||||
"Stretching the tendrils of chaos to new lands...",
|
||||
"Bridging the gap between survival and regret..."
|
||||
}
|
||||
|
||||
Public.gleba_trees =
|
||||
{
|
||||
'jellystem',
|
||||
'yumako-tree'
|
||||
}
|
||||
|
||||
Public.enemy_progression =
|
||||
{
|
||||
{
|
||||
max_level = 2,
|
||||
biter_types = { 'small-biter', 'small-wriggler-pentapod' },
|
||||
spitter_types = { 'small-spitter' },
|
||||
worm_types = { 'small-worm-turret' },
|
||||
spawner_types = { 'biter-spawner', 'spitter-spawner', 'gleba-spawner-small' },
|
||||
spawn_qualities = { 'normal' }
|
||||
},
|
||||
{
|
||||
max_level = 5,
|
||||
biter_types = { 'small-biter', 'medium-biter', 'small-wriggler-pentapod' },
|
||||
spitter_types = { 'small-spitter', 'medium-spitter', 'small-strafer-pentapod' },
|
||||
worm_types = { 'small-worm-turret', 'medium-worm-turret' },
|
||||
spawner_types = { 'biter-spawner', 'spitter-spawner', 'gleba-spawner-small' },
|
||||
spawn_qualities = { 'normal', 'uncommon' }
|
||||
},
|
||||
{
|
||||
max_level = 8,
|
||||
biter_types = { 'medium-biter', 'big-biter', 'medium-wriggler-pentapod', 'big-wriggler-pentapod', 'small-stomper-pentapod' },
|
||||
spitter_types = { 'medium-spitter', 'big-spitter', 'small-strafer-pentapod', 'medium-strafer-pentapod' },
|
||||
worm_types = { 'medium-worm-turret', 'big-worm-turret' },
|
||||
spawner_types = { 'biter-spawner', 'spitter-spawner', 'gleba-spawner' },
|
||||
spawn_qualities = { 'uncommon', 'rare' }
|
||||
},
|
||||
{
|
||||
max_level = 15,
|
||||
biter_types = { 'big-biter', 'behemoth-biter', 'big-wriggler-pentapod', 'medium-stomper-pentapod' },
|
||||
spitter_types = { 'big-spitter', 'behemoth-spitter', 'big-strafer-pentapod', 'medium-strafer-pentapod' },
|
||||
worm_types = { 'big-worm-turret', 'behemoth-worm-turret' },
|
||||
spawner_types = { 'biter-spawner', 'spitter-spawner', 'gleba-spawner' },
|
||||
spawn_qualities = { 'rare', 'epic' }
|
||||
},
|
||||
{
|
||||
max_level = math.huge,
|
||||
biter_types = { 'big-biter', 'behemoth-biter', 'big-wriggler-pentapod', 'big-stomper-pentapod' },
|
||||
spitter_types = { 'big-spitter', 'behemoth-spitter', 'big-strafer-pentapod', 'medium-strafer-pentapod' },
|
||||
worm_types = { 'big-worm-turret', 'behemoth-worm-turret' },
|
||||
spawner_types = { 'biter-spawner', 'spitter-spawner', 'gleba-spawner' },
|
||||
spawn_qualities = { 'epic', 'legendary' }
|
||||
}
|
||||
}
|
||||
|
||||
local set_tech_limit_token = Task.register(
|
||||
function ()
|
||||
Public.functions.disable_tech()
|
||||
end
|
||||
)
|
||||
|
||||
local function init_mirror_surface()
|
||||
if game.surfaces['island'] then
|
||||
return
|
||||
@@ -86,9 +358,8 @@ function Public.on_init()
|
||||
T.main_caption_color = { r = 150, g = 150, b = 0 }
|
||||
T.sub_caption_color = { r = 0, g = 150, b = 0 }
|
||||
|
||||
Scheduler.can_run_scheduler(true)
|
||||
|
||||
this.game_lost = false
|
||||
this.top_label_caption_override = nil
|
||||
|
||||
local surface = game.surfaces[1]
|
||||
surface.ignore_surface_conditions = true
|
||||
@@ -102,9 +373,9 @@ function Public.on_init()
|
||||
|
||||
this.soft_reset = true
|
||||
|
||||
this.bridge_position = { x = 0, y = 0 }
|
||||
this.game_over_if_market_dies = false
|
||||
|
||||
this.notified_market_safe = false
|
||||
this.bridge_position = { x = 0, y = 0 }
|
||||
|
||||
local mgs = surface.map_gen_settings
|
||||
mgs.water = 9.9
|
||||
@@ -170,7 +441,7 @@ function Public.on_init()
|
||||
|
||||
this.player_options = {}
|
||||
|
||||
this.autogenerate_islands = false
|
||||
this.auto_create_islands = false
|
||||
|
||||
this.vector = {}
|
||||
|
||||
@@ -183,12 +454,8 @@ function Public.on_init()
|
||||
game.forces.player.set_spawn_position({ 0, 2 }, surface)
|
||||
|
||||
this.alive_enemies = 0
|
||||
this.alive_boss_enemy_count = 0
|
||||
|
||||
this.current_level = this.current_level + 1
|
||||
this.current_stage = 1
|
||||
|
||||
this.completed_levels = {}
|
||||
|
||||
this.market_positions = {}
|
||||
|
||||
@@ -196,9 +463,7 @@ function Public.on_init()
|
||||
|
||||
this.rocket_silo = nil
|
||||
|
||||
this.connected_islands = {}
|
||||
|
||||
this.centered_points =
|
||||
this.islands_data =
|
||||
{
|
||||
[1] = { position = { x = 0, y = 0 }, radius = 200, level = 1 }
|
||||
}
|
||||
@@ -223,10 +488,6 @@ function Public.on_init()
|
||||
'legendary'
|
||||
}
|
||||
|
||||
this.tiles = {}
|
||||
|
||||
this.spawned_markets = {}
|
||||
|
||||
this.path_tiles = nil
|
||||
|
||||
this.max_biters_per_island = 150
|
||||
@@ -243,7 +504,8 @@ function Public.on_init()
|
||||
}
|
||||
end
|
||||
|
||||
this.nomed_marked = nil
|
||||
this.fallen_market = nil
|
||||
this.printed_location_for_fallen_market = nil
|
||||
|
||||
this.loot_stats =
|
||||
{
|
||||
@@ -267,6 +529,8 @@ function Public.on_init()
|
||||
|
||||
this.market_prices = {}
|
||||
|
||||
this.game_over_tasks_done = false
|
||||
|
||||
this.drift_corpses_toward_beach_enabled = true
|
||||
|
||||
this.clear_items_on_ground_state = true
|
||||
@@ -291,16 +555,61 @@ function Public.on_init()
|
||||
this.cooldown_complete_level = game.tick + 100
|
||||
this.voting_to_progress_enabled = true
|
||||
|
||||
this.reverse_start_position = true
|
||||
|
||||
this.checked_island = {}
|
||||
|
||||
this.time_until_next_island_is_created = nil -- 60 * 60 * 60 -- 1 hour
|
||||
this.time_until_next_island_is_created_static = nil
|
||||
this.auto_generate_upon_idle = true
|
||||
|
||||
game.forces.enemy.set_friend('player', false)
|
||||
game.forces.player.set_friend('enemy', false)
|
||||
game.forces.enemy.set_cease_fire('player', false)
|
||||
game.forces.player.set_cease_fire('enemy', false)
|
||||
|
||||
Public.draw_main_island({ x = 0, y = 0 }, 200)
|
||||
|
||||
Difficulty.reset_difficulty_poll({ closing_timeout = game.tick + 36000 })
|
||||
Difficulty.set_gui_width(20)
|
||||
Difficulty.set('button_height', 54)
|
||||
|
||||
Difficulty.set_difficulties(
|
||||
{
|
||||
[1] =
|
||||
{
|
||||
name = "I'm too young to die",
|
||||
index = 1,
|
||||
value = 1,
|
||||
color = { r = 0.00, g = 0.25, b = 0.00 },
|
||||
print_color = { r = 0.00, g = 0.4, b = 0.00 },
|
||||
count = 0,
|
||||
strength_modifier = 1.00,
|
||||
boss_modifier = 6.0
|
||||
},
|
||||
[2] =
|
||||
{
|
||||
name = 'Hurt me plenty',
|
||||
index = 2,
|
||||
value = 4,
|
||||
color = { r = 0.00, g = 0.00, b = 0.25 },
|
||||
print_color = { r = 0.0, g = 0.0, b = 0.5 },
|
||||
count = 0,
|
||||
strength_modifier = 5,
|
||||
boss_modifier = 7.0
|
||||
},
|
||||
[3] =
|
||||
{
|
||||
name = 'Ultra-violence',
|
||||
index = 3,
|
||||
value = 10,
|
||||
color = { r = 255, g = 128, b = 0.00 },
|
||||
print_color = { r = 255, g = 128, b = 0.00 },
|
||||
count = 0,
|
||||
strength_modifier = 12,
|
||||
boss_modifier = 8.0
|
||||
}
|
||||
})
|
||||
this.difficulty_vote_ended = false
|
||||
Server.to_discord_embed('** A fresh round of Infestation Islands has begun! **')
|
||||
Task.set_timeout_in_ticks(100, set_tech_limit_token)
|
||||
|
||||
@@ -808,6 +808,9 @@ local set_unit_raffle_token =
|
||||
local boss_raffle = WD.get('boss_raffle') --[[@as table]]
|
||||
|
||||
if level >= 100 and level < 200 then
|
||||
WD.set('biter_raffle', {})
|
||||
WD.set('spitter_raffle', {})
|
||||
WD.set('boss_raffle', {})
|
||||
biter_raffle['mtn-addon-small-piercing-biter-t2'] = round(2000 - level * 1.75, 6)
|
||||
biter_raffle['mtn-addon-small-acid-biter-t2'] = round(2000 - level * 1.75, 6)
|
||||
biter_raffle['mtn-addon-small-explosive-biter-t2'] = round(2000 - level * 1.75, 6)
|
||||
@@ -833,6 +836,9 @@ local set_unit_raffle_token =
|
||||
end
|
||||
|
||||
if level >= 200 and level < 250 then
|
||||
WD.set('biter_raffle', {})
|
||||
WD.set('spitter_raffle', {})
|
||||
WD.set('boss_raffle', {})
|
||||
biter_raffle['mtn-addon-small-piercing-biter-t3'] = round(1500 - level * 1.75, 6)
|
||||
biter_raffle['mtn-addon-small-acid-biter-t3'] = round(1500 - level * 1.75, 6)
|
||||
biter_raffle['mtn-addon-small-explosive-biter-t3'] = round(1500 - level * 1.75, 6)
|
||||
@@ -858,6 +864,8 @@ local set_unit_raffle_token =
|
||||
boss_raffle['mtn-addon-medium-fire-biter-t3'] = round(1500 - (level - 1.50), 6)
|
||||
end
|
||||
if level >= 250 and level < 300 then
|
||||
WD.set('biter_raffle', {})
|
||||
WD.set('spitter_raffle', {})
|
||||
if Public.is_modded_pt2 then
|
||||
biter_raffle['medium-wriggler-pentapod'] = round(250 - (level - 250), 6)
|
||||
end
|
||||
@@ -874,6 +882,9 @@ local set_unit_raffle_token =
|
||||
spitter_raffle['mtn-addon-medium-fire-spitter-t1'] = round(250 - (level - 250), 6)
|
||||
end
|
||||
if level >= 300 and level < 350 then
|
||||
WD.set('biter_raffle', {})
|
||||
WD.set('spitter_raffle', {})
|
||||
WD.set('boss_raffle', {})
|
||||
biter_raffle['mtn-addon-medium-piercing-biter-t2'] = round(300 - (level - 300), 6)
|
||||
biter_raffle['mtn-addon-medium-acid-biter-t2'] = round(300 - (level - 300), 6)
|
||||
biter_raffle['mtn-addon-medium-explosive-biter-t2'] = round(300 - (level - 300), 6)
|
||||
@@ -899,6 +910,9 @@ local set_unit_raffle_token =
|
||||
boss_raffle['mtn-addon-big-fire-biter-t1'] = round(300 - (level - 300), 6)
|
||||
end
|
||||
if level >= 350 and level < 400 then
|
||||
WD.set('biter_raffle', {})
|
||||
WD.set('spitter_raffle', {})
|
||||
WD.set('boss_raffle', {})
|
||||
biter_raffle['mtn-addon-medium-piercing-biter-t3'] = round(350 - (level - 350), 6)
|
||||
biter_raffle['mtn-addon-medium-acid-biter-t3'] = round(350 - (level - 350), 6)
|
||||
biter_raffle['mtn-addon-medium-explosive-biter-t3'] = round(350 - (level - 350), 6)
|
||||
@@ -925,6 +939,8 @@ local set_unit_raffle_token =
|
||||
end
|
||||
|
||||
if level >= 400 and level < 500 then
|
||||
WD.set('biter_raffle', {})
|
||||
WD.set('spitter_raffle', {})
|
||||
boss_raffle['mtn-addon-big-piercing-spitter-t3'] = round(400 - (level - 400), 6)
|
||||
boss_raffle['mtn-addon-big-acid-spitter-t3'] = round(400 - (level - 400), 6)
|
||||
boss_raffle['mtn-addon-big-explosive-spitter-t3'] = round(400 - (level - 400), 6)
|
||||
@@ -939,6 +955,9 @@ local set_unit_raffle_token =
|
||||
end
|
||||
|
||||
if level >= 500 and level < 550 then
|
||||
WD.set('biter_raffle', {})
|
||||
WD.set('spitter_raffle', {})
|
||||
WD.set('boss_raffle', {})
|
||||
if Public.is_modded_pt2 then
|
||||
biter_raffle['big-wriggler-pentapod'] = round(500 - (level - 500) * 2, 6)
|
||||
end
|
||||
@@ -967,6 +986,9 @@ local set_unit_raffle_token =
|
||||
boss_raffle['mtn-addon-behemoth-fire-biter-t1'] = round(500 - (level - 500) * 2, 6)
|
||||
end
|
||||
if level >= 550 and level < 600 then
|
||||
WD.set('biter_raffle', {})
|
||||
WD.set('spitter_raffle', {})
|
||||
WD.set('boss_raffle', {})
|
||||
biter_raffle['mtn-addon-big-piercing-biter-t2'] = round(550 - (level - 550) * 2, 6)
|
||||
biter_raffle['mtn-addon-big-acid-biter-t2'] = round(550 - (level - 550) * 2, 6)
|
||||
biter_raffle['mtn-addon-big-explosive-biter-t2'] = round(550 - (level - 550) * 2, 6)
|
||||
@@ -993,6 +1015,9 @@ local set_unit_raffle_token =
|
||||
end
|
||||
|
||||
if level >= 600 and level < 800 then
|
||||
WD.set('biter_raffle', {})
|
||||
WD.set('spitter_raffle', {})
|
||||
WD.set('boss_raffle', {})
|
||||
biter_raffle['mtn-addon-big-piercing-biter-t3'] = round(600 - (level - 600) * 2, 6)
|
||||
biter_raffle['mtn-addon-big-acid-biter-t3'] = round(600 - (level - 600) * 2, 6)
|
||||
biter_raffle['mtn-addon-big-explosive-biter-t3'] = round(600 - (level - 600) * 2, 6)
|
||||
@@ -1019,6 +1044,9 @@ local set_unit_raffle_token =
|
||||
end
|
||||
|
||||
if level >= 800 and level < 900 then
|
||||
WD.set('biter_raffle', {})
|
||||
WD.set('spitter_raffle', {})
|
||||
WD.set('boss_raffle', {})
|
||||
biter_raffle['mtn-addon-behemoth-piercing-biter-t1'] = round((level - 800) * 2.75, 6)
|
||||
biter_raffle['mtn-addon-behemoth-acid-biter-t1'] = round((level - 800) * 2.75, 6)
|
||||
biter_raffle['mtn-addon-behemoth-explosive-biter-t1'] = round((level - 800) * 2.75, 6)
|
||||
@@ -1044,6 +1072,9 @@ local set_unit_raffle_token =
|
||||
boss_raffle['mtn-addon-boss-fire-spitter-t1'] = round((level - 800) * 2.75, 6)
|
||||
end
|
||||
if level >= 900 and level < 1000 then
|
||||
WD.set('biter_raffle', {})
|
||||
WD.set('spitter_raffle', {})
|
||||
WD.set('boss_raffle', {})
|
||||
biter_raffle['mtn-addon-behemoth-piercing-biter-t2'] = round((level - 900) * 2.75, 6)
|
||||
biter_raffle['mtn-addon-behemoth-acid-biter-t2'] = round((level - 900) * 2.75, 6)
|
||||
biter_raffle['mtn-addon-behemoth-explosive-biter-t2'] = round((level - 900) * 2.75, 6)
|
||||
@@ -1070,6 +1101,9 @@ local set_unit_raffle_token =
|
||||
end
|
||||
|
||||
if level >= 1000 and level < 1100 then
|
||||
WD.set('biter_raffle', {})
|
||||
WD.set('spitter_raffle', {})
|
||||
WD.set('boss_raffle', {})
|
||||
biter_raffle['mtn-addon-behemoth-piercing-biter-t3'] = round((level - 1000) * 2.75, 6)
|
||||
biter_raffle['mtn-addon-behemoth-acid-biter-t3'] = round((level - 1000) * 2.75, 6)
|
||||
biter_raffle['mtn-addon-behemoth-explosive-biter-t3'] = round((level - 1000) * 2.75, 6)
|
||||
@@ -1096,6 +1130,9 @@ local set_unit_raffle_token =
|
||||
end
|
||||
|
||||
if level >= 1100 and level < 1200 then
|
||||
WD.set('biter_raffle', {})
|
||||
WD.set('spitter_raffle', {})
|
||||
WD.set('boss_raffle', {})
|
||||
biter_raffle['mtn-addon-behemoth-piercing-biter-t3'] = round((level - 1100) * 2.75, 6)
|
||||
biter_raffle['mtn-addon-behemoth-acid-biter-t3'] = round((level - 1100) * 2.75, 6)
|
||||
biter_raffle['mtn-addon-behemoth-explosive-biter-t3'] = round((level - 1100) * 2.75, 6)
|
||||
@@ -1122,6 +1159,9 @@ local set_unit_raffle_token =
|
||||
end
|
||||
|
||||
if level >= 1200 and level < 1300 then
|
||||
WD.set('biter_raffle', {})
|
||||
WD.set('spitter_raffle', {})
|
||||
WD.set('boss_raffle', {})
|
||||
biter_raffle['mtn-addon-behemoth-piercing-biter-t3'] = round((level - 1200) * 2.75, 6)
|
||||
biter_raffle['mtn-addon-behemoth-acid-biter-t3'] = round((level - 1200) * 2.75, 6)
|
||||
biter_raffle['mtn-addon-behemoth-explosive-biter-t3'] = round((level - 1200) * 2.75, 6)
|
||||
@@ -1148,6 +1188,9 @@ local set_unit_raffle_token =
|
||||
end
|
||||
|
||||
if level >= 1300 and level < 1400 then
|
||||
WD.set('biter_raffle', {})
|
||||
WD.set('spitter_raffle', {})
|
||||
WD.set('boss_raffle', {})
|
||||
biter_raffle['mtn-addon-behemoth-piercing-biter-t3'] = round((level - 1300) * 2.75, 6)
|
||||
biter_raffle['mtn-addon-behemoth-acid-biter-t3'] = round((level - 1300) * 2.75, 6)
|
||||
biter_raffle['mtn-addon-behemoth-explosive-biter-t3'] = round((level - 1300) * 2.75, 6)
|
||||
@@ -1174,6 +1217,9 @@ local set_unit_raffle_token =
|
||||
end
|
||||
|
||||
if level >= 1400 then
|
||||
WD.set('biter_raffle', {})
|
||||
WD.set('spitter_raffle', {})
|
||||
WD.set('boss_raffle', {})
|
||||
biter_raffle['mtn-addon-behemoth-piercing-biter-t3'] = round((level - 1400) * 2.75, 6)
|
||||
biter_raffle['mtn-addon-behemoth-acid-biter-t3'] = round((level - 1400) * 2.75, 6)
|
||||
biter_raffle['mtn-addon-behemoth-explosive-biter-t3'] = round((level - 1400) * 2.75, 6)
|
||||
|
||||
@@ -411,6 +411,10 @@ function Public.set(key, value)
|
||||
end
|
||||
end
|
||||
|
||||
function Public.get_closing_timeout()
|
||||
return math.round((this.closing_timeout - game.tick) / 60, 0)
|
||||
end
|
||||
|
||||
function Public.has_votes_ended()
|
||||
return game.tick > this.closing_timeout
|
||||
end
|
||||
|
||||
@@ -226,7 +226,7 @@ end
|
||||
Gui.on_click(
|
||||
melee_mode_name,
|
||||
function (event)
|
||||
local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Mtn v3 Spectate Ready Button')
|
||||
local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Mtn v3 Melee Mode Button')
|
||||
if is_spamming then
|
||||
return
|
||||
end
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
local Global = require 'utils.global'
|
||||
local Color = require 'utils.color_presets'
|
||||
-- local SpamProtection = require 'utils.spam_protection'
|
||||
local SpamProtection = require 'utils.spam_protection'
|
||||
local Event = require 'utils.event'
|
||||
local Gui = require 'utils.gui'
|
||||
local Commands = require 'utils.commands'
|
||||
@@ -382,10 +382,10 @@ local function on_gui_click(event)
|
||||
return
|
||||
end
|
||||
|
||||
-- local is_spamming = SpamProtection.is_spamming(player, nil, 'Player Inventory')
|
||||
-- if is_spamming then
|
||||
-- return
|
||||
-- end
|
||||
local is_spamming = SpamProtection.is_spamming(player, nil, 'Player Inventory')
|
||||
if is_spamming then
|
||||
return
|
||||
end
|
||||
|
||||
local data = get_player_data(player)
|
||||
if not data then
|
||||
|
||||
@@ -24,8 +24,6 @@ local floor = math.floor
|
||||
local random = math.random
|
||||
local abs = math.abs
|
||||
|
||||
local flush_interval = 120 -- every 2 seconds (120 ticks)
|
||||
|
||||
local this =
|
||||
{
|
||||
enabled = true,
|
||||
@@ -250,80 +248,6 @@ local function do_action(player, prefix, msg, ban_msg, kill)
|
||||
end
|
||||
end
|
||||
|
||||
local function flush_deconstruct_log()
|
||||
if not next(this.deconstruct_queue) then return end
|
||||
|
||||
local grouped = {}
|
||||
for _, data in ipairs(this.deconstruct_queue) do
|
||||
local player_name = data.player_name
|
||||
if not grouped[player_name] then
|
||||
grouped[player_name] = {}
|
||||
end
|
||||
table.insert(grouped[player_name], data)
|
||||
end
|
||||
|
||||
local ind = 0
|
||||
local success_count = 0
|
||||
local t = math.abs(math.floor(game.tick / 60))
|
||||
local formatted = FancyTime.short_fancy_time(t)
|
||||
|
||||
for player_name, entries in pairs(grouped) do
|
||||
local entity_counts = {}
|
||||
local details = {}
|
||||
for _, e in ipairs(entries) do
|
||||
local str = '[' .. formatted .. '] '
|
||||
str = str .. player_name .. ' marked ' .. e.entity_name .. ' for deconstruction'
|
||||
str = str .. ' at X:'
|
||||
str = str .. e.x
|
||||
str = str .. ' Y:'
|
||||
str = str .. e.y
|
||||
str = str .. ' '
|
||||
str = str .. 'surface:' .. e.surface
|
||||
|
||||
entity_counts[e.entity_name] = (entity_counts[e.entity_name] or 0) + 1
|
||||
increment(this.deconstruct_history, str)
|
||||
if ind == 0 then
|
||||
table.insert(details, string.format("(%d,%d,surface:%d)", e.x, e.y, e.surface))
|
||||
end
|
||||
ind = ind + 1
|
||||
if ind == #entries then
|
||||
table.insert(details, string.format("(%d,%d,surface:%d)", e.x, e.y, e.surface))
|
||||
ind = 0
|
||||
end
|
||||
if e.success then
|
||||
success_count = success_count + 1
|
||||
end
|
||||
end
|
||||
|
||||
local total = #entries
|
||||
local summary_parts = {}
|
||||
for name, count in pairs(entity_counts) do
|
||||
table.insert(summary_parts, string.format("%dx %s", count, name))
|
||||
end
|
||||
local summary_str = table.concat(summary_parts, ", ")
|
||||
|
||||
|
||||
|
||||
local message = string.format(
|
||||
"[%s] %s marked %d entities for deconstruction: %s | Positions: %s | Mined: %s",
|
||||
formatted,
|
||||
player_name,
|
||||
total,
|
||||
summary_str,
|
||||
table.concat(details, ", "),
|
||||
success_count .. ' / ' .. total
|
||||
)
|
||||
|
||||
Server.log_antigrief_data('deconstruct', message)
|
||||
end
|
||||
|
||||
this.deconstruct_queue = {}
|
||||
end
|
||||
|
||||
local function do_action_task()
|
||||
flush_deconstruct_log()
|
||||
end
|
||||
|
||||
local function on_marked_for_deconstruction(event)
|
||||
if not this.enabled or not event.player_index then return end
|
||||
|
||||
@@ -332,27 +256,15 @@ local function on_marked_for_deconstruction(event)
|
||||
if this.do_not_check_trusted then return end
|
||||
|
||||
local playtime = player.online_time
|
||||
local success = false
|
||||
local is_trusted = Session.get_trusted_player(player)
|
||||
if Session.get_session_player(player) then
|
||||
playtime = player.online_time + Session.get_session_player(player)
|
||||
success = true
|
||||
end
|
||||
if playtime < this.required_playtime and not is_trusted then
|
||||
event.entity.cancel_deconstruction(player.force.name, player.index)
|
||||
player.print('You are not accustomed to deconstructing yet.', { r = 0.22, g = 0.99, b = 0.99 })
|
||||
return
|
||||
end
|
||||
|
||||
table.insert(this.deconstruct_queue,
|
||||
{
|
||||
player_name = player.name,
|
||||
entity_name = event.entity.name,
|
||||
x = math.floor(event.entity.position.x),
|
||||
y = math.floor(event.entity.position.y),
|
||||
surface = event.entity.surface.index,
|
||||
success = success
|
||||
})
|
||||
end
|
||||
|
||||
local function on_player_ammo_inventory_changed(event)
|
||||
@@ -1076,8 +988,6 @@ local function on_player_deconstructed_area(event)
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
|
||||
local area = event.area
|
||||
local count = surface.count_entities_filtered({ area = area, type = 'resource', invert = true })
|
||||
local max_count = 0
|
||||
@@ -1519,6 +1429,5 @@ Event.add(de.on_console_command, on_console_command)
|
||||
Event.add(de.on_console_chat, on_console_chat)
|
||||
Event.add(de.on_player_muted, on_player_muted)
|
||||
Event.add(de.on_player_unmuted, on_player_unmuted)
|
||||
Event.on_nth_tick(flush_interval, do_action_task)
|
||||
|
||||
return Public
|
||||
|
||||
@@ -79,12 +79,11 @@ Global.register(
|
||||
this,
|
||||
function (tbl)
|
||||
this = tbl
|
||||
for _, command in pairs(this.commands) do
|
||||
setmetatable(command, Public.metatable)
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
script.register_metatable('CommandData', Public.metatable)
|
||||
|
||||
local function conv(v)
|
||||
if tonumber(v) then
|
||||
return tonumber(v)
|
||||
|
||||
@@ -42,6 +42,7 @@ local function get_lua_object_type_safe(obj)
|
||||
end
|
||||
|
||||
local function inspect_process(item)
|
||||
if _DEBUG then
|
||||
local object_name = get_lua_object_type_safe(item)
|
||||
if object_name and classes[object_name] then
|
||||
local class = classes[object_name]
|
||||
@@ -62,6 +63,7 @@ local function inspect_process(item)
|
||||
end
|
||||
return serpent.line(info, { comment = false, numformat = '%g' })
|
||||
end
|
||||
end
|
||||
|
||||
if type(item) ~= 'table' or type(item.__self) ~= 'userdata' then
|
||||
return item
|
||||
|
||||
@@ -116,6 +116,8 @@ Gui.on_click(
|
||||
local id = Global.get_global(token_id)
|
||||
local content = dump(id) or 'Could not load data.'
|
||||
|
||||
content = 'return ' .. content
|
||||
|
||||
if not game.is_multiplayer() then
|
||||
helpers.write_file(token_id .. '.lua', content, false, 1)
|
||||
right_panel.text = 'Content written to file on the client: ..\\script-output\\' .. token_id .. '.lua'
|
||||
@@ -123,8 +125,6 @@ Gui.on_click(
|
||||
helpers.write_file(token_id .. '.lua', content, false, 0)
|
||||
right_panel.text = 'Content written to file on the server: ..\\script-output\\' .. token_id .. '.lua'
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
)
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ local concat = table.concat
|
||||
local names = {}
|
||||
-- global
|
||||
local data = {}
|
||||
local removed_objects = {}
|
||||
local settings =
|
||||
{
|
||||
mod_gui_top_frame = true,
|
||||
@@ -43,9 +44,10 @@ local settings =
|
||||
|
||||
Public.token =
|
||||
Global.register(
|
||||
{ data = data, settings = settings },
|
||||
{ data = data, removed_objects = removed_objects, settings = settings },
|
||||
function (tbl)
|
||||
data = tbl.data
|
||||
removed_objects = tbl.removed_objects
|
||||
settings = tbl.settings
|
||||
end
|
||||
)
|
||||
@@ -155,7 +157,10 @@ function Public.set_data(element, value)
|
||||
data[player_index] = values
|
||||
end
|
||||
|
||||
values[element.index] = { value = value, name = element.name }
|
||||
local registration_number = script.register_on_object_destroyed(element)
|
||||
removed_objects[registration_number] = player_index
|
||||
|
||||
values[element.index] = { value = value, name = element.name, registration_number = registration_number }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -392,34 +397,6 @@ function Public.clear(element)
|
||||
element.clear()
|
||||
end
|
||||
|
||||
local function clear_invalid_data()
|
||||
if settings.disable_clear_invalid_data then
|
||||
return
|
||||
end
|
||||
|
||||
for _, player in pairs(game.players) do
|
||||
local player_index = player.index
|
||||
local values = data[player_index]
|
||||
if values then
|
||||
for k, element in next, values do
|
||||
if type(element) == 'table' then
|
||||
for key, obj in next, element do
|
||||
if type(obj) == 'table' and obj.valid ~= nil then
|
||||
if not obj.valid then
|
||||
element[key] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
if type(element) == 'userdata' and not element.valid then
|
||||
values[k] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Event.on_nth_tick(300, clear_invalid_data)
|
||||
|
||||
local function handler_factory(event_id)
|
||||
local handlers
|
||||
|
||||
@@ -922,6 +899,19 @@ local function draw_main_frame(player)
|
||||
return frame, inside_frame
|
||||
end
|
||||
|
||||
local function on_object_destroyed(event)
|
||||
local player_index = removed_objects[event.registration_number]
|
||||
if not player_index then return end
|
||||
|
||||
local element_index = event.useful_id
|
||||
removed_objects[event.registration_number] = nil
|
||||
|
||||
local player_data = data[player_index]
|
||||
if player_data then
|
||||
player_data[element_index] = nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.get_content(player)
|
||||
local left_frame = Public.get_main_frame(player)
|
||||
@@ -1168,6 +1158,8 @@ Event.add(
|
||||
end
|
||||
)
|
||||
|
||||
Event.add(defines.events.on_object_destroyed, on_object_destroyed)
|
||||
|
||||
function Public.data()
|
||||
return data
|
||||
end
|
||||
|
||||
@@ -276,12 +276,12 @@ function Inspector:putTable(t)
|
||||
if t == inspect.KEY or t == inspect.METATABLE then
|
||||
self:puts(tostring(t))
|
||||
elseif self:alreadyVisited(t) then
|
||||
self:puts('<table ', self:getId(t), '>')
|
||||
self:puts('[[<ref to table ', self:getId(t), '>]]')
|
||||
elseif self.level >= self.depth then
|
||||
self:puts('{...}')
|
||||
else
|
||||
if self.tableAppearances[t] > 1 then
|
||||
self:puts('<', self:getId(t), '>')
|
||||
self:puts('[[<', self:getId(t), '>]],')
|
||||
end
|
||||
|
||||
local nonSequentialKeys, sequenceLength = getNonSequentialKeys(t)
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
-- Created by Gerkiz
|
||||
|
||||
local Global = require 'utils.global'
|
||||
local Server = require 'utils.server'
|
||||
local Event = require 'utils.event'
|
||||
local Core = require 'utils.core'
|
||||
|
||||
@@ -42,9 +40,9 @@ Task.__index = Task
|
||||
script.register_metatable('Task', Task)
|
||||
|
||||
--- Registers a callback for a task (data stage / module load time; not at runtime).
|
||||
---@param name string
|
||||
---@param fn function
|
||||
---@param uid? string|number
|
||||
---@param name string - Helps identify the task in the debugger
|
||||
---@param fn function - The callback function
|
||||
---@param uid? string|number - The unique identifier for the task
|
||||
---@return number|string|nil
|
||||
function Public.register_function(name, fn, uid)
|
||||
if game then error('Cannot register functions in runtime') end
|
||||
@@ -62,9 +60,9 @@ function Public.register_function(name, fn, uid)
|
||||
end
|
||||
|
||||
--- Gets the function by id
|
||||
---@param id number|string
|
||||
---@return function|nil
|
||||
---@return string|nil
|
||||
---@param id number|string - The unique identifier for the task
|
||||
---@return function|nil - The callback function
|
||||
---@return string|nil - The name of the task
|
||||
function Public.get_function_by_id(id)
|
||||
return loaded[id], named[id]
|
||||
end
|
||||
@@ -96,13 +94,13 @@ end
|
||||
|
||||
|
||||
--- Gets the callback for this task
|
||||
---@return function|nil
|
||||
---@return function|nil - The callback function
|
||||
function Task:get_callback()
|
||||
return Public.get_function_by_id(self._uid)
|
||||
end
|
||||
|
||||
--- Sets the data for this task
|
||||
---@param tbl table
|
||||
---@param tbl table - The data for the task
|
||||
---@return Task - Self for chaining
|
||||
function Task:set_data(tbl)
|
||||
self._data = tbl
|
||||
@@ -117,9 +115,9 @@ function Task:log()
|
||||
end
|
||||
|
||||
--- Creates a new child task
|
||||
---@param delay number
|
||||
---@param uid number|string|nil
|
||||
---@return Task
|
||||
---@param delay number - The delay in ticks before the task is executed
|
||||
---@param uid number|string|nil - The unique identifier for the task
|
||||
---@return Task - The new child task
|
||||
function Task:new_child(delay, uid)
|
||||
local c = new_task(delay, uid)
|
||||
c._parent = self
|
||||
@@ -128,6 +126,9 @@ function Task:new_child(delay, uid)
|
||||
return c
|
||||
end
|
||||
|
||||
--- Runs the task
|
||||
---@param current_tick number - The current tick
|
||||
---@return boolean - Whether the task was executed
|
||||
function Task:run(current_tick)
|
||||
if self._tick and self._tick > current_tick then return false end
|
||||
if self._completed then return false end
|
||||
@@ -143,6 +144,9 @@ function Task:run(current_tick)
|
||||
return true
|
||||
end
|
||||
|
||||
--- Schedules the next task in the DFS
|
||||
---@param n Task - The task to schedule
|
||||
---@param current_tick number - The current tick
|
||||
local function schedule_next_in_dfs(n, current_tick)
|
||||
while n do
|
||||
if n._next_child_ix <= #n._children then
|
||||
@@ -159,9 +163,9 @@ local function schedule_next_in_dfs(n, current_tick)
|
||||
end
|
||||
|
||||
--- Creates a new task
|
||||
---@param delay number
|
||||
---@param uid number|string|nil
|
||||
---@return Task
|
||||
---@param delay number - The delay in ticks before the task is executed
|
||||
---@param uid number|string|nil - The unique identifier for the task
|
||||
---@return Task - The new task
|
||||
function Public.new(delay, uid)
|
||||
local t = new_task(delay, uid)
|
||||
t._tick = game.tick + normalize_delay(delay)
|
||||
@@ -170,19 +174,29 @@ function Public.new(delay, uid)
|
||||
end
|
||||
|
||||
--- Sets whether the scheduler can run
|
||||
---@param condition boolean - Whether the scheduler can run
|
||||
function Public.can_run_scheduler(condition)
|
||||
---@param condition boolean - Whether the scheduler can run (true to run, false to stop)
|
||||
function Public.set_can_run_scheduler(condition)
|
||||
this.can_run_scheduler = condition or false
|
||||
end
|
||||
|
||||
--- Clears the tasks
|
||||
function Public.clear_tasks()
|
||||
this.tasks = {}
|
||||
this.next_id = 0
|
||||
Core.log('Scheduler tasks have been cleared!')
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_tick,
|
||||
function ()
|
||||
local tick = game.tick
|
||||
|
||||
local can_run_scheduler = this.can_run_scheduler
|
||||
if not can_run_scheduler then
|
||||
this.tasks = {}
|
||||
Server.output_script_data('Scheduler task has been cleared and stopped!')
|
||||
return
|
||||
end
|
||||
|
||||
if not this.tasks or #this.tasks == 0 then
|
||||
this.next_id = 0
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
local Event = require 'utils.event'
|
||||
local Global = require 'utils.global'
|
||||
local Commands = require 'utils.commands'
|
||||
local Server = require 'utils.server'
|
||||
local Public = {}
|
||||
|
||||
local this = {
|
||||
local this =
|
||||
{
|
||||
prevent_spam = {}, -- the default table where all player indexes will be stored
|
||||
default_tick = 10, -- this defines the default tick to check whether or not a user is spamming a button.
|
||||
debug_text = false,
|
||||
debug_spam = false
|
||||
debug_spam = false,
|
||||
show_debug_text_for = {}
|
||||
}
|
||||
|
||||
local main_text = '[Spam Info] '
|
||||
@@ -22,14 +26,14 @@ local function debug_text(str)
|
||||
if not this.debug_text then
|
||||
return
|
||||
end
|
||||
log(main_text .. str)
|
||||
Server.output_script_data(main_text .. str)
|
||||
end
|
||||
|
||||
local function debug_spam(str)
|
||||
if not this.debug_spam then
|
||||
return
|
||||
end
|
||||
log(main_text .. str)
|
||||
Server.output_script_data(main_text .. str)
|
||||
end
|
||||
|
||||
function Public.reset_spam_table()
|
||||
@@ -59,7 +63,15 @@ function Public.is_spamming(player, value_to_compare, text)
|
||||
end
|
||||
|
||||
if text then
|
||||
debug_text('Frame: ' .. text)
|
||||
if this.show_debug_text_for then
|
||||
for name, _ in pairs(this.show_debug_text_for) do
|
||||
local debug_player = game.get_player(name)
|
||||
if debug_player and debug_player.valid then
|
||||
debug_player.print('Player ' .. player.name .. ' clicked on: ' .. text .. ' on surface: ' .. player.surface.name .. ' at position: ' .. player.position.x .. ', ' .. player.position.y .. ' at tick: ' .. game.tick)
|
||||
end
|
||||
end
|
||||
end
|
||||
debug_text('Player ' .. player.name .. ' clicked on: ' .. text .. ' on surface: ' .. player.surface.name .. ' at position: ' .. player.position.x .. ', ' .. player.position.y .. ' at tick: ' .. game.tick)
|
||||
end
|
||||
|
||||
if game.tick_paused then
|
||||
@@ -67,7 +79,7 @@ function Public.is_spamming(player, value_to_compare, text)
|
||||
end
|
||||
|
||||
if this.debug_spam then
|
||||
log(debug.traceback())
|
||||
Server.output_script_data(debug.traceback())
|
||||
end
|
||||
|
||||
local tick = game.tick
|
||||
@@ -126,4 +138,41 @@ Event.on_init(
|
||||
end
|
||||
)
|
||||
|
||||
Commands.new('sp_debug_text', 'Spam Protection - Shows the debug text for when players are clicking gui buttons.')
|
||||
:require_admin()
|
||||
:add_parameter('state', false, 'boolean')
|
||||
:callback(
|
||||
function (player, state)
|
||||
this.debug_text = state
|
||||
player.print('Debug text for spam protection has been ' .. (state and 'enabled' or 'disabled') .. '!')
|
||||
end
|
||||
)
|
||||
|
||||
Commands.new('sp_debug_spam', 'Spam Protection - Shows the debug spam for when players are clicking gui buttons.')
|
||||
:require_admin()
|
||||
:add_parameter('state', false, 'boolean')
|
||||
:callback(
|
||||
function (player, state)
|
||||
this.debug_spam = state
|
||||
player.print('Debug spam for spam protection has been ' .. (state and 'enabled' or 'disabled') .. '!')
|
||||
end
|
||||
)
|
||||
|
||||
Commands.new('sp_print_text', 'Spam Protection - Prints the debug text for when players are clicking gui buttons to your console.')
|
||||
:require_admin()
|
||||
:add_parameter('state', false, 'boolean')
|
||||
:callback(
|
||||
function (player, state)
|
||||
this.show_debug_text_for = this.show_debug_text_for or {}
|
||||
|
||||
if state then
|
||||
this.show_debug_text_for[player.name] = true
|
||||
player.print('Debug text for spam protection has been enabled!')
|
||||
else
|
||||
this.show_debug_text_for[player.name] = nil
|
||||
player.print('Debug text for spam protection has been disabled!')
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
return Public
|
||||
|
||||
@@ -275,7 +275,7 @@ end)
|
||||
Commands.new('undo_player_actions', 'Undoes the actions of a player as a player by creating a poll.')
|
||||
:add_parameter('player', false, 'player')
|
||||
:require_validation('Only utilize this command if the player is jailed and has entities in the undo queue.')
|
||||
:require_playtime(60 * 60 * 60 * 24 * 40) -- 30 days
|
||||
:require_playtime(60 * 60 * 60 * 24 * 40) -- 40 days
|
||||
:callback(function (player, target_player)
|
||||
if not target_player or not target_player.valid then
|
||||
return player.print('Player is not valid.')
|
||||
|
||||
Reference in New Issue
Block a user