'use strict'; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /* global on log playerIsGM findObjs getObj getAttrByName sendChat globalconfig state */ /* CASHMASTER 0.8.1 A currency management script for the D&D 5e OGL sheets on roll20.net. Please use `!cm` for inline help and examples. arthurbauer@me.com */ var initCM = function initCM() { // Initialize State object if (!state.CashMaster) { log('Initializing CashMaster'); state.CashMaster = { Party: [], DefaultCharacterNames: {}, TransactionHistory: [], MaxTransactionId: 0 }; } if (!state.CashMaster.Party) { log('Initializing CashMaster.Party'); state.CashMaster.Party = []; } if (!state.CashMaster.DefaultCharacterNames) { log('Initializing CashMaster.DefaultCharacterNames'); state.CashMaster.DefaultCharacterNames = {}; } if (!state.CashMaster.TransactionHistory) { log('Initializing CashMaster.TransactionHistory'); state.CashMaster.TransactionHistory = []; } if (!state.CashMaster.MaxTransactionId) { state.CashMaster.MaxTransactionId = 0; state.CashMaster.TransactionHistory.forEach(function (tx) { tx.Id = state.CashMaster.MaxTransactionId++; // eslint-disable-line no-param-reassign, no-plusplus }); } }; var transactionHistoryLength = 20; var recordTransaction = function recordTransaction(type, initiator, playerEffects) { var id = state.CashMaster.MaxTransactionId++; // eslint-disable-line no-param-reassign, no-plusplus var timestamp = new Date().toUTCString(); log('Add Transaction'); log(' Id: ' + id); log(' Type: ' + type); log(' Initiator: ' + initiator); log(' Player Effects: ' + playerEffects); log(' Timestamp: ' + timestamp); state.CashMaster.TransactionHistory.push({ Id: id, Type: type, Initiator: initiator, PlayerEffects: playerEffects, Time: timestamp, Reverted: false }); // Only track a finite number of transactions so we don't clog up state if (state.CashMaster.TransactionHistory.length > transactionHistoryLength) { state.CashMaster.TransactionHistory.shift(); } }; var getDelta = function getDelta(finalState, initialState) { return [finalState[0] - initialState[0], finalState[1] - initialState[1], finalState[2] - initialState[2], finalState[3] - initialState[3], finalState[4] - initialState[4]]; }; var getPlayerEffect = function getPlayerEffect(playerName, delta) { return { PlayerName: playerName, Delta: delta }; }; var getInverseOperation = function getInverseOperation(delta) { return [-delta[0], -delta[1], -delta[2], -delta[3], -delta[4]]; }; // How much each coing is worth of those below it. // In order: pp, gp, ep, sp var conversionRatio = [10, 2, 5, 10]; var cashsplit = function cashsplit(c, m, x) { //! cashsplit var ct = 0; var cr = 0; if (c !== null) { ct = Math.floor(c / m); cr = c % m; if (cr >= x || c < 0 && cr < 0 && -cr < x) { ct += 1; } } return ct; }; var getattr = function getattr(cid, att) { //! getattr var attr = findObjs({ type: 'attribute', characterid: cid, name: att })[0]; if (attr) { return attr.get('current'); } return ''; }; var setattr = function setattr(cid, att, val) { //! setattr var attr = findObjs({ type: 'attribute', characterid: cid, name: att })[0]; if (typeof attr === 'undefined' || attr == null) { var _attr = createObj('attribute', { name: att, characterid: cid, current: parseFloat(val) }); // eslint-disable-line no-unused-vars, no-undef, no-shadow } else { attr.setWithWorker({ current: parseFloat(val) }); // .set() } }; var changeMoney = function changeMoney(startamount, addamount) { //! changeMoney if (addamount !== null) { var total = startamount; var currency = addamount.slice(-2); var amount2 = -parseFloat(addamount.substr(0, addamount.length - 2)); var origamount = total; var amount3 = 0; if (currency === 'cp') { amount3 = amount2 / 100; } if (currency === 'sp') { amount3 = amount2 / 10; } if (currency === 'ep') { amount3 = amount2 / 2; } if (currency === 'gp') { amount3 = amount2; } if (currency === 'pp') { amount3 = amount2 * 10; } if (total[0] * 10 + total[1] + total[2] / 2 + total[3] / 10 + total[4] / 100 >= -amount3) { total[4] += amount3 * 100; while (total[4] < 0) { total[4] += 10; total[3] -= 1; } // cp while (total[3] < 0) { if (total[4] >= 10) { total[4] -= 10; total[3] += 1; } else { total[3] += 5; total[2] -= 1; } } // sp while (total[2] < 0) { if (total[3] >= 5) { total[3] -= 5; total[2] += 1; } else { total[2] += 2; total[1] -= 1; } } // ep while (total[1] < 0) { if (total[2] >= 2) { total[2] -= 2; total[1] += 1; } else { total[1] += 10; total[0] -= 1; } } // gp while (total[0] < 0) { if (total[1] >= 10) { total[1] -= 10; total[0] += 1; } else { total = origamount; return 'ERROR: Not enough cash.'; } } // pp return total; } return 'ERROR: Not enough cash.'; } return 0; }; // Merge funds into the densest denomination possible. // Account expects {pp, gp, ep, sp, cp} var mergeMoney = function mergeMoney(account) { if (account == null) { return 'ERROR: Acount does not exist.'; } if (account.length !== 5) { return 'ERROR: Account must be an array in the order of {pp, gp, ep, sp, cp}.'; } for (var i = account.length - 1; i > 0; i -= 1) { var coinCount = account[i]; var carry = Math.floor(coinCount / conversionRatio[i - 1]); var remainder = coinCount % conversionRatio[i - 1]; account[i] = remainder; // eslint-disable-line no-param-reassign account[i - 1] += carry; // eslint-disable-line no-param-reassign } return account; }; var toUsd = function toUsd(total) { var usd = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 110; //! toUsd var output = ''; if (usd > 0) { output = total + ' gp
(~ ' + Math.round(total * usd / 5) * 5 + ' USD)
'; } else { output = total + ' gp'; } return output; }; var formatCurrency = function formatCurrency(pp, gp, ep, sp, cp) { var currencyStringArray = []; if (pp && pp !== 0) currencyStringArray.push('' + pp + 'pp'); if (gp && gp !== 0) currencyStringArray.push('' + gp + 'gp'); if (ep && ep !== 0) currencyStringArray.push('' + ep + 'ep'); if (sp && sp !== 0) currencyStringArray.push('' + sp + 'sp'); if (cp && cp !== 0) currencyStringArray.push('' + cp + 'cp'); return currencyStringArray.join(', '); }; var playerCoinStatus = function playerCoinStatus(character) { var usd = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 110; //! playerCoinStatus var name = getAttrByName(character.id, 'character_name'); var pp = parseFloat(getattr(character.id, 'pp')) || 0; var gp = parseFloat(getattr(character.id, 'gp')) || 0; var ep = parseFloat(getattr(character.id, 'ep')) || 0; var sp = parseFloat(getattr(character.id, 'sp')) || 0; var cp = parseFloat(getattr(character.id, 'cp')) || 0; var total = Math.round((pp * 10 + ep * 0.5 + gp + sp / 10 + cp / 100) * 10000) / 10000; var weight = (pp + gp + ep + sp + cp) / 50; var output = name + ': $' + toUsd(total, usd) + '
'; output += formatCurrency(pp, gp, ep, sp, cp); output += '
(' + weight + ' lbs)


'; return [output, total]; }; var getNonZeroCurrency = function getNonZeroCurrency(accountArray) { var currencyStringArray = []; if (accountArray[0] && accountArray[0] !== 0) currencyStringArray.push(accountArray[0] + 'pp'); if (accountArray[1] && accountArray[1] !== 0) currencyStringArray.push(accountArray[1] + 'gp'); if (accountArray[2] && accountArray[2] !== 0) currencyStringArray.push(accountArray[2] + 'ep'); if (accountArray[3] && accountArray[3] !== 0) currencyStringArray.push(accountArray[3] + 'sp'); if (accountArray[4] && accountArray[4] !== 0) currencyStringArray.push(accountArray[4] + 'cp'); return currencyStringArray.join(' '); }; var getRecipientOptions = function getRecipientOptions() { if (state.CashMaster) { var existingOptions = state.CashMaster.Party.join('|'); // If ones already exist, append "|Other, ?{Type Full Name}" if (existingOptions.length > 0) { return '|' + existingOptions + '|Other,?{Type Full Name&#125;'; } return ''; } return null; }; var getCharByAny = function getCharByAny(nameOrId) { var character = null; // Try to directly load the character ID character = getObj('character', nameOrId); if (character) { return character; } // Try to load indirectly from the token ID var token = getObj('graphic', nameOrId); if (token) { character = getObj('character', token.get('represents')); if (character) { return character; } } // Try loading through char name var list = findObjs({ _type: 'character', name: nameOrId }); if (list.length === 1) { return list[0]; } // Default to null return null; }; var getStringInQuotes = function getStringInQuotes(string) { var quietMode = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; var scname = 'CashMaster'; var startQuote = string.indexOf('"'); var endQuote = string.lastIndexOf('"'); if (startQuote >= endQuote) { if (!quietMode) { sendChat(scname, '**ERROR:** You must specify a target by name within double quotes in the phrase ' + string); } return null; } return string.substring(startQuote + 1, endQuote); }; var getDefaultCharNameFromPlayer = function getDefaultCharNameFromPlayer(playerid) { var defaultName = state.CashMaster.DefaultCharacterNames[playerid]; if (!defaultName) { return null; } return defaultName; }; var ParseException = function ParseException(message) { var _this = this; _classCallCheck(this, ParseException); this.message = message; this.name = 'Parse Exception'; this.toString = function () { return _this.name + ': ' + _this.message; }; }; on('ready', function () { var v = '0.8.1'; // version number var usd = 110; /* Change this if you want to have a rough estimation of a character’s wealth in USD. After some research I believe a reasonable exchange ratio is roughly 1 gp = 110 USD Set it to 0 to disable it completely. */ var scname = 'CashMaster'; // script name var selectedsheet = 'OGL'; // You can set this to "5E-Shaped" if you're using the Shaped sheet // detecting useroptions from one-click if (globalconfig && globalconfig.cashmaster && globalconfig.cashmaster.useroptions) { selectedsheet = globalconfig.cashmaster.useroptions.selectedsheet; // eslint-disable-line prefer-destructuring } var rt = ''; if (selectedsheet === 'OGL') { rt = ['desc', 'desc']; } else if (selectedsheet === '5E-Shaped') { rt = ['5e-shaped', 'text']; } else { rt = ['default', 'name=' + scname + ' }}{{note']; } log(scname + ' v' + v + ' online. For assistance, use `!cm -help`'); var pp = void 0; var gp = void 0; var ep = void 0; var sp = void 0; var cp = void 0; var total = void 0; var output = void 0; var ppa = void 0; var gpa = void 0; var epa = void 0; var spa = void 0; var cpa = void 0; var ppg = void 0; var gpg = void 0; var epg = void 0; var spg = void 0; var cpg = void 0; var name = void 0; var usd2 = void 0; var pcName = void 0; var populateCoinContents = function populateCoinContents(input) { ppg = /([\s|,|^|"|'])((-?\d{1,16} ?)(pp|PP|Pp|pP))(\s|,|$|"|')/; ppa = ppg.exec(input); gpg = /([\s|,|^|"|'])((-?\d{1,16} ?)(gp|GP|Gp|gP))(\s|,|$|"|')/; gpa = gpg.exec(input); epg = /([\s|,|^|"|'])((-?\d{1,16} ?)(ep|EP|Ep|eP))(\s|,|$|"|')/; epa = epg.exec(input); spg = /([\s|,|^|"|'])((-?\d{1,16} ?)(sp|SP|Sp|sP))(\s|,|$|"|')/; spa = spg.exec(input); cpg = /([\s|,|^|"|'])((-?\d{1,16} ?)(cp|CP|Cp|cP))(\s|,|$|"|')/; cpa = cpg.exec(input); }; var parseSubcommand = function parseSubcommand(msg, subcommand, argTokens) { var subjectList = []; var targetList = []; var currencySpecified = false; var allowStringTarget = argTokens.includes('-dropWithReason') || argTokens.includes('-giveNPC'); // Wrapping in try/catch because of the forEach. This allows us to easily escape to report errors to the user immediately. try { // Advanced Mode var tagList = subcommand.split(' -'); tagList.forEach(function (param) { if (param.startsWith('S ')) { var subjectNameList = getStringInQuotes(param); var subjectNames = subjectNameList.split(','); subjectNames.forEach(function (subjectName) { if (subjectName.length === 0) { throw new ParseException('Empty string subject provided!'); } var subject = getCharByAny(subjectName); if (subject == null) { throw new ParseException('Provided Subject name does not exist!'); } subjectList.push(subject); }); } else if (param.startsWith('T ')) { var targetNameList = getStringInQuotes(param); var targetNames = targetNameList.split(','); targetNames.forEach(function (targetName) { if (allowStringTarget) { targetList.push(targetName); } else { if (targetName.length === 0) { throw new ParseException('Empty string target provided!'); } var target = getCharByAny(targetName); if (target == null) { throw new ParseException('Provided Target name does not exist!'); } targetList.push(target); } }); } else if (param.startsWith('C ')) { var currencyString = getStringInQuotes(param); if (currencyString === null) { return; } populateCoinContents(currencyString); currencySpecified = true; } }); // Simple Mode if (subjectList.length === 0) { // Prevent double-parsing targetList = []; var ambiguousNameList = getStringInQuotes(subcommand, true); var ambiguousNames = []; if (ambiguousNameList !== null) { ambiguousNames = ambiguousNameList.split(','); } var defaultName = getDefaultCharNameFromPlayer(msg.playerid); // In the event the user has no default and token selected (or have specified -noToken), assume subject if (defaultName === null && (msg.selected === null || argTokens.includes('-noToken') || argTokens.includes('-nt'))) { ambiguousNames.forEach(function (subjectName) { var subject = getCharByAny(subjectName); if (subject == null) { throw new ParseException('Provided Subject name does not exist!'); } subjectList.push(subject); }); } else { // Otherwise, assume selected are subject and quoted are targets ambiguousNames.forEach(function (targetName) { if (allowStringTarget) { targetList.push(targetName); } else { var target = getCharByAny(targetName); if (target == null) { throw new ParseException('Provided Target name does not exist!'); } targetList.push(target); } }); // Load from selection if (msg.selected != null) { msg.selected.forEach(function (selection) { log('Selection: ' + selection); var token = getObj('graphic', selection._id); // eslint-disable-line no-underscore-dangle var subject = null; if (token) { subject = getObj('character', token.get('represents')); } if (subject === null) { sendChat(scname, '**ERROR:** sender does not exist.'); return null; } subjectList.push(subject); return null; }); } // Load from default if (subjectList.length === 0) { if (defaultName === null) { return null; } var subject = getCharByAny(defaultName); if (subject === null) { return null; } subjectList.push(subject); } } } // If given no particular subset to parse, parse the whole subcommand // WARNING: This could cause unexpected behavior when using object id mode if (!currencySpecified) { populateCoinContents(subcommand); } } catch (e) { sendChat(scname, '/w ' + msg.who + ' **ERROR:** ' + e); sendChat(scname, '/w gm **ERROR:** ' + msg.who + ' received: ' + e); return null; } log('Subjects: ' + subjectList); log('Targets: ' + targetList); return { Subjects: subjectList, Targets: targetList }; }; var printTransactionHistory = function printTransactionHistory(sender) { var historyContent = '/w ' + sender + ' &{template:' + rt[0] + '} {{' + rt[1] + '=

Cash Master


'; state.CashMaster.TransactionHistory.forEach(function (transaction) { var playerEffects = ''; historyContent += '

' + transaction.Type + '


' + transaction.Time + '
Initiated by ' + transaction.Initiator + '
Player Effects' + playerEffects + '
'; // If it hasn't been reverted yet, display revert button. Otherwise, strikethrough. if (!transaction.Reverted) { operationList.push('-revert ' + transaction.Id); var revertOperation = '!cm ' + operationList.join(';'); historyContent += '[Revert Transaction](' + revertOperation + ')
'; } }); historyContent += '}}'; sendChat(scname, historyContent); }; on('chat:message', function (msg) { var subcommands = msg.content.split(';'); if (msg.type !== 'api') return; if (msg.content.startsWith('!cm') !== true) return; // Initialize State object initCM(); // Log the received command log('CM Command: ' + msg.content); // Execute each operation subcommands.forEach(function (subcommand) { log('CM Subcommand: ' + subcommand); var argTokens = subcommand.split(/\s+/); // Operations that do not require a selection if (subcommand === '!cm' || argTokens.includes('-help') || argTokens.includes('-h')) { //! help sendChat(scname, '/w gm

CashMaster

A currency management script for the D&D 5e OGL and 5e Shaped sheets on Roll20.net.

Please use !cm for inline help and examples.

Setup

Player Setup

  1. Create a macro bar button for the command !cm -menu
  2. Press the CashMaster button you just created. It will display a menu in the chat log.
  3. Click on your character token
  4. Press the chat UI button titled Set Default Character.

GM Setup

  1. Set the character sheet setting (OGL, 5E-Shaped, or other).
  2. Create a macro bar button for the command !cm -menu
  3. Press the CashMaster button you just created. It will display a menu in the chat log.
  4. Select the character tokens of ALL party members and companion NPCs. Do not select pets or mounts unless the party considers them an equal member of the party (and thus should be a valid recipient for -loot and similar commands). Such creatures must have full character sheets with currency fields.
  5. Press the chat UI button titled Set Party to Selected.

Player Commands

Help Commands

Accounting commands

A character has a tracked account if it has discrete values for its saved coins. PCs necessarily have tracked accounts while NPCs usually do not, instead having as much gold as the DM feels is necessary at that moment.

GM Commands

In addition to the above commands, the GM has access to the following commands.

Help commands

Accounting Commands

These operations directly add and remove gold from party inventories.

Admin Commands

Use caution when using the below commands.

Tips

  1. -noToken and -nt will cause CashMaster to disregard what character is selected.
  2. You can use several coin values at once, e.g. !cm -loot 50gp 150sp 2000cp or !cm -pay 2sp 5cp.
  3. You can combine multiple subcommands into a single chat command with a semicolon ; between them. For example, !cm -add 5gp; -merge
  4. You can select multiple subjects and targets using Advanced Mode. For example, !cm -transfer -S "Billy Bob,Joe Bob" -T "Sarah Bob,Sonya Bob" -C "10gp". When using multiple subjects and targets, it will perform an operation for each subject-target pair. In that case, it will perform four transactions of 10gp each.
  5. In Advanced Mode, you don't need to specify -C "[amoung][currency]" and can instead just use the standard [amount][currency]. The -C currency tag allows you to specify the gp value at a particular point in the command in case you have strangley-named or inconveniently ID'd characters.
  6. CashMaster will parse both character IDs and character names. You can even mix and match! If Billy Bob's ID was -L4ncF3ych3ZLtWaY3uY, Instead of the example in Tip 4, you could use !cm -transfer -S "-L4ncF3ych3ZLtWaY3uY,Joe Bob" -T "Sarah Bob,Sonya Bob" -C "10gp".
  7. CashMaster is compatible with @{selected|character_id} and @{target|character_id} as they will simply be parsed down to IDs. As an example, your players could use !cm -t -T "@{target|character_id}" 1gp to transfer a gold amongst themselves.

Examples

  1. !cm -overview will show a cash overview.
  2. !cm -add 50gp will add 50 gp to every selected character.
  3. !cm -loot 50gp will (more or less evenly) distribute 50 gp among the party members.
  4. !cm -pay 10gp will subtract 10gp from each selected character. It will try to exchange the other coin types (e.g. it will use 1pp if the player doesn't have 10gp).
  5. !cm -share will collect all the money and share it evenly on the members, using gp, sp and cp only (pp and ep will be converted). Can also be used for one character to 'exchange' money.
  6. !cm -transfer "Tazeka Liranov" 40gp will transfer 40 gp from the selected token to the character sheet named Tazeka Liranov.
  7. !cm -convert - same as !cm -share, but will also use platinum and electrum.

Credits

With thanks to Kryx/mlenser and Michael G./VoltCruelerz for their contributions.

'); // eslint-disable-line quotes } // Display the CashMaster Menu if (argTokens.includes('-menu') || argTokens.includes('-toolbar') || argTokens.includes('-tool')) { var menuContent = '/w ' + msg.who + ' &{template:' + rt[0] + '} {{' + rt[1] + '=

Cash Master


' + '

Universal Commands

' + '
Tools' + '
[Toolbar](!cm -tool)' + '
[Status](!cm -status)' + '
Operations' + ('
[Transfer to PC](!cm -transfer "?{Recipient' + getRecipientOptions() + '}" ?{Currency to Transfer})') + '
[Transfer to NPC](!cm -giveNPC "?{List recipient name and reason}" ?{Currency to Transfer})' + ('
[Invoice Player](!cm -invoice "?{Invoicee' + getRecipientOptions() + '}" ?{Currency to Request})') + '
Utilities' + '
[Set Default Character](!cm -sc ?{Will you set a new default character|Yes})' + '
[Remove Default Character](!cm -rc ?{Will you remove your default character|Yes})'; if (playerIsGM(msg.playerid)) { menuContent = menuContent + '

GM-Only Commands

' + 'Base Commands' + '
[Readme](!cm -help)
[Party Overview](!cm -overview)' + '
[Selected USD](!cm -overview --usd)' + '
Accounting Commands' + '
[Credit Each Selected](!cm -add ?{Currency to Add})' + '
[Bill Each Selected](!cm -sub ?{Currency to Bill})' + '
[Split Among Selected](!cm -loot ?{Amount to Split})' + '
[Transaction History](!cm -th)' + '
Admin Commands' + '
[Compress Coins of Selected](!cm -merge)' + '
[Reallocate Coins](!cm -s ?{Will you REALLOCATE party funds evenly|Yes})' + '
[Set Party to Selected](!cm -sp ?{Will you SET the party to selected|Yes})'; } menuContent += '}}'; sendChat(scname, menuContent); return; } // Selectionless GM commands if (playerIsGM(msg.playerid)) { if (argTokens.includes('-transactionHistory') || argTokens.includes('-th')) { var sender = msg.who; printTransactionHistory(sender); return; } if (argTokens.includes('-revert') || argTokens.includes('-r')) { var id = parseFloat(argTokens[1]); var tx = state.CashMaster.TransactionHistory.find(function (element) { return element.Id === id; }); tx.Reverted = true; var _sender = msg.who; printTransactionHistory(_sender); return; } } // From this point forward, there must at minimum be a Subject (possibly targets as well). var parsedSubcommand = parseSubcommand(msg, subcommand, argTokens); if (parsedSubcommand === null) { log('Invalid Input. Validate that a subject is provided and input is not malformed.'); sendChat(scname, '/w gm **ERROR:** Invalid Input. Validate that a subject is provided and input is not malformed. In response to ' + msg.who + '\'s command ' + subcommand); return; } var subjects = parsedSubcommand.Subjects; var targets = parsedSubcommand.Targets; if (subjects === null) { log('Invalid Input (null subjects). Aborting.'); sendChat(scname, '/w gm **ERROR:** No subject provided by ' + msg.who + ' in command ' + subcommand); return; } if (subjects.length === 0) { log('Invalid Input (no subjects). Aborting.'); sendChat(scname, '/w gm **ERROR:** No subject provided by ' + msg.who + ' in command ' + subcommand + '.'); return; } // Coin Transfer between players if (argTokens.includes('-transfer') || argTokens.includes('-t')) { subjects.forEach(function (subject) { targets.forEach(function (target) { output = ''; var transactionOutput = ''; var subjectOutput = ''; var targetOutput = ''; var subjectName = getAttrByName(subject.id, 'character_name'); var targetName = getAttrByName(target.id, 'character_name'); // Check that the sender is not attempting to send money to themselves if (subject.id === target.id) { sendChat(scname, '**ERROR:** target character must not be selected character.'); return; } // Verify subject has enough to perform transfer // Check if the player attempted to steal from another and populate the transaction data transactionOutput += '
Transaction Data'; if (ppa !== null) { var val = parseFloat(ppa[3]); transactionOutput += '
' + ppa[2] + ''; if (val < 0 && !playerIsGM(msg.playerid)) { sendChat(scname, '**ERROR:** ' + msg.who + ' may not demand payment from ' + targetName + '.'); return; } } if (gpa !== null) { var _val = parseFloat(gpa[3]); transactionOutput += '
' + gpa[2] + ''; if (_val < 0 && !playerIsGM(msg.playerid)) { sendChat(scname, '**ERROR:** ' + msg.who + ' may not demand payment from ' + targetName + '.'); return; } } if (epa !== null) { var _val2 = parseFloat(epa[3]); transactionOutput += '
' + epa[2] + ''; if (_val2 < 0 && !playerIsGM(msg.playerid)) { sendChat(scname, '**ERROR:** ' + msg.who + ' may not demand payment from ' + targetName + '.'); return; } } if (spa !== null) { var _val3 = parseFloat(spa[3]); transactionOutput += '
' + spa[2] + ''; if (_val3 < 0 && !playerIsGM(msg.playerid)) { sendChat(scname, '**ERROR:** ' + msg.who + ' may not demand payment from ' + targetName + '.'); return; } } if (cpa !== null) { var _val4 = parseFloat(cpa[3]); transactionOutput += '
' + cpa[2] + ''; if (_val4 < 0 && !playerIsGM(msg.playerid)) { sendChat(scname, '/w gm **ERROR:** ' + msg.who + ' may not demand payment from ' + targetName + '.'); return; } } // Load subject's existing account var dpp = parseFloat(getattr(subject.id, 'pp')) || 0; var dgp = parseFloat(getattr(subject.id, 'gp')) || 0; var dep = parseFloat(getattr(subject.id, 'ep')) || 0; var dsp = parseFloat(getattr(subject.id, 'sp')) || 0; var dcp = parseFloat(getattr(subject.id, 'cp')) || 0; var subjectAccount = [dpp, dgp, dep, dsp, dcp]; var subjectInitial = [dpp, dgp, dep, dsp, dcp]; if (ppa !== null) subjectAccount = changeMoney(subjectAccount, ppa[2]); if (gpa !== null) subjectAccount = changeMoney(subjectAccount, gpa[2]); if (epa !== null) subjectAccount = changeMoney(subjectAccount, epa[2]); if (spa !== null) subjectAccount = changeMoney(subjectAccount, spa[2]); if (cpa !== null) subjectAccount = changeMoney(subjectAccount, cpa[2]); // Verify subject has enough to perform transfer subjectOutput += '
' + subjectName + ' has '; if (subjectAccount === 'ERROR: Not enough cash.') { subjectOutput += 'not enough cash!'; } else { var subjectEffect = getPlayerEffect(subjectName, getDelta(subjectAccount, subjectInitial)); // Update subject account and update output setattr(subject.id, 'pp', parseFloat(subjectAccount[0])); setattr(subject.id, 'gp', parseFloat(subjectAccount[1])); setattr(subject.id, 'ep', parseFloat(subjectAccount[2])); setattr(subject.id, 'sp', parseFloat(subjectAccount[3])); setattr(subject.id, 'cp', parseFloat(subjectAccount[4])); subjectOutput += '
' + subjectAccount[0] + 'pp'; subjectOutput += '
' + subjectAccount[1] + 'gp'; subjectOutput += '
' + subjectAccount[2] + 'ep'; subjectOutput += '
' + subjectAccount[3] + 'sp'; subjectOutput += '
' + subjectAccount[4] + 'cp'; // targetFunds var tpp = parseFloat(getattr(target.id, 'pp')) || 0; var tgp = parseFloat(getattr(target.id, 'gp')) || 0; var tep = parseFloat(getattr(target.id, 'ep')) || 0; var tsp = parseFloat(getattr(target.id, 'sp')) || 0; var tcp = parseFloat(getattr(target.id, 'cp')) || 0; var targetInitial = [tpp, tgp, tep, tsp, tcp]; if (ppa !== null) tpp += parseFloat(ppa[3]); if (gpa !== null) tgp += parseFloat(gpa[3]); if (epa !== null) tep += parseFloat(epa[3]); if (spa !== null) tsp += parseFloat(spa[3]); if (cpa !== null) tcp += parseFloat(cpa[3]); var targetFinal = [tpp, tgp, tep, tsp, tcp]; var targetEffect = getPlayerEffect(targetName, getDelta(targetFinal, targetInitial)); setattr(target.id, 'pp', tpp); setattr(target.id, 'gp', tgp); setattr(target.id, 'ep', tep); setattr(target.id, 'sp', tsp); setattr(target.id, 'cp', tcp); targetOutput += '
' + targetName + ' has '; targetOutput += '
' + tpp + 'pp'; targetOutput += '
' + tgp + 'gp'; targetOutput += '
' + tep + 'ep'; targetOutput += '
' + tsp + 'sp'; targetOutput += '
' + tcp + 'cp'; recordTransaction('Transfer to PC', msg.who, [subjectEffect, targetEffect]); } sendChat(scname, '/w gm &{template:' + rt[0] + '} {{' + rt[1] + '=GM Transfer Report
' + subjectName + '>' + targetName + '
' + transactionOutput + subjectOutput + targetOutput + '}}'); sendChat(scname, '/w ' + msg.who + ' &{template:' + rt[0] + '} {{' + rt[1] + '=Sender Transfer Report
' + subjectName + ' > ' + targetName + '
' + output + transactionOutput + subjectOutput + '}}'); sendChat(scname, '/w ' + targetName + ' &{template:' + rt[0] + '} {{' + rt[1] + '=Recipient Transfer Report
' + subjectName + ' > ' + targetName + '
' + output + transactionOutput + targetOutput + '}}'); }); }); return; } // Invoice between players if (argTokens.includes('-invoice') || argTokens.includes('-i')) { subjects.forEach(function (subject) { targets.forEach(function (target) { output = ''; var transactionOutput = ''; var targetOutput = ''; var invoiceAmount = ''; var subjectName = getAttrByName(subject.id, 'character_name'); var targetName = getAttrByName(target.id, 'character_name'); // Check that the sender is not attempting to send money to themselves if (subject.id === target.id) { sendChat(scname, '**ERROR:** target character must not be selected character.'); return; } // Verify subject has enough to perform transfer // Check if the player attempted to reverse-invoice themselves transactionOutput += '
Requested Funds:'; if (ppa !== null) { var val = parseFloat(ppa[3]); transactionOutput += '
' + ppa[2]; invoiceAmount += ' ' + ppa[2]; if (val < 0 && !playerIsGM(msg.playerid)) { sendChat(scname, '**ERROR:** ' + msg.who + ' may not reverse-invoice themselves.'); return; } } if (gpa !== null) { var _val5 = parseFloat(gpa[3]); transactionOutput += '
' + gpa[2]; invoiceAmount += ' ' + gpa[2]; if (_val5 < 0 && !playerIsGM(msg.playerid)) { sendChat(scname, '**ERROR:** ' + msg.who + ' may not reverse-invoice themselves.'); return; } } if (epa !== null) { var _val6 = parseFloat(epa[3]); transactionOutput += '
' + epa[2]; invoiceAmount += ' ' + epa[2]; if (_val6 < 0 && !playerIsGM(msg.playerid)) { sendChat(scname, '**ERROR:** ' + msg.who + ' may not reverse-invoice themselves.'); return; } } if (spa !== null) { var _val7 = parseFloat(spa[3]); transactionOutput += '
' + spa[2]; invoiceAmount += ' ' + spa[2]; if (_val7 < 0 && !playerIsGM(msg.playerid)) { sendChat(scname, '**ERROR:** ' + msg.who + ' may not reverse-invoice themselves.'); return; } } if (cpa !== null) { var _val8 = parseFloat(cpa[3]); transactionOutput += '
' + cpa[2]; invoiceAmount += ' ' + cpa[2]; if (_val8 < 0 && !playerIsGM(msg.playerid)) { sendChat(scname, '/w gm **ERROR:** ' + msg.who + ' may not reverse-invoice themselves.'); return; } } // Load target's existing account var tpp = parseFloat(getattr(target.id, 'pp')) || 0; var tgp = parseFloat(getattr(target.id, 'gp')) || 0; var tep = parseFloat(getattr(target.id, 'ep')) || 0; var tsp = parseFloat(getattr(target.id, 'sp')) || 0; var tcp = parseFloat(getattr(target.id, 'cp')) || 0; targetOutput += '
Current Funds of ' + targetName + ''; targetOutput += '
' + tpp + 'pp'; targetOutput += '
' + tgp + 'gp'; targetOutput += '
' + tep + 'ep'; targetOutput += '
' + tsp + 'sp'; targetOutput += '
' + tcp + 'cp'; sendChat(scname, '/w gm &{template:' + rt[0] + '} {{' + rt[1] + '=GM Invoice Report
' + subjectName + '>' + targetName + '
' + transactionOutput + targetOutput + '}}'); sendChat(scname, '/w ' + msg.who + ' &{template:' + rt[0] + '} {{' + rt[1] + '=Invoice Sent to ' + targetName + '
' + transactionOutput + '}}'); sendChat(scname, '/w ' + targetName + ' &{template:' + rt[0] + '} {{' + rt[1] + '=Invoice Received from ' + subjectName + '
' + transactionOutput + targetOutput + '
[Pay](!cm -transfer -S "' + targetName + '" -T "' + subjectName + '" -C "' + invoiceAmount + '")}}'); }); }); return; } // Display coin count to player if (argTokens.includes('-status') || argTokens.includes('-ss')) { subjects.forEach(function (subject) { var coinStatus = playerCoinStatus(subject); sendChat(scname, '/w ' + msg.who + ' &{template:' + rt[0] + '} {{' + rt[1] + '=Coin Purse Status
' + coinStatus[0] + '}}'); }); return; } // Drop Currency or Give it to an NPC if (argTokens.includes('-dropWithReason') || argTokens.includes('-giveNPC')) { subjects.forEach(function (subject) { output = ''; var transactionOutput = ''; var subjectOutput = ''; var subjectName = getAttrByName(subject.id, 'character_name'); var reason = targets[0]; // Verify subject has enough to perform transfer // Check if the player attempted to steal from another and populate the transaction data transactionOutput += '
Transaction Data'; if (ppa !== null) { var val = parseFloat(ppa[3]); transactionOutput += '
' + ppa[2]; if (val < 0 && !playerIsGM(msg.playerid)) { sendChat(scname, '**ERROR:** ' + msg.who + ' tried to steal.'); return; } } if (gpa !== null) { var _val9 = parseFloat(gpa[3]); transactionOutput += '
' + gpa[2]; if (_val9 < 0 && !playerIsGM(msg.playerid)) { sendChat(scname, '**ERROR:** ' + msg.who + ' tried to steal.'); return; } } if (epa !== null) { var _val10 = parseFloat(epa[3]); transactionOutput += '
' + epa[2]; if (_val10 < 0 && !playerIsGM(msg.playerid)) { sendChat(scname, '**ERROR:** ' + msg.who + ' tried to steal.'); return; } } if (spa !== null) { var _val11 = parseFloat(spa[3]); transactionOutput += '
' + spa[2]; if (_val11 < 0 && !playerIsGM(msg.playerid)) { sendChat(scname, '**ERROR:** ' + msg.who + ' tried to steal.'); return; } } if (cpa !== null) { var _val12 = parseFloat(cpa[3]); transactionOutput += '
' + cpa[2]; if (_val12 < 0 && !playerIsGM(msg.playerid)) { sendChat(scname, '**ERROR:** ' + msg.who + ' tried to steal.'); return; } } // Load subject's existing account var dpp = parseFloat(getattr(subject.id, 'pp')) || 0; var dgp = parseFloat(getattr(subject.id, 'gp')) || 0; var dep = parseFloat(getattr(subject.id, 'ep')) || 0; var dsp = parseFloat(getattr(subject.id, 'sp')) || 0; var dcp = parseFloat(getattr(subject.id, 'cp')) || 0; var subjectInitial = [dpp, dgp, dep, dsp, dcp]; var subjectAccount = [dpp, dgp, dep, dsp, dcp]; if (ppa !== null) subjectAccount = changeMoney(subjectAccount, ppa[2]); if (gpa !== null) subjectAccount = changeMoney(subjectAccount, gpa[2]); if (epa !== null) subjectAccount = changeMoney(subjectAccount, epa[2]); if (spa !== null) subjectAccount = changeMoney(subjectAccount, spa[2]); if (cpa !== null) subjectAccount = changeMoney(subjectAccount, cpa[2]); // Verify subject has enough to perform transfer subjectOutput += '
' + subjectName + ' has '; if (subjectAccount === 'ERROR: Not enough cash.') { subjectOutput += 'not enough cash!'; } else { var subjectEffect = getPlayerEffect(subjectName, getDelta(subjectAccount, subjectInitial)); // Update subject account and update output setattr(subject.id, 'pp', parseFloat(subjectAccount[0])); setattr(subject.id, 'gp', parseFloat(subjectAccount[1])); setattr(subject.id, 'ep', parseFloat(subjectAccount[2])); setattr(subject.id, 'sp', parseFloat(subjectAccount[3])); setattr(subject.id, 'cp', parseFloat(subjectAccount[4])); subjectOutput += '
' + subjectAccount[0] + 'pp'; subjectOutput += '
' + subjectAccount[1] + 'gp'; subjectOutput += '
' + subjectAccount[2] + 'ep'; subjectOutput += '
' + subjectAccount[3] + 'sp'; subjectOutput += '
' + subjectAccount[4] + 'cp'; recordTransaction('Transfer to NPC', msg.who, [subjectEffect]); } sendChat(scname, '/w gm &{template:' + rt[0] + '} {{' + rt[1] + '=GM Transfer Report
' + subjectName + '
' + reason + '
' + transactionOutput + subjectOutput + '}}'); sendChat(scname, '/w ' + subjectName + ' &{template:' + rt[0] + '} {{' + rt[1] + '=Sender Transfer Report
' + subjectName + '
' + reason + '
' + output + transactionOutput + subjectOutput + '}}'); }); return; } // Set the default character for a given player if (argTokens.includes('-setDefaultCharacterName') || argTokens.includes('-sc')) { var setNewCharacter = false; if (msg.selected) { var pcToken = msg.selected[0]; var token = getObj('graphic', pcToken._id); // eslint-disable-line no-underscore-dangle if (token) { var pc = getObj('character', token.get('represents')); if (pc) { pcName = getAttrByName(pc.id, 'character_name'); if (pcName) { var mapLog = 'Mapping Speaker ' + msg.playerid + ' to PC ' + pcName; log(mapLog); state.CashMaster.DefaultCharacterNames[msg.playerid] = pcName; sendChat(scname, '/w gm ' + mapLog); sendChat(scname, '/w ' + msg.who + ' Updated Default Character to ' + pcName); setNewCharacter = true; } } } } if (!setNewCharacter) { sendChat(scname, '/w ' + msg.who + ' **ERROR:** You did not have a named character token selected.'); } } // Removes the default character for a given player if (argTokens.includes('-removeDefaultCharacterName') || argTokens.includes('-rc')) { if (state.CashMaster.DefaultCharacterNames[msg.playerid]) { delete state.CashMaster.DefaultCharacterNames[msg.playerid]; sendChat(scname, '/w gm Erased Default Character for ' + msg.who); sendChat(scname, '/w ' + msg.who + ' Erased Default Character'); } else { sendChat(scname, '/w ' + msg.who + ' You do not have a default character assigned.'); } } // GM-Only Commands if (playerIsGM(msg.playerid)) { // Calculate pre-existing party total var partytotal = 0; var partycounter = 0; var partymember = null; var partyGoldOperation = false; // Create party gold output string if (subjects) { partymember = subjects.length; subjects.forEach(function (subject) { partycounter += 1; name = getAttrByName(subject.id, 'character_name'); pp = parseFloat(getattr(subject.id, 'pp')) || 0; gp = parseFloat(getattr(subject.id, 'gp')) || 0; ep = parseFloat(getattr(subject.id, 'ep')) || 0; sp = parseFloat(getattr(subject.id, 'sp')) || 0; cp = parseFloat(getattr(subject.id, 'cp')) || 0; total = Math.round((pp * 10 + ep * 0.5 + gp + sp / 10 + cp / 100) * 10000) / 10000; partytotal = total + partytotal; }); partytotal = Math.round(partytotal * 100, 0) / 100; } // Merge a player's coin into the densest possible if (argTokens.includes('-merge') || argTokens.includes('-m')) { output = ''; var transactionEffects = []; subjects.forEach(function (subject) { // Load player's existing account var subjectName = getAttrByName(subject.id, 'character_name'); var playerAccount = [parseFloat(getattr(subject.id, 'pp')) || 0, parseFloat(getattr(subject.id, 'gp')) || 0, parseFloat(getattr(subject.id, 'ep')) || 0, parseFloat(getattr(subject.id, 'sp')) || 0, parseFloat(getattr(subject.id, 'cp')) || 0]; var playerInitial = [playerAccount[0], playerAccount[1], playerAccount[2], playerAccount[3], playerAccount[4]]; var mergeResult = mergeMoney(playerAccount); if (mergeResult.length == null) { output += '
' + subjectName + ' has '; output += mergeResult; output += '
' + playerAccount[0] + 'pp'; output += '
' + playerAccount[1] + 'gp'; output += '
' + playerAccount[2] + 'ep'; output += '
' + playerAccount[3] + 'sp'; output += '
' + playerAccount[4] + 'cp'; return; } // Update subject account and update output setattr(subject.id, 'pp', parseFloat(mergeResult[0])); setattr(subject.id, 'gp', parseFloat(mergeResult[1])); setattr(subject.id, 'ep', parseFloat(mergeResult[2])); setattr(subject.id, 'sp', parseFloat(mergeResult[3])); setattr(subject.id, 'cp', parseFloat(mergeResult[4])); output += '
' + subjectName + ' has '; output += '
' + mergeResult[0] + 'pp'; output += '
' + mergeResult[1] + 'gp'; output += '
' + mergeResult[2] + 'ep'; output += '
' + mergeResult[3] + 'sp'; output += '
' + mergeResult[4] + 'cp'; transactionEffects.push(getPlayerEffect(subjectName, getDelta(mergeResult, playerInitial))); recordTransaction('Merge', msg.who, transactionEffects); }); sendChat(scname, '/w gm &{template:' + rt[0] + '} {{' + rt[1] + '=Coin Merge Report
' + output + '}}'); partyGoldOperation = true; } // Reallocate existing resources of party as if all coin purses were thrown together and split evenly if (argTokens.includes('-share') || argTokens.includes('-best-share') || argTokens.includes('-s') || argTokens.includes('-bs')) { output = ''; var cashshare = partytotal / partycounter; var newcounter = 0; var pps = Math.floor(cashshare / 10); if (argTokens.includes('-share') || argTokens.includes('-s')) { pps = 0; } var rest = cashshare - pps * 10; var gps = Math.floor(rest); rest = (rest - gps) * 2; var eps = Math.floor(rest); if (argTokens.includes('-share') || argTokens.includes('-s')) { eps = 0; } rest = (rest - eps) * 5; var sps = Math.floor(rest); rest = (rest - sps) * 10; var cps = Math.round(rest); rest = (rest - cps) * partycounter; sendChat(scname, '/w gm &{template:' + rt[0] + '} {{' + rt[1] + '=Let\u2019s share this!
Everyone receives the equivalent of ' + toUsd(cashshare) + ' gp: ' + pps + ' platinum, ' + gps + ' gold, ' + eps + ' electrum, ' + sps + ' silver, and ' + cps + ' copper.}}'); var _transactionEffects = []; subjects.forEach(function (subject) { var subjectName = getAttrByName(subject.id, 'character_name'); var ipp = parseFloat(getattr(subject.id, 'pp')) || 0; var igp = parseFloat(getattr(subject.id, 'gp')) || 0; var iep = parseFloat(getattr(subject.id, 'ep')) || 0; var isp = parseFloat(getattr(subject.id, 'sp')) || 0; var icp = parseFloat(getattr(subject.id, 'cp')) || 0; var playerInitial = [ipp, igp, iep, isp, icp]; setattr(subject.id, 'pp', pps); setattr(subject.id, 'gp', gps); setattr(subject.id, 'ep', eps); setattr(subject.id, 'sp', sps); // enough copper coins? If not, the last one in the group has to take the diff if ((rest > 0.999 || rest < -0.999) && newcounter === partycounter) { cps += Math.round(rest); } setattr(subject.id, 'cp', cps); _transactionEffects.push(getPlayerEffect(subjectName, getDelta([pps, gps, eps, sps, cps], playerInitial))); partyGoldOperation = true; }); recordTransaction('Reallocate Currency', msg.who, _transactionEffects); } // Add coin to target if (argTokens.includes('-add') || argTokens.includes('-a') || argTokens.includes('-credit')) { output = ''; // Perform operations on each target var _transactionEffects2 = []; subjects.forEach(function (subject) { var subjectName = getAttrByName(subject.id, 'character_name'); pp = parseFloat(getattr(subject.id, 'pp')) || 0; gp = parseFloat(getattr(subject.id, 'gp')) || 0; ep = parseFloat(getattr(subject.id, 'ep')) || 0; sp = parseFloat(getattr(subject.id, 'sp')) || 0; cp = parseFloat(getattr(subject.id, 'cp')) || 0; var subjectInitial = [pp, gp, ep, sp, cp]; var subjectFinal = [pp, gp, ep, sp, cp]; total = Math.round((pp * 10 + ep * 0.5 + gp + sp / 10 + cp / 100) * 10000) / 10000; partytotal = total + partytotal; output += '
' + subjectName + ''; if (ppa) { setattr(subject.id, 'pp', parseFloat(pp) + parseFloat(ppa[3])); output += '
' + ppa[2]; subjectFinal[0] += parseFloat(ppa[3]); } if (gpa) { setattr(subject.id, 'gp', parseFloat(gp) + parseFloat(gpa[3])); output += '
' + gpa[2]; subjectFinal[1] += parseFloat(gpa[3]); } if (epa) { setattr(subject.id, 'ep', parseFloat(ep) + parseFloat(epa[3])); output += '
' + epa[2]; subjectFinal[2] += parseFloat(epa[3]); } if (spa) { setattr(subject.id, 'sp', parseFloat(sp) + parseFloat(spa[3])); output += '
' + spa[2]; subjectFinal[3] += parseFloat(spa[3]); } if (cpa) { setattr(subject.id, 'cp', parseFloat(cp) + parseFloat(cpa[3])); output += '
' + cpa[2]; subjectFinal[4] += parseFloat(cpa[3]); } _transactionEffects2.push(getPlayerEffect(subjectName, getDelta(subjectFinal, subjectInitial))); sendChat(scname, '/w ' + subjectName + ' &{template:' + rt[0] + '} {{' + rt[1] + '=GM has Disbursed Coin
' + output + '}}'); }); var type = msg.content.includes('-revert ') ? 'Revert Transaction' : 'Add'; recordTransaction(type, msg.who, _transactionEffects2); var s = subjects.length > 1 ? 's' : ''; sendChat(scname, '/w gm &{template:' + rt[0] + '} {{' + rt[1] + '=Disbursement to Player' + s + '
' + output + '}}'); } // Subtract coin from target if (argTokens.includes('-pay') || argTokens.includes('-p') || argTokens.includes('-subtract') || argTokens.includes('-sub') || argTokens.includes('-bill')) { output = ''; var _transactionEffects3 = []; subjects.forEach(function (subject) { partycounter += 1; var subjectName = getAttrByName(subject.id, 'character_name'); pp = parseFloat(getattr(subject.id, 'pp')) || 0; gp = parseFloat(getattr(subject.id, 'gp')) || 0; ep = parseFloat(getattr(subject.id, 'ep')) || 0; sp = parseFloat(getattr(subject.id, 'sp')) || 0; cp = parseFloat(getattr(subject.id, 'cp')) || 0; var targetInitial = [pp, gp, ep, sp, cp]; var targetFinal = [pp, gp, ep, sp, cp]; if (ppa !== null) targetFinal = changeMoney(targetFinal, ppa[2]); if (gpa !== null) targetFinal = changeMoney(targetFinal, gpa[2]); if (epa !== null) targetFinal = changeMoney(targetFinal, epa[2]); if (spa !== null) targetFinal = changeMoney(targetFinal, spa[2]); if (cpa !== null) targetFinal = changeMoney(targetFinal, cpa[2]); output += '
' + subjectName + ' has '; if (targetFinal === 'ERROR: Not enough cash.') output += 'not enough cash!';else { setattr(subject.id, 'pp', parseFloat(targetFinal[0])); output += '
' + targetFinal[0] + 'pp'; setattr(subject.id, 'gp', parseFloat(targetFinal[1])); output += '
' + targetFinal[1] + 'gp'; setattr(subject.id, 'ep', parseFloat(targetFinal[2])); output += '
' + targetFinal[2] + 'ep'; setattr(subject.id, 'sp', parseFloat(targetFinal[3])); output += '
' + targetFinal[3] + 'sp'; setattr(subject.id, 'cp', parseFloat(targetFinal[4])); output += '
' + targetFinal[4] + 'cp'; _transactionEffects3.push(getPlayerEffect(subjectName, getDelta(targetFinal, targetInitial))); } sendChat(scname, '/w ' + subjectName + ' &{template:' + rt[0] + '} {{' + rt[1] + '=GM has Removed Coin
' + output + '}}'); }); recordTransaction('Subtract', msg.who, _transactionEffects3); var _s = msg.selected.length > 1 ? 's' : ''; sendChat(scname, '/w gm &{template:' + rt[0] + '} {{' + rt[1] + '=Bill Collection from Player' + _s + '
' + output + '}}'); partyGoldOperation = true; } // Evenly distribute sum of coin to group of players if (argTokens.includes('-loot') || argTokens.includes('-l')) { populateCoinContents(subcommand); output = ''; partycounter = 0; var _transactionEffects4 = []; msg.selected.forEach(function (obj) { var token = getObj('graphic', obj._id); // eslint-disable-line no-underscore-dangle var character = void 0; if (token) { character = getObj('character', token.get('represents')); } if (character) { partycounter += 1; name = getAttrByName(character.id, 'character_name'); pp = parseFloat(getattr(character.id, 'pp')) || 0; gp = parseFloat(getattr(character.id, 'gp')) || 0; ep = parseFloat(getattr(character.id, 'ep')) || 0; sp = parseFloat(getattr(character.id, 'sp')) || 0; cp = parseFloat(getattr(character.id, 'cp')) || 0; var targetInitial = [pp, gp, ep, sp, cp]; var targetFinal = [pp, gp, ep, sp, cp]; var ppt = void 0; var gpt = void 0; var ept = void 0; var spt = void 0; var cpt = void 0; if (ppa !== null) { ppt = cashsplit(ppa[3], partymember, partycounter); } if (gpa !== null) { gpt = cashsplit(gpa[3], partymember, partycounter); } if (epa !== null) { ept = cashsplit(epa[3], partymember, partycounter); } if (spa !== null) { spt = cashsplit(spa[3], partymember, partycounter); } if (cpa !== null) { cpt = cashsplit(cpa[3], partymember, partycounter); } output += '
' + name + ''; if (ppa) { targetFinal[0] = parseFloat(pp) + parseFloat(ppt); setattr(character.id, 'pp', targetFinal[0]); output += '
' + ppt + 'pp'; } if (gpa) { targetFinal[1] = parseFloat(gp) + parseFloat(gpt); setattr(character.id, 'gp', targetFinal[1]); output += '
' + gpt + 'gp'; } if (epa) { targetFinal[2] = parseFloat(ep) + parseFloat(ept); setattr(character.id, 'ep', targetFinal[2]); output += '
' + ept + 'ep'; } if (spa) { targetFinal[3] = parseFloat(sp) + parseFloat(spt); setattr(character.id, 'sp', targetFinal[3]); output += '
' + spt + 'sp'; } if (cpa) { targetFinal[4] = parseFloat(cp) + parseFloat(cpt); setattr(character.id, 'cp', targetFinal[4]); output += '
' + cpt + 'cp'; } sendChat(scname, '/w ' + name + ' &{template:' + rt[0] + '} {{' + rt[1] + '=Distributing Loot
' + output + '}}'); _transactionEffects4.push(getPlayerEffect(name, getDelta(targetFinal, targetInitial))); } }); recordTransaction('Distribute Loot', msg.who, _transactionEffects4); sendChat(scname, '/w gm &{template:' + rt[0] + '} {{' + rt[1] + '=Distributing Loot
' + output + '}}'); partyGoldOperation = true; } // Set Party to selected if (argTokens.includes('-setParty') || argTokens.includes('-sp')) { var partyList = []; if (!argTokens.includes('-clear')) { msg.selected.forEach(function (obj) { var token = getObj('graphic', obj._id); // eslint-disable-line no-underscore-dangle var pc = void 0; if (token) { pc = getObj('character', token.get('represents')); if (pc) { pcName = getAttrByName(pc.id, 'character_name'); if (pcName) { partyList.push(pcName); } } } }); } log('Party List: ' + partyList); state.CashMaster.Party = partyList; sendChat(scname, '/w gm **Party:' + partyList.length + '**
' + partyList); } // Calculate party gold value if (partyGoldOperation || argTokens.includes('-overview') || argTokens.includes('-o')) { //! overview partytotal = 0; partycounter = 0; if (!argTokens.includes('--usd')) usd2 = 0;else usd2 = usd; output = '/w gm &{template:' + rt[0] + '} {{' + rt[1] + '=Party\u2019s cash overview

'; subjects.forEach(function (subject) { output += playerCoinStatus(subject, usd2)[0]; partytotal += playerCoinStatus(subject, usd2)[1]; }); partytotal = Math.round(partytotal * 100, 0) / 100; output += 'Party total: ' + toUsd(partytotal, usd2) + '}}'; sendChat(scname, output); } } }); }); });