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