Complete.Org: Mailing Lists: Archives: freeciv-dev: July 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: Sun, 11 Jul 2004 20:58:05 -0700
Reply-to: rt@xxxxxxxxxxx

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

> [jdorje - Thu Jun 10 02:58:32 2004]:
> 
> 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.

Here's an update of the patch.  Still only gtk2 is supported.  This is
easy to fix but I think we should just unify the function instead.

Design people should take a look at this.  I think this interface is
pretty good but I'm sure it could be improved.

Also some changes to the documentation will be necessary.

jason

Index: client/control.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/control.c,v
retrieving revision 1.137
diff -u -r1.137 control.c
--- client/control.c    25 Jun 2004 23:35:55 -0000      1.137
+++ client/control.c    12 Jul 2004 03:56:40 -0000
@@ -1318,7 +1318,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.135
diff -u -r1.135 mapview_common.c
--- client/mapview_common.c     25 Jun 2004 16:38:48 -0000      1.135
+++ client/mapview_common.c     12 Jul 2004 03:56:40 -0000
@@ -902,6 +902,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
@@ -1458,10 +1472,13 @@
 
   /* Draw citymap overlays on top. */
   gui_rect_iterate(gui_x0, gui_y0, width, height, map_x, map_y) {
-    if (normalize_map_pos(&map_x, &map_y)) {
-      struct city *pcity = find_city_near_tile(map_x, map_y);
+    if (normalize_map_pos(&map_x, &map_y)
+       && tile_get_known(map_x, map_y) != TILE_UNKNOWN) {
+      struct unit *punit;
+      struct city *pcity;
       int city_x, city_y, canvas_x2, canvas_y2;
 
+      pcity = find_city_or_settler_near_tile(map_x, map_y, &punit);
       if (pcity
          && city_colors[pcity->client.color] != COLOR_STD_LAST
          && map_to_city_map(&city_x, &city_y, pcity, map_x, map_y)
@@ -1475,6 +1492,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;
@@ -1841,16 +1866,26 @@
 }
 
 /**************************************************************************
-  Find the "best" city to associate with the selected tile.
+  Find the "best" city/settlers to associate with the selected tile.
     a.  If a city is working the tile, return that city.
     b.  If another player's city is working the tile, return NULL.
     c.  If any selected cities are within range, return the closest one.
     d.  If any cities are within range, return the closest one.
-    e.  If nobody can work it, return NULL.
+    e.  If any active (with color) settler could work it if they founded a
+        city, choose the closest one (only if punit != NULL).
+    f.  If any settler could work it if they founded a city, choose the
+        closest one (only if punit != NULL).
+    g.  If nobody 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, *closest_city;
+  struct unit *closest_settler = NULL, *best_settler = NULL;
+
+  if (punit) {
+    *punit = NULL;
+  }
 
   if (pcity) {
     if (pcity->owner == game.player_idx) {
@@ -1888,7 +1923,49 @@
   } city_map_checked_iterate_end;
 
   /* rule d */
-  return closest_city;
+  if (closest_city || !punit) {
+    return closest_city;
+  }
+
+  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
+           && city_can_be_built_here(psettler->x, psettler->y, psettler)) {
+         if (!closest_settler) {
+           closest_settler = psettler;
+         }
+         if (!best_settler && psettler->client.color != 0) {
+           best_settler = psettler;
+         }
+       }
+      } unit_list_iterate_end;
+    }
+  } city_map_iterate_outwards_end;
+
+  if (best_settler) {
+    /* Rule e */
+    *punit = best_settler;
+  } else if (closest_settler) {
+    /* Rule f */
+    *punit = closest_settler;
+  }
+
+  /* rule g */
+  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.70
diff -u -r1.70 mapview_common.h
--- client/mapview_common.h     25 Jun 2004 13:53:25 -0000      1.70
+++ client/mapview_common.h     12 Jul 2004 03:56:40 -0000
@@ -153,6 +153,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);
 
@@ -178,7 +179,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.386
diff -u -r1.386 packhand.c
--- client/packhand.c   11 Jul 2004 15:05:55 -0000      1.386
+++ client/packhand.c   12 Jul 2004 03:56:41 -0000
@@ -1228,7 +1228,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        12 Jul 2004 03:56:41 -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.211
diff -u -r1.211 unit.c
--- common/unit.c       25 Jun 2004 23:29:59 -0000      1.211
+++ common/unit.c       12 Jul 2004 03:56:42 -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       12 Jul 2004 03:56:42 -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]