diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c index 7b94b874..15a18798 100644 --- a/src/game/g_cmds.c +++ b/src/game/g_cmds.c @@ -1400,6 +1400,164 @@ Cmd_ListEntities_f(edict_t *ent) } } +static int +get_ammo_usage(gitem_t *weap) +{ + if (!weap) + { + return 0; + } + + /* handles grenades and tesla which only use 1 ammo per shot */ + /* have to check this because they don't store their ammo usage in weap->quantity */ + if (weap->flags & IT_AMMO) + { + return 1; + } + + /* weapons store their ammo usage in the quantity field */ + return weap->quantity; +} + +static gitem_t * +cycle_weapon(edict_t *ent) +{ + gclient_t *cl; + gitem_t *noammo_fallback; + gitem_t *noweap_fallback; + gitem_t *weap; + gitem_t *ammo; + int i; + int start; + int num_weaps; + + if (!ent) + { + return NULL; + } + + cl = ent->client; + + if (!cl) + { + return NULL; + } + + num_weaps = gi.argc(); + + /* find where we want to start the search for the next eligible weapon */ + if (cl->pers.weapon) + { + for (i = 1; i < num_weaps; i++) + { + if (Q_stricmp(cl->pers.weapon->classname, gi.argv(i)) == 0) + { + break; + } + } + + i++; + + if (i >= num_weaps) + { + i = 1; + } + } + else + { + i = 1; + } + + start = i; + noammo_fallback = NULL; + noweap_fallback = NULL; + + /* find the first eligible weapon in the list we can switch to */ + do + { + weap = FindItemByClassname(gi.argv(i)); + + if (weap && weap != cl->pers.weapon && (weap->flags & IT_WEAPON) && weap->use) + { + if (cl->pers.inventory[ITEM_INDEX(weap)] > 0) + { + if (weap->ammo) + { + ammo = FindItem(weap->ammo); + if (ammo) + { + if (cl->pers.inventory[ITEM_INDEX(ammo)] >= get_ammo_usage(weap)) + { + return weap; + } + + if (!noammo_fallback) + { + noammo_fallback = weap; + } + } + } + else + { + return weap; + } + } + else if (!noweap_fallback) + { + noweap_fallback = weap; + } + } + + i++; + + if (i >= num_weaps) + { + i = 1; + } + } while (i != start); + + /* if no weapon was found, the fallbacks will be used for + printing the appropriate error message to the console + */ + + if (noammo_fallback) + { + return noammo_fallback; + } + + return noweap_fallback; +} + +void +Cmd_CycleWeap_f(edict_t *ent) +{ + gitem_t *weap; + + if (!ent) + { + return; + } + + if (gi.argc() <= 1) + { + gi.cprintf(ent, PRINT_HIGH, "Usage: cycleweap classname1 classname2 .. classnameN\n"); + return; + } + + weap = cycle_weapon(ent); + if (weap) + { + if (ent->client->pers.inventory[ITEM_INDEX(weap)] <= 0) + { + gi.cprintf(ent, PRINT_HIGH, "Out of item: %s\n", weap->pickup_name); + } + else + { + weap->use(ent, weap); + } + } +} + void ClientCommand(edict_t *ent) { @@ -1548,6 +1706,10 @@ ClientCommand(edict_t *ent) { Cmd_ListEntities_f(ent); } + else if (Q_stricmp(cmd, "cycleweap") == 0) + { + Cmd_CycleWeap_f(ent); + } else /* anything that doesn't match a command will be a chat */ { Cmd_Say_f(ent, false, true);