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