📄 sv.java
字号:
/* * SV.java * Copyright (C) 2003 * * $Id: SV.java,v 1.12 2006/01/21 21:53:32 salomo Exp $ *//* Copyright (C) 1997-2001 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */package jake2.server;import jake2.Defines;import jake2.Globals;import jake2.client.M;import jake2.game.GameBase;import jake2.game.edict_t;import jake2.game.pushed_t;import jake2.game.trace_t;import jake2.qcommon.Com;import jake2.util.Lib;import jake2.util.Math3D;/** * SV */public final class SV { /////////////////////////////////////// public static edict_t[] SV_TestEntityPosition(edict_t ent) { trace_t trace; int mask; if (ent.clipmask != 0) mask = ent.clipmask; else mask = Defines.MASK_SOLID; trace = GameBase.gi.trace(ent.s.origin, ent.mins, ent.maxs, ent.s.origin, ent, mask); if (trace.startsolid) return GameBase.g_edicts; return null; } /////////////////////////////////////// public static void SV_CheckVelocity(edict_t ent) { int i; // // bound velocity // for (i = 0; i < 3; i++) { if (ent.velocity[i] > GameBase.sv_maxvelocity.value) ent.velocity[i] = GameBase.sv_maxvelocity.value; else if (ent.velocity[i] < -GameBase.sv_maxvelocity.value) ent.velocity[i] = -GameBase.sv_maxvelocity.value; } } /** * Runs thinking code for this frame if necessary. */ public static boolean SV_RunThink(edict_t ent) { float thinktime; thinktime = ent.nextthink; if (thinktime <= 0) return true; if (thinktime > GameBase.level.time + 0.001) return true; ent.nextthink = 0; if (ent.think == null) Com.Error(Defines.ERR_FATAL, "NULL ent.think"); ent.think.think(ent); return false; } /** * Two entities have touched, so run their touch functions. */ public static void SV_Impact(edict_t e1, trace_t trace) { edict_t e2; e2 = trace.ent; if (e1.touch != null && e1.solid != Defines.SOLID_NOT) e1.touch.touch(e1, e2, trace.plane, trace.surface); if (e2.touch != null && e2.solid != Defines.SOLID_NOT) e2.touch.touch(e2, e1, GameBase.dummyplane, null); } /** * SV_FlyMove * * The basic solid body movement clip that slides along multiple planes * Returns the clipflags if the velocity was modified (hit something solid) * 1 = floor 2 = wall / step 4 = dead stop */ public final static int MAX_CLIP_PLANES = 5; public static int SV_FlyMove(edict_t ent, float time, int mask) { edict_t hit; int bumpcount, numbumps; float[] dir = { 0.0f, 0.0f, 0.0f }; float d; int numplanes; float[][] planes = new float[MAX_CLIP_PLANES][3]; float[] primal_velocity = { 0.0f, 0.0f, 0.0f }; float[] original_velocity = { 0.0f, 0.0f, 0.0f }; float[] new_velocity = { 0.0f, 0.0f, 0.0f }; int i, j; trace_t trace; float[] end = { 0.0f, 0.0f, 0.0f }; float time_left; int blocked; numbumps = 4; blocked = 0; Math3D.VectorCopy(ent.velocity, original_velocity); Math3D.VectorCopy(ent.velocity, primal_velocity); numplanes = 0; time_left = time; ent.groundentity = null; for (bumpcount = 0; bumpcount < numbumps; bumpcount++) { for (i = 0; i < 3; i++) end[i] = ent.s.origin[i] + time_left * ent.velocity[i]; trace = GameBase.gi.trace(ent.s.origin, ent.mins, ent.maxs, end, ent, mask); if (trace.allsolid) { // entity is trapped in another solid Math3D.VectorCopy(Globals.vec3_origin, ent.velocity); return 3; } if (trace.fraction > 0) { // actually covered some distance Math3D.VectorCopy(trace.endpos, ent.s.origin); Math3D.VectorCopy(ent.velocity, original_velocity); numplanes = 0; } if (trace.fraction == 1) break; // moved the entire distance hit = trace.ent; if (trace.plane.normal[2] > 0.7) { blocked |= 1; // floor if (hit.solid == Defines.SOLID_BSP) { ent.groundentity = hit; ent.groundentity_linkcount = hit.linkcount; } } if (trace.plane.normal[2] == 0.0f) { blocked |= 2; // step } // // run the impact function // SV_Impact(ent, trace); if (!ent.inuse) break; // removed by the impact function time_left -= time_left * trace.fraction; // cliped to another plane if (numplanes >= MAX_CLIP_PLANES) { // this shouldn't // really happen Math3D.VectorCopy(Globals.vec3_origin, ent.velocity); return 3; } Math3D.VectorCopy(trace.plane.normal, planes[numplanes]); numplanes++; // // modify original_velocity so it parallels all of the clip planes // for (i = 0; i < numplanes; i++) { GameBase.ClipVelocity(original_velocity, planes[i], new_velocity, 1); for (j = 0; j < numplanes; j++) if ((j != i) && !Math3D.VectorEquals(planes[i], planes[j])) { if (Math3D.DotProduct(new_velocity, planes[j]) < 0) break; // not ok } if (j == numplanes) break; } if (i != numplanes) { // go along this plane Math3D.VectorCopy(new_velocity, ent.velocity); } else { // go along the crease if (numplanes != 2) { // gi.dprintf ("clip velocity, numplanes == // %i\n",numplanes); Math3D.VectorCopy(Globals.vec3_origin, ent.velocity); return 7; } Math3D.CrossProduct(planes[0], planes[1], dir); d = Math3D.DotProduct(dir, ent.velocity); Math3D.VectorScale(dir, d, ent.velocity); } // // if original velocity is against the original velocity, stop dead // to avoid tiny occilations in sloping corners // if (Math3D.DotProduct(ent.velocity, primal_velocity) <= 0) { Math3D.VectorCopy(Globals.vec3_origin, ent.velocity); return blocked; } } return blocked; } /** * SV_AddGravity. */ public static void SV_AddGravity(edict_t ent) { ent.velocity[2] -= ent.gravity * GameBase.sv_gravity.value * Defines.FRAMETIME; } /** * Does not change the entities velocity at all */ public static trace_t SV_PushEntity(edict_t ent, float[] push) { trace_t trace; float[] start = { 0, 0, 0 }; float[] end = { 0, 0, 0 }; int mask; Math3D.VectorCopy(ent.s.origin, start); Math3D.VectorAdd(start, push, end); // FIXME: test this // a goto statement was replaced. boolean retry = false; do { if (ent.clipmask != 0) mask = ent.clipmask; else mask = Defines.MASK_SOLID; trace = GameBase.gi .trace(start, ent.mins, ent.maxs, end, ent, mask); Math3D.VectorCopy(trace.endpos, ent.s.origin); GameBase.gi.linkentity(ent); retry = false; if (trace.fraction != 1.0) { SV_Impact(ent, trace); // if the pushed entity went away and the pusher is still there if (!trace.ent.inuse && ent.inuse) { // move the pusher back and try again Math3D.VectorCopy(start, ent.s.origin); GameBase.gi.linkentity(ent); //goto retry; retry = true; } } } while (retry); if (ent.inuse) GameBase.G_TouchTriggers(ent); return trace; } /** * Objects need to be moved back on a failed push, otherwise riders would * continue to slide. */ public static boolean SV_Push(edict_t pusher, float[] move, float[] amove) { int i, e; edict_t check, block[]; float[] mins = { 0, 0, 0 }; float[] maxs = { 0, 0, 0 }; pushed_t p; float[] org = { 0, 0, 0 }; float[] org2 = { 0, 0, 0 }; float[] move2 = { 0, 0, 0 }; float[] forward = { 0, 0, 0 }; float[] right = { 0, 0, 0 }; float[] up = { 0, 0, 0 }; // clamp the move to 1/8 units, so the position will // be accurate for client side prediction for (i = 0; i < 3; i++) { float temp; temp = move[i] * 8.0f; if (temp > 0.0) temp += 0.5; else temp -= 0.5; move[i] = 0.125f * (int) temp; } // find the bounding box for (i = 0; i < 3; i++) { mins[i] = pusher.absmin[i] + move[i]; maxs[i] = pusher.absmax[i] + move[i]; } // we need this for pushing things later Math3D.VectorSubtract(Globals.vec3_origin, amove, org); Math3D.AngleVectors(org, forward, right, up); // save the pusher's original position GameBase.pushed[GameBase.pushed_p].ent = pusher; Math3D.VectorCopy(pusher.s.origin, GameBase.pushed[GameBase.pushed_p].origin); Math3D.VectorCopy(pusher.s.angles, GameBase.pushed[GameBase.pushed_p].angles); if (pusher.client != null) GameBase.pushed[GameBase.pushed_p].deltayaw = pusher.client.ps.pmove.delta_angles[Defines.YAW]; GameBase.pushed_p++; // move the pusher to it's final position Math3D.VectorAdd(pusher.s.origin, move, pusher.s.origin); Math3D.VectorAdd(pusher.s.angles, amove, pusher.s.angles); GameBase.gi.linkentity(pusher); // see if any solid entities are inside the final position //check= g_edicts + 1; for (e = 1; e < GameBase.num_edicts; e++) { check = GameBase.g_edicts[e]; if (!check.inuse) continue; if (check.movetype == Defines.MOVETYPE_PUSH || check.movetype == Defines.MOVETYPE_STOP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -