#include "g_local.h" game_locals_t game; level_locals_t level; game_import_t gi; game_export_t globals; spawn_temp_t st; int sm_meat_index; int snd_fry; int meansOfDeath; edict_t *g_edicts; cvar_t *deathmatch; cvar_t *coop; cvar_t *dmflags; cvar_t *skill; cvar_t *fraglimit; cvar_t *timelimit; cvar_t *password; cvar_t *spectator_password; cvar_t *needpass; cvar_t *maxclients; cvar_t *maxspectators; cvar_t *maxentities; cvar_t *g_select_empty; cvar_t *dedicated; cvar_t *filterban; cvar_t *sv_maxvelocity; cvar_t *sv_gravity; cvar_t *sv_rollspeed; cvar_t *sv_rollangle; cvar_t *gun_x; cvar_t *gun_y; cvar_t *gun_z; cvar_t *run_pitch; cvar_t *run_roll; cvar_t *bob_up; cvar_t *bob_pitch; cvar_t *bob_roll; cvar_t *flood_msgs; cvar_t *flood_persecond; cvar_t *flood_waitdelay; cvar_t *sv_maplist; //added by psychospaz cvar_t *sv_teams; cvar_t *sv_teams_locked; cvar_t *sv_cheats; cvar_t *sv_bullet_marks; cvar_t *sv_tracers; cvar_t *sv_fall; cvar_t *sv_bulletmarks; cvar_t *sv_laser_type; cvar_t *sv_waterlevel; cvar_t *sv_stunts; cvar_t *sv_matrix; cvar_t *sv_bloodyview; cvar_t *sv_banned_weapons; cvar_t *sv_grapple; cvar_t *sv_chatdistance; cvar_t *sv_stunt_door; cvar_t *sv_realbullets; cvar_t *sv_spawner; cvar_t *sv_serversideonly; cvar_t *sv_sprite_explosions; cvar_t *sv_damageslow; cvar_t *sv_surfacereflection; cvar_t *sv_itemrotate; cvar_t *sv_mzlmodel; cvar_t *sv_lowlag; cvar_t *sv_monsterspawntime; cvar_t *motd; int bulletmarks = 0; //actual in-game int tracers=0; cvar_t *day; int headShot; //psychospaz end void SpawnEntities (char *mapname, char *entities, char *spawnpoint); void ClientThink (edict_t *ent, usercmd_t *cmd); qboolean ClientConnect (edict_t *ent, char *userinfo); void ClientUserinfoChanged (edict_t *ent, char *userinfo); void ClientDisconnect (edict_t *ent); void ClientBegin (edict_t *ent); void ClientCommand (edict_t *ent); void RunEntity (edict_t *ent); void WriteGame (char *filename, qboolean autosave); void ReadGame (char *filename); void WriteLevel (char *filename); void ReadLevel (char *filename); void InitGame (void); void G_RunFrame (void); //=================================================================== void ShutdownGame (void) { gi.dprintf ("\n%c%c%c%c Shutdown PsychoMod %c%c%c%c\n\n", (char)128, (char)129, (char)129, (char)129, (char)129, (char)129, (char)129, (char)130); gi.FreeTags (TAG_LEVEL); gi.FreeTags (TAG_GAME); } /* ================= GetGameAPI Returns a pointer to the structure with all entry points and global variables ================= */ game_export_t *GetGameAPI (game_import_t *import) { gi = *import; globals.apiversion = GAME_API_VERSION; globals.Init = InitGame; globals.Shutdown = ShutdownGame; globals.SpawnEntities = SpawnEntities; globals.WriteGame = WriteGame; globals.ReadGame = ReadGame; globals.WriteLevel = WriteLevel; globals.ReadLevel = ReadLevel; globals.ClientThink = ClientThink; globals.ClientConnect = ClientConnect; globals.ClientUserinfoChanged = ClientUserinfoChanged; globals.ClientDisconnect = ClientDisconnect; globals.ClientBegin = ClientBegin; globals.ClientCommand = ClientCommand; globals.RunFrame = G_RunFrame; globals.ServerCommand = ServerCommand; globals.edict_size = sizeof(edict_t); return &globals; } #ifndef GAME_HARD_LINKED // this is only here so the functions in q_shared.c and q_shwin.c can link void Sys_Error (char *error, ...) { va_list argptr; char text[1024]; va_start (argptr, error); vsprintf (text, error, argptr); va_end (argptr); gi.error (ERR_FATAL, "%s", text); } void Com_Printf (char *msg, ...) { va_list argptr; char text[1024]; va_start (argptr, msg); vsprintf (text, msg, argptr); va_end (argptr); gi.dprintf ("%s", text); } #endif //====================================================================== /* ================= ClientEndServerFrames ================= */ void ClientEndServerFrames (void) { int i; edict_t *ent; // calc the player views now that all pushing // and damage has been added for (i=0 ; ivalue ; i++) { ent = g_edicts + 1 + i; if (!ent->inuse || !ent->client) continue; ClientEndServerFrame (ent); } ent = &g_edicts[0]; for (i=0 ; iinuse) continue; if (!sv_itemrotate->value) ent->s.effects &= ~EF_ROTATE; if (!(ent->svflags&SVF_MONSTER) && !(ent->PlayerDeadName) && !(ent->item && !(ent->flags&FL_RESPAWN) && ent->solid && !(ent->s.effects&EF_ROTATE))) continue; if (ent->svflags&SVF_MONSTER && ent->solid!=SOLID_BBOX) continue; if ((int)sv_surfacereflection->value) AddReflection(ent); if (ent->item) //trying to sneak yerselves shadows eh? continue; if (((int)sv_bulletmarks->value || (!deathmatch->value && !coop->value))) AddShadow(ent); } } /* ================= CreateTargetChangeLevel Returns the created target changelevel ================= */ edict_t *CreateTargetChangeLevel(char *map) { edict_t *ent; ent = G_Spawn (); ent->classname = "target_changelevel"; Com_sprintf(level.nextmap, sizeof(level.nextmap), "%s", map); ent->map = level.nextmap; return ent; } /* ================= EndDMLevel The timelimit or fraglimit has been exceeded ================= */ void EndDMLevel (void) { edict_t *ent; char *s, *t, *f; static const char *seps = " ,\n\r"; // stay on same level flag if ((int)dmflags->value & DF_SAME_LEVEL) { BeginIntermission (CreateTargetChangeLevel (level.mapname) ); return; } // see if it's in the map list if (*sv_maplist->string) { s = strdup(sv_maplist->string); f = NULL; t = strtok(s, seps); while (t != NULL) { if (Q_stricmp(t, level.mapname) == 0) { // it's in the list, go to the next one t = strtok(NULL, seps); if (t == NULL) { // end of list, go to first one if (f == NULL) // there isn't a first one, same level BeginIntermission (CreateTargetChangeLevel (level.mapname) ); else BeginIntermission (CreateTargetChangeLevel (f) ); } else BeginIntermission (CreateTargetChangeLevel (t) ); free(s); return; } if (!f) f = t; t = strtok(NULL, seps); } free(s); } if (level.nextmap[0]) // go to a specific map BeginIntermission (CreateTargetChangeLevel (level.nextmap) ); else { // search for a changelevel ent = G_Find (NULL, FOFS(classname), "target_changelevel"); if (!ent) { // the map designer didn't include a changelevel, // so create a fake ent that goes back to the same level BeginIntermission (CreateTargetChangeLevel (level.mapname) ); return; } BeginIntermission (ent); } } /* ================= CheckNeedPass ================= */ void CheckNeedPass (void) { int need; // if password or spectator_password has changed, update needpass // as needed if (password->modified || spectator_password->modified) { password->modified = spectator_password->modified = false; need = 0; if (*password->string && Q_stricmp(password->string, "none")) need |= 1; if (*spectator_password->string && Q_stricmp(spectator_password->string, "none")) need |= 2; gi.cvar_set("needpass", va("%d", need)); } } /* ================= CheckDMRules ================= */ void CheckDMRules (void) { int i; gclient_t *cl; if (level.intermissiontime) return; if (!deathmatch->value) return; if (timelimit->value) { if (level.time >= timelimit->value*60) { gi.bprintf (PRINT_HIGH, "Timelimit hit.\n"); EndDMLevel (); return; } } if (fraglimit->value) { for (i=0 ; ivalue ; i++) { cl = game.clients + i; if (!g_edicts[i+1].inuse) continue; if (cl->resp.score >= fraglimit->value) { gi.bprintf (PRINT_HIGH, "Fraglimit hit.\n"); EndDMLevel (); return; } } } } /* ============= ExitLevel ============= */ void ExitLevel (void) { int i; edict_t *ent; char command [256]; Com_sprintf (command, sizeof(command), "gamemap \"%s\"\n", level.changemap); gi.AddCommandString (command); level.changemap = NULL; level.exitintermission = 0; level.intermissiontime = 0; ClientEndServerFrames (); // clear some things before going to next level for (i=0 ; ivalue ; i++) { ent = g_edicts + 1 + i; if (!ent->inuse) continue; if (ent->health > ent->client->pers.max_health) ent->health = ent->client->pers.max_health; if (ent->client->aquasuit) { ent->client->newweapon = ent->client->pers.lastweapon; ChangeWeapon (ent); gi.cprintf(ent, PRINT_HIGH, "Weapons Mode\n"); } } } /* ================ G_RunFrame Advances the world by 0.1 seconds ================ */ void MonsterSpawn (edict_t *ent, vec3_t origin, vec3_t angles); void Random_Monster_Spawn (void) { edict_t *ent; char *monster; int j; if (!(deathmatch->value)) return; deathmatch->value=0; ent = G_Spawn(); MonsterSpawn (ent, ent->s.origin, ent->s.angles); VectorCopy(ent->s.origin,ent->s.old_origin); if (random()>.8) { ent->classname=""; monster="Hover"; SP_monster_hover(ent); } else if (random()>.85) { ent->classname="monster_floater"; monster="Floater"; SP_monster_floater(ent); } else if (random()>.85) { ent->classname="monster_mutant"; monster="Mutant"; SP_monster_mutant(ent); } else if (random()>.85) { ent->classname="monster_chick"; monster="Chick"; SP_monster_chick(ent); } else if (random()>.85) { ent->classname="monster_soldier_ss"; monster="SMG Soldier"; SP_monster_soldier_ss(ent); } else if (random()>.85) { ent->classname="monster_soldier"; monster="Shotgun Soldier"; SP_monster_soldier(ent); } else if (random()>.85) { ent->classname="monster_soldier_light"; monster="Blaster Soldier"; SP_monster_soldier_light(ent); } else if (random()>.85) { ent->classname="monster_infantry"; monster="Infantry"; SP_monster_infantry(ent); } else if (random()>.85) { ent->classname="monster_gunner"; monster="Gunner"; SP_monster_gunner(ent); } else { ent->classname="monster_berserk"; monster="Berserk"; SP_monster_berserk(ent); } gi.cprintf (NULL, PRINT_HIGH, "Spawning %s\n", monster); //END MONSTER SPAWN CODE //clear spawn point ent->target_ent = ent; ent->MonsterFind = ent; ent->enemy = ent; ent->goalentity = ent; ent->movetarget = ent; deathmatch->value=1; } void G_RunFrame (void) { int i; edict_t *ent; char lights[2]; // new line level.framenum++; level.time = level.framenum*FRAMETIME; if (level.framenum == 1) { if (!deathmatch->value && !coop->value) sv_serversideonly->value = 0; } // new code starts here if (day->value) daycycletime = (int)((day->value) * 600 + 1); else daycycletime = 0; if (daycycletime > 0) { oldlightlevel = lightlevel; lightlevel = level.framenum % (daycycletime); if (lightlevel > (daycycletime / 2)) lightlevel = daycycletime - lightlevel; lightlevel = 52 - (int)(((float) lightlevel / (float) (daycycletime/2)) * 52); if (lightlevel <= 13) lightlevel = 0; else if (lightlevel >= 35) lightlevel = 25; else lightlevel = lightlevel - 13; lightlevel = 'c' + lightlevel; if (lightlevel > 'z') lightlevel = 'z' - (lightlevel - 'z'); lights[0] = lightlevel; lights[1] = '\0'; gi.configstring(CS_LIGHTS+0, lights); } // new code ends here // choose a client for monsters to target this frame AI_SetSightClient (); // exit intermissions if (level.exitintermission) { ExitLevel (); return; } // // treat each object in turn // even the world gets a chance to think // ent = &g_edicts[0]; for (i=0 ; iinuse) continue; level.current_entity = ent; VectorCopy (ent->s.origin, ent->s.old_origin); // if the ground entity moved, make sure we are still on it if ((ent->groundentity) && (ent->groundentity->linkcount != ent->groundentity_linkcount)) { ent->groundentity = NULL; if ( !(ent->flags & (FL_SWIM|FL_FLY)) && (ent->svflags & SVF_MONSTER) ) { M_CheckGround (ent); } } if (i > 0 && i <= maxclients->value) { ClientBeginServerFrame (ent); continue; } G_RunEntity (ent); } if ((int)sv_monsterspawntime->value>0) if (((int)(level.time*10)%(int)(sv_monsterspawntime->value*10))==0) Random_Monster_Spawn(); // see if it is time to end a deathmatch CheckDMRules (); // see if needpass needs updated CheckNeedPass (); // build the playerstate_t structures for all players ClientEndServerFrames (); }