From d04a390ca08452a6dbfd26e2615fc27fba700f6f Mon Sep 17 00:00:00 2001
From: Marko Lindqvist <cazfi74@gmail.com>
Date: Wed, 12 Mar 2025 01:05:22 +0200
Subject: [PATCH 54/54] Pass trigger action to
 can_unit_do_activity_targeted_at()

See RM #344

Signed-off-by: Marko Lindqvist <cazfi74@gmail.com>
---
 ai/default/daiunit.c         | 12 ++++++-----
 client/control.h             |  8 ++++----
 common/unit.c                | 40 +++++++++++++++++++++---------------
 common/unit.h                |  5 ++++-
 common/unitlist.c            |  8 +++++---
 common/unitlist.h            |  4 +++-
 server/actiontools.c         |  3 ++-
 server/savegame/savecompat.c |  1 +
 server/unithand.c            | 33 ++++++++++++++++++++---------
 server/unittools.c           | 11 ++++++----
 server/unittools.h           |  3 ++-
 11 files changed, 82 insertions(+), 46 deletions(-)

diff --git a/ai/default/daiunit.c b/ai/default/daiunit.c
index fe7407737f..50e960fc76 100644
--- a/ai/default/daiunit.c
+++ b/ai/default/daiunit.c
@@ -859,11 +859,13 @@ static void dai_military_findjob(struct ai_type *ait, const struct civ_map *nmap
 
   /* Keep barbarians aggressive and primitive */
   if (is_barbarian(pplayer)) {
-    if (can_unit_do_activity(nmap, punit, ACTIVITY_PILLAGE)
-        && is_land_barbarian(pplayer)) {
-      /* Land barbarians pillage */
-      unit_activity_handling(punit, ACTIVITY_PILLAGE,
-                             activity_default_action(ACTIVITY_PILLAGE));
+    if (is_land_barbarian(pplayer)) {
+      enum gen_action action = activity_default_action(ACTIVITY_PILLAGE);
+
+      if (can_unit_do_activity(nmap, punit, ACTIVITY_PILLAGE, action)) {
+        /* Land barbarians pillage */
+        unit_activity_handling(punit, ACTIVITY_PILLAGE, action);
+      }
     }
     dai_unit_new_task(ait, punit, AIUNIT_NONE, NULL);
 
diff --git a/client/control.h b/client/control.h
index c049feda8b..b11504fb7d 100644
--- a/client/control.h
+++ b/client/control.h
@@ -39,13 +39,13 @@ enum quickselect_type {
 };
 
 #define can_unit_do_activity_client(_punit_, _act_) \
-  can_unit_do_activity(&(wld.map), _punit_, _act_)
+  can_unit_do_activity(&(wld.map), _punit_, _act_, activity_default_action(_act_))
 #define can_unit_do_activity_targeted_client(_punit_, _act_, _tgt_) \
-  can_unit_do_activity_targeted(&(wld.map), _punit_, _act_, _tgt_)
+  can_unit_do_activity_targeted(&(wld.map), _punit_, _act_, activity_default_action(_act_), _tgt_)
 #define can_units_do_activity_client(_punits_, _act_) \
-  can_units_do_activity(&(wld.map), _punits_, _act_)
+  can_units_do_activity(&(wld.map), _punits_, _act_, activity_default_action(_act_))
 #define can_units_do_activity_targeted_client(_punits_, _act_, _tgt_) \
-  can_units_do_activity_targeted(&(wld.map), _punits_, _act_, _tgt_)
+  can_units_do_activity_targeted(&(wld.map), _punits_, _act_, activity_default_action(_act_), _tgt_)
 
 void control_init(void);
 void control_free(void);
diff --git a/common/unit.c b/common/unit.c
index 35b427fa25..a8ded2251c 100644
--- a/common/unit.c
+++ b/common/unit.c
@@ -869,15 +869,18 @@ bool can_unit_continue_current_activity(const struct civ_map *nmap,
   struct extra_type *target = punit->activity_target;
   enum unit_activity current2 = 
               (current == ACTIVITY_FORTIFIED) ? ACTIVITY_FORTIFYING : current;
+  enum gen_action action = punit->action;
   bool result;
 
   punit->activity = ACTIVITY_IDLE;
   punit->activity_target = NULL;
 
-  result = can_unit_do_activity_targeted(nmap, punit, current2, target);
+  result = can_unit_do_activity_targeted(nmap, punit, current2, action,
+                                         target);
 
   punit->activity = current;
   punit->activity_target = target;
+  punit->action = action;
 
   return result;
 }
@@ -891,7 +894,8 @@ bool can_unit_continue_current_activity(const struct civ_map *nmap,
 **************************************************************************/
 bool can_unit_do_activity(const struct civ_map *nmap,
                           const struct unit *punit,
-                          enum unit_activity activity)
+                          enum unit_activity activity,
+                          enum gen_action action)
 {
   struct extra_type *target = NULL;
 
@@ -921,7 +925,8 @@ bool can_unit_do_activity(const struct civ_map *nmap,
     }
   }
 
-  return can_unit_do_activity_targeted(nmap, punit, activity, target);
+  return can_unit_do_activity_targeted(nmap, punit, activity, action,
+                                       target);
 }
 
 /**********************************************************************//**
@@ -931,10 +936,11 @@ bool can_unit_do_activity(const struct civ_map *nmap,
 bool can_unit_do_activity_targeted(const struct civ_map *nmap,
                                    const struct unit *punit,
                                    enum unit_activity activity,
+                                   enum gen_action action,
                                    struct extra_type *target)
 {
-  return can_unit_do_activity_targeted_at(nmap, punit, activity, target,
-					  unit_tile(punit));
+  return can_unit_do_activity_targeted_at(nmap, punit, activity, action,
+                                          target, unit_tile(punit));
 }
 
 /**********************************************************************//**
@@ -944,6 +950,7 @@ bool can_unit_do_activity_targeted(const struct civ_map *nmap,
 bool can_unit_do_activity_targeted_at(const struct civ_map *nmap,
                                       const struct unit *punit,
                                       enum unit_activity activity,
+                                      enum gen_action action,
                                       struct extra_type *target,
                                       const struct tile *ptile)
 {
@@ -995,42 +1002,42 @@ bool can_unit_do_activity_targeted_at(const struct civ_map *nmap,
     /* The call below doesn't support actor tile speculation. */
     fc_assert_msg(unit_tile(punit) == ptile,
                   "Please use action_speculate_unit_on_tile()");
-    return is_action_enabled_unit_on_tile(nmap, ACTION_CLEAN,
+    return is_action_enabled_unit_on_tile(nmap, action,
                                           punit, ptile, target);
 
   case ACTIVITY_MINE:
     /* The call below doesn't support actor tile speculation. */
     fc_assert_msg(unit_tile(punit) == ptile,
                   "Please use action_speculate_unit_on_tile()");
-    return is_action_enabled_unit_on_tile(nmap, ACTION_MINE, punit,
+    return is_action_enabled_unit_on_tile(nmap, action, punit,
                                           ptile, target);
 
   case ACTIVITY_PLANT:
     /* The call below doesn't support actor tile speculation. */
     fc_assert_msg(unit_tile(punit) == ptile,
                   "Please use action_speculate_unit_on_tile()");
-    return is_action_enabled_unit_on_tile(nmap, ACTION_PLANT,
+    return is_action_enabled_unit_on_tile(nmap, action,
                                           punit, ptile, NULL);
 
   case ACTIVITY_IRRIGATE:
     /* The call below doesn't support actor tile speculation. */
     fc_assert_msg(unit_tile(punit) == ptile,
                   "Please use action_speculate_unit_on_tile()");
-    return is_action_enabled_unit_on_tile(nmap, ACTION_IRRIGATE, punit,
+    return is_action_enabled_unit_on_tile(nmap, action, punit,
                                           ptile, target);
 
   case ACTIVITY_CULTIVATE:
     /* The call below doesn't support actor tile speculation. */
     fc_assert_msg(unit_tile(punit) == ptile,
                   "Please use action_speculate_unit_on_tile()");
-    return is_action_enabled_unit_on_tile(nmap, ACTION_CULTIVATE,
+    return is_action_enabled_unit_on_tile(nmap, action,
                                           punit, ptile, NULL);
 
   case ACTIVITY_FORTIFYING:
     /* The call below doesn't support actor tile speculation. */
     fc_assert_msg(unit_tile(punit) == ptile,
                   "Please use action_speculate_unit_on_self()");
-    return is_action_enabled_unit_on_self(nmap, ACTION_FORTIFY,
+    return is_action_enabled_unit_on_self(nmap, action,
                                           punit);
 
   case ACTIVITY_FORTIFIED:
@@ -1040,14 +1047,14 @@ bool can_unit_do_activity_targeted_at(const struct civ_map *nmap,
     /* The call below doesn't support actor tile speculation. */
     fc_assert_msg(unit_tile(punit) == ptile,
                   "Please use action_speculate_unit_on_tile()");
-    return is_action_enabled_unit_on_tile(nmap, ACTION_BASE,
+    return is_action_enabled_unit_on_tile(nmap, action,
                                           punit, ptile, target);
 
   case ACTIVITY_GEN_ROAD:
     /* The call below doesn't support actor tile speculation. */
     fc_assert_msg(unit_tile(punit) == ptile,
                   "Please use action_speculate_unit_on_tile()");
-    return is_action_enabled_unit_on_tile(nmap, ACTION_ROAD,
+    return is_action_enabled_unit_on_tile(nmap, action,
                                           punit, ptile, target);
 
   case ACTIVITY_SENTRY:
@@ -1062,7 +1069,7 @@ bool can_unit_do_activity_targeted_at(const struct civ_map *nmap,
     /* The call below doesn't support actor tile speculation. */
     fc_assert_msg(unit_tile(punit) == ptile,
                   "Please use action_speculate_unit_on_tile()");
-    RETURN_IS_ACTIVITY_ENABLED_UNIT_ON(action_by_number(ACTION_PILLAGE));
+    RETURN_IS_ACTIVITY_ENABLED_UNIT_ON(action_by_number(action));
 
   case ACTIVITY_EXPLORE:
     return (!unit_type_get(punit)->fuel && !is_losing_hp(punit));
@@ -1071,14 +1078,14 @@ bool can_unit_do_activity_targeted_at(const struct civ_map *nmap,
     /* The call below doesn't support actor tile speculation. */
     fc_assert_msg(unit_tile(punit) == ptile,
                   "Please use action_speculate_unit_on_tile()");
-    return is_action_enabled_unit_on_tile(nmap, ACTION_TRANSFORM_TERRAIN,
+    return is_action_enabled_unit_on_tile(nmap, action,
                                           punit, ptile, NULL);
 
   case ACTIVITY_CONVERT:
     /* The call below doesn't support actor tile speculation. */
     fc_assert_msg(unit_tile(punit) == ptile,
                   "Please use action_speculate_unit_on_self()");
-    return is_action_enabled_unit_on_self(nmap, ACTION_CONVERT, punit);
+    return is_action_enabled_unit_on_self(nmap, action, punit);
 
   case ACTIVITY_LAST:
     break;
@@ -1086,6 +1093,7 @@ bool can_unit_do_activity_targeted_at(const struct civ_map *nmap,
 
   log_error("can_unit_do_activity_targeted_at() unknown activity %d",
             activity);
+
   return FALSE;
 
 #undef RETURN_IS_ACTIVITY_ENABLED_UNIT_ON
diff --git a/common/unit.h b/common/unit.h
index 389e72484f..a5502309e9 100644
--- a/common/unit.h
+++ b/common/unit.h
@@ -342,14 +342,17 @@ bool can_unit_continue_current_activity(const struct civ_map *nmap,
                                         struct unit *punit);
 bool can_unit_do_activity(const struct civ_map *nmap,
                           const struct unit *punit,
-                          enum unit_activity activity);
+                          enum unit_activity activity,
+                          enum gen_action action);
 bool can_unit_do_activity_targeted(const struct civ_map *nmap,
                                    const struct unit *punit,
                                    enum unit_activity activity,
+                                   enum gen_action action,
                                    struct extra_type *target);
 bool can_unit_do_activity_targeted_at(const struct civ_map *nmap,
                                       const struct unit *punit,
                                       enum unit_activity activity,
+                                      enum gen_action action,
                                       struct extra_type *target,
                                       const struct tile *ptile);
 void set_unit_activity(struct unit *punit, enum unit_activity new_activity,
diff --git a/common/unitlist.c b/common/unitlist.c
index ef13c1aee8..b336bbddf6 100644
--- a/common/unitlist.c
+++ b/common/unitlist.c
@@ -127,10 +127,11 @@ bool can_units_do_on_map(const struct civ_map *nmap,
 ****************************************************************************/
 bool can_units_do_activity(const struct civ_map *nmap,
                            const struct unit_list *punits,
-                           enum unit_activity activity)
+                           enum unit_activity activity,
+                           enum gen_action action)
 {
   unit_list_iterate(punits, punit) {
-    if (can_unit_do_activity(nmap, punit, activity)) {
+    if (can_unit_do_activity(nmap, punit, activity, action)) {
       return TRUE;
     }
   } unit_list_iterate_end;
@@ -144,10 +145,11 @@ bool can_units_do_activity(const struct civ_map *nmap,
 bool can_units_do_activity_targeted(const struct civ_map *nmap,
                                     const struct unit_list *punits,
                                     enum unit_activity activity,
+                                    enum gen_action action,
                                     struct extra_type *pextra)
 {
   unit_list_iterate(punits, punit) {
-    if (can_unit_do_activity_targeted(nmap, punit, activity, pextra)) {
+    if (can_unit_do_activity_targeted(nmap, punit, activity, action, pextra)) {
       return TRUE;
     }
   } unit_list_iterate_end;
diff --git a/common/unitlist.h b/common/unitlist.h
index 9927af4f39..a042165eca 100644
--- a/common/unitlist.h
+++ b/common/unitlist.h
@@ -77,10 +77,12 @@ bool can_units_do_on_map(const struct civ_map *nmap,
                                        const struct unit *punit));
 bool can_units_do_activity(const struct civ_map *nmap,
                            const struct unit_list *punits,
-                           enum unit_activity activity);
+                           enum unit_activity activity,
+                           enum gen_action action);
 bool can_units_do_activity_targeted(const struct civ_map *nmap,
                                     const struct unit_list *punits,
                                     enum unit_activity activity,
+                                    enum gen_action action,
                                     struct extra_type *pextra);
 bool can_units_do_any_road(const struct civ_map *nmap,
                            const struct unit_list *punits);
diff --git a/server/actiontools.c b/server/actiontools.c
index 3bb306cff3..dc31738a9a 100644
--- a/server/actiontools.c
+++ b/server/actiontools.c
@@ -918,7 +918,8 @@ int action_sub_target_id_for_action(const struct action *paction,
       struct extra_type *pextra = NULL;
       enum unit_activity activity = action_get_activity(paction);
 
-      unit_assign_specific_activity_target(actor_unit, &activity, &pextra);
+      unit_assign_specific_activity_target(actor_unit, &activity,
+                                           action_number(paction), &pextra);
 
       if (pextra != NULL) {
         return extra_number(pextra);
diff --git a/server/savegame/savecompat.c b/server/savegame/savecompat.c
index 880f28c7af..aafb5c1799 100644
--- a/server/savegame/savecompat.c
+++ b/server/savegame/savecompat.c
@@ -1905,6 +1905,7 @@ static void compat_post_load_030100(struct loaddata *loading,
     unit_list_iterate(pplayer->units, punit) {
       unit_assign_specific_activity_target(punit,
                                            &punit->activity,
+                                           punit->action,
                                            &punit->activity_target);
     } unit_list_iterate_end;
   } players_iterate_alive_end;
diff --git a/server/unithand.c b/server/unithand.c
index 87e51052d7..e9945a04ee 100644
--- a/server/unithand.c
+++ b/server/unithand.c
@@ -6475,7 +6475,8 @@ void handle_unit_sscs_set(struct player *pplayer,
         fc_assert(FALSE);
       }
     } else if (value == 1) {
-      if (!can_unit_do_activity(nmap, punit, ACTIVITY_SENTRY)) {
+      if (!can_unit_do_activity(nmap, punit, ACTIVITY_SENTRY,
+                                activity_default_action(ACTIVITY_SENTRY))) {
         return;
       }
 
@@ -6573,7 +6574,8 @@ bool unit_server_side_agent_set(struct player *pplayer,
     }
     break;
   case SSA_AUTOEXPLORE:
-    if (!can_unit_do_activity(nmap, punit, ACTIVITY_EXPLORE)) {
+    if (!can_unit_do_activity(nmap, punit, ACTIVITY_EXPLORE,
+                              activity_default_action(ACTIVITY_EXPLORE))) {
       return FALSE;
     }
     break;
@@ -6676,7 +6678,8 @@ bool unit_activity_handling(struct unit *punit,
     /* Assume untargeted pillaging if no target specified */
     unit_activity_handling_targeted(punit, new_activity, &target,
                                     trigger_action);
-  } else if (can_unit_do_activity(nmap, punit, new_activity)) {
+  } else if (can_unit_do_activity(nmap, punit, new_activity,
+                                  trigger_action)) {
     free_unit_orders(punit);
     unit_activity_internal(punit, new_activity, trigger_action);
   }
@@ -6694,7 +6697,10 @@ static bool unit_activity_internal(struct unit *punit,
                                    enum unit_activity new_activity,
                                    enum gen_action trigger_action)
 {
-  if (!can_unit_do_activity(&(wld.map), punit, new_activity)) {
+  const struct civ_map *nmap = &(wld.map);
+
+  if (!can_unit_do_activity(nmap, punit, new_activity,
+                            trigger_action)) {
     return FALSE;
   } else {
     enum unit_activity old_activity = punit->activity;
@@ -6737,10 +6743,13 @@ bool unit_activity_handling_targeted(struct unit *punit,
                                      struct extra_type **new_target,
                                      enum gen_action trigger_action)
 {
+  const struct civ_map *nmap = &(wld.map);
+
   if (!activity_requires_target(new_activity)) {
     unit_activity_handling(punit, new_activity, trigger_action);
-  } else if (can_unit_do_activity_targeted(&(wld.map), punit,
-                                           new_activity, *new_target)) {
+  } else if (can_unit_do_activity_targeted(nmap, punit,
+                                           new_activity, trigger_action,
+                                           *new_target)) {
     struct action_list *list = action_list_by_activity(new_activity);
 
     free_unit_orders(punit);
@@ -6770,8 +6779,11 @@ static bool unit_activity_targeted_internal(struct unit *punit,
                                             struct extra_type **new_target,
                                             enum gen_action trigger_action)
 {
-  if (!can_unit_do_activity_targeted(&(wld.map), punit,
-                                     new_activity, *new_target)) {
+  const struct civ_map *nmap = &(wld.map);
+
+  if (!can_unit_do_activity_targeted(nmap, punit,
+                                     new_activity, trigger_action,
+                                     *new_target)) {
     return FALSE;
   } else {
     enum unit_activity old_activity = punit->activity;
@@ -6779,7 +6791,8 @@ static bool unit_activity_targeted_internal(struct unit *punit,
     enum unit_activity stored_activity = new_activity;
 
     unit_assign_specific_activity_target(punit,
-                                         &new_activity, new_target);
+                                         &new_activity, trigger_action,
+                                         new_target);
     if (new_activity != stored_activity
         && !activity_requires_target(new_activity)) {
       /* unit_assign_specific_activity_target() changed our target activity
@@ -6788,7 +6801,7 @@ static bool unit_activity_targeted_internal(struct unit *punit,
     } else {
       set_unit_activity_targeted(punit, new_activity, *new_target,
                                  trigger_action);
-      send_unit_info(NULL, punit);
+      send_unit_info(nullptr, punit);
       unit_activity_dependencies(punit, old_activity, old_target);
 
       if (new_activity == ACTIVITY_PILLAGE) {
diff --git a/server/unittools.c b/server/unittools.c
index 6708bd6ed4..6d5aaea58f 100644
--- a/server/unittools.c
+++ b/server/unittools.c
@@ -1081,12 +1081,13 @@ bool unit_activity_needs_target_from_client(enum unit_activity activity)
 **************************************************************************/
 void unit_assign_specific_activity_target(struct unit *punit,
                                           enum unit_activity *activity,
+                                          enum gen_action action,
                                           struct extra_type **target)
 {
   const struct civ_map *nmap = &(wld.map);
 
   if (*activity == ACTIVITY_PILLAGE
-      && *target == NULL) {
+      && *target == nullptr) {
     struct tile *ptile = unit_tile(punit);
     struct extra_type *tgt;
     bv_extras extras = *tile_extras(ptile);
@@ -1095,7 +1096,8 @@ void unit_assign_specific_activity_target(struct unit *punit,
 
       BV_CLR(extras, extra_index(tgt));
 
-      if (can_unit_do_activity_targeted(nmap, punit, *activity, tgt)) {
+      if (can_unit_do_activity_targeted(nmap, punit, *activity, action,
+                                        tgt)) {
         *target = tgt;
         return;
       }
@@ -1171,7 +1173,8 @@ void place_partisans(struct tile *pcenter, struct player *powner,
     struct unit *punit;
 
     punit = unit_virtual_prepare(powner, ptile, u_type, 0, 0, -1, -1);
-    if (can_unit_do_activity(nmap, punit, ACTIVITY_FORTIFYING)) {
+    if (can_unit_do_activity(nmap, punit, ACTIVITY_FORTIFYING,
+                             activity_default_action(ACTIVITY_FORTIFYING))) {
       punit->activity = ACTIVITY_FORTIFIED; /* Yes; directly fortified */
     }
 
@@ -4636,7 +4639,7 @@ bool execute_orders(struct unit *punit, const bool fresh)
 
         fc_assert(activity == ACTIVITY_SENTRY);
 
-        if (can_unit_do_activity(nmap, punit, activity)) {
+        if (can_unit_do_activity(nmap, punit, activity, order.action)) {
           punit->done_moving = TRUE;
           set_unit_activity(punit, activity, order.action);
           send_unit_info(NULL, punit);
diff --git a/server/unittools.h b/server/unittools.h
index 59acc4d0c3..8999964f7f 100644
--- a/server/unittools.h
+++ b/server/unittools.h
@@ -122,12 +122,13 @@ void bounce_unit(struct unit *punit, bool verbose);
 bool unit_activity_needs_target_from_client(enum unit_activity activity);
 void unit_assign_specific_activity_target(struct unit *punit,
                                           enum unit_activity *activity,
+                                          enum gen_action action,
                                           struct extra_type **target);
 void unit_forget_last_activity(struct unit *punit);
 void unit_make_contact(const struct unit *punit,
                        struct tile *ptile, struct player *pplayer);
 
-/* creation/deletion/upgrading */
+/* Creation/deletion/upgrading */
 void transform_unit(struct unit *punit, const struct unit_type *to_unit,
                     int vet_loss);
 struct unit *create_unit(struct player *pplayer, struct tile *ptile,
-- 
2.47.2

