|
|
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);
156: deathmatch = gi.cvar ("deathmatch", "0", CVAR_LATCH);
157: coop = gi.cvar ("coop", "0", CVAR_LATCH);
158: skill = gi.cvar ("skill", "1", CVAR_LATCH);
159: maxentities = gi.cvar ("maxentities", "1024", CVAR_LATCH);
160:
161: // change anytime vars
162: dmflags = gi.cvar ("dmflags", "0", CVAR_SERVERINFO);
163: fraglimit = gi.cvar ("fraglimit", "0", CVAR_SERVERINFO);
164: timelimit = gi.cvar ("timelimit", "0", CVAR_SERVERINFO);
165: password = gi.cvar ("password", "", CVAR_USERINFO);
1.1.1.2 ! root 166: filterban = gi.cvar ("filterban", "1", 0);
1.1 root 167:
168: g_select_empty = gi.cvar ("g_select_empty", "0", CVAR_ARCHIVE);
169:
170: run_pitch = gi.cvar ("run_pitch", "0.002", 0);
171: run_roll = gi.cvar ("run_roll", "0.005", 0);
172: bob_up = gi.cvar ("bob_up", "0.005", 0);
173: bob_pitch = gi.cvar ("bob_pitch", "0.002", 0);
174: bob_roll = gi.cvar ("bob_roll", "0.002", 0);
175:
1.1.1.2 ! root 176: // flood control
! 177: flood_msgs = gi.cvar ("flood_msgs", "4", 0);
! 178: flood_persecond = gi.cvar ("flood_persecond", "4", 0);
! 179: flood_waitdelay = gi.cvar ("flood_waitdelay", "10", 0);
! 180:
1.1 root 181: // items
182: InitItems ();
183:
184: Com_sprintf (game.helpmessage1, sizeof(game.helpmessage1), "");
185:
186: Com_sprintf (game.helpmessage2, sizeof(game.helpmessage2), "");
187:
188: // initialize all entities for this game
189: game.maxentities = maxentities->value;
190: g_edicts = gi.TagMalloc (game.maxentities * sizeof(g_edicts[0]), TAG_GAME);
191: globals.edicts = g_edicts;
192: globals.max_edicts = game.maxentities;
193:
194: // initialize all clients for this game
195: game.maxclients = maxclients->value;
196: game.clients = gi.TagMalloc (game.maxclients * sizeof(game.clients[0]), TAG_GAME);
197: globals.num_edicts = game.maxclients+1;
198: }
199:
200: //=========================================================
201:
202: void WriteField1 (FILE *f, field_t *field, byte *base)
203: {
204: void *p;
205: int len;
206: int index;
207:
1.1.1.2 ! root 208: if (field->flags & FFL_SPAWNTEMP)
! 209: return;
! 210:
1.1 root 211: p = (void *)(base + field->ofs);
212: switch (field->type)
213: {
214: case F_INT:
215: case F_FLOAT:
216: case F_ANGLEHACK:
217: case F_VECTOR:
218: case F_IGNORE:
219: break;
220:
221: case F_LSTRING:
222: case F_GSTRING:
223: if ( *(char **)p )
224: len = strlen(*(char **)p) + 1;
225: else
226: len = 0;
227: *(int *)p = len;
228: break;
229: case F_EDICT:
230: if ( *(edict_t **)p == NULL)
231: index = -1;
232: else
233: index = *(edict_t **)p - g_edicts;
234: *(int *)p = index;
235: break;
236: case F_CLIENT:
237: if ( *(gclient_t **)p == NULL)
238: index = -1;
239: else
240: index = *(gclient_t **)p - game.clients;
241: *(int *)p = index;
242: break;
243: case F_ITEM:
244: if ( *(edict_t **)p == NULL)
245: index = -1;
246: else
247: index = *(gitem_t **)p - itemlist;
248: *(int *)p = index;
249: break;
250:
1.1.1.2 ! root 251: //relative to code segment
! 252: case F_FUNCTION:
! 253: if (*(byte **)p == NULL)
! 254: index = 0;
! 255: else
! 256: index = *(byte **)p - ((byte *)InitGame);
! 257: *(int *)p = index;
! 258: break;
! 259:
! 260: //relative to data segment
! 261: case F_MMOVE:
! 262: if (*(byte **)p == NULL)
! 263: index = 0;
! 264: else
! 265: index = *(byte **)p - (byte *)&mmove_reloc;
! 266: *(int *)p = index;
! 267: break;
! 268:
1.1 root 269: default:
270: gi.error ("WriteEdict: unknown field type");
271: }
272: }
273:
1.1.1.2 ! root 274:
1.1 root 275: void WriteField2 (FILE *f, field_t *field, byte *base)
276: {
277: int len;
278: void *p;
279:
1.1.1.2 ! root 280: if (field->flags & FFL_SPAWNTEMP)
! 281: return;
! 282:
1.1 root 283: p = (void *)(base + field->ofs);
284: switch (field->type)
285: {
286: case F_LSTRING:
287: if ( *(char **)p )
288: {
289: len = strlen(*(char **)p) + 1;
290: fwrite (*(char **)p, len, 1, f);
291: }
292: break;
293: }
294: }
295:
296: void ReadField (FILE *f, field_t *field, byte *base)
297: {
298: void *p;
299: int len;
300: int index;
301:
1.1.1.2 ! root 302: if (field->flags & FFL_SPAWNTEMP)
! 303: return;
! 304:
1.1 root 305: p = (void *)(base + field->ofs);
306: switch (field->type)
307: {
308: case F_INT:
309: case F_FLOAT:
310: case F_ANGLEHACK:
311: case F_VECTOR:
312: case F_IGNORE:
313: break;
314:
315: case F_LSTRING:
316: len = *(int *)p;
317: if (!len)
318: *(char **)p = NULL;
319: else
320: {
321: *(char **)p = gi.TagMalloc (len, TAG_LEVEL);
322: fread (*(char **)p, len, 1, f);
323: }
324: break;
325: case F_EDICT:
326: index = *(int *)p;
327: if ( index == -1 )
328: *(edict_t **)p = NULL;
329: else
330: *(edict_t **)p = &g_edicts[index];
331: break;
332: case F_CLIENT:
333: index = *(int *)p;
334: if ( index == -1 )
335: *(gclient_t **)p = NULL;
336: else
337: *(gclient_t **)p = &game.clients[index];
338: break;
339: case F_ITEM:
340: index = *(int *)p;
341: if ( index == -1 )
342: *(gitem_t **)p = NULL;
343: else
344: *(gitem_t **)p = &itemlist[index];
345: break;
346:
1.1.1.2 ! root 347: //relative to code segment
! 348: case F_FUNCTION:
! 349: index = *(int *)p;
! 350: if ( index == 0 )
! 351: *(byte **)p = NULL;
! 352: else
! 353: *(byte **)p = ((byte *)InitGame) + index;
! 354: break;
! 355:
! 356: //relative to data segment
! 357: case F_MMOVE:
! 358: index = *(int *)p;
! 359: if (index == 0)
! 360: *(byte **)p = NULL;
! 361: else
! 362: *(byte **)p = (byte *)&mmove_reloc + index;
! 363: break;
! 364:
1.1 root 365: default:
366: gi.error ("ReadEdict: unknown field type");
367: }
368: }
369:
370: //=========================================================
371:
372: /*
373: ==============
374: WriteClient
375:
376: All pointer variables (except function pointers) must be handled specially.
377: ==============
378: */
379: void WriteClient (FILE *f, gclient_t *client)
380: {
381: field_t *field;
382: gclient_t temp;
383:
384: // all of the ints, floats, and vectors stay as they are
385: temp = *client;
386:
387: // change the pointers to lengths or indexes
388: for (field=clientfields ; field->name ; field++)
389: {
390: WriteField1 (f, field, (byte *)&temp);
391: }
392:
393: // write the block
394: fwrite (&temp, sizeof(temp), 1, f);
395:
396: // now write any allocated data following the edict
397: for (field=clientfields ; field->name ; field++)
398: {
399: WriteField2 (f, field, (byte *)client);
400: }
401: }
402:
403: /*
404: ==============
405: ReadClient
406:
407: All pointer variables (except function pointers) must be handled specially.
408: ==============
409: */
410: void ReadClient (FILE *f, gclient_t *client)
411: {
412: field_t *field;
413:
414: fread (client, sizeof(*client), 1, f);
415:
416: for (field=clientfields ; field->name ; field++)
417: {
418: ReadField (f, field, (byte *)client);
419: }
420: }
421:
422: /*
423: ============
424: WriteGame
425:
426: This will be called whenever the game goes to a new level,
427: and when the user explicitly saves the game.
428:
429: Game information include cross level data, like multi level
430: triggers, help computer info, and all client states.
431:
432: A single player death will automatically restore from the
433: last save position.
434: ============
435: */
436: void WriteGame (char *filename, qboolean autosave)
437: {
438: FILE *f;
439: int i;
440: char str[16];
441:
442: if (!autosave)
443: SaveClientData ();
444:
445: f = fopen (filename, "wb");
446: if (!f)
447: gi.error ("Couldn't open %s", filename);
448:
449: memset (str, 0, sizeof(str));
450: strcpy (str, __DATE__);
451: fwrite (str, sizeof(str), 1, f);
452:
453: game.autosaved = autosave;
454: fwrite (&game, sizeof(game), 1, f);
455: game.autosaved = false;
456:
457: for (i=0 ; i<game.maxclients ; i++)
458: WriteClient (f, &game.clients[i]);
459:
460: fclose (f);
461: }
462:
463: void ReadGame (char *filename)
464: {
465: FILE *f;
466: int i;
467: char str[16];
468:
469: gi.FreeTags (TAG_GAME);
470:
471: f = fopen (filename, "rb");
472: if (!f)
473: gi.error ("Couldn't open %s", filename);
474:
475: fread (str, sizeof(str), 1, f);
476: if (strcmp (str, __DATE__))
477: {
478: fclose (f);
479: gi.error ("Savegame from an older version.\n");
480: }
481:
482: g_edicts = gi.TagMalloc (game.maxentities * sizeof(g_edicts[0]), TAG_GAME);
483: globals.edicts = g_edicts;
484:
485: fread (&game, sizeof(game), 1, f);
486: game.clients = gi.TagMalloc (game.maxclients * sizeof(game.clients[0]), TAG_GAME);
487: for (i=0 ; i<game.maxclients ; i++)
488: ReadClient (f, &game.clients[i]);
489:
490: fclose (f);
491: }
492:
493: //==========================================================
494:
495:
496: /*
497: ==============
498: WriteEdict
499:
500: All pointer variables (except function pointers) must be handled specially.
501: ==============
502: */
503: void WriteEdict (FILE *f, edict_t *ent)
504: {
505: field_t *field;
506: edict_t temp;
507:
508: // all of the ints, floats, and vectors stay as they are
509: temp = *ent;
510:
511: // change the pointers to lengths or indexes
1.1.1.2 ! root 512: for (field=fields ; field->name ; field++)
1.1 root 513: {
514: WriteField1 (f, field, (byte *)&temp);
515: }
516:
517: // write the block
518: fwrite (&temp, sizeof(temp), 1, f);
519:
520: // now write any allocated data following the edict
1.1.1.2 ! root 521: for (field=fields ; field->name ; field++)
1.1 root 522: {
523: WriteField2 (f, field, (byte *)ent);
524: }
525:
526: }
527:
528: /*
529: ==============
530: WriteLevelLocals
531:
532: All pointer variables (except function pointers) must be handled specially.
533: ==============
534: */
535: void WriteLevelLocals (FILE *f)
536: {
537: field_t *field;
538: level_locals_t temp;
539:
540: // all of the ints, floats, and vectors stay as they are
541: temp = level;
542:
543: // change the pointers to lengths or indexes
544: for (field=levelfields ; field->name ; field++)
545: {
546: WriteField1 (f, field, (byte *)&temp);
547: }
548:
549: // write the block
550: fwrite (&temp, sizeof(temp), 1, f);
551:
552: // now write any allocated data following the edict
553: for (field=levelfields ; field->name ; field++)
554: {
555: WriteField2 (f, field, (byte *)&level);
556: }
557: }
558:
559:
560: /*
561: ==============
562: ReadEdict
563:
564: All pointer variables (except function pointers) must be handled specially.
565: ==============
566: */
567: void ReadEdict (FILE *f, edict_t *ent)
568: {
569: field_t *field;
570:
571: fread (ent, sizeof(*ent), 1, f);
572:
1.1.1.2 ! root 573: for (field=fields ; field->name ; field++)
1.1 root 574: {
575: ReadField (f, field, (byte *)ent);
576: }
577: }
578:
579: /*
580: ==============
581: ReadLevelLocals
582:
583: All pointer variables (except function pointers) must be handled specially.
584: ==============
585: */
586: void ReadLevelLocals (FILE *f)
587: {
588: field_t *field;
589:
590: fread (&level, sizeof(level), 1, f);
591:
592: for (field=levelfields ; field->name ; field++)
593: {
594: ReadField (f, field, (byte *)&level);
595: }
596: }
597:
598: /*
599: =================
600: WriteLevel
601:
602: =================
603: */
604: void WriteLevel (char *filename)
605: {
606: int i;
607: edict_t *ent;
608: FILE *f;
609: void *base;
610:
611: f = fopen (filename, "wb");
612: if (!f)
613: gi.error ("Couldn't open %s", filename);
614:
615: // write out edict size for checking
616: i = sizeof(edict_t);
617: fwrite (&i, sizeof(i), 1, f);
618:
619: // write out a function pointer for checking
620: base = (void *)InitGame;
621: fwrite (&base, sizeof(base), 1, f);
622:
623: // write out level_locals_t
624: WriteLevelLocals (f);
625:
626: // write out all the entities
627: for (i=0 ; i<globals.num_edicts ; i++)
628: {
629: ent = &g_edicts[i];
630: if (!ent->inuse)
631: continue;
632: fwrite (&i, sizeof(i), 1, f);
633: WriteEdict (f, ent);
634: }
635: i = -1;
636: fwrite (&i, sizeof(i), 1, f);
637:
638: fclose (f);
639: }
640:
641:
642: /*
643: =================
644: ReadLevel
645:
1.1.1.2 ! root 646: SpawnEntities will allready have been called on the
1.1 root 647: level the same way it was when the level was saved.
648:
649: That is necessary to get the baselines
650: set up identically.
651:
652: The server will have cleared all of the world links before
653: calling ReadLevel.
654:
655: No clients are connected yet.
656: =================
657: */
658: void ReadLevel (char *filename)
659: {
660: int entnum;
661: FILE *f;
662: int i;
663: void *base;
664: edict_t *ent;
665:
666: f = fopen (filename, "rb");
667: if (!f)
668: gi.error ("Couldn't open %s", filename);
669:
670: // free any dynamic memory allocated by loading the level
671: // base state
672: gi.FreeTags (TAG_LEVEL);
673:
674: // wipe all the entities
675: memset (g_edicts, 0, game.maxentities*sizeof(g_edicts[0]));
676: globals.num_edicts = maxclients->value+1;
677:
678: // check edict size
679: fread (&i, sizeof(i), 1, f);
680: if (i != sizeof(edict_t))
681: {
682: fclose (f);
683: gi.error ("ReadLevel: mismatched edict size");
684: }
685:
686: // check function pointer base address
687: fread (&base, sizeof(base), 1, f);
1.1.1.2 ! root 688: #ifdef _WIN32
1.1 root 689: if (base != (void *)InitGame)
690: {
691: fclose (f);
692: gi.error ("ReadLevel: function pointers have moved");
693: }
1.1.1.2 ! root 694: #else
! 695: gi.dprintf("Function offsets %d\n", ((byte *)base) - ((byte *)InitGame));
! 696: #endif
1.1 root 697:
698: // load the level locals
699: ReadLevelLocals (f);
700:
701: // load all the entities
702: while (1)
703: {
704: if (fread (&entnum, sizeof(entnum), 1, f) != 1)
705: {
706: fclose (f);
707: gi.error ("ReadLevel: failed to read entnum");
708: }
709: if (entnum == -1)
710: break;
711: if (entnum >= globals.num_edicts)
712: globals.num_edicts = entnum+1;
713:
714: ent = &g_edicts[entnum];
715: ReadEdict (f, ent);
716:
717: // let the server rebuild world links for this ent
718: memset (&ent->area, 0, sizeof(ent->area));
719: gi.linkentity (ent);
720: }
721:
722: fclose (f);
723:
724: // mark all clients as unconnected
725: for (i=0 ; i<maxclients->value ; i++)
726: {
727: ent = &g_edicts[i+1];
728: ent->client = game.clients + i;
729: ent->client->pers.connected = false;
730: }
731:
732: // do any load time things at this point
733: for (i=0 ; i<globals.num_edicts ; i++)
734: {
735: ent = &g_edicts[i];
736:
737: if (!ent->inuse)
738: continue;
739:
740: // fire any cross-level triggers
741: if (ent->classname)
742: if (strcmp(ent->classname, "target_crosslevel_target") == 0)
743: ent->nextthink = level.time + ent->delay;
744: }
745: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.