summaryrefslogtreecommitdiff
path: root/NET/worlds/scape/HoloPilot.java
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-02-12 22:33:32 -0800
committerFuwn <[email protected]>2026-02-12 22:33:32 -0800
commitc7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9 (patch)
treedf9f48bf128a6c0186a8e91857d6ff30fe0e9f18 /NET/worlds/scape/HoloPilot.java
downloadworldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.tar.xz
worldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.zip
Initial commit
Diffstat (limited to 'NET/worlds/scape/HoloPilot.java')
-rw-r--r--NET/worlds/scape/HoloPilot.java579
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();
+ }
+ }
+}