/* * =============== * G_SetSpectatorStats * =============== */ public static void G_SetSpectatorStats(edict_t ent) { var cl = ent.client; if (null == cl.chase_target) { PlayerHud.G_SetStats(ent); } cl.ps.stats[Defines.STAT_SPECTATOR] = 1; // layouts are independant in spectator cl.ps.stats[Defines.STAT_LAYOUTS] = 0; if (cl.pers.health <= 0 || GameBase.level.intermissiontime != 0 || cl.showscores) { cl.ps.stats[Defines.STAT_LAYOUTS] |= 1; } if (cl.showinventory && cl.pers.health > 0) { cl.ps.stats[Defines.STAT_LAYOUTS] |= 2; } if (cl.chase_target != null && cl.chase_target.inuse) { //cl.ps.stats[STAT_CHASE] = (short) (CS_PLAYERSKINS + // (cl.chase_target - g_edicts) - 1); cl.ps.stats[Defines.STAT_CHASE] = (short)(Defines.CS_PLAYERSKINS + cl.chase_target.index - 1); } else { cl.ps.stats[Defines.STAT_CHASE] = 0; } }
/* * ====================================================================== * * INTERMISSION * * ====================================================================== */ public static void MoveClientToIntermission(edict_t ent) { if (GameBase.deathmatch.value != 0 || GameBase.coop.value != 0) { ent.client.showscores = true; } Math3D.VectorCopy(GameBase.level.intermission_origin, ent.s.origin); ent.client.ps.pmove.origin[0] = (short)(GameBase.level.intermission_origin[0] * 8); ent.client.ps.pmove.origin[1] = (short)(GameBase.level.intermission_origin[1] * 8); ent.client.ps.pmove.origin[2] = (short)(GameBase.level.intermission_origin[2] * 8); Math3D.VectorCopy(GameBase.level.intermission_angle, ent.client.ps.viewangles); ent.client.ps.pmove.pm_type = Defines.PM_FREEZE; ent.client.ps.gunindex = 0; ent.client.ps.blend[3] = 0; ent.client.ps.rdflags &= ~Defines.RDF_UNDERWATER; // clean up powerup info ent.client.quad_framenum = 0; ent.client.invincible_framenum = 0; ent.client.breather_framenum = 0; ent.client.enviro_framenum = 0; ent.client.grenade_blew_up = false; ent.client.grenade_time = 0; ent.viewheight = 0; ent.s.modelindex = 0; ent.s.modelindex2 = 0; ent.s.modelindex3 = 0; ent.s.modelindex = 0; ent.s.effects = 0; ent.s.sound = 0; ent.solid = Defines.SOLID_NOT; // add the layout if (GameBase.deathmatch.value != 0 || GameBase.coop.value != 0) { PlayerHud.DeathmatchScoreboardMessage(ent, null); GameBase.gi.unicast(ent, true); } }
/* * =============== * G_CheckChaseStats * =============== */ public static void G_CheckChaseStats(edict_t ent) { int i; gclient_t cl; for (i = 1; i <= GameBase.maxclients.value; i++) { cl = GameBase.g_edicts[i].client; if (!GameBase.g_edicts[i].inuse || cl.chase_target != ent) { continue; } //memcpy(cl.ps.stats, ent.client.ps.stats, sizeof(cl.ps.stats)); Array.Copy(ent.client.ps.stats, 0, cl.ps.stats, 0, Defines.MAX_STATS); PlayerHud.G_SetSpectatorStats(GameBase.g_edicts[i]); } }
/* * ================== * Cmd_Score_f * * Display the scoreboard * ================== */ public static void Cmd_Score_f(edict_t ent) { ent.client.showinventory = false; ent.client.showhelp = false; if (0 == GameBase.deathmatch.value && 0 == GameBase.coop.value) { return; } if (ent.client.showscores) { ent.client.showscores = false; return; } ent.client.showscores = true; PlayerHud.DeathmatchScoreboard(ent); }
/** * Cmd_Help_f * * Display the current help message. * */ public static void Help_f(edict_t ent) { // this is for backwards compatability if (GameBase.deathmatch.value != 0) { Cmd.Score_f(ent); return; } ent.client.showinventory = false; ent.client.showscores = false; if (ent.client.showhelp && ent.client.pers.game_helpchanged == GameBase.game.helpchanged) { ent.client.showhelp = false; return; } ent.client.showhelp = true; ent.client.pers.helpchanged = 0; PlayerHud.HelpComputer(ent); }
public static void BeginIntermission(edict_t targ) { int i, n; edict_t ent, client; if (GameBase.level.intermissiontime != 0) { return; // already activated } GameBase.game.autosaved = false; // respawn any dead clients for (i = 0; i < GameBase.maxclients.value; i++) { client = GameBase.g_edicts[1 + i]; if (!client.inuse) { continue; } if (client.health <= 0) { PlayerClient.respawn(client); } } GameBase.level.intermissiontime = GameBase.level.time; GameBase.level.changemap = targ.map; if (GameBase.level.changemap.IndexOf('*') > -1) { if (GameBase.coop.value != 0) { for (i = 0; i < GameBase.maxclients.value; i++) { client = GameBase.g_edicts[1 + i]; if (!client.inuse) { continue; } // strip players of all keys between units for (n = 1; n < GameItemList.itemlist.Length; n++) { // null pointer exception fixed. (RST) if (GameItemList.itemlist[n] != null) { if ((GameItemList.itemlist[n].flags & Defines.IT_KEY) != 0) { client.client.pers.inventory[n] = 0; } } } } } } else { if (0 == GameBase.deathmatch.value) { GameBase.level.exitintermission = true; // go immediately to the // next level return; } } GameBase.level.exitintermission = false; // find an intermission spot ent = GameBase.G_FindEdict(null, GameBase.findByClass, "info_player_intermission"); if (ent == null) { // the map creator forgot to put in an intermission // point... ent = GameBase.G_FindEdict(null, GameBase.findByClass, "info_player_start"); if (ent == null) { ent = GameBase.G_FindEdict(null, GameBase.findByClass, "info_player_deathmatch"); } } else { // chose one of four spots i = Lib.rand() & 3; EdictIterator es = null; while (i-- > 0) { es = GameBase.G_Find(es, GameBase.findByClass, "info_player_intermission"); if (es == null) // wrap around the list { continue; } ent = es.o; } } Math3D.VectorCopy(ent.s.origin, GameBase.level.intermission_origin); Math3D.VectorCopy(ent.s.angles, GameBase.level.intermission_angle); // move all clients to the intermission point for (i = 0; i < GameBase.maxclients.value; i++) { client = GameBase.g_edicts[1 + i]; if (!client.inuse) { continue; } PlayerHud.MoveClientToIntermission(client); } }
/* * ================== * DeathmatchScoreboard * * Draw instead of help message. Note that it isn't that hard to overflow * the 1400 byte message limit! * ================== */ public static void DeathmatchScoreboard(edict_t ent) { PlayerHud.DeathmatchScoreboardMessage(ent, ent.enemy); GameBase.gi.unicast(ent, true); }
/** * Called for each player at the end of the server frame and right after * spawning. */ public static void ClientEndServerFrame(edict_t ent) { float bobtime; int i; PlayerView.current_player = ent; PlayerView.current_client = ent.client; // // If the origin or velocity have changed since ClientThink(), // update the pmove values. This will happen when the client // is pushed by a bmodel or kicked by an explosion. // // If it wasn't updated here, the view position would lag a frame // behind the body position when pushed -- "sinking into plats" // for (i = 0; i < 3; i++) { PlayerView.current_client.ps.pmove.origin[i] = (short)(ent.s.origin[i] * 8.0); PlayerView.current_client.ps.pmove.velocity[i] = (short)(ent.velocity[i] * 8.0); } // // If the end of unit layout is displayed, don't give // the player any normal movement attributes // if (GameBase.level.intermissiontime != 0) { // FIXME: add view drifting here? PlayerView.current_client.ps.blend[3] = 0; PlayerView.current_client.ps.fov = 90; PlayerHud.G_SetStats(ent); return; } Math3D.AngleVectors(ent.client.v_angle, PlayerView.forward, PlayerView.right, PlayerView.up); // burn from lava, etc PlayerView.P_WorldEffects(); // // set model angles from view angles so other things in // the world can tell which direction you are looking // if (ent.client.v_angle[Defines.PITCH] > 180) { ent.s.angles[Defines.PITCH] = (-360 + ent.client.v_angle[Defines.PITCH]) / 3; } else { ent.s.angles[Defines.PITCH] = ent.client.v_angle[Defines.PITCH] / 3; } ent.s.angles[Defines.YAW] = ent.client.v_angle[Defines.YAW]; ent.s.angles[Defines.ROLL] = 0; ent.s.angles[Defines.ROLL] = PlayerView.SV_CalcRoll(ent.s.angles, ent.velocity) * 4; // // calculate speed and cycle to be used for // all cyclic walking effects // PlayerView.xyspeed = (float)Math.Sqrt(ent.velocity[0] * ent.velocity[0] + ent.velocity[1] * ent.velocity[1]); if (PlayerView.xyspeed < 5) { PlayerView.bobmove = 0; PlayerView.current_client.bobtime = 0; // start at beginning of cycle again } else if (ent.groundentity != null) { // so bobbing only cycles when on // ground if (PlayerView.xyspeed > 210) { PlayerView.bobmove = 0.25f; } else if (PlayerView.xyspeed > 100) { PlayerView.bobmove = 0.125f; } else { PlayerView.bobmove = 0.0625f; } } bobtime = PlayerView.current_client.bobtime += PlayerView.bobmove; if ((PlayerView.current_client.ps.pmove.pm_flags & pmove_t.PMF_DUCKED) != 0) { bobtime *= 4; } PlayerView.bobcycle = (int)bobtime; PlayerView.bobfracsin = (float)Math.Abs(Math.Sin(bobtime * Math.PI)); // detect hitting the floor PlayerView.P_FallingDamage(ent); // apply all the damage taken this frame PlayerView.P_DamageFeedback(ent); // determine the view offsets PlayerView.SV_CalcViewOffset(ent); // determine the gun offsets PlayerView.SV_CalcGunOffset(ent); // determine the full screen color blend // must be after viewoffset, so eye contents can be // accurately determined // FIXME: with client prediction, the contents // should be determined by the client PlayerView.SV_CalcBlend(ent); // chase cam stuff if (ent.client.resp.spectator) { PlayerHud.G_SetSpectatorStats(ent); } else { PlayerHud.G_SetStats(ent); } PlayerHud.G_CheckChaseStats(ent); PlayerView.G_SetClientEvent(ent); PlayerView.G_SetClientEffects(ent); PlayerView.G_SetClientSound(ent); PlayerView.G_SetClientFrame(ent); Math3D.VectorCopy(ent.velocity, ent.client.oldvelocity); Math3D.VectorCopy(ent.client.ps.viewangles, ent.client.oldviewangles); // clear weapon kicks Math3D.VectorClear(ent.client.kick_origin); Math3D.VectorClear(ent.client.kick_angles); // if the scoreboard is up, update it if (ent.client.showscores && 0 == (GameBase.level.framenum & 31)) { PlayerHud.DeathmatchScoreboardMessage(ent, ent.enemy); GameBase.gi.unicast(ent, false); } }