diff options
Diffstat (limited to 'src/jake2/game/GameBase.java')
-rw-r--r-- | src/jake2/game/GameBase.java | 1364 |
1 files changed, 693 insertions, 671 deletions
diff --git a/src/jake2/game/GameBase.java b/src/jake2/game/GameBase.java index f71ba76..f9b83de 100644 --- a/src/jake2/game/GameBase.java +++ b/src/jake2/game/GameBase.java @@ -1,26 +1,25 @@ /* -Copyright (C) 1997-2001 Id Software, Inc. + 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 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. + 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. + 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. + 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. -*/ + */ // Created on 30.11.2003 by RST. -// $Id: GameBase.java,v 1.7 2004-09-10 19:02:54 salomo Exp $ - +// $Id: GameBase.java,v 1.8 2004-09-22 19:22:05 salomo Exp $ /** Father of all GameObjects. */ package jake2.game; @@ -33,660 +32,683 @@ import jake2.qcommon.Com; import jake2.server.*; import jake2.util.*; -public class GameBase extends Globals { - public static cplane_t dummyplane= new cplane_t(); - public static game_locals_t game= new game_locals_t(); - public static level_locals_t level= new level_locals_t(); - public static game_import_t gi= new game_import_t(); - public static spawn_temp_t st= new spawn_temp_t(); - - public static int sm_meat_index; - public static int snd_fry; - public static int meansOfDeath; - public static int num_edicts; - - public static edict_t g_edicts[]= new edict_t[MAX_EDICTS]; - static { - for (int n= 0; n < MAX_EDICTS; n++) - g_edicts[n]= new edict_t(n); - } - - public static cvar_t deathmatch= new cvar_t(); - public static cvar_t coop= new cvar_t(); - public static cvar_t dmflags= new cvar_t(); - public static cvar_t skill; // = new cvar_t(); - public static cvar_t fraglimit= new cvar_t(); - public static cvar_t timelimit= new cvar_t(); - public static cvar_t password= new cvar_t(); - public static cvar_t spectator_password= new cvar_t(); - public static cvar_t needpass= new cvar_t(); - public static cvar_t maxclients= new cvar_t(); - public static cvar_t maxspectators= new cvar_t(); - public static cvar_t maxentities= new cvar_t(); - public static cvar_t g_select_empty= new cvar_t(); - public static cvar_t dedicated= new cvar_t(); - - public static cvar_t filterban= new cvar_t(); - - public static cvar_t sv_maxvelocity= new cvar_t(); - public static cvar_t sv_gravity= new cvar_t(); - - public static cvar_t sv_rollspeed= new cvar_t(); - public static cvar_t sv_rollangle= new cvar_t(); - public static cvar_t gun_x= new cvar_t(); - public static cvar_t gun_y= new cvar_t(); - public static cvar_t gun_z= new cvar_t(); - - public static cvar_t run_pitch= new cvar_t(); - public static cvar_t run_roll= new cvar_t(); - public static cvar_t bob_up= new cvar_t(); - public static cvar_t bob_pitch= new cvar_t(); - public static cvar_t bob_roll= new cvar_t(); - - public static cvar_t sv_cheats= new cvar_t(); - - public static cvar_t flood_msgs= new cvar_t(); - public static cvar_t flood_persecond= new cvar_t(); - public static cvar_t flood_waitdelay= new cvar_t(); - - public static cvar_t sv_maplist= new cvar_t(); - - public final static float STOP_EPSILON= 0.1f; - - /** - * Slide off of the impacting object - * returns the blocked flags (1 = floor, 2 = step / wall). - */ - public static int ClipVelocity(float[] in, float[] normal, float[] out, float overbounce) { - float backoff; - float change; - int i, blocked; - - blocked= 0; - if (normal[2] > 0) - blocked |= 1; // floor - if (normal[2] == 0.0f) - blocked |= 2; // step - - backoff= Math3D.DotProduct(in, normal) * overbounce; - - for (i= 0; i < 3; i++) { - change= normal[i] * backoff; - out[i]= in[i] - change; - if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON) - out[i]= 0; - } - - return blocked; - } - - /** - 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; - - /* - ============= - G_Find - - Searches all active entities for the next one that holds - the matching string at fieldofs (use the FOFS() macro) in the structure. - - Searches beginning at the edict after from, or the beginning if null - null will be returned if the end of the list is reached. - - ============= - */ - - /** - * Finds an edict. - * Call with null as from parameter to search from array beginning. - */ - - public static EdictIterator G_Find(EdictIterator from, EdictFindFilter eff, String s) { - - if (from == null) - from= new EdictIterator(0); - else - from.i++; - - for (; from.i < num_edicts; from.i++) { - from.o= g_edicts[from.i]; - if (from.o.classname == null) { - Com.Printf("edict with classname = null" + from.o.index); - } - - if (!from.o.inuse) - continue; - - if (eff.matches(from.o, s)) - return from; - } - - return null; - } - - // comfort version (rst) - public static edict_t G_FindEdict(EdictIterator from, EdictFindFilter eff, String s) { - EdictIterator ei= G_Find(from, eff, s); - if (ei == null) - return null; - else - return ei.o; - } - - /** - * Returns entities that have origins within a spherical area. - */ - public static EdictIterator findradius(EdictIterator from, float[] org, float rad) { - float[] eorg= { 0, 0, 0 }; - int j; - - if (from == null) - from= new EdictIterator(0); - else - from.i++; - - for (; from.i < num_edicts; from.i++) { - from.o= g_edicts[from.i]; - if (!from.o.inuse) - continue; - - if (from.o.solid == SOLID_NOT) - continue; - - for (j= 0; j < 3; j++) - eorg[j]= org[j] - (from.o.s.origin[j] + (from.o.mins[j] + from.o.maxs[j]) * 0.5f); - - if (Math3D.VectorLength(eorg) > rad) - continue; - return from; - } - - return null; - } - - /** - * Searches all active entities for the next one that holds - * the matching string at fieldofs (use the FOFS() macro) in the structure. - * - * Searches beginning at the edict after from, or the beginning if null - * null will be returned if the end of the list is reached. - */ - - public static int MAXCHOICES= 8; - - public static edict_t G_PickTarget(String targetname) { - int num_choices= 0; - edict_t choice[]= new edict_t[MAXCHOICES]; - - if (targetname == null) { - gi.dprintf("G_PickTarget called with null targetname\n"); - return null; - } - - EdictIterator es= null; - - while ((es= G_Find(es, findByTarget, targetname)) != null) { - choice[num_choices++]= es.o; - if (num_choices == MAXCHOICES) - break; - } - - if (num_choices == 0) { - gi.dprintf("G_PickTarget: target " + targetname + " not found\n"); - return null; - } - - return choice[Lib.rand() % num_choices]; - } - - public static float[] VEC_UP= { 0, -1, 0 }; - public static float[] MOVEDIR_UP= { 0, 0, 1 }; - public static float[] VEC_DOWN= { 0, -2, 0 }; - public static float[] MOVEDIR_DOWN= { 0, 0, -1 }; - - public static void G_SetMovedir(float[] angles, float[] movedir) { - if (Math3D.VectorCompare(angles, VEC_UP) != 0) { - Math3D.VectorCopy(MOVEDIR_UP, movedir); - } - else if (Math3D.VectorCompare(angles, VEC_DOWN) != 0) { - Math3D.VectorCopy(MOVEDIR_DOWN, movedir); - } - else { - Math3D.AngleVectors(angles, movedir, null, null); - } - - Math3D.VectorClear(angles); - } - - public static String G_CopyString(String in) { - return new String(in); - } - - /* - ============ - G_TouchTriggers - - ============ - */ - - static edict_t touch[]= new edict_t[MAX_EDICTS]; - public static void G_TouchTriggers(edict_t ent) { - int i, num; - edict_t hit; - - - // dead things don't activate triggers! - if ((ent.client != null || (ent.svflags & SVF_MONSTER) != 0) && (ent.health <= 0)) - return; - - num= gi.BoxEdicts(ent.absmin, ent.absmax, touch, MAX_EDICTS, AREA_TRIGGERS); - - // be careful, it is possible to have an entity in this - // list removed before we get to it (killtriggered) - for (i= 0; i < num; i++) { - hit= touch[i]; - - if (!hit.inuse) - continue; - - if (hit.touch == null) - continue; - - //rst: just for debugging player triggers - //if (ent.index == 1) - //Com.Printf("trigger:" + hit.classname + "(" + hit.index + ")\n"); - - hit.touch.touch(hit, ent, GameBase.dummyplane, null); - } - } - - public static pushed_t pushed[]= new pushed_t[MAX_EDICTS]; - static { - for (int n= 0; n < MAX_EDICTS; n++) - pushed[n]= new pushed_t(); - } - - public static int pushed_p; - - public static edict_t obstacle; - - /* - ============= - M_CheckBottom - - Returns false if any part of the bottom of the entity is off an edge that - is not a staircase. - - ============= - */ - public static int c_yes, c_no; - - public static int STEPSIZE= 18; - - // ============================================================================ - /* - ================ - G_RunEntity - - ================ - */ - public static void G_RunEntity(edict_t ent) { - - if (ent.prethink != null) - ent.prethink.think(ent); - - switch ((int) ent.movetype) { - case MOVETYPE_PUSH : - case MOVETYPE_STOP : - SV.SV_Physics_Pusher(ent); - break; - case MOVETYPE_NONE : - SV.SV_Physics_None(ent); - break; - case MOVETYPE_NOCLIP : - SV.SV_Physics_Noclip(ent); - break; - case MOVETYPE_STEP : - SV.SV_Physics_Step(ent); - break; - case MOVETYPE_TOSS : - case MOVETYPE_BOUNCE : - case MOVETYPE_FLY : - case MOVETYPE_FLYMISSILE : - SV.SV_Physics_Toss(ent); - break; - default : - gi.error("SV_Physics: bad movetype " + (int) ent.movetype); - } - } - - /* - ================ - SV_NewChaseDir - - ================ - */ - public static int DI_NODIR= -1; - - public static void ClearBounds(float[] mins, float[] maxs) { - mins[0]= mins[1]= mins[2]= 99999; - maxs[0]= maxs[1]= maxs[2]= -99999; - } - - public static void AddPointToBounds(float[] v, float[] mins, float[] maxs) { - int i; - float val; - - for (i= 0; i < 3; i++) { - val= v[i]; - if (val < mins[i]) - mins[i]= val; - if (val > maxs[i]) - maxs[i]= val; - } - } - - public static EdictFindFilter findByTarget= new EdictFindFilter() { - public boolean matches(edict_t e, String s) { - if (e.targetname == null) - return false; - return e.targetname.equalsIgnoreCase(s); - } - }; - - public static EdictFindFilter findByClass= new EdictFindFilter() { - public boolean matches(edict_t e, String s) { - return e.classname.equalsIgnoreCase(s); - } - }; - - //=================================================================== - - public static void ShutdownGame() { - gi.dprintf("==== ShutdownGame ====\n"); - } - - //====================================================================== - - /* - ================= - ClientEndServerFrames - ================= - */ - public static void ClientEndServerFrames() { - int i; - edict_t ent; - - // calc the player views now that all pushing - // and damage has been added - for (i= 0; i < maxclients.value; i++) { - ent= g_edicts[1 + i]; - if (!ent.inuse || null == ent.client) - continue; - Game.ClientEndServerFrame(ent); - } - - } - - /* - ================= - CreateTargetChangeLevel - - Returns the created target changelevel - ================= - */ - public static edict_t CreateTargetChangeLevel(String map) { - edict_t ent; - - ent= Game.G_Spawn(); - ent.classname= "target_changelevel"; - level.nextmap= map; - ent.map= level.nextmap; - return ent; - } - - /* - ================= - EndDMLevel - - The timelimit or fraglimit has been exceeded - ================= - */ - public static void EndDMLevel() { - edict_t ent; - //char * s, * t, * f; - //static const char * seps = " ,\n\r"; - String s, t, f; - String seps= " ,\n\r"; - - // stay on same level flag - if (((int) dmflags.value & DF_SAME_LEVEL) != 0) { - Game.BeginIntermission(CreateTargetChangeLevel(level.mapname)); - return; - } - - // see if it's in the map list - if (sv_maplist.string.length() > 0) { - s= sv_maplist.string; - f= null; - StringTokenizer tk= new StringTokenizer(s, seps); - t= tk.nextToken(); - //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= tk.nextToken(); - if (t == null) { // end of list, go to first one - if (f == null) // there isn't a first one, same level - Game.BeginIntermission(CreateTargetChangeLevel(level.mapname)); - else - Game.BeginIntermission(CreateTargetChangeLevel(f)); - } - else - Game.BeginIntermission(CreateTargetChangeLevel(t)); - return; - } - if (f == null) - f= t; - t= tk.nextToken(); - } - - } - - if (level.nextmap.length() > 0) // go to a specific map - Game.BeginIntermission(CreateTargetChangeLevel(level.nextmap)); - else { // search for a changelevel - EdictIterator edit= null; - edit= G_Find(edit, findByClass, "target_changelevel"); - if (edit == null) { // the map designer didn't include a changelevel, - // so create a fake ent that goes back to the same level - Game.BeginIntermission(CreateTargetChangeLevel(level.mapname)); - return; - } - ent= edit.o; - Game.BeginIntermission(ent); - } - } - - /* - ================= - CheckNeedPass - ================= - */ - public static void CheckNeedPass() { - 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.length() > 0) && 0 != Q_stricmp(password.string, "none")) - need |= 1; - if ((spectator_password.string.length() > 0) && 0 != Q_stricmp(spectator_password.string, "none")) - need |= 2; - - gi.cvar_set("needpass", "" + need); - } - } - - /* - ================= - CheckDMRules - ================= - */ - public static void CheckDMRules() { - int i; - gclient_t cl; - - if (level.intermissiontime != 0) - return; - - if (0 == deathmatch.value) - return; - - if (timelimit.value != 0) { - if (level.time >= timelimit.value * 60) { - gi.bprintf(PRINT_HIGH, "Timelimit hit.\n"); - EndDMLevel(); - return; - } - } - - if (fraglimit.value != 0) { - for (i= 0; i < maxclients.value; 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 - ============= - */ - public static void ExitLevel() { - int i; - edict_t ent; - //char command[256]; - String command; - - command= "gamemap \"" + level.changemap + "\"\n"; - gi.AddCommandString(command); - level.changemap= null; - level.exitintermission= false; - level.intermissiontime= 0; - ClientEndServerFrames(); - - // clear some things before going to next level - for (i= 0; i < maxclients.value; 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; - } - - } - - /* - ================ - G_RunFrame - - Advances the world by 0.1 seconds - ================ - */ - public static void G_RunFrame() { - int i; - edict_t ent; - - level.framenum++; - level.time= level.framenum * FRAMETIME; - - // choose a client for monsters to target this frame - Game.AI_SetSightClient(); - - // exit intermissions - - if (level.exitintermission) { - ExitLevel(); - return; - } - - // - // treat each object in turn - // even the world gets a chance to think - // - - for (i= 0; i < num_edicts; i++) { - ent= g_edicts[i]; - if (!ent.inuse) - 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 != null) && (ent.groundentity.linkcount != ent.groundentity_linkcount)) { - ent.groundentity= null; - if (0 == (ent.flags & (FL_SWIM | FL_FLY)) && (ent.svflags & SVF_MONSTER) != 0) { - M.M_CheckGround(ent); - } - } - - if (i > 0 && i <= maxclients.value) { - Game.ClientBeginServerFrame(ent); - continue; - } - - G_RunEntity(ent); - } - - // 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(); - } - - /* - ================= - GetGameAPI - - Returns a pointer to the structure with all entry points - and global variables - ================= - */ - - public static void GetGameApi(game_import_t imp) { - gi= imp; - - gi.pointcontents= new pmove_t.PointContentsAdapter() { - public int pointcontents(float[] o) { - return SV_WORLD.SV_PointContents(o); - } - }; - } +public class GameBase { + public static cplane_t dummyplane = new cplane_t(); + + public static game_locals_t game = new game_locals_t(); + + public static level_locals_t level = new level_locals_t(); + + public static game_import_t gi = new game_import_t(); + + public static spawn_temp_t st = new spawn_temp_t(); + + public static int sm_meat_index; + + public static int snd_fry; + + public static int meansOfDeath; + + public static int num_edicts; + + public static edict_t g_edicts[] = new edict_t[Defines.MAX_EDICTS]; + static { + for (int n = 0; n < Defines.MAX_EDICTS; n++) + g_edicts[n] = new edict_t(n); + } + + public static cvar_t deathmatch = new cvar_t(); + + public static cvar_t coop = new cvar_t(); + + public static cvar_t dmflags = new cvar_t(); + + public static cvar_t skill; // = new cvar_t(); + + public static cvar_t fraglimit = new cvar_t(); + + public static cvar_t timelimit = new cvar_t(); + + public static cvar_t password = new cvar_t(); + + public static cvar_t spectator_password = new cvar_t(); + + public static cvar_t needpass = new cvar_t(); + + public static cvar_t maxclients = new cvar_t(); + + public static cvar_t maxspectators = new cvar_t(); + + public static cvar_t maxentities = new cvar_t(); + + public static cvar_t g_select_empty = new cvar_t(); + + public static cvar_t dedicated = new cvar_t(); + + public static cvar_t filterban = new cvar_t(); + + public static cvar_t sv_maxvelocity = new cvar_t(); + + public static cvar_t sv_gravity = new cvar_t(); + + public static cvar_t sv_rollspeed = new cvar_t(); + + public static cvar_t sv_rollangle = new cvar_t(); + + public static cvar_t gun_x = new cvar_t(); + + public static cvar_t gun_y = new cvar_t(); + + public static cvar_t gun_z = new cvar_t(); + + public static cvar_t run_pitch = new cvar_t(); + + public static cvar_t run_roll = new cvar_t(); + + public static cvar_t bob_up = new cvar_t(); + + public static cvar_t bob_pitch = new cvar_t(); + + public static cvar_t bob_roll = new cvar_t(); + + public static cvar_t sv_cheats = new cvar_t(); + + public static cvar_t flood_msgs = new cvar_t(); + + public static cvar_t flood_persecond = new cvar_t(); + + public static cvar_t flood_waitdelay = new cvar_t(); + + public static cvar_t sv_maplist = new cvar_t(); + + public final static float STOP_EPSILON = 0.1f; + + /** + * Slide off of the impacting object returns the blocked flags (1 = floor, 2 = + * step / wall). + */ + public static int ClipVelocity(float[] in, float[] normal, float[] out, + float overbounce) { + float backoff; + float change; + int i, blocked; + + blocked = 0; + if (normal[2] > 0) + blocked |= 1; // floor + if (normal[2] == 0.0f) + blocked |= 2; // step + + backoff = Math3D.DotProduct(in, normal) * overbounce; + + for (i = 0; i < 3; i++) { + change = normal[i] * backoff; + out[i] = in[i] - change; + if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON) + out[i] = 0; + } + + return blocked; + } + + /** + * 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; + + /* + * ============= G_Find + * + * Searches all active entities for the next one that holds the matching + * string at fieldofs (use the FOFS() macro) in the structure. + * + * Searches beginning at the edict after from, or the beginning if null null + * will be returned if the end of the list is reached. + * + * ============= + */ + + /** + * Finds an edict. Call with null as from parameter to search from array + * beginning. + */ + + public static EdictIterator G_Find(EdictIterator from, EdictFindFilter eff, + String s) { + + if (from == null) + from = new EdictIterator(0); + else + from.i++; + + for (; from.i < num_edicts; from.i++) { + from.o = g_edicts[from.i]; + if (from.o.classname == null) { + Com.Printf("edict with classname = null" + from.o.index); + } + + if (!from.o.inuse) + continue; + + if (eff.matches(from.o, s)) + return from; + } + + return null; + } + + // comfort version (rst) + public static edict_t G_FindEdict(EdictIterator from, EdictFindFilter eff, + String s) { + EdictIterator ei = G_Find(from, eff, s); + if (ei == null) + return null; + else + return ei.o; + } + + /** + * Returns entities that have origins within a spherical area. + */ + public static EdictIterator findradius(EdictIterator from, float[] org, + float rad) { + float[] eorg = { 0, 0, 0 }; + int j; + + if (from == null) + from = new EdictIterator(0); + else + from.i++; + + for (; from.i < num_edicts; from.i++) { + from.o = g_edicts[from.i]; + if (!from.o.inuse) + continue; + + if (from.o.solid == Defines.SOLID_NOT) + continue; + + for (j = 0; j < 3; j++) + eorg[j] = org[j] + - (from.o.s.origin[j] + (from.o.mins[j] + from.o.maxs[j]) * 0.5f); + + if (Math3D.VectorLength(eorg) > rad) + continue; + return from; + } + + return null; + } + + /** + * Searches all active entities for the next one that holds the matching + * string at fieldofs (use the FOFS() macro) in the structure. + * + * Searches beginning at the edict after from, or the beginning if null null + * will be returned if the end of the list is reached. + */ + + public static int MAXCHOICES = 8; + + public static edict_t G_PickTarget(String targetname) { + int num_choices = 0; + edict_t choice[] = new edict_t[MAXCHOICES]; + + if (targetname == null) { + gi.dprintf("G_PickTarget called with null targetname\n"); + return null; + } + + EdictIterator es = null; + + while ((es = G_Find(es, findByTarget, targetname)) != null) { + choice[num_choices++] = es.o; + if (num_choices == MAXCHOICES) + break; + } + + if (num_choices == 0) { + gi.dprintf("G_PickTarget: target " + targetname + " not found\n"); + return null; + } + + return choice[Lib.rand() % num_choices]; + } + + public static float[] VEC_UP = { 0, -1, 0 }; + + public static float[] MOVEDIR_UP = { 0, 0, 1 }; + + public static float[] VEC_DOWN = { 0, -2, 0 }; + + public static float[] MOVEDIR_DOWN = { 0, 0, -1 }; + + public static void G_SetMovedir(float[] angles, float[] movedir) { + if (Math3D.VectorCompare(angles, VEC_UP) != 0) { + Math3D.VectorCopy(MOVEDIR_UP, movedir); + } else if (Math3D.VectorCompare(angles, VEC_DOWN) != 0) { + Math3D.VectorCopy(MOVEDIR_DOWN, movedir); + } else { + Math3D.AngleVectors(angles, movedir, null, null); + } + + Math3D.VectorClear(angles); + } + + public static String G_CopyString(String in) { + return new String(in); + } + + /* + * ============ G_TouchTriggers + * + * ============ + */ + + static edict_t touch[] = new edict_t[Defines.MAX_EDICTS]; + + public static void G_TouchTriggers(edict_t ent) { + int i, num; + edict_t hit; + + // dead things don't activate triggers! + if ((ent.client != null || (ent.svflags & Defines.SVF_MONSTER) != 0) + && (ent.health <= 0)) + return; + + num = gi.BoxEdicts(ent.absmin, ent.absmax, touch, Defines.MAX_EDICTS, + Defines.AREA_TRIGGERS); + + // be careful, it is possible to have an entity in this + // list removed before we get to it (killtriggered) + for (i = 0; i < num; i++) { + hit = touch[i]; + + if (!hit.inuse) + continue; + + if (hit.touch == null) + continue; + + //rst: just for debugging player triggers + //if (ent.index == 1) + //Com.Printf("trigger:" + hit.classname + "(" + hit.index + ")\n"); + + hit.touch.touch(hit, ent, GameBase.dummyplane, null); + } + } + + public static pushed_t pushed[] = new pushed_t[Defines.MAX_EDICTS]; + static { + for (int n = 0; n < Defines.MAX_EDICTS; n++) + pushed[n] = new pushed_t(); + } + + public static int pushed_p; + + public static edict_t obstacle; + + /* + * ============= M_CheckBottom + * + * Returns false if any part of the bottom of the entity is off an edge that + * is not a staircase. + * + * ============= + */ + public static int c_yes, c_no; + + public static int STEPSIZE = 18; + + // ============================================================================ + /* + * ================ G_RunEntity + * + * ================ + */ + public static void G_RunEntity(edict_t ent) { + + if (ent.prethink != null) + ent.prethink.think(ent); + + switch ((int) ent.movetype) { + case Defines.MOVETYPE_PUSH: + case Defines.MOVETYPE_STOP: + SV.SV_Physics_Pusher(ent); + break; + case Defines.MOVETYPE_NONE: + SV.SV_Physics_None(ent); + break; + case Defines.MOVETYPE_NOCLIP: + SV.SV_Physics_Noclip(ent); + break; + case Defines.MOVETYPE_STEP: + SV.SV_Physics_Step(ent); + break; + case Defines.MOVETYPE_TOSS: + case Defines.MOVETYPE_BOUNCE: + case Defines.MOVETYPE_FLY: + case Defines.MOVETYPE_FLYMISSILE: + SV.SV_Physics_Toss(ent); + break; + default: + gi.error("SV_Physics: bad movetype " + (int) ent.movetype); + } + } + + /* + * ================ SV_NewChaseDir + * + * ================ + */ + public static int DI_NODIR = -1; + + public static void ClearBounds(float[] mins, float[] maxs) { + mins[0] = mins[1] = mins[2] = 99999; + maxs[0] = maxs[1] = maxs[2] = -99999; + } + + public static void AddPointToBounds(float[] v, float[] mins, float[] maxs) { + int i; + float val; + + for (i = 0; i < 3; i++) { + val = v[i]; + if (val < mins[i]) + mins[i] = val; + if (val > maxs[i]) + maxs[i] = val; + } + } + + public static EdictFindFilter findByTarget = new EdictFindFilter() { + public boolean matches(edict_t e, String s) { + if (e.targetname == null) + return false; + return e.targetname.equalsIgnoreCase(s); + } + }; + + public static EdictFindFilter findByClass = new EdictFindFilter() { + public boolean matches(edict_t e, String s) { + return e.classname.equalsIgnoreCase(s); + } + }; + + //=================================================================== + + public static void ShutdownGame() { + gi.dprintf("==== ShutdownGame ====\n"); + } + + //====================================================================== + + /* + * ================= ClientEndServerFrames ================= + */ + public static void ClientEndServerFrames() { + int i; + edict_t ent; + + // calc the player views now that all pushing + // and damage has been added + for (i = 0; i < maxclients.value; i++) { + ent = g_edicts[1 + i]; + if (!ent.inuse || null == ent.client) + continue; + PlayerView.ClientEndServerFrame(ent); + } + + } + + /* + * ================= CreateTargetChangeLevel + * + * Returns the created target changelevel ================= + */ + public static edict_t CreateTargetChangeLevel(String map) { + edict_t ent; + + ent = GameUtil.G_Spawn(); + ent.classname = "target_changelevel"; + level.nextmap = map; + ent.map = level.nextmap; + return ent; + } + + /* + * ================= EndDMLevel + * + * The timelimit or fraglimit has been exceeded ================= + */ + public static void EndDMLevel() { + edict_t ent; + //char * s, * t, * f; + //static const char * seps = " ,\n\r"; + String s, t, f; + String seps = " ,\n\r"; + + // stay on same level flag + if (((int) dmflags.value & Defines.DF_SAME_LEVEL) != 0) { + PlayerHud.BeginIntermission(CreateTargetChangeLevel(level.mapname)); + return; + } + + // see if it's in the map list + if (sv_maplist.string.length() > 0) { + s = sv_maplist.string; + f = null; + StringTokenizer tk = new StringTokenizer(s, seps); + t = tk.nextToken(); + //t = strtok(s, seps); + while (t != null) { + if (Lib.Q_stricmp(t, level.mapname) == 0) { + // it's in the list, go to the next one + t = tk.nextToken(); + if (t == null) { // end of list, go to first one + if (f == null) // there isn't a first one, same level + PlayerHud + .BeginIntermission(CreateTargetChangeLevel(level.mapname)); + else + PlayerHud + .BeginIntermission(CreateTargetChangeLevel(f)); + } else + PlayerHud.BeginIntermission(CreateTargetChangeLevel(t)); + return; + } + if (f == null) + f = t; + t = tk.nextToken(); + } + + } + + if (level.nextmap.length() > 0) // go to a specific map + PlayerHud.BeginIntermission(CreateTargetChangeLevel(level.nextmap)); + else { // search for a changelevel + EdictIterator edit = null; + edit = G_Find(edit, findByClass, "target_changelevel"); + if (edit == null) { // the map designer didn't include a + // changelevel, + // so create a fake ent that goes back to the same level + PlayerHud + .BeginIntermission(CreateTargetChangeLevel(level.mapname)); + return; + } + ent = edit.o; + PlayerHud.BeginIntermission(ent); + } + } + + /* + * ================= CheckNeedPass ================= + */ + public static void CheckNeedPass() { + 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.length() > 0) + && 0 != Lib.Q_stricmp(password.string, "none")) + need |= 1; + if ((spectator_password.string.length() > 0) + && 0 != Lib.Q_stricmp(spectator_password.string, "none")) + need |= 2; + + gi.cvar_set("needpass", "" + need); + } + } + + /* + * ================= CheckDMRules ================= + */ + public static void CheckDMRules() { + int i; + gclient_t cl; + + if (level.intermissiontime != 0) + return; + + if (0 == deathmatch.value) + return; + + if (timelimit.value != 0) { + if (level.time >= timelimit.value * 60) { + gi.bprintf(Defines.PRINT_HIGH, "Timelimit hit.\n"); + EndDMLevel(); + return; + } + } + + if (fraglimit.value != 0) { + for (i = 0; i < maxclients.value; i++) { + cl = game.clients[i]; + if (!g_edicts[i + 1].inuse) + continue; + + if (cl.resp.score >= fraglimit.value) { + gi.bprintf(Defines.PRINT_HIGH, "Fraglimit hit.\n"); + EndDMLevel(); + return; + } + } + } + } + + /* + * ============= ExitLevel ============= + */ + public static void ExitLevel() { + int i; + edict_t ent; + //char command[256]; + String command; + + command = "gamemap \"" + level.changemap + "\"\n"; + gi.AddCommandString(command); + level.changemap = null; + level.exitintermission = false; + level.intermissiontime = 0; + ClientEndServerFrames(); + + // clear some things before going to next level + for (i = 0; i < maxclients.value; 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; + } + + } + + /* + * ================ G_RunFrame + * + * Advances the world by 0.1 seconds ================ + */ + public static void G_RunFrame() { + int i; + edict_t ent; + + level.framenum++; + level.time = level.framenum * Defines.FRAMETIME; + + // choose a client for monsters to target this frame + GameUtil.AI_SetSightClient(); + + // exit intermissions + + if (level.exitintermission) { + ExitLevel(); + return; + } + + // + // treat each object in turn + // even the world gets a chance to think + // + + for (i = 0; i < num_edicts; i++) { + ent = g_edicts[i]; + if (!ent.inuse) + continue; + + level.current_entity = ent; + + Math3D.VectorCopy(ent.s.origin, ent.s.old_origin); + + // if the ground entity moved, make sure we are still on it + if ((ent.groundentity != null) + && (ent.groundentity.linkcount != ent.groundentity_linkcount)) { + ent.groundentity = null; + if (0 == (ent.flags & (Defines.FL_SWIM | Defines.FL_FLY)) + && (ent.svflags & Defines.SVF_MONSTER) != 0) { + M.M_CheckGround(ent); + } + } + + if (i > 0 && i <= maxclients.value) { + PlayerClient.ClientBeginServerFrame(ent); + continue; + } + + G_RunEntity(ent); + } + + // 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(); + } + + /* + * ================= GetGameAPI + * + * Returns a pointer to the structure with all entry points and global + * variables ================= + */ + + public static void GetGameApi(game_import_t imp) { + gi = imp; + + gi.pointcontents = new pmove_t.PointContentsAdapter() { + public int pointcontents(float[] o) { + return SV_WORLD.SV_PointContents(o); + } + }; + } }
\ No newline at end of file |