// // boom.js // // An object with this entity script will blow up when clicked or grabbed, // throwing nearby objects flying. After a time period, it will return all the objects to their original positions. // // Created by Philip Rosedale on March 7, 2016 // Copyright 2016 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() { var entityID, wantDebug = true, BLAST_FORCE = 10, BLAST_RADIUS = 10, BLAST_STEPDOWN = 10.0, TIME_TILL_RESTORE = 10.0, NETWORK_MAX_ROUNDRIP_MSECS = 1000, COUNTDOWN_TIME_MSECS = 2000, ZERO_GRAVITY = { x: 0, y: 0, z: 0 }, FALL_GRAVITY = { x: 0, y: -4.0, z: 0 }, SOUND_BOOM = SoundCache.getSound("http://hifi-content.s3.amazonaws.com/alan/dev/Audio/bigboom_converted.wav"), SOUND_COUNTDOWN = SoundCache.getSound("https://s3.amazonaws.com/hifi-public/philip/countdown_converted.wav"), RED = { red: 255, green: 0, blue: 0 }, affected = [], state = "ready" function printDebug(message) { if (wantDebug) { print(message); } } function blowStuffUp(position, force, radius, stepdown, gravity) { var stuff = Entities.findEntities(position, radius); printDebug("Blowing " + stuff.length + " things up"); for (var i = 0; i < stuff.length; i++) { var properties = Entities.getEntityProperties(stuff[i]); if (!properties.locked && (stuff[i] != entityID)) { // Store original position affected.push({ entityID: stuff[i], position: properties.position, rotation: properties.rotation, gravity: properties.gravity, dynamic: properties.dynamic }); var diff = Vec3.subtract(Vec3.sum(properties.position, { x: 0, y: -stepdown, z: 0 }), position); var distance = Vec3.length(diff); var velocity = Vec3.sum(properties.velocity, Vec3.multiply(force, Vec3.normalize(diff))); var angularVelocity = { x: Math.random() * force, y: Math.random() * force, z: Math.random() * force }; Entities.editEntity(stuff[i], { dynamic: true, gravity: gravity, velocity: velocity, angularVelocity: angularVelocity }); } } } function replaceStuff() { if (state == "waitingToReplace") { printDebug("replace phase 1"); for (var i = 0; i < affected.length; i++) { // Set everything back the first time and non-dynamic, wait for a network RT Entities.editEntity(affected[i].entityID, { position: affected[i].position, rotation: affected[i].rotation, gravity: ZERO_GRAVITY, dynamic: false, velocity: { x: 0, y: 0, z: 0 }, angularVelocity: { x: 0, y: 0, z: 0 } }); } state = "replacePhase2"; Script.setTimeout(replaceStuff, NETWORK_MAX_ROUNDRIP_MSECS); } else { printDebug("replace phase 2"); for (var i = 0; i < affected.length; i++) { // After network RT, do it again with original dynamic state Entities.editEntity(affected[i].entityID, { position: affected[i].position, rotation: affected[i].rotation, gravity: affected[i].gravity, dynamic: affected[i].dynamic, velocity: { x: 0, y: 0, z: 0 }, angularVelocity: { x: 0, y: 0, z: 0 } }); } state = "ready"; affected = []; } } function maybeBlowUp() { if (state == "ready") { printDebug("start countdown"); var properties = Entities.getEntityProperties(entityID); Audio.playSound(SOUND_COUNTDOWN, { position: properties.position, volume: 1.0, loop: false }); state = "countdown"; Script.setTimeout(maybeBlowUp, COUNTDOWN_TIME_MSECS); } else if (state == "countdown") { // blow up printDebug("Explode!"); var properties = Entities.getEntityProperties(entityID); Entities.editEntity(entityID, { color: RED }); Audio.playSound(SOUND_BOOM, { position: properties.position, volume: 1.0, loop: false }); blowStuffUp(properties.position, BLAST_FORCE, BLAST_RADIUS, BLAST_STEPDOWN, FALL_GRAVITY); Script.setTimeout(replaceStuff, TIME_TILL_RESTORE * 1000); state = "waitingToReplace"; } } this.startNearGrab = function() { maybeBlowUp(); } this.mousePressOnEntity = function() { maybeBlowUp(); } this.preload = function(givenEntityID) { printDebug("load boom..."); entityID = givenEntityID; }; this.unload = function() { printDebug("Unload boom..."); }; });