|
|
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: 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: // see if it's in the map list
213: if (*sv_maplist->string) {
214: s = strdup(sv_maplist->string);
215: f = NULL;
216: t = strtok(s, seps);
217: while (t != NULL) {
218: if (Q_stricmp(t, level.mapname) == 0) {
219: // it's in the list, go to the next one
220: t = strtok(NULL, seps);
221: if (t == NULL) { // end of list, go to first one
222: if (f == NULL) // there isn't a first one, same level
223: BeginIntermission (CreateTargetChangeLevel (level.mapname) );
224: else
225: BeginIntermission (CreateTargetChangeLevel (f) );
226: } else
227: BeginIntermission (CreateTargetChangeLevel (t) );
228: free(s);
229: return;
230: }
231: if (!f)
232: f = t;
233: t = strtok(NULL, seps);
234: }
235: free(s);
236: }
237:
238: if (level.nextmap[0]) // go to a specific map
239: BeginIntermission (CreateTargetChangeLevel (level.nextmap) );
240: else { // search for a changelevel
241: ent = G_Find (NULL, FOFS(classname), "target_changelevel");
242: if (!ent)
243: { // the map designer didn't include a changelevel,
244: // so create a fake ent that goes back to the same level
245: BeginIntermission (CreateTargetChangeLevel (level.mapname) );
246: return;
247: }
248: BeginIntermission (ent);
249: }
250: }
251:
252: /*
253: =================
254: CheckDMRules
255: =================
256: */
257: void CheckDMRules (void)
258: {
259: int i;
260: gclient_t *cl;
261:
262: if (level.intermissiontime)
263: return;
264:
265: if (!deathmatch->value)
266: return;
267:
268: if (timelimit->value)
269: {
270: if (level.time >= timelimit->value*60)
271: {
272: gi.bprintf (PRINT_HIGH, "Timelimit hit.\n");
273: EndDMLevel ();
274: return;
275: }
276: }
277:
278: if (fraglimit->value)
279: {
280: for (i=0 ; i<maxclients->value ; i++)
281: {
282: cl = game.clients + i;
283: if (!g_edicts[i+1].inuse)
284: continue;
285:
286: if (cl->resp.score >= fraglimit->value)
287: {
288: gi.bprintf (PRINT_HIGH, "Fraglimit hit.\n");
289: EndDMLevel ();
290: return;
291: }
292: }
293: }
294: }
295:
296:
297: /*
298: =============
299: ExitLevel
300: =============
301: */
302: void ExitLevel (void)
303: {
304: int i;
305: edict_t *ent;
306: char command [256];
307:
308: Com_sprintf (command, sizeof(command), "gamemap \"%s\"\n", level.changemap);
309: gi.AddCommandString (command);
310: level.changemap = NULL;
311: level.exitintermission = 0;
312: level.intermissiontime = 0;
313: ClientEndServerFrames ();
314:
315: // clear some things before going to next level
316: for (i=0 ; i<maxclients->value ; i++)
317: {
318: ent = g_edicts + 1 + i;
319: if (!ent->inuse)
320: continue;
321: if (ent->health > ent->client->pers.max_health)
322: ent->health = ent->client->pers.max_health;
323: }
324:
325: }
326:
327: /*
328: ================
329: G_RunFrame
330:
331: Advances the world by 0.1 seconds
332: ================
333: */
334: void G_RunFrame (void)
335: {
336: int i;
337: edict_t *ent;
338:
339: level.framenum++;
340: level.time = level.framenum*FRAMETIME;
341:
342: // choose a client for monsters to target this frame
343: AI_SetSightClient ();
344:
345: // exit intermissions
346:
347: if (level.exitintermission)
348: {
349: ExitLevel ();
350: return;
351: }
352:
353: //
354: // treat each object in turn
355: // even the world gets a chance to think
356: //
357: ent = &g_edicts[0];
358: for (i=0 ; i<globals.num_edicts ; i++, ent++)
359: {
360: if (!ent->inuse)
361: continue;
362:
363: level.current_entity = ent;
364:
365: VectorCopy (ent->s.origin, ent->s.old_origin);
366:
367: // if the ground entity moved, make sure we are still on it
368: if ((ent->groundentity) && (ent->groundentity->linkcount != ent->groundentity_linkcount))
369: {
370: ent->groundentity = NULL;
371: if ( !(ent->flags & (FL_SWIM|FL_FLY)) && (ent->svflags & SVF_MONSTER) )
372: {
373: M_CheckGround (ent);
374: }
375: }
376:
377: if (i > 0 && i <= maxclients->value)
378: {
379: ClientBeginServerFrame (ent);
380: continue;
381: }
382:
383: G_RunEntity (ent);
384: }
385:
386: // see if it is time to end a deathmatch
387: CheckDMRules ();
388:
389: // build the playerstate_t structures for all players
390: ClientEndServerFrames ();
391: }
392:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.