<URL: http://bugs.freeciv.org/Ticket/Display.html?id=40407 >

> [EMAIL PROTECTED] - Sa 26. Jul 2008, 23:03:29]:

> Hmmm, I can't remember if you can see the strongest unit inside ANY city
> (sorry).  I guess from a tactical/logical point of view it doesn't make
> sense that you can see what the 'enemy' has in its defences.
> 
> However I think it's definitely required for your own cities - OK, I'll make
> a wish-list request.

I dunno how it was in civ2 but in civ3 you could only see the strongest enemy 
unit defending a city on top of the sprite of the city, while you could 
always see your full stacks of units.

Attached patch is one way of how this feature could be implemented in current 
trunk version. I created two new options in the game for this: one on the 
server side called "seecitydefender", which is disabled by default. Once 
enabled the server will send the info about the strongest unit occupying any 
city within vision so it can be displayed. 

For the displaying on the client there is the second 
option "draw_units_in_cities" that I incorporated so far only in the gtk-2.0 
GUI. This is the reason why I enabled it by default, so players using other 
GUI's that have no way yet to change this view option will have no drawback 
when playing on a server with seecitydefender enabled. 
If this option is disabled on the server side you should still be able to see 
full unit stacks on top of own and allied cities with the client side option 
enabled.

Greetings,
Nico

diff -Nur -X.diff_ignore trunk/client/control.c changed/client/control.c
--- trunk/client/control.c	2008-07-27 21:46:43.000000000 +0200
+++ changed/client/control.c	2008-08-10 22:03:55.000000000 +0200
@@ -602,7 +602,7 @@
   }
 
   /* If a city is here, return nothing (unit hidden by city). */
-  if (tile_city(ptile)) {
+  if (tile_city(ptile) && !draw_units_in_cities) {
     return NULL;
   }
 
@@ -1833,6 +1833,19 @@
 }
 
 /**************************************************************************
+ Toggle option to display units on top of cities
+**************************************************************************/
+void request_toggle_units_in_cities(void)
+{
+  if (!can_client_change_view()) {
+    return;
+  }
+
+  draw_units_in_cities ^= 1;
+  update_map_canvas_visible();
+}
+
+/**************************************************************************
 ...
 **************************************************************************/
 void request_center_focus_unit(void)
@@ -2849,6 +2862,14 @@
 }
 
 /**************************************************************************
+...
+**************************************************************************/
+void key_units_in_cities_toggle(void)
+{
+  request_toggle_units_in_cities();
+}
+
+/**************************************************************************
   Toggle editor mode in the server.
 **************************************************************************/
 void key_editor_toggle(void)
diff -Nur -X.diff_ignore trunk/client/control.h changed/client/control.h
--- trunk/client/control.h	2008-07-27 21:46:43.000000000 +0200
+++ changed/client/control.h	2008-08-10 21:59:47.000000000 +0200
@@ -110,6 +110,7 @@
 void request_toggle_units(void);
 void request_toggle_focus_unit(void);
 void request_toggle_fog_of_war(void);
+void request_toggle_units_in_cities(void);
 
 void wakeup_sentried_units(struct tile *ptile);
 
@@ -154,6 +155,7 @@
 void key_units_toggle(void);
 void key_focus_unit_toggle(void);
 void key_fog_of_war_toggle(void);
+void key_units_in_cities_toggle(void);
 void key_end_turn(void);
 void key_city_outlines_toggle(void);
 void key_city_output_toggle(void);
diff -Nur -X.diff_ignore trunk/client/gui-gtk-2.0/menu.c changed/client/gui-gtk-2.0/menu.c
--- trunk/client/gui-gtk-2.0/menu.c	2008-08-02 22:46:09.000000000 +0200
+++ changed/client/gui-gtk-2.0/menu.c	2008-08-10 22:12:48.000000000 +0200
@@ -118,6 +118,7 @@
   MENU_VIEW_SHOW_UNITS,
   MENU_VIEW_SHOW_FOCUS_UNIT,
   MENU_VIEW_SHOW_FOG_OF_WAR,
+  MENU_VIEW_SHOW_UNITS_IN_CITIES,
   MENU_VIEW_FULL_SCREEN,
   MENU_VIEW_CENTER_VIEW,
 
@@ -397,6 +398,10 @@
     if (draw_fog_of_war ^ GTK_CHECK_MENU_ITEM(widget)->active)
       key_fog_of_war_toggle();
     break;
