Complete.Org: Mailing Lists: Archives: freeciv-dev: June 2004:
[Freeciv-Dev] (PR#8944) settler citymap overlays
Home

[Freeciv-Dev] (PR#8944) settler citymap overlays

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] (PR#8944) settler citymap overlays
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Wed, 9 Jun 2004 19:58:33 -0700
Reply-to: rt@xxxxxxxxxxx

<URL: http://rt.freeciv.org/Ticket/Display.html?id=8944 >

People have often requested a citymap overlay for settlers, so you can 
see their city range.

This patch implements that.  The settler overlay works just like the 
city overlay.  (It also fixes a bad drawing bug in packhand.c, which 
should be fixed separately.)

This is just a demo at this point.  Only gui-gtk-2.0 is supported.

jason

Index: client/control.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/control.c,v
retrieving revision 1.136
diff -u -r1.136 control.c
--- client/control.c    28 May 2004 19:13:07 -0000      1.136
+++ client/control.c    10 Jun 2004 02:56:13 -0000
@@ -1319,7 +1319,18 @@
   if (punit->transported_by == -1) {
     /* We have to refresh the tile before moving.  This will draw
      * the tile without the unit (because it was unlinked above). */
-    refresh_tile_mapcanvas(x, y, FALSE);
+    if (unit_type_flag(punit->type, F_CITIES)) {
+      int width = get_citydlg_canvas_width();
+      int height = get_citydlg_canvas_height();
+      int canvas_x, canvas_y;
+
+      map_to_canvas_pos(&canvas_x, &canvas_y, x, y);
+      update_map_canvas(canvas_x - (width - NORMAL_TILE_WIDTH) / 2,
+                       canvas_y - (height - NORMAL_TILE_HEIGHT) / 2,
+                       width, height);
+    } else {
+      refresh_tile_mapcanvas(x, y, FALSE);
+    }
 
     if (do_animation) {
       int dx, dy;
Index: client/mapview_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.c,v
retrieving revision 1.123
diff -u -r1.123 mapview_common.c
--- client/mapview_common.c     10 Jun 2004 01:04:52 -0000      1.123
+++ client/mapview_common.c     10 Jun 2004 02:56:14 -0000
@@ -842,6 +842,20 @@
                    width, height);
 }
 
+void toggle_unit_color(struct unit *punit)
+{
+  int canvas_x, canvas_y;
+  int width = get_citydlg_canvas_width();
+  int height = get_citydlg_canvas_height();
+
+  punit->client.color = (punit->client.color + 1) % NUM_CITY_COLORS;
+
+  map_to_canvas_pos(&canvas_x, &canvas_y, punit->x, punit->y);
+  update_map_canvas(canvas_x - (width - NORMAL_TILE_WIDTH) / 2,
+                   canvas_y - (height - NORMAL_TILE_HEIGHT) / 2,
+                   width, height);
+}
+
 /****************************************************************************
   Return the vertices of the given edge of the tile.  This will return
   FALSE if the edge doesn't exist (or if it does exist but is part of an
@@ -1467,8 +1481,11 @@
   /* Draw citymap overlays on top. */
   gui_rect_iterate(gui_x0, gui_y0, width, height, map_x, map_y, draw) {
     if (((draw & D_B) || (draw & D_M))
-       && normalize_map_pos(&map_x, &map_y)) {
-      struct city *pcity = find_city_near_tile(map_x, map_y);
+       && normalize_map_pos(&map_x, &map_y)
+       && tile_get_known(map_x, map_y) != TILE_UNKNOWN) {
+      struct unit *punit;
+      struct city *pcity = find_city_or_settler_near_tile(map_x, map_y,
+                                                         &punit);
       int city_x, city_y, canvas_x2, canvas_y2;
 
       if (pcity
@@ -1484,6 +1501,14 @@
          put_city_tile_output(pcity, city_x, city_y,
                               mapview_canvas.store, canvas_x2, canvas_y2);
        }
+      } else if (punit
+                && city_colors[punit->client.color] != COLOR_STD_LAST
+                && map_to_canvas_pos(&canvas_x2, &canvas_y2,
+                                     map_x, map_y)) {
+       /* Draw citymap overlay for settlers. */
+       put_city_worker(mapview_canvas.store,
+                       city_colors[punit->client.color], C_TILE_EMPTY,
+                       canvas_x2, canvas_y2);
       }
     }
   } gui_rect_iterate_end;
@@ -1941,7 +1966,7 @@
 }
 
 /**************************************************************************
-  Find the "best" city to associate with the selected tile.
+  Find the "best" city or settlers to associate with the selected tile.
     a.  A city working the tile is the best
     b.  If another player is working the tile, return NULL.
     c.  If no city is working the tile, choose a city that could work
@@ -1949,12 +1974,20 @@
     d.  If multiple cities could work it, choose the most recently
         "looked at".
     e.  If none of the cities were looked at last, choose "randomly".
-    f.  If no cities can work it, return NULL.
+    f.  If any settlers could work it if they founded a city, choose the
+        closest settler (only if punit != NULL).
+    g.  If no cities or settlers can work it, return NULL.
 **************************************************************************/
