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