1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-01-14 02:34:09 +02:00
ComfyFactorio/maps/mountain_fortress_v3/entities.lua

1698 lines
52 KiB
Lua
Raw Normal View History

2020-05-20 09:09:39 +02:00
require 'modules.rocks_broken_paint_tiles'
2020-05-17 12:23:55 +02:00
local Event = require 'utils.event'
local Public = require 'maps.mountain_fortress_v3.table'
2020-08-14 22:41:45 +02:00
local Server = require 'utils.server'
2021-05-25 22:19:20 +02:00
local RPG = require 'modules.rpg.main'
2020-12-05 19:09:09 +02:00
local Collapse = require 'modules.collapse'
2020-06-07 13:33:24 +02:00
local Alert = require 'utils.alert'
local Task = require 'utils.task_token'
2022-04-05 19:28:08 +02:00
local Score = require 'utils.gui.score'
local Discord = require 'utils.discord'
2021-05-15 16:01:07 +02:00
local Core = require 'utils.core'
local Diff = require 'modules.difficulty_vote_by_amount'
local format_number = require 'util'.format_number
local RPG_Progression = require 'utils.datastore.rpg_data'
2020-05-17 12:23:55 +02:00
local WD = require 'modules.wave_defense.table'
2024-05-27 20:30:03 +02:00
local scenario_name = Public.scenario_name
local StatData = require 'utils.datastore.statistics'
StatData.add_normalize('coins', 'Coins collected'):set_tooltip('The amount of coins the player has collected through mining/killed enemies.')
2020-05-17 12:23:55 +02:00
2024-10-14 23:46:34 +02:00
2020-08-09 20:22:33 +02:00
local random = math.random
local floor = math.floor
local abs = math.abs
local round = math.round
2020-05-17 12:23:55 +02:00
-- Use these settings for live
local send_ping_to_channel = Discord.channel_names.mtn_channel
-- Use these settings for testing
-- bot-lounge
-- local send_ping_to_channel = Discord.channel_names.bot_quarters
-- dev
-- local send_ping_to_channel = Discord.channel_names.bot_quarters
-- local role_to_mention = Discord.role_mentions.test_role
2020-10-30 18:32:40 +02:00
local chests = {
'wooden-chest',
'iron-chest',
'steel-chest',
'crash-site-chest-1',
'crash-site-chest-2',
'crash-site-spaceship-wreck-big-1',
'crash-site-spaceship-wreck-big-2',
'crash-site-spaceship-wreck-medium-1',
'crash-site-spaceship-wreck-medium-2',
'crash-site-spaceship-wreck-medium-3'
}
2024-11-08 22:56:53 +02:00
local valid_forces = {
[2] = true,
[4] = true,
[5] = true
}
2020-10-30 18:32:40 +02:00
local size_chests = #chests
2020-05-17 12:23:55 +02:00
local treasure_chest_messages = {
({ 'entity.treasure_1' }),
({ 'entity.treasure_2' }),
({ 'entity.treasure_3' })
2020-05-17 12:23:55 +02:00
}
local rare_treasure_chest_messages = {
({ 'entity.treasure_rare_1' }),
({ 'entity.treasure_rare_2' }),
({ 'entity.treasure_rare_3' })
2020-05-17 12:23:55 +02:00
}
local disabled_threats = {
['entity-ghost'] = true,
['raw-fish'] = true
}
local defeated_messages = {
({ 'entity.defeated_1' }),
({ 'entity.defeated_2' }),
({ 'entity.defeated_3' }),
({ 'entity.defeated_4' })
2020-05-17 12:23:55 +02:00
}
2020-07-29 19:30:45 +02:00
local protect_types = {
2020-06-03 20:09:00 +02:00
['cargo-wagon'] = true,
['artillery-wagon'] = true,
['fluid-wagon'] = true,
2020-07-29 19:30:45 +02:00
['locomotive'] = true,
2020-08-09 20:22:33 +02:00
['reactor'] = true,
['spider-vehicle'] = true,
['car'] = true
2020-06-03 20:09:00 +02:00
}
2024-10-26 13:05:31 +02:00
local change_force_for_drills_token =
Task.register(
function (event)
local entity = event.entity
if not entity or not entity.valid then return end
entity.force = 'bonus_drill'
end
)
2023-12-03 01:21:37 +02:00
local function get_random_weighted(player, weighted_table, item_index, weight_index)
2020-10-30 18:32:40 +02:00
local total_weight = 0
item_index = item_index or 1
weight_index = weight_index or 2
2023-12-03 01:21:37 +02:00
local debug_vars = Public.get('debug_vars')
2020-10-30 18:32:40 +02:00
for _, w in pairs(weighted_table) do
total_weight = total_weight + w[weight_index]
end
local index = random() * total_weight
local weight_sum = 0
for _, w in pairs(weighted_table) do
weight_sum = weight_sum + w[weight_index]
if weight_sum >= index then
2023-12-03 01:21:37 +02:00
if debug_vars and debug_vars.enabled and debug_vars.vars then
local vars = debug_vars.vars.mining_chance
vars[player.name] = vars[player.name] or {}
vars[player.name][w[3]] = vars[player.name][w[3]] or 0
vars[player.name][w[3]] = vars[player.name][w[3]] + 1
end
2020-10-30 18:32:40 +02:00
return w[item_index]
end
end
end
local function on_entity_removed(data)
local entity = data.entity
local upgrades = Public.get('upgrades')
2020-10-30 18:32:40 +02:00
local built = {
2020-11-15 20:23:54 +02:00
['land-mine'] = upgrades.landmine.built,
['flamethrower-turret'] = upgrades.flame_turret.built
2020-10-30 18:32:40 +02:00
}
local validator = {
['land-mine'] = 'landmine',
['flamethrower-turret'] = 'flame_turret'
}
local name = validator[entity.name]
if built[entity.name] and entity.force.index == 1 then
2020-11-15 20:23:54 +02:00
upgrades[name].built = upgrades[name].built - 1
if upgrades[name].built <= 0 then
upgrades[name].built = 0
2020-10-30 18:32:40 +02:00
end
end
end
2020-11-15 20:23:54 +02:00
local function check_health()
local locomotive_health = Public.get('locomotive_health')
local locomotive_max_health = Public.get('locomotive_max_health')
local carriages = Public.get('carriages')
if locomotive_health <= 0 then
Public.set('locomotive_health', 0)
end
2024-10-14 23:46:34 +02:00
2020-11-15 20:23:54 +02:00
local m = locomotive_health / locomotive_max_health
if carriages then
for i = 1, #carriages do
local entity = carriages[i]
2020-11-04 18:14:30 +02:00
if not (entity and entity.valid) then
return
end
if entity.type == 'locomotive' then
2024-10-14 23:46:34 +02:00
entity.health = entity.max_health * m
2020-11-04 18:14:30 +02:00
else
2024-10-14 23:46:34 +02:00
entity.health = entity.max_health * m
2020-11-04 18:14:30 +02:00
end
end
end
end
2020-11-15 20:23:54 +02:00
local function check_health_final_damage(final_damage_amount)
local carriages = Public.get('carriages')
2020-11-15 20:23:54 +02:00
if carriages then
for i = 1, #carriages do
local entity = carriages[i]
2020-11-04 18:14:30 +02:00
if not (entity and entity.valid) then
return
end
entity.health = entity.health + final_damage_amount
end
end
end
2021-05-16 14:57:42 +02:00
local function set_train_final_health(final_damage_amount, repair)
2020-05-17 12:23:55 +02:00
if final_damage_amount == 0 then
return
end
2020-06-03 20:09:00 +02:00
local locomotive = Public.get('locomotive')
2020-11-15 20:23:54 +02:00
if not (locomotive and locomotive.valid) then
2020-07-28 11:24:16 +02:00
return
end
local locomotive_health = Public.get('locomotive_health')
local locomotive_max_health = Public.get('locomotive_max_health')
2021-05-16 14:57:42 +02:00
if not repair then
local poison_deployed = Public.get('poison_deployed')
local robotics_deployed = Public.get('robotics_deployed')
2021-05-16 14:57:42 +02:00
local lower_high = locomotive_max_health * 0.4
local higher_high = locomotive_max_health * 0.5
local lower_low = locomotive_max_health * 0.2
local higher_low = locomotive_max_health * 0.3
if locomotive_health >= lower_high and locomotive_health <= higher_high then
if not poison_deployed then
local carriages = Public.get('carriages')
2021-05-16 14:57:42 +02:00
if WD.get('wave_number') <= 800 then
2023-01-09 12:28:15 +02:00
if carriages then
for i = 1, #carriages do
local entity = carriages[i]
Public.enable_poison_defense(entity.position)
end
2021-05-16 14:57:42 +02:00
end
end
local p = {
position = locomotive.position
}
local msg = ({ 'entity.train_taking_damage' })
2021-05-16 14:57:42 +02:00
Alert.alert_all_players_location(p, msg)
Public.set().poison_deployed = true
2021-05-16 14:57:42 +02:00
end
elseif locomotive_health >= lower_low and locomotive_health <= higher_low then
if not robotics_deployed then
local carriages = Public.get('carriages')
2021-05-16 14:57:42 +02:00
if carriages then
2022-04-18 18:46:19 +02:00
for i = 1, #carriages do
local entity = carriages[i]
Public.enable_robotic_defense(entity.position)
end
end
2021-05-16 14:57:42 +02:00
local p = {
position = locomotive.position
}
local msg = ({ 'entity.train_taking_damage' })
2021-05-16 14:57:42 +02:00
Alert.alert_all_players_location(p, msg)
Public.set().robotics_deployed = true
end
2021-05-16 14:57:42 +02:00
elseif locomotive_health >= locomotive_max_health then
Public.set().poison_deployed = false
end
2020-06-07 13:33:24 +02:00
end
2024-11-11 09:57:27 +02:00
if locomotive_health <= 0 then
2024-11-07 00:51:45 +02:00
Public.set('locomotive_position', locomotive.position)
2024-11-11 09:57:27 +02:00
Public.game_is_over()
end
2020-11-15 20:23:54 +02:00
if locomotive_health <= 0 then
check_health_final_damage(final_damage_amount)
2020-06-03 20:09:00 +02:00
return
end
Public.set('locomotive_health', floor(locomotive_health - final_damage_amount))
2020-11-15 20:23:54 +02:00
if locomotive_health > locomotive_max_health then
Public.set('locomotive_health', locomotive_max_health)
2020-05-17 12:23:55 +02:00
end
locomotive_health = Public.get('locomotive_health')
2020-06-03 20:09:00 +02:00
2020-11-15 20:23:54 +02:00
check_health()
2020-06-03 20:09:00 +02:00
local health_text = Public.get('health_text')
2020-11-15 20:23:54 +02:00
if health_text and health_text.valid then
health_text.text = 'HP: ' .. round(locomotive_health) .. ' / ' .. round(locomotive_max_health)
end
2020-05-17 12:23:55 +02:00
end
2024-05-28 10:43:10 +02:00
local function is_protected(e)
2024-10-14 23:46:34 +02:00
if string.sub(e.surface.name, 0, #scenario_name) ~= scenario_name then
2024-05-28 10:43:10 +02:00
return true
end
2023-08-10 14:28:32 +02:00
2024-05-28 10:43:10 +02:00
if protect_types[e.type] then
return true
2023-06-22 22:57:07 +02:00
end
2023-08-10 14:28:32 +02:00
2023-06-22 22:57:07 +02:00
return false
end
2021-10-10 22:27:53 +02:00
local function protect_entities(data)
local cause = data.cause
local entity = data.entity
local force = data.force
local dmg = data.final_damage_amount
2020-11-17 13:45:27 +02:00
if not dmg then
return
end
local check_heavy_damage = Public.get('check_heavy_damage')
if check_heavy_damage then
2023-05-26 16:24:22 +02:00
if (entity.type == 'simple-entity' or entity.type == 'simple-entity-with-owner') and dmg >= 500 then
entity.health = entity.health + dmg
end
2020-11-17 13:45:27 +02:00
end
2020-05-17 12:23:55 +02:00
2020-06-03 20:09:00 +02:00
if entity.force.index ~= 1 then
return
end
2020-05-17 12:23:55 +02:00
local carriages_numbers = Public.get('carriages_numbers')
2024-05-28 10:43:10 +02:00
if is_protected(entity) then
2021-10-10 22:27:53 +02:00
if (cause and cause.valid) then
2023-05-26 16:24:22 +02:00
if Public.valid_enemy_forces[cause.force.name] then
if carriages_numbers and carriages_numbers[entity.unit_number] then
2021-05-16 14:57:42 +02:00
set_train_final_health(dmg, false)
return
else
entity.health = entity.health - dmg
return
2020-12-05 19:09:09 +02:00
end
2020-11-17 13:45:27 +02:00
end
2021-10-10 22:27:53 +02:00
elseif not (cause and cause.valid) then
2023-05-26 16:24:22 +02:00
if force and Public.valid_enemy_forces[force.name] then
if carriages_numbers and carriages_numbers[entity.unit_number] then
2021-05-16 14:57:42 +02:00
set_train_final_health(dmg, false)
return
else
entity.health = entity.health - dmg
return
2020-12-05 19:09:09 +02:00
end
2020-05-17 12:23:55 +02:00
end
end
2020-11-17 13:45:27 +02:00
entity.health = entity.health + dmg
2020-05-17 12:23:55 +02:00
end
end
2020-10-30 18:32:40 +02:00
local function hidden_treasure(player, entity)
2021-05-26 09:45:37 +02:00
local rpg = RPG.get_value_from_player(player.index)
if not rpg then
return
end
2021-05-26 09:45:37 +02:00
local magic = rpg.magicka
2023-12-01 02:25:49 +02:00
local magic_requirement = Public.get('magic_requirement')
2020-07-06 15:45:09 +02:00
2023-12-01 02:25:49 +02:00
if magic >= magic_requirement then
2020-08-09 20:22:33 +02:00
local msg = rare_treasure_chest_messages[random(1, #rare_treasure_chest_messages)]
2020-06-07 13:33:24 +02:00
Alert.alert_player(player, 5, msg)
Public.add_loot_rare(entity.surface, entity.position, 'wooden-chest', magic)
2020-05-17 12:23:55 +02:00
return
end
2020-08-09 20:22:33 +02:00
local msg = treasure_chest_messages[random(1, #treasure_chest_messages)]
2020-10-30 18:32:40 +02:00
Alert.alert_player(player, 5, msg, nil, nil, 0.3)
Public.add_loot(entity.surface, entity.position, chests[random(1, size_chests)])
2020-05-17 12:23:55 +02:00
end
2021-10-10 22:27:53 +02:00
local function biters_chew_rocks_faster(data)
local cause = data.cause
local entity = data.entity
local final_damage_amount = data.final_damage_amount
if entity.force.index ~= 3 then
2020-05-17 12:23:55 +02:00
return
end --Neutral Force
2021-10-10 22:27:53 +02:00
if not cause then
2020-05-17 12:23:55 +02:00
return
end
2021-10-10 22:27:53 +02:00
if not cause.valid then
2020-05-17 12:23:55 +02:00
return
end
2024-11-08 22:56:53 +02:00
if not valid_forces[cause.force.index] then
2020-05-17 12:23:55 +02:00
return
end --Enemy Force
2021-10-10 22:27:53 +02:00
entity.health = entity.health - final_damage_amount * 7
2020-05-17 12:23:55 +02:00
end
local projectiles = { 'grenade', 'explosive-rocket', 'grenade', 'explosive-rocket', 'explosive-cannon-projectile' }
2020-10-30 18:32:40 +02:00
2020-11-17 13:45:27 +02:00
local function angry_tree(entity, cause, player)
2020-05-17 12:23:55 +02:00
if entity.type ~= 'tree' then
return
end
2020-07-07 16:30:04 +02:00
2020-11-18 16:24:22 +02:00
if random(1, 6) == 1 then
Public.buried_biter(entity.surface, entity.position)
2020-05-17 12:23:55 +02:00
end
2020-11-18 16:24:22 +02:00
if random(1, 8) == 1 then
Public.buried_worm(entity.surface, entity.position)
2020-05-17 12:23:55 +02:00
end
2020-08-31 20:37:27 +02:00
if random(1, 32) ~= 1 then
2020-05-17 12:23:55 +02:00
return
end
local position = false
if cause then
if cause.valid then
position = cause.position
end
end
if not position then
position = { entity.position.x + (-20 + random(0, 40)), entity.position.y + (-20 + random(0, 40)) }
2020-05-17 12:23:55 +02:00
end
2020-11-17 13:45:27 +02:00
if player then
2021-05-25 22:19:20 +02:00
local forest_zone = RPG.get_value_from_player(player.index, 'forest_zone')
2020-11-17 13:45:27 +02:00
if forest_zone and random(1, 32) == 1 then
local cbl = Public.refill_turret_callback
local data = { callback_data = Public.piercing_rounds_magazine_ammo }
2020-11-17 13:45:27 +02:00
local e =
entity.surface.create_entity(
{
name = 'gun-turret',
position = entity.position,
force = 'enemy'
}
)
if e.can_insert(Public.piercing_rounds_magazine_ammo) then
e.insert(Public.piercing_rounds_magazine_ammo)
end
local callback = Task.get(cbl)
2020-11-17 13:45:27 +02:00
callback(e, data)
return
end
end
2020-05-17 12:23:55 +02:00
entity.surface.create_entity(
{
2020-08-09 20:22:33 +02:00
name = projectiles[random(1, 5)],
2020-05-17 12:23:55 +02:00
position = entity.position,
force = 'neutral',
source = entity.position,
target = position,
max_range = 16,
speed = 0.01
}
)
end
local function give_coin(player)
local coin_amount = Public.get('coin_amount')
local coin_override = Public.get('coin_override')
2021-05-25 22:19:20 +02:00
local forest_zone = RPG.get_value_from_player(player.index, 'forest_zone')
2020-11-17 13:45:27 +02:00
if forest_zone then
2020-11-17 16:03:05 +02:00
if random(1, 3) ~= 1 then
2020-11-17 13:45:27 +02:00
return
end
end
2020-10-30 18:32:40 +02:00
2020-10-30 23:05:05 +02:00
if coin_amount >= 1 then
if coin_override then
player.insert({ name = 'coin', count = coin_override })
2024-05-27 20:30:03 +02:00
StatData.get_data(player):increase('coins', coin_override)
2020-10-30 23:05:05 +02:00
else
2024-05-27 20:30:03 +02:00
---@diagnostic disable-next-line: param-type-mismatch
player.insert({ name = 'coin', count = random(1, coin_amount) })
2024-05-27 20:30:03 +02:00
StatData.get_data(player):increase('coins', coin_amount)
2020-10-30 23:05:05 +02:00
end
end
2020-05-17 12:23:55 +02:00
end
2021-02-04 21:23:07 +02:00
local immunity_spawner =
Task.register(
function (data)
local entity = data.entity
if not entity or not entity.valid then
return
end
entity.destructible = true
2021-02-04 21:23:07 +02:00
end
)
2021-02-04 21:23:07 +02:00
local unstuck_player_token =
Task.register(
function (data)
local index = data.index
if not index then
return
end
local player = game.get_player(index)
if not player or not player.valid then
return
end
2024-10-26 02:06:48 +02:00
local surface = player.physical_surface
2024-11-07 00:51:45 +02:00
local position = surface.find_non_colliding_position('character', player.physical_position, 32, 1)
if not position then
return
end
player.teleport(position, surface)
end
)
2020-10-30 18:32:40 +02:00
local mining_events = {
{
function ()
2020-10-30 18:32:40 +02:00
end,
300000,
2023-12-08 14:52:17 +02:00
'Nothing #1'
2020-10-30 18:32:40 +02:00
},
{
function ()
2020-10-30 18:32:40 +02:00
end,
16384,
2023-12-08 14:52:17 +02:00
'Nothing #2'
2020-10-30 18:32:40 +02:00
},
{
function ()
2020-10-30 18:32:40 +02:00
end,
4096,
2023-12-08 14:52:17 +02:00
'Nothing #3'
2023-12-03 01:21:37 +02:00
},
2020-10-30 18:32:40 +02:00
{
function (entity)
if Public.is_around_train(entity) then
2020-10-30 18:32:40 +02:00
entity.destroy()
return
end
Public.buried_biter(entity.surface, entity.position)
2020-10-30 18:32:40 +02:00
entity.destroy()
end,
4096,
2023-12-08 14:52:17 +02:00
'Angry Biter #1'
2023-12-03 01:21:37 +02:00
},
{
function (entity)
2023-12-03 01:21:37 +02:00
if Public.is_around_train(entity) then
entity.destroy()
return
end
Public.buried_biter(entity.surface, entity.position)
entity.destroy()
end,
512,
2023-12-08 14:52:17 +02:00
'Angry Biter #2'
2020-10-30 18:32:40 +02:00
},
{
function (entity)
if Public.is_around_train(entity) then
2020-10-30 18:32:40 +02:00
entity.destroy()
return
end
Public.buried_worm(entity.surface, entity.position)
2020-10-30 18:32:40 +02:00
entity.destroy()
end,
2048,
2023-12-08 14:52:17 +02:00
'Angry Worm #1'
2020-10-30 18:32:40 +02:00
},
{
function (entity)
if Public.is_around_train(entity) then
2020-10-30 18:32:40 +02:00
entity.destroy()
return
end
2024-10-14 23:46:34 +02:00
Public.tick_tack_trap(entity)
2020-10-30 18:32:40 +02:00
entity.destroy()
end,
2048,
2023-12-08 14:52:17 +02:00
'Dangerous Trap #1'
2020-10-30 18:32:40 +02:00
},
{
function (entity, index)
if Public.is_around_train(entity) then
2020-10-30 18:32:40 +02:00
entity.destroy()
return
end
local player = game.get_player(index)
if entity.type == 'tree' then
2020-11-17 13:45:27 +02:00
angry_tree(entity, player.character, player)
2020-10-30 18:32:40 +02:00
entity.destroy()
end
end,
2023-12-08 14:52:17 +02:00
1024,
'Angry Tree #1'
2020-10-30 18:32:40 +02:00
},
{
function (entity, index)
2020-10-30 18:32:40 +02:00
local player = game.get_player(index)
2023-12-08 14:52:17 +02:00
hidden_treasure(player, entity)
Task.set_timeout_in_ticks(5, unstuck_player_token, { index = index })
2020-10-30 18:32:40 +02:00
end,
2023-12-08 14:52:17 +02:00
1024,
'Treasure Tier #1'
2020-10-30 18:32:40 +02:00
},
{
function (entity, index)
2020-10-30 18:32:40 +02:00
local player = game.get_player(index)
2023-12-08 14:52:17 +02:00
hidden_treasure(player, entity)
Task.set_timeout_in_ticks(5, unstuck_player_token, { index = index })
2020-10-30 18:32:40 +02:00
end,
2023-12-08 14:52:17 +02:00
512,
'Treasure Tier #2'
2020-10-30 18:32:40 +02:00
},
{
function (entity, index)
2020-10-30 18:32:40 +02:00
local player = game.get_player(index)
hidden_treasure(player, entity)
Task.set_timeout_in_ticks(5, unstuck_player_token, { index = index })
2020-10-30 18:32:40 +02:00
end,
256,
2023-12-08 14:52:17 +02:00
'Treasure Tier #3'
2020-10-30 18:32:40 +02:00
},
{
function (entity, index)
2020-10-30 18:32:40 +02:00
local player = game.get_player(index)
hidden_treasure(player, entity)
Task.set_timeout_in_ticks(5, unstuck_player_token, { index = index })
2020-10-30 18:32:40 +02:00
end,
128,
2023-12-08 14:52:17 +02:00
'Treasure Tier #4'
2020-10-30 18:32:40 +02:00
},
{
function (entity, index)
2020-10-30 18:32:40 +02:00
local player = game.get_player(index)
hidden_treasure(player, entity)
Task.set_timeout_in_ticks(5, unstuck_player_token, { index = index })
2020-10-30 18:32:40 +02:00
end,
64,
2023-12-08 14:52:17 +02:00
'Treasure Tier #5'
2020-10-30 18:32:40 +02:00
},
{
function (entity, index)
2020-10-30 18:32:40 +02:00
local player = game.get_player(index)
hidden_treasure(player, entity)
Task.set_timeout_in_ticks(5, unstuck_player_token, { index = index })
2020-10-30 18:32:40 +02:00
end,
32,
2023-12-08 14:52:17 +02:00
'Treasure Tier #6'
2020-10-30 18:32:40 +02:00
},
{
function (entity, index)
2020-10-30 18:32:40 +02:00
local player = game.get_player(index)
hidden_treasure(player, entity)
Task.set_timeout_in_ticks(5, unstuck_player_token, { index = index })
2020-10-30 18:32:40 +02:00
end,
16,
2023-12-08 14:52:17 +02:00
'Treasure Tier #7'
2020-10-30 18:32:40 +02:00
},
{
function (entity, index)
if Public.is_around_train(entity) then
2020-10-30 18:32:40 +02:00
entity.destroy()
return
end
local ent_to_create = { 'biter-spawner', 'spitter-spawner' }
2020-10-30 18:32:40 +02:00
local position = entity.position
local surface = entity.surface
local e = surface.create_entity({ name = ent_to_create[random(1, #ent_to_create)], position = position, force = 'enemy' })
e.destructible = false
Task.set_timeout_in_ticks(300, immunity_spawner, { entity = e })
Task.set_timeout_in_ticks(5, unstuck_player_token, { index = index })
end,
2023-12-08 14:52:17 +02:00
512,
'Nest #1'
},
{
function (entity, index)
if Public.is_around_train(entity) then
entity.destroy()
return
end
local ent_to_create = { 'biter-spawner', 'spitter-spawner' }
local position = entity.position
local surface = entity.surface
local e = surface.create_entity({ name = ent_to_create[random(1, #ent_to_create)], position = position, force = 'enemy' })
2021-02-04 21:23:07 +02:00
e.destructible = false
Task.set_timeout_in_ticks(300, immunity_spawner, { entity = e })
Task.set_timeout_in_ticks(5, unstuck_player_token, { index = index })
2020-10-30 18:32:40 +02:00
end,
512,
2023-12-08 14:52:17 +02:00
'Nest #2'
2020-10-30 18:32:40 +02:00
},
{
function (entity)
2021-10-29 00:06:35 +02:00
local chest = 'crash-site-chest-' .. random(1, 2)
local container = entity.surface.create_entity({ name = chest, position = entity.position, force = 'neutral' })
2021-11-18 01:58:54 +02:00
if container and container.health then
container.insert({ name = 'vehicle-machine-gun', count = 1 })
2021-11-18 01:58:54 +02:00
container.health = random(1, container.health)
2021-10-29 00:06:35 +02:00
end
end,
2023-12-08 14:52:17 +02:00
64,
'VSMG #1'
2021-10-29 00:06:35 +02:00
},
2020-10-30 18:32:40 +02:00
{
function (entity, index)
2020-10-30 18:32:40 +02:00
local position = entity.position
local surface = entity.surface
surface.create_entity({ name = 'car', position = position, force = 'player' })
Task.set_timeout_in_ticks(5, unstuck_player_token, { index = index })
2020-10-30 18:32:40 +02:00
local player = game.players[index]
local msg = ({ 'entity.found_car', player.name })
2020-10-30 18:32:40 +02:00
Alert.alert_player(player, 15, msg)
end,
2023-12-08 14:52:17 +02:00
32,
'Car #1'
2020-10-30 18:32:40 +02:00
}
}
2020-05-17 12:23:55 +02:00
local function on_player_mined_entity(event)
local entity = event.entity
2022-04-10 11:21:52 +02:00
local player = game.get_player(event.player_index)
2020-05-17 12:23:55 +02:00
if not player.valid then
return
end
if not entity.valid then
return
end
2024-10-27 00:01:15 +02:00
local current_task = Public.get('current_task')
if not current_task.done then
return
end
2021-05-26 09:45:37 +02:00
local rpg_char = RPG.get_value_from_player(player.index)
2024-10-21 15:43:11 +02:00
if not rpg_char then return end
2020-05-17 12:23:55 +02:00
2024-10-14 23:46:34 +02:00
if string.sub(entity.surface.name, 0, #scenario_name) ~= scenario_name then
2020-05-17 12:23:55 +02:00
return
end
2020-10-30 18:32:40 +02:00
local d = {
2020-11-15 20:23:54 +02:00
entity = entity
2020-06-03 20:09:00 +02:00
}
2020-10-30 18:32:40 +02:00
on_entity_removed(d)
2020-06-03 20:09:00 +02:00
2020-05-17 12:23:55 +02:00
if disabled_threats[entity.name] then
return
end
local mined_scrap = Public.get('mined_scrap')
2020-11-15 20:23:54 +02:00
2020-12-04 02:09:52 +02:00
if entity.type == 'simple-entity' or entity.type == 'simple-entity-with-owner' or entity.type == 'tree' then
Public.set().mined_scrap = mined_scrap + 1
Public.on_player_mined_entity(event)
2020-08-21 13:56:01 +02:00
if entity.type == 'tree' then
2020-10-30 18:32:40 +02:00
if random(1, 3) == 1 then
2020-08-21 13:56:01 +02:00
give_coin(player)
end
2023-05-27 17:43:18 +02:00
elseif entity.type == 'simple-entity-with-owner' then
2023-05-26 16:24:22 +02:00
if random(1, 6) == 1 then
give_coin(player)
end
2023-05-27 17:43:18 +02:00
else
give_coin(player)
2020-08-21 13:56:01 +02:00
end
2020-07-24 17:33:28 +02:00
if rpg_char.stone_path then
2023-09-27 20:00:05 +02:00
local upgrades = Public.get('upgrades')
if not upgrades.has_upgraded_tile_when_mining then
entity.surface.set_tiles({ { name = 'stone-path', position = entity.position } }, true)
2023-09-27 20:00:05 +02:00
else
entity.surface.set_tiles({ { name = 'black-refined-concrete', position = entity.position } }, true)
2023-09-27 20:00:05 +02:00
end
2020-07-24 17:33:28 +02:00
end
2020-10-30 11:45:12 +02:00
2023-12-03 01:21:37 +02:00
local func = get_random_weighted(player, mining_events)
2020-10-30 18:32:40 +02:00
func(entity, player.index)
2020-05-17 12:23:55 +02:00
end
end
2020-06-03 20:09:00 +02:00
local function on_robot_mined_entity(event)
local entity = event.entity
if not entity.valid then
2020-05-17 12:23:55 +02:00
return
end
2020-06-03 20:09:00 +02:00
2024-10-27 00:01:15 +02:00
local current_task = Public.get('current_task')
if not current_task.done then
return
end
2024-10-14 23:46:34 +02:00
if string.sub(entity.surface.name, 0, #scenario_name) ~= scenario_name then
2020-05-17 12:23:55 +02:00
return
end
2020-06-03 20:09:00 +02:00
2020-10-30 18:32:40 +02:00
local d = {
2020-11-15 20:23:54 +02:00
entity = entity
2020-06-03 20:09:00 +02:00
}
2020-10-30 18:32:40 +02:00
on_entity_removed(d)
2020-06-03 20:09:00 +02:00
end
2021-10-10 22:27:53 +02:00
local function get_damage(data)
local entity = data.entity
local original_damage_amount = data.original_damage_amount
local damage = original_damage_amount + original_damage_amount * random(1, 100)
2020-06-05 18:01:32 +02:00
if entity.prototype.resistances then
if entity.prototype.resistances.physical then
damage = damage - entity.prototype.resistances.physical.decrease
damage = damage - damage * entity.prototype.resistances.physical.percent
end
end
2020-08-09 20:22:33 +02:00
damage = round(damage, 3)
2020-06-05 18:01:32 +02:00
if damage < 1 then
damage = 1
end
return damage
end
local function kaboom(entity, target, damage)
local base_vector = { target.position.x - entity.position.x, target.position.y - entity.position.y }
2020-06-05 18:01:32 +02:00
local vector = { base_vector[1], base_vector[2] }
2020-06-05 18:01:32 +02:00
vector[1] = vector[1] * 512
vector[2] = vector[2] * 256
local msg = { 'TASTY', 'MUNCH', 'SNACK_TIME', 'OVER 9000!' }
2020-06-05 18:01:32 +02:00
entity.surface.create_entity(
{
2024-09-25 20:46:27 +02:00
name = 'compi-speech-bubble',
position = { entity.position.x + base_vector[1] * 0.5, entity.position.y + base_vector[2] * 0.5 },
2020-08-09 20:22:33 +02:00
text = msg[random(1, #msg)],
2024-09-25 20:46:27 +02:00
source = entity,
lifetime = 30
2020-06-05 18:01:32 +02:00
}
)
2020-08-09 20:22:33 +02:00
if abs(vector[1]) > abs(vector[2]) then
local d = abs(vector[1])
if abs(vector[1]) > 0 then
2020-06-05 18:01:32 +02:00
vector[1] = vector[1] / d
end
2020-08-09 20:22:33 +02:00
if abs(vector[2]) > 0 then
2020-06-05 18:01:32 +02:00
vector[2] = vector[2] / d
end
else
2020-08-09 20:22:33 +02:00
local d = abs(vector[2])
if abs(vector[2]) > 0 then
2020-06-05 18:01:32 +02:00
vector[2] = vector[2] / d
end
2020-08-09 20:22:33 +02:00
if abs(vector[1]) > 0 and d > 0 then
2020-06-05 18:01:32 +02:00
vector[1] = vector[1] / d
end
end
2020-06-25 17:59:16 +02:00
vector[1] = vector[1] * 1.6
vector[2] = vector[2] * 1.6
2020-06-05 18:01:32 +02:00
2020-06-25 17:59:16 +02:00
local a = 0.30
2020-06-05 18:01:32 +02:00
2020-06-25 17:59:16 +02:00
for i = 1, 8, 1 do
2020-06-05 18:01:32 +02:00
for x = i * -1 * a, i * a, 1 do
for y = i * -1 * a, i * a, 1 do
local p = { entity.position.x + x + vector[1] * i, entity.position.y + y + vector[2] * i }
entity.surface.create_trivial_smoke({ name = 'fire-smoke', position = p })
for _, e in pairs(entity.surface.find_entities({ { p[1] - a, p[2] - a }, { p[1] + a, p[2] + a } })) do
2020-06-05 18:01:32 +02:00
if e.valid then
if e.health then
if e.destructible and e.minable then
if e.force.index ~= entity.force.index then
e.health = e.health - damage * 0.05
if e.health <= 0 then
e.die(e.force.name, entity)
end
end
end
end
end
end
end
end
end
end
2021-10-10 22:27:53 +02:00
local function boss_puncher(data)
local cause = data.cause
local entity = data.entity
2020-06-03 20:09:00 +02:00
if not cause then
return
end
if not cause.valid then
return
end
2020-06-05 18:01:32 +02:00
if cause.force.index ~= 2 then
return
end
2020-06-03 20:09:00 +02:00
if entity.force.index ~= 1 then
return
end
if not entity then
return
end
if not entity.valid then
return
end
2020-08-09 20:22:33 +02:00
if random(1, 10) == 1 then
2021-10-10 22:27:53 +02:00
kaboom(cause, entity, get_damage(data))
2020-06-03 20:09:00 +02:00
end
end
local function on_entity_damaged(event)
local entity = event.entity
2020-11-17 13:45:27 +02:00
if not (entity and entity.valid) then
2020-06-03 20:09:00 +02:00
return
end
2021-10-10 22:27:53 +02:00
local cause = event.cause
local force = event.force
local final_damage_amount = event.final_damage_amount
local original_damage_amount = event.original_damage_amount
2020-06-25 17:59:16 +02:00
local wave_number = WD.get_wave()
2020-10-30 23:05:05 +02:00
local boss_wave_warning = WD.get_alert_boss_wave()
local munch_time = Public.get('munch_time')
2023-09-05 00:03:55 +02:00
local final_battle = Public.get('final_battle')
2020-06-25 17:59:16 +02:00
2021-10-10 22:27:53 +02:00
local data = {
cause = cause,
entity = entity,
final_damage_amount = final_damage_amount,
original_damage_amount = original_damage_amount,
2023-09-05 00:03:55 +02:00
force = force,
final_battle = final_battle
2021-10-10 22:27:53 +02:00
}
protect_entities(data)
biters_chew_rocks_faster(data)
2020-08-21 13:56:01 +02:00
2020-08-04 12:10:15 +02:00
if munch_time then
2020-10-30 23:05:05 +02:00
if boss_wave_warning or wave_number >= 1000 then
2020-08-09 20:22:33 +02:00
if random(0, 512) == 1 then
2021-10-10 22:27:53 +02:00
boss_puncher(data)
2020-06-25 17:59:16 +02:00
end
end
2020-06-05 18:01:32 +02:00
end
2020-05-17 12:23:55 +02:00
end
local function on_player_repaired_entity(event)
if not event.entity then
return
end
if not event.entity.valid then
return
end
if not event.entity.health then
return
end
local entity = event.entity
local carriages_numbers = Public.get('carriages_numbers')
local tick = game.tick
2020-12-30 12:07:44 +02:00
if carriages_numbers[entity.unit_number] then
2022-04-10 11:21:52 +02:00
local player = game.get_player(event.player_index)
local rpg_t = RPG.get_value_from_player(player.index)
local repair_speed
if not rpg_t.mtn_repair then
rpg_t.mtn_repair = 0
end
if rpg_t.mtn_repair > tick then
repair_speed = 1
else
repair_speed = RPG.get_magicka(player)
end
2022-08-05 15:48:47 +02:00
if repair_speed <= 1 then
if rpg_t.mtn_repair < tick then
rpg_t.mtn_repair = tick + 10
end
2021-10-15 23:45:10 +02:00
set_train_final_health(-1, true)
2020-06-07 13:33:24 +02:00
return
else
if rpg_t.mtn_repair < tick then
rpg_t.mtn_repair = tick + 10
end
2021-05-16 14:57:42 +02:00
set_train_final_health(-repair_speed, true)
2020-06-07 13:33:24 +02:00
return
end
2020-05-17 12:23:55 +02:00
end
end
local function on_entity_died(event)
local entity = event.entity
if not entity.valid then
return
end
2023-08-01 01:06:31 +02:00
local unit_number = entity.unit_number
2020-11-17 13:45:27 +02:00
local cause = event.cause
2024-10-14 23:46:34 +02:00
if string.sub(entity.surface.name, 0, #scenario_name) ~= scenario_name then
2020-06-03 20:09:00 +02:00
return
end
2020-10-30 18:32:40 +02:00
local d = {
2020-11-15 20:23:54 +02:00
entity = entity
2020-06-03 20:09:00 +02:00
}
2023-08-01 01:06:31 +02:00
local enemy_spawners = Public.get('enemy_spawners')
if enemy_spawners.spawners[unit_number] then
enemy_spawners.spawners[unit_number] = nil
end
2020-10-30 18:32:40 +02:00
on_entity_removed(d)
2020-05-17 12:23:55 +02:00
2020-11-17 13:45:27 +02:00
local player
2023-05-26 16:24:22 +02:00
local valid_enemy_forces = Public.valid_enemy_forces
2020-11-17 13:45:27 +02:00
if cause then
if cause.valid then
if (cause and cause.name == 'character' and cause.player) then
player = cause.player
end
2023-05-26 16:24:22 +02:00
if valid_enemy_forces[cause.force.name] or cause.force.index == 3 then
2020-05-17 12:23:55 +02:00
entity.destroy()
return
end
end
end
if disabled_threats[entity.name] then
return
end
local biters_killed = Public.get('biters_killed')
local biters = Public.get('biters')
2020-11-15 20:23:54 +02:00
2020-08-26 12:09:06 +02:00
if entity.type == 'unit' or entity.type == 'unit-spawner' then
Public.set().biters_killed = biters_killed + 1
2020-11-15 20:23:54 +02:00
biters.amount = biters.amount - 1
if biters.amount <= 0 then
biters.amount = 0
2020-09-17 09:14:07 +02:00
end
if Public.is_around_train(entity) then
2020-08-26 12:09:06 +02:00
return
end
if random(1, 512) == 1 then
2024-10-14 23:46:34 +02:00
Public.tick_tack_trap(entity)
2020-08-26 12:09:06 +02:00
return
end
end
2020-08-10 23:15:29 +02:00
if entity.type == 'tree' then
2020-08-26 12:09:06 +02:00
for _, e in pairs(
2020-09-17 09:14:07 +02:00
entity.surface.find_entities_filtered(
2020-08-26 12:09:06 +02:00
{
area = {
{ entity.position.x - 4, entity.position.y - 4 },
{ entity.position.x + 4, entity.position.y + 4 }
2020-08-26 12:09:06 +02:00
},
name = 'fire-flame-on-tree'
}
)
) do
if e.valid then
e.destroy()
return
end
end
if Public.is_around_train(entity) then
2020-08-10 23:15:29 +02:00
return
end
2020-11-17 13:45:27 +02:00
angry_tree(entity, cause, player)
2020-08-10 23:15:29 +02:00
return
end
2020-08-26 12:09:06 +02:00
if entity.type == 'simple-entity' then
if Public.is_around_train(entity) then
2020-07-10 16:08:50 +02:00
entity.destroy()
return
end
2020-08-09 20:22:33 +02:00
if random(1, 32) == 1 then
2024-03-23 10:10:54 +02:00
Public.buried_biter(entity.surface, entity.position, 6)
2020-08-09 20:22:33 +02:00
entity.destroy()
2020-05-17 12:23:55 +02:00
return
end
2020-08-26 12:09:06 +02:00
if random(1, 64) == 1 then
Public.buried_worm(entity.surface, entity.position)
2020-08-09 20:22:33 +02:00
entity.destroy()
return
end
2020-08-26 12:09:06 +02:00
if random(1, 512) == 1 then
2024-10-14 23:46:34 +02:00
Public.tick_tack_trap(entity)
2020-06-05 18:01:32 +02:00
return
end
2020-05-17 12:23:55 +02:00
entity.destroy()
return
end
end
2020-12-28 11:48:25 +02:00
local function get_sorted_list(column_name, score_list)
for _ = 1, #score_list, 1 do
for y = 1, #score_list, 1 do
if not score_list[y + 1] then
break
end
if score_list[y][column_name] < score_list[y + 1][column_name] then
local key = score_list[y]
score_list[y] = score_list[y + 1]
score_list[y + 1] = key
end
end
end
return score_list
end
local function get_mvps(force)
local get_score = Score.get_table().score_table
if not get_score[force] then
return false
end
local score = get_score[force]
local score_list = {}
for _, p in pairs(game.players) do
if score.players[p.name] then
local killscore = 0
if score.players[p.name].killscore then
killscore = score.players[p.name].killscore
end
local built_entities = 0
if score.players[p.name].built_entities then
built_entities = score.players[p.name].built_entities
end
local mined_entities = 0
if score.players[p.name].mined_entities then
mined_entities = score.players[p.name].mined_entities
end
table.insert(score_list, { name = p.name, killscore = killscore, built_entities = built_entities, mined_entities = mined_entities })
2020-12-28 11:48:25 +02:00
end
end
local mvp = {}
2024-11-02 11:39:16 +02:00
if not score_list[1] or not score_list[1].name then return mvp end
2020-12-28 11:48:25 +02:00
score_list = get_sorted_list('killscore', score_list)
mvp.killscore = { name = score_list[1].name, score = score_list[1].killscore }
2020-12-29 01:09:18 +02:00
score_list = get_sorted_list('mined_entities', score_list)
mvp.mined_entities = { name = score_list[1].name, score = score_list[1].mined_entities }
2020-12-28 11:48:25 +02:00
score_list = get_sorted_list('built_entities', score_list)
mvp.built_entities = { name = score_list[1].name, score = score_list[1].built_entities }
2020-12-28 11:48:25 +02:00
return mvp
end
local function show_mvps(player)
local get_score = Score.get_table().score_table
local wave_defense_table = WD.get_table()
if not get_score then
return
end
if player.gui.left['mvps'] then
return
end
local frame = player.gui.left.add({ type = 'frame', name = 'mvps', direction = 'vertical' })
local l = frame.add({ type = 'label', caption = 'MVPs:' })
2020-12-28 11:48:25 +02:00
l.style.font = 'default-listbox'
l.style.font_color = { r = 0.55, g = 0.55, b = 0.99 }
2020-12-28 11:48:25 +02:00
local t = frame.add({ type = 'table', column_count = 2 })
2020-12-28 11:48:25 +02:00
local mvp = get_mvps('player')
if mvp then
local wave_defense = t.add({ type = 'label', caption = 'Highest Wave >> ' })
2020-12-28 11:48:25 +02:00
wave_defense.style.font = 'default-listbox'
wave_defense.style.font_color = { r = 0.22, g = 0.77, b = 0.44 }
local wave_defense_text = t.add({ type = 'label', caption = 'This rounds highest wave was: ' .. wave_defense_table.wave_number })
2020-12-28 11:48:25 +02:00
wave_defense_text.style.font = 'default-bold'
wave_defense_text.style.font_color = { r = 0.33, g = 0.66, b = 0.9 }
2020-12-28 11:48:25 +02:00
2024-11-11 09:57:27 +02:00
if mvp.killscore then
local fighter_label = t.add({ type = 'label', caption = 'Fighter >> ' })
fighter_label.style.font = 'default-listbox'
fighter_label.style.font_color = { r = 0.22, g = 0.77, b = 0.44 }
local fighter_label_text = t.add({ type = 'label', caption = mvp.killscore.name .. ' with a killing score of ' .. mvp.killscore.score .. ' kills!' })
fighter_label_text.style.font = 'default-bold'
fighter_label_text.style.font_color = { r = 0.33, g = 0.66, b = 0.9 }
end
if mvp.built_entities then
local builder_label = t.add({ type = 'label', caption = 'Builder >> ' })
builder_label.style.font = 'default-listbox'
builder_label.style.font_color = { r = 0.22, g = 0.77, b = 0.44 }
local builder_label_text = t.add({ type = 'label', caption = mvp.built_entities.name .. ' built ' .. mvp.built_entities.score .. ' things!' })
builder_label_text.style.font = 'default-bold'
builder_label_text.style.font_color = { r = 0.33, g = 0.66, b = 0.9 }
end
if mvp.mined_entities then
local miners_label = t.add({ type = 'label', caption = 'Miners >> ' })
miners_label.style.font = 'default-listbox'
miners_label.style.font_color = { r = 0.22, g = 0.77, b = 0.44 }
local miners_label_text = t.add({ type = 'label', caption = mvp.mined_entities.name .. ' mined a total of ' .. mvp.mined_entities.score .. ' entities!' })
miners_label_text.style.font = 'default-bold'
miners_label_text.style.font_color = { r = 0.33, g = 0.66, b = 0.9 }
end
2020-12-28 11:48:25 +02:00
local sent_to_discord = Public.get('sent_to_discord')
2024-10-26 01:34:21 +02:00
local server_name_matches = Server.check_server_name(Public.discord_name)
2020-12-28 11:48:25 +02:00
if not sent_to_discord and server_name_matches then
local message = {
title = 'Game over',
description = 'Player statistics is below',
color = 'failure',
field1 = {
text1 = 'Highest Wave:',
text2 = wave_defense_table.wave_number,
inline = 'false'
2024-11-11 09:57:27 +02:00
}
}
if mvp.killscore then
message.field2 = {
text1 = 'MVP Fighter:',
text2 = mvp.killscore.name .. ' with a killing score of ' .. mvp.killscore.score .. ' kills!',
inline = 'false'
2024-11-11 09:57:27 +02:00
}
end
if mvp.built_entities then
message.field3 = {
text1 = 'MVP Builder:',
text2 = mvp.built_entities.name .. ' built ' .. mvp.built_entities.score .. ' things!',
inline = 'false'
2024-11-11 09:57:27 +02:00
}
end
if mvp.mined_entities then
message.field4 = {
text1 = 'MVP Miners:',
text2 = mvp.mined_entities.name .. ' mined a total of ' .. mvp.mined_entities.score .. ' entities!',
inline = 'false'
}
2024-11-11 09:57:27 +02:00
end
Server.to_discord_embed_parsed(message)
local wave = WD.get_wave()
local threat = WD.get('threat')
local collapse_speed = Collapse.get_speed()
local collapse_amount = Collapse.get_amount()
local diff = Diff.get()
if not diff then
return
end
local time_played = Core.format_time(game.ticks_played)
local total_players = #game.players
2023-09-20 21:37:45 +02:00
local total_connected_players = #game.connected_players
local pickaxe_upgrades = Public.pickaxe_upgrades
local upgrades = Public.get('upgrades')
local pick_tier = pickaxe_upgrades[upgrades.pickaxe_tier]
if Public.get('prestige_system_enabled') then
RPG_Progression.save_all_players()
end
local date = Server.get_start_time()
2023-06-17 23:31:14 +02:00
game.server_save('Final_Mtn_v3_' .. tostring(date) .. '_wave' .. tostring(wave))
local text = {
2022-07-10 22:52:01 +02:00
title = 'Game over!',
description = 'Game statistics from the game is below',
color = 'failure',
field1 = {
text1 = 'Time played:',
text2 = time_played,
2023-10-04 20:12:26 +02:00
inline = 'false'
},
field2 = {
text1 = 'Highest wave:',
2023-10-04 20:12:26 +02:00
text2 = wave,
inline = 'false'
},
field3 = {
text1 = 'Total connected players:',
text2 = total_players,
2023-10-04 20:12:26 +02:00
inline = 'false'
},
field4 = {
text1 = 'Threat:',
text2 = format_number(threat, true),
2023-10-04 20:12:26 +02:00
inline = 'false'
},
field5 = {
text1 = 'Pickaxe Upgrade:',
2022-07-20 00:44:41 +02:00
text2 = pick_tier .. ' (' .. upgrades.pickaxe_tier .. ')',
2023-10-04 20:12:26 +02:00
inline = 'false'
},
field6 = {
text1 = 'Collapse Speed:',
text2 = collapse_speed,
2023-10-04 20:12:26 +02:00
inline = 'false'
},
field7 = {
text1 = 'Collapse Amount:',
text2 = collapse_amount,
2023-10-04 20:12:26 +02:00
inline = 'false'
2023-09-20 21:37:45 +02:00
},
field8 = {
text1 = 'Connected players:',
text2 = total_connected_players,
2023-10-04 20:12:26 +02:00
inline = 'false'
}
}
if server_name_matches then
2023-09-19 09:01:11 +02:00
if wave >= 500 then
Server.to_discord_named_parsed_embed(send_ping_to_channel, text)
end
else
Server.to_discord_embed_parsed(text)
2021-04-04 13:50:17 +02:00
end
Public.set('sent_to_discord', true)
2020-12-28 11:48:25 +02:00
end
end
end
2024-11-11 09:57:27 +02:00
function Public.game_is_over()
Public.set('game_lost', true)
Public.set_stateful('current_streak', 0)
Public.loco_died()
end
2020-10-30 18:32:40 +02:00
function Public.unstuck_player(index)
if not index then
return
end
2020-10-30 18:32:40 +02:00
local player = game.get_player(index)
if not player or not player.valid then
return
end
2024-10-26 02:06:48 +02:00
local surface = player.physical_surface
2024-10-21 15:43:11 +02:00
local position = surface.find_non_colliding_position('character', player.physical_position, 32, 1)
2020-10-30 18:32:40 +02:00
if not position then
return
end
player.teleport(position, surface)
end
2022-10-25 20:52:59 +02:00
2024-11-07 00:51:45 +02:00
function Public.loco_died()
local game_lost = Public.get('game_lost')
2021-01-26 21:17:52 +02:00
if not game_lost then
return
end
2024-10-27 00:01:15 +02:00
if not Public.is_task_done() then return end
local announced_message = Public.get('announced_message')
if announced_message then
return
end
2024-11-07 00:51:45 +02:00
local notified_game_over = Public.get('notified_game_over')
if notified_game_over then
return
end
local active_surface_index = Public.get('active_surface_index')
2024-03-28 23:22:36 +02:00
if not active_surface_index then
return
end
2020-11-15 20:23:54 +02:00
local surface = game.surfaces[active_surface_index]
2024-11-07 00:51:45 +02:00
Collapse.start_now(false, true)
2020-12-28 11:48:25 +02:00
for _, player in pairs(game.connected_players) do
player.play_sound { path = 'utility/game_lost', volume_modifier = 0.75 }
show_mvps(player)
end
local this = Public.get()
2020-11-15 20:23:54 +02:00
2020-05-17 12:23:55 +02:00
this.locomotive_health = 0
2024-11-07 00:51:45 +02:00
if this.health_text and this.health_text.valid and this.locomotive and this.locomotive.valid then
this.locomotive.color = { 0.49, 0, 255, 1 }
this.health_text.text = 'HP: ' .. round(this.locomotive_health) .. ' / ' .. round(this.locomotive_max_health)
end
2024-11-07 00:51:45 +02:00
WD.set('game_lost', true)
WD.set('target', nil)
2020-09-04 22:04:28 +02:00
local msg = defeated_messages[random(1, #defeated_messages)]
2024-11-07 00:51:45 +02:00
local p = this.locomotive_position or { x = 0, y = 0 }
2020-06-07 13:33:24 +02:00
local pos = {
2024-11-07 00:51:45 +02:00
position = p,
2020-06-07 13:33:24 +02:00
}
Alert.alert_all_players_location(pos, msg)
2020-05-17 12:23:55 +02:00
game.forces.enemy.set_friend('player', true)
2024-11-07 00:51:45 +02:00
game.forces.aggressors.set_friend('player', true)
game.forces.aggressors_frenzy.set_friend('player', true)
2020-05-17 12:23:55 +02:00
game.forces.player.set_friend('enemy', true)
2024-11-07 00:51:45 +02:00
game.forces.player.set_friend('aggressors', true)
game.forces.player.set_friend('aggressors_frenzy', true)
2020-05-17 12:23:55 +02:00
2024-11-07 00:51:45 +02:00
local fake_shooter = surface.create_entity({ name = 'character', position = p, force = 'enemy' })
2020-05-17 12:23:55 +02:00
surface.create_entity(
{
name = 'atomic-rocket',
2024-11-07 00:51:45 +02:00
position = p,
2020-05-17 12:23:55 +02:00
force = 'enemy',
speed = 1,
max_range = 1200,
2024-11-07 00:51:45 +02:00
target = p,
2020-05-17 12:23:55 +02:00
source = fake_shooter
}
)
2024-11-07 00:51:45 +02:00
surface.spill_item_stack({ position = p, stack = { name = 'coin', count = 512, quality = 'normal' } })
2020-07-08 22:57:43 +02:00
this.game_reset_tick = 5400
2020-05-17 12:23:55 +02:00
for _, player in pairs(game.connected_players) do
player.play_sound { path = 'utility/game_lost', volume_modifier = 0.75 }
2020-12-28 11:48:25 +02:00
show_mvps(player)
2020-05-17 12:23:55 +02:00
end
2024-11-07 00:51:45 +02:00
Public.set('notified_game_over', true)
2020-05-17 12:23:55 +02:00
end
2023-08-01 01:06:31 +02:00
local function on_entity_spawned(event)
local enemy_spawners = Public.get('enemy_spawners')
2024-03-28 23:22:36 +02:00
if not enemy_spawners or not enemy_spawners.enabled then
2023-08-01 01:06:31 +02:00
return
end
local spawner = event.spawner
if not spawner or not spawner.valid then
return
end
local unit_number = spawner.unit_number
local position = spawner.position
if not enemy_spawners.spawners[unit_number] then
enemy_spawners.spawners[unit_number] = {
entity = spawner,
count = 0
}
end
local surface = spawner.surface
enemy_spawners.spawners[unit_number].count = enemy_spawners.spawners[unit_number].count + 1
if enemy_spawners.spawners[unit_number].count >= 100 then
local entity = enemy_spawners.spawners[unit_number].entity
if entity and entity.valid then
surface.create_entity({ name = 'explosion', position = position })
2023-08-01 01:06:31 +02:00
entity.destroy()
enemy_spawners.spawners[unit_number] = nil
end
end
end
2020-05-23 21:18:18 +02:00
local function on_built_entity(event)
2024-10-09 19:45:35 +02:00
local entity = event.entity
2024-10-27 00:01:15 +02:00
if not entity or not entity.valid then
return
end
if string.sub(entity.surface.name, 0, #scenario_name) == Public.init_name then
entity.destroy()
2020-05-23 21:18:18 +02:00
return
end
2024-10-14 23:46:34 +02:00
if string.sub(entity.surface.name, 0, #scenario_name) ~= scenario_name then
2020-07-27 11:07:32 +02:00
return
end
2022-04-10 11:21:52 +02:00
local position = entity.position
local player = game.get_player(event.player_index)
if entity.name == 'radar' then
if entity.surface.count_entities_filtered({ type = 'radar', position = position, radius = 64 }) > 1 then
2024-09-25 20:46:27 +02:00
player.create_local_flying_text(
2022-04-10 11:21:52 +02:00
{
position = entity.position,
text = ({ 'entity.radar_limit' }),
2024-09-25 20:46:27 +02:00
color = { 255, 0, 0 },
2022-04-10 11:21:52 +02:00
}
)
2024-10-26 02:06:48 +02:00
player.physical_surface.spill_item_stack({ position = position, stack = { name = entity.name, count = 1, quality = 'normal' } })
2024-10-25 16:15:09 +02:00
2022-04-10 11:21:52 +02:00
entity.destroy()
return
end
end
2021-11-20 21:04:13 +02:00
local valid_drills = {
['burner-mining-drill'] = true,
['electric-mining-drill'] = true
}
if valid_drills[entity.name] then
2024-10-26 13:05:31 +02:00
Task.set_timeout_in_ticks(30, change_force_for_drills_token, { entity = entity })
2021-11-18 01:58:54 +02:00
return
end
local upgrades = Public.get('upgrades')
2020-11-15 20:23:54 +02:00
local upg = upgrades
2020-05-23 21:18:18 +02:00
local built = {
['land-mine'] = upg.landmine.built,
['flamethrower-turret'] = upg.flame_turret.built
}
local limit = {
['land-mine'] = upg.landmine.limit,
['flamethrower-turret'] = upg.flame_turret.limit
}
local validator = {
['land-mine'] = 'landmine',
['flamethrower-turret'] = 'flame_turret'
}
local name = validator[entity.name]
2020-07-18 16:36:24 +02:00
if built[entity.name] and entity.force.index == 1 then
2020-05-23 21:18:18 +02:00
if built[entity.name] < limit[entity.name] then
2020-11-15 20:23:54 +02:00
upgrades[name].built = built[entity.name] + 1
upgrades.unit_number[name][entity] = entity
upgrades.showed_text = false
2020-05-23 21:18:18 +02:00
2024-09-25 20:46:27 +02:00
player.create_local_flying_text(
2020-05-23 21:18:18 +02:00
{
position = entity.position,
2020-11-15 20:23:54 +02:00
text = upgrades[name].built .. ' / ' .. limit[entity.name] .. ' ' .. entity.name,
2024-09-25 20:46:27 +02:00
color = { r = 0.82, g = 0.11, b = 0.11 },
2020-05-23 21:18:18 +02:00
}
)
else
2020-11-15 20:23:54 +02:00
if not upgrades.showed_text then
2024-09-25 20:46:27 +02:00
player.create_local_flying_text(
2020-05-23 21:18:18 +02:00
{
position = entity.position,
text = ({ 'entity.entity_limit_reached', entity.name }),
2024-09-25 20:46:27 +02:00
color = { r = 0.82, g = 0.11, b = 0.11 },
2020-05-23 21:18:18 +02:00
}
)
2020-11-15 20:23:54 +02:00
upgrades.showed_text = true
2020-05-23 21:18:18 +02:00
end
player.insert({ name = entity.name, count = 1 })
2020-05-23 21:18:18 +02:00
entity.destroy()
end
end
end
local function on_robot_built_entity(event)
2024-10-09 19:45:35 +02:00
local entity = event.entity
2020-05-23 21:18:18 +02:00
if not entity.valid then
return
end
2024-10-14 23:46:34 +02:00
if string.sub(entity.surface.name, 0, #scenario_name) ~= scenario_name then
2020-07-27 11:07:32 +02:00
return
end
2022-04-10 11:21:52 +02:00
local position = entity.position
if entity.name == 'radar' then
if entity.surface.count_entities_filtered({ type = 'radar', position = position, radius = 64 }) > 1 then
2022-04-10 11:21:52 +02:00
entity.surface.create_entity(
{
2024-09-25 20:46:27 +02:00
name = 'compi-speech-bubble',
2022-04-10 11:21:52 +02:00
position = entity.position,
text = ({ 'entity.radar_limit' }),
2024-09-25 20:46:27 +02:00
source = entity,
lifetime = 30
2022-04-10 11:21:52 +02:00
}
)
2024-10-25 16:15:09 +02:00
entity.surface.spill_item_stack({ position = entity.position, stack = { name = entity.name, count = 1 } })
2022-04-10 11:21:52 +02:00
entity.destroy()
return
end
end
2021-11-20 21:04:13 +02:00
local valid_drills = {
['burner-mining-drill'] = true,
['electric-mining-drill'] = true
}
if valid_drills[entity.name] then
2024-10-26 13:05:31 +02:00
Task.set_timeout_in_ticks(30, change_force_for_drills_token, { entity = entity })
2021-11-18 01:58:54 +02:00
return
end
local upgrades = Public.get('upgrades')
2020-11-15 20:23:54 +02:00
local upg = upgrades
2020-07-24 17:33:28 +02:00
local surface = entity.surface
2020-05-23 21:18:18 +02:00
local built = {
['land-mine'] = upg.landmine.built,
['flamethrower-turret'] = upg.flame_turret.built
}
local limit = {
['land-mine'] = upg.landmine.limit,
['flamethrower-turret'] = upg.flame_turret.limit
}
local validator = {
['land-mine'] = 'landmine',
['flamethrower-turret'] = 'flame_turret'
}
local name = validator[entity.name]
2020-07-18 16:36:24 +02:00
if built[entity.name] and entity.force.index == 1 then
2020-05-23 21:18:18 +02:00
if built[entity.name] < limit[entity.name] then
2020-11-15 20:23:54 +02:00
upgrades[name].built = built[entity.name] + 1
upgrades.unit_number[name][entity] = entity
upgrades.showed_text = false
2020-05-23 21:18:18 +02:00
surface.create_entity(
{
2024-09-25 20:46:27 +02:00
name = 'compi-speech-bubble',
2020-05-23 21:18:18 +02:00
position = entity.position,
2020-11-15 20:23:54 +02:00
text = upgrades[name].built .. ' / ' .. limit[entity.name] .. ' ' .. entity.name,
2024-09-25 20:46:27 +02:00
source = entity,
lifetime = 30
2020-05-23 21:18:18 +02:00
}
)
else
2020-11-15 20:23:54 +02:00
if not upgrades.showed_text then
2020-05-23 21:18:18 +02:00
surface.create_entity(
{
2024-09-25 20:46:27 +02:00
name = 'compi-speech-bubble',
2020-05-23 21:18:18 +02:00
position = entity.position,
text = ({ 'entity.entity_limit_reached', entity.name }),
2024-09-25 20:46:27 +02:00
source = entity,
lifetime = 30
2020-05-23 21:18:18 +02:00
}
)
2020-11-15 20:23:54 +02:00
upgrades.showed_text = true
2020-05-23 21:18:18 +02:00
end
local inventory = event.robot.get_inventory(defines.inventory.robot_cargo)
inventory.insert({ name = entity.name, count = 1 })
2020-05-23 21:18:18 +02:00
entity.destroy()
end
end
2020-07-24 17:33:28 +02:00
end
local on_player_or_robot_built_tile = function (event)
2020-07-24 17:33:28 +02:00
local surface = game.surfaces[event.surface_index]
2024-10-14 23:46:34 +02:00
if string.sub(surface.name, 0, #scenario_name) ~= scenario_name then
2020-07-24 17:33:28 +02:00
return
end
local tiles = event.tiles
if not tiles then
return
end
2024-05-27 20:30:03 +02:00
for _, v in pairs(tiles) do
2020-07-24 17:33:28 +02:00
local old_tile = v.old_tile
if old_tile.name == 'black-refined-concrete' then
surface.set_tiles({ { name = 'black-refined-concrete', position = v.position } }, true)
2020-07-24 17:33:28 +02:00
end
if old_tile.name == 'blue-refined-concrete' then
surface.set_tiles({ { name = 'blue-refined-concrete', position = v.position } }, true)
2020-07-24 17:33:28 +02:00
end
if old_tile.name == 'cyan-refined-concrete' then
surface.set_tiles({ { name = 'cyan-refined-concrete', position = v.position } }, true)
2020-07-24 17:33:28 +02:00
end
if old_tile.name == 'hazard-concrete-right' then
surface.set_tiles({ { name = 'hazard-concrete-right', position = v.position } }, true)
2020-07-24 17:33:28 +02:00
end
2020-08-12 18:05:57 +02:00
if old_tile.name == 'lab-dark-2' then
surface.set_tiles({ { name = 'lab-dark-2', position = v.position } }, true)
2020-08-10 23:15:29 +02:00
end
2020-07-24 17:33:28 +02:00
end
2020-05-23 21:18:18 +02:00
end
2021-10-29 00:06:35 +02:00
Public.get_random_weighted = get_random_weighted
Event.add_event_filter(defines.events.on_entity_damaged, { filter = 'final-damage-amount', comparison = '>', value = 0 })
2020-05-17 12:23:55 +02:00
Event.add(defines.events.on_entity_damaged, on_entity_damaged)
2023-08-01 01:06:31 +02:00
Event.add(defines.events.on_entity_spawned, on_entity_spawned)
2020-05-17 12:23:55 +02:00
Event.add(defines.events.on_player_repaired_entity, on_player_repaired_entity)
Event.add(defines.events.on_player_mined_entity, on_player_mined_entity)
2020-06-03 20:09:00 +02:00
Event.add(defines.events.on_robot_mined_entity, on_robot_mined_entity)
2020-05-17 12:23:55 +02:00
Event.add(defines.events.on_entity_died, on_entity_died)
2020-05-23 21:18:18 +02:00
Event.add(defines.events.on_built_entity, on_built_entity)
Event.add(defines.events.on_robot_built_entity, on_robot_built_entity)
2020-07-24 17:33:28 +02:00
Event.add(defines.events.on_player_built_tile, on_player_or_robot_built_tile)
Event.add(defines.events.on_robot_built_tile, on_player_or_robot_built_tile)
2020-05-17 12:23:55 +02:00
return Public