/* ======================================================================= * * Game command processing. * * ======================================================================= */ #include "header/local.h" #include "monster/misc/player.h" static char * ClientTeam(edict_t *ent, char* value) { char *p; value[0] = 0; if (!ent) { return value; } if (!ent->client) { return value; } strcpy(value, Info_ValueForKey(ent->client->pers.userinfo, "skin")); p = strchr(value, '/'); if (!p) { return value; } if ((int)(dmflags->value) & DF_MODELTEAMS) { *p = 0; return value; } return ++p; } qboolean OnSameTeam(edict_t *ent1, edict_t *ent2) { char ent1Team[512]; char ent2Team[512]; if (!ent1 || !ent2) { return false; } if (!((int)(dmflags->value) & (DF_MODELTEAMS | DF_SKINTEAMS))) { return false; } ClientTeam(ent1, ent1Team); ClientTeam(ent2, ent2Team); if (ent1Team[0] != '\0' && strcmp(ent1Team, ent2Team) == 0) { return true; } return false; } void SelectNextItem(edict_t *ent, int itflags) { gclient_t *cl; int i, index; gitem_t *it; if (!ent) { return; } cl = ent->client; if (cl->chase_target) { ChaseNext(ent); return; } /* scan for the next valid one */ for (i = 1; i <= MAX_ITEMS; i++) { index = (cl->pers.selected_item + i) % MAX_ITEMS; if (!cl->pers.inventory[index]) { continue; } it = &itemlist[index]; if (!it->use) { continue; } if (!(it->flags & itflags)) { continue; } cl->pers.selected_item = index; return; } cl->pers.selected_item = -1; } void SelectPrevItem(edict_t *ent, int itflags) { gclient_t *cl; int i, index; gitem_t *it; if (!ent) { return; } cl = ent->client; if (cl->chase_target) { ChasePrev(ent); return; } /* scan for the next valid one */ for (i = 1; i <= MAX_ITEMS; i++) { index = (cl->pers.selected_item + MAX_ITEMS - i) % MAX_ITEMS; if (!cl->pers.inventory[index]) { continue; } it = &itemlist[index]; if (!it->use) { continue; } if (!(it->flags & itflags)) { continue; } cl->pers.selected_item = index; return; } cl->pers.selected_item = -1; } void ValidateSelectedItem(edict_t *ent) { gclient_t *cl; if (!ent) { return; } cl = ent->client; if (cl->pers.inventory[cl->pers.selected_item]) { return; /* valid */ } SelectNextItem(ent, -1); } /* ================================================================================= */ /* * Give items to a client */ void Cmd_Give_f(edict_t *ent) { char *name; gitem_t *it; int index; int i; qboolean give_all; edict_t *it_ent; if (!ent) { return; } if ((deathmatch->value || coop->value) && !sv_cheats->value) { gi.cprintf(ent, PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n"); return; } name = gi.args(); if (Q_stricmp(name, "all") == 0) { give_all = true; } else { give_all = false; } if (give_all || (Q_stricmp(gi.argv(1), "health") == 0)) { if (gi.argc() == 3) { ent->health = atoi(gi.argv(2)); ent->health = ent->health < 1 ? 1 : ent->health; } else { ent->health = ent->max_health; } if (!give_all) { return; } } if (give_all || (Q_stricmp(name, "weapons") == 0)) { for (i = 0; i < game.num_items; i++) { it = itemlist + i; if (!it->pickup) { continue; } if (!(it->flags & IT_WEAPON)) { continue; } ent->client->pers.inventory[i] += 1; } if (!give_all) { return; } } if (give_all || (Q_stricmp(name, "ammo") == 0)) { for (i = 0; i < game.num_items; i++) { it = itemlist + i; if (!it->pickup) { continue; } if (!(it->flags & IT_AMMO)) { continue; } Add_Ammo(ent, it, 1000); } if (!give_all) { return; } } if (give_all || (Q_stricmp(name, "armor") == 0)) { gitem_armor_t *info; it = FindItem("Jacket Armor"); ent->client->pers.inventory[ITEM_INDEX(it)] = 0; it = FindItem("Combat Armor"); ent->client->pers.inventory[ITEM_INDEX(it)] = 0; it = FindItem("Body Armor"); info = (gitem_armor_t *)it->info; ent->client->pers.inventory[ITEM_INDEX(it)] = info->max_count; if (!give_all) { return; } } if (give_all || (Q_stricmp(name, "Power Shield") == 0)) { it = FindItem("Power Shield"); it_ent = G_Spawn(); it_ent->classname = it->classname; SpawnItem(it_ent, it); Touch_Item(it_ent, ent, NULL, NULL); if (it_ent->inuse) { G_FreeEdict(it_ent); } if (!give_all) { return; } } if (give_all) { for (i = 0; i < game.num_items; i++) { it = itemlist + i; if (!it->pickup) { continue; } if (it->flags & IT_NOT_GIVEABLE) { continue; } if (it->flags & (IT_ARMOR | IT_WEAPON | IT_AMMO)) { continue; } ent->client->pers.inventory[i] = 1; } return; } it = FindItem(name); if (!it) { name = gi.argv(1); it = FindItem(name); if (!it) { gi.cprintf(ent, PRINT_HIGH, "unknown item\n"); return; } } if (!it->pickup) { gi.cprintf(ent, PRINT_HIGH, "non-pickup item\n"); return; } if (it->flags & IT_NOT_GIVEABLE) { gi.dprintf("item cannot be given\n"); return; } index = ITEM_INDEX(it); if (it->flags & IT_AMMO) { if (gi.argc() == 3) { ent->client->pers.inventory[index] = atoi(gi.argv(2)); } else { ent->client->pers.inventory[index] += it->quantity; } } else { it_ent = G_Spawn(); it_ent->classname = it->classname; SpawnItem(it_ent, it); /* since some items don't actually spawn when you say to .. */ if (!it_ent->inuse) { return; } Touch_Item(it_ent, ent, NULL, NULL); if (it_ent->inuse) { G_FreeEdict(it_ent); } } } /* * Sets client to godmode */ void Cmd_God_f(edict_t *ent) { char *msg; if (!ent) { return; } if ((deathmatch->value || coop->value) && !sv_cheats->value) { gi.cprintf(ent, PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n"); return; } ent->flags ^= FL_GODMODE; if (!(ent->flags & FL_GODMODE)) { msg = "godmode OFF\n"; } else { msg = "godmode ON\n"; } gi.cprintf(ent, PRINT_HIGH, msg); } /* * Sets client to notarget */ void Cmd_Notarget_f(edict_t *ent) { char *msg; if (!ent) { return; } if ((deathmatch->value || coop->value) && !sv_cheats->value) { gi.cprintf(ent, PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n"); return; } ent->flags ^= FL_NOTARGET; if (!(ent->flags & FL_NOTARGET)) { msg = "notarget OFF\n"; } else { msg = "notarget ON\n"; } gi.cprintf(ent, PRINT_HIGH, msg); } void Cmd_Noclip_f(edict_t *ent) { char *msg; if (!ent) { return; } if ((deathmatch->value || coop->value) && !sv_cheats->value) { gi.cprintf(ent, PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n"); return; } if (ent->movetype == MOVETYPE_NOCLIP) { ent->movetype = MOVETYPE_WALK; msg = "noclip OFF\n"; } else { ent->movetype = MOVETYPE_NOCLIP; msg = "noclip ON\n"; } gi.cprintf(ent, PRINT_HIGH, msg); } /* * Use an inventory item */ void Cmd_Use_f(edict_t *ent) { int index; gitem_t *it; char *s; if (!ent) { return; } s = gi.args(); it = FindItem(s); if (!it) { gi.cprintf(ent, PRINT_HIGH, "unknown item: %s\n", s); return; } if (!it->use) { gi.cprintf(ent, PRINT_HIGH, "Item is not usable.\n"); return; } index = ITEM_INDEX(it); if (!ent->client->pers.inventory[index]) { gi.cprintf(ent, PRINT_HIGH, "Out of item: %s\n", s); return; } it->use(ent, it); } /* * Drop an inventory item */ void Cmd_Drop_f(edict_t *ent) { int index; gitem_t *it; char *s; if (!ent) { return; } s = gi.args(); it = FindItem(s); if (!it) { gi.cprintf(ent, PRINT_HIGH, "unknown item: %s\n", s); return; } if (!it->drop) { gi.cprintf(ent, PRINT_HIGH, "Item is not dropable.\n"); return; } index = ITEM_INDEX(it); if (!ent->client->pers.inventory[index]) { gi.cprintf(ent, PRINT_HIGH, "Out of item: %s\n", s); return; } it->drop(ent, it); } void Cmd_Score_f(edict_t *ent) { if (!ent) { return; } ent->client->showinventory = false; ent->client->showhelp = false; if (!deathmatch->value && !coop->value) { return; } if (ent->client->showscores) { ent->client->showscores = false; return; } ent->client->showscores = true; DeathmatchScoreboardMessage(ent, ent->enemy); gi.unicast(ent, true); } void Cmd_Help_f(edict_t *ent) { if (!ent) { return; } /* this is for backwards compatability */ if (deathmatch->value) { Cmd_Score_f(ent); return; } ent->client->showinventory = false; ent->client->showscores = false; if (ent->client->showhelp) { ent->client->showhelp = false; return; } ent->client->showhelp = true; ent->client->pers.helpchanged = 0; HelpComputerMessage(ent); gi.unicast(ent, true); } void Cmd_Inven_f(edict_t *ent) { gclient_t *cl; if (!ent) { return; } cl = ent->client; cl->showscores = false; cl->showhelp = false; if (cl->showinventory) { cl->showinventory = false; return; } cl->showinventory = true; InventoryMessage(ent); gi.unicast(ent, true); } void Cmd_InvUse_f(edict_t *ent) { gitem_t *it; if (!ent) { return; } ValidateSelectedItem(ent); if (ent->client->pers.selected_item == -1) { gi.cprintf(ent, PRINT_HIGH, "No item to use.\n"); return; } it = &itemlist[ent->client->pers.selected_item]; if (!it->use) { gi.cprintf(ent, PRINT_HIGH, "Item is not usable.\n"); return; } it->use(ent, it); } void Cmd_WeapPrev_f(edict_t *ent) { gclient_t *cl; int i, index; gitem_t *it; int selected_weapon; if (!ent) { return; } cl = ent->client; if (!cl->pers.weapon) { return; } selected_weapon = ITEM_INDEX(cl->pers.weapon); /* scan for the next valid one */ for (i = 1; i <= MAX_ITEMS; i++) { /* prevent scrolling through ALL weapons */ index = (selected_weapon + MAX_ITEMS - i) % MAX_ITEMS; if (!cl->pers.inventory[index]) { continue; } it = &itemlist[index]; if (!it->use) { continue; } if (!(it->flags & IT_WEAPON)) { continue; } it->use(ent, it); /* prevent scrolling through ALL weapons */ if (cl->newweapon == it) { return; } } } void Cmd_WeapNext_f(edict_t *ent) { gclient_t *cl; int i, index; gitem_t *it; int selected_weapon; if (!ent) { return; } cl = ent->client; if (!cl->pers.weapon) { return; } selected_weapon = ITEM_INDEX(cl->pers.weapon); /* scan for the next valid one */ for (i = 1; i <= MAX_ITEMS; i++) { /* prevent scrolling through ALL weapons */ index = (selected_weapon + i) % MAX_ITEMS; if (!cl->pers.inventory[index]) { continue; } it = &itemlist[index]; if (!it->use) { continue; } if (!(it->flags & IT_WEAPON)) { continue; } it->use(ent, it); /* prevent scrolling through ALL weapons */ if (cl->newweapon == it) { return; } } } void Cmd_WeapLast_f(edict_t *ent) { gclient_t *cl; int index; gitem_t *it; if (!ent) { return; } cl = ent->client; if (!cl->pers.weapon || !cl->pers.lastweapon) { return; } index = ITEM_INDEX(cl->pers.lastweapon); if (!cl->pers.inventory[index]) { return; } it = &itemlist[index]; if (!it->use) { return; } if (!(it->flags & IT_WEAPON)) { return; } it->use(ent, it); } void Cmd_InvDrop_f(edict_t *ent) { gitem_t *it; if (!ent) { return; } ValidateSelectedItem(ent); if (ent->client->pers.selected_item == -1) { gi.cprintf(ent, PRINT_HIGH, "No item to drop.\n"); return; } it = &itemlist[ent->client->pers.selected_item]; if (!it->drop) { gi.cprintf(ent, PRINT_HIGH, "Item is not dropable.\n"); return; } it->drop(ent, it); } void Cmd_Kill_f(edict_t *ent) { if (!ent) { return; } if ((level.time - ent->client->respawn_time) < 5) { return; } ent->flags &= ~FL_GODMODE; ent->health = 0; meansOfDeath = MOD_SUICIDE; /* make sure no trackers are still hurting us. */ if (ent->client->tracker_pain_framenum) { RemoveAttackingPainDaemons(ent); } if (ent->client->owned_sphere) { G_FreeEdict(ent->client->owned_sphere); ent->client->owned_sphere = NULL; } player_die(ent, ent, ent, 100000, vec3_origin); } void Cmd_PutAway_f(edict_t *ent) { if (!ent) { return; } ent->client->showscores = false; ent->client->showhelp = false; ent->client->showinventory = false; } int PlayerSort(void const *a, void const *b) { int anum, bnum; if (!a || !b) { return 0; } anum = *(int *)a; bnum = *(int *)b; anum = game.clients[anum].ps.stats[STAT_FRAGS]; bnum = game.clients[bnum].ps.stats[STAT_FRAGS]; if (anum < bnum) { return -1; } if (anum > bnum) { return 1; } return 0; } void Cmd_Players_f(edict_t *ent) { int i; int count; char small[64]; char large[1280]; int index[256]; if (!ent) { return; } count = 0; for (i = 0; i < maxclients->value; i++) { if (game.clients[i].pers.connected) { index[count] = i; count++; } } /* sort by frags */ qsort(index, count, sizeof(index[0]), PlayerSort); /* print information */ large[0] = 0; for (i = 0; i < count; i++) { Com_sprintf(small, sizeof(small), "%3i %s\n", game.clients[index[i]].ps.stats[STAT_FRAGS], game.clients[index[i]].pers.netname); if (strlen(small) + strlen(large) > sizeof(large) - 100) { /* can't print all of them in one packet */ strcat(large, "...\n"); break; } strcat(large, small); } gi.cprintf(ent, PRINT_HIGH, "%s\n%i players\n", large, count); } void Cmd_Wave_f(edict_t *ent) { int i; if (!ent) { return; } i = atoi(gi.argv(1)); /* can't wave when ducked */ if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) { return; } if (ent->client->anim_priority > ANIM_WAVE) { return; } ent->client->anim_priority = ANIM_WAVE; switch (i) { case 0: gi.cprintf(ent, PRINT_HIGH, "flipoff\n"); ent->s.frame = FRAME_flip01 - 1; ent->client->anim_end = FRAME_flip12; break; case 1: gi.cprintf(ent, PRINT_HIGH, "salute\n"); ent->s.frame = FRAME_salute01 - 1; ent->client->anim_end = FRAME_salute11; break; case 2: gi.cprintf(ent, PRINT_HIGH, "taunt\n"); ent->s.frame = FRAME_taunt01 - 1; ent->client->anim_end = FRAME_taunt17; break; case 3: gi.cprintf(ent, PRINT_HIGH, "wave\n"); ent->s.frame = FRAME_wave01 - 1; ent->client->anim_end = FRAME_wave11; break; case 4: default: gi.cprintf(ent, PRINT_HIGH, "point\n"); ent->s.frame = FRAME_point01 - 1; ent->client->anim_end = FRAME_point12; break; } } void Cmd_Say_f(edict_t *ent, qboolean team, qboolean arg0) { int i, j; edict_t *other; char *p; char text[2048]; gclient_t *cl; if (!ent) { return; } if ((gi.argc() < 2) && !arg0) { return; } if (!((int)(dmflags->value) & (DF_MODELTEAMS | DF_SKINTEAMS))) { team = false; } if (team) { Com_sprintf(text, sizeof(text), "(%s): ", ent->client->pers.netname); } else { Com_sprintf(text, sizeof(text), "%s: ", ent->client->pers.netname); } if (arg0) { strcat(text, gi.argv(0)); strcat(text, " "); strcat(text, gi.args()); } else { p = gi.args(); if (*p == '"') { p++; p[strlen(p) - 1] = 0; } strcat(text, p); } /* don't let text be too long for malicious reasons */ if (strlen(text) > 150) { text[150] = 0; } strcat(text, "\n"); if (flood_msgs->value) { cl = ent->client; if (level.time < cl->flood_locktill) { gi.cprintf(ent, PRINT_HIGH, "You can't talk for %d more seconds\n", (int)(cl->flood_locktill - level.time)); return; } i = cl->flood_whenhead - flood_msgs->value + 1; if (i < 0) { i = (sizeof(cl->flood_when) / sizeof(cl->flood_when[0])) + i; } if (cl->flood_when[i] && (level.time - cl->flood_when[i] < flood_persecond->value)) { cl->flood_locktill = level.time + flood_waitdelay->value; gi.cprintf(ent, PRINT_CHAT, "Flood protection: You can't talk for %d seconds.\n", (int)flood_waitdelay->value); return; } cl->flood_whenhead = (cl->flood_whenhead + 1) % (sizeof(cl->flood_when) / sizeof(cl->flood_when[0])); cl->flood_when[cl->flood_whenhead] = level.time; } if (dedicated->value) { gi.cprintf(NULL, PRINT_CHAT, "%s", text); } for (j = 1; j <= game.maxclients; j++) { other = &g_edicts[j]; if (!other->inuse) { continue; } if (!other->client) { continue; } if (team) { if (!OnSameTeam(ent, other)) { continue; } } gi.cprintf(other, PRINT_CHAT, "%s", text); } } void Cmd_Ent_Count_f(edict_t *ent) { int x; edict_t *e; if (!ent) { return; } x = 0; for (e = g_edicts; e < &g_edicts[globals.num_edicts]; e++) { if (e->inuse) { x++; } } gi.dprintf("%d entites active\n", x); } void Cmd_PlayerList_f(edict_t *ent) { int i; char st[80]; char text[1400]; edict_t *e2; if (!ent) { return; } /* connect time, ping, score, name */ *text = 0; for (i = 0, e2 = g_edicts + 1; i < maxclients->value; i++, e2++) { if (!e2->inuse) { continue; } Com_sprintf(st, sizeof(st), "%02d:%02d %4d %3d %s%s\n", (level.framenum - e2->client->resp.enterframe) / 600, ((level.framenum - e2->client->resp.enterframe) % 600) / 10, e2->client->ping, e2->client->resp.score, e2->client->pers.netname, e2->client->resp.spectator ? " (spectator)" : ""); if (strlen(text) + strlen(st) > sizeof(text) - 50) { sprintf(text + strlen(text), "And more...\n"); gi.cprintf(ent, PRINT_HIGH, "%s", text); return; } strcat(text, st); } gi.cprintf(ent, PRINT_HIGH, "%s", text); } void Cmd_Teleport_f(edict_t *ent) { if (!ent) { return; } if ((deathmatch->value || coop->value) && !sv_cheats->value) { gi.cprintf(ent, PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n"); return; } if (gi.argc() != 4) { gi.cprintf(ent, PRINT_HIGH, "Usage: teleport x y z\n"); return; } /* Unlink it to prevent unwanted interactions with other entities. This works because linkentity() uses the first available slot and the player is always at postion 0. */ gi.unlinkentity(ent); /* Set new position */ ent->s.origin[0] = atof(gi.argv(1)); ent->s.origin[1] = atof(gi.argv(2)); ent->s.origin[2] = atof(gi.argv(3)) + 10.0; /* Remove velocity and keep the entity briefly in place to give the server and clients time to catch up. */ VectorClear(ent->velocity); ent->client->ps.pmove.pm_time = 20; ent->client->ps.pmove.pm_flags |= PMF_TIME_TELEPORT; /* Remove viewangles. They'll be recalculated by the client at the next frame. */ VectorClear(ent->s.angles); VectorClear(ent->client->ps.viewangles); VectorClear(ent->client->v_angle); /* Telefrag everything that's in the target location. */ KillBox(ent); /* And link it back in. */ gi.linkentity(ent); } void Cmd_ListEntities_f(edict_t *ent) { if ((deathmatch->value || coop->value) && !sv_cheats->value) { gi.cprintf(ent, PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n"); return; } if (gi.argc() < 2) { gi.cprintf(ent, PRINT_HIGH, "Usage: listentities \n"); return; } /* What to print? */ qboolean all = false; qboolean ammo = false; qboolean items = false; qboolean keys = false; qboolean monsters = false; qboolean weapons = false; for (int i = 1; i < gi.argc(); i++) { const char *arg = gi.argv(i); if (Q_stricmp(arg, "all") == 0) { all = true; } else if (Q_stricmp(arg, "ammo") == 0) { ammo = true; } else if (Q_stricmp(arg, "items") == 0) { items = true; } else if (Q_stricmp(arg, "keys") == 0) { keys = true; } else if (Q_stricmp(arg, "monsters") == 0) { monsters = true; } else if (Q_stricmp(arg, "weapons") == 0) { weapons = true; } else { gi.cprintf(ent, PRINT_HIGH, "Usage: listentities \n"); } } /* Print what's requested. */ for (int i = 0; i < globals.num_edicts; i++) { edict_t *cur = &g_edicts[i]; qboolean print = false; /* Ensure that the entity is valid. */ if (!cur->classname) { continue; } if (all) { print = true; } else { if (ammo) { if (strncmp(cur->classname, "ammo_", 5) == 0) { print = true; } } if (items) { if (strncmp(cur->classname, "item_", 5) == 0) { print = true; } } if (keys) { if (strncmp(cur->classname, "key_", 4) == 0) { print = true; } } if (monsters) { if (strncmp(cur->classname, "monster_", 8) == 0) { print = true; } } if (weapons) { if (strncmp(cur->classname, "weapon_", 7) == 0) { print = true; } } } if (print) { /* We use dprintf() because cprintf() may flood the server... */ gi.dprintf("%s: %f %f %f\n", cur->classname, cur->s.origin[0], cur->s.origin[1], cur->s.origin[2]); } } } void ClientCommand(edict_t *ent) { char *cmd; if (!ent) { return; } if (!ent->client) { return; /* not fully in game yet */ } cmd = gi.argv(0); if (Q_stricmp(cmd, "players") == 0) { Cmd_Players_f(ent); return; } if (Q_stricmp(cmd, "say") == 0) { Cmd_Say_f(ent, false, false); return; } if (Q_stricmp(cmd, "say_team") == 0) { Cmd_Say_f(ent, true, false); return; } if (Q_stricmp(cmd, "score") == 0) { Cmd_Score_f(ent); return; } if (Q_stricmp(cmd, "help") == 0) { Cmd_Help_f(ent); return; } if (level.intermissiontime) { return; } if (Q_stricmp(cmd, "use") == 0) { Cmd_Use_f(ent); } else if (Q_stricmp(cmd, "drop") == 0) { Cmd_Drop_f(ent); } else if (Q_stricmp(cmd, "give") == 0) { Cmd_Give_f(ent); } else if (Q_stricmp(cmd, "god") == 0) { Cmd_God_f(ent); } else if (Q_stricmp(cmd, "notarget") == 0) { Cmd_Notarget_f(ent); } else if (Q_stricmp(cmd, "noclip") == 0) { Cmd_Noclip_f(ent); } else if (Q_stricmp(cmd, "inven") == 0) { Cmd_Inven_f(ent); } else if (Q_stricmp(cmd, "invnext") == 0) { SelectNextItem(ent, -1); } else if (Q_stricmp(cmd, "invprev") == 0) { SelectPrevItem(ent, -1); } else if (Q_stricmp(cmd, "invnextw") == 0) { SelectNextItem(ent, IT_WEAPON); } else if (Q_stricmp(cmd, "invprevw") == 0) { SelectPrevItem(ent, IT_WEAPON); } else if (Q_stricmp(cmd, "invnextp") == 0) { SelectNextItem(ent, IT_POWERUP); } else if (Q_stricmp(cmd, "invprevp") == 0) { SelectPrevItem(ent, IT_POWERUP); } else if (Q_stricmp(cmd, "invuse") == 0) { Cmd_InvUse_f(ent); } else if (Q_stricmp(cmd, "invdrop") == 0) { Cmd_InvDrop_f(ent); } else if (Q_stricmp(cmd, "weapprev") == 0) { Cmd_WeapPrev_f(ent); } else if (Q_stricmp(cmd, "weapnext") == 0) { Cmd_WeapNext_f(ent); } else if (Q_stricmp(cmd, "weaplast") == 0) { Cmd_WeapLast_f(ent); } else if (Q_stricmp(cmd, "kill") == 0) { Cmd_Kill_f(ent); } else if (Q_stricmp(cmd, "putaway") == 0) { Cmd_PutAway_f(ent); } else if (Q_stricmp(cmd, "wave") == 0) { Cmd_Wave_f(ent); } else if (Q_stricmp(cmd, "playerlist") == 0) { Cmd_PlayerList_f(ent); } else if (Q_stricmp(cmd, "entcount") == 0) { Cmd_Ent_Count_f(ent); } else if (Q_stricmp(cmd, "disguise") == 0) { ent->flags |= FL_DISGUISED; } else if (Q_stricmp(cmd, "teleport") == 0) { Cmd_Teleport_f(ent); } else if (Q_stricmp(cmd, "listentities") == 0) { Cmd_ListEntities_f(ent); } else /* anything that doesn't match a command will be a chat */ { Cmd_Say_f(ent, false, true); } }