From 4748c237ec385563f216a0ac4c7664ca833d7306 Mon Sep 17 00:00:00 2001
From: Gerkiz <fs@nvfs.se>
Date: Mon, 11 Nov 2024 08:57:27 +0100
Subject: [PATCH] Push bug fixes and tweaks

---
 maps/mountain_fortress_v3/entities.lua        |  80 ++++++-----
 maps/mountain_fortress_v3/ic/functions.lua    | 135 +++++++++---------
 maps/mountain_fortress_v3/ic/gui.lua          |  36 ++---
 maps/mountain_fortress_v3/ic/minimap.lua      |   8 +-
 maps/mountain_fortress_v3/icw/functions.lua   |  10 +-
 maps/mountain_fortress_v3/locomotive.lua      |  67 +++++----
 .../locomotive/market.lua                     |   2 +-
 maps/mountain_fortress_v3/main.lua            |   5 +-
 maps/mountain_fortress_v3/stateful/gui.lua    |   8 ++
 maps/mountain_fortress_v3/surface.lua         |   2 +-
 utils/gui/admin.lua                           |   2 +-
 11 files changed, 188 insertions(+), 167 deletions(-)

diff --git a/maps/mountain_fortress_v3/entities.lua b/maps/mountain_fortress_v3/entities.lua
index 68a35c7ab..f3d959758 100644
--- a/maps/mountain_fortress_v3/entities.lua
+++ b/maps/mountain_fortress_v3/entities.lua
@@ -248,12 +248,9 @@ local function set_train_final_health(final_damage_amount, repair)
         end
     end
 
-    if locomotive_health <= 0 or locomotive.health <= 5 then
+    if locomotive_health <= 0 then
         Public.set('locomotive_position', locomotive.position)
-        locomotive.health = 1
-        Public.set('game_lost', true)
-        Public.set_stateful('current_streak', 0)
-        Public.loco_died()
+        Public.game_is_over()
     end
 
     if locomotive_health <= 0 then
@@ -1179,26 +1176,32 @@ local function show_mvps(player)
         wave_defense_text.style.font = 'default-bold'
         wave_defense_text.style.font_color = { r = 0.33, g = 0.66, b = 0.9 }
 
-        local fighter_label = t.add({ type = 'label', caption = 'Fighter >> ' })
-        fighter_label.style.font = 'default-listbox'
-        fighter_label.style.font_color = { r = 0.22, g = 0.77, b = 0.44 }
-        local fighter_label_text = t.add({ type = 'label', caption = mvp.killscore.name .. ' with a killing score of ' .. mvp.killscore.score .. ' kills!' })
-        fighter_label_text.style.font = 'default-bold'
-        fighter_label_text.style.font_color = { r = 0.33, g = 0.66, b = 0.9 }
-
-        local builder_label = t.add({ type = 'label', caption = 'Builder >> ' })
-        builder_label.style.font = 'default-listbox'
-        builder_label.style.font_color = { r = 0.22, g = 0.77, b = 0.44 }
-        local builder_label_text = t.add({ type = 'label', caption = mvp.built_entities.name .. ' built ' .. mvp.built_entities.score .. ' things!' })
-        builder_label_text.style.font = 'default-bold'
-        builder_label_text.style.font_color = { r = 0.33, g = 0.66, b = 0.9 }
-
-        local miners_label = t.add({ type = 'label', caption = 'Miners >> ' })
-        miners_label.style.font = 'default-listbox'
-        miners_label.style.font_color = { r = 0.22, g = 0.77, b = 0.44 }
-        local miners_label_text = t.add({ type = 'label', caption = mvp.mined_entities.name .. ' mined a total of  ' .. mvp.mined_entities.score .. ' entities!' })
-        miners_label_text.style.font = 'default-bold'
-        miners_label_text.style.font_color = { r = 0.33, g = 0.66, b = 0.9 }
+        if mvp.killscore then
+            local fighter_label = t.add({ type = 'label', caption = 'Fighter >> ' })
+            fighter_label.style.font = 'default-listbox'
+            fighter_label.style.font_color = { r = 0.22, g = 0.77, b = 0.44 }
+            local fighter_label_text = t.add({ type = 'label', caption = mvp.killscore.name .. ' with a killing score of ' .. mvp.killscore.score .. ' kills!' })
+            fighter_label_text.style.font = 'default-bold'
+            fighter_label_text.style.font_color = { r = 0.33, g = 0.66, b = 0.9 }
+        end
+
+        if mvp.built_entities then
+            local builder_label = t.add({ type = 'label', caption = 'Builder >> ' })
+            builder_label.style.font = 'default-listbox'
+            builder_label.style.font_color = { r = 0.22, g = 0.77, b = 0.44 }
+            local builder_label_text = t.add({ type = 'label', caption = mvp.built_entities.name .. ' built ' .. mvp.built_entities.score .. ' things!' })
+            builder_label_text.style.font = 'default-bold'
+            builder_label_text.style.font_color = { r = 0.33, g = 0.66, b = 0.9 }
+        end
+
+        if mvp.mined_entities then
+            local miners_label = t.add({ type = 'label', caption = 'Miners >> ' })
+            miners_label.style.font = 'default-listbox'
+            miners_label.style.font_color = { r = 0.22, g = 0.77, b = 0.44 }
+            local miners_label_text = t.add({ type = 'label', caption = mvp.mined_entities.name .. ' mined a total of  ' .. mvp.mined_entities.score .. ' entities!' })
+            miners_label_text.style.font = 'default-bold'
+            miners_label_text.style.font_color = { r = 0.33, g = 0.66, b = 0.9 }
+        end
 
         local sent_to_discord = Public.get('sent_to_discord')
         local server_name_matches = Server.check_server_name(Public.discord_name)
