|
|
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.