1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 */
20 #include "g_local.h"
21 #include "m_player.h"
22 
23 
ClientTeam(edict_t * ent)24 char *ClientTeam (edict_t *ent)
25 {
26 	char		*p;
27 	static char	value[512];
28 
29 	value[0] = 0;
30 
31 	if (!ent->client)
32 		return value;
33 
34 	strcpy(value, Info_ValueForKey (ent->client->pers.userinfo, "skin"));
35 	p = strchr(value, '/');
36 	if (!p)
37 		return value;
38 
39 	if ((int)(dmflags->value) & DF_MODELTEAMS)
40 	{
41 		*p = 0;
42 		return value;
43 	}
44 
45 	// if ((int)(dmflags->value) & DF_SKINTEAMS)
46 	return ++p;
47 }
48 
OnSameTeam(edict_t * ent1,edict_t * ent2)49 qboolean OnSameTeam (edict_t *ent1, edict_t *ent2)
50 {
51 	char	ent1Team [512];
52 	char	ent2Team [512];
53 
54 	if (!((int)(dmflags->value) & (DF_MODELTEAMS | DF_SKINTEAMS)))
55 		return false;
56 
57 	strcpy (ent1Team, ClientTeam (ent1));
58 	strcpy (ent2Team, ClientTeam (ent2));
59 
60 	if (strcmp(ent1Team, ent2Team) == 0)
61 		return true;
62 	return false;
63 }
64 
65 
SelectNextItem(edict_t * ent,int itflags)66 void SelectNextItem (edict_t *ent, int itflags)
67 {
68 	gclient_t	*cl;
69 	int			i, index;
70 	gitem_t		*it;
71 
72 	cl = ent->client;
73 
74 //ZOID
75 	if (cl->menu) {
76 		PMenu_Next(ent);
77 		return;
78 	} else if (cl->chase_target) {
79 		ChaseNext(ent);
80 		return;
81 	}
82 //ZOID
83 
84 	// scan  for the next valid one
85 	for (i=1 ; i<=MAX_ITEMS ; i++)
86 	{
87 		index = (cl->pers.selected_item + i)%MAX_ITEMS;
88 		if (!cl->pers.inventory[index])
89 			continue;
90 		it = &itemlist[index];
91 		if (!it->use)
92 			continue;
93 		if (!(it->flags & itflags))
94 			continue;
95 
96 		cl->pers.selected_item = index;
97 		return;
98 	}
99 
100 	cl->pers.selected_item = -1;
101 }
102 
SelectPrevItem(edict_t * ent,int itflags)103 void SelectPrevItem (edict_t *ent, int itflags)
104 {
105 	gclient_t	*cl;
106 	int			i, index;
107 	gitem_t		*it;
108 
109 	cl = ent->client;
110 
111 //ZOID
112 	if (cl->menu) {
113 		PMenu_Prev(ent);
114 		return;
115 	} else if (cl->chase_target) {
116 		ChasePrev(ent);
117 		return;
118 	}
119 //ZOID
120 
121 	// scan  for the next valid one
122 	for (i=1 ; i<=MAX_ITEMS ; i++)
123 	{
124 		index = (cl->pers.selected_item + MAX_ITEMS - i)%MAX_ITEMS;
125 		if (!cl->pers.inventory[index])
126 			continue;
127 		it = &itemlist[index];
128 		if (!it->use)
129 			continue;
130 		if (!(it->flags & itflags))
131 			continue;
132 
133 		cl->pers.selected_item = index;
134 		return;
135 	}
136 
137 	cl->pers.selected_item = -1;
138 }
139 
ValidateSelectedItem(edict_t * ent)140 void ValidateSelectedItem (edict_t *ent)
141 {
142 	gclient_t	*cl;
143 
144 	cl = ent->client;
145 
146 	if (cl->pers.inventory[cl->pers.selected_item])
147 		return;		// valid
148 
149 	SelectNextItem (ent, -1);
150 }
151 
152 
153 //=================================================================================
154 
155 /*
156 ==================
157 Cmd_Give_f
158 
159 Give items to a client
160 ==================
161 */
Cmd_Give_f(edict_t * ent)162 void Cmd_Give_f (edict_t *ent)
163 {
164 	char		*name;
165 	gitem_t		*it;
166 	int			index;
167 	int			i;
168 	qboolean	give_all;
169 	edict_t		*it_ent;
170 
171 	if (deathmatch->value && !sv_cheats->value)
172 	{
173 		gi.cprintf (ent, PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n");
174 		return;
175 	}
176 
177 	name = gi.args();
178 
179 	if (Q_stricmp(name, "all") == 0)
180 		give_all = true;
181 	else
182 		give_all = false;
183 
184 	if (give_all || Q_stricmp(gi.argv(1), "health") == 0)
185 	{
186 		if (gi.argc() == 3)
187 			ent->health = atoi(gi.argv(2));
188 		else
189 			ent->health = ent->max_health;
190 		if (!give_all)
191 			return;
192 	}
193 
194 	if (give_all || Q_stricmp(name, "weapons") == 0)
195 	{
196 		for (i=0 ; i<game.num_items ; i++)
197 		{
198 			it = itemlist + i;
199 			if (!it->pickup)
200 				continue;
201 			if (!(it->flags & IT_WEAPON))
202 				continue;
203 			ent->client->pers.inventory[i] += 1;
204 		}
205 		if (!give_all)
206 			return;
207 	}
208 
209 	if (give_all || Q_stricmp(name, "ammo") == 0)
210 	{
211 		for (i=0 ; i<game.num_items ; i++)
212 		{
213 			it = itemlist + i;
214 			if (!it->pickup)
215 				continue;
216 			if (!(it->flags & IT_AMMO))
217 				continue;
218 			Add_Ammo (ent, it, 1000);
219 		}
220 		if (!give_all)
221 			return;
222 	}
223 
224 	if (give_all || Q_stricmp(name, "armor") == 0)
225 	{
226 		gitem_armor_t	*info;
227 
228 		it = FindItem("Jacket Armor");
229 		ent->client->pers.inventory[ITEM_INDEX(it)] = 0;
230 
231 		it = FindItem("Combat Armor");
232 		ent->client->pers.inventory[ITEM_INDEX(it)] = 0;
233 
234 		it = FindItem("Body Armor");
235 		info = (gitem_armor_t *)it->info;
236 		ent->client->pers.inventory[ITEM_INDEX(it)] = info->max_count;
237 
238 		if (!give_all)
239 			return;
240 	}
241 
242 	if (give_all || Q_stricmp(name, "Power Shield") == 0)
243 	{
244 		it = FindItem("Power Shield");
245 		it_ent = G_Spawn();
246 		it_ent->classname = it->classname;
247 		SpawnItem (it_ent, it);
248 		Touch_Item (it_ent, ent, NULL, NULL);
249 		if (it_ent->inuse)
250 			G_FreeEdict(it_ent);
251 
252 		if (!give_all)
253 			return;
254 	}
255 
256 	if (give_all)
257 	{
258 		for (i=0 ; i<game.num_items ; i++)
259 		{
260 			it = itemlist + i;
261 			if (!it->pickup)
262 				continue;
263 			if (it->flags & (IT_ARMOR|IT_WEAPON|IT_AMMO))
264 				continue;
265 			ent->client->pers.inventory[i] = 1;
266 		}
267 		return;
268 	}
269 
270 	it = FindItem (name);
271 	if (!it)
272 	{
273 		name = gi.argv(1);
274 		it = FindItem (name);
275 		if (!it)
276 		{
277 			gi.cprintf (ent, PRINT_HIGH, "unknown item\n");
278 			return;
279 		}
280 	}
281 
282 	if (!it->pickup)
283 	{
284 		gi.cprintf (ent, PRINT_HIGH, "non-pickup item\n");
285 		return;
286 	}
287 
288 	index = ITEM_INDEX(it);
289 
290 	if (it->flags & IT_AMMO)
291 	{
292 		if (gi.argc() == 3)
293 			ent->client->pers.inventory[index] = atoi(gi.argv(2));
294 		else
295 			ent->client->pers.inventory[index] += it->quantity;
296 	}
297 	else
298 	{
299 		it_ent = G_Spawn();
300 		it_ent->classname = it->classname;
301 		SpawnItem (it_ent, it);
302 		Touch_Item (it_ent, ent, NULL, NULL);
303 		if (it_ent->inuse)
304 			G_FreeEdict(it_ent);
305 	}
306 }
307 
308 
309 /*
310 ==================
311 Cmd_God_f
312 
313 Sets client to godmode
314 
315 argv(0) god
316 ==================
317 */
Cmd_God_f(edict_t * ent)318 void Cmd_God_f (edict_t *ent)
319 {
320 	char	*msg;
321 
322 	if (deathmatch->value && !sv_cheats->value)
323 	{
324 		gi.cprintf (ent, PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n");
325 		return;
326 	}
327 
328 	ent->flags ^= FL_GODMODE;
329 	if (!(ent->flags & FL_GODMODE) )
330 		msg = "godmode OFF\n";
331 	else
332 		msg = "godmode ON\n";
333 
334 	gi.cprintf (ent, PRINT_HIGH, msg);
335 }
336 
337 
338 /*
339 ==================
340 Cmd_Notarget_f
341 
342 Sets client to notarget
343 
344 argv(0) notarget
345 ==================
346 */
Cmd_Notarget_f(edict_t * ent)347 void Cmd_Notarget_f (edict_t *ent)
348 {
349 	char	*msg;
350 
351 	if (deathmatch->value && !sv_cheats->value)
352 	{
353 		gi.cprintf (ent, PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n");
354 		return;
355 	}
356 
357 	ent->flags ^= FL_NOTARGET;
358 	if (!(ent->flags & FL_NOTARGET) )
359 		msg = "notarget OFF\n";
360 	else
361 		msg = "notarget ON\n";
362 
363 	gi.cprintf (ent, PRINT_HIGH, msg);
364 }
365 
366 
367 /*
368 ==================
369 Cmd_Noclip_f
370 
371 argv(0) noclip
372 ==================
373 */
Cmd_Noclip_f(edict_t * ent)374 void Cmd_Noclip_f (edict_t *ent)
375 {
376 	char	*msg;
377 
378 	if (deathmatch->value && !sv_cheats->value)
379 	{
380 		gi.cprintf (ent, PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n");
381 		return;
382 	}
383 
384 	if (ent->movetype == MOVETYPE_NOCLIP)
385 	{
386 		ent->movetype = MOVETYPE_WALK;
387 		msg = "noclip OFF\n";
388 	}
389 	else
390 	{
391 		ent->movetype = MOVETYPE_NOCLIP;
392 		msg = "noclip ON\n";
393 	}
394 
395 	gi.cprintf (ent, PRINT_HIGH, msg);
396 }
397 
398 
399 /*
400 ==================
401 Cmd_Use_f
402 
403 Use an inventory item
404 ==================
405 */
Cmd_Use_f(edict_t * ent)406 void Cmd_Use_f (edict_t *ent)
407 {
408 	int			index;
409 	gitem_t		*it;
410 	char		*s;
411 
412 	s = gi.args();
413 	it = FindItem (s);
414 	if (!it)
415 	{
416 		gi.cprintf (ent, PRINT_HIGH, "unknown item: %s\n", s);
417 		return;
418 	}
419 	if (!it->use)
420 	{
421 		gi.cprintf (ent, PRINT_HIGH, "Item is not usable.\n");
422 		return;
423 	}
424 	index = ITEM_INDEX(it);
425 	if (!ent->client->pers.inventory[index])
426 	{
427 		gi.cprintf (ent, PRINT_HIGH, "Out of item: %s\n", s);
428 		return;
429 	}
430 
431 	it->use (ent, it);
432 }
433 
434 
435 /*
436 ==================
437 Cmd_Drop_f
438 
439 Drop an inventory item
440 ==================
441 */
Cmd_Drop_f(edict_t * ent)442 void Cmd_Drop_f (edict_t *ent)
443 {
444 	int			index;
445 	gitem_t		*it;
446 	char		*s;
447 
448 //ZOID--special case for tech powerups
449 	if (Q_stricmp(gi.args(), "tech") == 0 && (it = CTFWhat_Tech(ent)) != NULL) {
450 		it->drop (ent, it);
451 		return;
452 	}
453 //ZOID
454 
455 	s = gi.args();
456 	it = FindItem (s);
457 	if (!it)
458 	{
459 		gi.cprintf (ent, PRINT_HIGH, "unknown item: %s\n", s);
460 		return;
461 	}
462 	if (!it->drop)
463 	{
464 		gi.cprintf (ent, PRINT_HIGH, "Item is not dropable.\n");
465 		return;
466 	}
467 	index = ITEM_INDEX(it);
468 	if (!ent->client->pers.inventory[index])
469 	{
470 		gi.cprintf (ent, PRINT_HIGH, "Out of item: %s\n", s);
471 		return;
472 	}
473 
474 	it->drop (ent, it);
475 }
476 
477 
478 /*
479 =================
480 Cmd_Inven_f
481 =================
482 */
Cmd_Inven_f(edict_t * ent)483 void Cmd_Inven_f (edict_t *ent)
484 {
485 	int			i;
486 	gclient_t	*cl;
487 
488 	cl = ent->client;
489 
490 	cl->showscores = false;
491 	cl->showhelp = false;
492 
493 //ZOID
494 	if (ent->client->menu) {
495 		PMenu_Close(ent);
496 		ent->client->update_chase = true;
497 		return;
498 	}
499 //ZOID
500 
501 	if (cl->showinventory)
502 	{
503 		cl->showinventory = false;
504 		return;
505 	}
506 
507 //ZOID
508 	if (ctf->value && cl->resp.ctf_team == CTF_NOTEAM) {
509 		CTFOpenJoinMenu(ent);
510 		return;
511 	}
512 //ZOID
513 
514 	cl->showinventory = true;
515 
516 	gi.WriteByte (svc_inventory);
517 	for (i=0 ; i<MAX_ITEMS ; i++)
518 	{
519 		gi.WriteShort (cl->pers.inventory[i]);
520 	}
521 	gi.unicast (ent, true);
522 }
523 
524 /*
525 =================
526 Cmd_InvUse_f
527 =================
528 */
Cmd_InvUse_f(edict_t * ent)529 void Cmd_InvUse_f (edict_t *ent)
530 {
531 	gitem_t		*it;
532 
533 //ZOID
534 	if (ent->client->menu) {
535 		PMenu_Select(ent);
536 		return;
537 	}
538 //ZOID
539 
540 	ValidateSelectedItem (ent);
541 
542 	if (ent->client->pers.selected_item == -1)
543 	{
544 		gi.cprintf (ent, PRINT_HIGH, "No item to use.\n");
545 		return;
546 	}
547 
548 	it = &itemlist[ent->client->pers.selected_item];
549 	if (!it->use)
550 	{
551 		gi.cprintf (ent, PRINT_HIGH, "Item is not usable.\n");
552 		return;
553 	}
554 	it->use (ent, it);
555 }
556 
557 //ZOID
558 /*
559 =================
560 Cmd_LastWeap_f
561 =================
562 */
Cmd_LastWeap_f(edict_t * ent)563 void Cmd_LastWeap_f (edict_t *ent)
564 {
565 	gclient_t	*cl;
566 
567 	cl = ent->client;
568 
569 	if (!cl->pers.weapon || !cl->pers.lastweapon)
570 		return;
571 
572 	cl->pers.lastweapon->use (ent, cl->pers.lastweapon);
573 }
574 //ZOID
575 
576 /*
577 =================
578 Cmd_WeapPrev_f
579 =================
580 */
Cmd_WeapPrev_f(edict_t * ent)581 void Cmd_WeapPrev_f (edict_t *ent)
582 {
583 	gclient_t	*cl;
584 	int			i, index;
585 	gitem_t		*it;
586 	int			selected_weapon;
587 
588 	cl = ent->client;
589 
590 	if (!cl->pers.weapon)
591 		return;
592 
593 	selected_weapon = ITEM_INDEX(cl->pers.weapon);
594 
595 	// scan  for the next valid one
596 	for (i=1 ; i<=MAX_ITEMS ; i++)
597 	{
598 		index = (selected_weapon + i)%MAX_ITEMS;
599 		if (!cl->pers.inventory[index])
600 			continue;
601 		it = &itemlist[index];
602 		if (!it->use)
603 			continue;
604 		if (! (it->flags & IT_WEAPON) )
605 			continue;
606 		it->use (ent, it);
607 		if (cl->pers.weapon == it)
608 			return;	// successful
609 	}
610 }
611 
612 /*
613 =================
614 Cmd_WeapNext_f
615 =================
616 */
Cmd_WeapNext_f(edict_t * ent)617 void Cmd_WeapNext_f (edict_t *ent)
618 {
619 	gclient_t	*cl;
620 	int			i, index;
621 	gitem_t		*it;
622 	int			selected_weapon;
623 
624 	cl = ent->client;
625 
626 	if (!cl->pers.weapon)
627 		return;
628 
629 	selected_weapon = ITEM_INDEX(cl->pers.weapon);
630 
631 	// scan  for the next valid one
632 	for (i=1 ; i<=MAX_ITEMS ; i++)
633 	{
634 		index = (selected_weapon + MAX_ITEMS - i)%MAX_ITEMS;
635 		if (!cl->pers.inventory[index])
636 			continue;
637 		it = &itemlist[index];
638 		if (!it->use)
639 			continue;
640 		if (! (it->flags & IT_WEAPON) )
641 			continue;
642 		it->use (ent, it);
643 		if (cl->pers.weapon == it)
644 			return;	// successful
645 	}
646 }
647 
648 /*
649 =================
650 Cmd_WeapLast_f
651 =================
652 */
Cmd_WeapLast_f(edict_t * ent)653 void Cmd_WeapLast_f (edict_t *ent)
654 {
655 	gclient_t	*cl;
656 	int			index;
657 	gitem_t		*it;
658 
659 	cl = ent->client;
660 
661 	if (!cl->pers.weapon || !cl->pers.lastweapon)
662 		return;
663 
664 	index = ITEM_INDEX(cl->pers.lastweapon);
665 	if (!cl->pers.inventory[index])
666 		return;
667 	it = &itemlist[index];
668 	if (!it->use)
669 		return;
670 	if (! (it->flags & IT_WEAPON) )
671 		return;
672 	it->use (ent, it);
673 }
674 
675 /*
676 =================
677 Cmd_InvDrop_f
678 =================
679 */
Cmd_InvDrop_f(edict_t * ent)680 void Cmd_InvDrop_f (edict_t *ent)
681 {
682 	gitem_t		*it;
683 
684 	ValidateSelectedItem (ent);
685 
686 	if (ent->client->pers.selected_item == -1)
687 	{
688 		gi.cprintf (ent, PRINT_HIGH, "No item to drop.\n");
689 		return;
690 	}
691 
692 	it = &itemlist[ent->client->pers.selected_item];
693 	if (!it->drop)
694 	{
695 		gi.cprintf (ent, PRINT_HIGH, "Item is not dropable.\n");
696 		return;
697 	}
698 	it->drop (ent, it);
699 }
700 
701 /*
702 =================
703 Cmd_Kill_f
704 =================
705 */
Cmd_Kill_f(edict_t * ent)706 void Cmd_Kill_f (edict_t *ent)
707 {
708 //ZOID
709 	if (ent->solid == SOLID_NOT)
710 		return;
711 //ZOID
712 
713 	if((level.time - ent->client->respawn_time) < 5)
714 		return;
715 	ent->flags &= ~FL_GODMODE;
716 	ent->health = 0;
717 	meansOfDeath = MOD_SUICIDE;
718 	player_die (ent, ent, ent, 100000, vec3_origin);
719 }
720 
721 /*
722 =================
723 Cmd_PutAway_f
724 =================
725 */
Cmd_PutAway_f(edict_t * ent)726 void Cmd_PutAway_f (edict_t *ent)
727 {
728 	ent->client->showscores = false;
729 	ent->client->showhelp = false;
730 	ent->client->showinventory = false;
731 //ZOID
732 	if (ent->client->menu)
733 		PMenu_Close(ent);
734 	ent->client->update_chase = true;
735 //ZOID
736 }
737 
738 
PlayerSort(void const * a,void const * b)739 int PlayerSort (void const *a, void const *b)
740 {
741 	int		anum, bnum;
742 
743 	anum = *(int *)a;
744 	bnum = *(int *)b;
745 
746 	anum = game.clients[anum].ps.stats[STAT_FRAGS];
747 	bnum = game.clients[bnum].ps.stats[STAT_FRAGS];
748 
749 	if (anum < bnum)
750 		return -1;
751 	if (anum > bnum)
752 		return 1;
753 	return 0;
754 }
755 
756 /*
757 =================
758 Cmd_Players_f
759 =================
760 */
Cmd_Players_f(edict_t * ent)761 void Cmd_Players_f (edict_t *ent)
762 {
763 	int		i;
764 	int		count;
765 	char	small[64];
766 	char	large[1280];
767 	int		index[256];
768 
769 	count = 0;
770 	for (i = 0 ; i < maxclients->value ; i++)
771 		if (game.clients[i].pers.connected)
772 		{
773 			index[count] = i;
774 			count++;
775 		}
776 
777 	// sort by frags
778 	qsort (index, count, sizeof(index[0]), PlayerSort);
779 
780 	// print information
781 	large[0] = 0;
782 
783 	for (i = 0 ; i < count ; i++)
784 	{
785 		Com_sprintf (small, sizeof(small), "%3i %s\n",
786 			game.clients[index[i]].ps.stats[STAT_FRAGS],
787 			game.clients[index[i]].pers.netname);
788 		if (strlen (small) + strlen(large) > sizeof(large) - 100 )
789 		{	// can't print all of them in one packet
790 			strcat (large, "...\n");
791 			break;
792 		}
793 		strcat (large, small);
794 	}
795 
796 	gi.cprintf (ent, PRINT_HIGH, "%s\n%i players\n", large, count);
797 }
798 
799 /*
800 =================
801 Cmd_Wave_f
802 =================
803 */
Cmd_Wave_f(edict_t * ent)804 void Cmd_Wave_f (edict_t *ent)
805 {
806 	int		i;
807 
808 	i = atoi (gi.argv(1));
809 
810 	// can't wave when ducked
811 	if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
812 		return;
813 
814 	if (ent->client->anim_priority > ANIM_WAVE)
815 		return;
816 
817 	ent->client->anim_priority = ANIM_WAVE;
818 
819 	switch (i)
820 	{
821 	case 0:
822 		gi.cprintf (ent, PRINT_HIGH, "flipoff\n");
823 		ent->s.frame = FRAME_flip01-1;
824 		ent->client->anim_end = FRAME_flip12;
825 		break;
826 	case 1:
827 		gi.cprintf (ent, PRINT_HIGH, "salute\n");
828 		ent->s.frame = FRAME_salute01-1;
829 		ent->client->anim_end = FRAME_salute11;
830 		break;
831 	case 2:
832 		gi.cprintf (ent, PRINT_HIGH, "taunt\n");
833 		ent->s.frame = FRAME_taunt01-1;
834 		ent->client->anim_end = FRAME_taunt17;
835 		break;
836 	case 3:
837 		gi.cprintf (ent, PRINT_HIGH, "wave\n");
838 		ent->s.frame = FRAME_wave01-1;
839 		ent->client->anim_end = FRAME_wave11;
840 		break;
841 	case 4:
842 	default:
843 		gi.cprintf (ent, PRINT_HIGH, "point\n");
844 		ent->s.frame = FRAME_point01-1;
845 		ent->client->anim_end = FRAME_point12;
846 		break;
847 	}
848 }
849 
CheckFlood(edict_t * ent)850 qboolean CheckFlood(edict_t *ent)
851 {
852 	int		i;
853 	gclient_t *cl;
854 
855 	if (flood_msgs->value) {
856 		cl = ent->client;
857 
858         if (level.time < cl->flood_locktill) {
859 			gi.cprintf(ent, PRINT_HIGH, "You can't talk for %d more seconds\n",
860 				(int)(cl->flood_locktill - level.time));
861             return true;
862         }
863         i = cl->flood_whenhead - flood_msgs->value + 1;
864         if (i < 0)
865             i = (sizeof(cl->flood_when)/sizeof(cl->flood_when[0])) + i;
866 		if (cl->flood_when[i] &&
867 			level.time - cl->flood_when[i] < flood_persecond->value) {
868 			cl->flood_locktill = level.time + flood_waitdelay->value;
869 			gi.cprintf(ent, PRINT_CHAT, "Flood protection:  You can't talk for %d seconds.\n",
870 				(int)flood_waitdelay->value);
871             return true;
872         }
873 		cl->flood_whenhead = (cl->flood_whenhead + 1) %
874 			(sizeof(cl->flood_when)/sizeof(cl->flood_when[0]));
875 		cl->flood_when[cl->flood_whenhead] = level.time;
876 	}
877 	return false;
878 }
879 
880 /*
881 ==================
882 Cmd_Say_f
883 ==================
884 */
Cmd_Say_f(edict_t * ent,qboolean team,qboolean arg0)885 void Cmd_Say_f (edict_t *ent, qboolean team, qboolean arg0)
886 {
887 	int		j;
888 	edict_t	*other;
889 	char	*p;
890 	char	text[2048];
891 
892 	if (gi.argc () < 2 && !arg0)
893 		return;
894 
895 	if (!((int)(dmflags->value) & (DF_MODELTEAMS | DF_SKINTEAMS)))
896 		team = false;
897 
898 	if (team)
899 		Com_sprintf (text, sizeof(text), "(%s): ", ent->client->pers.netname);
900 	else
901 		Com_sprintf (text, sizeof(text), "%s: ", ent->client->pers.netname);
902 
903 	if (arg0)
904 	{
905 		strcat (text, gi.argv(0));
906 		strcat (text, " ");
907 		strcat (text, gi.args());
908 	}
909 	else
910 	{
911 		p = gi.args();
912 
913 		if (*p == '"')
914 		{
915 			p++;
916 			p[strlen(p)-1] = 0;
917 		}
918 		strcat(text, p);
919 	}
920 
921 	// don't let text be too long for malicious reasons
922 	if (strlen(text) > 150)
923 		text[150] = 0;
924 
925 	strcat(text, "\n");
926 
927 	if (CheckFlood(ent))
928 		return;
929 
930 	if (dedicated->value)
931 		gi.cprintf(NULL, PRINT_CHAT, "%s", text);
932 
933 	for (j = 1; j <= game.maxclients; j++)
934 	{
935 		other = &g_edicts[j];
936 		if (!other->inuse)
937 			continue;
938 		if (!other->client)
939 			continue;
940 		if (team)
941 		{
942 			if (!OnSameTeam(ent, other))
943 				continue;
944 		}
945 		gi.cprintf(other, PRINT_CHAT, "%s", text);
946 	}
947 }
948 
949 /*
950 =================
951 ClientCommand
952 =================
953 */
ClientCommand(edict_t * ent)954 void ClientCommand (edict_t *ent)
955 {
956 	char	*cmd;
957 
958 	if (!ent->client)
959 		return;		// not fully in game yet
960 
961 	cmd = gi.argv(0);
962 
963 	if (Q_stricmp (cmd, "players") == 0)
964 	{
965 		Cmd_Players_f (ent);
966 		return;
967 	}
968 	if (Q_stricmp (cmd, "say") == 0)
969 	{
970 		Cmd_Say_f (ent, false, false);
971 		return;
972 	}
973 	if (Q_stricmp (cmd, "say_team") == 0 || Q_stricmp (cmd, "steam") == 0)
974 	{
975 		CTFSay_Team(ent, gi.args());
976 		return;
977 	}
978 	if (Q_stricmp (cmd, "score") == 0)
979 	{
980 		Cmd_Score_f (ent);
981 		return;
982 	}
983 	if (Q_stricmp (cmd, "help") == 0)
984 	{
985 		Cmd_Help_f (ent);
986 		return;
987 	}
988 
989 	if (level.intermissiontime)
990 		return;
991 
992 	if (Q_stricmp (cmd, "use") == 0)
993 		Cmd_Use_f (ent);
994 	else if (Q_stricmp (cmd, "drop") == 0)
995 		Cmd_Drop_f (ent);
996 	else if (Q_stricmp (cmd, "give") == 0)
997 		Cmd_Give_f (ent);
998 	else if (Q_stricmp (cmd, "god") == 0)
999 		Cmd_God_f (ent);
1000 	else if (Q_stricmp (cmd, "notarget") == 0)
1001 		Cmd_Notarget_f (ent);
1002 	else if (Q_stricmp (cmd, "noclip") == 0)
1003 		Cmd_Noclip_f (ent);
1004 	else if (Q_stricmp (cmd, "inven") == 0)
1005 		Cmd_Inven_f (ent);
1006 	else if (Q_stricmp (cmd, "invnext") == 0)
1007 		SelectNextItem (ent, -1);
1008 	else if (Q_stricmp (cmd, "invprev") == 0)
1009 		SelectPrevItem (ent, -1);
1010 	else if (Q_stricmp (cmd, "invnextw") == 0)
1011 		SelectNextItem (ent, IT_WEAPON);
1012 	else if (Q_stricmp (cmd, "invprevw") == 0)
1013 		SelectPrevItem (ent, IT_WEAPON);
1014 	else if (Q_stricmp (cmd, "invnextp") == 0)
1015 		SelectNextItem (ent, IT_POWERUP);
1016 	else if (Q_stricmp (cmd, "invprevp") == 0)
1017 		SelectPrevItem (ent, IT_POWERUP);
1018 	else if (Q_stricmp (cmd, "invuse") == 0)
1019 		Cmd_InvUse_f (ent);
1020 	else if (Q_stricmp (cmd, "invdrop") == 0)
1021 		Cmd_InvDrop_f (ent);
1022 	else if (Q_stricmp (cmd, "weapprev") == 0)
1023 		Cmd_WeapPrev_f (ent);
1024 	else if (Q_stricmp (cmd, "weapnext") == 0)
1025 		Cmd_WeapNext_f (ent);
1026 	else if (Q_stricmp (cmd, "weaplast") == 0)
1027 		Cmd_WeapLast_f (ent);
1028 	else if (Q_stricmp (cmd, "kill") == 0)
1029 		Cmd_Kill_f (ent);
1030 	else if (Q_stricmp (cmd, "putaway") == 0)
1031 		Cmd_PutAway_f (ent);
1032 	else if (Q_stricmp (cmd, "wave") == 0)
1033 		Cmd_Wave_f (ent);
1034 //ZOID
1035 	else if (Q_stricmp (cmd, "team") == 0)
1036 	{
1037 		CTFTeam_f (ent);
1038 	} else if (Q_stricmp(cmd, "id") == 0) {
1039 		CTFID_f (ent);
1040 	} else if (Q_stricmp(cmd, "yes") == 0) {
1041 		CTFVoteYes(ent);
1042 	} else if (Q_stricmp(cmd, "no") == 0) {
1043 		CTFVoteNo(ent);
1044 	} else if (Q_stricmp(cmd, "ready") == 0) {
1045 		CTFReady(ent);
1046 	} else if (Q_stricmp(cmd, "notready") == 0) {
1047 		CTFNotReady(ent);
1048 	} else if (Q_stricmp(cmd, "ghost") == 0) {
1049 		CTFGhost(ent);
1050 	} else if (Q_stricmp(cmd, "admin") == 0) {
1051 		CTFAdmin(ent);
1052 	} else if (Q_stricmp(cmd, "stats") == 0) {
1053 		CTFStats(ent);
1054 	} else if (Q_stricmp(cmd, "warp") == 0) {
1055 		CTFWarp(ent);
1056 	} else if (Q_stricmp(cmd, "boot") == 0) {
1057 		CTFBoot(ent);
1058 	} else if (Q_stricmp(cmd, "playerlist") == 0) {
1059 		CTFPlayerList(ent);
1060 	} else if (Q_stricmp(cmd, "observer") == 0) {
1061 		CTFObserver(ent);
1062 	}
1063 //ZOID
1064 	else	// anything that doesn't match a command will be a chat
1065 		Cmd_Say_f (ent, false, true);
1066 }
1067