|
|
1.1 root 1:
2: #include "quakedef.h"
3:
4:
5: /*
6: ==================
7: Host_Quit_f
8: ==================
9: */
10:
11: extern void M_Menu_Quit_f (void);
12:
13: void Host_Quit_f (void)
14: {
15: if (key_dest != key_console && cls.state != ca_dedicated)
16: {
17: M_Menu_Quit_f ();
18: return;
19: }
20: CL_Disconnect ();
21: Host_ShutdownServer(false);
22:
23: Sys_Quit ();
24: }
25:
26:
27: /*
28: ==================
29: Host_Status_f
30: ==================
31: */
32: void Host_Status_f (void)
33: {
34: client_t *client;
35: int seconds;
36: int minutes;
37: int hours = 0;
38: int j;
39: void (*print) (char *fmt, ...);
40:
41: if (cmd_source == src_command)
42: {
43: if (!sv.active)
44: {
45: Cmd_ForwardToServer ();
46: return;
47: }
48: print = Con_Printf;
49: }
50: else
51: print = SV_ClientPrintf;
52:
53: print ("host: %s\n", Cvar_VariableString ("hostname"));
54: print ("version: %4.2f\n", VERSION);
55: if (tcpipAvailable)
56: print ("tcp/ip: %s\n", my_tcpip_address);
57: if (ipxAvailable)
58: print ("ipx: %s\n", my_ipx_address);
59: print ("map: %s\n", sv.name);
60: print ("players: %i active (%i max)\n\n", net_activeconnections, svs.maxclients);
61: for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
62: {
63: if (!client->active)
64: continue;
65: seconds = (int)(net_time - client->netconnection->connecttime);
66: minutes = seconds / 60;
67: if (minutes)
68: {
69: seconds -= (minutes * 60);
70: hours = minutes / 60;
71: if (hours)
72: minutes -= (hours * 60);
73: }
74: else
75: hours = 0;
76: print ("#%-2u %-16.16s %3i %2i:%02i:%02i\n", j+1, client->name, (int)client->edict->v.frags, hours, minutes, seconds);
77: print (" %s\n", client->netconnection->address);
78: }
79: }
80:
81:
82: /*
83: ==================
84: Host_God_f
85:
86: Sets client to godmode
87: ==================
88: */
89: void Host_God_f (void)
90: {
91: if (cmd_source == src_command)
92: {
93: Cmd_ForwardToServer ();
94: return;
95: }
96:
97: if (pr_global_struct->deathmatch && !host_client->privileged)
98: return;
99:
100: sv_player->v.flags = (int)sv_player->v.flags ^ FL_GODMODE;
101: if (!((int)sv_player->v.flags & FL_GODMODE) )
102: SV_ClientPrintf ("godmode OFF\n");
103: else
104: SV_ClientPrintf ("godmode ON\n");
105: }
106:
107: void Host_Notarget_f (void)
108: {
109: if (cmd_source == src_command)
110: {
111: Cmd_ForwardToServer ();
112: return;
113: }
114:
115: if (pr_global_struct->deathmatch && !host_client->privileged)
116: return;
117:
118: sv_player->v.flags = (int)sv_player->v.flags ^ FL_NOTARGET;
119: if (!((int)sv_player->v.flags & FL_NOTARGET) )
120: SV_ClientPrintf ("notarget OFF\n");
121: else
122: SV_ClientPrintf ("notarget ON\n");
123: }
124:
125: qboolean noclip_anglehack;
126:
127: void Host_Noclip_f (void)
128: {
129: if (cmd_source == src_command)
130: {
131: Cmd_ForwardToServer ();
132: return;
133: }
134:
135: if (pr_global_struct->deathmatch && !host_client->privileged)
136: return;
137:
138: if (sv_player->v.movetype != MOVETYPE_NOCLIP)
139: {
140: noclip_anglehack = true;
141: sv_player->v.movetype = MOVETYPE_NOCLIP;
142: SV_ClientPrintf ("noclip ON\n");
143: }
144: else
145: {
146: noclip_anglehack = false;
147: sv_player->v.movetype = MOVETYPE_WALK;
148: SV_ClientPrintf ("noclip OFF\n");
149: }
150: }
151:
152: /*
153: ==================
154: Host_Fly_f
155:
156: Sets client to flymode
157: ==================
158: */
159: void Host_Fly_f (void)
160: {
161: if (cmd_source == src_command)
162: {
163: Cmd_ForwardToServer ();
164: return;
165: }
166:
167: if (pr_global_struct->deathmatch && !host_client->privileged)
168: return;
169:
170: if (sv_player->v.movetype != MOVETYPE_FLY)
171: {
172: sv_player->v.movetype = MOVETYPE_FLY;
173: SV_ClientPrintf ("flymode ON\n");
174: }
175: else
176: {
177: sv_player->v.movetype = MOVETYPE_WALK;
178: SV_ClientPrintf ("flymode OFF\n");
179: }
180: }
181:
182:
183: /*
184: ==================
185: Host_Ping_f
186:
187: ==================
188: */
189: void Host_Ping_f (void)
190: {
191: int i, j;
192: float total;
193: client_t *client;
194:
195: if (cmd_source == src_command)
196: {
197: Cmd_ForwardToServer ();
198: return;
199: }
200:
201: SV_ClientPrintf ("Client ping times:\n");
202: for (i=0, client = svs.clients ; i<svs.maxclients ; i++, client++)
203: {
204: if (!client->active)
205: continue;
206: total = 0;
207: for (j=0 ; j<NUM_PING_TIMES ; j++)
208: total+=client->ping_times[j];
209: total /= NUM_PING_TIMES;
210: SV_ClientPrintf ("%4i %s\n", (int)(total*1000), client->name);
211: }
212: }
213:
214: /*
215: ===============================================================================
216:
217: SERVER TRANSITIONS
218:
219: ===============================================================================
220: */
221:
222:
223: /*
224: ======================
225: Host_Map_f
226:
227: handle a
228: map <servername>
229: command from the console. Active clients are kicked off.
230: ======================
231: */
232: void Host_Map_f (void)
233: {
234: int i;
235: char name[MAX_QPATH];
236:
237: if (cmd_source != src_command)
238: return;
239:
240: cls.demonum = -1; // stop demo loop in case this fails
241:
242: CL_Disconnect ();
243: Host_ShutdownServer(false);
244:
245: key_dest = key_game; // remove console or menu
246: SCR_BeginLoadingPlaque ();
247:
248: cls.mapstring[0] = 0;
249: for (i=0 ; i<Cmd_Argc() ; i++)
250: {
251: strcat (cls.mapstring, Cmd_Argv(i));
252: strcat (cls.mapstring, " ");
253: }
254: strcat (cls.mapstring, "\n");
255:
256: svs.serverflags = 0; // haven't completed an episode yet
257: strcpy (name, Cmd_Argv(1));
258: SV_SpawnServer (name);
259: if (!sv.active)
260: return;
261:
262: if (cls.state != ca_dedicated)
263: {
264: strcpy (cls.spawnparms, "");
265:
266: for (i=2 ; i<Cmd_Argc() ; i++)
267: {
268: strcat (cls.spawnparms, Cmd_Argv(i));
269: strcat (cls.spawnparms, " ");
270: }
271:
272: Cmd_ExecuteString ("connect local", src_command);
273: }
274: }
275:
276: /*
277: ==================
278: Host_Changelevel_f
279:
280: Goes to a new map, taking all clients along
281: ==================
282: */
283: void Host_Changelevel_f (void)
284: {
285: char level[MAX_QPATH];
286:
287: if (Cmd_Argc() != 2)
288: {
289: Con_Printf ("changelevel <levelname> : continue game on a new level\n");
290: return;
291: }
292: if (!sv.active || cls.demoplayback)
293: {
294: Con_Printf ("Only the server may changelevel\n");
295: return;
296: }
297: SV_SaveSpawnparms ();
298: strcpy (level, Cmd_Argv(1));
299: SV_SpawnServer (level);
300: }
301:
302: /*
303: ==================
304: Host_Restart_f
305:
306: Restarts the current server for a dead player
307: ==================
308: */
309: void Host_Restart_f (void)
310: {
311: char mapname[MAX_QPATH];
312:
313: if (cls.demoplayback || !sv.active)
314: return;
315:
316: if (cmd_source != src_command)
317: return;
318: strcpy (mapname, sv.name); // must copy out, because it gets cleared
319: // in sv_spawnserver
320: SV_SpawnServer (mapname);
321: }
322:
323: /*
324: ==================
325: Host_Reconnect_f
326:
327: This command causes the client to wait for the signon messages again.
328: This is sent just before a server changes levels
329: ==================
330: */
331: void Host_Reconnect_f (void)
332: {
333: SCR_BeginLoadingPlaque ();
334: cls.signon = 0; // need new connection messages
335: }
336:
337: /*
338: =====================
339: Host_Connect_f
340:
341: User command to connect to server
342: =====================
343: */
344: void Host_Connect_f (void)
345: {
346: char name[MAX_QPATH];
347:
348: cls.demonum = -1; // stop demo loop in case this fails
349: if (cls.demoplayback)
350: {
351: CL_StopPlayback ();
352: CL_Disconnect ();
353: }
354: strcpy (name, Cmd_Argv(1));
355: CL_EstablishConnection (name);
356: Host_Reconnect_f ();
357: }
358:
359:
360: /*
361: ===============================================================================
362:
363: LOAD / SAVE GAME
364:
365: ===============================================================================
366: */
367:
368: #define SAVEGAME_VERSION 5
369:
370: /*
371: ===============
372: Host_SavegameComment
373:
374: Writes a 30 character comment describing the current
375: ===============
376: */
377: void Host_SavegameComment (char *text)
378: {
379: int i;
380: char kills[20];
381:
382: for (i=0 ; i<SAVEGAME_COMMENT_LENGTH ; i++)
383: text[i] = ' ';
384: memcpy (text, cl.levelname, strlen(cl.levelname));
385: sprintf (kills,"kills:%3i/%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]);
386: memcpy (text+22, kills, strlen(kills));
387: // convert space to _ to make stdio happy
388: for (i=0 ; i<SAVEGAME_COMMENT_LENGTH ; i++)
389: if (text[i] == ' ')
390: text[i] = '_';
391: }
392:
393: /*
394: ===============
395: Host_Savegame_f
396: ===============
397: */
398: void Host_Savegame_f (void)
399: {
400: char name[256];
401: FILE *f;
402: int i;
403: char comment[SAVEGAME_COMMENT_LENGTH+1];
404:
405: if (cmd_source != src_command)
406: return;
407:
408: if (!sv.active)
409: {
410: Con_Printf ("Not playing a local game.\n");
411: return;
412: }
413:
414: if (cl.intermission)
415: {
416: Con_Printf ("Can't save in intermission.\n");
417: return;
418: }
419:
420: if (svs.maxclients != 1)
421: {
422: Con_Printf ("Can't save multiplayer games.\n");
423: return;
424: }
425:
426: if (Cmd_Argc() != 2)
427: {
428: Con_Printf ("save <savename> : save a game\n");
429: return;
430: }
431:
432: if (strstr(Cmd_Argv(1), ".."))
433: {
434: Con_Printf ("Relative pathnames are not allowed.\n");
435: return;
436: }
437:
438: for (i=0 ; i<svs.maxclients ; i++)
439: {
440: if (svs.clients[i].active && (svs.clients[i].edict->v.health <= 0) )
441: {
442: Con_Printf ("Can't savegame with a dead player\n");
443: return;
444: }
445: }
446:
447: sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1));
448: COM_DefaultExtension (name, ".sav");
449:
450: Con_Printf ("Saving game to %s...\n", name);
451: f = fopen (name, "w");
452: if (!f)
453: {
454: Con_Printf ("ERROR: couldn't open.\n");
455: return;
456: }
457:
458: fprintf (f, "%i\n", SAVEGAME_VERSION);
459: Host_SavegameComment (comment);
460: fprintf (f, "%s\n", comment);
461: for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
462: fprintf (f, "%f\n", svs.clients->spawn_parms[i]);
463: fprintf (f, "%f\n", skill.value);
464: fprintf (f, "%s\n", sv.name);
465: fprintf (f, "%f\n",sv.time);
466:
467: // write the light styles
468:
469: for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
470: {
471: if (sv.lightstyles[i])
472: fprintf (f, "%s\n", sv.lightstyles[i]);
473: else
474: fprintf (f,"m\n");
475: }
476:
477:
478: ED_WriteGlobals (f);
479: for (i=0 ; i<sv.num_edicts ; i++)
480: {
481: ED_Write (f, EDICT_NUM(i));
482: fflush (f);
483: }
484: fclose (f);
485: Con_Printf ("done.\n");
486: }
487:
488:
489: /*
490: ===============
491: Host_Loadgame_f
492: ===============
493: */
494: void Host_Loadgame_f (void)
495: {
496: char name[MAX_OSPATH];
497: FILE *f;
498: char mapname[MAX_QPATH];
499: float time, sk;
500: char str[32768], *start;
501: int i, r;
502: edict_t *ent;
503: int entnum;
504: int version;
505: float spawn_parms[NUM_SPAWN_PARMS];
506:
507: if (cmd_source != src_command)
508: return;
509:
510: if (Cmd_Argc() != 2)
511: {
512: Con_Printf ("load <savename> : load a game\n");
513: return;
514: }
515:
516: cls.demonum = -1; // stop demo loop in case this fails
517:
518: sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1));
519: COM_DefaultExtension (name, ".sav");
520:
521: // we can't call SCR_BeginLoadingPlaque, because too much stack space has
522: // been used. The menu calls it before stuffing loadgame command
523: // SCR_BeginLoadingPlaque ();
524:
525: Con_Printf ("Loading game from %s...\n", name);
526: f = fopen (name, "r");
527: if (!f)
528: {
529: Con_Printf ("ERROR: couldn't open.\n");
530: return;
531: }
532:
533: fscanf (f, "%i\n", &version);
534: if (version != SAVEGAME_VERSION)
535: {
536: fclose (f);
537: Con_Printf ("Savegame is version %i, not %i\n", version, SAVEGAME_VERSION);
538: return;
539: }
540: fscanf (f, "%s\n", str);
541: for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
542: fscanf (f, "%f\n", &spawn_parms[i]);
543: fscanf (f, "%f\n", &sk);
544: Cvar_SetValue ("skill", sk);
545:
546: fscanf (f, "%s\n",mapname);
547: fscanf (f, "%f\n",&time);
548:
549: CL_Disconnect_f ();
550:
551: SV_SpawnServer (mapname);
552: if (!sv.active)
553: {
554: Con_Printf ("Couldn't load map\n");
555: return;
556: }
557: sv.paused = true; // pause until all clients connect
558: sv.loadgame = true;
559:
560: // load the light styles
561:
562: for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
563: {
564: fscanf (f, "%s\n", str);
565: sv.lightstyles[i] = Hunk_Alloc (strlen(str)+1);
566: strcpy (sv.lightstyles[i], str);
567: }
568:
569: // load the edicts out of the savegame file
570: entnum = -1; // -1 is the globals
571: while (!feof(f))
572: {
573: for (i=0 ; i<sizeof(str)-1 ; i++)
574: {
575: r = fgetc (f);
576: if (r == EOF || !r)
577: break;
578: str[i] = r;
579: if (r == '}')
580: {
581: i++;
582: break;
583: }
584: }
585: if (i == sizeof(str)-1)
586: Sys_Error ("Loadgame buffer overflow");
587: str[i] = 0;
588: start = str;
589: start = COM_Parse(str);
590: if (!com_token[0])
591: break; // end of file
592: if (strcmp(com_token,"{"))
593: Sys_Error ("First token isn't a brace");
594:
595: if (entnum == -1)
596: { // parse the global vars
597: ED_ParseGlobals (start);
598: }
599: else
600: { // parse an edict
601:
602: ent = EDICT_NUM(entnum);
603: memset (&ent->v, 0, progs->entityfields * 4);
604: ent->free = false;
605: ED_ParseEdict (start, ent);
606:
607: // link it into the bsp tree
608: if (!ent->free)
609: SV_LinkEdict (ent, false);
610: }
611:
612: entnum++;
613: }
614:
615: sv.num_edicts = entnum;
616: sv.time = time;
617:
618: fclose (f);
619:
620: for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
621: svs.clients->spawn_parms[i] = spawn_parms[i];
622:
623: if (cls.state != ca_dedicated)
624: {
625: CL_EstablishConnection ("local");
626: Host_Reconnect_f ();
627: }
628: }
629:
630: //============================================================================
631:
632: /*
633: ======================
634: Host_Name_f
635: ======================
636: */
637: void Host_Name_f (void)
638: {
639: char *newName;
640:
641: if (Cmd_Argc () == 1)
642: {
643: Con_Printf ("\"name\" is \"%s\"\n", cl_name.string);
644: return;
645: }
646: if (Cmd_Argc () == 2)
647: newName = Cmd_Argv(1);
648: else
649: newName = Cmd_Args();
650: newName[15] = 0;
651:
652: if (cmd_source == src_command)
653: {
654: if (Q_strcmp(cl_name.string, newName) == 0)
655: return;
656: Cvar_Set ("_cl_name", newName);
657: if (cls.state == ca_connected)
658: Cmd_ForwardToServer ();
659: return;
660: }
661:
662: if (host_client->name[0] && strcmp(host_client->name, "unconnected") )
663: if (Q_strcmp(host_client->name, newName) != 0)
664: Con_Printf ("%s renamed to %s\n", host_client->name, newName);
665: Q_strcpy (host_client->name, newName);
666: host_client->edict->v.netname = host_client->name - pr_strings;
667:
668: // send notification to all clients
669:
670: MSG_WriteByte (&sv.reliable_datagram, svc_updatename);
671: MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients);
672: MSG_WriteString (&sv.reliable_datagram, host_client->name);
673: }
674:
675:
676: void Host_Version_f (void)
677: {
678: Con_Printf ("Version %4.2f\n", VERSION);
679: Con_Printf ("Exe: "__TIME__" "__DATE__"\n");
680: }
681:
682: #ifdef IDGODS
683: void Host_Please_f (void)
684: {
685: client_t *cl;
686: int j;
687:
688: if (cmd_source != src_command)
689: return;
690:
691: if ((Cmd_Argc () == 3) && Q_strcmp(Cmd_Argv(1), "#") == 0)
692: {
693: j = Q_atof(Cmd_Argv(2)) - 1;
694: if (j < 0 || j >= svs.maxclients)
695: return;
696: if (!svs.clients[j].active)
697: return;
698: cl = &svs.clients[j];
699: if (cl->privileged)
700: {
701: cl->privileged = false;
702: cl->edict->v.flags = (int)cl->edict->v.flags & ~(FL_GODMODE|FL_NOTARGET);
703: cl->edict->v.movetype = MOVETYPE_WALK;
704: noclip_anglehack = false;
705: }
706: else
707: cl->privileged = true;
708: }
709:
710: if (Cmd_Argc () != 2)
711: return;
712:
713: for (j=0, cl = svs.clients ; j<svs.maxclients ; j++, cl++)
714: {
715: if (!cl->active)
716: continue;
717: if (Q_strcasecmp(cl->name, Cmd_Argv(1)) == 0)
718: {
719: if (cl->privileged)
720: {
721: cl->privileged = false;
722: cl->edict->v.flags = (int)cl->edict->v.flags & ~(FL_GODMODE|FL_NOTARGET);
723: cl->edict->v.movetype = MOVETYPE_WALK;
724: noclip_anglehack = false;
725: }
726: else
727: cl->privileged = true;
728: break;
729: }
730: }
731: }
732: #endif
733:
734:
735: void Host_Say(qboolean teamonly)
736: {
737: client_t *client;
738: client_t *save;
739: int j;
740: char *p;
741: unsigned char text[64];
742: qboolean fromServer = false;
743:
744: if (cmd_source == src_command)
745: {
746: if (cls.state == ca_dedicated)
747: {
748: fromServer = true;
749: teamonly = false;
750: }
751: else
752: {
753: Cmd_ForwardToServer ();
754: return;
755: }
756: }
757:
758: if (Cmd_Argc () < 2)
759: return;
760:
761: save = host_client;
762:
763: p = Cmd_Args();
764: // remove quotes if present
765: if (*p == '"')
766: {
767: p++;
768: p[Q_strlen(p)-1] = 0;
769: }
770:
771: // turn on color set 1
772: if (!fromServer)
773: sprintf (text, "%c%s: ", 1, save->name);
774: else
775: sprintf (text, "%c<%s> ", 1, hostname.string);
776:
777: j = sizeof(text) - 2 - Q_strlen(text); // -2 for /n and null terminator
778: if (Q_strlen(p) > j)
779: p[j] = 0;
780:
781: strcat (text, p);
782: strcat (text, "\n");
783:
784: for (j = 0, client = svs.clients; j < svs.maxclients; j++, client++)
785: {
786: if (!client || !client->active || !client->spawned)
787: continue;
788: if (teamplay.value && teamonly && client->edict->v.team != save->edict->v.team)
789: continue;
790: host_client = client;
791: SV_ClientPrintf("%s", text);
792: }
793: host_client = save;
794: }
795:
796:
797: void Host_Say_f(void)
798: {
799: Host_Say(false);
800: }
801:
802:
803: void Host_Say_Team_f(void)
804: {
805: Host_Say(true);
806: }
807:
808:
809: void Host_Tell_f(void)
810: {
811: client_t *client;
812: client_t *save;
813: int j;
814: char *p;
815: char text[80];
816:
817: if (cmd_source == src_command)
818: {
819: Cmd_ForwardToServer ();
820: return;
821: }
822:
823: if (Cmd_Argc () < 3)
824: return;
825:
826: save = host_client;
827: Q_strcpy(text, save->name);
828: Q_strcat(text, ": ");
829: p = Cmd_Args();
830:
831: p += Q_strlen(Cmd_Argv(1));
832: while (*p == ' ')
833: p++;
834:
835: if (*p != '"')
836: {
837: Q_strcat(text, p);
838: }
839: else
840: {
841: Q_strcat(text, p+1);
842: text[Q_strlen(text)-1] = 0;
843: }
844: Q_strcat(text, "\n");
845:
846: for (j = 0, client = svs.clients; j < svs.maxclients; j++, client++)
847: {
848: if (!client->active || !client->spawned)
849: continue;
850: if (Q_strcasecmp(client->name, Cmd_Argv(1)))
851: continue;
852: host_client = client;
853: SV_ClientPrintf("%s", text);
854: break;
855: }
856: host_client = save;
857: }
858:
859:
860: /*
861: ==================
862: Host_Color_f
863: ==================
864: */
865: void Host_Color_f(void)
866: {
867: int top, bottom;
868: int playercolor;
869:
870: if (Cmd_Argc() == 1)
871: {
872: Con_Printf ("\"color\" is \"%i %i\"\n", ((int)cl_color.value) >> 4, ((int)cl_color.value) & 0x0f);
873: Con_Printf ("color <0-13> [0-13]\n");
874: return;
875: }
876:
877: if (Cmd_Argc() == 2)
878: top = bottom = atoi(Cmd_Argv(1));
879: else
880: {
881: top = atoi(Cmd_Argv(1));
882: bottom = atoi(Cmd_Argv(2));
883: }
884:
885: top &= 15;
886: if (top > 13)
887: top = 13;
888: bottom &= 15;
889: if (bottom > 13)
890: bottom = 13;
891:
892: playercolor = top*16 + bottom;
893:
894: if (cmd_source == src_command)
895: {
896: Cvar_SetValue ("_cl_color", playercolor);
897: if (cls.state == ca_connected)
898: Cmd_ForwardToServer ();
899: return;
900: }
901:
902: host_client->colors = playercolor;
903: host_client->edict->v.team = bottom + 1;
904:
905: // send notification to all clients
906: MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
907: MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients);
908: MSG_WriteByte (&sv.reliable_datagram, host_client->colors);
909: }
910:
911: /*
912: ==================
913: Host_Kill_f
914: ==================
915: */
916: void Host_Kill_f (void)
917: {
918: if (cmd_source == src_command)
919: {
920: Cmd_ForwardToServer ();
921: return;
922: }
923:
924: if (sv_player->v.health <= 0)
925: {
926: SV_ClientPrintf ("Can't suicide -- allready dead!\n");
927: return;
928: }
929:
930: pr_global_struct->time = sv.time;
931: pr_global_struct->self = EDICT_TO_PROG(sv_player);
932: PR_ExecuteProgram (pr_global_struct->ClientKill);
933: }
934:
935: /*
936: ==================
937: Host_Pause_f
938: ==================
939: */
940: void Host_Pause_f (void)
941: {
942: extern cvar_t pausable;
943:
944: if (cmd_source == src_command)
945: {
946: Cmd_ForwardToServer ();
947: return;
948: }
949: if (!pausable.value)
950: SV_ClientPrintf ("Pause not allowed.\n");
951: else
952: {
953: sv.paused ^= 1;
954: if (sv.paused)
955: SV_BroadcastPrintf ("%s paused the game\n", pr_strings + sv_player->v.netname);
956: else
957: SV_BroadcastPrintf ("%s unpaused the game\n",pr_strings + sv_player->v.netname);
958: // send notification to all clients
959: MSG_WriteByte (&sv.reliable_datagram, svc_setpause);
960: MSG_WriteByte (&sv.reliable_datagram, sv.paused);
961: }
962: }
963:
964: //===========================================================================
965:
966:
967: /*
968: ==================
969: Host_PreSpawn_f
970: ==================
971: */
972: void Host_PreSpawn_f (void)
973: {
974: if (cmd_source == src_command)
975: {
976: Con_Printf ("prespawn is not valid from the console\n");
977: return;
978: }
979:
980: if (host_client->spawned)
981: {
982: Con_Printf ("prespawn not valid -- allready spawned\n");
983: return;
984: }
985:
986: SZ_Write (&host_client->message, sv.signon.data, sv.signon.cursize);
987: MSG_WriteByte (&host_client->message, svc_signonnum);
988: MSG_WriteByte (&host_client->message, 2);
989: host_client->sendsignon = true;
990: }
991:
992: /*
993: ==================
994: Host_Spawn_f
995: ==================
996: */
997: void Host_Spawn_f (void)
998: {
999: int i;
1000: client_t *client;
1001: edict_t *ent;
1002:
1003: if (cmd_source == src_command)
1004: {
1005: Con_Printf ("spawn is not valid from the console\n");
1006: return;
1007: }
1008:
1009: if (host_client->spawned)
1010: {
1011: Con_Printf ("Spawn not valid -- allready spawned\n");
1012: return;
1013: }
1014:
1015: // run the entrance script
1016: if (sv.loadgame)
1017: { // loaded games are fully inited allready
1018: // if this is the last client to be connected, unpause
1019: sv.paused = false;
1020: }
1021: else
1022: {
1023: // set up the edict
1024: ent = host_client->edict;
1025:
1026: memset (&ent->v, 0, progs->entityfields * 4);
1027: ent->v.colormap = NUM_FOR_EDICT(ent);
1028: ent->v.team = (host_client->colors & 15) + 1;
1029: ent->v.netname = host_client->name - pr_strings;
1030:
1031: // copy spawn parms out of the client_t
1032:
1033: for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1034: (&pr_global_struct->parm1)[i] = host_client->spawn_parms[i];
1035:
1036: // call the spawn function
1037:
1038: pr_global_struct->time = sv.time;
1039: pr_global_struct->self = EDICT_TO_PROG(sv_player);
1040: PR_ExecuteProgram (pr_global_struct->ClientConnect);
1041:
1042: PR_ExecuteProgram (pr_global_struct->PutClientInServer);
1043: }
1044:
1045:
1046: // send all current names, colors, and frag counts
1047: SZ_Clear (&host_client->message);
1048:
1049: // send time of update
1050: MSG_WriteByte (&host_client->message, svc_time);
1051: MSG_WriteFloat (&host_client->message, sv.time);
1052:
1053: for (i=0, client = svs.clients ; i<svs.maxclients ; i++, client++)
1054: {
1055: MSG_WriteByte (&host_client->message, svc_updatename);
1056: MSG_WriteByte (&host_client->message, i);
1057: MSG_WriteString (&host_client->message, client->name);
1058: MSG_WriteByte (&host_client->message, svc_updatefrags);
1059: MSG_WriteByte (&host_client->message, i);
1060: MSG_WriteShort (&host_client->message, client->old_frags);
1061: MSG_WriteByte (&host_client->message, svc_updatecolors);
1062: MSG_WriteByte (&host_client->message, i);
1063: MSG_WriteByte (&host_client->message, client->colors);
1064: }
1065:
1066: // send all current light styles
1067: for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
1068: {
1069: MSG_WriteByte (&host_client->message, svc_lightstyle);
1070: MSG_WriteByte (&host_client->message, (char)i);
1071: MSG_WriteString (&host_client->message, sv.lightstyles[i]);
1072: }
1073:
1074: //
1075: // send some stats
1076: //
1077: MSG_WriteByte (&host_client->message, svc_updatestat);
1078: MSG_WriteByte (&host_client->message, STAT_TOTALSECRETS);
1079: MSG_WriteLong (&host_client->message, pr_global_struct->total_secrets);
1080:
1081: MSG_WriteByte (&host_client->message, svc_updatestat);
1082: MSG_WriteByte (&host_client->message, STAT_TOTALMONSTERS);
1083: MSG_WriteLong (&host_client->message, pr_global_struct->total_monsters);
1084:
1085: MSG_WriteByte (&host_client->message, svc_updatestat);
1086: MSG_WriteByte (&host_client->message, STAT_SECRETS);
1087: MSG_WriteLong (&host_client->message, pr_global_struct->found_secrets);
1088:
1089: MSG_WriteByte (&host_client->message, svc_updatestat);
1090: MSG_WriteByte (&host_client->message, STAT_MONSTERS);
1091: MSG_WriteLong (&host_client->message, pr_global_struct->killed_monsters);
1092:
1093:
1094: //
1095: // send a fixangle
1096: // Never send a roll angle, because savegames can catch the server
1097: // in a state where it is expecting the client to correct the angle
1098: // and it won't happen if the game was just loaded, so you wind up
1099: // with a permanent head tilt
1100: ent = EDICT_NUM( 1 + (host_client - svs.clients) );
1101: MSG_WriteByte (&host_client->message, svc_setangle);
1102: for (i=0 ; i < 2 ; i++)
1103: MSG_WriteAngle (&host_client->message, ent->v.angles[i] );
1104: MSG_WriteAngle (&host_client->message, 0 );
1105:
1106: SV_WriteClientdataToMessage (sv_player, &host_client->message);
1107:
1108: MSG_WriteByte (&host_client->message, svc_signonnum);
1109: MSG_WriteByte (&host_client->message, 3);
1110: host_client->sendsignon = true;
1111: }
1112:
1113: /*
1114: ==================
1115: Host_Begin_f
1116: ==================
1117: */
1118: void Host_Begin_f (void)
1119: {
1120: if (cmd_source == src_command)
1121: {
1122: Con_Printf ("begin is not valid from the console\n");
1123: return;
1124: }
1125:
1126: host_client->spawned = true;
1127: }
1128:
1129: //===========================================================================
1130:
1131:
1132: /*
1133: ==================
1134: Host_Kick_f
1135:
1136: Kicks a user off of the server
1137: ==================
1138: */
1139: void Host_Kick_f (void)
1140: {
1141: char *who;
1142: char *message = NULL;
1143: client_t *save;
1144: int i;
1145: qboolean byNumber = false;
1146:
1147: if (cmd_source == src_command)
1148: {
1149: if (!sv.active)
1150: {
1151: Cmd_ForwardToServer ();
1152: return;
1153: }
1154: }
1155: else if (pr_global_struct->deathmatch && !host_client->privileged)
1156: return;
1157:
1158: save = host_client;
1159:
1160: if (Cmd_Argc() > 2 && Q_strcmp(Cmd_Argv(1), "#") == 0)
1161: {
1162: i = Q_atof(Cmd_Argv(2)) - 1;
1163: if (i < 0 || i >= svs.maxclients)
1164: return;
1165: if (!svs.clients[i].active)
1166: return;
1167: host_client = &svs.clients[i];
1168: byNumber = true;
1169: }
1170: else
1171: {
1172: for (i = 0, host_client = svs.clients; i < svs.maxclients; i++, host_client++)
1173: {
1174: if (!host_client->active)
1175: continue;
1176: if (Q_strcasecmp(host_client->name, Cmd_Argv(1)) == 0)
1177: break;
1178: }
1179: }
1180:
1181: if (i < svs.maxclients)
1182: {
1183: if (cmd_source == src_command)
1184: if (cls.state == ca_dedicated)
1185: who = "Console";
1186: else
1187: who = cl_name.string;
1188: else
1189: who = save->name;
1190:
1191: // can't kick yourself!
1192: if (host_client == save)
1193: return;
1194:
1195: if (Cmd_Argc() > 2)
1196: {
1197: message = COM_Parse(Cmd_Args());
1198: if (byNumber)
1199: {
1200: message++; // skip the #
1201: while (*message == ' ') // skip white space
1202: message++;
1203: message += Q_strlen(Cmd_Argv(2)); // skip the number
1204: }
1205: while (*message && *message == ' ')
1206: message++;
1207: }
1208: if (message)
1209: SV_ClientPrintf ("Kicked by %s: %s\n", who, message);
1210: else
1211: SV_ClientPrintf ("Kicked by %s\n", who);
1212: SV_DropClient (false);
1213: }
1214:
1215: host_client = save;
1216: }
1217:
1218: /*
1219: ===============================================================================
1220:
1221: DEBUGGING TOOLS
1222:
1223: ===============================================================================
1224: */
1225:
1226: /*
1227: ==================
1228: Host_Give_f
1229: ==================
1230: */
1231: void Host_Give_f (void)
1232: {
1233: char *t;
1234: int v;
1235:
1236: if (cmd_source == src_command)
1237: {
1238: Cmd_ForwardToServer ();
1239: return;
1240: }
1241:
1242: if (pr_global_struct->deathmatch && !host_client->privileged)
1243: return;
1244:
1245: t = Cmd_Argv(1);
1246: v = atoi (Cmd_Argv(2));
1247:
1248: switch (t[0])
1249: {
1250: case '2':
1251: case '3':
1252: case '4':
1253: case '5':
1254: case '6':
1255: case '7':
1256: case '8':
1257: case '9':
1258: sv_player->v.items = (int)sv_player->v.items | IT_SHOTGUN<< (t[0] - '2');
1259: break;
1260:
1261: case 's':
1262: sv_player->v.ammo_shells = v;
1263: break;
1264: case 'n':
1265: sv_player->v.ammo_nails = v;
1266: break;
1267: case 'r':
1268: sv_player->v.ammo_rockets = v;
1269: break;
1270: case 'h':
1271: sv_player->v.health = v;
1272: break;
1273: case 'c':
1274: sv_player->v.ammo_cells = v;
1275: break;
1276: }
1277: }
1278:
1279: edict_t *FindViewthing (void)
1280: {
1281: int i;
1282: edict_t *e;
1283:
1284: for (i=0 ; i<sv.num_edicts ; i++)
1285: {
1286: e = EDICT_NUM(i);
1287: if ( !strcmp (pr_strings + e->v.classname, "viewthing") )
1288: return e;
1289: }
1290: Con_Printf ("No viewthing on map\n");
1291: return NULL;
1292: }
1293:
1294: /*
1295: ==================
1296: Host_Viewmodel_f
1297: ==================
1298: */
1299: void Host_Viewmodel_f (void)
1300: {
1301: edict_t *e;
1302: model_t *m;
1303:
1304: e = FindViewthing ();
1305: if (!e)
1306: return;
1307:
1308: m = Mod_ForName (Cmd_Argv(1), false);
1309: if (!m)
1310: {
1311: Con_Printf ("Can't load %s\n", Cmd_Argv(1));
1312: return;
1313: }
1314:
1315: e->v.frame = 0;
1316: cl.model_precache[(int)e->v.modelindex] = m;
1317: }
1318:
1319: /*
1320: ==================
1321: Host_Viewframe_f
1322: ==================
1323: */
1324: void Host_Viewframe_f (void)
1325: {
1326: edict_t *e;
1327: int f;
1328: model_t *m;
1329:
1330: e = FindViewthing ();
1331: if (!e)
1332: return;
1333: m = cl.model_precache[(int)e->v.modelindex];
1334:
1335: f = atoi(Cmd_Argv(1));
1336: if (f >= m->numframes)
1337: f = m->numframes-1;
1338:
1339: e->v.frame = f;
1340: }
1341:
1342:
1343: void PrintFrameName (model_t *m, int frame)
1344: {
1345: aliashdr_t *hdr;
1346: maliasframedesc_t *pframedesc;
1347:
1348: hdr = (aliashdr_t *)Mod_Extradata (m);
1349: if (!hdr)
1350: return;
1351: pframedesc = &hdr->frames[frame];
1352:
1353: Con_Printf ("frame %i: %s\n", frame, pframedesc->name);
1354: }
1355:
1356: /*
1357: ==================
1358: Host_Viewnext_f
1359: ==================
1360: */
1361: void Host_Viewnext_f (void)
1362: {
1363: edict_t *e;
1364: model_t *m;
1365:
1366: e = FindViewthing ();
1367: if (!e)
1368: return;
1369: m = cl.model_precache[(int)e->v.modelindex];
1370:
1371: e->v.frame = e->v.frame + 1;
1372: if (e->v.frame >= m->numframes)
1373: e->v.frame = m->numframes - 1;
1374:
1375: PrintFrameName (m, e->v.frame);
1376: }
1377:
1378: /*
1379: ==================
1380: Host_Viewprev_f
1381: ==================
1382: */
1383: void Host_Viewprev_f (void)
1384: {
1385: edict_t *e;
1386: model_t *m;
1387:
1388: e = FindViewthing ();
1389: if (!e)
1390: return;
1391:
1392: m = cl.model_precache[(int)e->v.modelindex];
1393:
1394: e->v.frame = e->v.frame - 1;
1395: if (e->v.frame < 0)
1396: e->v.frame = 0;
1397:
1398: PrintFrameName (m, e->v.frame);
1399: }
1400:
1401: /*
1402: ===============================================================================
1403:
1404: DEMO LOOP CONTROL
1405:
1406: ===============================================================================
1407: */
1408:
1409:
1410: /*
1411: ==================
1412: Host_Startdemos_f
1413: ==================
1414: */
1415: void Host_Startdemos_f (void)
1416: {
1417: int i, c;
1418:
1419: if (cls.state == ca_dedicated)
1420: {
1421: if (!sv.active)
1422: Cbuf_AddText ("map start\n");
1423: return;
1424: }
1425:
1426: c = Cmd_Argc() - 1;
1427: if (c > MAX_DEMOS)
1428: {
1429: Con_Printf ("Max %i demos in demoloop\n", MAX_DEMOS);
1430: c = MAX_DEMOS;
1431: }
1432: Con_Printf ("%i demo(s) in loop\n", c);
1433:
1434: for (i=1 ; i<c+1 ; i++)
1435: strncpy (cls.demos[i-1], Cmd_Argv(i), sizeof(cls.demos[0])-1);
1436:
1437: if (!sv.active && cls.demonum != -1 && !cls.demoplayback)
1438: {
1439: cls.demonum = 0;
1440: CL_NextDemo ();
1441: }
1442: else
1443: cls.demonum = -1;
1444: }
1445:
1446:
1447: /*
1448: ==================
1449: Host_Demos_f
1450:
1451: Return to looping demos
1452: ==================
1453: */
1454: void Host_Demos_f (void)
1455: {
1456: if (cls.state == ca_dedicated)
1457: return;
1458: if (cls.demonum == -1)
1459: cls.demonum = 1;
1460: CL_Disconnect_f ();
1461: CL_NextDemo ();
1462: }
1463:
1464: /*
1465: ==================
1466: Host_Stopdemo_f
1467:
1468: Return to looping demos
1469: ==================
1470: */
1471: void Host_Stopdemo_f (void)
1472: {
1473: if (cls.state == ca_dedicated)
1474: return;
1475: if (!cls.demoplayback)
1476: return;
1477: CL_StopPlayback ();
1478: CL_Disconnect ();
1479: }
1480:
1481: //=============================================================================
1482:
1483: /*
1484: ==================
1485: Host_InitCommands
1486: ==================
1487: */
1488: void Host_InitCommands (void)
1489: {
1490: Cmd_AddCommand ("status", Host_Status_f);
1491: Cmd_AddCommand ("quit", Host_Quit_f);
1492: Cmd_AddCommand ("god", Host_God_f);
1493: Cmd_AddCommand ("notarget", Host_Notarget_f);
1494: Cmd_AddCommand ("fly", Host_Fly_f);
1495: Cmd_AddCommand ("map", Host_Map_f);
1496: Cmd_AddCommand ("restart", Host_Restart_f);
1497: Cmd_AddCommand ("changelevel", Host_Changelevel_f);
1498: Cmd_AddCommand ("connect", Host_Connect_f);
1499: Cmd_AddCommand ("reconnect", Host_Reconnect_f);
1500: Cmd_AddCommand ("name", Host_Name_f);
1501: Cmd_AddCommand ("noclip", Host_Noclip_f);
1502: Cmd_AddCommand ("version", Host_Version_f);
1503: #ifdef IDGODS
1504: Cmd_AddCommand ("please", Host_Please_f);
1505: #endif
1506: Cmd_AddCommand ("say", Host_Say_f);
1507: Cmd_AddCommand ("say_team", Host_Say_Team_f);
1508: Cmd_AddCommand ("tell", Host_Tell_f);
1509: Cmd_AddCommand ("color", Host_Color_f);
1510: Cmd_AddCommand ("kill", Host_Kill_f);
1511: Cmd_AddCommand ("pause", Host_Pause_f);
1512: Cmd_AddCommand ("spawn", Host_Spawn_f);
1513: Cmd_AddCommand ("begin", Host_Begin_f);
1514: Cmd_AddCommand ("prespawn", Host_PreSpawn_f);
1515: Cmd_AddCommand ("kick", Host_Kick_f);
1516: Cmd_AddCommand ("ping", Host_Ping_f);
1517: Cmd_AddCommand ("load", Host_Loadgame_f);
1518: Cmd_AddCommand ("save", Host_Savegame_f);
1519: Cmd_AddCommand ("give", Host_Give_f);
1520:
1521: Cmd_AddCommand ("startdemos", Host_Startdemos_f);
1522: Cmd_AddCommand ("demos", Host_Demos_f);
1523: Cmd_AddCommand ("stopdemo", Host_Stopdemo_f);
1524:
1525: Cmd_AddCommand ("viewmodel", Host_Viewmodel_f);
1526: Cmd_AddCommand ("viewframe", Host_Viewframe_f);
1527: Cmd_AddCommand ("viewnext", Host_Viewnext_f);
1528: Cmd_AddCommand ("viewprev", Host_Viewprev_f);
1529: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.