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

Apparently, I forgot to attach the patch....  Here's S2_2 at the
current revision:

Index: client/control.c
===================================================================
--- client/control.c    (revision 13927)
+++ client/control.c    (working copy)
@@ -50,14 +50,17 @@
 /* gui-dep code may adjust depending on tile size etc: */
 int num_units_below = MAX_NUM_UNITS_BELOW;
 
-/* unit_focus points to the current unit in focus */
-static struct unit_list *pfocus_units;
+/* current_focus points to the current unit(s) in focus */
+static struct unit_list *current_focus;
 
-/* The previously focused unit.  Focus can generally be recalled on this
- * unit with keypad 5.  FIXME: this is not reset when the client
- * disconnects. */
+/* The previously focused unit(s).  Focus can generally be recalled
+ * with keypad 5 (or the equivalent). 
+ * FIXME: this is not reset when the client disconnects. */
 static struct unit_list *previous_focus;
 
+/* The priority focused unit(s). */
+static struct unit_list *priority_focus;
+
 /* These should be set via set_hover_state() */
 enum cursor_hover_state hover_state = HOVER_NONE;
 struct tile *hover_tile = NULL;
@@ -83,9 +86,8 @@
 /*************************************************************************/
 
 static struct unit *find_best_focus_candidate(bool accept_current);
-static void store_focus(void);
 static struct unit *quickselect(struct tile *ptile,
-                        enum quickselect_type qtype);
+                                enum quickselect_type qtype);
 
 /**************************************************************************
   Called only by main() in client/civclient.c.
@@ -96,8 +98,11 @@
 
   caravan_arrival_queue = genlist_new();
   diplomat_arrival_queue = genlist_new();
-  pfocus_units = unit_list_new();
+
+  current_focus = unit_list_new();
   previous_focus = unit_list_new();
+  priority_focus = unit_list_new();
+
   for (i = 0; i < MAX_NUM_BATTLEGROUPS; i++) {
     battlegroups[i] = unit_list_new();
   }
@@ -112,14 +117,55 @@
 
   genlist_free(caravan_arrival_queue);
   genlist_free(diplomat_arrival_queue);
-  unit_list_free(pfocus_units);
+
+  unit_list_free(current_focus);
   unit_list_free(previous_focus);
+  unit_list_free(priority_focus);
+
   for (i = 0; i < MAX_NUM_BATTLEGROUPS; i++) {
     unit_list_free(battlegroups[i]);
   }
 }
 
 /**************************************************************************
+...
+**************************************************************************/
+struct unit_list *get_units_in_focus(void)
+{
+  return current_focus;
+}
+
+/****************************************************************************
+  Return the number of units currently in focus (0 or more).
+****************************************************************************/
+int get_num_units_in_focus(void)
+{
+  return unit_list_size(current_focus);
+}
+
+/**************************************************************************
+  Store the focus unit(s).  This is used so that we can return to the
+  previously focused unit with an appropriate keypress.
+**************************************************************************/
+static void store_previous_focus(void)
+{
+  if (get_num_units_in_focus() > 0) {
+    unit_list_unlink_all(previous_focus);
+    unit_list_iterate(get_units_in_focus(), punit) {
+      unit_list_append(previous_focus, punit);
+    } unit_list_iterate_end;
+  }
+}
+
+/****************************************************************************
+  Store a priority focus unit.
+****************************************************************************/
+void urgent_unit_focus(struct unit *punit)
+{
+  unit_list_append(priority_focus, punit);
+}
+
+/**************************************************************************
   Called when a unit is killed; this removes it from the control lists.
 **************************************************************************/
 void control_unit_killed(struct unit *punit)
@@ -127,12 +173,16 @@
   int i;
 
   goto_unit_killed(punit);
+
   unit_list_unlink(get_units_in_focus(), punit);
   if (get_num_units_in_focus() < 1) {
     set_hover_state(NULL, HOVER_NONE, ACTIVITY_LAST, ORDER_LAST);
   }
   update_unit_info_label(get_units_in_focus());
+
   unit_list_unlink(previous_focus, punit);
+  unit_list_unlink(priority_focus, punit);
+
   for (i = 0; i < MAX_NUM_BATTLEGROUPS; i++) {
     unit_list_unlink(battlegroups[i], punit);
   }
