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