void AddCEntity(centity_t ent) { // event-only entities will have been dealt with already if (ent.currentState.eType >= 13) return; // calculate the current origin CalcEntityLerpPositions(ent); switch (ent.currentState.eType) { case 1: Player(ent); break; } }
static Globals( ) { for (var i = 0; i < cl_entities.Length; i++) { cl_entities[i] = new centity_t(); } for (var i = 0; i < cl_parse_entities.Length; i++) { cl_parse_entities[i] = new entity_state_t(null); } for (var i = 0; i < key_lines.Length; i++) { key_lines[i] = new Byte[Defines.MAXCMDLINE]; } }
void Player(centity_t ent) { // the client number is stored in clientNum. It can't be derived // from the entity number, because a single client may have // multiple corpses on the level using the same clientinfo int clientNum = ent.currentState.clientNum; if (clientNum < 0 || clientNum >= 64) { Common.Instance.Error("Bad clientNum on player entity"); } clientInfo_t ci = cgs.clientinfo[clientNum]; // it is possible to see corpses from disconnected players that may // not have valid clientinfo //if (!ci.infoValid) // return; if (clientNum == Client.Instance.cl.snap.ps.clientNum) return; VertexPositionColor[] vecs = MiscRender.CreateBox(Common.playerMins, Common.playerMaxs, new Color4(System.Drawing.Color.Red) { Alpha = 0.5f }); float pitch, roll, yaw; pitch = ent.lerpAngles.Z * (float)(Math.PI / 180f); roll = ent.lerpAngles.Y * (float)(Math.PI / 180f); yaw = ent.lerpAngles.X * (float)(Math.PI / 180f); //Common.Instance.WriteLine("{0}, {1}, {2}", yaw, pitch, roll); Matrix posmat = Matrix.RotationX(yaw) * Matrix.RotationZ(roll) * Matrix.Translation(ent.lerpOrigin); for (int i = 0; i < vecs.Length; i++) { Vector4 vec = Vector3.Transform(vecs[i].Position, posmat); vecs[i].Position.X = vec.X; vecs[i].Position.Y = vec.Y; vecs[i].Position.Z = vec.Z; } Renderer.Instance.SourceMap.bboxVerts.AddRange(vecs); }
void InterpolateEntityPosition(centity_t ent) { // it would be an internal error to find an entity that interpolates without // a snapshot ahead of the current one if (cg.nextSnap == null) { Common.Instance.Error("InterpolateEntityPosition: cg.nextSnap == null"); } float f = cg.frameInterpolation; // this will linearize a sine or parabolic curve, but it is important // to not extrapolate player positions if more recent data is available Vector3 current, next; Common.Instance.EvaluateTrajectory(ent.currentState.pos, cg.snap.serverTime, out current); Common.Instance.EvaluateTrajectory(ent.nextState.pos, cg.nextSnap.serverTime, out next); ent.lerpOrigin[0] = current[0] + f * (next[0] - current[0]); ent.lerpOrigin[1] = current[1] + f * (next[1] - current[1]); ent.lerpOrigin[2] = current[2] + f * (next[2] - current[2]); Common.Instance.EvaluateTrajectory(ent.currentState.apos, cg.snap.serverTime, out current); Common.Instance.EvaluateTrajectory(ent.nextState.apos, cg.nextSnap.serverTime, out next); ent.lerpAngles[0] = current[0] + f * (next[0] - current[0]); ent.lerpAngles[1] = current[1] + f * (next[1] - current[1]); ent.lerpAngles[2] = current[2] + f * (next[2] - current[2]); }
void CalcEntityLerpPositions(centity_t ent) { // if this player does not want to see extrapolated players // make sure the clients use TR_INTERPOLATE if (ent.currentState.number < 64) { ent.currentState.pos.trType = Common.trType_t.TR_INTERPOLATE; ent.nextState.pos.trType = Common.trType_t.TR_INTERPOLATE; } if (ent.interpolate && ent.currentState.pos.trType == Common.trType_t.TR_INTERPOLATE) { InterpolateEntityPosition(ent); return; } // first see if we can interpolate between two snaps for // linear extrapolated clients if (ent.interpolate && ent.currentState.pos.trType == Common.trType_t.TR_LINEAR_STOP && ent.currentState.number < 64) { InterpolateEntityPosition(ent); return; } // just use the current frame and evaluate as best we can Common.Instance.EvaluateTrajectory(ent.currentState.pos, cg.time, out ent.lerpOrigin); Common.Instance.EvaluateTrajectory(ent.currentState.apos, cg.time, out ent.lerpAngles); // adjust for riding a mover if it wasn't rolled into the predicted // player state if (ent != cg.predictedPlayerEntity) { AdjustPositionForMover(ent.lerpOrigin, ent.currentState.groundEntityNum, cg.snap.serverTime, cg.time, out ent.lerpOrigin); } }
/* =============== CG_TransitionEntity cent->nextState is moved to cent->currentState and events are fired =============== */ void TransitionEntity(centity_t cent) { cent.currentState = cent.nextState; cent.currentValid = true; // reset if the entity wasn't in the last frame or was teleported if (!cent.interpolate) { ResetEntity(cent); } // clear the next state. if will be set by the next CG_SetNextSnap cent.interpolate = false; // Todo: Check for events CheckEvents(cent); }
void CheckEvents(centity_t cent) { // calculate the position at exactly the frame time Common.Instance.EvaluateTrajectory(cent.currentState.pos, cg.snap.serverTime, out cent.lerpOrigin); }
void ResetEntity(centity_t cent) { // if the previous snapshot this entity was updated in is at least // an event window back in time then we can reset the previous event if (cent.snapShotTime <= cg.time - 300) { cent.previousEvent = 0; } cent.trailTime = cg.snap.serverTime; cent.lerpOrigin = cent.currentState.origin; cent.lerpAngles = cent.currentState.angles; if (cent.currentState.eType == 1) { ResetPlayerEntity(cent); } }
/* =============== CG_ResetPlayerEntity A player just came into view or teleported, so reset all animation info =============== */ void ResetPlayerEntity(centity_t cent) { cent.errorTime = -99999; // guarantee no error decay added cent.extrapolated = false; //ClearLerpFrame(cgs.clientinfo[cent.currentState.clientNum], cent.pe Common.Instance.EvaluateTrajectory(cent.currentState.pos, cg.time, out cent.lerpOrigin); Common.Instance.EvaluateTrajectory(cent.currentState.apos, cg.time, out cent.lerpAngles); cent.rawOrigin = cent.lerpOrigin; cent.rawAngles = cent.lerpAngles; // Todo: Move torse & legs }
/* ================= CG_Init Called after every level change or subsystem restart Will perform callbacks to make the loading info screen update. ================= */ public void Init(int serverMessageNum, int serverCommandSequence, int clientNum) { // clear everything cgs = new cgs_t(); cgs.clientinfo = new clientInfo_t[64]; cg = new cg_t(); Entities = new centity_t[1024]; for (int i = 0; i < 1024; i++) { Entities[i] = new centity_t(); } cg.clientNum = clientNum; cgs.processedSnapshotNum = serverMessageNum; cgs.serverCommandSequence = serverCommandSequence; RegisterCVars(); InitConsoleCommands(); // get the gamestate from the client system cgs.gameState = Client.Instance.cl.gamestate; string s = cgs.gameState.data[(int)ConfigString.CS_LEVEL_START_TIME]; cgs.levelStartTime = int.Parse(s); ParseServerInfo(); // load the new map LoadString("Collision map"); ClipMap.Instance.LoadMap(cgs.mapname, true); cg.loading = true; // force players to load instead of defer <- ?? LoadString("Graphics"); RegisterGraphics(); LoadString("Clients"); RegisterClients(); cg.loading = false; // future players will be deferred //InitLocalEntities(); // Make sure we have update values (scores) SetConfigValues(); LoadString(""); }