1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2024-12-26 22:56:43 +02:00

Mtn v3 - stateful changes

This commit is contained in:
Gerkiz 2023-08-10 14:28:32 +02:00
parent 9aa278b1e9
commit a45e9ef598
19 changed files with 2004 additions and 29 deletions

View File

@ -1,7 +1,7 @@
[mountain_fortress_v3]
map_info_main_caption=M O U N T A I N F O R T R E S S V3
map_info_sub_caption= ~~ diggy diggy choo choo ~~
map_info_text=[color=red]READ THIS!\nIf there are any code bugs or desyncs. Please report asap to @Gerkiz!\nIf there are any game breaking bugs then this map might be shutdown to hot-fix the issue.[/color]\n\nThe biters have caught the scent of fish in the cargo wagon.\nGuide the choo into the mountain and protect it as long as possible!\nThis however will not be an easy task,\nsince their strength and numbers increase over time.\n\nIn addition, the southern grounds collapse over time.\n\nDelve deep for greater treasures, but also face increased dangers.\nMining productivity research will overhaul your mining equipment, increasing the size of your backpack.\n\nAs you dig, you will encounter impassable dark chasms or rivers.\nArtillery will try to shoot you down! Dig fast, dig north!\n\nSome explosives may cause rocks to fall down the mountain, filling the void, creating new ways.\nAll they need is a container and a well aimed shot.\n\nEnter the cargo wagon to reveal the wagon surface!\n\nRandom buildings that generate resources can be found throughout the world.\n\nPlacing steel-chests near cargo-wagons enables you to quickly move content.\n\nStaying inside the train aura prevents biters from spawning when mining entities.\n\nRadars cannot be built near each other.\n\nRPG GUI is disabled inside the train.\n\nDisconnecting wagons is disabled.\nYou can't cancel crafting when standing inside the train aura.\n\nDon't try to run north with your Spidertron if the train is not near you.\nYou have been warned.\n\nMining drills have great mining-bonus which also is increased after each research, use them when you can!\n\nThe mystical chest in the locomotive offers some rewards.\nOne must feed the chest to receive such rewards.\n\nGood luck on your journey!
map_info_sub_caption= ~~ diggy diggy rocky rocky ~~
map_info_text=[color=red][img=utility/danger_icon] READ THIS! [img=utility/danger_icon]\nIf there are any code bugs or desyncs. Please report asap to @Gerkiz!\nIf there are any game breaking bugs then this map might be shutdown to hot-fix the issue.[/color]\n\nCheck out the [img=utility/custom_tag_icon] for information regarding on how one can win the game!\n\nThe biters have caught the scent of fish in the cargo wagon.\nGuide the choo into the mountain and protect it as long as possible!\nThis however will not be an easy task,\nsince their strength and numbers increase over time.\n\nIn addition, the southern grounds collapse over time.\n\nDelve deep for greater treasures, but also face increased dangers.\nMining productivity research will overhaul your mining equipment, increasing the size of your backpack.\n\nAs you dig, you will encounter impassable dark chasms or rivers.\nArtillery will try to shoot you down! Dig fast, dig north!\n\nSome explosives may cause rocks to fall down the mountain, filling the void, creating new ways.\nAll they need is a container and a well aimed shot.\n\nEnter the cargo wagon to reveal the wagon surface!\n\nRandom buildings that generate resources can be found throughout the world.\n\nPlacing steel-chests near cargo-wagons enables you to quickly move content.\n\nStaying inside the train aura prevents biters from spawning when mining entities.\n\nRadars cannot be built near each other.\n\nRPG GUI is disabled inside the train.\n\nDisconnecting wagons is disabled.\nYou can't cancel crafting when standing inside the train aura.\n\nDon't try to run north with your Spidertron if the train is not near you.\nYou have been warned.\n\nMining drills have great mining-bonus which also is increased after each research, use them when you can!\n\nThe mystical chest in the locomotive offers some rewards.\nOne must feed the chest to receive such rewards.\n\nGood luck on your journey!
[breached_wall]
collapse_start=[color=blue]Mapkeeper:[/color]\nWarning, Collapse has begun!
@ -133,3 +133,37 @@ diff_tooltip=Wave Defense is based on amount of players.\nBonus XP on join: __1_
[functions]
researched_complete=__1__ has been researched!
[stateful]
win_conditions=Win conditions
rounds_survived=[font=default-bold]Rounds survived: [/font]
zone=[font=default-bold]Breach zones: [/font]
wave=[font=default-bold]Survive until wave: [/font]
mystical_chest=[font=default-bold]Feeding the hungry chest: [/font]
enemies_killed=[font=default-bold]Enemies killed: [/font]
launch_rockets=[font=default-bold]Rockets launched: [/font]
rocks_mined=[font=default-bold]Rocks mined: [/font]
trees_mined=[font=default-bold]Trees mined: [/font]
production=[font=default-bold]Produce the following items: [/font]
production_single=[font=default-bold]Produce the following item: [/font]
research=[font=default-bold]Research __1__: [/font]
locomotive_market_pickaxe=[font=default-bold]Pickaxe upgrades from market: [/font]
locomotive_market_health=[font=default-bold]Health upgrades from market: [/font]
locomotive_market_xp_points=[font=default-bold]XP points from market: [/font]
clock=within __3__/__4__ __5__ [img=utility/clock]
not_done=__1__/__2__ [img=utility/not_available]
not_done_empty=[img=utility/not_available]
done=__2__/__2__ [img=utility/check_mark_green]
done_empty=[img=utility/check_mark_green]
win_conditions_tooltip=In order to win the game, you must complete all these objectives that are listed below! [img=utility/force_editor_icon]
tooltip_failed=You've failed to complete this objective. [img=utility/not_available]
tooltip_completed=This objective has been complete. [img=utility/check_mark_green]
tooltip_1=Breaching zone: __1__ will mark this objective as complete.\nNote the main [entity=locomotive] needs to stay in this zone.
tooltip_2=Surviving until wave: __1__ will mark this objective as complete.
tooltip_3=Producing all the required items will mark this objective as complete.
tooltip_final=[entity=behemoth-biter] Final battle awaits.

View File

