📄 sv.java
字号:
|| check.movetype == Defines.MOVETYPE_NONE || check.movetype == Defines.MOVETYPE_NOCLIP) continue; if (check.area.prev == null) continue; // not linked in anywhere // if the entity is standing on the pusher, it will definitely be // moved if (check.groundentity != pusher) { // see if the ent needs to be tested if (check.absmin[0] >= maxs[0] || check.absmin[1] >= maxs[1] || check.absmin[2] >= maxs[2] || check.absmax[0] <= mins[0] || check.absmax[1] <= mins[1] || check.absmax[2] <= mins[2]) continue; // see if the ent's bbox is inside the pusher's final position if (SV_TestEntityPosition(check) == null) continue; } if ((pusher.movetype == Defines.MOVETYPE_PUSH) || (check.groundentity == pusher)) { // move this entity GameBase.pushed[GameBase.pushed_p].ent = check; Math3D.VectorCopy(check.s.origin, GameBase.pushed[GameBase.pushed_p].origin); Math3D.VectorCopy(check.s.angles, GameBase.pushed[GameBase.pushed_p].angles); GameBase.pushed_p++; // try moving the contacted entity Math3D.VectorAdd(check.s.origin, move, check.s.origin); if (check.client != null) { // FIXME: doesn't rotate monsters? check.client.ps.pmove.delta_angles[Defines.YAW] += amove[Defines.YAW]; } // figure movement due to the pusher's amove Math3D.VectorSubtract(check.s.origin, pusher.s.origin, org); org2[0] = Math3D.DotProduct(org, forward); org2[1] = -Math3D.DotProduct(org, right); org2[2] = Math3D.DotProduct(org, up); Math3D.VectorSubtract(org2, org, move2); Math3D.VectorAdd(check.s.origin, move2, check.s.origin); // may have pushed them off an edge if (check.groundentity != pusher) check.groundentity = null; block = SV_TestEntityPosition(check); if (block == null) { // pushed ok GameBase.gi.linkentity(check); // impact? continue; } // if it is ok to leave in the old position, do it // this is only relevent for riding entities, not pushed // FIXME: this doesn't acount for rotation Math3D.VectorSubtract(check.s.origin, move, check.s.origin); block = SV_TestEntityPosition(check); if (block == null) { GameBase.pushed_p--; continue; } } // save off the obstacle so we can call the block function GameBase.obstacle = check; // move back any entities we already moved // go backwards, so if the same entity was pushed // twice, it goes back to the original position for (int ip = GameBase.pushed_p - 1; ip >= 0; ip--) { p = GameBase.pushed[ip]; Math3D.VectorCopy(p.origin, p.ent.s.origin); Math3D.VectorCopy(p.angles, p.ent.s.angles); if (p.ent.client != null) { p.ent.client.ps.pmove.delta_angles[Defines.YAW] = (short) p.deltayaw; } GameBase.gi.linkentity(p.ent); } return false; } // FIXME: is there a better way to handle this? // see if anything we moved has touched a trigger for (int ip = GameBase.pushed_p - 1; ip >= 0; ip--) GameBase.G_TouchTriggers(GameBase.pushed[ip].ent); return true; } /** * * Bmodel objects don't interact with each other, but push all box objects. */ public static void SV_Physics_Pusher(edict_t ent) { float[] move = { 0, 0, 0 }; float[] amove = { 0, 0, 0 }; edict_t part, mv; // if not a team captain, so movement will be handled elsewhere if ((ent.flags & Defines.FL_TEAMSLAVE) != 0) return; // make sure all team slaves can move before commiting // any moves or calling any think functions // if the move is blocked, all moved objects will be backed out // retry: GameBase.pushed_p = 0; for (part = ent; part != null; part = part.teamchain) { if (part.velocity[0] != 0 || part.velocity[1] != 0 || part.velocity[2] != 0 || part.avelocity[0] != 0 || part.avelocity[1] != 0 || part.avelocity[2] != 0) { // object // is // moving Math3D.VectorScale(part.velocity, Defines.FRAMETIME, move); Math3D.VectorScale(part.avelocity, Defines.FRAMETIME, amove); if (!SV_Push(part, move, amove)) break; // move was blocked } } if (GameBase.pushed_p > Defines.MAX_EDICTS) SV_GAME.PF_error(Defines.ERR_FATAL, "pushed_p > &pushed[MAX_EDICTS], memory corrupted"); if (part != null) { // the move failed, bump all nextthink times and back out moves for (mv = ent; mv != null; mv = mv.teamchain) { if (mv.nextthink > 0) mv.nextthink += Defines.FRAMETIME; } // if the pusher has a "blocked" function, call it // otherwise, just stay in place until the obstacle is gone if (part.blocked != null) part.blocked.blocked(part, GameBase.obstacle); } else { // the move succeeded, so call all think functions for (part = ent; part != null; part = part.teamchain) { SV_RunThink(part); } } } /** * Non moving objects can only think. */ public static void SV_Physics_None(edict_t ent) { // regular thinking SV_RunThink(ent); } /** * A moving object that doesn't obey physics. */ public static void SV_Physics_Noclip(edict_t ent) { // regular thinking if (!SV_RunThink(ent)) return; Math3D.VectorMA(ent.s.angles, Defines.FRAMETIME, ent.avelocity, ent.s.angles); Math3D.VectorMA(ent.s.origin, Defines.FRAMETIME, ent.velocity, ent.s.origin); GameBase.gi.linkentity(ent); } /** * Toss, bounce, and fly movement. When onground, do nothing. */ public static void SV_Physics_Toss(edict_t ent) { trace_t trace; float[] move = { 0, 0, 0 }; float backoff; edict_t slave; boolean wasinwater; boolean isinwater; float[] old_origin = { 0, 0, 0 }; // regular thinking SV_RunThink(ent); // if not a team captain, so movement will be handled elsewhere if ((ent.flags & Defines.FL_TEAMSLAVE) != 0) return; if (ent.velocity[2] > 0) ent.groundentity = null; // check for the groundentity going away if (ent.groundentity != null) if (!ent.groundentity.inuse) ent.groundentity = null; // if onground, return without moving if (ent.groundentity != null) return; Math3D.VectorCopy(ent.s.origin, old_origin); SV_CheckVelocity(ent); // add gravity if (ent.movetype != Defines.MOVETYPE_FLY && ent.movetype != Defines.MOVETYPE_FLYMISSILE) SV_AddGravity(ent); // move angles Math3D.VectorMA(ent.s.angles, Defines.FRAMETIME, ent.avelocity, ent.s.angles); // move origin Math3D.VectorScale(ent.velocity, Defines.FRAMETIME, move); trace = SV_PushEntity(ent, move); if (!ent.inuse) return; if (trace.fraction < 1) { if (ent.movetype == Defines.MOVETYPE_BOUNCE) backoff = 1.5f; else backoff = 1; GameBase.ClipVelocity(ent.velocity, trace.plane.normal, ent.velocity, backoff); // stop if on ground if (trace.plane.normal[2] > 0.7) { if (ent.velocity[2] < 60 || ent.movetype != Defines.MOVETYPE_BOUNCE) { ent.groundentity = trace.ent; ent.groundentity_linkcount = trace.ent.linkcount; Math3D.VectorCopy(Globals.vec3_origin, ent.velocity); Math3D.VectorCopy(Globals.vec3_origin, ent.avelocity); } } // if (ent.touch) // ent.touch (ent, trace.ent, &trace.plane, trace.surface); } // check for water transition wasinwater = (ent.watertype & Defines.MASK_WATER) != 0; ent.watertype = GameBase.gi.pointcontents.pointcontents(ent.s.origin); isinwater = (ent.watertype & Defines.MASK_WATER) != 0; if (isinwater) ent.waterlevel = 1; else ent.waterlevel = 0; if (!wasinwater && isinwater) GameBase.gi.positioned_sound(old_origin, ent, Defines.CHAN_AUTO, GameBase.gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0); else if (wasinwater && !isinwater) GameBase.gi.positioned_sound(ent.s.origin, ent, Defines.CHAN_AUTO, GameBase.gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0); // move teamslaves for (slave = ent.teamchain; slave != null; slave = slave.teamchain) { Math3D.VectorCopy(ent.s.origin, slave.s.origin); GameBase.gi.linkentity(slave); } } // FIXME: hacked in for E3 demo public static void SV_AddRotationalFriction(edict_t ent) { int n; float adjustment; Math3D.VectorMA(ent.s.angles, Defines.FRAMETIME, ent.avelocity, ent.s.angles); adjustment = Defines.FRAMETIME * Defines.sv_stopspeed * Defines.sv_friction; for (n = 0; n < 3; n++) { if (ent.avelocity[n] > 0) { ent.avelocity[n] -= adjustment; if (ent.avelocity[n] < 0) ent.avelocity[n] = 0; } else { ent.avelocity[n] += adjustment; if (ent.avelocity[n] > 0) ent.avelocity[n] = 0; } } } /** * Monsters freefall when they don't have a ground entity, otherwise all * movement is done with discrete steps. * * This is also used for objects that have become still on the ground, but * will fall if the floor is pulled out from under them. FIXME: is this * true? */ public static void SV_Physics_Step(edict_t ent) { boolean wasonground; boolean hitsound = false; float vel[]; float speed, newspeed, control; float friction; edict_t groundentity; int mask; // airborn monsters should always check for ground if (ent.groundentity == null) M.M_CheckGround(ent); groundentity = ent.groundentity; SV_CheckVelocity(ent); if (groundentity != null) wasonground = true; else wasonground = false; if (ent.avelocity[0] != 0 || ent.avelocity[1] != 0 || ent.avelocity[2] != 0) SV_AddRotationalFriction(ent); // add gravity except: // flying monsters // swimming monsters who are in the water if (!wasonground) if (0 == (ent.flags & Defines.FL_FLY)) if (!((ent.flags & Defines.FL_SWIM) != 0 && (ent.waterlevel > 2))) { if (ent.velocity[2] < GameBase.sv_gravity.value * -0.1) hitsound = true; if (ent.waterlevel == 0) SV_AddGravity(ent); } // friction for flying monsters that have been given vertical velocity if ((ent.flags & Defines.FL_FLY) != 0 && (ent.velocity[2] != 0)) { speed = Math.abs(ent.velocity[2]); control = speed < Defines.sv_stopspeed ? Defines.sv_stopspeed : speed; friction = Defines.sv_friction / 3; newspeed = speed - (Defines.FRAMETIME * control * friction); if (newspeed < 0) newspeed = 0; newspeed /= speed; ent.velocity[2] *= newspeed; } // friction for flying monsters that have been given vertical velocity if ((ent.flags & Defines.FL_SWIM) != 0 && (ent.velocity[2] != 0)) { speed = Math.abs(ent.velocity[2]); control = speed < Defines.sv_stopspeed ? Defines.sv_stopspeed : speed; newspeed = speed - (Defines.FRAMETIME * control * Defines.sv_waterfriction * ent.waterlevel); if (newspeed < 0) newspeed = 0; newspeed /= speed; ent.velocity[2] *= newspeed; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -