diff options
| author | Fuwn <[email protected]> | 2026-02-12 22:33:32 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2026-02-12 22:33:32 -0800 |
| commit | c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9 (patch) | |
| tree | df9f48bf128a6c0186a8e91857d6ff30fe0e9f18 /NET/worlds/scape/HoloPilot.java | |
| download | worldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.tar.xz worldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.zip | |
Initial commit
Diffstat (limited to 'NET/worlds/scape/HoloPilot.java')
| -rw-r--r-- | NET/worlds/scape/HoloPilot.java | 579 |
1 files changed, 579 insertions, 0 deletions
diff --git a/NET/worlds/scape/HoloPilot.java b/NET/worlds/scape/HoloPilot.java new file mode 100644 index 0000000..8f8a518 --- /dev/null +++ b/NET/worlds/scape/HoloPilot.java @@ -0,0 +1,579 @@ +package NET.worlds.scape; + +import NET.worlds.console.Console; +import NET.worlds.core.Std; +import NET.worlds.network.URL; +import java.io.IOException; +import java.util.Enumeration; +import java.util.Vector; + +public class HoloPilot extends Pilot implements AnimatedActionHandler, AnimatedActionCallback { + private Camera cam; + private SmoothDriver smoothDriver; + private boolean cameraIsFree = false; + private AnimatedActionHandlerImp handler; + private HandsOffDriver hod; + String lastName; + Transform lastInverse; + Point3 lastCamWorldPos; + float lastCamRadius; + float lastCamYaw; + int lastDrawTime; + int framesSinceMoved = 0; + Room lastCamRoom; + Transform defaultTransform = Transform.make(); + Point3 aimPoint = new Point3(0.0F, 0.0F, 0.0F); + float defaultCameraYaw = 0.0F; + float defaultCameraRadius = 0.0F; + public static final int CAM_MODE_VEHICLE = 99; + public static final int CAM_MODE_FIRST_PERSON = 1; + public static final int CAM_MODE_LOW_FIRST_PERSON = 2; + public static final int CAM_MODE_WAIST = 3; + public static final int CAM_MODE_SHOULDER = 4; + public static final int CAM_MODE_HEAD = 5; + public static final int CAM_MODE_OVERHEAD = 6; + public static final int CAM_MODE_BEHIND = 7; + public static final int CAM_MODE_WIDESHOT = 8; + public static final int CAM_MODE_ORTHOGRAPHIC = 9; + public static final int CAM_SPEED_SLOW = 1; + public static final int CAM_SPEED_MEDIUM = 2; + public static final int CAM_SPEED_FAST = 3; + public static final int CAM_SPEED_LOCKED = 4; + private boolean substWarned = false; + protected Point3 boxLo = new Point3(); + protected Point3 boxHi = new Point3(); + protected float stepHeight = 30.0F; + private static Object classCookie = new Object(); + + public HoloPilot(URL movURL) { + this.setSourceURL(movURL); + this.loadInit(); + } + + @Override + public void setSleepMode(String mode) { + Drone d = this.getInternalDrone(); + if (d != null) { + d.setSleepMode(mode); + } + } + + @Override + public float animate(String action) { + super.animate(action); + Drone d = this.getInternalDrone(); + return d != null ? d.animate(action) : 0.0F; + } + + @Override + public Vector getAnimationList() { + Vector v = super.getAnimationList(); + Drone d = this.getInternalDrone(); + if (d == null) { + return v; + } else { + Vector v2 = (Vector)d.getAnimationList().clone(); + + for (int i = 0; i < v.size(); i++) { + v2.addElement(v.elementAt(i)); + } + + return v2; + } + } + + public HoloPilot() { + } + + @Override + public void loadInit() { + this.smoothDriver = new SmoothDriver(); + this.smoothDriver.setEyeHeight(0.0F); + this.cam = new Camera(); + this.add(this.cam); + Drone selfImage = Drone.make(null, null); + this.add(selfImage); + selfImage.setAvatarNow(this.getSourceURL()); + this.addHandler(this.smoothDriver); + this.addHandler(new PitchDriver()); + this.handler = new AnimatedActionHandlerImp(); + this.setEyeHeight(150.0F); + } + + @Override + public void addCallback(AnimatedActionCallback c) { + assert this.handler != null; + + this.handler.addCallback(c); + } + + @Override + public void removeCallback(AnimatedActionCallback c) { + assert this.handler != null; + + this.handler.removeCallback(c); + } + + @Override + public void notifyCallbacks(int completionCode) { + assert this.handler != null; + + this.handler.notifyCallbacks(completionCode); + } + + public void walkTo(Point2 destPoint, float destYaw) { + this.walkTo(destPoint, destYaw, 80.0F); + } + + public void walkTo(Point2 destPoint, float yaw, float velocity) { + this.removeHandler(this.smoothDriver); + this.hod = new HandsOffDriver(); + this.hod.setDestPos(destPoint, yaw, velocity); + this.hod.addCallback(this); + this.addHandler(this.hod); + } + + public void removeSmoothDriver() { + this.removeHandler(this.smoothDriver); + } + + public void returnSmoothDriver() { + this.addHandler(this.smoothDriver); + } + + public SmoothDriver getSmoothDriver() { + return this.smoothDriver; + } + + public void removeHandsOffDriver() { + if (this.hod != null) { + this.removeHandler(this.hod); + this.hod = null; + } + } + + public void returnHandsOffDriver() { + if (this.hod == null) { + this.hod = new HandsOffDriver(); + this.addHandler(this.hod); + } + } + + @Override + public void motionComplete(int completionCode) { + this.removeHandler(this.hod); + this.hod = null; + this.addHandler(this.smoothDriver); + this.notifyCallbacks(completionCode); + } + + public void updateName() { + String name = this.getLongID(); + if (name != null) { + if (this.lastName == null || !this.lastName.equals(name)) { + this.lastName = name; + Drone d = this.getInternalDrone(); + if (d != null) { + d.setName(name); + } + } + } + } + + public Drone getInternalDrone() { + Enumeration e = this.getContents(); + + while (e.hasMoreElements()) { + Object o = e.nextElement(); + if (o instanceof Drone) { + return (Drone)o; + } + } + + return null; + } + + private void setLastInverse(Transform t) { + if (this.lastInverse != null) { + this.lastInverse.recycle(); + } + + this.lastInverse = t; + } + + @Override + protected void transferFrom(Pilot old) { + if (old != null && old instanceof HoloPilot) { + HoloPilot o = (HoloPilot)old; + this.setOutsideCameraMode(o.getOutsideCameraMode(), o.getOutsideCameraSpeed()); + super.transferFrom(old); + if (o.lastCamWorldPos != null) { + this.setLastInverse(o.lastInverse.getTransform()); + this.lastCamWorldPos = new Point3(o.lastCamWorldPos); + } + + this.lastCamRoom = o.lastCamRoom; + this.lastCamRadius = o.lastCamRadius; + this.lastCamYaw = o.lastCamYaw; + this.lastDrawTime = o.lastDrawTime; + this.framesSinceMoved = this.framesSinceMoved; + } else { + super.transferFrom(old); + } + } + + @Override + public void aboutToDraw() { + if (this.cameraMode == 1 || this.cameraMode == 2) { + this.lastCamWorldPos = null; + this.cam.makeIdentity(); + } else if (!this.cameraIsFree) { + Transform world = this.getObjectToWorldMatrix(); + int thisDrawTime = Std.getRealTime(); + Room thisCamRoom = this.getRoom(); + Transform inv = world.getTransform().invert(); + float radius; + float yaw; + if (this.lastCamWorldPos == null || this.cameraSpeed == 4 || this.cameraMode == 99) { + this.lastCamWorldPos = new Point3(); + radius = this.defaultCameraRadius; + yaw = this.defaultCameraYaw; + } else if (thisCamRoom != this.lastCamRoom) { + yaw = this.lastCamYaw; + radius = this.lastCamRadius; + } else { + Point3 p = this.lastCamWorldPos; + p.times(inv); + radius = (float)Math.sqrt(p.x * p.x + p.y * p.y); + if (radius > this.defaultCameraRadius + 10.0F) { + radius = this.defaultCameraRadius + 10.0F; + } + + if (this.cameraSpeed == 3) { + radius = this.defaultCameraRadius; + } + + yaw = (float)(Math.atan2(p.y, p.x) * 180.0 / Math.PI); + this.lastInverse.post(world); + float yawMove = this.lastInverse.getYaw(); + if (yawMove > 180.0F) { + yawMove -= 360.0F; + } + + Point3Temp lip = this.lastInverse.getPosition(); + if (this.cameraSpeed != 1 || Math.abs(yawMove) < 1.0F && lip.x * lip.x + lip.y * lip.y < 1.0F) { + if (++this.framesSinceMoved > 2) { + float dyaw = this.defaultCameraYaw - yaw; + if (dyaw < -180.0F) { + dyaw += 360.0F; + } else if (dyaw > 180.0F) { + dyaw -= 360.0F; + } + + float drad = this.defaultCameraRadius - radius; + float dtime = thisDrawTime - this.lastDrawTime; + float maxYawCorrection = 0.04F; + float maxRadCorrection = 0.03F; + if (Math.abs(dyaw) > 1500.0F * maxYawCorrection) { + maxYawCorrection *= 1.5F; + } + + maxYawCorrection *= dtime; + if (dyaw < -maxYawCorrection) { + dyaw = -maxYawCorrection; + } else if (dyaw > maxYawCorrection) { + dyaw = maxYawCorrection; + } + + maxRadCorrection *= dtime; + if (drad < -maxRadCorrection) { + drad = -maxRadCorrection; + } else if (drad > maxRadCorrection) { + drad = maxRadCorrection; + } + + yaw += dyaw; + radius += drad; + if (this.cameraSpeed == 3) { + if (yaw > this.defaultCameraYaw + 40.0F) { + yaw = this.defaultCameraYaw + 40.0F; + } else if (yaw < this.defaultCameraYaw - 40.0F) { + yaw = this.defaultCameraYaw - 40.0F; + } + } + } + } else { + this.framesSinceMoved = 0; + } + } + + this.setLastInverse(inv); + float hackedZ = this.aimPoint.z; + float hackedYaw = yaw; + float hackedRadius = radius; + if (this.hod != null) { + hackedYaw = yaw + this.hod.getCameraPan(); + hackedRadius = radius + this.hod.getCameraZoom(); + if (hackedRadius < this.defaultCameraRadius) { + hackedZ -= (this.defaultCameraRadius - hackedRadius) * this.smoothDriver.getEyeHeight() / this.defaultCameraRadius; + } + } + + this.cam.makeIdentity().post(this.defaultTransform); + this.cam.moveBy(hackedRadius, 0.0F, 0.0F); + this.cam.postspin(0.0F, 0.0F, 1.0F, hackedYaw); + this.cam.moveBy(this.aimPoint.x, this.aimPoint.y, hackedZ); + this.lastCamRadius = radius; + this.lastCamYaw = yaw; + double angle = yaw * Math.PI / 180.0; + this.lastCamWorldPos.x = (float)(radius * Math.cos(angle)); + this.lastCamWorldPos.y = (float)(radius * Math.sin(angle)); + this.lastCamWorldPos.z = 0.0F; + this.lastCamWorldPos.times(world); + this.lastCamWorldPos.z = 0.0F; + this.lastDrawTime = thisDrawTime; + this.lastCamRoom = thisCamRoom; + world.recycle(); + } + } + + @Override + public void setOutsideCameraMode(int camMode, int camSpeed) { + this.defaultTransform.makeIdentity(); + this.aimPoint.x = 0.0F; + this.aimPoint.y = 0.0F; + this.aimPoint.z = 0.0F; + this.setEyeHeight(150.0F); + if (this.getInternalDrone() != null && this.getInternalDrone() instanceof PosableDrone) { + PosableShape ps = ((PosableDrone)this.getInternalDrone()).getInternalPosableShape(); + if (ps != null && ps instanceof VehicleShape) { + VehicleShape vs = (VehicleShape)ps; + if (vs.fixedCamera) { + this.defaultTransform + .moveTo(vs.camX, vs.camY, vs.camZ) + .postspin(1.0F, 0.0F, 0.0F, vs.camRoll) + .postspin(0.0F, 1.0F, 0.0F, vs.camYaw) + .postspin(0.0F, 0.0F, 1.0F, vs.camPitch); + this.aimPoint.x = vs.camAimX; + this.aimPoint.y = vs.camAimY; + this.aimPoint.z = vs.camAimZ; + this.setEyeHeight(vs.eyeHeight); + camMode = 99; + } + } + } + + this.cam.setAlwaysClearBackground(false); + this.cam.setBumpable(true); + switch (camMode) { + case 1: + case 99: + break; + case 2: + this.setEyeHeight(100.0F); + break; + case 3: + this.defaultTransform.moveTo(0.0F, -120.0F, -60.0F).postspin(1.0F, 0.0F, 0.0F, -10.0F).postspin(0.0F, 0.0F, 1.0F, 30.0F); + this.aimPoint.x = 15.0F; + this.aimPoint.z = -10.0F; + break; + case 4: + this.defaultTransform.moveTo(0.0F, -140.0F, -40.0F).postspin(1.0F, 0.0F, 0.0F, -10.0F).postspin(0.0F, 0.0F, 1.0F, 15.0F); + this.aimPoint.x = 15.0F; + this.aimPoint.z = 10.0F; + break; + case 5: + this.defaultTransform.moveTo(0.0F, -140.0F, 0.0F).postspin(1.0F, 0.0F, 0.0F, -10.0F).postspin(0.0F, 0.0F, 1.0F, 15.0F); + this.aimPoint.x = 15.0F; + this.aimPoint.z = 10.0F; + break; + case 6: + this.defaultTransform.moveTo(0.0F, -100.0F, 0.0F).postspin(1.0F, 0.0F, 0.0F, -30.0F).postspin(0.0F, 0.0F, 1.0F, 30.0F); + this.aimPoint.x = 15.0F; + this.aimPoint.z = 10.0F; + break; + case 7: + this.defaultTransform.moveTo(0.0F, -140.0F, 0.0F).postspin(1.0F, 0.0F, 0.0F, -10.0F); + break; + case 8: + this.defaultTransform.moveTo(0.0F, -220.0F, -40.0F).postspin(1.0F, 0.0F, 0.0F, -30.0F).postspin(0.0F, 0.0F, 1.0F, 30.0F); + this.aimPoint.x = 15.0F; + this.aimPoint.z = 10.0F; + break; + case 9: + this.defaultTransform.moveTo(0.0F, -140.0F, 300.0F).postspin(1.0F, 0.0F, 0.0F, -10.0F); + this.aimPoint.x = 0.0F; + this.aimPoint.z = 300.0F; + this.cam.setAlwaysClearBackground(true); + this.cam.setBumpable(false); + camSpeed = 4; + break; + default: + camMode = 1; + camSpeed = 3; + this.defaultCameraRadius = 0.0F; + this.defaultCameraYaw = 0.0F; + } + + if (camMode != 1 && camMode != 2) { + float x = this.defaultTransform.getX(); + float y = this.defaultTransform.getY(); + this.aimPoint.z = this.aimPoint.z + this.defaultTransform.getZ(); + this.defaultCameraRadius = (float)Math.sqrt(x * x + y * y); + this.defaultCameraYaw = (float)(Math.atan2(y, x) * 180.0 / Math.PI); + this.defaultTransform.moveTo(0.0F, 0.0F, 0.0F); + this.defaultTransform.postspin(0.0F, 0.0F, 1.0F, -this.defaultCameraYaw); + } + + super.setOutsideCameraMode(camMode, camSpeed); + } + + @Override + public void resetAvatarNow() { + URL to = this.getSourceURL(); + Drone d = this.getInternalDrone(); + d.setAvatarNow(to); + if (!d.shouldBeForcedHuman() || PosableShape.getHuman(to).equals(to)) { + this.substWarned = false; + } else if (!this.substWarned) { + this.substWarned = true; + Console.println(Console.message("Sub-human")); + } + } + + public void setEyeHeight(float h) { + float hOld = this.smoothDriver.getEyeHeight(); + if (h != hOld) { + this.smoothDriver.setEyeHeight(h); + this.getInternalDrone().moveBy(0.0F, 0.0F, hOld - h); + this.setLocalBoundBox(Point3Temp.make(-30.0F, -30.0F, -h), Point3Temp.make(30.0F, 50.0F, 20.0F)); + } + } + + public BoundBoxTemp getLocalBoundBox() { + return BoundBoxTemp.make(this.boxLo, this.boxHi); + } + + public void setLocalBoundBox(BoundBoxTemp b) { + this.boxLo = new Point3(b.lo); + this.boxHi = new Point3(b.hi); + } + + public void setLocalBoundBox(Point3Temp lo, Point3Temp hi) { + this.setLocalBoundBox(BoundBoxTemp.make(lo, hi)); + } + + @Override + public BoundBoxTemp getBoundBox() { + Point3Temp lo = Point3Temp.make(this.boxLo); + lo.z = lo.z + this.stepHeight; + Point3Temp hi = this.boxHi; + Transform xfrm = this.getObjectToWorldMatrix(); + Point3Temp p = Point3Temp.make(lo).times(xfrm); + BoundBoxTemp w = BoundBoxTemp.make(p, p); + w.encompass(Point3Temp.make(hi).times(xfrm)); + w.encompass(Point3Temp.make(lo.x, lo.y, hi.z).times(xfrm)); + w.encompass(Point3Temp.make(lo.x, hi.y, lo.z).times(xfrm)); + w.encompass(Point3Temp.make(lo.x, hi.y, hi.z).times(xfrm)); + w.encompass(Point3Temp.make(hi.x, lo.y, lo.z).times(xfrm)); + w.encompass(Point3Temp.make(hi.x, lo.y, hi.z).times(xfrm)); + w.encompass(Point3Temp.make(hi.x, hi.y, lo.z).times(xfrm)); + xfrm.recycle(); + return w; + } + + @Override + public float getFootHeight() { + if (this.isActive()) { + Transform t = this.getObjectToWorldMatrix(); + float pitch = t.getPitch(); + t.pitch(-pitch); + float ret = Point3Temp.make(this.boxLo).times(t).z; + t.recycle(); + return ret; + } else { + return 0.0F; + } + } + + public float getStepHeight() { + return this.stepHeight; + } + + public void setStepHeight(float h) { + this.stepHeight = h; + } + + public void releaseCamera() { + this.cameraIsFree = true; + } + + public void reclaimCamera() { + this.cameraIsFree = false; + } + + public Camera getCamera() { + return this.cam; + } + + @Override + public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException { + Object ret = null; + switch (index - offset) { + case 0: + if (mode == 0) { + ret = Point3PropertyEditor.make(new Property(this, index, "Bump Box Start")); + } else if (mode == 1) { + ret = new Point3(this.boxLo); + } else if (mode == 2) { + this.boxLo = new Point3((Point3)value); + } + break; + case 1: + if (mode == 0) { + ret = Point3PropertyEditor.make(new Property(this, index, "Bump Box End")); + } else if (mode == 1) { + ret = new Point3(this.boxHi); + } else if (mode == 2) { + this.boxHi = new Point3((Point3)value); + } + break; + case 2: + if (mode == 0) { + ret = FloatPropertyEditor.make(new Property(this, index, "Step Height")); + } else if (mode == 1) { + ret = new Float(this.getStepHeight()); + } else if (mode == 2) { + this.setStepHeight((Float)value); + } + break; + default: + ret = super.properties(index, offset + 3, mode, value); + } + + return ret; + } + + @Override + public void saveState(Saver s) throws IOException { + s.saveVersion(0, classCookie); + super.saveState(s); + s.saveFloat(this.stepHeight); + s.save(this.boxLo); + s.save(this.boxHi); + } + + @Override + public void restoreState(Restorer r) throws IOException, TooNewException { + switch (r.restoreVersion(classCookie)) { + case 0: + super.restoreState(r); + this.stepHeight = r.restoreFloat(); + this.boxLo = (Point3)r.restore(); + this.boxHi = (Point3)r.restore(); + return; + default: + throw new TooNewException(); + } + } +} |