222 lines
8 KiB
JavaScript
222 lines
8 KiB
JavaScript
// pingPongGun.js
|
|
//
|
|
// Script Type: Entity
|
|
// Created by James B. Pollack @imgntn on 9/21/2015
|
|
// Copyright 2015 High Fidelity, Inc.
|
|
//
|
|
// This script shoots a ping pong ball.
|
|
// Distributed under the Apache License, Version 2.0.
|
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
//
|
|
|
|
(function() {
|
|
var TRIGGER_THRESHOLD = 0.3;
|
|
|
|
var BULLET_BLUE_MODEL_URL = "http://hifi-content.s3.amazonaws.com/alan/dev/Glow-ball-blue.fbx";
|
|
var BULLET_RED_MODEL_URL = "http://hifi-content.s3.amazonaws.com/alan/dev/Glow-ball-red.fbx";
|
|
|
|
var GUN_LOAD_SOUND_URL = "https://hifi-content.s3.amazonaws.com/DomainContent/Event%20/Sounds/Gun/GunLoad02.wav";
|
|
var GUN_FIRE1_SOUND_URL = "https://hifi-content.s3.amazonaws.com/DomainContent/Event%20/Sounds/Gun/GunFire01.wav";
|
|
var GUN_FIRE2_SOUND_URL = "https://hifi-content.s3.amazonaws.com/DomainContent/Event%20/Sounds/Gun/GunFire02.wav";
|
|
var GUN_FIRE3_SOUND_URL = "https://hifi-content.s3.amazonaws.com/DomainContent/Event%20/Sounds/Gun/GunFire03.wav";
|
|
|
|
var GUN_TIP_FWD_OFFSET = -1;
|
|
var GUN_TIP_UP_OFFSET = 0.12;
|
|
var GUN_FORCE = 20;
|
|
var BALL_RESTITUTION = 0.2;
|
|
var BALL_LINEAR_DAMPING = 0.1;
|
|
var BALL_DENSITY = 10000;
|
|
|
|
var BALL_GRAVITY = {
|
|
x: 0,
|
|
y: -10,
|
|
z: 0
|
|
};
|
|
|
|
var BALL_DIMENSIONS = {
|
|
x: 2.5,
|
|
y: 2.5,
|
|
z: 2.5
|
|
};
|
|
|
|
var BALL_COLLIDER_DIMENSIONS = {
|
|
x: 0.94,
|
|
y: 2.0,
|
|
z: 0.94
|
|
};
|
|
|
|
var BALL_ANGULAR_VEL = {
|
|
x: 2,
|
|
y: 3,
|
|
z: 1
|
|
};
|
|
|
|
var TRIGGER_CONTROLS = [
|
|
Controller.Standard.LT,
|
|
Controller.Standard.RT
|
|
];
|
|
|
|
function PortalGun() {
|
|
}
|
|
|
|
PortalGun.prototype = {
|
|
hand: null,
|
|
gunTipPosition: null,
|
|
cooldownActive: false,
|
|
|
|
preload: function(entityID) {
|
|
this.entityID = entityID;
|
|
this.gunFireSound = SoundCache.getSound(GUN_FIRE1_SOUND_URL);
|
|
this.gunLoadSound = SoundCache.getSound(GUN_LOAD_SOUND_URL);
|
|
|
|
this.hasReleasedInitialTriggerPress = false;
|
|
|
|
this.color = 'red';
|
|
|
|
var userData = Entities.getEntityProperties(entityID, 'userData').userData;
|
|
try {
|
|
userData = JSON.parse(userData);
|
|
if (userData.color === 'red' || userData.color === 'blue') {
|
|
this.color = userData.color;
|
|
} else {
|
|
print("ERROR, invalid color:", userData.color);
|
|
}
|
|
} catch (e) {
|
|
print("ERROR, could not find gun color");
|
|
}
|
|
},
|
|
startEquip: function(entityID, args) {
|
|
this.hand = args[0] === "left" ? 0 : 1;
|
|
},
|
|
continueEquip: function(entityID, args) {
|
|
if (this.cooldownActive) {
|
|
return;
|
|
}
|
|
|
|
var triggerValue = Controller.getValue(TRIGGER_CONTROLS[this.hand]);
|
|
if (triggerValue > TRIGGER_THRESHOLD) {
|
|
if (this.hasReleasedInitialTriggerPress) {
|
|
this.shootBall();
|
|
}
|
|
} else {
|
|
this.hasReleasedInitialTriggerPress = true;
|
|
}
|
|
},
|
|
releaseEquip: function(entityID, args) {
|
|
},
|
|
shootBall: function() {
|
|
if (this.cooldownActive) {
|
|
print("Not allowing portal bullet to be shot while cooldown active");
|
|
return;
|
|
}
|
|
Controller.triggerHapticPulse(10.0, 0.5, this.hand);
|
|
|
|
var gunProperties = Entities.getEntityProperties(this.entityID, ["position", "rotation"]);
|
|
|
|
var gunTipPosition = this.getGunTipPosition(gunProperties);
|
|
|
|
var audioProperties = {
|
|
volume: 0.9,
|
|
position: gunTipPosition,
|
|
localOnly: true
|
|
};
|
|
|
|
Audio.playSound(this.gunFireSound, audioProperties);
|
|
|
|
var forwardVec = Quat.getFront(Quat.multiply(gunProperties.rotation, Quat.fromPitchYawRollDegrees(0, 180, 0)));
|
|
forwardVec = Vec3.normalize(forwardVec);
|
|
forwardVec = Vec3.multiply(forwardVec, GUN_FORCE);
|
|
|
|
var projectileProperties = {
|
|
name: 'CTF/PortalBullet',
|
|
type: 'Model',
|
|
modelURL: this.color === 'blue' ? BULLET_BLUE_MODEL_URL : BULLET_RED_MODEL_URL,
|
|
dimensions: BALL_DIMENSIONS,
|
|
damping: BALL_LINEAR_DAMPING,
|
|
gravity: BALL_GRAVITY,
|
|
restitution: BALL_RESTITUTION,
|
|
density: BALL_DENSITY,
|
|
dynamic: true,
|
|
rotation: gunProperties.rotation,
|
|
position: gunTipPosition,
|
|
angularDamping: 0,
|
|
angularVelocity: BALL_ANGULAR_VEL,
|
|
velocity: forwardVec,
|
|
lifetime: 10,
|
|
collisionless: true,
|
|
visible: true
|
|
};
|
|
var projectileID = Entities.addEntity(projectileProperties);
|
|
|
|
var portalProperties = {
|
|
name: 'CTF/PortalCollider',
|
|
type: 'Sphere',
|
|
localPosition: { x: 0, y: 0, z: 0 },
|
|
dimensions: BALL_DIMENSIONS,
|
|
parentID: projectileID,
|
|
dynamic: false,
|
|
lifetime: 10,
|
|
visible: false,
|
|
script: Script.resolvePath("portalBulletClientEntity.js"),
|
|
collisionless: true,
|
|
userData: JSON.stringify({
|
|
//portalTargetLocation: "hifi://lionsgate.highfidelity.io/-104.376,-0.496867,-8.28224/0,0.721841,0,0.692059"
|
|
portalTargetLocation: "/16.0555,-0.372284,18.5259/0,0.631228,0,0.775597"
|
|
})
|
|
};
|
|
Entities.addEntity(portalProperties);
|
|
|
|
var self = this;
|
|
this.cooldownActive = true;
|
|
Script.setTimeout(function() {
|
|
var gunProperties = Entities.getEntityProperties(self.entityID, ["position", "rotation"]);
|
|
var gunTipPosition = self.getGunTipPosition(gunProperties);
|
|
var audioProperties = {
|
|
volume: 0.9,
|
|
position: gunTipPosition,
|
|
localOnly: true
|
|
};
|
|
Audio.playSound(self.gunLoadSound, audioProperties);
|
|
self.cooldownActive = false;
|
|
}, 1000);
|
|
},
|
|
getGunTipPosition: function(properties) {
|
|
// the tip of the gun is going to be in a different place than the center,
|
|
// so we move in space relative to the model to find that position
|
|
var frontVector = Quat.getFront(properties.rotation);
|
|
var frontOffset = Vec3.multiply(frontVector, GUN_TIP_FWD_OFFSET);
|
|
var upVector = Quat.getUp(properties.rotation);
|
|
var upOffset = Vec3.multiply(upVector, GUN_TIP_UP_OFFSET);
|
|
|
|
var gunTipPosition = Vec3.sum(properties.position, frontOffset);
|
|
gunTipPosition = Vec3.sum(gunTipPosition, upOffset);
|
|
|
|
return gunTipPosition;
|
|
},
|
|
createTipEntity: function(entityID) {
|
|
// for debugging where its going to shoot from
|
|
var gunProperties = Entities.getEntityProperties(entityID, ["position", "rotation"]);
|
|
|
|
var tipProps = {
|
|
name: 'Ping pong tip test',
|
|
dimensions: {
|
|
x: 0.1,
|
|
y: 0.1,
|
|
z: 0.1
|
|
},
|
|
color: {
|
|
red: 0,
|
|
green: 255,
|
|
blue: 0
|
|
},
|
|
type: 'Box',
|
|
parentID: entityID,
|
|
position: this.getGunTipPosition(gunProperties)
|
|
};
|
|
Entities.addEntity(tipProps);
|
|
}
|
|
};
|
|
|
|
// entity scripts should return a newly varructed object of our type
|
|
return new PortalGun();
|
|
});
|