icculus quake2 doxygen  1.0 dev
g_save.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 
19 */
20 
21 #include "g_local.h"
22 
23 #define Function(f) {#f, f}
24 
26 
28  {"classname", FOFS(classname), F_LSTRING},
29  {"model", FOFS(model), F_LSTRING},
30  {"spawnflags", FOFS(spawnflags), F_INT},
31  {"speed", FOFS(speed), F_FLOAT},
32  {"accel", FOFS(accel), F_FLOAT},
33  {"decel", FOFS(decel), F_FLOAT},
34  {"target", FOFS(target), F_LSTRING},
35  {"targetname", FOFS(targetname), F_LSTRING},
36  {"pathtarget", FOFS(pathtarget), F_LSTRING},
37  {"deathtarget", FOFS(deathtarget), F_LSTRING},
38  {"killtarget", FOFS(killtarget), F_LSTRING},
39  {"combattarget", FOFS(combattarget), F_LSTRING},
40  {"message", FOFS(message), F_LSTRING},
41  {"team", FOFS(team), F_LSTRING},
42  {"wait", FOFS(wait), F_FLOAT},
43  {"delay", FOFS(delay), F_FLOAT},
44  {"random", FOFS(random), F_FLOAT},
45  {"move_origin", FOFS(move_origin), F_VECTOR},
46  {"move_angles", FOFS(move_angles), F_VECTOR},
47  {"style", FOFS(style), F_INT},
48  {"count", FOFS(count), F_INT},
49  {"health", FOFS(health), F_INT},
50  {"sounds", FOFS(sounds), F_INT},
51  {"light", 0, F_IGNORE},
52  {"dmg", FOFS(dmg), F_INT},
53  {"mass", FOFS(mass), F_INT},
54  {"volume", FOFS(volume), F_FLOAT},
55  {"attenuation", FOFS(attenuation), F_FLOAT},
56  {"map", FOFS(map), F_LSTRING},
57  {"origin", FOFS(s.origin), F_VECTOR},
58  {"angles", FOFS(s.angles), F_VECTOR},
59  {"angle", FOFS(s.angles), F_ANGLEHACK},
60 
61  {"goalentity", FOFS(goalentity), F_EDICT, FFL_NOSPAWN},
62  {"movetarget", FOFS(movetarget), F_EDICT, FFL_NOSPAWN},
63  {"enemy", FOFS(enemy), F_EDICT, FFL_NOSPAWN},
64  {"oldenemy", FOFS(oldenemy), F_EDICT, FFL_NOSPAWN},
65  {"activator", FOFS(activator), F_EDICT, FFL_NOSPAWN},
66  {"groundentity", FOFS(groundentity), F_EDICT, FFL_NOSPAWN},
67  {"teamchain", FOFS(teamchain), F_EDICT, FFL_NOSPAWN},
68  {"teammaster", FOFS(teammaster), F_EDICT, FFL_NOSPAWN},
69  {"owner", FOFS(owner), F_EDICT, FFL_NOSPAWN},
70  {"mynoise", FOFS(mynoise), F_EDICT, FFL_NOSPAWN},
71  {"mynoise2", FOFS(mynoise2), F_EDICT, FFL_NOSPAWN},
72  {"target_ent", FOFS(target_ent), F_EDICT, FFL_NOSPAWN},
73  {"chain", FOFS(chain), F_EDICT, FFL_NOSPAWN},
74 
75  {"prethink", FOFS(prethink), F_FUNCTION, FFL_NOSPAWN},
76  {"think", FOFS(think), F_FUNCTION, FFL_NOSPAWN},
77  {"blocked", FOFS(blocked), F_FUNCTION, FFL_NOSPAWN},
78  {"touch", FOFS(touch), F_FUNCTION, FFL_NOSPAWN},
79  {"use", FOFS(use), F_FUNCTION, FFL_NOSPAWN},
80  {"pain", FOFS(pain), F_FUNCTION, FFL_NOSPAWN},
81  {"die", FOFS(die), F_FUNCTION, FFL_NOSPAWN},
82 
83  {"stand", FOFS(monsterinfo.stand), F_FUNCTION, FFL_NOSPAWN},
84  {"idle", FOFS(monsterinfo.idle), F_FUNCTION, FFL_NOSPAWN},
85  {"search", FOFS(monsterinfo.search), F_FUNCTION, FFL_NOSPAWN},
86  {"walk", FOFS(monsterinfo.walk), F_FUNCTION, FFL_NOSPAWN},
87  {"run", FOFS(monsterinfo.run), F_FUNCTION, FFL_NOSPAWN},
88  {"dodge", FOFS(monsterinfo.dodge), F_FUNCTION, FFL_NOSPAWN},
89  {"attack", FOFS(monsterinfo.attack), F_FUNCTION, FFL_NOSPAWN},
90  {"melee", FOFS(monsterinfo.melee), F_FUNCTION, FFL_NOSPAWN},
91  {"sight", FOFS(monsterinfo.sight), F_FUNCTION, FFL_NOSPAWN},
92  {"checkattack", FOFS(monsterinfo.checkattack), F_FUNCTION, FFL_NOSPAWN},
93  {"currentmove", FOFS(monsterinfo.currentmove), F_MMOVE, FFL_NOSPAWN},
94 
95  {"endfunc", FOFS(moveinfo.endfunc), F_FUNCTION, FFL_NOSPAWN},
96 
97  // temp spawn vars -- only valid when the spawn function is called
98  {"lip", STOFS(lip), F_INT, FFL_SPAWNTEMP},
99  {"distance", STOFS(distance), F_INT, FFL_SPAWNTEMP},
100  {"height", STOFS(height), F_INT, FFL_SPAWNTEMP},
101  {"noise", STOFS(noise), F_LSTRING, FFL_SPAWNTEMP},
102  {"pausetime", STOFS(pausetime), F_FLOAT, FFL_SPAWNTEMP},
103  {"item", STOFS(item), F_LSTRING, FFL_SPAWNTEMP},
104 
105 //need for item field in edict struct, FFL_SPAWNTEMP item will be skipped on saves
106  {"item", FOFS(item), F_ITEM},
107 
108  {"gravity", STOFS(gravity), F_LSTRING, FFL_SPAWNTEMP},
109  {"sky", STOFS(sky), F_LSTRING, FFL_SPAWNTEMP},
110  {"skyrotate", STOFS(skyrotate), F_FLOAT, FFL_SPAWNTEMP},
111  {"skyaxis", STOFS(skyaxis), F_VECTOR, FFL_SPAWNTEMP},
112  {"minyaw", STOFS(minyaw), F_FLOAT, FFL_SPAWNTEMP},
113  {"maxyaw", STOFS(maxyaw), F_FLOAT, FFL_SPAWNTEMP},
114  {"minpitch", STOFS(minpitch), F_FLOAT, FFL_SPAWNTEMP},
115  {"maxpitch", STOFS(maxpitch), F_FLOAT, FFL_SPAWNTEMP},
116  {"nextmap", STOFS(nextmap), F_LSTRING, FFL_SPAWNTEMP},
117 
118  {0, 0, 0, 0}
119 
120 };
121 
123 {
124  {"changemap", LLOFS(changemap), F_LSTRING},
125 
126  {"sight_client", LLOFS(sight_client), F_EDICT},
127  {"sight_entity", LLOFS(sight_entity), F_EDICT},
128  {"sound_entity", LLOFS(sound_entity), F_EDICT},
129  {"sound2_entity", LLOFS(sound2_entity), F_EDICT},
130 
131  {NULL, 0, F_INT}
132 };
133 
135 {
136  {"pers.weapon", CLOFS(pers.weapon), F_ITEM},
137  {"pers.lastweapon", CLOFS(pers.lastweapon), F_ITEM},
138  {"newweapon", CLOFS(newweapon), F_ITEM},
139 
140  {NULL, 0, F_INT}
141 };
142 
143 /*
144 ============
145 InitGame
146 
147 This will be called when the dll is first loaded, which
148 only happens when a new game is started or a save game
149 is loaded.
150 ============
151 */
152 void InitGame (void)
153 {
154  gi.dprintf ("==== InitGame ====\n");
155 
156  gun_x = gi.cvar ("gun_x", "0", 0);
157  gun_y = gi.cvar ("gun_y", "0", 0);
158  gun_z = gi.cvar ("gun_z", "0", 0);
159 
160  //FIXME: sv_ prefix is wrong for these
161  sv_rollspeed = gi.cvar ("sv_rollspeed", "200", 0);
162  sv_rollangle = gi.cvar ("sv_rollangle", "2", 0);
163  sv_maxvelocity = gi.cvar ("sv_maxvelocity", "2000", 0);
164  sv_gravity = gi.cvar ("sv_gravity", "800", 0);
165 
166  // noset vars
167  dedicated = gi.cvar ("dedicated", "0", CVAR_NOSET);
168 
169  // latched vars
170  sv_cheats = gi.cvar ("cheats", "0", CVAR_SERVERINFO|CVAR_LATCH);
171  gi.cvar ("gamename", GAMEVERSION , CVAR_SERVERINFO | CVAR_LATCH);
172  gi.cvar ("gamedate", __DATE__ , CVAR_SERVERINFO | CVAR_LATCH);
173 
174  maxclients = gi.cvar ("maxclients", "4", CVAR_SERVERINFO | CVAR_LATCH);
175  maxspectators = gi.cvar ("maxspectators", "4", CVAR_SERVERINFO);
176  deathmatch = gi.cvar ("deathmatch", "0", CVAR_LATCH);
177  coop = gi.cvar ("coop", "0", CVAR_LATCH);
178  skill = gi.cvar ("skill", "1", CVAR_LATCH);
179  maxentities = gi.cvar ("maxentities", "1024", CVAR_LATCH);
180 
181  // change anytime vars
182  dmflags = gi.cvar ("dmflags", "0", CVAR_SERVERINFO);
183  fraglimit = gi.cvar ("fraglimit", "0", CVAR_SERVERINFO);
184  timelimit = gi.cvar ("timelimit", "0", CVAR_SERVERINFO);
185  password = gi.cvar ("password", "", CVAR_USERINFO);
186  spectator_password = gi.cvar ("spectator_password", "", CVAR_USERINFO);
187  needpass = gi.cvar ("needpass", "0", CVAR_SERVERINFO);
188  filterban = gi.cvar ("filterban", "1", 0);
189 
190  g_select_empty = gi.cvar ("g_select_empty", "0", CVAR_ARCHIVE);
191 
192  run_pitch = gi.cvar ("run_pitch", "0.002", 0);
193  run_roll = gi.cvar ("run_roll", "0.005", 0);
194  bob_up = gi.cvar ("bob_up", "0.005", 0);
195  bob_pitch = gi.cvar ("bob_pitch", "0.002", 0);
196  bob_roll = gi.cvar ("bob_roll", "0.002", 0);
197 
198  // flood control
199  flood_msgs = gi.cvar ("flood_msgs", "4", 0);
200  flood_persecond = gi.cvar ("flood_persecond", "4", 0);
201  flood_waitdelay = gi.cvar ("flood_waitdelay", "10", 0);
202 
203  // dm map list
204  sv_maplist = gi.cvar ("sv_maplist", "", 0);
205 
206  // items
207  InitItems ();
208 
210 
212 
213  // initialize all entities for this game
218 
219  // initialize all clients for this game
223 }
224 
225 //=========================================================
226 
227 void WriteField1 (FILE *f, field_t *field, byte *base)
228 {
229  void *p;
230  int len;
231  int index;
232 
233  if (field->flags & FFL_SPAWNTEMP)
234  return;
235 
236  p = (void *)(base + field->ofs);
237  switch (field->type)
238  {
239  case F_INT:
240  case F_FLOAT:
241  case F_ANGLEHACK:
242  case F_VECTOR:
243  case F_IGNORE:
244  break;
245 
246  case F_LSTRING:
247  case F_GSTRING:
248  if ( *(char **)p )
249  len = strlen(*(char **)p) + 1;
250  else
251  len = 0;
252  *(int *)p = len;
253  break;
254  case F_EDICT:
255  if ( *(edict_t **)p == NULL)
256  index = -1;
257  else
258  index = *(edict_t **)p - g_edicts;
259  *(int *)p = index;
260  break;
261  case F_CLIENT:
262  if ( *(gclient_t **)p == NULL)
263  index = -1;
264  else
265  index = *(gclient_t **)p - game.clients;
266  *(int *)p = index;
267  break;
268  case F_ITEM:
269  if ( *(edict_t **)p == NULL)
270  index = -1;
271  else
272  index = *(gitem_t **)p - itemlist;
273  *(int *)p = index;
274  break;
275 
276  //relative to code segment
277  case F_FUNCTION:
278  if (*(byte **)p == NULL)
279  index = 0;
280  else
281  index = *(byte **)p - ((byte *)InitGame);
282  *(int *)p = index;
283  break;
284 
285  //relative to data segment
286  case F_MMOVE:
287  if (*(byte **)p == NULL)
288  index = 0;
289  else
290  index = *(byte **)p - (byte *)&mmove_reloc;
291  *(int *)p = index;
292  break;
293 
294  default:
295  gi.error ("WriteEdict: unknown field type");
296  }
297 }
298 
299 
300 void WriteField2 (FILE *f, field_t *field, byte *base)
301 {
302  int len;
303  void *p;
304 
305  if (field->flags & FFL_SPAWNTEMP)
306  return;
307 
308  p = (void *)(base + field->ofs);
309  switch (field->type)
310  {
311  case F_LSTRING:
312  if ( *(char **)p )
313  {
314  len = strlen(*(char **)p) + 1;
315  fwrite (*(char **)p, len, 1, f);
316  }
317  break;
318  default:
319  break;
320  }
321 }
322 
323 void ReadField (FILE *f, field_t *field, byte *base)
324 {
325  void *p;
326  int len;
327  int index;
328 
329  if (field->flags & FFL_SPAWNTEMP)
330  return;
331 
332  p = (void *)(base + field->ofs);
333  switch (field->type)
334  {
335  case F_INT:
336  case F_FLOAT:
337  case F_ANGLEHACK:
338  case F_VECTOR:
339  case F_IGNORE:
340  break;
341 
342  case F_LSTRING:
343  len = *(int *)p;
344  if (!len)
345  *(char **)p = NULL;
346  else
347  {
348  /*
349  SBF: FIXME - 32 extra bytes alloc'd since the saved
350  string might not be long enough
351  */
352  *(char **)p = gi.TagMalloc (32+len, TAG_LEVEL);
353  fread (*(char **)p, len, 1, f);
354  }
355  break;
356  case F_EDICT:
357  index = *(int *)p;
358  if ( index == -1 )
359  *(edict_t **)p = NULL;
360  else
361  *(edict_t **)p = &g_edicts[index];
362  break;
363  case F_CLIENT:
364  index = *(int *)p;
365  if ( index == -1 )
366  *(gclient_t **)p = NULL;
367  else
368  *(gclient_t **)p = &game.clients[index];
369  break;
370  case F_ITEM:
371  index = *(int *)p;
372  if ( index == -1 )
373  *(gitem_t **)p = NULL;
374  else
375  *(gitem_t **)p = &itemlist[index];
376  break;
377 
378  //relative to code segment
379  case F_FUNCTION:
380  index = *(int *)p;
381  if ( index == 0 )
382  *(byte **)p = NULL;
383  else
384  *(byte **)p = ((byte *)InitGame) + index;
385  break;
386 
387  //relative to data segment
388  case F_MMOVE:
389  index = *(int *)p;
390  if (index == 0)
391  *(byte **)p = NULL;
392  else
393  *(byte **)p = (byte *)&mmove_reloc + index;
394  break;
395 
396  default:
397  gi.error ("ReadEdict: unknown field type");
398  }
399 }
400 
401 //=========================================================
402 
403 /*
404 ==============
405 WriteClient
406 
407 All pointer variables (except function pointers) must be handled specially.
408 ==============
409 */
410 void WriteClient (FILE *f, gclient_t *client)
411 {
412  field_t *field;
413  gclient_t temp;
414 
415  // all of the ints, floats, and vectors stay as they are
416  temp = *client;
417 
418  // change the pointers to lengths or indexes
419  for (field=clientfields ; field->name ; field++)
420  {
421  WriteField1 (f, field, (byte *)&temp);
422  }
423 
424  // write the block
425  fwrite (&temp, sizeof(temp), 1, f);
426 
427  // now write any allocated data following the edict
428  for (field=clientfields ; field->name ; field++)
429  {
430  WriteField2 (f, field, (byte *)client);
431  }
432 }
433 
434 /*
435 ==============
436 ReadClient
437 
438 All pointer variables (except function pointers) must be handled specially.
439 ==============
440 */
441 void ReadClient (FILE *f, gclient_t *client)
442 {
443  field_t *field;
444 
445  fread (client, sizeof(*client), 1, f);
446 
447  for (field=clientfields ; field->name ; field++)
448  {
449  ReadField (f, field, (byte *)client);
450  }
451 }
452 
453 /*
454 ============
455 WriteGame
456 
457 This will be called whenever the game goes to a new level,
458 and when the user explicitly saves the game.
459 
460 Game information include cross level data, like multi level
461 triggers, help computer info, and all client states.
462 
463 A single player death will automatically restore from the
464 last save position.
465 ============
466 */
467 void WriteGame (char *filename, qboolean autosave)
468 {
469  FILE *f;
470  int i;
471  char str[16];
472 
473  if (!autosave)
474  SaveClientData ();
475 
476  f = fopen (filename, "wb");
477  if (!f)
478  gi.error ("Couldn't open %s", filename);
479 
480  memset (str, 0, sizeof(str));
481  strcpy (str, __DATE__);
482  fwrite (str, sizeof(str), 1, f);
483 
484  game.autosaved = autosave;
485  fwrite (&game, sizeof(game), 1, f);
486  game.autosaved = false;
487 
488  for (i=0 ; i<game.maxclients ; i++)
489  WriteClient (f, &game.clients[i]);
490 
491  fclose (f);
492 }
493 
494 void ReadGame (char *filename)
495 {
496  FILE *f;
497  int i;
498  char str[16];
499 
500  gi.FreeTags (TAG_GAME);
501 
502  f = fopen (filename, "rb");
503  if (!f)
504  gi.error ("Couldn't open %s", filename);
505 
506  fread (str, sizeof(str), 1, f);
507  if (strcmp (str, __DATE__))
508  {
509  fclose (f);
510  gi.error ("Savegame from an older version.\n");
511  }
512 
515 
516  fread (&game, sizeof(game), 1, f);
518  for (i=0 ; i<game.maxclients ; i++)
519  ReadClient (f, &game.clients[i]);
520 
521  fclose (f);
522 }
523 
524 //==========================================================
525 
526 
527 /*
528 ==============
529 WriteEdict
530 
531 All pointer variables (except function pointers) must be handled specially.
532 ==============
533 */
534 void WriteEdict (FILE *f, edict_t *ent)
535 {
536  field_t *field;
537  edict_t temp;
538 
539  // all of the ints, floats, and vectors stay as they are
540  temp = *ent;
541 
542  // change the pointers to lengths or indexes
543  for (field=fields ; field->name ; field++)
544  {
545  WriteField1 (f, field, (byte *)&temp);
546  }
547 
548  // write the block
549  fwrite (&temp, sizeof(temp), 1, f);
550 
551  // now write any allocated data following the edict
552  for (field=fields ; field->name ; field++)
553  {
554  WriteField2 (f, field, (byte *)ent);
555  }
556 
557 }
558 
559 /*
560 ==============
561 WriteLevelLocals
562 
563 All pointer variables (except function pointers) must be handled specially.
564 ==============
565 */
566 void WriteLevelLocals (FILE *f)
567 {
568  field_t *field;
569  level_locals_t temp;
570 
571  // all of the ints, floats, and vectors stay as they are
572  temp = level;
573 
574  // change the pointers to lengths or indexes
575  for (field=levelfields ; field->name ; field++)
576  {
577  WriteField1 (f, field, (byte *)&temp);
578  }
579 
580  // write the block
581  fwrite (&temp, sizeof(temp), 1, f);
582 
583  // now write any allocated data following the edict
584  for (field=levelfields ; field->name ; field++)
585  {
586  WriteField2 (f, field, (byte *)&level);
587  }
588 }
589 
590 
591 /*
592 ==============
593 ReadEdict
594 
595 All pointer variables (except function pointers) must be handled specially.
596 ==============
597 */
598 void ReadEdict (FILE *f, edict_t *ent)
599 {
600  field_t *field;
601 
602  fread (ent, sizeof(*ent), 1, f);
603 
604  for (field=fields ; field->name ; field++)
605  {
606  ReadField (f, field, (byte *)ent);
607  }
608 }
609 
610 /*
611 ==============
612 ReadLevelLocals
613 
614 All pointer variables (except function pointers) must be handled specially.
615 ==============
616 */
617 void ReadLevelLocals (FILE *f)
618 {
619  field_t *field;
620 
621  fread (&level, sizeof(level), 1, f);
622 
623  for (field=levelfields ; field->name ; field++)
624  {
625  ReadField (f, field, (byte *)&level);
626  }
627 }
628 
629 /*
630 =================
631 WriteLevel
632 
633 =================
634 */
635 void WriteLevel (char *filename)
636 {
637  int i;
638  edict_t *ent;
639  FILE *f;
640  void *base;
641 
642  f = fopen (filename, "wb");
643  if (!f)
644  gi.error ("Couldn't open %s", filename);
645 
646  // write out edict size for checking
647  i = sizeof(edict_t);
648  fwrite (&i, sizeof(i), 1, f);
649 
650  // write out a function pointer for checking
651  base = (void *)InitGame;
652  fwrite (&base, sizeof(base), 1, f);
653 
654  // write out level_locals_t
655  WriteLevelLocals (f);
656 
657  // write out all the entities
658  for (i=0 ; i<globals.num_edicts ; i++)
659  {
660  ent = &g_edicts[i];
661  if (!ent->inuse)
662  continue;
663  fwrite (&i, sizeof(i), 1, f);
664  WriteEdict (f, ent);
665  }
666  i = -1;
667  fwrite (&i, sizeof(i), 1, f);
668 
669  fclose (f);
670 }
671 
672 
673 /*
674 =================
675 ReadLevel
676 
677 SpawnEntities will allready have been called on the
678 level the same way it was when the level was saved.
679 
680 That is necessary to get the baselines
681 set up identically.
682 
683 The server will have cleared all of the world links before
684 calling ReadLevel.
685 
686 No clients are connected yet.
687 =================
688 */
689 void ReadLevel (char *filename)
690 {
691  int entnum;
692  FILE *f;
693  int i;
694  void *base;
695  edict_t *ent;
696 
697  f = fopen (filename, "rb");
698  if (!f)
699  gi.error ("Couldn't open %s", filename);
700 
701  // free any dynamic memory allocated by loading the level
702  // base state
704 
705  // wipe all the entities
706  memset (g_edicts, 0, game.maxentities*sizeof(g_edicts[0]));
708 
709  // check edict size
710  fread (&i, sizeof(i), 1, f);
711  if (i != sizeof(edict_t))
712  {
713  fclose (f);
714  gi.error ("ReadLevel: mismatched edict size");
715  }
716 
717  // check function pointer base address
718  fread (&base, sizeof(base), 1, f);
719 #ifdef _WIN32
720  if (base != (void *)InitGame)
721  {
722  fclose (f);
723  gi.error ("ReadLevel: function pointers have moved");
724  }
725 #else
726  gi.dprintf("Function offsets %d\n", ((byte *)base) - ((byte *)InitGame));
727 #endif
728 
729  // load the level locals
730  ReadLevelLocals (f);
731 
732  // load all the entities
733  while (1)
734  {
735  if (fread (&entnum, sizeof(entnum), 1, f) != 1)
736  {
737  fclose (f);
738  gi.error ("ReadLevel: failed to read entnum");
739  }
740  if (entnum == -1)
741  break;
742  if (entnum >= globals.num_edicts)
743  globals.num_edicts = entnum+1;
744 
745  ent = &g_edicts[entnum];
746  ReadEdict (f, ent);
747 
748  // let the server rebuild world links for this ent
749  memset (&ent->area, 0, sizeof(ent->area));
750  gi.linkentity (ent);
751  }
752 
753  fclose (f);
754 
755  // mark all clients as unconnected
756  for (i=0 ; i<maxclients->value ; i++)
757  {
758  ent = &g_edicts[i+1];
759  ent->client = game.clients + i;
760  ent->client->pers.connected = false;
761  }
762 
763  // do any load time things at this point
764  for (i=0 ; i<globals.num_edicts ; i++)
765  {
766  ent = &g_edicts[i];
767 
768  if (!ent->inuse)
769  continue;
770 
771  // fire any cross-level triggers
772  if (ent->classname)
773  if (strcmp(ent->classname, "target_crosslevel_target") == 0)
774  ent->nextthink = level.time + ent->delay;
775  }
776 }
gi
game_import_t gi
Definition: g_main.c:25
game_import_t::dprintf
void(* dprintf)(char *fmt,...)
Definition: game.h:106
deathmatch
cvar_t * deathmatch
Definition: g_main.c:35
F_FUNCTION
@ F_FUNCTION
Definition: g_local.h:578
dedicated
cvar_t * dedicated
Definition: common.c:47
height
GLsizei height
Definition: qgl_win.c:69
run_roll
cvar_t * run_roll
Definition: g_main.c:62
game_locals_t::helpmessage1
char helpmessage1[512]
Definition: g_local.h:272
field_t
Definition: g_local.h:583
sv_rollspeed
cvar_t * sv_rollspeed
Definition: g_main.c:55
WriteField2
void WriteField2(FILE *f, field_t *field, byte *base)
Definition: g_save.c:300
CVAR_NOSET
#define CVAR_NOSET
Definition: q_shared.h:312
F_IGNORE
@ F_IGNORE
Definition: g_local.h:580
level_locals_t
Definition: g_local.h:301
maxclients
cvar_t * maxclients
Definition: g_main.c:44
ReadField
void ReadField(FILE *f, field_t *field, byte *base)
Definition: g_save.c:323
client_persistant_t::connected
qboolean connected
Definition: g_local.h:833
run_pitch
cvar_t * run_pitch
Definition: g_main.c:61
game_import_t::cvar
cvar_t *(* cvar)(char *var_name, char *value, int flags)
Definition: game.h:162
WriteGame
void WriteGame(char *filename, qboolean autosave)
Definition: g_save.c:467
F_VECTOR
@ F_VECTOR
Definition: g_local.h:573
game_export_t::edicts
struct edict_s * edicts
Definition: game.h:229
password
cvar_t * password
Definition: g_main.c:41
gun_x
cvar_t * gun_x
Definition: g_main.c:57
game_export_t::max_edicts
int max_edicts
Definition: game.h:232
qboolean
qboolean
Definition: q_shared.h:56
flood_msgs
cvar_t * flood_msgs
Definition: g_main.c:69
edict_s::inuse
qboolean inuse
Definition: g_local.h:970
i
int i
Definition: q_shared.c:305
skyaxis
vec3_t skyaxis
Definition: r_main.c:33
maxspectators
cvar_t * maxspectators
Definition: g_main.c:45
edict_s::client
struct gclient_s * client
Definition: g_local.h:965
WriteClient
void WriteClient(FILE *f, gclient_t *client)
Definition: g_save.c:410
FOFS
#define FOFS(x)
Definition: g_local.h:504
maxentities
cvar_t * maxentities
Definition: g_main.c:46
TAG_LEVEL
#define TAG_LEVEL
Definition: g_local.h:77
F_ITEM
@ F_ITEM
Definition: g_local.h:576
gun_y
cvar_t * gun_y
Definition: g_local.h:530
clientfields
field_t clientfields[]
Definition: g_save.c:134
g_edicts
edict_t * g_edicts
Definition: g_main.c:33
F_EDICT
@ F_EDICT
Definition: g_local.h:575
itemlist
gitem_t itemlist[]
Definition: g_items.c:1134
CVAR_SERVERINFO
#define CVAR_SERVERINFO
Definition: q_shared.h:311
F_FLOAT
@ F_FLOAT
Definition: g_local.h:570
gclient_s::pers
client_persistant_t pers
Definition: g_local.h:884
game_locals_t::helpmessage2
char helpmessage2[512]
Definition: g_local.h:273
FFL_NOSPAWN
#define FFL_NOSPAWN
Definition: g_local.h:566
ReadClient
void ReadClient(FILE *f, gclient_t *client)
Definition: g_save.c:441
mmove_reloc
mmove_t mmove_reloc
Definition: g_save.c:25
field_t::name
char * name
Definition: g_local.h:585
edict_s::classname
char * classname
Definition: g_local.h:1005
edict_s
Definition: g_local.h:962
timelimit
cvar_t * timelimit
Definition: g_main.c:40
F_CLIENT
@ F_CLIENT
Definition: g_local.h:577
levelfields
field_t levelfields[]
Definition: g_save.c:122
WriteField1
void WriteField1(FILE *f, field_t *field, byte *base)
Definition: g_save.c:227
gun_z
cvar_t * gun_z
Definition: g_local.h:530
skyrotate
float skyrotate
Definition: r_main.c:32
ReadLevel
void ReadLevel(char *filename)
Definition: g_save.c:689
field_t::type
fieldtype_t type
Definition: g_local.h:587
mmove_t
Definition: g_local.h:408
CVAR_ARCHIVE
#define CVAR_ARCHIVE
Definition: q_shared.h:309
spectator_password
cvar_t * spectator_password
Definition: g_main.c:42
game_locals_t::clients
gclient_t * clients
Definition: g_local.h:277
edict_s::nextthink
float nextthink
Definition: g_local.h:1036
cvar_s::value
float value
Definition: q_shared.h:324
ReadLevelLocals
void ReadLevelLocals(FILE *f)
Definition: g_save.c:617
game
game_locals_t game
Definition: g_main.c:23
flood_persecond
cvar_t * flood_persecond
Definition: g_main.c:70
flood_waitdelay
cvar_t * flood_waitdelay
Definition: g_main.c:71
random
#define random()
Definition: g_local.h:509
edict_t
struct edict_s edict_t
Definition: game.h:52
field_t::ofs
int ofs
Definition: g_local.h:586
NULL
#define NULL
Definition: q_shared.h:60
globals
game_export_t globals
Definition: g_main.c:26
filterban
cvar_t * filterban
Definition: g_main.c:50
ReadEdict
void ReadEdict(FILE *f, edict_t *ent)
Definition: g_save.c:598
WriteLevelLocals
void WriteLevelLocals(FILE *f)
Definition: g_save.c:566
CVAR_LATCH
#define CVAR_LATCH
Definition: q_shared.h:314
game_import_t::TagMalloc
void *(* TagMalloc)(int size, int tag)
Definition: game.h:157
F_MMOVE
@ F_MMOVE
Definition: g_local.h:579
FFL_SPAWNTEMP
#define FFL_SPAWNTEMP
Definition: g_local.h:565
GAMEVERSION
#define GAMEVERSION
Definition: g_local.h:31
LLOFS
#define LLOFS(x)
Definition: g_local.h:506
field_t::flags
int flags
Definition: g_local.h:588
bob_up
cvar_t * bob_up
Definition: g_main.c:63
skill
cvar_t * skill
Definition: g_main.c:38
WriteLevel
void WriteLevel(char *filename)
Definition: g_save.c:635
game_locals_t::autosaved
qboolean autosaved
Definition: g_local.h:293
game_import_t::error
void(* error)(char *fmt,...)
Definition: game.h:118
coop
cvar_t * coop
Definition: g_main.c:36
g_select_empty
cvar_t * g_select_empty
Definition: g_main.c:47
TAG_GAME
#define TAG_GAME
Definition: g_local.h:76
bob_pitch
cvar_t * bob_pitch
Definition: g_main.c:64
sv_cheats
cvar_t * sv_cheats
Definition: g_main.c:67
needpass
cvar_t * needpass
Definition: g_main.c:43
level
GLint level
Definition: qgl_win.c:116
bob_roll
cvar_t * bob_roll
Definition: g_main.c:65
CVAR_USERINFO
#define CVAR_USERINFO
Definition: q_shared.h:310
game_import_t::FreeTags
void(* FreeTags)(int tag)
Definition: game.h:159
InitItems
void InitItems(void)
Definition: g_items.c:2186
fields
field_t fields[]
Definition: g_save.c:27
sv_maplist
cvar_t * sv_maplist
Definition: g_main.c:73
sv_rollangle
cvar_t * sv_rollangle
Definition: g_main.c:56
sv_gravity
cvar_t * sv_gravity
Definition: g_main.c:53
InitGame
void InitGame(void)
Definition: g_save.c:152
STOFS
#define STOFS(x)
Definition: g_local.h:505
sv_maxvelocity
cvar_t * sv_maxvelocity
Definition: g_main.c:52
dmflags
cvar_t * dmflags
Definition: g_main.c:37
F_LSTRING
@ F_LSTRING
Definition: g_local.h:571
edict_s::delay
float delay
Definition: g_local.h:1088
edict_s::area
link_t area
Definition: g_local.h:974
SaveClientData
void SaveClientData(void)
Definition: p_client.c:650
game_locals_t::maxentities
int maxentities
Definition: g_local.h:285
fraglimit
cvar_t * fraglimit
Definition: g_main.c:39
WriteEdict
void WriteEdict(FILE *f, edict_t *ent)
Definition: g_save.c:534
gclient_s
Definition: g_local.h:877
game_import_t::linkentity
void(* linkentity)(edict_t *ent)
Definition: game.h:138
F_INT
@ F_INT
Definition: g_local.h:569
ReadGame
void ReadGame(char *filename)
Definition: g_save.c:494
F_ANGLEHACK
@ F_ANGLEHACK
Definition: g_local.h:574
Com_sprintf
void Com_sprintf(char *dest, int size, char *fmt,...)
Definition: q_shared.c:1236
F_GSTRING
@ F_GSTRING
Definition: g_local.h:572
CLOFS
#define CLOFS(x)
Definition: g_local.h:507
game_export_t::num_edicts
int num_edicts
Definition: game.h:231
count
GLint GLsizei count
Definition: qgl_win.c:128
g_local.h
gitem_s
Definition: g_local.h:234
game_locals_t::maxclients
int maxclients
Definition: g_local.h:284