diff --git a/doc/050_commands.md b/doc/050_commands.md index 8cd3d7b2..6826c3e2 100644 --- a/doc/050_commands.md +++ b/doc/050_commands.md @@ -10,6 +10,11 @@ original clients (Vanilla Quake II) commands are still in place. skipped if it is not a valid weapon classname, you do not own it in your inventory or you do not have enough ammo to use it. +* **prefweap **: Similar to the previous command, this will + select the first weapon available in the priority list given. Useful + to set a "panic button". E.g. the following will select your best + shotgun: `prefweap weapon_supershotgun weapon_shotgun`. + * **gamemode **: Provides a convenient way to switch the game mode between `coop`, `dm` and `sp` without having to set three cvars the correct way. `?` prints the current mode. diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c index 15a18798..cb201969 100644 --- a/src/game/g_cmds.c +++ b/src/game/g_cmds.c @@ -1558,6 +1558,112 @@ Cmd_CycleWeap_f(edict_t *ent) } } +static gitem_t * +preferred_weapon(edict_t *ent) +{ + gclient_t *cl; + gitem_t *noammo_fallback; + gitem_t *noweap_fallback; + gitem_t *weap; + gitem_t *ammo; + int i; + int num_weaps; + + if (!ent) + { + return NULL; + } + + cl = ent->client; + + if (!cl) + { + return NULL; + } + + num_weaps = gi.argc(); + noammo_fallback = NULL; + noweap_fallback = NULL; + + /* find the first eligible weapon in the list we can switch to */ + for (i = 1; i < num_weaps; i++) + { + weap = FindItemByClassname(gi.argv(i)); + + if (weap && (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; + } + } + } + + /* 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_PrefWeap_f(edict_t *ent) +{ + gitem_t *weap; + + if (!ent) + { + return; + } + + if (gi.argc() <= 1) + { + gi.cprintf(ent, PRINT_HIGH, "Usage: prefweap classname1 classname2 .. classnameN\n"); + return; + } + + weap = preferred_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) { @@ -1710,6 +1816,10 @@ ClientCommand(edict_t *ent) { Cmd_CycleWeap_f(ent); } + else if (Q_stricmp(cmd, "prefweap") == 0) + { + Cmd_PrefWeap_f(ent); + } else /* anything that doesn't match a command will be a chat */ { Cmd_Say_f(ent, false, true);