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 *(char **)p = gi.TagMalloc (len, TAG_LEVEL);
349 fread (*(char **)p, len, 1, f);
350 }
351 break;
352 case F_EDICT:
353 index = *(int *)p;
354 if ( index == -1 )
355 *(edict_t **)p = NULL;
356 else
357 *(edict_t **)p = &g_edicts[index];
358 break;
359 case F_CLIENT:
360 index = *(int *)p;
361 if ( index == -1 )
362 *(gclient_t **)p = NULL;
363 else
364 *(gclient_t **)p = &game.clients[index];
365 break;
366 case F_ITEM:
367 index = *(int *)p;
368 if ( index == -1 )
369 *(gitem_t **)p = NULL;
370 else
371 *(gitem_t **)p = &itemlist[index];
372 break;
373
374 //relative to code segment
375 case F_FUNCTION:
376 index = *(int *)p;
377 if ( index == 0 )
378 *(byte **)p = NULL;
379 else
380 *(byte **)p = ((byte *)InitGame) + index;
381 break;
382
383 //relative to data segment
384 case F_MMOVE:
385 index = *(int *)p;
386 if (index == 0)
387 *(byte **)p = NULL;
388 else
389 *(byte **)p = (byte *)&mmove_reloc + index;
390 break;
391
392 default:
393 gi.error ("ReadEdict: unknown field type");
394 }
395 }
396
397 //=========================================================
398
399 /*
400 ==============
401 WriteClient
402
403 All pointer variables (except function pointers) must be handled specially.
404 ==============
405 */
WriteClient(FILE * f,gclient_t * client)406 void WriteClient (FILE *f, gclient_t *client)
407 {
408 field_t *field;
409 gclient_t temp;
410
411 // all of the ints, floats, and vectors stay as they are
412 temp = *client;
413
414 // change the pointers to lengths or indexes
415 for (field=clientfields ; field->name ; field++)
416 {
417 WriteField1 (f, field, (byte *)&temp);
418 }
419
420 // write the block
421 fwrite (&temp, sizeof(temp), 1, f);
422
423 // now write any allocated data following the edict
424 for (field=clientfields ; field->name ; field++)
425 {
426 WriteField2 (f, field, (byte *)client);
427 }
428 }
429
430 /*
431 ==============
432 ReadClient
433
434 All pointer variables (except function pointers) must be handled specially.
435 ==============
436 */
ReadClient(FILE * f,gclient_t * client)437 void ReadClient (FILE *f, gclient_t *client)
438 {
439 field_t *field;
440
441 fread (client, sizeof(*client), 1, f);
442
443 for (field=clientfields ; field->name ; field++)
444 {
445 ReadField (f, field, (byte *)client);
446 }
447 }
448
449 /*
450 ============
451 WriteGame
452
453 This will be called whenever the game goes to a new level,
454 and when the user explicitly saves the game.
455
456 Game information include cross level data, like multi level
457 triggers, help computer info, and all client states.
458
459 A single player death will automatically restore from the
460 last save position.
461 ============
462 */
WriteGame(char * filename,qboolean autosave)463 void WriteGame (char *filename, qboolean autosave)
464 {
465 FILE *f;
466 int i;
467 char str[16];
468
469 if (!autosave)
470 SaveClientData ();
471
472 f = fopen (filename, "wb");
473 if (!f)
474 gi.error ("Couldn't open %s", filename);
475
476 memset (str, 0, sizeof(str));
477 strcpy (str, __DATE__);
478 fwrite (str, sizeof(str), 1, f);
479
480 game.autosaved = autosave;
481 fwrite (&game, sizeof(game), 1, f);
482 game.autosaved = false;
483
484 for (i=0 ; i<game.maxclients ; i++)
485 WriteClient (f, &game.clients[i]);
486
487 fclose (f);
488 }
489
ReadGame(char * filename)490 void ReadGame (char *filename)
491 {
492 FILE *f;
493 int i;
494 char str[16];
495
496 gi.FreeTags (TAG_GAME);
497
498 f = fopen (filename, "rb");
499 if (!f)
500 gi.error ("Couldn't open %s", filename);
501
502 fread (str, sizeof(str), 1, f);
503 if (strcmp (str, __DATE__))
504 {
505 fclose (f);
506 gi.error ("Savegame from an older version.\n");
507 }
508
509 g_edicts = gi.TagMalloc (game.maxentities * sizeof(g_edicts[0]), TAG_GAME);
510 globals.edicts = g_edicts;
511
512 fread (&game, sizeof(game), 1, f);
513 game.clients = gi.TagMalloc (game.maxclients * sizeof(game.clients[0]), TAG_GAME);
514 for (i=0 ; i<game.maxclients ; i++)
515 ReadClient (f, &game.clients[i]);
516
517 fclose (f);
518 }
519
520 //==========================================================
521
522
523 /*
524 ==============
525 WriteEdict
526
527 All pointer variables (except function pointers) must be handled specially.
528 ==============
529 */
WriteEdict(FILE * f,edict_t * ent)530 void WriteEdict (FILE *f, edict_t *ent)
531 {
532 field_t *field;
533 edict_t temp;
534
535 // all of the ints, floats, and vectors stay as they are
536 temp = *ent;
537
538 // change the pointers to lengths or indexes
539 for (field=fields ; field->name ; field++)
540 {
541 WriteField1 (f, field, (byte *)&temp);
542 }
543
544 // write the block
545 fwrite (&temp, sizeof(temp), 1, f);
546
547 // now write any allocated data following the edict
548 for (field=fields ; field->name ; field++)
549 {
550 WriteField2 (f, field, (byte *)ent);
551 }
552
553 }
554
555 /*
556 ==============
557 WriteLevelLocals
558
559 All pointer variables (except function pointers) must be handled specially.
560 ==============
561 */
WriteLevelLocals(FILE * f)562 void WriteLevelLocals (FILE *f)
563 {
564 field_t *field;
565 level_locals_t temp;
566
567 // all of the ints, floats, and vectors stay as they are
568 temp = level;
569
570 // change the pointers to lengths or indexes
571 for (field=levelfields ; field->name ; field++)
572 {
573 WriteField1 (f, field, (byte *)&temp);
574 }
575
576 // write the block
577 fwrite (&temp, sizeof(temp), 1, f);
578
579 // now write any allocated data following the edict
580 for (field=levelfields ; field->name ; field++)
581 {
582 WriteField2 (f, field, (byte *)&level);
583 }
584 }
585
586
587 /*
588 ==============
589 ReadEdict
590
591 All pointer variables (except function pointers) must be handled specially.
592 ==============
593 */
ReadEdict(FILE * f,edict_t * ent)594 void ReadEdict (FILE *f, edict_t *ent)
595 {
596 field_t *field;
597
598 fread (ent, sizeof(*ent), 1, f);
599
600 for (field=fields ; field->name ; field++)
601 {
602 ReadField (f, field, (byte *)ent);
603 }
604 }
605
606 /*
607 ==============
608 ReadLevelLocals
609
610 All pointer variables (except function pointers) must be handled specially.
611 ==============
612 */
ReadLevelLocals(FILE * f)613 void ReadLevelLocals (FILE *f)
614 {
615 field_t *field;
616
617 fread (&level, sizeof(level), 1, f);
618
619 for (field=levelfields ; field->name ; field++)
620 {
621 ReadField (f, field, (byte *)&level);
622 }
623 }
624
625 /*
626 =================
627 WriteLevel
628
629 =================
630 */
WriteLevel(char * filename)631 void WriteLevel (char *filename)
632 {
633 int i;
634 edict_t *ent;
635 FILE *f;
636 void *base;
637
638 f = fopen (filename, "wb");
639 if (!f)
640 gi.error ("Couldn't open %s", filename);
641
642 // write out edict size for checking
643 i = sizeof(edict_t);
644 fwrite (&i, sizeof(i), 1, f);
645
646 // write out a function pointer for checking
647 base = (void *)InitGame;
648 fwrite (&base, sizeof(base), 1, f);
649
650 // write out level_locals_t
651 WriteLevelLocals (f);
652
653 // write out all the entities
654 for (i=0 ; i<globals.num_edicts ; i++)
655 {
656 ent = &g_edicts[i];
657 if (!ent->inuse)
658 continue;
659 fwrite (&i, sizeof(i), 1, f);
660 WriteEdict (f, ent);
661 }
662 i = -1;
663 fwrite (&i, sizeof(i), 1, f);
664
665 fclose (f);
666 }
667
668
669 /*
670 =================
671 ReadLevel
672
673 SpawnEntities will allready have been called on the
674 level the same way it was when the level was saved.
675
676 That is necessary to get the baselines
677 set up identically.
678
679 The server will have cleared all of the world links before
680 calling ReadLevel.
681
682 No clients are connected yet.
683 =================
684 */
ReadLevel(char * filename)685 void ReadLevel (char *filename)
686 {
687 int entnum;
688 FILE *f;
689 int i;
690 void *base;
691 edict_t *ent;
692
693 f = fopen (filename, "rb");
694 if (!f)
695 gi.error ("Couldn't open %s", filename);
696
697 // free any dynamic memory allocated by loading the level
698 // base state
699 gi.FreeTags (TAG_LEVEL);
700
701 // wipe all the entities
702 memset (g_edicts, 0, game.maxentities*sizeof(g_edicts[0]));
703 globals.num_edicts = maxclients->value+1;
704
705 // check edict size
706 fread (&i, sizeof(i), 1, f);
707 if (i != sizeof(edict_t))
708 {
709 fclose (f);
710 gi.error ("ReadLevel: mismatched edict size");
711 }
712
713 // check function pointer base address
714 fread (&base, sizeof(base), 1, f);
715 #ifdef _WIN32
716 if (base != (void *)InitGame)
717 {
718 fclose (f);
719 gi.error ("ReadLevel: function pointers have moved");
720 }
721 #else
722 gi.dprintf("Function offsets %d\n", ((byte *)base) - ((byte *)InitGame));
723 #endif
724
725 // load the level locals
726 ReadLevelLocals (f);
727
728 // load all the entities
729 while (1)
730 {
731 if (fread (&entnum, sizeof(entnum), 1, f) != 1)
732 {
733 fclose (f);
734 gi.error ("ReadLevel: failed to read entnum");
735 }
736 if (entnum == -1)
737 break;
738 if (entnum >= globals.num_edicts)
739 globals.num_edicts = entnum+1;
740
741 ent = &g_edicts[entnum];
742 ReadEdict (f, ent);
743
744 // let the server rebuild world links for this ent
745 memset (&ent->area, 0, sizeof(ent->area));
746 gi.linkentity (ent);
747 }
748
749 fclose (f);
750
751 // mark all clients as unconnected
752 for (i=0 ; i<maxclients->value ; i++)
753 {
754 ent = &g_edicts[i+1];
755 ent->client = game.clients + i;
756 ent->client->pers.connected = false;
757 }
758
759 // do any load time things at this point
760 for (i=0 ; i<globals.num_edicts ; i++)
761 {
762 ent = &g_edicts[i];
763
764 if (!ent->inuse)
765 continue;
766
767 // fire any cross-level triggers
768 if (ent->classname)
769 if (strcmp(ent->classname, "target_crosslevel_target") == 0)
770 ent->nextthink = level.time + ent->delay;
771 }
772 }
773