@@ -1212,23 +1215,30 @@ local function show_mvps(player)
                     text1 = 'Highest Wave:',
                     text2 = wave_defense_table.wave_number,
                     inline = 'false'
-                },
-                field2 = {
+                }
+            }
+            if mvp.killscore then
+                message.field2 = {
                     text1 = 'MVP Fighter:',
                     text2 = mvp.killscore.name .. ' with a killing score of ' .. mvp.killscore.score .. ' kills!',
                     inline = 'false'
-                },
-                field3 = {
+                }
+            end
+            if mvp.built_entities then
+                message.field3 = {
                     text1 = 'MVP Builder:',
                     text2 = mvp.built_entities.name .. ' built ' .. mvp.built_entities.score .. ' things!',
                     inline = 'false'
-                },
-                field4 = {
+                }
+            end
+            if mvp.mined_entities then
+                message.field4 = {
                     text1 = 'MVP Miners:',
                     text2 = mvp.mined_entities.name .. ' mined a total of ' .. mvp.mined_entities.score .. ' entities!',
                     inline = 'false'
                 }
-            }
+            end
+
             Server.to_discord_embed_parsed(message)
             local wave = WD.get_wave()
             local threat = WD.get('threat')
@@ -1309,6 +1319,12 @@ local function show_mvps(player)
     end
 end
 
+function Public.game_is_over()
+    Public.set('game_lost', true)
+    Public.set_stateful('current_streak', 0)
+    Public.loco_died()
+end
+
 function Public.unstuck_player(index)
     if not index then
         return
diff --git a/maps/mountain_fortress_v3/ic/functions.lua b/maps/mountain_fortress_v3/ic/functions.lua
index 2f41e7838..72508a8e4 100644
--- a/maps/mountain_fortress_v3/ic/functions.lua
+++ b/maps/mountain_fortress_v3/ic/functions.lua
@@ -94,8 +94,8 @@ local enable_car_to_be_mined =
 
 local function get_trusted_system(player)
     local trust_system = IC.get('trust_system')
-    if not trust_system[player.index] then
-        trust_system[player.index] = {
+    if not trust_system[player.name] then
+        trust_system[player.name] = {
             players = {
                 [player.name] = { trusted = true, drive = true }
             },
@@ -105,12 +105,12 @@ local function get_trusted_system(player)
         }
     end
 
-    return trust_system[player.index]
+    return trust_system[player.name]
 end
 
 local function does_player_table_exist(player)
     local trust_system = IC.get('trust_system')
-    if not trust_system[player.index] then
+    if not trust_system[player.name] then
         return false
     else
         return true
@@ -128,8 +128,8 @@ local function render_owner_text(renders, player, entity, new_owner)
         b = player.color.b * 0.6 + 0.25,
         a = 1
     }
