📄 gamefunc.java
字号:
/* * 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. * */// Created on 18.11.2003 by RST.// $Id: GameFunc.java,v 1.9 2006/01/21 21:53:32 salomo Exp $package jake2.game;import jake2.Defines;import jake2.Globals;import jake2.util.Lib;import jake2.util.Math3D;public class GameFunc { static void Move_Calc(edict_t ent, float[] dest, EntThinkAdapter func) { Math3D.VectorClear(ent.velocity); Math3D.VectorSubtract(dest, ent.s.origin, ent.moveinfo.dir); ent.moveinfo.remaining_distance = Math3D .VectorNormalize(ent.moveinfo.dir); ent.moveinfo.endfunc = func; if (ent.moveinfo.speed == ent.moveinfo.accel && ent.moveinfo.speed == ent.moveinfo.decel) { if (GameBase.level.current_entity == ((ent.flags & Defines.FL_TEAMSLAVE) != 0 ? ent.teammaster : ent)) { Move_Begin.think(ent); } else { ent.nextthink = GameBase.level.time + Defines.FRAMETIME; ent.think = Move_Begin; } } else { // accelerative ent.moveinfo.current_speed = 0; ent.think = Think_AccelMove; ent.nextthink = GameBase.level.time + Defines.FRAMETIME; } } static void AngleMove_Calc(edict_t ent, EntThinkAdapter func) { Math3D.VectorClear(ent.avelocity); ent.moveinfo.endfunc = func; if (GameBase.level.current_entity == ((ent.flags & Defines.FL_TEAMSLAVE) != 0 ? ent.teammaster : ent)) { AngleMove_Begin.think(ent); } else { ent.nextthink = GameBase.level.time + Defines.FRAMETIME; ent.think = AngleMove_Begin; } } /** * Think_AccelMove * * The team has completed a frame of movement, so change the speed for the * next frame. */ static float AccelerationDistance(float target, float rate) { return target * ((target / rate) + 1) / 2; }; static void plat_CalcAcceleratedMove(moveinfo_t moveinfo) { float accel_dist; float decel_dist; moveinfo.move_speed = moveinfo.speed; if (moveinfo.remaining_distance < moveinfo.accel) { moveinfo.current_speed = moveinfo.remaining_distance; return; } accel_dist = AccelerationDistance(moveinfo.speed, moveinfo.accel); decel_dist = AccelerationDistance(moveinfo.speed, moveinfo.decel); if ((moveinfo.remaining_distance - accel_dist - decel_dist) < 0) { float f; f = (moveinfo.accel + moveinfo.decel) / (moveinfo.accel * moveinfo.decel); moveinfo.move_speed = (float) ((-2 + Math.sqrt(4 - 4 * f * (-2 * moveinfo.remaining_distance))) / (2 * f)); decel_dist = AccelerationDistance(moveinfo.move_speed, moveinfo.decel); } moveinfo.decel_distance = decel_dist; }; static void plat_Accelerate(moveinfo_t moveinfo) { // are we decelerating? if (moveinfo.remaining_distance <= moveinfo.decel_distance) { if (moveinfo.remaining_distance < moveinfo.decel_distance) { if (moveinfo.next_speed != 0) { moveinfo.current_speed = moveinfo.next_speed; moveinfo.next_speed = 0; return; } if (moveinfo.current_speed > moveinfo.decel) moveinfo.current_speed -= moveinfo.decel; } return; } // are we at full speed and need to start decelerating during this move? if (moveinfo.current_speed == moveinfo.move_speed) if ((moveinfo.remaining_distance - moveinfo.current_speed) < moveinfo.decel_distance) { float p1_distance; float p2_distance; float distance; p1_distance = moveinfo.remaining_distance - moveinfo.decel_distance; p2_distance = moveinfo.move_speed * (1.0f - (p1_distance / moveinfo.move_speed)); distance = p1_distance + p2_distance; moveinfo.current_speed = moveinfo.move_speed; moveinfo.next_speed = moveinfo.move_speed - moveinfo.decel * (p2_distance / distance); return; } // are we accelerating? if (moveinfo.current_speed < moveinfo.speed) { float old_speed; float p1_distance; float p1_speed; float p2_distance; float distance; old_speed = moveinfo.current_speed; // figure simple acceleration up to move_speed moveinfo.current_speed += moveinfo.accel; if (moveinfo.current_speed > moveinfo.speed) moveinfo.current_speed = moveinfo.speed; // are we accelerating throughout this entire move? if ((moveinfo.remaining_distance - moveinfo.current_speed) >= moveinfo.decel_distance) return; // during this move we will accelrate from current_speed to // move_speed // and cross over the decel_distance; figure the average speed for // the // entire move p1_distance = moveinfo.remaining_distance - moveinfo.decel_distance; p1_speed = (old_speed + moveinfo.move_speed) / 2.0f; p2_distance = moveinfo.move_speed * (1.0f - (p1_distance / p1_speed)); distance = p1_distance + p2_distance; moveinfo.current_speed = (p1_speed * (p1_distance / distance)) + (moveinfo.move_speed * (p2_distance / distance)); moveinfo.next_speed = moveinfo.move_speed - moveinfo.decel * (p2_distance / distance); return; } // we are at constant velocity (move_speed) return; }; static void plat_go_up(edict_t ent) { if (0 == (ent.flags & Defines.FL_TEAMSLAVE)) { if (ent.moveinfo.sound_start != 0) GameBase.gi.sound(ent, Defines.CHAN_NO_PHS_ADD + Defines.CHAN_VOICE, ent.moveinfo.sound_start, 1, Defines.ATTN_STATIC, 0); ent.s.sound = ent.moveinfo.sound_middle; } ent.moveinfo.state = STATE_UP; Move_Calc(ent, ent.moveinfo.start_origin, plat_hit_top); } static void plat_spawn_inside_trigger(edict_t ent) { edict_t trigger; float[] tmin = { 0, 0, 0 }, tmax = { 0, 0, 0 }; // // middle trigger // trigger = GameUtil.G_Spawn(); trigger.touch = Touch_Plat_Center; trigger.movetype = Defines.MOVETYPE_NONE; trigger.solid = Defines.SOLID_TRIGGER; trigger.enemy = ent; tmin[0] = ent.mins[0] + 25; tmin[1] = ent.mins[1] + 25; tmin[2] = ent.mins[2]; tmax[0] = ent.maxs[0] - 25; tmax[1] = ent.maxs[1] - 25; tmax[2] = ent.maxs[2] + 8; tmin[2] = tmax[2] - (ent.pos1[2] - ent.pos2[2] + GameBase.st.lip); if ((ent.spawnflags & PLAT_LOW_TRIGGER) != 0) tmax[2] = tmin[2] + 8; if (tmax[0] - tmin[0] <= 0) { tmin[0] = (ent.mins[0] + ent.maxs[0]) * 0.5f; tmax[0] = tmin[0] + 1; } if (tmax[1] - tmin[1] <= 0) { tmin[1] = (ent.mins[1] + ent.maxs[1]) * 0.5f; tmax[1] = tmin[1] + 1; } Math3D.VectorCopy(tmin, trigger.mins); Math3D.VectorCopy(tmax, trigger.maxs); GameBase.gi.linkentity(trigger); } /** * QUAKED func_plat (0 .5 .8) ? PLAT_LOW_TRIGGER speed default 150 * * Plats are always drawn in the extended position, so they will light * correctly. * * If the plat is the target of another trigger or button, it will start out * disabled in the extended position until it is trigger, when it will lower * and become a normal plat. * * "speed" overrides default 200. "accel" overrides default 500 "lip" * overrides default 8 pixel lip * * If the "height" key is set, that will determine the amount the plat * moves, instead of being implicitly determoveinfoned by the model's * height. * * Set "sounds" to one of the following: 1) base fast 2) chain slow */ static void SP_func_plat(edict_t ent) { Math3D.VectorClear(ent.s.angles); ent.solid = Defines.SOLID_BSP; ent.movetype = Defines.MOVETYPE_PUSH; GameBase.gi.setmodel(ent, ent.model); ent.blocked = plat_blocked; if (0 == ent.speed) ent.speed = 20; else ent.speed *= 0.1; if (ent.accel == 0) ent.accel = 5; else ent.accel *= 0.1; if (ent.decel == 0) ent.decel = 5; else ent.decel *= 0.1; if (ent.dmg == 0) ent.dmg = 2; if (GameBase.st.lip == 0) GameBase.st.lip = 8; // pos1 is the top position, pos2 is the bottom Math3D.VectorCopy(ent.s.origin, ent.pos1); Math3D.VectorCopy(ent.s.origin, ent.pos2); if (GameBase.st.height != 0) ent.pos2[2] -= GameBase.st.height; else ent.pos2[2] -= (ent.maxs[2] - ent.mins[2]) - GameBase.st.lip; ent.use = Use_Plat; plat_spawn_inside_trigger(ent); // the "start moving" trigger if (ent.targetname != null) { ent.moveinfo.state = STATE_UP; } else { Math3D.VectorCopy(ent.pos2, ent.s.origin); GameBase.gi.linkentity(ent); ent.moveinfo.state = STATE_BOTTOM; } ent.moveinfo.speed = ent.speed; ent.moveinfo.accel = ent.accel; ent.moveinfo.decel = ent.decel; ent.moveinfo.wait = ent.wait; Math3D.VectorCopy(ent.pos1, ent.moveinfo.start_origin); Math3D.VectorCopy(ent.s.angles, ent.moveinfo.start_angles); Math3D.VectorCopy(ent.pos2, ent.moveinfo.end_origin); Math3D.VectorCopy(ent.s.angles, ent.moveinfo.end_angles); ent.moveinfo.sound_start = GameBase.gi.soundindex("plats/pt1_strt.wav"); ent.moveinfo.sound_middle = GameBase.gi.soundindex("plats/pt1_mid.wav"); ent.moveinfo.sound_end = GameBase.gi.soundindex("plats/pt1_end.wav"); } /** * DOORS * * spawn a trigger surrounding the entire team unless it is already targeted * by another. * */ /** * QUAKED func_door (0 .5 .8) ? START_OPEN x CRUSHER NOMONSTER ANIMATED * TOGGLE ANIMATED_FAST TOGGLE wait in both the start and end states for a * trigger event. START_OPEN the door to moves to its destination when * spawned, and operate in reverse. It is used to temporarily or permanently * close off an area when triggered (not useful for touch or takedamage * doors). NOMONSTER monsters will not trigger this door * * "message" is printed when the door is touched if it is a trigger door and * it hasn't been fired yet "angle" determines the opening direction * "targetname" if set, no touch field will be spawned and a remote button * or trigger field activates the door. "health" if set, door must be shot * open "speed" movement speed (100 default) "wait" wait before returning (3 * default, -1 = never return) "lip" lip remaining at end of move (8 * default) "dmg" damage to inflict when blocked (2 default) "sounds" 1) * silent 2) light 3) medium 4) heavy */ static void door_use_areaportals(edict_t self, boolean open) { edict_t t = null; if (self.target == null) return; EdictIterator edit = null; while ((edit = GameBase .G_Find(edit, GameBase.findByTarget, self.target)) != null) { t = edit.o;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -