Complete.Org: Mailing Lists: Archives: freeciv-dev: November 2003:
[Freeciv-Dev] (PR#6948) Quickselect unit
Home

[Freeciv-Dev] (PR#6948) Quickselect unit

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] (PR#6948) Quickselect unit
From: "Arnstein Lindgard" <a-l@xxxxxxx>
Date: Tue, 25 Nov 2003 09:28:26 -0800
Reply-to: rt@xxxxxxxxxxx

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

Feature: Quickselect a unit from a tile, bypassing stack or city
popups. Gtk[12] and xaw.

Use <control> left/right click, for sea/land units. Priorities:

SEA:  Transporter
      Sea unit
      Any unit

LAND: Military land unit
      Non-combatant
      Sea unit
      Any unit

Units with moves left before exhausted. Focus unit is excluded.
Repeat click to get another unit.

It's a simple patch which is enormously useful for tactical
situations in multiplayer, and otherwise convenient.


Arnstein


diff -ruN -Xdiff_ignore freeciv/client/control.c quickselect/client/control.c
--- freeciv/client/control.c    Sat Nov 22 23:37:20 2003
+++ quickselect/client/control.c        Mon Nov 24 23:54:27 2003
@@ -73,6 +73,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);
 
 /**************************************************************************
 ...
@@ -1298,7 +1300,7 @@
 /**************************************************************************
  Handles everything when the user clicked a tile
 **************************************************************************/
-void do_map_click(int xtile, int ytile)
+void do_map_click(int xtile, int ytile, enum quickselect_type qtype)
 {
   struct city *pcity = map_get_city(xtile, ytile);
   struct tile *ptile = map_get_tile(xtile, ytile);
@@ -1336,7 +1338,18 @@
     update_unit_info_label(punit);
     return;
   }
-  
+
+  /* Bypass stack popup if quickselect is specified. */
+  if (qtype) {
+    struct unit *qunit = quickselect(ptile, qtype);
+    if (qunit) {
+      set_unit_focus_and_select(qunit);
+    }
+    return;
+  }
+
+  /* Otherwise use popups. */
+
   if (pcity && game.player_idx==pcity->owner) {
     popup_city_dialog(pcity, FALSE);
     return;
@@ -1365,6 +1378,104 @@
 }
 
 /**************************************************************************
+ Quickselecting a unit is normally done with <control> left/right click.
+ Bypassing the stack popup is quite convenient, and can be tactically
+ important in furious multiplayer games.
+**************************************************************************/
+static struct unit *quickselect(struct tile *ptile,
+                          enum quickselect_type qtype)
+{
+  int listsize = unit_list_size(&ptile->units);
+  struct unit *panytransporter = NULL,
+              *panymovesea  = NULL, *panysea  = NULL,
+              *panymoveland = NULL, *panyland = NULL,
+              *panymoveunit = NULL, *panyunit = NULL;
+
+  assert(qtype > SELECT_POPUP);
+
+  if (listsize == 0) {
+    return NULL;
+  } else if (listsize == 1) {
+    struct unit *punit = unit_list_get(&ptile->units, 0);
+    return (game.player_idx == punit->owner) ? punit : NULL;
+  }
+
+  /*  Quickselect priorities. Units with moves left
+   *  before exhausted. Focus unit is excluded.
+   *
+   *    SEA:  Transporter
+   *          Sea unit
+   *          Any unit
+   *
+   *    LAND: Military land unit
+   *          Non-combatant
+   *          Sea unit
+   *          Any unit
+   */
+
+  unit_list_iterate(ptile->units, punit)  {
+  if(game.player_idx != punit->owner || punit == punit_focus) {
+    continue;
+  }
+  if (qtype == SELECT_SEA) {
+    /* transporter */
+    if (get_transporter_capacity(punit)) {
+      if (punit->moves_left > 0)
+        return punit;
+      else if (!panytransporter)
+        panytransporter = punit;
+    }
+    /* any sea, pref. moves left */
+    else if (is_sailing_unit(punit)) {
+      if (punit->moves_left > 0) {
+        if (!panymovesea)
+          panymovesea = punit;
+      } else if (!panysea)
+          panysea = punit;
+    }
+  } else if (qtype == SELECT_LAND) {
+    if (is_ground_unit(punit))  {
+      if (punit->moves_left > 0) {
+        if (is_military_unit(punit)) {
+          return punit;
+        } else if (!panymoveland)
+            panymoveland = punit;
+      }
+      else if (!panyland)
+        panyland = punit;
+    }
+    else if (is_sailing_unit(punit)) {
+      if (punit->moves_left > 0)
+        panymovesea = punit;
+      else
+        panysea = punit;
+    }
+  }
+  if (punit->moves_left > 0 && !panymoveunit)
+    panymoveunit = punit;
+  if (!panyunit)
+    panyunit = punit;
+  } unit_list_iterate_end;
+
+  if (qtype == SELECT_SEA) {
+    if      (panytransporter) return panytransporter;
+    else if (panymovesea)     return panymovesea;
+    else if (panysea)         return panysea;
+    else if (panymoveunit)    return panymoveunit;
+    else if (panyunit)        return panyunit;
+  }
+  else if (qtype == SELECT_LAND) {
+    if      (panymoveland)    return panymoveland;
+    else if (panyland)        return panyland;
+    else if (panymovesea)     return panymovesea;
+    else if (panysea)         return panysea;
+    else if (panymoveunit)    return panymoveunit;
+    else if (panyunit)        return panyunit;
+  }
+  return NULL;
+}
+
+/**************************************************************************
  Finish the goto mode and let the unit which is stored in hover_unit move
  to a given location.
 **************************************************************************/
diff -ruN -Xdiff_ignore freeciv/client/control.h quickselect/client/control.h
--- freeciv/client/control.h    Wed Nov 19 18:32:57 2003
+++ quickselect/client/control.h        Mon Nov 24 22:34:56 2003
@@ -24,6 +24,11 @@
   HOVER_PATROL
 };
 
