|
|
1.1 root 1:
2: #include "g_local.h"
3:
4: game_locals_t game;
5: level_locals_t level;
6: game_import_t gi;
7: game_export_t globals;
8: spawn_temp_t st;
9:
10: int sm_meat_index;
11: int snd_fry;
12: int meansOfDeath;
13:
14: edict_t *g_edicts;
15:
16: cvar_t *deathmatch;
17: cvar_t *coop;
18: cvar_t *dmflags;
19: cvar_t *skill;
20: cvar_t *fraglimit;
21: cvar_t *timelimit;
22: //ZOID
23: cvar_t *capturelimit;
24: cvar_t *instantweap;
25: //ZOID
26: cvar_t *password;
27: cvar_t *maxclients;
28: cvar_t *maxentities;
29: cvar_t *g_select_empty;
30: cvar_t *dedicated;
31:
32: cvar_t *sv_maxvelocity;
33: cvar_t *sv_gravity;
34:
35: cvar_t *sv_rollspeed;
36: cvar_t *sv_rollangle;
37: cvar_t *gun_x;
38: cvar_t *gun_y;
39: cvar_t *gun_z;
40:
41: cvar_t *run_pitch;
42: cvar_t *run_roll;
43: cvar_t *bob_up;
44: cvar_t *bob_pitch;
45: cvar_t *bob_roll;
46:
47: cvar_t *sv_cheats;
48:
49: cvar_t *flood_msgs;
50: cvar_t *flood_persecond;
51: cvar_t *flood_waitdelay;
52:
53: cvar_t *sv_maplist;
54:
55: void SpawnEntities (char *mapname, char *entities, char *spawnpoint);
56: void ClientThink (edict_t *ent, usercmd_t *cmd);
57: qboolean ClientConnect (edict_t *ent, char *userinfo);
58: void ClientUserinfoChanged (edict_t *ent, char *userinfo);
59: void ClientDisconnect (edict_t *ent);
60: void ClientBegin (edict_t *ent);
61: void ClientCommand (edict_t *ent);
62: void RunEntity (edict_t *ent);
63: void WriteGame (char *filename, qboolean autosave);
64: void ReadGame (char *filename);
65: void WriteLevel (char *filename);
66: void ReadLevel (char *filename);
67: void InitGame (void);
68: void G_RunFrame (void);
69:
70:
71: //===================================================================
72:
73:
74: void ShutdownGame (void)
75: {
76: gi.dprintf ("==== ShutdownGame ====\n");
77:
78: gi.FreeTags (TAG_LEVEL);
79: gi.FreeTags (TAG_GAME);
80: }
81:
82:
83: /*
84: =================
85: GetGameAPI
86:
87: Returns a pointer to the structure with all entry points
88: and global variables
89: =================
90: */
91: game_export_t *GetGameAPI (game_import_t *import)
92: {
93: gi = *import;
94:
95: globals.apiversion = GAME_API_VERSION;
96: globals.Init = InitGame;
97: globals.Shutdown = ShutdownGame;
98: globals.SpawnEntities = SpawnEntities;
99:
100: globals.WriteGame = WriteGame;
101: globals.ReadGame = ReadGame;
102: globals.WriteLevel = WriteLevel;
103: globals.ReadLevel = ReadLevel;
104:
105: globals.ClientThink = ClientThink;
106: globals.ClientConnect = ClientConnect;
107: globals.ClientUserinfoChanged = ClientUserinfoChanged;
108: globals.ClientDisconnect = ClientDisconnect;
109: globals.ClientBegin = ClientBegin;
110: globals.ClientCommand = ClientCommand;
111:
112: globals.RunFrame = G_RunFrame;
113:
114: globals.ServerCommand = ServerCommand;
115:
116: globals.edict_size = sizeof(edict_t);
117:
118: return &globals;
119: }
120:
121: #ifndef GAME_HARD_LINKED
122: // this is only here so the functions in q_shared.c and q_shwin.c can link
123: void Sys_Error (char *error, ...)
124: {
125: va_list argptr;
126: char text[1024];
127:
128: va_start (argptr, error);
129: vsprintf (text, error, argptr);
130: va_end (argptr);
131:
132: gi.error (ERR_FATAL, "%s", text);
133: }
134:
135: void Com_Printf (char *msg, ...)
136: {
137: va_list argptr;
138: char text[1024];
139:
140: va_start (argptr, msg);
141: vsprintf (text, msg, argptr);
142: va_end (argptr);
143:
144: gi.dprintf ("%s", text);
145: }
146:
147: #endif
148:
149: //======================================================================
150:
151:
152: /*
153: =================
154: ClientEndServerFrames
155: =================
156: */
157: void ClientEndServerFrames (void)
158: {
159: int i;
160: edict_t *ent;
161:
162: // calc the player views now that all pushing
163: // and damage has been added
164: for (i=0 ; i<maxclients->value ; i++)
165: {
166: ent = g_edicts + 1 + i;
167: if (!ent->inuse || !ent->client)
168: continue;
169: ClientEndServerFrame (ent);
170: }
171:
172: }
173:
174: /*
175: =================
176: CreateTargetChangeLevel
177:
178: Returns the created target changelevel
179: =================
180: */
181: edict_t *CreateTargetChangeLevel(char *map)
182: {
183: edict_t *ent;
184:
185: ent = G_Spawn ();
186: ent->classname = "target_changelevel";
187: Com_sprintf(level.nextmap, sizeof(level.nextmap), "%s", map);
188: ent->map = level.nextmap;
189: return ent;
190: }
191:
192: /*
193: =================
194: EndDMLevel
195:
196: The timelimit or fraglimit has been exceeded
197: =================
198: */
199: void EndDMLevel (void)
200: {
201: edict_t *ent;
202: char *s, *t, *f;
203: static const char *seps = " ,\n\r";
204:
205: // stay on same level flag
206: if ((int)dmflags->value & DF_SAME_LEVEL)
207: {
208: BeginIntermission (CreateTargetChangeLevel (level.mapname) );
209: return;
210: }
211:
212: if (*level.forcemap) {
213: BeginIntermission (CreateTargetChangeLevel (level.forcemap) );
214: return;
215: }
216:
217: // see if it's in the map list
218: if (*sv_maplist->string) {
219: s = strdup(sv_maplist->string);
220: f = NULL;
221: t = strtok(s, seps);
222: while (t != NULL) {
223: if (Q_stricmp(t, level.mapname) == 0) {
224: // it's in the list, go to the next one
225: t = strtok(NULL, seps);
226: if (t == NULL) { // end of list, go to first one
227: if (f == NULL) // there isn't a first one, same level
228: BeginIntermission (CreateTargetChangeLevel (level.mapname) );
229: else
230: BeginIntermission (CreateTargetChangeLevel (f) );
231: } else
232: BeginIntermission (CreateTargetChangeLevel (t) );
233: free(s);
234: return;
235: }
236: if (!f)
237: f = t;
238: t = strtok(NULL, seps);
239: }
240: free(s);
241: }
242:
243: if (level.nextmap[0]) // go to a specific map
244: BeginIntermission (CreateTargetChangeLevel (level.nextmap) );
245: else { // search for a changelevel
246: ent = G_Find (NULL, FOFS(classname), "target_changelevel");
247: if (!ent)
248: { // the map designer didn't include a changelevel,
249: // so create a fake ent that goes back to the same level
250: BeginIntermission (CreateTargetChangeLevel (level.mapname) );
251: return;
252: }
253: BeginIntermission (ent);
254: }
255: }
256:
257: /*
258: =================
259: CheckDMRules
260: =================
261: */
262: void CheckDMRules (void)
263: {
264: int i;
265: gclient_t *cl;
266:
267: if (level.intermissiontime)
268: return;
269:
270: if (!deathmatch->value)
271: return;
272:
273: //ZOID
274: if (ctf->value && CTFCheckRules()) {
275: EndDMLevel ();
276: return;
277: }
278: if (CTFInMatch())
279: return; // no checking in match mode
280: //ZOID
281:
282: if (timelimit->value)
283: {
284: if (level.time >= timelimit->value*60)
285: {
286: gi.bprintf (PRINT_HIGH, "Timelimit hit.\n");
287: EndDMLevel ();
288: return;
289: }
290: }
291:
292: if (fraglimit->value)
293: for (i=0 ; i<maxclients->value ; i++)
294: {
295: cl = game.clients + i;
296: if (!g_edicts[i+1].inuse)
297: continue;
298:
299: if (cl->resp.score >= fraglimit->value)
300: {
301: gi.bprintf (PRINT_HIGH, "Fraglimit hit.\n");
302: EndDMLevel ();
303: return;
304: }
305: }
306: }
307:
308:
309: /*
310: =============
311: ExitLevel
312: =============
313: */
314: void ExitLevel (void)
315: {
316: int i;
317: edict_t *ent;
318: char command [256];
319:
320: level.exitintermission = 0;
321: level.intermissiontime = 0;
322:
323: if (CTFNextMap())
324: return;
325:
326: Com_sprintf (command, sizeof(command), "gamemap \"%s\"\n", level.changemap);
327: gi.AddCommandString (command);
328: ClientEndServerFrames ();
329:
330: level.changemap = NULL;
331:
332: // clear some things before going to next level
333: for (i=0 ; i<maxclients->value ; i++)
334: {
335: ent = g_edicts + 1 + i;
336: if (!ent->inuse)
337: continue;
338: if (ent->health > ent->client->pers.max_health)
339: ent->health = ent->client->pers.max_health;
340: }
341: }
342:
343: /*
344: ================
345: G_RunFrame
346:
347: Advances the world by 0.1 seconds
348: ================
349: */
350: void G_RunFrame (void)
351: {
352: int i;
353: edict_t *ent;
354:
355: level.framenum++;
356: level.time = level.framenum*FRAMETIME;
357:
358: // choose a client for monsters to target this frame
359: AI_SetSightClient ();
360:
361: // exit intermissions
362:
363: if (level.exitintermission)
364: {
365: ExitLevel ();
366: return;
367: }
368:
369: //
370: // treat each object in turn
371: // even the world gets a chance to think
372: //
373: ent = &g_edicts[0];
374: for (i=0 ; i<globals.num_edicts ; i++, ent++)
375: {
376: if (!ent->inuse)
377: continue;
378:
379: level.current_entity = ent;
380:
381: VectorCopy (ent->s.origin, ent->s.old_origin);
382:
383: // if the ground entity moved, make sure we are still on it
384: if ((ent->groundentity) && (ent->groundentity->linkcount != ent->groundentity_linkcount))
385: {
386: ent->groundentity = NULL;
387: if ( !(ent->flags & (FL_SWIM|FL_FLY)) && (ent->svflags & SVF_MONSTER) )
388: {
389: M_CheckGround (ent);
390: }
391: }
392:
393: if (i > 0 && i <= maxclients->value)
394: {
395: ClientBeginServerFrame (ent);
396: continue;
397: }
398:
399: G_RunEntity (ent);
400: }
401:
402: // see if it is time to end a deathmatch
403: CheckDMRules ();
404:
405: // build the playerstate_t structures for all players
406: ClientEndServerFrames ();
407: }
408:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.