12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754 |
- // Copyright (c) ZeniMax Media Inc.
- // Licensed under the GNU General Public License 2.0.
- #include "g_local.h"
- #include "m_player.h"
- void SelectNextItem(edict_t *ent, item_flags_t itflags, bool menu = true)
- {
- gclient_t *cl;
- item_id_t i, index;
- gitem_t *it;
- cl = ent->client;
- // ZOID
- if (menu && cl->menu)
- {
- PMenu_Next(ent);
- return;
- }
- else if (menu && cl->chase_target)
- {
- ChaseNext(ent);
- return;
- }
- // ZOID
- // scan for the next valid one
- for (i = static_cast<item_id_t>(IT_NULL + 1); i <= IT_TOTAL; i = static_cast<item_id_t>(i + 1))
- {
- index = static_cast<item_id_t>((cl->pers.selected_item + i) % IT_TOTAL);
- if (!cl->pers.inventory[index])
- continue;
- it = &itemlist[index];
- if (!it->use)
- continue;
- if (!(it->flags & itflags))
- continue;
- cl->pers.selected_item = index;
- cl->pers.selected_item_time = level.time + SELECTED_ITEM_TIME;
- cl->ps.stats[STAT_SELECTED_ITEM_NAME] = CS_ITEMS + index;
- return;
- }
- cl->pers.selected_item = IT_NULL;
- }
- void SelectPrevItem(edict_t *ent, item_flags_t itflags)
- {
- gclient_t *cl;
- item_id_t i, index;
- gitem_t *it;
- cl = ent->client;
- // ZOID
- if (cl->menu)
- {
- PMenu_Prev(ent);
- return;
- }
- else if (cl->chase_target)
- {
- ChasePrev(ent);
- return;
- }
- // ZOID
- // scan for the next valid one
- for (i = static_cast<item_id_t>(IT_NULL + 1); i <= IT_TOTAL; i = static_cast<item_id_t>(i + 1))
- {
- index = static_cast<item_id_t>((cl->pers.selected_item + IT_TOTAL - i) % IT_TOTAL);
- if (!cl->pers.inventory[index])
- continue;
- it = &itemlist[index];
- if (!it->use)
- continue;
- if (!(it->flags & itflags))
- continue;
- cl->pers.selected_item = index;
- cl->pers.selected_item_time = level.time + SELECTED_ITEM_TIME;
- cl->ps.stats[STAT_SELECTED_ITEM_NAME] = CS_ITEMS + index;
- return;
- }
- cl->pers.selected_item = IT_NULL;
- }
- void ValidateSelectedItem(edict_t *ent)
- {
- gclient_t *cl;
- cl = ent->client;
- if (cl->pers.inventory[cl->pers.selected_item])
- return; // valid
- SelectNextItem(ent, IF_ANY, false);
- }
- //=================================================================================
- inline bool G_CheatCheck(edict_t *ent)
- {
- if (game.maxclients > 1 && !sv_cheats->integer)
- {
- gi.LocClient_Print(ent, PRINT_HIGH, "$g_need_cheats");
- return false;
- }
- return true;
- }
- static void SpawnAndGiveItem(edict_t *ent, item_id_t id)
- {
- gitem_t *it = GetItemByIndex(id);
- if (!it)
- return;
- edict_t *it_ent = G_Spawn();
- it_ent->classname = it->classname;
- SpawnItem(it_ent, it);
- if (it_ent->inuse)
- {
- Touch_Item(it_ent, ent, null_trace, true);
- if (it_ent->inuse)
- G_FreeEdict(it_ent);
- }
- }
- /*
- ==================
- Cmd_Give_f
- Give items to a client
- ==================
- */
- void Cmd_Give_f(edict_t *ent)
- {
- const char *name;
- gitem_t *it;
- item_id_t index;
- int i;
- bool give_all;
- edict_t *it_ent;
- if (!G_CheatCheck(ent))
- return;
- name = gi.args();
- if (Q_strcasecmp(name, "all") == 0)
- give_all = true;
- else
- give_all = false;
- if (give_all || Q_strcasecmp(gi.argv(1), "health") == 0)
- {
- if (gi.argc() == 3)
- ent->health = atoi(gi.argv(2));
- else
- ent->health = ent->max_health;
- if (!give_all)
- return;
- }
- if (give_all || Q_strcasecmp(name, "weapons") == 0)
- {
- for (i = 0; i < IT_TOTAL; i++)
- {
- it = itemlist + i;
- if (!it->pickup)
- continue;
- if (!(it->flags & IF_WEAPON))
- continue;
- ent->client->pers.inventory[i] += 1;
- }
- if (!give_all)
- return;
- }
- if (give_all || Q_strcasecmp(name, "ammo") == 0)
- {
- if (give_all)
- SpawnAndGiveItem(ent, IT_ITEM_PACK);
- for (i = 0; i < IT_TOTAL; i++)
- {
- it = itemlist + i;
- if (!it->pickup)
- continue;
- if (!(it->flags & IF_AMMO))
- continue;
- Add_Ammo(ent, it, 1000);
- }
- if (!give_all)
- return;
- }
- if (give_all || Q_strcasecmp(name, "armor") == 0)
- {
- ent->client->pers.inventory[IT_ARMOR_JACKET] = 0;
- ent->client->pers.inventory[IT_ARMOR_COMBAT] = 0;
- ent->client->pers.inventory[IT_ARMOR_BODY] = GetItemByIndex(IT_ARMOR_BODY)->armor_info->max_count;
- if (!give_all)
- return;
- }
- if (give_all)
- {
- SpawnAndGiveItem(ent, IT_ITEM_POWER_SHIELD);
- if (!give_all)
- return;
- }
- if (give_all)
- {
- for (i = 0; i < IT_TOTAL; i++)
- {
- it = itemlist + i;
- if (!it->pickup)
- continue;
- // ROGUE
- if (it->flags & (IF_ARMOR | IF_WEAPON | IF_AMMO | IF_NOT_GIVEABLE | IF_TECH))
- continue;
- else if (it->pickup == CTFPickup_Flag)
- continue;
- else if ((it->flags & IF_HEALTH) && !it->use)
- continue;
- // ROGUE
- ent->client->pers.inventory[i] = (it->flags & IF_KEY) ? 8 : 1;
- }
- G_CheckPowerArmor(ent);
- ent->client->pers.power_cubes = 0xFF;
- return;
- }
- it = FindItem(name);
- if (!it)
- {
- name = gi.argv(1);
- it = FindItem(name);
- }
- if (!it)
- it = FindItemByClassname(name);
- if (!it)
- {
- gi.LocClient_Print(ent, PRINT_HIGH, "$g_unknown_item");
- return;
- }
- // ROGUE
- if (it->flags & IF_NOT_GIVEABLE)
- {
- gi.LocClient_Print(ent, PRINT_HIGH, "$g_not_giveable");
- return;
- }
- // ROGUE
- index = it->id;
- if (!it->pickup)
- {
- ent->client->pers.inventory[index] = 1;
- return;
- }
- if (it->flags & IF_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);
- // PMM - since some items don't actually spawn when you say to ..
- if (!it_ent->inuse)
- return;
- // pmm
- Touch_Item(it_ent, ent, null_trace, true);
- if (it_ent->inuse)
- G_FreeEdict(it_ent);
- }
- }
- void Cmd_SetPOI_f(edict_t *self)
- {
- if (!G_CheatCheck(self))
- return;
- level.current_poi = self->s.origin;
- level.valid_poi = true;
- }
- void Cmd_CheckPOI_f(edict_t *self)
- {
- if (!G_CheatCheck(self))
- return;
- if (!level.valid_poi)
- return;
-
- char visible_pvs = gi.inPVS(self->s.origin, level.current_poi, false) ? 'y' : 'n';
- char visible_pvs_portals = gi.inPVS(self->s.origin, level.current_poi, true) ? 'y' : 'n';
- char visible_phs = gi.inPHS(self->s.origin, level.current_poi, false) ? 'y' : 'n';
- char visible_phs_portals = gi.inPHS(self->s.origin, level.current_poi, true) ? 'y' : 'n';
- gi.Com_PrintFmt("pvs {} + portals {}, phs {} + portals {}\n", visible_pvs, visible_pvs_portals, visible_phs, visible_phs_portals);
- }
- // [Paril-KEX]
- static void Cmd_Target_f(edict_t *ent)
- {
- if (!G_CheatCheck(ent))
- return;
- ent->target = gi.argv(1);
- G_UseTargets(ent, ent);
- ent->target = nullptr;
- }
- /*
- ==================
- Cmd_God_f
- Sets client to godmode
- argv(0) god
- ==================
- */
- void Cmd_God_f(edict_t *ent)
- {
- const char *msg;
- if (!G_CheatCheck(ent))
- return;
- ent->flags ^= FL_GODMODE;
- if (!(ent->flags & FL_GODMODE))
- msg = "godmode OFF\n";
- else
- msg = "godmode ON\n";
- gi.LocClient_Print(ent, PRINT_HIGH, msg);
- }
- void ED_ParseField(const char *key, const char *value, edict_t *ent);
- /*
- ==================
- Cmd_Immortal_f
- Sets client to immortal - take damage but never go below 1 hp
- argv(0) immortal
- ==================
- */
- void Cmd_Immortal_f(edict_t *ent)
- {
- const char *msg;
- if (!G_CheatCheck(ent))
- return;
- ent->flags ^= FL_IMMORTAL;
- if (!(ent->flags & FL_IMMORTAL))
- msg = "immortal OFF\n";
- else
- msg = "immortal ON\n";
- gi.LocClient_Print(ent, PRINT_HIGH, msg);
- }
- /*
- =================
- Cmd_Spawn_f
- Spawn class name
- argv(0) spawn
- argv(1) <classname>
- argv(2+n) "key"...
- argv(3+n) "value"...
- =================
- */
- void Cmd_Spawn_f(edict_t *ent)
- {
- if (!G_CheatCheck(ent))
- return;
- solid_t backup = ent->solid;
- ent->solid = SOLID_NOT;
- gi.linkentity(ent);
- edict_t* other = G_Spawn();
- other->classname = gi.argv(1);
- other->s.origin = ent->s.origin + (AngleVectors(ent->s.angles).forward * 24.f);
- other->s.angles[1] = ent->s.angles[1];
- st = {};
- if (gi.argc() > 3)
- {
- for (int i = 2; i < gi.argc(); i += 2)
- ED_ParseField(gi.argv(i), gi.argv(i + 1), other);
- }
- ED_CallSpawn(other);
- if (other->inuse)
- {
- vec3_t forward, end;
- AngleVectors(ent->client->v_angle, forward, nullptr, nullptr);
- end = ent->s.origin;
- end[2] += ent->viewheight;
- end += (forward * 8192);
- trace_t tr = gi.traceline(ent->s.origin + vec3_t{0.f, 0.f, (float) ent->viewheight}, end, other, MASK_SHOT | CONTENTS_MONSTERCLIP);
- other->s.origin = tr.endpos;
- for (int32_t i = 0; i < 3; i++)
- {
- if (tr.plane.normal[i] > 0)
- other->s.origin[i] -= other->mins[i] * tr.plane.normal[i];
- else
- other->s.origin[i] += other->maxs[i] * -tr.plane.normal[i];
- }
- while (gi.trace(other->s.origin, other->mins, other->maxs, other->s.origin, other,
- MASK_SHOT | CONTENTS_MONSTERCLIP)
- .startsolid)
- {
- float dx = other->mins[0] - other->maxs[0];
- float dy = other->mins[1] - other->maxs[1];
- other->s.origin += forward * -sqrtf(dx * dx + dy * dy);
- if ((other->s.origin - ent->s.origin).dot(forward) < 0)
- {
- gi.Client_Print(ent, PRINT_HIGH, "Couldn't find a suitable spawn location\n");
- G_FreeEdict(other);
- break;
- }
- }
- if (other->inuse)
- gi.linkentity(other);
- if ((other->svflags & SVF_MONSTER) && other->think)
- other->think(other);
- }
- ent->solid = backup;
- gi.linkentity(ent);
- }
- /*
- =================
- Cmd_Spawn_f
- Telepo'
- argv(0) teleport
- argv(1) x
- argv(2) y
- argv(3) z
- =================
- */
- void Cmd_Teleport_f(edict_t *ent)
- {
- if (!G_CheatCheck(ent))
- return;
- if (gi.argc() < 4)
- {
- gi.LocClient_Print(ent, PRINT_HIGH, "Not enough args; teleport x y z\n");
- return;
- }
- ent->s.origin[0] = (float) atof(gi.argv(1));
- ent->s.origin[1] = (float) atof(gi.argv(2));
- ent->s.origin[2] = (float) atof(gi.argv(3));
- if (gi.argc() >= 4)
- {
- float pitch = (float) atof(gi.argv(4));
- float yaw = (float) atof(gi.argv(5));
- float roll = (float) atof(gi.argv(6));
- vec3_t ang { pitch, yaw, roll };
- ent->client->ps.pmove.delta_angles = ( ang - ent->client->resp.cmd_angles );
- ent->client->ps.viewangles = {};
- ent->client->v_angle = {};
- }
- gi.linkentity(ent);
- }
- /*
- ==================
- Cmd_Notarget_f
- Sets client to notarget
- argv(0) notarget
- ==================
- */
- void Cmd_Notarget_f(edict_t *ent)
- {
- const char *msg;
- if (!G_CheatCheck(ent))
- return;
- ent->flags ^= FL_NOTARGET;
- if (!(ent->flags & FL_NOTARGET))
- msg = "notarget OFF\n";
- else
- msg = "notarget ON\n";
- gi.LocClient_Print(ent, PRINT_HIGH, msg);
- }
- /*
- ==================
- Cmd_Novisible_f
- Sets client to "super notarget"
- argv(0) notarget
- ==================
- */
- void Cmd_Novisible_f(edict_t *ent)
- {
- const char *msg;
- if (!G_CheatCheck(ent))
- return;
- ent->flags ^= FL_NOVISIBLE;
- if (!(ent->flags & FL_NOVISIBLE))
- msg = "novisible OFF\n";
- else
- msg = "novisible ON\n";
- gi.LocClient_Print(ent, PRINT_HIGH, msg);
- }
- void Cmd_AlertAll_f(edict_t *ent)
- {
- if (!G_CheatCheck(ent))
- return;
- for (size_t i = 0; i < globals.num_edicts; i++)
- {
- edict_t *t = &g_edicts[i];
- if (!t->inuse || t->health <= 0 || !(t->svflags & SVF_MONSTER))
- continue;
- t->enemy = ent;
- FoundTarget(t);
- }
- }
- /*
- ==================
- Cmd_Noclip_f
- argv(0) noclip
- ==================
- */
- void Cmd_Noclip_f(edict_t *ent)
- {
- const char *msg;
- if (!G_CheatCheck(ent))
- return;
- if (ent->movetype == MOVETYPE_NOCLIP)
- {
- ent->movetype = MOVETYPE_WALK;
- msg = "noclip OFF\n";
- }
- else
- {
- ent->movetype = MOVETYPE_NOCLIP;
- msg = "noclip ON\n";
- }
- gi.LocClient_Print(ent, PRINT_HIGH, msg);
- }
- /*
- ==================
- Cmd_Use_f
- Use an inventory item
- ==================
- */
- void Cmd_Use_f(edict_t *ent)
- {
- item_id_t index;
- gitem_t *it;
- const char *s;
- if (ent->health <= 0 || ent->deadflag)
- return;
- s = gi.args();
- const char *cmd = gi.argv(0);
- if (!Q_strcasecmp(cmd, "use_index") || !Q_strcasecmp(cmd, "use_index_only"))
- {
- it = GetItemByIndex((item_id_t) atoi(s));
- }
- else
- {
- it = FindItem(s);
- }
- if (!it)
- {
- gi.LocClient_Print(ent, PRINT_HIGH, "$g_unknown_item_name", s);
- return;
- }
- if (!it->use)
- {
- gi.LocClient_Print(ent, PRINT_HIGH, "$g_item_not_usable");
- return;
- }
- index = it->id;
- // Paril: Use_Weapon handles weapon availability
- if (!(it->flags & IF_WEAPON) && !ent->client->pers.inventory[index])
- {
- gi.LocClient_Print(ent, PRINT_HIGH, "$g_out_of_item", it->pickup_name);
- return;
- }
- // allow weapon chains for use
- ent->client->no_weapon_chains = !!strcmp(gi.argv(0), "use") && !!strcmp(gi.argv(0), "use_index");
- it->use(ent, it);
- ValidateSelectedItem(ent);
- }
- /*
- ==================
- Cmd_Drop_f
- Drop an inventory item
- ==================
- */
- void Cmd_Drop_f(edict_t *ent)
- {
- item_id_t index;
- gitem_t *it;
- const char *s;
- if (ent->health <= 0 || ent->deadflag)
- return;
- // ZOID--special case for tech powerups
- if (Q_strcasecmp(gi.args(), "tech") == 0)
- {
- it = CTFWhat_Tech(ent);
- if (it)
- {
- it->drop(ent, it);
- ValidateSelectedItem(ent);
- }
- return;
- }
- // ZOID
- s = gi.args();
- const char *cmd = gi.argv(0);
- if (!Q_strcasecmp(cmd, "drop_index"))
- {
- it = GetItemByIndex((item_id_t) atoi(s));
- }
- else
- {
- it = FindItem(s);
- }
- if (!it)
- {
- gi.LocClient_Print(ent, PRINT_HIGH, "Unknown item : {}\n", s);
- return;
- }
- if (!it->drop)
- {
- gi.LocClient_Print(ent, PRINT_HIGH, "$g_item_not_droppable");
- return;
- }
- index = it->id;
- if (!ent->client->pers.inventory[index])
- {
- gi.LocClient_Print(ent, PRINT_HIGH, "$g_out_of_item", it->pickup_name);
- return;
- }
- it->drop(ent, it);
- ValidateSelectedItem(ent);
- }
- /*
- =================
- Cmd_Inven_f
- =================
- */
- void Cmd_Inven_f(edict_t *ent)
- {
- int i;
- gclient_t *cl;
- cl = ent->client;
- cl->showscores = false;
- cl->showhelp = false;
- globals.server_flags &= ~SERVER_FLAG_SLOW_TIME;
- // ZOID
- if (ent->client->menu)
- {
- PMenu_Close(ent);
- ent->client->update_chase = true;
- return;
- }
- // ZOID
- if (cl->showinventory)
- {
- cl->showinventory = false;
- return;
- }
- // ZOID
- if (G_TeamplayEnabled() && cl->resp.ctf_team == CTF_NOTEAM)
- {
- CTFOpenJoinMenu(ent);
- return;
- }
- // ZOID
- cl->showinventory = true;
- gi.WriteByte(svc_inventory);
- for (i = 0; i < IT_TOTAL; i++)
- gi.WriteShort(cl->pers.inventory[i]);
- for (; i < MAX_ITEMS; i++)
- gi.WriteShort(0);
- gi.unicast(ent, true);
- }
- /*
- =================
- Cmd_InvUse_f
- =================
- */
- void Cmd_InvUse_f(edict_t *ent)
- {
- gitem_t *it;
- // ZOID
- if (ent->client->menu)
- {
- PMenu_Select(ent);
- return;
- }
- // ZOID
- if (ent->health <= 0 || ent->deadflag)
- return;
- ValidateSelectedItem(ent);
- if (ent->client->pers.selected_item == IT_NULL)
- {
- gi.LocClient_Print(ent, PRINT_HIGH, "$g_no_item_to_use");
- return;
- }
- it = &itemlist[ent->client->pers.selected_item];
- if (!it->use)
- {
- gi.LocClient_Print(ent, PRINT_HIGH, "$g_item_not_usable");
- return;
- }
- // don't allow weapon chains for invuse
- ent->client->no_weapon_chains = true;
- it->use(ent, it);
- ValidateSelectedItem(ent);
- }
- /*
- =================
- Cmd_WeapPrev_f
- =================
- */
- void Cmd_WeapPrev_f(edict_t *ent)
- {
- gclient_t *cl;
- item_id_t i, index;
- gitem_t *it;
- item_id_t selected_weapon;
- cl = ent->client;
- if (ent->health <= 0 || ent->deadflag)
- return;
- if (!cl->pers.weapon)
- return;
- // don't allow weapon chains for weapprev
- cl->no_weapon_chains = true;
- selected_weapon = cl->pers.weapon->id;
- // scan for the next valid one
- for (i = static_cast<item_id_t>(IT_NULL + 1); i <= IT_TOTAL; i = static_cast<item_id_t>(i + 1))
- {
- // PMM - prevent scrolling through ALL weapons
- index = static_cast<item_id_t>((selected_weapon + IT_TOTAL - i) % IT_TOTAL);
- if (!cl->pers.inventory[index])
- continue;
- it = &itemlist[index];
- if (!it->use)
- continue;
- if (!(it->flags & IF_WEAPON))
- continue;
- it->use(ent, it);
- // ROGUE
- if (cl->newweapon == it)
- return; // successful
- // ROGUE
- }
- }
- /*
- =================
- Cmd_WeapNext_f
- =================
- */
- void Cmd_WeapNext_f(edict_t *ent)
- {
- gclient_t *cl;
- item_id_t i, index;
- gitem_t *it;
- item_id_t selected_weapon;
- cl = ent->client;
- if (ent->health <= 0 || ent->deadflag)
- return;
- if (!cl->pers.weapon)
- return;
- // don't allow weapon chains for weapnext
- cl->no_weapon_chains = true;
- selected_weapon = cl->pers.weapon->id;
- // scan for the next valid one
- for (i = static_cast<item_id_t>(IT_NULL + 1); i <= IT_TOTAL; i = static_cast<item_id_t>(i + 1))
- {
- // PMM - prevent scrolling through ALL weapons
- index = static_cast<item_id_t>((selected_weapon + i) % IT_TOTAL);
- if (!cl->pers.inventory[index])
- continue;
- it = &itemlist[index];
- if (!it->use)
- continue;
- if (!(it->flags & IF_WEAPON))
- continue;
- it->use(ent, it);
- // PMM - prevent scrolling through ALL weapons
- // ROGUE
- if (cl->newweapon == it)
- return;
- // ROGUE
- }
- }
- /*
- =================
- Cmd_WeapLast_f
- =================
- */
- void Cmd_WeapLast_f(edict_t *ent)
- {
- gclient_t *cl;
- int index;
- gitem_t *it;
- cl = ent->client;
- if (ent->health <= 0 || ent->deadflag)
- return;
- if (!cl->pers.weapon || !cl->pers.lastweapon)
- return;
- // don't allow weapon chains for weaplast
- cl->no_weapon_chains = true;
- index = cl->pers.lastweapon->id;
- if (!cl->pers.inventory[index])
- return;
- it = &itemlist[index];
- if (!it->use)
- return;
- if (!(it->flags & IF_WEAPON))
- return;
- it->use(ent, it);
- }
- /*
- =================
- Cmd_InvDrop_f
- =================
- */
- void Cmd_InvDrop_f(edict_t *ent)
- {
- gitem_t *it;
- if (ent->health <= 0 || ent->deadflag)
- return;
- ValidateSelectedItem(ent);
- if (ent->client->pers.selected_item == IT_NULL)
- {
- gi.LocClient_Print(ent, PRINT_HIGH, "$g_no_item_to_drop");
- return;
- }
- it = &itemlist[ent->client->pers.selected_item];
- if (!it->drop)
- {
- gi.LocClient_Print(ent, PRINT_HIGH, "$g_item_not_droppable");
- return;
- }
- it->drop(ent, it);
- ValidateSelectedItem(ent);
- }
- /*
- =================
- Cmd_Kill_f
- =================
- */
- void Cmd_Kill_f(edict_t *ent)
- {
- // ZOID
- if (ent->client->resp.spectator)
- return;
- // ZOID
- if ((level.time - ent->client->respawn_time) < 5_sec)
- return;
- ent->flags &= ~FL_GODMODE;
- ent->health = 0;
- // ROGUE
- // make sure no trackers are still hurting us.
- if (ent->client->tracker_pain_time)
- RemoveAttackingPainDaemons(ent);
- if (ent->client->owned_sphere)
- {
- G_FreeEdict(ent->client->owned_sphere);
- ent->client->owned_sphere = nullptr;
- }
- // ROGUE
- // [Paril-KEX] don't allow kill to take points away in TDM
- player_die(ent, ent, ent, 100000, vec3_origin, { MOD_SUICIDE, !!teamplay->integer });
- }
- /*
- =================
- Cmd_Kill_AI_f
- =================
- */
- void Cmd_Kill_AI_f( edict_t * ent ) {
- if ( !sv_cheats->integer ) {
- gi.LocClient_Print( ent, PRINT_HIGH, "Kill_AI: Cheats Must Be Enabled!\n" );
- return;
- }
- // except the one we're looking at...
- edict_t *looked_at = nullptr;
- vec3_t start = ent->s.origin + vec3_t{0.f, 0.f, (float) ent->viewheight};
- vec3_t end = start + ent->client->v_forward * 1024.f;
- looked_at = gi.traceline(start, end, ent, MASK_SHOT).ent;
- const int numEdicts = globals.num_edicts;
- for ( int edictIdx = 1; edictIdx < numEdicts; ++edictIdx )
- {
- edict_t * edict = &g_edicts[ edictIdx ];
- if ( !edict->inuse || edict == looked_at ) {
- continue;
- }
- if ( ( edict->svflags & SVF_MONSTER ) == 0 )
- {
- continue;
- }
- G_FreeEdict( edict );
- }
- gi.LocClient_Print( ent, PRINT_HIGH, "Kill_AI: All AI Are Dead...\n" );
- }
- /*
- =================
- Cmd_Where_f
- =================
- */
- void Cmd_Where_f( edict_t * ent ) {
- if ( ent == nullptr || ent->client == nullptr ) {
- return;
- }
- const vec3_t & origin = ent->s.origin;
- std::string location;
- fmt::format_to( std::back_inserter( location ), FMT_STRING( "{:.1f} {:.1f} {:.1f} {:.1f} {:.1f} {:.1f}\n" ), origin[ 0 ], origin[ 1 ], origin[ 2 ], ent->client->ps.viewangles[0], ent->client->ps.viewangles[1], ent->client->ps.viewangles[2] );
- gi.LocClient_Print( ent, PRINT_HIGH, "Location: {}\n", location.c_str() );
- gi.SendToClipBoard( location.c_str() );
- }
- /*
- =================
- Cmd_Clear_AI_Enemy_f
- =================
- */
- void Cmd_Clear_AI_Enemy_f( edict_t * ent ) {
- if ( !sv_cheats->integer ) {
- gi.LocClient_Print( ent, PRINT_HIGH, "Cmd_Clear_AI_Enemy: Cheats Must Be Enabled!\n" );
- return;
- }
- const int numEdicts = globals.num_edicts;
- for ( int edictIdx = 1; edictIdx < numEdicts; ++edictIdx ) {
- edict_t * edict = &g_edicts[ edictIdx ];
- if ( !edict->inuse ) {
- continue;
- }
- if ( ( edict->svflags & SVF_MONSTER ) == 0 ) {
- continue;
- }
- edict->monsterinfo.aiflags |= AI_FORGET_ENEMY;
- }
- gi.LocClient_Print( ent, PRINT_HIGH, "Cmd_Clear_AI_Enemy: Clear All AI Enemies...\n" );
- }
- /*
- =================
- Cmd_PutAway_f
- =================
- */
- void Cmd_PutAway_f(edict_t *ent)
- {
- ent->client->showscores = false;
- ent->client->showhelp = false;
- ent->client->showinventory = false;
- globals.server_flags &= ~SERVER_FLAG_SLOW_TIME;
- // ZOID
- if (ent->client->menu)
- PMenu_Close(ent);
- ent->client->update_chase = true;
- // ZOID
- }
- int PlayerSort(const void *a, const void *b)
- {
- int anum, bnum;
- anum = *(const int *) a;
- bnum = *(const 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;
- }
- constexpr size_t MAX_IDEAL_PACKET_SIZE = 1024;
- /*
- =================
- Cmd_Players_f
- =================
- */
- void Cmd_Players_f(edict_t *ent)
- {
- size_t i;
- size_t count;
- static std::string small, large;
- int index[MAX_CLIENTS];
- small.clear();
- large.clear();
- count = 0;
- for (i = 0; i < game.maxclients; 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;
- if (count)
- {
- for (i = 0; i < count; i++)
- {
- fmt::format_to(std::back_inserter(small), FMT_STRING("{:3} {}\n"), game.clients[index[i]].ps.stats[STAT_FRAGS],
- game.clients[index[i]].pers.netname);
- if (small.length() + large.length() > MAX_IDEAL_PACKET_SIZE - 50)
- { // can't print all of them in one packet
- large += "...\n";
- break;
- }
- large += small;
- small.clear();
- }
-
- // remove the last newline
- large.pop_back();
- }
- gi.LocClient_Print(ent, PRINT_HIGH | PRINT_NO_NOTIFY, "$g_players", large.c_str(), count);
- }
- bool CheckFlood(edict_t *ent)
- {
- int i;
- gclient_t *cl;
- if (flood_msgs->integer)
- {
- cl = ent->client;
- if (level.time < cl->flood_locktill)
- {
- gi.LocClient_Print(ent, PRINT_HIGH, "$g_flood_cant_talk",
- (cl->flood_locktill - level.time).seconds<int32_t>());
- return true;
- }
- i = cl->flood_whenhead - flood_msgs->integer + 1;
- if (i < 0)
- i = (sizeof(cl->flood_when) / sizeof(cl->flood_when[0])) + i;
- if (i >= q_countof(cl->flood_when))
- i = 0;
- if (cl->flood_when[i] && level.time - cl->flood_when[i] < gtime_t::from_sec(flood_persecond->value))
- {
- cl->flood_locktill = level.time + gtime_t::from_sec(flood_waitdelay->value);
- gi.LocClient_Print(ent, PRINT_CHAT, "$g_flood_cant_talk",
- flood_waitdelay->integer);
- return true;
- }
- cl->flood_whenhead = (cl->flood_whenhead + 1) % (sizeof(cl->flood_when) / sizeof(cl->flood_when[0]));
- cl->flood_when[cl->flood_whenhead] = level.time;
- }
- return false;
- }
- /*
- =================
- Cmd_Wave_f
- =================
- */
- void Cmd_Wave_f(edict_t *ent)
- {
- int i;
- i = atoi(gi.argv(1));
- // no dead or noclip waving
- if (ent->deadflag || ent->movetype == MOVETYPE_NOCLIP)
- return;
- // can't wave when ducked
- bool do_animate = ent->client->anim_priority <= ANIM_WAVE && !(ent->client->ps.pmove.pm_flags & PMF_DUCKED);
- if (do_animate)
- ent->client->anim_priority = ANIM_WAVE;
- const char *other_notify_msg = nullptr, *other_notify_none_msg = nullptr;
- vec3_t start, dir;
- P_ProjectSource(ent, ent->client->v_angle, { 0, 0, 0 }, start, dir);
- // see who we're aiming at
- edict_t *aiming_at = nullptr;
- float best_dist = -9999;
- for (auto player : active_players())
- {
- if (player == ent)
- continue;
- vec3_t cdir = player->s.origin - start;
- float dist = cdir.normalize();
- float dot = ent->client->v_forward.dot(cdir);
- if (dot < 0.97)
- continue;
- else if (dist < best_dist)
- continue;
- best_dist = dist;
- aiming_at = player;
- }
- switch (i)
- {
- case GESTURE_FLIP_OFF:
- other_notify_msg = "$g_flipoff_other";
- other_notify_none_msg = "$g_flipoff_none";
- if (do_animate)
- {
- ent->s.frame = FRAME_flip01 - 1;
- ent->client->anim_end = FRAME_flip12;
- }
- break;
- case GESTURE_SALUTE:
- other_notify_msg = "$g_salute_other";
- other_notify_none_msg = "$g_salute_none";
- if (do_animate)
- {
- ent->s.frame = FRAME_salute01 - 1;
- ent->client->anim_end = FRAME_salute11;
- }
- break;
- case GESTURE_TAUNT:
- other_notify_msg = "$g_taunt_other";
- other_notify_none_msg = "$g_taunt_none";
- if (do_animate)
- {
- ent->s.frame = FRAME_taunt01 - 1;
- ent->client->anim_end = FRAME_taunt17;
- }
- break;
- case GESTURE_WAVE:
- other_notify_msg = "$g_wave_other";
- other_notify_none_msg = "$g_wave_none";
- if (do_animate)
- {
- ent->s.frame = FRAME_wave01 - 1;
- ent->client->anim_end = FRAME_wave11;
- }
- break;
- case GESTURE_POINT:
- default:
- other_notify_msg = "$g_point_other";
- other_notify_none_msg = "$g_point_none";
- if (do_animate)
- {
- ent->s.frame = FRAME_point01 - 1;
- ent->client->anim_end = FRAME_point12;
- }
- break;
- }
- bool has_a_target = false;
- if (i == GESTURE_POINT)
- {
- for (auto player : active_players())
- {
- if (player == ent)
- continue;
- else if (!OnSameTeam(ent, player))
- continue;
- has_a_target = true;
- break;
- }
- }
- if (i == GESTURE_POINT && has_a_target)
- {
- // don't do this stuff if we're flooding
- if (CheckFlood(ent))
- return;
- trace_t tr = gi.traceline(start, start + (ent->client->v_forward * 2048), ent, MASK_SHOT & ~CONTENTS_WINDOW);
- other_notify_msg = "$g_point_other_ping";
- uint32_t key = GetUnicastKey();
- if (tr.fraction != 1.0f)
- {
- // send to all teammates
- for (auto player : active_players())
- {
- if (player != ent && !OnSameTeam(ent, player))
- continue;
- gi.WriteByte(svc_poi);
- gi.WriteShort(POI_PING + (ent->s.number - 1));
- gi.WriteShort(5000);
- gi.WritePosition(tr.endpos);
- gi.WriteShort(level.pic_ping);
- gi.WriteByte(208);
- gi.WriteByte(POI_FLAG_NONE);
- gi.unicast(player, false);
- gi.local_sound(player, CHAN_AUTO, gi.soundindex("misc/help_marker.wav"), 1.0f, ATTN_NONE, 0.0f, key);
- gi.LocClient_Print(player, PRINT_HIGH, other_notify_msg, ent->client->pers.netname);
- }
- }
- }
- else
- {
- if (CheckFlood(ent))
- return;
- edict_t* targ = nullptr;
- while ((targ = findradius(targ, ent->s.origin, 1024)) != nullptr)
- {
- if (ent == targ) continue;
- if (!targ->client) continue;
- if (!gi.inPVS(ent->s.origin, targ->s.origin, false)) continue;
- if (aiming_at && other_notify_msg)
- gi.LocClient_Print(targ, PRINT_TTS, other_notify_msg, ent->client->pers.netname, aiming_at->client->pers.netname);
- else if (other_notify_none_msg)
- gi.LocClient_Print(targ, PRINT_TTS, other_notify_none_msg, ent->client->pers.netname);
- }
- if (aiming_at && other_notify_msg)
- gi.LocClient_Print(ent, PRINT_TTS, other_notify_msg, ent->client->pers.netname, aiming_at->client->pers.netname);
- else if (other_notify_none_msg)
- gi.LocClient_Print(ent, PRINT_TTS, other_notify_none_msg, ent->client->pers.netname);
- }
- ent->client->anim_time = 0_ms;
- }
- #ifndef KEX_Q2_GAME
- /*
- ==================
- Cmd_Say_f
- NB: only used for non-Playfab stuff
- ==================
- */
- void Cmd_Say_f(edict_t *ent, bool arg0)
- {
- edict_t *other;
- const char *p_in;
- static std::string text;
- if (gi.argc() < 2 && !arg0)
- return;
- else if (CheckFlood(ent))
- return;
- text.clear();
- fmt::format_to(std::back_inserter(text), FMT_STRING("{}: "), ent->client->pers.netname);
- if (arg0)
- {
- text += gi.argv(0);
- text += " ";
- text += gi.args();
- }
- else
- {
- p_in = gi.args();
- size_t in_len = strlen(p_in);
- if (p_in[0] == '\"' && p_in[in_len - 1] == '\"')
- text += std::string_view(p_in + 1, in_len - 2);
- else
- text += p_in;
- }
- // don't let text be too long for malicious reasons
- if (text.length() > 150)
- text.resize(150);
- if (text.back() != '\n')
- text.push_back('\n');
- if (sv_dedicated->integer)
- gi.Client_Print(nullptr, PRINT_CHAT, text.c_str());
- for (uint32_t j = 1; j <= game.maxclients; j++)
- {
- other = &g_edicts[j];
- if (!other->inuse)
- continue;
- if (!other->client)
- continue;
- gi.Client_Print(other, PRINT_CHAT, text.c_str());
- }
- }
- #endif
- void Cmd_PlayerList_f(edict_t *ent)
- {
- uint32_t i;
- static std::string str, text;
- edict_t *e2;
- str.clear();
- text.clear();
- // connect time, ping, score, name
- for (i = 0, e2 = g_edicts + 1; i < game.maxclients; i++, e2++)
- {
- if (!e2->inuse)
- continue;
- fmt::format_to(std::back_inserter(str), FMT_STRING("{:02}:{:02} {:4} {:3} {}{}\n"), (level.time - e2->client->resp.entertime).milliseconds() / 60000,
- ((level.time - e2->client->resp.entertime).milliseconds() % 60000) / 1000, e2->client->ping,
- e2->client->resp.score, e2->client->pers.netname, e2->client->resp.spectator ? " (spectator)" : "");
- if (text.length() + str.length() > MAX_IDEAL_PACKET_SIZE - 50)
- {
- text += "...\n";
- break;
- }
- text += str;
- }
- if (text.length())
- gi.Client_Print(ent, PRINT_HIGH, text.c_str());
- }
- void Cmd_Switchteam_f(edict_t* ent)
- {
- if (!G_TeamplayEnabled())
- return;
- // [Paril-KEX] in force-join, just do a regular team join.
- if (g_teamplay_force_join->integer)
- {
- // check if we should even switch teams
- edict_t *player;
- uint32_t team1count = 0, team2count = 0;
- ctfteam_t best_team;
- for (uint32_t i = 1; i <= game.maxclients; i++)
- {
- player = &g_edicts[i];
- // NB: we are counting ourselves in this one, unlike
- // the other assign team func
- if (!player->inuse)
- continue;
- switch (player->client->resp.ctf_team)
- {
- case CTF_TEAM1:
- team1count++;
- break;
- case CTF_TEAM2:
- team2count++;
- break;
- default:
- break;
- }
- }
- if (team1count < team2count)
- best_team = CTF_TEAM1;
- else
- best_team = CTF_TEAM2;
- if (ent->client->resp.ctf_team != best_team)
- {
- ////
- ent->svflags = SVF_NONE;
- ent->flags &= ~FL_GODMODE;
- ent->client->resp.ctf_team = best_team;
- ent->client->resp.ctf_state = 0;
- char value[MAX_INFO_VALUE] = { 0 };
- gi.Info_ValueForKey(ent->client->pers.userinfo, "skin", value, sizeof(value));
- CTFAssignSkin(ent, value);
- // if anybody has a menu open, update it immediately
- CTFDirtyTeamMenu();
- if (ent->solid == SOLID_NOT)
- {
- // spectator
- PutClientInServer(ent);
- G_PostRespawn(ent);
- gi.LocBroadcast_Print(PRINT_HIGH, "$g_joined_team",
- ent->client->pers.netname, CTFTeamName(best_team));
- return;
- }
- ent->health = 0;
- player_die(ent, ent, ent, 100000, vec3_origin, { MOD_SUICIDE, true });
- // don't even bother waiting for death frames
- ent->deadflag = true;
- respawn(ent);
- ent->client->resp.score = 0;
- gi.LocBroadcast_Print(PRINT_HIGH, "$g_changed_team",
- ent->client->pers.netname, CTFTeamName(best_team));
- }
- return;
- }
- if (ent->client->resp.ctf_team != CTF_NOTEAM)
- CTFObserver(ent);
- if (!ent->client->menu)
- CTFOpenJoinMenu(ent);
- }
- static void Cmd_ListMonsters_f(edict_t *ent)
- {
- if (!G_CheatCheck(ent))
- return;
- else if (!g_debug_monster_kills->integer)
- return;
- for (size_t i = 0; i < level.total_monsters; i++)
- {
- edict_t *e = level.monsters_registered[i];
- if (!e || !e->inuse)
- continue;
- else if (!(e->svflags & SVF_MONSTER) || (e->monsterinfo.aiflags & AI_DO_NOT_COUNT))
- continue;
- else if (e->deadflag)
- continue;
- gi.Com_PrintFmt("{}\n", *e);
- }
- }
- /*
- =================
- ClientCommand
- =================
- */
- void ClientCommand(edict_t *ent)
- {
- const char *cmd;
- if (!ent->client)
- return; // not fully in game yet
- cmd = gi.argv(0);
- if (Q_strcasecmp(cmd, "players") == 0)
- {
- Cmd_Players_f(ent);
- return;
- }
- // [Paril-KEX] these have to go through the lobby system
- #ifndef KEX_Q2_GAME
- if (Q_strcasecmp(cmd, "say") == 0)
- {
- Cmd_Say_f(ent, false);
- return;
- }
- if (Q_strcasecmp(cmd, "say_team") == 0 || Q_strcasecmp(cmd, "steam") == 0)
- {
- if (G_TeamplayEnabled())
- CTFSay_Team(ent, gi.args());
- else
- Cmd_Say_f(ent, false);
- return;
- }
- #endif
- if (Q_strcasecmp(cmd, "score") == 0)
- {
- Cmd_Score_f(ent);
- return;
- }
- if (Q_strcasecmp(cmd, "help") == 0)
- {
- Cmd_Help_f(ent);
- return;
- }
- if (Q_strcasecmp(cmd, "listmonsters") == 0)
- {
- Cmd_ListMonsters_f(ent);
- return;
- }
- if (level.intermissiontime)
- return;
-
- if ( Q_strcasecmp( cmd, "target" ) == 0 )
- Cmd_Target_f( ent );
- else if ( Q_strcasecmp( cmd, "use" ) == 0 || Q_strcasecmp( cmd, "use_only" ) == 0 ||
- Q_strcasecmp( cmd, "use_index" ) == 0 || Q_strcasecmp( cmd, "use_index_only" ) == 0 )
- Cmd_Use_f( ent );
- else if ( Q_strcasecmp( cmd, "drop" ) == 0 ||
- Q_strcasecmp( cmd, "drop_index" ) == 0 )
- Cmd_Drop_f( ent );
- else if ( Q_strcasecmp( cmd, "give" ) == 0 )
- Cmd_Give_f( ent );
- else if ( Q_strcasecmp( cmd, "god" ) == 0 )
- Cmd_God_f( ent );
- else if (Q_strcasecmp(cmd, "immortal") == 0)
- Cmd_Immortal_f(ent);
- else if ( Q_strcasecmp( cmd, "setpoi" ) == 0 )
- Cmd_SetPOI_f( ent );
- else if ( Q_strcasecmp( cmd, "checkpoi" ) == 0 )
- Cmd_CheckPOI_f( ent );
- // Paril: cheats to help with dev
- else if ( Q_strcasecmp( cmd, "spawn" ) == 0 )
- Cmd_Spawn_f( ent );
- else if ( Q_strcasecmp( cmd, "teleport" ) == 0 )
- Cmd_Teleport_f( ent );
- else if ( Q_strcasecmp( cmd, "notarget" ) == 0 )
- Cmd_Notarget_f( ent );
- else if ( Q_strcasecmp( cmd, "novisible" ) == 0 )
- Cmd_Novisible_f( ent );
- else if ( Q_strcasecmp( cmd, "alertall" ) == 0 )
- Cmd_AlertAll_f( ent );
- else if ( Q_strcasecmp( cmd, "noclip" ) == 0 )
- Cmd_Noclip_f( ent );
- else if ( Q_strcasecmp( cmd, "inven" ) == 0 )
- Cmd_Inven_f( ent );
- else if ( Q_strcasecmp( cmd, "invnext" ) == 0 )
- SelectNextItem( ent, IF_ANY );
- else if ( Q_strcasecmp( cmd, "invprev" ) == 0 )
- SelectPrevItem( ent, IF_ANY );
- else if ( Q_strcasecmp( cmd, "invnextw" ) == 0 )
- SelectNextItem( ent, IF_WEAPON );
- else if ( Q_strcasecmp( cmd, "invprevw" ) == 0 )
- SelectPrevItem( ent, IF_WEAPON );
- else if ( Q_strcasecmp( cmd, "invnextp" ) == 0 )
- SelectNextItem( ent, IF_POWERUP );
- else if ( Q_strcasecmp( cmd, "invprevp" ) == 0 )
- SelectPrevItem( ent, IF_POWERUP );
- else if ( Q_strcasecmp( cmd, "invuse" ) == 0 )
- Cmd_InvUse_f( ent );
- else if ( Q_strcasecmp( cmd, "invdrop" ) == 0 )
- Cmd_InvDrop_f( ent );
- else if ( Q_strcasecmp( cmd, "weapprev" ) == 0 )
- Cmd_WeapPrev_f( ent );
- else if ( Q_strcasecmp( cmd, "weapnext" ) == 0 )
- Cmd_WeapNext_f( ent );
- else if ( Q_strcasecmp( cmd, "weaplast" ) == 0 || Q_strcasecmp( cmd, "lastweap" ) == 0 )
- Cmd_WeapLast_f( ent );
- else if ( Q_strcasecmp( cmd, "kill" ) == 0 )
- Cmd_Kill_f( ent );
- else if ( Q_strcasecmp( cmd, "kill_ai" ) == 0 )
- Cmd_Kill_AI_f( ent );
- else if ( Q_strcasecmp( cmd, "where" ) == 0 )
- Cmd_Where_f( ent );
- else if ( Q_strcasecmp( cmd, "clear_ai_enemy" ) == 0 )
- Cmd_Clear_AI_Enemy_f( ent );
- else if (Q_strcasecmp(cmd, "putaway") == 0)
- Cmd_PutAway_f(ent);
- else if (Q_strcasecmp(cmd, "wave") == 0)
- Cmd_Wave_f(ent);
- else if (Q_strcasecmp(cmd, "playerlist") == 0)
- Cmd_PlayerList_f(ent);
- // ZOID
- else if (Q_strcasecmp(cmd, "team") == 0)
- CTFTeam_f(ent);
- else if (Q_strcasecmp(cmd, "id") == 0)
- CTFID_f(ent);
- else if (Q_strcasecmp(cmd, "yes") == 0)
- CTFVoteYes(ent);
- else if (Q_strcasecmp(cmd, "no") == 0)
- CTFVoteNo(ent);
- else if (Q_strcasecmp(cmd, "ready") == 0)
- CTFReady(ent);
- else if (Q_strcasecmp(cmd, "notready") == 0)
- CTFNotReady(ent);
- else if (Q_strcasecmp(cmd, "ghost") == 0)
- CTFGhost(ent);
- else if (Q_strcasecmp(cmd, "admin") == 0)
- CTFAdmin(ent);
- else if (Q_strcasecmp(cmd, "stats") == 0)
- CTFStats(ent);
- else if (Q_strcasecmp(cmd, "warp") == 0)
- CTFWarp(ent);
- else if (Q_strcasecmp(cmd, "boot") == 0)
- CTFBoot(ent);
- else if (Q_strcasecmp(cmd, "playerlist") == 0)
- CTFPlayerList(ent);
- else if (Q_strcasecmp(cmd, "observer") == 0)
- CTFObserver(ent);
- // ZOID
- else if (Q_strcasecmp(cmd, "switchteam") == 0)
- Cmd_Switchteam_f(ent);
- #ifndef KEX_Q2_GAME
- else // anything that doesn't match a command will be a chat
- Cmd_Say_f(ent, true);
- #else
- // anything that doesn't match a command will inform them
- else
- gi.LocClient_Print(ent, PRINT_HIGH, "invalid game command \"{}\"\n", gi.argv(0));
- #endif
- }
|