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
25 mmove_t mmove_reloc;
26
27 field_t fields[] = {
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
122 field_t levelfields[] =
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
134 field_t clientfields[] =
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 */
InitGame(void)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
209 Com_sprintf (game.helpmessage1, sizeof(game.helpmessage1), "");
210
211 Com_sprintf (game.helpmessage2, sizeof(game.helpmessage2), "");
212
213 // initialize all entities for this game
214 game.maxentities = maxentities->value;
215 g_edicts = gi.TagMalloc (game.maxentities * sizeof(g_edicts[0]), TAG_GAME);
216 globals.edicts = g_edicts;
217 globals.max_edicts = game.maxentities;
218
219 // initialize all clients for this game
220 game.maxclients = maxclients->value;
221 game.clients = gi.TagMalloc (game.maxclients * sizeof(game.clients[0]), TAG_GAME);
222 globals.num_edicts = game.maxclients+1;
223 }
224
225 //=========================================================
226
WriteField1(FILE * f,field_t * field,byte * base)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
WriteField2(FILE * f,field_t * field,byte * base)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
ReadField(FILE * f,field_t * field,byte * base)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 */
WriteClient(FILE * f,gclient_t * client)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 */
ReadClient(FILE * f,gclient_t * client)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 */
WriteGame(char * filename,qboolean autosave)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
ReadGame(char * filename)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
513 g_edicts = gi.TagMalloc (game.maxentities * sizeof(g_edicts[0]), TAG_GAME);
514 globals.edicts = g_edicts;
515
516 fread (&game, sizeof(game), 1, f);
517 game.clients = gi.TagMalloc (game.maxclients * sizeof(game.clients[0]), TAG_GAME);
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 */
WriteEdict(FILE * f,edict_t * ent)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 */
WriteLevelLocals(FILE * f)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 */
ReadEdict(FILE * f,edict_t * ent)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 */
ReadLevelLocals(FILE * f)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 */
WriteLevel(char * filename)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 */
ReadLevel(char * filename)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
703 gi.FreeTags (TAG_LEVEL);
704
705 // wipe all the entities
706 memset (g_edicts, 0, game.maxentities*sizeof(g_edicts[0]));
707 globals.num_edicts = maxclients->value+1;
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 }
777