foxygit / doom Log in
commit 6d6375349747e1870f9c74bc950bfd25b6bb2b51
Author:     Simon Howard <fraggle@soulsphere.org>
AuthorDate: Mon Jan 19 21:50:28 2015 -0500
Commit:     Simon Howard <fraggle@soulsphere.org>
CommitDate: Mon Jan 19 21:50:28 2015 -0500

    Add extra checks to weapon cycling loops.

    Ensure that the loops to find the next weapon always terminate -
    even if there are somehow no weapons equipped. Also, only ever do
    weapon cycling when in the GS_LEVEL gamestate. This fixes #503 -
    thanks to Fabian and raithe on Doomworld.
---
 src/doom/g_game.c    | 13 +++++++------
 src/heretic/g_game.c | 11 ++++++-----
 src/hexen/g_game.c   | 12 ++++++++----
 src/strife/g_game.c  | 11 ++++++-----
 4 files changed, 27 insertions(+), 20 deletions(-)

diff --git a/src/doom/g_game.c b/src/doom/g_game.c
index 0b9dda08..64f5b274 100644
--- a/src/doom/g_game.c
+++ b/src/doom/g_game.c
@@ -281,7 +281,7 @@ static boolean WeaponSelectable(weapontype_t weapon)
 static int G_NextWeapon(int direction)
 {
     weapontype_t weapon;
-    int i;
+    int start_i, i;

     // Find index in the table.

@@ -302,13 +302,13 @@ static int G_NextWeapon(int direction)
         }
     }

-    // Switch weapon.
-
+    // Switch weapon. Don't loop forever.
+    start_i = i;
     do
     {
         i += direction;
         i = (i + arrlen(weapon_order_table)) % arrlen(weapon_order_table);
-    } while (!WeaponSelectable(weapon_order_table[i].weapon));
+    } while (i != start_i && !WeaponSelectable(weapon_order_table[i].weapon));

     return weapon_order_table[i].weapon_num;
 }
@@ -445,12 +445,11 @@ void G_BuildTiccmd (ticcmd_t* cmd, int maketic)
     // next_weapon variable is set to change weapons when
     // we generate a ticcmd.  Choose a new weapon.

-    if (next_weapon != 0)
+    if (gamestate == GS_LEVEL && next_weapon != 0)
     {
         i = G_NextWeapon(next_weapon);
         cmd->buttons |= BT_CHANGE;
         cmd->buttons |= i << BT_WEAPONSHIFT;
-        next_weapon = 0;
     }
     else
     {
@@ -469,6 +468,8 @@ void G_BuildTiccmd (ticcmd_t* cmd, int maketic)
         }
     }

+    next_weapon = 0;
+
     // mouse
     if (mousebuttons[mousebforward])
     {
diff --git a/src/heretic/g_game.c b/src/heretic/g_game.c
index 389c0e1d..1154925a 100644
--- a/src/heretic/g_game.c
+++ b/src/heretic/g_game.c
@@ -228,7 +228,7 @@ static boolean WeaponSelectable(weapontype_t weapon)
 static int G_NextWeapon(int direction)
 {
     weapontype_t weapon;
-    int i;
+    int start_i, i;

     // Find index in the table.

@@ -249,13 +249,13 @@ static int G_NextWeapon(int direction)
         }
     }

-    // Switch weapon.
-
+    // Switch weapon. Don't loop forever.
+    start_i = i;
     do
     {
         i += direction;
         i = (i + arrlen(weapon_order_table)) % arrlen(weapon_order_table);
-    } while (!WeaponSelectable(weapon_order_table[i].weapon));
+    } while (i != start_i && !WeaponSelectable(weapon_order_table[i].weapon));

     return weapon_order_table[i].weapon_num;
 }
@@ -466,7 +466,8 @@ void G_BuildTiccmd(ticcmd_t *cmd, int maketic)
     // we generate a ticcmd.  Choose a new weapon.
     // (Can't weapon cycle when the player is a chicken)

-    if (players[consoleplayer].chickenTics == 0 && next_weapon != 0)
+    if (gamestate == GS_LEVEL
+     && players[consoleplayer].chickenTics == 0 && next_weapon != 0)
     {
         i = G_NextWeapon(next_weapon);
         cmd->buttons |= BT_CHANGE;
diff --git a/src/hexen/g_game.c b/src/hexen/g_game.c
index 6d10dcfd..3593ffe2 100644
--- a/src/hexen/g_game.c
+++ b/src/hexen/g_game.c
@@ -451,9 +451,11 @@ void G_BuildTiccmd(ticcmd_t *cmd, int maketic)

     // Weapon cycling. Switch to previous or next weapon.
     // (Disabled when player is a pig).
-
-    if (players[consoleplayer].morphTics == 0 && next_weapon != 0)
+    if (gamestate == GS_LEVEL
+     && players[consoleplayer].morphTics == 0 && next_weapon != 0)
     {
+        int start_i;
+
         if (players[consoleplayer].pendingweapon == WP_NOCHANGE)
         {
             i = players[consoleplayer].readyweapon;
@@ -463,9 +465,11 @@ void G_BuildTiccmd(ticcmd_t *cmd, int maketic)
             i = players[consoleplayer].pendingweapon;
         }

+        // Don't loop forever.
+        start_i = i;
         do {
-            i = (i + next_weapon) % NUMWEAPONS;
-        } while (!players[consoleplayer].weaponowned[i]);
+            i = (i + next_weapon + NUMWEAPONS) % NUMWEAPONS;
+        } while (i != start_i && !players[consoleplayer].weaponowned[i]);

         cmd->buttons |= BT_CHANGE;
         cmd->buttons |= i << BT_WEAPONSHIFT;
diff --git a/src/strife/g_game.c b/src/strife/g_game.c
index 8d074a1f..e0c0ae27 100644
--- a/src/strife/g_game.c
+++ b/src/strife/g_game.c
@@ -289,7 +289,7 @@ static boolean WeaponSelectable(weapontype_t weapon)
 static int G_NextWeapon(int direction)
 {
     weapontype_t weapon;
-    int i;
+    int start_i, i;

     // Find index in the table.

@@ -311,12 +311,12 @@ static int G_NextWeapon(int direction)
     }

     // Switch weapon.
-
+    start_i = i;
     do
     {
         i += direction;
         i = (i + arrlen(weapon_order_table)) % arrlen(weapon_order_table);
-    } while (!WeaponSelectable(weapon_order_table[i].weapon));
+    } while (i != start_i && !WeaponSelectable(weapon_order_table[i].weapon));

     return weapon_order_table[i].weapon_num;
 }
@@ -511,12 +511,11 @@ void G_BuildTiccmd (ticcmd_t* cmd, int maketic)
     // next_weapon variable is set to change weapons when
     // we generate a ticcmd.  Choose a new weapon.

-    if (next_weapon != 0)
+    if (gamestate == GS_LEVEL && next_weapon != 0)
     {
         i = G_NextWeapon(next_weapon);
         cmd->buttons |= BT_CHANGE;
         cmd->buttons |= i << BT_WEAPONSHIFT;
-        next_weapon = 0;
     }
     else
     {
@@ -535,6 +534,8 @@ void G_BuildTiccmd (ticcmd_t* cmd, int maketic)
         }
     }

+    next_weapon = 0;
+
     // mouse
     if (mousebuttons[mousebforward])
     {