From ba9397c954ecd6723d0218acccdbb15c518df290 Mon Sep 17 00:00:00 2001
From: Marko Lindqvist <cazfi74@gmail.com>
Date: Sun, 26 Oct 2025 10:09:06 +0200
Subject: [PATCH 22/22] savegame: Respect savegame item order when loading
 action sub targets

See RM #1611

Signed-off-by: Marko Lindqvist <cazfi74@gmail.com>
---
 server/savegame/savegame3.c | 57 ++++++++++++++++++++++++-------------
 1 file changed, 37 insertions(+), 20 deletions(-)

diff --git a/server/savegame/savegame3.c b/server/savegame/savegame3.c
index 7a3b2efba9..9188ddc317 100644
--- a/server/savegame/savegame3.c
+++ b/server/savegame/savegame3.c
@@ -2219,8 +2219,8 @@ static void sg_load_game(struct loaddata *loading)
                      "Undefined value '%c' within 'game.global_advances'.",
                      str[i]);
       if (str[i] == '1') {
-        struct advance *padvance =
-            advance_by_rule_name(loading->technology.order[i]);
+        struct advance *padvance
+          = advance_by_rule_name(loading->technology.order[i]);
 
         if (padvance != NULL) {
           game.info.global_advances[advance_number(padvance)] = TRUE;
@@ -3738,9 +3738,10 @@ static void sg_load_players_basic(struct loaddata *loading)
                    "'players.destroyed_wonders'.", str[k]);
 
     if (str[k] == '1') {
-      struct impr_type *pimprove =
-          improvement_by_rule_name(loading->improvement.order[k]);
-      if (pimprove) {
+      struct impr_type *pimprove
+        = improvement_by_rule_name(loading->improvement.order[k]);
+
+      if (pimprove != NULL) {
         game.info.great_wonder_owners[improvement_index(pimprove)]
           = WONDER_DESTROYED;
       }
@@ -6528,27 +6529,42 @@ static bool sg_load_player_unit(struct loaddata *loading,
           switch (action_id_get_sub_target_kind(order->action)) {
           case ASTK_BUILDING:
             /* Sub target is a building. */
-            if (!improvement_by_number(order_sub_tgt)) {
+            if (order_sub_tgt < 0
+                || order_sub_tgt >= loading->improvement.size
+                || !loading->improvement.order[order_sub_tgt]) {
               /* Sub target is invalid. */
               log_sg("Cannot find building %d for %s to %s",
                      order_sub_tgt, unit_rule_name(punit),
                      action_id_name_translation(order->action));
               order->sub_target = B_LAST;
             } else {
-              order->sub_target = order_sub_tgt;
+              struct impr_type *pimprove
+                = improvement_by_rule_name(loading->improvement.order[order_sub_tgt]);
+
+              if (pimprove != NULL) {
+                order->sub_target = improvement_index(pimprove);
+              }
             }
             break;
           case ASTK_TECH:
             /* Sub target is a technology. */
-            if (order_sub_tgt == A_NONE
-                || (!valid_advance_by_number(order_sub_tgt)
-                    && order_sub_tgt != A_FUTURE)) {
-              /* Target tech is invalid. */
-              log_sg("Cannot find tech %d for %s to steal",
-                     order_sub_tgt, unit_rule_name(punit));
-              order->sub_target = A_NONE;
-            } else {
-              order->sub_target = order_sub_tgt;
+            {
+              bool failure = order_sub_tgt < 0
+                || order_sub_tgt >= loading->technology.size
+                || !loading->technology.order[order_sub_tgt];
+              struct advance *padvance = NULL;
+
+              if (!failure) {
+                padvance = advance_by_rule_name(loading->technology.order[order_sub_tgt]);
+              }
+              if (padvance == NULL) {
+                /* Target tech is invalid. */
+                log_sg("Cannot find tech %d for %s to steal",
+                       order_sub_tgt, unit_rule_name(punit));
+                order->sub_target = A_NONE;
+              } else {
+                order->sub_target = advance_index(padvance);
+              }
             }
             break;
           case ASTK_EXTRA:
@@ -6587,7 +6603,8 @@ static bool sg_load_player_unit(struct loaddata *loading,
         if (order->order == ORDER_ACTIVITY || action_wants_extra) {
           enum unit_activity act;
 
-          if (order_sub_tgt < 0 || order_sub_tgt >= loading->extra.size) {
+          if (order_sub_tgt < 0 || order_sub_tgt >= loading->extra.size
+              || !loading->extra.order[order_sub_tgt]) {
             if (order_sub_tgt != EXTRA_NONE) {
               log_sg("Cannot find extra %d for %s to build",
                      order_sub_tgt, unit_rule_name(punit));
@@ -6595,7 +6612,7 @@ static bool sg_load_player_unit(struct loaddata *loading,
 
             order->sub_target = EXTRA_NONE;
           } else {
-            order->sub_target = order_sub_tgt;
+            order->sub_target = extra_index(loading->extra.order[order_sub_tgt]);
           }
 
           /* An action or an activity may require an extra target. */
@@ -7709,8 +7726,8 @@ static void sg_load_researches(struct loaddata *loading)
                      str[j], i);
 
       if (str[j] == '1') {
-        struct advance *padvance =
-            advance_by_rule_name(loading->technology.order[j]);
+        struct advance *padvance
+          = advance_by_rule_name(loading->technology.order[j]);
 
         if (padvance) {
           research_invention_set(presearch, advance_number(padvance),
-- 
2.51.0