@ -207,7 +207,7 @@ commands.add_command(
)
commands.add_command(
'toggle_collapse',
'disable_collapse',
'Toggles the collapse feature',
function()
local player = game.player
@ -217,19 +217,21 @@ commands.add_command(
player.print("[ERROR] You're not admin!", Color.fail)
return
end
if not Collapse.start_now() then
Collapse.start_now(true)
game.print(mapkeeper .. ' ' .. player.name .. ', has started collapse!', {r = 0.98, g = 0.66, b = 0.22})
if Collapse.get_disable_state() then
Collapse.disable_collapse(false)
game.print(mapkeeper .. ' ' .. player.name .. ', has enabled collapse!', {r = 0.98, g = 0.66, b = 0.22})
log(player.name .. ', has enabled collapse!')
else
Collapse.start_now(false)
game.print(mapkeeper .. ' ' .. player.name .. ', has stopped collapse!', {r = 0.98, g = 0.66, b = 0.22})
Collapse.disable_collapse(true)
game.print(mapkeeper .. ' ' .. player.name .. ', has disabled collapse!', {r = 0.98, g = 0.66, b = 0.22})
log(player.name .. ', has disabled collapse!')
end
else
if not Collapse.start_now() then
Collapse.start_now(true)
if Collapse.get_disable_state() then
Collapse.disable_collapse(false)
log('Collapse has started.')
else
Collapse.start_now(false)
Collapse.disable_collapse(true)
log('Collapse has stopped.')
end
end

View File

@ -28,5 +28,6 @@ Public.linked_chests = require 'maps.mountain_fortress_v3.locomotive.linked_ches
Public.market = require 'maps.mountain_fortress_v3.locomotive.market'
Public.permission_groups = require 'maps.mountain_fortress_v3.locomotive.permission_groups'
Public.spawn_locomotive = require 'maps.mountain_fortress_v3.locomotive.spawn_locomotive'
Public.stateful = require 'maps.mountain_fortress_v3.stateful.main'
return Public

View File

@ -282,9 +282,17 @@ local function is_protected(e)
if string.sub(e.surface.name, 0, #map_name) ~= map_name then
return true
end
local boss_map_name = 'boss_room'
if string.sub(e.surface.name, 0, #boss_map_name) ~= boss_map_name then
return true
end
if protect_types[e.type] then
return true
end
return false
end

View File

@ -1658,12 +1658,21 @@ function Public.set_player_to_god(player)
return false
end
local pos = surface.find_non_colliding_position('character', game.forces.player.get_spawn_position(surface), 3, 0, 5)
if pos then
player.teleport(pos, surface)
if string.sub(player.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, 5)
if pos then
player.teleport(pos, surface)
else
pos = game.forces.player.get_spawn_position(surface)
player.teleport(pos, surface)
end
else
pos = game.forces.player.get_spawn_position(surface)
player.teleport(pos, surface)
local pos = player.surface.find_non_colliding_position('character', {0, 0}, 3, 0, 5)
if pos then
player.teleport(pos, player.surface)
else
player.teleport({pos}, player.surface)
end
end
Event.raise(

View File

@ -5,6 +5,7 @@ local IC_Gui = require 'maps.mountain_fortress_v3.ic.gui'
local IC_Minimap = require 'maps.mountain_fortress_v3.ic.minimap'
local Difficulty = require 'modules.difficulty_vote_by_amount'
local Gui = require 'utils.gui'
local Color = require 'utils.color_presets'
local SpamProtection = require 'utils.spam_protection'
local format_number = require 'util'.format_number
@ -60,6 +61,10 @@ local function spectate_button(player)
return
end
if Public.get('final_battle') then
return
end
local b =
player.gui.top.add {
type = 'sprite-button',
@ -541,6 +546,10 @@ Gui.on_click(
return
end
if Public.get('final_battle') then
return player.print('Not possible during the final battle.', Color.warning)
end
if player.character and player.character.valid then
local success = Public.set_player_to_spectator(player)
if success then

View File

@ -6,6 +6,7 @@ local Task = require 'utils.task'
local Token = require 'utils.token'
local SpamProtection = require 'utils.spam_protection'
local deepcopy = table.deepcopy
local random = math.random
local sqrt = math.sqrt
@ -807,6 +808,35 @@ function Public.create_wagon(icw, created_entity, delay_surface)
return wagon
end
function Public.migrate_wagon(icw, source, target)
if not validate_entity(target) then
return
end
local target_wagon = target.unit_number
local source_wagon = source.unit_number
for door_id, entity_id in pairs(icw.doors) do
if entity_id == source_wagon then
icw.doors[door_id] = target_wagon
end
end
for _, surface_data in pairs(icw.surfaces) do
if surface_data.name == source_wagon then
surface_data.name = tostring(target_wagon)
end
end
for unit_number, unit_data in pairs(icw.wagons) do
if unit_number == source_wagon then
unit_data.surface.name = tostring(target_wagon)
unit_data.entity = target
icw.wagons[target_wagon] = deepcopy(unit_data)
return icw.wagons[target_wagon]
end
end
end
function Public.use_cargo_wagon_door_with_entity(icw, player, door)
local player_data = get_player_data(icw, player)
if player_data.state then

View File

@ -139,6 +139,11 @@ function Public.register_wagon(wagon_entity)
return Functions.create_wagon(icw, wagon_entity)
end
function Public.migrate_wagon(source, target)
local icw = ICW.get()
return Functions.migrate_wagon(icw, source, target)
end
local on_player_or_robot_built_tile = Functions.on_player_or_robot_built_tile
Event.on_init(on_init)

View File

@ -370,7 +370,7 @@ local function get_driver_action(entity)
local total_time = player.online_time + Session.get_session_player(player)
if total_time and total_time < playtime_required_to_drive_train then
player.print('[color=blue][Locomotive][/color] Not enough playtime acquired to drive train.')
player.print('[color=blue][Locomotive][/color] Not enough playtime acquired to drive the train.')
driver.driving = false
return
end
@ -598,7 +598,6 @@ function Public.is_around_train(entity)
return false
end
local surface = game.surfaces[active_surface_index]
local upgrades = Public.get('upgrades')
@ -625,6 +624,12 @@ function Public.render_train_hp()
return
end
local health_text = Public.get('health_text')
if health_text then
rendering.destroy(health_text)
end
Public.set(
'health_text',
rendering.draw_text {
@ -724,6 +729,7 @@ local function tick()
end
Event.on_nth_tick(5, tick)
Event.on_nth_tick(150, set_carriages)
Event.add(defines.events.on_research_finished, on_research_finished)
Event.add(defines.events.on_player_changed_surface, on_player_changed_surface)

View File

@ -5,6 +5,9 @@ Mountain Fortress v3 is maintained by Gerkiz and hosted by Comfy.
Want to host it? Ask Gerkiz#0001 at discord!
]]
-- develop setting
local _DEV_MODE = true
local Event = require 'utils.event'
local Public = require 'maps.mountain_fortress_v3.core'
local Discord = require 'utils.discord'
@ -137,7 +140,7 @@ function Public.reset_map()
-- OfflinePlayers.set_offline_players_surface_removal(true)
RPG.rpg_reset_all_players()
RPG.set_surface_name(game.surfaces[this.active_surface_index].name)
RPG.set_surface_name({game.surfaces[this.active_surface_index].name, 'boss_room'})
RPG.enable_health_and_mana_bars(true)
RPG.enable_wave_defense(true)
RPG.enable_mana(true)
@ -174,7 +177,7 @@ function Public.reset_map()
Explosives.set_surface_whitelist({[surface.name] = true})
Explosives.check_growth_below_void(true)
game.forces.player.set_spawn_position({-27, 25}, surface)
game.forces.player.set_spawn_position({x = -27, y = 25}, surface)
game.forces.player.manual_mining_speed_modifier = 0
game.forces.player.set_ammo_damage_modifier('artillery-shell', -0.95)
game.forces.player.worker_robots_battery_modifier = 4
@ -218,6 +221,7 @@ function Public.reset_map()
Difficulty.reset_difficulty_poll({closing_timeout = game.tick + 36000})
Difficulty.set_gui_width(20)
Difficulty.show_gui(false)
Collapse.set_kill_entities(false)
Collapse.set_kill_specific_entities(collapse_kill)
@ -259,12 +263,12 @@ function Public.reset_map()
Public.set_difficulty()
Public.disable_creative()
if not surface.is_chunk_generated({-20, 22}) then
surface.request_to_generate_chunks({-20, 22}, 0.1)
if not surface.is_chunk_generated({x = -20, y = 22}) then
surface.request_to_generate_chunks({x = -20, y = 22}, 0.1)
surface.force_generate_chunk_requests()
end
game.forces.player.set_spawn_position({-27, 25}, surface)
game.forces.player.set_spawn_position({x = -27, y = 25}, surface)
game.speed = 1
Task.set_queue_speed(16)
@ -276,6 +280,14 @@ function Public.reset_map()
this.market_announce = game.tick + 1200
this.game_lost = false
Public.stateful.enable(true)
Public.stateful.create()
if _DEV_MODE then
Collapse.disable_collapse(true)
WD.disable_spawning_biters(true)
end
Task.set_timeout_in_ticks(25, announce_new_map)
end

View File

@ -624,6 +624,8 @@ function Public.add_mystical_chest(player)
init_price_check(locomotive, mystical_chest)
if player and player.valid then
mystical_chest_reward(player)
local mystical_chest_completed = Public.get('mystical_chest_completed')
Public.set('mystical_chest_completed', mystical_chest_completed + 1)
end
return true
end

View File

@ -0,0 +1,74 @@
local Public = require 'maps.mountain_fortress_v3.stateful.table'
local map_name = 'boss_room'
local bp =
'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'
function Public.create()
local surface =
game.surfaces.music or
game.create_surface(
map_name,
{
autoplace_controls = {
['coal'] = {frequency = 0, size = 3, richness = 3},
['stone'] = {frequency = 0, size = 3, richness = 3},
['copper-ore'] = {frequency = 0, size = 3, richness = 3},
['iron-ore'] = {frequency = 0, size = 3, richness = 3},
['uranium-ore'] = {frequency = 0, size = 3, richness = 3},
['crude-oil'] = {frequency = 0, size = 3, richness = 1},
['trees'] = {frequency = 0, size = 0, richness = 0},
['enemy-base'] = {frequency = 15, size = 0, richness = 1}
},
cliff_settings = {cliff_elevation_0 = 1024, cliff_elevation_interval = 10, name = 'cliff'},
height = 1024,
width = 1024,
peaceful_mode = false,
seed = 1337,
starting_area = 'very-low',
starting_points = {{x = 0, y = 0}},
terrain_segmentation = 'none',
water = 'none'
}
)
local position = {x = -500, y = 503}
surface.daytime = 0.5
surface.freeze_daytime = true
surface.min_brightness = 0.3
surface.brightness_visual_weights = {1, 1, 1}
surface.request_to_generate_chunks(position, 2)
surface.request_to_generate_chunks({0, 0}, 2)
surface.force_generate_chunk_requests()
local item = surface.create_entity {name = 'item-on-ground', position = position, stack = {name = 'blueprint', count = 1}}
if not item then
return
end
local success = item.stack.import_stack(bp)
if success <= 0 then
local ghosts = item.stack.build_blueprint {surface = surface, force = 'player', position = position, force_build = true}
for _, ghost in pairs(ghosts) do
local _, ent = ghost.silent_revive({raise_revive = true})
if ent and ent.valid then
ent.destructible = false
ent.minable = false
end
end
end
if item.valid then
item.destroy()
end
return surface
end
function Public.nuke_world()
if game.surfaces.boss_room then
game.delete_surface(map_name)
end
Public.create()
end
return Public

View File

@ -0,0 +1,427 @@
local Event = require 'utils.event'
local Task = require 'utils.task'
local Token = require 'utils.token'
local Public = require 'maps.mountain_fortress_v3.stateful.table'
local ceil = math.ceil
local queue_task = Task.queue_task
local tiles_per_call = 8
local total_calls = ceil(1024 / tiles_per_call)
local regen_decoratives = false
local generate_map = require 'maps.mountain_fortress_v3.stateful.terrain'.heavy_functions
-- Simple "loop" that is UPS friendly.
local function get_position(data)
data.yv = data.yv + 1
if data.yv == 32 then
if data.xv == 32 then
data.xv = 0
end
if data.yv == 32 then
data.yv = 0
end
data.xv = data.xv + 1
end
data.position = {x = data.top_x + data.xv, y = data.top_y + data.yv}
end
local function do_tile_inner(tiles, tile, pos)
if type(tile) == 'string' then
tiles[#tiles + 1] = {name = tile, position = pos}
end
end
local function do_tile(x, y, data, shape)
local pos = {x, y}
-- local coords need to be 'centered' to allow for correct rotation and scaling.
local tile = shape(data)
if type(tile) == 'table' then
do_tile_inner(data.tiles, tile.tile, pos)
local hidden_tile = tile.hidden_tile
if hidden_tile then
data.hidden_tiles[#data.hidden_tiles + 1] = {tile = hidden_tile, position = pos}
end
local entities = tile.entities
if entities then
for _, entity in ipairs(entities) do
if not entity.position then
entity.position = pos
end
data.entities[#data.entities + 1] = entity
end
end
local buildings = tile.buildings
if buildings then
for _, entity in ipairs(buildings) do
if not entity.position then
entity.position = pos
end
data.buildings[#data.buildings + 1] = entity
end
end
local decoratives = tile.decoratives
if decoratives then
for _, decorative in ipairs(decoratives) do
data.decoratives[#data.decoratives + 1] = decorative
end
end
else
do_tile_inner(data.tiles, tile, pos)
end
end
local function do_row(row, data, shape)
local y = data.top_y + row
local top_x = data.top_x
local tiles = data.tiles
data.y = y
for x = top_x, top_x + 31 do
data.x = x
local pos = {data.x, data.y}
get_position(data)
-- local coords need to be 'centered' to allow for correct rotation and scaling.
local tile = shape(data)
if type(tile) == 'table' then
do_tile_inner(tiles, tile.tile, pos)
local hidden_tile = tile.hidden_tile
if hidden_tile then
data.hidden_tiles[#data.hidden_tiles + 1] = {tile = hidden_tile, position = pos}
end
local entities = tile.entities
if entities then
for _, entity in ipairs(entities) do
if not entity.position then
entity.position = pos
end
data.entities[#data.entities + 1] = entity
end
end
local buildings = tile.buildings
if buildings then
for _, entity in ipairs(buildings) do
if not entity.position then
entity.position = pos
end
data.buildings[#data.buildings + 1] = entity
end
end
local decoratives = tile.decoratives
if decoratives then
for _, decorative in ipairs(decoratives) do
if not decorative.position then
decorative.position = pos
end
data.decoratives[#data.decoratives + 1] = decorative
end
end
else
do_tile_inner(tiles, tile, pos)
end
end
end
local function do_place_tiles(data)
local surface = data.surface
surface.set_tiles(data.tiles, true)
end
local function do_place_hidden_tiles(data)
local surface = data.surface
surface.set_tiles(data.hidden_tiles, true)
end
local function do_place_decoratives(data)
local surface = data.surface
if regen_decoratives then
surface.regenerate_decorative(nil, {{data.top_x / 32, data.top_y / 32}})
end
local dec = data.decoratives
if #dec > 0 then
surface.create_decoratives({check_collision = true, decoratives = dec})
end
end
local function do_place_buildings(data)
local surface = data.surface
local entity
local callback
for _, e in ipairs(data.buildings) do
if e.e_type then
local p = e.position
if
surface.count_entities_filtered {
area = {{p.x - 32, p.y - 32}, {p.x + 32, p.y + 32}},
type = e.e_type,
limit = 1
} == 0
then
entity = surface.create_entity(e)
if entity and entity.valid then
if e.direction then
entity.direction = e.direction
end
if e.force then
entity.force = e.force
end
if e.callback then
local c = e.callback.callback
if c then
local d = {callback_data = e.callback.data}
if not d then
callback = Token.get(c)
callback(entity)
else
callback = Token.get(c)
callback(entity, d)
end
end
end
end
end
end
end
end
local function do_place_entities(data)
local surface = data.surface
local entity
local callback
for _, e in ipairs(data.entities) do
if e.collision then
if surface.can_place_entity(e) then
entity = surface.create_entity(e)
if entity then
if e.direction then
entity.direction = e.direction
end
if e.active ~= nil then
entity.active = e.active
end
if e.force then
entity.force = e.force
end
if e.amount then
entity.amount = e.amount
end
if e.callback then
callback = Token.get(e.callback)
callback({entity = entity})
end
end
end
else
entity = surface.create_entity(e)
if entity then
if e.direction then
entity.direction = e.direction
end
if e.active ~= nil then
entity.active = e.active
end
if e.force then
entity.force = e.force
end
if e.amount then
entity.amount = e.amount
end
if e.callback then
callback = Token.get(e.callback)
callback({entity = entity})
end
end
end
end
end
local function map_gen_action(data)
local state = data.y
if state < 32 then
local shape = generate_map
if shape == nil then
return false
end
if not data.surface.valid then
return
end
local count = tiles_per_call
local y = state + data.top_y
local x = data.x
local max_x = data.top_x + 32
data.y = y
repeat
count = count - 1
get_position(data)
do_tile(x, y, data, shape)
x = x + 1
if x == max_x then
y = y + 1
if y == data.top_y + 32 then
break
end
x = data.top_x
data.y = y
end
data.x = x
until count == 0
data.y = y - data.top_y
return true
elseif state == 32 then
do_place_tiles(data)
data.y = 33
return true
elseif state == 33 then
do_place_hidden_tiles(data)
data.y = 34
return true
elseif state == 34 then
do_place_entities(data)
data.y = 35
return true
elseif state == 35 then
do_place_decoratives(data)
data.y = 36
return false
end
end
local map_gen_action_token = Token.register(map_gen_action)
--- Adds generation of a Chunk of the map to the queue
-- @param event <table> the event table from on_chunk_generated
local function schedule_chunk(event)
local surface = event.surface
local shape = generate_map
if event.tick < 1 then
return
end
if not surface.valid then
return
end
if not shape then
return
end
local area = event.area
local data = {
yv = -0,
xv = 0,
y = 0,
x = area.left_top.x,
area = area,
top_x = area.left_top.x,
top_y = area.left_top.y,
surface = surface,
tiles = {},
hidden_tiles = {},
entities = {},
buildings = {},
decoratives = {},
markets = {},
treasure = {}
}
if not data.surface or not data.surface.valid then
return
end
queue_task(map_gen_action_token, data, total_calls)
end
--- Generates a Chunk of map when called
-- @param event <table> the event table from on_chunk_generated
local function do_chunk(event)
local surface = event.surface
local shape = generate_map
if not surface.valid then
return
end
if not shape then
return
end
local area = event.area
local data = {
yv = -0,
xv = 0,
area = area,
top_x = area.left_top.x,
top_y = area.left_top.y,
surface = surface,
tiles = {},
hidden_tiles = {},
entities = {},
buildings = {},
decoratives = {},
markets = {},
treasure = {}
}
if not data.surface.valid then
return
end
for row = 0, 31 do
do_row(row, data, shape)
end
do_place_tiles(data)
do_place_hidden_tiles(data)
do_place_entities(data)
do_place_buildings(data)
do_place_decoratives(data)
end
local function on_chunk(event)
local force_chunk = Public.get_stateful('force_chunk')
local stop_chunk = Public.get_stateful('stop_chunk')
if stop_chunk then
return
end
if force_chunk then
do_chunk(event)
else
schedule_chunk(event)
end
end
Event.add(defines.events.on_chunk_generated, on_chunk)
return Public

View File

@ -0,0 +1,534 @@
local Event = require 'utils.event'
local SpamProtection = require 'utils.spam_protection'
local Public = require 'maps.mountain_fortress_v3.table'
local Gui = require 'utils.gui'
local WD = require 'modules.wave_defense.table'
local Token = require 'utils.token'
local Task = require 'utils.task'
local main_button_name = Gui.uid_name()
local main_frame_name = Gui.uid_name()
local close_button = Gui.uid_name()
local random = math.random
local function create_particles(surface, name, position, amount, cause_position)
local d1 = (-100 + random(0, 200)) * 0.0004
local d2 = (-100 + random(0, 200)) * 0.0004
name = name or 'leaf-particle'
if cause_position then
d1 = (cause_position.x - position.x) * 0.025
d2 = (cause_position.y - position.y) * 0.025
end
for _ = 1, amount, 1 do
local m = random(4, 10)
local m2 = m * 0.005
surface.create_particle(
{
name = name,
position = position,
frame_speed = 1,
vertical_speed = 0.130,
height = 0,
movement = {
(m2 - (random(0, m) * 0.01)) + d1,
(m2 - (random(0, m) * 0.01)) + d2
}
}
)
end
end
local spread_particles_token =
Token.register(
function(event)
local player_index = event.player_index
local player = game.get_player(player_index)
if not player or not player.valid then
return
end
local particle = event.particle
create_particles(player.surface, particle, player.position, 128)
end
)
local function create_button(player)
local b =
player.gui.top.add(
{
type = 'sprite-button',
name = main_button_name,
sprite = 'utility/custom_tag_icon',
tooltip = 'Has information about all objectives that needs to be completed'
}
)
b.style.minimal_height = 38
b.style.maximal_height = 38
end
local function play_game_won_sound()
local players = game.connected_players
for i = 1, #players do
local player = players[i]
player.play_sound {path = 'utility/game_won', volume_modifier = 0.75}
Task.set_timeout_in_ticks(10, spread_particles_token, {player_index = player.index, particle = 'iron-ore-particle'})
Task.set_timeout_in_ticks(15, spread_particles_token, {player_index = player.index, particle = 'branch-particle'})
Task.set_timeout_in_ticks(20, spread_particles_token, {player_index = player.index, particle = 'copper-ore-particle'})
Task.set_timeout_in_ticks(25, spread_particles_token, {player_index = player.index, particle = 'branch-particle'})
Task.set_timeout_in_ticks(30, spread_particles_token, {player_index = player.index, particle = 'stone-particle'})
Task.set_timeout_in_ticks(35, spread_particles_token, {player_index = player.index, particle = 'branch-particle'})
Task.set_timeout_in_ticks(40, spread_particles_token, {player_index = player.index, particle = 'coal-particle'})
Task.set_timeout_in_ticks(45, spread_particles_token, {player_index = player.index, particle = 'branch-particle'})
end
end
local function spacer(frame)
local flow = frame.add({type = 'flow'})
flow.style.minimal_height = 2
end
local function objective_frames(stateful, player_frame, objective, data)
local objective_name = objective[1]
if objective_name == 'supplies' or objective_name == 'single_item' then
local supplies = stateful.objectives.supplies
local tbl = player_frame.add {type = 'table', column_count = 2}
tbl.style.horizontally_stretchable = true
local left_flow = tbl.add({type = 'flow'})
left_flow.style.horizontal_align = 'left'
left_flow.style.horizontally_stretchable = true
if objective_name == 'single_item' then
left_flow.add({type = 'label', caption = {'stateful.production_single'}})
else
left_flow.add({type = 'label', caption = {'stateful.production'}})
end
player_frame.add({type = 'line', direction = 'vertical'})
local right_flow = tbl.add({type = 'flow'})
right_flow.style.horizontal_align = 'right'
right_flow.style.horizontally_stretchable = true
data.supply_completed = right_flow.add({type = 'label', caption = '[img=utility/not_available]'})
-- if objective[1]() then
-- right_flow.add({type = 'label', caption = '[img=utility/check_mark_green]'})
-- else
-- end
data.supply = {}
local flow = player_frame.add({type = 'flow'})
local item_table = flow.add({type = 'table', name = 'item_table', column_count = 3})
if objective_name ~= 'single_item' then
data.supply[#data.supply + 1] = item_table.add({type = 'sprite-button', name = supplies[1].name, sprite = 'item/' .. supplies[1].name, enabled = false, number = supplies[1].count})
data.supply[#data.supply + 1] = item_table.add({type = 'sprite-button', name = supplies[2].name, sprite = 'item/' .. supplies[2].name, enabled = false, number = supplies[2].count})
data.supply[#data.supply + 1] = item_table.add({type = 'sprite-button', name = supplies[3].name, sprite = 'item/' .. supplies[3].name, enabled = false, number = supplies[3].count})
else
local single_item = stateful.objectives.single_item
data.single_item = item_table.add({type = 'sprite-button', name = single_item.name, sprite = 'item/' .. single_item.name, enabled = false, number = single_item.count})
end
return
end
if objective_name == 'locomotive_market_selection' then
local callback_token = stateful.objectives.locomotive_market_selection[1]
local callback_data = stateful.objectives.locomotive_market_selection[2]
local callback = Token.get(callback_token)
local _, locale_left, locale_right = callback(callback_data)
local tbl = player_frame.add {type = 'table', column_count = 2}
tbl.style.horizontally_stretchable = true
local left_flow = tbl.add({type = 'flow'})
left_flow.style.horizontal_align = 'left'
left_flow.style.horizontally_stretchable = true
left_flow.add({type = 'label', caption = locale_left})
local right_flow = tbl.add({type = 'flow'})
right_flow.style.horizontal_align = 'right'
right_flow.style.horizontally_stretchable = true
local locomotive_market = right_flow.add({type = 'label', caption = locale_right})
data.locomotive_market = locomotive_market
return
end
local callback = Token.get(objective[2])
local _, objective_locale_left, objective_locale_right = callback()
local tbl = player_frame.add {type = 'table', column_count = 2}
tbl.style.horizontally_stretchable = true
local left_flow = tbl.add({type = 'flow'})
left_flow.style.horizontal_align = 'left'
left_flow.style.horizontally_stretchable = true
data.random_objectives = {}
left_flow.add({type = 'label', caption = objective_locale_left})
local right_flow = tbl.add({type = 'flow'})
right_flow.style.horizontal_align = 'right'
right_flow.style.horizontally_stretchable = true
local objective_locale_right_label = right_flow.add({type = 'label', caption = objective_locale_right})
data.random_objectives[#data.random_objectives + 1] = {name = objective_name, frame = objective_locale_right_label}
end
local function update_data()
local players = game.connected_players
local stateful = Public.get_stateful()
local breached_wall = Public.get('breached_wall')
local wave_number = WD.get('wave_number')
local supplies = stateful.objectives.supplies
local single_item = stateful.objectives.single_item
local callback_token = stateful.objectives.locomotive_market_selection[1]
local callback_data = stateful.objectives.locomotive_market_selection[2]
local callback_locomotive = Token.get(callback_token)
local locomotive_completed, _, locale_right = callback_locomotive(callback_data)
for i = 1, #players do
local player = players[i]
local f = player.gui.screen[main_frame_name]
local data = Gui.get_data(f)
if data then
if data.rounds_survived and data.rounds_survived.valid then
data.rounds_survived.caption = stateful.rounds_survived
end
if data.randomized_zone_label and data.randomized_zone_label.valid then
breached_wall = breached_wall - 1
if breached_wall >= stateful.objectives.randomized_zone then
data.randomized_zone_label.caption = breached_wall .. '/' .. stateful.objectives.randomized_zone .. ' [img=utility/check_mark_green]'
if not stateful.objectives_completed.randomized_zone_label then
stateful.objectives_completed.randomized_zone_label = true
play_game_won_sound()
end
else
data.randomized_zone_label.caption = breached_wall .. '/' .. stateful.objectives.randomized_zone .. ' [img=utility/not_available]'
end
end
if data.randomized_wave_label and data.randomized_wave_label.valid then
if wave_number >= stateful.objectives.randomized_wave then
data.randomized_wave_label.caption = wave_number .. '/' .. stateful.objectives.randomized_wave .. ' [img=utility/check_mark_green]'
if not stateful.objectives_completed.randomized_wave_label then
stateful.objectives_completed.randomized_wave_label = true
play_game_won_sound()
end
else
data.randomized_wave_label.caption = wave_number .. '/' .. stateful.objectives.randomized_wave .. ' [img=utility/not_available]'
end
end
if data.supply and next(data.supply) then
local items_done = 0
for index = 1, #data.supply do
local frame = data.supply[index]
if frame and frame.valid then
local supplies_data = supplies[index]
if supplies_data.count == 0 then
items_done = items_done + 1
frame.number = nil
frame.sprite = 'utility/check_mark_green'
else
frame.number = supplies_data.count
end
if items_done == 3 then
if data.supply_completed and data.supply_completed.valid then
data.supply_completed.caption = ' [img=utility/check_mark_green]'
if not stateful.objectives_completed.supplies then
stateful.objectives_completed.supplies = true
play_game_won_sound()
end
end
end
end
end
end
if data.single_item and data.single_item.valid then
local frame = data.single_item
if single_item.count == 0 then
frame.number = nil
frame.sprite = 'utility/check_mark_green'
if not stateful.objectives_completed.single_item then
stateful.objectives_completed.single_item = true
play_game_won_sound()
end
else
frame.number = single_item.count
end
end
if data.locomotive_market and data.locomotive_market.valid then
data.locomotive_market.caption = locale_right
if locomotive_completed and not stateful.objectives_completed.locomotive_market then
stateful.objectives_completed.locomotive_market = true
play_game_won_sound()
end
end
if data.random_objectives and next(data.random_objectives) then
for index = 1, #data.random_objectives do
local frame_data = data.random_objectives[index]
local name = frame_data.name
local frame = frame_data.frame
for objective_index = 1, #stateful.selected_objectives do
local objective = stateful.selected_objectives[objective_index]
local objective_name = objective[1]
local callback = Token.get(objective[2])
local completed, _, objective_locale_right = callback()
if name == objective_name and frame and frame.valid then
frame.caption = objective_locale_right
if completed and not stateful.objectives_completed[objective_name] then
stateful.objectives_completed[objective_name] = true
play_game_won_sound()
end
end
end
end
end
end
end
end
local function update_raw()
local stateful = Public.get_stateful()
local breached_wall = Public.get('breached_wall')
local wave_number = WD.get('wave_number')
local supplies = stateful.objectives.supplies
local single_item = stateful.objectives.single_item
local callback_token = stateful.objectives.locomotive_market_selection[1]
local callback_data = stateful.objectives.locomotive_market_selection[2]
local callback_locomotive = Token.get(callback_token)
local locomotive_completed, _, _ = callback_locomotive(callback_data)
breached_wall = breached_wall - 1
if breached_wall >= stateful.objectives.randomized_zone then
if not stateful.objectives_completed.randomized_zone_label then
stateful.objectives_completed.randomized_zone_label = true
play_game_won_sound()
stateful.objectives_completed_count = stateful.objectives_completed_count + 1
end
end
if wave_number >= stateful.objectives.randomized_wave then
if not stateful.objectives_completed.randomized_wave_label then
stateful.objectives_completed.randomized_wave_label = true
play_game_won_sound()
stateful.objectives_completed_count = stateful.objectives_completed_count + 1
end
end
if supplies and next(supplies) then
local items_done = 0
for index = 1, #supplies do
local supplies_data = supplies[index]
if supplies_data.count == 0 then
items_done = items_done + 1
end
if items_done == 3 then
if not stateful.objectives_completed.supplies then
stateful.objectives_completed.supplies = true
play_game_won_sound()
stateful.objectives_completed_count = stateful.objectives_completed_count + 1
end
end
end
end
if single_item and single_item.count == 0 then
if not stateful.objectives_completed.single_item then
stateful.objectives_completed.single_item = true
play_game_won_sound()
stateful.objectives_completed_count = stateful.objectives_completed_count + 1
end
end
if locomotive_completed then
if not stateful.objectives_completed.locomotive_market then
stateful.objectives_completed.locomotive_market = true
play_game_won_sound()
stateful.objectives_completed_count = stateful.objectives_completed_count + 1
end
end
for objective_index = 1, #stateful.selected_objectives do
local objective = stateful.selected_objectives[objective_index]
local objective_name = objective[1]
local callback = Token.get(objective[2])
local completed, _, _ = callback()
if completed and completed == true and not stateful.objectives_completed[objective_name] then
stateful.objectives_completed[objective_name] = true
play_game_won_sound()
stateful.objectives_completed_count = stateful.objectives_completed_count + 1
end
end
end
local function main_frame(player)
local main_player_frame = player.gui.screen[main_frame_name]
if main_player_frame then
Gui.remove_data_recursively(main_player_frame)
main_player_frame.destroy()
return
end
local data = {}
local stateful = Public.get_stateful()
local breached_wall = Public.get('breached_wall')
breached_wall = breached_wall - 1
local wave_number = WD.get('wave_number')
local frame = player.gui.screen.add {type = 'frame', name = main_frame_name, caption = {'stateful.win_conditions'}, direction = 'vertical'}
frame.location = {x = 1, y = 45}
frame.style.maximal_height = 500
frame.style.minimal_width = 200
frame.style.maximal_width = 400
local rounds_survived_tbl = frame.add {type = 'table', column_count = 2}
rounds_survived_tbl.style.horizontally_stretchable = true
local rounds_survived_left_flow = rounds_survived_tbl.add({type = 'flow'})
rounds_survived_left_flow.style.horizontal_align = 'left'
rounds_survived_left_flow.style.horizontally_stretchable = true
rounds_survived_left_flow.add({type = 'label', caption = {'stateful.rounds_survived'}})
frame.add({type = 'line', direction = 'vertical'})
local rounds_survived_right_flow = rounds_survived_tbl.add({type = 'flow'})
rounds_survived_right_flow.style.horizontal_align = 'right'
rounds_survived_right_flow.style.horizontally_stretchable = true
data.rounds_survived_label = rounds_survived_right_flow.add({type = 'label', caption = stateful.rounds_survived})
spacer(frame)
frame.add({type = 'line'})
spacer(frame)
local objective_tbl = frame.add {type = 'table', column_count = 2}
objective_tbl.style.horizontally_stretchable = true
local zone_left_flow = objective_tbl.add({type = 'flow'})
zone_left_flow.style.horizontal_align = 'left'
zone_left_flow.style.horizontally_stretchable = true
zone_left_flow.add({type = 'label', caption = {'stateful.zone'}})
frame.add({type = 'line', direction = 'vertical'})
local zone_right_flow = objective_tbl.add({type = 'flow'})
zone_right_flow.style.horizontal_align = 'right'
zone_right_flow.style.horizontally_stretchable = true
if breached_wall >= stateful.objectives.randomized_zone then
data.randomized_zone_label = zone_right_flow.add({type = 'label', caption = breached_wall .. '/' .. stateful.objectives.randomized_zone .. ' [img=utility/check_mark_green]'})
else
data.randomized_zone_label = zone_right_flow.add({type = 'label', caption = breached_wall .. '/' .. stateful.objectives.randomized_zone .. ' [img=utility/not_available]'})
end
-- new frame
local wave_left_flow = objective_tbl.add({type = 'flow'})
wave_left_flow.style.horizontal_align = 'left'
wave_left_flow.style.horizontally_stretchable = true
wave_left_flow.add({type = 'label', caption = {'stateful.wave'}})
frame.add({type = 'line', direction = 'vertical'})
local wave_right_flow = objective_tbl.add({type = 'flow'})
wave_right_flow.style.horizontal_align = 'right'
wave_right_flow.style.horizontally_stretchable = true
if wave_number >= stateful.objectives.randomized_wave then
data.randomized_wave_label = wave_right_flow.add({type = 'label', caption = wave_number .. '/' .. stateful.objectives.randomized_wave .. ' [img=utility/check_mark_green]'})
else
local randomized_wave = wave_right_flow.add({type = 'label', caption = wave_number .. '/' .. stateful.objectives.randomized_wave .. ' [img=utility/not_available]'})
data.randomized_wave_label = randomized_wave
end
--dynamic conditions
for index = 1, #stateful.selected_objectives do
local objective = stateful.selected_objectives[index]
objective_frames(stateful, frame, objective, data)
end
-- warn players
spacer(frame)
frame.add({type = 'line'})
spacer(frame)
local final_label = frame.add({type = 'label', caption = {'stateful.tooltip_final'}})
final_label.style.single_line = false
spacer(frame)
frame.add({type = 'line'})
spacer(frame)
local close = frame.add({type = 'button', name = close_button, caption = 'Close'})
close.style.horizontally_stretchable = true
Gui.set_data(frame, data)
-- update_world_gui(player)
end
local function on_player_joined_game(event)
local player = game.players[event.player_index]
if not player then
return
end
if not player.gui.top[main_button_name] then
create_button(player)
end
end
Gui.on_click(
main_button_name,
function(event)
local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Mtn v3 stateful Button')
if is_spamming then
return
end
local player = event.player
if not player or not player.valid then
return
end
local frame = player.gui.screen[main_frame_name]
if player.character and player.character.valid then
if frame then
Gui.remove_data_recursively(frame)
frame.destroy()
else
Gui.clear_all_active_frames(player)
main_frame(player)
end
end
end
)
Gui.on_click(
close_button,
function(event)
local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Mtn v3 stateful Button')
if is_spamming then
return
end
local player = event.player
if not player or not player.valid then
return
end
local frame = player.gui.screen[main_frame_name]
if frame then
Gui.remove_data_recursively(frame)
frame.destroy()
end
end
)
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
Event.on_nth_tick(60, update_data)
Event.on_nth_tick(120, update_raw)
return Public

View File

@ -0,0 +1,56 @@
local Public = require 'maps.mountain_fortress_v3.stateful.table'
local Event = require 'utils.event'
local WD = require 'modules.wave_defense.table'
Public.stateful_gui = require 'maps.mountain_fortress_v3.stateful.gui'
Public.stateful_terrain = require 'maps.mountain_fortress_v3.stateful.terrain'
Public.stateful_generate = require 'maps.mountain_fortress_v3.stateful.generate'
Public.stateful_blueprints = require 'maps.mountain_fortress_v3.stateful.blueprints'
local random = math.random
local shuffle = table.shuffle_table
Event.add(
defines.events.on_research_finished,
function(event)
local research = event.research
if not research then
return
end
local name = research.name
local objectives = Public.get_stateful('objectives')
if not objectives then
return
end
if name == objectives.research_level_selection then
objectives.research_level_count = objectives.research_level_count + 1
end
end
)
Event.on_nth_tick(
200,
function()
local final_battle = Public.get_stateful('final_battle')
if not final_battle then
return
end
Public.set('final_battle', true)
Public.allocate()
local spawn_positions = Public.stateful_spawn_points
local sizeof = Public.sizeof_stateful_spawn_points
local area = spawn_positions[random(1, sizeof)]
shuffle(area)
WD.set_spawn_position(area[1])
Event.raise(WD.events.on_spawn_unit_group, {fs = true, bypass = true})
end
)
return Public

View File

@ -0,0 +1,523 @@
local Global = require 'utils.global'
local Event = require 'utils.event'
local Server = require 'utils.server'
local Token = require 'utils.token'
local shuffle = table.shuffle_table
local WD = require 'modules.wave_defense.table'
local format_number = require 'util'.format_number
local ICW = require 'maps.mountain_fortress_v3.icw.main'
local Core = require 'utils.core'
local Public = require 'maps.mountain_fortress_v3.table'
local this = {
enabled = false,
rounds_survived = 0
}
local random = math.random
local floor = math.floor
local dataset = 'scenario_settings'
local dataset_key = 'mtn_v3'
Global.register(
this,
function(tbl)
this = tbl
end
)
local stateful_spawn_points = {
{{x = -186, y = -170}, {x = 177, y = 119}},
{{x = -190, y = -200}, {x = 160, y = -160}},
{{x = -190, y = -0}, {x = 160, y = -0}},
{{x = -186, y = -170}, {x = 177, y = 119}},
{{x = -160, y = -200}, {x = 160, y = -160}},
{{x = 160, y = -200}, {x = 190, y = -160}},
{{x = 160, y = 0}, {x = 190, y = 0}},
{{x = -186, y = -170}, {x = 177, y = 119}},
{{x = 160, y = -160}, {x = 190, y = 160}},
{{x = 160, y = 160}, {x = 190, y = 200}},
{{x = -160, y = 160}, {x = 160, y = 200}},
{{x = -190, y = 160}, {x = -160, y = 200}},
{{x = -190, y = -160}, {x = -160, y = 160}}
}
local disabled_items = {
['landfill'] = true,
['spidertron'] = true,
['fluid-wagon'] = true,
['cliff-explosives'] = true,
['atomic-bomb'] = true,
['land-mine'] = true,
['loader'] = true,
['fast-loader'] = true,
['express-loader'] = true
}
local function get_item_produced_count(item_name)
local force = game.forces.player
local production = force.item_production_statistics.input_counts[item_name]
if not production then
return false
end
return production
end
local function get_entity_mined_count(item_name)
local force = game.forces.player
local count = 0
for name, entity_count in pairs(force.entity_build_count_statistics.output_counts) do
if name:find(item_name) then
count = count + entity_count
end
end
return count
end
local function get_killed_enemies_count(primary, secondary)
local force = game.forces.player
local count = 0
for name, entity_count in pairs(force.kill_count_statistics.input_counts) do
if name:find(primary) or name:find(secondary) then
count = count + entity_count
end
end
return count
end
local apply_settings =
Token.register(
function(data)
local settings = data and data.value or nil
if not settings then
return
end
Server.set_data(dataset, dataset_key, settings)
end
)
local locomotive_market_pickaxe_token =
Token.register(
function(count)
local upgrades = Public.get('upgrades')
if upgrades.pickaxe_tier >= count then
return true, {'stateful.locomotive_market_pickaxe'}, {'stateful.done', count, count}
end
return false, {'stateful.locomotive_market_pickaxe'}, {'stateful.not_done', upgrades.pickaxe_tier, count}
end
)
local locomotive_market_health_token =
Token.register(
function(count)
local upgrades = Public.get('upgrades')
if upgrades.health_upgrades >= count then
return true, {'stateful.locomotive_market_health'}, {'stateful.done', count, count}
end
return false, {'stateful.locomotive_market_health'}, {'stateful.not_done', upgrades.health_upgrades, count}
end
)
local locomotive_market_xp_points_token =
Token.register(
function(count)
local upgrades = Public.get('upgrades')
if upgrades.xp_points_upgrade >= count then
return true, {'stateful.locomotive_market_xp_points'}, {'stateful.done', count, count}
end
return false, {'stateful.locomotive_market_xp_points'}, {'stateful.not_done', upgrades.xp_points_upgrade, count}
end
)
local empty_token =
Token.register(
function()
return false
end
)
local killed_enemies_token =
Token.register(
function()
local enemies_killed = Public.get_killed_enemies_count('biter', 'spitter')
if enemies_killed >= this.objectives.killed_enemies then
return true, {'stateful.enemies_killed'}, {'stateful.done', format_number(this.objectives.killed_enemies, true), format_number(this.objectives.killed_enemies)}
end
return false, {'stateful.enemies_killed'}, {'stateful.not_done', format_number(enemies_killed, true), format_number(this.objectives.killed_enemies, true)}
end
)
local complete_mystical_chest_amount_token =
Token.register(
function()
local mystical_chest_completed = Public.get('mystical_chest_completed')
if mystical_chest_completed >= this.objectives.complete_mystical_chest_amount then
return true, {'stateful.mystical_chest'}, {'stateful.done', this.objectives.complete_mystical_chest_amount, this.objectives.complete_mystical_chest_amount}
end
return false, {'stateful.mystical_chest'}, {'stateful.not_done', mystical_chest_completed, this.objectives.complete_mystical_chest_amount}
end
)
local research_level_selection_token =
Token.register(
function()
local actual = this.objectives.research_level_count
local expected = this.objectives.research_level_selection.count
if actual >= expected then
return true, {'stateful.research', this.objectives.research_level_selection.name}, {'stateful.done', expected, expected}
end
return false, {'stateful.research', this.objectives.research_level_selection.name}, {'stateful.not_done', actual, expected}
end
)
local trees_farmed_token =
Token.register(
function()
local trees = get_entity_mined_count('tree')
if trees >= this.objectives.trees_farmed then
return true, {'stateful.trees_mined'}, {'stateful.done', format_number(this.objectives.trees_farmed, true), format_number(this.objectives.trees_farmed, true)}
end
return false, {'stateful.trees_mined'}, {'stateful.not_done', format_number(trees, true), format_number(this.objectives.trees_farmed, true)}
end
)
local rocks_farmed_token =
Token.register(
function()
local rocks = get_entity_mined_count('rock')
if rocks >= this.objectives.rocks_farmed then
return true, {'stateful.rocks_mined'}, {'stateful.done', format_number(this.objectives.rocks_farmed, true), format_number(this.objectives.rocks_farmed, true)}
end
return false, {'stateful.rocks_mined'}, {'stateful.not_done', format_number(rocks, true), format_number(this.objectives.rocks_farmed, true)}
end
)
local rockets_launched_token =
Token.register(
function()
local launched = game.forces.player.rockets_launched
if launched >= this.objectives.rockets_launched then
return true, {'stateful.launch_rockets'}, {'stateful.done', format_number(this.objectives.rockets_launched, true), format_number(this.objectives.rockets_launched, true)}
end
return false, {'stateful.launch_rockets'}, {'stateful.not_done', format_number(launched, true), format_number(this.objectives.rockets_launched, true)}
end
)
local function scale(setting, limit)
local factor = 1.2
local scale_value = floor(setting * (factor ^ this.rounds_survived))
if limit and scale_value >= limit then
return limit
end
return scale_value
end
local function get_random_items()
local recipes = game.forces.player.recipes
local items = {}
local i = 0
for _, recipe in pairs(recipes) do
if recipe.prototype.energy > 6 and not disabled_items[recipe.name] then
items[i] = recipe
i = i + 1
end
end
shuffle(items)
local container = {
[1] = {name = items[1].products[1].name, count = scale(random(100, 5000))},
[2] = {name = items[2].products[1].name, count = scale(random(100, 5000))},
[3] = {name = items[3].products[1].name, count = scale(random(100, 5000))}
}
return container
end
local function get_random_item()
local recipes = game.forces.player.recipes
local items = {}
local i = 0
for _, recipe in pairs(recipes) do
if recipe.prototype.energy > 1 and not disabled_items[recipe.name] then
items[i] = recipe
i = i + 1
end
end
shuffle(items)
shuffle(items)
return {name = items[10].products[1].name, count = scale(random(5000, 100000), 40000000)}
end
local function get_random_research_recipe()
-- scale(10, 20)
local research_level_list = {
'energy-weapons-damage-7',
'physical-projectile-damage-7',
'refined-flammables-7',
'stronger-explosives-7',
'mining-productivity-4',
'worker-robots-speed-6',
'follower-robot-count-7'
}
shuffle(research_level_list)
return {name = research_level_list[1], count = scale(random(10, 20), 40)}
end
local function get_random_locomotive_tier()
local tiers = {
'pickaxe',
'health',
'xp_point'
}
shuffle(tiers)
local pickaxe_count = scale(random(10, 20), 59)
local health_count = scale(random(10, 40), 100)
local xp_points_count = scale(random(10, 40), 100)
if tiers[1] == 'pickaxe' then
return {
locomotive_market_pickaxe_token,
pickaxe_count
}
end
if tiers[1] == 'health' then
return {
locomotive_market_health_token,
health_count
}
end
if tiers[1] == 'xp_point' then
return {
locomotive_market_xp_points_token,
xp_points_count
}
end
end
local function get_random_objectives()
local items = {
{
'supplies',
empty_token
},
{
'single_item',
empty_token
},
{
'killed_enemies',
killed_enemies_token
},
{
'complete_mystical_chest_amount',
complete_mystical_chest_amount_token
},
{
'research_level_selection',
research_level_selection_token
},
{
'locomotive_market_selection',
empty_token
},
{
'trees_farmed',
trees_farmed_token
},
{
'rocks_farmed',
rocks_farmed_token
},
{
'rockets_launched',
rockets_launched_token
}
}
shuffle(items)
return {
items[1],
items[2],
items[3]
}
end
function Public.reset_stateful()
this.objectives_completed = {}
this.objectives_completed_count = 0
this.final_battle = false
this.selected_objectives = get_random_objectives()
this.objectives = {
randomized_zone = scale(random(7, 20), 40),
randomized_wave = scale(random(500, 2000), 4000),
supplies = get_random_items(),
single_item = get_random_item(),
killed_enemies = scale(random(500000, 3000000), 10000000),
complete_mystical_chest_amount = scale(random(10, 50), 500),
research_level_selection = get_random_research_recipe(),
research_level_count = 0,
locomotive_market_selection = get_random_locomotive_tier(),
trees_farmed = scale(random(5000, 100000), 400000),
rocks_farmed = scale(random(50000, 500000), 4000000),
rockets_launched = scale(random(100, 500), 5000)
}
this.force_chunk = true
end
function Public.migrate_and_create(locomotive)
local carriages = Public.get('carriages')
local surface = game.get_surface('boss_room')
local position = locomotive.position
for _, entity in pairs(carriages) do
if entity and entity.valid and entity.unit_number ~= locomotive.unit_number then
local new_position = {x = position.x, y = position.y + 5}
local new_wagon = surface.create_entity({name = entity.name, position = new_position, force = 'player', defines.direction.north})
if new_wagon and new_wagon.valid then
position = new_position
ICW.migrate_wagon(entity, new_wagon)
end
end
end
end
function Public.move_all_players()
local market = Public.get('market')
if not market or not market.valid then
return
end
local surface = market.surface
Core.iter_connected_players(
function(player)
local pos = surface.find_non_colliding_position('character', market.position, 3, 0, 5)
if pos then
player.teleport(pos, surface)
else
pos = market.position
player.teleport(pos, surface)
Public.unstuck(player.index)
end
end
)
end
function Public.allocate()
local stateful_locomotive = Public.get_stateful('stateful_locomotive')
local stateful_locomotive_migrated = Public.get_stateful('stateful_locomotive_migrated')
if stateful_locomotive and not stateful_locomotive_migrated then
-- Public.move_all_players()
Public.set_stateful('stateful_locomotive_migrated', true)
local locomotive = Public.get('locomotive')
local icw_data = ICW.migrate_wagon(locomotive, stateful_locomotive)
local surface = game.get_surface('boss_room')
Public.set_target(stateful_locomotive, icw_data)
game.forces.player.chart(surface, {{-358, -151}, {358, 151}})
Public.migrate_and_create(stateful_locomotive)
end
end
function Public.set_target(target, icw_data)
Public.set('locomotive', target)
local wave_defense_table = WD.get()
wave_defense_table.surface_index = game.get_surface('boss_room').index
wave_defense_table.target = target
wave_defense_table.spawn_position = {x = -206, y = -80}
Public.set('active_surface_index', game.get_surface('boss_room').index)
Public.set('icw_locomotive', icw_data)
Public.render_train_hp()
end
function Public.increase_enemy_damage_and_health()
if this.rounds_survived == 1 then
Event.raise(WD.events.on_biters_evolved, {})
else
for _ = 1, this.rounds_survived do
Event.raise(WD.events.on_biters_evolved, {})
end
end
end
function Public.get_stateful(key)
if key then
return this[key]
else
return this
end
end
function Public.set_stateful(key, value)
if key and (value or value == false) then
this[key] = value
return this[key]
elseif key then
return this[key]
else
return this
end
end
function Public.remove_stateful(key, sub_key)
if key and sub_key then
if this[key] and this[key][sub_key] then
this[key][sub_key] = nil
end
elseif key then
if this[key] then
this[key] = nil
end
end
end
function Public.enable(state)
this.enabled = state or false
end
Event.on_init(Public.reset_stateful)
Event.add(
Server.events.on_server_started,
function()
if this.settings_applied then
return
end
this.settings_applied = true
Public.increase_enemy_damage_and_health()
Server.try_get_data(dataset, dataset_key, apply_settings)
end
)
Public.get_item_produced_count = get_item_produced_count
Public.get_entity_mined_count = get_entity_mined_count
Public.get_killed_enemies_count = get_killed_enemies_count
Public.stateful_spawn_points = stateful_spawn_points
Public.sizeof_stateful_spawn_points = #stateful_spawn_points
return Public

View File

@ -0,0 +1,241 @@
local Public = require 'maps.mountain_fortress_v3.stateful.table'
local map_name = 'boss_room'
local random = math.random
local ceil = math.ceil
local floor = math.floor
local Token = require 'utils.token'
local assign_locomotive_token =
Token.register(
function(event)
local entity = event.entity
if not entity or not entity.valid then
return
end
entity.get_inventory(defines.inventory.fuel).insert({name = 'wood', count = 100})
for y = -1, 0, 0.05 do
local scale = random(50, 100) * 0.01
rendering.draw_sprite(
{
sprite = 'entity/small-biter',
orientation = random(0, 100) * 0.01,
x_scale = scale,
y_scale = scale,
tint = {random(60, 255), random(60, 255), random(60, 255)},
render_layer = 'selection-box',
target = entity,
target_offset = {-0.7 + random(0, 140) * 0.01, y},
surface = entity.surface
}
)
end
rendering.draw_light(
{
sprite = 'utility/light_medium',
scale = 5.5,
intensity = 1,
minimum_darkness = 0,
oriented = true,
color = {255, 255, 255},
target = entity,
surface = entity.surface,
visible = true,
only_in_alt_mode = false
}
)
entity.color = {random(2, 255), random(60, 255), random(60, 255)}
Public.set_stateful('stateful_locomotive', entity)
entity.minable = false
end
)
local start_ground_tiles = {
'grass-1',
'grass-1',
'grass-2',
'sand-2',
'grass-1',
'grass-4',
'sand-2',
'grass-3',
'grass-4',
'grass-2',
'sand-3',
'grass-4'
}
local mud_tiles = {
'water-mud',
'water-shallow',
'water-mud',
'water-shallow',
'water-mud',
'water-shallow',
'water-mud',
'water-shallow',
'water-mud',
'water-shallow'
}
local tree_raffle = {
'dry-tree',
'tree-01',
'tree-02-red',
'tree-04',
'tree-08-brown'
}
local size_of_tree_raffle = #tree_raffle
local function is_out_of_map(p)
if p.x < 512 and p.x >= -512 then
return
end
if p.y < 512 and p.y >= -512 then
return
end
return true
end
local function void_tiles(p)
if p.y > 480 then
return false
end
if p.y < 160 and p.y >= -160 then
return false
end
return true
end
local function enemy_spawn_positions(p)
if p.x < 200 and p.x >= -212 then
return false
end
return true
end
local function draw_rails(data)
local entities = data.entities
local y = data.yv
-- for y = 0, 30, 2 do
entities[#entities + 1] = {name = 'straight-rail', position = {0, data.top_y + y}, direction = defines.direction.north, force = 'player'}
-- end
if data.top_y == -32 then
entities[#entities + 1] = {name = 'locomotive', position = {0, -24}, force = 'player', direction = defines.direction.north, callback = assign_locomotive_token}
end
end
local function border_chunk(p, data)
local decoratives = data.decoratives
local tiles = data.tiles
local entities = data.entities
local pos = p
if pos.y == 0 or pos.y > 0 then
if random(1, ceil(pos.y + pos.y) + 64) == 1 then
entities[#entities + 1] = {name = tree_raffle[random(1, size_of_tree_raffle)], position = pos, collision = true}
end
else
if random(ceil(pos.y - pos.y) - 64, -1) == -1 then
entities[#entities + 1] = {name = tree_raffle[random(1, size_of_tree_raffle)], position = pos, collision = true}
end
end
local noise = Public.get_noise('dungeon_sewer', pos, data.seed)
local index = floor(noise * 32) % 11 + 1
tiles[#tiles + 1] = {name = start_ground_tiles[index], position = pos}
if random(1, 128) == 1 then
local name = 'biter-spawner'
if random(1, 4) == 1 then
name = 'spitter-spawner'
end
if enemy_spawn_positions(p) then
entities[#entities + 1] = {name = name, position = pos, force = 'enemy', collision = true, active = false}
end
end
if not is_out_of_map(pos) then
if pos.y == 0 or pos.y >= 0 then
if random(1, pos.y + 2) == 1 then
decoratives[#decoratives + 1] = {
name = 'rock-small',
position = pos,
amount = random(1, 32)
}
end
if random(1, pos.y + 2) == 1 then
decoratives[#decoratives + 1] = {
name = 'rock-tiny',
position = pos,
amount = random(1, 32)
}
end
else
if random(pos.y - 2, -1) == -1 then
decoratives[#decoratives + 1] = {
name = 'rock-small',
position = pos,
amount = random(1, 32)
}
end
if random(pos.y - 2, -1) == -1 then
decoratives[#decoratives + 1] = {
name = 'rock-tiny',
position = pos,
amount = random(1, 32)
}
end
end
end
end
local function oozy_tiles(p, seed, tiles)
local noise = Public.get_noise('no_rocks_2', p, seed)
local index = floor(noise * 32) % 9 + 1
if noise < -0.3 then
local noise_cave_ponds = Public.get_noise('cave_ponds', p, seed)
local small_caves = Public.get_noise('small_caves', p, seed)
if noise_cave_ponds < 0.45 and noise_cave_ponds > -0.45 then
if small_caves > 0.45 then
tiles[#tiles + 1] = {name = 'out-of-map', position = p}
return
end
if small_caves < -0.45 then
tiles[#tiles + 1] = {name = mud_tiles[index], position = p}
return
end
end
end
end
function Public.heavy_functions(data)
local surface = data.surface
local p = data.position
local get_tile = surface.get_tile(p)
if string.sub(surface.name, 0, #map_name) ~= map_name then
return
end
if not data.seed then
data.seed = surface.map_gen_settings.seed
end
if get_tile.valid and get_tile.name == 'out-of-map' then
return
end
if void_tiles(p) then
data.tiles[#data.tiles + 1] = {name = 'out-of-map', position = p}
return
end
border_chunk(p, data)
oozy_tiles(p, data.seed, data.tiles)
draw_rails(data)
end
return Public

View File

@ -173,6 +173,7 @@ function Public.reset_main_table()
}
this.pickaxe_speed_per_purchase = 0.07
this.breached_wall = 1
this.final_battle = false
this.left_top = {
x = 0,
y = 0
@ -247,6 +248,7 @@ function Public.reset_main_table()
this.market_announce = game.tick + 1200
this.check_heavy_damage = true
this.prestige_system_enabled = false
this.mystical_chest_completed = 0
this.mystical_chest_enabled = true
this.check_if_threat_below_zero = true
this.mc_rewards = {

View File

@ -2801,18 +2801,18 @@ end
function Public.heavy_functions(data)
local top_y = data.top_y
local surface = data.surface
local p = data.position
local get_tile = surface.get_tile(p)
local adjusted_zones = Public.get('adjusted_zones')
init_terrain(adjusted_zones)
local map_name = 'mtn_v3'
if string.sub(surface.name, 0, #map_name) ~= map_name then
return
end
local p = data.position
local get_tile = surface.get_tile(p)
local adjusted_zones = Public.get('adjusted_zones')
init_terrain(adjusted_zones)
if not data.seed then
data.seed = Public.get('random_seed')
end