@@ -216,7 +266,7 @@
 ****************************************************************************/
 struct unit *head_of_units_in_focus(void)
 {
-  return unit_list_get(pfocus_units, 0);
+  return unit_list_get(current_focus, 0);
 }
 
 /****************************************************************************
@@ -249,6 +299,28 @@
 }
 
 /**************************************************************************
+  ...
+**************************************************************************/
+static void current_focus_append(struct unit *punit)
+{
+  unit_list_append(current_focus, punit);
+
+  punit->focus_status = FOCUS_AVAIL;
+  refresh_unit_mapcanvas(punit, punit->tile, TRUE, FALSE);
+
+  if (unit_has_orders(punit)) {
+    /* Clear the focus unit's orders. */
+    request_orders_cleared(punit);
+  }
+
+  if (punit->activity != ACTIVITY_IDLE || punit->ai.control)  {
+    punit->ai.control = FALSE;
+    refresh_unit_city_dialogs(punit);
+    request_new_unit_activity(punit, ACTIVITY_IDLE);
+  }
+}
+
+/**************************************************************************
   Sets the focus unit directly.  The unit given will be given the
   focus; if NULL the focus will be cleared.
 
@@ -270,19 +342,16 @@
    * solution would be a set_units_focus() */
   if (!(get_num_units_in_focus() == 1
        && punit == head_of_units_in_focus())) {
-    store_focus();
+    store_previous_focus();
     focus_changed = TRUE;
   }
 
   /* Redraw the old focus unit (to fix blinking or remove the selection
    * circle). */
-  unit_list_iterate(pfocus_units, punit_old) {
+  unit_list_iterate(current_focus, punit_old) {
     refresh_unit_mapcanvas(punit_old, punit_old->tile, TRUE, FALSE);
   } unit_list_iterate_end;
-  unit_list_unlink_all(pfocus_units);
-  if (punit) {
-    unit_list_append(pfocus_units, punit);
-  }
+  unit_list_unlink_all(current_focus);
 
   if (!can_client_change_view()) {
     /* This function can be called to set the focus to NULL when
@@ -291,28 +360,16 @@
     return;
   }
 
-  if(punit) {
+  if (NULL != punit) {
     auto_center_on_focus_unit();
-
-    punit->focus_status=FOCUS_AVAIL;
-    refresh_unit_mapcanvas(punit, punit->tile, TRUE, FALSE);
-
-    if (unit_has_orders(punit)) {
-      /* Clear the focus unit's orders. */
-      request_orders_cleared(punit);
-    }
-    if (punit->activity != ACTIVITY_IDLE || punit->ai.control)  {
-      punit->ai.control = FALSE;
-      refresh_unit_city_dialogs(punit);
-      request_new_unit_activity(punit, ACTIVITY_IDLE);
-    }
+    current_focus_append(punit);
   }
 
   if (focus_changed) {
     set_hover_state(NULL, HOVER_NONE, ACTIVITY_LAST, ORDER_LAST);
   }
 
-  update_unit_info_label(pfocus_units);
+  update_unit_info_label(current_focus);
   update_menus();
 }
 
@@ -338,19 +395,8 @@
     set_hover_state(NULL, HOVER_NONE, ACTIVITY_LAST, ORDER_LAST);
   }
 
-  unit_list_append(pfocus_units, punit);
-  punit->focus_status = FOCUS_AVAIL;
-  refresh_unit_mapcanvas(punit, punit->tile, TRUE, FALSE);
-  if (unit_has_orders(punit)) {
-    /* Clear the focus unit's orders. */
-    request_orders_cleared(punit);
-  }
-  if (punit->activity != ACTIVITY_IDLE || punit->ai.control)  {
-    punit->ai.control = FALSE;
-    refresh_unit_city_dialogs(punit);
-    request_new_unit_activity(punit, ACTIVITY_IDLE);
-  }
-  update_unit_info_label(pfocus_units);
+  current_focus_append(punit);
+  update_unit_info_label(current_focus);
   update_menus();
 }
 
