From f2e70f36a0aab7f8fb0b18bf0816ef0acc5631fe Mon Sep 17 00:00:00 2001
From: Marko Lindqvist <cazfi74@gmail.com>
Date: Fri, 26 Nov 2021 17:29:56 +0200
Subject: [PATCH 2/3] Add "NonNatBombardTgt" unit class flag

Use it to fix the issue of attacks by Ships against Helicopters counted
as land bombardment when initiated from a city.

Reported by log65536

See osdn #43255

Signed-off-by: Marko Lindqvist <cazfi74@gmail.com>
---
 common/combat.c                  | 12 +++++++-----
 common/unittype.c                | 17 ++++++++++++++++
 common/unittype.h                | 33 +++++++++++++++++++-------------
 data/alien/units.ruleset         | 11 ++++++++---
 data/civ1/units.ruleset          |  4 +++-
 data/civ2/units.ruleset          |  4 +++-
 data/civ2civ3/units.ruleset      | 13 +++++++++----
 data/classic/units.ruleset       |  4 +++-
 data/experimental/units.ruleset  |  6 ++++--
 data/granularity/units.ruleset   |  4 +++-
 data/multiplayer/units.ruleset   |  4 +++-
 data/ruledit/comments-3.1.txt    |  2 ++
 data/sandbox/units.ruleset       | 11 +++++++----
 data/stub/units.ruleset          |  2 ++
 data/webperimental/units.ruleset |  4 +++-
 fc_version                       |  2 +-
 server/rscompat.c                | 12 ++++++++++++
 server/rscompat.h                |  2 ++
 server/ruleset.c                 |  1 +
 19 files changed, 110 insertions(+), 38 deletions(-)

