content/hifi-content/caitlyn/swampboat/hoverKart.js
2022-02-13 22:19:19 +01:00

692 lines
20 KiB
JavaScript

var appUUID = Uuid.generate();
var ROOT = "http://mpassets.highfidelity.com/5cb2cc54-729a-461f-abeb-0bdd357345e0-v1/";
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
var icon = ROOT + "hoverKart.svg?";
var appHTML = ROOT + "hoverKart.html";
var button = tablet.addButton({
icon: icon,
text: "SWAMPBOAT2"
});
var isOpen = false;
var running = false;
var ANIMATION_URL = ROOT + "sitting.fbx";
var ANIMATION_FPS = 30, ANIMATION_FIRST_FRAME = 1, ANIMATION_LAST_FRAME = 200;
var kartWearRotation = {x: 0, y: 0, z: 0, w: 1};
var kartURL = ROOT + "raceboat_diesel.fbx";
var kartEntity;
var kartName = "hoverKart";
var SCALE = 1;
var TIMEOUT = 500;
var INT_2 = 2;
var MS_CONVERSION = 1000;
var jointIndex = -1;
var kartSize = {
x: 1.1228,
y: 0.6090,
z: 1.8364
};
var soundEnabled = true;
var sounds = {
setup: function () {
var s = {
IDLE_SOUND_URL: ROOT + "engine.wav",
RUNNING_SOUND_URL: ROOT + "engineDrive.wav",
REZ_SOUND_URL: ROOT + "rez.wav",
DEREZ_SOUND_URL: ROOT + "derez.wav",
JUMP_SOUND_URL: ROOT + "jump.wav",
REZ_SOUND_VOLUME: 0.1,
IDLE_SOUND_VOLUME: 0.03,
RUNNING_SOUND_VOLUME: 0.03,
RUNNING_SOUND_VOLUME_MIN: 0.03,
RUNNING_SOUND_VOLUME_MAX: 0.6,
idleInjector: null,
runningInjector: null,
rezInjector: null,
derezInjector: null,
jumpInjector: null,
positionTimer: null,
positionTimerInterval: 100,
runningTimer: null,
runningTimerInterval: 100
};
s.idleProps = {position: MyAvatar.position, volume: s.IDLE_SOUND_VOLUME, loop: true};
s.runningProps = {position: MyAvatar.position, volume: s.RUNNING_SOUND_VOLUME, loop: true};
s.effectProps = {position: MyAvatar.position, volume: s.REZ_SOUND_VOLUME, loop: false};
s.idleSoundURL = SoundCache.getSound(s.IDLE_SOUND_URL);
s.runningSoundURL = SoundCache.getSound(s.RUNNING_SOUND_URL);
s.rezSoundURL = SoundCache.getSound(s.REZ_SOUND_URL);
s.derezSoundURL = SoundCache.getSound(s.DEREZ_SOUND_URL);
s.jumpSoundURL = SoundCache.getSound(s.JUMP_SOUND_URL);
if (!s.idleSoundURL.downloaded) {
s.idleSoundURL = SoundCache.getSound(s.IDLE_SOUND_URL);
}
if (!s.runningSoundURL.downloaded) {
s.runningSoundURL = SoundCache.getSound(s.RUNNING_SOUND_URL);
}
if (!s.rezSoundURL.downloaded) {
s.rezSoundURL = SoundCache.getSound(s.REZ_SOUND_URL);
}
if (!s.derezSoundURL.downloaded) {
s.derezSoundURL = SoundCache.getSound(s.DEREZ_SOUND_URL);
}
if (!s.jumpSoundURL.downloaded) {
s.jumpSoundURL = SoundCache.getSound(s.JUMP_SOUND_URL);
}
s.playJump = function () {
if (s.jumpInjector === null) {
s.effectProps.position = MyAvatar.position;
s.jumpInjector = Audio.playSound(s.jumpSoundURL, s.effectProps);
} else {
s.effectProps.position = MyAvatar.position;
s.jumpInjector.setOptions(s.effectProps);
s.jumpInjector.restart();
}
};
s.playRez = function () {
if (s.rezInjector === null) {
s.effectProps.position = MyAvatar.position;
s.rezInjector = Audio.playSound(s.rezSoundURL, s.effectProps);
} else {
s.effectProps.position = MyAvatar.position;
s.rezInjector.setOptions(s.effectProps);
s.rezInjector.restart();
}
};
s.playDerez = function () {
if (s.derezInjector === null) {
s.effectProps.position = MyAvatar.position;
s.derezInjector = Audio.playSound(s.derezSoundURL, s.effectProps);
} else {
s.effectProps.position = MyAvatar.position;
s.derezInjector.setOptions(s.effectProps);
s.derezInjector.restart();
}
};
s.playIdle = function () {
if (s.runningInjector !== null) {
Script.clearInterval(s.runningTimer);
s.runningInjector.stop();
}
if (s.idleInjector === null) {
s.idleProps.position = MyAvatar.position;
s.idleInjector = Audio.playSound(s.idleSoundURL, s.idleProps);
} else {
s.idleProps.position = MyAvatar.position;
s.idleInjector.setOptions(s.idleProps);
s.idleInjector.restart();
}
};
s.playRunning = function () {
if (s.idleInjector !== null) {
s.idleInjector.stop();
}
if (s.runningInjector === null) {
s.runningProps.position = MyAvatar.position;
s.runningInjector = Audio.playSound(s.runningSoundURL, s.runningProps);
} else {
s.runningProps.position = MyAvatar.position;
s.runningInjector.setOptions(s.runningProps);
s.runningInjector.restart();
}
s.runningTimer = Script.setInterval(s.runningUpdate, s.runningTimerInterval);
};
s.runningUpdate = function () {
var vel = MyAvatar.motorVelocity;
s.RUNNING_SOUND_VOLUME = normalize(Math.abs(vel.z), s.RUNNING_SOUND_VOLUME_MIN, s.RUNNING_SOUND_VOLUME_MAX) * Math.sign(vel.z);
};
s.positionUpdate = function () {
s.idleProps.position = MyAvatar.position;
s.runningProps.position = MyAvatar.position;
if (s.idleInjector !== null) {
s.idleInjector.setOptions(s.idleProps);
}
if (s.runningInjector !== null) {
s.runningInjector.setOptions(s.runningProps);
}
};
s.start = function () {
s.positionTimer = Script.setInterval(s.positionUpdate, s.positionTimerInterval);
s.playIdle();
};
s.stop = function () {
Script.clearInterval(s.positionTimer);
if (s.idleInjector !== null) {
s.idleInjector.stop();
}
if (s.runningInjector !== null) {
s.runningInjector.stop();
}
};
s.idleInjector = Audio.playSound(s.idleSoundURL, {volume: 0});
s.runningInjector = Audio.playSound(s.runningSoundURL, {volume: 0});
s.idleInjector.stop();
s.runningInjector.stop();
return s;
}
};
var vehicleSounds = sounds.setup();
var camera = {
setup: function () {
var cam = {active: false, offset: {x: 0, y: 2, z: 7}, speedPos: 10, speedRot: 5};
cam.update = function (deltaTime) {
if (cam.active && !HMD.active) {
var endPos = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(spinOut.active ? Camera.orientation : MyAvatar.orientation, cam.offset));
Camera.position = Vec3.mix(Camera.position, endPos, cam.speedPos * deltaTime);
if (!spinOut.active) {
var endRot = MyAvatar.orientation;
Camera.orientation = Quat.slerp(Camera.orientation, endRot, cam.speedRot * deltaTime);
}
}
};
return cam;
}
};
var kartCamera = camera.setup();
var spinOut = {
active: false, amount: 12, target: 1080, count: 1, lastAmount: 0, spinOut: function (deltaTime) {
spinOut.count -= deltaTime / INT_2;
spinOut.amount = spinOut.target * cubicIn(spinOut.count);
MyAvatar.orientation = Quat.multiply(MyAvatar.orientation, Quat.fromPitchYawRollDegrees(0, spinOut.amount - spinOut.lastAmount, 0));
spinOut.lastAmount = spinOut.amount;
if (spinOut.count <= 0) {
spinOut.amount = 0;
spinOut.count = 1;
vel.z = 0;
spinOut.active = false;
}
}
};
var boost = {
active: false, power: 10, duration: 5, boost: function (power, duration) {
print("BoostON");
boost.active = true;
boost.power = power;
boost.duration = duration;
Script.setTimeout(function () {
print("BoostOFF");
boost.active = false;
}, duration * MS_CONVERSION);
}
};
var force = 20;
var dir = 0;
var turn = 0;
var air = 0.5;
var drift = 0.5;
var vel = {x: 0, y: 0, z: 0};
var vehicleYaw = 40;
var defaultYaw = 100;
var SPEED_RESET_MIN = 0.5;
var SPEED_RESET_MAX = 5;
var MIN_HMD = 0.05;
var MAX_HMD = 0.8;
var oldjumpValue = 0;
var MOTOR_TIMESCALE = 1.0;
var MOTOR_TIMESCALE_MAX = 1000000.0;
MyAvatar.motorReferenceFrame = "avatar";
var Vive = Controller.Hardware.Vive;
var KEY_SPACE = 32;
var controllerMapping;
var controllerMappingName;
var oldCameraMode = "third person";
Script.scriptEnding.connect(function () {
Controller.disableMapping(controllerMappingName);
});
controllerMappingName = 'Hifi-HoverKart-Mapping';
controllerMapping = Controller.newMapping(controllerMappingName);
function empty(val) {
}
controllerMapping.from(Controller.Hardware.Keyboard.W).to(function (value) {
if (value !== 0) {
dir = 1;
} else {
if (dir === 1) {
dir = 0;
}
}
});
controllerMapping.from(Controller.Hardware.Keyboard.S).to(function (value) {
if (value !== 0) {
dir = -1;
} else {
if (dir === -1) {
dir = 0;
}
}
});
controllerMapping.from(Controller.Hardware.Keyboard.A).to(function (value) {
if (value !== 0) {
turn = 1;
} else {
if (turn === 1) {
turn = 0;
}
}
});
controllerMapping.from(Controller.Hardware.Keyboard.D).to(function (value) {
if (value !== 0) {
turn = -1;
} else {
if (turn === -1) {
turn = 0;
}
}
});
controllerMapping.from(Controller.Standard.LY).to(function (value) {
if (Vive && Controller.getValue(Controller.Standard.LS) === 0) {
dir = 0;
return;
}
if (Math.abs(value) < MIN_HMD) {
value = 0;
}
if (Math.abs(value) > MAX_HMD) {
value = 1*Math.sign(value);
}
dir = -value;
});
controllerMapping.from(Controller.Standard.RX).to(function (value) {
if (Vive && Controller.getValue(Controller.Standard.RS) === 0) {
turn = 0;
return;
}
if (Math.abs(value) < MIN_HMD) {
value = 0;
}
if (Math.abs(value) > MAX_HMD) {
value = 1*Math.sign(value);
}
turn = -value;
});
controllerMapping.from(Controller.Standard.LeftPrimaryThumb).to(empty);
// utils start
if (!Math.sign) {
Math.sign = function (x) {
return ((x > 0) - (x < 0)) || +x;
};
}
if (!Math.moveTowards) {
Math.moveTowards = function (current, target, maxDelta) {
if (Math.abs(target - current) <= maxDelta) {
return target;
}
return current + Math.sign(target - current) * maxDelta;
};
}
function normalize(value, min, max) {
var normalized = (value - min) / (max - min);
if (normalized < 0) {
normalized = 0;
}
if (normalized > 1) {
normalized = 1;
}
return normalized;
}
function cubicIn(t) {
return t * t * t;
}
// utils end
function sit() {
jointIndex = MyAvatar.getJointIndex("Hips");
MyAvatar.restoreAnimation();
MyAvatar.getAnimationRoles().filter(function (role) {
return !/^(right|left)/.test(role);
}).forEach(function (role) {
MyAvatar.overrideRoleAnimation(role, ANIMATION_URL, ANIMATION_FPS, true, ANIMATION_FIRST_FRAME, ANIMATION_LAST_FRAME);
});
Script.setTimeout(function () {
MyAvatar.setJointRotation(jointIndex, Quat.IDENTITY);
}, TIMEOUT);
kartEntity = Entities.addEntity({
visible: true,
name: kartName,
type: "Model",
modelURL: kartURL,
parentID: MyAvatar.sessionUUID,
parentJointIndex: jointIndex,
localPosition: {x: 0, y: 0, z: 0},
localRotation: kartWearRotation,
dimensions: Vec3.multiply((SCALE * MyAvatar.scale), kartSize),
collisionless: true,
userData: "{ \"grabbableKey\": { \"grabbable\": false} }"
}, true);
}
function unsit() {
MyAvatar.getAnimationRoles().filter(function (role) {
return !/^(right|left)/.test(role);
}).forEach(function (role) {
MyAvatar.restoreRoleAnimation(role);
});
MyAvatar.clearJointData(jointIndex);
Entities.deleteEntity(kartEntity);
}
function toggleCamera(on) {
if (on) {
oldCameraMode = Camera.mode;
if (running && !HMD.active) {
Camera.setModeString("independent");
}
kartCamera.active = true;
}
if (!on) {
kartCamera.active = false;
if (running && !HMD.active) {
Camera.setModeString(oldCameraMode === "independent" ? "third person" : oldCameraMode);
}
}
}
function toggleSound(on) {
if (on) {
if (running) {
vehicleSounds = sounds.setup();
vehicleSounds.start();
}
soundEnabled = true;
}
if (!on) {
soundEnabled = false;
if (running) {
vehicleSounds.stop();
}
}
}
function timeFunction(deltaTime) {
var jumpValue = Controller.getValue(Controller.Standard.RY);
if (jumpValue < -MIN_HMD) {
jumpValue = 1;
} else {
jumpValue = 0;
}
if (oldjumpValue !== jumpValue && oldjumpValue > MIN_HMD) {
vehicleSounds.playJump();
}
if (oldjumpValue !== jumpValue) {
oldjumpValue = jumpValue;
}
if ((dir !== 0 || boost.active) && vehicleSounds.idleInjector.playing) {
vehicleSounds.playRunning();
} else if (dir === 0 && !boost.active && vehicleSounds.runningInjector.playing) {
vehicleSounds.playIdle();
}
MyAvatar.motorTimescale = MOTOR_TIMESCALE;
vel = {
x: (MyAvatar.motorVelocity.x + (vel.x * deltaTime)) * (Math.pow(drift, deltaTime)),
y: vel.y,
z: (vel.z + (((dir * force) + (boost.active ? boost.power : 0)) * deltaTime)) * (Math.pow(air, deltaTime))
};
MyAvatar.motorVelocity = {
x: vel.x,
y: MyAvatar.motorVelocity.y,
z: vel.z
};
MyAvatar.orientation = Quat.multiply(MyAvatar.orientation, Quat.fromPitchYawRollDegrees(0, (vehicleYaw * deltaTime) * turn, 0));
var localVelocity = Vec3.multiplyQbyV(Quat.inverse(MyAvatar.orientation), MyAvatar.velocity);
if (Math.abs(localVelocity.z) < SPEED_RESET_MIN && Math.abs(vel.z) > SPEED_RESET_MAX) {
vel.z = 0;
}
if (spinOut.active) {
spinOut.spinOut(deltaTime);
}
kartCamera.update(deltaTime);
}
function messageReceived(channel, message) {
if (channel === "VROOM_MESSAGE") {
var data = JSON.parse(message);
if (data.type === "boost") {
boost.boost(data.data.power, data.data.duration);
}
if (data.type === "spinOut") {
spinOut.active = true;
}
}
}
function keyPressEvent(event) {
if (event.key === KEY_SPACE && !event.isAutoRepeat && soundEnabled && running) {
vehicleSounds.playJump();
}
}
Messages.messageReceived.connect(messageReceived);
// humbletim's barnacle locator
function findBarnacles(name) {
return Object.keys(MyAvatar.getAvatarEntityData())
.filter(function (id) {
return Entities.getNestableType(id) === 'entity';
})
.map(function (entityID) {
return Entities.getEntityProperties(entityID);
})
.filter(function (props) {
return props.name === name;
});
}
var oldKarts = findBarnacles(kartName);
oldKarts.forEach(function (ent) {
Entities.deleteEntity(ent.id);
});
// Tablet Code
function onClicked() { // Nothing else here!
if (isOpen) {
tablet.gotoHomeScreen();
} else {
tablet.gotoWebScreen(appHTML + "?enabled=" + running + "&camera=" + kartCamera.active + "&sound=" + soundEnabled + "&appUUID=" + appUUID, {});
}
}
function onScreenChanged(type, url) {
isOpen = (url === appHTML);
if (isOpen) {
tablet.emitScriptEvent(JSON.stringify({state: running}));
}
}
button.clicked.connect(onClicked);
tablet.screenChanged.connect(onScreenChanged);
function init() {
Controller.keyPressEvent.connect(keyPressEvent);
try {
tablet.webEventReceived.connect(onWebEventReceived);
} catch (e) {
print("connectWebHandler: error connecting: " + e);
}
}
function onWebEventReceived(event) {
event = JSON.parse(event);
if (event.appUUID === appUUID) {
if (event.type === "ready") {
// vehicleSounds = sounds.setup();
// Bleh
}
if (event.sound === true) {
toggleSound(true);
}
if (event.sound === false) {
toggleSound(false);
}
if (event.camera === true) {
toggleCamera(true);
}
if (event.camera === false) {
toggleCamera(false);
}
if (event.state === true) {
if (soundEnabled) {
vehicleSounds = sounds.setup();
vehicleSounds.playRez();
vehicleSounds.start();
}
running = true;
if (kartCamera.active && !HMD.active) {
oldCameraMode = Camera.mode;
Camera.setModeString("independent");
}
sit();
Controller.enableMapping(controllerMappingName);
MyAvatar.setHMDLeanRecenterEnabled(false);
defaultYaw = MyAvatar.yawSpeed;
MyAvatar.yawSpeed = vehicleYaw;
Script.update.connect(timeFunction);
}
if (event.state === false) {
running = false;
if (soundEnabled) {
vehicleSounds.playDerez();
vehicleSounds.stop();
}
if (kartCamera.active && !HMD.active) {
Camera.setModeString(oldCameraMode);
}
unsit();
Script.update.disconnect(timeFunction);
MyAvatar.motorTimescale = MOTOR_TIMESCALE_MAX;
MyAvatar.setHMDLeanRecenterEnabled(true);
Controller.disableMapping(controllerMappingName);
MyAvatar.yawSpeed = defaultYaw;
}
}
}
function shutdown() {
try {
tablet.webEventReceived.disconnect(onWebEventReceived);
} catch (e) {
print("disconnectWebHandler: error disconnecting web handler: " + e);
return;
}
MyAvatar.motorTimescale = MOTOR_TIMESCALE_MAX;
MyAvatar.yawSpeed = defaultYaw;
if (Camera.mode === "independent") {
Camera.setModeString(oldCameraMode);
}
try {
unsit();
} catch (e) {
// empty
}
try {
vehicleSounds.stop();
} catch (e) {
// empty
}
try {
Controller.keyPressEvent.disconnect(keyPressEvent);
} catch (e) {
// empty
}
try {
Messages.messageReceived.disconnect(messageReceived);
} catch (e) {
// empty
}
try {
Script.update.disconnect(timeFunction);
} catch (e) {
// empty
}
try {
Controller.disableMapping(controllerMappingName);
} catch (e) {
// empty
}
try {
button.clicked.disconnect(onClicked);
} catch (e) {
// empty
}
tablet.screenChanged.disconnect(onScreenChanged);
tablet.removeButton(button);
}
init();
Script.scriptEnding.connect(function () {
shutdown();
});