-    if renders[player.index] and renders[player.index].valid then
-        renders[player.index].destroy()
+    if renders[player.name] and renders[player.name].valid then
+        renders[player.name].destroy()
     end
 
     local ce_name = entity.name
@@ -139,7 +139,7 @@ local function render_owner_text(renders, player, entity, new_owner)
     end
 
     if new_owner then
-        renders[new_owner.index] =
+        renders[new_owner.name] =
             rendering.draw_text {
                 text = '## - ' .. new_owner.name .. "'s " .. ce_name .. ' - ##',
                 surface = entity.surface,
@@ -151,7 +151,7 @@ local function render_owner_text(renders, player, entity, new_owner)
                 scale_with_zoom = false
             }
     else
-        renders[player.index] =
+        renders[player.name] =
             rendering.draw_text {
                 text = '## - ' .. player.name .. "'s " .. ce_name .. ' - ##',
                 surface = entity.surface,
@@ -187,7 +187,7 @@ end
 local function get_owner_car_object(player)
     local cars = IC.get('cars')
     for _, car in pairs(cars) do
-        if car.owner == player.index then
+        if car.owner == player.name then
             return car
         end
     end
@@ -211,7 +211,7 @@ end
 
 local function get_owner_car_surface(cars, player, target)
     for _, car in pairs(cars) do
-        if car.owner == player.index then
+        if car.owner == player.name then
             local surface_index = car.surface
             local surface = game.surfaces[surface_index]
             if validate_entity(surface) then
@@ -244,9 +244,9 @@ end
 local function get_player_entity(player)
     local cars = IC.get('cars')
     for _, car in pairs(cars) do
-        if car.owner == player.index and type(car.entity) == 'boolean' then
+        if car.owner == player.name and type(car.entity) == 'boolean' then
             return car, true
-        elseif car.owner == player.index then
+        elseif car.owner == player.name then
             return car, false
         end
     end
@@ -256,12 +256,12 @@ end
 local function get_owner_car_name(player)
     local cars = IC.get('cars')
     local saved_surfaces = IC.get('saved_surfaces')
-    local index = saved_surfaces[player.index]
+    local index = saved_surfaces[player.name]
     for _, car in pairs(cars) do
         if not index then
             return false
         end
-        if car.owner == player.index then
+        if car.owner == player.name then
             return car.name
         end
     end
@@ -370,12 +370,12 @@ local function upgrade_surface(player, entity)
     local cars = IC.get('cars')
     local doors = IC.get('doors')
     local surfaces = IC.get('surfaces')
-    local index = saved_surfaces[player.index]
+    local index = saved_surfaces[player.name]
     if not index then
         return
     end
 
-    if saved_surfaces[player.index] then
+    if saved_surfaces[player.name] then
         local car = get_owner_car_object(player)
         if ce.name == 'spidertron' then
             car.name = 'spidertron'
@@ -390,7 +390,7 @@ local function upgrade_surface(player, entity)
         replace_surface_entity(cars, ce, index)
         kill_doors(car)
         Public.create_car_room(car)
-        saved_surfaces[player.index] = nil
+        saved_surfaces[player.name] = nil
         return true
     end
     return false
@@ -404,7 +404,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.name] = { saved_entity = entity.unit_number, name = entity.name }
 end
 
 local function kick_players_out_of_vehicles(car)
@@ -440,7 +440,7 @@ local function kick_players_from_surface(car, owner_id)
         if validate_entity(main_surface) then
             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
+                    if owner_id and owner_id == e.player.name then
                         goto continue
                     end
                     local p = main_surface.find_non_colliding_position('character', game.forces.player.get_spawn_position(main_surface), 3, 0)
@@ -456,7 +456,7 @@ local function kick_players_from_surface(car, owner_id)
 
     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
+            if owner_id and owner_id == e.player.name then
                 goto continue
             end
             local p = car.entity.surface.find_non_colliding_position('character', car.entity.position, 128, 0.5)
