1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2024-12-28 23:06:38 +02:00
ComfyFactorio/maps/mountain_fortress_v3/functions.lua
2024-10-26 17:37:07 +02:00

2027 lines
65 KiB
Lua

local Event = require 'utils.event'
local Public = require 'maps.mountain_fortress_v3.table'
local Server = require 'utils.server'
local Task = require 'utils.task_token'
local Color = require 'utils.color_presets'
local ICW = require 'maps.mountain_fortress_v3.icw.main'
local Global = require 'utils.global'
local Alert = require 'utils.alert'
local WD = require 'modules.wave_defense.table'
local RPG = require 'modules.rpg.main'
local Collapse = require 'modules.collapse'
local Difficulty = require 'modules.difficulty_vote_by_amount'
local ICW_Func = require 'maps.mountain_fortress_v3.icw.functions'
local math2d = require 'math2d'
local Misc = require 'utils.commands.misc'
local Core = require 'utils.core'
local Beams = require 'modules.render_beam'
local BottomFrame = require 'utils.gui.bottom_frame'
local Modifiers = require 'utils.player_modifiers'
local Session = require 'utils.datastore.session_data'
local scenario_name = Public.scenario_name
local zone_settings = Public.zone_settings
local remove_boost_movement_speed_on_respawn
local de = defines.events
local this = {
power_sources = { index = 1 },
refill_turrets = { index = 1 },
magic_crafters = { index = 1 },
magic_fluid_crafters = { index = 1 },
art_table = { index = 1 },
editor_mode = {},
techs = {},
limit_types = {},
starting_items = {
['pistol'] = {
count = 1
},
['firearm-magazine'] = {
count = 16
},
['rail'] = {
count = 16
},
['wood'] = {
count = 16
},
['explosives'] = {
count = 32
}
}
}
local exit_editor_mode_token =
Task.register(
function (event)
local player_index = event.player_index
this.editor_mode[player_index] = nil
end
)
local random_respawn_messages = {
'The doctors stitched you up as best they could.',
'Ow! Your right leg hurts.',
'Ow! Your left leg hurts.',
'You can feel your whole body aching.',
"You still have some bullet wounds that aren't patched up.",
'You feel dizzy but adrenalin is granting you speed.',
'Adrenalin is kicking in, but your body is damaged.'
}
local health_values = {
'0.35',
'0.40',
'0.45',
'0.50',
'0.55',
'0.60',
'0.65',
'0.70',
'0.75',
'0.80',
'0.85',
'0.90',
'0.95',
'1'
}
Global.register(
this,
function (t)
this = t
end
)
local random = math.random
local floor = math.floor
local round = math.round
local sqrt = math.sqrt
local remove = table.remove
local magic_crafters_per_tick = 3
local magic_fluid_crafters_per_tick = 8
local tile_damage = 50
local artillery_target_entities = {
'character',
'tank',
'car',
'radar',
'lab',
'furnace',
'locomotive',
'cargo-wagon',
'fluid-wagon',
'artillery-wagon',
'artillery-turret',
'laser-turret',
'gun-turret',
'flamethrower-turret',
'silo',
'spidertron'
}
local function debug_str(msg)
local debug = Public.get('debug')
if not debug then
return
end
print('Mtn: ' .. msg)
end
local function show_text(msg, pos, surface, player)
surface.create_entity({
name = 'compi-speech-bubble',
position = pos,
text = msg,
source = player.character,
lifetime = 30
})
end
local function fast_remove(tbl, index)
local count = #tbl
if index > count then
return
elseif index < count then
tbl[index] = tbl[count]
end
tbl[count] = nil
end
local pause_waves_custom_callback_token =
Task.register(
function (event)
local wave_number = WD.get_wave()
if wave_number >= 200 then
Collapse.start_now(event.start, not event.start)
local status_str = event.start and 'is active once again!' or 'has stopped!'
Alert.alert_all_players(30, 'Collapse ' .. status_str, nil, 'achievement/tech-maniac', 0.6)
end
end
)
local function do_refill_turrets()
local refill_turrets = this.refill_turrets
local index = refill_turrets.index
if index > #refill_turrets then
refill_turrets.index = 1
return
end
local turret_data = refill_turrets[index]
local turret = turret_data.turret
if not turret.valid then
fast_remove(refill_turrets, index)
return
end
refill_turrets.index = index + 1
local data = turret_data.data
if data.liquid then
turret.set_fluid(1, data)
elseif data then
turret.insert(data)
end
end
local function do_magic_crafters()
local magic_crafters = this.magic_crafters
local limit = #magic_crafters
if limit == 0 then
return
end
local index = magic_crafters.index
for _ = 1, magic_crafters_per_tick do
if index > limit then
index = 1
end
local data = magic_crafters[index]
local entity = data.entity
if not entity.valid then
fast_remove(magic_crafters, index)
limit = limit - 1
if limit == 0 then
return
end
else
index = index + 1
local tick = game.tick
local last_tick = data.last_tick
local rate = data.rate
local count = (tick - last_tick) * rate
local fcount = floor(count)
if fcount > 1 then
fcount = 1
end
if fcount > 0 then
if entity.get_output_inventory().can_insert({ name = data.item, count = fcount }) then
entity.get_output_inventory().insert { name = data.item, count = fcount }
entity.products_finished = entity.products_finished + fcount
data.last_tick = round(tick - (count - fcount) / rate)
end
end
end
end
magic_crafters.index = index
end
local function do_magic_fluid_crafters()
local magic_fluid_crafters = this.magic_fluid_crafters
local limit = #magic_fluid_crafters
if limit == 0 then
return
end
local index = magic_fluid_crafters.index
for _ = 1, magic_fluid_crafters_per_tick do
if index > limit then
index = 1
end
local data = magic_fluid_crafters[index]
local entity = data.entity
if not entity.valid then
fast_remove(magic_fluid_crafters, index)
limit = limit - 1
if limit == 0 then
return
end
else
index = index + 1
local tick = game.tick
local last_tick = data.last_tick
local rate = data.rate
local count = (tick - last_tick) * rate
local fcount = floor(count)
if fcount > 0 then
local fluidbox_index = data.fluidbox_index
local fb_data = entity.get_fluid(fluidbox_index) or { name = data.item, amount = 0 }
fb_data.amount = fb_data.amount + fcount
entity.set_fluid(fluidbox_index, fb_data)
entity.products_finished = entity.products_finished + fcount
data.last_tick = tick - (count - fcount) / rate
end
end
end
magic_fluid_crafters.index = index
end
local artillery_target_callback =
Task.register(
function (data)
local position = data.position
local entity = data.entity
local index = data.index
local art_table = this.art_table
local outpost = art_table[index]
if not outpost then
return
end
if not entity.valid then
outpost.last_fire_tick = 0
return
end
local tx, ty = position.x, position.y
local fired_at_target = false
local pos = entity.position
local x, y = pos.x, pos.y
local dx, dy = tx - x, ty - y
local d = dx * dx + dy * dy
if d >= 1024 and d <= 441398 then -- 704 in depth~
if entity.name == 'character' then
entity.surface.create_entity {
name = 'artillery-projectile',
position = position,
target = entity,
force = 'enemy',
speed = 1.5
}
fired_at_target = true
elseif entity.name ~= 'character' then
entity.surface.create_entity {
name = 'rocket',
position = position,
target = entity,
force = 'enemy',
speed = 1.5
}
fired_at_target = true
end
end
if not fired_at_target then
outpost.last_fire_tick = 0
end
end
)
local function do_beams_away()
local wave_number = WD.get_wave()
local orbital_strikes = Public.get('orbital_strikes')
if not orbital_strikes or not orbital_strikes.enabled then
return
end
if wave_number > 500 then
local difficulty_index = Difficulty.get('index')
local wave_nth = 9999
if difficulty_index == 1 then
wave_nth = 500
elseif difficulty_index == 2 then
wave_nth = 250
elseif difficulty_index == 3 then
wave_nth = 100
end
if wave_number % wave_nth == 0 then
local active_surface_index = Public.get('active_surface_index')
local surface = game.get_surface(active_surface_index)
if not orbital_strikes[wave_number] then
orbital_strikes[wave_number] = true
Beams.new_beam_delayed(surface, random(500, 3000))
end
end
end
end
local function do_clear_enemy_spawners()
local tick = game.tick
if tick % 1000 ~= 0 then
return
end
local enemy_spawners = Public.get('enemy_spawners')
if not enemy_spawners or not enemy_spawners.enabled then
return
end
for unit_number, spawner in pairs(enemy_spawners.spawners) do
if not spawner.entity or not spawner.entity.valid then
enemy_spawners.spawners[unit_number] = nil
end
end
end
local function do_clear_rocks_slowly()
local rocks_to_remove = Public.get('rocks_to_remove')
if not rocks_to_remove or not next(rocks_to_remove) then
return
end
for _ = 1, 300 do
local entity = table.remove(rocks_to_remove, #rocks_to_remove)
if entity and entity.valid then
entity.destroy()
end
end
end
local function do_replace_tiles_slowly()
local active_surface_index = Public.get('active_surface_index')
if not active_surface_index then return end
local surface = game.get_surface(active_surface_index)
if not (surface and surface.valid) then
return
end
local tiles_to_replace = Public.get('tiles_to_replace')
if not tiles_to_replace or not next(tiles_to_replace) then
return
end
for _ = 1, 1000 do
local tile = table.remove(tiles_to_replace, #tiles_to_replace)
if tile and tile.valid then
surface.set_tiles({ { name = 'water-shallow', position = tile.position } }, true)
end
end
end
local function do_season_fix()
local active_surface_index = Public.get('active_surface_index')
local surface = game.surfaces[active_surface_index]
if not (surface and surface.valid) then
return
end
local current_season = Public.get('current_season')
if current_season and current_season.valid then
current_season.destroy()
end
Public.set(
'current_season',
rendering.draw_text {
text = 'Season: ' .. Public.get_stateful('season'),
surface = surface,
target = { -0, 12 },
color = { r = 0.98, g = 0.77, b = 0.22 },
scale = 3,
font = 'heading-1',
alignment = 'center',
scale_with_zoom = false
}
)
end
local do_season_fix_token = Task.register(do_season_fix)
local function do_artillery_turrets_targets()
local art_table = this.art_table
local index = art_table.index
if index > #art_table then
art_table.index = 1
return
end
art_table.index = index + 1
local outpost = art_table[index]
local now = game.tick
if now - outpost.last_fire_tick < 480 then
return
end
local turrets = outpost.artillery_turrets
for i = #turrets, 1, -1 do
local turret = turrets[i]
if not turret.valid then
fast_remove(turrets, i)
end
end
local count = #turrets
if count == 0 then
fast_remove(art_table, index)
return
end
local turret = turrets[1]
local area = outpost.artillery_area
local surface = turret.surface
local entities = surface.find_entities_filtered { area = area, name = artillery_target_entities, force = 'player' }
if #entities == 0 then
return
end
local position = turret.position
outpost.last_fire_tick = now
for i = 1, count do
local entity = entities[random(#entities)]
if entity and entity.valid then
local data = { position = position, entity = entity, index = index }
Task.set_timeout_in_ticks(i * 60, artillery_target_callback, data)
end
end
end
local function add_magic_crafter_output(entity, output, distance)
local magic_fluid_crafters = this.magic_fluid_crafters
local magic_crafters = this.magic_crafters
local rate = output.min_rate + output.distance_factor * distance
local fluidbox_index = output.fluidbox_index
local data = {
entity = entity,
last_tick = game.tick,
base_rate = round(rate, 8),
rate = round(rate, 8),
item = output.item,
fluidbox_index = fluidbox_index
}
if fluidbox_index then
magic_fluid_crafters[#magic_fluid_crafters + 1] = data
else
magic_crafters[#magic_crafters + 1] = data
end
end
local function tick()
do_refill_turrets()
do_magic_crafters()
do_magic_fluid_crafters()
do_artillery_turrets_targets()
do_beams_away()
do_clear_enemy_spawners()
do_clear_rocks_slowly()
do_replace_tiles_slowly()
end
Public.deactivate_callback =
Task.register(
function (entity)
if entity and entity.valid then
entity.active = false
entity.operable = false
entity.destructible = false
end
end
)
Public.neutral_force =
Task.register(
function (entity)
if entity and entity.valid then
entity.force = 'neutral'
end
end
)
Public.enemy_force =
Task.register(
function (entity)
if entity and entity.valid then
entity.force = 'enemy'
end
end
)
Public.active_not_destructible_callback =
Task.register(
function (entity)
if entity and entity.valid then
entity.active = true
entity.operable = false
entity.destructible = false
end
end
)
Public.disable_minable_callback =
Task.register(
function (entity)
if entity and entity.valid then
entity.minable = false
end
end
)
Public.disable_minable_and_ICW_callback =
Task.register(
function (entity)
if entity and entity.valid then
local wagons_in_the_wild = Public.get('wagons_in_the_wild')
entity.minable = false
entity.destructible = false
ICW.register_wagon(entity)
wagons_in_the_wild[entity.unit_number] = entity
end
end
)
Public.disable_destructible_callback =
Task.register(
function (entity)
if entity and entity.valid then
entity.destructible = false
entity.minable = false
end
end
)
Public.disable_active_callback =
Task.register(
function (entity)
if entity and entity.valid then
entity.active = false
end
end
)
local disable_active_callback = Public.disable_active_callback
Public.refill_turret_callback =
Task.register(
function (turret, data)
local refill_turrets = this.refill_turrets
local callback_data = data.callback_data
turret.direction = 3
refill_turrets[#refill_turrets + 1] = { turret = turret, data = callback_data }
end
)
Public.refill_artillery_turret_callback =
Task.register(
function (turret, data)
local refill_turrets = this.refill_turrets
local art_table = this.art_table
local index = art_table.index
turret.active = false
turret.direction = 3
refill_turrets[#refill_turrets + 1] = { turret = turret, data = data.callback_data }
local artillery_data = art_table[index]
if not artillery_data then
artillery_data = {}
end
local artillery_turrets = artillery_data.artillery_turrets
if not artillery_turrets then
artillery_turrets = {}
artillery_data.artillery_turrets = artillery_turrets
local pos = turret.position
local x, y = pos.x, pos.y
local adjusted_zones = Public.get('adjusted_zones')
if adjusted_zones.reversed then
artillery_data.artillery_area = { { x - 112, y - 212 }, { x + 112, y } }
else
artillery_data.artillery_area = { { x - 112, y }, { x + 112, y + 212 } }
end
artillery_data.last_fire_tick = 0
art_table[#art_table + 1] = artillery_data
end
artillery_turrets[#artillery_turrets + 1] = turret
end
)
Public.refill_liquid_turret_callback =
Task.register(
function (turret, data)
local refill_turrets = this.refill_turrets
local callback_data = data.callback_data
callback_data.liquid = true
refill_turrets[#refill_turrets + 1] = { turret = turret, data = callback_data }
end
)
Public.power_source_callback =
Task.register(
function (turret)
local power_sources = this.power_sources
power_sources[#power_sources + 1] = turret
end
)
Public.magic_item_crafting_callback =
Task.register(
function (entity, data)
local callback_data = data.callback_data
if not (entity and entity.valid) then
return
end
entity.minable = false
entity.destructible = false
entity.operable = false
local force = game.forces.player
local tech = callback_data.tech
if not callback_data.testing then
if tech then
if not force.technologies[tech].researched then
entity.destroy()
return
end
end
end
local recipe = callback_data.recipe
if recipe then
entity.set_recipe(recipe)
else
local furance_item = callback_data.furance_item
if furance_item then
local inv = entity.get_inventory(defines.inventory.furnace_result)
inv.insert(furance_item)
end
end
local p = entity.position
local x, y = p.x, p.y
local distance = sqrt(x * x + y * y)
local output = callback_data.output
if #output == 0 then
add_magic_crafter_output(entity, output, distance)
else
for i = 1, #output do
local o = output[i]
add_magic_crafter_output(entity, o, distance)
end
end
if not callback_data.keep_active then
Task.set_timeout_in_ticks(2, disable_active_callback, entity) -- causes problems with refineries.
end
end
)
Public.magic_item_crafting_callback_weighted =
Task.register(
function (entity, data)
local callback_data = data.callback_data
if not (entity and entity.valid) then
return
end
local weights = callback_data.weights
local loot = callback_data.loot
local destructible = callback_data.destructible
if not destructible then
entity.destructible = false
end
entity.minable = false
entity.operable = false
local p = entity.position
local i = random() * weights.total
local index = table.binary_search(weights, i)
if (index < 0) then
index = bit32.bnot(index)
end
local stack = loot[index].stack
if not stack then
return
end
local force = game.forces.player
local tech = stack.tech
if not callback_data.testing then
if tech then
if force.technologies[tech] then
if not force.technologies[tech].researched then
entity.destroy()
return
end
end
end
end
local recipe = stack.recipe
if recipe then
entity.set_recipe(recipe)
else
local furance_item = stack.furance_item
if furance_item then
local inv = entity.get_inventory(defines.inventory.furnace_result)
inv.insert(furance_item)
end
end
local x, y = p.x, p.y
local distance = sqrt(x * x + y * y)
local output = stack.output
if #output == 0 then
add_magic_crafter_output(entity, output, distance)
else
for o_i = 1, #output do
local o = output[o_i]
add_magic_crafter_output(entity, o, distance)
end
end
if not callback_data.keep_active then
Task.set_timeout_in_ticks(2, disable_active_callback, entity) -- causes problems with refineries.
end
end
)
function Public.prepare_weighted_loot(loot)
local total = 0
local weights = {}
for i = 1, #loot do
local v = loot[i]
total = total + v.weight
weights[#weights + 1] = total
end
weights.total = total
return weights
end
function Public.do_random_loot(entity, weights, loot)
if not entity.valid then
return
end
entity.operable = false
--entity.destructible = false
local i = random() * weights.total
local index = table.binary_search(weights, i)
if (index < 0) then
index = bit32.bnot(index)
end
local stack = loot[index].stack
if not stack then
return
end
local df = stack.distance_factor
local count
if df then
local p = entity.position
local x, y = p.x, p.y
local d = sqrt(x * x + y * y)
count = stack.count + d * df
else
count = stack.count
end
entity.insert { name = stack.name, count = count }
end
local function calc_players()
local players = game.connected_players
local check_afk_players = Public.get('check_afk_players')
if not check_afk_players then
return #players
end
local total = 0
Core.iter_connected_players(
function (player)
if player.afk_time < 36000 then
total = total + 1
end
end
)
if total <= 0 then
total = #players
end
return total
end
remove_boost_movement_speed_on_respawn =
Task.register(
function (data)
local player = data.player
if not player or not player.valid then
return
end
Modifiers.update_single_modifier(player, 'character_running_speed_modifier', 'v3_move_boost')
Modifiers.update_player_modifiers(player)
player.print('Movement speed bonus removed!', { color = Color.info })
local rpg_t = RPG.get_value_from_player(player.index)
rpg_t.has_boost_on_respawn = nil
end
)
local boost_movement_speed_on_respawn =
Task.register(
function (data)
local player = data.player
if not player or not player.valid then
return
end
if not player.character or not player.character.valid then
return
end
local rpg_t = RPG.get_value_from_player(player.index)
if rpg_t.has_boost_on_respawn then
return
end
rpg_t.has_boost_on_respawn = true
Modifiers.update_single_modifier(player, 'character_running_speed_modifier', 'v3_move_boost', 1)
Modifiers.update_player_modifiers(player)
Task.set_timeout_in_ticks(800, remove_boost_movement_speed_on_respawn, { player = player })
player.print('Movement speed bonus applied! Be quick and fetch your corpse!', { color = Color.info })
end
)
local function on_wave_created(event)
if not event or not event.wave_number then
return
end
local wave_number = event.wave_number
if wave_number % 50 == 0 then
if wave_number >= 1500 then
WD.set_pause_wave_in_ticks(random(36000, 54000))
else
WD.set_pause_wave_in_ticks(random(18000, 54000))
end
end
end
local function on_primary_target_missing()
local locomotive = Public.get('locomotive')
if not locomotive or not locomotive.valid then
return
end
WD.set('target', locomotive)
local target_settings = WD.get_es('target_settings')
target_settings.main_target = locomotive
WD.set_main_target(locomotive)
end
local function on_player_cursor_stack_changed(event)
local player = game.get_player(event.player_index)
if not player or not player.valid then
return
end
if player.admin then
return
end
local item = player.cursor_stack
if not item then
return
end
if not item.valid_for_read then
return
end
local name = item.name
local pm = player.permission_group.name
local blacklisted_spawn_items = {
['cut-paste-tool'] = true,
['spidertron-remote'] = true,
['artillery-targeting-remote'] = true,
}
if pm == 'Default' or pm == 'limited' or pm == 'jail' or pm == 'not_trusted' or pm == 'near_locomotive' or pm == 'main_surface' then
if blacklisted_spawn_items[name] then
player.print('You are not allowed to use this item.', { color = Color.warning })
player.cursor_stack.clear()
return
end
return
end
end
function Public.find_rocks_and_slowly_remove()
local active_surface_index = Public.get('active_surface_index')
local surface = game.get_surface(active_surface_index)
if not (surface and surface.valid) then
return
end
local ents = surface.find_entities_filtered({ type = 'simple-entity' })
if ents and #ents > 0 then
Public.set('rocks_to_remove', ents)
end
end
function Public.find_void_tiles_and_replace()
local active_surface_index = Public.get('active_surface_index')
local surface = game.get_surface(active_surface_index)
if not (surface and surface.valid) then
return
end
local cp = Collapse.get_position()
local rp = Collapse.get_reverse_position()
local area = {
left_top = { x = (-zone_settings.zone_width / 2) + 10, y = -rp.y - 1000 },
right_bottom = { x = (zone_settings.zone_width / 2) - 10, y = cp.y }
}
local adjusted_zones = Public.get('adjusted_zones')
if adjusted_zones.reversed then
area = {
left_top = { x = ((zone_settings.zone_width / 2) + 10) * -1, y = cp.y },
right_bottom = { x = math.abs((-zone_settings.zone_width / 2) - 10), y = rp.y },
}
end
local tiles = surface.find_tiles_filtered({ area = area, name = { 'out-of-map', 'water', 'deepwater', 'water-green', 'deepwater-green' } })
if tiles and #tiles > 0 then
Public.set('tiles_to_replace', tiles)
end
end
function Public.set_difficulty()
local final_battle = Public.get('final_battle')
if final_battle then
return
end
local pre_final_battle = Public.get('pre_final_battle')
if pre_final_battle then
return
end
local game_lost = Public.get('game_lost')
if game_lost then
return
end
local Diff = Difficulty.get()
if not Diff then
return
end
local wave_defense_table = WD.get_table()
local check_if_threat_below_zero = Public.get('check_if_threat_below_zero')
local collapse_amount = Public.get('collapse_amount')
local collapse_speed = Public.get('collapse_speed')
local difficulty = Public.get('difficulty')
local mining_bonus_till_wave = Public.get('mining_bonus_till_wave')
local mining_bonus = Public.get('mining_bonus')
local disable_mining_boost = Public.get('disable_mining_boost')
local wave_number = WD.get_wave()
local player_count = calc_players()
if not Diff.value then
Diff.value = 0.1
end
if not wave_defense_table.enforce_max_active_biters then
if Diff.index == 1 then
wave_defense_table.max_active_biters = 768 + player_count * (90 * Diff.value)
elseif Diff.index == 2 then
wave_defense_table.max_active_biters = 845 + player_count * (90 * Diff.value)
elseif Diff.index == 3 then
wave_defense_table.max_active_biters = 1000 + player_count * (90 * Diff.value)
end
if wave_defense_table.max_active_biters >= 4000 then
wave_defense_table.max_active_biters = 4000
end
end
-- threat gain / wave
if Diff.index == 1 then
wave_defense_table.threat_gain_multiplier = 1.2 + player_count * Diff.value * 0.1
elseif Diff.index == 2 then
wave_defense_table.threat_gain_multiplier = 2 + player_count * Diff.value * 0.1
elseif Diff.index == 3 then
wave_defense_table.threat_gain_multiplier = 4 + player_count * Diff.value * 0.1
end
-- local amount = player_count * 0.40 + 2 -- too high?
local amount = player_count * difficulty.multiply + 2
amount = floor(amount)
if amount < difficulty.lowest then
amount = difficulty.lowest
elseif amount > difficulty.highest then
amount = difficulty.highest -- lowered from 20 to 10
end
local wave = WD.get('wave_number')
local threat_check = nil
if check_if_threat_below_zero then
threat_check = wave_defense_table.threat <= 0
end
if Diff.index == 1 then
if wave < 100 then
wave_defense_table.wave_interval = 4500
else
wave_defense_table.wave_interval = 3600 - player_count * 60
end
if wave_defense_table.wave_interval < 2000 or threat_check then
wave_defense_table.wave_interval = 2000
end
elseif Diff.index == 2 then
if wave < 100 then
wave_defense_table.wave_interval = 3000
else
wave_defense_table.wave_interval = 2600 - player_count * 60
end
if wave_defense_table.wave_interval < 1800 or threat_check then
wave_defense_table.wave_interval = 1800
end
elseif Diff.index == 3 then
if wave < 100 then
wave_defense_table.wave_interval = 3000
else
wave_defense_table.wave_interval = 1600 - player_count * 60
end
wave_defense_table.wave_interval = 1600 - player_count * 60
if wave_defense_table.wave_interval < 1600 or threat_check then
wave_defense_table.wave_interval = 1600
end
end
if collapse_amount then
Collapse.set_amount(collapse_amount)
else
Collapse.set_amount(amount)
end
if collapse_speed then
Collapse.set_speed(collapse_speed)
else
if player_count >= 1 and player_count <= 8 then
Collapse.set_speed(8)
elseif player_count > 8 and player_count <= 20 then
Collapse.set_speed(7)
elseif player_count > 20 and player_count <= 35 then
Collapse.set_speed(6)
elseif player_count > 35 then
Collapse.set_speed(5)
end
end
if player_count >= 1 and not disable_mining_boost then
local force = game.forces.player
if wave_number < mining_bonus_till_wave then
-- the mining speed of the players will increase drastically since RPG is also loaded.
-- additional mining speed comes from steel axe research: 100%, and difficulty settings: too young to die 50%, hurt me plenty 25%
force.manual_mining_speed_modifier = force.manual_mining_speed_modifier - mining_bonus
if player_count <= 5 then
mining_bonus = 3 -- set a static 300% bonus if there are <= 5 players.
elseif player_count >= 6 and player_count <= 10 then
mining_bonus = 1 -- set a static 100% bonus if there are <= 10 players.
elseif player_count >= 11 then
mining_bonus = 0 -- back to 0% with more than 11 players
end
if mining_bonus < 0 then
mining_bonus = 0
end
force.manual_mining_speed_modifier = force.manual_mining_speed_modifier + mining_bonus
Public.set('mining_bonus', mining_bonus) -- Setting mining_bonus globally so it remembers how much to reduce
else
force.manual_mining_speed_modifier = force.manual_mining_speed_modifier - mining_bonus
Public.set('disable_mining_boost', true)
end
if force.manual_mining_speed_modifier < 0 then
force.manual_mining_speed_modifier = 0
end
end
end
function Public.render_direction(surface, reversed)
local counter = Public.get('soft_reset_counter')
local winter_mode = Public.get('winter_mode')
local text = 'Welcome to Mountain Fortress v3!'
if winter_mode then
text = 'Welcome to Wintery Mountain Fortress v3!'
end
Public.set(
'current_season',
rendering.draw_text {
text = 'Season: ' .. Public.get_stateful('season'),
surface = surface,
target = { -0, 12 },
color = { r = 0.98, g = 0.77, b = 0.22 },
scale = 3,
font = 'heading-1',
alignment = 'center',
scale_with_zoom = false
}
)
Task.set_timeout_in_ticks(25, do_season_fix_token, {})
Task.set_timeout_in_ticks(50, do_season_fix_token, {})
if counter then
rendering.draw_text {
text = text .. '\nRun: ' .. counter,
surface = surface,
target = { -0, 10 },
color = { r = 0.98, g = 0.66, b = 0.22 },
scale = 3,
font = 'heading-1',
alignment = 'center',
scale_with_zoom = false
}
else
rendering.draw_text {
text = text,
surface = surface,
target = { -0, 10 },
color = { r = 0.98, g = 0.66, b = 0.22 },
scale = 3,
font = 'heading-1',
alignment = 'center',
scale_with_zoom = false
}
end
local x_min = -zone_settings.zone_width / 2
local x_max = zone_settings.zone_width / 2
if reversed then
local inc = 0
for _ = 1, 5 do
rendering.draw_text {
text = '',
surface = surface,
target = { -0, -20 - inc },
color = { r = 0.98, g = 0.66, b = 0.22 },
scale = 3,
font = 'heading-1',
alignment = 'center',
scale_with_zoom = false
}
inc = inc + 10
end
rendering.draw_text {
text = 'Biters will attack this area.',
surface = surface,
target = { -0, -70 },
color = { r = 0.98, g = 0.66, b = 0.22 },
scale = 3,
font = 'heading-1',
alignment = 'center',
scale_with_zoom = false
}
surface.create_entity({ name = 'electric-beam', position = { x_min, -74 }, source = { x_min, -74 }, target = { x_max, -74 } })
surface.create_entity({ name = 'electric-beam', position = { x_min, -74 }, source = { x_min, -74 }, target = { x_max, -74 } })
else
local inc = 0
for _ = 1, 5 do
rendering.draw_text {
text = '',
surface = surface,
target = { -0, 20 + inc },
color = { r = 0.98, g = 0.66, b = 0.22 },
scale = 3,
font = 'heading-1',
alignment = 'center',
scale_with_zoom = false
}
inc = inc + 10
end
rendering.draw_text {
text = 'Biters will attack this area.',
surface = surface,
target = { -0, 70 },
color = { r = 0.98, g = 0.66, b = 0.22 },
scale = 3,
font = 'heading-1',
alignment = 'center',
scale_with_zoom = false
}
surface.create_entity({ name = 'electric-beam', position = { x_min, 74 }, source = { x_min, 74 }, target = { x_max, 74 } })
surface.create_entity({ name = 'electric-beam', position = { x_min, 74 }, source = { x_min, 74 }, target = { x_max, 74 } })
end
end
function Public.boost_difficulty()
local difficulty_set = Public.get('difficulty_set')
if difficulty_set then
return
end
local force = game.forces.player
force.manual_mining_speed_modifier = force.manual_mining_speed_modifier + 0.5
force.character_running_speed_modifier = 0.15
force.manual_crafting_speed_modifier = 0.15
Public.set('coin_amount', 1)
Public.set('upgrades').flame_turret.limit = 12
Public.set('upgrades').landmine.limit = 50
Public.set('locomotive_health', 10000)
Public.set('locomotive_max_health', 10000)
Public.set('bonus_xp_on_join', 500)
WD.set('next_wave', game.tick + 3600 * 15)
Public.set('spidertron_unlocked_at_zone', 10)
WD.set_normal_unit_current_health(1.2)
WD.set_unit_health_increment_per_wave(0.30)
WD.set_boss_unit_current_health(2)
WD.set_boss_health_increment_per_wave(1.5)
WD.set('death_mode', false)
Public.set('difficulty_set', true)
end
function Public.set_spawn_position()
local collapse_pos = Collapse.get_position()
local locomotive = Public.get('locomotive')
local final_battle = Public.get('final_battle')
if final_battle then
return
end
if not locomotive or not locomotive.valid then
return
end
--TODO check if final battle
local l = locomotive.position
local retries = 0
local function check_tile(surface, tile, tbl, inc)
if not (surface and surface.valid) then
return false
end
if not tile then
return false
end
local get_tile = surface.get_tile(tile)
if get_tile.valid and get_tile.name == 'out-of-map' then
remove(tbl, inc - inc + 1)
return true
else
return false
end
end
::retry::
local y_value_position = Public.get('y_value_position')
local locomotive_positions = Public.get('locomotive_pos')
local total_pos = #locomotive_positions.tbl
local active_surface_index = Public.get('active_surface_index')
local surface = game.surfaces[active_surface_index]
if not (surface and surface.valid) then
return
end
local spawn_near_collapse = Public.get('spawn_near_collapse')
if spawn_near_collapse.active then
local collapse_position = surface.find_non_colliding_position('rocket-silo', collapse_pos, 64, 2)
if not collapse_position then
collapse_position = surface.find_non_colliding_position('solar-panel', collapse_pos, 32, 2)
end
if not collapse_position then
collapse_position = surface.find_non_colliding_position('steel-chest', collapse_pos, 32, 2)
end
local sizeof = locomotive_positions.tbl[total_pos - total_pos + 1]
if not sizeof then
goto continue
end
if check_tile(surface, sizeof, locomotive_positions.tbl, total_pos) then
retries = retries + 1
if retries == 2 then
goto continue
end
goto retry
end
local locomotive_position = surface.find_non_colliding_position('steel-chest', sizeof, 128, 1)
local distance_from = floor(math2d.position.distance(locomotive_position, locomotive.position))
local l_y = l.y
local t_y = locomotive_position.y
local c_y = collapse_pos.y
local adjusted_zones = Public.get('adjusted_zones')
local compare_pos
local compare_next
if adjusted_zones.reversed then
compare_pos = l_y - t_y >= spawn_near_collapse.compare
compare_next = c_y - t_y >= spawn_near_collapse.compare_next
else
compare_pos = l_y - t_y <= spawn_near_collapse.compare
compare_next = c_y - t_y <= spawn_near_collapse.compare_next
end
if total_pos > spawn_near_collapse.total_pos then
if compare_pos then
if locomotive_position then
if check_tile(surface, sizeof, locomotive_positions.tbl, total_pos) then
debug_str('total_pos was higher - found oom')
retries = retries + 1
if retries == 2 then
goto continue
end
goto retry
end
debug_str('total_pos was higher - spawning at locomotive_position')
WD.set_spawn_position(locomotive_position)
end
elseif compare_next then
if distance_from >= spawn_near_collapse.distance_from then
local success = check_tile(surface, locomotive_position, locomotive_positions.tbl, total_pos)
if success then
debug_str('distance_from was higher - found oom')
return
end
debug_str('distance_from was higher - spawning at locomotive_position')
WD.set_spawn_position({ x = locomotive_position.x, y = collapse_pos.y - y_value_position })
else
debug_str('distance_from was lower - spawning at locomotive_position')
WD.set_spawn_position({ x = locomotive_position.x, y = collapse_pos.y - y_value_position })
end
else
if collapse_position then
debug_str('total_pos was higher - spawning at collapse_position')
collapse_position = { x = collapse_position.x, y = collapse_position.y - y_value_position }
WD.set_spawn_position(collapse_position)
end
end
else
if collapse_position then
debug_str('total_pos was lower - spawning at collapse_position')
collapse_position = { x = collapse_position.x, y = collapse_position.y - y_value_position }
WD.set_spawn_position(collapse_position)
end
end
end
::continue::
end
function Public.on_player_joined_game(event)
local active_surface_index = Public.get('active_surface_index')
if not active_surface_index then
return
end
local players = Public.get('players')
local player = game.players[event.player_index]
local surface = game.surfaces[active_surface_index]
Public.set_difficulty()
ICW_Func.is_minimap_valid(player, surface)
Modifiers.update_player_modifiers(player)
if player.online_time < 1 then
if not players[player.index] then
players[player.index] = {}
end
local message = ({ 'main.greeting', player.name })
Alert.alert_player(player, 15, message)
if Public.get('death_mode') then
local death_message = ({ 'main.death_mode_warning' })
Alert.alert_player(player, 15, death_message)
end
player.clear_items_inside()
for item, data in pairs(this.starting_items) do
player.insert({ name = item, count = data.count })
end
end
if player.online_time < 1 then
local pos = surface.find_non_colliding_position('character', game.forces.player.get_spawn_position(surface), 3, 0)
if pos then
player.teleport(pos, surface)
else
pos = game.forces.player.get_spawn_position(surface)
player.teleport(pos, surface)
end
else
local p = { x = player.physical_position.x, y = player.physical_position.y }
local get_tile = surface.get_tile(p.x, p.y)
if get_tile.valid and get_tile.name == 'out-of-map' then
local pos = surface.find_non_colliding_position('character', game.forces.player.get_spawn_position(surface), 3, 0)
if pos then
player.teleport(pos, surface)
else
pos = game.forces.player.get_spawn_position(surface)
player.teleport(pos, surface)
end
end
end
local locomotive = Public.get('locomotive')
if not locomotive or not locomotive.valid then
return
end
local adjusted_zones = Public.get('adjusted_zones')
local distance_from_train
if adjusted_zones.reversed then
distance_from_train = player.physical_position.y < locomotive.position.y
else
distance_from_train = player.physical_position.y > locomotive.position.y
end
if distance_from_train then
local pos = surface.find_non_colliding_position('character', game.forces.player.get_spawn_position(surface), 3, 0)
if pos then
player.teleport(pos, surface)
else
pos = game.forces.player.get_spawn_position(surface)
player.teleport(pos, surface)
end
end
end
function Public.on_player_left_game()
Public.set_difficulty()
end
function Public.is_creativity_mode_on()
local creative_enabled = Misc.get('creative_enabled')
if creative_enabled then
WD.set('next_wave', 1000)
Public.set_difficulty()
end
end
function Public.disable_creative()
Misc.set('creative_enabled', false)
end
function Public.on_player_respawned(event)
local player = game.get_player(event.player_index)
if not player or not player.valid then
return
end
if player.character and player.character.valid then
Task.set_timeout_in_ticks(15, boost_movement_speed_on_respawn, { player = player })
player.character.health = round(player.character.health * health_values[random(1, #health_values)])
player.print(random_respawn_messages[random(1, #random_respawn_messages)])
end
end
function Public.on_player_driving_changed_state(event)
local player = game.get_player(event.player_index)
if not player or not player.valid then
return
end
local entity = event.entity
if not entity or not entity.valid then
return
end
local unit_number = entity.unit_number
local wagons_in_the_wild = Public.get('wagons_in_the_wild')
if not wagons_in_the_wild or not next(wagons_in_the_wild) then
return
end
local wagon = wagons_in_the_wild[unit_number]
if not wagon or not wagon.valid then
wagons_in_the_wild[unit_number] = nil
return
end
wagon.destructible = true
wagons_in_the_wild[unit_number] = nil
end
function Public.on_pre_player_toggled_map_editor(event)
local player = game.get_player(event.player_index)
if not player or not player.valid then
return
end
if player.name == 'Gerkiz' or not game.is_multiplayer() then
return
end
if this.editor_mode[player.index] then
return
end
this.editor_mode[player.index] = true
player.toggle_map_editor()
Task.set_timeout_in_ticks(5, exit_editor_mode_token, { player_index = player.index })
end
function Public.on_player_changed_position(event)
local active_surface_index = Public.get('active_surface_index')
if not active_surface_index then
return
end
local player = game.players[event.player_index]
if not player or not player.valid then
return
end
if player.controller_type == defines.controllers.remote then
return
end
if player.controller_type == defines.controllers.spectator then
return
end
if string.sub(player.physical_surface.name, 0, #scenario_name) ~= scenario_name then
return
end
local position = player.physical_position
local surface = game.surfaces[active_surface_index]
local adjusted_zones = Public.get('adjusted_zones')
local p = { x = player.physical_position.x, y = player.physical_position.y }
local config_tile = Public.get('void_or_tile')
if config_tile == 'lab-dark-2' then
local get_tile = surface.get_tile(p.x, p.y)
if get_tile.valid and get_tile.name == 'lab-dark-2' then
if random(1, 2) == 1 then
if random(1, 2) == 1 then
show_text('This path is not for players!', p, surface, player)
end
player.physical_surface.create_entity({ name = 'fire-flame', position = player.physical_position })
player.character.health = player.character.health - tile_damage
if player.character.health == 0 then
player.character.die()
local message = ({ 'main.death_message_' .. random(1, 7), player.name })
game.print(message, { r = 0.98, g = 0.66, b = 0.22 })
end
end
end
end
if adjusted_zones.reversed then
if position.y < -74 then
player.teleport({ position.x, position.y + 1 }, surface)
player.print(({ 'main.forcefield' }), { r = 0.98, g = 0.66, b = 0.22 })
if player.character then
player.character.health = player.character.health - 5
player.character.surface.create_entity({ name = 'water-splash', position = position })
if player.character.health <= 0 then
player.character.die('enemy')
end
end
end
else
if position.y >= 74 then
player.teleport({ position.x, position.y - 1 }, surface)
player.print(({ 'main.forcefield' }), { r = 0.98, g = 0.66, b = 0.22 })
if player.character then
player.character.health = player.character.health - 5
player.character.surface.create_entity({ name = 'water-splash', position = position })
if player.character.health <= 0 then
player.character.die('enemy')
end
end
end
end
end
local disable_recipes = function (force)
force.recipes['cargo-wagon'].enabled = false
force.recipes['fluid-wagon'].enabled = false
force.recipes['car'].enabled = false
force.recipes['tank'].enabled = false
force.recipes['artillery-wagon'].enabled = false
force.recipes['artillery-turret'].enabled = false
force.recipes['artillery-shell'].enabled = false
force.recipes['locomotive'].enabled = false
force.recipes['pistol'].enabled = false
force.recipes['discharge-defense-equipment'].enabled = false
end
function Public.disable_tech()
local force = game.forces.player
force.technologies['landfill'].enabled = false
force.technologies['spidertron'].enabled = false
force.technologies['spidertron'].researched = false
force.technologies['atomic-bomb'].enabled = false
force.technologies['atomic-bomb'].researched = false
force.technologies['artillery'].enabled = false
force.technologies['artillery'].researched = false
force.technologies['artillery-shell-range-1'].enabled = false
force.technologies['artillery-shell-range-1'].researched = false
force.technologies['artillery-shell-speed-1'].enabled = false
force.technologies['artillery-shell-speed-1'].researched = false
if Public.get('space_age') then
force.technologies['artillery-shell-damage-1'].enabled = false
force.technologies['artillery-shell-damage-1'].researched = false
end
force.technologies['lamp'].researched = true
force.technologies['railway'].researched = true
force.technologies['land-mine'].enabled = false
force.technologies['fluid-wagon'].enabled = false
force.technologies['cliff-explosives'].enabled = false
disable_recipes(force)
end
local disable_tech = Public.disable_tech
---@param event EventData.on_research_finished
function Public.on_research_finished(event)
disable_tech()
local research = event.research
local bonus_drill = game.forces.bonus_drill
local player = game.forces.player
local research_name = research.name
local force = research.force
if event.tick > 2000 then
if Public.get('print_tech_to_discord') and force.name == 'player' then
Server.to_discord_embed_raw('<a:Modded:835932131036364810> ' .. research_name:gsub('^%l', string.upper) .. ' has been researched!')
end
end
if research.name == 'toolbelt' then
Public.set('toolbelt_researched_count', 10)
end
if script.active_mods.quality then
local quality_list = Public.get('quality_list')
if research.name == 'quality-module' then
quality_list[#quality_list + 1] = 'uncommon'
end
if research.name == 'quality-module-2' then
quality_list[#quality_list + 1] = 'rare'
end
if research.name == 'epic-quality' then
quality_list[#quality_list + 1] = 'epic'
end
if research.name == 'legendary-quality' then
quality_list[#quality_list + 1] = 'legendary'
end
end
research.force.character_inventory_slots_bonus = (player.mining_drill_productivity_bonus * 50) + (Public.get('toolbelt_researched_count') or 0)
if bonus_drill then
bonus_drill.mining_drill_productivity_bonus = bonus_drill.mining_drill_productivity_bonus + 0.03
if bonus_drill.mining_drill_productivity_bonus >= 3 then
bonus_drill.mining_drill_productivity_bonus = 3
end
end
local players = game.connected_players
for i = 1, #players do
local p = players[i]
Modifiers.update_player_modifiers(p)
end
if research.name == 'steel-axe' then
local msg = 'Steel-axe technology has been researched, 100% has been applied.\nBuy Pickaxe-upgrades in the market to boost it even more!'
Alert.alert_all_players(30, msg, nil, 'achievement/tech-maniac', 0.6)
end
local force_name = research.force.name
if not force_name then
return
end
local flamethrower_damage = Public.get('flamethrower_damage')
flamethrower_damage[force_name] = -0.85
if research.name == 'military' then
game.forces[force_name].set_turret_attack_modifier('flamethrower-turret', flamethrower_damage[force_name])
game.forces[force_name].set_ammo_damage_modifier('flamethrower', flamethrower_damage[force_name])
end
if string.sub(research.name, 0, 18) == 'refined-flammables' then
flamethrower_damage[force_name] = flamethrower_damage[force_name] + 0.10
game.forces[force_name].set_turret_attack_modifier('flamethrower-turret', flamethrower_damage[force_name])
game.forces[force_name].set_ammo_damage_modifier('flamethrower', flamethrower_damage[force_name])
end
end
function Public.set_player_to_god(player)
if player.character and player.character.valid then
return false
end
if not player.character and player.controller_type ~= defines.controllers.spectator then
player.print('[color=blue][Spectate][/color] It seems that you are not in the realm of the living.', { color = Color.warning })
return false
end
local spectate = Public.get('spectate')
if spectate[player.index] and spectate[player.index].delay and spectate[player.index].delay > game.tick then
local cooldown = floor((spectate[player.index].delay - game.tick) / 60) + 1 .. ' seconds!'
player.print('[color=blue][Spectate][/color] Retry again in ' .. cooldown, { color = Color.warning })
return false
end
spectate[player.index] = nil
player.set_controller({ type = defines.controllers.god })
player.create_character()
local active_surface_index = Public.get('active_surface_index')
local surface = game.get_surface(active_surface_index)
if not surface or not surface.valid then
return false
end
if string.sub(player.physical_surface.name, 0, #surface.name) == surface.name then
local pos = surface.find_non_colliding_position('character', game.forces.player.get_spawn_position(surface), 3, 0)
if pos then
player.teleport(pos, surface)
else
pos = game.forces.player.get_spawn_position(surface)
player.teleport(pos, surface)
end
else
local pos = player.physical_surface.find_non_colliding_position('character', { 0, 0 }, 3, 0)
if pos then
player.teleport(pos, player.physical_surface)
else
player.teleport({ pos }, player.physical_surface)
end
end
Event.raise(
BottomFrame.events.bottom_quickbar_respawn_raise,
{
player_index = player.index
}
)
player.tag = ''
game.print('[color=blue][Spectate][/color] ' .. player.name .. ' is no longer spectating!')
Server.to_discord_bold(table.concat { '*** ', '[Spectate] ' .. player.name .. ' is no longer spectating!', ' ***' })
return true
end
function Public.set_player_to_spectator(player)
if player.in_combat then
player.print('[color=blue][Spectate][/color] You are in combat. Try again soon.', { color = Color.warning })
return false
end
if player.driving then
return player.print('[color=blue][Spectate][/color] Please exit the vehicle before continuing', { color = Color.warning })
end
local spectate = Public.get('spectate')
if not spectate[player.index] then
spectate[player.index] = {
verify = false
}
player.print('[color=blue][Spectate][/color] Please click the spectate button again if you really want to this.', { color = Color.warning })
return false
end
if player.character and player.character.valid then
player.character.die()
end
player.character = nil
player.spectator = true
player.tag = '[img=utility/create_ghost_on_entity_death_modifier_icon]'
player.set_controller({ type = defines.controllers.spectator })
game.print('[color=blue][Spectate][/color] ' .. player.name .. ' is now spectating.')
Server.to_discord_bold(table.concat { '*** ', '[Spectate] ' .. player.name .. ' is now spectating.', ' ***' })
if spectate[player.index] and not spectate[player.index].delay then
spectate[player.index].verify = true
spectate[player.index].delay = game.tick + 3600
end
return true
end
Public.firearm_magazine_ammo = { name = 'firearm-magazine', count = 200 }
Public.piercing_rounds_magazine_ammo = { name = 'piercing-rounds-magazine', count = 200 }
Public.uranium_rounds_magazine_ammo = { name = 'uranium-rounds-magazine', count = 200 }
Public.light_oil_ammo = { name = 'light-oil', amount = 100 }
Public.artillery_shell_ammo = { name = 'artillery-shell', count = 15 }
Public.laser_turrent_power_source = { buffer_size = 2400000, power_production = 40000 }
Public.pause_waves_custom_callback_token = pause_waves_custom_callback_token
function Public.get_func(key)
if key then
return this[key]
else
return this
end
end
function Public.show_all_gui(player)
for _, child in pairs(player.gui.top.children) do
child.visible = true
end
end
function Public.clear_spec_tag(player)
if player.tag == '[Spectator]' then
player.tag = ''
end
end
function Public.equip_players(starting_items, recreate)
local players = Public.get('players')
for _, player in pairs(game.players) do
if player.character and player.character.valid then
player.character.destroy()
end
player.clear_items_inside()
if player.connected then
if not player.character then
player.set_controller({ type = defines.controllers.god })
player.create_character()
end
player.character.destructible = true
Modifiers.update_player_modifiers(player)
if not recreate then
starting_items = starting_items or this.starting_items
for item, item_data in pairs(this.starting_items) do
player.insert({ name = item, count = item_data.count })
end
end
Public.show_all_gui(player)
Public.clear_spec_tag(player)
else
if player.character then
player.character.destructible = true
end
players[player.index] = nil
Session.clear_player(player)
game.remove_offline_players({ player.index })
end
end
end
function Public.reset_func_table()
this.power_sources = { index = 1 }
this.refill_turrets = { index = 1 }
this.magic_crafters = { index = 1 }
this.magic_fluid_crafters = { index = 1 }
this.techs = {}
this.limit_types = {}
this.starting_items = {
['pistol'] = {
count = 1
},
['firearm-magazine'] = {
count = 16
},
['rail'] = {
count = 16
},
['wood'] = {
count = 16
},
['explosives'] = {
count = 32
}
}
end
local on_player_joined_game = Public.on_player_joined_game
local on_player_left_game = Public.on_player_left_game
local on_research_finished = Public.on_research_finished
local on_player_changed_position = Public.on_player_changed_position
local on_player_respawned = Public.on_player_respawned
local on_player_driving_changed_state = Public.on_player_driving_changed_state
local on_pre_player_toggled_map_editor = Public.on_pre_player_toggled_map_editor
Event.add(de.on_player_joined_game, on_player_joined_game)
Event.add(de.on_player_left_game, on_player_left_game)
Event.add(de.on_research_finished, on_research_finished)
Event.add(de.on_player_changed_position, on_player_changed_position)
Event.add(de.on_player_respawned, on_player_respawned)
Event.add(de.on_player_driving_changed_state, on_player_driving_changed_state)
Event.add(de.on_pre_player_toggled_map_editor, on_pre_player_toggled_map_editor)
Event.add(de.on_player_cursor_stack_changed, on_player_cursor_stack_changed)
Event.on_nth_tick(10, tick)
Event.add(WD.events.on_wave_created, on_wave_created)
Event.add(WD.events.on_primary_target_missing, on_primary_target_missing)
return Public