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