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