You've already forked ComfyFactorio
							
							
				mirror of
				https://github.com/ComfyFactory/ComfyFactorio.git
				synced 2025-10-30 23:47:41 +02:00 
			
		
		
		
	Mtn v3 - fix bugs
Fixes final battle where biters would not spawn at all Misc changes and tweaks.
This commit is contained in:
		| @@ -74,6 +74,8 @@ local function on_entity_died(event) | ||||
|         return | ||||
|     end | ||||
|  | ||||
|  | ||||
|  | ||||
|     local cause = event.cause | ||||
|  | ||||
|     local coin_count = get_coin_count(entity) | ||||
| @@ -122,27 +124,33 @@ local function on_entity_died(event) | ||||
|                 end | ||||
|                 if forest_zone then | ||||
|                     if random(1, 12) == 1 then | ||||
|                         player.insert({name = 'coin', count = coin_count}) | ||||
|                         player.insert({ name = 'coin', count = coin_count }) | ||||
|                         if p then | ||||
|                             StatData.get_data(p.index):increase('coins', coin_count) | ||||
|                         end | ||||
|                     end | ||||
|                 else | ||||
|                     player.insert({name = 'coin', count = coin_count}) | ||||
|                     player.insert({ name = 'coin', count = coin_count }) | ||||
|                     if p then | ||||
|                         StatData.get_data(p.index):increase('coins', coin_count) | ||||
|                     end | ||||
|                 end | ||||
|             end | ||||
|         end | ||||
|         if entities_that_earn_coins[cause.name] then | ||||
|             event.entity.surface.spill_item_stack(cause.position, {name = 'coin', count = coin_count}, true) | ||||
|             reward_has_been_given = true | ||||
|         if not Public.get('final_battle') then | ||||
|             if entities_that_earn_coins[cause.name] then | ||||
|                 event.entity.surface.spill_item_stack(cause.position, { name = 'coin', count = coin_count }, true) | ||||
|                 reward_has_been_given = true | ||||
|             end | ||||
|         end | ||||
|     end | ||||
|  | ||||
|     if Public.get('final_battle') then | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     if reward_has_been_given == false then | ||||
|         event.entity.surface.spill_item_stack(event.entity.position, {name = 'coin', count = coin_count}, true) | ||||
|         event.entity.surface.spill_item_stack(event.entity.position, { name = 'coin', count = coin_count }, true) | ||||
|     end | ||||
| end | ||||
|  | ||||
|   | ||||
| @@ -8,7 +8,7 @@ local this = {} | ||||
|  | ||||
| Global.register( | ||||
|     this, | ||||
|     function(t) | ||||
|     function (t) | ||||
|         this = t | ||||
|     end | ||||
| ) | ||||
| @@ -51,7 +51,7 @@ local function create_particles(data) | ||||
|                 frame_speed = 0.1, | ||||
|                 vertical_speed = 0.1, | ||||
|                 height = 0.1, | ||||
|                 movement = {m2 - (random(0, m) * 0.01), m2 - (random(0, m) * 0.01)} | ||||
|                 movement = { m2 - (random(0, m) * 0.01), m2 - (random(0, m) * 0.01) } | ||||
|             } | ||||
|         ) | ||||
|     end | ||||
| @@ -97,7 +97,7 @@ local function spawn_biters(data) | ||||
|  | ||||
|     local unit_settings = WD.get('unit_settings') | ||||
|  | ||||
|     local unit = surface.create_entity({name = unit_to_create, position = position}) | ||||
|     local unit = surface.create_entity({ name = unit_to_create, position = position, force = data.force or 'enemy' }) | ||||
|     max_biters.amount = max_biters.amount + 1 | ||||
|  | ||||
|     if random(1, 30) == 1 then | ||||
| @@ -134,7 +134,7 @@ local function spawn_worms(data) | ||||
|  | ||||
|     WD.wave_defense_set_worm_raffle(sqrt(position.x ^ 2 + position.y ^ 2) * 0.20) | ||||
|  | ||||
|     local unit = surface.create_entity({name = unit_to_create, position = position}) | ||||
|     local unit = surface.create_entity({ name = unit_to_create, position = position }) | ||||
|     max_biters.amount = max_biters.amount + 1 | ||||
|  | ||||
|     local worm_unit_settings = WD.get('worm_unit_settings') | ||||
| @@ -151,7 +151,7 @@ local function spawn_worms(data) | ||||
|     end | ||||
| end | ||||
|  | ||||
| function Public.buried_biter(surface, position, count) | ||||
| function Public.buried_biter(surface, position, count, force) | ||||
|     if not (surface and surface.valid) then | ||||
|         return | ||||
|     end | ||||
| @@ -176,21 +176,21 @@ function Public.buried_biter(surface, position, count) | ||||
|  | ||||
|         this[game.tick + t][#this[game.tick + t] + 1] = { | ||||
|             callback = 'create_particles', | ||||
|             data = {surface = surface, position = {x = position.x, y = position.y}, amount = math.ceil(t * 0.05)} | ||||
|             data = { surface = surface, position = { x = position.x, y = position.y }, amount = math.ceil(t * 0.05) } | ||||
|         } | ||||
|  | ||||
|         if t == 60 then | ||||
|             if count == 1 then | ||||
|                 this[game.tick + t][#this[game.tick + t] + 1] = { | ||||
|                     callback = 'spawn_biters', | ||||
|                     data = {surface = surface, position = {x = position.x, y = position.y}, count = count or 1} | ||||
|                     data = { surface = surface, position = { x = position.x, y = position.y }, count = count or 1, force = force or 'enemy' } | ||||
|                 } | ||||
|             else | ||||
|                 local tick = 2 | ||||
|                 for _ = 1, count do | ||||
|                     this[game.tick + t][#this[game.tick + t] + 1 + tick] = { | ||||
|                         callback = 'spawn_biters', | ||||
|                         data = {surface = surface, position = {x = position.x, y = position.y}, count = count or 1} | ||||
|                         data = { surface = surface, position = { x = position.x, y = position.y }, count = count or 1, force = force or 'enemy' } | ||||
|                     } | ||||
|                     tick = tick + 2 | ||||
|                 end | ||||
| @@ -220,13 +220,13 @@ function Public.buried_worm(surface, position) | ||||
|  | ||||
|         this[game.tick + t][#this[game.tick + t] + 1] = { | ||||
|             callback = 'create_particles', | ||||
|             data = {surface = surface, position = {x = position.x, y = position.y}, amount = math.ceil(t * 0.05)} | ||||
|             data = { surface = surface, position = { x = position.x, y = position.y }, amount = math.ceil(t * 0.05) } | ||||
|         } | ||||
|  | ||||
|         if t == 60 then | ||||
|             this[game.tick + t][#this[game.tick + t] + 1] = { | ||||
|                 callback = 'spawn_worms', | ||||
|                 data = {surface = surface, position = {x = position.x, y = position.y}} | ||||
|                 data = { surface = surface, position = { x = position.x, y = position.y } } | ||||
|             } | ||||
|         end | ||||
|     end | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| local Public = require 'maps.mountain_fortress_v3.table' | ||||
| local Task = require 'utils.task' | ||||
| local Task = require 'utils.task_token' | ||||
| local Server = require 'utils.server' | ||||
| local Collapse = require 'modules.collapse' | ||||
| local WD = require 'modules.wave_defense.table' | ||||
| @@ -8,6 +8,14 @@ local Commands = require 'utils.commands' | ||||
| local mapkeeper = '[color=blue]Mapkeeper:[/color]' | ||||
| local scenario_name = Public.scenario_name | ||||
|  | ||||
| local gather_time_token = | ||||
|     Task.register( | ||||
|         function () | ||||
|             local stateful = Public.get_stateful() | ||||
|             stateful.collection.gather_time_timer = 0 | ||||
|         end | ||||
|     ) | ||||
|  | ||||
| Commands.new('scenario', 'Usable only for admins - controls the scenario!') | ||||
|     :require_admin() | ||||
|     :require_validation() | ||||
| @@ -101,7 +109,9 @@ Commands.new('mtn_complete_quests', 'Usable only for admins - sets the queue spe | ||||
|     :callback( | ||||
|         function (player) | ||||
|             Discord.send_notification_raw(scenario_name, player.name .. ' completed all the quest via command.') | ||||
|             Public.stateful.set_stateful('objectives_completed_count', 6) | ||||
|             local stateful = Public.get_stateful() | ||||
|             stateful.objectives_completed_count = 6 | ||||
|             Task.set_timeout_in_ticks(50, gather_time_token, {}) | ||||
|             game.print(mapkeeper .. player.name .. ', has forced completed all quests!', { r = 0.98, g = 0.66, b = 0.22 }) | ||||
|             player.print('Quests completed.') | ||||
|         end | ||||
| @@ -165,20 +175,6 @@ Commands.new('mtn_toggle_orbital_strikes', | ||||
|         end | ||||
|     ) | ||||
|  | ||||
| Commands.new('mtn_toggle_end_game', 'Usable only for admins - initiates the final battle!') | ||||
|     :require_admin() | ||||
|     :require_validation() | ||||
|     :callback( | ||||
|         function (player) | ||||
|             Discord.send_notification_raw(scenario_name, player.name .. ' toggled the end game.') | ||||
|             Public.stateful.set_stateful('final_battle', true) | ||||
|             Public.set('final_battle', true) | ||||
|  | ||||
|             game.print(mapkeeper .. ' ' .. player.name .. ', has triggered the final battle sequence!', | ||||
|                 { r = 0.98, g = 0.66, b = 0.22 }) | ||||
|         end | ||||
|     ) | ||||
|  | ||||
| Commands.new('mtn_get_queue_speed', 'Usable only for admins - gets the queue speed of this map!') | ||||
|     :require_admin() | ||||
|     :require_validation() | ||||
|   | ||||
| @@ -398,7 +398,7 @@ local function do_clear_rocks_slowly() | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     for _ = 1, 30 do | ||||
|     for _ = 1, 300 do | ||||
|         local entity = table.remove(rocks_to_remove, #rocks_to_remove) | ||||
|  | ||||
|         if entity and entity.valid then | ||||
| @@ -407,6 +407,26 @@ local function do_clear_rocks_slowly() | ||||
|     end | ||||
| end | ||||
|  | ||||
| local function do_replace_tiles_slowly() | ||||
|     local active_surface_index = Public.get('active_surface_index') | ||||
|     local surface = game.get_surface(active_surface_index) | ||||
|     if not (surface and surface.valid) then | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     local tiles_to_replace = Public.get('tiles_to_replace') | ||||
|     if not tiles_to_replace or not next(tiles_to_replace) then | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     for _ = 1, 300 do | ||||
|         local tile = table.remove(tiles_to_replace, #tiles_to_replace) | ||||
|         if tile and tile.valid then | ||||
|             surface.set_tiles({ { name = 'water-shallow', position = tile.position } }, true) | ||||
|         end | ||||
|     end | ||||
| end | ||||
|  | ||||
| local function do_season_fix() | ||||
|     local active_surface_index = Public.get('active_surface_index') | ||||
|     local surface = game.surfaces[active_surface_index] | ||||
| @@ -423,7 +443,7 @@ local function do_season_fix() | ||||
|     Public.set( | ||||
|         'current_season', | ||||
|         rendering.draw_text { | ||||
|             text = 'Season: ' .. Public.stateful.get_stateful('season'), | ||||
|             text = 'Season: ' .. Public.get_stateful('season'), | ||||
|             surface = surface, | ||||
|             target = { -0, 12 }, | ||||
|             color = { r = 0.98, g = 0.77, b = 0.22 }, | ||||
| @@ -522,6 +542,7 @@ local function tick() | ||||
|     do_beams_away() | ||||
|     do_clear_enemy_spawners() | ||||
|     do_clear_rocks_slowly() | ||||
|     do_replace_tiles_slowly() | ||||
| end | ||||
|  | ||||
| Public.deactivate_callback = | ||||
| @@ -950,6 +971,27 @@ function Public.find_rocks_and_slowly_remove() | ||||
|     end | ||||
| end | ||||
|  | ||||
| function Public.find_void_tiles_and_replace() | ||||
|     local active_surface_index = Public.get('active_surface_index') | ||||
|     local surface = game.get_surface(active_surface_index) | ||||
|     if not (surface and surface.valid) then | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     local cp = Collapse.get_position() | ||||
|     local rp = Collapse.get_reverse_position() | ||||
|  | ||||
|     local area = { | ||||
|         left_top = { x = (-zone_settings.zone_width / 2) + 10, y = cp.y }, | ||||
|         right_bottom = { x = (zone_settings.zone_width / 2) - 10, y = rp.y } | ||||
|     } | ||||
|  | ||||
|     local tiles = surface.find_tiles_filtered({ area = area, name = { 'out-of-map', 'water', 'deepwater', 'water-green', 'deepwater-green' } }) | ||||
|     if tiles and #tiles > 0 then | ||||
|         Public.set('tiles_to_replace', tiles) | ||||
|     end | ||||
| end | ||||
|  | ||||
| function Public.set_difficulty() | ||||
|     local final_battle = Public.get('final_battle') | ||||
|     if final_battle then | ||||
| @@ -1106,7 +1148,7 @@ function Public.render_direction(surface, reversed) | ||||
|     Public.set( | ||||
|         'current_season', | ||||
|         rendering.draw_text { | ||||
|             text = 'Season: ' .. Public.stateful.get_stateful('season'), | ||||
|             text = 'Season: ' .. Public.get_stateful('season'), | ||||
|             surface = surface, | ||||
|             target = { -0, 12 }, | ||||
|             color = { r = 0.98, g = 0.77, b = 0.22 }, | ||||
|   | ||||
| @@ -8,6 +8,7 @@ local WPT = require 'maps.mountain_fortress_v3.table' | ||||
| local RPG = require 'modules.rpg.main' | ||||
| local OfflinePlayers = require 'modules.clear_vacant_players' | ||||
| local Event = require 'utils.event' | ||||
| local Server = require 'utils.server' | ||||
|  | ||||
| local Public = {} | ||||
| local main_tile_name = 'black-refined-concrete' | ||||
| @@ -40,19 +41,19 @@ end | ||||
|  | ||||
| local enable_car_to_be_mined = | ||||
|     Task.register( | ||||
|     function(event) | ||||
|         local entity = event.entity | ||||
|         local owner_name = event.owner_name | ||||
|         if entity and entity.valid then | ||||
|             entity.minable = true | ||||
|             local msg = owner_name .. "'s vehicle is now minable!" | ||||
|             local p = { | ||||
|                 position = entity.position | ||||
|             } | ||||
|             Alert.alert_all_players_location(p, msg, nil, 30) | ||||
|         function (event) | ||||
|             local entity = event.entity | ||||
|             local owner_name = event.owner_name | ||||
|             if entity and entity.valid then | ||||
|                 entity.minable = true | ||||
|                 local msg = owner_name .. "'s vehicle is now minable!" | ||||
|                 local p = { | ||||
|                     position = entity.position | ||||
|                 } | ||||
|                 Alert.alert_all_players_location(p, msg, nil, 30) | ||||
|             end | ||||
|         end | ||||
|     end | ||||
| ) | ||||
|     ) | ||||
|  | ||||
| local function log_err(err) | ||||
|     local debug_mode = IC.get('debug_mode') | ||||
| @@ -68,7 +69,7 @@ local function get_trusted_system(player) | ||||
|     if not trust_system[player.index] then | ||||
|         trust_system[player.index] = { | ||||
|             players = { | ||||
|                 [player.name] = {trusted = true, drive = true} | ||||
|                 [player.name] = { trusted = true, drive = true } | ||||
|             }, | ||||
|             allow_anyone = 'left', | ||||
|             auto_upgrade = 'left', | ||||
| @@ -112,29 +113,29 @@ local function render_owner_text(renders, player, entity, new_owner) | ||||
|     if new_owner then | ||||
|         renders[new_owner.index] = | ||||
|             rendering.draw_text { | ||||
|             text = '## - ' .. new_owner.name .. "'s " .. ce_name .. ' - ##', | ||||
|             surface = entity.surface, | ||||
|             target = entity, | ||||
|             target_offset = {0, -2.6}, | ||||
|             color = color, | ||||
|             scale = 1.05, | ||||
|             font = 'default-large-semibold', | ||||
|             alignment = 'center', | ||||
|             scale_with_zoom = false | ||||
|         } | ||||
|                 text = '## - ' .. new_owner.name .. "'s " .. ce_name .. ' - ##', | ||||
|                 surface = entity.surface, | ||||
|                 target = entity, | ||||
|                 target_offset = { 0, -2.6 }, | ||||
|                 color = color, | ||||
|                 scale = 1.05, | ||||
|                 font = 'default-large-semibold', | ||||
|                 alignment = 'center', | ||||
|                 scale_with_zoom = false | ||||
|             } | ||||
|     else | ||||
|         renders[player.index] = | ||||
|             rendering.draw_text { | ||||
|             text = '## - ' .. player.name .. "'s " .. ce_name .. ' - ##', | ||||
|             surface = entity.surface, | ||||
|             target = entity, | ||||
|             target_offset = {0, -2.6}, | ||||
|             color = color, | ||||
|             scale = 1.05, | ||||
|             font = 'default-large-semibold', | ||||
|             alignment = 'center', | ||||
|             scale_with_zoom = false | ||||
|         } | ||||
|                 text = '## - ' .. player.name .. "'s " .. ce_name .. ' - ##', | ||||
|                 surface = entity.surface, | ||||
|                 target = entity, | ||||
|                 target_offset = { 0, -2.6 }, | ||||
|                 color = color, | ||||
|                 scale = 1.05, | ||||
|                 font = 'default-large-semibold', | ||||
|                 alignment = 'center', | ||||
|                 scale_with_zoom = false | ||||
|             } | ||||
|     end | ||||
|     entity.color = color | ||||
| end | ||||
| @@ -244,11 +245,11 @@ local function get_saved_entity(entity, index) | ||||
|     if index and index.name ~= entity.name then | ||||
|         local msg = | ||||
|             table.concat( | ||||
|             { | ||||
|                 'The built entity is not the same as the saved one. ', | ||||
|                 'Saved entity is: ' .. upperCase(index.name) .. ' - Built entity is: ' .. upperCase(entity.name) .. '. ' | ||||
|             } | ||||
|         ) | ||||
|                 { | ||||
|                     'The built entity is not the same as the saved one. ', | ||||
|                     'Saved entity is: ' .. upperCase(index.name) .. ' - Built entity is: ' .. upperCase(entity.name) .. '. ' | ||||
|                 } | ||||
|             ) | ||||
|         return false, msg | ||||
|     end | ||||
|     return true | ||||
| @@ -376,7 +377,7 @@ local function save_surface(entity, player) | ||||
|     car.entity = false | ||||
|     car.saved_entity = entity.unit_number | ||||
|  | ||||
|     saved_surfaces[player.index] = {saved_entity = entity.unit_number, name = entity.name} | ||||
|     saved_surfaces[player.index] = { saved_entity = entity.unit_number, name = entity.name } | ||||
| end | ||||
|  | ||||
| local function kick_players_out_of_vehicles(car) | ||||
| @@ -421,7 +422,7 @@ local function kick_players_from_surface(car, owner_id) | ||||
|     if not car.entity or not car.entity.valid then | ||||
|         local main_surface = game.surfaces[allowed_surface] | ||||
|         if validate_entity(main_surface) then | ||||
|             for _, e in pairs(surface.find_entities_filtered({area = car.area})) do | ||||
|             for _, e in pairs(surface.find_entities_filtered({ area = car.area })) do | ||||
|                 if validate_entity(e) and e.name == 'character' and e.player then | ||||
|                     if owner_id and owner_id == e.player.index then | ||||
|                         goto continue | ||||
| @@ -438,7 +439,7 @@ local function kick_players_from_surface(car, owner_id) | ||||
|         end | ||||
|     end | ||||
|  | ||||
|     for _, e in pairs(surface.find_entities_filtered({area = car.area})) do | ||||
|     for _, e in pairs(surface.find_entities_filtered({ area = car.area })) do | ||||
|         if validate_entity(e) and e.name == 'character' and e.player then | ||||
|             if owner_id and owner_id == e.player.index then | ||||
|                 goto continue | ||||
| @@ -467,7 +468,7 @@ local function kick_non_trusted_players_from_surface(car) | ||||
|     local position = car.entity and car.entity.valid and car.entity.position or game.forces.player.get_spawn_position(main_surface) | ||||
|     local owner = game.get_player(car.owner) and game.get_player(car.owner).name or false | ||||
|     Core.iter_connected_players( | ||||
|         function(player) | ||||
|         function (player) | ||||
|             local is_trusted = trust_system and trust_system.players and trust_system.players[player.name] and trust_system.players[player.name].trusted | ||||
|             if player.surface.index == surface_index and player.index ~= car.owner and not is_trusted then | ||||
|                 if position then | ||||
| @@ -654,26 +655,26 @@ local function construct_doors(car) | ||||
|  | ||||
|     local doors = IC.get('doors') | ||||
|  | ||||
|     for _, x in pairs({area.left_top.x - 1.5, area.right_bottom.x + 1.5}) do | ||||
|         local p = {x = x, y = area.left_top.y + ((area.right_bottom.y - area.left_top.y) * 0.5)} | ||||
|     for _, x in pairs({ area.left_top.x - 1.5, area.right_bottom.x + 1.5 }) do | ||||
|         local p = { x = x, y = area.left_top.y + ((area.right_bottom.y - area.left_top.y) * 0.5) } | ||||
|         if p.x < 0 then | ||||
|             surface.set_tiles({{name = main_tile_name, position = {x = p.x + 0.5, y = p.y}}}, true) | ||||
|             surface.set_tiles({ { name = main_tile_name, position = { x = p.x + 0.5, y = p.y } } }, true) | ||||
|         else | ||||
|             surface.set_tiles({{name = main_tile_name, position = {x = p.x - 1, y = p.y}}}, true) | ||||
|             surface.set_tiles({ { name = main_tile_name, position = { x = p.x - 1, y = p.y } } }, true) | ||||
|         end | ||||
|         local e = | ||||
|             surface.create_entity( | ||||
|             { | ||||
|                 name = 'car', | ||||
|                 position = {x, area.left_top.y + ((area.right_bottom.y - area.left_top.y) * 0.5)}, | ||||
|                 force = 'neutral', | ||||
|                 create_build_effect_smoke = false | ||||
|             } | ||||
|         ) | ||||
|                 { | ||||
|                     name = 'car', | ||||
|                     position = { x, area.left_top.y + ((area.right_bottom.y - area.left_top.y) * 0.5) }, | ||||
|                     force = 'neutral', | ||||
|                     create_build_effect_smoke = false | ||||
|                 } | ||||
|             ) | ||||
|         e.destructible = false | ||||
|         e.minable = false | ||||
|         e.operable = false | ||||
|         e.get_inventory(defines.inventory.fuel).insert({name = 'coal', count = 1}) | ||||
|         e.get_inventory(defines.inventory.fuel).insert({ name = 'coal', count = 1 }) | ||||
|         if type(car.entity) == 'boolean' then | ||||
|             return | ||||
|         end | ||||
| @@ -714,34 +715,34 @@ end | ||||
|  | ||||
| local remove_car = | ||||
|     Task.register( | ||||
|     function(data) | ||||
|         local player = data.player | ||||
|         local car = data.car | ||||
|         player.remove_item({name = car.name, count = 1}) | ||||
|     end | ||||
| ) | ||||
|         function (data) | ||||
|             local player = data.player | ||||
|             local car = data.car | ||||
|             player.remove_item({ name = car.name, count = 1 }) | ||||
|         end | ||||
|     ) | ||||
|  | ||||
| local find_remove_car = | ||||
|     Task.register( | ||||
|     function(data) | ||||
|         local index = data.index | ||||
|         local types = data.types | ||||
|         local position = data.position | ||||
|         function (data) | ||||
|             local index = data.index | ||||
|             local types = data.types | ||||
|             local position = data.position | ||||
|  | ||||
|         local surface = game.get_surface(index) | ||||
|         if not surface or not surface.valid then | ||||
|             return | ||||
|         end | ||||
|             local surface = game.get_surface(index) | ||||
|             if not surface or not surface.valid then | ||||
|                 return | ||||
|             end | ||||
|  | ||||
|         for _, dropped_ent in pairs(surface.find_entities_filtered {type = 'item-entity', area = {{position.x - 10, position.y - 10}, {position.x + 10, position.y + 10}}}) do | ||||
|             if dropped_ent and dropped_ent.valid and dropped_ent.stack then | ||||
|                 if types[dropped_ent.stack.name] then | ||||
|                     dropped_ent.destroy() | ||||
|             for _, dropped_ent in pairs(surface.find_entities_filtered { type = 'item-entity', area = { { position.x - 10, position.y - 10 }, { position.x + 10, position.y + 10 } } }) do | ||||
|                 if dropped_ent and dropped_ent.valid and dropped_ent.stack then | ||||
|                     if types[dropped_ent.stack.name] then | ||||
|                         dropped_ent.destroy() | ||||
|                     end | ||||
|                 end | ||||
|             end | ||||
|         end | ||||
|     end | ||||
| ) | ||||
|     ) | ||||
|  | ||||
| function Public.save_car(event) | ||||
|     local entity = event.entity | ||||
| @@ -798,11 +799,11 @@ function Public.save_car(event) | ||||
|         } | ||||
|         Task.set_timeout_in_ticks(10, remove_car, params) | ||||
|         if restore_on_theft then | ||||
|             local e = player.surface.create_entity({name = car.name, position = position, force = player.force, create_build_effect_smoke = false}) | ||||
|             local e = player.surface.create_entity({ name = car.name, position = position, force = player.force, create_build_effect_smoke = false }) | ||||
|             e.health = health | ||||
|             restore_surface(p, e) | ||||
|         elseif p.can_insert({name = car.name, count = 1}) then | ||||
|             p.insert({name = car.name, count = 1, health = health}) | ||||
|         elseif p.can_insert({ name = car.name, count = 1 }) then | ||||
|             p.insert({ name = car.name, count = 1, health = health }) | ||||
|             p.print(module_tag .. 'Your car was stolen from you - the gods foresaw this and granted you a new one.', Color.info) | ||||
|         end | ||||
|     end | ||||
| @@ -861,13 +862,13 @@ function Public.remove_surface(player) | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     for _, tile in pairs(surface.find_tiles_filtered({area = car.area})) do | ||||
|         surface.set_tiles({{name = 'out-of-map', position = tile.position}}, true) | ||||
|     for _, tile in pairs(surface.find_tiles_filtered({ area = car.area })) do | ||||
|         surface.set_tiles({ { name = 'out-of-map', position = tile.position } }, true) | ||||
|     end | ||||
|     for _, x in pairs({car.area.left_top.x - 1.5, car.area.right_bottom.x + 1.5}) do | ||||
|         local p = {x = x, y = car.area.left_top.y + ((car.area.right_bottom.y - car.area.left_top.y) * 0.5)} | ||||
|         surface.set_tiles({{name = 'out-of-map', position = {x = p.x + 0.5, y = p.y}}}, true) | ||||
|         surface.set_tiles({{name = 'out-of-map', position = {x = p.x - 1, y = p.y}}}, true) | ||||
|     for _, x in pairs({ car.area.left_top.x - 1.5, car.area.right_bottom.x + 1.5 }) do | ||||
|         local p = { x = x, y = car.area.left_top.y + ((car.area.right_bottom.y - car.area.left_top.y) * 0.5) } | ||||
|         surface.set_tiles({ { name = 'out-of-map', position = { x = p.x + 0.5, y = p.y } } }, true) | ||||
|         surface.set_tiles({ { name = 'out-of-map', position = { x = p.x - 1, y = p.y } } }, true) | ||||
|     end | ||||
|     game.delete_surface(surface) | ||||
| end | ||||
| @@ -923,6 +924,8 @@ function Public.kill_car(entity) | ||||
|  | ||||
|     game.print(module_tag .. owner.name .. messages[math.random(1, #messages)] .. ' ' .. gps_tag) | ||||
|  | ||||
|     Server.to_discord_bold(table.concat { '*** ', '[Personal Vehicle] ***', owner.name .. messages[math.random(1, #messages)] .. ' ', gps_tag }) | ||||
|  | ||||
|     local player_gui_data = IC.get('player_gui_data') | ||||
|     if player_gui_data[owner.name] then | ||||
|         player_gui_data[owner.name] = nil | ||||
| @@ -941,13 +944,13 @@ function Public.kill_car(entity) | ||||
|     local surface_index = car.surface | ||||
|     local surface = game.surfaces[surface_index] | ||||
|     kill_doors(car) | ||||
|     for _, tile in pairs(surface.find_tiles_filtered({area = car.area})) do | ||||
|         surface.set_tiles({{name = 'out-of-map', position = tile.position}}, true) | ||||
|     for _, tile in pairs(surface.find_tiles_filtered({ area = car.area })) do | ||||
|         surface.set_tiles({ { name = 'out-of-map', position = tile.position } }, true) | ||||
|     end | ||||
|     for _, x in pairs({car.area.left_top.x - 1.5, car.area.right_bottom.x + 1.5}) do | ||||
|         local p = {x = x, y = car.area.left_top.y + ((car.area.right_bottom.y - car.area.left_top.y) * 0.5)} | ||||
|         surface.set_tiles({{name = 'out-of-map', position = {x = p.x + 0.5, y = p.y}}}, true) | ||||
|         surface.set_tiles({{name = 'out-of-map', position = {x = p.x - 1, y = p.y}}}, true) | ||||
|     for _, x in pairs({ car.area.left_top.x - 1.5, car.area.right_bottom.x + 1.5 }) do | ||||
|         local p = { x = x, y = car.area.left_top.y + ((car.area.right_bottom.y - car.area.left_top.y) * 0.5) } | ||||
|         surface.set_tiles({ { name = 'out-of-map', position = { x = p.x + 0.5, y = p.y } } }, true) | ||||
|         surface.set_tiles({ { name = 'out-of-map', position = { x = p.x - 1, y = p.y } } }, true) | ||||
|     end | ||||
|     car.entity.force.chart(surface, car.area) | ||||
|     game.delete_surface(surface) | ||||
| @@ -979,7 +982,7 @@ function Public.kill_car_but_save_surface(entity) | ||||
|     end | ||||
|  | ||||
|     local c = 0 | ||||
|     local entities = surface.find_entities_filtered({area = car.area, force = 'player'}) | ||||
|     local entities = surface.find_entities_filtered({ area = car.area, force = 'player' }) | ||||
|     if entities and #entities > 0 then | ||||
|         for _, e in pairs(entities) do | ||||
|             if e and e.valid and e.name ~= 'character' then | ||||
| @@ -1093,21 +1096,21 @@ function Public.create_room_surface(unit_number) | ||||
|         ['height'] = 2, | ||||
|         ['water'] = 0, | ||||
|         ['starting_area'] = 1, | ||||
|         ['cliff_settings'] = {cliff_elevation_interval = 0, cliff_elevation_0 = 0}, | ||||
|         ['cliff_settings'] = { cliff_elevation_interval = 0, cliff_elevation_0 = 0 }, | ||||
|         ['default_enable_all_autoplace_controls'] = true, | ||||
|         ['autoplace_settings'] = { | ||||
|             ['entity'] = {treat_missing_as_default = false}, | ||||
|             ['tile'] = {treat_missing_as_default = true}, | ||||
|             ['decorative'] = {treat_missing_as_default = false} | ||||
|             ['entity'] = { treat_missing_as_default = false }, | ||||
|             ['tile'] = { treat_missing_as_default = true }, | ||||
|             ['decorative'] = { treat_missing_as_default = false } | ||||
|         } | ||||
|     } | ||||
|     local surface = game.create_surface(tostring(unit_number), map_gen_settings) | ||||
|     surface.freeze_daytime = true | ||||
|     surface.daytime = 0.1 | ||||
|     surface.request_to_generate_chunks({16, 16}, 1) | ||||
|     surface.request_to_generate_chunks({ 16, 16 }, 1) | ||||
|     surface.force_generate_chunk_requests() | ||||
|     for _, tile in pairs(surface.find_tiles_filtered({area = {{-2, -2}, {2, 2}}})) do | ||||
|         surface.set_tiles({{name = 'out-of-map', position = tile.position}}, true) | ||||
|     for _, tile in pairs(surface.find_tiles_filtered({ area = { { -2, -2 }, { 2, 2 } } })) do | ||||
|         surface.set_tiles({ { name = 'out-of-map', position = tile.position } }, true) | ||||
|     end | ||||
|     local surfaces = IC.get('surfaces') | ||||
|     surfaces[unit_number] = surface.index | ||||
| @@ -1129,18 +1132,18 @@ function Public.create_car_room(car) | ||||
|  | ||||
|     for x = area.left_top.x, area.right_bottom.x - 1, 1 do | ||||
|         for y = area.left_top.y + 2, area.right_bottom.y - 3, 1 do | ||||
|             tiles[#tiles + 1] = {name = main_tile_name, position = {x, y}} | ||||
|             tiles[#tiles + 1] = { name = main_tile_name, position = { x, y } } | ||||
|         end | ||||
|     end | ||||
|     for x = -3, 2, 1 do | ||||
|         for y = area.right_bottom.y - 4, area.right_bottom.y - 2, 1 do | ||||
|             tiles[#tiles + 1] = {name = main_tile_name, position = {x, y}} | ||||
|             tiles[#tiles + 1] = { name = main_tile_name, position = { x, y } } | ||||
|         end | ||||
|     end | ||||
|  | ||||
|     for x = area.left_top.x, area.right_bottom.x - 1, 1 do | ||||
|         for y = -0, 1, 1 do | ||||
|             tiles[#tiles + 1] = {name = 'water', position = {x, y}} | ||||
|             tiles[#tiles + 1] = { name = 'water', position = { x, y } } | ||||
|         end | ||||
|     end | ||||
|  | ||||
| @@ -1153,7 +1156,7 @@ function Public.create_car_room(car) | ||||
|             local fishes = {} | ||||
|             for x = area.left_top.x, area.right_bottom.x - 1, 1 do | ||||
|                 for y = -0, 1, 1 do | ||||
|                     fishes[#fishes + 1] = {name = 'fish', position = {x, y}} | ||||
|                     fishes[#fishes + 1] = { name = 'fish', position = { x, y } } | ||||
|                 end | ||||
|             end | ||||
|  | ||||
| @@ -1172,33 +1175,33 @@ function Public.create_car_room(car) | ||||
|  | ||||
|     local lx, ly, rx, ry = 4, 1, 5, 1 | ||||
|  | ||||
|     local position1 = {area.left_top.x + lx, area.left_top.y + ly} | ||||
|     local position2 = {area.right_bottom.x - rx, area.left_top.y + ry} | ||||
|     local position1 = { area.left_top.x + lx, area.left_top.y + ly } | ||||
|     local position2 = { area.right_bottom.x - rx, area.left_top.y + ry } | ||||
|  | ||||
|     local e1 = | ||||
|         surface.create_entity( | ||||
|         { | ||||
|             name = 'logistic-chest-requester', | ||||
|             position = position1, | ||||
|             force = 'neutral', | ||||
|             create_build_effect_smoke = false | ||||
|         } | ||||
|     ) | ||||
|             { | ||||
|                 name = 'logistic-chest-requester', | ||||
|                 position = position1, | ||||
|                 force = 'neutral', | ||||
|                 create_build_effect_smoke = false | ||||
|             } | ||||
|         ) | ||||
|     e1.destructible = false | ||||
|     e1.minable = false | ||||
|  | ||||
|     local e2 = | ||||
|         surface.create_entity( | ||||
|         { | ||||
|             name = 'logistic-chest-passive-provider', | ||||
|             position = position2, | ||||
|             force = 'neutral', | ||||
|             create_build_effect_smoke = false | ||||
|         } | ||||
|     ) | ||||
|             { | ||||
|                 name = 'logistic-chest-passive-provider', | ||||
|                 position = position2, | ||||
|                 force = 'neutral', | ||||
|                 create_build_effect_smoke = false | ||||
|             } | ||||
|         ) | ||||
|     e2.destructible = false | ||||
|     e2.minable = false | ||||
|     car.transfer_entities = {e1, e2} | ||||
|     car.transfer_entities = { e1, e2 } | ||||
|     return | ||||
| end | ||||
|  | ||||
| @@ -1269,8 +1272,8 @@ function Public.create_car(event) | ||||
|     cars[un] = { | ||||
|         entity = ce, | ||||
|         area = { | ||||
|             left_top = {x = car_area.left_top.x, y = car_area.left_top.y}, | ||||
|             right_bottom = {x = car_area.right_bottom.x, y = car_area.right_bottom.y} | ||||
|             left_top = { x = car_area.left_top.x, y = car_area.left_top.y }, | ||||
|             right_bottom = { x = car_area.right_bottom.x, y = car_area.right_bottom.y } | ||||
|         }, | ||||
|         doors = {}, | ||||
|         health_pool = { | ||||
| @@ -1310,7 +1313,7 @@ function Public.remove_invalid_cars() | ||||
|                 local owner = game.get_player(car.owner) and game.get_player(car.owner) or false | ||||
|                 if (not (owner and owner.connected) or JailData.get_is_jailed(owner.name)) and not car.schedule_enable_mining then | ||||
|                     car.schedule_enable_mining = true | ||||
|                     Task.set_timeout_in_ticks(30, enable_car_to_be_mined, {entity = car.entity, owner_name = owner.name}) | ||||
|                     Task.set_timeout_in_ticks(30, enable_car_to_be_mined, { entity = car.entity, owner_name = owner.name }) | ||||
|                 end | ||||
|                 if owner and owner.connected then | ||||
|                     car.schedule_enable_mining = nil | ||||
| @@ -1387,7 +1390,7 @@ function Public.use_door_with_entity(player, door) | ||||
|  | ||||
|     if validate_entity(car.entity) then | ||||
|         player_data.fallback_surface = car.entity.surface | ||||
|         player_data.fallback_position = {car.entity.position.x, car.entity.position.y} | ||||
|         player_data.fallback_position = { car.entity.position.x, car.entity.position.y } | ||||
|     end | ||||
|  | ||||
|     if validate_entity(car.entity) and car.entity.surface.name == player.surface.name then | ||||
| @@ -1412,9 +1415,9 @@ function Public.use_door_with_entity(player, door) | ||||
|         local x_vector = door.position.x - player.position.x | ||||
|         local position | ||||
|         if x_vector > 0 then | ||||
|             position = {area.left_top.x + 0.5, area.left_top.y + ((area.right_bottom.y - area.left_top.y) * 0.5)} | ||||
|             position = { area.left_top.x + 0.5, area.left_top.y + ((area.right_bottom.y - area.left_top.y) * 0.5) } | ||||
|         else | ||||
|             position = {area.right_bottom.x - 0.5, area.left_top.y + ((area.right_bottom.y - area.left_top.y) * 0.5)} | ||||
|             position = { area.right_bottom.x - 0.5, area.left_top.y + ((area.right_bottom.y - area.left_top.y) * 0.5) } | ||||
|         end | ||||
|         local p = surface.find_non_colliding_position('character', position, 128, 0.5) | ||||
|         if p then | ||||
| @@ -1436,7 +1439,7 @@ function Public.use_door_with_entity(player, door) | ||||
|         end | ||||
|         local surface = car.entity.surface | ||||
|         local x_vector = (door.position.x / math.abs(door.position.x)) * 2 | ||||
|         local position = {car.entity.position.x + x_vector, car.entity.position.y} | ||||
|         local position = { car.entity.position.x + x_vector, car.entity.position.y } | ||||
|         local surface_position = surface.find_non_colliding_position('character', position, 128, 0.5) | ||||
|         if car.entity.type == 'car' or car.entity.name == 'spidertron' then | ||||
|             player.teleport(surface_position, surface) | ||||
| @@ -1589,7 +1592,7 @@ Public.kick_non_trusted_players_from_surface = kick_non_trusted_players_from_sur | ||||
|  | ||||
| Event.add( | ||||
|     OfflinePlayers.events.remove_surface, | ||||
|     function(event) | ||||
|     function (event) | ||||
|         local target = event.target | ||||
|         if not target then | ||||
|             return | ||||
|   | ||||
| @@ -10,6 +10,7 @@ local Alert = require 'utils.alert' | ||||
| local Color = require 'utils.color_presets' | ||||
| local Modifiers = require 'utils.player_modifiers' | ||||
| local Core = require 'utils.core' | ||||
| local Task = require 'utils.task_token' | ||||
|  | ||||
| local zone_settings = Public.zone_settings | ||||
|  | ||||
| @@ -45,6 +46,20 @@ local denied_train_types = { | ||||
|     ['artillery-wagon'] = true | ||||
| } | ||||
|  | ||||
| Public.check_if_spawning_near_train_custom_callback = | ||||
|     Task.register( | ||||
|         function (event) | ||||
|             local entity = event.entity | ||||
|             local disable_spawn_near_target = event.disable_spawn_near_target | ||||
|  | ||||
|             if Public.is_around_train(entity) and disable_spawn_near_target then | ||||
|                 return true | ||||
|             end | ||||
|  | ||||
|             return false | ||||
|         end | ||||
|     ) | ||||
|  | ||||
| local function add_random_loot_to_main_market(rarity) | ||||
|     local main_market_items = Public.get('main_market_items') | ||||
|     local items = Public.get_random_item(rarity, true, false) | ||||
| @@ -85,16 +100,16 @@ local function add_random_loot_to_main_market(rarity) | ||||
| end | ||||
|  | ||||
| local function death_effects(player) | ||||
|     local position = {x = player.position.x - 0.75, y = player.position.y - 1} | ||||
|     local position = { x = player.position.x - 0.75, y = player.position.y - 1 } | ||||
|     local b = 0.75 | ||||
|     for _ = 1, 5, 1 do | ||||
|         local p = { | ||||
|             (position.x + 0.4) + (b * -1 + math.random(0, b * 20) * 0.1), | ||||
|             position.y + (b * -1 + math.random(0, b * 20) * 0.1) | ||||
|         } | ||||
|         player.surface.create_entity({name = 'flying-text', position = p, text = '☠️', color = {255, math.random(0, 100), 0}}) | ||||
|         player.surface.create_entity({ name = 'flying-text', position = p, text = '☠️', color = { 255, math.random(0, 100), 0 } }) | ||||
|     end | ||||
|     player.play_sound {path = 'utility/axe_fighting', volume_modifier = 0.9} | ||||
|     player.play_sound { path = 'utility/axe_fighting', volume_modifier = 0.9 } | ||||
| end | ||||
|  | ||||
| local messages = { | ||||
| @@ -162,7 +177,7 @@ local function hurt_players_outside_of_aura() | ||||
|  | ||||
|     local map_name = 'mtn_v3' | ||||
|     Core.iter_connected_players( | ||||
|         function(player) | ||||
|         function (player) | ||||
|             if sub(player.surface.name, 0, #map_name) == map_name then | ||||
|                 local position = player.position | ||||
|                 local inside = ((position.x - loco.x) ^ 2 + (position.y - loco.y) ^ 2) < upgrades.locomotive_aura_radius ^ 2 | ||||
| @@ -170,9 +185,9 @@ local function hurt_players_outside_of_aura() | ||||
|                     local entity = player.character | ||||
|                     if entity and entity.valid then | ||||
|                         death_effects(player) | ||||
|                         player.surface.create_entity({name = 'fire-flame', position = position}) | ||||
|                         player.surface.create_entity({ name = 'fire-flame', position = position }) | ||||
|                         if random(1, 3) == 1 then | ||||
|                             player.surface.create_entity({name = 'medium-scorchmark', position = position, force = 'neutral'}) | ||||
|                             player.surface.create_entity({ name = 'medium-scorchmark', position = position, force = 'neutral' }) | ||||
|                         end | ||||
|                         local max_health = floor(player.character.prototype.max_health + player.character_health_bonus + player.force.character_health_bonus) | ||||
|                         local vehicle = player.vehicle | ||||
| @@ -181,7 +196,7 @@ local function hurt_players_outside_of_aura() | ||||
|                         end | ||||
|                         if death_mode then | ||||
|                             if entity.name == 'character' then | ||||
|                                 game.print(player.name .. messages[random(1, #messages)], {r = 200, g = 0, b = 0}) | ||||
|                                 game.print(player.name .. messages[random(1, #messages)], { r = 200, g = 0, b = 0 }) | ||||
|                             end | ||||
|                             if entity.valid then | ||||
|                                 entity.die() | ||||
| @@ -209,7 +224,7 @@ local function hurt_players_outside_of_aura() | ||||
|                             if entity.valid then | ||||
|                                 if entity.health - damage <= 0 then | ||||
|                                     if entity.name == 'character' then | ||||
|                                         game.print(player.name .. messages[random(1, #messages)], {r = 200, g = 0, b = 0}) | ||||
|                                         game.print(player.name .. messages[random(1, #messages)], { r = 200, g = 0, b = 0 }) | ||||
|                                     end | ||||
|                                 end | ||||
|                             end | ||||
| @@ -223,7 +238,7 @@ local function hurt_players_outside_of_aura() | ||||
|     ) | ||||
| end | ||||
| local function give_passive_xp(data) | ||||
|     local xp_floating_text_color = {r = 188, g = 201, b = 63} | ||||
|     local xp_floating_text_color = { r = 188, g = 201, b = 63 } | ||||
|     local visuals_delay = 1800 | ||||
|     local loco_surface = Public.get('loco_surface') | ||||
|     if not (loco_surface and loco_surface.valid) then | ||||
| @@ -238,7 +253,7 @@ local function give_passive_xp(data) | ||||
|     local loco = locomotive.position | ||||
|  | ||||
|     Core.iter_connected_players( | ||||
|         function(player) | ||||
|         function (player) | ||||
|             local position = player.position | ||||
|             local inside = ((position.x - loco.x) ^ 2 + (position.y - loco.y) ^ 2) < upgrades.locomotive_aura_radius ^ 2 | ||||
|             if player.afk_time < 200 and not RPG.get_last_spell_cast(player) then | ||||
| @@ -261,7 +276,7 @@ local function give_passive_xp(data) | ||||
|  | ||||
|                     player.create_local_flying_text { | ||||
|                         text = '+' .. '', | ||||
|                         position = {x = pos.x, y = pos.y - 2}, | ||||
|                         position = { x = pos.x, y = pos.y - 2 }, | ||||
|                         color = xp_floating_text_color, | ||||
|                         time_to_live = 60, | ||||
|                         speed = 3 | ||||
| @@ -320,7 +335,7 @@ local function fish_tag() | ||||
|         locomotive_cargo.force.add_chart_tag( | ||||
|             locomotive_cargo.surface, | ||||
|             { | ||||
|                 icon = {type = 'item', name = 'raw-fish'}, | ||||
|                 icon = { type = 'item', name = 'raw-fish' }, | ||||
|                 position = locomotive_cargo.position, | ||||
|                 text = ' ' | ||||
|             } | ||||
| @@ -341,7 +356,7 @@ local function set_player_spawn() | ||||
|     if not position then | ||||
|         return | ||||
|     end | ||||
|     game.forces.player.set_spawn_position({x = position.x, y = position.y}, locomotive.surface) | ||||
|     game.forces.player.set_spawn_position({ x = position.x, y = position.y }, locomotive.surface) | ||||
| end | ||||
|  | ||||
| local function refill_fish() | ||||
| @@ -352,7 +367,7 @@ local function refill_fish() | ||||
|     if not locomotive_cargo.valid then | ||||
|         return | ||||
|     end | ||||
|     locomotive_cargo.get_inventory(defines.inventory.cargo_wagon).insert({name = 'raw-fish', count = random(2, 5)}) | ||||
|     locomotive_cargo.get_inventory(defines.inventory.cargo_wagon).insert({ name = 'raw-fish', count = random(2, 5) }) | ||||
| end | ||||
|  | ||||
| local function set_carriages() | ||||
| @@ -485,12 +500,12 @@ local function on_research_finished(event) | ||||
|     local name = research.name | ||||
|  | ||||
|     if name == 'discharge-defense-equipment' then | ||||
|         local message = ({'locomotive.discharge_unlocked'}) | ||||
|         local message = ({ 'locomotive.discharge_unlocked' }) | ||||
|         Alert.alert_all_players(15, message, nil, 'achievement/tech-maniac', 0.1) | ||||
|     end | ||||
|  | ||||
|     if name == 'artillery' then | ||||
|         local message = ({'locomotive.artillery_unlocked'}) | ||||
|         local message = ({ 'locomotive.artillery_unlocked' }) | ||||
|         Alert.alert_all_players(15, message, nil, 'achievement/tech-maniac', 0.1) | ||||
|     end | ||||
|  | ||||
| @@ -506,7 +521,7 @@ local function on_research_finished(event) | ||||
|  | ||||
|     local breached_wall = Public.get('breached_wall') | ||||
|     add_random_loot_to_main_market(breached_wall) | ||||
|     local message = ({'locomotive.new_items_at_market'}) | ||||
|     local message = ({ 'locomotive.new_items_at_market' }) | ||||
|     Alert.alert_all_players(5, message, nil, 'achievement/tech-maniac', 0.1) | ||||
|     Public.refresh_gui() | ||||
| end | ||||
| @@ -569,7 +584,7 @@ local function check_on_player_changed_surface() | ||||
|     end | ||||
|  | ||||
|     Core.iter_players( | ||||
|         function(player) | ||||
|         function (player) | ||||
|             if player.surface.name == 'nauvis' then | ||||
|                 local pos = surface.find_non_colliding_position('character', game.forces.player.get_spawn_position(surface), 3, 0, 5) | ||||
|                 if pos then | ||||
| @@ -756,7 +771,7 @@ function Public.render_train_hp() | ||||
|             text = 'HP: ' .. locomotive_health .. ' / ' .. locomotive_max_health, | ||||
|             surface = surface, | ||||
|             target = locomotive, | ||||
|             target_offset = {0, -4.5}, | ||||
|             target_offset = { 0, -4.5 }, | ||||
|             color = locomotive.color, | ||||
|             scale = 1.40, | ||||
|             font = 'default-game', | ||||
| @@ -771,7 +786,7 @@ function Public.render_train_hp() | ||||
|             text = 'Comfy Choo Choo', | ||||
|             surface = surface, | ||||
|             target = locomotive, | ||||
|             target_offset = {0, -6.25}, | ||||
|             target_offset = { 0, -6.25 }, | ||||
|             color = locomotive.color, | ||||
|             scale = 1.80, | ||||
|             font = 'default-game', | ||||
|   | ||||
| @@ -8,130 +8,130 @@ local floor = math.floor | ||||
|  | ||||
| local function initial_cargo_boxes() | ||||
|     return { | ||||
|         {name = 'loader', count = 1}, | ||||
|         {name = 'stone-furnace', count = 2}, | ||||
|         {name = 'coal', count = random(32, 64)}, | ||||
|         {name = 'coal', count = random(32, 64)}, | ||||
|         {name = 'loader', count = 1}, | ||||
|         {name = 'iron-ore', count = random(32, 128)}, | ||||
|         {name = 'copper-ore', count = random(32, 128)}, | ||||
|         {name = 'submachine-gun', count = 1}, | ||||
|         {name = 'loader', count = 1}, | ||||
|         {name = 'submachine-gun', count = 1}, | ||||
|         {name = 'submachine-gun', count = 1}, | ||||
|         {name = 'stone-furnace', count = 2}, | ||||
|         {name = 'submachine-gun', count = 1}, | ||||
|         {name = 'submachine-gun', count = 1}, | ||||
|         {name = 'loader', count = 1}, | ||||
|         {name = 'submachine-gun', count = 1}, | ||||
|         {name = 'automation-science-pack', count = random(4, 32)}, | ||||
|         {name = 'submachine-gun', count = 1}, | ||||
|         {name = 'stone-wall', count = random(4, 32)}, | ||||
|         {name = 'shotgun', count = 1}, | ||||
|         {name = 'shotgun', count = 1}, | ||||
|         {name = 'shotgun', count = 1}, | ||||
|         {name = 'stone-wall', count = random(4, 32)}, | ||||
|         {name = 'gun-turret', count = 1}, | ||||
|         {name = 'gun-turret', count = 1}, | ||||
|         {name = 'gun-turret', count = 1}, | ||||
|         {name = 'gun-turret', count = 1}, | ||||
|         {name = 'stone-wall', count = random(4, 32)}, | ||||
|         {name = 'shotgun-shell', count = random(4, 5)}, | ||||
|         {name = 'shotgun-shell', count = random(4, 5)}, | ||||
|         {name = 'shotgun-shell', count = random(4, 5)}, | ||||
|         {name = 'gun-turret', count = 1}, | ||||
|         {name = 'land-mine', count = random(6, 18)}, | ||||
|         {name = 'grenade', count = random(2, 7)}, | ||||
|         {name = 'grenade', count = random(2, 8)}, | ||||
|         {name = 'gun-turret', count = 1}, | ||||
|         {name = 'grenade', count = random(2, 7)}, | ||||
|         {name = 'light-armor', count = random(2, 4)}, | ||||
|         {name = 'iron-gear-wheel', count = random(7, 15)}, | ||||
|         {name = 'iron-gear-wheel', count = random(7, 15)}, | ||||
|         {name = 'gun-turret', count = 1}, | ||||
|         {name = 'iron-gear-wheel', count = random(7, 15)}, | ||||
|         {name = 'iron-gear-wheel', count = random(7, 15)}, | ||||
|         {name = 'iron-plate', count = random(15, 23)}, | ||||
|         {name = 'iron-plate', count = random(15, 23)}, | ||||
|         {name = 'iron-plate', count = random(15, 23)}, | ||||
|         {name = 'iron-plate', count = random(15, 23)}, | ||||
|         {name = 'copper-plate', count = random(15, 23)}, | ||||
|         {name = 'copper-plate', count = random(15, 23)}, | ||||
|         {name = 'copper-plate', count = random(15, 23)}, | ||||
|         {name = 'copper-plate', count = random(15, 23)}, | ||||
|         {name = 'firearm-magazine', count = random(10, 56)}, | ||||
|         {name = 'firearm-magazine', count = random(10, 56)}, | ||||
|         {name = 'firearm-magazine', count = random(10, 56)}, | ||||
|         {name = 'firearm-magazine', count = random(10, 56)}, | ||||
|         {name = 'rail', count = random(16, 24)}, | ||||
|         {name = 'rail', count = random(16, 24)} | ||||
|         { name = 'loader',                  count = 1 }, | ||||
|         { name = 'stone-furnace',           count = 2 }, | ||||
|         { name = 'coal',                    count = random(32, 64) }, | ||||
|         { name = 'coal',                    count = random(32, 64) }, | ||||
|         { name = 'loader',                  count = 1 }, | ||||
|         { name = 'iron-ore',                count = random(32, 128) }, | ||||
|         { name = 'copper-ore',              count = random(32, 128) }, | ||||
|         { name = 'submachine-gun',          count = 1 }, | ||||
|         { name = 'loader',                  count = 1 }, | ||||
|         { name = 'submachine-gun',          count = 1 }, | ||||
|         { name = 'submachine-gun',          count = 1 }, | ||||
|         { name = 'stone-furnace',           count = 2 }, | ||||
|         { name = 'submachine-gun',          count = 1 }, | ||||
|         { name = 'submachine-gun',          count = 1 }, | ||||
|         { name = 'loader',                  count = 1 }, | ||||
|         { name = 'submachine-gun',          count = 1 }, | ||||
|         { name = 'automation-science-pack', count = random(4, 32) }, | ||||
|         { name = 'submachine-gun',          count = 1 }, | ||||
|         { name = 'stone-wall',              count = random(4, 32) }, | ||||
|         { name = 'shotgun',                 count = 1 }, | ||||
|         { name = 'shotgun',                 count = 1 }, | ||||
|         { name = 'shotgun',                 count = 1 }, | ||||
|         { name = 'stone-wall',              count = random(4, 32) }, | ||||
|         { name = 'gun-turret',              count = 1 }, | ||||
|         { name = 'gun-turret',              count = 1 }, | ||||
|         { name = 'gun-turret',              count = 1 }, | ||||
|         { name = 'gun-turret',              count = 1 }, | ||||
|         { name = 'stone-wall',              count = random(4, 32) }, | ||||
|         { name = 'shotgun-shell',           count = random(4, 5) }, | ||||
|         { name = 'shotgun-shell',           count = random(4, 5) }, | ||||
|         { name = 'shotgun-shell',           count = random(4, 5) }, | ||||
|         { name = 'gun-turret',              count = 1 }, | ||||
|         { name = 'land-mine',               count = random(6, 18) }, | ||||
|         { name = 'grenade',                 count = random(2, 7) }, | ||||
|         { name = 'grenade',                 count = random(2, 8) }, | ||||
|         { name = 'gun-turret',              count = 1 }, | ||||
|         { name = 'grenade',                 count = random(2, 7) }, | ||||
|         { name = 'light-armor',             count = random(2, 4) }, | ||||
|         { name = 'iron-gear-wheel',         count = random(7, 15) }, | ||||
|         { name = 'iron-gear-wheel',         count = random(7, 15) }, | ||||
|         { name = 'gun-turret',              count = 1 }, | ||||
|         { name = 'iron-gear-wheel',         count = random(7, 15) }, | ||||
|         { name = 'iron-gear-wheel',         count = random(7, 15) }, | ||||
|         { name = 'iron-plate',              count = random(15, 23) }, | ||||
|         { name = 'iron-plate',              count = random(15, 23) }, | ||||
|         { name = 'iron-plate',              count = random(15, 23) }, | ||||
|         { name = 'iron-plate',              count = random(15, 23) }, | ||||
|         { name = 'copper-plate',            count = random(15, 23) }, | ||||
|         { name = 'copper-plate',            count = random(15, 23) }, | ||||
|         { name = 'copper-plate',            count = random(15, 23) }, | ||||
|         { name = 'copper-plate',            count = random(15, 23) }, | ||||
|         { name = 'firearm-magazine',        count = random(10, 56) }, | ||||
|         { name = 'firearm-magazine',        count = random(10, 56) }, | ||||
|         { name = 'firearm-magazine',        count = random(10, 56) }, | ||||
|         { name = 'firearm-magazine',        count = random(10, 56) }, | ||||
|         { name = 'rail',                    count = random(16, 24) }, | ||||
|         { name = 'rail',                    count = random(16, 24) } | ||||
|     } | ||||
| end | ||||
|  | ||||
| local place_tiles_token = | ||||
|     Task.register( | ||||
|     function(event) | ||||
|         local surface = event.surface | ||||
|         if not surface or not surface.valid then | ||||
|             return | ||||
|         end | ||||
|         local position = event.position | ||||
|         if not position then | ||||
|             return | ||||
|         end | ||||
|         function (event) | ||||
|             local surface = event.surface | ||||
|             if not surface or not surface.valid then | ||||
|                 return | ||||
|             end | ||||
|             local position = event.position | ||||
|             if not position then | ||||
|                 return | ||||
|             end | ||||
|  | ||||
|         MapFunctions.draw_noise_tile_circle(position, 'black-refined-concrete', surface, 22) | ||||
|     end | ||||
| ) | ||||
|             MapFunctions.draw_noise_tile_circle(position, 'black-refined-concrete', surface, 22) | ||||
|         end | ||||
|     ) | ||||
|  | ||||
| local set_loco_cargo = | ||||
|     Task.register( | ||||
|     function(data) | ||||
|         local surface = data.surface | ||||
|         if not surface or not surface.valid then | ||||
|             return | ||||
|         end | ||||
|         function (data) | ||||
|             local surface = data.surface | ||||
|             if not surface or not surface.valid then | ||||
|                 return | ||||
|             end | ||||
|  | ||||
|         local cargo_boxes = initial_cargo_boxes() | ||||
|             local cargo_boxes = initial_cargo_boxes() | ||||
|  | ||||
|         local p = {} | ||||
|             local p = {} | ||||
|  | ||||
|         local rad = 16 ^ 2 | ||||
|         for x = -15, 15, 1 do | ||||
|             for y = 0, 67, 1 do | ||||
|                 local va = floor((0 - x) ^ 2 + (53 - y) ^ 2) | ||||
|                 if ((va < rad - 50) and (va > rad - 100)) then | ||||
|                     if random(1, 3) == 1 then | ||||
|                         p[#p + 1] = {x = x, y = y} | ||||
|             local rad = 16 ^ 2 | ||||
|             for x = -15, 15, 1 do | ||||
|                 for y = 0, 67, 1 do | ||||
|                     local va = floor((0 - x) ^ 2 + (53 - y) ^ 2) | ||||
|                     if ((va < rad - 50) and (va > rad - 100)) then | ||||
|                         if random(1, 3) == 1 then | ||||
|                             p[#p + 1] = { x = x, y = y } | ||||
|                         end | ||||
|                     end | ||||
|                 end | ||||
|             end | ||||
|         end | ||||
|  | ||||
|         for i = 1, #cargo_boxes, 1 do | ||||
|             if not p[i] then | ||||
|                 break | ||||
|             end | ||||
|             local name = 'crash-site-chest-1' | ||||
|             for i = 1, #cargo_boxes, 1 do | ||||
|                 if not p[i] then | ||||
|                     break | ||||
|                 end | ||||
|                 local name = 'crash-site-chest-1' | ||||
|  | ||||
|             if random(1, 3) == 1 then | ||||
|                 name = 'crash-site-chest-2' | ||||
|             end | ||||
|             if surface.can_place_entity({name = name, position = p[i]}) then | ||||
|                 local e = surface.create_entity({name = name, position = p[i], force = 'neutral', create_build_effect_smoke = false}) | ||||
|                 e.minable = false | ||||
|                 e.destructible = true | ||||
|                 e.health = random(15, 30) | ||||
|                 local inventory = e.get_inventory(defines.inventory.chest) | ||||
|                 inventory.insert(cargo_boxes[i]) | ||||
|                 if random(1, 3) == 1 then | ||||
|                     name = 'crash-site-chest-2' | ||||
|                 end | ||||
|                 if surface.can_place_entity({ name = name, position = p[i] }) then | ||||
|                     local e = surface.create_entity({ name = name, position = p[i], force = 'neutral', create_build_effect_smoke = false }) | ||||
|                     e.minable = false | ||||
|                     e.destructible = true | ||||
|                     e.health = random(15, 30) | ||||
|                     local inventory = e.get_inventory(defines.inventory.chest) | ||||
|                     inventory.insert(cargo_boxes[i]) | ||||
|                 end | ||||
|             end | ||||
|         end | ||||
|     end | ||||
| ) | ||||
|     ) | ||||
|  | ||||
| function Public.locomotive_spawn(surface, position, reversed) | ||||
|     local this = Public.get() | ||||
|     local extra_wagons = Public.stateful.get_stateful('extra_wagons') | ||||
|     local extra_wagons = Public.get_stateful('extra_wagons') | ||||
|  | ||||
|     if not extra_wagons then | ||||
|         extra_wagons = 0 | ||||
| @@ -140,22 +140,22 @@ function Public.locomotive_spawn(surface, position, reversed) | ||||
|     if reversed then | ||||
|         position.y = position.y - (6 * extra_wagons) | ||||
|         for y = -6, 6, 2 do | ||||
|             surface.create_entity({name = 'straight-rail', position = {position.x, position.y + y}, force = 'player', direction = 0}) | ||||
|             surface.create_entity({ name = 'straight-rail', position = { position.x, position.y + y }, force = 'player', direction = 0 }) | ||||
|         end | ||||
|         this.locomotive = surface.create_entity({name = 'locomotive', position = {position.x, position.y + -3}, force = 'player', direction = defines.direction.south}) | ||||
|         this.locomotive.get_inventory(defines.inventory.fuel).insert({name = 'wood', count = 100}) | ||||
|         this.locomotive = surface.create_entity({ name = 'locomotive', position = { position.x, position.y + -3 }, force = 'player', direction = defines.direction.south }) | ||||
|         this.locomotive.get_inventory(defines.inventory.fuel).insert({ name = 'wood', count = 100 }) | ||||
|  | ||||
|         this.locomotive_cargo = surface.create_entity({name = 'cargo-wagon', position = {position.x, position.y + 3}, force = 'player', direction = defines.direction.south}) | ||||
|         this.locomotive_cargo.get_inventory(defines.inventory.cargo_wagon).insert({name = 'raw-fish', count = 8}) | ||||
|         this.locomotive_cargo = surface.create_entity({ name = 'cargo-wagon', position = { position.x, position.y + 3 }, force = 'player', direction = defines.direction.south }) | ||||
|         this.locomotive_cargo.get_inventory(defines.inventory.cargo_wagon).insert({ name = 'raw-fish', count = 8 }) | ||||
|     else | ||||
|         for y = -6, 6, 2 do | ||||
|             surface.create_entity({name = 'straight-rail', position = {position.x, position.y + y}, force = 'player', direction = 0}) | ||||
|             surface.create_entity({ name = 'straight-rail', position = { position.x, position.y + y }, force = 'player', direction = 0 }) | ||||
|         end | ||||
|         this.locomotive = surface.create_entity({name = 'locomotive', position = {position.x, position.y + -3}, force = 'player'}) | ||||
|         this.locomotive.get_inventory(defines.inventory.fuel).insert({name = 'wood', count = 100}) | ||||
|         this.locomotive = surface.create_entity({ name = 'locomotive', position = { position.x, position.y + -3 }, force = 'player' }) | ||||
|         this.locomotive.get_inventory(defines.inventory.fuel).insert({ name = 'wood', count = 100 }) | ||||
|  | ||||
|         this.locomotive_cargo = surface.create_entity({name = 'cargo-wagon', position = {position.x, position.y + 3}, force = 'player'}) | ||||
|         this.locomotive_cargo.get_inventory(defines.inventory.cargo_wagon).insert({name = 'raw-fish', count = 8}) | ||||
|         this.locomotive_cargo = surface.create_entity({ name = 'cargo-wagon', position = { position.x, position.y + 3 }, force = 'player' }) | ||||
|         this.locomotive_cargo.get_inventory(defines.inventory.cargo_wagon).insert({ name = 'raw-fish', count = 8 }) | ||||
|     end | ||||
|  | ||||
|     local winter_mode_locomotive = Public.wintery(this.locomotive, 5.5) | ||||
| @@ -167,7 +167,7 @@ function Public.locomotive_spawn(surface, position, reversed) | ||||
|                 intensity = 1, | ||||
|                 minimum_darkness = 0, | ||||
|                 oriented = true, | ||||
|                 color = {255, 255, 255}, | ||||
|                 color = { 255, 255, 255 }, | ||||
|                 target = this.locomotive, | ||||
|                 surface = surface, | ||||
|                 visible = true, | ||||
| @@ -186,7 +186,7 @@ function Public.locomotive_spawn(surface, position, reversed) | ||||
|                 intensity = 1, | ||||
|                 minimum_darkness = 0, | ||||
|                 oriented = true, | ||||
|                 color = {255, 255, 255}, | ||||
|                 color = { 255, 255, 255 }, | ||||
|                 target = this.locomotive_cargo, | ||||
|                 surface = surface, | ||||
|                 visible = true, | ||||
| @@ -209,16 +209,16 @@ function Public.locomotive_spawn(surface, position, reversed) | ||||
|                 orientation = random(0, 100) * 0.01, | ||||
|                 x_scale = scale, | ||||
|                 y_scale = scale, | ||||
|                 tint = {random(60, 255), random(60, 255), random(60, 255)}, | ||||
|                 tint = { random(60, 255), random(60, 255), random(60, 255) }, | ||||
|                 render_layer = 'selection-box', | ||||
|                 target = this.locomotive_cargo, | ||||
|                 target_offset = {-0.7 + random(0, 140) * 0.01, y}, | ||||
|                 target_offset = { -0.7 + random(0, 140) * 0.01, y }, | ||||
|                 surface = surface | ||||
|             } | ||||
|         ) | ||||
|     end | ||||
|  | ||||
|     this.locomotive.color = {random(2, 255), random(60, 255), random(60, 255)} | ||||
|     this.locomotive.color = { random(2, 255), random(60, 255), random(60, 255) } | ||||
|     this.locomotive.minable = false | ||||
|     this.locomotive_cargo.minable = false | ||||
|     this.locomotive_cargo.operable = true | ||||
| @@ -240,19 +240,19 @@ function Public.locomotive_spawn(surface, position, reversed) | ||||
|  | ||||
|         local pos = this.locomotive_cargo.position | ||||
|  | ||||
|         local new_position = {x = pos.x, y = pos.y + inc} | ||||
|         local new_position = { x = pos.x, y = pos.y + inc } | ||||
|  | ||||
|         for y = pos.y, new_position.y + (6 * extra_wagons), 2 do | ||||
|             surface.create_entity({name = 'straight-rail', position = {new_position.x, y}, force = 'player', direction = 0}) | ||||
|             surface.create_entity({ name = 'straight-rail', position = { new_position.x, y }, force = 'player', direction = 0 }) | ||||
|         end | ||||
|  | ||||
|         for _ = 1, extra_wagons do | ||||
|             local new_wagon = surface.create_entity({name = 'cargo-wagon', position = new_position, force = 'player', defines.direction.north}) | ||||
|             local new_wagon = surface.create_entity({ name = 'cargo-wagon', position = new_position, force = 'player', defines.direction.north }) | ||||
|             if new_wagon and new_wagon.valid then | ||||
|                 new_wagon.minable = false | ||||
|                 new_wagon.operable = true | ||||
|                 inc = inc + 7 | ||||
|                 new_position = {x = pos.x, y = pos.y + inc} | ||||
|                 new_position = { x = pos.x, y = pos.y + inc } | ||||
|                 ICW.register_wagon(new_wagon) | ||||
|             end | ||||
|         end | ||||
| @@ -260,13 +260,13 @@ function Public.locomotive_spawn(surface, position, reversed) | ||||
|  | ||||
|     local all_the_fish = Public.get('all_the_fish') | ||||
|     if all_the_fish then | ||||
|         this.locomotive_cargo.get_inventory(defines.inventory.cargo_wagon).insert({name = 'raw-fish', count = 999999}) | ||||
|         this.locomotive_cargo.get_inventory(defines.inventory.cargo_wagon).insert({ name = 'raw-fish', count = 999999 }) | ||||
|     end | ||||
|  | ||||
|     Task.set_timeout_in_ticks(15, place_tiles_token, {surface = surface, position = position}) | ||||
|     Task.set_timeout_in_ticks(15, place_tiles_token, { surface = surface, position = position }) | ||||
|     Task.set_timeout_in_ticks(50, set_loco_cargo, data) | ||||
|  | ||||
|     game.forces.player.set_spawn_position({this.locomotive.position.x - 5, this.locomotive.position.y}, locomotive.surface) | ||||
|     game.forces.player.set_spawn_position({ this.locomotive.position.x - 5, this.locomotive.position.y }, locomotive.surface) | ||||
| end | ||||
|  | ||||
| return Public | ||||
|   | ||||
| @@ -80,7 +80,7 @@ local collapse_kill = { | ||||
|     enabled = true | ||||
| } | ||||
|  | ||||
| local init_bonus_drill_force = function() | ||||
| local init_bonus_drill_force = function () | ||||
|     local bonus_drill = game.forces.bonus_drill | ||||
|     local player = game.forces.player | ||||
|     if not bonus_drill then | ||||
| @@ -91,7 +91,7 @@ local init_bonus_drill_force = function() | ||||
|     bonus_drill.mining_drill_productivity_bonus = 0.5 | ||||
| end | ||||
|  | ||||
| local is_position_near_tbl = function(position, tbl) | ||||
| local is_position_near_tbl = function (position, tbl) | ||||
|     local status = false | ||||
|     local function inside(pos) | ||||
|         return pos.x >= position.x and pos.y >= position.y and pos.x <= position.x and pos.y <= position.y | ||||
| @@ -108,13 +108,13 @@ end | ||||
|  | ||||
| local announce_new_map = | ||||
|     Task.register( | ||||
|     function() | ||||
|         local server_name = Server.check_server_name(scenario_name) | ||||
|         if server_name then | ||||
|             Server.to_discord_named_raw(send_ping_to_channel, role_to_mention .. ' ** Mtn Fortress was just reset! **') | ||||
|         function () | ||||
|             local server_name = Server.check_server_name(scenario_name) | ||||
|             if server_name then | ||||
|                 Server.to_discord_named_raw(send_ping_to_channel, role_to_mention .. ' ** Mtn Fortress was just reset! **') | ||||
|             end | ||||
|         end | ||||
|     end | ||||
| ) | ||||
|     ) | ||||
|  | ||||
| function Public.reset_map() | ||||
|     game.forces.player.reset() | ||||
| @@ -168,7 +168,7 @@ function Public.reset_map() | ||||
|     JailData.set_valid_surface(tostring(surface.name)) | ||||
|     JailData.reset_vote_table() | ||||
|  | ||||
|     Explosives.set_surface_whitelist({[surface.name] = true}) | ||||
|     Explosives.set_surface_whitelist({ [surface.name] = true }) | ||||
|     Explosives.disable(false) | ||||
|     Explosives.slow_explode(true) | ||||
|  | ||||
| @@ -194,7 +194,7 @@ function Public.reset_map() | ||||
|     AntiGrief.enable_jail(true) | ||||
|     AntiGrief.damage_entity_threshold(20) | ||||
|     AntiGrief.decon_surface_blacklist(surface.name) | ||||
|     AntiGrief.filtered_types_on_decon({'tree', 'simple-entity', 'fish'}) | ||||
|     AntiGrief.filtered_types_on_decon({ 'tree', 'simple-entity', 'fish' }) | ||||
|     AntiGrief.set_limit_per_table(2000) | ||||
|  | ||||
|     PL.show_roles_in_list(true) | ||||
| @@ -213,10 +213,10 @@ function Public.reset_map() | ||||
|             player.gui.left['mvps'].destroy() | ||||
|         end | ||||
|         ICMinimap.kill_minimap(player) | ||||
|         Event.raise(Public.events.reset_map, {player_index = player.index}) | ||||
|         Event.raise(Public.events.reset_map, { player_index = player.index }) | ||||
|     end | ||||
|  | ||||
|     Difficulty.reset_difficulty_poll({closing_timeout = game.tick + 36000}) | ||||
|     Difficulty.reset_difficulty_poll({ closing_timeout = game.tick + 36000 }) | ||||
|     Difficulty.set_gui_width(20) | ||||
|  | ||||
|     Collapse.set_kill_entities(false) | ||||
| @@ -242,15 +242,15 @@ function Public.reset_map() | ||||
|     if this.adjusted_zones.reversed then | ||||
|         Explosives.check_growth_below_void(false) | ||||
|         this.spawn_near_collapse.compare = abs(this.spawn_near_collapse.compare) | ||||
|         Collapse.set_position({0, -130}) | ||||
|         Collapse.set_position({ 0, -130 }) | ||||
|         Collapse.set_direction('south') | ||||
|         Public.locomotive_spawn(surface, {x = -18, y = -25}, this.adjusted_zones.reversed) | ||||
|         Public.locomotive_spawn(surface, { x = -18, y = -25 }, this.adjusted_zones.reversed) | ||||
|     else | ||||
|         Explosives.check_growth_below_void(true) | ||||
|         this.spawn_near_collapse.compare = abs(this.spawn_near_collapse.compare) * -1 | ||||
|         Collapse.set_position({0, 130}) | ||||
|         Collapse.set_position({ 0, 130 }) | ||||
|         Collapse.set_direction('north') | ||||
|         Public.locomotive_spawn(surface, {x = -18, y = 25}, this.adjusted_zones.reversed) | ||||
|         Public.locomotive_spawn(surface, { x = -18, y = 25 }, this.adjusted_zones.reversed) | ||||
|     end | ||||
|     Public.render_train_hp() | ||||
|     Public.render_direction(surface, this.adjusted_zones.reversed) | ||||
| @@ -260,7 +260,7 @@ function Public.reset_map() | ||||
|     wave_defense_table.target = this.locomotive | ||||
|     wave_defense_table.nest_building_density = 32 | ||||
|     wave_defense_table.game_lost = false | ||||
|     wave_defense_table.spawn_position = {x = 0, y = 84} | ||||
|     wave_defense_table.spawn_position = { x = 0, y = 84 } | ||||
|     WD.alert_boss_wave(true) | ||||
|     WD.enable_side_target(true) | ||||
|     WD.remove_entities(true) | ||||
| @@ -273,28 +273,31 @@ function Public.reset_map() | ||||
|     WD.increase_average_unit_group_size(true) | ||||
|     WD.increase_max_active_unit_groups(true) | ||||
|     WD.enable_random_spawn_positions(true) | ||||
|     Event.raise(WD.events.on_game_reset, {}) | ||||
|     WD.set_track_bosses_only(false) | ||||
|     WD.set_pause_waves_custom_callback(Public.pause_waves_custom_callback_token) | ||||
|     WD.set_threat_event_custom_callback(Public.check_if_spawning_near_train_custom_callback) | ||||
|     -- WD.set_es_unit_limit(400) -- moved to stateful | ||||
|     Event.raise(WD.events.on_game_reset, {}) | ||||
|  | ||||
|     Public.set_difficulty() | ||||
|     Public.disable_creative() | ||||
|     Public.boost_difficulty() | ||||
|  | ||||
|     if this.adjusted_zones.reversed then | ||||
|         if not surface.is_chunk_generated({x = -20, y = -22}) then | ||||
|             surface.request_to_generate_chunks({x = -20, y = -22}, 0.1) | ||||
|         if not surface.is_chunk_generated({ x = -20, y = -22 }) then | ||||
|             surface.request_to_generate_chunks({ x = -20, y = -22 }, 0.1) | ||||
|             surface.force_generate_chunk_requests() | ||||
|         end | ||||
|         game.forces.player.set_spawn_position({x = -27, y = -25}, surface) | ||||
|         WD.set_spawn_position({x = -16, y = -80}) | ||||
|         game.forces.player.set_spawn_position({ x = -27, y = -25 }, surface) | ||||
|         WD.set_spawn_position({ x = -16, y = -80 }) | ||||
|         WD.enable_inverted(true) | ||||
|     else | ||||
|         if not surface.is_chunk_generated({x = -20, y = 22}) then | ||||
|             surface.request_to_generate_chunks({x = -20, y = 22}, 0.1) | ||||
|         if not surface.is_chunk_generated({ x = -20, y = 22 }) then | ||||
|             surface.request_to_generate_chunks({ x = -20, y = 22 }, 0.1) | ||||
|             surface.force_generate_chunk_requests() | ||||
|         end | ||||
|         game.forces.player.set_spawn_position({x = -27, y = 25}, surface) | ||||
|         WD.set_spawn_position({x = -16, y = 80}) | ||||
|         game.forces.player.set_spawn_position({ x = -27, y = 25 }, surface) | ||||
|         WD.set_spawn_position({ x = -16, y = 80 }) | ||||
|         WD.enable_inverted(false) | ||||
|     end | ||||
|  | ||||
| @@ -310,7 +313,7 @@ function Public.reset_map() | ||||
|     this.game_lost = false | ||||
|  | ||||
|     RPG.rpg_reset_all_players() | ||||
|     RPG.set_surface_name({game.surfaces[this.active_surface_index].name}) | ||||
|     RPG.set_surface_name({ game.surfaces[this.active_surface_index].name }) | ||||
|     RPG.enable_health_and_mana_bars(true) | ||||
|     RPG.enable_wave_defense(true) | ||||
|     RPG.enable_mana(true) | ||||
| @@ -339,7 +342,7 @@ function Public.reset_map() | ||||
|     end | ||||
| end | ||||
|  | ||||
| local is_locomotive_valid = function() | ||||
| local is_locomotive_valid = function () | ||||
|     local locomotive = Public.get('locomotive') | ||||
|     if not locomotive or not locomotive.valid then | ||||
|         Public.set('game_lost', true) | ||||
| @@ -347,18 +350,18 @@ local is_locomotive_valid = function() | ||||
|     end | ||||
| end | ||||
|  | ||||
| local is_player_valid = function() | ||||
| local is_player_valid = function () | ||||
|     local players = game.connected_players | ||||
|     for i = 1, #players do | ||||
|         local player = players[i] | ||||
|         if player.connected and player.controller_type == 2 then | ||||
|             player.set_controller {type = defines.controllers.god} | ||||
|             player.set_controller { type = defines.controllers.god } | ||||
|             player.create_character() | ||||
|         end | ||||
|     end | ||||
| end | ||||
|  | ||||
| local has_the_game_ended = function() | ||||
| local has_the_game_ended = function () | ||||
|     local game_reset_tick = Public.get('game_reset_tick') | ||||
|     if game_reset_tick then | ||||
|         if game_reset_tick < 0 then | ||||
| @@ -379,7 +382,7 @@ local has_the_game_ended = function() | ||||
|                     cause_msg = 'soft-reset' | ||||
|                 end | ||||
|  | ||||
|                 game.print(({'main.reset_in', cause_msg, this.game_reset_tick / 60}), {r = 0.22, g = 0.88, b = 0.22}) | ||||
|                 game.print(({ 'main.reset_in', cause_msg, this.game_reset_tick / 60 }), { r = 0.22, g = 0.88, b = 0.22 }) | ||||
|             end | ||||
|  | ||||
|             if this.soft_reset and this.game_reset_tick == 0 then | ||||
| @@ -392,9 +395,9 @@ local has_the_game_ended = function() | ||||
|             if this.restart and this.game_reset_tick == 0 then | ||||
|                 if not this.announced_message then | ||||
|                     Public.set_scores() | ||||
|                     game.print(({'entity.notify_restart'}), {r = 0.22, g = 0.88, b = 0.22}) | ||||
|                     game.print(({ 'entity.notify_restart' }), { r = 0.22, g = 0.88, b = 0.22 }) | ||||
|                     local message = 'Soft-reset is disabled! Server will restart from scenario to load new changes.' | ||||
|                     Server.to_discord_bold(table.concat {'*** ', message, ' ***'}) | ||||
|                     Server.to_discord_bold(table.concat { '*** ', message, ' ***' }) | ||||
|                     Server.start_scenario('Mountain_Fortress_v3') | ||||
|                     this.announced_message = true | ||||
|                     return | ||||
| @@ -403,9 +406,9 @@ local has_the_game_ended = function() | ||||
|             if this.shutdown and this.game_reset_tick == 0 then | ||||
|                 if not this.announced_message then | ||||
|                     Public.set_scores() | ||||
|                     game.print(({'entity.notify_shutdown'}), {r = 0.22, g = 0.88, b = 0.22}) | ||||
|                     game.print(({ 'entity.notify_shutdown' }), { r = 0.22, g = 0.88, b = 0.22 }) | ||||
|                     local message = 'Soft-reset is disabled! Server will shutdown. Most likely because of updates.' | ||||
|                     Server.to_discord_bold(table.concat {'*** ', message, ' ***'}) | ||||
|                     Server.to_discord_bold(table.concat { '*** ', message, ' ***' }) | ||||
|                     Server.stop_scenario() | ||||
|                     this.announced_message = true | ||||
|                     return | ||||
| @@ -415,7 +418,7 @@ local has_the_game_ended = function() | ||||
|     end | ||||
| end | ||||
|  | ||||
| local chunk_load = function() | ||||
| local chunk_load = function () | ||||
|     local chunk_load_tick = Public.get('chunk_load_tick') | ||||
|     local tick = game.tick | ||||
|     if chunk_load_tick then | ||||
| @@ -429,17 +432,17 @@ end | ||||
|  | ||||
| local collapse_message = | ||||
|     Task.register( | ||||
|     function(data) | ||||
|         local pos = data.position | ||||
|         local message = data.message | ||||
|         local collapse_position = { | ||||
|             position = pos | ||||
|         } | ||||
|         Alert.alert_all_players_location(collapse_position, message) | ||||
|     end | ||||
| ) | ||||
|         function (data) | ||||
|             local pos = data.position | ||||
|             local message = data.message | ||||
|             local collapse_position = { | ||||
|                 position = pos | ||||
|             } | ||||
|             Alert.alert_all_players_location(collapse_position, message) | ||||
|         end | ||||
|     ) | ||||
|  | ||||
| local lock_locomotive_positions = function() | ||||
| local lock_locomotive_positions = function () | ||||
|     local locomotive = Public.get('locomotive') | ||||
|     if not locomotive or not locomotive.valid then | ||||
|         return | ||||
| @@ -455,10 +458,10 @@ local lock_locomotive_positions = function() | ||||
|     end | ||||
|  | ||||
|     local locomotive_positions = Public.get('locomotive_pos') | ||||
|     local p = {x = floor(locomotive.position.x), y = floor(locomotive.position.y)} | ||||
|     local p = { x = floor(locomotive.position.x), y = floor(locomotive.position.y) } | ||||
|     local success = is_position_near_tbl(locomotive.position, locomotive_positions.tbl) | ||||
|     if not success and not check_position(locomotive_positions.tbl, p) then | ||||
|         locomotive_positions.tbl[#locomotive_positions.tbl + 1] = {x = p.x, y = p.y} | ||||
|         locomotive_positions.tbl[#locomotive_positions.tbl + 1] = { x = p.x, y = p.y } | ||||
|     end | ||||
|  | ||||
|     local total_pos = #locomotive_positions.tbl | ||||
| @@ -467,7 +470,7 @@ local lock_locomotive_positions = function() | ||||
|     end | ||||
| end | ||||
|  | ||||
| local compare_collapse_and_train = function() | ||||
| local compare_collapse_and_train = function () | ||||
|     local collapse_pos = Collapse.get_position() | ||||
|     local locomotive = Public.get('locomotive') | ||||
|     if not (locomotive and locomotive.valid) then | ||||
| @@ -491,6 +494,7 @@ local compare_collapse_and_train = function() | ||||
|             else | ||||
|                 if Collapse.has_reverse_collapse_started() then | ||||
|                     Collapse.reverse_start_now(false, true) | ||||
|                     Public.find_void_tiles_and_replace() | ||||
|                 end | ||||
|             end | ||||
|         end | ||||
| @@ -516,7 +520,7 @@ local compare_collapse_and_train = function() | ||||
|     end | ||||
| end | ||||
|  | ||||
| local collapse_after_wave_200 = function() | ||||
| local collapse_after_wave_200 = function () | ||||
|     local final_battle = Public.get('final_battle') | ||||
|     if final_battle then | ||||
|         return | ||||
| @@ -538,18 +542,18 @@ local collapse_after_wave_200 = function() | ||||
|         local data = { | ||||
|             position = Collapse.get_position() | ||||
|         } | ||||
|         data.message = ({'breached_wall.collapse_start'}) | ||||
|         data.message = ({ 'breached_wall.collapse_start' }) | ||||
|         Task.set_timeout_in_ticks(100, collapse_message, data) | ||||
|     end | ||||
| end | ||||
|  | ||||
| local handle_changes = function() | ||||
| local handle_changes = function () | ||||
|     Public.set('restart', true) | ||||
|     Public.set('soft_reset', false) | ||||
|     print('Received new changes from backend.') | ||||
| end | ||||
|  | ||||
| local nth_40_tick = function() | ||||
| local nth_40_tick = function () | ||||
|     local update_gui = Public.update_gui | ||||
|     local players = game.connected_players | ||||
|  | ||||
| @@ -564,13 +568,13 @@ local nth_40_tick = function() | ||||
|     chunk_load() | ||||
| end | ||||
|  | ||||
| local nth_250_tick = function() | ||||
| local nth_250_tick = function () | ||||
|     compare_collapse_and_train() | ||||
|     collapse_after_wave_200() | ||||
|     Public.set_spawn_position() | ||||
| end | ||||
|  | ||||
| local nth_1000_tick = function() | ||||
| local nth_1000_tick = function () | ||||
|     Public.set_difficulty() | ||||
|     Public.is_creativity_mode_on() | ||||
| end | ||||
| @@ -579,17 +583,17 @@ function Public.init_mtn() | ||||
|     Public.reset_map() | ||||
|  | ||||
|     local tooltip = { | ||||
|         [1] = ({'main.diff_tooltip', '500', '50%', '15%', '15%', '1', '12', '50', '10000', '100%', '15', '10'}), | ||||
|         [2] = ({'main.diff_tooltip', '300', '25%', '10%', '10%', '2', '10', '50', '7000', '75%', '8', '8'}), | ||||
|         [3] = ({'main.diff_tooltip', '50', '0%', '0%', '0%', '4', '3', '10', '5000', '50%', '5', '6'}) | ||||
|         [1] = ({ 'main.diff_tooltip', '500', '50%', '15%', '15%', '1', '12', '50', '10000', '100%', '15', '10' }), | ||||
|         [2] = ({ 'main.diff_tooltip', '300', '25%', '10%', '10%', '2', '10', '50', '7000', '75%', '8', '8' }), | ||||
|         [3] = ({ 'main.diff_tooltip', '50', '0%', '0%', '0%', '4', '3', '10', '5000', '50%', '5', '6' }) | ||||
|     } | ||||
|  | ||||
|     Difficulty.set_tooltip(tooltip) | ||||
|  | ||||
|     local T = Map.Pop_info() | ||||
|     T.localised_category = 'mountain_fortress_v3' | ||||
|     T.main_caption_color = {r = 150, g = 150, b = 0} | ||||
|     T.sub_caption_color = {r = 0, g = 150, b = 0} | ||||
|     T.main_caption_color = { r = 150, g = 150, b = 0 } | ||||
|     T.sub_caption_color = { r = 0, g = 150, b = 0 } | ||||
|  | ||||
|     Explosives.set_destructible_tile('out-of-map', 1500) | ||||
|     Explosives.set_destructible_tile('water', 1000) | ||||
| @@ -609,7 +613,7 @@ end | ||||
|  | ||||
| Server.on_scenario_changed( | ||||
|     'Mountain_Fortress_v3', | ||||
|     function(data) | ||||
|     function (data) | ||||
|         local scenario = data.scenario | ||||
|         if scenario == 'Mountain_Fortress_v3' then | ||||
|             handle_changes() | ||||
| @@ -623,7 +627,7 @@ Event.on_nth_tick(1000, nth_1000_tick) | ||||
|  | ||||
| Event.add( | ||||
|     defines.events.on_player_created, | ||||
|     function(event) | ||||
|     function (event) | ||||
|         if event.player_index == 1 then | ||||
|             if not game.is_multiplayer() then | ||||
|                 Public.init_mtn() | ||||
|   | ||||
| @@ -12,55 +12,55 @@ local sqrt = math.sqrt | ||||
| local max_spill = 60 | ||||
|  | ||||
| local mining_chance_weights = { | ||||
|     {name = 'iron-plate', chance = 1000}, | ||||
|     {name = 'iron-gear-wheel', chance = 750}, | ||||
|     {name = 'copper-plate', chance = 750}, | ||||
|     {name = 'copper-cable', chance = 500}, | ||||
|     {name = 'electronic-circuit', chance = 300}, | ||||
|     {name = 'steel-plate', chance = 200}, | ||||
|     {name = 'solid-fuel', chance = 150}, | ||||
|     {name = 'pipe', chance = 100}, | ||||
|     {name = 'iron-stick', chance = 50}, | ||||
|     {name = 'battery', chance = 20}, | ||||
|     {name = 'empty-barrel', chance = 10}, | ||||
|     {name = 'crude-oil-barrel', chance = 30}, | ||||
|     {name = 'lubricant-barrel', chance = 20}, | ||||
|     {name = 'petroleum-gas-barrel', chance = 15}, | ||||
|     {name = 'sulfuric-acid-barrel', chance = 15}, | ||||
|     {name = 'heavy-oil-barrel', chance = 15}, | ||||
|     {name = 'light-oil-barrel', chance = 15}, | ||||
|     {name = 'water-barrel', chance = 10}, | ||||
|     {name = 'green-wire', chance = 10}, | ||||
|     {name = 'red-wire', chance = 10}, | ||||
|     {name = 'explosives', chance = 5}, | ||||
|     {name = 'advanced-circuit', chance = 5}, | ||||
|     {name = 'nuclear-fuel', chance = 1}, | ||||
|     {name = 'pipe-to-ground', chance = 10}, | ||||
|     {name = 'plastic-bar', chance = 5}, | ||||
|     {name = 'processing-unit', chance = 2}, | ||||
|     {name = 'used-up-uranium-fuel-cell', chance = 1}, | ||||
|     {name = 'uranium-fuel-cell', chance = 1}, | ||||
|     {name = 'rocket-fuel', chance = 3}, | ||||
|     {name = 'rocket-control-unit', chance = 1}, | ||||
|     {name = 'low-density-structure', chance = 1}, | ||||
|     {name = 'heat-pipe', chance = 1}, | ||||
|     {name = 'engine-unit', chance = 4}, | ||||
|     {name = 'electric-engine-unit', chance = 2}, | ||||
|     {name = 'logistic-robot', chance = 1}, | ||||
|     {name = 'construction-robot', chance = 1}, | ||||
|     {name = 'land-mine', chance = 3}, | ||||
|     {name = 'grenade', chance = 10}, | ||||
|     {name = 'rocket', chance = 3}, | ||||
|     {name = 'explosive-rocket', chance = 3}, | ||||
|     {name = 'cannon-shell', chance = 2}, | ||||
|     {name = 'explosive-cannon-shell', chance = 2}, | ||||
|     {name = 'uranium-cannon-shell', chance = 1}, | ||||
|     {name = 'explosive-uranium-cannon-shell', chance = 1}, | ||||
|     {name = 'artillery-shell', chance = 1}, | ||||
|     {name = 'cluster-grenade', chance = 2}, | ||||
|     {name = 'defender-capsule', chance = 5}, | ||||
|     {name = 'destroyer-capsule', chance = 1}, | ||||
|     {name = 'distractor-capsule', chance = 2} | ||||
|     { name = 'iron-plate',                     chance = 1000 }, | ||||
|     { name = 'iron-gear-wheel',                chance = 750 }, | ||||
|     { name = 'copper-plate',                   chance = 750 }, | ||||
|     { name = 'copper-cable',                   chance = 500 }, | ||||
|     { name = 'electronic-circuit',             chance = 300 }, | ||||
|     { name = 'steel-plate',                    chance = 200 }, | ||||
|     { name = 'solid-fuel',                     chance = 150 }, | ||||
|     { name = 'pipe',                           chance = 100 }, | ||||
|     { name = 'iron-stick',                     chance = 50 }, | ||||
|     { name = 'battery',                        chance = 20 }, | ||||
|     { name = 'empty-barrel',                   chance = 10 }, | ||||
|     { name = 'crude-oil-barrel',               chance = 30 }, | ||||
|     { name = 'lubricant-barrel',               chance = 20 }, | ||||
|     { name = 'petroleum-gas-barrel',           chance = 15 }, | ||||
|     { name = 'sulfuric-acid-barrel',           chance = 15 }, | ||||
|     { name = 'heavy-oil-barrel',               chance = 15 }, | ||||
|     { name = 'light-oil-barrel',               chance = 15 }, | ||||
|     { name = 'water-barrel',                   chance = 10 }, | ||||
|     { name = 'green-wire',                     chance = 10 }, | ||||
|     { name = 'red-wire',                       chance = 10 }, | ||||
|     { name = 'explosives',                     chance = 5 }, | ||||
|     { name = 'advanced-circuit',               chance = 5 }, | ||||
|     { name = 'nuclear-fuel',                   chance = 1 }, | ||||
|     { name = 'pipe-to-ground',                 chance = 10 }, | ||||
|     { name = 'plastic-bar',                    chance = 5 }, | ||||
|     { name = 'processing-unit',                chance = 2 }, | ||||
|     { name = 'used-up-uranium-fuel-cell',      chance = 1 }, | ||||
|     { name = 'uranium-fuel-cell',              chance = 1 }, | ||||
|     { name = 'rocket-fuel',                    chance = 3 }, | ||||
|     { name = 'rocket-control-unit',            chance = 1 }, | ||||
|     { name = 'low-density-structure',          chance = 1 }, | ||||
|     { name = 'heat-pipe',                      chance = 1 }, | ||||
|     { name = 'engine-unit',                    chance = 4 }, | ||||
|     { name = 'electric-engine-unit',           chance = 2 }, | ||||
|     { name = 'logistic-robot',                 chance = 1 }, | ||||
|     { name = 'construction-robot',             chance = 1 }, | ||||
|     { name = 'land-mine',                      chance = 3 }, | ||||
|     { name = 'grenade',                        chance = 10 }, | ||||
|     { name = 'rocket',                         chance = 3 }, | ||||
|     { name = 'explosive-rocket',               chance = 3 }, | ||||
|     { name = 'cannon-shell',                   chance = 2 }, | ||||
|     { name = 'explosive-cannon-shell',         chance = 2 }, | ||||
|     { name = 'uranium-cannon-shell',           chance = 1 }, | ||||
|     { name = 'explosive-uranium-cannon-shell', chance = 1 }, | ||||
|     { name = 'artillery-shell',                chance = 1 }, | ||||
|     { name = 'cluster-grenade',                chance = 2 }, | ||||
|     { name = 'defender-capsule',               chance = 5 }, | ||||
|     { name = 'destroyer-capsule',              chance = 1 }, | ||||
|     { name = 'distractor-capsule',             chance = 2 } | ||||
| } | ||||
|  | ||||
| local scrap_yield_amounts = { | ||||
| @@ -191,11 +191,11 @@ local function create_particles(surface, name, position, amount, cause_position) | ||||
| end | ||||
|  | ||||
| local mining_chances_ores = { | ||||
|     {name = 'iron-ore', chance = 26}, | ||||
|     {name = 'copper-ore', chance = 21}, | ||||
|     {name = 'coal', chance = 17}, | ||||
|     {name = 'stone', chance = 6}, | ||||
|     {name = 'uranium-ore', chance = 2} | ||||
|     { name = 'iron-ore',    chance = 26 }, | ||||
|     { name = 'copper-ore',  chance = 21 }, | ||||
|     { name = 'coal',        chance = 17 }, | ||||
|     { name = 'stone',       chance = 6 }, | ||||
|     { name = 'uranium-ore', chance = 2 } | ||||
| } | ||||
|  | ||||
| local harvest_raffle_ores = {} | ||||
| @@ -269,17 +269,20 @@ local function get_amount(data) | ||||
| end | ||||
|  | ||||
| function Public.entity_died_randomness(data) | ||||
|     if Public.get('final_battle') then | ||||
|         return | ||||
|     end | ||||
|     local entity = data.entity | ||||
|     local surface = data.surface | ||||
|     local harvest | ||||
|  | ||||
|     harvest = harvest_raffle_ores[random(1, size_of_ore_raffle)] | ||||
|  | ||||
|     local position = {x = entity.position.x, y = entity.position.y} | ||||
|     local position = { x = entity.position.x, y = entity.position.y } | ||||
|  | ||||
|     surface.spill_item_stack(position, {name = harvest, count = random(1, 5)}, true) | ||||
|     surface.spill_item_stack(position, { name = harvest, count = random(1, 5) }, true) | ||||
|     local particle = particles[harvest] | ||||
|     create_particles(surface, particle, position, 16, {x = entity.position.x, y = entity.position.y}) | ||||
|     create_particles(surface, particle, position, 16, { x = entity.position.x, y = entity.position.y }) | ||||
| end | ||||
|  | ||||
| local function randomness(data) | ||||
| @@ -300,14 +303,14 @@ local function randomness(data) | ||||
|         harvest = harvest_raffle_ores[random(1, size_of_ore_raffle)] | ||||
|     end | ||||
|  | ||||
|     local position = {x = entity.position.x, y = entity.position.y} | ||||
|     local position = { x = entity.position.x, y = entity.position.y } | ||||
|  | ||||
|     player.surface.create_entity( | ||||
|         { | ||||
|             name = 'flying-text', | ||||
|             position = position, | ||||
|             text = '+' .. harvest_amount .. '  [img=item/' .. harvest .. ']', | ||||
|             color = {r = 200, g = 160, b = 30} | ||||
|             color = { r = 200, g = 160, b = 30 } | ||||
|         } | ||||
|     ) | ||||
|  | ||||
| @@ -317,33 +320,33 @@ local function randomness(data) | ||||
|  | ||||
|     if harvest_amount > max_spill then | ||||
|         if spill_items_to_surface then | ||||
|             player.surface.spill_item_stack(position, {name = harvest, count = max_spill}, true) | ||||
|             player.surface.spill_item_stack(position, { name = harvest, count = max_spill }, true) | ||||
|         else | ||||
|             player.insert({name = harvest, count = max_spill}) | ||||
|             player.insert({ name = harvest, count = max_spill }) | ||||
|         end | ||||
|         harvest_amount = harvest_amount - max_spill | ||||
|         local inserted_count = player.insert({name = harvest, count = harvest_amount}) | ||||
|         local inserted_count = player.insert({ name = harvest, count = harvest_amount }) | ||||
|         harvest_amount = harvest_amount - inserted_count | ||||
|         if harvest_amount > 0 then | ||||
|             if spill_items_to_surface then | ||||
|                 player.surface.spill_item_stack(position, {name = harvest, count = harvest_amount}, true) | ||||
|                 player.surface.spill_item_stack(position, { name = harvest, count = harvest_amount }, true) | ||||
|             else | ||||
|                 player.insert({name = harvest, count = harvest_amount}) | ||||
|                 player.insert({ name = harvest, count = harvest_amount }) | ||||
|             end | ||||
|         end | ||||
|     else | ||||
|         if spill_items_to_surface then | ||||
|             player.surface.spill_item_stack(position, {name = harvest, count = harvest_amount}, true) | ||||
|             player.surface.spill_item_stack(position, { name = harvest, count = harvest_amount }, true) | ||||
|         else | ||||
|             player.insert({name = harvest, count = harvest_amount}) | ||||
|             player.insert({ name = harvest, count = harvest_amount }) | ||||
|         end | ||||
|     end | ||||
|     local particle = particles[harvest] | ||||
|  | ||||
|     if data.script_character then | ||||
|         create_particles(player.surface, particle, position, 16, {x = data.script_character.position.x, y = data.script_character.position.y}) | ||||
|         create_particles(player.surface, particle, position, 16, { x = data.script_character.position.x, y = data.script_character.position.y }) | ||||
|     else | ||||
|         create_particles(player.surface, particle, position, 16, {x = player.position.x, y = player.position.y}) | ||||
|         create_particles(player.surface, particle, position, 16, { x = player.position.x, y = player.position.y }) | ||||
|     end | ||||
| end | ||||
|  | ||||
| @@ -358,14 +361,14 @@ local function randomness_scrap(data) | ||||
|     local r2 = math.ceil(scrap_yield_amounts[harvest] * (1.7 + (amount_bonus * 1.7))) | ||||
|     local harvest_amount = math.random(r1, r2) | ||||
|  | ||||
|     local position = {x = entity.position.x, y = entity.position.y} | ||||
|     local position = { x = entity.position.x, y = entity.position.y } | ||||
|  | ||||
|     player.surface.create_entity( | ||||
|         { | ||||
|             name = 'flying-text', | ||||
|             position = position, | ||||
|             text = '+' .. harvest_amount .. '  [img=item/' .. harvest .. ']', | ||||
|             color = {r = 200, g = 160, b = 30} | ||||
|             color = { r = 200, g = 160, b = 30 } | ||||
|         } | ||||
|     ) | ||||
|  | ||||
| @@ -375,32 +378,32 @@ local function randomness_scrap(data) | ||||
|  | ||||
|     if harvest_amount > max_spill then | ||||
|         if spill_items_to_surface then | ||||
|             player.surface.spill_item_stack(position, {name = harvest, count = max_spill}, true) | ||||
|             player.surface.spill_item_stack(position, { name = harvest, count = max_spill }, true) | ||||
|         else | ||||
|             player.insert({name = harvest, count = max_spill}) | ||||
|             player.insert({ name = harvest, count = max_spill }) | ||||
|         end | ||||
|         harvest_amount = harvest_amount - max_spill | ||||
|         local inserted_count = player.insert({name = harvest, count = harvest_amount}) | ||||
|         local inserted_count = player.insert({ name = harvest, count = harvest_amount }) | ||||
|         harvest_amount = harvest_amount - inserted_count | ||||
|         if harvest_amount > 0 then | ||||
|             if spill_items_to_surface then | ||||
|                 player.surface.spill_item_stack(position, {name = harvest, count = harvest_amount}, true) | ||||
|                 player.surface.spill_item_stack(position, { name = harvest, count = harvest_amount }, true) | ||||
|             else | ||||
|                 player.insert({name = harvest, count = harvest_amount}) | ||||
|                 player.insert({ name = harvest, count = harvest_amount }) | ||||
|             end | ||||
|         end | ||||
|     else | ||||
|         if spill_items_to_surface then | ||||
|             player.surface.spill_item_stack(position, {name = harvest, count = harvest_amount}, true) | ||||
|             player.surface.spill_item_stack(position, { name = harvest, count = harvest_amount }, true) | ||||
|         else | ||||
|             player.insert({name = harvest, count = harvest_amount}) | ||||
|             player.insert({ name = harvest, count = harvest_amount }) | ||||
|         end | ||||
|     end | ||||
|     local particle = particles[harvest] | ||||
|     if data.script_character then | ||||
|         create_particles(player.surface, particle, position, 64, {x = data.script_character.position.x, y = data.script_character.position.y}) | ||||
|         create_particles(player.surface, particle, position, 64, { x = data.script_character.position.x, y = data.script_character.position.y }) | ||||
|     else | ||||
|         create_particles(player.surface, particle, position, 64, {x = player.position.x, y = player.position.y}) | ||||
|         create_particles(player.surface, particle, position, 64, { x = player.position.x, y = player.position.y }) | ||||
|     end | ||||
| end | ||||
|  | ||||
| @@ -433,6 +436,10 @@ function Public.on_player_mined_entity(event) | ||||
|             return | ||||
|         end | ||||
|  | ||||
|         if Public.get('final_battle') then | ||||
|             return | ||||
|         end | ||||
|  | ||||
|         local data = { | ||||
|             entity = entity, | ||||
|             player = player | ||||
| @@ -457,7 +464,7 @@ end | ||||
|  | ||||
| Event.add( | ||||
|     Public.events.on_entity_mined, | ||||
|     function(event) | ||||
|     function (event) | ||||
|         if not event then | ||||
|             return | ||||
|         end | ||||
| @@ -468,7 +475,7 @@ Event.add( | ||||
|  | ||||
| Event.add( | ||||
|     Ai.events.on_entity_mined, | ||||
|     function(event) | ||||
|     function (event) | ||||
|         if not event then | ||||
|             return | ||||
|         end | ||||
|   | ||||
| @@ -61,17 +61,17 @@ end | ||||
|  | ||||
| local spread_particles_token = | ||||
|     Task.register( | ||||
|     function(event) | ||||
|         local player_index = event.player_index | ||||
|         local player = game.get_player(player_index) | ||||
|         if not player or not player.valid then | ||||
|             return | ||||
|         end | ||||
|         local particle = event.particle | ||||
|         function (event) | ||||
|             local player_index = event.player_index | ||||
|             local player = game.get_player(player_index) | ||||
|             if not player or not player.valid then | ||||
|                 return | ||||
|             end | ||||
|             local particle = event.particle | ||||
|  | ||||
|         create_particles(player.surface, particle, player.position, 128) | ||||
|     end | ||||
| ) | ||||
|             create_particles(player.surface, particle, player.position, 128) | ||||
|         end | ||||
|     ) | ||||
|  | ||||
| local function pretty_format(input) | ||||
|     local action = string.gsub(input, '-', ' ') | ||||
| @@ -147,7 +147,7 @@ end | ||||
|  | ||||
| local function clear_all_frames() | ||||
|     Core.iter_players( | ||||
|         function(player) | ||||
|         function (player) | ||||
|             local b_frame = player.gui.screen[boss_frame_name] | ||||
|             if b_frame then | ||||
|                 Gui.remove_data_recursively(b_frame) | ||||
| @@ -165,7 +165,7 @@ end | ||||
|  | ||||
| local function refresh_frames() | ||||
|     Core.iter_connected_players( | ||||
|         function(player) | ||||
|         function (player) | ||||
|             local frame = player.gui.screen[main_frame_name] | ||||
|             if frame and frame.valid then | ||||
|                 Gui.remove_data_recursively(frame) | ||||
| @@ -180,35 +180,35 @@ end | ||||
|  | ||||
| local warn_player_sound_token = | ||||
|     Task.register( | ||||
|     function(event) | ||||
|         local player_index = event.player_index | ||||
|         local player = game.get_player(player_index) | ||||
|         if not player or not player.valid then | ||||
|             return | ||||
|         function (event) | ||||
|             local player_index = event.player_index | ||||
|             local player = game.get_player(player_index) | ||||
|             if not player or not player.valid then | ||||
|                 return | ||||
|             end | ||||
|             local particle = event.particle | ||||
|  | ||||
|             player.play_sound { path = 'utility/new_objective', volume_modifier = 0.75 } | ||||
|  | ||||
|             create_particles(player.surface, particle, player.position, 128) | ||||
|         end | ||||
|         local particle = event.particle | ||||
|  | ||||
|         player.play_sound {path = 'utility/new_objective', volume_modifier = 0.75} | ||||
|  | ||||
|         create_particles(player.surface, particle, player.position, 128) | ||||
|     end | ||||
| ) | ||||
|     ) | ||||
|  | ||||
| local function create_button(player) | ||||
|     if Gui.get_mod_gui_top_frame() then | ||||
|         local b = | ||||
|             Gui.add_mod_button( | ||||
|             player, | ||||
|             { | ||||
|                 type = 'sprite-button', | ||||
|                 name = main_button_name, | ||||
|                 sprite = 'utility/custom_tag_icon', | ||||
|                 tooltip = 'Has information about all objectives that needs to be completed', | ||||
|                 style = Gui.button_style | ||||
|             } | ||||
|         ) | ||||
|                 player, | ||||
|                 { | ||||
|                     type = 'sprite-button', | ||||
|                     name = main_button_name, | ||||
|                     sprite = 'utility/custom_tag_icon', | ||||
|                     tooltip = 'Has information about all objectives that needs to be completed', | ||||
|                     style = Gui.button_style | ||||
|                 } | ||||
|             ) | ||||
|         if b then | ||||
|             b.style.font_color = {165, 165, 165} | ||||
|             b.style.font_color = { 165, 165, 165 } | ||||
|             b.style.font = 'heading-3' | ||||
|             b.style.minimal_height = 36 | ||||
|             b.style.maximal_height = 36 | ||||
| @@ -218,14 +218,14 @@ local function create_button(player) | ||||
|     else | ||||
|         local b = | ||||
|             player.gui.top.add( | ||||
|             { | ||||
|                 type = 'sprite-button', | ||||
|                 name = main_button_name, | ||||
|                 sprite = 'utility/custom_tag_icon', | ||||
|                 tooltip = 'Has information about all objectives that needs to be completed', | ||||
|                 style = Gui.button_style | ||||
|             } | ||||
|         ) | ||||
|                 { | ||||
|                     type = 'sprite-button', | ||||
|                     name = main_button_name, | ||||
|                     sprite = 'utility/custom_tag_icon', | ||||
|                     tooltip = 'Has information about all objectives that needs to be completed', | ||||
|                     style = Gui.button_style | ||||
|                 } | ||||
|             ) | ||||
|         b.style.minimal_height = 38 | ||||
|         b.style.maximal_height = 38 | ||||
|     end | ||||
| @@ -233,13 +233,13 @@ end | ||||
|  | ||||
| local function create_input_element(frame, type, value, items, index, tooltip, custom_space) | ||||
|     if type == 'slider' then | ||||
|         return frame.add({type = 'slider', value = value, minimum_value = 0, maximum_value = 1}) | ||||
|         return frame.add({ type = 'slider', value = value, minimum_value = 0, maximum_value = 1 }) | ||||
|     end | ||||
|     if type == 'boolean' then | ||||
|         return frame.add({type = 'checkbox', state = value}) | ||||
|         return frame.add({ type = 'checkbox', state = value }) | ||||
|     end | ||||
|     if type == 'label' then | ||||
|         local label = frame.add({type = 'label', caption = value}) | ||||
|         local label = frame.add({ type = 'label', caption = value }) | ||||
|         label.style.font = 'default-listbox' | ||||
|         label.tooltip = tooltip or '' | ||||
|         if custom_space then | ||||
| @@ -248,62 +248,62 @@ local function create_input_element(frame, type, value, items, index, tooltip, c | ||||
|         return label | ||||
|     end | ||||
|     if type == 'dropdown' then | ||||
|         return frame.add({type = 'drop-down', items = items, selected_index = index}) | ||||
|         return frame.add({ type = 'drop-down', items = items, selected_index = index }) | ||||
|     end | ||||
|     return frame.add({type = 'text-box', text = value}) | ||||
|     return frame.add({ type = 'text-box', text = value }) | ||||
| end | ||||
|  | ||||
| local function play_game_won() | ||||
|     Explosives.disable(false) | ||||
|     Core.iter_connected_players( | ||||
|         function(player) | ||||
|         function (player) | ||||
|             Explosives.detonate_entity(player) | ||||
|             player.play_sound {path = 'utility/game_won', volume_modifier = 0.75} | ||||
|             Task.set_timeout_in_ticks(10, spread_particles_token, {player_index = player.index, particle = 'iron-ore-particle'}) | ||||
|             Task.set_timeout_in_ticks(15, spread_particles_token, {player_index = player.index, particle = 'branch-particle'}) | ||||
|             Task.set_timeout_in_ticks(20, spread_particles_token, {player_index = player.index, particle = 'copper-ore-particle'}) | ||||
|             Task.set_timeout_in_ticks(25, spread_particles_token, {player_index = player.index, particle = 'branch-particle'}) | ||||
|             Task.set_timeout_in_ticks(30, spread_particles_token, {player_index = player.index, particle = 'stone-particle'}) | ||||
|             Task.set_timeout_in_ticks(35, spread_particles_token, {player_index = player.index, particle = 'branch-particle'}) | ||||
|             Task.set_timeout_in_ticks(40, spread_particles_token, {player_index = player.index, particle = 'coal-particle'}) | ||||
|             Task.set_timeout_in_ticks(45, spread_particles_token, {player_index = player.index, particle = 'branch-particle'}) | ||||
|             player.play_sound { path = 'utility/game_won', volume_modifier = 0.75 } | ||||
|             Task.set_timeout_in_ticks(10, spread_particles_token, { player_index = player.index, particle = 'iron-ore-particle' }) | ||||
|             Task.set_timeout_in_ticks(15, spread_particles_token, { player_index = player.index, particle = 'branch-particle' }) | ||||
|             Task.set_timeout_in_ticks(20, spread_particles_token, { player_index = player.index, particle = 'copper-ore-particle' }) | ||||
|             Task.set_timeout_in_ticks(25, spread_particles_token, { player_index = player.index, particle = 'branch-particle' }) | ||||
|             Task.set_timeout_in_ticks(30, spread_particles_token, { player_index = player.index, particle = 'stone-particle' }) | ||||
|             Task.set_timeout_in_ticks(35, spread_particles_token, { player_index = player.index, particle = 'branch-particle' }) | ||||
|             Task.set_timeout_in_ticks(40, spread_particles_token, { player_index = player.index, particle = 'coal-particle' }) | ||||
|             Task.set_timeout_in_ticks(45, spread_particles_token, { player_index = player.index, particle = 'branch-particle' }) | ||||
|         end | ||||
|     ) | ||||
| end | ||||
|  | ||||
| local function play_achievement_unlocked() | ||||
|     Core.iter_connected_players( | ||||
|         function(player) | ||||
|             player.play_sound {path = 'utility/achievement_unlocked', volume_modifier = 0.75} | ||||
|             Task.set_timeout_in_ticks(10, spread_particles_token, {player_index = player.index, particle = 'iron-ore-particle'}) | ||||
|             Task.set_timeout_in_ticks(15, spread_particles_token, {player_index = player.index, particle = 'branch-particle'}) | ||||
|             Task.set_timeout_in_ticks(20, spread_particles_token, {player_index = player.index, particle = 'copper-ore-particle'}) | ||||
|             Task.set_timeout_in_ticks(25, spread_particles_token, {player_index = player.index, particle = 'branch-particle'}) | ||||
|             Task.set_timeout_in_ticks(30, spread_particles_token, {player_index = player.index, particle = 'stone-particle'}) | ||||
|             Task.set_timeout_in_ticks(35, spread_particles_token, {player_index = player.index, particle = 'branch-particle'}) | ||||
|             Task.set_timeout_in_ticks(40, spread_particles_token, {player_index = player.index, particle = 'coal-particle'}) | ||||
|             Task.set_timeout_in_ticks(45, spread_particles_token, {player_index = player.index, particle = 'branch-particle'}) | ||||
|         function (player) | ||||
|             player.play_sound { path = 'utility/achievement_unlocked', volume_modifier = 0.75 } | ||||
|             Task.set_timeout_in_ticks(10, spread_particles_token, { player_index = player.index, particle = 'iron-ore-particle' }) | ||||
|             Task.set_timeout_in_ticks(15, spread_particles_token, { player_index = player.index, particle = 'branch-particle' }) | ||||
|             Task.set_timeout_in_ticks(20, spread_particles_token, { player_index = player.index, particle = 'copper-ore-particle' }) | ||||
|             Task.set_timeout_in_ticks(25, spread_particles_token, { player_index = player.index, particle = 'branch-particle' }) | ||||
|             Task.set_timeout_in_ticks(30, spread_particles_token, { player_index = player.index, particle = 'stone-particle' }) | ||||
|             Task.set_timeout_in_ticks(35, spread_particles_token, { player_index = player.index, particle = 'branch-particle' }) | ||||
|             Task.set_timeout_in_ticks(40, spread_particles_token, { player_index = player.index, particle = 'coal-particle' }) | ||||
|             Task.set_timeout_in_ticks(45, spread_particles_token, { player_index = player.index, particle = 'branch-particle' }) | ||||
|         end | ||||
|     ) | ||||
| end | ||||
|  | ||||
| local function alert_players_sound() | ||||
|     Core.iter_connected_players( | ||||
|         function(player) | ||||
|             Task.set_timeout_in_ticks(10, warn_player_sound_token, {player_index = player.index, particle = 'iron-ore-particle'}) | ||||
|             Task.set_timeout_in_ticks(20, warn_player_sound_token, {player_index = player.index, particle = 'branch-particle'}) | ||||
|             Task.set_timeout_in_ticks(30, warn_player_sound_token, {player_index = player.index, particle = 'copper-ore-particle'}) | ||||
|             Task.set_timeout_in_ticks(40, warn_player_sound_token, {player_index = player.index, particle = 'branch-particle'}) | ||||
|             Task.set_timeout_in_ticks(50, warn_player_sound_token, {player_index = player.index, particle = 'stone-particle'}) | ||||
|             Task.set_timeout_in_ticks(60, warn_player_sound_token, {player_index = player.index, particle = 'branch-particle'}) | ||||
|             Task.set_timeout_in_ticks(70, warn_player_sound_token, {player_index = player.index, particle = 'coal-particle'}) | ||||
|             Task.set_timeout_in_ticks(80, warn_player_sound_token, {player_index = player.index, particle = 'branch-particle'}) | ||||
|         function (player) | ||||
|             Task.set_timeout_in_ticks(10, warn_player_sound_token, { player_index = player.index, particle = 'iron-ore-particle' }) | ||||
|             Task.set_timeout_in_ticks(20, warn_player_sound_token, { player_index = player.index, particle = 'branch-particle' }) | ||||
|             Task.set_timeout_in_ticks(30, warn_player_sound_token, { player_index = player.index, particle = 'copper-ore-particle' }) | ||||
|             Task.set_timeout_in_ticks(40, warn_player_sound_token, { player_index = player.index, particle = 'branch-particle' }) | ||||
|             Task.set_timeout_in_ticks(50, warn_player_sound_token, { player_index = player.index, particle = 'stone-particle' }) | ||||
|             Task.set_timeout_in_ticks(60, warn_player_sound_token, { player_index = player.index, particle = 'branch-particle' }) | ||||
|             Task.set_timeout_in_ticks(70, warn_player_sound_token, { player_index = player.index, particle = 'coal-particle' }) | ||||
|             Task.set_timeout_in_ticks(80, warn_player_sound_token, { player_index = player.index, particle = 'branch-particle' }) | ||||
|         end | ||||
|     ) | ||||
| end | ||||
|  | ||||
| local function spacer(frame) | ||||
|     local flow = frame.add({type = 'flow'}) | ||||
|     local flow = frame.add({ type = 'flow' }) | ||||
|     flow.style.minimal_height = 2 | ||||
| end | ||||
|  | ||||
| @@ -311,33 +311,33 @@ local function objective_frames(stateful, player_frame, objective, data) | ||||
|     local objective_name = objective.name | ||||
|     if objective_name == 'supplies' or objective_name == 'single_item' then | ||||
|         local supplies = stateful.objectives.supplies | ||||
|         local tbl = player_frame.add {type = 'table', column_count = 2} | ||||
|         local tbl = player_frame.add { type = 'table', column_count = 2 } | ||||
|         tbl.style.horizontally_stretchable = true | ||||
|         local left_flow = tbl.add({type = 'flow'}) | ||||
|         local left_flow = tbl.add({ type = 'flow' }) | ||||
|         left_flow.style.horizontal_align = 'left' | ||||
|         left_flow.style.horizontally_stretchable = true | ||||
|  | ||||
|         if objective_name == 'single_item' then | ||||
|             left_flow.add({type = 'label', caption = {'stateful.production_single'}, tooltip = {'stateful.production_tooltip'}}) | ||||
|             left_flow.add({ type = 'label', caption = { 'stateful.production_single' }, tooltip = { 'stateful.production_tooltip' } }) | ||||
|         else | ||||
|             left_flow.add({type = 'label', caption = {'stateful.production'}, tooltip = {'stateful.production_tooltip'}}) | ||||
|             left_flow.add({ type = 'label', caption = { 'stateful.production' }, tooltip = { 'stateful.production_tooltip' } }) | ||||
|         end | ||||
|         player_frame.add({type = 'line', direction = 'vertical'}) | ||||
|         local right_flow = tbl.add({type = 'flow'}) | ||||
|         player_frame.add({ type = 'line', direction = 'vertical' }) | ||||
|         local right_flow = tbl.add({ type = 'flow' }) | ||||
|         right_flow.style.horizontal_align = 'right' | ||||
|         right_flow.style.horizontally_stretchable = true | ||||
|  | ||||
|         if objective_name == 'single_item' then | ||||
|             if stateful.objectives_completed.single_item then | ||||
|                 data.single_item_complete = right_flow.add({type = 'label', caption = ' [img=utility/check_mark_green]', tooltip = {'stateful.tooltip_completed'}}) | ||||
|                 data.single_item_complete = right_flow.add({ type = 'label', caption = ' [img=utility/check_mark_green]', tooltip = { 'stateful.tooltip_completed' } }) | ||||
|             else | ||||
|                 data.single_item_complete = right_flow.add({type = 'label', caption = ' [img=utility/not_available]', tooltip = {'stateful.tooltip_not_completed'}}) | ||||
|                 data.single_item_complete = right_flow.add({ type = 'label', caption = ' [img=utility/not_available]', tooltip = { 'stateful.tooltip_not_completed' } }) | ||||
|             end | ||||
|         else | ||||
|             if stateful.objectives_completed.supplies then | ||||
|                 data.supply_completed = right_flow.add({type = 'label', caption = ' [img=utility/check_mark_green]', tooltip = {'stateful.tooltip_completed'}}) | ||||
|                 data.supply_completed = right_flow.add({ type = 'label', caption = ' [img=utility/check_mark_green]', tooltip = { 'stateful.tooltip_completed' } }) | ||||
|             else | ||||
|                 data.supply_completed = right_flow.add({type = 'label', caption = ' [img=utility/not_available]', tooltip = {'stateful.tooltip_not_completed'}}) | ||||
|                 data.supply_completed = right_flow.add({ type = 'label', caption = ' [img=utility/not_available]', tooltip = { 'stateful.tooltip_not_completed' } }) | ||||
|             end | ||||
|         end | ||||
|  | ||||
| @@ -345,15 +345,15 @@ local function objective_frames(stateful, player_frame, objective, data) | ||||
|             data.supply = {} | ||||
|         end | ||||
|  | ||||
|         local flow = player_frame.add({type = 'flow'}) | ||||
|         local item_table = flow.add({type = 'table', name = 'item_table', column_count = 3}) | ||||
|         local flow = player_frame.add({ type = 'flow' }) | ||||
|         local item_table = flow.add({ type = 'table', name = 'item_table', column_count = 3 }) | ||||
|         if objective_name ~= 'single_item' then | ||||
|             data.supply[#data.supply + 1] = item_table.add({type = 'sprite-button', name = supplies[1].name, sprite = 'item/' .. supplies[1].name, enabled = false, number = supplies[1].count}) | ||||
|             data.supply[#data.supply + 1] = item_table.add({type = 'sprite-button', name = supplies[2].name, sprite = 'item/' .. supplies[2].name, enabled = false, number = supplies[2].count}) | ||||
|             data.supply[#data.supply + 1] = item_table.add({type = 'sprite-button', name = supplies[3].name, sprite = 'item/' .. supplies[3].name, enabled = false, number = supplies[3].count}) | ||||
|             data.supply[#data.supply + 1] = item_table.add({ type = 'sprite-button', name = supplies[1].name, sprite = 'item/' .. supplies[1].name, enabled = false, number = supplies[1].count }) | ||||
|             data.supply[#data.supply + 1] = item_table.add({ type = 'sprite-button', name = supplies[2].name, sprite = 'item/' .. supplies[2].name, enabled = false, number = supplies[2].count }) | ||||
|             data.supply[#data.supply + 1] = item_table.add({ type = 'sprite-button', name = supplies[3].name, sprite = 'item/' .. supplies[3].name, enabled = false, number = supplies[3].count }) | ||||
|         else | ||||
|             local single_item = stateful.objectives.single_item | ||||
|             data.single_item = item_table.add({type = 'sprite-button', name = single_item.name, sprite = 'item/' .. single_item.name, enabled = false, number = single_item.count}) | ||||
|             data.single_item = item_table.add({ type = 'sprite-button', name = single_item.name, sprite = 'item/' .. single_item.name, enabled = false, number = single_item.count }) | ||||
|         end | ||||
|  | ||||
|         return | ||||
| @@ -363,19 +363,19 @@ local function objective_frames(stateful, player_frame, objective, data) | ||||
|  | ||||
|     local _, objective_locale_left, objective_locale_right, tooltip_left, tooltip_right = callback() | ||||
|  | ||||
|     local tbl = player_frame.add {type = 'table', column_count = 2} | ||||
|     local tbl = player_frame.add { type = 'table', column_count = 2 } | ||||
|     tbl.style.horizontally_stretchable = true | ||||
|     local left_flow = tbl.add({type = 'flow'}) | ||||
|     local left_flow = tbl.add({ type = 'flow' }) | ||||
|     left_flow.style.horizontal_align = 'left' | ||||
|     left_flow.style.horizontally_stretchable = true | ||||
|  | ||||
|     left_flow.add({type = 'label', caption = objective_locale_left, tooltip = tooltip_left}) | ||||
|     local right_flow = tbl.add({type = 'flow'}) | ||||
|     left_flow.add({ type = 'label', caption = objective_locale_left, tooltip = tooltip_left }) | ||||
|     local right_flow = tbl.add({ type = 'flow' }) | ||||
|     right_flow.style.horizontal_align = 'right' | ||||
|     right_flow.style.horizontally_stretchable = true | ||||
|  | ||||
|     local objective_locale_right_label = right_flow.add({type = 'label', caption = objective_locale_right, tooltip = tooltip_right}) | ||||
|     data.random_objectives[#data.random_objectives + 1] = {name = objective_name, frame = objective_locale_right_label} | ||||
|     local objective_locale_right_label = right_flow.add({ type = 'label', caption = objective_locale_right, tooltip = tooltip_right }) | ||||
|     data.random_objectives[#data.random_objectives + 1] = { name = objective_name, frame = objective_locale_right_label } | ||||
|     return | ||||
| end | ||||
|  | ||||
| @@ -393,16 +393,16 @@ local function buff_window(player) | ||||
|     local inside_table_style = inside_table.style | ||||
|     inside_table_style.width = 530 | ||||
|  | ||||
|     local info_text = inside_table.add({type = 'label', caption = 'All the buffs that have been gathered throughout the runs!'}) | ||||
|     local info_text = inside_table.add({ type = 'label', caption = 'All the buffs that have been gathered throughout the runs!' }) | ||||
|     local info_text_style = info_text.style | ||||
|     info_text_style.font = 'heading-2' | ||||
|     info_text_style.padding = 0 | ||||
|     info_text_style.left_padding = 10 | ||||
|     info_text_style.horizontal_align = 'left' | ||||
|     info_text_style.vertical_align = 'bottom' | ||||
|     info_text_style.font_color = {0.55, 0.55, 0.99} | ||||
|     info_text_style.font_color = { 0.55, 0.55, 0.99 } | ||||
|  | ||||
|     local buff_pane = inside_table.add({type = 'scroll-pane'}) | ||||
|     local buff_pane = inside_table.add({ type = 'scroll-pane' }) | ||||
|     local ns = buff_pane.style | ||||
|     ns.vertically_squashable = true | ||||
|     ns.bottom_padding = 5 | ||||
| @@ -410,36 +410,36 @@ local function buff_window(player) | ||||
|     ns.right_padding = 5 | ||||
|     ns.top_padding = 5 | ||||
|  | ||||
|     buff_pane.add({type = 'line'}) | ||||
|     buff_pane.add({ type = 'line' }) | ||||
|  | ||||
|     local starting_items_label = buff_pane.add({type = 'label', caption = 'Starting items'}) | ||||
|     local starting_items_label = buff_pane.add({ type = 'label', caption = 'Starting items' }) | ||||
|     local starting_items_label_style = starting_items_label.style | ||||
|     starting_items_label_style.font = 'heading-3' | ||||
|     starting_items_label_style.padding = 0 | ||||
|     starting_items_label_style.horizontal_align = 'left' | ||||
|     starting_items_label_style.font_color = {0.55, 0.55, 0.99} | ||||
|     starting_items_label_style.font_color = { 0.55, 0.55, 0.99 } | ||||
|  | ||||
|     local starting_grid = buff_pane.add({type = 'table', column_count = 8}) | ||||
|     local starting_grid = buff_pane.add({ type = 'table', column_count = 8 }) | ||||
|  | ||||
|     buff_pane.add({type = 'line'}) | ||||
|     buff_pane.add({ type = 'line' }) | ||||
|  | ||||
|     local force_label = buff_pane.add({type = 'label', caption = 'Force Buffs'}) | ||||
|     local force_label = buff_pane.add({ type = 'label', caption = 'Force Buffs' }) | ||||
|     local force_label_style = force_label.style | ||||
|     force_label_style.font = 'heading-3' | ||||
|     force_label_style.padding = 0 | ||||
|     force_label_style.horizontal_align = 'left' | ||||
|     force_label_style.font_color = {0.55, 0.55, 0.99} | ||||
|     local force_grid = buff_pane.add({type = 'table', column_count = 2}) | ||||
|     force_label_style.font_color = { 0.55, 0.55, 0.99 } | ||||
|     local force_grid = buff_pane.add({ type = 'table', column_count = 2 }) | ||||
|  | ||||
|     buff_pane.add({type = 'line'}) | ||||
|     buff_pane.add({ type = 'line' }) | ||||
|  | ||||
|     local custom_label = buff_pane.add({type = 'label', caption = 'Custom Buffs'}) | ||||
|     local custom_label = buff_pane.add({ type = 'label', caption = 'Custom Buffs' }) | ||||
|     local custom_label_style = custom_label.style | ||||
|     custom_label_style.font = 'heading-3' | ||||
|     custom_label_style.padding = 0 | ||||
|     custom_label_style.horizontal_align = 'left' | ||||
|     custom_label_style.font_color = {0.55, 0.55, 0.99} | ||||
|     local custom_grid = buff_pane.add({type = 'table', column_count = 2}) | ||||
|     custom_label_style.font_color = { 0.55, 0.55, 0.99 } | ||||
|     local custom_grid = buff_pane.add({ type = 'table', column_count = 2 }) | ||||
|  | ||||
|     if stateful.buffs and next(stateful.buffs) then | ||||
|         if stateful.buffs_collected and next(stateful.buffs_collected) then | ||||
| @@ -501,64 +501,64 @@ local function boss_frame(player, alert) | ||||
|     local stateful = Public.get_stateful() | ||||
|     local collection = stateful.collection | ||||
|  | ||||
|     local frame = player.gui.screen.add {type = 'frame', name = boss_frame_name, caption = {'stateful.win_conditions'}, direction = 'vertical'} | ||||
|     local frame = player.gui.screen.add { type = 'frame', name = boss_frame_name, caption = { 'stateful.win_conditions' }, direction = 'vertical' } | ||||
|     if not alert then | ||||
|         frame.location = {x = 1, y = 45} | ||||
|         frame.location = { x = 1, y = 45 } | ||||
|     else | ||||
|         frame.location = {x = 1, y = 123} | ||||
|         frame.location = { x = 1, y = 123 } | ||||
|     end | ||||
|     frame.style.maximal_height = 500 | ||||
|     frame.style.minimal_width = 200 | ||||
|     frame.style.maximal_width = 400 | ||||
|     local season_tbl = frame.add {type = 'table', column_count = 2} | ||||
|     local season_tbl = frame.add { type = 'table', column_count = 2 } | ||||
|     season_tbl.style.horizontally_stretchable = true | ||||
|  | ||||
|     local season_left_flow = season_tbl.add({type = 'flow'}) | ||||
|     local season_left_flow = season_tbl.add({ type = 'flow' }) | ||||
|     season_left_flow.style.horizontal_align = 'left' | ||||
|     season_left_flow.style.horizontally_stretchable = true | ||||
|  | ||||
|     season_left_flow.add({type = 'label', caption = {'stateful.season'}, tooltip = {'stateful.season_tooltip', stateful.time_to_reset}}) | ||||
|     frame.add({type = 'line', direction = 'vertical'}) | ||||
|     local season_right_flow = season_tbl.add({type = 'flow'}) | ||||
|     season_left_flow.add({ type = 'label', caption = { 'stateful.season' }, tooltip = { 'stateful.season_tooltip', stateful.time_to_reset } }) | ||||
|     frame.add({ type = 'line', direction = 'vertical' }) | ||||
|     local season_right_flow = season_tbl.add({ type = 'flow' }) | ||||
|     season_right_flow.style.horizontal_align = 'right' | ||||
|     season_right_flow.style.horizontally_stretchable = true | ||||
|  | ||||
|     data.season_label = season_right_flow.add({type = 'label', caption = stateful.season}) | ||||
|     data.season_label = season_right_flow.add({ type = 'label', caption = stateful.season }) | ||||
|  | ||||
|     spacer(frame) | ||||
|  | ||||
|     local rounds_survived_tbl = frame.add {type = 'table', column_count = 2} | ||||
|     local rounds_survived_tbl = frame.add { type = 'table', column_count = 2 } | ||||
|     rounds_survived_tbl.style.horizontally_stretchable = true | ||||
|  | ||||
|     local rounds_survived_left_flow = rounds_survived_tbl.add({type = 'flow'}) | ||||
|     local rounds_survived_left_flow = rounds_survived_tbl.add({ type = 'flow' }) | ||||
|     rounds_survived_left_flow.style.horizontal_align = 'left' | ||||
|     rounds_survived_left_flow.style.horizontally_stretchable = true | ||||
|  | ||||
|     rounds_survived_left_flow.add({type = 'label', caption = {'stateful.rounds_survived'}, tooltip = {'stateful.rounds_survived_tooltip'}}) | ||||
|     frame.add({type = 'line', direction = 'vertical'}) | ||||
|     local rounds_survived_right_flow = rounds_survived_tbl.add({type = 'flow'}) | ||||
|     rounds_survived_left_flow.add({ type = 'label', caption = { 'stateful.rounds_survived' }, tooltip = { 'stateful.rounds_survived_tooltip' } }) | ||||
|     frame.add({ type = 'line', direction = 'vertical' }) | ||||
|     local rounds_survived_right_flow = rounds_survived_tbl.add({ type = 'flow' }) | ||||
|     rounds_survived_right_flow.style.horizontal_align = 'right' | ||||
|     rounds_survived_right_flow.style.horizontally_stretchable = true | ||||
|  | ||||
|     data.rounds_survived_label = rounds_survived_right_flow.add({type = 'label', caption = stateful.rounds_survived}) | ||||
|     data.rounds_survived_label = rounds_survived_right_flow.add({ type = 'label', caption = stateful.rounds_survived }) | ||||
|     spacer(frame) | ||||
|  | ||||
|     frame.add({type = 'line'}) | ||||
|     frame.add({ type = 'line' }) | ||||
|  | ||||
|     spacer(frame) | ||||
|  | ||||
|     if not collection.game_won then | ||||
|         local objective_tbl = frame.add {type = 'table', column_count = 2} | ||||
|         local objective_tbl = frame.add { type = 'table', column_count = 2 } | ||||
|         objective_tbl.style.horizontally_stretchable = true | ||||
|  | ||||
|         if collection.gather_time <= 0 then | ||||
|             local survive_for_left_flow = objective_tbl.add({type = 'flow'}) | ||||
|             local survive_for_left_flow = objective_tbl.add({ type = 'flow' }) | ||||
|             survive_for_left_flow.style.horizontal_align = 'left' | ||||
|             survive_for_left_flow.style.horizontally_stretchable = true | ||||
|  | ||||
|             survive_for_left_flow.add({type = 'label', caption = {'stateful.survive_for'}}) | ||||
|             frame.add({type = 'line', direction = 'vertical'}) | ||||
|             local survive_for_right_flow = objective_tbl.add({type = 'flow'}) | ||||
|             survive_for_left_flow.add({ type = 'label', caption = { 'stateful.survive_for' } }) | ||||
|             frame.add({ type = 'line', direction = 'vertical' }) | ||||
|             local survive_for_right_flow = objective_tbl.add({ type = 'flow' }) | ||||
|             survive_for_right_flow.style.horizontal_align = 'right' | ||||
|             survive_for_right_flow.style.horizontally_stretchable = true | ||||
|  | ||||
| @@ -569,42 +569,42 @@ local function boss_frame(player, alert) | ||||
|             end | ||||
|  | ||||
|             if collection.survive_for <= 0 then | ||||
|                 data.survive_for = survive_for_right_flow.add({type = 'label', caption = {'stateful.won'}}) | ||||
|                 data.survive_for = survive_for_right_flow.add({ type = 'label', caption = { 'stateful.won' } }) | ||||
|             else | ||||
|                 data.survive_for = survive_for_right_flow.add({type = 'label', caption = survive_for_timer}) | ||||
|                 data.survive_for = survive_for_right_flow.add({ type = 'label', caption = survive_for_timer }) | ||||
|             end | ||||
|         end | ||||
|         -- new frame | ||||
|         local biter_sprites_tbl = objective_tbl.add({type = 'flow'}) | ||||
|         local biter_sprites_tbl = objective_tbl.add({ type = 'flow' }) | ||||
|         biter_sprites_tbl.style.horizontal_align = 'left' | ||||
|         biter_sprites_tbl.style.horizontally_stretchable = true | ||||
|  | ||||
|         biter_sprites_tbl.add({type = 'label', caption = {'stateful.biter_sprites'}}) | ||||
|         biter_sprites_tbl.add({ type = 'label', caption = { 'stateful.biter_sprites' } }) | ||||
|     else | ||||
|         local objective_tbl = frame.add {type = 'table', column_count = 2} | ||||
|         local objective_tbl = frame.add { type = 'table', column_count = 2 } | ||||
|         objective_tbl.style.horizontally_stretchable = true | ||||
|  | ||||
|         local game_won_left_flow = objective_tbl.add({type = 'flow'}) | ||||
|         local game_won_left_flow = objective_tbl.add({ type = 'flow' }) | ||||
|         game_won_left_flow.style.horizontal_align = 'left' | ||||
|         game_won_left_flow.style.horizontally_stretchable = true | ||||
|  | ||||
|         game_won_left_flow.add({type = 'label', caption = {'stateful.game_won'}}) | ||||
|         game_won_left_flow.add({ type = 'label', caption = { 'stateful.game_won' } }) | ||||
|     end | ||||
|  | ||||
|     local close = frame.add({type = 'button', name = close_button, caption = 'Close'}) | ||||
|     local close = frame.add({ type = 'button', name = close_button, caption = 'Close' }) | ||||
|     close.style.horizontally_stretchable = true | ||||
|     Gui.set_data(frame, data) | ||||
| end | ||||
|  | ||||
| local function refresh_boss_frame() | ||||
|     Core.iter_connected_players( | ||||
|         function(player) | ||||
|         function (player) | ||||
|             boss_frame(player) | ||||
|         end | ||||
|     ) | ||||
| end | ||||
|  | ||||
| main_frame = function(player) | ||||
| main_frame = function (player) | ||||
|     local main_player_frame = player.gui.screen[main_frame_name] | ||||
|     if main_player_frame then | ||||
|         Gui.remove_data_recursively(main_player_frame) | ||||
| @@ -618,99 +618,99 @@ main_frame = function(player) | ||||
|     breached_wall = breached_wall - 1 | ||||
|     local wave_number = WD.get('wave_number') | ||||
|  | ||||
|     local frame = player.gui.screen.add {type = 'frame', name = main_frame_name, caption = {'stateful.win_conditions'}, direction = 'vertical', tooltip = {'stateful.win_conditions_tooltip'}} | ||||
|     local frame = player.gui.screen.add { type = 'frame', name = main_frame_name, caption = { 'stateful.win_conditions' }, direction = 'vertical', tooltip = { 'stateful.win_conditions_tooltip' } } | ||||
|     if Gui.get_mod_gui_top_frame() then | ||||
|         frame.location = {x = 0, y = 67} | ||||
|         frame.location = { x = 0, y = 67 } | ||||
|     else | ||||
|         frame.location = {x = 1, y = 45} | ||||
|         frame.location = { x = 1, y = 45 } | ||||
|     end | ||||
|     frame.style.maximal_height = 700 | ||||
|     frame.style.minimal_width = 200 | ||||
|     frame.style.maximal_width = 400 | ||||
|     local season_tbl = frame.add {type = 'table', column_count = 2} | ||||
|     local season_tbl = frame.add { type = 'table', column_count = 2 } | ||||
|     season_tbl.style.horizontally_stretchable = true | ||||
|  | ||||
|     local season_left_flow = season_tbl.add({type = 'flow'}) | ||||
|     local season_left_flow = season_tbl.add({ type = 'flow' }) | ||||
|     season_left_flow.style.horizontal_align = 'left' | ||||
|     season_left_flow.style.horizontally_stretchable = true | ||||
|  | ||||
|     season_left_flow.add({type = 'label', caption = {'stateful.season'}, tooltip = {'stateful.season_tooltip', stateful.time_to_reset}}) | ||||
|     frame.add({type = 'line', direction = 'vertical'}) | ||||
|     local season_right_flow = season_tbl.add({type = 'flow'}) | ||||
|     season_left_flow.add({ type = 'label', caption = { 'stateful.season' }, tooltip = { 'stateful.season_tooltip', stateful.time_to_reset } }) | ||||
|     frame.add({ type = 'line', direction = 'vertical' }) | ||||
|     local season_right_flow = season_tbl.add({ type = 'flow' }) | ||||
|     season_right_flow.style.horizontal_align = 'right' | ||||
|     season_right_flow.style.horizontally_stretchable = true | ||||
|  | ||||
|     data.season_label = season_right_flow.add({type = 'label', caption = stateful.season}) | ||||
|     data.season_label = season_right_flow.add({ type = 'label', caption = stateful.season }) | ||||
|  | ||||
|     spacer(frame) | ||||
|  | ||||
|     local rounds_survived_tbl = frame.add {type = 'table', column_count = 2} | ||||
|     local rounds_survived_tbl = frame.add { type = 'table', column_count = 2 } | ||||
|     rounds_survived_tbl.style.horizontally_stretchable = true | ||||
|  | ||||
|     local rounds_survived_left_flow = rounds_survived_tbl.add({type = 'flow'}) | ||||
|     local rounds_survived_left_flow = rounds_survived_tbl.add({ type = 'flow' }) | ||||
|     rounds_survived_left_flow.style.horizontal_align = 'left' | ||||
|     rounds_survived_left_flow.style.horizontally_stretchable = true | ||||
|  | ||||
|     rounds_survived_left_flow.add({type = 'label', caption = {'stateful.rounds_survived'}, tooltip = {'stateful.rounds_survived_tooltip'}}) | ||||
|     frame.add({type = 'line', direction = 'vertical'}) | ||||
|     local rounds_survived_right_flow = rounds_survived_tbl.add({type = 'flow'}) | ||||
|     rounds_survived_left_flow.add({ type = 'label', caption = { 'stateful.rounds_survived' }, tooltip = { 'stateful.rounds_survived_tooltip' } }) | ||||
|     frame.add({ type = 'line', direction = 'vertical' }) | ||||
|     local rounds_survived_right_flow = rounds_survived_tbl.add({ type = 'flow' }) | ||||
|     rounds_survived_right_flow.style.horizontal_align = 'right' | ||||
|     rounds_survived_right_flow.style.horizontally_stretchable = true | ||||
|  | ||||
|     data.rounds_survived_label = rounds_survived_right_flow.add({type = 'label', caption = stateful.rounds_survived}) | ||||
|     data.rounds_survived_label = rounds_survived_right_flow.add({ type = 'label', caption = stateful.rounds_survived }) | ||||
|     spacer(frame) | ||||
|  | ||||
|     frame.add({type = 'line'}) | ||||
|     frame.add({ type = 'line' }) | ||||
|  | ||||
|     spacer(frame) | ||||
|  | ||||
|     if stateful.buffs and next(stateful.buffs) then | ||||
|         local buff_tbl = frame.add {type = 'table', column_count = 2} | ||||
|         local buff_tbl = frame.add { type = 'table', column_count = 2 } | ||||
|         buff_tbl.style.horizontally_stretchable = true | ||||
|  | ||||
|         local buff_left_flow = buff_tbl.add({type = 'flow'}) | ||||
|         local buff_left_flow = buff_tbl.add({ type = 'flow' }) | ||||
|         buff_left_flow.style.horizontal_align = 'left' | ||||
|         buff_left_flow.style.horizontally_stretchable = true | ||||
|  | ||||
|         local buff_right_flow = buff_tbl.add({type = 'flow'}) | ||||
|         local buff_right_flow = buff_tbl.add({ type = 'flow' }) | ||||
|         buff_right_flow.style.horizontal_align = 'right' | ||||
|         buff_right_flow.style.horizontally_stretchable = true | ||||
|  | ||||
|         buff_right_flow.add({name = on_click_buff_name, type = 'label', caption = '[img=utility/center]', tooltip = {'stateful.buff_tooltip_click'}}) | ||||
|         buff_right_flow.add({ name = on_click_buff_name, type = 'label', caption = '[img=utility/center]', tooltip = { 'stateful.buff_tooltip_click' } }) | ||||
|  | ||||
|         local buff_label = buff_left_flow.add({type = 'label', caption = {'stateful.buffs'}, tooltip = {'stateful.buff_tooltip'}}) | ||||
|         local buff_label = buff_left_flow.add({ type = 'label', caption = { 'stateful.buffs' }, tooltip = { 'stateful.buff_tooltip' } }) | ||||
|         buff_label.style.single_line = false | ||||
|         frame.add({type = 'line', direction = 'vertical'}) | ||||
|         frame.add({ type = 'line', direction = 'vertical' }) | ||||
|  | ||||
|         spacer(frame) | ||||
|  | ||||
|         frame.add({type = 'line'}) | ||||
|         frame.add({ type = 'line' }) | ||||
|     end | ||||
|  | ||||
|     spacer(frame) | ||||
|  | ||||
|     if stateful.objectives_completed.boss_time then | ||||
|         local gather_objective_tbl = frame.add {type = 'table', column_count = 2} | ||||
|         local gather_objective_tbl = frame.add { type = 'table', column_count = 2 } | ||||
|         gather_objective_tbl.style.horizontally_stretchable = true | ||||
|  | ||||
|         local gather_warning_flow = gather_objective_tbl.add({type = 'flow'}) | ||||
|         local gather_warning_flow = gather_objective_tbl.add({ type = 'flow' }) | ||||
|         gather_warning_flow.style.horizontal_align = 'left' | ||||
|         gather_warning_flow.style.horizontally_stretchable = true | ||||
|  | ||||
|         gather_warning_flow.add({type = 'label', caption = {'stateful.gather'}}) | ||||
|         frame.add({type = 'line', direction = 'vertical'}) | ||||
|         gather_warning_flow.add({ type = 'label', caption = { 'stateful.gather' } }) | ||||
|         frame.add({ type = 'line', direction = 'vertical' }) | ||||
|  | ||||
|         local objective_tbl = frame.add {type = 'table', column_count = 2} | ||||
|         local objective_tbl = frame.add { type = 'table', column_count = 2 } | ||||
|         objective_tbl.style.horizontally_stretchable = true | ||||
|  | ||||
|         local warn_timer_flow_left = objective_tbl.add({type = 'flow'}) | ||||
|         local warn_timer_flow_left = objective_tbl.add({ type = 'flow' }) | ||||
|         warn_timer_flow_left.style.horizontal_align = 'left' | ||||
|         warn_timer_flow_left.style.horizontally_stretchable = true | ||||
|  | ||||
|         warn_timer_flow_left.add({type = 'label', caption = {'stateful.warp'}, tooltip = {'stateful.warp_tooltip'}}) | ||||
|         frame.add({type = 'line', direction = 'vertical'}) | ||||
|         warn_timer_flow_left.add({ type = 'label', caption = { 'stateful.warp' }, tooltip = { 'stateful.warp_tooltip' } }) | ||||
|         frame.add({ type = 'line', direction = 'vertical' }) | ||||
|  | ||||
|         local warn_timer_flow_right = objective_tbl.add({type = 'flow'}) | ||||
|         local warn_timer_flow_right = objective_tbl.add({ type = 'flow' }) | ||||
|         warn_timer_flow_right.style.horizontal_align = 'right' | ||||
|         warn_timer_flow_right.style.horizontally_stretchable = true | ||||
|  | ||||
| @@ -720,42 +720,42 @@ main_frame = function(player) | ||||
|             time_left = floor(stateful.collection.gather_time / 60) .. 's' | ||||
|         end | ||||
|  | ||||
|         data.gather_time_label = warn_timer_flow_right.add({type = 'label', caption = time_left}) | ||||
|         data.gather_time_label = warn_timer_flow_right.add({ type = 'label', caption = time_left }) | ||||
|     else | ||||
|         local objective_tbl = frame.add {type = 'table', column_count = 2} | ||||
|         local objective_tbl = frame.add { type = 'table', column_count = 2 } | ||||
|         objective_tbl.style.horizontally_stretchable = true | ||||
|  | ||||
|         local zone_left_flow = objective_tbl.add({type = 'flow'}) | ||||
|         local zone_left_flow = objective_tbl.add({ type = 'flow' }) | ||||
|         zone_left_flow.style.horizontal_align = 'left' | ||||
|         zone_left_flow.style.horizontally_stretchable = true | ||||
|  | ||||
|         zone_left_flow.add({type = 'label', caption = {'stateful.zone'}, tooltip = {'stateful.zone_tooltip'}}) | ||||
|         frame.add({type = 'line', direction = 'vertical'}) | ||||
|         local zone_right_flow = objective_tbl.add({type = 'flow'}) | ||||
|         zone_left_flow.add({ type = 'label', caption = { 'stateful.zone' }, tooltip = { 'stateful.zone_tooltip' } }) | ||||
|         frame.add({ type = 'line', direction = 'vertical' }) | ||||
|         local zone_right_flow = objective_tbl.add({ type = 'flow' }) | ||||
|         zone_right_flow.style.horizontal_align = 'right' | ||||
|         zone_right_flow.style.horizontally_stretchable = true | ||||
|  | ||||
|         if breached_wall >= stateful.objectives.randomized_zone then | ||||
|             data.randomized_zone_label = zone_right_flow.add({type = 'label', caption = breached_wall .. '/' .. stateful.objectives.randomized_zone .. ' [img=utility/check_mark_green]', tooltip = {'stateful.tooltip_completed'}}) | ||||
|             data.randomized_zone_label = zone_right_flow.add({ type = 'label', caption = breached_wall .. '/' .. stateful.objectives.randomized_zone .. ' [img=utility/check_mark_green]', tooltip = { 'stateful.tooltip_completed' } }) | ||||
|         else | ||||
|             data.randomized_zone_label = zone_right_flow.add({type = 'label', caption = breached_wall .. '/' .. stateful.objectives.randomized_zone .. ' [img=utility/not_available]', tooltip = {'stateful.tooltip_not_completed'}}) | ||||
|             data.randomized_zone_label = zone_right_flow.add({ type = 'label', caption = breached_wall .. '/' .. stateful.objectives.randomized_zone .. ' [img=utility/not_available]', tooltip = { 'stateful.tooltip_not_completed' } }) | ||||
|         end | ||||
|  | ||||
|         -- new frame | ||||
|         local wave_left_flow = objective_tbl.add({type = 'flow'}) | ||||
|         local wave_left_flow = objective_tbl.add({ type = 'flow' }) | ||||
|         wave_left_flow.style.horizontal_align = 'left' | ||||
|         wave_left_flow.style.horizontally_stretchable = true | ||||
|  | ||||
|         wave_left_flow.add({type = 'label', caption = {'stateful.wave'}, tooltip = {'stateful.wave_tooltip'}}) | ||||
|         frame.add({type = 'line', direction = 'vertical'}) | ||||
|         local wave_right_flow = objective_tbl.add({type = 'flow'}) | ||||
|         wave_left_flow.add({ type = 'label', caption = { 'stateful.wave' }, tooltip = { 'stateful.wave_tooltip' } }) | ||||
|         frame.add({ type = 'line', direction = 'vertical' }) | ||||
|         local wave_right_flow = objective_tbl.add({ type = 'flow' }) | ||||
|         wave_right_flow.style.horizontal_align = 'right' | ||||
|         wave_right_flow.style.horizontally_stretchable = true | ||||
|  | ||||
|         if wave_number >= stateful.objectives.randomized_wave then | ||||
|             data.randomized_wave_label = wave_right_flow.add({type = 'label', caption = wave_number .. '/' .. stateful.objectives.randomized_wave .. ' [img=utility/check_mark_green]', tooltip = {'stateful.tooltip_completed'}}) | ||||
|             data.randomized_wave_label = wave_right_flow.add({ type = 'label', caption = wave_number .. '/' .. stateful.objectives.randomized_wave .. ' [img=utility/check_mark_green]', tooltip = { 'stateful.tooltip_completed' } }) | ||||
|         else | ||||
|             data.randomized_wave_label = wave_right_flow.add({type = 'label', caption = wave_number .. '/' .. stateful.objectives.randomized_wave .. ' [img=utility/not_available]', tooltip = {'stateful.tooltip_not_completed'}}) | ||||
|             data.randomized_wave_label = wave_right_flow.add({ type = 'label', caption = wave_number .. '/' .. stateful.objectives.randomized_wave .. ' [img=utility/not_available]', tooltip = { 'stateful.tooltip_not_completed' } }) | ||||
|         end | ||||
|  | ||||
|         --dynamic conditions | ||||
| @@ -769,7 +769,7 @@ main_frame = function(player) | ||||
|  | ||||
|     -- warn players | ||||
|     spacer(frame) | ||||
|     frame.add({type = 'line'}) | ||||
|     frame.add({ type = 'line' }) | ||||
|     spacer(frame) | ||||
|     -- if not stateful.collection.final_arena_disabled then | ||||
|     --     local final_label = frame.add({type = 'label', caption = {'stateful.tooltip_final'}}) | ||||
| @@ -784,7 +784,7 @@ main_frame = function(player) | ||||
|     -- frame.add({type = 'line'}) | ||||
|     spacer(frame) | ||||
|  | ||||
|     local close = frame.add({type = 'button', name = close_button, caption = 'Close'}) | ||||
|     local close = frame.add({ type = 'button', name = close_button, caption = 'Close' }) | ||||
|     close.style.horizontally_stretchable = true | ||||
|     Gui.set_data(frame, data) | ||||
| end | ||||
| @@ -818,7 +818,7 @@ local function update_data() | ||||
|             if data.randomized_zone_label and data.randomized_zone_label.valid and stateful.objectives.randomized_zone then | ||||
|                 if breached_wall >= stateful.objectives.randomized_zone then | ||||
|                     data.randomized_zone_label.caption = breached_wall .. '/' .. stateful.objectives.randomized_zone .. ' [img=utility/check_mark_green]' | ||||
|                     data.randomized_zone_label.tooltip = {'stateful.tooltip_completed'} | ||||
|                     data.randomized_zone_label.tooltip = { 'stateful.tooltip_completed' } | ||||
|                 else | ||||
|                     data.randomized_zone_label.caption = breached_wall .. '/' .. stateful.objectives.randomized_zone .. ' [img=utility/not_available]' | ||||
|                 end | ||||
| @@ -827,7 +827,7 @@ local function update_data() | ||||
|             if data.randomized_wave_label and data.randomized_wave_label.valid and stateful.objectives.randomized_wave then | ||||
|                 if wave_number >= stateful.objectives.randomized_wave then | ||||
|                     data.randomized_wave_label.caption = wave_number .. '/' .. stateful.objectives.randomized_wave .. ' [img=utility/check_mark_green]' | ||||
|                     data.randomized_wave_label.tooltip = {'stateful.tooltip_completed'} | ||||
|                     data.randomized_wave_label.tooltip = { 'stateful.tooltip_completed' } | ||||
|                 else | ||||
|                     data.randomized_wave_label.caption = wave_number .. '/' .. stateful.objectives.randomized_wave .. ' [img=utility/not_available]' | ||||
|                 end | ||||
| @@ -947,7 +947,7 @@ local function update_data() | ||||
|                 end | ||||
|  | ||||
|                 if collection.survive_for <= 0 then | ||||
|                     data_boss.survive_for.caption = {'stateful.won'} | ||||
|                     data_boss.survive_for.caption = { 'stateful.won' } | ||||
|                 else | ||||
|                     data_boss.survive_for.caption = survive_for_timer | ||||
|                 end | ||||
| @@ -1079,11 +1079,10 @@ local function update_raw() | ||||
|                 LinkedChests.clear_linked_frames() | ||||
|                 stateful.final_battle = true | ||||
|                 Public.set('final_battle', true) | ||||
|                 WD.set('final_battle', true) | ||||
|  | ||||
|                 collection.survive_for = game.tick + Stateful.scale(10 * 3600, 35 * 3600) | ||||
|                 collection.survive_for_timer = collection.survive_for | ||||
|                 collection.nuke_blueprint = true | ||||
|                 -- Public.stateful_blueprints.nuke_blueprint() | ||||
|                 WD.disable_spawning_biters(false) | ||||
|                 Public.allocate() | ||||
|                 Public.set_final_battle() | ||||
| @@ -1131,7 +1130,7 @@ local function update_raw() | ||||
|                 notify_won_to_discord(buff) | ||||
|                 local locomotive = Public.get('locomotive') | ||||
|                 if locomotive and locomotive.valid then | ||||
|                     locomotive.surface.spill_item_stack(locomotive.position, {name = 'coin', count = 512}, false) | ||||
|                     locomotive.surface.spill_item_stack(locomotive.position, { name = 'coin', count = 512 }, false) | ||||
|                 end | ||||
|                 Public.set('game_reset_tick', 5400) | ||||
|                 return | ||||
| @@ -1193,7 +1192,7 @@ local function update_raw() | ||||
|             notify_won_to_discord(buff) | ||||
|             local locomotive = Public.get('locomotive') | ||||
|             if locomotive and locomotive.valid then | ||||
|                 locomotive.surface.spill_item_stack(locomotive.position, {name = 'coin', count = 512}, false) | ||||
|                 locomotive.surface.spill_item_stack(locomotive.position, { name = 'coin', count = 512 }, false) | ||||
|             end | ||||
|             Public.set('game_reset_tick', 5400) | ||||
|             return | ||||
| @@ -1210,13 +1209,15 @@ local function update_raw() | ||||
|         end | ||||
|         Explosives.disable(true) | ||||
|         WD.disable_spawning_biters(true) | ||||
|         Collapse.set_reverse_position({0, reverse_position}) | ||||
|         WD.set_track_bosses_only(false) | ||||
|         Collapse.set_reverse_position({ 0, reverse_position }) | ||||
|         Collapse.set_reverse_direction() | ||||
|         Collapse.reverse_start_now(true) | ||||
|         Alert.alert_all_players(200, 'Reverse collapse has been initiated!') | ||||
|         Server.to_discord_embed('Reverse collapse has been initiated!') | ||||
|         -- Public.stateful_blueprints.blueprint() | ||||
|         WD.nuke_wave_gui() | ||||
|         WD.set('final_battle', true) | ||||
|         Public.set('pre_final_battle', true) | ||||
|  | ||||
|         refresh_frames() | ||||
| @@ -1236,7 +1237,7 @@ end | ||||
|  | ||||
| Gui.on_click( | ||||
|     main_button_name, | ||||
|     function(event) | ||||
|     function (event) | ||||
|         local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Mtn v3 open stateful Button') | ||||
|         if is_spamming then | ||||
|             return | ||||
| @@ -1279,7 +1280,7 @@ Gui.on_click( | ||||
|  | ||||
| Gui.on_click( | ||||
|     close_button, | ||||
|     function(event) | ||||
|     function (event) | ||||
|         local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Mtn v3 close stateful Button') | ||||
|         if is_spamming then | ||||
|             return | ||||
| @@ -1308,7 +1309,7 @@ Gui.on_click( | ||||
|  | ||||
| Gui.on_click( | ||||
|     close_buffs_window_name, | ||||
|     function(event) | ||||
|     function (event) | ||||
|         local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Buff Close Button') | ||||
|         if is_spamming then | ||||
|             return | ||||
| @@ -1329,7 +1330,7 @@ Gui.on_click( | ||||
|  | ||||
| Gui.on_custom_close( | ||||
|     buffs_window_name, | ||||
|     function(event) | ||||
|     function (event) | ||||
|         local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Buff Custom Close') | ||||
|         if is_spamming then | ||||
|             return | ||||
| @@ -1350,7 +1351,7 @@ Gui.on_custom_close( | ||||
|  | ||||
| Gui.on_click( | ||||
|     on_click_buff_name, | ||||
|     function(event) | ||||
|     function (event) | ||||
|         local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Buff Open Button') | ||||
|         if is_spamming then | ||||
|             return | ||||
|   | ||||
| @@ -9,7 +9,6 @@ Public.stateful_gui = require 'maps.mountain_fortress_v3.stateful.gui' | ||||
| Public.stateful_blueprints = require 'maps.mountain_fortress_v3.stateful.blueprints' | ||||
|  | ||||
| local random = math.random | ||||
| local shuffle = table.shuffle_table | ||||
|  | ||||
| local valid_types = { | ||||
|     ['unit'] = true, | ||||
| @@ -49,7 +48,7 @@ end | ||||
|  | ||||
| Event.add( | ||||
|     defines.events.on_research_finished, | ||||
|     function(event) | ||||
|     function (event) | ||||
|         local research = event.research | ||||
|         if not research then | ||||
|             return | ||||
| @@ -71,8 +70,8 @@ Event.add( | ||||
| ) | ||||
|  | ||||
| Event.on_nth_tick( | ||||
|     350, | ||||
|     function() | ||||
|     150, | ||||
|     function () | ||||
|         local final_battle = Public.get_stateful('final_battle') | ||||
|         if not final_battle then | ||||
|             return | ||||
| @@ -88,32 +87,32 @@ Event.on_nth_tick( | ||||
|         end | ||||
|  | ||||
|         if collection.gather_time and collection.gather_time <= 0 and collection.survive_for and collection.survive_for > 0 then | ||||
|             local spawn_positions = Public.get_stateful('stateful_spawn_points') | ||||
|             local spawn_positions = table.deepcopy(Public.get_stateful('stateful_spawn_points')) | ||||
|  | ||||
|             if not spawn_positions then | ||||
|                 Public.set_stateful( | ||||
|                     'stateful_spawn_points', | ||||
|                     { | ||||
|                         {{x = -205, y = -37}, {x = 195, y = 37}}, | ||||
|                         {{x = -205, y = -112}, {x = 195, y = 112}}, | ||||
|                         {{x = -205, y = -146}, {x = 195, y = 146}}, | ||||
|                         {{x = -205, y = -112}, {x = 195, y = 112}}, | ||||
|                         {{x = -205, y = -72}, {x = 195, y = 72}}, | ||||
|                         {{x = -205, y = -146}, {x = 195, y = 146}}, | ||||
|                         {{x = -205, y = -37}, {x = 195, y = 37}}, | ||||
|                         {{x = -205, y = -5}, {x = 195, y = 5}}, | ||||
|                         {{x = -205, y = -23}, {x = 195, y = 23}}, | ||||
|                         {{x = -205, y = -5}, {x = 195, y = 5}}, | ||||
|                         {{x = -205, y = -72}, {x = 195, y = 72}}, | ||||
|                         {{x = -205, y = -23}, {x = 195, y = 23}}, | ||||
|                         {{x = -205, y = -54}, {x = 195, y = 54}}, | ||||
|                         {{x = -205, y = -80}, {x = 195, y = 80}}, | ||||
|                         {{x = -205, y = -54}, {x = 195, y = 54}}, | ||||
|                         {{x = -205, y = -80}, {x = 195, y = 80}}, | ||||
|                         {{x = -205, y = -103}, {x = 195, y = 103}}, | ||||
|                         {{x = -205, y = -150}, {x = 195, y = 150}}, | ||||
|                         {{x = -205, y = -103}, {x = 195, y = 103}}, | ||||
|                         {{x = -205, y = -150}, {x = 195, y = 150}} | ||||
|                         { { x = -205, y = -37 },  { x = 195, y = 37 } }, | ||||
|                         { { x = -205, y = -112 }, { x = 195, y = 112 } }, | ||||
|                         { { x = -205, y = -146 }, { x = 195, y = 146 } }, | ||||
|                         { { x = -205, y = -112 }, { x = 195, y = 112 } }, | ||||
|                         { { x = -205, y = -72 },  { x = 195, y = 72 } }, | ||||
|                         { { x = -205, y = -146 }, { x = 195, y = 146 } }, | ||||
|                         { { x = -205, y = -37 },  { x = 195, y = 37 } }, | ||||
|                         { { x = -205, y = -5 },   { x = 195, y = 5 } }, | ||||
|                         { { x = -205, y = -23 },  { x = 195, y = 23 } }, | ||||
|                         { { x = -205, y = -5 },   { x = 195, y = 5 } }, | ||||
|                         { { x = -205, y = -72 },  { x = 195, y = 72 } }, | ||||
|                         { { x = -205, y = -23 },  { x = 195, y = 23 } }, | ||||
|                         { { x = -205, y = -54 },  { x = 195, y = 54 } }, | ||||
|                         { { x = -205, y = -80 },  { x = 195, y = 80 } }, | ||||
|                         { { x = -205, y = -54 },  { x = 195, y = 54 } }, | ||||
|                         { { x = -205, y = -80 },  { x = 195, y = 80 } }, | ||||
|                         { { x = -205, y = -103 }, { x = 195, y = 103 } }, | ||||
|                         { { x = -205, y = -150 }, { x = 195, y = 150 } }, | ||||
|                         { { x = -205, y = -103 }, { x = 195, y = 103 } }, | ||||
|                         { { x = -205, y = -150 }, { x = 195, y = 150 } } | ||||
|                     } | ||||
|                 ) | ||||
|  | ||||
| @@ -129,17 +128,19 @@ Event.on_nth_tick( | ||||
|                 return | ||||
|             end | ||||
|  | ||||
|             area[1].x = area[1].x - locomotive.position.x | ||||
|             area[1].y = area[1].y - locomotive.position.y | ||||
|  | ||||
|             area[2].x = area[2].x + locomotive.position.x | ||||
|             area[1].y = area[1].y + locomotive.position.y | ||||
|             area[2].y = area[2].y + locomotive.position.y | ||||
|  | ||||
|             shuffle(area) | ||||
|             if random(1, 2) == 1 then | ||||
|                 WD.set_spawn_position(area[1]) | ||||
|             else | ||||
|                 WD.set_spawn_position(area[2]) | ||||
|             end | ||||
|  | ||||
|             WD.set_spawn_position(area[1]) | ||||
|             WD.set_main_target() | ||||
|             WD.build_worm_custom() | ||||
|             Event.raise(WD.events.on_spawn_unit_group_simple, {fs = true, bypass = true, random_bosses = true, scale = 8, force = 'aggressors_frenzy'}) | ||||
|             -- WD.place_custom_nest(locomotive.surface, area[1], 'aggressors_frenzy') | ||||
|             Event.raise(WD.events.on_spawn_unit_group_simple, { fs = true, bypass = true, random_bosses = true, scale = 32, force = 'aggressors_frenzy' }) | ||||
|             return | ||||
|         end | ||||
|  | ||||
| @@ -153,7 +154,7 @@ Event.on_nth_tick( | ||||
|  | ||||
| Event.add( | ||||
|     defines.events.on_player_crafted_item, | ||||
|     function(event) | ||||
|     function (event) | ||||
|         local player = game.get_player(event.player_index) | ||||
|         if not player or not player.valid then | ||||
|             return | ||||
| @@ -184,7 +185,7 @@ Event.add( | ||||
|  | ||||
| Event.add( | ||||
|     defines.events.on_rocket_launched, | ||||
|     function(event) | ||||
|     function (event) | ||||
|         local rocket_inventory = event.rocket.get_inventory(defines.inventory.rocket) | ||||
|         local slot = rocket_inventory[1] | ||||
|         if slot and slot.valid and slot.valid_for_read then | ||||
| @@ -204,7 +205,7 @@ Event.add( | ||||
|  | ||||
| Event.add( | ||||
|     RPG.events.on_spell_cast_success, | ||||
|     function(event) | ||||
|     function (event) | ||||
|         local player = game.get_player(event.player_index) | ||||
|         if not player or not player.valid then | ||||
|             return | ||||
| @@ -237,7 +238,7 @@ Event.add( | ||||
|  | ||||
| Event.on_nth_tick( | ||||
|     14400, | ||||
|     function() | ||||
|     function () | ||||
|         local final_battle = Public.get_stateful('final_battle') | ||||
|         if not final_battle then | ||||
|             return | ||||
| @@ -259,7 +260,7 @@ Event.on_nth_tick( | ||||
|         end | ||||
|  | ||||
|         if collection.gather_time and collection.gather_time <= 0 and collection.survive_for > 0 then | ||||
|             Beam.new_beam(surface, game.tick + 150) | ||||
|             Beam.new_beam(surface, game.tick + 350) | ||||
|         end | ||||
|     end | ||||
| ) | ||||
|   | ||||
| @@ -310,16 +310,6 @@ local function get_random_buff(fetch_all, only_force) | ||||
|                 { name = 'solid-fuel',    count = 100 } | ||||
|             } | ||||
|         }, | ||||
|         { | ||||
|             name = 'fast_startup', | ||||
|             discord = 'Assembling starting supplies - start with some assembling machines T1', | ||||
|             modifier = 'starting_items', | ||||
|             limit = 25, | ||||
|             add_per_buff = 2, | ||||
|             items = { | ||||
|                 { name = 'assembling-machine-1', count = 2 } | ||||
|             } | ||||
|         }, | ||||
|         { | ||||
|             name = 'fast_startup_1', | ||||
|             discord = 'Assembling starting supplies - start with some assembling machines T2', | ||||
| @@ -755,6 +745,15 @@ local function scale(setting, limit, factor) | ||||
|     return floor(scale_value) | ||||
| end | ||||
|  | ||||
| local function scale_lin(setting, limit, factor) | ||||
|     factor = factor or 1.05 | ||||
|     local scale_value = math.floor(setting + (factor * this.rounds_survived)) | ||||
|     if limit and scale_value >= limit then | ||||
|         return limit | ||||
|     end | ||||
|     return floor(scale_value) | ||||
| end | ||||
|  | ||||
| local function get_random_items() | ||||
|     local items = { | ||||
|         { 'advanced-circuit',               scale(225000, 9000000) }, | ||||
| @@ -1610,6 +1609,8 @@ function Public.reset_stateful(refresh_gui, clear_buffs) | ||||
|         supplies.single_item.count = supplies.single_item.total | ||||
|     end | ||||
|  | ||||
|     WD.set_es_unit_limit(scale_lin(100, 1000, 5.819)) | ||||
|  | ||||
|     this.objectives.handcrafted_items.actual = 0 | ||||
|     this.objectives.handcrafted_items_any.actual = 0 | ||||
|     this.objectives.cast_spell.actual = 0 | ||||
| @@ -1625,22 +1626,22 @@ function Public.reset_stateful(refresh_gui, clear_buffs) | ||||
|     end | ||||
|  | ||||
|     this.stateful_spawn_points = { | ||||
|         { { x = -205, y = -37 }, { x = 195, y = 37 } }, | ||||
|         { { x = -205, y = -37 },  { x = 195, y = 37 } }, | ||||
|         { { x = -205, y = -112 }, { x = 195, y = 112 } }, | ||||
|         { { x = -205, y = -146 }, { x = 195, y = 146 } }, | ||||
|         { { x = -205, y = -112 }, { x = 195, y = 112 } }, | ||||
|         { { x = -205, y = -72 }, { x = 195, y = 72 } }, | ||||
|         { { x = -205, y = -72 },  { x = 195, y = 72 } }, | ||||
|         { { x = -205, y = -146 }, { x = 195, y = 146 } }, | ||||
|         { { x = -205, y = -37 }, { x = 195, y = 37 } }, | ||||
|         { { x = -205, y = -5 }, { x = 195, y = 5 } }, | ||||
|         { { x = -205, y = -23 }, { x = 195, y = 23 } }, | ||||
|         { { x = -205, y = -5 }, { x = 195, y = 5 } }, | ||||
|         { { x = -205, y = -72 }, { x = 195, y = 72 } }, | ||||
|         { { x = -205, y = -23 }, { x = 195, y = 23 } }, | ||||
|         { { x = -205, y = -54 }, { x = 195, y = 54 } }, | ||||
|         { { x = -205, y = -80 }, { x = 195, y = 80 } }, | ||||
|         { { x = -205, y = -54 }, { x = 195, y = 54 } }, | ||||
|         { { x = -205, y = -80 }, { x = 195, y = 80 } }, | ||||
|         { { x = -205, y = -37 },  { x = 195, y = 37 } }, | ||||
|         { { x = -205, y = -5 },   { x = 195, y = 5 } }, | ||||
|         { { x = -205, y = -23 },  { x = 195, y = 23 } }, | ||||
|         { { x = -205, y = -5 },   { x = 195, y = 5 } }, | ||||
|         { { x = -205, y = -72 },  { x = 195, y = 72 } }, | ||||
|         { { x = -205, y = -23 },  { x = 195, y = 23 } }, | ||||
|         { { x = -205, y = -54 },  { x = 195, y = 54 } }, | ||||
|         { { x = -205, y = -80 },  { x = 195, y = 80 } }, | ||||
|         { { x = -205, y = -54 },  { x = 195, y = 54 } }, | ||||
|         { { x = -205, y = -80 },  { x = 195, y = 80 } }, | ||||
|         { { x = -205, y = -103 }, { x = 195, y = 103 } }, | ||||
|         { { x = -205, y = -150 }, { x = 195, y = 150 } }, | ||||
|         { { x = -205, y = -103 }, { x = 195, y = 103 } }, | ||||
| @@ -1709,7 +1710,7 @@ function Public.move_all_players() | ||||
|     Alert.alert_all_players(50, message, nil, nil, 1) | ||||
|     Core.iter_connected_players( | ||||
|         function (player) | ||||
|             local pos = surface.find_non_colliding_position('character', locomotive.position, 10, 0) | ||||
|             local pos = surface.find_non_colliding_position('character', locomotive.position, 32, 1) | ||||
|  | ||||
|             Public.stateful_gui.boss_frame(player, true) | ||||
|  | ||||
| @@ -1726,7 +1727,7 @@ function Public.move_all_players() | ||||
|         Core.iter_fake_connected_players( | ||||
|             global.characters, | ||||
|             function (player) | ||||
|                 local pos = surface.find_non_colliding_position('character', locomotive.position, 10, 0) | ||||
|                 local pos = surface.find_non_colliding_position('character', locomotive.position, 32, 1) | ||||
|  | ||||
|                 if pos then | ||||
|                     player.teleport(pos) | ||||
| @@ -1744,8 +1745,9 @@ function Public.set_final_battle() | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     local es_settings = WD.get_es('settings') | ||||
|     WD.set_es('final_battle', true) | ||||
|     this.final_battle = true | ||||
|     es_settings.final_battle = true | ||||
|     Public.set('final_battle', true) | ||||
| end | ||||
|  | ||||
|   | ||||
| @@ -35,14 +35,14 @@ Public.scenario_name = scenario_name | ||||
|  | ||||
| Global.register( | ||||
|     this, | ||||
|     function(tbl) | ||||
|     function (tbl) | ||||
|         this = tbl | ||||
|     end | ||||
| ) | ||||
|  | ||||
| Global.register( | ||||
|     stateful_settings, | ||||
|     function(tbl) | ||||
|     function (tbl) | ||||
|         stateful_settings = tbl | ||||
|     end | ||||
| ) | ||||
| @@ -149,7 +149,7 @@ function Public.reset_main_table() | ||||
|     this.gap_between_locomotive = { | ||||
|         hinders = {}, | ||||
|         gap = 900, | ||||
|         neg_gap = 3520, -- earlier 2112 (3 zones, whereas 704 is one zone) | ||||
|         neg_gap = 3520,          -- earlier 2112 (3 zones, whereas 704 is one zone) | ||||
|         neg_gap_collapse = 5520, -- earlier 2112 (3 zones, whereas 704 is one zone) | ||||
|         highest_pos = nil | ||||
|     } | ||||
| @@ -170,7 +170,7 @@ function Public.reset_main_table() | ||||
|     this.print_tech_to_discord = true | ||||
|     this.biters_killed = 0 | ||||
|     this.cleared_nauvis = false | ||||
|     this.locomotive_pos = {tbl = {}} | ||||
|     this.locomotive_pos = { tbl = {} } | ||||
|     this.trusted_only_car_tanks = true | ||||
|     --!grief prevention | ||||
|     this.enable_arties = 6 -- default to callback 6 | ||||
| @@ -304,6 +304,8 @@ function Public.reset_main_table() | ||||
|     this.mystical_chest_completed = 0 | ||||
|     this.mystical_chest_enabled = true | ||||
|     this.check_if_threat_below_zero = true | ||||
|     this.rocks_to_remove = nil | ||||
|     this.tiles_to_replace = nil | ||||
|     this.mc_rewards = { | ||||
|         current = {}, | ||||
|         temp_boosts = {} | ||||
| @@ -318,7 +320,7 @@ function Public.reset_main_table() | ||||
|         reversed = stateful_settings.reversed, | ||||
|         disable_terrain = false | ||||
|     } | ||||
|     this.alert_zone_1 = false -- alert the players | ||||
|     this.alert_zone_1 = false             -- alert the players | ||||
|     this.radars_reveal_new_chunks = false -- allows for the player to explore the map instead, | ||||
|  | ||||
|     this.mining_utils = { | ||||
| @@ -400,29 +402,29 @@ end | ||||
|  | ||||
| local apply_settings_token = | ||||
|     Task.register( | ||||
|     function(data) | ||||
|         local server_name_matches = Server.check_server_name(scenario_name) | ||||
|         local settings = data and data.value or nil | ||||
|         function (data) | ||||
|             local server_name_matches = Server.check_server_name(scenario_name) | ||||
|             local settings = data and data.value or nil | ||||
|  | ||||
|         if not settings then | ||||
|             if server_name_matches then | ||||
|                 Server.set_data(dataset, dataset_key, stateful_settings) | ||||
|             if not settings then | ||||
|                 if server_name_matches then | ||||
|                     Server.set_data(dataset, dataset_key, stateful_settings) | ||||
|                 else | ||||
|                     Server.set_data(dataset, dataset_key_dev, stateful_settings) | ||||
|                 end | ||||
|             else | ||||
|                 Server.set_data(dataset, dataset_key_dev, stateful_settings) | ||||
|                 for k, v in pairs(settings) do | ||||
|                     stateful_settings[k] = v | ||||
|                 end | ||||
|             end | ||||
|         else | ||||
|             for k, v in pairs(settings) do | ||||
|                 stateful_settings[k] = v | ||||
|             end | ||||
|         end | ||||
|  | ||||
|         Public.stateful_on_server_started() | ||||
|     end | ||||
| ) | ||||
|             Public.stateful_on_server_started() | ||||
|         end | ||||
|     ) | ||||
|  | ||||
| Event.add( | ||||
|     Server.events.on_server_started, | ||||
|     function() | ||||
|     function () | ||||
|         local start_data = Server.get_start_data() | ||||
|  | ||||
|         if not start_data.initialized then | ||||
|   | ||||
| @@ -7,7 +7,7 @@ local this = {} | ||||
|  | ||||
| Global.register( | ||||
|     this, | ||||
|     function(t) | ||||
|     function (t) | ||||
|         this = t | ||||
|     end | ||||
| ) | ||||
| @@ -50,7 +50,7 @@ local function create_particles(data) | ||||
|                 frame_speed = 0.1, | ||||
|                 vertical_speed = 0.1, | ||||
|                 height = 0.1, | ||||
|                 movement = {m2 - (random(0, m) * 0.01), m2 - (random(0, m) * 0.01)} | ||||
|                 movement = { m2 - (random(0, m) * 0.01), m2 - (random(0, m) * 0.01) } | ||||
|             } | ||||
|         ) | ||||
|     end | ||||
| @@ -87,7 +87,7 @@ local function spawn_biters(data) | ||||
|  | ||||
|     local unit_settings = Public.get('unit_settings') | ||||
|  | ||||
|     local unit = surface.create_entity({name = unit_to_create, position = position}) | ||||
|     local unit = surface.create_entity({ name = unit_to_create, position = position, force = data.force or 'enemy' }) | ||||
|  | ||||
|     if random(1, 30) == 1 then | ||||
|         BiterHealthBooster.add_boss_unit(unit, modified_boss_unit_health.current_value, 0.38) | ||||
| @@ -98,6 +98,8 @@ local function spawn_biters(data) | ||||
|         end | ||||
|         BiterHealthBooster.add_unit(unit, final_health) | ||||
|     end | ||||
|  | ||||
|     Event.raise(Public.events.on_entity_created, { entity = unit, boss_unit = false }) | ||||
| end | ||||
|  | ||||
| local function spawn_worms(data) | ||||
| @@ -110,7 +112,7 @@ local function spawn_worms(data) | ||||
|  | ||||
|     local unit_to_create = Public.wave_defense_roll_worm_name(sqrt(position.x ^ 2 + position.y ^ 2) * 0.20) | ||||
|  | ||||
|     local unit = surface.create_entity({name = unit_to_create, position = position}) | ||||
|     local unit = surface.create_entity({ name = unit_to_create, position = position }) | ||||
|     local worm_unit_settings = Public.get('worm_unit_settings') | ||||
|  | ||||
|     if random(1, 30) == 1 then | ||||
| @@ -124,7 +126,7 @@ local function spawn_worms(data) | ||||
|     end | ||||
| end | ||||
|  | ||||
| function Public.buried_biter(surface, position, max, entity_name) | ||||
| function Public.buried_biter(surface, position, max, entity_name, force) | ||||
|     if not surface then | ||||
|         return | ||||
|     end | ||||
| @@ -155,7 +157,7 @@ function Public.buried_biter(surface, position, max, entity_name) | ||||
|  | ||||
|         this[game.tick + t][#this[game.tick + t] + 1] = { | ||||
|             callback = 'create_particles', | ||||
|             data = {surface = surface, position = {x = position.x, y = position.y}, amount = 4} | ||||
|             data = { surface = surface, position = { x = position.x, y = position.y }, amount = 4 } | ||||
|         } | ||||
|  | ||||
|         if t > 90 then | ||||
| @@ -163,7 +165,7 @@ function Public.buried_biter(surface, position, max, entity_name) | ||||
|                 a = a + 1 | ||||
|                 this[game.tick + t][#this[game.tick + t] + 1] = { | ||||
|                     callback = 'spawn_biters', | ||||
|                     data = {surface = surface, position = {x = position.x, y = position.y}, entity_name = entity_name} | ||||
|                     data = { surface = surface, position = { x = position.x, y = position.y }, entity_name = entity_name, force = force or 'enemy' } | ||||
|                 } | ||||
|                 if a >= max then | ||||
|                     break | ||||
| @@ -202,13 +204,13 @@ function Public.buried_worm(surface, position) | ||||
|  | ||||
|         this[game.tick + t][#this[game.tick + t] + 1] = { | ||||
|             callback = 'create_particles', | ||||
|             data = {surface = surface, position = {x = position.x, y = position.y}, amount = 4} | ||||
|             data = { surface = surface, position = { x = position.x, y = position.y }, amount = 4 } | ||||
|         } | ||||
|  | ||||
|         if not a then | ||||
|             this[game.tick + t][#this[game.tick + t] + 1] = { | ||||
|                 callback = 'spawn_worms', | ||||
|                 data = {surface = surface, position = {x = position.x, y = position.y}} | ||||
|                 data = { surface = surface, position = { x = position.x, y = position.y } } | ||||
|             } | ||||
|             a = true | ||||
|         end | ||||
|   | ||||
| @@ -6,8 +6,9 @@ Commands.new('wd_debug_module', 'Usable only for admins - controls wave defense | ||||
|     :require_admin() | ||||
|     :require_validation() | ||||
|     :add_parameter('skip/toggle_es/toggle_es_boss/spawn/next/next_50/next_1500/log_all/debug_health', false, 'string') | ||||
|     :add_parameter('state', true, 'boolean') | ||||
|     :callback( | ||||
|         function (player, action) | ||||
|         function (player, action, state) | ||||
|             if action == 'skip' then | ||||
|                 Public.get('enable_grace_time').enabled = false | ||||
|                 player.print(module_name .. ' grace skipped!') | ||||
| @@ -15,13 +16,13 @@ Commands.new('wd_debug_module', 'Usable only for admins - controls wave defense | ||||
|             end | ||||
|  | ||||
|             if action == 'toggle_es' then | ||||
|                 Public.set_module_status() | ||||
|                 Public.set_module_status(state or false) | ||||
|                 player.print(module_name .. ' ES has been toggled!') | ||||
|                 return true | ||||
|             end | ||||
|  | ||||
|             if action == 'toggle_es_boss' then | ||||
|                 Public.set_track_bosses_only() | ||||
|                 Public.set_track_bosses_only(state or false) | ||||
|                 player.print(module_name .. ' ES bosses has been toggled!') | ||||
|                 return true | ||||
|             end | ||||
|   | ||||
| @@ -22,7 +22,8 @@ local this = { | ||||
|         update_rate = 120, | ||||
|         enabled = true, | ||||
|         track_bosses_only = true, | ||||
|         wave_number = 0 | ||||
|         wave_number = 0, | ||||
|         unit_limit = 300, | ||||
|     }, | ||||
|     target_settings = {} | ||||
| } | ||||
| @@ -31,10 +32,10 @@ Public._esp = {} | ||||
|  | ||||
| Global.register( | ||||
|     this, | ||||
|     function(tbl) | ||||
|     function (tbl) | ||||
|         this = tbl | ||||
|         for _, state in pairs(this.states) do | ||||
|             setmetatable(state, {__index = Public._esp}) | ||||
|             setmetatable(state, { __index = Public._esp }) | ||||
|         end | ||||
|     end | ||||
| ) | ||||
| @@ -66,59 +67,77 @@ local tiers = { | ||||
| } | ||||
|  | ||||
| local tier_damage = { | ||||
|     ['small-biter'] = {min = 25, max = 50}, | ||||
|     ['medium-biter'] = {min = 50, max = 100}, | ||||
|     ['big-biter'] = {min = 75, max = 150}, | ||||
|     ['behemoth-biter'] = {min = 100, max = 200}, | ||||
|     ['small-spitter'] = {min = 25, max = 50}, | ||||
|     ['medium-spitter'] = {min = 50, max = 100}, | ||||
|     ['big-spitter'] = {min = 75, max = 150}, | ||||
|     ['behemoth-spitter'] = {min = 100, max = 200} | ||||
|     ['small-biter'] = { min = 25, max = 50 }, | ||||
|     ['medium-biter'] = { min = 50, max = 100 }, | ||||
|     ['big-biter'] = { min = 75, max = 150 }, | ||||
|     ['behemoth-biter'] = { min = 100, max = 200 }, | ||||
|     ['small-spitter'] = { min = 25, max = 50 }, | ||||
|     ['medium-spitter'] = { min = 50, max = 100 }, | ||||
|     ['big-spitter'] = { min = 75, max = 150 }, | ||||
|     ['behemoth-spitter'] = { min = 100, max = 200 } | ||||
| } | ||||
|  | ||||
| local commands = { | ||||
|     ['flee'] = 'goto', | ||||
|     ['goto'] = 'attack_area', | ||||
|     ['attack'] = 'attack', | ||||
|     ['attack_area'] = 'attack_area', | ||||
| } | ||||
|  | ||||
| --- A token to register tasks that entities are given | ||||
| local work_token | ||||
| work_token = | ||||
|     Token.register( | ||||
|     function(event) | ||||
|         if not event then | ||||
|             return | ||||
|         end | ||||
|         function (event) | ||||
|             if not event then | ||||
|                 return | ||||
|             end | ||||
|  | ||||
|         local state = Public.get_unit(event.unit_number) | ||||
|         local tick = game.tick | ||||
|         if not state then | ||||
|             return | ||||
|         end | ||||
|             local state = Public.get_unit(event.unit_number) | ||||
|             local tick = game.tick | ||||
|             if not state then | ||||
|                 return | ||||
|             end | ||||
|  | ||||
|         if state:validate() then | ||||
|             state:work(tick) | ||||
|             set_timeout_in_ticks(state:get_update_rate(), work_token, event) | ||||
|         else | ||||
|             state:remove() | ||||
|             if state:validate() then | ||||
|                 state:work(tick) | ||||
|                 state.command = commands[state.command] | ||||
|                 set_timeout_in_ticks(state:get_update_rate(), work_token, event) | ||||
|             else | ||||
|                 state:remove() | ||||
|             end | ||||
|         end | ||||
|     end | ||||
| ) | ||||
|     ) | ||||
|  | ||||
| --- Restores a given entity to their original force | ||||
| local restore_force_token = | ||||
|     Token.register( | ||||
|     function(event) | ||||
|         if not event then | ||||
|             return | ||||
|         end | ||||
|         local force_name = event.force_name | ||||
|         if not force_name then | ||||
|             return | ||||
|         end | ||||
|         function (event) | ||||
|             if not event then | ||||
|                 return | ||||
|             end | ||||
|             local force_name = event.force_name | ||||
|             if not force_name then | ||||
|                 return | ||||
|             end | ||||
|  | ||||
|         local state = Public.get_unit(event.unit_number) | ||||
|         if state then | ||||
|             state:set_force() | ||||
|             state.frenzied = false | ||||
|             local state = Public.get_unit(event.unit_number) | ||||
|             if state then | ||||
|                 state:set_force() | ||||
|                 state.frenzied = false | ||||
|             end | ||||
|         end | ||||
|     ) | ||||
|  | ||||
| local function has_unit_limit_reached() | ||||
|     local uid = Public.get_count() | ||||
|     if uid >= (this.settings.unit_limit and this.settings.unit_limit) then | ||||
|         Public.debug_print('has_unit_limit_reached - Max units reached?') | ||||
|         return true | ||||
|     end | ||||
| ) | ||||
|  | ||||
|     return false | ||||
| end | ||||
|  | ||||
| local function is_closer(pos1, pos2, pos) | ||||
|     return ((pos1.x - pos.x) ^ 2 + (pos1.y - pos.y) ^ 2) < ((pos2.x - pos.x) ^ 2 + (pos2.y - pos.y) ^ 2) | ||||
| @@ -140,9 +159,9 @@ local function aoe_punch(entity, target, damage) | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     local base_vector = {target.position.x - entity.position.x, target.position.y - entity.position.y} | ||||
|     local base_vector = { target.position.x - entity.position.x, target.position.y - entity.position.y } | ||||
|  | ||||
|     local vector = {base_vector[1], base_vector[2]} | ||||
|     local vector = { base_vector[1], base_vector[2] } | ||||
|     vector[1] = vector[1] * 1000 | ||||
|     vector[2] = vector[2] * 1000 | ||||
|  | ||||
| @@ -177,9 +196,9 @@ local function aoe_punch(entity, target, damage) | ||||
|     for i = 1, 16, 1 do | ||||
|         for x = i * -1 * a, i * a, 1 do | ||||
|             for y = i * -1 * a, i * a, 1 do | ||||
|                 local p = {cp.x + x + vector[1] * i, cp.y + y + vector[2] * i} | ||||
|                 cs.create_trivial_smoke({name = 'train-smoke', position = p}) | ||||
|                 for _, e in pairs(cs.find_entities({{p[1] - a, p[2] - a}, {p[1] + a, p[2] + a}})) do | ||||
|                 local p = { cp.x + x + vector[1] * i, cp.y + y + vector[2] * i } | ||||
|                 cs.create_trivial_smoke({ name = 'train-smoke', position = p }) | ||||
|                 for _, e in pairs(cs.find_entities({ { p[1] - a, p[2] - a }, { p[1] + a, p[2] + a } })) do | ||||
|                     if e.valid then | ||||
|                         if e.health then | ||||
|                             if e.destructible and e.minable and not valid_enemy_forces[e.force.name] then | ||||
| @@ -249,9 +268,9 @@ local function area_of_effect(entity, radius, callback, find_entities) | ||||
|         for y = area.left_top.y, area.right_bottom.y, 1 do | ||||
|             local d = floor((cp.x - x) ^ 2 + (cp.y - y) ^ 2) | ||||
|             if d < radius then | ||||
|                 local p = {x = x, y = y} | ||||
|                 local p = { x = x, y = y } | ||||
|                 if find_entities then | ||||
|                     for _, e in pairs(cs.find_entities({{p.x - 1, p.y - 1}, {p.x + 1, p.y + 1}})) do | ||||
|                     for _, e in pairs(cs.find_entities({ { p.x - 1, p.y - 1 }, { p.x + 1, p.y + 1 } })) do | ||||
|                         if e and e.valid and e.name ~= 'character' and e.health and e.destructible then | ||||
|                             callback(e, p) | ||||
|                         end | ||||
| @@ -266,91 +285,10 @@ end | ||||
|  | ||||
| local function shoot_laser(surface, source, enemy) | ||||
|     local force = source.force | ||||
|     surface.create_entity {name = 'laser-beam', position = source.position, force = 'player', target = enemy, source = source, max_length = 32, duration = 60} | ||||
|     surface.create_entity { name = 'laser-beam', position = source.position, force = 'player', target = enemy, source = source, max_length = 32, duration = 60 } | ||||
|     enemy.damage(20 * (1 + force.get_ammo_damage_modifier('laser') + force.get_gun_speed_modifier('laser')), force, 'laser', source) | ||||
| end | ||||
|  | ||||
| local function set_commands() | ||||
|     local unit = this.target_settings.main_target | ||||
|     if not unit or not unit.valid then | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     local commands = {} | ||||
|  | ||||
|     if this.target_settings.last_set_target == 'main' then | ||||
|         this.target_settings.last_set_target = 'random' | ||||
|         commands[#commands + 1] = { | ||||
|             type = defines.command.attack_area, | ||||
|             destination = {x = unit.position.x, y = unit.position.y}, | ||||
|             radius = 15, | ||||
|             distraction = defines.distraction.by_enemy | ||||
|         } | ||||
|         commands[#commands + 1] = { | ||||
|             type = defines.command.build_base, | ||||
|             destination = {x = unit.position.x, y = unit.position.y} | ||||
|         } | ||||
|         commands[#commands + 1] = { | ||||
|             type = defines.command.attack_area, | ||||
|             destination = {x = unit.position.x, y = unit.position.y}, | ||||
|             radius = 15, | ||||
|             distraction = defines.distraction.by_enemy | ||||
|         } | ||||
|         commands[#commands + 1] = { | ||||
|             type = defines.command.build_base, | ||||
|             destination = {x = unit.position.x, y = unit.position.y} | ||||
|         } | ||||
|     else | ||||
|         commands[#commands + 1] = { | ||||
|             type = defines.command.attack, | ||||
|             target = unit, | ||||
|             distraction = defines.distraction.by_anything | ||||
|         } | ||||
|         commands[#commands + 1] = { | ||||
|             type = defines.command.attack_area, | ||||
|             destination = {x = unit.position.x, y = unit.position.y}, | ||||
|             radius = 15, | ||||
|             distraction = defines.distraction.by_enemy | ||||
|         } | ||||
|         commands[#commands + 1] = { | ||||
|             type = defines.command.build_base, | ||||
|             destination = {x = unit.position.x, y = unit.position.y} | ||||
|         } | ||||
|         commands[#commands + 1] = { | ||||
|             type = defines.command.attack, | ||||
|             target = unit, | ||||
|             distraction = defines.distraction.by_anything | ||||
|         } | ||||
|         commands[#commands + 1] = { | ||||
|             type = defines.command.attack_area, | ||||
|             destination = {x = unit.position.x, y = unit.position.y}, | ||||
|             radius = 15, | ||||
|             distraction = defines.distraction.by_enemy | ||||
|         } | ||||
|         commands[#commands + 1] = { | ||||
|             type = defines.command.build_base, | ||||
|             destination = {x = unit.position.x, y = unit.position.y} | ||||
|         } | ||||
|         commands[#commands + 1] = { | ||||
|             type = defines.command.attack, | ||||
|             target = unit, | ||||
|             distraction = defines.distraction.by_anything | ||||
|         } | ||||
|         this.target_settings.last_set_target = 'main' | ||||
|     end | ||||
|  | ||||
|     local command = { | ||||
|         type = defines.command.compound, | ||||
|         structure_type = defines.compound_command.return_last, | ||||
|         commands = commands | ||||
|     } | ||||
|  | ||||
|     local surface = unit.surface | ||||
|  | ||||
|     surface.set_multi_command({command = command, unit_count = 5000, force = 'aggressors'}) | ||||
|     this.target_settings.commands = commands | ||||
| end | ||||
|  | ||||
| local function set_forces() | ||||
|     local aggressors = game.forces.aggressors | ||||
|     local aggressors_frenzy = game.forces.aggressors_frenzy | ||||
| @@ -380,11 +318,12 @@ end | ||||
|  | ||||
| local function on_init() | ||||
|     this.states = {} | ||||
|     this.settings.spawned_units = 0 | ||||
|     this.settings.frenzy_length = 3600 | ||||
|     this.settings.frenzy_burst_length = 160 | ||||
|     this.settings.update_rate = 120 | ||||
|     this.target_settings = {} | ||||
|     this.final_battle = false | ||||
|     this.settings.final_battle = false | ||||
|     set_forces() | ||||
| end | ||||
|  | ||||
| @@ -457,18 +396,6 @@ local function on_target_aquired(event) | ||||
|     else | ||||
|         this.target_settings.main_target = event.target | ||||
|     end | ||||
|  | ||||
|     local tick = game.tick | ||||
|  | ||||
|     if not this.target_settings.last_set_commands then | ||||
|         set_commands() | ||||
|         this.target_settings.last_set_commands = tick + 200 | ||||
|         this.target_settings.last_set_target = 'main' | ||||
|     end | ||||
|  | ||||
|     if tick > this.target_settings.last_set_commands then | ||||
|         set_commands() | ||||
|     end | ||||
| end | ||||
|  | ||||
| local function on_entity_created(event) | ||||
| @@ -496,10 +423,13 @@ local function on_entity_created(event) | ||||
|                 end | ||||
|                 state:set_burst_frenzy() | ||||
|                 state:set_boss() | ||||
|             else | ||||
|                 entity.destroy() | ||||
|             end | ||||
|         else | ||||
|             state = Public.new(data) | ||||
|             if not state then | ||||
|                 entity.destroy() | ||||
|                 return | ||||
|             end | ||||
|             state:set_burst_frenzy() | ||||
| @@ -565,6 +495,10 @@ local function on_entity_damaged(event) | ||||
|         state:spawn_children() | ||||
|     end | ||||
|  | ||||
|     if random(1, 128) == 1 then | ||||
|         state:flee_command() | ||||
|     end | ||||
|  | ||||
|     if state.boss_unit and entity.health <= max / 2 and state.teleported < 5 then | ||||
|         state.teleported = state.teleported + 1 | ||||
|         if random(1, 4) == 1 then | ||||
| @@ -577,13 +511,15 @@ end | ||||
| ---@param data table | ||||
| ---@return table|nil | ||||
| function Public.new(data) | ||||
|     local uid = Public.get_count() | ||||
|  | ||||
|     if uid > 200 then | ||||
|     if has_unit_limit_reached() then | ||||
|         if data.entity and data.entity.valid then | ||||
|             data.entity.destroy() | ||||
|         end | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     local state = setmetatable({}, {__index = Public._esp}) | ||||
|     local uid = Public.get_count() | ||||
|     local state = setmetatable({}, { __index = Public._esp }) | ||||
|     local tick = game.tick | ||||
|     state.entity = data.entity | ||||
|     state.surface_id = state.entity.surface_index | ||||
| @@ -591,17 +527,13 @@ function Public.new(data) | ||||
|     state.unit_number = state.entity.unit_number | ||||
|     state.teleported = 0 | ||||
|     state.uid = uid | ||||
|     state.command = 'goto' | ||||
|     state.id = state.entity.unit_number | ||||
|     state.update_rate = this.settings.update_rate + (10 * state.uid) | ||||
|     if data.delayed then | ||||
|         state.delayed = tick + data.delayed | ||||
|         state.ttl = data.ttl or (tick + data.delayed) + 7200 -- 2 minutes duration | ||||
|     else | ||||
|         state.ttl = data.ttl or tick + 3600 -- 1 minutes duration | ||||
|         state:validate() | ||||
|     end | ||||
|     state.ttl = data.ttl or tick + (5 * 3600) -- 5 minutes duration | ||||
|     state:validate() | ||||
|  | ||||
|     set_timeout_in_ticks(state.update_rate, work_token, {unit_number = state.unit_number}) | ||||
|     set_timeout_in_ticks(state.update_rate, work_token, { unit_number = state.unit_number }) | ||||
|  | ||||
|     this.states[state.id] = state | ||||
|  | ||||
| @@ -655,6 +587,22 @@ function Public.get_boss_unit() | ||||
|     end | ||||
| end | ||||
|  | ||||
| -- Clears invalid units | ||||
| ---@return table|nil | ||||
| function Public.check_states() | ||||
|     local c = 0 | ||||
|     for _, state in pairs(this.states) do | ||||
|         if state then | ||||
|             if not (state.entity and state.entity.valid) then | ||||
|                 state:remove() | ||||
|             else | ||||
|                 c = c + 1 | ||||
|             end | ||||
|         end | ||||
|     end | ||||
|     this.settings.spawned_units = c | ||||
| end | ||||
|  | ||||
| -- Gets a boss unit | ||||
| ---@return integer | ||||
| function Public.get_count() | ||||
| @@ -665,6 +613,8 @@ function Public.get_count() | ||||
|         end | ||||
|     end | ||||
|  | ||||
|     this.settings.spawned_units = c | ||||
|  | ||||
|     return c | ||||
| end | ||||
|  | ||||
| @@ -680,6 +630,10 @@ end | ||||
|  | ||||
| -- Removes the given entity from tracking | ||||
| function Public._esp:remove() | ||||
|     if self.entity and self.entity.valid then | ||||
|         self.entity.destroy() | ||||
|     end | ||||
|  | ||||
|     this.states[self.id] = nil | ||||
| end | ||||
|  | ||||
| @@ -727,7 +681,7 @@ function Public._esp:set_burst_frenzy() | ||||
|     end | ||||
|  | ||||
|     self.frenzied = true | ||||
|     set_timeout_in_ticks(this.settings.frenzy_burst_length, restore_force_token, {force_name = self.force.name, unit_number = self.unit_number}) | ||||
|     set_timeout_in_ticks(this.settings.frenzy_burst_length, restore_force_token, { force_name = self.force.name, unit_number = self.unit_number }) | ||||
|  | ||||
|     entity.force = game.forces.aggressors_frenzy | ||||
|     self.force = entity.force | ||||
| @@ -740,6 +694,10 @@ function Public._esp:spawn_children() | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     if has_unit_limit_reached() then | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     local tier = tiers[entity.name] | ||||
|  | ||||
|     if not tier then | ||||
| @@ -748,9 +706,9 @@ function Public._esp:spawn_children() | ||||
|  | ||||
|     local max = entity.prototype.max_health | ||||
|  | ||||
|     if entity.health <= max / 2 and not self.spawned_children then | ||||
|     if entity.health <= max / 4 and not self.spawned_children then | ||||
|         self.spawned_children = true | ||||
|         Public.buried_biter(entity.surface, entity.position, 1, tier) | ||||
|         Public.buried_biter(entity.surface, entity.position, 1, tier, entity.force.name) | ||||
|     end | ||||
| end | ||||
|  | ||||
| @@ -789,7 +747,7 @@ function Public._esp:laser(boss) | ||||
|  | ||||
|     local surface = entity.surface | ||||
|  | ||||
|     local enemies = surface.find_entities_filtered {radius = 10, limit = limit, force = 'player', position = entity.position} | ||||
|     local enemies = surface.find_entities_filtered { radius = 10, limit = limit, force = 'player', position = entity.position } | ||||
|     if enemies == nil or #enemies == 0 then | ||||
|         return | ||||
|     end | ||||
| @@ -808,9 +766,9 @@ function Public._esp:spew_damage() | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     local position = {entity.position.x + (-5 + random(0, 10)), entity.position.y + (-5 + random(0, 10))} | ||||
|     local position = { entity.position.x + (-5 + random(0, 10)), entity.position.y + (-5 + random(0, 10)) } | ||||
|  | ||||
|     entity.surface.create_entity({name = 'acid-stream-spitter-medium', position = position, target = position, source = position}) | ||||
|     entity.surface.create_entity({ name = 'acid-stream-spitter-medium', position = position, target = position, source = position }) | ||||
| end | ||||
|  | ||||
| --- Creates a projectile. | ||||
| @@ -820,7 +778,7 @@ function Public._esp:fire_projectile() | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     local position = {entity.position.x + (-10 + random(0, 20)), entity.position.y + (-10 + random(0, 20))} | ||||
|     local position = { entity.position.x + (-10 + random(0, 20)), entity.position.y + (-10 + random(0, 20)) } | ||||
|  | ||||
|     entity.surface.create_entity( | ||||
|         { | ||||
| @@ -842,7 +800,7 @@ function Public._esp:aoe_attack() | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     local position = {x = entity.position.x + (-10 + random(0, 20)), y = entity.position.y + (-10 + random(0, 20))} | ||||
|     local position = { x = entity.position.x + (-10 + random(0, 20)), y = entity.position.y + (-10 + random(0, 20)) } | ||||
|  | ||||
|     local target = { | ||||
|         valid = true, | ||||
| @@ -867,7 +825,7 @@ function Public._esp:area_of_spit_attack(range) | ||||
|     area_of_effect( | ||||
|         entity, | ||||
|         range or 10, | ||||
|         function(p) | ||||
|         function (p) | ||||
|             do_projectile(entity.surface, 'acid-stream-spitter-big', p, entity.force, p) | ||||
|         end, | ||||
|         false | ||||
| @@ -895,11 +853,11 @@ function Public._esp:find_targets() | ||||
|  | ||||
|     local obstacles = | ||||
|         entity.surface.find_entities_filtered { | ||||
|         position = entity.position, | ||||
|         radius = step_length / 2, | ||||
|         type = {'simple-entity', 'tree'}, | ||||
|         limit = 50 | ||||
|     } | ||||
|             position = entity.position, | ||||
|             radius = step_length / 2, | ||||
|             type = { 'simple-entity', 'tree' }, | ||||
|             limit = 50 | ||||
|         } | ||||
|     if obstacles then | ||||
|         shuffle_distance(obstacles, entity.position) | ||||
|         self.commands = self.commands or {} | ||||
| @@ -915,49 +873,6 @@ function Public._esp:find_targets() | ||||
|     end | ||||
| end | ||||
|  | ||||
| --- Attack target | ||||
| function Public._esp:attack_target() | ||||
|     local entity = self.entity | ||||
|     if not entity or not entity.valid then | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     local tick = game.tick | ||||
|     if not self.moving_to_attack_target then | ||||
|         self.moving_to_attack_target = 0 | ||||
|     end | ||||
|  | ||||
|     if tick < self.moving_to_attack_target then | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     self.moving_to_attack_target = tick + 200 | ||||
|  | ||||
|     if this.target_settings.commands and this.target_settings.commands.commands then | ||||
|         this.target_settings.commands = nil | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     if not this.target_settings.commands then | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     local compound_commands = this.target_settings.commands | ||||
|  | ||||
|     if self.commands and next(self.commands) then | ||||
|         compound_commands = self.commands | ||||
|     end | ||||
|  | ||||
|     local command = { | ||||
|         type = defines.command.compound, | ||||
|         structure_type = defines.compound_command.return_last, | ||||
|         commands = compound_commands | ||||
|     } | ||||
|     pcall(entity.set_command, command) | ||||
|  | ||||
|     self.commands = nil | ||||
| end | ||||
|  | ||||
| -- Sets the attack speed for the given force | ||||
| function Public._esp:set_attack_speed(speed) | ||||
|     if not speed then | ||||
| @@ -982,7 +897,7 @@ function Public._esp:switch_position() | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     local position = {entity.position.x + (-5 + random(0, 15)), entity.position.y + (5 + random(0, 15))} | ||||
|     local position = { entity.position.x + (-5 + random(0, 15)), entity.position.y + (5 + random(0, 15)) } | ||||
|  | ||||
|     local rand = entity.surface.find_non_colliding_position(entity.name, position, 0.2, 0.5) | ||||
|     if rand then | ||||
| @@ -1018,7 +933,9 @@ function Public._esp:set_boss() | ||||
|  | ||||
|     self.boss_unit = true | ||||
|  | ||||
|     if this.final_battle then | ||||
|     self:set_ttl(game.tick + (20 * 3600)) | ||||
|  | ||||
|     if this.settings.final_battle then | ||||
|         self.go_havoc = true | ||||
|         self.proj_int = tick + 120 | ||||
|         self.clear_go_havoc = tick + 3600 | ||||
| @@ -1033,21 +950,111 @@ function Public._esp:set_boss() | ||||
|     end | ||||
| end | ||||
|  | ||||
| --- Sets the time to live timer for the unit | ||||
| function Public._esp:set_ttl(ttl) | ||||
|     if not ttl then | ||||
|         error('No ttl given') | ||||
|     end | ||||
|  | ||||
|     self.ttl = ttl | ||||
| end | ||||
|  | ||||
| function Public._esp:go_to_location_command() | ||||
|     local unit = this.target_settings.main_target | ||||
|     if not unit or not unit.valid then | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     local entity = self.entity | ||||
|  | ||||
|     if not entity or not entity.valid then | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     pcall(entity.set_command, { | ||||
|         type = defines.command.go_to_location, | ||||
|         destination_entity = unit, | ||||
|         radius = 3 | ||||
|     }) | ||||
| end | ||||
|  | ||||
| function Public._esp:attack_command() | ||||
|     local unit = this.target_settings.main_target | ||||
|     if not unit or not unit.valid then | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     local entity = self.entity | ||||
|  | ||||
|     if not entity or not entity.valid then | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     pcall(entity.set_command, { | ||||
|         type = defines.command.attack, | ||||
|         target = unit | ||||
|     }) | ||||
| end | ||||
|  | ||||
| function Public._esp:attack_area_command() | ||||
|     local unit = this.target_settings.main_target | ||||
|     if not unit or not unit.valid then | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     local entity = self.entity | ||||
|  | ||||
|     if not entity or not entity.valid then | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     pcall(entity.set_command, { | ||||
|         type = defines.command.attack_area, | ||||
|         destination = { x = unit.position.x, y = unit.position.y }, | ||||
|         radius = 15, | ||||
|         distraction = defines.distraction.by_anything | ||||
|     }) | ||||
| end | ||||
|  | ||||
| function Public._esp:flee_command() | ||||
|     local unit = this.target_settings.main_target | ||||
|     if not unit or not unit.valid then | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     local entity = self.entity | ||||
|  | ||||
|     if not entity or not entity.valid then | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     pcall(entity.set_command, { | ||||
|         type = defines.command.flee, | ||||
|         from = unit, | ||||
|     }) | ||||
| end | ||||
|  | ||||
| function Public._esp:work(tick) | ||||
|     if self.go_frenzy then | ||||
|         self:set_frenzy() | ||||
|     end | ||||
|  | ||||
|     if self.command == 'goto' then | ||||
|         self:go_to_location_command() | ||||
|     elseif self.command == 'attack' then | ||||
|         self:attack_command() | ||||
|     elseif self.command == 'attack_area' then | ||||
|         self:attack_area_command() | ||||
|     end | ||||
|  | ||||
|     if self.go_havoc and self.clear_go_havoc > tick then | ||||
|         if tick > self.proj_int then | ||||
|             self:attack_target() | ||||
|         if tick < self.proj_int then | ||||
|             self:fire_projectile() | ||||
|             self.proj_int = tick + 120 | ||||
|         end | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     self:attack_target() | ||||
|  | ||||
|     if self.boss_unit then | ||||
|         if random(1, 20) == 1 then | ||||
| @@ -1069,6 +1076,9 @@ function Public._esp:work(tick) | ||||
|                 self:aoe_attack() | ||||
|             end | ||||
|         end | ||||
|         if tick > self.ttl then | ||||
|             self:remove() | ||||
|         end | ||||
|     elseif tick < self.ttl then | ||||
|         if random(1, 30) == 1 then | ||||
|             self:find_targets() | ||||
| @@ -1084,15 +1094,6 @@ function Public._esp:work(tick) | ||||
|     end | ||||
| end | ||||
|  | ||||
| Public.set_module_status = function() | ||||
|     on_init() | ||||
|     this.settings.enabled = not this.settings.enabled | ||||
| end | ||||
|  | ||||
| Public.set_track_bosses_only = function() | ||||
|     this.settings.track_bosses_only = not this.settings.track_bosses_only | ||||
| end | ||||
|  | ||||
| Event.on_init(on_init) | ||||
| Event.add(de.on_entity_died, on_entity_died) | ||||
| Event.add(de.on_entity_damaged, on_entity_damaged) | ||||
| @@ -1102,6 +1103,7 @@ Event.add(ev.on_entity_created, on_entity_created) | ||||
| Event.add(ev.on_target_aquired, on_target_aquired) | ||||
| Event.add(ev.on_evolution_factor_changed, on_evolution_factor_changed) | ||||
| Event.add(ev.on_game_reset, on_init) | ||||
| Event.on_nth_tick(100, Public.check_states) | ||||
|  | ||||
| --- This gets values from our table | ||||
| -- @param key <string> | ||||
| @@ -1132,4 +1134,22 @@ function Public.set_es(key, value) | ||||
|     end | ||||
| end | ||||
|  | ||||
| ---@param value boolean | ||||
| function Public.set_module_status(value) | ||||
|     on_init() | ||||
|     this.settings.enabled = value or false | ||||
| end | ||||
|  | ||||
| ---@param value boolean | ||||
| function Public.set_track_bosses_only(value) | ||||
|     this.settings.track_bosses_only = value or false | ||||
| end | ||||
|  | ||||
| ---@param value integer|number | ||||
| function Public.set_es_unit_limit(value) | ||||
|     this.settings.unit_limit = value or 300 | ||||
| end | ||||
|  | ||||
| Public.has_unit_limit_reached = has_unit_limit_reached | ||||
|  | ||||
| return Public | ||||
|   | ||||
| @@ -25,11 +25,11 @@ local function normalize_spawn_position() | ||||
|     local collapse_spawn_position = Collapse.get_position() | ||||
|     local inverted = Public.get('inverted') | ||||
|     if inverted then | ||||
|         local new_pos = {x = 0, y = collapse_spawn_position.y + 40} | ||||
|         local new_pos = { x = 0, y = collapse_spawn_position.y + 40 } | ||||
|         Public.set_spawn_position(new_pos) | ||||
|         return new_pos | ||||
|     else | ||||
|         local new_pos = {x = 0, y = collapse_spawn_position.y - 40} | ||||
|         local new_pos = { x = 0, y = collapse_spawn_position.y - 40 } | ||||
|         Public.set_spawn_position(new_pos) | ||||
|         return new_pos | ||||
|     end | ||||
| @@ -92,8 +92,8 @@ local function remove_trees(entity) | ||||
|     local surface = entity.surface | ||||
|     local radius = 10 | ||||
|     local pos = entity.position | ||||
|     local area = {{pos.x - radius, pos.y - radius}, {pos.x + radius, pos.y + radius}} | ||||
|     local trees = surface.find_entities_filtered {area = area, type = 'tree'} | ||||
|     local area = { { pos.x - radius, pos.y - radius }, { pos.x + radius, pos.y + radius } } | ||||
|     local trees = surface.find_entities_filtered { area = area, type = 'tree' } | ||||
|     if #trees > 0 then | ||||
|         for _, tree in pairs(trees) do | ||||
|             if tree and tree.valid then | ||||
| @@ -110,8 +110,8 @@ local function remove_rocks(entity) | ||||
|     local surface = entity.surface | ||||
|     local radius = 10 | ||||
|     local pos = entity.position | ||||
|     local area = {{pos.x - radius, pos.y - radius}, {pos.x + radius, pos.y + radius}} | ||||
|     local rocks = surface.find_entities_filtered {area = area, type = 'simple-entity'} | ||||
|     local area = { { pos.x - radius, pos.y - radius }, { pos.x + radius, pos.y + radius } } | ||||
|     local rocks = surface.find_entities_filtered { area = area, type = 'simple-entity' } | ||||
|     if #rocks > 0 then | ||||
|         for _, rock in pairs(rocks) do | ||||
|             if rock and rock.valid then | ||||
| @@ -136,11 +136,11 @@ local function fill_tiles(entity, size) | ||||
|         'deepwater', | ||||
|         'deepwater-green' | ||||
|     } | ||||
|     local area = {{pos.x - radius, pos.y - radius}, {pos.x + radius, pos.y + radius}} | ||||
|     local tiles = surface.find_tiles_filtered {area = area, name = t} | ||||
|     local area = { { pos.x - radius, pos.y - radius }, { pos.x + radius, pos.y + radius } } | ||||
|     local tiles = surface.find_tiles_filtered { area = area, name = t } | ||||
|     if #tiles > 0 then | ||||
|         for _, tile in pairs(tiles) do | ||||
|             surface.set_tiles({{name = 'sand-1', position = tile.position}}, true) | ||||
|             surface.set_tiles({ { name = 'sand-1', position = tile.position } }, true) | ||||
|         end | ||||
|     end | ||||
|     Public.debug_print('fill_tiles - filled tiles cause we found non-placable tiles.') | ||||
| @@ -163,11 +163,11 @@ local function get_spawn_pos() | ||||
|     local inverted = Public.get('inverted') | ||||
|     if inverted then | ||||
|         if initial_position.y - target.position.y < -10 then | ||||
|             initial_position = {x = initial_position.x, y = initial_position.y + 50} | ||||
|             initial_position = { x = initial_position.x, y = initial_position.y + 50 } | ||||
|         end | ||||
|     else | ||||
|         if initial_position.y - target.position.y > 10 then | ||||
|             initial_position = {x = initial_position.x, y = initial_position.y - 50} | ||||
|             initial_position = { x = initial_position.x, y = initial_position.y - 50 } | ||||
|         end | ||||
|     end | ||||
|  | ||||
| @@ -188,9 +188,9 @@ local function get_spawn_pos() | ||||
|             c = c + 1 | ||||
|             valid_position = Public.get('spawn_position') | ||||
|             Public.debug_print(serpent.block('valid_position - x:' .. valid_position.x .. ' y:' .. valid_position.y)) | ||||
|             remove_trees({surface = surface, position = valid_position, valid = true}) | ||||
|             remove_rocks({surface = surface, position = valid_position, valid = true}) | ||||
|             fill_tiles({surface = surface, position = valid_position, valid = true}) | ||||
|             remove_trees({ surface = surface, position = valid_position, valid = true }) | ||||
|             remove_rocks({ surface = surface, position = valid_position, valid = true }) | ||||
|             fill_tiles({ surface = surface, position = valid_position, valid = true }) | ||||
|             Public.set('spot', 'nil') | ||||
|             if c == 5 then | ||||
|                 return Public.debug_print('get_spawn_pos - we could not find a spawning pos?') | ||||
| @@ -333,7 +333,7 @@ local function set_main_target() | ||||
|     local target = Public.get('target') | ||||
|     if target then | ||||
|         if target.valid then | ||||
|             raise(Public.events.on_target_aquired, {target = target}) | ||||
|             raise(Public.events.on_target_aquired, { target = target }) | ||||
|             return | ||||
|         end | ||||
|     end | ||||
| @@ -349,12 +349,12 @@ local function set_main_target() | ||||
|         sec_target = get_random_character() | ||||
|     end | ||||
|     if not sec_target then | ||||
|         raise(Public.events.on_target_aquired, {target = target}) | ||||
|         raise(Public.events.on_target_aquired, { target = target }) | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     Public.set('target', sec_target) | ||||
|     raise(Public.events.on_target_aquired, {target = target}) | ||||
|     raise(Public.events.on_target_aquired, { target = target }) | ||||
|     Public.debug_print('set_main_target -- New main target ' .. sec_target.name .. ' at position x' .. sec_target.position.x .. ' y' .. sec_target.position.y .. ' selected.') | ||||
| end | ||||
|  | ||||
| @@ -367,7 +367,7 @@ local function set_group_spawn_position(surface) | ||||
|     if not position then | ||||
|         return | ||||
|     end | ||||
|     Public.set('spawn_position', {x = position.x, y = position.y}) | ||||
|     Public.set('spawn_position', { x = position.x, y = position.y }) | ||||
|     local spawn_position = get_spawn_pos() | ||||
|     if spawn_position then | ||||
|         Public.debug_print('set_group_spawn_position -- Changed position to x' .. spawn_position.x .. ' y' .. spawn_position.y .. '.') | ||||
| @@ -403,7 +403,7 @@ local function set_enemy_evolution() | ||||
|  | ||||
|     enemy.evolution_factor = evolution_factor | ||||
|  | ||||
|     raise(Public.events.on_evolution_factor_changed, {evolution_factor = evolution_factor}) | ||||
|     raise(Public.events.on_evolution_factor_changed, { evolution_factor = evolution_factor }) | ||||
| end | ||||
|  | ||||
| local function can_units_spawn() | ||||
| @@ -464,7 +464,7 @@ local function spawn_biter(surface, position, force_spawn, is_boss_biter, unit_s | ||||
|     if not force_spawn then | ||||
|         if not is_boss_biter then | ||||
|             if not can_units_spawn() then | ||||
|                 return | ||||
|                 return false | ||||
|             end | ||||
|         end | ||||
|     end | ||||
| @@ -484,9 +484,9 @@ local function spawn_biter(surface, position, force_spawn, is_boss_biter, unit_s | ||||
|  | ||||
|     if enable_random_spawn_positions then | ||||
|         if random(1, 3) == 1 then | ||||
|             position = {x = (-1 * (position.x + random(1, 10))), y = (position.y + random(1, 10))} | ||||
|             position = { x = (-1 * (position.x + random(1, 10))), y = (position.y + random(1, 10)) } | ||||
|         else | ||||
|             position = {x = (position.x + random(1, 10)), y = (position.y + random(1, 10))} | ||||
|             position = { x = (position.x + random(1, 10)), y = (position.y + random(1, 10)) } | ||||
|         end | ||||
|     end | ||||
|  | ||||
| @@ -502,10 +502,20 @@ local function spawn_biter(surface, position, force_spawn, is_boss_biter, unit_s | ||||
|         force = 'aggressors' | ||||
|     end | ||||
|  | ||||
|     local biter = surface.create_entity({name = name, position = position, force = force}) | ||||
|     -- biter.ai_settings.allow_destroy_when_commands_fail = true | ||||
|     -- biter.ai_settings.allow_try_return_to_spawner = false | ||||
|     -- biter.ai_settings.do_separation = true | ||||
|     local e = { name = name, position = position, force = force } | ||||
|  | ||||
|     if not surface.can_place_entity(e) then | ||||
|         return false | ||||
|     end | ||||
|  | ||||
|     local biter = surface.create_entity(e) | ||||
|     if not biter or not biter.valid then | ||||
|         return false | ||||
|     end | ||||
|  | ||||
|     biter.ai_settings.allow_destroy_when_commands_fail = true | ||||
|     biter.ai_settings.allow_try_return_to_spawner = false | ||||
|     biter.ai_settings.do_separation = true | ||||
|  | ||||
|     local increase_health_per_wave = Public.get('increase_health_per_wave') | ||||
|     local boost_units_when_wave_is_above = Public.get('boost_units_when_wave_is_above') | ||||
| @@ -553,7 +563,7 @@ local function spawn_biter(surface, position, force_spawn, is_boss_biter, unit_s | ||||
|  | ||||
|         generated_units.boss_units[#generated_units.boss_units + 1] = biter | ||||
|     else | ||||
|         generated_units.active_biters[biter.unit_number] = {entity = biter, spawn_tick = game.tick} | ||||
|         generated_units.active_biters[biter.unit_number] = { entity = biter, spawn_tick = game.tick } | ||||
|     end | ||||
|     local active_biter_count = Public.get('active_biter_count') | ||||
|     Public.set('active_biter_count', active_biter_count + 1) | ||||
| @@ -573,9 +583,9 @@ local function spawn_worm(surface, position, is_boss_worm) | ||||
|  | ||||
|     if enable_random_spawn_positions then | ||||
|         if random(1, 3) == 1 then | ||||
|             position = {x = (-1 * (position.x + random(1, 10))), y = (position.y + random(1, 10))} | ||||
|             position = { x = (-1 * (position.x + random(1, 10))), y = (position.y + random(1, 10)) } | ||||
|         else | ||||
|             position = {x = (position.x + random(1, 10)), y = (position.y + random(1, 10))} | ||||
|             position = { x = (position.x + random(1, 10)), y = (position.y + random(1, 10)) } | ||||
|         end | ||||
|     end | ||||
|  | ||||
| @@ -591,7 +601,7 @@ local function spawn_worm(surface, position, is_boss_worm) | ||||
|         force = 'aggressors' | ||||
|     end | ||||
|  | ||||
|     local worm = surface.create_entity({name = name, position = position, force = force}) | ||||
|     local worm = surface.create_entity({ name = name, position = position, force = force }) | ||||
|     local increase_health_per_wave = Public.get('increase_health_per_wave') | ||||
|     local boost_units_when_wave_is_above = Public.get('boost_units_when_wave_is_above') | ||||
|     local boost_bosses_when_wave_is_above = Public.get('boost_bosses_when_wave_is_above') | ||||
| @@ -757,7 +767,7 @@ local function set_next_wave() | ||||
|             local pos = { | ||||
|                 position = spawn_position | ||||
|             } | ||||
|             Alert.alert_all_players_location(pos, msg, {r = 0.8, g = 0.1, b = 0.1}) | ||||
|             Alert.alert_all_players_location(pos, msg, { r = 0.8, g = 0.1, b = 0.1 }) | ||||
|         end | ||||
|         threat_gain = threat_gain * 2 | ||||
|     else | ||||
| @@ -792,12 +802,12 @@ end | ||||
|  | ||||
| local function reform_group(group) | ||||
|     local unit_group_command_step_length = Public.get('unit_group_command_step_length') | ||||
|     local group_position = {x = group.position.x, y = group.position.y} | ||||
|     local group_position = { x = group.position.x, y = group.position.y } | ||||
|     local step_length = unit_group_command_step_length | ||||
|     local generated_units = Public.get('generated_units') | ||||
|     local position = group.surface.find_non_colliding_position('biter-spawner', group_position, step_length, 4) | ||||
|     if position then | ||||
|         local new_group = group.surface.create_unit_group {position = position, force = group.force} | ||||
|         local new_group = group.surface.create_unit_group { position = position, force = group.force } | ||||
|         for _, biter in pairs(group.members) do | ||||
|             new_group.add_member(biter) | ||||
|         end | ||||
| @@ -834,7 +844,7 @@ local function get_side_targets(group) | ||||
|     local search_side_targets = Public.get('search_side_targets') | ||||
|  | ||||
|     local commands = {} | ||||
|     local group_position = {x = group.position.x, y = group.position.y} | ||||
|     local group_position = { x = group.position.x, y = group.position.y } | ||||
|     local step_length = unit_group_command_step_length | ||||
|  | ||||
|     local side_target = Public.get_side_target() | ||||
| @@ -849,11 +859,11 @@ local function get_side_targets(group) | ||||
|         local old_position = group_position | ||||
|         local obstacles = | ||||
|             group.surface.find_entities_filtered { | ||||
|             position = old_position, | ||||
|             radius = step_length * 2, | ||||
|             type = search_side_targets, | ||||
|             limit = 100 | ||||
|         } | ||||
|                 position = old_position, | ||||
|                 radius = step_length * 2, | ||||
|                 type = search_side_targets, | ||||
|                 limit = 100 | ||||
|             } | ||||
|         if obstacles then | ||||
|             for v = 1, #obstacles, 1 do | ||||
|                 if obstacles[v].valid then | ||||
| @@ -879,7 +889,7 @@ end | ||||
| local function get_main_command(group) | ||||
|     local unit_group_command_step_length = Public.get('unit_group_command_step_length') | ||||
|     local commands = {} | ||||
|     local group_position = {x = group.position.x, y = group.position.y} | ||||
|     local group_position = { x = group.position.x, y = group.position.y } | ||||
|     local step_length = unit_group_command_step_length | ||||
|  | ||||
|     local target = Public.get('target') | ||||
| @@ -908,11 +918,11 @@ local function get_main_command(group) | ||||
|             group_position.y = group_position.y + vector[2] | ||||
|             local obstacles = | ||||
|                 group.surface.find_entities_filtered { | ||||
|                 position = old_position, | ||||
|                 radius = step_length / 2, | ||||
|                 type = {'simple-entity', 'tree'}, | ||||
|                 limit = 50 | ||||
|             } | ||||
|                     position = old_position, | ||||
|                     radius = step_length / 2, | ||||
|                     type = { 'simple-entity', 'tree' }, | ||||
|                     limit = 50 | ||||
|                 } | ||||
|             if obstacles then | ||||
|                 shuffle_distance(obstacles, old_position) | ||||
|                 for ii = 1, #obstacles, 1 do | ||||
| @@ -929,7 +939,7 @@ local function get_main_command(group) | ||||
|             if position then | ||||
|                 commands[#commands + 1] = { | ||||
|                     type = defines.command.attack_area, | ||||
|                     destination = {x = position.x, y = position.y}, | ||||
|                     destination = { x = position.x, y = position.y }, | ||||
|                     radius = 16, | ||||
|                     distraction = defines.distraction.by_anything | ||||
|                 } | ||||
| @@ -939,7 +949,7 @@ local function get_main_command(group) | ||||
|  | ||||
|     commands[#commands + 1] = { | ||||
|         type = defines.command.attack_area, | ||||
|         destination = {x = target_position.x, y = target_position.y}, | ||||
|         destination = { x = target_position.x, y = target_position.y }, | ||||
|         radius = 8, | ||||
|         distraction = defines.distraction.by_anything | ||||
|     } | ||||
| @@ -1131,10 +1141,10 @@ local function spawn_unit_group(fs, only_bosses) | ||||
|  | ||||
|     local radius = 10 | ||||
|     local area = { | ||||
|         left_top = {spawn_position.x - radius, spawn_position.y - radius}, | ||||
|         right_bottom = {spawn_position.x + radius, spawn_position.y + radius} | ||||
|         left_top = { spawn_position.x - radius, spawn_position.y - radius }, | ||||
|         right_bottom = { spawn_position.x + radius, spawn_position.y + radius } | ||||
|     } | ||||
|     for _, v in pairs(surface.find_entities_filtered {area = area, name = 'land-mine'}) do | ||||
|     for _, v in pairs(surface.find_entities_filtered { area = area, name = 'land-mine' }) do | ||||
|         if v and v.valid then | ||||
|             Public.debug_print('spawn_unit_group - found land-mines') | ||||
|             v.die() | ||||
| @@ -1142,9 +1152,9 @@ local function spawn_unit_group(fs, only_bosses) | ||||
|     end | ||||
|  | ||||
|     if remove_entities and not (fs and fs.bypass) then | ||||
|         remove_trees({surface = surface, position = spawn_position, valid = true}) | ||||
|         remove_rocks({surface = surface, position = spawn_position, valid = true}) | ||||
|         fill_tiles({surface = surface, position = spawn_position, valid = true}) | ||||
|         remove_trees({ surface = surface, position = spawn_position, valid = true }) | ||||
|         remove_rocks({ surface = surface, position = spawn_position, valid = true }) | ||||
|         fill_tiles({ surface = surface, position = spawn_position, valid = true }) | ||||
|     end | ||||
|  | ||||
|     local wave_number = Public.get('wave_number') | ||||
| @@ -1163,12 +1173,12 @@ local function spawn_unit_group(fs, only_bosses) | ||||
|  | ||||
|     local generated_units = Public.get('generated_units') | ||||
|  | ||||
|     local unit_group = surface.create_unit_group({position = spawn_position, force = force}) | ||||
|     local unit_group = surface.create_unit_group({ position = spawn_position, force = force }) | ||||
|  | ||||
|     event_data.unit_group = unit_group | ||||
|  | ||||
|     generated_units.unit_group_pos.index = generated_units.unit_group_pos.index + 1 | ||||
|     generated_units.unit_group_pos.positions[unit_group.group_number] = {position = unit_group.position, index = 0} | ||||
|     generated_units.unit_group_pos.positions[unit_group.group_number] = { position = unit_group.position, index = 0 } | ||||
|     local average_unit_group_size = Public.get('average_unit_group_size') | ||||
|     local unit_settings = Public.get('unit_settings') | ||||
|     event_data.unit_settings = unit_settings | ||||
| @@ -1189,7 +1199,7 @@ local function spawn_unit_group(fs, only_bosses) | ||||
|                 end | ||||
|                 unit_group.add_member(biter) | ||||
|  | ||||
|                 raise(Public.events.on_entity_created, {entity = biter, boss_unit = false, target = target}) | ||||
|                 raise(Public.events.on_entity_created, { entity = biter, boss_unit = false }) | ||||
|                 -- command_to_side_target(unit_group) | ||||
|             end | ||||
|         end | ||||
| @@ -1211,7 +1221,7 @@ local function spawn_unit_group(fs, only_bosses) | ||||
|                     break | ||||
|                 end | ||||
|                 unit_group.add_member(biter) | ||||
|                 raise(Public.events.on_entity_created, {entity = biter, boss_unit = true, target = target}) | ||||
|                 raise(Public.events.on_entity_created, { entity = biter, boss_unit = true }) | ||||
|             end | ||||
|             Public.set('boss_wave', false) | ||||
|         end | ||||
| @@ -1232,7 +1242,7 @@ local function spawn_unit_group(fs, only_bosses) | ||||
|                 break | ||||
|             end | ||||
|             unit_group.add_member(biter) | ||||
|             raise(Public.events.on_entity_created, {entity = biter, boss_unit = true, target = target}) | ||||
|             raise(Public.events.on_entity_created, { entity = biter, boss_unit = true }) | ||||
|         end | ||||
|     end | ||||
|  | ||||
| @@ -1250,7 +1260,7 @@ end | ||||
| local function spawn_unit_group_simple(fs) | ||||
|     local target = Public.get('target') | ||||
|     if not valid(target) then | ||||
|         Public.debug_print('spawn_unit_group - Target was not valid?') | ||||
|         Public.debug_print('spawn_unit_group_simple - Target was not valid?') | ||||
|         return | ||||
|     end | ||||
|  | ||||
| @@ -1266,7 +1276,6 @@ local function spawn_unit_group_simple(fs) | ||||
|     local wave_number = Public.get('wave_number') | ||||
|     Public.wave_defense_set_unit_raffle(wave_number) | ||||
|  | ||||
|     local event_data = {} | ||||
|  | ||||
|     local es_settings = Public.get_es('settings') | ||||
|  | ||||
| @@ -1277,20 +1286,13 @@ local function spawn_unit_group_simple(fs) | ||||
|  | ||||
|     local generated_units = Public.get('generated_units') | ||||
|  | ||||
|     local unit_group = surface.create_unit_group({position = spawn_position, force = force}) | ||||
|     local unit_group = surface.create_unit_group({ position = spawn_position, force = force }) | ||||
|  | ||||
|     event_data.unit_group = unit_group | ||||
|  | ||||
|     generated_units.unit_group_pos.index = generated_units.unit_group_pos.index + 1 | ||||
|     generated_units.unit_group_pos.positions[unit_group.group_number] = {position = unit_group.position, index = 0} | ||||
|     local average_unit_group_size = Public.get('average_unit_group_size') | ||||
|     generated_units.unit_group_pos.positions[unit_group.group_number] = { position = unit_group.position, index = 0 } | ||||
|     local unit_settings = Public.get('unit_settings') | ||||
|     event_data.unit_settings = unit_settings | ||||
|  | ||||
|     local group_size = floor(average_unit_group_size * Public.group_size_modifier_raffle[random(1, Public.group_size_modifier_raffle_size)]) | ||||
|  | ||||
|     event_data.group_size = group_size | ||||
|     event_data.boss_wave = false | ||||
|  | ||||
|     if not es_settings.generated_units then | ||||
|         es_settings.generated_units = 0 | ||||
| @@ -1300,16 +1302,20 @@ local function spawn_unit_group_simple(fs) | ||||
|     end | ||||
|  | ||||
|     local count = fs.scale or 1 | ||||
|     event_data.spawn_count = count | ||||
|     local s = 0 | ||||
|     for i = 1, count, 1 do | ||||
|         local is_boss = i % 2 == 0 | ||||
|         local biter = spawn_biter(surface, spawn_position, fs, is_boss, unit_settings, final_battle) | ||||
|         if not biter then | ||||
|             Public.debug_print('spawn_unit_group - No biter was found?') | ||||
|             break | ||||
|         local is_boss = i % 4 == 0 | ||||
|         local biter = spawn_biter(surface, spawn_position, fs and fs.bypass, is_boss, unit_settings, final_battle) | ||||
|         if biter then | ||||
|             s = s + 1 | ||||
|             unit_group.add_member(biter) | ||||
|             raise(Public.events.on_entity_created, { entity = biter, boss_unit = is_boss }) | ||||
|         end | ||||
|         unit_group.add_member(biter) | ||||
|         raise(Public.events.on_entity_created, {entity = biter, boss_unit = true, target = target}) | ||||
|     end | ||||
|  | ||||
|     if s == 0 then | ||||
|         Public.debug_print('spawn_unit_group - No biter was spawned?') | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     generated_units.unit_groups[unit_group.group_number] = unit_group | ||||
| @@ -1318,8 +1324,6 @@ local function spawn_unit_group_simple(fs) | ||||
|     if random(1, 2) == 1 then | ||||
|         Public.set('random_group', unit_group) | ||||
|     end | ||||
|     Public.set('spot', 'nil') | ||||
|     raise(Public.events.on_unit_group_created, event_data) | ||||
|     return true | ||||
| end | ||||
|  | ||||
| @@ -1381,7 +1385,7 @@ end | ||||
| if is_loaded_bool('maps.mountain_fortress_v3.table') then | ||||
|     local Core = require 'maps.mountain_fortress_v3.core' | ||||
|  | ||||
|     check_if_near_target = function(position) | ||||
|     check_if_near_target = function (position) | ||||
|         local entity = { | ||||
|             valid = true, | ||||
|             position = position | ||||
| @@ -1396,7 +1400,7 @@ if is_loaded_bool('maps.mountain_fortress_v3.table') then | ||||
|         return false | ||||
|     end | ||||
| else | ||||
|     check_if_near_target = function() | ||||
|     check_if_near_target = function () | ||||
|         return false | ||||
|     end | ||||
| end | ||||
| @@ -1421,16 +1425,19 @@ Public.spawn_unit_group = spawn_unit_group | ||||
|  | ||||
| Event.on_nth_tick( | ||||
|     30, | ||||
|     function() | ||||
|     function () | ||||
|         local tick = game.tick | ||||
|         local game_lost = Public.get('game_lost') | ||||
|         if game_lost then | ||||
|             return | ||||
|         end | ||||
|         local final_battle = Public.get('final_battle') | ||||
|         if final_battle then | ||||
|             return | ||||
|         end | ||||
|  | ||||
|         local paused = Public.get('paused') | ||||
|         if paused and not final_battle then | ||||
|         if paused then | ||||
|             local players = game.connected_players | ||||
|             for _, player in pairs(players) do | ||||
|                 Public.update_gui(player) | ||||
| @@ -1462,10 +1469,6 @@ Event.on_nth_tick( | ||||
|             tick_tasks_t2[t2]() | ||||
|         end | ||||
|  | ||||
|         if final_battle then | ||||
|             return | ||||
|         end | ||||
|  | ||||
|         local players = game.connected_players | ||||
|         for _, player in pairs(players) do | ||||
|             Public.update_gui(player) | ||||
| @@ -1475,9 +1478,9 @@ Event.on_nth_tick( | ||||
|  | ||||
| Event.add( | ||||
|     Public.events.on_biters_evolved, | ||||
|     function(event) | ||||
|     function (event) | ||||
|         if not event then | ||||
|             event = {force = game.forces.enemy} | ||||
|             event = { force = game.forces.enemy } | ||||
|         end | ||||
|  | ||||
|         increase_biter_damage(event.force) | ||||
| @@ -1493,12 +1496,13 @@ Event.add(Public.events.on_spawn_unit_group_simple, spawn_unit_group_simple) | ||||
|  | ||||
| Event.on_nth_tick( | ||||
|     50, | ||||
|     function() | ||||
|     function () | ||||
|         local final_battle = Public.get('final_battle') | ||||
|         if final_battle then | ||||
|             return | ||||
|         end | ||||
|  | ||||
|  | ||||
|         local tick_to_spawn_unit_groups = Public.get('tick_to_spawn_unit_groups') | ||||
|         local tick = game.tick | ||||
|         local will_not_spawn = tick % tick_to_spawn_unit_groups ~= 0 | ||||
| @@ -1524,5 +1528,6 @@ Public.set_next_wave = set_next_wave | ||||
| Public.normalize_spawn_position = normalize_spawn_position | ||||
| Public.check_if_near_target = check_if_near_target | ||||
| Public.spawn_worm = spawn_worm | ||||
| Public.set_main_target = set_main_target | ||||
|  | ||||
| return Public | ||||
|   | ||||
| @@ -4,7 +4,8 @@ local Gui = require 'utils.gui' | ||||
| local Event = require 'utils.event' | ||||
|  | ||||
| local this = { | ||||
|     pause_waves_custom_callback = nil | ||||
|     pause_waves_custom_callback = nil, | ||||
|     threat_event_custom_callback = nil | ||||
| } | ||||
| local Public = {} | ||||
| Public.events = { | ||||
| @@ -22,28 +23,28 @@ local insert = table.insert | ||||
|  | ||||
| Global.register( | ||||
|     this, | ||||
|     function(tbl) | ||||
|     function (tbl) | ||||
|         this = tbl | ||||
|     end | ||||
| ) | ||||
|  | ||||
| Public.group_size_modifier_raffle = {} | ||||
| local group_size_chances = { | ||||
|     {4, 0.4}, | ||||
|     {5, 0.5}, | ||||
|     {6, 0.6}, | ||||
|     {7, 0.7}, | ||||
|     {8, 0.8}, | ||||
|     {9, 0.9}, | ||||
|     {10, 1}, | ||||
|     {9, 1.1}, | ||||
|     {8, 1.2}, | ||||
|     {7, 1.3}, | ||||
|     {6, 1.4}, | ||||
|     {5, 1.5}, | ||||
|     {4, 1.6}, | ||||
|     {3, 1.7}, | ||||
|     {2, 1.8} | ||||
|     { 4,  0.4 }, | ||||
|     { 5,  0.5 }, | ||||
|     { 6,  0.6 }, | ||||
|     { 7,  0.7 }, | ||||
|     { 8,  0.8 }, | ||||
|     { 9,  0.9 }, | ||||
|     { 10, 1 }, | ||||
|     { 9,  1.1 }, | ||||
|     { 8,  1.2 }, | ||||
|     { 7,  1.3 }, | ||||
|     { 6,  1.4 }, | ||||
|     { 5,  1.5 }, | ||||
|     { 4,  1.6 }, | ||||
|     { 3,  1.7 }, | ||||
|     { 2,  1.8 } | ||||
| } | ||||
|  | ||||
| for _, v in pairs(group_size_chances) do | ||||
| @@ -71,7 +72,7 @@ function Public.reset_wave_defense() | ||||
|     this.log_wave_to_discord = true | ||||
|     this.paused = false | ||||
|     this.pause_without_votes = true | ||||
|     this.pause_wave_in_ticks = 18000 -- 5 minutes | ||||
|     this.pause_wave_in_ticks = 18000              -- 5 minutes | ||||
|     this.next_pause_interval = game.tick + 216000 -- 1 hour | ||||
|     this.game_lost = false | ||||
|     this.get_random_close_spawner_attempts = 5 | ||||
| @@ -89,7 +90,7 @@ function Public.reset_wave_defense() | ||||
|     } | ||||
|     this.side_targets = {} | ||||
|     this.simple_entity_shredding_cost_modifier = 0.009 | ||||
|     this.spawn_position = {x = 0, y = 64} | ||||
|     this.spawn_position = { x = 0, y = 64 } | ||||
|     this.spitter_raffle = {} | ||||
|     this.surface_index = 1 | ||||
|     this.target = nil | ||||
| @@ -103,7 +104,7 @@ function Public.reset_wave_defense() | ||||
|     this.random_group = nil | ||||
|     this.unit_group_command_delay = 3600 * 20 | ||||
|     this.unit_group_command_step_length = 15 | ||||
|     this.search_side_targets = {'simple-entity', 'tree', 'car', 'spider-vehicle', 'character'} | ||||
|     this.search_side_targets = { 'simple-entity', 'tree', 'car', 'spider-vehicle', 'character' } | ||||
|     this.wave_interval = 3600 | ||||
|     this.wave_enforced = false | ||||
|     this.wave_number = 0 | ||||
| @@ -162,10 +163,10 @@ function Public.reset_wave_defense() | ||||
|     this.worm_unit_settings = { | ||||
|         -- note that final health modifier isn't lower than 1 | ||||
|         scale_units_by_health = { | ||||
|             ['land-mine'] = 0.5, -- not active as of now | ||||
|             ['gun-turret'] = 0.5, -- not active as of now | ||||
|             ['land-mine'] = 0.5,           -- not active as of now | ||||
|             ['gun-turret'] = 0.5,          -- not active as of now | ||||
|             ['flamethrower-turret'] = 0.4, -- not active as of now | ||||
|             ['artillery-turret'] = 0.25, -- not active as of now | ||||
|             ['artillery-turret'] = 0.25,   -- not active as of now | ||||
|             ['small-worm-turret'] = 0.8, | ||||
|             ['medium-worm-turret'] = 0.6, | ||||
|             ['big-worm-turret'] = 0.3, | ||||
| @@ -438,7 +439,7 @@ end | ||||
| function Public.nuke_wave_gui() | ||||
|     if Gui.get_mod_gui_top_frame() then | ||||
|         Core.iter_players( | ||||
|             function(player) | ||||
|             function (player) | ||||
|                 local g = Gui.get_button_flow(player)['wave_defense'] | ||||
|                 if g and g.valid then | ||||
|                     g.destroy() | ||||
| @@ -447,7 +448,7 @@ function Public.nuke_wave_gui() | ||||
|         ) | ||||
|     else | ||||
|         Core.iter_players( | ||||
|             function(player) | ||||
|             function (player) | ||||
|                 if player.gui.top.wave_defense and player.gui.top.wave_defense.valid then | ||||
|                     player.gui.top.wave_defense.destroy() | ||||
|                 end | ||||
| @@ -456,9 +457,9 @@ function Public.nuke_wave_gui() | ||||
|     end | ||||
| end | ||||
|  | ||||
| --- Sets a custom callback whenever the pause_waves func is run | ||||
| function Public.set_pause_waves_custom_callback(value) | ||||
|     this.pause_waves_custom_callback = value or nil | ||||
| --- Sets a custom callback | ||||
| function Public.set_pause_waves_custom_callback(callback) | ||||
|     this.pause_waves_custom_callback = callback or nil | ||||
| end | ||||
|  | ||||
| --- Gets a custom callback | ||||
| @@ -466,6 +467,16 @@ function Public.get_pause_waves_custom_callback() | ||||
|     return this.pause_waves_custom_callback or nil | ||||
| end | ||||
|  | ||||
| --- Sets a custom callback | ||||
| function Public.set_threat_event_custom_callback(callback) | ||||
|     this.threat_event_custom_callback = callback or nil | ||||
| end | ||||
|  | ||||
| --- Gets a custom callback | ||||
| function Public.get_threat_event_custom_callback() | ||||
|     return this.threat_event_custom_callback or nil | ||||
| end | ||||
|  | ||||
| --- Toggle debug - when you need to troubleshoot. | ||||
| -- @param <null> | ||||
| function Public.toggle_debug() | ||||
| @@ -505,7 +516,7 @@ end | ||||
| -- Event.on_nth_tick(30, Public.debug_module) | ||||
|  | ||||
| Event.on_init( | ||||
|     function() | ||||
|     function () | ||||
|         Public.reset_wave_defense() | ||||
|     end | ||||
| ) | ||||
|   | ||||
| @@ -6,18 +6,17 @@ local Task = require 'utils.task' | ||||
|  | ||||
| local round = math.round | ||||
| local random = math.random | ||||
| local place_nest_near_unit_group | ||||
|  | ||||
| local immunity_spawner = | ||||
|     Token.register( | ||||
|     function(data) | ||||
|         local entity = data.entity | ||||
|         if not entity or not entity.valid then | ||||
|             return | ||||
|         function (data) | ||||
|             local entity = data.entity | ||||
|             if not entity or not entity.valid then | ||||
|                 return | ||||
|             end | ||||
|             entity.destructible = true | ||||
|         end | ||||
|         entity.destructible = true | ||||
|     end | ||||
| ) | ||||
|     ) | ||||
|  | ||||
| local function is_boss(entity) | ||||
|     local unit_number = entity.unit_number | ||||
| @@ -63,156 +62,130 @@ local function remove_unit(entity) | ||||
|     end | ||||
| end | ||||
|  | ||||
| if is_loaded_bool('maps.mountain_fortress_v3.table') then | ||||
|     local Core = require 'maps.mountain_fortress_v3.core' | ||||
|  | ||||
|     place_nest_near_unit_group = function() | ||||
|         local random_group = Public.get('random_group') | ||||
|         if not (random_group and random_group.valid) then | ||||
|             return | ||||
|         end | ||||
|  | ||||
|         local disable_spawn_near_target = Public.get('disable_spawn_near_target') | ||||
|  | ||||
|         local generated_units = Public.get('generated_units') | ||||
|         local group = generated_units.unit_groups[random_group.group_number] | ||||
|         if not group then | ||||
|             return | ||||
|         end | ||||
|         if not group.valid then | ||||
|             return | ||||
|         end | ||||
|         if not group.members then | ||||
|             return | ||||
|         end | ||||
|         if not group.members[1] then | ||||
|             return | ||||
|         end | ||||
|         local unit = group.members[random(1, #group.members)] | ||||
|         if not unit.valid then | ||||
|             return | ||||
|         end | ||||
|  | ||||
|         if Core.is_around_train(unit) and disable_spawn_near_target then | ||||
|             Public.debug_print('place_nest_near_unit_group  - cannot spawn inside locomotive aura') | ||||
|             return | ||||
|         end | ||||
|  | ||||
|         local name = 'biter-spawner' | ||||
|         if random(1, 3) == 1 then | ||||
|             name = 'spitter-spawner' | ||||
|         end | ||||
|  | ||||
|         local position = unit.surface.find_non_colliding_position(name, unit.position, 12, 1) | ||||
|         if not position then | ||||
|             return | ||||
|         end | ||||
|         local r = Public.get('nest_building_density') | ||||
|         if | ||||
|             unit.surface.count_entities_filtered( | ||||
|                 { | ||||
|                     type = 'unit-spawner', | ||||
|                     force = unit.force, | ||||
|                     area = {{position.x - r, position.y - r}, {position.x + r, position.y + r}} | ||||
|                 } | ||||
|             ) > 0 | ||||
|          then | ||||
|             return | ||||
|         end | ||||
|  | ||||
|         local boss = is_boss(unit) | ||||
|  | ||||
|         local modified_unit_health = Public.get('modified_unit_health') | ||||
|         local modified_boss_unit_health = Public.get('modified_boss_unit_health') | ||||
|  | ||||
|         local spawner = unit.surface.create_entity({name = name, position = position, force = unit.force}) | ||||
|         spawner.destructible = false | ||||
|         local immunity_delay = random(100, 200) | ||||
|         Task.set_timeout_in_ticks(immunity_delay, immunity_spawner, {entity = spawner}) | ||||
|  | ||||
|         if boss then | ||||
|             BiterHealthBooster.add_boss_unit(spawner, modified_boss_unit_health.current_value, 0.5) | ||||
|         else | ||||
|             BiterHealthBooster.add_unit(spawner, modified_unit_health.current_value) | ||||
|         end | ||||
|         generated_units.nests[#generated_units.nests + 1] = spawner | ||||
|         unit.surface.create_entity({name = 'blood-explosion-huge', position = position}) | ||||
|         unit.surface.create_entity({name = 'blood-explosion-huge', position = unit.position}) | ||||
|         remove_unit(unit) | ||||
|         unit.destroy() | ||||
|         local threat = Public.get('threat') | ||||
|         Public.set('threat', threat - Public.threat_values[name]) | ||||
|         return true | ||||
| local place_nest_near_unit_group = function () | ||||
|     local random_group = Public.get('random_group') | ||||
|     if not (random_group and random_group.valid) then | ||||
|         return | ||||
|     end | ||||
| else | ||||
|     place_nest_near_unit_group = function() | ||||
|         local random_group = Public.get('random_group') | ||||
|         if not (random_group and random_group.valid) then | ||||
|             return | ||||
|         end | ||||
|  | ||||
|         local generated_units = Public.get('generated_units') | ||||
|         local group = generated_units.unit_groups[random_group.group_number] | ||||
|         if not group then | ||||
|             return | ||||
|         end | ||||
|         if not group.valid then | ||||
|             return | ||||
|         end | ||||
|         if not group.members then | ||||
|             return | ||||
|         end | ||||
|         if not group.members[1] then | ||||
|             return | ||||
|         end | ||||
|         local unit = group.members[random(1, #group.members)] | ||||
|         if not unit.valid then | ||||
|             return | ||||
|         end | ||||
|         local name = 'biter-spawner' | ||||
|         if random(1, 3) == 1 then | ||||
|             name = 'spitter-spawner' | ||||
|         end | ||||
|         local position = unit.surface.find_non_colliding_position(name, unit.position, 12, 1) | ||||
|         if not position then | ||||
|             return | ||||
|         end | ||||
|         local r = Public.get('nest_building_density') | ||||
|         if | ||||
|             unit.surface.count_entities_filtered( | ||||
|                 { | ||||
|                     type = 'unit-spawner', | ||||
|                     force = unit.force, | ||||
|                     area = {{position.x - r, position.y - r}, {position.x + r, position.y + r}} | ||||
|                 } | ||||
|             ) > 0 | ||||
|          then | ||||
|             return | ||||
|         end | ||||
|     local disable_spawn_near_target = Public.get('disable_spawn_near_target') | ||||
|  | ||||
|         local boss = is_boss(unit) | ||||
|  | ||||
|         local modified_unit_health = Public.get('modified_unit_health') | ||||
|         local modified_boss_unit_health = Public.get('modified_boss_unit_health') | ||||
|  | ||||
|         local spawner = unit.surface.create_entity({name = name, position = position, force = unit.force}) | ||||
|         spawner.destructible = false | ||||
|         Task.set_timeout_in_ticks(100, immunity_spawner, {entity = spawner}) | ||||
|  | ||||
|         if boss then | ||||
|             BiterHealthBooster.add_boss_unit(spawner, modified_boss_unit_health.current_value, 0.5) | ||||
|         else | ||||
|             BiterHealthBooster.add_unit(spawner, modified_unit_health.current_value) | ||||
|         end | ||||
|         generated_units.nests[#generated_units.nests + 1] = spawner | ||||
|         unit.surface.create_entity({name = 'blood-explosion-huge', position = position}) | ||||
|         unit.surface.create_entity({name = 'blood-explosion-huge', position = unit.position}) | ||||
|         remove_unit(unit) | ||||
|         unit.destroy() | ||||
|         local threat = Public.get('threat') | ||||
|         Public.set('threat', threat - Public.threat_values[name]) | ||||
|         return true | ||||
|     local generated_units = Public.get('generated_units') | ||||
|     local group = generated_units.unit_groups[random_group.group_number] | ||||
|     if not group then | ||||
|         return | ||||
|     end | ||||
|     if not group.valid then | ||||
|         return | ||||
|     end | ||||
|     if not group.members then | ||||
|         return | ||||
|     end | ||||
|     if not group.members[1] then | ||||
|         return | ||||
|     end | ||||
|     local unit = group.members[random(1, #group.members)] | ||||
|     if not unit.valid then | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     local custom_callback = Public.get('threat_event_custom_callback') | ||||
|     if custom_callback then | ||||
|         local cb = Task.get(custom_callback) | ||||
|         if cb then | ||||
|             local result = cb({ entity = unit, disable_spawn_near_target = disable_spawn_near_target }) | ||||
|             if result then | ||||
|                 Public.debug_print('place_nest_near_unit_group  - custom callback returned true') | ||||
|                 return | ||||
|             end | ||||
|         end | ||||
|     end | ||||
|  | ||||
|     local name = 'biter-spawner' | ||||
|     if random(1, 3) == 1 then | ||||
|         name = 'spitter-spawner' | ||||
|     end | ||||
|  | ||||
|     local position = unit.surface.find_non_colliding_position(name, unit.position, 12, 1) | ||||
|     if not position then | ||||
|         return | ||||
|     end | ||||
|     local r = Public.get('nest_building_density') | ||||
|     if | ||||
|         unit.surface.count_entities_filtered( | ||||
|             { | ||||
|                 type = 'unit-spawner', | ||||
|                 force = unit.force, | ||||
|                 area = { { position.x - r, position.y - r }, { position.x + r, position.y + r } } | ||||
|             } | ||||
|         ) > 0 | ||||
|     then | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     local boss = is_boss(unit) | ||||
|  | ||||
|     local modified_unit_health = Public.get('modified_unit_health') | ||||
|     local modified_boss_unit_health = Public.get('modified_boss_unit_health') | ||||
|  | ||||
|     local spawner = unit.surface.create_entity({ name = name, position = position, force = unit.force }) | ||||
|     spawner.destructible = false | ||||
|     local immunity_delay = random(100, 200) | ||||
|     Task.set_timeout_in_ticks(immunity_delay, immunity_spawner, { entity = spawner }) | ||||
|  | ||||
|     if boss then | ||||
|         BiterHealthBooster.add_boss_unit(spawner, modified_boss_unit_health.current_value, 0.5) | ||||
|     else | ||||
|         BiterHealthBooster.add_unit(spawner, modified_unit_health.current_value) | ||||
|     end | ||||
|     generated_units.nests[#generated_units.nests + 1] = spawner | ||||
|     unit.surface.create_entity({ name = 'blood-explosion-huge', position = position }) | ||||
|     unit.surface.create_entity({ name = 'blood-explosion-huge', position = unit.position }) | ||||
|     remove_unit(unit) | ||||
|     unit.destroy() | ||||
|     local threat = Public.get('threat') | ||||
|     Public.set('threat', threat - Public.threat_values[name]) | ||||
|     return true | ||||
| end | ||||
|  | ||||
| Public.place_custom_nest = function (surface, position, force) | ||||
|     local name = 'biter-spawner' | ||||
|     if random(1, 3) == 1 then | ||||
|         name = 'spitter-spawner' | ||||
|     end | ||||
|  | ||||
|     if not position then | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     position = surface.find_non_colliding_position(name, position, 12, 1) | ||||
|     if not position then | ||||
|         return | ||||
|     end | ||||
|     local r = Public.get('nest_building_density') | ||||
|     if | ||||
|         surface.count_entities_filtered( | ||||
|             { | ||||
|                 type = 'unit-spawner', | ||||
|                 force = force, | ||||
|                 area = { { position.x - r, position.y - r }, { position.x + r, position.y + r } } | ||||
|             } | ||||
|         ) > 0 | ||||
|     then | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     local modified_boss_unit_health = Public.get('modified_boss_unit_health') | ||||
|  | ||||
|     local spawner = surface.create_entity({ name = name, position = position, force = force }) | ||||
|     spawner.destructible = false | ||||
|     local immunity_delay = random(100, 200) | ||||
|     Task.set_timeout_in_ticks(immunity_delay, immunity_spawner, { entity = spawner }) | ||||
|  | ||||
|     BiterHealthBooster.add_boss_unit(spawner, modified_boss_unit_health.current_value, 0.5) | ||||
|  | ||||
|     surface.create_entity({ name = 'blood-explosion-huge', position = position }) | ||||
|     surface.create_entity({ name = 'blood-explosion-huge', position = position }) | ||||
| end | ||||
|  | ||||
| function Public.build_nest() | ||||
| @@ -293,13 +266,13 @@ function Public.build_worm() | ||||
|             { | ||||
|                 type = 'turret', | ||||
|                 force = unit.force, | ||||
|                 area = {{position.x - r, position.y - r}, {position.x + r, position.y + r}} | ||||
|                 area = { { position.x - r, position.y - r }, { position.x + r, position.y + r } } | ||||
|             } | ||||
|         ) > 0 | ||||
|      then | ||||
|     then | ||||
|         return | ||||
|     end | ||||
|     local u = unit.surface.create_entity({name = worm, position = position, force = unit.force}) | ||||
|     local u = unit.surface.create_entity({ name = worm, position = position, force = unit.force }) | ||||
|     local worm_unit_settings = Public.get('worm_unit_settings') | ||||
|     local modified_unit_health = Public.get('modified_unit_health') | ||||
|     local modified_boss_unit_health = Public.get('modified_boss_unit_health') | ||||
| @@ -314,8 +287,8 @@ function Public.build_worm() | ||||
|         BiterHealthBooster.add_unit(u, final_health) | ||||
|     end | ||||
|  | ||||
|     unit.surface.create_entity({name = 'blood-explosion-huge', position = position}) | ||||
|     unit.surface.create_entity({name = 'blood-explosion-huge', position = unit.position}) | ||||
|     unit.surface.create_entity({ name = 'blood-explosion-huge', position = position }) | ||||
|     unit.surface.create_entity({ name = 'blood-explosion-huge', position = unit.position }) | ||||
|     remove_unit(unit) | ||||
|     unit.destroy() | ||||
|     Public.set('threat', threat - Public.threat_values[worm]) | ||||
| @@ -364,21 +337,21 @@ function Public.build_worm_custom() | ||||
|             { | ||||
|                 type = 'turret', | ||||
|                 force = unit.force, | ||||
|                 area = {{position.x - r, position.y - r}, {position.x + r, position.y + r}} | ||||
|                 area = { { position.x - r, position.y - r }, { position.x + r, position.y + r } } | ||||
|             } | ||||
|         ) > 0 | ||||
|      then | ||||
|     then | ||||
|         return | ||||
|     end | ||||
|     local u = unit.surface.create_entity({name = worm, position = position, force = unit.force}) | ||||
|     local u = unit.surface.create_entity({ name = worm, position = position, force = unit.force }) | ||||
|     local modified_boss_unit_health = Public.get('modified_boss_unit_health') | ||||
|  | ||||
|     BiterHealthBooster.add_boss_unit(u, modified_boss_unit_health.current_value, 0.5) | ||||
|  | ||||
|     table.remove(group, generated_units.boss_unit_index) | ||||
|  | ||||
|     unit.surface.create_entity({name = 'blood-explosion-huge', position = position}) | ||||
|     unit.surface.create_entity({name = 'blood-explosion-huge', position = unit.position}) | ||||
|     unit.surface.create_entity({ name = 'blood-explosion-huge', position = position }) | ||||
|     unit.surface.create_entity({ name = 'blood-explosion-huge', position = unit.position }) | ||||
|     remove_unit(unit) | ||||
|     unit.destroy() | ||||
| end | ||||
| @@ -390,14 +363,14 @@ local function shred_simple_entities(entity) | ||||
|     end | ||||
|     local simple_entities = | ||||
|         entity.surface.find_entities_filtered( | ||||
|         { | ||||
|             type = 'simple-entity', | ||||
|             area = { | ||||
|                 {entity.position.x - 3, entity.position.y - 3}, | ||||
|                 {entity.position.x + 3, entity.position.y + 3} | ||||
|             { | ||||
|                 type = 'simple-entity', | ||||
|                 area = { | ||||
|                     { entity.position.x - 3, entity.position.y - 3 }, | ||||
|                     { entity.position.x + 3, entity.position.y + 3 } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     ) | ||||
|         ) | ||||
|     if #simple_entities == 0 then | ||||
|         return | ||||
|     end | ||||
| @@ -444,7 +417,7 @@ local function spawn_unit_spawner_inhabitants(entity) | ||||
|     end | ||||
|     Public.wave_defense_set_unit_raffle(wave_number) | ||||
|     for _ = 1, count, 1 do | ||||
|         local position = {entity.position.x + (-4 + math.random(0, 8)), entity.position.y + (-4 + math.random(0, 8))} | ||||
|         local position = { entity.position.x + (-4 + math.random(0, 8)), entity.position.y + (-4 + math.random(0, 8)) } | ||||
|         if math.random(1, 4) == 1 then | ||||
|             entity.surface.create_entity( | ||||
|                 { | ||||
|   | ||||
| @@ -388,6 +388,8 @@ function Public.new(name, help) | ||||
|         error('Command already exists: ' .. name, 2) | ||||
|     end | ||||
|  | ||||
|     if game then error('Cannot run new() when game is initialized : ' .. name, 2) end | ||||
|  | ||||
|     local command = | ||||
|         setmetatable( | ||||
|             { | ||||
| @@ -549,4 +551,24 @@ function Public:callback(func) | ||||
|     end | ||||
| end | ||||
|  | ||||
| Public.new('get', 'Hover over an object to get its name.') | ||||
|     :require_admin() | ||||
|     :callback( | ||||
|         function (player) | ||||
|             local entity = player.selected | ||||
|             if not entity or not entity.valid then | ||||
|                 return false | ||||
|             end | ||||
|  | ||||
|             player.print('[color=orange]Name:[/color] ' .. entity.name) | ||||
|             player.print('[color=orange]Type:[/color] ' .. entity.type) | ||||
|             player.print('[color=orange]Force:[/color] ' .. entity.force.name) | ||||
|             player.print('[color=orange]Destructible:[/color] ' .. (entity.destructible and 'true' or 'false')) | ||||
|             player.print('[color=orange]Minable:[/color] ' .. (entity.minable and 'true' or 'false')) | ||||
|             player.print('[color=orange]Unit Number:[/color] ' .. (entity.unit_number or 'nil')) | ||||
|             player.print('[color=orange]Position:[/color] ' .. serpent.line(entity.position)) | ||||
|             return true | ||||
|         end | ||||
|     ) | ||||
|  | ||||
| return Public | ||||
|   | ||||
| @@ -666,6 +666,7 @@ local function jail(player, offender, msg, raised, mute) | ||||
|         votejail[offender].jailed = true | ||||
|     end | ||||
|  | ||||
|     -- Enable this to clear the console for the jailed player | ||||
|     to_jail_player.clear_console() | ||||
|     Utils.print_to(offender, message) | ||||
|     return true | ||||
|   | ||||
| @@ -33,7 +33,7 @@ local this = { | ||||
|  | ||||
| Global.register( | ||||
|     this, | ||||
|     function(tbl) | ||||
|     function (tbl) | ||||
|         this = tbl | ||||
|     end | ||||
| ) | ||||
| @@ -63,29 +63,29 @@ end | ||||
|  | ||||
| local delayed_last_page_token = | ||||
|     Task.register( | ||||
|     function(event) | ||||
|         local player_index = event.player_index | ||||
|         local player = game.get_player(player_index) | ||||
|         if not player or not player.valid then | ||||
|             return | ||||
|         end | ||||
|         function (event) | ||||
|             local player_index = event.player_index | ||||
|             local player = game.get_player(player_index) | ||||
|             if not player or not player.valid then | ||||
|                 return | ||||
|             end | ||||
|  | ||||
|         local element = event.element | ||||
|         if not element or not element.valid then | ||||
|             return | ||||
|         end | ||||
|             local element = event.element | ||||
|             if not element or not element.valid then | ||||
|                 return | ||||
|             end | ||||
|  | ||||
|         local player_data = get_player_data(player) | ||||
|         if not player_data or not player_data.table_count then | ||||
|             return | ||||
|         end | ||||
|         local last_page = ceil(player_data.table_count / rows_per_page) | ||||
|             local player_data = get_player_data(player) | ||||
|             if not player_data or not player_data.table_count then | ||||
|                 return | ||||
|             end | ||||
|             local last_page = ceil(player_data.table_count / rows_per_page) | ||||
|  | ||||
|         player_data.current_page = last_page | ||||
|         local data = {player = player, frame = element} | ||||
|         create_admin_panel(data) | ||||
|     end | ||||
| ) | ||||
|             player_data.current_page = last_page | ||||
|             local data = { player = player, frame = element } | ||||
|             create_admin_panel(data) | ||||
|         end | ||||
|     ) | ||||
|  | ||||
| local function clear_validation_action(player_name, action) | ||||
|     local admin_button_validation = AntiGrief.get('admin_button_validation') | ||||
| @@ -96,22 +96,22 @@ end | ||||
|  | ||||
| local clear_validation_token = | ||||
|     Token.register( | ||||
|     function(event) | ||||
|         local action = event.action | ||||
|         if not action then | ||||
|             return | ||||
|         end | ||||
|         local player_name = event.player_name | ||||
|         if not player_name then | ||||
|             return | ||||
|         end | ||||
|         function (event) | ||||
|             local action = event.action | ||||
|             if not action then | ||||
|                 return | ||||
|             end | ||||
|             local player_name = event.player_name | ||||
|             if not player_name then | ||||
|                 return | ||||
|             end | ||||
|  | ||||
|         local admin_button_validation = AntiGrief.get('admin_button_validation') | ||||
|         if admin_button_validation and admin_button_validation[action] then | ||||
|             admin_button_validation[action][player_name] = nil | ||||
|             local admin_button_validation = AntiGrief.get('admin_button_validation') | ||||
|             if admin_button_validation and admin_button_validation[action] then | ||||
|                 admin_button_validation[action][player_name] = nil | ||||
|             end | ||||
|         end | ||||
|     end | ||||
| ) | ||||
|     ) | ||||
|  | ||||
| local function validate_action(player, action) | ||||
|     local admin_button_validation = AntiGrief.get('admin_button_validation') | ||||
| @@ -121,7 +121,7 @@ local function validate_action(player, action) | ||||
|  | ||||
|     if not admin_button_validation[action][player.name] then | ||||
|         admin_button_validation[action][player.name] = true | ||||
|         Task.set_timeout_in_ticks(100, clear_validation_token, {player_name = player.name, action = action}) | ||||
|         Task.set_timeout_in_ticks(200, clear_validation_token, { player_name = player.name, action = action }) | ||||
|         player.print('Please run this again if you are certain that you want to run this action[' .. action .. '].', Color.warning) | ||||
|         return true | ||||
|     end | ||||
| @@ -131,7 +131,7 @@ end | ||||
| local function admin_only_message(str) | ||||
|     for _, player in pairs(game.connected_players) do | ||||
|         if player.admin == true then | ||||
|             player.print('Admins-only-message: ' .. str, {r = 0.88, g = 0.88, b = 0.88}) | ||||
|             player.print('Admins-only-message: ' .. str, { r = 0.88, g = 0.88, b = 0.88 }) | ||||
|         end | ||||
|     end | ||||
| end | ||||
| @@ -142,7 +142,7 @@ local function jail(player, source_player) | ||||
|     end | ||||
|  | ||||
|     if player.name == source_player.name then | ||||
|         player.print("You can't select yourself!", {r = 1, g = 0.5, b = 0.1}) | ||||
|         player.print("You can't select yourself!", { r = 1, g = 0.5, b = 0.1 }) | ||||
|         clear_validation_action(source_player.name, 'jail') | ||||
|         return | ||||
|     end | ||||
| @@ -150,13 +150,34 @@ local function jail(player, source_player) | ||||
|     clear_validation_action(source_player.name, 'jail') | ||||
| end | ||||
|  | ||||
| local function clear_biters(player) | ||||
|     if validate_action(player, 'clear_biters') then | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     local surface = player.surface | ||||
|     local count = 0 | ||||
|     for c in surface.get_chunks() do | ||||
|         for _, entity in pairs(surface.find_entities_filtered({ area = { { c.x * 32, c.y * 32 }, { c.x * 32 + 32, c.y * 32 + 32 } }, type = "unit" })) do | ||||
|             if entity and entity.valid then | ||||
|                 entity.destroy() | ||||
|                 count = count + 1 | ||||
|             end | ||||
|         end | ||||
|     end | ||||
|  | ||||
|     player.print('Cleared: ' .. count .. ' biters.', Color.warning) | ||||
|  | ||||
|     clear_validation_action(player.name, 'clear_biters') | ||||
| end | ||||
|  | ||||
| local function mute(player, source_player) | ||||
|     if validate_action(source_player, 'mute') then | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     if player.name == source_player.name then | ||||
|         player.print("You can't select yourself!", {r = 1, g = 0.5, b = 0.1}) | ||||
|         player.print("You can't select yourself!", { r = 1, g = 0.5, b = 0.1 }) | ||||
|         clear_validation_action(source_player.name, 'mute') | ||||
|         return | ||||
|     end | ||||
| @@ -164,7 +185,7 @@ local function mute(player, source_player) | ||||
|     local muted = Jailed.mute_player(player) | ||||
|     local muted_str = muted and 'muted' or 'unmuted' | ||||
|     clear_validation_action(source_player.name, 'jail') | ||||
|     game.print(player.name .. ' was ' .. muted_str .. ' by player ' .. source_player.name .. '!', {r = 1, g = 0.5, b = 0.1}) | ||||
|     game.print(player.name .. ' was ' .. muted_str .. ' by player ' .. source_player.name .. '!', { r = 1, g = 0.5, b = 0.1 }) | ||||
| end | ||||
|  | ||||
| local function free(player, source_player) | ||||
| @@ -173,7 +194,7 @@ local function free(player, source_player) | ||||
|     end | ||||
|  | ||||
|     if player.name == source_player.name then | ||||
|         player.print("You can't select yourself!", {r = 1, g = 0.5, b = 0.1}) | ||||
|         player.print("You can't select yourself!", { r = 1, g = 0.5, b = 0.1 }) | ||||
|         clear_validation_action(source_player.name, 'free') | ||||
|         return | ||||
|     end | ||||
| @@ -193,19 +214,19 @@ local function bring_player(player, source_player) | ||||
|     end | ||||
|  | ||||
|     if player.name == source_player.name then | ||||
|         player.print("You can't select yourself!", {r = 1, g = 0.5, b = 0.1}) | ||||
|         player.print("You can't select yourself!", { r = 1, g = 0.5, b = 0.1 }) | ||||
|         clear_validation_action(source_player.name, 'bring_player') | ||||
|         return | ||||
|     end | ||||
|     if player.driving == true then | ||||
|         source_player.print('Target player is in a vehicle, teleport not available.', {r = 0.88, g = 0.88, b = 0.88}) | ||||
|         source_player.print('Target player is in a vehicle, teleport not available.', { r = 0.88, g = 0.88, b = 0.88 }) | ||||
|         clear_validation_action(source_player.name, 'bring_player') | ||||
|         return | ||||
|     end | ||||
|     local pos = source_player.surface.find_non_colliding_position('character', source_player.position, 50, 1) | ||||
|     if pos then | ||||
|         player.teleport(pos, source_player.surface) | ||||
|         game.print(player.name .. ' has been teleported to ' .. source_player.name .. '. ' .. bring_player_messages[math.random(1, #bring_player_messages)], {r = 0.98, g = 0.66, b = 0.22}) | ||||
|         game.print(player.name .. ' has been teleported to ' .. source_player.name .. '. ' .. bring_player_messages[math.random(1, #bring_player_messages)], { r = 0.98, g = 0.66, b = 0.22 }) | ||||
|         clear_validation_action(source_player.name, 'bring_player') | ||||
|     end | ||||
| end | ||||
| @@ -220,29 +241,29 @@ local function go_to_player(player, source_player) | ||||
|     end | ||||
|  | ||||
|     if player.name == source_player.name then | ||||
|         player.print("You can't select yourself!", {r = 1, g = 0.5, b = 0.1}) | ||||
|         player.print("You can't select yourself!", { r = 1, g = 0.5, b = 0.1 }) | ||||
|         clear_validation_action(source_player.name, 'go_to_player') | ||||
|         return | ||||
|     end | ||||
|     local pos = player.surface.find_non_colliding_position('character', player.position, 50, 1) | ||||
|     if pos then | ||||
|         source_player.teleport(pos, player.surface) | ||||
|         game.print(source_player.name .. ' is visiting ' .. player.name .. '. ' .. go_to_player_messages[math.random(1, #go_to_player_messages)], {r = 0.98, g = 0.66, b = 0.22}) | ||||
|         game.print(source_player.name .. ' is visiting ' .. player.name .. '. ' .. go_to_player_messages[math.random(1, #go_to_player_messages)], { r = 0.98, g = 0.66, b = 0.22 }) | ||||
|         clear_validation_action(source_player.name, 'go_to_player') | ||||
|     end | ||||
| end | ||||
|  | ||||
| local function spank(player, source_player) | ||||
|     if player.name == source_player.name then | ||||
|         return player.print("You can't select yourself!", {r = 1, g = 0.5, b = 0.1}) | ||||
|         return player.print("You can't select yourself!", { r = 1, g = 0.5, b = 0.1 }) | ||||
|     end | ||||
|     if player.character then | ||||
|         if player.character.health > 1 then | ||||
|             player.character.damage(1, 'player') | ||||
|         end | ||||
|         player.character.health = player.character.health - 5 | ||||
|         player.surface.create_entity({name = 'water-splash', position = player.position}) | ||||
|         game.print(source_player.name .. ' spanked ' .. player.name, {r = 0.98, g = 0.66, b = 0.22}) | ||||
|         player.surface.create_entity({ name = 'water-splash', position = player.position }) | ||||
|         game.print(source_player.name .. ' spanked ' .. player.name, { r = 0.98, g = 0.66, b = 0.22 }) | ||||
|     end | ||||
| end | ||||
|  | ||||
| @@ -252,15 +273,15 @@ local damage_messages = { | ||||
| } | ||||
| local function damage(player, source_player) | ||||
|     if player.name == source_player.name then | ||||
|         return player.print("You can't select yourself!", {r = 1, g = 0.5, b = 0.1}) | ||||
|         return player.print("You can't select yourself!", { r = 1, g = 0.5, b = 0.1 }) | ||||
|     end | ||||
|     if player.character then | ||||
|         if player.character.health > 1 then | ||||
|             player.character.damage(1, 'player') | ||||
|         end | ||||
|         player.character.health = player.character.health - 125 | ||||
|         player.surface.create_entity({name = 'big-explosion', position = player.position}) | ||||
|         game.print(player.name .. damage_messages[math.random(1, #damage_messages)] .. source_player.name, {r = 0.98, g = 0.66, b = 0.22}) | ||||
|         player.surface.create_entity({ name = 'big-explosion', position = player.position }) | ||||
|         game.print(player.name .. damage_messages[math.random(1, #damage_messages)] .. source_player.name, { r = 0.98, g = 0.66, b = 0.22 }) | ||||
|     end | ||||
| end | ||||
|  | ||||
| @@ -276,13 +297,13 @@ local function kill(player, source_player) | ||||
|         return | ||||
|     end | ||||
|     if player.name == source_player.name then | ||||
|         player.print("You can't select yourself!", {r = 1, g = 0.5, b = 0.1}) | ||||
|         player.print("You can't select yourself!", { r = 1, g = 0.5, b = 0.1 }) | ||||
|         clear_validation_action(source_player.name, 'kill') | ||||
|         return | ||||
|     end | ||||
|     if player.character then | ||||
|         player.character.die('player') | ||||
|         game.print(player.name .. kill_messages[math.random(1, #kill_messages)], {r = 0.98, g = 0.66, b = 0.22}) | ||||
|         game.print(player.name .. kill_messages[math.random(1, #kill_messages)], { r = 0.98, g = 0.66, b = 0.22 }) | ||||
|         admin_only_message(source_player.name .. ' killed ' .. player.name) | ||||
|         clear_validation_action(source_player.name, 'kill') | ||||
|     end | ||||
| @@ -298,7 +319,7 @@ local function enemy(player, source_player) | ||||
|     end | ||||
|  | ||||
|     if player.name == source_player.name then | ||||
|         player.print("You can't select yourself!", {r = 1, g = 0.5, b = 0.1}) | ||||
|         player.print("You can't select yourself!", { r = 1, g = 0.5, b = 0.1 }) | ||||
|         clear_validation_action(source_player.name, 'enemy') | ||||
|         return | ||||
|     end | ||||
| @@ -306,7 +327,7 @@ local function enemy(player, source_player) | ||||
|         game.create_force('enemy_players') | ||||
|     end | ||||
|     player.force = game.forces.enemy_players | ||||
|     game.print(player.name .. ' is now an enemy! ' .. enemy_messages[math.random(1, #enemy_messages)], {r = 0.95, g = 0.15, b = 0.15}) | ||||
|     game.print(player.name .. ' is now an enemy! ' .. enemy_messages[math.random(1, #enemy_messages)], { r = 0.95, g = 0.15, b = 0.15 }) | ||||
|     admin_only_message(source_player.name .. ' has turned ' .. player.name .. ' into an enemy') | ||||
|     clear_validation_action(source_player.name, 'enemy') | ||||
| end | ||||
| @@ -317,12 +338,12 @@ local function ally(player, source_player) | ||||
|     end | ||||
|  | ||||
|     if player.name == source_player.name then | ||||
|         player.print("You can't select yourself!", {r = 1, g = 0.5, b = 0.1}) | ||||
|         player.print("You can't select yourself!", { r = 1, g = 0.5, b = 0.1 }) | ||||
|         clear_validation_action(source_player.name, 'ally') | ||||
|         return | ||||
|     end | ||||
|     player.force = game.forces.player | ||||
|     game.print(player.name .. ' is our ally again!', {r = 0.98, g = 0.66, b = 0.22}) | ||||
|     game.print(player.name .. ' is our ally again!', { r = 0.98, g = 0.66, b = 0.22 }) | ||||
|     admin_only_message(source_player.name .. ' made ' .. player.name .. ' our ally') | ||||
|     clear_validation_action(source_player.name, 'ally') | ||||
| end | ||||
| @@ -334,10 +355,10 @@ local function turn_off_global_speakers(player) | ||||
|  | ||||
|     local counter = 0 | ||||
|     for _, surface in pairs(game.surfaces) do | ||||
|         local speakers = surface.find_entities_filtered({name = 'programmable-speaker'}) | ||||
|         local speakers = surface.find_entities_filtered({ name = 'programmable-speaker' }) | ||||
|         for _, speaker in pairs(speakers) do | ||||
|             if speaker.parameters.playback_globally == true then | ||||
|                 speaker.surface.create_entity({name = 'massive-explosion', position = speaker.position}) | ||||
|                 speaker.surface.create_entity({ name = 'massive-explosion', position = speaker.position }) | ||||
|                 speaker.destroy() | ||||
|                 counter = counter + 1 | ||||
|             end | ||||
| @@ -347,9 +368,9 @@ local function turn_off_global_speakers(player) | ||||
|         return | ||||
|     end | ||||
|     if counter == 1 then | ||||
|         game.print(player.name .. ' has nuked ' .. counter .. ' global speaker.', {r = 0.98, g = 0.66, b = 0.22}) | ||||
|         game.print(player.name .. ' has nuked ' .. counter .. ' global speaker.', { r = 0.98, g = 0.66, b = 0.22 }) | ||||
|     else | ||||
|         game.print(player.name .. ' has nuked ' .. counter .. ' global speakers.', {r = 0.98, g = 0.66, b = 0.22}) | ||||
|         game.print(player.name .. ' has nuked ' .. counter .. ' global speakers.', { r = 0.98, g = 0.66, b = 0.22 }) | ||||
|     end | ||||
|     clear_validation_action(player.name, 'turn_off_global_speakers') | ||||
| end | ||||
| @@ -361,7 +382,7 @@ local function delete_all_blueprints(player) | ||||
|  | ||||
|     local counter = 0 | ||||
|     for _, surface in pairs(game.surfaces) do | ||||
|         for _, ghost in pairs(surface.find_entities_filtered({type = {'entity-ghost', 'tile-ghost'}})) do | ||||
|         for _, ghost in pairs(surface.find_entities_filtered({ type = { 'entity-ghost', 'tile-ghost' } })) do | ||||
|             ghost.destroy() | ||||
|             counter = counter + 1 | ||||
|         end | ||||
| @@ -371,9 +392,9 @@ local function delete_all_blueprints(player) | ||||
|         return | ||||
|     end | ||||
|     if counter == 1 then | ||||
|         game.print(counter .. ' blueprint has been cleared!', {r = 0.98, g = 0.66, b = 0.22}) | ||||
|         game.print(counter .. ' blueprint has been cleared!', { r = 0.98, g = 0.66, b = 0.22 }) | ||||
|     else | ||||
|         game.print(counter .. ' blueprints have been cleared!', {r = 0.98, g = 0.66, b = 0.22}) | ||||
|         game.print(counter .. ' blueprints have been cleared!', { r = 0.98, g = 0.66, b = 0.22 }) | ||||
|     end | ||||
|     local server_name = Server.get_server_name() or 'CommandHandler' | ||||
|     Discord.send_notification_raw(server_name, player.name .. ' cleared all the blueprints on the map.') | ||||
| @@ -389,7 +410,7 @@ local function pause_game_tick(player) | ||||
|     local paused = game.tick_paused | ||||
|     local paused_str = paused and 'unpaused' or 'paused' | ||||
|     game.tick_paused = not paused | ||||
|     game.print('Game has been ' .. paused_str .. ' by ' .. player.name, {r = 0.98, g = 0.66, b = 0.22}) | ||||
|     game.print('Game has been ' .. paused_str .. ' by ' .. player.name, { r = 0.98, g = 0.66, b = 0.22 }) | ||||
|     local server_name = Server.get_server_name() or 'CommandHandler' | ||||
|     Discord.send_notification_raw(server_name, player.name .. ' ' .. paused_str .. ' the game.') | ||||
|     clear_validation_action(player.name, 'pause_game_tick') | ||||
| @@ -411,7 +432,7 @@ local function clear_items_on_ground(player) | ||||
|     end | ||||
|  | ||||
|     local i = 0 | ||||
|     for _, entity in pairs(player.surface.find_entities_filtered {type = 'item-entity', name = 'item-on-ground'}) do | ||||
|     for _, entity in pairs(player.surface.find_entities_filtered { type = 'item-entity', name = 'item-on-ground' }) do | ||||
|         if entity and entity.valid then | ||||
|             entity.destroy() | ||||
|             i = i + 1 | ||||
| @@ -429,7 +450,7 @@ local function create_mini_camera_gui(player, caption, position, surface) | ||||
|     if player.gui.center['mini_camera'] then | ||||
|         player.gui.center['mini_camera'].destroy() | ||||
|     end | ||||
|     local frame = player.gui.center.add({type = 'frame', name = 'mini_camera', caption = caption}) | ||||
|     local frame = player.gui.center.add({ type = 'frame', name = 'mini_camera', caption = caption }) | ||||
|     surface = tonumber(surface) | ||||
|     surface = game.surfaces[surface] | ||||
|     if not surface or not surface.valid then | ||||
| @@ -438,14 +459,14 @@ local function create_mini_camera_gui(player, caption, position, surface) | ||||
|  | ||||
|     local camera = | ||||
|         frame.add( | ||||
|         { | ||||
|             type = 'camera', | ||||
|             name = 'mini_cam_element', | ||||
|             position = position, | ||||
|             zoom = 0.6, | ||||
|             surface_index = surface.index | ||||
|         } | ||||
|     ) | ||||
|             { | ||||
|                 type = 'camera', | ||||
|                 name = 'mini_cam_element', | ||||
|                 position = position, | ||||
|                 zoom = 0.6, | ||||
|                 surface_index = surface.index | ||||
|             } | ||||
|         ) | ||||
|     camera.style.minimal_width = 640 | ||||
|     camera.style.minimal_height = 480 | ||||
| end | ||||
| @@ -555,14 +576,14 @@ local function draw_events(player_data) | ||||
|     else | ||||
|         scroll_pane = | ||||
|             frame.add( | ||||
|             { | ||||
|                 type = 'scroll-pane', | ||||
|                 name = 'datalog', | ||||
|                 direction = 'vertical', | ||||
|                 horizontal_scroll_policy = 'never', | ||||
|                 vertical_scroll_policy = 'auto' | ||||
|             } | ||||
|         ) | ||||
|                 { | ||||
|                     type = 'scroll-pane', | ||||
|                     name = 'datalog', | ||||
|                     direction = 'vertical', | ||||
|                     horizontal_scroll_policy = 'never', | ||||
|                     vertical_scroll_policy = 'auto' | ||||
|                 } | ||||
|             ) | ||||
|         scroll_pane.style.maximal_height = 200 | ||||
|         scroll_pane.style.minimal_width = 790 | ||||
|     end | ||||
| @@ -570,7 +591,7 @@ local function draw_events(player_data) | ||||
|     search_text_locally( | ||||
|         history, | ||||
|         player_data, | ||||
|         function(history_label, tooltip) | ||||
|         function (history_label, tooltip) | ||||
|             if not history_label then | ||||
|                 return | ||||
|             end | ||||
| @@ -624,7 +645,7 @@ local function text_changed(event) | ||||
|         player_data.search_text = nil | ||||
|         local last_page = ceil(player_data.table_count / rows_per_page) | ||||
|         player_data.current_page = last_page | ||||
|         local data = {player = player, frame = frame} | ||||
|         local data = { player = player, frame = frame } | ||||
|         create_admin_panel(data) | ||||
|         return | ||||
|     end | ||||
| @@ -650,36 +671,36 @@ local function create_pagination_buttons(player_data, frame, table_count) | ||||
|  | ||||
|     local button_flow = | ||||
|         frame.add { | ||||
|         type = 'flow', | ||||
|         direction = 'horizontal' | ||||
|     } | ||||
|             type = 'flow', | ||||
|             direction = 'horizontal' | ||||
|         } | ||||
|     local prev_button = | ||||
|         button_flow.add { | ||||
|         type = 'button', | ||||
|         name = prev_button_name, | ||||
|         caption = '◀️', | ||||
|         style = 'back_button' | ||||
|     } | ||||
|             type = 'button', | ||||
|             name = prev_button_name, | ||||
|             caption = '◀️', | ||||
|             style = 'back_button' | ||||
|         } | ||||
|     prev_button.style.font = 'default-bold' | ||||
|     prev_button.style.minimal_width = 32 | ||||
|     prev_button.tooltip = 'Previous page\nHolding [color=yellow]shift[/color] while pressing LMB/RMB will jump to the first page.' | ||||
|  | ||||
|     local count_label = | ||||
|         button_flow.add { | ||||
|         type = 'label', | ||||
|         name = count_label_name, | ||||
|         caption = current_page .. '/' .. last_page | ||||
|     } | ||||
|             type = 'label', | ||||
|             name = count_label_name, | ||||
|             caption = current_page .. '/' .. last_page | ||||
|         } | ||||
|     count_label.style.font = 'default-bold' | ||||
|     player_data.count_label = count_label | ||||
|  | ||||
|     local next_button = | ||||
|         button_flow.add { | ||||
|         type = 'button', | ||||
|         name = next_button_name, | ||||
|         caption = '▶️', | ||||
|         style = 'forward_button' | ||||
|     } | ||||
|             type = 'button', | ||||
|             name = next_button_name, | ||||
|             caption = '▶️', | ||||
|             style = 'forward_button' | ||||
|         } | ||||
|     next_button.style.font = 'default-bold' | ||||
|     next_button.style.minimal_width = 32 | ||||
|     next_button.tooltip = 'Next page\nHolding [color=yellow]shift[/color] while pressing LMB/RMB will jump to the last page.' | ||||
| @@ -687,7 +708,7 @@ local function create_pagination_buttons(player_data, frame, table_count) | ||||
|     player_data.table_count = table_count | ||||
| end | ||||
|  | ||||
| create_admin_panel = function(data) | ||||
| create_admin_panel = function (data) | ||||
|     local player = data.player | ||||
|     local frame = data.frame | ||||
|     local antigrief = AntiGrief.get() | ||||
| @@ -726,14 +747,14 @@ create_admin_panel = function(data) | ||||
|         checkbox_caption = 'Currently showing: all players that have played on this server.' | ||||
|     end | ||||
|  | ||||
|     frame.add({type = 'checkbox', name = listable_players_name, caption = checkbox_caption, state = checkbox_state or false}) | ||||
|     frame.add({ type = 'checkbox', name = listable_players_name, caption = checkbox_caption, state = checkbox_state or false }) | ||||
|  | ||||
|     local drop_down = frame.add({type = 'drop-down', name = 'admin_player_select', items = player_names, selected_index = selected_index}) | ||||
|     local drop_down = frame.add({ type = 'drop-down', name = 'admin_player_select', items = player_names, selected_index = selected_index }) | ||||
|     drop_down.style.minimal_width = 326 | ||||
|     drop_down.style.right_padding = 12 | ||||
|     drop_down.style.left_padding = 12 | ||||
|  | ||||
|     local t = frame.add({type = 'table', column_count = 4}) | ||||
|     local t = frame.add({ type = 'table', column_count = 4 }) | ||||
|     local buttons = { | ||||
|         t.add( | ||||
|             { | ||||
| @@ -751,7 +772,7 @@ create_admin_panel = function(data) | ||||
|                 tooltip = 'Jails and mutes the player, they will no longer be able to chat.' | ||||
|             } | ||||
|         ), | ||||
|         t.add({type = 'button', caption = 'Free', name = 'free', tooltip = 'Frees the player from jail.'}), | ||||
|         t.add({ type = 'button', caption = 'Free', name = 'free', tooltip = 'Frees the player from jail.' }), | ||||
|         t.add( | ||||
|             { | ||||
|                 type = 'button', | ||||
| @@ -800,7 +821,7 @@ create_admin_panel = function(data) | ||||
|                 tooltip = 'Damages the selected player with greater damage.\nCan not kill the player.' | ||||
|             } | ||||
|         ), | ||||
|         t.add({type = 'button', caption = 'Kill', name = 'kill', tooltip = 'Kills the selected player instantly.'}) | ||||
|         t.add({ type = 'button', caption = 'Kill', name = 'kill', tooltip = 'Kills the selected player instantly.' }) | ||||
|     } | ||||
|     for _, button in pairs(buttons) do | ||||
|         button.style.font = 'default-bold' | ||||
| @@ -808,12 +829,12 @@ create_admin_panel = function(data) | ||||
|         button.style.minimal_width = 106 | ||||
|     end | ||||
|  | ||||
|     local line = frame.add {type = 'line'} | ||||
|     local line = frame.add { type = 'line' } | ||||
|     line.style.top_margin = 8 | ||||
|     line.style.bottom_margin = 8 | ||||
|  | ||||
|     frame.add({type = 'label', caption = 'Global Actions:'}) | ||||
|     local actionTable = frame.add({type = 'table', column_count = 4}) | ||||
|     frame.add({ type = 'label', caption = 'Global Actions:' }) | ||||
|     local actionTable = frame.add({ type = 'table', column_count = 4 }) | ||||
|     local bottomButtons = { | ||||
|         actionTable.add( | ||||
|             { | ||||
| @@ -854,6 +875,14 @@ create_admin_panel = function(data) | ||||
|                 name = 'clear_items_on_ground', | ||||
|                 tooltip = 'Clears all items on the ground.\nThis might lag the game!' | ||||
|             } | ||||
|         ), | ||||
|         actionTable.add( | ||||
|             { | ||||
|                 type = 'button', | ||||
|                 caption = 'Remove biters', | ||||
|                 name = 'clear_biters', | ||||
|                 tooltip = 'Clears out all biters (friendly and enemy).\nThis might lag the game!' | ||||
|             } | ||||
|         ) | ||||
|         ---	t.add({type = "button", caption = "Cancel all deconstruction orders", name = "remove_all_deconstruction_orders"}) | ||||
|     } | ||||
| @@ -862,7 +891,7 @@ create_admin_panel = function(data) | ||||
|         button.style.minimal_width = 80 | ||||
|     end | ||||
|  | ||||
|     local bottomLine = frame.add {type = 'line'} | ||||
|     local bottomLine = frame.add { type = 'line' } | ||||
|     bottomLine.style.top_margin = 8 | ||||
|     bottomLine.style.bottom_margin = 8 | ||||
|  | ||||
| @@ -905,34 +934,34 @@ create_admin_panel = function(data) | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     local search_table = frame.add({type = 'table', column_count = 3}) | ||||
|     search_table.add({type = 'label', caption = 'Search: '}) | ||||
|     local search_text = search_table.add({type = 'textfield'}) | ||||
|     local search_table = frame.add({ type = 'table', column_count = 3 }) | ||||
|     search_table.add({ type = 'label', caption = 'Search: ' }) | ||||
|     local search_text = search_table.add({ type = 'textfield' }) | ||||
|     search_text.text = player_data.search_text or '' | ||||
|     search_text.style.width = 140 | ||||
|     local btn = | ||||
|         search_table.add { | ||||
|         type = 'sprite-button', | ||||
|         tooltip = '[color=blue]Info![/color]\nSearching does not filter the amount of pages shown.\nThis is a limitation in the Factorio engine.\nIterating over the whole table would lag the game.\nSo when searching, you will still see the same amount of pages.\nAnd the results will be "janky".', | ||||
|         sprite = 'utility/questionmark' | ||||
|     } | ||||
|             type = 'sprite-button', | ||||
|             tooltip = '[color=blue]Info![/color]\nSearching does not filter the amount of pages shown.\nThis is a limitation in the Factorio engine.\nIterating over the whole table would lag the game.\nSo when searching, you will still see the same amount of pages.\nAnd the results will be "janky".', | ||||
|             sprite = 'utility/questionmark' | ||||
|         } | ||||
|     btn.style.height = 20 | ||||
|     btn.style.width = 20 | ||||
|     btn.enabled = false | ||||
|     btn.focus() | ||||
|  | ||||
|     local bottomLine2 = frame.add({type = 'label', caption = '----------------------------------------------'}) | ||||
|     local bottomLine2 = frame.add({ type = 'label', caption = '----------------------------------------------' }) | ||||
|     bottomLine2.style.font = 'default-listbox' | ||||
|     bottomLine2.style.font_color = {r = 0.98, g = 0.66, b = 0.22} | ||||
|     bottomLine2.style.font_color = { r = 0.98, g = 0.66, b = 0.22 } | ||||
|  | ||||
|     local selected_index_2 = 1 | ||||
|     if player_data and player_data.selected_history_index then | ||||
|         selected_index_2 = player_data.selected_history_index | ||||
|     end | ||||
|  | ||||
|     local pagination_table = frame.add({type = 'table', column_count = 2, name = 'pagination_table'}) | ||||
|     local pagination_table = frame.add({ type = 'table', column_count = 2, name = 'pagination_table' }) | ||||
|  | ||||
|     local drop_down_2 = pagination_table.add({type = 'drop-down', name = 'admin_history_select', items = histories, selected_index = selected_index_2}) | ||||
|     local drop_down_2 = pagination_table.add({ type = 'drop-down', name = 'admin_history_select', items = histories, selected_index = selected_index_2 }) | ||||
|     drop_down_2.style.right_padding = 12 | ||||
|     drop_down_2.style.left_padding = 12 | ||||
|  | ||||
| @@ -979,7 +1008,8 @@ local admin_global_functions = { | ||||
|     ['delete_all_blueprints'] = delete_all_blueprints, | ||||
|     ['pause_game_tick'] = pause_game_tick, | ||||
|     ['save_game'] = save_game, | ||||
|     ['clear_items_on_ground'] = clear_items_on_ground | ||||
|     ['clear_items_on_ground'] = clear_items_on_ground, | ||||
|     ['clear_biters'] = clear_biters | ||||
| } | ||||
|  | ||||
| local function get_surface_from_string(str) | ||||
| @@ -1047,7 +1077,7 @@ local function get_position_from_string(str) | ||||
|     local y = string.sub(str, y_pos, y_pos + a1) | ||||
|     x = tonumber(x) | ||||
|     y = tonumber(y) | ||||
|     local position = {x = x, y = y} | ||||
|     local position = { x = x, y = y } | ||||
|     return position | ||||
| end | ||||
|  | ||||
| @@ -1085,7 +1115,7 @@ local function on_gui_click(event) | ||||
|             return | ||||
|         end | ||||
|         if target_player_name == 'Select Player' then | ||||
|             player.print('[AdminGui] No target player selected.', {r = 0.88, g = 0.88, b = 0.88}) | ||||
|             player.print('[AdminGui] No target player selected.', { r = 0.88, g = 0.88, b = 0.88 }) | ||||
|             return | ||||
|         end | ||||
|         local target_player = game.players[target_player_name] | ||||
| @@ -1148,7 +1178,7 @@ local function on_gui_selection_state_changed(event) | ||||
|             return | ||||
|         end | ||||
|  | ||||
|         Task.set_timeout_in_ticks(5, delayed_last_page_token, {player_index = player.index, element = frame}) | ||||
|         Task.set_timeout_in_ticks(5, delayed_last_page_token, { player_index = player.index, element = frame }) | ||||
|  | ||||
|         player_data.current_page = 1 | ||||
|  | ||||
| @@ -1156,7 +1186,7 @@ local function on_gui_selection_state_changed(event) | ||||
|         if is_spamming then | ||||
|             return | ||||
|         end | ||||
|         local data = {player = player, frame = frame} | ||||
|         local data = { player = player, frame = frame } | ||||
|         create_admin_panel(data) | ||||
|     end | ||||
|     if name == 'admin_player_select' then | ||||
| @@ -1176,16 +1206,16 @@ local function on_gui_selection_state_changed(event) | ||||
|             return | ||||
|         end | ||||
|  | ||||
|         local data = {player = player, frame = frame} | ||||
|         local data = { player = player, frame = frame } | ||||
|         create_admin_panel(data) | ||||
|     end | ||||
| end | ||||
|  | ||||
| Gui.add_tab_to_gui({name = module_name, caption = 'Admin', id = create_admin_panel_token, admin = true}) | ||||
| Gui.add_tab_to_gui({ name = module_name, caption = 'Admin', id = create_admin_panel_token, admin = true }) | ||||
|  | ||||
| Gui.on_click( | ||||
|     module_name, | ||||
|     function(event) | ||||
|     function (event) | ||||
|         local player = event.player | ||||
|         Gui.reload_active_tab(player) | ||||
|     end | ||||
| @@ -1248,7 +1278,7 @@ end | ||||
|  | ||||
| Gui.on_click( | ||||
|     prev_button_name, | ||||
|     function(event) | ||||
|     function (event) | ||||
|         local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Prev button click') | ||||
|         if is_spamming then | ||||
|             return | ||||
| @@ -1289,14 +1319,14 @@ Gui.on_click( | ||||
|  | ||||
|         player_data.current_page = current_page | ||||
|  | ||||
|         local data = {player = player, frame = element.parent.parent.parent} | ||||
|         local data = { player = player, frame = element.parent.parent.parent } | ||||
|         create_admin_panel(data) | ||||
|     end | ||||
| ) | ||||
|  | ||||
| Gui.on_click( | ||||
|     next_button_name, | ||||
|     function(event) | ||||
|     function (event) | ||||
|         local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Next button click') | ||||
|         if is_spamming then | ||||
|             return | ||||
| @@ -1342,14 +1372,14 @@ Gui.on_click( | ||||
|  | ||||
|         player_data.current_page = current_page | ||||
|  | ||||
|         local data = {player = player, frame = element.parent.parent.parent} | ||||
|         local data = { player = player, frame = element.parent.parent.parent } | ||||
|         create_admin_panel(data) | ||||
|     end | ||||
| ) | ||||
|  | ||||
| Gui.on_checked_state_changed( | ||||
|     listable_players_name, | ||||
|     function(event) | ||||
|     function (event) | ||||
|         local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Listable players click') | ||||
|         if is_spamming then | ||||
|             return | ||||
| @@ -1369,7 +1399,7 @@ Gui.on_checked_state_changed( | ||||
|  | ||||
|         player_data.show_all_players = element.state | ||||
|  | ||||
|         local data = {player = player, frame = element.parent} | ||||
|         local data = { player = player, frame = element.parent } | ||||
|         create_admin_panel(data) | ||||
|     end | ||||
| ) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user