diff --git a/maps/mountain_fortress_v3/balance.lua b/maps/mountain_fortress_v3/balance.lua index 6820748b..48dfa8cd 100644 --- a/maps/mountain_fortress_v3/balance.lua +++ b/maps/mountain_fortress_v3/balance.lua @@ -1,6 +1,7 @@ local Event = require 'utils.event' local Difficulty = require 'modules.difficulty_vote' local Public = {} +Public.events = {breached_wall = Event.generate_event_name('breached_wall')} function Public.init_enemy_weapon_damage() local data = { @@ -31,27 +32,25 @@ end local function enemy_weapon_damage() local Diff = Difficulty.get() - if game.tick < 100 then - goto rtn - end + local e = game.forces.enemy local data = { - ['artillery-shell'] = 0.1, - ['biological'] = 0.1, - ['bullet'] = 0.1, - ['capsule'] = 0.1, - ['combat-robot-beam'] = 0.1, - ['combat-robot-laser'] = 0.1, - ['electric'] = 0.1, - ['flamethrower'] = 0.1, - --['grenade'] = 0.1, - --['landmine'] = 0.1, - ['laser-turret'] = 0.1, - ['melee'] = 0.1 - --['railgun'] = 0.1, - --['rocket'] = 0.1, - --['shotgun-shell'] = 0.1 + ['artillery-shell'] = 0.08, + ['biological'] = 0.08, + ['bullet'] = 0.08, + ['capsule'] = 0.08, + ['combat-robot-beam'] = 0.08, + ['combat-robot-laser'] = 0.08, + ['electric'] = 0.08, + ['flamethrower'] = 0.08, + --['grenade'] = 0.08, + --['landmine'] = 0.08, + ['laser-turret'] = 0.08, + ['melee'] = 0.08 + --['railgun'] = 0.08, + --['rocket'] = 0.08, + --['shotgun-shell'] = 0.08 } for k, v in pairs(data) do @@ -61,10 +60,10 @@ local function enemy_weapon_damage() e.set_ammo_damage_modifier(k, new + e_old) end - - ::rtn:: end -Event.on_nth_tick(54000, enemy_weapon_damage) +Event.add(Public.events.breached_wall, enemy_weapon_damage) + +--Event.on_nth_tick(54000, enemy_weapon_damage) return Public diff --git a/maps/mountain_fortress_v3/basic_markets.lua b/maps/mountain_fortress_v3/basic_markets.lua new file mode 100644 index 00000000..d86304a7 --- /dev/null +++ b/maps/mountain_fortress_v3/basic_markets.lua @@ -0,0 +1,259 @@ +local Public = {} + +local market = {} + +market.weapons = { + ['pistol'] = {value = 10, rarity = 1}, + ['submachine-gun'] = {value = 50, rarity = 2}, + ['shotgun'] = {value = 40, rarity = 2}, + ['combat-shotgun'] = {value = 400, rarity = 5}, + ['rocket-launcher'] = {value = 500, rarity = 6}, + ['flamethrower'] = {value = 750, rarity = 6}, + ['land-mine'] = {value = 3, rarity = 5} +} + +market.ammo = { + ['firearm-magazine'] = {value = 3, rarity = 1}, + ['piercing-rounds-magazine'] = {value = 6, rarity = 4}, + ['uranium-rounds-magazine'] = {value = 20, rarity = 8}, + ['shotgun-shell'] = {value = 3, rarity = 1}, + ['piercing-shotgun-shell'] = {value = 8, rarity = 5}, + ['cannon-shell'] = {value = 8, rarity = 4}, + ['explosive-cannon-shell'] = {value = 12, rarity = 5}, + ['uranium-cannon-shell'] = {value = 16, rarity = 7}, + ['explosive-uranium-cannon-shell'] = {value = 20, rarity = 8}, + ['artillery-shell'] = {value = 64, rarity = 7}, + ['rocket'] = {value = 45, rarity = 7}, + ['explosive-rocket'] = {value = 50, rarity = 7}, + ['atomic-bomb'] = {value = 11000, rarity = 10}, + ['flamethrower-ammo'] = {value = 20, rarity = 6}, + ['explosives'] = {value = 3, rarity = 1} +} + +market.caspules = { + ['grenade'] = {value = 16, rarity = 2}, + ['cluster-grenade'] = {value = 64, rarity = 5}, + ['poison-capsule'] = {value = 32, rarity = 6}, + ['slowdown-capsule'] = {value = 8, rarity = 1}, + ['defender-capsule'] = {value = 8, rarity = 1}, + ['distractor-capsule'] = {value = 20, rarity = 5}, + ['destroyer-capsule'] = {value = 32, rarity = 7}, + ['discharge-defense-remote'] = {value = 64, rarity = 6}, + ['artillery-targeting-remote'] = {value = 32, rarity = 7}, + ['raw-fish'] = {value = 6, rarity = 1} +} + +market.armor = { + ['light-armor'] = {value = 25, rarity = 1}, + ['heavy-armor'] = {value = 250, rarity = 4}, + ['modular-armor'] = {value = 750, rarity = 5}, + ['power-armor'] = {value = 2500, rarity = 6}, + ['power-armor-mk2'] = {value = 20000, rarity = 10} +} + +market.equipment = { + ['solar-panel-equipment'] = {value = 240, rarity = 3}, + ['fusion-reactor-equipment'] = {value = 9000, rarity = 7}, + ['energy-shield-equipment'] = {value = 400, rarity = 6}, + ['energy-shield-mk2-equipment'] = {value = 4000, rarity = 8}, + ['battery-equipment'] = {value = 160, rarity = 2}, + ['battery-mk2-equipment'] = {value = 2000, rarity = 8}, + ['personal-laser-defense-equipment'] = {value = 2500, rarity = 7}, + ['discharge-defense-equipment'] = {value = 2000, rarity = 5}, + ['belt-immunity-equipment'] = {value = 200, rarity = 1}, + ['exoskeleton-equipment'] = {value = 800, rarity = 3}, + ['personal-roboport-equipment'] = {value = 500, rarity = 3}, + ['personal-roboport-mk2-equipment'] = {value = 5000, rarity = 8}, + ['night-vision-equipment'] = {value = 250, rarity = 1} +} + +market.defense = { + ['stone-wall'] = {value = 4, rarity = 1}, + ['gate'] = {value = 8, rarity = 1}, + ['repair-pack'] = {value = 8, rarity = 1}, + ['gun-turret'] = {value = 64, rarity = 1}, + ['laser-turret'] = {value = 1024, rarity = 6}, + ['flamethrower-turret'] = {value = 2048, rarity = 6}, + ['artillery-turret'] = {value = 8192, rarity = 8}, + ['rocket-silo'] = {value = 64000, rarity = 10} +} + +market.logistic = { + ['wooden-chest'] = {value = 3, rarity = 1}, + ['iron-chest'] = {value = 10, rarity = 2}, + ['steel-chest'] = {value = 24, rarity = 3}, + ['storage-tank'] = {value = 32, rarity = 4}, + ['transport-belt'] = {value = 4, rarity = 1}, + ['fast-transport-belt'] = {value = 8, rarity = 4}, + ['express-transport-belt'] = {value = 24, rarity = 7}, + ['underground-belt'] = {value = 8, rarity = 1}, + ['fast-underground-belt'] = {value = 32, rarity = 4}, + ['express-underground-belt'] = {value = 64, rarity = 7}, + ['splitter'] = {value = 16, rarity = 1}, + ['fast-splitter'] = {value = 48, rarity = 4}, + ['express-splitter'] = {value = 128, rarity = 7}, + ['loader'] = {value = 256, rarity = 2}, + ['fast-loader'] = {value = 512, rarity = 5}, + ['express-loader'] = {value = 768, rarity = 8}, + ['burner-inserter'] = {value = 4, rarity = 1}, + ['inserter'] = {value = 8, rarity = 1}, + ['long-handed-inserter'] = {value = 12, rarity = 2}, + ['fast-inserter'] = {value = 16, rarity = 4}, + ['filter-inserter'] = {value = 24, rarity = 5}, + ['stack-inserter'] = {value = 96, rarity = 6}, + ['stack-filter-inserter'] = {value = 128, rarity = 7}, + ['small-electric-pole'] = {value = 2, rarity = 1}, + ['medium-electric-pole'] = {value = 12, rarity = 4}, + ['big-electric-pole'] = {value = 24, rarity = 5}, + ['substation'] = {value = 96, rarity = 8}, + ['pipe'] = {value = 2, rarity = 1}, + ['pipe-to-ground'] = {value = 8, rarity = 1}, + ['pump'] = {value = 16, rarity = 4}, + ['logistic-robot'] = {value = 28, rarity = 5}, + ['construction-robot'] = {value = 28, rarity = 3}, + ['logistic-chest-active-provider'] = {value = 128, rarity = 7}, + ['logistic-chest-passive-provider'] = {value = 128, rarity = 6}, + ['logistic-chest-storage'] = {value = 128, rarity = 6}, + ['logistic-chest-buffer'] = {value = 128, rarity = 7}, + ['logistic-chest-requester'] = {value = 128, rarity = 7}, + ['roboport'] = {value = 4096, rarity = 8} +} + +market.vehicles = { + ['rail'] = {value = 4, rarity = 1}, + ['train-stop'] = {value = 32, rarity = 3}, + ['rail-signal'] = {value = 8, rarity = 5}, + ['rail-chain-signal'] = {value = 8, rarity = 5}, + ['locomotive'] = {value = 400, rarity = 4}, + ['cargo-wagon'] = {value = 200, rarity = 4}, + ['fluid-wagon'] = {value = 300, rarity = 5}, + ['artillery-wagon'] = {value = 8192, rarity = 8}, + ['car'] = {value = 80, rarity = 1}, + ['tank'] = {value = 1800, rarity = 5} +} + +market.wire = { + ['small-lamp'] = {value = 4, rarity = 1}, + ['red-wire'] = {value = 4, rarity = 1}, + ['green-wire'] = {value = 4, rarity = 1}, + ['arithmetic-combinator'] = {value = 16, rarity = 1}, + ['decider-combinator'] = {value = 16, rarity = 1}, + ['constant-combinator'] = {value = 16, rarity = 1}, + ['power-switch'] = {value = 16, rarity = 1}, + ['programmable-speaker'] = {value = 24, rarity = 1} +} + +local function get_types() + local types = {} + for k, _ in pairs(market) do + types[#types + 1] = k + end + return types +end + +local function get_resource_market_sells() + local sells = { + {price = {{'coin', math.random(5, 10)}}, offer = {type = 'give-item', item = 'wood', count = 50}}, + {price = {{'coin', math.random(5, 10)}}, offer = {type = 'give-item', item = 'iron-ore', count = 50}}, + {price = {{'coin', math.random(5, 10)}}, offer = {type = 'give-item', item = 'copper-ore', count = 50}}, + {price = {{'coin', math.random(5, 10)}}, offer = {type = 'give-item', item = 'stone', count = 50}}, + {price = {{'coin', math.random(5, 10)}}, offer = {type = 'give-item', item = 'coal', count = 50}}, + {price = {{'coin', math.random(8, 16)}}, offer = {type = 'give-item', item = 'uranium-ore', count = 50}}, + {price = {{'coin', math.random(2, 4)}}, offer = {type = 'give-item', item = 'crude-oil-barrel', count = 1}} + } + table.shuffle_table(sells) + return sells +end + +local function get_resource_market_buys() + local buys = { + {price = {{'wood', math.random(10, 12)}}, offer = {type = 'give-item', item = 'coin'}}, + {price = {{'iron-ore', math.random(10, 12)}}, offer = {type = 'give-item', item = 'coin'}}, + {price = {{'copper-ore', math.random(10, 12)}}, offer = {type = 'give-item', item = 'coin'}}, + {price = {{'stone', math.random(10, 12)}}, offer = {type = 'give-item', item = 'coin'}}, + {price = {{'coal', math.random(10, 12)}}, offer = {type = 'give-item', item = 'coin'}}, + {price = {{'uranium-ore', math.random(8, 10)}}, offer = {type = 'give-item', item = 'coin'}}, + {price = {{'water-barrel', 1}}, offer = {type = 'give-item', item = 'coin', count = math.random(1, 2)}}, + {price = {{'lubricant-barrel', 1}}, offer = {type = 'give-item', item = 'coin', count = math.random(3, 6)}}, + {price = {{'sulfuric-acid-barrel', 1}}, offer = {type = 'give-item', item = 'coin', count = math.random(4, 8)}}, + {price = {{'light-oil-barrel', 1}}, offer = {type = 'give-item', item = 'coin', count = math.random(2, 4)}}, + {price = {{'heavy-oil-barrel', 1}}, offer = {type = 'give-item', item = 'coin', count = math.random(2, 4)}}, + {price = {{'petroleum-gas-barrel', 1}}, offer = {type = 'give-item', item = 'coin', count = math.random(3, 5)}} + } + table.shuffle_table(buys) + return buys +end + +local function get_market_item_list(market_types, rarity) + if rarity < 1 then + rarity = 1 + end + if rarity > 10 then + rarity = 10 + end + local list = {} + for _, market_type in pairs(market_types) do + for k, item in pairs(market[market_type]) do + --if item.rarity <= rarity and item.rarity + 7 >= rarity then + if item.rarity <= rarity then + local price = math.random(math.floor(item.value * 0.75), math.floor(item.value * 1.25)) + if price < 1 then + price = 1 + end + if price > 64000 then + price = 64000 + end + list[#list + 1] = {price = {{'coin', price}}, offer = {type = 'give-item', item = k}} + end + end + end + if #list == 0 then + return false + end + return list +end + +function Public.mountain_market(surface, position, rarity) + local types = get_types() + table.shuffle_table(types) + local items = get_market_item_list({types[1], types[2], types[3]}, rarity) + if not items then + return + end + if #items > 0 then + table.shuffle_table(items) + end + local mrk = surface.create_entity({name = 'market', position = position, force = 'neutral'}) + + local blacklist = { + ['cargo-wagon'] = true, + ['locomotive'] = true, + ['artillery-wagon'] = true, + ['fluid-wagon'] = true, + ['land-mine'] = true + } + + for i = 1, math.random(5, 10), 1 do + local item = items[i] + if not item then + break + end + if not blacklist[item.offer.item] then + mrk.add_market_item(items[i]) + end + end + + local sells = get_resource_market_sells() + for i = 1, math.random(1, 3), 1 do + mrk.add_market_item(sells[i]) + end + + local buys = get_resource_market_buys() + for i = 1, math.random(1, 3), 1 do + mrk.add_market_item(buys[i]) + end + + return mrk +end + +return Public diff --git a/maps/mountain_fortress_v3/biter_corpse_remover.lua b/maps/mountain_fortress_v3/biter_corpse_remover.lua new file mode 100644 index 00000000..d645be15 --- /dev/null +++ b/maps/mountain_fortress_v3/biter_corpse_remover.lua @@ -0,0 +1,121 @@ +-- dependencies +local Event = require 'utils.event' +local Global = require 'utils.global' +local table = require 'utils.table' +local remove = table.remove +local pairs = pairs +local next = next + +local biter_utils_conf = { + enabled = true, + chunk_size = 3, -- size of chunk in tiles + corpse_threshold = 5 -- number of corpses allowed on surface inside chunk +} + +-- Factorio removes corpses that hit 15 minutes anyway +local max_corpse_age = 7200 +local kills_per_cleanup = 500 + +-- x -> y -> array of {entity, tick} +local corpse_chunks = {} +local cleanup_count = {kills_per_cleanup} + +Global.register( + { + corpse_chunks = corpse_chunks, + cleanup_count = cleanup_count + }, + function(tbl) + corpse_chunks = tbl.corpse_chunks + cleanup_count = tbl.cleanup_count + end +) + +-- cleans up the stored list of corpses and chunks +local function remove_outdated_corpses(now) + -- loop each stored chunk + for x, column in pairs(corpse_chunks) do + for y, corpses in pairs(column) do + local count = #corpses + + for i = count, 1, -1 do + if corpses[i].tick < now then + remove(corpses, i) + count = count - 1 + end + end + + if count == 0 then + column[y] = nil + end + end + + if next(column) == nil then + corpse_chunks[x] = nil + end + end +end + +local function biter_died(event) + local prot = event.prototype + + -- Only trigger on dead units + if prot.type ~= 'unit' then + return + end + + local entity = event.corpses[1] + -- Ensure there is actually a corpse + if entity == nil then + return + end + + local tick = event.tick + + -- Chance to clean up old corpses and chunks + local cuc = cleanup_count[1] - 1 + if cuc <= 0 then + remove_outdated_corpses(tick) + cleanup_count[1] = kills_per_cleanup + else + cleanup_count[1] = cuc + end + + --Calculate the chunk position + local chunk_size = biter_utils_conf.chunk_size + local pos = entity.position + local x, y = pos.x, pos.y + x = x - (x % chunk_size) + y = y - (y % chunk_size) + + -- check global table has this position, add if not + local corpse_chunks_column = corpse_chunks[x] + if corpse_chunks_column == nil then + corpse_chunks_column = {} + corpse_chunks[x] = corpse_chunks_column + end + + local corpses = corpse_chunks_column[y] + if corpses == nil then + corpses = {} + corpse_chunks_column[y] = corpses + end + + -- Add this entity + local count = #corpses + 1 + corpses[count] = { + entity = entity, + tick = tick + max_corpse_age + } + + -- Cleanup old corpse if above threshold + if count > biter_utils_conf.corpse_threshold then + local old_entity = remove(corpses, 1).entity + + if old_entity.valid then + old_entity.destroy() + end + end +end + +Event.add(defines.events.on_post_entity_died, biter_died) diff --git a/maps/mountain_fortress_v3/breached_wall.lua b/maps/mountain_fortress_v3/breached_wall.lua new file mode 100644 index 00000000..f4c24a8b --- /dev/null +++ b/maps/mountain_fortress_v3/breached_wall.lua @@ -0,0 +1,59 @@ +local Collapse = require 'modules.collapse' +local Terrain = require 'maps.mountain_fortress_v3.terrain' +local Balance = require 'maps.mountain_fortress_v3.balance' +local WPT = require 'maps.mountain_fortress_v3.table' +local RPG = require 'maps.mountain_fortress_v3.rpg' +local Event = require 'utils.event' + +local raise_event = script.raise_event +local floor = math.floor +local sqrt = math.sqrt + +local function distance(player) + local rpg_t = RPG.get_table() + local rpg_extra = RPG.get_extra_table() + local breached_wall = WPT.get('breached_wall') + local distance_to_center = floor(sqrt(player.position.x ^ 2 + player.position.y ^ 2)) + local location = distance_to_center + if location < Terrain.level_depth * rpg_t[player.index].bonus - 10 then + return + end + local min = Terrain.level_depth * rpg_t[player.index].bonus + local max = (Terrain.level_depth + 5) * rpg_t[player.index].bonus + local breach_min = Terrain.level_depth * breached_wall + local breach_max = (Terrain.level_depth + 5) * breached_wall + local breach_min_times = location >= breach_min + local breach_max_times = location <= breach_max + local min_times = location >= min + local max_times = location <= max + if min_times and max_times then + if not Collapse.start_now() then + Collapse.start_now(true) + game.print('[color=blue]Mapkeeper:[/color] Warning, collapse has begun!') + end + local level = rpg_t[player.index].bonus + rpg_t[player.index].bonus = rpg_t[player.index].bonus + 1 + player.print('[color=blue]Mapkeeper:[/color] Survivor! Well done. You have completed level: ' .. level) + RPG.gain_xp(player, 150 * rpg_t[player.index].bonus) + if breach_min_times and breach_max_times then + rpg_extra.breached_walls = rpg_extra.breached_walls + 1 + rpg_extra.reward_new_players = 150 * rpg_extra.breached_walls + WPT.get().breached_wall = breached_wall + 1 + raise_event(Balance.events.breached_wall, {}) + end + return + end +end + +local function on_player_changed_position(event) + local player = game.players[event.player_index] + local map_name = 'mountain_fortress_v3' + + if string.sub(player.surface.name, 0, #map_name) ~= map_name then + return + end + + distance(player) +end + +Event.add(defines.events.on_player_changed_position, on_player_changed_position) diff --git a/maps/mountain_fortress_v3/commands.lua b/maps/mountain_fortress_v3/commands.lua index d7e9f4de..257753ef 100644 --- a/maps/mountain_fortress_v3/commands.lua +++ b/maps/mountain_fortress_v3/commands.lua @@ -20,22 +20,33 @@ commands.add_command( p("[ERROR] You're not admin!", Color.fail) return end + if not this.reset_are_you_sure then + this.reset_are_you_sure = true + player.print( + '[WARNING] This command will reset the current game, run this command again if you really want to do this!', + Color.yellow + ) + return + end + + game.print(mapkeeper .. ' ' .. player.name .. ', has reset the game!', {r = 0.98, g = 0.66, b = 0.22}) + this.reset_are_you_sure = nil + reset_map() else p = log + if not this.reset_are_you_sure then + this.reset_are_you_sure = true + p( + '[WARNING] This command will reset the current game, run this command again if you really want to do this!' + ) + return + end + + game.print(mapkeeper .. ' server, has reset the game!', {r = 0.98, g = 0.66, b = 0.22}) + this.reset_are_you_sure = nil + reset_map() end end - if not this.reset_are_you_sure then - this.reset_are_you_sure = true - player.print( - '[WARNING] This command will reset the current game, run this command again if you really want to do this!', - Color.yellow - ) - return - end - - game.print(mapkeeper .. ' ' .. player.name .. ', has reset the game!', {r = 0.98, g = 0.66, b = 0.22}) - this.reset_are_you_sure = nil - reset_map() end ) @@ -46,7 +57,7 @@ commands.add_command( local p local player = game.player local this = WPT.get() - local param = tostring(cmd.parameter) + local param = cmd.parameter if player then if player ~= nil then @@ -55,62 +66,137 @@ commands.add_command( p("[ERROR] You're not admin!", Color.fail) return end + + if param == 'true' or param == 'false' then + goto continue + else + p('[ERROR] Arguments are true or false', Color.yellow) + return + end + + ::continue:: + + if not this.reset_are_you_sure then + this.reset_are_you_sure = true + player.print( + '[WARNING] This command will disable the auto-reset feature, run this command again if you really want to do this!', + Color.yellow + ) + return + end + + if param == 'true' then + if this.disable_reset then + this.reset_are_you_sure = nil + return p('[WARNING] Reset is already disabled!', Color.fail) + end + + this.disable_reset = true + + p('[SUCCESS] Auto-reset is disabled!', Color.success) + this.reset_are_you_sure = nil + elseif param == 'false' then + if not this.disable_reset then + this.reset_are_you_sure = nil + return p('[WARNING] Reset is already enabled!', Color.fail) + end + + this.disable_reset = false + p('[SUCCESS] Auto-reset is enabled!', Color.success) + this.reset_are_you_sure = nil + end else p = log + if param == 'true' or param == 'false' then + goto continue + else + p('[ERROR] Arguments are true/false') + return + end + + ::continue:: + + if not this.reset_are_you_sure then + this.reset_are_you_sure = true + p( + '[WARNING] This command will disable the auto-reset feature, run this command again if you really want to do this!' + ) + return + end + + if param == 'true' then + if this.disable_reset then + this.reset_are_you_sure = nil + return p('[WARNING] Reset is already disabled!') + end + + this.disable_reset = true + + p('[SUCCESS] Auto-reset is disabled!', Color.success) + this.reset_are_you_sure = nil + elseif param == 'false' then + if not this.disable_reset then + this.reset_are_you_sure = nil + return p('[WARNING] Reset is already enabled!') + end + + this.disable_reset = false + p('[SUCCESS] Auto-reset is enabled!') + this.reset_are_you_sure = nil + end end end - if not param then - p('[ERROR] Arguments are true/false', Color.yellow) - return - end - - if not this.reset_are_you_sure then - this.reset_are_you_sure = true - player.print( - '[WARNING] This command will disable the auto-reset feature, run this command again if you really want to do this!', - Color.yellow - ) - return - end - - if param == 'true' then - if this.disable_reset then - this.reset_are_you_sure = nil - return p('[WARNING] Reset is already disabled!', Color.fail) - end - - this.disable_reset = true - - p('[SUCCESS] Auto-reset is disabled!', Color.success) - this.reset_are_you_sure = nil - elseif param == 'false' then - if not this.disable_reset then - this.reset_are_you_sure = nil - return p('[WARNING] Reset is already enabled!', Color.fail) - end - - this.disable_reset = false - p('[SUCCESS] Auto-reset is enabled!', Color.success) - this.reset_are_you_sure = nil - end end ) -if _DEBUG then - commands.add_command( - 'get_queue_speed', - 'Debug only, return the current task queue speed!', - function() - local player = game.player +commands.add_command( + 'set_queue_speed', + 'Usable only for admins - sets the queue speed of this map!', + function(cmd) + local p + local player = game.player + local param = tonumber(cmd.parameter) - if player then - if player ~= nil then - if not player.admin then - return - end + if player then + if player ~= nil then + p = player.print + if not player.admin then + p("[ERROR] You're not admin!", Color.fail) + return end + if not param then + return + end + p('Queue speed set to: ' .. param) + Task.set_queue_speed(param) + else + p = log + p('Queue speed set to: ' .. param) + Task.set_queue_speed(param) end - game.print(Task.get_queue_speed()) end - ) -end + end +) + +commands.add_command( + 'get_queue_speed', + 'Usable only for admins - gets the queue speed of this map!', + function() + local p + local player = game.player + + if player then + if player ~= nil then + p = player.print + if not player.admin then + p("[ERROR] You're not admin!", Color.fail) + return + end + p(Task.get_queue_speed()) + else + p = log + p(Task.get_queue_speed()) + end + end + end +) diff --git a/maps/mountain_fortress_v3/entities.lua b/maps/mountain_fortress_v3/entities.lua index a18aed49..06d95446 100644 --- a/maps/mountain_fortress_v3/entities.lua +++ b/maps/mountain_fortress_v3/entities.lua @@ -208,7 +208,7 @@ local function biters_chew_rocks_faster(event) return end --Enemy Force - event.entity.health = event.entity.health - event.final_damage_amount * 2.5 + event.entity.health = event.entity.health - event.final_damage_amount * 3.5 end local projectiles = {'grenade', 'explosive-rocket', 'grenade', 'explosive-rocket', 'explosive-cannon-projectile'} @@ -418,11 +418,12 @@ function Public.loco_died() local wave_defense_table = WD.get_table() Public.set_scores() if not this.locomotive.valid then + local Reset_map = require 'maps.mountain_fortress_v3.main'.reset_map wave_defense_table.game_lost = true wave_defense_table.target = nil game.print(mapkeeper .. ' ' .. defeated_messages[math.random(1, #defeated_messages)], {r = 1, g = 0.5, b = 0.1}) game.print(mapkeeper .. ' Better luck next time.', {r = 1, g = 0.5, b = 0.1}) - Public.reset_map() + Reset_map() return end this.locomotive_health = 0 @@ -432,7 +433,11 @@ function Public.loco_died() wave_defense_table.target = nil game.print(mapkeeper .. ' ' .. defeated_messages[math.random(1, #defeated_messages)], {r = 1, g = 0.5, b = 0.1}) game.print(mapkeeper .. ' Better luck next time.', {r = 1, g = 0.5, b = 0.1}) - game.print(mapkeeper .. ' Game will soft-reset shortly.', {r = 1, g = 0.5, b = 0.1}) + if not this.disable_reset then + game.print(mapkeeper .. ' Game will soft-reset shortly.', {r = 1, g = 0.5, b = 0.1}) + else + game.print(mapkeeper .. ' Game will not soft-reset. Soft-reset is disabled.', {r = 1, g = 0.5, b = 0.1}) + end game.forces.enemy.set_friend('player', true) game.forces.player.set_friend('enemy', true) @@ -458,9 +463,157 @@ function Public.loco_died() end end +local function on_built_entity(event) + local this = WPT.get() + local entity = event.created_entity + if not entity.valid then + return + end + + local upg = this.upgrades + + local built = { + ['land-mine'] = upg.landmine.built, + ['flamethrower-turret'] = upg.flame_turret.built + } + + local limit = { + ['land-mine'] = upg.landmine.limit, + ['flamethrower-turret'] = upg.flame_turret.limit + } + + local validator = { + ['land-mine'] = 'landmine', + ['flamethrower-turret'] = 'flame_turret' + } + + local name = validator[entity.name] + + if built[entity.name] then + local surface = entity.surface + + for k, _ in pairs(this.upgrades.unit_number[name]) do + if not k or not k.valid then + this.upgrades[name].built = #this.upgrades.unit_number[name] + this.upgrades.unit_number[name][k] = nil + built = { + ['land-mine'] = upg.landmine.built, + ['flamethrower-turret'] = upg.flame_turret.built + } + end + end + + if built[entity.name] < limit[entity.name] then + this.upgrades[name].built = built[entity.name] + 1 + this.upgrades.unit_number[name][entity] = entity + this.upgrades.showed_text = false + + surface.create_entity( + { + name = 'flying-text', + position = entity.position, + text = this.upgrades[name].built .. ' / ' .. limit[entity.name] .. ' ' .. entity.name, + color = {r = 0.82, g = 0.11, b = 0.11} + } + ) + else + if not this.upgrades.showed_text then + surface.create_entity( + { + name = 'flying-text', + position = entity.position, + text = entity.name .. ' limit reached. Purchase more slots at the market!', + color = {r = 0.82, g = 0.11, b = 0.11} + } + ) + + this.upgrades.showed_text = true + end + local player = game.players[event.player_index] + player.insert({name = entity.name, count = 1}) + entity.destroy() + end + end +end + +local function on_robot_built_entity(event) + local this = WPT.get() + local entity = event.created_entity + if not entity.valid then + return + end + + local upg = this.upgrades + + local built = { + ['land-mine'] = upg.landmine.built, + ['flamethrower-turret'] = upg.flame_turret.built + } + + local limit = { + ['land-mine'] = upg.landmine.limit, + ['flamethrower-turret'] = upg.flame_turret.limit + } + + local validator = { + ['land-mine'] = 'landmine', + ['flamethrower-turret'] = 'flame_turret' + } + + local name = validator[entity.name] + + if built[entity.name] then + local surface = entity.surface + + for k, _ in pairs(this.upgrades.unit_number[name]) do + if not k or not k.valid then + this.upgrades[name].built = #this.upgrades.unit_number[name] + this.upgrades.unit_number[name][k] = nil + built = { + ['land-mine'] = upg.landmine.built, + ['flamethrower-turret'] = upg.flame_turret.built + } + end + end + + if built[entity.name] < limit[entity.name] then + this.upgrades[name].built = built[entity.name] + 1 + this.upgrades.unit_number[name][entity] = entity + this.upgrades.showed_text = false + + surface.create_entity( + { + name = 'flying-text', + position = entity.position, + text = this.upgrades[name].built .. ' / ' .. limit[entity.name] .. ' ' .. entity.name, + color = {r = 0.82, g = 0.11, b = 0.11} + } + ) + else + if not this.upgrades.showed_text then + surface.create_entity( + { + name = 'flying-text', + position = entity.position, + text = entity.name .. ' limit reached. Purchase more slots at the market!', + color = {r = 0.82, g = 0.11, b = 0.11} + } + ) + + this.upgrades.showed_text = true + end + local inventory = event.robot.get_inventory(defines.inventory.robot_cargo) + inventory.insert({name = entity.name, count = 1}) + entity.destroy() + end + end +end + Event.add(defines.events.on_entity_damaged, on_entity_damaged) Event.add(defines.events.on_player_repaired_entity, on_player_repaired_entity) Event.add(defines.events.on_player_mined_entity, on_player_mined_entity) Event.add(defines.events.on_entity_died, on_entity_died) +Event.add(defines.events.on_built_entity, on_built_entity) +Event.add(defines.events.on_robot_built_entity, on_robot_built_entity) return Public diff --git a/maps/mountain_fortress_v3/functions.lua b/maps/mountain_fortress_v3/functions.lua new file mode 100644 index 00000000..999db42b --- /dev/null +++ b/maps/mountain_fortress_v3/functions.lua @@ -0,0 +1,296 @@ +local Token = require 'utils.token' +local ICW = require 'maps.mountain_fortress_v3.icw.main' +local WPT = require 'maps.mountain_fortress_v3.table' +local Event = require 'utils.event' + +local Public = {} + +local magic_crafters_per_tick = 3 +local magic_fluid_crafters_per_tick = 8 +local floor = math.floor + +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 function do_refill_turrets() + local refill_turrets = WPT.get('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.fluidbox[1] = data + elseif data then + turret.insert(data) + end +end + +local function turret_died(event) + local entity = event.entity + if not entity or not entity.valid then + return + end + + local number = entity.unit_number + if not number then + return + end + local power_sources = WPT.get('power_sources') + + local ps_data = power_sources[number] + if ps_data then + power_sources[number] = nil + + local ps_entity = ps_data.entity + local ps_pole = ps_data.pole + + if ps_entity and ps_entity.valid then + ps_entity.destroy() + end + + if ps_pole and ps_pole.valid then + ps_pole.destroy() + end + end +end + +local function do_magic_crafters() + local magic_crafters = WPT.get('magic_crafters') + local limit = #magic_crafters + if limit == 0 then + return + end + + local index = magic_crafters.index + + for i = 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 > 0 then + entity.get_output_inventory().insert {name = data.item, count = fcount} + data.last_tick = tick - (count - fcount) / rate + end + end + end + + magic_crafters.index = index +end + +local function do_magic_fluid_crafters() + local magic_fluid_crafters = WPT.get('magic_fluid_crafters') + local limit = #magic_fluid_crafters + + if limit == 0 then + return + end + + local index = magic_fluid_crafters.index + + for i = 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 = entity.fluidbox + + local fb_data = fb[fluidbox_index] or {name = data.item, amount = 0} + fb_data.amount = fb_data.amount + fcount + fb[fluidbox_index] = fb_data + + data.last_tick = tick - (count - fcount) / rate + end + end + end + + magic_fluid_crafters.index = index +end + +local function tick() + do_refill_turrets() + do_magic_crafters() + do_magic_fluid_crafters() +end + +Public.deactivate_callback = + Token.register( + function(entity) + entity.active = false + entity.operable = false + entity.destructible = false + end +) + +Public.neutral_force = + Token.register( + function(entity) + entity.force = 'neutral' + end +) + +Public.enemy_force = + Token.register( + function(entity) + entity.force = 'enemy' + end +) + +Public.active_not_destructible_callback = + Token.register( + function(entity) + entity.active = true + entity.operable = false + entity.destructible = false + end +) + +Public.disable_minable_callback = + Token.register( + function(entity) + entity.minable = false + end +) + +Public.disable_minable_and_ICW_callback = + Token.register( + function(entity) + entity.minable = false + local wagon = ICW.register_wagon(entity, true) + wagon.entity_count = 999 + end +) + +Public.disable_destructible_callback = + Token.register( + function(entity) + entity.destructible = false + end +) +Public.disable_active_callback = + Token.register( + function(entity) + entity.active = false + end +) + +Public.refill_turret_callback = + Token.register( + function(turret, data) + local refill_turrets = WPT.get('refill_turrets') + local callback_data = data.callback_data + turret.direction = 3 + + refill_turrets[#refill_turrets + 1] = {turret = turret, data = callback_data} + end +) + +Public.refill_liquid_turret_callback = + Token.register( + function(turret, data) + local refill_turrets = WPT.get('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 = + Token.register( + function(turret, data) + local power_sources = WPT.get('power_sources') + local callback_data = data.callback_data + + local power_source = + turret.surface.create_entity {name = 'hidden-electric-energy-interface', position = turret.position} + power_source.electric_buffer_size = callback_data.buffer_size + power_source.power_production = callback_data.power_production + power_source.destructible = false + local power_pole = + turret.surface.create_entity { + name = 'crash-site-electric-pole', + position = {x = turret.position.x, y = turret.position.y} + } + power_pole.destructible = false + power_pole.disconnect_neighbour() + + power_sources[turret.unit_number] = {entity = power_source, pole = power_pole} + 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} + +Event.add(defines.events.on_tick, tick) +Event.add(defines.events.on_entity_died, turret_died) + +return Public diff --git a/maps/mountain_fortress_v3/generate.lua b/maps/mountain_fortress_v3/generate.lua index c50c9ecf..560f41c2 100644 --- a/maps/mountain_fortress_v3/generate.lua +++ b/maps/mountain_fortress_v3/generate.lua @@ -1,4 +1,4 @@ -local Market = require 'functions.basic_markets' +local Market = require 'maps.mountain_fortress_v3.basic_markets' local Loot = require 'maps.mountain_fortress_v3.loot' local Task = require 'utils.task' local Token = require 'utils.token' @@ -8,7 +8,7 @@ local Terrain = require 'maps.mountain_fortress_v3.terrain'.heavy_functions local insert = table.insert local tiles_per_call = 16 --how many tiles are inserted with each call of insert_action -local total_calls = math.ceil(1024 / tiles_per_call) +local total_calls local regen_decoratives = false local force_chunk = false @@ -242,16 +242,55 @@ local function do_place_entities(data) local surface = data.surface local entity + local callback for _, e in ipairs(data.entities) do - if e.force then - entity = surface.create_entity({name = e.name, position = e.position, force = e.force}) + if e.collision then + if surface.can_place_entity(e) then + entity = surface.create_entity(e) + if entity and e.direction then + entity.direction = e.direction + end + if entity and e.force then + entity.force = e.force + end + if entity and e.callback then + local c = e.callback.callback + if not c then + return + end + local d = {callback_data = e.callback.data} + if not d then + callback = Token.get(c) + callback(entity) + return + end + callback = Token.get(c) + callback(entity, d) + end + end else entity = surface.create_entity(e) - end - if entity and e.callback then - local callback = Token.get(e.callback) - callback(entity, e.data) + if entity and e.direction then + entity.direction = e.direction + end + if entity and e.force then + entity.force = e.force + end + if entity and e.callback then + local c = e.callback.callback + if not c then + return + end + local d = {callback_data = e.callback.data} + if not d then + callback = Token.get(c) + callback(entity) + return + end + callback = Token.get(c) + callback(entity, d) + end end end end @@ -299,9 +338,11 @@ local function map_gen_action(data) repeat count = count - 1 + do_tile(y, x, data, shape) x = x + 1 + if x == max_x then y = y + 1 if y == data.top_y + 32 then @@ -365,6 +406,8 @@ function Public.schedule_chunk(event) local area = event.area local data = { + yv = 0, + xv = 0, y = 0, x = area.left_top.x, area = area, @@ -403,6 +446,8 @@ function Public.do_chunk(event) local area = event.area local data = { + yv = 0, + xv = 1, area = area, top_x = area.left_top.x, top_y = area.left_top.y, @@ -434,6 +479,15 @@ end local do_chunk = Public.do_chunk local schedule_chunk = Public.schedule_chunk +function Public.init(args) + if args then + tiles_per_call = args.tiles_per_call or 16 + regen_decoratives = args.regen_decoratives or false + end + + total_calls = math.ceil(1024 / tiles_per_call) +end + local function on_chunk(event) if force_chunk then do_chunk(event) @@ -445,5 +499,6 @@ local function on_chunk(event) end Event.add(defines.events.on_chunk_generated, on_chunk) +Public.init() return Public diff --git a/maps/mountain_fortress_v3/gui.lua b/maps/mountain_fortress_v3/gui.lua index 5e2b32e2..2a9ae451 100644 --- a/maps/mountain_fortress_v3/gui.lua +++ b/maps/mountain_fortress_v3/gui.lua @@ -1,26 +1,64 @@ +local Event = require 'utils.event' local RPG = require 'maps.mountain_fortress_v3.rpg' local WPT = require 'maps.mountain_fortress_v3.table' +local Gui = require 'utils.gui' local floor = math.floor local format_number = require 'util'.format_number -local function create_gui(player) +local Public = {} +local main_button_name = Gui.uid_name() +local main_frame_name = Gui.uid_name() + +local function validate_player(player) + if not player then + return false + end + if not player.valid then + return false + end + if not player.character then + return false + end + if not player.connected then + return false + end + if not game.players[player.name] then + return false + end + return true +end + +local function create_button(player) + player.gui.top.add( + { + type = 'sprite-button', + name = main_button_name, + sprite = 'item/dummy-steel-axe', + tooltip = 'Shows statistics!' + } + ) +end + +local function create_main_frame(player) local label local line + if player.gui.top['wave_defense'] then + player.gui.top['wave_defense'].visible = true + end - local frame = player.gui.top.add({type = 'frame', name = 'mountain_fortress_v3'}) + local frame = player.gui.top.add({type = 'frame', name = main_frame_name}) + frame.location = {x = 1, y = 40} frame.style.minimal_height = 38 frame.style.maximal_height = 38 label = frame.add({type = 'label', caption = ' ', name = 'label'}) label.style.font_color = {r = 0.88, g = 0.88, b = 0.88} label.style.font = 'default-bold' - label.style.font_color = {r = 0.33, g = 0.66, b = 0.9} label = frame.add({type = 'label', caption = ' ', name = 'global_pool'}) label.style.font_color = {r = 0.88, g = 0.88, b = 0.88} label.style.font = 'default-bold' label.style.right_padding = 4 - label.style.font_color = {r = 0.33, g = 0.66, b = 0.9} line = frame.add({type = 'line', direction = 'vertical'}) line.style.left_padding = 4 @@ -30,7 +68,6 @@ local function create_gui(player) label.style.font_color = {r = 0.88, g = 0.88, b = 0.88} label.style.font = 'default-bold' label.style.right_padding = 4 - label.style.font_color = {r = 0.33, g = 0.66, b = 0.9} line = frame.add({type = 'line', direction = 'vertical'}) line.style.left_padding = 4 @@ -40,7 +77,24 @@ local function create_gui(player) label.style.font_color = {r = 0.88, g = 0.88, b = 0.88} label.style.font = 'default-bold' label.style.right_padding = 4 - label.style.font_color = {r = 0.33, g = 0.66, b = 0.9} + + line = frame.add({type = 'line', direction = 'vertical'}) + line.style.left_padding = 4 + line.style.right_padding = 4 + + label = frame.add({type = 'label', caption = ' ', name = 'landmine'}) + label.style.font_color = {r = 0.88, g = 0.88, b = 0.88} + label.style.font = 'default-bold' + label.style.right_padding = 4 + + line = frame.add({type = 'line', direction = 'vertical'}) + line.style.left_padding = 4 + line.style.right_padding = 4 + + label = frame.add({type = 'label', caption = ' ', name = 'flame_turret'}) + label.style.font_color = {r = 0.88, g = 0.88, b = 0.88} + label.style.font = 'default-bold' + label.style.right_padding = 4 line = frame.add({type = 'line', direction = 'vertical'}) line.style.left_padding = 4 @@ -50,34 +104,158 @@ local function create_gui(player) label.style.font_color = {r = 0.88, g = 0.88, b = 0.88} label.style.font = 'default-bold' label.style.right_padding = 4 - label.style.font_color = {r = 0.33, g = 0.66, b = 0.9} end -local function update_gui(player) - local rpg = RPG.get_table() - local st = WPT.get() - - if not player.gui.top.mountain_fortress_v3 then - create_gui(player) +local function on_player_joined_game(event) + local player = game.players[event.player_index] + if not player then + return end - local gui = player.gui.top.mountain_fortress_v3 + + if not player.gui.top[main_button_name] then + create_button(player) + end +end + +local function on_gui_click(event) + local element = event.element + local player = game.players[event.player_index] + if not validate_player(player) then + return + end + if not element.valid then + return + end + + local locomotive = WPT.get('locomotive') + + local name = element.name + + if name == main_button_name then + if player.surface ~= locomotive.surface then + local s = player.gui.left.icw_map + if s and s.visible then + player.gui.left.icw_map.visible = false + return + elseif s and not s.visible then + player.gui.left.icw_map.visible = true + return + end + return + end + if player.gui.top[main_frame_name] then + local s = player.gui.top[main_frame_name] + if s and s.visible then + if player.gui.top['wave_defense'] then + player.gui.top['wave_defense'].visible = false + end + if player.gui.top['difficulty_gui'] then + player.gui.top['difficulty_gui'].visible = false + end + player.gui.top[main_frame_name].visible = false + return + elseif s and not s.visible then + for _, child in pairs(player.gui.left.children) do + child.destroy() + end + if player.gui.top['wave_defense'] then + player.gui.top['wave_defense'].visible = true + end + if player.gui.top['difficulty_gui'] then + player.gui.top['difficulty_gui'].visible = true + end + player.gui.top[main_frame_name].visible = true + return + end + else + for _, child in pairs(player.gui.left.children) do + child.destroy() + end + create_main_frame(player) + end + elseif name ~= main_button_name then + if player.gui.top[main_frame_name] then + local s = player.gui.top[main_frame_name] + if s and s.visible then + player.gui.top[main_frame_name].visible = false + return + end + end + end +end +local function on_player_changed_surface(event) + local player = game.players[event.player_index] + if not validate_player(player) then + return + end + + local locomotive = WPT.get('locomotive') + local loco_surface = WPT.get('loco_surface') + + if player.surface == locomotive.surface then + player.gui.top[main_button_name].tooltip = 'Shows statistics!' + player.gui.top[main_button_name].sprite = 'item/dummy-steel-axe' + elseif player.surface == loco_surface then + if player.gui.top['wave_defense'] then + player.gui.top['wave_defense'].visible = false + end + if player.gui.top['difficulty_gui'] then + player.gui.top['difficulty_gui'].visible = false + end + if player.gui.top[main_button_name] then + player.gui.top[main_button_name].tooltip = 'Hide locomotive minimap!' + player.gui.top[main_button_name].sprite = 'utility/map' + end + if player.gui.top[main_frame_name] then + local vis = player.gui.top[main_frame_name].visible + if vis then + player.gui.top[main_frame_name].visible = false + return + end + end + end +end + +function Public.update_gui(player) + local rpg = RPG.get_table() + local this = WPT.get() + + if not player.gui.top[main_frame_name] then + return + end + + if not player.gui.top[main_frame_name].visible then + return + end + local gui = player.gui.top[main_frame_name] if rpg.global_pool == 0 then gui.global_pool.caption = 'XP: 0' gui.global_pool.tooltip = 'Dig, handcraft or run to increase the pool!' elseif rpg.global_pool > 0 then gui.global_pool.caption = 'XP: ' .. format_number(floor(rpg.global_pool), true) - gui.global_pool.tooltip = 'Get this number over 5k to get some of this mad XP! \\o/' + gui.global_pool.tooltip = 'Amount of XP that is stored inside the global xp pool.' end - gui.scrap_mined.caption = ' [img=entity.tree-01][img=entity.rock-huge]: ' .. format_number(st.mined_scrap, true) + gui.scrap_mined.caption = ' [img=entity.tree-01][img=entity.rock-huge]: ' .. format_number(this.mined_scrap, true) gui.scrap_mined.tooltip = 'Amount of trees/rocks harvested.' - gui.biters_killed.caption = ' [img=entity.small-biter]: ' .. format_number(st.biters_killed, true) + gui.biters_killed.caption = ' [img=entity.small-biter]: ' .. format_number(this.biters_killed, true) gui.biters_killed.tooltip = 'Amount of biters killed.' - gui.train_upgrades.caption = ' [img=entity.locomotive]: ' .. format_number(st.train_upgrades, true) + gui.landmine.caption = ' [img=entity.land-mine]: ' .. format_number(this.upgrades.landmine.limit, true) + gui.landmine.tooltip = 'Amount of land-mines that can be built.' + + gui.flame_turret.caption = + ' [img=entity.flamethrower-turret]: ' .. format_number(this.upgrades.flame_turret.limit, true) + gui.flame_turret.tooltip = 'Amount of flamethrower-turrets that can be built.' + + gui.train_upgrades.caption = ' [img=entity.locomotive]: ' .. format_number(this.train_upgrades, true) gui.train_upgrades.tooltip = 'Amount of train upgrades.' end -return update_gui +Event.add(defines.events.on_player_joined_game, on_player_joined_game) +Event.add(defines.events.on_player_changed_surface, on_player_changed_surface) +Event.add(defines.events.on_gui_click, on_gui_click) + +return Public diff --git a/maps/mountain_fortress_v3/icw/functions.lua b/maps/mountain_fortress_v3/icw/functions.lua index 6f014be0..f00c3d72 100644 --- a/maps/mountain_fortress_v3/icw/functions.lua +++ b/maps/mountain_fortress_v3/icw/functions.lua @@ -89,7 +89,7 @@ end local function input_filtered(wagon_inventory, chest, chest_inventory, free_slots) local request_stacks = {} local prototypes = game.item_prototypes - for slot_index = 1, 4, 1 do + for slot_index = 1, 12, 1 do local stack = chest.get_request_slot(slot_index) if stack then request_stacks[stack.name] = 10 * prototypes[stack.name].stack_size @@ -389,10 +389,7 @@ function Public.create_wagon_room(icw, wagon) if wagon.entity.type == 'cargo-wagon' then local vectors = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}} local v = vectors[math_random(1, 4)] - local position = { - math_random(area.left_top.x + 4, area.right_bottom.x - 4), - math_random(area.left_top.y + 6, area.right_bottom.y - 6) - } + local position = {0, 30} local e = surface.create_entity( @@ -513,17 +510,26 @@ function Public.use_cargo_wagon_door(icw, player, door) local surface = wagon.entity.surface local x_vector = (door.position.x / math.abs(door.position.x)) * 2 local position = {wagon.entity.position.x + x_vector, wagon.entity.position.y} - local position = surface.find_non_colliding_position('character', position, 128, 0.5) + local surface_position = surface.find_non_colliding_position('character', position, 128, 0.5) if not position then return end + if not surface_position then + surface.request_to_generate_chunks({-20, 22}, 1) + if player.character and player.character.valid and player.character.driving then + if wagon.surface == player.surface then + player.character.driving = false + end + end + return + end if wagon.entity.type == 'locomotive' then - player.teleport(position, surface) + player.teleport(surface_position, surface) player_data.state = 2 player.driving = true Public.kill_minimap(player) else - player.teleport(position, surface) + player.teleport(surface_position, surface) Public.kill_minimap(player) end player_data.surface = surface.index diff --git a/maps/mountain_fortress_v3/icw/main.lua b/maps/mountain_fortress_v3/icw/main.lua index 6b4cecc2..a4516888 100644 --- a/maps/mountain_fortress_v3/icw/main.lua +++ b/maps/mountain_fortress_v3/icw/main.lua @@ -120,6 +120,7 @@ local function on_gui_opened(event) if not wagon then return end + Functions.draw_minimap( icw, game.players[event.player_index], diff --git a/maps/mountain_fortress_v3/locomotive.lua b/maps/mountain_fortress_v3/locomotive.lua index b1dc5735..0264d4b0 100644 --- a/maps/mountain_fortress_v3/locomotive.lua +++ b/maps/mountain_fortress_v3/locomotive.lua @@ -45,19 +45,21 @@ local function property_boost(data) if not validate_player(player) then return end - if Public.contains_positions(player.position, area) or player.surface.index == locomotive_surface.index then - local pos = player.position - RPG.gain_xp(player, 0.3 * (rpg[player.index].bonus + this.xp_points)) + if player.afk_time < 200 then + if Public.contains_positions(player.position, area) or player.surface.index == locomotive_surface.index then + local pos = player.position + RPG.gain_xp(player, 0.3 * (rpg[player.index].bonus + this.xp_points)) - player.create_local_flying_text { - text = '+' .. '', - position = {x = pos.x, y = pos.y - 2}, - color = xp_floating_text_color, - time_to_live = 60, - speed = 3 - } - rpg[player.index].xp_since_last_floaty_text = 0 - rpg[player.index].last_floaty_text = game.tick + visuals_delay + player.create_local_flying_text { + text = '+' .. '', + position = {x = pos.x, y = pos.y - 2}, + color = xp_floating_text_color, + time_to_live = 60, + speed = 3 + } + rpg[player.index].xp_since_last_floaty_text = 0 + rpg[player.index].last_floaty_text = game.tick + visuals_delay + end end end end @@ -157,17 +159,16 @@ function Public.boost_players_around_train() if not this.active_surface_index then return end - local surface = game.surfaces[this.active_surface_index] - local icw_table = ICW.get_table() - local unit_surface = this.locomotive.unit_number - local locomotive_surface = game.surfaces[icw_table.wagons[unit_surface].surface.index] - if not this.locomotive then return end if not this.locomotive.valid then return end + local surface = game.surfaces[this.active_surface_index] + local icw_table = ICW.get_table() + local unit_surface = this.locomotive.unit_number + local locomotive_surface = game.surfaces[icw_table.wagons[unit_surface].surface.index] local data = { this = this, @@ -182,27 +183,6 @@ function Public.render_train_hp() local this = WPT.get() local surface = game.surfaces[this.active_surface_index] - local names = { - 'Hanakocz', - 'Redlabel', - 'Hanakocz', - 'Gerkiz', - 'Hanakocz', - 'Mewmew', - 'Gerkiz', - 'Hanakocz', - 'Redlabel', - 'Gerkiz', - 'Hanakocz', - 'Redlabel', - 'Gerkiz', - 'Hanakocz' - } - - local size_of_names = #names - - local n = names[rnd(1, size_of_names)] - this.health_text = rendering.draw_text { text = 'HP: ' .. this.locomotive_health .. ' / ' .. this.locomotive_max_health, @@ -218,7 +198,7 @@ function Public.render_train_hp() this.caption = rendering.draw_text { - text = n .. 's Comfy Train', + text = 'Comfy Choo Choo', surface = surface, target = this.locomotive, target_offset = {0, -4.25}, @@ -299,6 +279,13 @@ function Public.locomotive_spawn(surface, position) this.loco_surface = locomotive.surface this.locomotive_index = locomotive + + local loco = this.loco_surface + + loco.request_to_generate_chunks({0, 19}, 1) + loco.force_generate_chunk_requests() + + game.forces.player.set_spawn_position({0, 19}, loco) end function Public.inside(pos, area) diff --git a/maps/mountain_fortress_v3/locomotive_market.lua b/maps/mountain_fortress_v3/locomotive_market.lua index ef234b21..087a0a2a 100644 --- a/maps/mountain_fortress_v3/locomotive_market.lua +++ b/maps/mountain_fortress_v3/locomotive_market.lua @@ -1,4 +1,5 @@ local Event = require 'utils.event' +local Server = require 'utils.server' local WPT = require 'maps.mountain_fortress_v3.table' local WD = require 'modules.wave_defense.table' local ICW = require 'maps.mountain_fortress_v3.icw.main' @@ -26,6 +27,8 @@ function Public.get_items() local health_cost = 30000 * (1 + this.health_upgrades) local aura_cost = 30000 * (1 + this.aura_upgrades) local xp_point_boost_cost = 30000 * (1 + this.xp_points_upgrade) + local flamethrower_turrets_cost = 7999 * (1 + this.upgrades.flame_turret.limit) + local land_mine_cost = 2 * (1 + this.upgrades.landmine.limit) local items = {} items['clear_threat_level'] = { @@ -60,6 +63,22 @@ function Public.get_items() sprite = 'item/computer', enabled = true } + items['flamethrower_turrets'] = { + stack = 1, + value = 'coin', + price = flamethrower_turrets_cost, + tooltip = 'Upgrades the amount of flamethrowers that can be placed.', + sprite = 'item/computer', + enabled = true + } + items['land_mine'] = { + stack = 1, + value = 'coin', + price = land_mine_cost, + tooltip = 'Upgrades the amount of landmines that can be placed.', + sprite = 'item/computer', + enabled = true + } items['small-lamp'] = {stack = 1, value = 'coin', price = 5, tooltip = 'Small Sunlight'} items['wood'] = {stack = 50, value = 'coin', price = 12, tooltip = 'Some fine Wood'} items['iron-ore'] = {stack = 50, value = 'coin', price = 12, tooltip = 'Some chunky iron'} @@ -71,16 +90,7 @@ function Public.get_items() items['raw-fish'] = {stack = 1, value = 'coin', price = 4, tooltip = 'Flappy Fish'} items['firearm-magazine'] = {stack = 1, value = 'coin', price = 5, tooltip = 'Firearm Pew'} items['crude-oil-barrel'] = {stack = 1, value = 'coin', price = 8, tooltip = 'Crude Oil Flame'} - -- - --[[ - items['loader'] = {stack = 1, value = 'coin', price = 150, tooltip = 'Ground Inserter.'} - items['fast-loader'] = { - stack = 1, - value = 'coin', - price = 300, - tooltip = 'Ground Fast Inserter' - } - ]] return items + return items end local space = { @@ -218,6 +228,66 @@ local function redraw_coins_left(gui, player) adjustSpace(coinsleft) end +local slot_upgrade_offers = { + [1] = {'gun-turret', 'gun turret'}, + [2] = {'laser-turret', 'laser turret'}, + [3] = {'artillery-turret', 'artillery turret'}, + [4] = {'flamethrower-turret', 'flamethrower turret'}, + [5] = {'land-mine', 'land mine'} +} + +local function slot_upgrade(player, offer_index) + local this = WPT.get() + + local data = this.players[player.index].data + if not data then + return + end + + local price = + this.entity_limits[slot_upgrade_offers[offer_index][1]].limit * + this.entity_limits[slot_upgrade_offers[offer_index][1]].slot_price + + local gain = 1 + if offer_index == 5 then + price = + math.ceil( + (this.entity_limits[slot_upgrade_offers[offer_index][1]].limit / 3) * + this.entity_limits[slot_upgrade_offers[offer_index][1]].slot_price + ) + gain = 3 + end + + if slot_upgrade_offers[offer_index][1] == 'flamethrower-turret' then + price = + (this.entity_limits[slot_upgrade_offers[offer_index][1]].limit + 1) * + this.entity_limits[slot_upgrade_offers[offer_index][1]].slot_price + end + + local coins_removed = player.remove_item({name = 'coin', count = price}) + if coins_removed ~= price then + if coins_removed > 0 then + player.insert({name = 'coin', count = coins_removed}) + end + player.print('Not enough coins.', {r = 0.22, g = 0.77, b = 0.44}) + return false + end + + this.entity_limits[slot_upgrade_offers[offer_index][1]].limit = + this.entity_limits[slot_upgrade_offers[offer_index][1]].limit + gain + game.print( + player.name .. ' has bought a ' .. slot_upgrade_offers[offer_index][2] .. ' slot for ' .. price .. ' coins!', + {r = 0.22, g = 0.77, b = 0.44} + ) + Server.to_discord_bold( + table.concat { + player.name .. ' has bought a ' .. slot_upgrade_offers[offer_index][2] .. ' slot for ' .. price .. ' coins!' + } + ) + redraw_market_items(data.item_frame, player, data.search_text) + redraw_coins_left(data.coins_left, player) +end + local function slider_changed(event) local player = game.players[event.player_index] local this = WPT.get() @@ -463,11 +533,21 @@ local function gui_click(event) player.remove_item({name = item.value, count = cost}) game.print( - shopkeeper .. ' ' .. player.name .. ' has bought the group some extra time. Threat level is reduced by 50%!', + shopkeeper .. + ' ' .. + player.name .. + ' has bought the clear threat modifier for ' .. + cost .. ' coins. Threat level is reduced by 50%!', {r = 0.98, g = 0.66, b = 0.22} ) - this.threat_upgrades = this.threat_upgrades + 1 - wdt.threat = wdt.threat / 2 + Server.to_discord_bold( + table.concat { + player.name .. + ' has bought the clear threat modifier for ' .. cost .. ' coins. Threat level is reduced by 50%!' + } + ) + this.threat_upgrades = this.threat_upgrades + item_count + wdt.threat = wdt.threat / 2 * item_count redraw_market_items(data.item_frame, player, data.search_text) redraw_coins_left(data.coins_left, player) @@ -479,14 +559,24 @@ local function gui_click(event) game.print( shopkeeper .. - ' ' .. player.name .. ' has bought the group a train health modifier! The train health is now buffed!', + ' ' .. + player.name .. + ' has bought the locomotive health modifier for ' .. + cost .. ' coins. The train health is now buffed.', {r = 0.98, g = 0.66, b = 0.22} ) - this.locomotive_max_health = this.locomotive_max_health + 2500 + Server.to_discord_bold( + table.concat { + player.name .. + ' has bought the locomotive health modifier for ' .. + cost .. ' coins. The train health is now buffed.' + } + ) + this.locomotive_max_health = this.locomotive_max_health + 2500 * item_count local m = this.locomotive_health / this.locomotive_max_health this.locomotive.health = 1000 * m - this.train_upgrades = this.train_upgrades + 1 - this.health_upgrades = this.health_upgrades + 1 + this.train_upgrades = this.train_upgrades + item_count + this.health_upgrades = this.health_upgrades + item_count rendering.set_text(this.health_text, 'HP: ' .. this.locomotive_health .. ' / ' .. this.locomotive_max_health) redraw_market_items(data.item_frame, player, data.search_text) @@ -498,12 +588,22 @@ local function gui_click(event) player.remove_item({name = item.value, count = cost}) game.print( - shopkeeper .. ' ' .. player.name .. ' has bought the group a XP aura modifier! The XP aura is now buffed!', + shopkeeper .. + ' ' .. + player.name .. + ' has bought the locomotive xp aura modifier for ' .. + cost .. ' coins. The XP aura is now buffed.', {r = 0.98, g = 0.66, b = 0.22} ) + Server.to_discord_bold( + table.concat { + player.name .. + ' has bought the locomotive xp aura modifier for ' .. cost .. ' coins. The XP aura is now buffed.' + } + ) this.locomotive_xp_aura = this.locomotive_xp_aura + 5 - this.aura_upgrades = this.aura_upgrades + 1 - this.train_upgrades = this.train_upgrades + 1 + this.aura_upgrades = this.aura_upgrades + item_count + this.train_upgrades = this.train_upgrades + item_count if this.circle then rendering.destroy(this.circle) @@ -529,12 +629,20 @@ local function gui_click(event) game.print( shopkeeper .. - ' ' .. player.name .. ' has bought the group a XP point modifier! You now gain more XP points!', + ' ' .. + player.name .. + ' has bought the xp point modifier for ' .. cost .. ' coins. You now gain more XP points.', {r = 0.98, g = 0.66, b = 0.22} ) + Server.to_discord_bold( + table.concat { + player.name .. + ' has bought the xp point modifier for ' .. cost .. ' coins. You now gain more XP points.' + } + ) this.xp_points = this.xp_points + 0.5 - this.xp_points_upgrade = this.xp_points_upgrade + 1 - this.train_upgrades = this.train_upgrades + 1 + this.xp_points_upgrade = this.xp_points_upgrade + item_count + this.train_upgrades = this.train_upgrades + item_count redraw_market_items(data.item_frame, player, data.search_text) redraw_coins_left(data.coins_left, player) @@ -542,6 +650,70 @@ local function gui_click(event) return end + if name == 'flamethrower_turrets' then + player.remove_item({name = item.value, count = cost}) + if item_count >= 1 then + game.print( + shopkeeper .. ' ' .. player.name .. ' has bought a flamethrower-turret slot for ' .. cost .. ' coins.', + {r = 0.98, g = 0.66, b = 0.22} + ) + Server.to_discord_bold( + table.concat { + player.name .. ' has bought a flamethrower-turret slot for ' .. cost .. ' coins.' + } + ) + else + game.print( + shopkeeper .. + ' ' .. + player.name .. + ' has bought ' .. item_count .. ' flamethrower-turret slots for ' .. cost .. ' coins.', + {r = 0.98, g = 0.66, b = 0.22} + ) + Server.to_discord_bold( + table.concat { + player.name .. + ' has bought ' .. item_count .. ' flamethrower-turret slots for ' .. cost .. ' coins.' + } + ) + end + this.upgrades.flame_turret.limit = this.upgrades.flame_turret.limit + item_count + + redraw_market_items(data.item_frame, player, data.search_text) + redraw_coins_left(data.coins_left, player) + + return + end + if name == 'land_mine' then + player.remove_item({name = item.value, count = cost}) + + if item_count >= 1 then + game.print( + shopkeeper .. ' ' .. player.name .. ' has bought a landmine slot for ' .. cost .. ' coins.', + {r = 0.98, g = 0.66, b = 0.22} + ) + else + game.print( + shopkeeper .. + ' ' .. player.name .. ' has bought ' .. item_count .. ' landmine slots for ' .. cost .. ' coins.', + {r = 0.98, g = 0.66, b = 0.22} + ) + if cost > 5000 then + Server.to_discord_bold( + table.concat { + player.name .. ' has bought ' .. item_count .. ' landmine slots for ' .. cost .. ' coins.' + } + ) + end + end + + this.upgrades.landmine.limit = this.upgrades.landmine.limit + item_count + + redraw_market_items(data.item_frame, player, data.search_text) + redraw_coins_left(data.coins_left, player) + return + end + if player_item_count >= cost then if player.can_insert({name = name, count = item_count}) then player.play_sound({path = 'entity-close/stone-furnace', volume_modifier = 0.65}) @@ -637,7 +809,8 @@ local function create_market(data, rebuild) text = 'Market', surface = surface, target = this.market, - target_offset = {0, 2}, + scale = 1.5, + target_offset = {0, -2}, color = {r = 0.98, g = 0.66, b = 0.22}, alignment = 'center' } @@ -650,9 +823,15 @@ local function create_market(data, rebuild) end local position = this.loco_surface.find_non_colliding_position('market', center_position, 128, 0.5) + local biters = { + 'big-biter', + 'behemoth-biter', + 'big-spitter', + 'behemoth-spitter' + } local e = this.loco_surface.create_entity( - {name = 'big-biter', position = position, force = 'player', create_build_effect_smoke = false} + {name = biters[random(1, 4)], position = position, force = 'player', create_build_effect_smoke = false} ) e.ai_settings.allow_destroy_when_commands_fail = false e.ai_settings.allow_try_return_to_spawner = false diff --git a/maps/mountain_fortress_v3/loot.lua b/maps/mountain_fortress_v3/loot.lua index d67e49fe..be942e6f 100644 --- a/maps/mountain_fortress_v3/loot.lua +++ b/maps/mountain_fortress_v3/loot.lua @@ -6,6 +6,7 @@ local math_abs = math.abs local math_floor = math.floor local blacklist = { + ['atomic-bomb'] = true, ['cargo-wagon'] = true, ['locomotive'] = true, ['artillery-wagon'] = true, diff --git a/maps/mountain_fortress_v3/main.lua b/maps/mountain_fortress_v3/main.lua index 0067b0e3..adf50a72 100644 --- a/maps/mountain_fortress_v3/main.lua +++ b/maps/mountain_fortress_v3/main.lua @@ -1,25 +1,8 @@ --- modules -require 'maps.mountain_fortress_v3.generate' -require 'maps.mountain_fortress_v3.player_list' -require 'maps.mountain_fortress_v3.commands' -require 'maps.mountain_fortress_v3.flamethrower_nerf' - -require 'modules.dynamic_landfill' -require 'modules.shotgun_buff' -require 'modules.rocks_heal_over_time' -require 'modules.no_deconstruction_of_neutral_entities' -require 'modules.rocks_yield_ore_veins' -require 'modules.spawners_contain_biters' -require 'modules.biters_yield_coins' -require 'modules.wave_defense.main' -require 'modules.pistol_buffs' -require 'modules.mineable_wreckage_yields_scrap' - local CS = require 'maps.mountain_fortress_v3.surface' local Server = require 'utils.server' local Explosives = require 'modules.explosives' local Entities = require 'maps.mountain_fortress_v3.entities' -local update_gui = require 'maps.mountain_fortress_v3.gui' +local Gui_mf = require 'maps.mountain_fortress_v3.gui' local ICW = require 'maps.mountain_fortress_v3.icw.main' local WD = require 'modules.wave_defense.table' local Map = require 'modules.map_info' @@ -35,6 +18,24 @@ local Collapse = require 'modules.collapse' local Difficulty = require 'modules.difficulty_vote' local Task = require 'utils.task' +require 'maps.mountain_fortress_v3.biter_corpse_remover' +require 'maps.mountain_fortress_v3.generate' +require 'maps.mountain_fortress_v3.player_list' +require 'maps.mountain_fortress_v3.commands' +require 'maps.mountain_fortress_v3.breached_wall' +require 'maps.mountain_fortress_v3.ore_generator' + +require 'modules.dynamic_landfill' +require 'modules.shotgun_buff' +require 'modules.rocks_heal_over_time' +require 'modules.no_deconstruction_of_neutral_entities' +require 'modules.rocks_yield_ore_veins' +require 'modules.spawners_contain_biters' +require 'modules.biters_yield_coins' +require 'modules.wave_defense.main' +require 'modules.pistol_buffs' +require 'modules.mineable_wreckage_yields_scrap' + local Public = {} local starting_items = {['pistol'] = 1, ['firearm-magazine'] = 16, ['rail'] = 16, ['wood'] = 16, ['explosives'] = 32} @@ -194,16 +195,15 @@ function Public.reset_map() disable_tech() local surface = game.surfaces[this.active_surface_index] - surface.min_brightness = 0.5 Explosives.set_surface_whitelist({[surface.name] = true}) - surface.request_to_generate_chunks({-17, 47}, 1) - surface.force_generate_chunk_requests() - game.forces.player.set_spawn_position({-27, 25}, surface) - game.forces.enemy.set_ammo_damage_modifier('bullet', 1) - game.forces.enemy.set_turret_attack_modifier('gun-turret', 1) + + game.forces.enemy.technologies['artillery-shell-range-1'].researched = true + game.forces.enemy.technologies['refined-flammables-1'].researched = true + game.forces.enemy.technologies['refined-flammables-2'].researched = true + game.forces.enemy.technologies['energy-weapons-damage-1'].researched = true global.bad_fire_history = {} global.friendly_fire_history = {} @@ -212,13 +212,14 @@ function Public.reset_map() get_score.score_table = {} Diff.difficulty_poll_closing_timeout = game.tick + 90000 Diff.difficulty_player_votes = {} + Diff.gui_width = 20 Collapse.set_kill_entities(false) Collapse.set_speed(8) Collapse.set_amount(1) Collapse.set_max_line_size(Terrain.level_width) Collapse.set_surface(surface) - Collapse.set_position({0, 162}) + Collapse.set_position({0, 130}) Collapse.set_direction('north') Collapse.start_now(false) @@ -241,10 +242,18 @@ function Public.reset_map() set_difficulty() - Task.start_queue() - Task.set_queue_speed(2) + if not surface.is_chunk_generated({-20, 22}) then + surface.request_to_generate_chunks({-20, 22}, 0.1) + surface.force_generate_chunk_requests() + surface.set_chunk_generated_status({-20, 22}, defines.chunk_generated_status.custom_tiles) + end - this.chunk_load_tick = game.tick + 500 + game.forces.player.set_spawn_position({-27, 25}, surface) + + Task.start_queue() + Task.set_queue_speed(4) + + this.chunk_load_tick = game.tick + 800 end local function on_player_changed_position(event) @@ -274,8 +283,8 @@ end local function on_player_joined_game(event) local this = WPT.get() - local surface = game.surfaces[this.active_surface_index] local player = game.players[event.player_index] + local surface = game.surfaces[this.active_surface_index] set_difficulty(event) @@ -294,18 +303,30 @@ local function on_player_joined_game(event) player.print('Greetings, ' .. player.name .. '!', {r = 0.98, g = 0.66, b = 0.22}) player.print('Please read the map info.', {r = 0.98, g = 0.66, b = 0.22}) this.players[player.index].first_join = true + for item, amount in pairs(starting_items) do + player.insert({name = item, count = amount}) + end end if player.surface.index ~= this.active_surface_index then - if not player.character then - player.create_character() - end player.teleport( surface.find_non_colliding_position('character', game.forces.player.get_spawn_position(surface), 3, 0, 5), surface ) - for item, amount in pairs(starting_items) do - player.insert({name = item, count = amount}) + else + local p = {x = player.position.x, y = player.position.y} + local oom = surface.get_tile(p).name == 'out-of-map' + if oom then + player.teleport( + surface.find_non_colliding_position( + 'character', + game.forces.player.get_spawn_position(surface), + 3, + 0, + 5 + ), + surface + ) end end end @@ -317,20 +338,32 @@ end local function on_pre_player_left_game(event) local this = WPT.get() local player = game.players[event.player_index] - if player.controller_type == defines.controllers.editor then - player.toggle_map_editor() - end + local tick if player.character then + if this.offline_players_enabled then + tick = game.tick + 432000 + else + tick = game.tick + end this.offline_players[#this.offline_players + 1] = { index = event.player_index, name = player.name, - tick = game.tick + tick = tick } end end local function remove_offline_players() local this = WPT.get() + if not this.offline_players_enabled then + if game.tick < 500 then + return + end + if game.tick % 432000 == 0 then + this.offline_players_enabled = true + end + return + end local offline_players = WPT.get('offline_players') local active_surface_index = WPT.get('active_surface_index') local surface = game.surfaces[active_surface_index] @@ -424,17 +457,36 @@ end local function on_research_finished(event) disable_recipes() - event.research.force.character_inventory_slots_bonus = game.forces.player.mining_drill_productivity_bonus * 50 -- +5 Slots / level + local research = event.research + local this = WPT.get() + + research.force.character_inventory_slots_bonus = game.forces.player.mining_drill_productivity_bonus * 50 -- +5 Slots / level local mining_speed_bonus = game.forces.player.mining_drill_productivity_bonus * 5 -- +50% speed / level - if event.research.force.technologies['steel-axe'].researched then + if research.force.technologies['steel-axe'].researched then mining_speed_bonus = mining_speed_bonus + 0.5 end -- +50% speed for steel-axe research - event.research.force.manual_mining_speed_modifier = mining_speed_bonus + research.force.manual_mining_speed_modifier = mining_speed_bonus + + local force_name = research.force.name + if not force_name then + return + end + this.flamethrower_damage[force_name] = -0.65 + if research.name == 'military' then + game.forces[force_name].set_turret_attack_modifier('flamethrower-turret', this.flamethrower_damage[force_name]) + game.forces[force_name].set_ammo_damage_modifier('flamethrower', this.flamethrower_damage[force_name]) + end + + if string.sub(research.name, 0, 18) == 'refined-flammables' then + this.flamethrower_damage[force_name] = this.flamethrower_damage[force_name] + 0.10 + game.forces[force_name].set_turret_attack_modifier('flamethrower-turret', this.flamethrower_damage[force_name]) + game.forces[force_name].set_ammo_damage_modifier('flamethrower', this.flamethrower_damage[force_name]) + end end local function is_locomotive_valid() - local this = WPT.get() - if not this.locomotive.valid then + local locomotive = WPT.get('locomotive') + if not locomotive.valid then Entities.loco_died() end end @@ -447,13 +499,10 @@ local function has_the_game_ended() this.game_reset_tick = nil Public.reset_map() else - if not this.reset_the_game then - game.print('Auto reset is disabled. Server is shutting down!', {r = 0.22, g = 0.88, b = 0.22}) - local message = 'Auto reset is disabled. Server is shutting down!' - Server.to_discord_bold(table.concat {'*** ', message, ' ***'}) - Server.stop_scenario() - this.reset_the_game = true - end + game.print('Auto reset is disabled. Server is shutting down!', {r = 0.22, g = 0.88, b = 0.22}) + local message = 'Auto reset is disabled. Server is shutting down!' + Server.to_discord_bold(table.concat {'*** ', message, ' ***'}) + Server.stop_scenario() end end return @@ -461,11 +510,11 @@ local function has_the_game_ended() end local function chunk_load() - local this = WPT.get() - if this.chunk_load_tick then - if this.chunk_load_tick < game.tick then - this.chunk_load_tick = nil - Task.set_queue_speed(0.8) + local chunk_load_tick = WPT.get('chunk_load_tick') + if chunk_load_tick then + if chunk_load_tick < game.tick then + WPT.get().chunk_load_tick = nil + Task.set_queue_speed(0.5) end end end @@ -474,24 +523,26 @@ local on_tick = function() local active_surface_index = WPT.get('active_surface_index') local surface = game.surfaces[active_surface_index] local wave_defense_table = WD.get_table() + local update_gui = Gui_mf.update_gui if game.tick % 30 == 0 then for _, player in pairs(game.connected_players) do update_gui(player) end + is_locomotive_valid() + has_the_game_ended() + chunk_load() + if game.tick % 1800 == 0 then + remove_offline_players() + Entities.set_scores() local collapse_pos = Collapse.get_position() local position = surface.find_non_colliding_position('stone-furnace', collapse_pos, 128, 1) if position then wave_defense_table.spawn_position = position end - remove_offline_players() - Entities.set_scores() end - is_locomotive_valid() - has_the_game_ended() - chunk_load() end end @@ -501,6 +552,36 @@ local on_init = function() global.custom_highscore.description = 'Wagon distance reached:' + local difficulties = { + [1] = { + name = 'Easy', + value = 0.75, + color = {r = 0.00, g = 0.25, b = 0.00}, + print_color = {r = 0.00, g = 0.4, b = 0.00} + }, + [2] = { + name = 'Normal', + value = 1, + color = {r = 0.00, g = 0.00, b = 0.25}, + print_color = {r = 0.0, g = 0.0, b = 0.5} + }, + [3] = { + name = 'Hard', + value = 1.5, + color = {r = 0.25, g = 0.00, b = 0.00}, + print_color = {r = 0.4, g = 0.0, b = 0.00} + } + } + + local tooltip = { + [1] = 'Makes the game really easy.\nDo note that wave_defense is still based on amount of players.\nAnd what difficulty you pick.', + [2] = 'Normal Mountain Fortress game-play.\nDo note that wave_defense is still based on amount of players.\nAnd what difficulty you pick.', + [3] = "Are you sure? It won't be easy.\nDo note that wave_defense is still based on amount of players.\nAnd what difficulty you pick." + } + + Difficulty.set_difficulties(difficulties) + Difficulty.set_tooltip(tooltip) + this.rocks_yield_ore_maximum_amount = 500 this.type_modifier = 1 this.rocks_yield_ore_base_amount = 50 @@ -517,6 +598,7 @@ local on_init = function() Explosives.set_destructible_tile('deepwater-green', 1000) Explosives.set_destructible_tile('deepwater', 1000) Explosives.set_destructible_tile('water-shallow', 1000) + Explosives.set_destructible_tile('water-mud', 1000) end Event.on_nth_tick(10, on_tick) diff --git a/maps/mountain_fortress_v3/ore_generator.lua b/maps/mountain_fortress_v3/ore_generator.lua new file mode 100644 index 00000000..1a6c04e0 --- /dev/null +++ b/maps/mountain_fortress_v3/ore_generator.lua @@ -0,0 +1,75 @@ +local Event = require 'utils.event' +local WPT = require 'maps.mountain_fortress_v3.table' + +local function spawn_ores(surface, position, resource, amount) + local radius = math.floor(amount ^ 0.24) + for x = position.x - radius, position.x + radius do + for y = position.y - radius, position.y + radius do + local intensity = math.floor(radius ^ 2 - (position.x - x) ^ 2 - (position.y - y) ^ 2) + if intensity > 0 then + local corrected_pos = surface.find_non_colliding_position('iron-ore', {x, y}, 5, 1) + if corrected_pos ~= nil then + surface.create_entity { + name = resource, + position = corrected_pos, + amount = intensity, + enable_tree_removal = false, + enable_cliff_removal = false + } + end + end + end + end + local miners = + surface.find_entities_filtered { + type = 'mining-drill', + area = {{position.x - radius, position.y - radius}, {position.x + radius, position.y + radius}} + } + for k, v in pairs(miners) do + v.active = false + v.active = true + end +end + +local function generate() + if game.tick % 216000 ~= 25200 then + return + end + local ore_loot = WPT.get('ore_loot') + local market = WPT.get('market') + if not market then + return + end + if not market.valid then + return + end + local force = game.forces.player + local item = math.random(1, 3) + item = ore_loot.ore_list[item] + if force and force.valid then + for _, surface_list in pairs(force.logistic_networks) do + for _, network in pairs(surface_list) do + if network and network.valid then + if network.get_item_count(item) < 1500000000 and network.get_item_count(item) >= ore_loot.limit then + local cell = network.cells[math.random(#network.cells)] + if cell and cell.valid and cell.owner and cell.owner.valid then + local least = {'iron-ore', 1000000000} + for k, v in pairs(ore_loot.ore_list) do + if least[2] > network.get_item_count(v) then + least[1], least[2] = v, network.get_item_count(v) + end + end + local res = least[1] + local amount = math.floor(network.get_item_count(item) / ore_loot.divisor) + spawn_ores(market.surface, market.position, res, amount * 20) + network.remove_item {name = item, count = amount} + game.print('The market has been blessed by the god of industry.') + end + end + end + end + end + end +end + +Event.add(defines.events.on_tick, generate) diff --git a/maps/mountain_fortress_v3/power.lua b/maps/mountain_fortress_v3/power.lua deleted file mode 100644 index 6d48dddb..00000000 --- a/maps/mountain_fortress_v3/power.lua +++ /dev/null @@ -1,67 +0,0 @@ -local Event = require 'utils.event' -local WPT = require 'maps.mountain_fortress_v3.table' - -local function balance(t) - local g = 0 - local c = 0 - for k, v in pairs(t) do - if (v.valid) then - g = g + v.energy - c = c + v.electric_buffer_size - end - end - for k, v in pairs(t) do - if (v.valid) then - local r = (v.electric_buffer_size / c) - v.energy = g * r - end - end -end - -local function tick() - local this = WPT.get() - if not this.energy['mountain_fortress_v3'] then - this.energy['mountain_fortress_v3'] = this.ow_energy - end - - if not this.energy['loco'] then - this.energy['loco'] = this.lo_energy - end - - local mountain_fortress_v3 = this.energy['mountain_fortress_v3'] - local loco = this.energy['loco'] - if not mountain_fortress_v3 or not loco then - return - end - if not mountain_fortress_v3.valid or not loco.valid then - return - end - balance(this.energy) -end - -local function built_entity(event) - local entity = event.created_entity - if not entity.valid then - return - end - local player = game.players[event.player_index] - local surface = entity.surface - local map_name = 'mountain_fortress_v3' - - if surface.name ~= map_name then - return - end - if - entity.name == 'steam-engine' or entity.name == 'steam-turbine' or entity.name == 'lab' or - entity.name == 'rocket-silo' - then - if not entity.valid then - return - end - player.print('"' .. entity.name .. '" Does not seem to work down here, thats strange!', {r = 1, g = 0, b = 0}) - entity.active = false - end -end - -Event.add(defines.events.on_tick, tick) ---Event.add(defines.events.on_built_entity, built_entity) diff --git a/maps/mountain_fortress_v3/rpg.lua b/maps/mountain_fortress_v3/rpg.lua index 0c642676..02ebf36b 100644 --- a/maps/mountain_fortress_v3/rpg.lua +++ b/maps/mountain_fortress_v3/rpg.lua @@ -17,8 +17,6 @@ require 'player_modifiers' local Global = require 'utils.global' local Tabs = require 'comfy_panel.main' local P = require 'player_modifiers' -local Collapse = require 'modules.collapse' -local Terrain = require 'maps.mountain_fortress_v3.terrain' local math_floor = math.floor local math_random = math.random @@ -37,7 +35,14 @@ local reset_tooltip = 'ONE-TIME reset if you picked the wrong path (this will ke local reset_not_available = 'ONE-TIME reset if you picked the wrong path (this will keep your points)\nAvailable after level 50.' +local teller = '[color=blue]Global Pool Reward:[/color]' + local rpg_t = {} +local rpg_extra = { + debug = false, + breached_walls = 1, + reward_new_players = 0 +} local rpg_frame_icons = { 'entity/small-worm-turret', 'entity/medium-worm-turret', @@ -58,10 +63,11 @@ local rpg_frame_icons = { } Global.register( - {rpg_t = rpg_t, rpg_frame_icons = rpg_frame_icons}, + {rpg_t = rpg_t, rpg_frame_icons = rpg_frame_icons, rpg_extra = rpg_extra}, function(tbl) rpg_t = tbl.rpg_t rpg_frame_icons = tbl.rpg_frame_icons + rpg_extra = tbl.rpg_extra end ) @@ -71,10 +77,29 @@ function Public.get_table() return rpg_t end +function Public.get_extra_table() + return rpg_extra +end + +function Public.toggle_debug() + if rpg_extra.debug then + rpg_extra.debug = false + else + rpg_extra.debug = true + end +end + +function Public.debug_log(str) + if not rpg_extra.debug then + return + end + print(str) +end + local classes = { ['engineer'] = 'ENGINEER', ['strength'] = 'MINER', - ['magic'] = 'SORCERER', + ['magicka'] = 'SORCERER', ['dexterity'] = 'ROGUE', ['vitality'] = 'TANK' } @@ -207,10 +232,10 @@ local function update_player_stats(player) local player_modifiers = P.get_table() local strength = rpg_t[player.index].strength - 10 player_modifiers[player.index].character_inventory_slots_bonus['rpg'] = math.round(strength * 0.2, 3) - player_modifiers[player.index].character_mining_speed_modifier['rpg'] = math.round(strength * 0.008, 3) + player_modifiers[player.index].character_mining_speed_modifier['rpg'] = math.round(strength * 0.007, 3) player_modifiers[player.index].character_maximum_following_robot_count_bonus['rpg'] = math.round(strength * 0.2, 3) - local magic = rpg_t[player.index].magic - 10 + local magic = rpg_t[player.index].magicka - 10 local v = magic * 0.22 player_modifiers[player.index].character_build_distance_bonus['rpg'] = math.round(v * 0.25, 3) player_modifiers[player.index].character_item_drop_distance_bonus['rpg'] = math.round(v * 0.25, 3) @@ -220,7 +245,7 @@ local function update_player_stats(player) player_modifiers[player.index].character_resource_reach_distance_bonus['rpg'] = math.round(v * 0.15, 3) local dexterity = rpg_t[player.index].dexterity - 10 - player_modifiers[player.index].character_running_speed_modifier['rpg'] = math.round(dexterity * 0.002, 3) + player_modifiers[player.index].character_running_speed_modifier['rpg'] = math.round(dexterity * 0.0015, 3) player_modifiers[player.index].character_crafting_speed_modifier['rpg'] = math.round(dexterity * 0.015, 3) player_modifiers[player.index].character_health_bonus['rpg'] = @@ -231,12 +256,12 @@ end local function get_class(player) local average = - (rpg_t[player.index].strength + rpg_t[player.index].magic + rpg_t[player.index].dexterity + + (rpg_t[player.index].strength + rpg_t[player.index].magicka + rpg_t[player.index].dexterity + rpg_t[player.index].vitality) / 4 local high_attribute = 0 local high_attribute_name = '' - for _, attribute in pairs({'strength', 'magic', 'dexterity', 'vitality'}) do + for _, attribute in pairs({'strength', 'magicka', 'dexterity', 'vitality'}) do if rpg_t[player.index][attribute] > high_attribute then high_attribute = rpg_t[player.index][attribute] high_attribute_name = attribute @@ -383,9 +408,9 @@ local function draw_gui(player, forced) local tip = 'Increases reach distance.' local e = add_gui_description(tt, 'MAGIC', w1) e.tooltip = tip - local e = add_gui_stat(tt, rpg_t[player.index].magic, w2) + local e = add_gui_stat(tt, rpg_t[player.index].magicka, w2) e.tooltip = tip - add_gui_increase_stat(tt, 'magic', player) + add_gui_increase_stat(tt, 'magicka', player) local tip = 'Increases running and crafting speed.' local e = add_gui_description(tt, 'DEXTERITY', w1) @@ -591,9 +616,12 @@ local function level_up(player) end function Public.gain_xp(player, amount) + Public.debug_log('RPG - ' .. player.name .. ' got org xp: ' .. amount) local fee = amount * 0.3 + Public.debug_log('RPG - ' .. player.name .. ' got fee: ' .. fee) rpg_t.global_pool = rpg_t.global_pool + fee amount = math_round(amount, 3) - fee + Public.debug_log('RPG - ' .. player.name .. ' got after fee: ' .. amount) rpg_t[player.index].xp = rpg_t[player.index].xp + amount rpg_t[player.index].xp_since_last_floaty_text = rpg_t[player.index].xp_since_last_floaty_text + amount if player.gui.left.rpg then @@ -622,24 +650,30 @@ end local function global_pool() local pool = rpg_t.global_pool - if pool <= 5000 then + local random_amount = math_random(5000, 10000) + if pool <= random_amount then return end local player_count = #game.connected_players local share = pool / player_count - rpg_t.global_pool = 0 + Public.debug_log('RPG - Share per player:' .. share) for _, p in pairs(game.connected_players) do - p.create_local_flying_text { - text = '+' .. math_floor(share) .. ' xp', - position = p.position, - color = xp_floating_text_color, - time_to_live = 240, - speed = 1 - } - rpg_t[p.index].xp_since_last_floaty_text = 0 - Public.gain_xp(p, share) - xp_effects(p) + if p.afk_time < 5000 then + p.create_local_flying_text { + text = '+' .. math_floor(share) .. ' xp', + position = p.position, + color = xp_floating_text_color, + time_to_live = 240, + speed = 1 + } + rpg_t[p.index].xp_since_last_floaty_text = 0 + Public.gain_xp(p, share) + xp_effects(p) + else + game.print(teller .. ' ' .. p.name .. ' received nothing. Reason: AFK') + end end + rpg_t.global_pool = 0 return end @@ -660,14 +694,14 @@ function Public.rpg_reset_player(player, one_time_reset) level = 1, xp = 0, strength = 10, - magic = 10, + magicka = 10, dexterity = 10, vitality = 10, points_to_distribute = 0, last_floaty_text = visuals_delay, xp_since_last_floaty_text = 0, reset = true, - bonus = 1, + bonus = rpg_extra.breached_walls or 1, rotated_entity_delay = 0, gui_refresh_delay = 0, last_mined_entity_position = {x = 0, y = 0} @@ -680,10 +714,10 @@ function Public.rpg_reset_player(player, one_time_reset) level = 1, xp = 0, strength = 10, - magic = 10, + magicka = 10, dexterity = 10, vitality = 10, - points_to_distribute = 5, + points_to_distribute = 0, last_floaty_text = visuals_delay, xp_since_last_floaty_text = 0, reset = false, @@ -707,6 +741,9 @@ function Public.rpg_reset_all_players() for _, p in pairs(game.connected_players) do Public.rpg_reset_player(p) end + rpg_extra.breached_walls = 1 + rpg_extra.reward_new_players = 0 + rpg_t.global_pool = 0 end local function on_gui_click(event) @@ -1111,29 +1148,6 @@ local function on_player_rotated_entity(event) Public.gain_xp(player, 0.20) end -local function distance(player) - local distance_to_center = math_floor(math_sqrt(player.position.x ^ 2 + player.position.y ^ 2)) - local location = distance_to_center - if location < Terrain.level_depth - 10 then - return - end - local min = Terrain.level_depth * rpg_t[player.index].bonus - local max = Terrain.level_depth + 5 * rpg_t[player.index].bonus - local min_times = location >= min - local max_times = location <= max - if min_times and max_times then - if not Collapse.start_now() then - Collapse.start_now(true) - game.print('[color=blue]Mapkeeper:[/color] Warning, collapse has begun!') - end - local level = rpg_t[player.index].bonus - rpg_t[player.index].bonus = rpg_t[player.index].bonus + 1 - player.print('[color=blue]Mapkeeper:[/color] Survivor! Well done. You have completed level: ' .. level) - Public.gain_xp(player, 300 * rpg_t[player.index].bonus) - return - end -end - local function on_player_changed_position(event) local player = game.players[event.player_index] local map_name = 'mountain_fortress_v3' @@ -1142,7 +1156,6 @@ local function on_player_changed_position(event) return end - distance(player) if math_random(1, 64) ~= 1 then return end @@ -1203,11 +1216,8 @@ local function on_player_crafted_item(event) if not player.valid then return end - local distance_multiplier = math_floor(math_sqrt(player.position.x ^ 2 + player.position.y ^ 2)) * 0.0005 + 1 - local amount = 0.30 * distance_multiplier - if amount >= 2 then - amount = 2 - end + local amount = 0.30 * math_random(1, 2) + Public.gain_xp(player, event.recipe.energy * amount) end @@ -1225,6 +1235,9 @@ local function on_player_joined_game(event) local player = game.players[event.player_index] if not rpg_t[player.index] then Public.rpg_reset_player(player) + if rpg_extra.reward_new_players > 10 then + Public.gain_xp(player, rpg_extra.reward_new_players) + end end for _, p in pairs(game.connected_players) do draw_level_text(p) diff --git a/maps/mountain_fortress_v3/surface.lua b/maps/mountain_fortress_v3/surface.lua index 16e994f4..ab88efba 100644 --- a/maps/mountain_fortress_v3/surface.lua +++ b/maps/mountain_fortress_v3/surface.lua @@ -53,18 +53,11 @@ function Public.create_surface() if not this.active_surface_index then this.active_surface_index = game.create_surface(surface_name, map_gen_settings).index - game.forces.player.set_spawn_position({-27, 25}, game.surfaces[this.active_surface_index]) else - game.forces.player.set_spawn_position({-27, 25}, game.surfaces[this.active_surface_index]) this.active_surface_index = Reset.soft_reset_map(game.surfaces[this.active_surface_index], map_gen_settings, starting_items).index end - local surface = game.surfaces[this.active_surface_index] - - surface.request_to_generate_chunks({-17, 45}, 1) - surface.force_generate_chunk_requests() - return this.active_surface_index end diff --git a/maps/mountain_fortress_v3/table.lua b/maps/mountain_fortress_v3/table.lua index b2143233..9c087dfd 100644 --- a/maps/mountain_fortress_v3/table.lua +++ b/maps/mountain_fortress_v3/table.lua @@ -5,7 +5,18 @@ local Event = require 'utils.event' local this = { disable_reset = false, players = {}, - offline_players = {} + offline_players = {}, + power_sources = {}, + refill_turrets = {index = 1}, + magic_crafters = {index = 1}, + magic_fluid_crafters = {index = 1}, + breached_wall = 1, + entity_limits = {}, + ore_loot = { + limit = 10000, + divisor = 10, + ore_list = {'iron-ore', 'copper-ore', 'coal'} + } } local Public = {} @@ -27,14 +38,37 @@ function Public.reset_table() this.train_upgrades = 0 this.offline_players = {} this.biter_pets = {} + this.power_sources = {} + this.flamethrower_damage = {} + this.refill_turrets = {index = 1} + this.magic_crafters = {index = 1} + this.magic_fluid_crafters = {index = 1} this.mined_scrap = 0 this.biters_killed = 0 this.locomotive_xp_aura = 40 this.xp_points = 0 this.xp_points_upgrade = 0 + this.upgrades = { + showed_text = false, + landmine = { + limit = 0, + built = 0 + }, + flame_turret = { + limit = 0, + built = 0 + }, + unit_number = { + landmine = {}, + flame_turret = {} + } + } this.aura_upgrades = 0 this.health_upgrades = 0 this.threat_upgrades = 0 + this.breached_wall = 1 + this.entity_limits = {} + this.offline_players_enabled = false this.left_top = { x = 0, y = 0 diff --git a/maps/mountain_fortress_v3/terrain.lua b/maps/mountain_fortress_v3/terrain.lua index 9e1fe5da..17af1dc3 100644 --- a/maps/mountain_fortress_v3/terrain.lua +++ b/maps/mountain_fortress_v3/terrain.lua @@ -1,8 +1,6 @@ local Biters = require 'modules.wave_defense.biter_rolls' -local ICW = require 'maps.mountain_fortress_v3.icw.main' -local Event = require 'utils.event' +local Functions = require 'maps.mountain_fortress_v3.functions' local WPT = require 'maps.mountain_fortress_v3.table' -local Loot = require 'maps.mountain_fortress_v3.loot' local get_noise = require 'utils.get_noise' local Public = {} @@ -60,182 +58,396 @@ local scrap_entities_index = #scrap_entities local spawner_raffle = {'biter-spawner', 'biter-spawner', 'biter-spawner', 'spitter-spawner'} local trees = {'dead-grey-trunk', 'dead-grey-trunk', 'dry-tree'} +local callback = { + [1] = {callback = Functions.refill_turret_callback, data = Functions.firearm_magazine_ammo}, + [2] = {callback = Functions.refill_turret_callback, data = Functions.piercing_rounds_magazine_ammo}, + [3] = {callback = Functions.refill_turret_callback, data = Functions.uranium_rounds_magazine_ammo}, + [4] = {callback = Functions.power_source_callback, data = Functions.laser_turrent_power_source}, + [5] = {callback = Functions.refill_liquid_turret_callback, data = Functions.light_oil_ammo}, + [6] = {callback = Functions.refill_turret_callback, data = Functions.artillery_shell_ammo} +} + +local turret_list = { + [1] = {name = 'gun-turret', callback = callback[1]}, + [2] = {name = 'gun-turret', callback = callback[2]}, + [3] = {name = 'gun-turret', callback = callback[3]}, + [4] = {name = 'laser-turret', callback = callback[4]}, + [5] = {name = 'flamethrower-turret', callback = callback[5]}, + [6] = {name = 'artillery-turret', callback = callback[6]} +} + local function place_wagon(data) local surface = data.surface - local left_top = data.left_top + local tiles = data.tiles + local entities = data.entities + local top_x = data.top_x + local top_y = data.top_y + if math_random(1, 2048) ~= 1 then + return + end - local position = {x = left_top.x + math_random(4, 12) * 2, y = left_top.y + math_random(4, 12) * 2} + local position = {x = top_x + math_random(4, 12) * 2, y = top_y + math_random(4, 12) * 2} + local wagon_mineable = { + callback = Functions.disable_minable_and_ICW_callback + } + local location local direction - local tiles local r1 = math_random(2, 4) * 2 local r2 = math_random(2, 4) * 2 if math_random(1, 2) == 1 then - tiles = surface.find_tiles_filtered({area = {{position.x, position.y - r1}, {position.x + 2, position.y + r2}}}) + location = + surface.find_tiles_filtered({area = {{position.x, position.y - r1}, {position.x + 2, position.y + r2}}}) direction = 0 else - tiles = surface.find_tiles_filtered({area = {{position.x - r1, position.y}, {position.x + r2, position.y + 2}}}) + location = + surface.find_tiles_filtered({area = {{position.x - r1, position.y}, {position.x + r2, position.y + 2}}}) direction = 2 end - for k, tile in pairs(tiles) do + for k, tile in pairs(location) do if tile.collides_with('resource-layer') then - surface.set_tiles({{name = 'landfill', position = tile.position}}, true) + tiles[#tiles + 1] = {name = 'landfill', position = tile.position} end for _, e in pairs(surface.find_entities_filtered({position = tile.position, force = {'neutral', 'enemy'}})) do e.destroy() end if tile.position.y % 2 == 0 and tile.position.x % 2 == 0 then - surface.create_entity( - {name = 'straight-rail', position = tile.position, force = 'player', direction = direction} - ) + entities[#entities + 1] = { + name = 'straight-rail', + position = tile.position, + force = 'player', + direction = direction + } end end - local entity = - surface.create_entity( - {name = wagon_raffle[math_random(1, #wagon_raffle)], position = position, force = 'player'} + table.insert( + entities, + { + name = wagon_raffle[math_random(1, #wagon_raffle)], + position = position, + force = 'player', + callback = wagon_mineable + } ) - entity.minable = false - - local wagon = ICW.register_wagon(entity, true) - wagon.entity_count = 999 end local function get_oil_amount(p) return (math_abs(p.y) * 200 + 10000) * math_random(75, 125) * 0.01 end -local function wall(data) - local surface = data.surface - local left_top = data.left_top - local seed = data.seed +function Public.increment_value(tbl, key, max, target) + if target then + if tbl.yv == 31 then + tbl[key] = tbl[key] + 1 + end + else + tbl[key] = tbl[key] + 1 + end - for x = 0, 31, 1 do - for y = 0, 31, 1 do - local p = {x = left_top.x + x, y = left_top.y + y} - local small_caves = get_noise('small_caves', p, seed) - local cave_ponds = get_noise('cave_rivers', p, seed + 100000) - if y > 9 + cave_ponds * 6 and y < 23 + small_caves * 6 then - if small_caves > 0.05 or cave_ponds > 0.05 then - surface.set_tiles({{name = 'deepwater-green', position = p}}) - if math_random(1, 48) == 1 then - surface.create_entity({name = 'fish', position = p}) - end + if tbl[key] == max then + tbl[key] = 0 + end + + return tbl[key] +end + +local function spawn_turret(entities, p, probability) + entities[#entities + 1] = { + name = turret_list[probability].name, + position = p, + force = 'enemy', + callback = turret_list[probability].callback, + direction = 4, + collision = true + } +end + +local function wall(data) + local tiles = data.tiles + local entities = data.entities + local surface = data.surface + local treasure = data.treasure + local stone_wall = {callback = Functions.disable_minable_callback} + + local y = Public.increment_value(data, 'yv', 32) + local x = Public.increment_value(data, 'xv', 32, true) + + local seed = data.seed + local p = {x = x + data.top_x, y = y + data.top_y} + + local small_caves = get_noise('small_caves', p, seed + 12300) + local cave_ponds = get_noise('cave_rivers', p, seed + 150000) + if y > 9 + cave_ponds * 6 and y < 23 + small_caves * 6 then + if small_caves > 0.02 or cave_ponds > 0.02 then + if small_caves > 0.005 then + tiles[#tiles + 1] = {name = 'water', position = p} + else + tiles[#tiles + 1] = {name = 'water-shallow', position = p} + if math_random(1, 32) == 1 then + entities[#entities + 1] = { + name = 'land-mine', + position = p, + force = 'enemy' + } + end + end + if math_random(1, 48) == 1 then + entities[#entities + 1] = {name = 'fish', position = p} + end + else + tiles[#tiles + 1] = {name = 'tutorial-grid', position = p} + + if math_random(1, 5) ~= 1 then + entities[#entities + 1] = {name = rock_raffle[math_random(1, #rock_raffle)], position = p} + if math_random(1, 32) == 1 then + entities[#entities + 1] = { + name = 'land-mine', + position = p, + force = 'enemy' + } + end + end + end + else + tiles[#tiles + 1] = {name = 'tutorial-grid', position = p} + + if + surface.can_place_entity( + { + name = 'stone-wall', + position = p, + force = 'enemy' + } + ) + then + if math_random(1, 512) == 1 and y > 3 and y < 28 then + if math_random(1, 2) == 1 then + treasure[#treasure + 1] = {position = p, chest = 'wooden-chest'} else - surface.set_tiles({{name = 'dirt-7', position = p}}) - if math_random(1, 5) ~= 1 then - surface.create_entity({name = rock_raffle[math_random(1, #rock_raffle)], position = p}) - end + treasure[#treasure + 1] = {position = p, chest = 'steel-chest'} end else - surface.set_tiles({{name = 'dirt-7', position = p}}) - - if - surface.can_place_entity( - { - name = 'stone-wall', - position = p, - force = 'enemy', - destructible = true - } - ) - then - if math_random(1, 512) == 1 and y > 3 and y < 28 then - if math_random(1, 2) == 1 then - Loot.add(surface, p, 'wooden-chest') - else - Loot.add(surface, p, 'steel-chest') + if y < 4 or y > 25 then + if y <= 24 then + if math_random(1, y + 1) == 1 then + entities[#entities + 1] = { + name = 'stone-wall', + position = p, + force = 'player', + callback = stone_wall + } end else - if y < 5 or y > 26 then - if y <= 15 then - if math_random(1, y + 1) == 1 then - local e = - surface.create_entity( - { - name = 'stone-wall', - position = p, - force = 'enemy', - destructible = true - } - ) - e.minable = false - end - else - if math_random(1, 32 - y) == 1 then - local e = - surface.create_entity( - { - name = 'stone-wall', - position = p, - force = 'enemy', - destructible = true - } - ) - e.minable = false - end - end - end - end - end - - if math_random(1, 16) == 1 then - if - surface.can_place_entity( - { - name = 'small-worm-turret', + if math_random(1, 32 - y) == 1 then + entities[#entities + 1] = { + name = 'stone-wall', position = p, - force = 'enemy', - destructible = true + force = 'player', + callback = stone_wall } - ) - then - Biters.wave_defense_set_worm_raffle(math_abs(p.y) * worm_level_modifier) - surface.create_entity( - { - name = Biters.wave_defense_roll_worm_name(), - position = p, - force = 'enemy', - destructible = true - } - ) - end - end - - if math_random(1, 32) == 1 then - if - surface.can_place_entity( - { - name = 'gun-turret', - position = p, - force = 'enemy', - destructible = true - } - ) - then - local e = - surface.create_entity( - { - name = 'gun-turret', - position = p, - force = 'enemy', - destructible = true - } - ) - if math_abs(p.y) < Public.level_depth * 2.5 then - e.insert({name = 'piercing-rounds-magazine', count = math_random(64, 128)}) - else - e.insert({name = 'uranium-rounds-magazine', count = math_random(64, 128)}) end end end end end + + if math_random(1, 48) == 1 then + if + surface.can_place_entity( + { + name = 'medium-worm-turret', + position = p, + force = 'enemy' + } + ) + then + Biters.wave_defense_set_worm_raffle(math_abs(p.y) * worm_level_modifier) + entities[#entities + 1] = { + name = Biters.wave_defense_roll_worm_name(), + position = p, + force = 'enemy' + } + end + end + + if math_random(1, 48) == 1 then + if math_abs(p.y) < Public.level_depth * 1.5 then + if math_random(1, 16) == 1 then + spawn_turret(entities, p, 1) + else + spawn_turret(entities, p, 2) + end + elseif math_abs(p.y) < Public.level_depth * 2.5 then + if math_random(1, 8) == 1 then + spawn_turret(entities, p, 3) + end + elseif math_abs(p.y) < Public.level_depth * 3.5 then + if math_random(1, 4) == 1 then + spawn_turret(entities, p, 4) + else + spawn_turret(entities, p, 3) + end + elseif math_abs(p.y) < Public.level_depth * 4.5 then + if math_random(1, 4) == 1 then + spawn_turret(entities, p, 4) + else + spawn_turret(entities, p, 5) + end + elseif math_abs(p.y) < Public.level_depth * 5.5 then + if math_random(1, 4) == 1 then + spawn_turret(entities, p, 4) + elseif math_random(1, 2) == 1 then + spawn_turret(entities, p, 5) + elseif math_random(1, 8) == 1 then + spawn_turret(entities, p, 6) + end + end + elseif math_abs(p.y) > Public.level_depth * 5.5 then + if math_random(1, 32) == 1 then + spawn_turret(entities, p, math_random(3, 6)) + end + end end end +local function process_level_13_position(x, y, data) + local p = {x = x, y = y} + local seed = data.seed + local tiles = data.tiles + local entities = data.entities + local treasure = data.treasure + + local small_caves = get_noise('small_caves', p, seed) + local noise_cave_ponds = get_noise('cave_ponds', p, seed) + + if small_caves > -0.22 and small_caves < 0.22 then + tiles[#tiles + 1] = {name = 'dirt-3', position = p} + if math_random(1, 768) == 1 then + treasure[#treasure + 1] = {position = p, chest = 'wooden-chest'} + end + if math_random(1, 2) == 1 then + entities[#entities + 1] = {name = rock_raffle[math_random(1, size_of_rock_raffle)], position = p} + end + return + end + + if small_caves < -0.35 or small_caves > 0.35 then + tiles[#tiles + 1] = {name = 'deepwater-green', position = p} + if math_random(1, 128) == 1 then + entities[#entities + 1] = {name = 'fish', position = p} + end + if math_random(1, 128) == 1 then + Biters.wave_defense_set_worm_raffle(math_abs(p.y) * worm_level_modifier) + entities[#entities + 1] = {name = Biters.wave_defense_roll_worm_name(), position = p, force = 'enemy'} + end + if math_random(1, 256) == 1 then + spawn_turret(entities, p, 4) + end + return + end + + if small_caves > -0.40 and small_caves < 0.40 then + if noise_cave_ponds > 0.35 then + tiles[#tiles + 1] = {name = 'dirt-' .. math_random(1, 4), position = p} + if math_random(1, 256) == 1 then + treasure[#treasure + 1] = {position = p, chest = 'wooden-chest'} + end + if math_random(1, 256) == 1 then + entities[#entities + 1] = {name = 'crude-oil', position = p, amount = get_oil_amount(p)} + end + return + end + if noise_cave_ponds > 0.25 then + tiles[#tiles + 1] = {name = 'dirt-7', position = p} + if math_random(1, 512) == 1 then + treasure[#treasure + 1] = {position = p, chest = 'wooden-chest'} + end + if math_random(1, 2) == 1 then + entities[#entities + 1] = {name = rock_raffle[math_random(1, size_of_rock_raffle)], position = p} + end + return + end + end + + tiles[#tiles + 1] = {name = 'water-shallow', position = p} +end + +local function process_level_12_position(x, y, data) + local p = {x = x, y = y} + local seed = data.seed + local tiles = data.tiles + local entities = data.entities + local markets = data.markets + local treasure = data.treasure + + local noise_1 = get_noise('small_caves', p, seed) + local noise_2 = get_noise('no_rocks_2', p, seed + 20000) + + if noise_1 > 0.65 then + if math_random(1, 100) > 88 then + entities[#entities + 1] = {name = 'tree-0' .. math_random(1, 9), position = p} + else + if math_random(1, 2) == 1 then + entities[#entities + 1] = {name = rock_raffle[math_random(1, size_of_rock_raffle)], position = p} + end + end + if math_random(1, 48) == 1 then + entities[#entities + 1] = {name = 'fish', position = p} + end + return + end + + if noise_1 < -0.72 then + tiles[#tiles + 1] = {name = 'lab-dark-2', position = p} + if math_random(1, 100) > 88 then + entities[#entities + 1] = {name = 'tree-0' .. math_random(1, 9), position = p} + end + return + end + + if noise_1 > -0.30 and noise_1 < 0.30 then + if noise_1 > -0.14 and noise_1 < 0.14 then + tiles[#tiles + 1] = {name = 'dirt-7', position = p} + if math_random(1, 2) == 1 then + entities[#entities + 1] = {name = rock_raffle[math_random(1, size_of_rock_raffle)], position = p} + end + if math_random(1, 256) == 1 then + treasure[#treasure + 1] = {position = p, chest = 'wooden-chest'} + end + else + tiles[#tiles + 1] = {name = 'water-shallow', position = p} + end + return + end + + if math_random(1, 64) == 1 and noise_2 > 0.65 then + if math_random(1, 32) == 1 then + entities[#entities + 1] = {name = 'stone', position = p, amount = math_abs(p.y) + 1} + elseif math_random(1, 32) == 1 then + entities[#entities + 1] = {name = 'iron-ore', position = p, amount = math_abs(p.y) + 1} + elseif math_random(1, 32) == 1 then + entities[#entities + 1] = {name = 'copper-ore', position = p, amount = math_abs(p.y) + 1} + elseif math_random(1, 32) == 1 then + entities[#entities + 1] = {name = 'coal', position = p, amount = math_abs(p.y) + 1} + end + end + if math_random(1, 8192) == 1 then + markets[#markets + 1] = p + end + if math_random(1, 1024) == 1 then + entities[#entities + 1] = { + name = 'crash-site-chest-' .. math_random(1, 2), + position = p, + force = 'neutral' + } + end + + tiles[#tiles + 1] = {name = 'lab-dark-2', position = p} +end + local function process_level_11_position(x, y, data) local p = {x = x, y = y} local seed = data.seed @@ -271,7 +483,7 @@ local function process_level_11_position(x, y, data) treasure[#treasure + 1] = {position = p, chest = 'wooden-chest'} end else - tiles[#tiles + 1] = {name = 'out-of-map', position = p} + tiles[#tiles + 1] = {name = 'water-shallow', position = p} end return end @@ -283,7 +495,11 @@ local function process_level_11_position(x, y, data) markets[#markets + 1] = p end if math_random(1, 1024) == 1 then - entities[#entities + 1] = {name = 'crash-site-chest-' .. math_random(1, 2), position = p, force = 'neutral'} + entities[#entities + 1] = { + name = 'crash-site-chest-' .. math_random(1, 2), + position = p, + force = 'neutral' + } end tiles[#tiles + 1] = {name = 'tutorial-grid', position = p} @@ -323,6 +539,9 @@ local function process_level_10_position(x, y, data) Biters.wave_defense_set_worm_raffle(math_abs(p.y) * worm_level_modifier) entities[#entities + 1] = {name = Biters.wave_defense_roll_worm_name(), position = p, force = 'enemy'} end + if math_random(1, 256) == 1 then + spawn_turret(entities, p, 4) + end tiles[#tiles + 1] = {name = 'water-shallow', position = p} return end @@ -419,7 +638,11 @@ local function process_level_8_position(x, y, data) if scrapyard < -0.25 or scrapyard > 0.25 then if math_random(1, 256) == 1 then - entities[#entities + 1] = {name = 'gun-turret', position = p, force = 'enemy'} + if math_random(1, 8) == 1 then + spawn_turret(entities, p, 3) + else + spawn_turret(entities, p, 4) + end end tiles[#tiles + 1] = {name = 'dirt-7', position = p} if scrapyard < -0.55 or scrapyard > 0.55 then @@ -623,6 +846,9 @@ local function process_level_6_position(x, y, data) Biters.wave_defense_set_worm_raffle(math_abs(p.y) * worm_level_modifier) entities[#entities + 1] = {name = Biters.wave_defense_roll_worm_name(), position = p, force = 'enemy'} end + if math_random(1, 256) == 1 then + spawn_turret(entities, p, 4) + end else tiles[#tiles + 1] = {name = 'dirt-7', position = p} if math_random(1, 100) > 15 then @@ -670,6 +896,9 @@ local function process_level_5_position(x, y, data) Biters.wave_defense_set_worm_raffle(math_abs(p.y) * worm_level_modifier) entities[#entities + 1] = {name = Biters.wave_defense_roll_worm_name(), position = p, force = 'enemy'} end + if math_random(1, 256) == 1 then + spawn_turret(entities, p, 4) + end return end @@ -893,6 +1122,9 @@ local function process_level_3_position(x, y, data) force = 'enemy' } end + if math_random(1, 256) == 1 then + spawn_turret(entities, p, 3) + end if math_random(1, 512) == 1 then treasure[#treasure + 1] = {position = p, chest = 'wooden-chest'} end @@ -1006,6 +1238,9 @@ local function process_level_2_position(x, y, data) force = 'enemy' } end + if math_random(1, 256) == 1 then + spawn_turret(entities, p, 2) + end if math_random(1, 1024) == 1 then treasure[#treasure + 1] = {position = p, chest = 'wooden-chest'} end @@ -1052,20 +1287,20 @@ local function process_level_1_position(x, y, data) local noise_cave_ponds = get_noise('cave_ponds', p, seed) --Chasms - if noise_cave_ponds < 0.12 and noise_cave_ponds > -0.12 then - if small_caves > 0.55 then + if noise_cave_ponds < 0.111 and noise_cave_ponds > -0.112 then + if small_caves > 0.53 then tiles[#tiles + 1] = {name = 'out-of-map', position = p} return end - if small_caves < -0.55 then + if small_caves < -0.53 then tiles[#tiles + 1] = {name = 'out-of-map', position = p} return end end - --Green Water Ponds - if noise_cave_ponds > 0.80 then - tiles[#tiles + 1] = {name = 'deepwater-green', position = p} + --Water Ponds + if noise_cave_ponds > 0.810 then + tiles[#tiles + 1] = {name = 'deepwater', position = p} if math_random(1, 16) == 1 then entities[#entities + 1] = {name = 'fish', position = p} end @@ -1074,7 +1309,7 @@ local function process_level_1_position(x, y, data) --Rivers local cave_rivers = get_noise('cave_rivers', p, seed + 100000) - if cave_rivers < 0.044 and cave_rivers > -0.044 then + if cave_rivers < 0.042 and cave_rivers > -0.042 then if noise_cave_ponds > 0 then tiles[#tiles + 1] = {name = 'water-shallow', position = p} if math_random(1, 64) == 1 then @@ -1084,17 +1319,27 @@ local function process_level_1_position(x, y, data) end end - if noise_cave_ponds > 0.76 then + if noise_cave_ponds > 0.74 then tiles[#tiles + 1] = {name = 'dirt-' .. math_random(4, 6), position = p} + tiles[#tiles + 1] = {name = 'grass-1', position = p} + if cave_rivers < -0.502 then + tiles[#tiles + 1] = {name = 'refined-hazard-concrete-right', position = p} + end + if math_random(1, 64) == 1 then + entities[#entities + 1] = {name = 'tree-0' .. math_random(1, 9), position = p} + end return end --Market Spots - if noise_cave_ponds < -0.75 then + if noise_cave_ponds < -0.74 then tiles[#tiles + 1] = {name = 'grass-' .. math_floor(noise_cave_ponds * 32) % 3 + 1, position = p} if math_random(1, 32) == 1 then markets[#markets + 1] = p end + if math_random(1, 512) == 1 then + spawn_turret(entities, p, 1) + end if math_random(1, 32) == 1 then entities[#entities + 1] = {name = 'tree-0' .. math_random(1, 9), position = p} end @@ -1118,11 +1363,14 @@ local function process_level_1_position(x, y, data) force = 'enemy' } end + if math_random(1, 512) == 1 then + spawn_turret(entities, p, 1) + end if math_random(1, 1024) == 1 then - treasure[#treasure + 1] = {position = p, chest = 'wooden-chest'} + treasure[#treasure + 1] = {position = p, chest = 'iron-chest'} end if math_random(1, 64) == 1 then - entities[#entities + 1] = {name = 'dead-tree-desert', position = p} + entities[#entities + 1] = {name = 'tree-0' .. math_random(1, 9), position = p} end return end @@ -1131,19 +1379,19 @@ local function process_level_1_position(x, y, data) --Main Rock Terrain local no_rocks_2 = get_noise('no_rocks_2', p, seed + 75000) - if no_rocks_2 > 0.65 or no_rocks_2 < -0.65 then + if no_rocks_2 > 0.66 or no_rocks_2 < -0.66 then tiles[#tiles + 1] = {name = 'dirt-' .. math_floor(no_rocks_2 * 8) % 2 + 5, position = p} if math_random(1, 32) == 1 then - entities[#entities + 1] = {name = 'dead-tree-desert', position = p} + entities[#entities + 1] = {name = 'tree-0' .. math_random(1, 9), position = p} end if math_random(1, 512) == 1 then - treasure[#treasure + 1] = {position = p, chest = 'wooden-chest'} + treasure[#treasure + 1] = {position = p, chest = 'iron-chest'} end return end if math_random(1, 2048) == 1 then - treasure[#treasure + 1] = {position = p, chest = 'wooden-chest'} + treasure[#treasure + 1] = {position = p, chest = 'iron-chest'} end tiles[#tiles + 1] = {name = 'dirt-7', position = p} if math_random(1, 100) > 25 then @@ -1162,7 +1410,9 @@ Public.levels = { process_level_8_position, process_level_9_position, process_level_10_position, - process_level_11_position + process_level_11_position, + process_level_12_position, + process_level_13_position } local function is_out_of_map(p) @@ -1174,7 +1424,7 @@ end local function process_bits(x, y, data) local left_top_y = data.area.left_top.y - local index = math_floor((math_abs(left_top_y / Public.level_depth)) % 11) + 1 + local index = math_floor((math_abs(left_top_y / Public.level_depth)) % 13) + 1 local process_level = Public.levels[index] if not process_level then process_level = Public.levels[#Public.levels] @@ -1185,94 +1435,85 @@ end local function border_chunk(data) local surface = data.surface - local left_top = data.left_top + local entities = data.entities + local decoratives = data.decoratives + local top_x = data.top_x + local top_y = data.top_y - for x = 0, 31, 1 do - for y = 0, 31, 1 do - local pos = {x = left_top.x + x, y = left_top.y + y} - local p = {x = left_top.x + x, y = left_top.y + y} - if surface.get_tile(p).name == 'out-of-map' then - return - end - if math_random(1, math.ceil(p.y + p.y) + 64) == 1 then - surface.create_entity({name = trees[math_random(1, #trees)], position = p}) - end - if not is_out_of_map(pos) then - if math_random(1, math.ceil(pos.y + pos.y) + 32) == 1 then - surface.create_entity({name = rock_raffle[math_random(1, #rock_raffle)], position = pos}) - end - if math_random(1, pos.y + 2) == 1 then - surface.create_decoratives { - check_collision = false, - decoratives = { - {name = 'rock-small', position = pos, amount = math_random(1, 1 + math.ceil(20 - y / 2))} - } - } - end - if math_random(1, pos.y + 2) == 1 then - surface.create_decoratives { - check_collision = false, - decoratives = { - {name = 'rock-tiny', position = pos, amount = math_random(1, 1 + math.ceil(20 - y / 2))} - } - } - end - end + local x = Public.increment_value(data, 'xv', 32) + local y = Public.increment_value(data, 'yv', 31) + + local pos = {x = x + data.top_x, y = y + data.top_y} + + if math_random(1, math.ceil(pos.y + pos.y) + 64) == 1 then + entities[#entities + 1] = {name = trees[math_random(1, #trees)], position = pos} + end + if not is_out_of_map(pos) then + if math_random(1, math.ceil(pos.y + pos.y) + 32) == 1 then + entities[#entities + 1] = {name = rock_raffle[math_random(1, #rock_raffle)], position = pos} + end + if math_random(1, pos.y + 2) == 1 then + decoratives[#decoratives + 1] = { + name = 'rock-small', + position = pos, + amount = math_random(1, 1 + math.ceil(20 - y / 2)) + } + end + if math_random(1, pos.y + 2) == 1 then + decoratives[#decoratives + 1] = { + name = 'rock-tiny', + position = pos, + amount = math_random(1, 1 + math.ceil(20 - y / 2)) + } end end for _, e in pairs( - surface.find_entities_filtered( - {area = {{left_top.x, left_top.y}, {left_top.x + 32, left_top.y + 32}}, type = 'cliff'} - ) + surface.find_entities_filtered({area = {{top_x, top_y}, {top_x + 32, top_y + 32}}, type = 'cliff'}) ) do e.destroy() end end -local function replace_water(data) +local function replace_water(x, y, data) local surface = data.surface - local left_top = data.left_top + local tiles = data.tiles - for x = 0, 31, 1 do - for y = 0, 31, 1 do - local p = {x = left_top.x + x, y = left_top.y + y} - if surface.get_tile(p).name == 'out-of-map' then - return - end - if surface.get_tile(p).collides_with('resource-layer') then - surface.set_tiles({{name = 'dirt-' .. math_random(1, 5), position = p}}, true) - end - end + local p = {x = x, y = y} + + if surface.get_tile(p).collides_with('resource-layer') then + tiles[#tiles + 1] = {name = 'dirt-' .. math_random(1, 5), position = p} end end -local function biter_chunk(data) +local function biter_chunk(x, y, data) local surface = data.surface - local left_top = data.left_top - + local entities = data.entities local tile_positions = {} - for x = 0, 31, 1 do - for y = 0, 31, 1 do - local p = {x = left_top.x + x, y = left_top.y + y} - tile_positions[#tile_positions + 1] = p - end - end + local p = {x = x, y = y} + tile_positions[#tile_positions + 1] = p - for i = 1, 1, 1 do + local disable_spawners = { + callback = Functions.deactivate_callback + } + local disable_worms = { + callback = Functions.active_not_destructible_callback + } + + if math.random(1, 128) == 1 then local position = surface.find_non_colliding_position('biter-spawner', tile_positions[math_random(1, #tile_positions)], 16, 2) if position then - local e = - surface.create_entity( - {name = spawner_raffle[math_random(1, #spawner_raffle)], position = position, force = 'enemy'} - ) - e.destructible = false - e.active = false + entities[#entities + 1] = { + name = spawner_raffle[math_random(1, #spawner_raffle)], + position = position, + force = 'enemy', + callback = disable_spawners + } end end - for i = 1, 3, 1 do + if math.random(1, 128) == 1 then local position = surface.find_non_colliding_position( 'big-worm-turret', @@ -1281,29 +1522,34 @@ local function biter_chunk(data) 2 ) if position then - local e = surface.create_entity({name = 'big-worm-turret', position = position, force = 'enemy'}) - e.destructible = false + entities[#entities + 1] = { + name = 'big-worm-turret', + position = position, + force = 'enemy', + callback = disable_worms + } end end end -local function out_of_map(data) +local function out_of_map(x, y, data) local surface = data.surface - local left_top = data.left_top - for x = 0, 31, 1 do - for y = 0, 31, 1 do - surface.set_tiles({{name = 'out-of-map', position = {x = left_top.x + x, y = left_top.y + y}}}) - end - end + surface.set_tiles({{name = 'out-of-map', position = {x = x, y = y}}}) end function Public.heavy_functions(x, y, data) - local area = data.area - local top_y = area.left_top.y + local top_x = data.top_x + local top_y = data.top_y local surface = data.surface local p = {x = data.x, y = data.y} local oom = surface.get_tile(p).name == 'out-of-map' + local map_name = 'mountain_fortress_v3' + + if string.sub(surface.name, 0, #map_name) ~= map_name then + return + end + if not data.seed then data.seed = data.surface.map_gen_settings.seed end @@ -1312,64 +1558,32 @@ function Public.heavy_functions(x, y, data) end if top_y % Public.level_depth == 0 and top_y < 0 then - return - end - - if top_y < 0 then - process_bits(x, y, data) - end -end - -local function on_chunk_generated(event) - local map_name = 'mountain_fortress_v3' - - if string.sub(event.surface.name, 0, #map_name) ~= map_name then - return - end - - local surface = event.surface - local seed = surface.map_gen_settings.seed - local left_top = event.area.left_top - local p = {x = left_top.x, y = left_top.y} - local oom = surface.get_tile(p).name == 'out-of-map' - - local data = { - surface = surface, - seed = seed, - left_top = left_top - } - - if oom then - return - end - - if left_top.y % Public.level_depth == 0 and left_top.y < 0 then WPT.get().left_top = data.left_top wall(data) return end - if left_top.y > 150 then - out_of_map(data) + if top_y > 120 then + out_of_map(x, y, data) return end - if left_top.y > 75 then - biter_chunk(data) + if top_y > 75 then + biter_chunk(x, y, data) end - if left_top.y > 32 then - game.forces.player.chart(surface, {{left_top.x, left_top.y}, {left_top.x + 31, left_top.y + 31}}) + if top_y > 32 then + game.forces.player.chart(surface, {{top_x, top_y}, {top_x + 31, top_y + 31}}) end - if left_top.y >= 0 then - replace_water(data) + if top_y >= 0 then + replace_water(x, y, data) end - if left_top.y >= 0 then + if top_y >= 0 then border_chunk(data) end - if left_top.y == -128 and left_top.x == -128 then + if top_y == -128 and top_x == -128 then local pl = WPT.get().locomotive.position for _, entity in pairs( surface.find_entities_filtered( @@ -1380,13 +1594,15 @@ local function on_chunk_generated(event) end end - if left_top.y < -256 then + if top_y < -256 then if math_random(1, chance_for_wagon_spawn) == 1 then place_wagon(data) end end + + if top_y < 0 then + process_bits(x, y, data) + end end -Event.add(defines.events.on_chunk_generated, on_chunk_generated) - return Public diff --git a/modules/difficulty_vote.lua b/modules/difficulty_vote.lua index a527fa77..347c3aa7 100644 --- a/modules/difficulty_vote.lua +++ b/modules/difficulty_vote.lua @@ -57,9 +57,10 @@ local this = { [7] = '' }, difficulty_vote_value = 1, - difficulty_vote_index = 4, + difficulty_vote_index = 1, difficulty_poll_closing_timeout = 54000, - difficulty_player_votes = {} + difficulty_player_votes = {}, + gui_width = 108 } local Public = {} @@ -112,6 +113,7 @@ local function difficulty_gui() b.style.font = 'heading-2' b.style.font_color = this.difficulties[this.difficulty_vote_index].print_color b.style.minimal_height = 38 + b.style.minimal_width = this.gui_width end end end @@ -142,7 +144,7 @@ local function poll_difficulty(player) name = 'difficulty_poll', direction = 'vertical' } - for i = 1, 7, 1 do + for i = 1, #this.difficulties, 1 do local b = frame.add({type = 'button', name = tostring(i), caption = this.difficulties[i].name}) b.style.font_color = this.difficulties[i].color b.style.font = 'heading-2' @@ -188,7 +190,7 @@ end function Public.reset_difficulty_poll() this.difficulty_vote_value = 1 - this.difficulty_vote_index = 4 + this.difficulty_vote_index = 1 this.difficulty_player_votes = {} this.difficulty_poll_closing_timeout = game.tick + 54000 for _, p in pairs(game.connected_players) do diff --git a/modules/dynamic_landfill.lua b/modules/dynamic_landfill.lua index 032bc9a7..17328526 100644 --- a/modules/dynamic_landfill.lua +++ b/modules/dynamic_landfill.lua @@ -5,113 +5,130 @@ local event = require 'utils.event' local math_random = math.random local table_insert = table.insert local water_tile_whitelist = { - ["water"] = true, - ["deepwater"] = true, - ["water-green"] = true, - ["deepwater-green"] = true - } + ['water'] = true, + ['deepwater'] = true, + ['water-green'] = true, + ['water-mud'] = true, + ['water-shallow'] = true, + ['deepwater-green'] = true +} local spiral_coords = {} for r = 1, 96, 1 do - for x = r * -1, r - 1, 1 do - table_insert(spiral_coords, {x = x, y = r * -1}) - end - for y = r * -1, r - 1, 1 do - table_insert(spiral_coords, {x = r, y = y}) - end - for x = r, r * -1 + 1, -1 do - table_insert(spiral_coords, {x = x, y = r}) - end - for y = r, r * -1 + 1, -1 do - table_insert(spiral_coords, {x = r * -1, y = y}) - end + for x = r * -1, r - 1, 1 do + table_insert(spiral_coords, {x = x, y = r * -1}) + end + for y = r * -1, r - 1, 1 do + table_insert(spiral_coords, {x = r, y = y}) + end + for x = r, r * -1 + 1, -1 do + table_insert(spiral_coords, {x = x, y = r}) + end + for y = r, r * -1 + 1, -1 do + table_insert(spiral_coords, {x = r * -1, y = y}) + end end local function get_chunk_position(position) - local chunk_position = {} - position.x = math.floor(position.x, 0) - position.y = math.floor(position.y, 0) - for x = 0, 31, 1 do - if (position.x - x) % 32 == 0 then chunk_position.x = (position.x - x) / 32 end - end - for y = 0, 31, 1 do - if (position.y - y) % 32 == 0 then chunk_position.y = (position.y - y) / 32 end - end - return chunk_position + local chunk_position = {} + position.x = math.floor(position.x, 0) + position.y = math.floor(position.y, 0) + for x = 0, 31, 1 do + if (position.x - x) % 32 == 0 then + chunk_position.x = (position.x - x) / 32 + end + end + for y = 0, 31, 1 do + if (position.y - y) % 32 == 0 then + chunk_position.y = (position.y - y) / 32 + end + end + return chunk_position end local function regenerate_decoratives(surface, position) - local chunk = get_chunk_position(position) - if not chunk then return end - surface.destroy_decoratives({area = {{chunk.x * 32, chunk.y * 32}, {chunk.x * 32 + 32, chunk.y * 32 + 32}}}) - local decorative_names = {} - for k,v in pairs(game.decorative_prototypes) do - if v.autoplace_specification then - decorative_names[#decorative_names+1] = k - end - end - surface.regenerate_decorative(decorative_names, {chunk}) + local chunk = get_chunk_position(position) + if not chunk then + return + end + surface.destroy_decoratives({area = {{chunk.x * 32, chunk.y * 32}, {chunk.x * 32 + 32, chunk.y * 32 + 32}}}) + local decorative_names = {} + for k, v in pairs(game.decorative_prototypes) do + if v.autoplace_specification then + decorative_names[#decorative_names + 1] = k + end + end + surface.regenerate_decorative(decorative_names, {chunk}) end local function is_this_a_valid_source_tile(pos, tiles) - for _, tile in pairs(tiles) do - if tile.position.x == pos.x and tile.position.y == pos.y then - return false - end - end - return true + for _, tile in pairs(tiles) do + if tile.position.x == pos.x and tile.position.y == pos.y then + return false + end + end + return true +end + +local function place_fitting_tile(position, surface, tiles_placed) + for _, coord in pairs(spiral_coords) do + local tile = surface.get_tile({position.x + coord.x, position.y + coord.y}) + if not tile.collides_with('player-layer') then + local valid_source_tile = is_this_a_valid_source_tile(tile.position, tiles_placed) + if tile.name == 'out-of-map' then + valid_source_tile = false + end + + if valid_source_tile then + if tile.hidden_tile then + surface.set_tiles({{name = tile.hidden_tile, position = position}}, true) + else + surface.set_tiles({{name = tile.name, position = position}}, true) + end + return + end + end + end end -local function place_fitting_tile(position, surface, tiles_placed) - for _, coord in pairs(spiral_coords) do - local tile = surface.get_tile({position.x + coord.x, position.y + coord.y}) - if not tile.collides_with("player-layer") then - local valid_source_tile = is_this_a_valid_source_tile(tile.position, tiles_placed) - if tile.name == "out-of-map" then valid_source_tile = false end - - if valid_source_tile then - if tile.hidden_tile then - surface.set_tiles({{name = tile.hidden_tile, position = position}}, true) - else - surface.set_tiles({{name = tile.name, position = position}}, true) - end - return - end - end - end -end - local function on_player_built_tile(event) - if event.item.name ~= "landfill" then return end - local surface = game.surfaces[event.surface_index] - - for _, placed_tile in pairs(event.tiles) do - if water_tile_whitelist[placed_tile.old_tile.name] then - place_fitting_tile(placed_tile.position, surface, event.tiles) - if regenerate_decoratives then - if math_random(1, 5) == 1 then - regenerate_decoratives(surface, placed_tile.position) - end - end - end - end + if not event.item then + return + end + if event.item.name ~= 'landfill' then + return + end + local surface = game.surfaces[event.surface_index] + + for _, placed_tile in pairs(event.tiles) do + if water_tile_whitelist[placed_tile.old_tile.name] then + place_fitting_tile(placed_tile.position, surface, event.tiles) + if regenerate_decoratives then + if math_random(1, 5) == 1 then + regenerate_decoratives(surface, placed_tile.position) + end + end + end + end end local function on_robot_built_tile(event) - if event.item.name ~= "landfill" then return end - local surface = event.robot.surface - - for _, placed_tile in pairs(event.tiles) do - if water_tile_whitelist[placed_tile.old_tile.name] then - place_fitting_tile(placed_tile.position, surface, event.tiles) - if regenerate_decoratives then - if math_random(1, 4) == 1 then - regenerate_decoratives(surface, placed_tile.position) - end - end - end - end + if event.item.name ~= 'landfill' then + return + end + local surface = event.robot.surface + + for _, placed_tile in pairs(event.tiles) do + if water_tile_whitelist[placed_tile.old_tile.name] then + place_fitting_tile(placed_tile.position, surface, event.tiles) + if regenerate_decoratives then + if math_random(1, 4) == 1 then + regenerate_decoratives(surface, placed_tile.position) + end + end + end + end end event.add(defines.events.on_player_built_tile, on_player_built_tile) -event.add(defines.events.on_robot_built_tile, on_robot_built_tile) \ No newline at end of file +event.add(defines.events.on_robot_built_tile, on_robot_built_tile) diff --git a/modules/wave_defense/side_targets.lua b/modules/wave_defense/side_targets.lua index 3bc2e58c..b199a51b 100644 --- a/modules/wave_defense/side_targets.lua +++ b/modules/wave_defense/side_targets.lua @@ -17,23 +17,23 @@ local side_target_types = { ["solar-panel"] = true, } -local function get_random_target(wave_defense_table) +local function get_random_target(wave_defense_table) local r = math.random(1, wave_defense_table.side_target_count) if not wave_defense_table.side_targets[r] then - table.remove(wave_defense_table.side_targets, r) + table.remove(wave_defense_table.side_targets, r) wave_defense_table.side_target_count = wave_defense_table.side_target_count - 1 - return + return end if not wave_defense_table.side_targets[r].valid then table.remove(wave_defense_table.side_targets, r) wave_defense_table.side_target_count = wave_defense_table.side_target_count - 1 - return + return end return wave_defense_table.side_targets[r] end function Public.get_side_target() - local wave_defense_table = WD.get_table() + local wave_defense_table = WD.get_table() for _ = 1, 512, 1 do if wave_defense_table.side_target_count == 0 then return end local target = get_random_target(wave_defense_table) @@ -43,21 +43,25 @@ end local function add_entity(entity) local wave_defense_table = WD.get_table() - + --skip entities that are on another surface if entity.surface.index ~= wave_defense_table.surface_index then return end - + --add entity to the side target list table.insert(wave_defense_table.side_targets, entity) wave_defense_table.side_target_count = wave_defense_table.side_target_count + 1 end local function on_built_entity(event) + if not event.created_entity then return end + if not event.created_entity.valid then return end if not side_target_types[event.created_entity.type] then return end add_entity(event.created_entity) end local function on_robot_built_entity(event) + if not event.created_entity then return end + if not event.created_entity.valid then return end if not side_target_types[event.created_entity.type] then return end add_entity(event.created_entity) end @@ -66,4 +70,4 @@ local event = require 'utils.event' event.add(defines.events.on_built_entity, on_built_entity) event.add(defines.events.on_robot_built_entity, on_robot_built_entity) -return Public \ No newline at end of file +return Public