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