1020 lines
No EOL
40 KiB
JavaScript
1020 lines
No EOL
40 KiB
JavaScript
// ACmoneyTree.js
|
|
|
|
// Created by Mark Brosche on 10-18-2018
|
|
// Copyright 2018 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
|
|
//
|
|
/* global EventBridge Users AccountServices Agent Avatar EntityViewer */
|
|
|
|
|
|
(function(){
|
|
var googleURL = "https://script.google.com/a/highfidelity.io/macros/s/AKfycbxvLCGJwYKGOlszXwm2m-Xa1U90RmnIEJiD6nD7Z8-1RlZaADY/exec";
|
|
var request = Script.require('./modules/request.js').request;
|
|
|
|
// The Metaverse to use
|
|
var HIFI_METAVERSE_URL = "https://highfidelity.com";
|
|
// The Recent Economic Activity endpoint on the High Fidelity Metaverse
|
|
var HIFI_HISTORY_ENDPOINT_URL = HIFI_METAVERSE_URL + "/api/v1/commerce/history";
|
|
// The Redmption endpoint on the High Fidelity Metaverse
|
|
var HIFI_REDEMPTION_ENDPOINT_URL = HIFI_METAVERSE_URL + "/api/v1/commerce/redeem";
|
|
|
|
var AVERAGE_INTERVAL = 1.5, // one and a half minutes
|
|
AVERAGE_HFC_AMOUNT = 10,
|
|
STANDARD_DEVIATION = 5,
|
|
SHOW_TIME_LENGTH = 60000, // One minute
|
|
RECIPIENT_MAX = 3,
|
|
MONEY_TREE_CHANNEL = "MoneyTreeChannel",
|
|
AC_SCRIPT_RUN = true,
|
|
SEARCH_CENTER = {"x": 0,"y":0,"z":0},
|
|
SEARCH_AREA= 1000;
|
|
|
|
var counterText,
|
|
activeText,
|
|
targetGiver = [],
|
|
targetRecipients = [],
|
|
payOnce = false,
|
|
randomHFCAmount = null,
|
|
userList= [],
|
|
coin = [],
|
|
interval = null,
|
|
indexGiver,
|
|
bankers = [],
|
|
treeOn = true,
|
|
tempList,
|
|
messageHandler,
|
|
power,
|
|
octreeInterval;
|
|
|
|
var approvedBankerList = [
|
|
"markb",
|
|
"ryan"
|
|
];
|
|
|
|
var staffList = [
|
|
"b",
|
|
"Jazmin",
|
|
"marko8904",
|
|
"mhard",
|
|
"theo",
|
|
"adamisawake",
|
|
"Aitolda",
|
|
"Alan_",
|
|
"alt.howard",
|
|
"amantley",
|
|
"amer",
|
|
"amukul",
|
|
"AndrewNyan",
|
|
"andy_batman",
|
|
"antoninas",
|
|
"asbecker8",
|
|
"Ashleigh_Harris",
|
|
"Becky",
|
|
"BenB",
|
|
"bimyou",
|
|
"birarda",
|
|
"c",
|
|
"Caitlyn",
|
|
"ChangX",
|
|
"Cheetah_Pattern",
|
|
"Clement",
|
|
"dantescalves",
|
|
"dback",
|
|
"diogenes",
|
|
"dogbones",
|
|
"emily",
|
|
"Emily_Sykes",
|
|
"emilythethird",
|
|
"Firebird25",
|
|
"freidrica",
|
|
"GoofyGoober",
|
|
"hifiDave",
|
|
"hifi_jamil",
|
|
"HifiJaz",
|
|
"hifimarko",
|
|
"HiFiMicki",
|
|
"High.Fidelity",
|
|
"howard.stearns",
|
|
"huffman",
|
|
"huffman2",
|
|
"hyperlogic",
|
|
"ingerjm0",
|
|
"JeffClinton",
|
|
"Jess",
|
|
"Jherico",
|
|
"john.highfidelity",
|
|
"JSON",
|
|
"jyoum",
|
|
"Kayla_HF",
|
|
"kencooke",
|
|
"kkurian",
|
|
"lameboycool",
|
|
"leviathan",
|
|
"luiscuenca",
|
|
"markb",
|
|
"maspring",
|
|
"miladn",
|
|
"mold",
|
|
"MissLiviRose",
|
|
"nbaldassini",
|
|
"Nik",
|
|
"Nissim",
|
|
"nvrndr",
|
|
"OneLisa",
|
|
"ovohightower",
|
|
"philip",
|
|
"r3tk0n",
|
|
"realMissLiviRose",
|
|
"rickcarr044",
|
|
"Roxie",
|
|
"Sabrina",
|
|
"sam",
|
|
"SamGondelman",
|
|
"sbbsteam",
|
|
"sbirarda",
|
|
"Sean",
|
|
"seanjones2848",
|
|
"serling",
|
|
"sethalves",
|
|
"shanzam",
|
|
"simon_walton",
|
|
"sophocles",
|
|
"TheBanker",
|
|
"thoys",
|
|
"WadeWatts",
|
|
"wayne",
|
|
"yoHighness",
|
|
"Ypsilanti",
|
|
"zack_hifi",
|
|
"ZappoMan",
|
|
"zfox",
|
|
"zfox1",
|
|
"zeenai",
|
|
"Battery",
|
|
"conference2",
|
|
"conference3",
|
|
"demo1",
|
|
"demo2",
|
|
"Langton",
|
|
"market",
|
|
"purchases",
|
|
"Anton.von.Trier",
|
|
"kitchen",
|
|
"mic1",
|
|
"mic2",
|
|
"ejahner",
|
|
"Freyja",
|
|
"qligmaloney",
|
|
"userTest",
|
|
"highfidelity",
|
|
"ryan",
|
|
"siphnos",
|
|
"ephesos",
|
|
"pytho",
|
|
"skelina"
|
|
];
|
|
|
|
if (AC_SCRIPT_RUN) {
|
|
Agent.isAvatar = true;
|
|
Avatar.skeletonModelURL = 'http://hifi-content.s3.amazonaws.com/ozan/dev/avatars/invisible_avatar/invisible_avatar.fst';
|
|
Avatar.displayName = "Money Tree Agent";
|
|
Avatar.position = {"x":-19.109256744384766,"y":-20.8349714279174805,"z":-11.181184768676758}; // Tree Position
|
|
|
|
var initialized = false;
|
|
|
|
var update = function(deltaTime) {
|
|
if (!initialized) {
|
|
if (Entities.serversExist() && Entities.canRez()) {
|
|
Entities.setPacketsPerSecond(6000);
|
|
EntityViewer.setPosition(SEARCH_CENTER);
|
|
EntityViewer.setCenterRadius(SEARCH_AREA);
|
|
// This should allow us to see nano-scale entities from great distances
|
|
EntityViewer.setVoxelSizeScale(Number.MAX_VALUE);
|
|
octreeInterval = Script.setInterval(function() {
|
|
EntityViewer.queryOctree();
|
|
}, 1000);
|
|
|
|
initialized = true;
|
|
Script.update.disconnect(update);
|
|
}
|
|
}
|
|
};
|
|
|
|
Script.update.connect(update);
|
|
|
|
Script.setTimeout(function(){
|
|
try {
|
|
Entities.deleteEntity(Entities.findEntitiesByName("Money Tree Counter", SEARCH_CENTER, SEARCH_AREA)[0]);
|
|
Entities.deleteEntity(Entities.findEntitiesByName("Money Tree Status", SEARCH_CENTER, SEARCH_AREA)[0]);
|
|
Entities.deleteEntity(Entities.findEntitiesByName("Power Button Spawner", SEARCH_CENTER, SEARCH_AREA)[0]);
|
|
console.log("[MONEY TREE] deleted stuff");
|
|
} catch (e) {
|
|
console.log("[MONEY TREE] could not find and delete anything");
|
|
}
|
|
|
|
counterText = Entities.addEntity({
|
|
type: "Text",
|
|
dimensions: { x: 0.3, y: 0.1854, z: 0.01 },
|
|
lineHeight: 0.125,
|
|
text: "-",
|
|
textColor: {"red": 255, "green": 255, "blue": 255},
|
|
backgroundColor: {"red": 0, "green": 0, "blue": 0},
|
|
name: "Money Tree Counter",
|
|
position: {"x":-17.9620418548584,"y":-10.537128448486328,"z":-10.67333984375},
|
|
rotation: {"x":-0.16071832180023193,"y":0.6887953877449036,"z":0.1588284969329834,"w":0.6887840032577515},
|
|
visible: true,
|
|
collisionless: true,
|
|
userData: "{ \"grabbableKey\": { \"grabbable\": false, \"kinematic\": false } }"
|
|
});
|
|
|
|
activeText = Entities.addEntity({
|
|
type: "Text",
|
|
dimensions: { x: 0.7585, y: 0.1695, z: 0.01 },
|
|
lineHeight: 0.115,
|
|
text: "STARTING...",
|
|
textColor: {"red": 255, "green": 255, "blue": 255},
|
|
backgroundColor: {"red": 0, "green": 0, "blue": 0},
|
|
name: "Money Tree Status",
|
|
position: {"x":-17.9667,"y":-10.5250,"z":-11.4147},
|
|
rotation: {"x":-0.15957793593406677,"y":0.6889334321022034,"z":0.1589823216199875,"w":0.6888881921768188},
|
|
visible: true,
|
|
collisionless: true,
|
|
userData: "{ \"grabbableKey\": { \"grabbable\": false, \"kinematic\": false } }"
|
|
});
|
|
|
|
messageHandler = function(channel, message, senderUUID, localOnly) {
|
|
if (channel !== MONEY_TREE_CHANNEL) {
|
|
print("not on channel");
|
|
return;
|
|
} else {
|
|
message = JSON.parse(message);
|
|
}
|
|
if (message.type === 'moneyGiven') {
|
|
if (senderUUID === targetGiver.nodeID){
|
|
for (var i = 0; i < targetRecipients.length; i++) {
|
|
if (message.recipientID === targetRecipients[i].nodeID && payOnce === false){
|
|
payOnce = true;
|
|
sendInput(targetRecipients[i].username);
|
|
spawnReceiverMessage(targetRecipients[i].nodeID, randomHFCAmount);
|
|
Entities.editEntity(activeText, {text: "WAITING..."});
|
|
Script.setTimeout(function(){
|
|
payOnce = false;
|
|
}, SHOW_TIME_LENGTH);
|
|
}
|
|
}
|
|
}
|
|
} else if (message.type === 'tree power') {
|
|
treeOn = message.state;
|
|
console.log("[MONEY TREE] tree state: ", treeOn);
|
|
if (treeOn === true) {
|
|
if (interval){
|
|
Script.clearInterval(interval);
|
|
}
|
|
startTree();
|
|
Entities.editEntity(activeText, {text: "STARTING..."});
|
|
} else {
|
|
if (interval){
|
|
Script.clearInterval(interval);
|
|
console.log("[MONEY TREE] money tree stopping soon");
|
|
}
|
|
Entities.editEntity(activeText, {text: "OUT OF ORDER"});
|
|
}
|
|
} else if (message.type === 'entering') {
|
|
var nameOnList = false;
|
|
var bankerOnList = false;
|
|
for ( var i = 0; i < approvedBankerList.length; i++) {
|
|
if (message.username === approvedBankerList[i]) {
|
|
for (var i = 0; i < bankers.length; i++) {
|
|
if ( message.username === bankers[i].username) {
|
|
bankerOnList = true;
|
|
}
|
|
}
|
|
if (!bankerOnList) {
|
|
bankers.push({
|
|
username: message.username,
|
|
nodeID: message.nodeID
|
|
});
|
|
bankerOverlay(bankers.length-1);
|
|
bankerOnList = true;
|
|
}
|
|
Entities.editEntity(counterText, {text: userList.length});
|
|
var activeRead = Entities.getEntityProperties(activeText, ['text']);
|
|
if (userList.length > 3 && activeRead.text === "MOAR PPL PLZ") {
|
|
Entities.editEntity(activeText, {text: "K LET'$ GROW!"});
|
|
}
|
|
}
|
|
}
|
|
for (var i = 0; i < userList.length; i++) {
|
|
if (message.username === userList[i].username) {
|
|
nameOnList = true;
|
|
}
|
|
}
|
|
if (!nameOnList) {
|
|
userList.push({
|
|
username: message.username,
|
|
nodeID: message.nodeID,
|
|
staff: false
|
|
});
|
|
for (var staff = 0; staff < staffList.length; staff++) {
|
|
if (message.username === staffList[staff]){
|
|
userList[userList.length-1].staff = true;
|
|
}
|
|
}
|
|
Entities.editEntity(counterText, {text: userList.length});
|
|
console.log("[MONEY TREE] user list length: ", userList.length);
|
|
var activeRead = Entities.getEntityProperties(activeText, ['text']);
|
|
if (userList.length >= 3 && activeRead.text === "MOAR PPL PLZ") {
|
|
Entities.editEntity(activeText, {text: "K LET'$ GROW!"});
|
|
} else if (userList.length < 3) {
|
|
Entities.editEntity(activeText, {text: "MOAR PPL PLZ"});
|
|
}
|
|
}
|
|
} else if (message.type === 'leaving') {
|
|
try {
|
|
for ( var i = 0; i < bankers.length; i++) {
|
|
if (message.username === bankers[i].username) {
|
|
bankers.splice(i, 1)[0];
|
|
Entities.deleteEntity(power);
|
|
if (!treeOn) {
|
|
Messages.sendMessage(MONEY_TREE_CHANNEL, JSON.stringify({
|
|
type: "delete power"
|
|
}));
|
|
if (power) {
|
|
var buttons = Entities.findEntitiesByName("Power Button Spawner", { x: -16.9779, y: -10.3132, z: -10.7944 }, 10);
|
|
for (var i = 0; i < buttons.length; i++) {
|
|
Entities.deleteEntity(buttons[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (var i = 0; i < userList.length; i++) {
|
|
if (message.username === userList[i].username) {
|
|
userList.splice(i, 1)[0];
|
|
Entities.editEntity(counterText, {text: userList.length});
|
|
i--;
|
|
if (userList.length < 3) {
|
|
Entities.editEntity(activeText, {text: "RESTING"});
|
|
}
|
|
}
|
|
}
|
|
} catch (e) {
|
|
print("[MONEY TREE] Error in retrieving username for deletion");
|
|
return;
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
Messages.messageReceived.connect(messageHandler);
|
|
Messages.subscribe(MONEY_TREE_CHANNEL);
|
|
|
|
try {
|
|
for (var i = 0; i < userList.length; i++) {
|
|
if (userList[i].username == "") {
|
|
userList.splice(i, 1)[0];
|
|
}
|
|
}
|
|
} catch (e) {
|
|
print("[MONEY TREE] userList error");
|
|
return;
|
|
}
|
|
}, 1500);
|
|
}
|
|
|
|
function bankerOverlay(index){
|
|
if (power){
|
|
var buttons = Entities.findEntitiesByName("Power Button Spawner", { x: -16.9779, y: -10.3132, z: -10.7944 }, 10);
|
|
for (var i = 0; i < buttons.length; i++) {
|
|
Entities.deleteEntity(buttons[i]);
|
|
}
|
|
Entities.deleteEntity(power);
|
|
}
|
|
var userData = { bankerID: bankers[index].nodeID, power: treeOn};
|
|
console.log("[MONEY TREE] CREATING POWER BUTTON, TREE is:", treeOn);
|
|
power = Entities.addEntity({
|
|
type: "Box",
|
|
dimensions: { x: 0.5, y: 0.5, z: 0.5 },
|
|
name: "Power Button Spawner",
|
|
script: "https://hifi-content.s3.amazonaws.com/brosche/DomainContent/Hub/MoneyTree/moneyTreeBankerClient.js",
|
|
userData: JSON.stringify(userData),
|
|
position: { x: -16.9779, y: -9.132, z: -10.7944 },
|
|
visible: false,
|
|
collisionless: true
|
|
});
|
|
}
|
|
|
|
function leftDomain(id){
|
|
for (var i = 0; i < userList.length; i++) {
|
|
if (userList[i].nodeID === id){
|
|
userList.splice(i, 1)[0];
|
|
}
|
|
}
|
|
Entities.editEntity(counterText, {text: userList.length});
|
|
if (userList.length < 3) {
|
|
Entities.editEntity(activeText, {text: "RESTING"});
|
|
}
|
|
}
|
|
|
|
function getMoney() {
|
|
try {
|
|
var payoutURL = "https://script.google.com/macros/s/AKfycbwwKdRHuSLQX5Ay595PXmKLmJnwzSX13SojHUH9or5LCdclzHg/exec?";
|
|
triviaURL = triviaURL + "category=" + "Giraffage_Hemsworth";
|
|
request(triviaURL, function (error, data) {
|
|
if (!error) {
|
|
console.log(JSON.stringify(data));
|
|
triviaData = data;
|
|
}
|
|
});
|
|
} catch (err) {
|
|
console.log("err:", err);
|
|
print("Could not get domain data using userData domainAPIURL");
|
|
}
|
|
}
|
|
|
|
// This function is used to send this script's specific version of an HTTP request.
|
|
// It's a stripped-down version of High Fidelity's included `request.js` module.
|
|
// This function will make the HTTP request and handle the data that's retrieved via a callback.
|
|
// It'll also handle dispensing HFC via pre-authorized transactions using HTTP PUT requests.
|
|
function request(options, callback) {
|
|
var httpRequest = new XMLHttpRequest(), key;
|
|
// QT bug: apparently doesn't handle onload. Workaround using readyState.
|
|
httpRequest.onreadystatechange = function () {
|
|
var READY_STATE_DONE = 4;
|
|
var HTTP_OK = 200;
|
|
if (httpRequest.readyState >= READY_STATE_DONE) {
|
|
var error = (httpRequest.status !== HTTP_OK) && httpRequest.status.toString() + ':' + httpRequest.statusText,
|
|
response = !error && httpRequest.responseText,
|
|
contentType = !error && httpRequest.getResponseHeader('content-type');
|
|
if (!error && contentType.indexOf('application/json') === 0) { // ignoring charset, etc.
|
|
try {
|
|
response = JSON.parse(response);
|
|
} catch (e) {
|
|
error = e;
|
|
}
|
|
}
|
|
if (error) {
|
|
response = { statusCode: httpRequest.status };
|
|
}
|
|
callback(error, response);
|
|
}
|
|
};
|
|
if (!options.method) {
|
|
options.method = 'GET';
|
|
}
|
|
if (options.body && (options.method === 'GET')) { // add query parameters
|
|
var params = [], appender = (-1 === options.uri.search('?')) ? '?' : '&';
|
|
for (key in options.body) {
|
|
if (options.body.hasOwnProperty(key)) {
|
|
params.push(key + '=' + options.body[key]);
|
|
}
|
|
}
|
|
options.uri += appender + params.join('&');
|
|
delete options.body;
|
|
}
|
|
if (options.json) {
|
|
options.headers = options.headers || {};
|
|
options.headers["Content-type"] = "application/json";
|
|
options.body = JSON.stringify(options.body);
|
|
}
|
|
for (key in options.headers || {}) {
|
|
if (options.headers.hasOwnProperty(key)) {
|
|
httpRequest.setRequestHeader(key, options.headers[key]);
|
|
}
|
|
}
|
|
httpRequest.open(options.method, options.uri, true);
|
|
httpRequest.send(options.body || null);
|
|
}
|
|
|
|
// This function will get auth data related to a 25-HFC pre-authorized
|
|
// transaction from our Google Sheet auth data database.
|
|
function getGoogleSheetAuthData(successCallback) {
|
|
var googleSheetRequestBody = {
|
|
hfc: "25"
|
|
};
|
|
|
|
request({
|
|
uri: GOOGLE_SHEET_AUTH_SCRIPT,
|
|
method: 'GET',
|
|
body: googleSheetRequestBody
|
|
}, function(error, response) {
|
|
try {
|
|
JSON.parse(response);
|
|
} catch(e) {
|
|
if (e instanceof SyntaxError) {
|
|
error = true;
|
|
}
|
|
}
|
|
if (error) {
|
|
console.log("ERROR while retrieving authorization data: " + JSON.stringify(response));
|
|
console.log("ERROR during slot machine payout: Couldn't get auth data from Google Sheet");
|
|
console.log("Slot machine was supposed to pay out to " + slotMachineCurrentPlayer + ".");
|
|
slotMachineCurrentPlayer = false;
|
|
if (entityExistsInDomain(SLOT_MACHINE_PLAY_TEXT_ID)) {
|
|
Entities.editEntity(SLOT_MACHINE_PLAY_TEXT_ID, {text: "Error during payout :("});
|
|
}
|
|
return false;
|
|
} else if (JSON.parse(response).status !== "success") {
|
|
console.log("Slot machine DOES NOT have payout funds available!");
|
|
console.log("Slot machine was supposed to pay out to " + slotMachineCurrentPlayer + ".");
|
|
slotMachineCurrentPlayer = false;
|
|
if (entityExistsInDomain(SLOT_MACHINE_PLAY_TEXT_ID)) {
|
|
Entities.editEntity(SLOT_MACHINE_PLAY_TEXT_ID, {text: "Error during payout :("});
|
|
}
|
|
return false;
|
|
} else {
|
|
console.log("Slot machine DOES have payout funds available! Returning auth data...");
|
|
response = JSON.parse(response);
|
|
|
|
successCallback(response.authorizationID, response.couponID); // payOutToCurrentPlayer()
|
|
return true;
|
|
}
|
|
});
|
|
}
|
|
|
|
// This function will pay out to the current slot machine player in `slotMachineCurrentPlayer`
|
|
// based on the passed `authID` and `coupon_id`.
|
|
function payOutToCurrentPlayer(authID, couponID) {
|
|
// Set up the `redeem` endpoint request body
|
|
var hifiRedemptionRequestBody = {
|
|
authorization_id: authID,
|
|
coupon_id: couponID,
|
|
username: slotMachineCurrentPlayer
|
|
};
|
|
|
|
console.log("Attempting payout! Redemption request body: " + JSON.stringify(hifiRedemptionRequestBody));
|
|
|
|
// Make the call to the redemption endpoint to pay out!
|
|
request({
|
|
uri: HIFI_REDEMPTION_ENDPOINT_URL,
|
|
method: 'PUT',
|
|
json: true,
|
|
body: hifiRedemptionRequestBody
|
|
}, function (error, response) {
|
|
if (error || (response.status !== 'success')) {
|
|
console.log("ERROR during slot machine payout: ", error || response.status);
|
|
console.log("Full response: " + JSON.stringify(response));
|
|
console.log("Slot machine was supposed to pay out to " + slotMachineCurrentPlayer + ".");
|
|
console.log("SLOT MACHINE DID NOT PAY OUT - Google Sheet will say auth used, but it wasn't!");
|
|
slotMachineCurrentPlayer = false;
|
|
if (entityExistsInDomain(SLOT_MACHINE_PLAY_TEXT_ID)) {
|
|
Entities.editEntity(SLOT_MACHINE_PLAY_TEXT_ID, {text: "Error during payout :("});
|
|
}
|
|
return;
|
|
} else {
|
|
console.log("Slot machine paid out to " + slotMachineCurrentPlayer + "!");
|
|
slotMachineCurrentPlayer = false;
|
|
if (entityExistsInDomain(SLOT_MACHINE_PLAY_TEXT_ID)) {
|
|
Entities.editEntity(SLOT_MACHINE_PLAY_TEXT_ID, {text: "YOU WON 25 HFC!!"});
|
|
resetPlayTextAfterDelay();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// This function will check our pre-authorized funds database to make
|
|
// sure we have funds available to pay out.
|
|
// If we do have funds available to pay out, we'll call `successCallback(callbackParam)`.
|
|
function checkIfSlotMachineHasAvailableFunds(successCallback, callbackParam) {
|
|
var googleSheetRequestBody = {
|
|
hfc: "25",
|
|
justChecking: true
|
|
};
|
|
|
|
console.log("Checking Google Sheet for available authorization data...");
|
|
request({
|
|
uri: GOOGLE_SHEET_AUTH_SCRIPT,
|
|
method: 'GET',
|
|
body: googleSheetRequestBody
|
|
}, function(error, response) {
|
|
try {
|
|
JSON.parse(response);
|
|
} catch (e) {
|
|
if (e instanceof SyntaxError) {
|
|
error = true;
|
|
}
|
|
}
|
|
if (error) {
|
|
console.log("ERROR while retrieving authorization data: " + JSON.stringify(response));
|
|
return false;
|
|
} else if (JSON.parse(response).status !== "success") {
|
|
console.log("Slot machine DOES NOT have payout authorizations available.");
|
|
if (entityExistsInDomain(SLOT_MACHINE_PLAY_TEXT_ID)) {
|
|
Entities.editEntity(SLOT_MACHINE_PLAY_TEXT_ID, {text: "Out of order :("});
|
|
}
|
|
return false;
|
|
} else {
|
|
console.log("Slot machine DOES have payout authorizations available.");
|
|
successCallback(callbackParam); // startSlotMachine(player);
|
|
return true;
|
|
}
|
|
});
|
|
}
|
|
|
|
// This function is used to allow the AC script to see and change entities
|
|
// in the domain.
|
|
function allowEntityAccess() {
|
|
Entities.setPacketsPerSecond(6000);
|
|
EntityViewer.setPosition(SLOT_MACHINE_AREA);
|
|
EntityViewer.setCenterRadius(1000);
|
|
// This should allow us to see nano-scale entities from great distances
|
|
EntityViewer.setVoxelSizeScale(Number.MAX_VALUE);
|
|
Script.setInterval(function() {
|
|
EntityViewer.queryOctree();
|
|
}, 1000);
|
|
console.log("This AC script now has access to entities in this domain!");
|
|
}
|
|
|
|
// This function checks to make sure that the entity server exists
|
|
// and that the AC script has Rez permissions.
|
|
// If one or both of those things is false, we'll check again in 5 seconds.
|
|
function maybeAllowEntityAccess() {
|
|
console.log("Attempting to give this AC script entity access...");
|
|
if (Entities.serversExist() && Entities.canRez()) {
|
|
allowEntityAccess();
|
|
} else {
|
|
if (!Entities.canRez()) {
|
|
console.log("This AC script doesn't have rez permissions!");
|
|
}
|
|
Script.setTimeout(maybeAllowEntityAccess, 5000);
|
|
}
|
|
}
|
|
|
|
// This function will be called on startup.
|
|
function startup() {
|
|
// Listen on the slot machine messaging channel!
|
|
Messages.subscribe(SLOT_MACHINE_MESSAGING_CHANNEL);
|
|
Messages.messageReceived.connect(onMessageReceived);
|
|
|
|
maybeAllowEntityAccess();
|
|
|
|
// Make sure the Play Text is set to the default when we're restarting the script.
|
|
if (entityExistsInDomain(SLOT_MACHINE_PLAY_TEXT_ID)) {
|
|
Entities.editEntity(SLOT_MACHINE_PLAY_TEXT_ID, {text: "Click Red Ball to Play!"});
|
|
}
|
|
|
|
// This function sets up a repeating interval. When the interval timer expires,
|
|
// the script will request our Recent Economic Activity.
|
|
Script.setInterval(function() {
|
|
checkForNewPlayers();
|
|
}, CHECK_RECENT_ACTIVITY_INTERVAL_MS);
|
|
}
|
|
startup();
|
|
|
|
// This function will be called when the script shuts down.
|
|
function shutdown() {
|
|
Messages.messageReceived.disconnect(onMessageReceived);
|
|
}
|
|
|
|
function spawnReceiverMessage(receiver, amount){
|
|
print("[MONEY TREE] spawing reciever message", JSON.stringify(receiver));
|
|
var userData = {
|
|
receiverID: receiver,
|
|
amount: amount
|
|
};
|
|
var avatar = AvatarList.getAvatar(receiver);
|
|
Entities.addEntity({
|
|
type: "Box",
|
|
dimensions: { x: 0.5, y: 0.5, z: 0.5 },
|
|
name: "Tree Gift Receipt",
|
|
script: "https://hifi-content.s3.amazonaws.com/brosche/DomainContent/Hub/MoneyTree/moneyTreeReceiverClient.js",
|
|
userData: JSON.stringify(userData),
|
|
lifetime: 5,
|
|
position: Vec3.sum(avatar.position, Vec3.multiplyQbyV(avatar.orientation, { x: -2.5, y: 0, z: -5 })),
|
|
visible: false,
|
|
collisionless: true,
|
|
parentID: receiver
|
|
});
|
|
try {
|
|
print("[MONEY TREE] making coin particle");
|
|
Entities.addEntity({
|
|
lifetime: 5,
|
|
collidesWith: "",
|
|
collisionMask: 0,
|
|
collisionless: true,
|
|
position: Vec3.sum(avatar.position, Vec3.multiplyQbyV(avatar.orientation, { x: 0, y: 0, z: -1 })),
|
|
dimensions: {
|
|
x: 0.15,
|
|
y: 0.15,
|
|
z: 0.15
|
|
},
|
|
isEmitting: true,
|
|
name: "Coin Particle",
|
|
type: "ParticleEffect",
|
|
userData: "{\"grabbableKey\":{\"grabbable\":false}}",
|
|
lifespan: 0.5,
|
|
maxParticles: 10,
|
|
textures: "https://hifi-content.s3.amazonaws.com/brosche/Trivia/Four%20Square/assets/pictures/tempsnip.png",
|
|
emitRate: 10,
|
|
emitSpeed: 1.5,
|
|
speedSpread: 2,
|
|
emitDimensions: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
emitOrientation: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
emitterShouldTrail: false,
|
|
particleRadius: 0.15,
|
|
radiusSpread: 0,
|
|
radiusStart: 0,
|
|
radiusFinish: 0.15,
|
|
color:{
|
|
red:255,
|
|
blue:255,
|
|
green:255
|
|
},
|
|
colorSpread:{
|
|
red:0,
|
|
blue:0,
|
|
green:0
|
|
},
|
|
colorStart:{
|
|
red:255,
|
|
blue:255,
|
|
green:255
|
|
},
|
|
colorFinish:{
|
|
red:255,
|
|
blue:255,
|
|
green:255
|
|
},
|
|
emitAcceleration:{
|
|
x:0,
|
|
y:-10,
|
|
z:1},
|
|
accelerationSpread:{
|
|
x:5,
|
|
y:3,
|
|
z:5
|
|
},
|
|
alpha: 1,
|
|
alphaSpread: 0,
|
|
alphaStart: 1,
|
|
alphaFinish: 1,
|
|
particleSpin: 0,
|
|
spinSpread: 0,
|
|
spinStart: 0,
|
|
spinFinish: 0,
|
|
rotateWithEntity: true,
|
|
polarStart: 0,
|
|
polarFinish: 0,
|
|
azimuthStart: -2.9321532249450684,
|
|
azimuthFinish: 0.5235987901687622
|
|
});
|
|
} catch (e) {
|
|
print("[MONEY TREE] error spawning coin particle", e);
|
|
}
|
|
}
|
|
|
|
function randomizeHFC(){
|
|
var funds = true;
|
|
var rand = gaussian(AVERAGE_HFC_AMOUNT, STANDARD_DEVIATION);
|
|
var listLength =Math.sqrt(userList.length);
|
|
var amount = Math.ceil(rand*listLength) - Math.ceil(rand*listLength) % 5;
|
|
if (!funds){
|
|
Entities.editEntity(activeText, {text: "BANKRUPT!"});
|
|
return 0;
|
|
}
|
|
if (amount >= 50){
|
|
amount = 50;
|
|
} else if (amount <= 5){
|
|
amount = 5;
|
|
}
|
|
return amount;
|
|
}
|
|
|
|
function randomizeInterval(){
|
|
var interval = gaussian(AVERAGE_INTERVAL, 1);
|
|
return interval;
|
|
}
|
|
|
|
function createCoinSpawner() {
|
|
console.log("[MONEY TREE] SPAWNING COINS");
|
|
if (coin.length > 0){
|
|
console.log("[MONEY TREE] DELETING COINS");
|
|
for (var i = 0; i < coin.length; i++ ) {
|
|
Entities.deleteEntity(coin[i]);
|
|
}
|
|
}
|
|
// Show the coins to the giver as overlays
|
|
if (targetRecipients[0] == null){
|
|
console.log("[MONEY TREE] could not find eligible recipients");
|
|
return;
|
|
} else if (targetRecipients.length < 2){
|
|
console.log("[MONEY TREE] not enough eligible recipients");
|
|
return;
|
|
} else {
|
|
console.log("[MONEY TREE] SPAWNING COINS...");
|
|
for (var i = 0; i < targetRecipients.length; i++){
|
|
var avatar = AvatarList.getAvatar(targetRecipients[i].nodeID);
|
|
var sum = Vec3.sum(avatar.position, Vec3.UP);
|
|
var userData = {
|
|
giverID: targetGiver.nodeID
|
|
};
|
|
coin[i] = Entities.addEntity({
|
|
type: "Box",
|
|
dimensions: { x: 0.5, y: 0.5, z: 0.5 },
|
|
name: "Money Tree Gift",
|
|
script: "https://hifi-content.s3.amazonaws.com/brosche/DomainContent/Hub/MoneyTree/moneyTreeClient.js",
|
|
userData: JSON.stringify(userData),
|
|
lifetime: 60,
|
|
position: sum,
|
|
visible: false,
|
|
collisionless: true,
|
|
parentID: avatar.sessionUUID
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
function pickAGiver(){
|
|
console.log("[MONEY TREE] PICKING GIVER");
|
|
// Choose a random user to display coins for giving
|
|
// Do not choose a user again until all other users in range have been selected.
|
|
indexGiver = randInt(0, userList.length-1);
|
|
if (indexGiver < 0){
|
|
return;
|
|
} else {
|
|
if (targetGiver){
|
|
if (userList[indexGiver].username === ""){
|
|
userList.splice(indexGiver, 1)[0];
|
|
if (indexGiver >= userList.length){
|
|
indexGiver = randInt(0, userList.length-1);
|
|
}
|
|
}
|
|
if (targetGiver.username !== userList[indexGiver].username){
|
|
targetGiver = userList[indexGiver];
|
|
} else {
|
|
indexGiver = randInt(0, userList.length-1);
|
|
targetGiver = userList[indexGiver];
|
|
}
|
|
} else {
|
|
targetGiver = userList[indexGiver];
|
|
}
|
|
}
|
|
}
|
|
|
|
function pickRecipients(){
|
|
console.log("[MONEY TREE] PICKING RECIPIENTS");
|
|
targetRecipients = [];
|
|
tempList = [];
|
|
tempList = userList.slice();
|
|
tempList.splice(indexGiver, 1)[0];
|
|
for (var i = 0; i < tempList.length; i++) {
|
|
if (tempList[i].staff === true) {
|
|
console.log("[MONEY TREE] removing staff", tempList[i].username);
|
|
tempList.splice(i,1)[0];
|
|
i--;
|
|
}
|
|
}
|
|
if (tempList.length < 2) {
|
|
console.log("[MONEY TREE] Not enough eligible recipients for receiver selection.");
|
|
Entities.editEntity(activeText, {text: "MOAR PPL PLZ"});
|
|
return;
|
|
}
|
|
var recipientCount = (tempList.length > RECIPIENT_MAX) ? RECIPIENT_MAX : tempList.length;
|
|
for (var i = 0; i < recipientCount; i++){
|
|
var index = randInt(0, tempList.length-1);
|
|
targetRecipients.push(tempList.splice(index-i, 1)[0]);
|
|
console.log("[MONEY TREE] recipient:", JSON.stringify(targetRecipients[i].username));
|
|
}
|
|
}
|
|
|
|
function randFloat(low, high) {
|
|
return low + Math.random() * (high - low);
|
|
}
|
|
|
|
function randInt(low, high) {
|
|
return Math.floor(randFloat(low, high));
|
|
}
|
|
|
|
function gaussian(mean, stdev) {
|
|
// returns a gaussian random function with the given mean and stdev.
|
|
var y2;
|
|
var useLast = false;
|
|
var y1;
|
|
if (useLast) {
|
|
y1 = y2;
|
|
useLast = false;
|
|
} else {
|
|
var x1, x2, w;
|
|
do {
|
|
x1 = 2.0 * Math.random() - 1.0;
|
|
x2 = 2.0 * Math.random() - 1.0;
|
|
w = x1 * x1 + x2 * x2;
|
|
} while ( w >= 1.0);
|
|
w = Math.sqrt((-2.0 * Math.log(w))/w);
|
|
y1 = x1 * w;
|
|
y2 = x2 * w;
|
|
useLast = true;
|
|
}
|
|
|
|
var retval = mean + stdev * y1;
|
|
if (retval > 0) {
|
|
return retval;
|
|
}
|
|
return -retval;
|
|
}
|
|
|
|
function sendInput(recipientUsername) {
|
|
// curl -X PUT -d authorization_id=<authorization ID from 1> -d coupon_id=<coupon ID from 1> -d username=steve https://highfidelity.com/api/v1/commerce/redeem;
|
|
var paramString = encodeURLParams({
|
|
date: new Date().toLocaleString(),
|
|
recipientUsername: recipientUsername,
|
|
amount: randomHFCAmount
|
|
});
|
|
|
|
var request = new XMLHttpRequest();
|
|
request.open('GET', googleURL + "?" + paramString);
|
|
request.timeout = 10000;
|
|
request.send();
|
|
}
|
|
|
|
function encodeURLParams(params) {
|
|
var paramPairs = [];
|
|
for (var key in params) {
|
|
paramPairs.push(key + "=" + params[key]);
|
|
}
|
|
return paramPairs.join("&");
|
|
}
|
|
|
|
function sweep(){
|
|
try {
|
|
var homelessParticles = Entities.findEntitiesByType("ParticleEffect", SEARCH_CENTER, SEARCH_AREA);
|
|
if (homelessParticles.length > 0) {
|
|
for (var i = 0; i < homelessParticles.length; i++ ) {
|
|
Entities.deleteEntity(homelessParticles[i]);
|
|
}
|
|
}
|
|
} catch (e) {
|
|
print("[MONEY TREE] particle sweep failed.");
|
|
return;
|
|
}
|
|
try {
|
|
var collect = Entities.findEntitiesByName("Coin Particle", SEARCH_CENTER, SEARCH_AREA);
|
|
if (collect.length > 0) {
|
|
for (var i = 0; i < collect.length; i++ ) {
|
|
Entities.editEntity(collect[i], { parentID: null });
|
|
Entities.deleteEntity(collect[i]);
|
|
}
|
|
}
|
|
if (coin.length > 0){
|
|
for (var i = 0; i < coin.length; i++ ) {
|
|
Entities.editEntity(coin[i], { parentID: null });
|
|
Entities.deleteEntity(coin[i]);
|
|
}
|
|
}
|
|
} catch (e) {
|
|
print("[MONEY TREE] entity sweep failed.");
|
|
return;
|
|
}
|
|
}
|
|
|
|
function startTree(){
|
|
interval = Script.setInterval(function(){
|
|
sweep();
|
|
Entities.editEntity(activeText, {text: "SEARCHING..."});
|
|
if (userList.length >= RECIPIENT_MAX){
|
|
randomHFCAmount = randomizeHFC();
|
|
if (randomHFCAmount === 0) {
|
|
Script.clearInterval(interval);
|
|
return;
|
|
}
|
|
pickAGiver();
|
|
console.log("[MONEY TREE] GIVER", JSON.stringify(targetGiver.username));
|
|
pickRecipients();
|
|
if (targetRecipients.length > 1) {
|
|
Entities.editEntity(activeText, {text: "OOH SHINY!"});
|
|
createCoinSpawner();
|
|
}
|
|
} else {
|
|
Entities.editEntity(activeText, {text: "MOAR PPL PLZ"});
|
|
}
|
|
}, randomizeInterval()*SHOW_TIME_LENGTH);
|
|
}
|
|
|
|
function appEnding() {
|
|
sweep();
|
|
Entities.deleteEntity(counterText);
|
|
Entities.deleteEntity(activeText);
|
|
if (interval){
|
|
Script.clearInterval(interval);
|
|
}
|
|
if (octreeInterval){
|
|
Script.clearInterval(octreeInterval);
|
|
}
|
|
Messages.unsubscribe(MONEY_TREE_CHANNEL);
|
|
Messages.messageReceived.disconnect(messageHandler);
|
|
}
|
|
|
|
startTree();
|
|
AvatarList.avatarRemovedEvent.connect(leftDomain);
|
|
Messages.subscribe(MONEY_TREE_CHANNEL);
|
|
Script.scriptEnding.connect(appEnding);
|
|
}()); |