-struct city *find_city_near_tile(int x, int y)
+struct city *find_city_or_settler_near_tile(int x, int y,
+                                           struct unit **punit)
 {
   struct city *pcity = map_get_tile(x, y)->worked, *pcity2;
   static struct city *last_pcity = NULL;
+  struct unit *closest_settler = NULL, *best_settler = NULL;
+
+  if (punit) {
+    *punit = NULL;
+  }
 
   if (pcity) {
     if (pcity->owner == game.player_idx) {
@@ -1990,7 +2023,52 @@
 
   /* rule e */
   last_pcity = pcity2;
-  return pcity2;
+  if (pcity2 || !punit) {
+    return pcity2;
+  }
+
+  /* rule f */
+  city_map_iterate_outwards(city_x, city_y) {
+    int new_x = x + city_x - CITY_MAP_RADIUS;
+    int new_y = y + city_y - CITY_MAP_RADIUS;
+
+    if (normalize_map_pos(&new_x, &new_y)) {
+      struct tile *ptile = map_get_tile(new_x, new_y);
+
+      unit_list_iterate(ptile->units, psettler) {
+       if (psettler->owner == game.player_idx
+           && unit_type_flag(psettler->type, F_CITIES)
+           && psettler->transported_by == -1) {
+         if (!closest_settler) {
+           /* The closest settler is the one nearest to the position. */
+           closest_settler = psettler;
+         }
+         if (city_colors[psettler->client.color] != COLOR_STD_LAST
+             && !best_settler) {
+           /* The best settler is the nearest one to the position that
+            * is "active". */
+           best_settler = psettler;
+         }
+       }
+      } unit_list_iterate_end;
+    }
+  } city_map_iterate_outwards_end;
+
+  if (best_settler) {
+    *punit = best_settler;
+  } else {
+    *punit = closest_settler;
+  }
+
+  return NULL;
+}
+
+/**************************************************************************
+  Find the nearest/best city that owns the tile.
+**************************************************************************/
+struct city *find_city_near_tile(int x, int y)
+{
+  return find_city_or_settler_near_tile(x, y, NULL);
 }
 
 /**************************************************************************
Index: client/mapview_common.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.h,v
retrieving revision 1.66
diff -u -r1.66 mapview_common.h
--- client/mapview_common.h     10 Jun 2004 01:04:52 -0000      1.66
+++ client/mapview_common.h     10 Jun 2004 02:56:14 -0000
@@ -258,6 +258,7 @@
                            struct canvas *pcanvas,
                            int canvas_x, int canvas_y);
 void toggle_city_color(struct city *pcity);
+void toggle_unit_color(struct unit *punit);
 void put_red_frame_tile(struct canvas *pcanvas,
                        int canvas_x, int canvas_y);
 
@@ -284,7 +285,9 @@
                             struct unit *punit1, int hp1);
 void move_unit_map_canvas(struct unit *punit,
                          int map_x, int map_y, int dx, int dy);
-                               
+
+struct city *find_city_or_settler_near_tile(int x, int y,
+                                           struct unit **punit);
 struct city *find_city_near_tile(int x, int y);
 
 void get_city_mapview_production(struct city *pcity,
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.378
diff -u -r1.378 packhand.c
--- client/packhand.c   10 Jun 2004 01:04:52 -0000      1.378
+++ client/packhand.c   10 Jun 2004 02:56:14 -0000
@@ -1093,7 +1093,7 @@
 
       /* Show where the unit is going. */
       do_move_unit(punit, packet_unit);
-      if (punit->transported_by != -1) {
+      if (punit->transported_by == -1) {
        repaint_unit = TRUE;
       }
 
@@ -1222,7 +1222,18 @@
   }
 
   if (repaint_unit) {
-    refresh_tile_mapcanvas(punit->x, punit->y, FALSE);
+    if (unit_type_flag(punit->type, F_CITIES)) {
+      int width = get_citydlg_canvas_width();
+      int height = get_citydlg_canvas_height();
+      int canvas_x, canvas_y;
+
+      map_to_canvas_pos(&canvas_x, &canvas_y, punit->x, punit->y);
+      update_map_canvas(canvas_x - (width - NORMAL_TILE_WIDTH) / 2,
+                       canvas_y - (height - NORMAL_TILE_HEIGHT) / 2,
+                       width, height);
+    } else {
+      refresh_tile_mapcanvas(punit->x, punit->y, FALSE);
+    }
   }
 
   if ((check_focus || get_unit_in_focus() == NULL) &&
Index: client/gui-gtk-2.0/mapctrl.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/mapctrl.c,v
retrieving revision 1.40
diff -u -r1.40 mapctrl.c
--- client/gui-gtk-2.0/mapctrl.c        10 Jun 2004 01:04:53 -0000      1.40
+++ client/gui-gtk-2.0/mapctrl.c        10 Jun 2004 02:56:14 -0000
@@ -375,6 +375,7 @@
 {
   int x,y;
   struct city *pcity;
+  struct unit *punit;
 
   if (!can_client_change_view()) {
     return;
@@ -385,13 +386,13 @@
     nearest_real_pos(&x, &y);
   }
 
-  pcity = find_city_near_tile(x, y);
-  if (!pcity) {
-    return;
+  pcity = find_city_or_settler_near_tile(x, y, &punit);
+  if (pcity) {
+    /* Shade tiles on usage */
+    toggle_city_color(pcity);
+  } else if (punit) {
+    toggle_unit_color(punit);
   }
-
-  /* Shade tiles on usage */
-  toggle_city_color(pcity);
 }
 
 
Index: common/unit.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/unit.c,v
retrieving revision 1.210
diff -u -r1.210 unit.c
--- common/unit.c       19 May 2004 00:49:31 -0000      1.210
+++ common/unit.c       10 Jun 2004 02:56:15 -0000
@@ -1724,6 +1724,7 @@
   punit->ord_city = 0;
   set_unit_activity(punit, ACTIVITY_IDLE);
   punit->occupy = 0;
+  punit->client.color = DEFAULT_CITY_COLOR;
   punit->has_orders = FALSE;
 
   return punit;
Index: common/unit.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/unit.h,v
retrieving revision 1.118
diff -u -r1.118 unit.h
--- common/unit.h       19 May 2004 00:49:31 -0000      1.118
+++ common/unit.h       10 Jun 2004 02:56:15 -0000
@@ -172,6 +172,10 @@
 
   int transported_by;
   int occupy; /* number of units that occupy transporter */
+  struct {
+    /* Equivalent to pcity->client.color.  Only for F_CITIES units. */
+    int color;
+  } client;
 
   bool has_orders;
   struct {

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#8944) settler citymap overlays, Jason Short <=