+  case MENU_VIEW_SHOW_UNITS_IN_CITIES:
+    if (draw_units_in_cities ^ GTK_CHECK_MENU_ITEM(widget)->active)
+      key_units_in_cities_toggle();
+    break;
   case MENU_VIEW_FULL_SCREEN:
     if (fullscreen_mode ^ GTK_CHECK_MENU_ITEM(widget)->active) {
       fullscreen_mode ^= 1;
@@ -862,7 +867,9 @@
   { "/" N_("View") "/" N_("Units"),			NULL,
 	view_menu_callback,	MENU_VIEW_SHOW_UNITS,			"<CheckItem>"	},
   { "/" N_("View") "/" N_("Focus Unit"),		NULL,
-	view_menu_callback,	MENU_VIEW_SHOW_FOCUS_UNIT,		"<CheckItem>"	},
+           view_menu_callback,	MENU_VIEW_SHOW_FOCUS_UNIT,		"<CheckItem>"	},
+  { "/" N_("View") "/" N_("Units in Cities"),		NULL,
+        view_menu_callback,	MENU_VIEW_SHOW_UNITS_IN_CITIES,		"<CheckItem>"	},
   { "/" N_("View") "/" N_("Fog of War"),		NULL,
 	view_menu_callback,	MENU_VIEW_SHOW_FOG_OF_WAR,		"<CheckItem>"	},
   { "/" N_("View") "/sep2",				NULL,
@@ -1463,6 +1470,8 @@
     menus_set_active("<main>/_View/Focus Unit", draw_focus_unit);
     menus_set_sensitive("<main>/_View/Focus Unit", !draw_units);
     menus_set_active("<main>/_View/Fog of War", draw_fog_of_war);
+    menus_set_active("<main>/_View/Units in Cities", draw_units_in_cities);
+    menus_set_sensitive("<main>/_View/Units in Cities", draw_units);
 
     menus_set_active("<main>/_View/_Full Screen", fullscreen_mode);
 
diff -Nur -X.diff_ignore trunk/client/options.c changed/client/options.c
--- trunk/client/options.c	2008-08-02 22:46:10.000000000 +0200
+++ changed/client/options.c	2008-08-10 22:17:14.000000000 +0200
@@ -310,6 +310,7 @@
 bool draw_pollution = TRUE;
 bool draw_cities = TRUE;
 bool draw_units = TRUE;
+bool draw_units_in_cities = TRUE;
 bool draw_focus_unit = FALSE;
 bool draw_fog_of_war = TRUE;
 bool draw_borders = TRUE;
@@ -338,6 +339,7 @@
   VIEW_OPTION(draw_specials),
   VIEW_OPTION(draw_pollution),
   VIEW_OPTION(draw_cities),
+  VIEW_OPTION(draw_units_in_cities),
   VIEW_OPTION(draw_units),
   VIEW_OPTION(draw_focus_unit),
   VIEW_OPTION(draw_fog_of_war),
diff -Nur -X.diff_ignore trunk/client/options.h changed/client/options.h
--- trunk/client/options.h	2008-08-02 22:46:10.000000000 +0200
+++ changed/client/options.h	2008-08-10 22:13:29.000000000 +0200
@@ -160,6 +160,7 @@
 extern bool draw_units;
 extern bool draw_focus_unit;
 extern bool draw_fog_of_war;
+extern bool draw_units_in_cities;
 extern bool draw_borders;
 extern bool draw_full_citybar;
 extern bool draw_unit_shields;
diff -Nur -X.diff_ignore trunk/common/game.c changed/common/game.c
--- trunk/common/game.c	2008-08-02 22:45:57.000000000 +0200
+++ changed/common/game.c	2008-08-10 22:43:54.000000000 +0200
@@ -287,6 +287,7 @@
   game.info.spacerace     = GAME_DEFAULT_SPACERACE;
   game.info.turnblock     = GAME_DEFAULT_TURNBLOCK;
   game.info.fogofwar      = GAME_DEFAULT_FOGOFWAR;
+  game.info.seecitydefender = GAME_DEFAULT_SEECITYDEFENDER;
   game.info.borders_sq    = GAME_DEFAULT_BORDERS;
   game.info.happyborders  = GAME_DEFAULT_HAPPYBORDERS;
   game.info.slow_invasions= GAME_DEFAULT_SLOW_INVASIONS;
diff -Nur -X.diff_ignore trunk/common/game.h changed/common/game.h
--- trunk/common/game.h	2008-08-02 22:45:57.000000000 +0200
+++ changed/common/game.h	2008-08-10 22:42:49.000000000 +0200
@@ -193,6 +193,8 @@
 
 #define GAME_DEFAULT_FOGOFWAR        TRUE
 
+#define GAME_DEFAULT_SEECITYDEFENDER FALSE
+
 /* 0 means no national borders. */
 #define GAME_DEFAULT_BORDERS         (4*4+1*1)
 #define GAME_MIN_BORDERS             0
diff -Nur -X.diff_ignore trunk/common/packets.def changed/common/packets.def
--- trunk/common/packets.def	2008-08-02 22:45:57.000000000 +0200
+++ changed/common/packets.def	2008-08-10 22:44:39.000000000 +0200
@@ -416,7 +416,8 @@
   BOOL turnblock;
   BOOL fixedlength;
   BOOL auto_ai_toggle;
-  BOOL fogofwar;  
+  BOOL fogofwar;
+  BOOL seecitydefender;
   UINT8 borders_sq;
   BOOL happyborders;
   BOOL slow_invasions;
diff -Nur -X.diff_ignore trunk/server/citytools.c changed/server/citytools.c
--- trunk/server/citytools.c	2008-08-02 22:46:03.000000000 +0200
+++ changed/server/citytools.c	2008-08-10 22:33:52.000000000 +0200
@@ -1437,11 +1437,13 @@
   /* After city has been transferred, some players may no longer see inside. */
   players_iterate(pplayer) {
     if (BV_ISSET(saw_entering, player_index(pplayer))
-        && !can_player_see_unit_at(pplayer, punit, pcity->tile)) {
+        && !can_player_see_unit_at(pplayer, punit, pcity->tile)
+        && !can_player_see_city_defender(pplayer, punit)) {
       /* Player saw unit entering, but now unit is hiding inside city */
       unit_goes_out_of_sight(pplayer, punit);
     } else if (!BV_ISSET(saw_entering, player_index(pplayer))
-               && can_player_see_unit_at(pplayer, punit, pcity->tile)) {
+               && (can_player_see_unit_at(pplayer, punit, pcity->tile)
+                   || can_player_see_city_defender(pplayer, punit))) {
       /* Player sees inside cities of new owner */
       send_unit_info_to_onlookers(pplayer->connections, punit,
                                   pcity->tile, FALSE);
diff -Nur -X.diff_ignore trunk/server/savegame.c changed/server/savegame.c
--- trunk/server/savegame.c	2008-08-02 22:46:03.000000000 +0200
+++ changed/server/savegame.c	2008-08-10 22:50:28.000000000 +0200
@@ -3978,6 +3978,7 @@
 
     game.info.fogofwar = secfile_lookup_bool_default(file, FALSE, "game.fogofwar");
     game.fogofwar_old = game.info.fogofwar;
+    game.info.seecitydefender = secfile_lookup_bool_default(file, FALSE, "game.seecitydefender");
   
     game.info.civilwarsize =
       secfile_lookup_int_default(file, GAME_DEFAULT_CIVILWARSIZE,
@@ -4620,6 +4621,8 @@
   secfile_insert_str(file, server.game_identifier, "game.id");
 
   secfile_insert_bool(file, game.info.fogofwar, "game.fogofwar");
+  secfile_insert_bool(file, game.info.seecitydefender, 
+                      "game.seecitydefender");
   secfile_insert_bool(file, game.info.spacerace, "game.spacerace");
   secfile_insert_bool(file, game.info.auto_ai_toggle, "game.auto_ai_toggle");
   secfile_insert_int(file, game.info.diplchance, "game.diplchance");
diff -Nur -X.diff_ignore trunk/server/settings.c changed/server/settings.c
--- trunk/server/settings.c	2008-08-02 22:46:03.000000000 +0200
+++ changed/server/settings.c	2008-08-10 22:47:02.000000000 +0200
@@ -776,6 +776,14 @@
 	      "changes in tiles not observed."), NULL, 
 	   GAME_DEFAULT_FOGOFWAR)
 
+  GEN_BOOL("seecitydefender", game.info.seecitydefender,
+            SSET_RULES, SSET_MILITARY, SSET_RARE, SSET_TO_CLIENT,
+            N_("Strongest unit defending enemy city visible"),
+            N_("If this is set to 1 you you can see the strongest unit of "
+               "other players defending a city. Other units occupying "
+               "the given city will remain hidden, though."), NULL,
+            GAME_DEFAULT_SEECITYDEFENDER)
+
   GEN_INT("diplchance", game.info.diplchance,
 	  SSET_RULES_FLEXIBLE, SSET_MILITARY, SSET_SITUATIONAL, SSET_TO_CLIENT,
 	  N_("Base chance for diplomats and spies to succeed."),
diff -Nur -X.diff_ignore trunk/server/unithand.c changed/server/unithand.c
--- trunk/server/unithand.c	2008-07-27 21:44:04.000000000 +0200
+++ changed/server/unithand.c	2008-08-10 22:29:25.000000000 +0200
@@ -787,10 +787,12 @@
        * Remove the client knowledge of the units.  This corresponds to the
        * send_packet_unit_short_info calls up above.
        */
-      if (!can_player_see_unit(other_player, pattacker)) {
+      if (!can_player_see_unit(other_player, pattacker)
+          && !can_player_see_city_defender(other_player, pattacker)) {
 	unit_goes_out_of_sight(other_player, pattacker);
       }
-      if (!can_player_see_unit(other_player, pdefender)) {
+      if (!can_player_see_unit(other_player, pdefender)
+          && !can_player_see_city_defender(other_player, pdefender)) {
 	unit_goes_out_of_sight(other_player, pdefender);
       }
     }
diff -Nur -X.diff_ignore trunk/server/unittools.c changed/server/unittools.c
--- trunk/server/unittools.c	2008-07-27 21:44:04.000000000 +0200
+++ changed/server/unittools.c	2008-08-10 22:40:15.000000000 +0200
@@ -1586,6 +1586,14 @@
       }
     } unit_list_iterate_safe_end;
   }
+  
+  /* With seecitydefender enabled we need to to send an update wich other
+   * unit is defending this city now the previous one has been wiped out */
+  if (tile_city(ptile) && game.info.seecitydefender) {
+    unit_list_iterate_safe(ptile->units, potherUnits) {
+      send_unit_info(NULL, potherUnits);
+    } unit_list_iterate_safe_end;
+  }
 }
 
 /**************************************************************************
@@ -1929,13 +1937,15 @@
       send_packet_unit_info(pconn, &info);
     } else if (pplayer) {
       bool see_in_old;
-      bool see_in_new = can_player_see_unit_at(pplayer, punit, punit->tile);
+      bool see_in_new = can_player_see_unit_at(pplayer, punit, punit->tile)
+                        || can_player_see_city_defender(pplayer, punit);
 
       if (punit->tile == ptile) {
 	/* This is not about movement */
 	see_in_old = see_in_new;
       } else {
-	see_in_old = can_player_see_unit_at(pplayer, punit, ptile);
+	see_in_old = can_player_see_unit_at(pplayer, punit, ptile)
+                     || can_player_see_city_defender(pplayer, punit);
       }
 
       if (see_in_new || see_in_old) {
@@ -1982,7 +1992,8 @@
 
     players_iterate(unitowner) {
       unit_list_iterate(unitowner->units, punit) {
-	if (!pplayer || can_player_see_unit(pplayer, punit)) {
+	if (!pplayer || can_player_see_unit(pplayer, punit)
+            || can_player_see_city_defender(pplayer, punit)) {
 	  send_unit_info_to_onlookers(pconn->self, punit,
 				      punit->tile, FALSE);
 	}
@@ -2370,6 +2381,44 @@
   }
 }
 
+/****************************************************************************
+  Check if enemy unit should be seen defending a city. If the owner
+  of the unit is not pplayer this will return TRUE only for the
+  single best defending unit of the stack so others should remain hidden
+****************************************************************************/
+bool can_player_see_city_defender(struct player *pplayer, struct unit *punit)
+{
+  if (pplayer == unit_owner(punit)) {
+    return TRUE;
+  }
+  if (game.info.seecitydefender && tile_city(punit->tile)) {
+    if (unit_list_size(punit->tile->units) > 1) {
+      int defValue = get_defense_power(punit);
+      bool same = FALSE;
+      bool first = FALSE;
+      unit_list_iterate(punit->tile->units, prefunit) {
+        if (prefunit == punit) {
+          /* If there are units with the same defensive power present
+          * we just select the first one appearing on the units list */
+          first = !same;
+          continue;
+        }
+        int refValue = get_defense_power(prefunit);
+        if (refValue > defValue) {
+          /* better defender present, abort */
+          return FALSE;
+        } else if (refValue == defValue) {
+          same = TRUE;
+        }
+      } unit_list_iterate_end;
+      return first;
+    } else {
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
 /*****************************************************************
   Check if unit survives enemy autoattacks. We assume that any
   unit that is adjacent to us can see us.
diff -Nur -X.diff_ignore trunk/server/unittools.h changed/server/unittools.h
--- trunk/server/unittools.h	2008-07-27 21:44:04.000000000 +0200
+++ changed/server/unittools.h	2008-08-10 23:09:01.000000000 +0200
@@ -52,6 +52,8 @@
 void unit_list_refresh_vision(struct unit_list *punitlist);
 void pay_for_units(struct player *pplayer, struct city *pcity);
 void bounce_unit(struct unit *punit, bool verbose);
+bool can_player_see_city_defender(struct player *pplayer,
+                                  struct unit *punit);
 
 /* creation/deletion/upgrading */
 void upgrade_unit(struct unit *punit, struct unit_type *to_unit,
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to