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