diff --git a/client/gui-gtk-3.22/menu.c b/client/gui-gtk-3.22/menu.c
index 6471fd144..75ef5d7d1 100644
--- a/client/gui-gtk-3.22/menu.c
+++ b/client/gui-gtk-3.22/menu.c
@@ -232,6 +232,7 @@ static void build_irrigation_callback(GtkMenuItem *item, gpointer data);
static void build_mine_callback(GtkMenuItem *item, gpointer data);
static void connect_road_callback(GtkMenuItem *item, gpointer data);
static void connect_rail_callback(GtkMenuItem *item, gpointer data);
+static void connect_maglev_callback(GtkMenuItem *item, gpointer data);
static void connect_irrigation_callback(GtkMenuItem *item, gpointer data);
static void transform_terrain_callback(GtkMenuItem *item, gpointer data);
static void clean_pollution_callback(GtkMenuItem *item, gpointer data);
@@ -503,6 +504,8 @@ static struct menu_entry_info menu_entries[] =
G_CALLBACK(connect_road_callback), MGROUP_UNIT },
{ "CONNECT_RAIL", N_("Connect With Rai_l"), GDK_KEY_l, GDK_SHIFT_MASK,
G_CALLBACK(connect_rail_callback), MGROUP_UNIT },
+ { "CONNECT_MAGLEV", N_("Connect With maglEv"), GDK_KEY_e, 0,
+ G_CALLBACK(connect_maglev_callback), MGROUP_UNIT },
{ "CONNECT_IRRIGATION", N_("Connect With Irri_gation"),
GDK_KEY_i, GDK_SHIFT_MASK,
G_CALLBACK(connect_irrigation_callback), MGROUP_UNIT },
@@ -1628,6 +1631,22 @@ static void connect_rail_callback(GtkMenuItem *action, gpointer data)
}
}
+/****************************************************************
+ Action "CONNECT_MAGLEV" callback.
+*****************************************************************/
+static void connect_maglev_callback(GtkMenuItem *action, gpointer data)
+{
+ struct road_type *pmaglev = road_by_compat_special(ROCO_MAGLEV);
+
+ if (pmaglev != NULL) {
+ struct extra_type *tgt;
+
+ tgt = road_extra_get(pmaglev);
+
+ key_unit_connect(ACTIVITY_GEN_ROAD, tgt);
+ }
+}
+
/****************************************************************
Action "CONNECT_IRRIGATION" callback.
*****************************************************************/
@@ -2150,6 +2169,13 @@ void real_menus_update(void)
extra_name_translation(road_extra_get(proad)));
menus_rename("CONNECT_RAIL", road_buf);
}
+
+ proad = road_by_compat_special(ROCO_MAGLEV);
+ if (proad != NULL) {
+ snprintf(road_buf, sizeof(road_buf), _("Connect With %s"),
+ extra_name_translation(road_extra_get(proad)));
+ menus_rename("CONNECT_MAGLEV", road_buf);
+ }
}
if (!can_client_issue_orders()) {
@@ -2330,6 +2356,18 @@ void real_menus_update(void)
}
menu_entry_set_sensitive("CONNECT_RAIL", conn_possible);
+ proad = road_by_compat_special(ROCO_MAGLEV);
+ if (proad != NULL) {
+ struct extra_type *tgt;
+
+ tgt = road_extra_get(proad);
+
+ conn_possible = can_units_do_connect(punits, ACTIVITY_GEN_ROAD, tgt);
+ } else {
+ conn_possible = FALSE;
+ }
+ menu_entry_set_sensitive("CONNECT_MAGLEV", conn_possible);
+
extras = extra_type_list_by_cause(EC_IRRIGATION);
if (extra_type_list_size(extras) > 0) {
diff --git a/common/fc_types.h b/common/fc_types.h
index 2d830ccb0..c7768d473 100644
--- a/common/fc_types.h
+++ b/common/fc_types.h
@@ -878,7 +878,7 @@ enum test_result {
/* Road type compatibility with old specials based roads.
* Used in the network protocol. */
-enum road_compat { ROCO_ROAD, ROCO_RAILROAD, ROCO_RIVER, ROCO_NONE };
+enum road_compat { ROCO_ROAD, ROCO_RAILROAD, ROCO_MAGLEV, ROCO_RIVER, ROCO_NONE };
/*
* Maximum number of trade routes a city can have in any situation.
diff --git a/data/civ2civ3/terrain.ruleset b/data/civ2civ3/terrain.ruleset
index 3e0220dc8..1ad579c66 100644
--- a/data/civ2civ3/terrain.ruleset
+++ b/data/civ2civ3/terrain.ruleset
@@ -2129,7 +2129,8 @@ vision_main_sq = 5
; In summary, output bonuses from roads are given by the formula:
; (base_prod + roads.incr_const + roads.incr*terrain.incr_pct) * roads.bonus
; compat_special = what kind of pre-2.5 special this road corresponds
-; to, if any: "Road", "Railroad", "River", or "None".
+; to, if any: "Road", "Railroad", "Maglev", "River",
+; or "None".
; Used for UI and loading old savegames
; integrates = list of road types that are suitable next steps
; for travel from this road type; such steps are
@@ -2186,6 +2187,7 @@ trade_incr = 0
food_bonus = 0
shield_bonus = 0
trade_bonus = 0
+compat_special = "Maglev"
flags = "RequiresBridge"
[road_river]
diff --git a/data/gtk3.22_menus.xml b/data/gtk3.22_menus.xml
index b7d10e14a..5a6fa53b0 100644
--- a/data/gtk3.22_menus.xml
+++ b/data/gtk3.22_menus.xml
@@ -359,6 +359,9 @@
+
+
+
diff --git a/server/ruleset.c b/server/ruleset.c
index 2b44410d4..2826f4076 100644
--- a/server/ruleset.c
+++ b/server/ruleset.c
@@ -2728,6 +2728,7 @@ static bool load_ruleset_terrain(struct section_file *file,
int j;
bool compat_road = FALSE;
bool compat_rail = FALSE;
+ bool compat_maglev = FALSE;
bool compat_river = FALSE;
const char **res;
const char *filename = secfile_name(file);
@@ -3594,6 +3595,13 @@ static bool load_ruleset_terrain(struct section_file *file,
}
compat_rail = TRUE;
proad->compat = ROCO_RAILROAD;
+ } else if (!fc_strcasecmp(special, "Maglev")) {
+ if (compat_maglev) {
+ ruleset_error(LOG_ERROR, "Multiple maglev marked as compatibility \"Maglev\"");
+ ok = FALSE;
+ }
+ compat_maglev = TRUE;
+ proad->compat = ROCO_MAGLEV;
} else if (!fc_strcasecmp(special, "River")) {
if (compat_river) {
ruleset_error(LOG_ERROR, "Multiple roads marked as compatibility \"River\"");
diff --git a/tools/ruleutil/rulesave.c b/tools/ruleutil/rulesave.c
index a7ddc9f33..2e2bb2c47 100644
--- a/tools/ruleutil/rulesave.c
+++ b/tools/ruleutil/rulesave.c
@@ -2396,6 +2396,9 @@ static bool save_terrain_ruleset(const char *filename, const char *name)
case ROCO_RAILROAD:
secfile_insert_str(sfile, "Railroad", "%s.compat_special", path);
break;
+ case ROCO_MAGLEV:
+ secfile_insert_str(sfile, "Maglev", "%s.compat_special", path);
+ break;
case ROCO_RIVER:
secfile_insert_str(sfile, "River", "%s.compat_special", path);
break;