diff --git a/common/combat.c b/common/combat.c
index 06dba776c7..430e7b0094 100644
--- a/common/combat.c
+++ b/common/combat.c
@@ -372,12 +372,14 @@ void get_modified_firepower(const struct unit *attacker,
 {
   struct city *pcity = tile_city(unit_tile(defender));
   const struct unit_type *att_type;
+  const struct unit_type *def_type;
   struct tile *att_tile;
 
   att_type = unit_type_get(attacker);
+  def_type = unit_type_get(defender);
 
   *att_fp = att_type->firepower;
-  *def_fp = unit_type_get(defender)->firepower;
+  *def_fp = def_type->firepower;
 
   /* Check CityBuster flag */
   if (unit_has_type_flag(attacker, UTYF_CITYBUSTER) && pcity) {
@@ -408,8 +410,7 @@ void get_modified_firepower(const struct unit *attacker,
    * When attacked by fighters, helicopters have their firepower
    * reduced to 1.
    */
-  if (combat_bonus_against(att_type->bonuses,
-                           unit_type_get(defender),
+  if (combat_bonus_against(att_type->bonuses, def_type,
                            CBONUS_LOW_FIREPOWER)) {
     *def_fp = 1;
   }
@@ -420,9 +421,10 @@ void get_modified_firepower(const struct unit *attacker,
    * Land bombardment is always towards tile not native for attacker.
    * It's initiated either from a tile not native to defender (Ocean for Land unit)
    * or from a tile where attacker is despite non-native terrain (city, transport) */
-  if (!is_native_tile(att_type, unit_tile(defender))
+  if (utype_has_class_flag(def_type, UCF_NONNAT_BOMBARD_TGT)
+      && !is_native_tile(att_type, unit_tile(defender))
       && (!can_exist_at_tile(&(wld.map),
-                             unit_type_get(defender), att_tile)
+                             def_type, att_tile)
           || !is_native_tile(att_type, att_tile))) {
     *att_fp = 1;
     *def_fp = 1;
diff --git a/common/unittype.c b/common/unittype.c
index 6c2145e8ea..d862e78a58 100644
--- a/common/unittype.c
+++ b/common/unittype.c
@@ -1691,6 +1691,23 @@ const char *uclass_rule_name(const struct unit_class *pclass)
   return rule_name_get(&pclass->name);
 }
 
+/**********************************************************************//**
+  Return whether the unit has the class flag.
+**************************************************************************/
+bool unit_has_class_flag(const struct unit *punit, enum unit_class_flag_id flag)
+{
+  return uclass_has_flag(unit_class_get(punit), flag);
+}
+
+/**********************************************************************//**
+  Return whether the unit type has the class flag.
+**************************************************************************/
+bool utype_has_class_flag(const struct unit_type *ptype,
+                          enum unit_class_flag_id flag)
+{
+  return uclass_has_flag(utype_class(ptype), flag);
+}
+
 /**********************************************************************//**
   Return a string with all the names of units with this flag. If "alts" is
   set, separate with "or", otherwise "and". Return FALSE if no unit with
diff --git a/common/unittype.h b/common/unittype.h
index 4a726a6b3a..2c529da225 100644
--- a/common/unittype.h
+++ b/common/unittype.h
@@ -85,19 +85,22 @@ struct ai_type;
 /* Frightens the huts it pops. */
 #define SPECENUM_VALUE11 UCF_HUT_FRIGHTEN
 #define SPECENUM_VALUE11NAME N_("?uclassflag:HutFrighten")
-
-#define SPECENUM_VALUE12 UCF_USER_FLAG_1
-#define SPECENUM_VALUE13 UCF_USER_FLAG_2
-#define SPECENUM_VALUE14 UCF_USER_FLAG_3
-#define SPECENUM_VALUE15 UCF_USER_FLAG_4
-#define SPECENUM_VALUE16 UCF_USER_FLAG_5
-#define SPECENUM_VALUE17 UCF_USER_FLAG_6
-#define SPECENUM_VALUE18 UCF_USER_FLAG_7
-#define SPECENUM_VALUE19 UCF_USER_FLAG_8
-#define SPECENUM_VALUE20 UCF_USER_FLAG_9
-#define SPECENUM_VALUE21 UCF_USER_FLAG_10
-#define SPECENUM_VALUE22 UCF_USER_FLAG_11
-#define SPECENUM_VALUE23 UCF_USER_FLAG_12
+/* Is a target for "Land Bombardment" attacks */
+#define SPECENUM_VALUE12 UCF_NONNAT_BOMBARD_TGT
+#define SPECENUM_VALUE12NAME N_("?uclassflag:NonNatBombardTgt")
+
+#define SPECENUM_VALUE13 UCF_USER_FLAG_1
+#define SPECENUM_VALUE14 UCF_USER_FLAG_2
+#define SPECENUM_VALUE15 UCF_USER_FLAG_3
+#define SPECENUM_VALUE16 UCF_USER_FLAG_4
+#define SPECENUM_VALUE17 UCF_USER_FLAG_5
+#define SPECENUM_VALUE18 UCF_USER_FLAG_6
+#define SPECENUM_VALUE19 UCF_USER_FLAG_7
+#define SPECENUM_VALUE20 UCF_USER_FLAG_8
+#define SPECENUM_VALUE21 UCF_USER_FLAG_9
+#define SPECENUM_VALUE22 UCF_USER_FLAG_10
+#define SPECENUM_VALUE23 UCF_USER_FLAG_11
+#define SPECENUM_VALUE24 UCF_USER_FLAG_12
 
 /* keep this last */
 #define SPECENUM_COUNT UCF_COUNT
@@ -733,6 +736,10 @@ struct unit_class *unit_class_by_rule_name(const char *s);
 const char *uclass_rule_name(const struct unit_class *pclass);
 const char *uclass_name_translation(const struct unit_class *pclass);
 
+bool unit_has_class_flag(const struct unit *punit, enum unit_class_flag_id flag);
+bool utype_has_class_flag(const struct unit_type *ptype,
+                          enum unit_class_flag_id flag);
+
 /**************************************************************************
   Return whether the given unit class has the flag.
 **************************************************************************/
diff --git a/data/alien/units.ruleset b/data/alien/units.ruleset
index 5c5cd92b03..13452c85d6 100644
--- a/data/alien/units.ruleset
+++ b/data/alien/units.ruleset
@@ -122,6 +122,8 @@ veteran_move_bonus = 0, 0, 0
 ;                       citizen. The effect "Unit_No_Lose_Pop" and the server
 ;                       setting 'killcitizen' can disable this.
 ; "HutFrighten"       = Will frighten rather than enter huts.
+; "NonNatBombardTgt"  = Certain attacks against these units are considered
+;                       Nonnative Bombard Attack type
 ;
 ; */ <-- avoid gettext warnings
 
@@ -131,7 +133,8 @@ min_speed     = 1
 hp_loss_pct   = 0
 flags         = "DamageSlows", "TerrainSpeed", "CanFortify", "ZOC",
                 "CollectRansom", "BuildAnywhere", "CanOccupyCity",
-                "CanPillage", "TerrainDefense", "KillCitizen","Airliftable"
+                "CanPillage", "TerrainDefense", "KillCitizen", "Airliftable",
+                "NonNatBombardTgt"
 
 [unitclass_native]
 name          = _("?unitclass:Native")
@@ -139,7 +142,8 @@ min_speed     = 1
 hp_loss_pct   = 0
 flags         = "DamageSlows", "TerrainSpeed", "CanFortify", "ZOC",
                 "CollectRansom", "BuildAnywhere", "CanOccupyCity",
-                "CanPillage", "TerrainDefense", "KillCitizen","Airliftable"
+                "CanPillage", "TerrainDefense", "KillCitizen", "Airliftable",
+                "NonNatBombardTgt"
 
 [unitclass_sea]
 name          = _("?unitclass:Sea")
@@ -156,7 +160,8 @@ min_speed     = 1
 hp_loss_pct   = 0
 flags         = "DamageSlows", "TerrainSpeed", "CanFortify", "ZOC",
                 "CollectRansom", "BuildAnywhere", "CanOccupyCity",
-                "CanPillage", "TerrainDefense", "KillCitizen"
+                "CanPillage", "TerrainDefense", "KillCitizen",
+                "NonNatBombardTgt"
 
 [unitclass_antigravity]
 name          = _("?unitclass:Antigravity")
diff --git a/data/civ1/units.ruleset b/data/civ1/units.ruleset
index 0659cd5d22..6dc0acc9ec 100644
--- a/data/civ1/units.ruleset
+++ b/data/civ1/units.ruleset
@@ -118,6 +118,8 @@ veteran_move_bonus = 0, 0
 ;                       citizen. The effect "Unit_No_Lose_Pop" and the server
 ;                       setting 'killcitizen' can disable this.
 ; "HutFrighten"       = Will frighten rather than enter huts.
+; "NonNatBombardTgt"  = Certain attacks against these units are considered
+;                       Nonnative Bombard Attack type
 ;
 ; */ <-- avoid gettext warnings
 
@@ -128,7 +130,7 @@ min_speed     = 1
 hp_loss_pct   = 0
 flags         = "TerrainSpeed", "CanOccupyCity", "BuildAnywhere",
                 "CollectRansom", "ZOC", "CanFortify", "CanPillage",
-                "TerrainDefense", "KillCitizen"
+                "TerrainDefense", "KillCitizen", "NonNatBombardTgt"
 
 [unitclass_sea]
 ; /* TRANS: Unit class: used adjectivally */
diff --git a/data/civ2/units.ruleset b/data/civ2/units.ruleset
index cd3d36d215..7fa64687fe 100644
--- a/data/civ2/units.ruleset
+++ b/data/civ2/units.ruleset
@@ -126,6 +126,8 @@ veteran_move_bonus = 0, 0
 ;                       citizen. The effect "Unit_No_Lose_Pop" and the server
 ;                       setting 'killcitizen' can disable this.
 ; "HutFrighten"       = Will frighten rather than enter huts.
+; "NonNatBombardTgt"  = Certain attacks against these units are considered
+;                       Nonnative Bombard Attack type
 ;
 ; */ <-- avoid gettext warnings
 
@@ -143,7 +145,7 @@ min_speed     = 1
 hp_loss_pct   = 0
 flags         = "TerrainSpeed", "DamageSlows", "CanOccupyCity", "BuildAnywhere",
                 "CollectRansom", "ZOC", "CanFortify", "CanPillage",
-                "TerrainDefense", "KillCitizen"
+                "TerrainDefense", "KillCitizen", "NonNatBombardTgt"
 helptext      = _("\
   * Can be airlifted from a suitable city.\
 ")
diff --git a/data/civ2civ3/units.ruleset b/data/civ2civ3/units.ruleset
index f391e68111..63eff6868b 100644
--- a/data/civ2civ3/units.ruleset
+++ b/data/civ2civ3/units.ruleset
@@ -135,6 +135,8 @@ veteran_move_bonus = 0, 0, 0, 0
 ;                       citizen. The effect "Unit_No_Lose_Pop" and the server
 ;                       setting 'killcitizen' can disable this.
 ; "HutFrighten"       = Will frighten rather than enter huts.
+; "NonNatBombardTgt"  = Certain attacks against these units are considered
+;                       Nonnative Bombard Attack type
 ;
 ; */ <-- avoid gettext warnings
 
@@ -153,7 +155,7 @@ min_speed     = 1
 hp_loss_pct   = 0
 flags         = "TerrainSpeed", "DamageSlows", "CanOccupyCity", "BuildAnywhere",
                 "CollectRansom", "ZOC", "CanFortify", "CanPillage",
-                "TerrainDefense", "Airliftable"
+                "TerrainDefense", "Airliftable", "NonNatBombardTgt"
 
 [unitclass_land_small]
 ; /* TRANS: Unit class: used adjectivally */
@@ -161,7 +163,8 @@ name          = _("?unitclass:Small Land")
 min_speed     = 1
 hp_loss_pct   = 0
 flags         = "TerrainSpeed", "DamageSlows", "BuildAnywhere", "CollectRansom",
-                "ZOC", "CanFortify", "TerrainDefense", "DoesntOccupyTile", "Airliftable"
+                "ZOC", "CanFortify", "TerrainDefense", "DoesntOccupyTile",
+                "Airliftable", "NonNatBombardTgt"
 
 [unitclass_land_big]
 ; /* TRANS: Unit class: used adjectivally */
@@ -169,7 +172,8 @@ name          = _("?unitclass:Big Land")
 min_speed     = 1
 hp_loss_pct   = 0
 flags         = "TerrainSpeed", "DamageSlows", "CanOccupyCity", "BuildAnywhere",
-                "CollectRansom","ZOC", "CanFortify", "KillCitizen", "Airliftable"
+                "CollectRansom","ZOC", "CanFortify", "KillCitizen", "Airliftable",
+                "NonNatBombardTgt"
 
 [unitclass_merchant]
 ; /* TRANS: Unit class: used adjectivally */
@@ -177,7 +181,8 @@ name          = _("?unitclass:Merchant")
 min_speed     = 1
 hp_loss_pct   = 0
 flags         = "BuildAnywhere", "DoesntOccupyTile",
-                "ZOC", "TerrainDefense", "TerrainSpeed", "Airliftable"
+                "ZOC", "TerrainDefense", "TerrainSpeed", "Airliftable",
+                "NonNatBombardTgt"
 
 [unitclass_sea]
 ; /* TRANS: Unit class: used adjectivally */
diff --git a/data/classic/units.ruleset b/data/classic/units.ruleset
index 304b0bbd20..0dee9b3e00 100644
--- a/data/classic/units.ruleset
+++ b/data/classic/units.ruleset
@@ -133,6 +133,8 @@ veteran_move_bonus = 0, 0, 0, 0
 ;                       citizen. The effect "Unit_No_Lose_Pop" and the server
 ;                       setting 'killcitizen' can disable this.
 ; "HutFrighten"       = Will frighten rather than enter huts.
+; "NonNatBombardTgt"  = Certain attacks against these units are considered
+;                       Nonnative Bombard Attack type
 ;
 ; */ <-- avoid gettext warnings
 
@@ -150,7 +152,7 @@ min_speed     = 1
 hp_loss_pct   = 0
 flags         = "TerrainSpeed", "DamageSlows", "CanOccupyCity", "BuildAnywhere",
                 "CollectRansom", "ZOC", "CanFortify", "CanPillage",
-                "TerrainDefense", "KillCitizen"
+                "TerrainDefense", "KillCitizen", "NonNatBombardTgt"
 helptext      = _("\
   * Can be airlifted from a suitable city.\
 ")
diff --git a/data/experimental/units.ruleset b/data/experimental/units.ruleset
index 64364a69bb..7cbb0c286c 100644
--- a/data/experimental/units.ruleset
+++ b/data/experimental/units.ruleset
@@ -137,6 +137,8 @@ veteran_move_bonus = 0, 0, 0, 0
 ;                       citizen. The effect "Unit_No_Lose_Pop" and the server
 ;                       setting 'killcitizen' can disable this.
 ; "HutFrighten"       = Will frighten rather than enter huts.
+; "NonNatBombardTgt"  = Certain attacks against these units are considered
+;                       Nonnative Bombard Attack type
 ;
 ; */ <-- avoid gettext warnings
 
@@ -154,7 +156,7 @@ min_speed     = 1
 hp_loss_pct   = 0
 flags         = "TerrainSpeed", "DamageSlows", "CanOccupyCity", "BuildAnywhere",
                 "CollectRansom", "ZOC", "CanFortify", "CanPillage",
-                "TerrainDefense", "KillCitizen", "Airliftable"
+                "TerrainDefense", "KillCitizen", "Airliftable", "NonNatBombardTgt"
 
 [unitclass_land_big]
 ; /* TRANS: "Big Land" is a unit class, like Land or Sea. Big Land units */
@@ -165,7 +167,7 @@ min_speed     = 1
 hp_loss_pct   = 0
 flags         = "TerrainSpeed", "DamageSlows", "CanOccupyCity", "BuildAnywhere",
                 "CollectRansom", "ZOC", "CanFortify", "CanPillage",
-                "TerrainDefense", "KillCitizen", "Airliftable"
+                "TerrainDefense", "KillCitizen", "Airliftable", "NonNatBombardTgt"
 
 [unitclass_sea]
 ; /* TRANS: Unit class: used adjectivally */
diff --git a/data/granularity/units.ruleset b/data/granularity/units.ruleset
index dc01fc30b5..437d93c686 100644
--- a/data/granularity/units.ruleset
+++ b/data/granularity/units.ruleset
@@ -115,6 +115,8 @@ veteran_move_bonus = 0
 ; "KillCitizen"       = Upon successful attack against a city unit kills one citizen.
 ;                       There's server setting, as well as effects, to disable this.
 ; "HutFrighten"       = Will frighten rather than enter huts.
+; "NonNatBombardTgt"  = Certain attacks against these units are considered
+;                       Nonnative Bombard Attack type
 ;
 ; */ <-- avoid gettext warnings
 
@@ -122,7 +124,7 @@ veteran_move_bonus = 0
 name          = _("Land")
 min_speed     = 1
 hp_loss_pct   = 0
-flags         = "TerrainSpeed"
+flags         = "TerrainSpeed", "NonNatBombardTgt"
 
 [unitclass_sea]
 name          = _("Sea")
diff --git a/data/multiplayer/units.ruleset b/data/multiplayer/units.ruleset
index 42eb5e0ffa..86f52f7cf6 100644
--- a/data/multiplayer/units.ruleset
+++ b/data/multiplayer/units.ruleset
@@ -133,6 +133,8 @@ veteran_move_bonus = 0, 0, 0, 0
 ;                       citizen. The effect "Unit_No_Lose_Pop" and the server
 ;                       setting 'killcitizen' can disable this.
 ; "HutFrighten"       = Will frighten rather than enter huts.
+; "NonNatBombardTgt"  = Certain attacks against these units are considered
+;                       Nonnative Bombard Attack type
 ;
 ; */ <-- avoid gettext warnings
 
@@ -150,7 +152,7 @@ min_speed     = 1
 hp_loss_pct   = 0
 flags         = "TerrainSpeed", "DamageSlows", "CanOccupyCity", "BuildAnywhere",
                 "CollectRansom", "ZOC", "CanFortify", "CanPillage",
-                "TerrainDefense", "KillCitizen"
+                "TerrainDefense", "KillCitizen", "NonNatBombardTgt"
 helptext      = _("\
   * Can be airlifted from a suitable city.\
 ")
diff --git a/data/ruledit/comments-3.1.txt b/data/ruledit/comments-3.1.txt
index c08bf48d82..6bf31022e3 100644
--- a/data/ruledit/comments-3.1.txt
+++ b/data/ruledit/comments-3.1.txt
@@ -292,6 +292,8 @@ uclasses = "\
 ;                       citizen. The effect \"Unit_No_Lose_Pop\" and the server\n\
 ;                       setting \'killcitizen\' can disable this.\n\
 ; \"HutFrighten\"       = Will frighten rather than enter huts.\n\
+; \"NonNatBombardTgt\"  = Certain attacks against these units are considered\n\
+;                       Nonnative Bombard Attack type\n\
 ;\n\
 ; */ <-- avoid gettext warnings\n\
 "
diff --git a/data/sandbox/units.ruleset b/data/sandbox/units.ruleset
index 74ff6061ba..732bcd25d7 100644
--- a/data/sandbox/units.ruleset
+++ b/data/sandbox/units.ruleset
@@ -145,6 +145,8 @@ veteran_move_bonus = 0, 0, 0, 0
 ;                       citizen. The effect "Unit_No_Lose_Pop" and the server
 ;                       setting 'killcitizen' can disable this.
 ; "HutFrighten"       = Will frighten rather than enter huts.
+; "NonNatBombardTgt"  = Certain attacks against these units are considered
+;                       Nonnative Bombard Attack type
 ;
 ; */ <-- avoid gettext warnings
 
@@ -163,7 +165,7 @@ min_speed     = 1
 hp_loss_pct   = 0
 flags         = "TerrainSpeed", "DamageSlows", "CanOccupyCity", "BuildAnywhere",
                 "CollectRansom", "ZOC", "CanFortify", "CanPillage",
-                "TerrainDefense", "LightWeight", "BorderPolice"
+                "TerrainDefense", "LightWeight", "BorderPolice", "NonNatBombardTgt"
 
 [unitclass_land_small]
 ; /* TRANS: Unit class: used adjectivally */
@@ -172,7 +174,7 @@ min_speed     = 1
 hp_loss_pct   = 0
 flags         = "TerrainSpeed", "DamageSlows", "BuildAnywhere", "CollectRansom",
                 "ZOC", "TerrainDefense", "DoesntOccupyTile", "LightWeight",
-                "Expellable"
+                "Expellable", "NonNatBombardTgt"
 
 [unitclass_land_big]
 ; /* TRANS: Unit class: used adjectivally */
@@ -180,7 +182,8 @@ name          = _("?unitclass:Big Land")
 min_speed     = 1
 hp_loss_pct   = 0
 flags         = "TerrainSpeed", "DamageSlows", "CanOccupyCity", "BuildAnywhere",
-                "CollectRansom","ZOC", "CanFortify", "KillCitizen", "MediumWeight"
+                "CollectRansom","ZOC", "CanFortify", "KillCitizen", "MediumWeight",
+                "NonNatBombardTgt"
 
 [unitclass_merchant]
 ; /* TRANS: Unit class: used adjectivally */
@@ -189,7 +192,7 @@ min_speed     = 1
 hp_loss_pct   = 0
 flags         = "BuildAnywhere", "DoesntOccupyTile",
                 "ZOC", "TerrainDefense", "TerrainSpeed", "MediumWeight",
-                "Expellable"
+                "Expellable", "NonNatBombardTgt"
 
 [unitclass_sea]
 ; /* TRANS: Unit class: used adjectivally */
diff --git a/data/stub/units.ruleset b/data/stub/units.ruleset
index 97634f658c..fdedf5afea 100644
--- a/data/stub/units.ruleset
+++ b/data/stub/units.ruleset
@@ -99,6 +99,8 @@ veteran_move_bonus = 0
 ; "KillCitizen"       = Upon successful attack against a city unit kills one citizen.
 ;                       There's server setting, as well as effects, to disable this.
 ; "HutFrighten"       = Will frighten rather than enter huts.
+; "NonNatBombardTgt"  = Certain attacks against these units are considered
+;                       Nonnative Bombard Attack type
 ;
 ; */ <-- avoid gettext warnings
 
diff --git a/data/webperimental/units.ruleset b/data/webperimental/units.ruleset
index 7c084fd097..ca0380ed51 100644
--- a/data/webperimental/units.ruleset
+++ b/data/webperimental/units.ruleset
@@ -140,6 +140,8 @@ veteran_move_bonus = 0, 0, 0, 0
 ;                       citizen. The effect "Unit_No_Lose_Pop" and the server
 ;                       setting 'killcitizen' can disable this.
 ; "HutFrighten"       = Will frighten rather than enter huts.
+; "NonNatBombardTgt"  = Certain attacks against these units are considered
+;                       Nonnative Bombard Attack type
 ;
 ; */ <-- avoid gettext warnings
 
@@ -157,7 +159,7 @@ min_speed     = 1
 hp_loss_pct   = 0
 flags         = "TerrainSpeed", "DamageSlows", "CanOccupyCity", "BuildAnywhere",
                 "CollectRansom", "CanFortify", "CanPillage",
-                "TerrainDefense", "KillCitizen"
+                "TerrainDefense", "KillCitizen", "NonNatBombardTgt"
 
 [unitclass_sea]
 ; /* TRANS: Unit class: used adjectivally */
diff --git a/fc_version b/fc_version
index 72699070ed..78fdfb6df9 100755
--- a/fc_version
+++ b/fc_version
@@ -56,7 +56,7 @@ DEFAULT_FOLLOW_TAG=S3_1
 #   - No new mandatory capabilities can be added to the release branch; doing
 #     so would break network capability of supposedly "compatible" releases.
 #
-NETWORK_CAPSTRING="+Freeciv.Devel-3.1-2021.Nov.23"
+NETWORK_CAPSTRING="+Freeciv.Devel-3.1-2021.Nov.26"
 
 FREECIV_DISTRIBUTOR=""
 
diff --git a/server/rscompat.c b/server/rscompat.c
index 6feb6bf7d9..5a18a680ea 100644
--- a/server/rscompat.c
+++ b/server/rscompat.c
@@ -2041,6 +2041,18 @@ const char *rscompat_combat_bonus_name_3_1(struct rscompat_info *compat,
   return old_type;
 }
 
+/**********************************************************************//**
+  Set compatibility unit class flags.
+**************************************************************************/
+void rscompat_uclass_flags_3_1(struct rscompat_info *compat,
+                               struct unit_class *pclass)
+{
+  if (compat->compat_mode && compat->ver_units < RSFORMAT_3_1) {
+    /* Old hardcoded behavior was like all units having NonNatBombardTgt */
+    BV_SET(pclass->flags, UCF_NONNAT_BOMBARD_TGT);
+  }
+}
+
 /**********************************************************************//**
   Adjust freeciv-3.0 ruleset extra definitions to freeciv-3.1
 **************************************************************************/
diff --git a/server/rscompat.h b/server/rscompat.h
index 30748b8888..c4448e1458 100644
--- a/server/rscompat.h
+++ b/server/rscompat.h
@@ -76,6 +76,8 @@ const char *rscompat_combat_bonus_name_3_1(struct rscompat_info *compat,
                                            const char *old_type);
 bool rscompat_old_effect_3_1(const char *type, struct section_file *file,
                              const char *sec_name, struct rscompat_info *compat);
+void rscompat_uclass_flags_3_1(struct rscompat_info *compat,
+                               struct unit_class *pclass);
 void rscompat_extra_adjust_3_1(struct rscompat_info *compat,
                                struct extra_type *pextra);
 bool rscompat_old_slow_invasions_3_1(struct rscompat_info *compat,
diff --git a/server/ruleset.c b/server/ruleset.c
index f89951c6f0..e7a1cc96d0 100644
--- a/server/ruleset.c
+++ b/server/ruleset.c
@@ -2105,6 +2105,7 @@ static bool load_ruleset_units(struct section_file *file,
       }
 
       BV_CLR_ALL(uc->flags);
+      rscompat_uclass_flags_3_1(compat, uc);
       slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec_name);
       for (j = 0; j < nval; j++) {
         sval = slist[j];
-- 
2.30.2