@@ -366,20 +412,6 @@
 }
 
 /**************************************************************************
-  Store the focus unit.  This is used so that we can return to the
-  previously focused unit with an appropriate keypress.
-**************************************************************************/
-static void store_focus(void)
-{
-  if (get_num_units_in_focus() > 0) {
-    unit_list_unlink_all(previous_focus);
-    unit_list_iterate(get_units_in_focus(), punit) {
-      unit_list_append(previous_focus, punit);
-    } unit_list_iterate_end;
-  }
-}
-
-/**************************************************************************
 If there is no unit currently in focus, or if the current unit in
 focus should not be in focus, then get a new focus unit.
 We let GOTO-ing units stay in focus, so that if they have moves left
@@ -415,22 +447,6 @@
 }
 
 /**************************************************************************
-...
-**************************************************************************/
-struct unit_list *get_units_in_focus(void)
-{
-  return pfocus_units;
-}
-
-/****************************************************************************
-  Return the number of units currently in focus (0 or more).
-****************************************************************************/
-int get_num_units_in_focus(void)
-{
-  return unit_list_size(pfocus_units);
-}
-
-/**************************************************************************
  This function may be called from packhand.c, via update_unit_focus(),
  as a result of packets indicating change in activity for a unit. Also
  called when user press the "Wait" command.
@@ -439,10 +455,12 @@
 **************************************************************************/
 void advance_unit_focus(void)
 {
+  struct unit *candidate = NULL;
   const int num_units_in_old_focus = get_num_units_in_focus();
-  struct unit *candidate = find_best_focus_candidate(FALSE);
 
-  if (!game.player_ptr || !can_client_change_view()) {
+  if (!game.player_ptr
+      || !is_player_phase(game.player_ptr, game.info.phase)
+      || !can_client_change_view()) {
     set_unit_focus(NULL);
     return;
   }
@@ -460,19 +478,44 @@
     }
   } unit_list_iterate_end;
 
