|
|
1.1.1.4 ! 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: cvar_t *password; 1.1.1.3 root 42: cvar_t *spectator_password; 1.1.1.4 ! root 43: cvar_t *needpass; 1.1 root 44: cvar_t *maxclients; 1.1.1.3 root 45: cvar_t *maxspectators; 1.1 root 46: cvar_t *maxentities; 47: cvar_t *g_select_empty; 48: cvar_t *dedicated; 49: 1.1.1.2 root 50: cvar_t *filterban; 51: 1.1 root 52: cvar_t *sv_maxvelocity; 53: cvar_t *sv_gravity; 54: 55: cvar_t *sv_rollspeed; 56: cvar_t *sv_rollangle; 57: cvar_t *gun_x; 58: cvar_t *gun_y; 59: cvar_t *gun_z; 60: 61: cvar_t *run_pitch; 62: cvar_t *run_roll; 63: cvar_t *bob_up; 64: cvar_t *bob_pitch; 65: cvar_t *bob_roll; 66: 67: cvar_t *sv_cheats; 68: 1.1.1.2 root 69: cvar_t *flood_msgs; 70: cvar_t *flood_persecond; 71: cvar_t *flood_waitdelay; 72: 1.1.1.3 root 73: cvar_t *sv_maplist; 74: 1.1 root 75: void SpawnEntities (char *mapname, char *entities, char *spawnpoint); 76: void ClientThink (edict_t *ent, usercmd_t *cmd); 77: qboolean ClientConnect (edict_t *ent, char *userinfo); 78: void ClientUserinfoChanged (edict_t *ent, char *userinfo); 79: void ClientDisconnect (edict_t *ent); 80: void ClientBegin (edict_t *ent); 81: void ClientCommand (edict_t *ent); 82: void RunEntity (edict_t *ent); 83: void WriteGame (char *filename, qboolean autosave); 84: void ReadGame (char *filename); 85: void WriteLevel (char *filename); 86: void ReadLevel (char *filename); 87: void InitGame (void); 88: void G_RunFrame (void); 89: 90: 91: //=================================================================== 92: 93: 94: void ShutdownGame (void) 95: { 96: gi.dprintf ("==== ShutdownGame ====\n"); 97: 98: gi.FreeTags (TAG_LEVEL); 99: gi.FreeTags (TAG_GAME); 100: } 101: 102: 103: /* 104: ================= 105: GetGameAPI 106: 107: Returns a pointer to the structure with all entry points 108: and global variables 109: ================= 110: */ 111: game_export_t *GetGameAPI (game_import_t *import) 112: { 113: gi = *import; 114: 115: globals.apiversion = GAME_API_VERSION; 116: globals.Init = InitGame; 117: globals.Shutdown = ShutdownGame; 118: globals.SpawnEntities = SpawnEntities; 119: 120: globals.WriteGame = WriteGame; 121: globals.ReadGame = ReadGame; 122: globals.WriteLevel = WriteLevel; 123: globals.ReadLevel = ReadLevel; 124: 125: globals.ClientThink = ClientThink; 126: globals.ClientConnect = ClientConnect; 127: globals.ClientUserinfoChanged = ClientUserinfoChanged; 128: globals.ClientDisconnect = ClientDisconnect; 129: globals.ClientBegin = ClientBegin; 130: globals.ClientCommand = ClientCommand; 131: 132: globals.RunFrame = G_RunFrame; 133: 134: globals.ServerCommand = ServerCommand; 135: 136: globals.edict_size = sizeof(edict_t); 137: 138: return &globals; 139: } 140: 141: #ifndef GAME_HARD_LINKED 142: // this is only here so the functions in q_shared.c and q_shwin.c can link 143: void Sys_Error (char *error, ...) 144: { 145: va_list argptr; 146: char text[1024]; 147: 148: va_start (argptr, error); 149: vsprintf (text, error, argptr); 150: va_end (argptr); 151: 152: gi.error (ERR_FATAL, "%s", text); 153: } 154: 155: void Com_Printf (char *msg, ...) 156: { 157: va_list argptr; 158: char text[1024]; 159: 160: va_start (argptr, msg); 161: vsprintf (text, msg, argptr); 162: va_end (argptr); 163: 164: gi.dprintf ("%s", text); 165: } 166: 167: #endif 168: 169: //====================================================================== 170: 171: 172: /* 173: ================= 174: ClientEndServerFrames 175: ================= 176: */ 177: void ClientEndServerFrames (void) 178: { 179: int i; 180: edict_t *ent; 181: 182: // calc the player views now that all pushing 183: // and damage has been added 184: for (i=0 ; i<maxclients->value ; i++) 185: { 186: ent = g_edicts + 1 + i; 187: if (!ent->inuse || !ent->client) 188: continue; 189: ClientEndServerFrame (ent); 190: } 191: 192: } 193: 194: /* 195: ================= 1.1.1.3 root 196: CreateTargetChangeLevel 197: 198: Returns the created target changelevel 199: ================= 200: */ 201: edict_t *CreateTargetChangeLevel(char *map) 202: { 203: edict_t *ent; 204: 205: ent = G_Spawn (); 206: ent->classname = "target_changelevel"; 207: Com_sprintf(level.nextmap, sizeof(level.nextmap), "%s", map); 208: ent->map = level.nextmap; 209: return ent; 210: } 211: 212: /* 213: ================= 1.1 root 214: EndDMLevel 215: 216: The timelimit or fraglimit has been exceeded 217: ================= 218: */ 219: void EndDMLevel (void) 220: { 221: edict_t *ent; 1.1.1.3 root 222: char *s, *t, *f; 223: static const char *seps = " ,\n\r"; 1.1 root 224: 225: // stay on same level flag 226: if ((int)dmflags->value & DF_SAME_LEVEL) 227: { 1.1.1.3 root 228: BeginIntermission (CreateTargetChangeLevel (level.mapname) ); 229: return; 1.1 root 230: } 1.1.1.3 root 231: 232: // see if it's in the map list 233: if (*sv_maplist->string) { 234: s = strdup(sv_maplist->string); 235: f = NULL; 236: t = strtok(s, seps); 237: while (t != NULL) { 238: if (Q_stricmp(t, level.mapname) == 0) { 239: // it's in the list, go to the next one 240: t = strtok(NULL, seps); 241: if (t == NULL) { // end of list, go to first one 242: if (f == NULL) // there isn't a first one, same level 243: BeginIntermission (CreateTargetChangeLevel (level.mapname) ); 244: else 245: BeginIntermission (CreateTargetChangeLevel (f) ); 246: } else 247: BeginIntermission (CreateTargetChangeLevel (t) ); 248: free(s); 249: return; 250: } 251: if (!f) 252: f = t; 253: t = strtok(NULL, seps); 254: } 255: free(s); 1.1 root 256: } 1.1.1.3 root 257: 258: if (level.nextmap[0]) // go to a specific map 259: BeginIntermission (CreateTargetChangeLevel (level.nextmap) ); 260: else { // search for a changelevel 1.1 root 261: ent = G_Find (NULL, FOFS(classname), "target_changelevel"); 262: if (!ent) 263: { // the map designer didn't include a changelevel, 264: // so create a fake ent that goes back to the same level 1.1.1.3 root 265: BeginIntermission (CreateTargetChangeLevel (level.mapname) ); 266: return; 1.1 root 267: } 1.1.1.3 root 268: BeginIntermission (ent); 1.1 root 269: } 270: } 271: 1.1.1.4 ! root 272: ! 273: /* ! 274: ================= ! 275: CheckNeedPass ! 276: ================= ! 277: */ ! 278: void CheckNeedPass (void) ! 279: { ! 280: int need; ! 281: ! 282: // if password or spectator_password has changed, update needpass ! 283: // as needed ! 284: if (password->modified || spectator_password->modified) ! 285: { ! 286: password->modified = spectator_password->modified = false; ! 287: ! 288: need = 0; ! 289: ! 290: if (*password->string && Q_stricmp(password->string, "none")) ! 291: need |= 1; ! 292: if (*spectator_password->string && Q_stricmp(spectator_password->string, "none")) ! 293: need |= 2; ! 294: ! 295: gi.cvar_set("needpass", va("%d", need)); ! 296: } ! 297: } ! 298: 1.1 root 299: /* 300: ================= 301: CheckDMRules 302: ================= 303: */ 304: void CheckDMRules (void) 305: { 306: int i; 307: gclient_t *cl; 308: 309: if (level.intermissiontime) 310: return; 311: 312: if (!deathmatch->value) 313: return; 314: 315: if (timelimit->value) 316: { 317: if (level.time >= timelimit->value*60) 318: { 319: gi.bprintf (PRINT_HIGH, "Timelimit hit.\n"); 320: EndDMLevel (); 321: return; 322: } 323: } 324: 325: if (fraglimit->value) 326: { 327: for (i=0 ; i<maxclients->value ; i++) 328: { 329: cl = game.clients + i; 330: if (!g_edicts[i+1].inuse) 331: continue; 332: 333: if (cl->resp.score >= fraglimit->value) 334: { 335: gi.bprintf (PRINT_HIGH, "Fraglimit hit.\n"); 336: EndDMLevel (); 337: return; 338: } 339: } 340: } 341: } 342: 343: 344: /* 345: ============= 346: ExitLevel 347: ============= 348: */ 349: void ExitLevel (void) 350: { 351: int i; 352: edict_t *ent; 353: char command [256]; 354: 355: Com_sprintf (command, sizeof(command), "gamemap \"%s\"\n", level.changemap); 356: gi.AddCommandString (command); 357: level.changemap = NULL; 358: level.exitintermission = 0; 359: level.intermissiontime = 0; 360: ClientEndServerFrames (); 361: 362: // clear some things before going to next level 363: for (i=0 ; i<maxclients->value ; i++) 364: { 365: ent = g_edicts + 1 + i; 366: if (!ent->inuse) 367: continue; 368: if (ent->health > ent->client->pers.max_health) 369: ent->health = ent->client->pers.max_health; 370: } 371: 372: } 373: 374: /* 375: ================ 376: G_RunFrame 377: 378: Advances the world by 0.1 seconds 379: ================ 380: */ 381: void G_RunFrame (void) 382: { 383: int i; 384: edict_t *ent; 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: continue; 428: } 429: 430: G_RunEntity (ent); 431: } 432: 433: // see if it is time to end a deathmatch 434: CheckDMRules (); 435: 1.1.1.4 ! root 436: // see if needpass needs updated ! 437: CheckNeedPass (); ! 438: 1.1 root 439: // build the playerstate_t structures for all players 440: ClientEndServerFrames (); 441: } 442:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.