@@ -484,7 +484,7 @@ local function kick_non_trusted_players_from_surface(car)
     Core.iter_connected_players(
         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.physical_surface.index == surface_index and player.index ~= car.owner and not is_trusted then
+            if player.physical_surface.index == surface_index and player.name ~= car.owner and not is_trusted then
                 if position then
                     local new_position = main_surface.find_non_colliding_position('character', position, 3, 0)
                     if new_position then
@@ -541,12 +541,12 @@ local function restore_surface(player, entity)
     local doors = IC.get('doors')
     local renders = IC.get('renders')
     local surfaces = IC.get('surfaces')
-    local index = saved_surfaces[player.index]
+    local index = saved_surfaces[player.name]
     if not index then
         return
     end
 
-    if saved_surfaces[player.index] then
+    if saved_surfaces[player.name] then
         local success, msg = get_saved_entity(ce, index)
         if not success then
             player.print(module_tag .. msg, { color = Color.warning })
@@ -556,7 +556,7 @@ local function restore_surface(player, entity)
         replace_doors(doors, ce, index)
         replace_surface(surfaces, ce, index)
         replace_surface_entity(cars, ce, index)
-        saved_surfaces[player.index] = nil
+        saved_surfaces[player.name] = nil
         render_owner_text(renders, player, ce)
         return true
     end
@@ -719,8 +719,8 @@ end
 
 local function get_player_data(player)
     local players = IC.get('players')
-    local player_data = players[player.index]
-    if players[player.index] then
+    local player_data = players[player.name]
+    if players[player.name] then
         return player_data
     end
     local fallback = WPT.get('active_surface_index') --[[@as string|integer]]
@@ -728,23 +728,23 @@ local function get_player_data(player)
         fallback = 1
     end
 
-    players[player.index] = {
+    players[player.name] = {
         surface = 1,
         fallback_surface = tonumber(fallback),
         notified = false
     }
-    return players[player.index]
+    return players[player.name]
 end
 
 local function get_persistent_player_data(player)
     local players = IC.get('players_persistent')
-    local player_data = players[player.index]
-    if players[player.index] then
+    local player_data = players[player.name]
+    if players[player.name] then
         return player_data
     end
 
-    players[player.index] = {}
-    return players[player.index]
+    players[player.name] = {}
+    return players[player.name]
 end
 
 local remove_car =
@@ -803,9 +803,9 @@ function Public.save_car(event)
 
     if car.owner == player.name then
         save_surface(entity, player)
-        if not players[player.index].notified then
+        if not players[player.name].notified then
             player.print(module_tag .. player.name .. ', the ' .. car.name .. ' surface has been saved.', { color = Color.success })
-            players[player.index].notified = true
+            players[player.name].notified = true
         end
     else
         local p = game.get_player(car.owner)
@@ -859,15 +859,15 @@ function Public.remove_surface(player)
     kick_players_from_surface(car)
 
     local trust_system = IC.get('trust_system')
-    if trust_system[player.index] then
-        trust_system[player.index] = nil
+    if trust_system[player.name] then
+        trust_system[player.name] = nil
     end
 
     local renders = IC.get('renders')
 
-    if renders[player.index] then
-        renders[player.index].destroy()
-        renders[player.index] = nil
+    if renders[player.name] then
+        renders[player.name].destroy()
+        renders[player.name] = nil
     end
 
     local player_gui_data = IC.get('player_gui_data')
@@ -876,13 +876,13 @@ function Public.remove_surface(player)
     end
 
     local players = IC.get('players')
-    if players[player.index] then
-        players[player.index] = nil
+    if players[player.name] then
+        players[player.name] = nil
     end
 
     local misc_settings = IC.get('misc_settings')
-    if misc_settings[player.index] then
-        misc_settings[player.index] = nil
+    if misc_settings[player.name] then
+        misc_settings[player.name] = nil
     end
 
     kill_doors(car)
@@ -937,8 +937,8 @@ function Public.kill_car(entity)
     if owner then
         owner = game.get_player(owner)
         if owner and owner.valid then
-            if trust_system[owner.index] then
-                trust_system[owner.index] = nil
+            if trust_system[owner.name] then
+                trust_system[owner.name] = nil
             end
         end
     end
@@ -949,9 +949,9 @@ function Public.kill_car(entity)
         return
     end
 
-    if renders[owner.index] and renders[owner.index].valid then
-        renders[owner.index].destroy()
-        renders[owner.index] = nil
+    if renders[owner.name] and renders[owner.name].valid then
+        renders[owner.name].destroy()
+        renders[owner.name] = nil
     end
 
     local gps_tag = '[gps=' .. entity_position.x .. ',' .. entity_position.y .. ',' .. entity_surface.name .. ']'
@@ -966,13 +966,13 @@ function Public.kill_car(entity)
     end
 
     local players = IC.get('players')
-    if players[owner.index] then
-        players[owner.index] = nil
+    if players[owner.name] then
+        players[owner.name] = nil
     end
 
     local misc_settings = IC.get('misc_settings')
-    if misc_settings[owner.index] then
-        misc_settings[owner.index] = nil
+    if misc_settings[owner.name] then
+        misc_settings[owner.name] = nil
     end
 
     local surface_index = car.surface
@@ -1042,8 +1042,8 @@ function Public.kill_car_but_save_surface(entity)
     if owner then
         owner = game.get_player(owner)
         if owner and owner.valid then
-            if trust_system[owner.index] then
-                trust_system[owner.index] = nil
+            if trust_system[owner.name] then
+                trust_system[owner.name] = nil
             end
         end
     end
@@ -1054,9 +1054,9 @@ function Public.kill_car_but_save_surface(entity)
 
     local renders = IC.get('renders')
 
-    if renders[owner.index] and renders[owner.index].valid then
-        renders[owner.index].destroy()
-        renders[owner.index] = nil
+    if renders[owner.name] and renders[owner.name].valid then
+        renders[owner.name].destroy()
+        renders[owner.name] = nil
     end
 
     local player_gui_data = IC.get('player_gui_data')
@@ -1065,13 +1065,13 @@ function Public.kill_car_but_save_surface(entity)
     end
 
     local players = IC.get('players')
-    if players[owner.index] then
-        players[owner.index] = nil
+    if players[owner.name] then
+        players[owner.name] = nil
     end
 
     local misc_settings = IC.get('misc_settings')
-    if misc_settings[owner.index] then
-        misc_settings[owner.index] = nil
+    if misc_settings[owner.name] then
+        misc_settings[owner.name] = nil
     end
 
     if not surfaces_deleted_by_button[owner.name] then
@@ -1104,7 +1104,7 @@ function Public.validate_owner(player, entity)
                 end
             end
             if p then
-                if car.owner ~= player.index and player.driving then
+                if car.owner ~= player.name and player.driving then
                     player.driving = false
                     if not player.admin then
                         if list.notify_on_driver_change == 'left' then
@@ -1240,7 +1240,6 @@ function Public.create_car_room(car)
     e2.destructible = false
     e2.minable = false
     car.transfer_entities = { e1, e2 }
-    return
 end
 
 function Public.create_car(event)
@@ -1408,7 +1407,7 @@ function Public.use_door_with_entity(player, door)
 
     local owner = game.players[car.owner]
     local list = get_trusted_system(owner)
-    if owner and owner.valid and owner.index ~= player.index and player.connected then
+    if owner and owner.valid and owner.name ~= player.name and player.connected then
         if list.allow_anyone == 'right' then
             if ((not list.players[player.name]) or (list.players[player.name] and not list.players[player.name].trusted)) and not player.admin then
                 if list.players[player.name] and list.players[player.name].drive then
@@ -1438,7 +1437,7 @@ function Public.use_door_with_entity(player, door)
     if validate_entity(car.entity) and car.entity.surface.name == player.physical_surface.name then
         local surface_index = car.surface
         local surface = game.surfaces[surface_index]
-        if validate_entity(car.entity) and car.owner == player.index then
+        if validate_entity(car.entity) and car.owner == player.name then
             Event.raise(
                 IC.events.used_car_door,
                 {
@@ -1469,7 +1468,7 @@ function Public.use_door_with_entity(player, door)
         end
         player_data.surface = surface.index
     else
-        if validate_entity(car.entity) and car.owner == player.index then
+        if validate_entity(car.entity) and car.owner == player.name then
             Event.raise(
                 IC.events.used_car_door,
                 {
@@ -1512,7 +1511,7 @@ end
 function Public.on_player_died(player)
     local cars = IC.get('cars')
     for _, car in pairs(cars) do
-        if car.owner == player.index then
+        if car.owner == player.name then
             local entity = car.entity
             if entity and entity.valid then
                 entity.minable = false
@@ -1524,7 +1523,7 @@ end
 function Public.on_player_respawned(player)
     local cars = IC.get('cars')
     for _, car in pairs(cars) do
-        if car.owner == player.index then
+        if car.owner == player.name then
             local entity = car.entity
             if entity and entity.valid then
                 entity.minable = true
diff --git a/maps/mountain_fortress_v3/ic/gui.lua b/maps/mountain_fortress_v3/ic/gui.lua
index c862b4df2..0c321bd30 100644
--- a/maps/mountain_fortress_v3/ic/gui.lua
+++ b/maps/mountain_fortress_v3/ic/gui.lua
@@ -83,20 +83,20 @@ end
 
 local function transfer_player_table(player, new_player)
     local trust_system = ICT.get('trust_system')
-    if not trust_system[player.index] then
+    if not trust_system[player.name] then
         return false
     end
 
-    if player.index == new_player.index then
+    if player.name == new_player.name then
         return false
     end
 
-    if not trust_system[new_player.index] then
-        trust_system[new_player.index] = trust_system[player.index]
+    if not trust_system[new_player.name] then
+        trust_system[new_player.name] = trust_system[player.name]
         local name = new_player.name
 
-        if not trust_system[new_player.index].players[name] then
-            increment(trust_system[new_player.index].players, name)
+        if not trust_system[new_player.name].players[name] then
+            increment(trust_system[new_player.name].players, name)
         end
 
         local renders = ICT.get('renders')
@@ -104,7 +104,7 @@ local function transfer_player_table(player, new_player)
         if not car then
             return error('Car was not found! This should not happen!', 2)
         end
-        car.owner = new_player.index
+        car.owner = new_player.name
 
         car.entity.minable = true
 
@@ -113,12 +113,12 @@ local function transfer_player_table(player, new_player)
         remove_toolbar(player)
         add_toolbar(new_player)
 
-        trust_system[player.index] = nil
+        trust_system[player.name] = nil
     else
         return false
     end
 
-    return trust_system[new_player.index]
+    return trust_system[new_player.name]
 end
 
 local function remove_main_frame(main_frame)
@@ -888,13 +888,13 @@ Gui.on_click(
 local clear_misc_settings =
     Task.register(
         function (data)
-            local player_index = data.player_index
+            local player_name = data.player_name
             local misc_settings = ICT.get('misc_settings')
-            if not misc_settings[player_index] then
+            if not misc_settings[player_name] then
                 return
             end
 
-            misc_settings[player_index] = nil
+            misc_settings[player_name] = nil
         end
     )
 
@@ -919,22 +919,22 @@ Gui.on_click(
         end
 
         local misc_settings = ICT.get('misc_settings')
-        if not misc_settings[player.index] then
-            misc_settings[player.index] = {
+        if not misc_settings[player.name] then
+            misc_settings[player.name] = {
                 first_warning = true
             }
 
             player.print('[IC] ARE YOU SURE? This action is irreversible!', { color = Color.warning })
-            Task.set_timeout_in_ticks(600, clear_misc_settings, { player_index = player.index })
+            Task.set_timeout_in_ticks(600, clear_misc_settings, { player_name = player.name })
             return
         end
 
-        if not misc_settings[player.index].final_warning then
-            misc_settings[player.index].final_warning = true
+        if not misc_settings[player.name].final_warning then
+            misc_settings[player.name].final_warning = true
             player.print(
                 '[IC] WARNING! WARNING WARNING! Pressing the save button ONE MORE TIME will DELETE your surface. This action is irreversible!',
                 Color.red)
-            Task.set_timeout_in_ticks(600, clear_misc_settings, { player_index = player.index })
+            Task.set_timeout_in_ticks(600, clear_misc_settings, { player_name = player.name })
             return
         end
 
diff --git a/maps/mountain_fortress_v3/ic/minimap.lua b/maps/mountain_fortress_v3/ic/minimap.lua
index 511d2627c..47d39c534 100644
--- a/maps/mountain_fortress_v3/ic/minimap.lua
+++ b/maps/mountain_fortress_v3/ic/minimap.lua
@@ -95,18 +95,18 @@ end
 
 local function get_player_data(player)
     local minimap = ICT.get('minimap')
-    local player_data = minimap[player.index]
-    if minimap[player.index] then
+    local player_data = minimap[player.name]
+    if minimap[player.name] then
         return player_data
     end
 
-    minimap[player.index] = {
+    minimap[player.name] = {
         zoom = 0.30,
         map_size = 360,
         auto = true,
         state = 'left'
     }
-    return minimap[player.index]
+    return minimap[player.name]
 end
 
 function Public.toggle_auto(player)
diff --git a/maps/mountain_fortress_v3/icw/functions.lua b/maps/mountain_fortress_v3/icw/functions.lua
index 014a24a38..8d104bcc6 100644
--- a/maps/mountain_fortress_v3/icw/functions.lua
+++ b/maps/mountain_fortress_v3/icw/functions.lua
@@ -972,12 +972,7 @@ function Public.reconstruct_all_trains(icw)
         if not validate_entity(wagon.entity) then
             icw.wagons[unit_number] = nil
             Public.request_reconstruction(icw)
-            return
-        end
-
-        local locomotive = WPT.get('locomotive')
-        if not (locomotive and locomotive.valid) then
-            return
+            goto cont
         end
 
         if not wagon.surface then
@@ -986,7 +981,8 @@ function Public.reconstruct_all_trains(icw)
         end
         local carriages = wagon.entity.train.carriages
 
-        Public.construct_train(icw, locomotive, carriages)
+        Public.construct_train(icw, wagon.entity, carriages)
+        ::cont::
     end
     delete_empty_surfaces(icw)
     return true
diff --git a/maps/mountain_fortress_v3/locomotive.lua b/maps/mountain_fortress_v3/locomotive.lua
index 2d95990a3..d83513938 100644
--- a/maps/mountain_fortress_v3/locomotive.lua
+++ b/maps/mountain_fortress_v3/locomotive.lua
@@ -441,50 +441,55 @@ local function get_driver_action(entity)
     end
 end
 
-local function set_locomotive_health()
-    local locomotive_health = Public.get('locomotive_health')
-    local locomotive_max_health = Public.get('locomotive_max_health')
-    local locomotive = Public.get('locomotive')
 
-    if not locomotive or not locomotive.valid then
-        return
+local function check_health(locomotive_health, locomotive_max_health)
+    local m = locomotive_health / locomotive_max_health
+    if locomotive_health > locomotive_max_health then
+        Public.set('locomotive_health', locomotive_max_health)
     end
 
-    local function check_health()
-        local m = locomotive_health / locomotive_max_health
-        if locomotive_health > locomotive_max_health then
-            Public.set('locomotive_health', locomotive_max_health)
-        end
-        local health_text = Public.get('health_text')
-        if health_text and health_text.valid then
-            health_text.text = 'HP: ' .. round(locomotive_health) .. ' / ' .. round(locomotive_max_health)
-        end
-
 
 
+    local health_text = Public.get('health_text')
+    if health_text and health_text.valid then
+        health_text.text = 'HP: ' .. round(locomotive_health) .. ' / ' .. round(locomotive_max_health)
+    end
 
-        local carriages = Public.get('carriages')
-        if carriages then
-            for i = 1, #carriages do
-                local entity = carriages[i]
-                if not (entity and entity.valid) then
-                    return
-                end
-                get_driver_action(entity)
-                if entity.type == 'locomotive' then
-                    entity.health = entity.max_health * m
-                else
-                    entity.health = entity.max_health * m
-                end
+    local carriages = Public.get('carriages')
+    if carriages then
+        for i = 1, #carriages do
+            local entity = carriages[i]
+            if not (entity and entity.valid) then
+                return
+            end
+            get_driver_action(entity)
+            if entity.type == 'locomotive' then
+                entity.health = entity.max_health * m
+            else
+                entity.health = entity.max_health * m
             end
         end
     end
+end
 
-    if not (locomotive and locomotive.valid) then
+local function set_locomotive_health()
+    local locomotive_health = Public.get('locomotive_health')
+    local locomotive_max_health = Public.get('locomotive_max_health')
+    local locomotive = Public.get('locomotive')
+
+    if not locomotive or not locomotive.valid then
+        Public.game_is_over()
         return
     end
 
-    check_health()
+    Public.set('locomotive_position', locomotive.position)
+
+    if locomotive_health <= 0 then
+        Public.game_is_over()
+        Public.set('locomotive_health', 0)
+    end
+
+    check_health(locomotive_health, locomotive_max_health)
 end
 
 local function validate_index()
diff --git a/maps/mountain_fortress_v3/locomotive/market.lua b/maps/mountain_fortress_v3/locomotive/market.lua
index bfa83b95b..903b11e63 100644
--- a/maps/mountain_fortress_v3/locomotive/market.lua
+++ b/maps/mountain_fortress_v3/locomotive/market.lua
@@ -473,7 +473,7 @@ local function get_items(player)
         static = false
     }
 
-    if not Public.is_modded then
+    if Public.is_modded then
         main_market_items['raw-fish'] = {
             stack = 1,
             value = 'coin',
diff --git a/maps/mountain_fortress_v3/main.lua b/maps/mountain_fortress_v3/main.lua
index 40f63cf4b..9a85c3746 100644
--- a/maps/mountain_fortress_v3/main.lua
+++ b/maps/mountain_fortress_v3/main.lua
@@ -107,7 +107,7 @@ local is_locomotive_valid = function ()
     if game.ticks_played < 1000 then return end
     if not locomotive or not locomotive.valid then
         Public.set('game_lost', true)
-        Public.loco_died()
+        Public.game_is_over()
     end
 end
 
@@ -615,11 +615,8 @@ function Public.reset_map(current_task)
 
     Misc.reset()
 
-
     LinkedChests.reset()
 
-
-
     BottomFrame.reset()
     Public.reset_buried_biters()
     Poll.reset()
diff --git a/maps/mountain_fortress_v3/stateful/gui.lua b/maps/mountain_fortress_v3/stateful/gui.lua
index ab80c7828..efa718e8c 100644
--- a/maps/mountain_fortress_v3/stateful/gui.lua
+++ b/maps/mountain_fortress_v3/stateful/gui.lua
@@ -1164,6 +1164,14 @@ local function update_raw()
                     Public.set_stateful_settings('reversed', true)
                 end
 
+                game.forces.enemy.set_friend('player', true)
+                game.forces.aggressors.set_friend('player', true)
+                game.forces.aggressors_frenzy.set_friend('player', true)
+
+                game.forces.player.set_friend('enemy', true)
+                game.forces.player.set_friend('aggressors', true)
+                game.forces.player.set_friend('aggressors_frenzy', true)
+
                 collection.game_won_notified = true
                 refresh_boss_frame()
                 play_game_won()
diff --git a/maps/mountain_fortress_v3/surface.lua b/maps/mountain_fortress_v3/surface.lua
index 77966e109..11d3d91ab 100644
--- a/maps/mountain_fortress_v3/surface.lua
+++ b/maps/mountain_fortress_v3/surface.lua
@@ -90,7 +90,7 @@ function Public.create_landing_surface()
         height = 64,
         width = 256,
         peaceful_mode = false,
-        seed = 1337,
+        seed = 42,
         starting_area = 'very-low',
         starting_points = { { x = 0, y = 0 } },
         terrain_segmentation = 'normal',
diff --git a/utils/gui/admin.lua b/utils/gui/admin.lua
index b33ccf8ac..bc5b53227 100644
--- a/utils/gui/admin.lua
+++ b/utils/gui/admin.lua
@@ -158,7 +158,7 @@ local function clear_biters(player)
     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
+        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", "turret", "unit-spawner" } })) do
             if entity and entity.valid then
                 entity.destroy()
                 count = count + 1