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