/** * Get the direction the door or button should move. * When the entity is spawned, the "angles" * indicates the direction the door should move, * but the format is a little bizarre, and the * value doesn't actually indicate the angles * for the entity, so we -have- to clear it, * once we get a copy, otherwise the doors * will appear on the maps in all sorts of odd positions. * @return a Vec3 pointing in the direction the door opens. */ public static Vector3f calcMoveDir(Angle3f angles) { // door goes up if (equals(angles, 0, -1, 0)) return new Vector3f(0, 0, 1); // door goes down if (equals(angles, 0, -2, 0)) return new Vector3f(0, 0, -1); // some other direction? Vector3f result = new Vector3f(); angles.getVectors(result, null, null); return result; }
/** * Fire a lead projectile. * @param p q2jgame.Player * @param start q2java.Vec3 * @param aimDir q2java.Vec3 * @param damage int * @param kick int * @param teImpact int * @param hSpread int * @param vSpread int */ public static void fireLead(GameObject p, Point3f start, Vector3f aimDir, int damage, int kick, int teImpact, int hSpread, int vSpread, String obitKey) { TraceResults tr; Vector3f forward = new Vector3f(); Vector3f right = new Vector3f(); Vector3f up = new Vector3f(); Point3f end = new Point3f(); float r; float u; Point3f waterStart = null; boolean water = false; int content_mask = Engine.MASK_SHOT | Engine.MASK_WATER; tr = Engine.trace(p.fEntity.getOrigin(), start, p.fEntity, Engine.MASK_SHOT); if (!(tr.fFraction < 1.0)) { // limit the scope of "dir" { Angle3f dir = Q2Recycler.getAngle3f(); dir.set(aimDir); dir.getVectors(forward, right, up); Q2Recycler.put(dir); } r = (float) (GameUtil.cRandom() * hSpread); u = (float) (GameUtil.cRandom() * vSpread); end.scaleAdd(8192, forward, start); end.scaleAdd(r, right, end); end.scaleAdd(u, up, end); if ((Engine.getPointContents(start) & Engine.MASK_WATER) != 0) { water = true; waterStart = new Point3f(start); content_mask &= ~Engine.MASK_WATER; } tr = Engine.trace(start, end, p.fEntity, content_mask); // see if we hit water if ((tr.fContents & Engine.MASK_WATER) != 0) { int color; water = true; waterStart = new Point3f(tr.fEndPos); if (!start.equals(tr.fEndPos)) { if ((tr.fContents & Engine.CONTENTS_WATER) != 0) { if (tr.fSurfaceName.equals("*brwater")) color = Engine.SPLASH_BROWN_WATER; else color = Engine.SPLASH_BLUE_WATER; } else if ((tr.fContents & Engine.CONTENTS_SLIME) != 0) color = Engine.SPLASH_SLIME; else if ((tr.fContents & Engine.CONTENTS_LAVA) != 0) color = Engine.SPLASH_LAVA; else color = Engine.SPLASH_UNKNOWN; if (color != Engine.SPLASH_UNKNOWN) { Engine.writeByte(Engine.SVC_TEMP_ENTITY); Engine.writeByte(Engine.TE_SPLASH); Engine.writeByte(8); Engine.writePosition(tr.fEndPos); Engine.writeDir(tr.fPlaneNormal); Engine.writeByte(color); Engine.multicast(tr.fEndPos, Engine.MULTICAST_PVS); } // change bullet's course when it enters water Vector3f diff = Q2Recycler.getVector3f(); Angle3f ang = Q2Recycler.getAngle3f(); diff.sub(end, start); ang.set(diff); ang.getVectors(forward, right, up); r = (float)(GameUtil.cRandom() * hSpread * 2); u = (float)(GameUtil.cRandom() * vSpread * 2); end.scaleAdd(8192, forward, waterStart); end.scaleAdd(r, right, end); end.scaleAdd(u, up, end); Q2Recycler.put(ang); Q2Recycler.put(diff); } // re-trace ignoring water this time tr = Engine.trace(waterStart, end, p.fEntity, Engine.MASK_SHOT); } } // send gun puff / flash if ((tr.fSurfaceName == null) || ((tr.fSurfaceFlags & Engine.SURF_SKY) == 0)) { if ((tr.fFraction < 1.0) && (!tr.fSurfaceName.startsWith("sky"))) { if (tr.fEntity.getReference() instanceof GameObject) ((GameObject)tr.fEntity.getReference()).damage(p, p, aimDir, tr.fEndPos, tr.fPlaneNormal, damage, kick, GameObject.DAMAGE_BULLET, teImpact, obitKey); } } // if went through water, determine where the end and make a bubble trail if (water) { Point3f pos = Q2Recycler.getPoint3f(); Vector3f leadDir = Q2Recycler.getVector3f(); leadDir.sub(tr.fEndPos, waterStart); leadDir.normalize(); pos.scaleAdd(-2, leadDir, tr.fEndPos); // = tr.fEndPos.vectorMA(-2, dir); if ((Engine.getPointContents(pos) & Engine.MASK_WATER) != 0) tr.fEndPos = new Point3f(pos); else tr = Engine.trace(pos, waterStart, tr.fEntity, Engine.MASK_WATER); pos.add(tr.fEndPos, waterStart); pos.scale(0.5F); Engine.writeByte(Engine.SVC_TEMP_ENTITY); Engine.writeByte(Engine.TE_BUBBLETRAIL); Engine.writePosition(waterStart); Engine.writePosition(tr.fEndPos); Engine.multicast(pos, Engine.MULTICAST_PVS); Q2Recycler.put(leadDir); Q2Recycler.put(pos); } }