+/* Selecting unit from a stack without popup. */
+enum quickselect_type {
+  SELECT_POPUP = 0, SELECT_SEA, SELECT_LAND
+};
+
 extern int hover_unit; /* unit hover_state applies to */
 extern enum cursor_hover_state hover_state;
 extern bool draw_goto_line;
@@ -34,7 +39,7 @@
 void do_unit_nuke(struct unit *punit);
 void do_unit_paradrop_to(struct unit *punit, int x, int y);
 void do_unit_patrol_to(struct unit *punit, int x, int y);
-void do_map_click(int xtile, int ytile);
+void do_map_click(int xtile, int ytile, enum quickselect_type qtype);
 
 void set_hover_state(struct unit *punit, enum cursor_hover_state state);
 void request_center_focus_unit(void);
diff -ruN -Xdiff_ignore freeciv/client/gui-gtk/mapctrl.c 
quickselect/client/gui-gtk/mapctrl.c
--- freeciv/client/gui-gtk/mapctrl.c    Fri Nov 14 13:30:55 2003
+++ quickselect/client/gui-gtk/mapctrl.c        Mon Nov 24 21:58:33 2003
@@ -226,6 +226,10 @@
     if ((ev->state & GDK_SHIFT_MASK) && (ev->state & GDK_CONTROL_MASK)) {
       adjust_workers_button_pressed(ev->x, ev->y);
     }
+    /* <CONTROL> + LMB : Quickselect a sea unit. */
+    else if (ev->state & GDK_CONTROL_MASK) {
+      action_button_pressed(ev->x, ev->y, SELECT_SEA);
+    }
     /* <SHIFT> + LMB: Copy Production. */
     else if(is_real && (ev->state & GDK_SHIFT_MASK)) {
       clipboard_copy_production(xtile, ytile);
@@ -238,9 +242,7 @@
     }
     /* Plain LMB click. */
     else {
-      if (is_real) {
-        action_button_pressed(ev->x, ev->y);
-      }
+      action_button_pressed(ev->x, ev->y, SELECT_POPUP);
     }
     break;
 