-  if(!candidate) {
-    /* First try for "waiting" units. */
-    unit_list_iterate(game.player_ptr->units, punit) {
-      if(punit->focus_status == FOCUS_WAIT) {
-        punit->focus_status = FOCUS_AVAIL;
-      }
-    } unit_list_iterate_end;
+  if (unit_list_size(priority_focus) > 0) {
+    /* Try top of the urgent list. */
+    candidate = unit_list_get(priority_focus, 0);
+
+    if (get_num_units_in_focus() > 0) {
+      /* Rarely, more than one unit on the same tile will be in the list. */
+      unit_list_iterate(priority_focus, punit) {
+        if (head_of_units_in_focus()->tile == punit->tile) {
+          /* Use the first one found */
+          candidate = punit;
+          break;
+        }
+      } unit_list_iterate_end;
+    }
+    unit_list_unlink(priority_focus, candidate);
+
+    /* Autocenter on Wakeup, regardless of the local option 
+     * "auto_center_on_unit". */
+    if (!tile_visible_and_not_on_border_mapcanvas(candidate->tile)) {
+      center_tile_mapcanvas(candidate->tile);
+    }
+  } else {
     candidate = find_best_focus_candidate(FALSE);
-  }
 
-  /* Accept current focus unit as last resort. */
-  if (!candidate) {
-    candidate = find_best_focus_candidate(TRUE);
+    if (!candidate) {
+      /* Try for "waiting" units. */
+      unit_list_iterate(game.player_ptr->units, punit) {
+        if(punit->focus_status == FOCUS_WAIT) {
+          punit->focus_status = FOCUS_AVAIL;
+        }
+      } unit_list_iterate_end;
+      candidate = find_best_focus_candidate(FALSE);
+
+      if (!candidate) {
+        /* Accept current focus unit as last resort. */
+        candidate = find_best_focus_candidate(TRUE);
+      }
+    }
   }
 
   set_unit_focus(candidate);
@@ -500,12 +543,6 @@
 {
   struct tile *ptile = get_center_tile_mapcanvas();
 
-  if (!game.player_ptr
-      || !is_player_phase(game.player_ptr, game.info.phase)) {
-    /* No focus unit wanted. */
-    return NULL;
-  }
-
   if (!get_focus_unit_on_tile(ptile)) {
     struct unit *pfirst = head_of_units_in_focus();
 
@@ -1147,6 +1184,23 @@
 }
 
 /**************************************************************************
+  ...
+**************************************************************************/
+void wakeup_sentried_units(struct tile *ptile)
+{
+  if (!can_client_issue_orders()) {
+    return;
+  }
+  unit_list_iterate(ptile->units, punit) {
+    if (punit->activity == ACTIVITY_SENTRY
+       && game.player_ptr == unit_owner(punit)) {
+      request_new_unit_activity(punit, ACTIVITY_IDLE);
+    }
+  }
+  unit_list_iterate_end;
+}
+
+/**************************************************************************
 (RP:) un-sentry all my own sentried units on punit's tile
 **************************************************************************/
 void request_unit_wakeup(struct unit *punit)
@@ -1222,23 +1276,6 @@
 }
 
 /**************************************************************************
-  ...
-**************************************************************************/
-void wakeup_sentried_units(struct tile *ptile)
-{
-  if (!can_client_issue_orders()) {
-    return;
-  }
-  unit_list_iterate(ptile->units, punit) {
-    if (punit->activity == ACTIVITY_SENTRY
-       && game.player_ptr == unit_owner(punit)) {
-      request_new_unit_activity(punit, ACTIVITY_IDLE);
-    }
-  }
-  unit_list_iterate_end;
-}
-
-/**************************************************************************
 Player pressed 'b' or otherwise instructed unit to build or add to city.
 If the unit can build a city, we popup the appropriate dialog.
 Otherwise, we just send a packet to the server.
@@ -2018,7 +2055,7 @@
  convenient, and can be tactically important in furious multiplayer games.
 **************************************************************************/
 static struct unit *quickselect(struct tile *ptile,
-                          enum quickselect_type qtype)
+                                enum quickselect_type qtype)
 {
   int listsize = unit_list_size(ptile->units);
   struct unit *panytransporter = NULL,
@@ -2247,7 +2284,7 @@
 }
 
 /**************************************************************************
-  Recall the previous focus unit and focus on it.  See store_focus().
+  Recall the previous focus unit(s).  See store_previous_focus().
 **************************************************************************/
 void key_recall_previous_focus_unit(void)
 {
Index: client/control.h
===================================================================
--- client/control.h    (revision 13927)
+++ client/control.h    (working copy)
@@ -119,19 +119,23 @@
 bool unit_is_in_focus(const struct unit *punit);
 struct unit *get_focus_unit_on_tile(const struct tile *ptile);
 struct unit *head_of_units_in_focus(void);
-void auto_center_on_focus_unit(void);
-void advance_unit_focus(void);
 struct unit_list *get_units_in_focus(void);
 int get_num_units_in_focus(void);
+
 void set_unit_focus(struct unit *punit);
+void set_unit_focus_and_select(struct unit *punit);
 void add_unit_focus(struct unit *punit);
-void set_unit_focus_and_select(struct unit *punit);
+void urgent_unit_focus(struct unit *punit);
+
+void advance_unit_focus(void);
+void auto_center_on_focus_unit(void);
 void update_unit_focus(void);
+void update_unit_pix_label(struct unit_list *punitlist);
+
 struct unit *find_visible_unit(struct tile *ptile);
 void set_units_in_combat(struct unit *pattacker, struct unit *pdefender);
 double blink_active_unit(void);
 double blink_turn_done_button(void);
-void update_unit_pix_label(struct unit_list *punitlist);
 
 void process_caravan_arrival(struct unit *punit);
 void process_diplomat_arrival(struct unit *pdiplomat, int victim_id);
Index: client/packhand.c
===================================================================
--- client/packhand.c   (revision 13927)
+++ client/packhand.c   (working copy)
@@ -1109,17 +1109,10 @@
           && unit_owner(punit) == game.player_ptr
           && punit->activity == ACTIVITY_SENTRY
           && packet_unit->activity == ACTIVITY_IDLE
-         && is_player_phase(game.player_ptr, game.info.phase)
-              /* only 1 wakeup focus per tile is useful */
-          && !get_focus_unit_on_tile(packet_unit->tile)) {
-        set_unit_focus(punit);
+         && is_player_phase(game.player_ptr, game.info.phase)) {
+        /* many wakeup units per tile are handled */
+        urgent_unit_focus(punit);
         check_focus = FALSE; /* and keep it */
-
-        /* Autocenter on Wakeup, regardless of the local option 
-         * "auto_center_on_unit". */
-        if (!tile_visible_and_not_on_border_mapcanvas(punit->tile)) {
-          center_tile_mapcanvas(punit->tile);
-        }
       }
 
       punit->activity = packet_unit->activity;
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to