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