@@ -258,8 +260,12 @@
 
   case 3: /* RIGHT mouse button */
 
+    /* <CONTROL> + RMB : Quickselect a land unit. */
+    if (ev->state & GDK_CONTROL_MASK) {
+      action_button_pressed(ev->x, ev->y, SELECT_LAND);
+    }
     /* <SHIFT> + RMB: Paste Production. */
-    if(ev->state & GDK_SHIFT_MASK) {
+    else if(ev->state & GDK_SHIFT_MASK) {
       clipboard_paste_production(pcity);
       cancel_tile_hiliting();
     }
diff -ruN -Xdiff_ignore freeciv/client/gui-gtk-2.0/mapctrl.c 
quickselect/client/gui-gtk-2.0/mapctrl.c
--- freeciv/client/gui-gtk-2.0/mapctrl.c        Fri Nov 14 13:30:56 2003
+++ quickselect/client/gui-gtk-2.0/mapctrl.c    Mon Nov 24 23:11:01 2003
@@ -206,6 +206,10 @@
     if ((ev->state & GDK_SHIFT_MASK) && (ev->state & GDK_CONTROL_MASK)) {
       adjust_workers_button_pressed(ev->x, ev->y);
     }
+    /* <CONTROL> + LMB : Quickselect a sea unit. */
+    else if (ev->state & GDK_CONTROL_MASK) {
+      action_button_pressed(ev->x, ev->y, SELECT_SEA);
+    }
     /* <SHIFT> + LMB: Copy Production. */
     else if(is_real && (ev->state & GDK_SHIFT_MASK)) {
       clipboard_copy_production(xtile, ytile);
@@ -218,9 +222,7 @@
     }
     /* Plain LMB click. */
     else {
-      if (is_real) {
-        action_button_pressed(ev->x, ev->y);
-      }
+      action_button_pressed(ev->x, ev->y, SELECT_POPUP);
     }
     break;
 
@@ -238,8 +240,12 @@
 
   case 3: /* RIGHT mouse button */
 
+    /* <CONTROL> + RMB : Quickselect a land unit. */
+    if (ev->state & GDK_CONTROL_MASK) {
+      action_button_pressed(ev->x, ev->y, SELECT_LAND);
+    }
     /* <SHIFT> + RMB: Paste Production. */
-    if(ev->state & GDK_SHIFT_MASK) {
+    else if(ev->state & GDK_SHIFT_MASK) {
       clipboard_paste_production(pcity);
       cancel_tile_hiliting();
     }
diff -ruN -Xdiff_ignore freeciv/client/gui-sdl/mapctrl.c 
quickselect/client/gui-sdl/mapctrl.c
--- freeciv/client/gui-sdl/mapctrl.c    Fri Nov 14 13:30:56 2003
+++ quickselect/client/gui-sdl/mapctrl.c        Mon Nov 24 23:12:45 2003
@@ -1888,7 +1888,7 @@
        }                     
       }
     } else {
-      action_button_pressed(pButtonEvent->x, pButtonEvent->y);
+      action_button_pressed(pButtonEvent->x, pButtonEvent->y, SELECT_POPUP);
     }
   } else {
     if (pButtonEvent->button == SDL_BUTTON_MIDDLE) {
diff -ruN -Xdiff_ignore freeciv/client/gui-win32/mapctrl.c 
quickselect/client/gui-win32/mapctrl.c
--- freeciv/client/gui-win32/mapctrl.c  Fri Nov 14 13:30:56 2003
+++ quickselect/client/gui-win32/mapctrl.c      Mon Nov 24 23:13:47 2003
@@ -238,7 +238,7 @@
                                    LOWORD(lParam), HIWORD(lParam))) {
       popit(LOWORD(lParam),HIWORD(lParam),xtile,ytile);
     } else {
-      action_button_pressed(LOWORD(lParam), HIWORD(lParam));
+      action_button_pressed(LOWORD(lParam), HIWORD(lParam), SELECT_POPUP);
     }
     break;
   case WM_MBUTTONDOWN:
diff -ruN -Xdiff_ignore freeciv/client/gui-xaw/mapctrl.c 
quickselect/client/gui-xaw/mapctrl.c
--- freeciv/client/gui-xaw/mapctrl.c    Fri Nov 14 13:30:56 2003
+++ quickselect/client/gui-xaw/mapctrl.c        Mon Nov 24 23:35:01 2003
@@ -207,11 +207,15 @@
     return;
   }
 
-  if (ev->button == Button1) {
-    action_button_pressed(ev->x, ev->y);
-  } else if (canvas_to_map_pos(&x, &y, ev->x, ev->y)
-            && (ev->button == Button2 || ev->state & ControlMask)) {
+  if (ev->button == Button1 && (ev->state & ControlMask)) {
+    action_button_pressed(ev->x, ev->y, SELECT_SEA);
+  } else if (ev->button == Button1) {
+    action_button_pressed(ev->x, ev->y, SELECT_POPUP);
+  } else if (ev->button == Button2 &&
+             canvas_to_map_pos(&x, &y, ev->x, ev->y)) {
     popit(ev->x, ev->y, x, y);
+  } else if (ev->button == Button3 && (ev->state & ControlMask)) {
+    action_button_pressed(ev->x, ev->y, SELECT_LAND);
   } else if (ev->button == Button3) {
     recenter_button_pressed(ev->x, ev->y);
   }
diff -ruN -Xdiff_ignore freeciv/client/mapctrl_common.c 
quickselect/client/mapctrl_common.c
--- freeciv/client/mapctrl_common.c     Mon Nov 17 19:27:28 2003
+++ quickselect/client/mapctrl_common.c Mon Nov 24 21:54:11 2003
@@ -423,7 +423,8 @@
   left-click) is pressed.  For more sophisticated user control use (or
   write) a different xxx_button_pressed function.
 **************************************************************************/
-void action_button_pressed(int canvas_x, int canvas_y)
+void action_button_pressed(int canvas_x, int canvas_y,
+                enum quickselect_type qtype)
 {
   int map_x, map_y;
 
@@ -431,7 +432,7 @@
     /* FIXME: Some actions here will need to check can_client_issue_orders.
      * But all we can check is the lowest common requirement. */
     if (canvas_to_map_pos(&map_x, &map_y, canvas_x, canvas_y)) {
-      do_map_click(map_x, map_y);
+      do_map_click(map_x, map_y, qtype);
     }
   }
 }
diff -ruN -Xdiff_ignore freeciv/client/mapctrl_common.h 
quickselect/client/mapctrl_common.h
--- freeciv/client/mapctrl_common.h     Fri Nov 14 13:30:54 2003
+++ quickselect/client/mapctrl_common.h Mon Nov 24 22:36:26 2003
@@ -17,6 +17,8 @@
 #include "map.h"               /* enum direction8 */
 #include "shared.h"            /* bool type */
 
+#include "control.h"            /* quickselect_type */
+
 extern bool rbutton_down;
 extern bool rectangle_active;
 extern bool tiles_hilited_cities;
@@ -34,7 +36,8 @@
 void release_right_button(int canvas_x, int canvas_y);
 bool get_turn_done_button_state(void);
 void scroll_mapview(enum direction8 gui_dir);
-void action_button_pressed(int canvas_x, int canvas_y);
+void action_button_pressed(int canvas_x, int canvas_y,
+                enum quickselect_type qtype);
 void wakeup_button_pressed(int canvas_x, int canvas_y);
 void adjust_workers_button_pressed(int canvas_x, int canvas_y);
 void recenter_button_pressed(int canvas_x, int canvas_y);

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#6948) Quickselect unit, Arnstein Lindgard <=