diff --git a/control.lua b/control.lua index 0db937a5..cdad477a 100644 --- a/control.lua +++ b/control.lua @@ -25,6 +25,7 @@ require "modules.floaty_chat" ---- enable modules here ---- --require "tools.cheat_mode" --require "modules.the_floor_is_lava" +--require "modules.biters_landfill_on_death" --require "modules.autodecon_when_depleted" --require "modules.biter_noms_you" --require "modules.biters_avoid_damage" @@ -51,19 +52,21 @@ require "modules.floaty_chat" --require "modules.surrounded_by_worms" --require "modules.more_attacks" --require "modules.evolution_extended" +--require "modules.shopping_chests" ----------------------------- ---- enable maps here ---- +--require "maps.fish_defender.main" +--require "maps.biter_battles_v2.biter_battles_v2" +require "maps.island_troopers.main" --require "maps.tank_conquest.tank_conquest" --require "maps.territorial_control" --require "maps.cave_choppy.cave_miner" ---require "maps.biter_battles_v2.biter_battles_v2" --require "maps.biter_battles.biter_battles" ---require "maps.fish_defender.fish_defender" --require "maps.wave_of_death.WoD" --require "maps.stone_maze.main" --require "maps.overgrowth" -require "maps.tetris.main" +--require "maps.tetris.main" --require "maps.maze_challenge" --require "maps.cave_miner" --require "maps.rocky_waste" diff --git a/maps/island_troopers/enemies.lua b/maps/island_troopers/enemies.lua index 6efdf457..b9f64a9f 100644 --- a/maps/island_troopers/enemies.lua +++ b/maps/island_troopers/enemies.lua @@ -1,3 +1,13 @@ +local difficulties_votes = { + [1] = {amount_modifier = 0.52, strength_modifier = 0.40, boss_modifier = 0.7}, + [2] = {amount_modifier = 0.76, strength_modifier = 0.65, boss_modifier = 0.8}, + [3] = {amount_modifier = 0.92, strength_modifier = 0.85, boss_modifier = 0.9}, + [4] = {amount_modifier = 1.00, strength_modifier = 1.00, boss_modifier = 1.0}, + [5] = {amount_modifier = 1.16, strength_modifier = 1.25, boss_modifier = 1.1}, + [6] = {amount_modifier = 1.48, strength_modifier = 1.75, boss_modifier = 1.2}, + [7] = {amount_modifier = 2.12, strength_modifier = 2.50, boss_modifier = 1.3} +} + function get_biter() local max_chance = 0 for k, v in pairs(global.biter_chances) do @@ -11,6 +21,19 @@ function get_biter() end end +function get_worm() + local max_chance = 0 + for k, v in pairs(global.worm_chances) do + max_chance = max_chance + v + end + local r = math.random(1, max_chance) + local current_chance = 0 + for k, v in pairs(global.worm_chances) do + current_chance = current_chance + v + if r <= current_chance then return k end + end +end + function set_biter_chances(level) global.biter_chances = { ["small-biter"] = 1000 - level * 10, @@ -33,4 +56,84 @@ function set_biter_chances(level) for k, v in pairs(global.biter_chances) do if global.biter_chances[k] < 0 then global.biter_chances[k] = 0 end end +end + +function set_worm_chances(level) + global.worm_chances = { + ["small-worm-turret"] = 1000 - level * 10, + ["medium-worm-turret"] = level * 10, + ["big-worm-turret"] = 0, + ["behemoth-worm-turret"] = 0, + } + if level > 100 then + global.worm_chances["big-worm-turret"] = (level - 100) * 25 + global.worm_chances["big-worm-turret"] = (level - 100) * 25 + end + if level > 200 then + global.worm_chances["behemoth-worm-turret"] = (level - 200) * 50 + global.worm_chances["behemoth-worm-turret"] = (level - 200) * 50 + end + for k, v in pairs(global.worm_chances) do + if global.worm_chances[k] < 0 then global.worm_chances[k] = 0 end + end +end + + +local function is_boss_stage() + if global.current_stage == 1 then return false end + if global.current_stage % 5 == 0 then return true end + if global.current_stage == #global.stages - 1 then return true end +end + +function add_enemies(surface, tiles) + table.shuffle_table(tiles) + + if is_boss_stage() then + set_biter_chances(global.current_level + 100) + local boss_count = math.random(1, math.floor(global.current_level * 0.5) + 1) + if boss_count > 16 then boss_count = 16 end + for k, tile in pairs(tiles) do + if surface.can_place_entity({name = "small-biter", position = tile.position, force = "enemy"}) then + local unit = surface.create_entity({name = get_biter(), position = tile.position, force = "enemy"}) + unit.ai_settings.allow_destroy_when_commands_fail = false + unit.ai_settings.allow_try_return_to_spawner = false + add_boss_unit(unit, global.current_level * difficulties_votes[global.difficulty_vote_index].boss_modifier, 0.55) + global.alive_boss_enemy_count = global.alive_boss_enemy_count + 1 + global.alive_boss_enemy_entities[unit.unit_number] = unit + global.alive_enemies = global.alive_enemies + 1 + boss_count = boss_count - 1 + if boss_count == 0 then break end + end + end + end + + if math.random(1, 4) == 1 or is_boss_stage() then + set_worm_chances(global.current_level) + local worm_count = math.random(1, global.current_level) + if worm_count > 32 then worm_count = 32 end + for k, tile in pairs(tiles) do + if surface.can_place_entity({name = "big-worm-turret", position = tile.position, force = "enemy"}) then + surface.create_entity({name = get_worm(), position = tile.position, force = "enemy"}) + global.alive_enemies = global.alive_enemies + 1 + worm_count = worm_count - 1 + if worm_count == 0 then break end + end + end + end + + set_biter_chances(global.current_level * difficulties_votes[global.difficulty_vote_index].strength_modifier) + local amount = ((global.current_level * 25) / #global.stages) * global.current_stage + amount = amount * difficulties_votes[global.difficulty_vote_index].amount_modifier + for k, tile in pairs(tiles) do + if surface.can_place_entity({name = "small-biter", position = tile.position, force = "enemy"}) then + local unit = surface.create_entity({name = get_biter(), position = tile.position, force = "enemy"}) + unit.ai_settings.allow_destroy_when_commands_fail = false + unit.ai_settings.allow_try_return_to_spawner = false + global.alive_enemies = global.alive_enemies + 1 + amount = amount - 1 + end + if amount <= 0 then break end + end + + update_stage_gui() end \ No newline at end of file diff --git a/maps/island_troopers/main.lua b/maps/island_troopers/main.lua index b5ef723d..fc733126 100644 --- a/maps/island_troopers/main.lua +++ b/maps/island_troopers/main.lua @@ -1,7 +1,9 @@ +require "maps.island_troopers.map_intro" require "functions.noise_vector_path" require "modules.shopping_chests" require "modules.no_turrets" require "modules.dangerous_goods" +require "modules.difficulty_vote" require "maps.island_troopers.enemies" require "maps.island_troopers.terrain" @@ -20,10 +22,13 @@ local function create_stage_gui(player) style.font = "default-large-bold" end -local function update_gui() +function update_stage_gui() local caption = "Level: " .. global.current_level - caption = caption .. " | Stage: " + caption = caption .. " | Stage: " caption = caption .. global.current_stage + caption = caption .. " | Bugs remaining: " + caption = caption .. global.alive_enemies + for _, player in pairs(game.connected_players) do if player.gui.top.stage_gui then player.gui.top.stage_gui.caption = caption @@ -56,8 +61,8 @@ local function set_next_level() global.path_tiles = nil - local island_size = 16 + math.random(global.current_level * 2, global.current_level * 5) - if island_size > 256 then island_size = 256 end + local island_size = 16 + math.random(global.current_level, global.current_level * 2) + if island_size > 128 then island_size = 128 end global.stages = {} global.stages[1] = { @@ -65,7 +70,7 @@ local function set_next_level() size = island_size, } - local stages_amount = global.current_level + 1 + local stages_amount = (global.current_level * 0.5) + 1 if stages_amount > 16 then stages_amount = 16 end for i = 1, stages_amount, 1 do global.stages[#global.stages + 1] = { @@ -78,14 +83,17 @@ local function set_next_level() size = false, } - game.print("Level " .. global.current_level) - update_gui() + --game.print("Level " .. global.current_level) + update_stage_gui() global.gamestate = 2 end local function earn_credits(amount) - game.print(amount .. " credits recieved!", {r = 255, g = 215, b = 0}) + for _, player in pairs(game.connected_players) do + player.play_sound{path="utility/new_objective", volume_modifier=0.5} + end + game.print(amount .. " credits have been transfered to the factory.", {r = 255, g = 215, b = 0}) global.credits = global.credits + amount end @@ -104,16 +112,16 @@ end local function wait_until_stage_is_beaten() if global.alive_enemies > 0 then return end if global.stages[global.current_stage].size then - earn_credits(global.current_stage * global.current_level * 100) + earn_credits(global.current_stage * global.current_level * 50) global.current_stage = global.current_stage + 1 global.gamestate = 2 - update_gui() + update_stage_gui() return end - earn_credits(global.current_stage * global.current_level * 100 * 2) - game.print("Level " .. global.current_level .. " complete!!") + earn_credits(global.current_stage * global.current_level * 100) + --game.print("Level " .. global.current_level .. " complete!!") global.gamestate = 5 - update_gui() + update_stage_gui() end local function on_player_joined_game(event) @@ -126,12 +134,13 @@ end local function on_init() local surface = game.surfaces[1] - surface.request_to_generate_chunks({x = 0, y = 0}, 8) + surface.request_to_generate_chunks({x = 0, y = 0}, 16) surface.force_generate_chunk_requests() + global.difficulty_poll_closing_timeout = 3600 * 5 global.level_vectors = {} global.alive_boss_enemy_entities = {} - global.current_level = 0 + global.current_level = 0 global.gamestate = 1 game.forces.player.set_spawn_position({0, 2}, surface) @@ -149,6 +158,7 @@ local function on_entity_died(event) if entity.force.name ~= "enemy" then return end global.alive_enemies = global.alive_enemies - 1 + update_stage_gui() if entity.type ~= "unit" then return end if not global.alive_boss_enemy_entities[entity.unit_number] then return end diff --git a/maps/island_troopers/map_intro.lua b/maps/island_troopers/map_intro.lua new file mode 100644 index 00000000..d6290425 --- /dev/null +++ b/maps/island_troopers/map_intro.lua @@ -0,0 +1,90 @@ +local event = require 'utils.event' + +local main_caption = " --Island Troopers-- " +local sub_caption = " " +local info = [[ + You are stranded on this coastal planet and your mission is to get out of here. + + The peaceful inhabitants live in the sea and are plagued by bugs. + They need your help! + + They will send you the bugs along with the seabed to the surface. + If you eliminate the bugs, you will receive credits as a thank-you for removing the bugs. + With the credits you can buy raw materials from requirement boxes. + These can already be found on the coast. + + Be careful! Over time, residents will send stronger bugs to the surface! +]] + +local function create_map_intro_button(player) + if player.gui.top["map_intro_button"] then return end + local b = player.gui.top.add({type = "sprite-button", caption = "?", name = "map_intro_button", tooltip = "Map Info"}) + b.style.font_color = {r=0.11, g=0.8, b=0.44} + b.style.font = "heading-1" + b.style.minimal_height = 38 + b.style.minimal_width = 38 + b.style.top_padding = 2 + b.style.left_padding = 4 + b.style.right_padding = 4 + b.style.bottom_padding = 2 +end + +local function create_map_intro(player) + if player.gui.left["map_intro_frame"] then player.gui.left["map_intro_frame"].destroy() end + local frame = player.gui.left.add {type = "frame", name = "map_intro_frame", direction = "vertical"} + local t = frame.add {type = "table", column_count = 1} + + local tt = t.add {type = "table", column_count = 3} + local l = tt.add {type = "label", caption = main_caption} + l.style.font = "heading-1" + l.style.font_color = {r=0.11, g=0.8, b=0.44} + + local l = tt.add {type = "label", caption = sub_caption} + l.style.font = "heading-2" + l.style.font_color = {r=0.33, g=0.66, b=0.9} + l.style.minimal_width = 385 + + local b = tt.add {type = "button", caption = "X", name = "close_map_intro_frame", align = "right"} + b.style.font = "heading-2" + b.style.minimal_height = 30 + b.style.minimal_width = 30 + b.style.top_padding = 2 + b.style.left_padding = 4 + b.style.right_padding = 4 + b.style.bottom_padding = 2 + + local tt = t.add {type = "table", column_count = 1} + local frame = t.add {type = "frame"} + local l = frame.add {type = "label", caption = info} + l.style.single_line = false + l.style.font = "heading-2" + l.style.font_color = {r=0.75, g=0.8, b=0.8} + l.style.minimal_width = 480 +end + +local function on_gui_click(event) + if not event then return end + if not event.element then return end + if not event.element.valid then return end + local player = game.players[event.element.player_index] + if event.element.name == "close_map_intro_frame" then player.gui.left["map_intro_frame"].destroy() return end + if event.element.name == "map_intro_button" then + if player.gui.left["map_intro_frame"] then + player.gui.left["map_intro_frame"].destroy() + else + create_map_intro(player) + end + return + end +end + +local function on_player_joined_game(event) + local player = game.players[event.player_index] + create_map_intro_button(player) + if player.online_time == 0 then + create_map_intro(player) + end +end + +event.add(defines.events.on_player_joined_game, on_player_joined_game) +event.add(defines.events.on_gui_click, on_gui_click) \ No newline at end of file diff --git a/maps/island_troopers/terrain.lua b/maps/island_troopers/terrain.lua index b9a85c49..9810b190 100644 --- a/maps/island_troopers/terrain.lua +++ b/maps/island_troopers/terrain.lua @@ -14,10 +14,10 @@ local function process_island_position(position, radius, noise, distance) if distance + noise * radius * 1.7 <= radius then return {name = "grass-1", position = position} end - if distance + noise * radius * 0.8 <= radius then + if distance + noise * radius * 0.4 <= radius then return {name = "sand-1", position = position} end - if distance + noise * radius * 0.6 <= radius then + if distance + noise * radius * 0.2 <= radius then return {name = "water", position = position} end end @@ -56,47 +56,6 @@ local function get_vector() return {1, y_modifier} end -local function is_boss_stage() - if global.current_stage == 1 then return false end - if global.current_stage % 5 == 0 then return true end - if global.current_stage == #global.stages - 1 then return true end -end - -local function add_enemies(surface, tiles) - table.shuffle_table(tiles) - - if is_boss_stage() then - set_biter_chances(global.current_level + 100) - local boss_biters = math.random(1, global.current_level) - for k, tile in pairs(tiles) do - if surface.can_place_entity({name = "small-biter", position = tile.position, force = "enemy"}) then - local unit = surface.create_entity({name = get_biter(), position = tile.position, force = "enemy"}) - unit.ai_settings.allow_destroy_when_commands_fail = false - unit.ai_settings.allow_try_return_to_spawner = false - add_boss_unit(unit, global.current_level * 2, 0.55) - global.alive_boss_enemy_count = global.alive_boss_enemy_count + 1 - global.alive_boss_enemy_entities[unit.unit_number] = unit - global.alive_enemies = global.alive_enemies + 1 - boss_biters = boss_biters - 1 - if boss_biters == 0 then break end - end - end - end - - set_biter_chances(global.current_level) - local amount = math.ceil(((global.current_level * 25) / #global.stages) * global.current_stage) - for k, tile in pairs(tiles) do - if surface.can_place_entity({name = "small-biter", position = tile.position, force = "enemy"}) then - local unit = surface.create_entity({name = get_biter(), position = tile.position, force = "enemy"}) - unit.ai_settings.allow_destroy_when_commands_fail = false - unit.ai_settings.allow_try_return_to_spawner = false - global.alive_enemies = global.alive_enemies + 1 - amount = amount - 1 - end - if amount == 0 then break end - end -end - function draw_the_island() if not global.stages[global.current_stage].size then global.gamestate = 4 return end local surface = game.surfaces[1] @@ -104,10 +63,22 @@ function draw_the_island() local tiles = draw_island_tiles(surface, position, global.stages[global.current_stage].size) local tree = "tree-0" .. math_random(1,9) - for _, t in pairs(tiles) do - if math.random(1,128) == 1 then surface.create_entity({name = rock_raffle[math_random(1, #rock_raffle)], position = t.position}) end + local seed = math.random(1, 1000000) + + for _, t in pairs(tiles) do + if math.random(1, 32) == 1 then + local noise = simplex_noise(t.position.x * 0.02, t.position.y * 0.02, seed) + if noise > 0.75 or noise < -0.75 then + surface.create_entity({name = rock_raffle[math_random(1, #rock_raffle)], position = t.position}) + end + end + if surface.can_place_entity({name = "wooden-chest", position = t.position}) then - if math.random(1,64) == 1 then surface.create_entity({name = tree, position = t.position}) end + if math.random(1, 64) == 1 then + if simplex_noise(t.position.x * 0.02, t.position.y * 0.02, seed) > 0.25 then + surface.create_entity({name = tree, position = t.position}) + end + end end end @@ -124,13 +95,13 @@ local path_tile_names = {"grass-2", "grass-3", "grass-4", "water-shallow"} function draw_path_to_next_stage() local surface = game.surfaces[1] - if global.current_stage ~= #global.stages then - if global.current_stage == #global.stages - 1 then - game.print("--Final Stage--") - else - game.print("--Stage " .. global.current_stage .. "--") - end - end + --if global.current_stage ~= #global.stages then + -- if global.current_stage == #global.stages - 1 then + --game.print("--Final Stage--") + -- else + --game.print("--Stage " .. global.current_stage .. "--") + -- end + --end local position = {x = 0, y = 0} if global.path_tiles then position = global.path_tiles[#global.path_tiles].position end @@ -146,7 +117,7 @@ function draw_path_to_next_stage() global.gamestate = 3 end -local tile_whitelist = {"grass-1", "grass-2", "grass-3", "grass-4", "water-mud", "water-shallow", "sand-1", "water"} +local tile_whitelist = {"grass-1", "grass-2", "grass-3", "grass-4", "water-mud", "water-shallow", "sand-1", "water", "landfill"} local function get_level_tiles(surface) global.level_tiles = {} for chunk in surface.get_chunks() do @@ -214,15 +185,15 @@ function kill_the_level() end local function process_tile(surface, position) - if position.x < -64 then surface.set_tiles({{name = "out-of-map", position = position}}, true) return end + if position.x < -96 then surface.set_tiles({{name = "out-of-map", position = position}}, true) return end if position.y < 0 then surface.set_tiles({{name = "deepwater", position = position}}, true) return end if position.y > 32 then surface.set_tiles({{name = "water-green", position = position}}, true) return end - if position.y > 12 + simplex_noise(position.x * 0.010, 0, game.surfaces[1].map_gen_settings.seed) * 6 then surface.set_tiles({{name = "water-green", position = position}}, true) return end + if position.y > 10 + simplex_noise(position.x * 0.010, 0, game.surfaces[1].map_gen_settings.seed) * 4 then surface.set_tiles({{name = "water-green", position = position}}, true) return end surface.set_tiles({{name = "sand-1", position = position}}, true) - if position.y == 6 + math.floor(simplex_noise(position.x * 0.010, 0, game.surfaces[1].map_gen_settings.seed) * 4) then + if position.y == 6 then if position.x % 64 == 32 then create_shopping_chest(surface, position, false) end if position.x % 128 == 0 then create_dump_chest(surface, position, false) end end @@ -242,6 +213,8 @@ local function on_chunk_generated(event) process_tile(surface, position) end end + + surface.destroy_decoratives(event.area) end local event = require 'utils.event' diff --git a/modules/difficulty_vote.lua b/modules/difficulty_vote.lua index 9107408f..ec0cb490 100644 --- a/modules/difficulty_vote.lua +++ b/modules/difficulty_vote.lua @@ -11,12 +11,20 @@ local difficulties = { } local function difficulty_gui() + local tooltip = "Current difficulty of the map is " .. difficulties[global.difficulty_vote_index].name + tooltip = tooltip .. "." + for _, player in pairs(game.connected_players) do - if player.gui.top["difficulty_gui"] then player.gui.top["difficulty_gui"].destroy() end - local b = player.gui.top.add { type = "button", caption = difficulties[global.difficulty_vote_index].name, tooltip = "Current difficulty of the map is " .. difficulties[global.difficulty_vote_index].name .. ".", name = "difficulty_gui" } - b.style.font = "heading-2" - b.style.font_color = difficulties[global.difficulty_vote_index].print_color - b.style.minimal_height = 38 + if player.gui.top["difficulty_gui"] then + player.gui.top["difficulty_gui"].caption = difficulties[global.difficulty_vote_index].name + player.gui.top["difficulty_gui"].tooltip = tooltip + player.gui.top["difficulty_gui"].style.font_color = difficulties[global.difficulty_vote_index].print_color + else + local b = player.gui.top.add { type = "button", caption = difficulties[global.difficulty_vote_index].name, tooltip = tooltip, name = "difficulty_gui" } + b.style.font = "heading-2" + b.style.font_color = difficulties[global.difficulty_vote_index].print_color + b.style.minimal_height = 38 + end end end @@ -85,6 +93,7 @@ local function on_player_joined_game(event) if not global.difficulty_vote_value then global.difficulty_vote_value = 1 end if not global.difficulty_vote_index then global.difficulty_vote_index = 4 end if not global.difficulty_player_votes then global.difficulty_player_votes = {} end + if not global.difficulty_poll_closing_timeout then global.difficulty_poll_closing_timeout = 54000 end if game.tick < global.difficulty_poll_closing_timeout then if not global.difficulty_player_votes[player.name] then poll_difficulty(player) diff --git a/modules/shopping_chests.lua b/modules/shopping_chests.lua index 2d3dd015..45444256 100644 --- a/modules/shopping_chests.lua +++ b/modules/shopping_chests.lua @@ -8,6 +8,7 @@ local shop_list = { ["crude-oil-barrel"] = 6, ["empty-barrel"] = 5, ["landfill"] = 2.5, + ["raw-fish"] = 4, } function create_shopping_chest(surface, position, destructible) @@ -59,18 +60,31 @@ local function process_dump_chest(k, chest) if inventory.is_empty() then return end for k, price in pairs(shop_list) do local removed = inventory.remove(k) - global.credits = global.credits + (removed * shop_list[k]) + if removed > 0 then + local gain = removed * shop_list[k] + global.credits = global.credits + gain + chest.surface.create_entity({name = "flying-text", position = chest.position, text = "+" .. gain .. " ø", color = {r = 200, g = 160, b = 30}}) + return + end end end local function gui() + local tooltip = "Trade goods: " + for k, v in pairs(shop_list) do + tooltip = tooltip .. k + tooltip = tooltip .. " " + tooltip = tooltip .. v + tooltip = tooltip .. " | " + end + for _, player in pairs(game.connected_players) do if player.gui.top.credits_button then player.gui.top.credits_button.destroy() end local frame = player.gui.top.add({type = "frame", name = "credits_button"}) frame.style.maximal_height = 38 frame.style.top_padding = 0 frame.style.left_padding = 0 - local element = frame.add({type = "label", name = "credits", caption = global.credits .. " ø", tooltip = "Credits of the factory."}) + local element = frame.add({type = "label", name = "credits", caption = global.credits .. " ø", tooltip = tooltip}) local style = element.style style.minimal_height = 38 style.maximal_height = 38