diff --git a/unpublishedScripts/marketplace/boppo/boppoClownEntity.js b/unpublishedScripts/marketplace/boppo/boppoClownEntity.js new file mode 100644 index 0000000000..ef01e47f6f --- /dev/null +++ b/unpublishedScripts/marketplace/boppo/boppoClownEntity.js @@ -0,0 +1,80 @@ +// +// boppoClownEntity.js +// +// Created by Thijs Wenker on 3/15/17. +// Copyright 2017 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 +// + +/* globals BoppoClownEntity:true LookAtTarget */ + +(function() { + var SFX_PREFIX = 'http://hifi-content.s3-us-west-1.amazonaws.com/caitlyn/production/elBoppo/sfx/'; + var CHANNEL_PREFIX = 'io.highfidelity.boppo_server_'; + var PUNCH_SOUNDS = [ + 'punch_1.wav', + 'punch_2.wav' + ]; + var PUNCH_COOLDOWN = 300; + + Script.include(Script.resolvePath('lookAtEntity.js?v2')); + + BoppoClownEntity = function() { + var _this, + _entityID, + _boppoUserData, + _lookAtTarget, + _punchSounds = [], + _lastPlayedPunch = {}; + + var getOwnBoppoUserData = function() { + try { + return JSON.parse(Entities.getEntityProperties(_entityID, ['userData']).userData).Boppo; + } catch (e) { + // e + } + return {}; + }; + + BoppoClownEntity = function () { + _this = this; + PUNCH_SOUNDS.forEach(function(punch) { + _punchSounds.push(SoundCache.getSound(SFX_PREFIX + punch)); + }); + }; + + BoppoClownEntity.prototype = { + preload: function(entityID) { + _entityID = entityID; + _boppoUserData = getOwnBoppoUserData(); + _lookAtTarget = new LookAtTarget(_entityID); + }, + collisionWithEntity: function(boppoEntity, collidingEntity, collisionInfo) { + if (collisionInfo.type === 0 && + Entities.getEntityProperties(collidingEntity, ['name']).name.indexOf('Boxing Glove ') === 0) { + + if (_lastPlayedPunch[collidingEntity] === undefined || + Date.now() - _lastPlayedPunch[collidingEntity] > PUNCH_COOLDOWN) { + + // If boxing glove detected here: + Messages.sendMessage(CHANNEL_PREFIX + _boppoUserData.gameParentID, 'hit'); + + _lookAtTarget.lookAtByAction(); + var randomPunchIndex = Math.floor(Math.random() * _punchSounds.length); + Audio.playSound(_punchSounds[randomPunchIndex], { + position: collisionInfo.contactPoint + }); + _lastPlayedPunch[collidingEntity] = Date.now(); + } + } + } + + }; + + return new BoppoClownEntity(); + }; + + return new BoppoClownEntity(); +}); diff --git a/unpublishedScripts/marketplace/boppo/boppoServer.js b/unpublishedScripts/marketplace/boppo/boppoServer.js new file mode 100644 index 0000000000..ebe938c043 --- /dev/null +++ b/unpublishedScripts/marketplace/boppo/boppoServer.js @@ -0,0 +1,299 @@ +// +// boppoServer.js +// +// Created by Thijs Wenker on 3/15/17. +// Copyright 2017 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 +// + +/* globals BoppoServer:true */ + +(function() { + var SFX_PREFIX = 'http://hifi-content.s3-us-west-1.amazonaws.com/caitlyn/production/elBoppo/sfx/'; + var CLOWN_LAUGHS = [ + 'clown_laugh_1.wav', + 'clown_laugh_2.wav', + 'clown_laugh_3.wav', + 'clown_laugh_4.wav' + ]; + var TICK_TOCK_SOUND = 'ticktock%20-%20tock.wav'; + var BOXING_RING_BELL_START = 'boxingRingBell.wav'; + var BOXING_RING_BELL_END = 'boxingRingBell-end.wav'; + var BOPPO_MUSIC = 'boppoMusic.wav'; + var CHANNEL_PREFIX = 'io.highfidelity.boppo_server_'; + var MESSAGE_HIT = 'hit'; + var MESSAGE_ENTER_ZONE = 'enter-zone'; + var MESSAGE_UNLOAD_FIX = 'unload-fix'; + // don't set the search radius too high, it might remove boppo's from other nearby instances + var BOPPO_SEARCH_RADIUS = 4.0; + + var MILLISECONDS_PER_SECOND = 1000; + // Make sure the entities are loaded at startup (TODO: more solid fix) + var LOAD_TIMEOUT = 5000; + var SECONDS_PER_MINUTE = 60; + var DEFAULT_PLAYTIME = 30; // seconds + var BASE_TEN = 10; + var TICK_TOCK_FROM = 3; // seconds + var COOLDOWN_TIME_MS = MILLISECONDS_PER_SECOND * 3; + + BoppoServer = function() { + var _this, + _isInitialized = false, + _clownLaughs = [], + _musicInjector, + _music, + _laughingInjector, + _tickTockSound, + _boxingBellRingStart, + _boxingBellRingEnd, + _entityID, + _boppoClownID, + _channel, + _boppoEntities, + _isGameRunning, + _updateInterval, + _timeLeft, + _hits, + _coolDown; + + var getOwnBoppoUserData = function() { + try { + return JSON.parse(Entities.getEntityProperties(_entityID, ['userData']).userData).Boppo; + } catch (e) { + // e + } + return {}; + }; + + var updateBoppoEntities = function() { + Entities.getChildrenIDs(_entityID).forEach(function(entityID) { + try { + var userData = JSON.parse(Entities.getEntityProperties(entityID, ['userData']).userData); + if (userData.Boppo.type !== undefined) { + _boppoEntities[userData.Boppo.type] = entityID; + } + } catch (e) { + // e + } + }); + }; + + var clearUntrackedBoppos = function() { + var position = Entities.getEntityProperties(_entityID, ['position']).position; + Entities.findEntities(position, BOPPO_SEARCH_RADIUS).forEach(function(entityID) { + try { + if (JSON.parse(Entities.getEntityProperties(entityID, ['userData']).userData).Boppo.type === 'boppo') { + Entities.deleteEntity(entityID); + } + } catch (e) { + // e + } + }); + }; + + var updateTimerDisplay = function() { + if (_boppoEntities['timer']) { + var secondsString = _timeLeft % SECONDS_PER_MINUTE; + if (secondsString < BASE_TEN) { + secondsString = '0' + secondsString; + } + var minutesString = Math.floor(_timeLeft / SECONDS_PER_MINUTE); + Entities.editEntity(_boppoEntities['timer'], { + text: minutesString + ':' + secondsString + }); + } + }; + + var updateScoreDisplay = function() { + if (_boppoEntities['score']) { + Entities.editEntity(_boppoEntities['score'], { + text: 'SCORE: ' + _hits + }); + } + }; + + var playSoundAtBoxingRing = function(sound, properties) { + var _properties = properties ? properties : {}; + _properties['position'] = Entities.getEntityProperties(_entityID, ['position']).position; + // play beep + return Audio.playSound(sound, _properties); + }; + + var onUpdate = function() { + _timeLeft--; + + if (_timeLeft > 0 && _timeLeft <= TICK_TOCK_FROM) { + // play beep + playSoundAtBoxingRing(_tickTockSound); + } + if (_timeLeft === 0) { + if (_musicInjector !== undefined && _musicInjector.isPlaying()) { + _musicInjector.stop(); + _musicInjector = undefined; + } + playSoundAtBoxingRing(_boxingBellRingEnd); + _isGameRunning = false; + Script.clearInterval(_updateInterval); + _updateInterval = null; + _coolDown = true; + Script.setTimeout(function() { + _coolDown = false; + _this.resetBoppo(); + }, COOLDOWN_TIME_MS); + } + updateTimerDisplay(); + }; + + var onMessage = function(channel, message, sender) { + if (channel === _channel) { + if (message === MESSAGE_HIT) { + _this.hit(); + } else if (message === MESSAGE_ENTER_ZONE && !_isGameRunning) { + _this.resetBoppo(); + } else if (message === MESSAGE_UNLOAD_FIX && _isInitialized) { + _this.unload(); + } + } + }; + + BoppoServer = function () { + _this = this; + _hits = 0; + _boppoClownID = null; + _coolDown = false; + CLOWN_LAUGHS.forEach(function(clownLaugh) { + _clownLaughs.push(SoundCache.getSound(SFX_PREFIX + clownLaugh)); + }); + _tickTockSound = SoundCache.getSound(SFX_PREFIX + TICK_TOCK_SOUND); + _boxingBellRingStart = SoundCache.getSound(SFX_PREFIX + BOXING_RING_BELL_START); + _boxingBellRingEnd = SoundCache.getSound(SFX_PREFIX + BOXING_RING_BELL_END); + _music = SoundCache.getSound(SFX_PREFIX + BOPPO_MUSIC); + _boppoEntities = {}; + }; + + BoppoServer.prototype = { + preload: function(entityID) { + _entityID = entityID; + _channel = CHANNEL_PREFIX + entityID; + + Messages.sendLocalMessage(_channel, MESSAGE_UNLOAD_FIX); + Script.setTimeout(function() { + clearUntrackedBoppos(); + updateBoppoEntities(); + Messages.subscribe(_channel); + Messages.messageReceived.connect(onMessage); + _this.resetBoppo(); + _isInitialized = true; + }, LOAD_TIMEOUT); + }, + resetBoppo: function() { + if (_boppoClownID !== null) { + print('deleting boppo: ' + _boppoClownID); + Entities.deleteEntity(_boppoClownID); + } + var boppoBaseProperties = Entities.getEntityProperties(_entityID, ['position', 'rotation']); + _boppoClownID = Entities.addEntity({ + angularDamping: 0.0, + collisionSoundURL: 'http://hifi-content.s3.amazonaws.com/caitlyn/production/elBoppo/51460__andre-rocha-nascimento__basket-ball-01-bounce.wav', + collisionsWillMove: true, + compoundShapeURL: 'http://hifi-content.s3.amazonaws.com/caitlyn/production/elBoppo/bopo_phys.obj', + damping: 1.0, + density: 10000, + dimensions: { + x: 1.2668079137802124, + y: 2.0568051338195801, + z: 0.88563752174377441 + }, + dynamic: 1.0, + friction: 1.0, + gravity: { + x: 0, + y: -25, + z: 0 + }, + modelURL: 'http://hifi-content.s3.amazonaws.com/caitlyn/production/elBoppo/elBoppo3_VR.fbx', + name: 'El Boppo the Punching Bag Clown', + registrationPoint: { + x: 0.5, + y: 0, + z: 0.3 + }, + restitution: 0.99, + rotation: boppoBaseProperties.rotation, + position: Vec3.sum(boppoBaseProperties.position, + Vec3.multiplyQbyV(boppoBaseProperties.rotation, { + x: 0.08666179329156876, + y: -1.5698202848434448, + z: 0.1847127377986908 + })), + script: Script.resolvePath('boppoClownEntity.js'), + shapeType: 'compound', + type: 'Model', + userData: JSON.stringify({ + lookAt: { + targetID: _boppoEntities['lookAtThis'], + disablePitch: true, + disableYaw: false, + disableRoll: true, + clearDisabledAxis: true, + rotationOffset: { x: 0.0, y: 180.0, z: 0.0} + }, + Boppo: { + type: 'boppo', + gameParentID: _entityID + }, + grabbableKey: { + grabbable: false + } + }) + }); + updateBoppoEntities(); + _boppoEntities['boppo'] = _boppoClownID; + }, + laugh: function() { + if (_laughingInjector !== undefined && _laughingInjector.isPlaying()) { + return; + } + var randomLaughIndex = Math.floor(Math.random() * _clownLaughs.length); + _laughingInjector = Audio.playSound(_clownLaughs[randomLaughIndex], { + position: Entities.getEntityProperties(_boppoClownID, ['position']).position + }); + }, + hit: function() { + if (_coolDown) { + return; + } + if (!_isGameRunning) { + var boxingRingBoppoData = getOwnBoppoUserData(); + _updateInterval = Script.setInterval(onUpdate, MILLISECONDS_PER_SECOND); + _timeLeft = boxingRingBoppoData.playTimeSeconds ? parseInt(boxingRingBoppoData.playTimeSeconds) : + DEFAULT_PLAYTIME; + _isGameRunning = true; + _hits = 0; + playSoundAtBoxingRing(_boxingBellRingStart); + _musicInjector = playSoundAtBoxingRing(_music, {loop: true, volume: 0.6}); + } + _hits++; + updateTimerDisplay(); + updateScoreDisplay(); + _this.laugh(); + }, + unload: function() { + print('unload called'); + if (_updateInterval) { + Script.clearInterval(_updateInterval); + } + Messages.messageReceived.connect(onMessage); + Messages.unsubscribe(_channel); + Entities.deleteEntity(_boppoClownID); + print('endOfUnload'); + } + }; + + return new BoppoServer(); + }; + + return new BoppoServer(); +}); diff --git a/unpublishedScripts/marketplace/boppo/clownGloveDispenser.js b/unpublishedScripts/marketplace/boppo/clownGloveDispenser.js new file mode 100644 index 0000000000..42675d609a --- /dev/null +++ b/unpublishedScripts/marketplace/boppo/clownGloveDispenser.js @@ -0,0 +1,154 @@ +// +// clownGloveDispenser.js +// +// Created by Thijs Wenker on 8/2/16. +// Copyright 2016 High Fidelity, Inc. +// +// Based on examples/winterSmashUp/targetPractice/shooterPlatform.js +// +// 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 _this = this; + + var CHANNEL_PREFIX = 'io.highfidelity.boppo_server_'; + + var leftBoxingGlove = undefined; + var rightBoxingGlove = undefined; + + var inZone = false; + + var wearGloves = function() { + leftBoxingGlove = Entities.addEntity({ + position: MyAvatar.position, + collisionsWillMove: true, + dimensions: { + x: 0.24890634417533875, + y: 0.28214839100837708, + z: 0.21127720177173615 + }, + dynamic: true, + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + modelURL: "http://hifi-content.s3.amazonaws.com/caitlyn/production/elBoppo/LFT_glove_VR3.fbx", + name: "Boxing Glove - Left", + registrationPoint: { + x: 0.5, + y: 0, + z: 0.5 + }, + shapeType: "simple-hull", + type: "Model", + userData: JSON.stringify({ + grabbableKey: { + invertSolidWhileHeld: true + }, + wearable: { + joints: { + LeftHand: [ + {x: 0, y: 0.0, z: 0.02 }, + Quat.fromVec3Degrees({x: 0, y: 0, z: 0}) + ] + } + } + }) + }); + Messages.sendLocalMessage('Hifi-Hand-Grab', JSON.stringify({hand: 'left', entityID: leftBoxingGlove})); + // Allows teleporting while glove is wielded + Messages.sendLocalMessage('Hifi-Teleport-Ignore-Add', leftBoxingGlove); + + rightBoxingGlove = Entities.addEntity({ + position: MyAvatar.position, + collisionsWillMove: true, + dimensions: { + x: 0.24890634417533875, + y: 0.28214839100837708, + z: 0.21127720177173615 + }, + dynamic: true, + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + modelURL: "http://hifi-content.s3.amazonaws.com/caitlyn/production/elBoppo/RT_glove_VR2.fbx", + name: "Boxing Glove - Right", + registrationPoint: { + x: 0.5, + y: 0, + z: 0.5 + }, + shapeType: "simple-hull", + type: "Model", + userData: JSON.stringify({ + grabbableKey: { + invertSolidWhileHeld: true + }, + wearable: { + joints: { + RightHand: [ + {x: 0, y: 0.0, z: 0.02 }, + Quat.fromVec3Degrees({x: 0, y: 0, z: 0}) + ] + } + } + }) + }); + Messages.sendLocalMessage('Hifi-Hand-Grab', JSON.stringify({hand: 'right', entityID: rightBoxingGlove})); + // Allows teleporting while glove is wielded + Messages.sendLocalMessage('Hifi-Teleport-Ignore-Add', rightBoxingGlove); + }; + + var cleanUpGloves = function() { + if (leftBoxingGlove !== undefined) { + Entities.deleteEntity(leftBoxingGlove); + leftBoxingGlove = undefined; + } + if (rightBoxingGlove !== undefined) { + Entities.deleteEntity(rightBoxingGlove); + rightBoxingGlove = undefined; + } + }; + + var wearGlovesIfHMD = function() { + // cleanup your old gloves if they're still there (unlikely) + cleanUpGloves(); + if (HMD.active) { + wearGloves(); + } + }; + + _this.preload = function(entityID) { + HMD.displayModeChanged.connect(function() { + if (inZone) { + wearGlovesIfHMD(); + } + }); + }; + + _this.unload = function() { + cleanUpGloves(); + }; + + _this.enterEntity = function(entityID) { + inZone = true; + print('entered boxing glove dispenser entity'); + wearGlovesIfHMD(); + + // Reset boppo if game is not running: + var parentID = Entities.getEntityProperties(entityID, ['parentID']).parentID; + Messages.sendMessage(CHANNEL_PREFIX + parentID, 'enter-zone'); + }; + + _this.leaveEntity = function(entityID) { + inZone = false; + cleanUpGloves(); + }; + + _this.unload = _this.leaveEntity; +}); diff --git a/unpublishedScripts/marketplace/boppo/createElBoppo.js b/unpublishedScripts/marketplace/boppo/createElBoppo.js new file mode 100644 index 0000000000..6bef9bc0fd --- /dev/null +++ b/unpublishedScripts/marketplace/boppo/createElBoppo.js @@ -0,0 +1,426 @@ +// +// createElBoppo.js +// +// Created by Thijs Wenker on 3/17/17. +// Copyright 2017 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 +// + +/* globals SCRIPT_IMPORT_PROPERTIES */ + +var MODELS_PATH = 'http://hifi-content.s3.amazonaws.com/DomainContent/Welcome%20Area/production/models/boxingRing/'; +var SCRIPT_PATH = this.isCleanupAndSpawnScript ? + 'http://s3-us-west-1.amazonaws.com/hifi-content/thoys/dev/2017/elBoppo/' : + Script.resolvePath(''); +var WANT_CLEANUP_ON_SCRIPT_ENDING = false; + +var getCreatePosition = function() { + // can either return position defined by resetScript or avatar position + if (this.isCleanupAndSpawnScript) { + return SCRIPT_IMPORT_PROPERTIES.rootPosition; + } + return Vec3.sum(MyAvatar.position, {x: 1, z: -2}); +}; + +var boxingRing = Entities.addEntity({ + dimensions: { + x: 4.0584001541137695, + y: 4.0418000221252441, + z: 3.0490000247955322 + }, + modelURL: MODELS_PATH + 'assembled/boppoBoxingRingAssembly.fbx', + name: 'Boxing Ring Assembly', + rotation: { + w: 0.9996337890625, + x: -1.52587890625e-05, + y: -0.026230275630950928, + z: -4.57763671875e-05 + }, + position: getCreatePosition(), + scriptTimestamp: 1489612158459, + serverScripts: SCRIPT_PATH + 'boppoServer.js', + shapeType: 'static-mesh', + type: 'Model', + userData: JSON.stringify({ + Boppo: { + type: 'boxingring', + playTimeSeconds: 15 + } + }) +}); + +var boppoEntities = [ + { + dimensions: { + x: 0.36947935819625854, + y: 0.25536194443702698, + z: 0.059455446898937225 + }, + modelURL: MODELS_PATH + 'boxingGameSign/boppoSignFrame.fbx', + parentID: boxingRing, + localPosition: { + x: -1.0251024961471558, + y: 0.51661628484725952, + z: -1.1176263093948364 + }, + rotation: { + w: 0.996856689453125, + x: 0.013321161270141602, + y: 0.0024566650390625, + z: 0.078049898147583008 + }, + shapeType: 'box', + type: 'Model' + }, + { + dimensions: { + x: 0.33255371451377869, + y: 0.1812121719121933, + z: 0.0099999997764825821 + }, + lineHeight: 0.125, + name: 'Boxing Ring - High Score Board', + parentID: boxingRing, + localPosition: { + x: -1.0239436626434326, + y: 0.52212876081466675, + z: -1.0971509218215942 + }, + rotation: { + w: 0.9876401424407959, + x: 0.013046503067016602, + y: 0.0012359619140625, + z: 0.15605401992797852 + }, + text: '0:00', + textColor: { + blue: 0, + green: 0, + red: 255 + }, + type: 'Text', + userData: JSON.stringify({ + Boppo: { + type: 'timer' + } + }) + }, + { + dimensions: { + x: 0.50491130352020264, + y: 0.13274604082107544, + z: 0.0099999997764825821 + }, + lineHeight: 0.090000003576278687, + name: 'Boxing Ring - Score Board', + parentID: boxingRing, + localPosition: { + x: -0.77596306800842285, + y: 0.37797555327415466, + z: -1.0910623073577881 + }, + rotation: { + w: 0.9518122673034668, + x: 0.004237703513354063, + y: -0.0010041374480351806, + z: 0.30455198884010315 + }, + text: 'SCORE: 0', + textColor: { + blue: 0, + green: 0, + red: 255 + }, + type: 'Text', + userData: JSON.stringify({ + Boppo: { + type: 'score' + } + }) + }, + { + dimensions: { + x: 0.58153259754180908, + y: 0.1884911060333252, + z: 0.059455446898937225 + }, + modelURL: MODELS_PATH + 'boxingGameSign/boppoSignFrame.fbx', + parentID: boxingRing, + localPosition: { + x: -0.78200173377990723, + y: 0.35684797167778015, + z: -1.108180046081543 + }, + rotation: { + w: 0.97814905643463135, + x: 0.0040436983108520508, + y: -0.0005645751953125, + z: 0.20778214931488037 + }, + shapeType: 'box', + type: 'Model' + }, + { + dimensions: { + x: 4.1867804527282715, + y: 3.5065803527832031, + z: 5.6845207214355469 + }, + name: 'El Boppo the Clown boxing area & glove maker', + parentID: boxingRing, + localPosition: { + x: -0.012308252975344658, + y: 0.054641719907522202, + z: 0.98782551288604736 + }, + rotation: { + w: 1, + x: -1.52587890625e-05, + y: -1.52587890625e-05, + z: -1.52587890625e-05 + }, + script: SCRIPT_PATH + 'clownGloveDispenser.js', + shapeType: 'box', + type: 'Zone', + visible: false + }, + { + color: { + blue: 255, + green: 5, + red: 255 + }, + dimensions: { + x: 0.20000000298023224, + y: 0.20000000298023224, + z: 0.20000000298023224 + }, + name: 'LookAtBox', + parentID: boxingRing, + localPosition: { + x: -0.1772226095199585, + y: -1.7072629928588867, + z: 1.3122396469116211 + }, + rotation: { + w: 0.999969482421875, + x: 1.52587890625e-05, + y: 0.0043793916702270508, + z: 1.52587890625e-05 + }, + shape: 'Cube', + type: 'Box', + userData: JSON.stringify({ + Boppo: { + type: 'lookAtThis' + } + }) + }, + { + color: { + blue: 209, + green: 157, + red: 209 + }, + dimensions: { + x: 1.6913000345230103, + y: 1.2124500274658203, + z: 0.2572999894618988 + }, + name: 'boppoBackBoard', + parentID: boxingRing, + localPosition: { + x: -0.19500596821308136, + y: -1.1044719219207764, + z: -0.55993378162384033 + }, + rotation: { + w: 0.9807126522064209, + x: -0.19511711597442627, + y: 0.0085297822952270508, + z: 0.0016937255859375 + }, + shape: 'Cube', + type: 'Box', + visible: false + }, + { + color: { + blue: 0, + green: 0, + red: 255 + }, + dimensions: { + x: 1.8155574798583984, + y: 0.92306196689605713, + z: 0.51203572750091553 + }, + name: 'boppoBackBoard', + parentID: boxingRing, + localPosition: { + x: -0.11036647111177444, + y: -0.051978692412376404, + z: -0.79054081439971924 + }, + rotation: { + w: 0.9807431697845459, + x: 0.19505608081817627, + y: 0.0085602998733520508, + z: -0.0017547607421875 + }, + shape: 'Cube', + type: 'Box', + visible: false + }, + { + color: { + blue: 209, + green: 157, + red: 209 + }, + dimensions: { + x: 1.9941408634185791, + y: 1.2124500274658203, + z: 0.2572999894618988 + }, + name: 'boppoBackBoard', + localPosition: { + x: 0.69560068845748901, + y: -1.3840068578720093, + z: 0.059689953923225403 + }, + rotation: { + w: 0.73458456993103027, + x: -0.24113833904266357, + y: -0.56545358896255493, + z: -0.28734266757965088 + }, + shape: 'Cube', + type: 'Box', + visible: false + }, + { + color: { + blue: 82, + green: 82, + red: 82 + }, + dimensions: { + x: 8.3777303695678711, + y: 0.87573593854904175, + z: 7.9759469032287598 + }, + parentID: boxingRing, + localPosition: { + x: -0.38302639126777649, + y: -2.121284008026123, + z: 0.3699878454208374 + }, + rotation: { + w: 0.70711839199066162, + x: -7.62939453125e-05, + y: 0.70705735683441162, + z: -1.52587890625e-05 + }, + shape: 'Triangle', + type: 'Shape' + }, + { + color: { + blue: 209, + green: 157, + red: 209 + }, + dimensions: { + x: 1.889795184135437, + y: 0.86068248748779297, + z: 0.2572999894618988 + }, + name: 'boppoBackBoard', + parentID: boxingRing, + localPosition: { + x: -0.95167744159698486, + y: -1.4756947755813599, + z: -0.042313352227210999 + }, + rotation: { + w: 0.74004733562469482, + x: -0.24461740255355835, + y: 0.56044864654541016, + z: 0.27998781204223633 + }, + shape: 'Cube', + type: 'Box', + visible: false + }, + { + color: { + blue: 0, + green: 0, + red: 255 + }, + dimensions: { + x: 4.0720257759094238, + y: 0.50657749176025391, + z: 1.4769613742828369 + }, + name: 'boppo-stepsRamp', + parentID: boxingRing, + localPosition: { + x: -0.002939039608463645, + y: -1.9770187139511108, + z: 2.2165381908416748 + }, + rotation: { + w: 0.99252307415008545, + x: 0.12184333801269531, + y: -1.52587890625e-05, + z: -1.52587890625e-05 + }, + shape: 'Cube', + type: 'Box', + visible: false + }, + { + color: { + blue: 150, + green: 150, + red: 150 + }, + cutoff: 90, + dimensions: { + x: 5.2220535278320312, + y: 5.2220535278320312, + z: 5.2220535278320312 + }, + falloffRadius: 2, + intensity: 15, + name: 'boxing ring light', + parentID: boxingRing, + localPosition: { + x: -1.4094564914703369, + y: -0.36021926999092102, + z: 0.81797939538955688 + }, + rotation: { + w: 0.9807431697845459, + x: 1.52587890625e-05, + y: -0.19520866870880127, + z: -1.52587890625e-05 + }, + type: 'Light' + } +]; + +boppoEntities.forEach(function(entityProperties) { + entityProperties['parentID'] = boxingRing; + Entities.addEntity(entityProperties); +}); + +if (WANT_CLEANUP_ON_SCRIPT_ENDING) { + Script.scriptEnding.connect(function() { + Entities.deleteEntity(boxingRing); + }); +} diff --git a/unpublishedScripts/marketplace/boppo/lookAtEntity.js b/unpublishedScripts/marketplace/boppo/lookAtEntity.js new file mode 100644 index 0000000000..ba072814f2 --- /dev/null +++ b/unpublishedScripts/marketplace/boppo/lookAtEntity.js @@ -0,0 +1,98 @@ +// +// lookAtTarget.js +// +// Created by Thijs Wenker on 3/15/17. +// Copyright 2017 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 +// + +/* globals LookAtTarget:true */ + +LookAtTarget = function(sourceEntityID) { + /* private variables */ + var _this, + _options, + _sourceEntityID, + _sourceEntityProperties, + REQUIRED_PROPERTIES = ['position', 'rotation', 'userData'], + LOOK_AT_TAG = 'lookAtTarget'; + + LookAtTarget = function(sourceEntityID) { + _this = this; + _sourceEntityID = sourceEntityID; + _this.updateOptions(); + }; + + /* private functions */ + var updateEntitySourceProperties = function() { + _sourceEntityProperties = Entities.getEntityProperties(_sourceEntityID, REQUIRED_PROPERTIES); + }; + + var getUpdatedActionProperties = function() { + return { + targetRotation: _this.getLookAtRotation(), + angularTimeScale: 0.1, + ttl: 10 + }; + }; + + var getNewActionProperties = function() { + var newActionProperties = getUpdatedActionProperties(); + newActionProperties.tag = LOOK_AT_TAG; + return newActionProperties; + }; + + LookAtTarget.prototype = { + /* public functions */ + updateOptions: function() { + updateEntitySourceProperties(); + _options = JSON.parse(_sourceEntityProperties.userData).lookAt; + }, + getTargetPosition: function() { + return Entities.getEntityProperties(_options.targetID).position; + }, + getLookAtRotation: function() { + _this.updateOptions(); + + var newRotation = Quat.lookAt(_sourceEntityProperties.position, _this.getTargetPosition(), Vec3.UP); + if (_options.rotationOffset !== undefined) { + newRotation = Quat.multiply(newRotation, Quat.fromVec3Degrees(_options.rotationOffset)); + } + if (_options.disablePitch || _options.disableYaw || _options.disablePitch) { + var disabledAxis = _options.clearDisabledAxis ? Vec3.ZERO : + Quat.safeEulerAngles(_sourceEntityProperties.rotation); + var newEulers = Quat.safeEulerAngles(newRotation); + newRotation = Quat.fromVec3Degrees({ + x: _options.disablePitch ? disabledAxis.x : newEulers.x, + y: _options.disableYaw ? disabledAxis.y : newEulers.y, + z: _options.disableRoll ? disabledAxis.z : newEulers.z + }); + } + return newRotation; + }, + lookAtDirectly: function() { + Entities.editEntity(_sourceEntityID, {rotation: _this.getLookAtRotation()}); + }, + lookAtByAction: function() { + var actionIDs = Entities.getActionIDs(_sourceEntityID); + var actionFound = false; + actionIDs.forEach(function(actionID) { + if (actionFound) { + return; + } + var actionArguments = Entities.getActionArguments(_sourceEntityID, actionID); + if (actionArguments.tag === LOOK_AT_TAG) { + actionFound = true; + Entities.updateAction(_sourceEntityID, actionID, getUpdatedActionProperties()); + } + }); + if (!actionFound) { + Entities.addAction('spring', _sourceEntityID, getNewActionProperties()); + } + } + }; + + return new LookAtTarget(sourceEntityID); +};