mirror of
https://github.com/overte-org/overte.git
synced 2025-05-07 10:19:25 +02:00
970 lines
No EOL
36 KiB
JavaScript
970 lines
No EOL
36 KiB
JavaScript
//
|
|
// bow.js
|
|
//
|
|
// This script attaches to a bow that you can pick up with a hand controller. Load an arrow and then shoot it.
|
|
// Created by James B. Pollack @imgntn on 10/19/2015
|
|
// Copyright 2015 High Fidelity, Inc.
|
|
//
|
|
// Distributed under the Apache License, Version 2.0.
|
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
//
|
|
|
|
(function() {
|
|
|
|
Script.include("../../libraries/utils.js");
|
|
|
|
var NOTCH_ARROW_SOUND_URL = 'http://hifi-content.s3.amazonaws.com/james/bow_and_arrow/sounds/notch.wav?123';
|
|
var SHOOT_ARROW_SOUND_URL = 'http://hifi-content.s3.amazonaws.com/james/bow_and_arrow/sounds/String_release2.L.wav';
|
|
var STRING_PULL_SOUND_URL = 'http://hifi-content.s3.amazonaws.com/james/bow_and_arrow/sounds/Bow_draw.1.L.wav';
|
|
var ARROW_WHIZZ_SOUND_URL = 'http://hifi-content.s3.amazonaws.com/james/bow_and_arrow/sounds/whizz.wav';
|
|
//todo : multiple impact sounds
|
|
var ARROW_HIT_SOUND_URL = 'http://hifi-content.s3.amazonaws.com/james/bow_and_arrow/sounds/Arrow_impact1.L.wav'
|
|
var ARROW_DIMENSIONS = {
|
|
x: 0.02,
|
|
y: 0.02,
|
|
z: 0.64
|
|
};
|
|
|
|
var ZERO_VEC = {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
};
|
|
|
|
var LINE_ENTITY_DIMENSIONS = {
|
|
x: 1000,
|
|
y: 1000,
|
|
z: 1000
|
|
};
|
|
|
|
var ARROW_OFFSET = -0.36;
|
|
var ARROW_TIP_OFFSET = 0.32;
|
|
var ARROW_GRAVITY = {
|
|
x: 0,
|
|
y: -4.8,
|
|
z: 0
|
|
};
|
|
|
|
var ARROW_MODEL_URL = "http://hifi-content.s3.amazonaws.com/james/bow_and_arrow/models/newarrow_textured.fbx";
|
|
var ARROW_COLLISION_HULL_URL = "http://hifi-content.s3.amazonaws.com/james/bow_and_arrow/models/newarrow_collision_hull.obj";
|
|
|
|
var ARROW_DIMENSIONS = {
|
|
x: 0.02,
|
|
y: 0.02,
|
|
z: 0.64
|
|
};
|
|
|
|
|
|
var TOP_NOTCH_OFFSET = 0.6;
|
|
var BOTTOM_NOTCH_OFFSET = 0.6;
|
|
|
|
var LINE_DIMENSIONS = {
|
|
x: 5,
|
|
y: 5,
|
|
z: 5
|
|
};
|
|
|
|
var DRAW_STRING_THRESHOLD = 0.80;
|
|
|
|
var TARGET_LINE_LENGTH = 1;
|
|
|
|
var LEFT_TIP = 1;
|
|
var RIGHT_TIP = 3;
|
|
|
|
var NOTCH_DETECTOR_OFFSET_FORWARD = 0.08;
|
|
var NOTCH_DETECTOR_OFFSET_UP = 0.035;
|
|
|
|
var NOTCH_DETECTOR_DIMENSIONS = {
|
|
x: 0.05,
|
|
y: 0.05,
|
|
z: 0.05
|
|
};
|
|
|
|
var NOTCH_DETECTOR_DISTANCE = 0.1;
|
|
|
|
var SHOT_SCALE = {
|
|
min1: 0,
|
|
max1: 0.6,
|
|
min2: 1,
|
|
max2: 10
|
|
}
|
|
|
|
var BOW_SPATIAL_KEY = {
|
|
relativePosition: {
|
|
x: 0,
|
|
y: 0.06,
|
|
z: 0.11
|
|
},
|
|
relativeRotation: Quat.fromPitchYawRollDegrees(0, -90, 90)
|
|
}
|
|
|
|
var arrowTrackers = [];
|
|
|
|
var _this;
|
|
|
|
function Bow() {
|
|
_this = this;
|
|
return;
|
|
}
|
|
|
|
Bow.prototype = {
|
|
isGrabbed: false,
|
|
stringDrawn: false,
|
|
aiming: false,
|
|
arrowTipPosition: null,
|
|
preNotchString: null,
|
|
hasArrowNotched: false,
|
|
notchDetector: null,
|
|
arrow: null,
|
|
arrowIsBurning: false,
|
|
prePickupString: null,
|
|
stringData: {
|
|
currentColor: {
|
|
red: 255,
|
|
green: 255,
|
|
blue: 255
|
|
}
|
|
},
|
|
preload: function(entityID) {
|
|
print('preload bow')
|
|
this.entityID = entityID;
|
|
this.bowID = entityID;
|
|
this.stringPullSound = SoundCache.getSound(STRING_PULL_SOUND_URL);
|
|
this.shootArrowSound = SoundCache.getSound(SHOOT_ARROW_SOUND_URL);
|
|
this.arrowHitSound = SoundCache.getSound(ARROW_HIT_SOUND_URL);
|
|
this.arrowNotchSound = SoundCache.getSound(NOTCH_ARROW_SOUND_URL);
|
|
this.arrowWhizzSound = SoundCache.getSound(ARROW_WHIZZ_SOUND_URL);
|
|
this.createPreNotchString();
|
|
Script.update.connect(this.drawStringsBeforePickup);
|
|
|
|
},
|
|
|
|
unload: function() {
|
|
// Script.update.disconnect(this.updateArrowTrackers);
|
|
|
|
// while (arrowTrackers.length > 0) {
|
|
// var tracker = arrowTrackers.pop();
|
|
// tracker.childEntities.forEach(function(child) {
|
|
// Entities.deleteEntity(child);
|
|
// })
|
|
// tracker.childParticleSystems.forEach(function(child) {
|
|
// Entities.deleteEntity(child);
|
|
// })
|
|
// Entities.deleteEntity(tracker.arrowID);
|
|
// }
|
|
this.deleteStrings();
|
|
Entities.deleteEntity(this.notchDetector);
|
|
Entities.deleteEntity(this.preNotchString);
|
|
Entities.deleteEntity(this.arrow);
|
|
Script.update.disconnect(this.drawStringsBeforePickup);
|
|
|
|
},
|
|
|
|
setLeftHand: function() {
|
|
if (this.isGrabbed === true) {
|
|
return false;
|
|
}
|
|
this.hand = 'left';
|
|
},
|
|
|
|
setRightHand: function() {
|
|
if (this.isGrabbed === true) {
|
|
return false;
|
|
}
|
|
this.hand = 'right';
|
|
},
|
|
|
|
startNearGrab: function() {
|
|
if (this.isGrabbed === true) {
|
|
return false;
|
|
}
|
|
this.isGrabbed = true;
|
|
this.initialHand = this.hand;
|
|
|
|
setEntityCustomData('grabbableKey', this.entityID, {
|
|
turnOffOtherHand: true,
|
|
invertSolidWhileHeld: true,
|
|
spatialKey: BOW_SPATIAL_KEY
|
|
});
|
|
|
|
},
|
|
|
|
continueNearGrab: function() {
|
|
|
|
// print('collidable bow' + Entities.getEntityProperties(this.entityID, "collisionsWillMove").collisionsWillMove)
|
|
// print('collidable arrow' + Entities.getEntityProperties(this.arrow, "collisionsWillMove").collisionsWillMove)
|
|
// print('collidable notch' + Entities.getEntityProperties(this.notchDetector, "collisionsWillMove").collisionsWillMove)
|
|
// print('collidable topstring' + Entities.getEntityProperties(this.topString, "collisionsWillMove").collisionsWillMove)
|
|
// print('collidable bottomstring' + Entities.getEntityProperties(this.bottomString, "collisionsWillMove").collisionsWillMove)
|
|
// print('collidable prenotchstring' + Entities.getEntityProperties(this.preNotchString, "collisionsWillMove").collisionsWillMove)
|
|
|
|
this.bowProperties = Entities.getEntityProperties(this.entityID, ["position", "rotation", "userData"]);
|
|
|
|
this.updateNotchDetectorPosition();
|
|
|
|
// if (this.hasArrowNotched === false) {
|
|
// this.hasArrowNotched = true
|
|
|
|
// this.arrowIsBurning = false
|
|
// setEntityCustomData('grabbableKey', this.entityID, {
|
|
// turnOffOtherHand: true,
|
|
// invertSolidWhileHeld: true,
|
|
// spatialKey: BOW_SPATIAL_KEY
|
|
// });
|
|
// }
|
|
|
|
//create a string across the bow when we pick it up
|
|
// if (this.preNotchString === null) {
|
|
// this.createPreNotchString();
|
|
// }
|
|
|
|
if (this.preNotchString !== null && this.aiming === false) {
|
|
// print('DRAW PRE NOTCH STRING')
|
|
// this.drawPreNotchStrings();
|
|
// this.updateArrowAttachedToBow();
|
|
}
|
|
|
|
// create the notch detector that arrows will look for
|
|
if (this.notchDetector === null) {
|
|
this.createNotchDetector();
|
|
}
|
|
|
|
//if we have an arrow notched, then draw some new strings
|
|
// if (this.hasArrowNotched === true) {
|
|
if (this.aiming === true) {
|
|
Entities.editEntity(this.preNotchString, {
|
|
visible: false
|
|
})
|
|
} else {
|
|
Entities.editEntity(this.preNotchString, {
|
|
visible: true
|
|
})
|
|
}
|
|
//only test for strings now that an arrow is notched
|
|
|
|
this.checkStringHand();
|
|
|
|
// } else {
|
|
// // print('DONT DO ANYTHING')
|
|
// //otherwise, don't do much of anything.
|
|
|
|
// }
|
|
},
|
|
|
|
releaseGrab: function() {
|
|
print('RELEASE GRAB EVENT')
|
|
if (this.isGrabbed === true && this.hand === this.initialHand) {
|
|
this.isGrabbed = false;
|
|
this.stringDrawn = false;
|
|
this.deleteStrings();
|
|
setEntityCustomData('grabbableKey', this.entityID, {
|
|
turnOffOtherHand: false,
|
|
invertSolidWhileHeld: true,
|
|
spatialKey: BOW_SPATIAL_KEY
|
|
});
|
|
Entities.deleteEntity(this.notchDetector);
|
|
// Entities.deleteEntity(this.preNotchString);
|
|
Entities.deleteEntity(this.arrow);
|
|
this.aiming = false;
|
|
this.notchDetector = null;
|
|
this.hasArrowNotched = false;
|
|
// this.preNotchString = null;
|
|
|
|
}
|
|
},
|
|
|
|
createArrow: function() {
|
|
this.playArrowNotchSound();
|
|
|
|
var arrow = Entities.addEntity({
|
|
name: 'Hifi-Arrow',
|
|
type: 'Model',
|
|
modelURL: ARROW_MODEL_URL,
|
|
shapeType: 'compound',
|
|
compoundShapeURL: ARROW_COLLISION_HULL_URL,
|
|
dimensions: ARROW_DIMENSIONS,
|
|
position: this.bowProperties.position,
|
|
collisionsWillMove: false,
|
|
ignoreForCollisions: true,
|
|
collisionSoundURL: ARROW_HIT_SOUND_URL,
|
|
gravity: ARROW_GRAVITY,
|
|
damping: 0.01,
|
|
userData: JSON.stringify({
|
|
grabbableKey: {
|
|
invertSolidWhileHeld: true,
|
|
grabbable: false
|
|
}
|
|
})
|
|
|
|
});
|
|
var arrowProps = Entities.getEntityProperties(arrow)
|
|
Script.addEventHandler(arrow, "collisionWithEntity", function(entityA, entityB, collision) {
|
|
//have to reverse lookup the tracker by the arrow id to get access to the children
|
|
|
|
print('ARROW COLLIDED WITH::' + entityB);
|
|
print('NAME OF ENTITY:::' + Entities.getEntityProperties(entityB, "name").name)
|
|
|
|
});
|
|
|
|
return arrow
|
|
},
|
|
|
|
createStrings: function() {
|
|
this.createTopString();
|
|
this.createBottomString();
|
|
},
|
|
|
|
createTopString: function() {
|
|
var stringProperties = {
|
|
name: 'Hifi-Bow-Top-String',
|
|
type: 'Line',
|
|
position: Vec3.sum(this.bowProperties.position, TOP_NOTCH_OFFSET),
|
|
dimensions: LINE_DIMENSIONS,
|
|
collisionsWillMove: false,
|
|
ignoreForCollisions: true,
|
|
userData: JSON.stringify({
|
|
grabbableKey: {
|
|
grabbable: false
|
|
}
|
|
})
|
|
};
|
|
|
|
this.topString = Entities.addEntity(stringProperties);
|
|
},
|
|
|
|
createBottomString: function() {
|
|
var stringProperties = {
|
|
name: 'Hifi-Bow-Bottom-String',
|
|
type: 'Line',
|
|
position: Vec3.sum(this.bowProperties.position, BOTTOM_NOTCH_OFFSET),
|
|
dimensions: LINE_DIMENSIONS,
|
|
collisionsWillMove: false,
|
|
ignoreForCollisions: true,
|
|
userData: JSON.stringify({
|
|
grabbableKey: {
|
|
grabbable: false
|
|
}
|
|
})
|
|
};
|
|
|
|
this.bottomString = Entities.addEntity(stringProperties);
|
|
},
|
|
|
|
deleteStrings: function() {
|
|
Entities.deleteEntity(this.topString);
|
|
Entities.deleteEntity(this.bottomString);
|
|
},
|
|
|
|
updateStringPositions: function() {
|
|
// print('update string positions!!!')
|
|
var upVector = Quat.getUp(this.bowProperties.rotation);
|
|
var upOffset = Vec3.multiply(upVector, TOP_NOTCH_OFFSET);
|
|
var downVector = Vec3.multiply(-1, Quat.getUp(this.bowProperties.rotation));
|
|
var downOffset = Vec3.multiply(downVector, BOTTOM_NOTCH_OFFSET);
|
|
var backOffset = Vec3.multiply(-0.1, Quat.getFront(this.bowProperties.rotation));
|
|
|
|
var topStringPosition = Vec3.sum(this.bowProperties.position, upOffset);
|
|
this.topStringPosition = Vec3.sum(topStringPosition, backOffset);
|
|
var bottomStringPosition = Vec3.sum(this.bowProperties.position, downOffset);
|
|
this.bottomStringPosition = Vec3.sum(bottomStringPosition, backOffset);
|
|
|
|
Entities.editEntity(this.preNotchString, {
|
|
position: this.topStringPosition
|
|
});
|
|
|
|
Entities.editEntity(this.topString, {
|
|
position: this.topStringPosition
|
|
});
|
|
|
|
Entities.editEntity(this.bottomString, {
|
|
position: this.bottomStringPosition
|
|
});
|
|
|
|
},
|
|
|
|
drawStrings: function() {
|
|
|
|
this.updateStringPositions();
|
|
var lineVectors = this.getLocalLineVectors();
|
|
|
|
Entities.editEntity(this.topString, {
|
|
linePoints: [{
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
}, lineVectors[0]],
|
|
lineWidth: 5,
|
|
color: this.stringData.currentColor
|
|
});
|
|
|
|
Entities.editEntity(this.bottomString, {
|
|
linePoints: [{
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
}, lineVectors[1]],
|
|
lineWidth: 5,
|
|
color: this.stringData.currentColor
|
|
});
|
|
|
|
},
|
|
|
|
getLocalLineVectors: function() {
|
|
var topVector = Vec3.subtract(this.arrowRearPosition, this.topStringPosition);
|
|
var bottomVector = Vec3.subtract(this.arrowRearPosition, this.bottomStringPosition);
|
|
return [topVector, bottomVector];
|
|
},
|
|
|
|
drawStringsBeforePickup: function() {
|
|
_this.drawPreNotchStrings();
|
|
},
|
|
|
|
createPreNotchString: function() {
|
|
this.bowProperties = Entities.getEntityProperties(_this.entityID, ["position", "rotation", "userData"]);
|
|
|
|
var stringProperties = {
|
|
type: 'Line',
|
|
position: Vec3.sum(this.bowProperties.position, TOP_NOTCH_OFFSET),
|
|
dimensions: LINE_DIMENSIONS,
|
|
visible: true,
|
|
ignoreForCollisions: true,
|
|
collisionsWillMove: false,
|
|
userData: JSON.stringify({
|
|
grabbableKey: {
|
|
grabbable: false
|
|
}
|
|
})
|
|
};
|
|
|
|
this.preNotchString = Entities.addEntity(stringProperties);
|
|
},
|
|
|
|
drawPreNotchStrings: function() {
|
|
this.bowProperties = Entities.getEntityProperties(_this.entityID, ["position", "rotation", "userData"]);
|
|
|
|
|
|
this.updateStringPositions();
|
|
|
|
var downVector = Vec3.multiply(-1, Quat.getUp(this.bowProperties.rotation));
|
|
var downOffset = Vec3.multiply(downVector, BOTTOM_NOTCH_OFFSET * 2);
|
|
|
|
Entities.editEntity(this.preNotchString, {
|
|
name: 'Hifi-Pre-Notch-String',
|
|
linePoints: [{
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
}, Vec3.sum({
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
}, downOffset)],
|
|
lineWidth: 5,
|
|
color: this.stringData.currentColor,
|
|
});
|
|
},
|
|
|
|
checkStringHand: function() {
|
|
//invert the hands because our string will be held with the opposite hand of the first one we pick up the bow with
|
|
if (this.initialHand === 'left') {
|
|
this.getStringHandPosition = MyAvatar.getRightPalmPosition;
|
|
this.getStringHandRotation = MyAvatar.getRightPalmRotation;
|
|
this.getGrabHandPosition = MyAvatar.getLeftPalmPosition;
|
|
this.getGrabHandRotation = MyAvatar.getLeftPalmRotation;
|
|
this.stringTriggerAction = Controller.findAction("RIGHT_HAND_CLICK");
|
|
} else if (this.initialHand === 'right') {
|
|
this.getStringHandPosition = MyAvatar.getLeftPalmPosition;
|
|
this.getStringHandRotation = MyAvatar.getLeftPalmRotation;
|
|
this.getGrabHandPosition = MyAvatar.getRightPalmPosition;
|
|
this.getGrabHandRotation = MyAvatar.getRightPalmRotation;
|
|
this.stringTriggerAction = Controller.findAction("LEFT_HAND_CLICK");
|
|
}
|
|
|
|
this.triggerValue = Controller.getActionValue(this.stringTriggerAction);
|
|
// print('TRIGGER VALUE:::' + this.triggerValue)
|
|
|
|
if (this.triggerValue < DRAW_STRING_THRESHOLD && this.stringDrawn === true) {
|
|
|
|
// firing the arrow
|
|
print('HIT RELEASE LOOP IN CHECK')
|
|
|
|
this.hasArrowNotched = false;
|
|
this.aiming = false;
|
|
this.stringDrawn = false;
|
|
this.releaseArrow();
|
|
|
|
} else if (this.triggerValue >= DRAW_STRING_THRESHOLD && this.stringDrawn === true) {
|
|
// print('HIT CONTINUE LOOP IN CHECK')
|
|
this.aiming = true;
|
|
//continuing to aim the arrow
|
|
this.stringData.handPosition = this.getStringHandPosition();
|
|
this.stringData.handRotation = this.getStringHandRotation();
|
|
this.stringData.grabHandPosition = this.getGrabHandPosition();
|
|
this.stringData.grabHandRotation = this.getGrabHandRotation();
|
|
this.drawStrings();
|
|
this.updateArrowPositionInNotch();
|
|
|
|
} else if (this.triggerValue >= DRAW_STRING_THRESHOLD && this.stringDrawn === false) {
|
|
this.arrow = this.createArrow();
|
|
print('CREATE ARROW' + this.arrow);
|
|
// print('HIT START LOOP IN CHECK')
|
|
this.playStringPullSound();
|
|
|
|
//the first time aiming the arrow
|
|
this.stringDrawn = true;
|
|
this.createStrings();
|
|
// var arrowTracker = this.createArrowTracker(this.arrow);
|
|
// arrowTrackers.push(arrowTracker)
|
|
|
|
this.stringData.handPosition = this.getStringHandPosition();
|
|
this.stringData.handRotation = this.getStringHandRotation();
|
|
this.stringData.grabHandPosition = this.getGrabHandPosition();
|
|
|
|
this.stringData.grabHandRotation = this.getGrabHandRotation();
|
|
|
|
this.drawStrings();
|
|
this.updateArrowPositionInNotch();
|
|
|
|
}
|
|
},
|
|
|
|
setArrowTipPosition: function(arrowPosition, arrowRotation) {
|
|
var frontVector = Quat.getFront(arrowRotation);
|
|
var frontOffset = Vec3.multiply(frontVector, ARROW_TIP_OFFSET);
|
|
var arrowTipPosition = Vec3.sum(arrowPosition, frontOffset);
|
|
this.arrowTipPosition = arrowTipPosition;
|
|
return arrowTipPosition;
|
|
|
|
},
|
|
setArrowRearPosition: function(arrowPosition, arrowRotation) {
|
|
var frontVector = Quat.getFront(arrowRotation);
|
|
var frontOffset = Vec3.multiply(frontVector, -ARROW_TIP_OFFSET);
|
|
var arrowTipPosition = Vec3.sum(arrowPosition, frontOffset);
|
|
this.arrowRearPosition = arrowTipPosition;
|
|
return arrowTipPosition;
|
|
|
|
},
|
|
getArrowPosition: function() {
|
|
var arrowVector = Vec3.subtract(this.stringData.handPosition, this.stringData.grabHandPosition);
|
|
arrowVector = Vec3.normalize(arrowVector);
|
|
arrowVector = Vec3.multiply(arrowVector, ARROW_OFFSET);
|
|
var arrowPosition = Vec3.sum(this.stringData.grabHandPosition, arrowVector);
|
|
return arrowPosition;
|
|
},
|
|
|
|
updateArrowAttachedToBow: function() {
|
|
Entities.editEntity(this.arrow, {
|
|
position: this.notchDetectorPosition,
|
|
rotation: this.bowProperties.rotation
|
|
})
|
|
},
|
|
|
|
updateArrowPositionInNotch: function() {
|
|
//move it backwards
|
|
var handToNotch = Vec3.subtract(this.notchDetectorPosition, this.stringData.handPosition);
|
|
var pullBackDistance = Vec3.length(handToNotch);
|
|
|
|
if (pullBackDistance >= 0.6) {
|
|
pullBackDistance = 0.6;
|
|
}
|
|
|
|
var pullBackOffset = Vec3.multiply(handToNotch, -pullBackDistance);
|
|
var arrowPosition = Vec3.sum(this.notchDetectorPosition, pullBackOffset);
|
|
this.changeStringPullSoundVolume(pullBackDistance);
|
|
//move it forward a bit
|
|
var pushForwardOffset = Vec3.multiply(handToNotch, -ARROW_OFFSET);
|
|
var finalArrowPosition = Vec3.sum(arrowPosition, pushForwardOffset);
|
|
|
|
var arrowRotation = Quat.rotationBetween(Vec3.FRONT, handToNotch);
|
|
this.setArrowTipPosition(finalArrowPosition, arrowRotation);
|
|
this.setArrowRearPosition(finalArrowPosition, arrowRotation);
|
|
Entities.editEntity(this.arrow, {
|
|
position: finalArrowPosition,
|
|
rotation: arrowRotation
|
|
})
|
|
|
|
},
|
|
|
|
releaseArrow: function() {
|
|
print('RELEASE ARROW!!!')
|
|
|
|
var handToNotch = Vec3.subtract(this.notchDetectorPosition, this.stringData.handPosition);
|
|
var pullBackDistance = Vec3.length(handToNotch);
|
|
// if (pullBackDistance >= 0.6) {
|
|
// pullBackDistance = 0.6;
|
|
// }
|
|
|
|
var arrowRotation = Quat.rotationBetween(Vec3.FRONT, handToNotch);
|
|
|
|
print('HAND DISTANCE:: ' + pullBackDistance);
|
|
var arrowForce = this.scaleArrowShotStrength(pullBackDistance);
|
|
print('ARROW FORCE::' + arrowForce);
|
|
// handToNotch = Vec3.normalize(handToNotch)
|
|
//var forwardVec = handToNotch;
|
|
var forwardVec = Vec3.multiply(handToNotch, arrowForce);
|
|
//var forwardVec = Vec3.multiply(handToNotch, handToNotch);
|
|
var arrowProperties = {
|
|
// rotation: arrowRotation,
|
|
ignoreForCollisions: false,
|
|
collisionsWillMove: true,
|
|
velocity: forwardVec,
|
|
lifetime: 10
|
|
};
|
|
|
|
this.playShootArrowSound();
|
|
|
|
Entities.editEntity(this.arrow, arrowProperties);
|
|
|
|
var arrowStore = this.arrow;
|
|
this.arrow = null;
|
|
|
|
Entities.editEntity(this.preNotchString, {
|
|
visible: true
|
|
});
|
|
|
|
this.deleteStrings();
|
|
|
|
},
|
|
|
|
scaleArrowShotStrength: function(value) {
|
|
var min1 = SHOT_SCALE.min1;
|
|
var max1 = SHOT_SCALE.max1;
|
|
var min2 = SHOT_SCALE.min2;
|
|
var max2 = SHOT_SCALE.max2;
|
|
return min2 + (max2 - min2) * ((value - min1) / (max1 - min1));
|
|
},
|
|
|
|
createNotchDetector: function() {
|
|
print('CREATE NOTCH DETECTOR')
|
|
var detectorPosition;
|
|
var frontVector = Quat.getFront(this.bowProperties.rotation);
|
|
var notchVectorForward = Vec3.multiply(frontVector, NOTCH_DETECTOR_OFFSET_FORWARD);
|
|
var upVector = Quat.getUp(this.bowProperties.rotation);
|
|
var notchVectorUp = Vec3.multiply(upVector, NOTCH_DETECTOR_OFFSET_UP);
|
|
|
|
detectorPosition = Vec3.sum(this.bowProperties.position, notchVectorForward);
|
|
detectorPosition = Vec3.sum(detectorPosition, notchVectorUp);
|
|
|
|
var detectorProperties = {
|
|
name: 'Hifi-NotchDetector',
|
|
type: 'Box',
|
|
visible: false,
|
|
collisionsWillMove: false,
|
|
ignoreForCollisions: true,
|
|
dimensions: NOTCH_DETECTOR_DIMENSIONS,
|
|
position: detectorPosition,
|
|
color: {
|
|
red: 0,
|
|
green: 255,
|
|
blue: 0
|
|
}
|
|
};
|
|
|
|
this.notchDetector = Entities.addEntity(detectorProperties);
|
|
},
|
|
|
|
updateNotchDetectorPosition: function() {
|
|
var detectorPosition;
|
|
var frontVector = Quat.getFront(this.bowProperties.rotation);
|
|
var notchVectorForward = Vec3.multiply(frontVector, NOTCH_DETECTOR_OFFSET_FORWARD);
|
|
var upVector = Quat.getUp(this.bowProperties.rotation);
|
|
var notchVectorUp = Vec3.multiply(upVector, NOTCH_DETECTOR_OFFSET_UP);
|
|
|
|
detectorPosition = Vec3.sum(this.bowProperties.position, notchVectorForward);
|
|
detectorPosition = Vec3.sum(detectorPosition, notchVectorUp);
|
|
|
|
this.notchDetectorPosition = detectorPosition;
|
|
|
|
Entities.editEntity(this.notchDetector, {
|
|
position: this.notchDetectorPosition,
|
|
rotation: this.bowProperties.rotation
|
|
});
|
|
},
|
|
|
|
createFireParticleSystem: function() {
|
|
print('MAKING A FIRE')
|
|
//will probably need to dynamically update the orientation to match the arrow???
|
|
var myOrientation = Quat.fromPitchYawRollDegrees(-90, 0, 0.0);
|
|
|
|
var animationSettings = JSON.stringify({
|
|
fps: 30,
|
|
running: true,
|
|
loop: true,
|
|
firstFrame: 1,
|
|
lastFrame: 10000
|
|
});
|
|
|
|
var fire = Entities.addEntity({
|
|
type: "ParticleEffect",
|
|
name: "Hifi-Arrow-Fire",
|
|
animationSettings: animationSettings,
|
|
textures: "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png",
|
|
emitRate: 100,
|
|
position: MyAvatar.position,
|
|
colorStart: {
|
|
red: 70,
|
|
green: 70,
|
|
blue: 137
|
|
},
|
|
color: {
|
|
red: 200,
|
|
green: 99,
|
|
blue: 42
|
|
},
|
|
colorFinish: {
|
|
red: 255,
|
|
green: 99,
|
|
blue: 32
|
|
},
|
|
radiusSpread: 0.01,
|
|
radiusStart: 0.02,
|
|
radiusEnd: 0.001,
|
|
particleRadius: 0.15,
|
|
radiusFinish: 0.0,
|
|
emitOrientation: myOrientation,
|
|
emitSpeed: 0.3,
|
|
speedSpread: 0.1,
|
|
alphaStart: 0.05,
|
|
alpha: 0.1,
|
|
alphaFinish: 0.05,
|
|
emitDimensions: {
|
|
x: 0.5,
|
|
y: 0.5,
|
|
z: 0.1
|
|
},
|
|
polarFinish: 0.1,
|
|
emitAcceleration: {
|
|
x: 0.0,
|
|
y: 0.0,
|
|
z: 0.0
|
|
},
|
|
accelerationSpread: {
|
|
x: 0.1,
|
|
y: 0.01,
|
|
z: 0.1
|
|
},
|
|
lifespan: 0.5,
|
|
ignoreForCollisions: true,
|
|
collisionsWillMove: false,
|
|
});
|
|
|
|
return fire;
|
|
|
|
},
|
|
createArrowTracker: function(arrow, isBurning) {
|
|
print('in create arrow tracker:::' + arrow)
|
|
var _t = this;
|
|
|
|
// var isBurning = this.arrowIsBurning;
|
|
//delete this line below once debugging is done
|
|
var isBurning = isBurning || true;
|
|
var arrowTracker = {
|
|
arrowID: arrow,
|
|
// whizzingSound: _t.playWhizzSound(),
|
|
//fireSound: _t.createFireSound(),
|
|
hasPlayedCollisionSound: false,
|
|
glowBox: _t.createGlowBoxAsModel(),
|
|
fireParticleSystem: _t.createFireParticleSystem(),
|
|
childEntities: [],
|
|
childSounds: [],
|
|
childParticleSystems: [],
|
|
init: function() {
|
|
print('init arrow tracker')
|
|
this.setChildren();
|
|
|
|
},
|
|
setCollisionCallback: function() {
|
|
print('set arrow tracker callback' + this.arrowID)
|
|
|
|
Script.addEventHandler(this.arrowID, "collisionWithEntity", function(entityA, entityB, collision) {
|
|
//have to reverse lookup the tracker by the arrow id to get access to the children
|
|
var tracker = getArrowTrackerByArrowID(entityA);
|
|
Entities.deleteEntity(tracker.glowBox);
|
|
|
|
});
|
|
},
|
|
setChildren: function() {
|
|
print('set arrow tracker children')
|
|
// this.childSounds.push(this.whizzingSound);
|
|
// this.childSounds.push(this.fireSound);
|
|
this.childEntities.push(this.glowBox);
|
|
this.childParticleSystems.push(this.fireParticleSystem);
|
|
},
|
|
updateChildEntities: function(arrowID) {
|
|
var arrowProperties = Entities.getEntityProperties(this.arrowID, ["position", "rotation"]);
|
|
_t.setArrowTipPosition(arrowProperties.position, arrowProperties.rotation);
|
|
_t.setArrowRearPosition(arrowProperties.position, arrowProperties.rotation);
|
|
//update the positions
|
|
// this.soundEntities.forEach(function(injector) {
|
|
// var audioProperties = {
|
|
// volume: 0.25,
|
|
// position: arrowProperties.position
|
|
// };
|
|
// injector.options = audioProperties;
|
|
// })
|
|
|
|
this.childEntities.forEach(function(child) {
|
|
Entities.editEntity(child, {
|
|
position: arrowProperties.position,
|
|
rotation: arrowProperties.rotation
|
|
})
|
|
})
|
|
|
|
this.childParticleSystems.forEach(function(child) {
|
|
Entities.editEntity(child, {
|
|
position: _t.arrowTipPosition
|
|
})
|
|
})
|
|
|
|
}
|
|
};
|
|
arrowTracker.init();
|
|
arrowTracker.setCollisionCallback();
|
|
|
|
return arrowTracker
|
|
},
|
|
createFireBurningSound: function() {
|
|
var audioProperties = {
|
|
volume: 0.25,
|
|
position: this.bowProperties.position,
|
|
loop: true
|
|
};
|
|
|
|
var injector = Audio.playSound(this.fireBurningSound, audioProperties);
|
|
|
|
return injector
|
|
},
|
|
createGlowBoxAsModel: function() {
|
|
var GLOW_MODEL_URL = 'http://hifi-content.s3.amazonaws.com/james/bow_and_arrow/models/glow.fbx';
|
|
var properties = {
|
|
name: 'Hifi-Arrow-Glow-Model',
|
|
type: 'Model',
|
|
modelURL: GLOW_MODEL_URL,
|
|
dimensions: ARROW_DIMENSIONS,
|
|
collisionsWillMove: false,
|
|
ignoreForCollisions: true,
|
|
userData: JSON.stringify({
|
|
grabbableKey: {
|
|
grabbable: false
|
|
}
|
|
})
|
|
}
|
|
var glowBox = Entities.addEntity(properties);
|
|
return glowBox
|
|
},
|
|
createGlowBox: function() {
|
|
print('creating glow box')
|
|
var shaderUrl = Script.resolvePath('../../shaders/exampleV2.fs');
|
|
var properties = {
|
|
name: 'Hifi-Arrow-Glow',
|
|
type: 'Box',
|
|
dimensions: ARROW_DIMENSIONS,
|
|
collisionsWillMove: false,
|
|
ignoreForCollisions: true,
|
|
color: {
|
|
red: 255,
|
|
green: 0,
|
|
blue: 255
|
|
},
|
|
//i want to use shader but for some reason its white... need to fix;
|
|
|
|
|
|
// userData: JSON.stringify({
|
|
// "grabbableKey": {
|
|
// grabbable: false
|
|
// },
|
|
// "ProceduralEntity": {
|
|
// "shaderUrl": shaderUrl,
|
|
// // V2 and onwards, shaders must include a version identifier, or they will default
|
|
// // to V1 behavior
|
|
// "version": 2,
|
|
// // Any values specified here will be passed on to uniforms with matching names in
|
|
// // the shader. Only numbers and arrays of length 1-4 of numbers are supported.
|
|
// //
|
|
// // The size of the data must match the size of the uniform:
|
|
// // a number or 1 value array = 'uniform float'
|
|
// // 2 value array = 'uniform vec2'
|
|
// // 3 value array = 'uniform vec3'
|
|
// // 4 value array = 'uniform vec4'
|
|
// //
|
|
// // Uniforms should always be declared in the shader with a default value
|
|
// // or failure to specify the value here will result in undefined behavior.
|
|
// "uniforms": {
|
|
// // uniform float iSpeed = 1.0;
|
|
// "iSpeed": 2.0,
|
|
// // uniform vec3 iSize = vec3(1.0);
|
|
// "iSize": [1.0, 2.0, 4.0]
|
|
// }
|
|
// }
|
|
// })
|
|
}
|
|
var glowBox = Entities.addEntity(properties);
|
|
return glowBox
|
|
},
|
|
updateArrowTrackers: function() {
|
|
// print('updating arrow trackers:::' + arrowTrackers.length);
|
|
arrowTrackers.forEach(function(tracker) {
|
|
var arrowID = tracker.arrowID;
|
|
tracker.updateChildEntities(arrowID);
|
|
})
|
|
},
|
|
playStringPullSound: function() {
|
|
var audioProperties = {
|
|
volume: 0.25,
|
|
position: this.bowProperties.position
|
|
};
|
|
this.stringPullInjector = Audio.playSound(this.stringPullSound, audioProperties);
|
|
},
|
|
playShootArrowSound: function(sound) {
|
|
var audioProperties = {
|
|
volume: 0.25,
|
|
position: this.bowProperties.position
|
|
};
|
|
Audio.playSound(this.shootArrowSound, audioProperties);
|
|
},
|
|
playArrowHitSound: function(position) {
|
|
var audioProperties = {
|
|
volume: 0.25,
|
|
position: position
|
|
};
|
|
Audio.playSound(this.arrowHitSound, audioProperties);
|
|
},
|
|
playArrowNotchSound: function() {
|
|
print('play arrow notch sound')
|
|
var audioProperties = {
|
|
volume: 0.25,
|
|
position: this.bowProperties.position
|
|
};
|
|
Audio.playSound(this.arrowNotchSound, audioProperties);
|
|
},
|
|
playArrowWhizzSound: function() {
|
|
|
|
var audioProperties = {
|
|
volume: 0.0,
|
|
position: this.bowProperties.position
|
|
};
|
|
var injector = Audio.playSound(this.arrowWhizzSound, audioProperties);
|
|
|
|
return injector
|
|
},
|
|
changeStringPullSoundVolume: function(pullBackDistance) {
|
|
var audioProperties = {
|
|
volume: 0.25,
|
|
position: this.bowProperties.position
|
|
}
|
|
|
|
this.stringPullInjector.options = audioProperties
|
|
}
|
|
|
|
|
|
};
|
|
|
|
getArrowTrackerByArrowID = function(arrowID) {
|
|
var result = arrowTrackers.filter(function(tracker) {
|
|
return tracker.arrowID === arrowID;
|
|
});
|
|
var tracker = result[0]
|
|
return tracker
|
|
}
|
|
return new Bow();
|
|
}); |