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