Files
roll20-character-sheets/GammaWorld3e/merged-compendium-companion.js
Noel da Costa a13948698b GammaWorld 3e - new sheet (#6388)
* Initial Commit

GammaWorld 3e
This initial commit includes everything necessary to generate the sheet html, css and companion script. Insrtuctions in the README

* Added sheet.json

- Updated README
- added preview png

* Updated paths and sheet.json

PR validation didn't like the html and css in a subfolder.
2020-05-11 11:11:38 -04:00

100 lines
50 KiB
JavaScript

/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = "./src/api-scripts/companion.js");
/******/ })
/************************************************************************/
/******/ ({
/***/ "./src/api-scripts/companion.js":
/*!**************************************!*\
!*** ./src/api-scripts/companion.js ***!
\**************************************/
/*! no static exports found */
/***/ (function(module, exports) {
eval("/*\n * Version 0.0.1\n * Made By Noel da Costa\n */\n// import compendium from './compendium'\nfunction empty(mixedVar) {\n // discuss at: http://locutus.io/php/empty/\n // original by: Philippe Baumann\n // input by: Onno Marsman (https://twitter.com/onnomarsman)\n // input by: LH\n // input by: Stoyan Kyosev (http://www.svest.org/)\n // bugfixed by: Kevin van Zonneveld (http://kvz.io)\n // improved by: Onno Marsman (https://twitter.com/onnomarsman)\n // improved by: Francesco\n // improved by: Marc Jansen\n // improved by: Rafał Kukawski (http://blog.kukawski.pl)\n // example 1: empty(null)\n // returns 1: true\n // example 2: empty(undefined)\n // returns 2: true\n // example 3: empty([])\n // returns 3: true\n // example 4: empty({})\n // returns 4: true\n // example 5: empty({'aFunc' : function () { alert('humpty'); } })\n // returns 5: false\n var undef;\n var key;\n var i;\n var len;\n var emptyValues = [undef, null, false, 0, \"\", \"0\"];\n\n for (i = 0, len = emptyValues.length; i < len; i++) {\n if (mixedVar === emptyValues[i]) {\n return true;\n }\n }\n\n if (typeof mixedVar === \"object\") {\n for (key in mixedVar) {\n if (mixedVar.hasOwnProperty(key)) {\n return false;\n }\n }\n return true;\n }\n\n return false;\n}\n\n// @license: GammaWorld compendium not included for licensing reasons, but you can create your own, contact me for advice on how\n// import compendium from './compendium'\n\nvar GW3Companion =\n GW3Companion ||\n (function () {\n \"use strict\";\n\n let observers = {\n tokenChange: [],\n };\n\n // Styling for the chat responses.\n const styles = {\n reset: \"padding: 0; margin: 0;\",\n menu:\n \"background-color: #fff; border: 1px dashed #ae2400; padding: 5px 5px 10px 5px; border-radius: 5px;\",\n button:\n \"background-color: #000; border: 1px solid #292929; border-radius: 3px; padding: 5px; color: #fff; text-align: center;\",\n list: \"list-style: none;\",\n float: {\n right: \"float: right;\",\n left: \"float: left;\",\n },\n success:\n \"color: green; background-color: white; padding: 0.3rem 1rem; margin-left: 1rem, border-radius: 3px;\",\n fail:\n \"color: red; background-color: white; padding: 0.3rem 1rem; margin-left: 1rem, border-radius: 3px;\",\n rank:\n \"border: solid 1px black; border-radius: 2px; padding: 2px 4px; background-color: #fefefe; cursor: pointer; display: inline-block;\",\n overflow: \"overflow: hidden;\",\n row: \"margin-bottom: 5px\",\n fullWidth: \"width: 100%;\",\n underline: \"text-decoration: underline;\",\n strikethrough: \"text-decoration: strikethrough\",\n effect:\n \"font-weight: bold; margin-top: 5px; border: 1px solid grey; padding: 1rem; border-radius: 5px; background-color: #aaa; color: white;\",\n },\n script_name = \"GW3Companion\",\n state_name = \"GW3COMPANION\",\n markers = [\n \"none\",\n \"blue\",\n \"brown\",\n \"green\",\n \"pink\",\n \"purple\",\n \"red\",\n \"yellow\",\n \"-\",\n \"all-for-one\",\n \"angel-outfit\",\n \"archery-target\",\n \"arrowed\",\n \"aura\",\n \"back-pain\",\n \"black-flag\",\n \"bleeding-eye\",\n \"bolt-shield\",\n \"broken-heart\",\n \"broken-shield\",\n \"broken-skull\",\n \"chained-heart\",\n \"chemical-bolt\",\n \"cobweb\",\n \"dead\",\n \"death-zone\",\n \"drink-me\",\n \"edge-crack\",\n \"fishing-net\",\n \"fist\",\n \"fluffy-wing\",\n \"flying-flag\",\n \"frozen-orb\",\n \"grab\",\n \"grenade\",\n \"half-haze\",\n \"half-heart\",\n \"interdiction\",\n \"lightning-helix\",\n \"ninja-mask\",\n \"overdrive\",\n \"padlock\",\n \"pummeled\",\n \"radioactive\",\n \"rolling-tomb\",\n \"screaming\",\n \"sentry-gun\",\n \"skull\",\n \"sleepy\",\n \"snail\",\n \"spanner\",\n \"stopwatch\",\n \"strong\",\n \"three-leaves\",\n \"tread\",\n \"trophy\",\n \"white-tower\",\n ],\n generateUUID = (function () {\n var a = 0,\n b = [];\n return function () {\n var c = new Date().getTime() + 0,\n d = c === a;\n a = c;\n for (var e = new Array(8), f = 7; 0 <= f; f--) {\n e[\n f\n ] = \"-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz\".charAt(\n c % 64\n );\n c = Math.floor(c / 64);\n }\n c = e.join(\"\");\n if (d) {\n for (f = 11; 0 <= f && 63 === b[f]; f--) {\n b[f] = 0;\n }\n b[f]++;\n } else {\n for (f = 0; 12 > f; f++) {\n b[f] = Math.floor(64 * Math.random());\n }\n }\n for (f = 0; 12 > f; f++) {\n c += \"-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz\".charAt(\n b[f]\n );\n }\n return c;\n };\n })(),\n generateRowID = function () {\n return generateUUID().replace(/_/g, \"Z\");\n },\n getParameters = function (args) {\n let parameters = {};\n _.each(args, (arg, key) => {\n let splat = args.shift().split(\"|\");\n if (splat[1] !== undefined) {\n parameters[splat[0]] =\n splat[0] === \"title\" ? splat[1].replace(\"_\", \" \") : splat[1];\n }\n });\n return parameters;\n },\n getRollResult = function (msg, rolltext, callback, parameters) {\n sendChat(msg.playerid, rolltext, function (ops) {\n const rollresult = ops[0];\n log(rollresult);\n let result = JSON.parse(ops[0].content);\n roll = parseInt(result.total);\n callback(roll, parameters);\n });\n },\n handleInput = (msg) => {\n if (msg.type != \"api\") return;\n let data = {},\n listItems = [],\n contents = \"\",\n button = \"\";\n // Split the message into command and argument(s)\n let args = msg.content.split(\" \");\n let command = args.shift().substring(1);\n let extracommand = args.shift();\n log(msg);\n log(\"GM issued \" + script_name + \" msg: \" + msg.content);\n log(\"GM issued \" + script_name + \" command: \" + command);\n if (command == state[state_name].config.command) {\n switch (extracommand) {\n case \"reset\":\n if (!playerIsGM(msg.playerid)) return;\n state[state_name] = {};\n setDefaults(true);\n sendConfigMenu();\n break;\n\n case \"config\":\n if (!playerIsGM(msg.playerid)) return;\n let message;\n if (args.length > 0) {\n let setting = args.shift().split(\"|\");\n let key = setting.shift();\n let value =\n setting[0] === \"true\"\n ? true\n : setting[0] === \"false\"\n ? false\n : setting[0];\n state[state_name].config[key] = value;\n if (key === \"bar\") {\n //registerEventHandlers();\n message =\n '<span style=\"color: red\">The API Sandbox needs to be restarted for this to take effect.</span>';\n }\n }\n\n sendConfigMenu(false, message);\n break;\n case \"set\":\n if (!playerIsGM(msg.playerid)) return;\n if (args.length > 0) {\n let score = args.shift().split(\"|\");\n let ability = score.shift();\n log(\"ability: \" + ability);\n log(\"score: \" + score);\n _.each(msg.selected, function (obj) {\n let token, character, attribute, exists;\n token = getObj(\"graphic\", obj._id);\n if (token) {\n character = getObj(\"character\", token.get(\"represents\"));\n }\n\n // attribute = getAttrByName(parameters['character'], `${ability}_rolled`);\n attribute = findObjs({\n _type: \"attribute\",\n characterid: character.id,\n name: `${ability}_rolled`,\n });\n log(\"ATTRIBUTE: \");\n log(attribute);\n log(attribute.length);\n if (attribute.length) {\n attribute[0].setWithWorker({ current: score });\n }\n // if (character) {\n // let rowId = generateRowID();\n // let objTemplate = {\n // max: '',\n // _id: rowId,\n // _characterid: character.id\n // };\n // let obj = Object.assign(objTemplate, {\n // name:`attr_${ability}_rolled`,\n // current: score\n // });\n // log(obj);\n // createObj('attribute',obj);\n // }\n });\n }\n break;\n case \"act\":\n log(\"ACT roll\");\n if (args.length > 0) {\n log(args);\n // Get main settings\n let rankSetting = args.shift().split(\"|\");\n let rank = rankSetting.shift();\n let roll1 = rankSetting[0];\n let roll2 = rankSetting[1];\n\n // Get other parameters\n const parameters = getParameters(args);\n log(\"parameters: \");\n log(parameters);\n log(\"act passed rank: \" + rank);\n log(roll1);\n log(roll2);\n // log(value);\n\n // get target if any and target CS mod and\n rollAct(msg, rank, parameters, roll1, roll2);\n }\n break;\n case \"import\":\n let ids = args.shift().split(\"|\");\n let category = ids.shift();\n log(\"name: \" + ids);\n log(\"typeof ids: \" + typeof ids);\n log(\"ids: \" + ids);\n log(\"category: \" + category);\n log(\"typeof category: \" + typeof category);\n importCompendiumItemToCharacter(msg, ids, category);\n break;\n case \"category\":\n log(\"category\");\n if (args.length > 0) {\n let category = args.shift();\n let cost = 0;\n data = getData();\n listItems = [];\n let items = Object.keys(data[category]);\n let subcat = {};\n let header = \"\";\n _.each(items, (item) => {\n // render type headers\n if (data[category][item].type) {\n log(\"type: \" + data[category][item].type);\n if (!subcat[data[category][item].type]) {\n subcat[data[category][item].type] = true;\n header = `<h3>${ucFirst(data[category][item].type)}</h3>`;\n log(\"set header\");\n log(header);\n } else {\n header = \"\";\n }\n }\n cost = data[category][item].cost\n ? data[category][item].cost\n : data[category][item].rarity === 2\n ? \"**\"\n : \"\";\n button =\n header +\n makeButton(\n ucFirst(data[category][item].name),\n `!gw import ${category}|${item}`,\n styles.button + styles.float.right\n );\n // log(\"COST: \"+cost);\n if (cost !== \"\") {\n listItems.push(`<span>cost: ${cost}</span>` + button);\n } else {\n listItems.push(button);\n }\n });\n let backbutton = makeButton(\n \"Back\",\n `!gw compendium`,\n styles.button + styles.float.right\n );\n\n contents =\n makeList(\n listItems,\n styles.reset + styles.list + styles.overflow,\n styles.overflow\n ) +\n '<hr><p style=\"font-size: 80%\">You can always come back to the compendium by typing `!' +\n state[state_name].config.command +\n \" compendium`.</p><hr>\" +\n backbutton;\n makeAndSendMenu(\n contents,\n \"Compendium </br> \" + category + \" import\",\n \"\"\n );\n }\n // button = makeButton('Backpack', '!' + state[state_name].config.command + ' import backpack', styles.button + styles.fullWidth);\n // makeAndSendMenu(button, 'Import Gear');\n break;\n case \"compendium\":\n log(\"compendium\");\n data = getData();\n listItems = [];\n let categories = [\"armour\", \"attacks\", \"gear\", \"mutations\"];\n _.each(categories, (category) => {\n button = makeButton(\n ucFirst(category),\n `!gw category ${category}`,\n styles.button + styles.float.right\n );\n listItems.push(button);\n });\n contents =\n makeList(\n listItems,\n styles.reset + styles.list + styles.overflow,\n styles.overflow\n ) +\n '<hr><p style=\"font-size: 80%\">You can always come back to the compendium by typing `!' +\n state[state_name].config.command +\n \" compendium`.</p><hr>\";\n makeAndSendMenu(contents, \"Compendium - Categories\", \"\");\n break;\n case \"effect\":\n if (args.length > 0) {\n log(args);\n let setting = args.shift().split(\"|\");\n log(setting);\n let effect = setting.shift();\n let background = setting[0] || null;\n let colour =\n background == \"white\" || background == \"yellow\"\n ? \"black\"\n : \"white\";\n let result = getEffectResult(effect, background);\n let title = result.name;\n let player = getObj(\"player\", msg.playerid);\n log(\"PLAYER: \");\n log(player);\n const parameters = getParameters(args);\n let whisper = parameters[\"whisper\"]\n ? player.get(\"_displayname\")\n : \"\";\n let content = `<div>${makeResult(\n colour,\n background,\n result.result\n )}</div>`;\n makeAndSendResult(content, title, whisper, msg.playerid);\n }\n break;\n default:\n sendConfigMenu();\n break;\n }\n }\n },\n getRollColour = (roll, row) => {\n let colour = \"white\",\n RF = 0,\n background = \"black\";\n if (roll >= row[0]) {\n colour = \"black\";\n background = \"white\";\n }\n if (roll >= row[1]) {\n colour = \"white\";\n RF++;\n background = \"blue\";\n }\n if (roll >= row[2]) {\n colour = \"white\";\n RF++;\n background = \"green\";\n }\n if (row[3] !== null && roll >= row[3]) {\n colour = \"black\";\n RF++;\n background = \"yellow\";\n }\n if (row[4] !== null && roll >= row[4]) {\n colour = \"white\";\n RF++;\n background = \"orange\";\n }\n if (roll >= row[5]) {\n colour = \"white\";\n RF++;\n background = \"red\";\n }\n return { colour, RF, background };\n },\n rollAct = (msg, rank, parameters = {}, roll1, roll2) => {\n const self = this;\n log(\"rollACT: \" + rank);\n const data = getData();\n let save,\n rankHTML = \"\",\n effectType = \"effect\",\n token = false,\n character = false,\n targetCharacter = false,\n colorResult = {},\n effectName = \"\",\n category = parameters[\"category\"],\n dmgTotalString = \"\";\n rank = parseInt(rank);\n rankHTML = `<span style=\"${styles.rank}\" title=\"Score: ${rank}\">${rank}</span>`;\n sendChat(msg.playerid, \"/roll 2d100\", function (ops) {\n log(\"roll1: \" + roll1);\n log(\"roll2: \" + roll2);\n if (roll1) {\n log(\"roll1 hardcoded\");\n } else {\n log(\"roll object\");\n log(ops);\n log(JSON.parse(ops[0].content));\n // return;\n roll1 = parseInt(JSON.parse(ops[0].content).rolls[0].results[0].v);\n roll2 = parseInt(JSON.parse(ops[0].content).rolls[0].results[1].v);\n }\n // ops will be an ARRAY of command results.\n log(\"roll1: \" + roll1);\n log(\"roll2: \" + roll2);\n if (parameters[\"mod\"]) {\n // log('calculating rank based on mod');\n // log(parameters['character']);\n // log(`${parameters['mod']}_mod`);\n // log(getAttrByName(parameters['character'], 'PS_modifier'));\n\n const mod = parseInt(\n getAttrByName(\n parameters[\"character\"],\n `${parameters[\"mod\"]}_modifier`\n )\n );\n rankHTML += ` + <span style=\"${styles.rank}\" title=\"${parameters[\"mod\"]} modifier\">${mod}</span>`;\n rank += mod;\n }\n if (parameters[\"character\"]) {\n log(\"character: \");\n log(character);\n character = getObj(\"character\", parameters[\"character\"]);\n }\n if (parameters[\"CS\"]) {\n log(\"calculating rank based on CS: \" + parseInt(parameters[\"CS\"]));\n rankHTML += ` + <span style=\"${styles.rank}\" title=\"Situational CS\">${parameters[\"CS\"]}</span>`;\n rank += parseInt(parameters[\"CS\"]);\n log(\"rank: \" + rank);\n }\n if (parameters[\"tech\"]) {\n log(\"calculating rank based on tech level\");\n let character_tech_level;\n if (character) {\n character_tech_level = getAttrByName(\n character.id,\n \"character_tech_level\"\n );\n let tech_difference = Math.abs(\n parseInt(character_tech_level) - parseInt(parameters[\"tech\"])\n );\n rankHTML += ` - <span style=\"${styles.rank}\" title=\"Tech Level Difference\">${tech_difference}</span>`;\n rank -= tech_difference;\n log(\"rank: \" + rank);\n }\n }\n if (parameters[\"target_id\"]) {\n log(\"target attributes\");\n token = getObj(\"graphic\", parameters[\"target_id\"]);\n log(token);\n if (token) {\n targetCharacter = getObj(\"character\", token.get(\"represents\"));\n log(targetCharacter);\n }\n if (!targetCharacter) {\n log(\"character not found\");\n return;\n }\n if (parameters[\"target_mod\"]) {\n let modVal = getAttrByName(\n targetCharacter.id,\n parameters[\"target_mod\"]\n );\n log(\"modVal: \" + modVal);\n rank += parseInt(modVal);\n // attributes = findObjs({\n // _type: 'attribute',\n // characterid: targetCharacter.id\n // });\n // _.each(attributes, fnction(attribute) {\n // log(attribute);\n // });\n }\n // minus target's DX mod for melee attacks\n if (\n parameters[\"category\"] === \"attacks\" &&\n parameters[\"type\"] === \"melee\"\n ) {\n let targetDXmod = getAttrByName(\n targetCharacter.id,\n \"DX_modifier\"\n );\n log(\"targetDXmod: \" + targetDXmod);\n rankHTML += ` - <span style=\"${styles.rank}\" title=\"Melee target DX mod\">${targetDXmod}</span>`;\n rank -= parseInt(targetDXmod);\n }\n }\n\n rankHTML += `: <span style=\"${styles.rank}\" title=\"Final Rank\">${rank}</span>`;\n let row = getActRow(rank);\n log(\"row: \" + row);\n log(typeof row);\n log(Array.isArray(row));\n if (!Array.isArray(row)) {\n let player = getObj(\"player\", msg.playerid);\n makeAndSendResult(\n \"ACT roll failed!\",\n \"Error:\",\n player.get(\"_displayname\"),\n msg.playerid\n );\n return;\n }\n\n colorResult = getRollColour(roll1, row);\n // log('color: ' + colour);\n // log('background: ' + background);\n // log('RC: ' + background);\n // log('RF: ' + RF);\n let title = `ACT Roll'`;\n if (parameters[\"title\"]) {\n if (parameters[\"category\"] && parameters[\"title\"] === \"ref\") {\n if (\n data[parameters[\"category\"]] &&\n data[parameters[\"category\"]][parameters[\"id\"]]\n ) {\n title = data[parameters[\"category\"]][parameters[\"id\"]].name;\n }\n } else {\n title = parameters[\"title\"];\n }\n title += ` (${rank})`;\n }\n let content = \"\";\n content += `<div style=\"${styles.row}; font-weight: bold;\">Roll: <span>${roll1}</span><div style=\"font-weight: bold; margin-bottom: 5px;\">Rank: ${rankHTML}</div>`;\n\n if (parameters[\"dmg\"]) {\n log(\n \"damage parameter: \" +\n parameters[\"dmg\"] +\n \" - \" +\n parameters[\"damage_type\"]\n );\n let baseDmg,\n DR = 0,\n soaked;\n if (parameters[\"dmg\"] === \"mutation\") {\n baseDmg = parseInt(rank) / 2;\n } else if (parameters[\"dmg\"].includes(\"/\")) {\n let dmg = parameters[\"dmg\"].split(\"/\");\n log(\"dmg: \");\n log(dmg);\n let size =\n getAttrByName(targetCharacter.id, \"character_size\") || 3;\n log(\"size: \" + size);\n baseDmg = parseInt(size) < 4 ? dmg[0] : dmg[1];\n } else {\n baseDmg = parseInt(parameters[\"dmg\"]);\n }\n log(\"baseDMG: \" + baseDmg);\n log(\"RF: \" + colorResult.RF);\n DR = getAttrByName(targetCharacter.id, \"DR_physical\") || 0;\n log(\"DR: \" + DR);\n\n let dmgTotal = parseInt(colorResult.RF) * parseInt(baseDmg);\n if (DR) {\n soaked = dmgTotal + parseInt(DR);\n }\n soaked = soaked < 1 ? 0 : soaked;\n log(\"dmgTotal: \" + dmgTotal);\n dmgTotalString = `Physical Damage: <span title=\"Base: ${baseDmg}, Dmg: ${dmgTotal} DR: ${DR}\">${soaked}</span>`;\n }\n\n content += makeResult(\n colorResult.colour,\n colorResult.background,\n colorResult.background,\n \"RF\",\n colorResult.RF,\n dmgTotalString\n );\n\n const send = (msg, parameters, title, content) => {\n if (parameters[\"character\"]) {\n makeAndSendResult(\n content,\n title,\n \"\",\n parameters[\"character\"],\n \"character\"\n );\n } else {\n makeAndSendResult(content, title, \"\", msg.playerid);\n }\n };\n\n // check save from item or from damage type\n if (parameters[\"damage_type\"]) {\n if (data[\"damage_types\"][parameters[\"damage_type\"]]) {\n if (data[\"damage_types\"][parameters[\"damage_type\"]][\"save\"]) {\n save = data[\"damage_types\"][parameters[\"damage_type\"]].save;\n }\n }\n }\n\n if (parameters[\"effect\"]) {\n effectName = parameters[\"effect\"];\n if (\n !empty(data.effects) &&\n !empty(data.effects[parameters[\"effect\"]])\n ) {\n effectName = data.effects[parameters[\"effect\"]].name;\n // let result = getEffectResult(parameters['effect'], colorResult.background);\n content += `<div style=\"font-weight: bold\">Effect: </div><div>${effectName}</div>`;\n } else if (\n !empty(data.damage_types) &&\n data.damage_types[parameters[\"effect\"]]\n ) {\n log(\n \"damage_type based on effect: \" +\n parameters[\"effect\"] +\n \", \" +\n data.damage_types[parameters[\"effect\"]]\n );\n content += `<div style=\"${\n styles.effect\n }\">Effect: <span style=\"font-weight: normal\" title=\"${\n data.damage_types[parameters[\"effect\"]].description\n }\">${data.damage_types[parameters[\"effect\"]].name}</span></div>`;\n save = data.damage_types[parameters[\"effect\"]].save;\n }\n }\n\n if (parameters[\"effect_crit\"]) {\n log(\"effect_crit: \" + parameters[\"effect_crit\"]);\n log(\"background: \" + colorResult.background);\n log(\n !empty(data.effects) && data.effects[parameters[\"effect_crit\"]]\n );\n if (colorResult.background === \"red\") {\n if (data.effects[parameters[\"effect_crit\"]]) {\n effectType = \"effect_crit\";\n content += `<div style=\"${\n styles.effect\n }\">Critical Effect: <span style=\"font-weight: normal\">${\n data.effects[parameters[\"effect_crit\"]].name\n }</span></div>`;\n } else if (data.damage_types[parameters[\"effect_crit\"]]) {\n log(data.damage_types);\n log(parameters[\"effect_crit\"]);\n log(data.damage_types[parameters[\"effect_crit\"]]);\n content += `<div style=\"${\n styles.effect\n }\">Critical Effect: <span style=\"font-weight: normal\" title=\"${\n data.damage_types[parameters[\"effect_crit\"]].description\n }\">${\n data.damage_types[parameters[\"effect_crit\"]].name\n }</span></div>`;\n save = data.damage_types[parameters[\"effect_crit\"]].save;\n }\n }\n }\n\n if (parameters[\"save\"]) {\n save = save || parameters[\"save\"];\n let saveScore = getAttrByName(targetCharacter.id, `${save}`);\n let effectsActRow = getActRow(saveScore);\n let effectsColorResult = getRollColour(roll2, effectsActRow);\n let effectsResult = { result: effectsColorResult.background };\n let result = \"\";\n log(\"effectType: \" + effectType);\n log(parameters[effectType]);\n if (!empty(data.effects) && data.effects[parameters[effectType]]) {\n effectsResult = getEffectResult(\n parameters[effectType],\n effectsColorResult.background\n );\n }\n result = effectsResult.result;\n let success =\n parseInt(effectsColorResult.RF) >= parseInt(colorResult.RF);\n let successMessage = success\n ? `<span style=\"${styles.success}\">success</span>`\n : `<span style=\"${styles.fail}\">fail</span>`;\n content += `<div style=\"font-weight: bold; margin-top: 1rem; border: 1px solid #aaa; padding: 1rem; border-radius: 5px; background-color: ${effectsColorResult.background}; color: ${effectsColorResult.colour};\">Save (${effectName}): <span style=\"font-weight: normal; font-variant:small-caps;\">${result} ${successMessage}</span></div>`;\n }\n send(msg, parameters, title, content);\n });\n },\n getActRow = (rank) => {\n log(\"getActRow\");\n rank = parseInt(rank);\n log(typeof rank + \": \" + rank);\n const cols = {\n A: [18, 74, 99, null, null, 100],\n B: [17, 73, 98, 99, null, 100],\n C: [16, 72, 97, 99, null, 100],\n \"1\": [15, 71, 96, 98, 99, 100],\n \"2\": [14, 69, 94, 97, 99, 100],\n \"3\": [13, 68, 93, 97, 97, 100],\n \"4\": [12, 66, 91, 96, 97, 100],\n \"5\": [11, 62, 87, 93, 97, 99],\n \"6\": [10, 60, 85, 92, 96, 99],\n \"7\": [9, 58, 83, 91, 96, 99],\n \"8\": [8, 56, 80, 89, 95, 99],\n \"9\": [7, 54, 78, 88, 93, 99],\n \"10\": [6, 52, 75, 86, 92, 99],\n \"11\": [5, 49, 71, 83, 91, 98],\n \"12\": [5, 47, 68, 81, 90, 98],\n \"13\": [4, 44, 65, 79, 89, 98],\n \"14\": [4, 42, 62, 77, 88, 98],\n \"15\": [4, 40, 58, 75, 87, 98],\n \"16\": [3, 37, 53, 72, 86, 97],\n \"17\": [3, 35, 49, 70, 85, 97],\n \"18\": [3, 33, 45, 68, 84, 97],\n \"19\": [3, 30, 41, 66, 83, 97],\n \"20\": [2, 26, 36, 63, 82, 96],\n \"21\": [2, 23, 32, 61, 81, 96],\n X: [2, 20, 27, 59, 80, 96],\n Y: [2, 17, 22, 56, 78, 95],\n Z: [2, 13, 16, 51, 76, 94],\n };\n if (rank <= -26) return cols[\"A\"];\n if (rank <= -6) return cols[\"B\"];\n if (rank <= 0) return cols[\"C\"];\n if (rank === 1) return cols[\"1\"];\n if (rank === 2) return cols[\"2\"];\n if (rank === 3) return cols[\"3\"];\n if (rank === 4) return cols[\"4\"];\n if (rank === 5) return cols[\"5\"];\n if (rank === 6) return cols[\"6\"];\n if (rank === 7) return cols[\"7\"];\n if (rank === 8) return cols[\"8\"];\n if (rank === 9) return cols[\"9\"];\n if (rank === 10) return cols[\"10\"];\n if (rank === 11) return cols[\"11\"];\n if (rank === 12) return cols[\"12\"];\n if (rank === 13) return cols[\"13\"];\n if (rank === 14) return cols[\"14\"];\n if (rank === 15) return cols[\"15\"];\n if (rank === 16) return cols[\"16\"];\n if (rank === 17) return cols[\"17\"];\n if (rank === 18) return cols[\"18\"];\n if (rank === 19) return cols[\"19\"];\n if (rank === 20) return cols[\"20\"];\n if (rank === 21) return cols[\"21\"];\n if (rank <= 120) return cols[\"X\"];\n if (rank <= 600) return cols[\"Y\"];\n if (rank > 600) return cols[\"Z\"];\n },\n getEffectResult = (effect, colour) => {\n let data = getData().effects;\n const index =\n colour === \"red\"\n ? 0\n : colour === \"orange\"\n ? 1\n : colour === \"yellow\"\n ? 2\n : colour === \"green\"\n ? 3\n : colour === \"blue\"\n ? 4\n : colour === \"white\"\n ? 5\n : 6;\n log(\"index: \", index);\n log(\"effectname: \", effect);\n log(data[effect]);\n log(data[effect].name);\n log(data[effect].data[index]);\n return { name: data[effect].name, result: data[effect].data[index] };\n },\n importCompendiumItemToCharacter = function (msg, ids, category) {\n log(\"import\");\n const data = getData();\n let player = getObj(\"player\", msg.playerid);\n log(\"player:\");\n log(player);\n log(\"player displayname:\");\n log(player.get(\"_displayname\"));\n if (msg.selected === undefined) {\n makeAndSendResult(\n \"Please first select a token representing the character to which you wish to import!\",\n \"Error:\",\n player.get(\"_displayname\"),\n msg.playerid\n );\n return;\n }\n _.each(msg.selected, function (obj) {\n let token, character, attribute, sections, exists;\n token = getObj(\"graphic\", obj._id);\n if (token) {\n character = getObj(\"character\", token.get(\"represents\"));\n }\n if (character) {\n attribute = findObjs({\n _type: \"attribute\",\n characterid: character.id,\n });\n } else {\n log(\"character not found\");\n return;\n }\n if (!attribute) {\n makeAndSendResult(\n \"This character sheet is blank.\",\n \"Error: \",\n player.get(\"_displayname\"),\n character.id,\n \"character\"\n );\n return;\n }\n _.each(ids, (itemId) => {\n let rowId = generateRowID();\n let objTemplate = {\n max: \"\",\n _id: rowId,\n _characterid: character.id,\n };\n if (data[category] === undefined) {\n makeAndSendResult(\n \"The selected category could not be found.\",\n \"Error: \",\n player.get(\"_displayname\"),\n character.id,\n \"character\"\n );\n return;\n }\n // let items = data[category].filter(item => item.id === itemId);\n if (!_.has(data[category], itemId)) {\n makeAndSendResult(\n \"The selected itemID could not be found.\",\n \"Error: \",\n player.get(\"_displayname\"),\n character.id,\n \"character\"\n );\n return;\n }\n let itemAttributes = data[category][itemId];\n log(\"itemAttributes: \");\n log(itemAttributes);\n _.each(itemAttributes, (attributeValue, attributeName) => {\n if (attributeName !== \"id\") {\n let obj = Object.assign(objTemplate, {\n name: `repeating_${category}_${rowId}_${attributeName}`,\n current: attributeValue,\n });\n log(obj);\n createObj(\"attribute\", obj);\n }\n });\n // add in the compendium reference\n let obj = Object.assign(objTemplate, {\n name: `repeating_${category}_${rowId}_ref`,\n current: itemId,\n });\n createObj(\"attribute\", obj);\n if (category === \"armour\" || category === \"gear\") {\n let obj = Object.assign(objTemplate, {\n name: `repeating_${category}_${rowId}_equipped`,\n current: 0,\n });\n createObj(\"attribute\", obj);\n }\n if (category === \"attacks\" || category === \"ammo\") {\n if (category === \"attacks\") {\n let character_rank = parseInt(\n getAttrByName(character.id, \"character_rank\")\n );\n log(\"character rank:\" + character_rank);\n if (character_rank === NaN) {\n log(\n \"character rank was not found and thus the attack rank could not be accurately determined and will default to 1\"\n );\n character_rank = 1;\n }\n let obj = Object.assign(objTemplate, {\n name: `repeating_${category}_${rowId}_rank`,\n current: character_rank,\n });\n createObj(\"attribute\", obj);\n }\n // also add it to gear\n _.each(itemAttributes, (attributeValue, attributeName) => {\n if (attributeName !== \"id\") {\n let obj = Object.assign(objTemplate, {\n name: `repeating_gear_${rowId}_${attributeName}`,\n current: attributeValue,\n });\n log(obj);\n createObj(\"attribute\", obj);\n }\n });\n }\n if (category === \"mutations\") {\n sendChat(msg.playerid, \"/roll 2d6\", function (ops) {\n let rollresult = ops[0];\n let result = JSON.parse(ops[0].content);\n let rolltotal = parseInt(result.total);\n if (itemAttributes.modifier !== undefined) {\n let mod =\n itemAttributes[\"type\"] === \"mental\"\n ? \"MS_modifier\"\n : \"PS_modifier\";\n let ability = attribute.filter((x) => x.get(\"name\") === mod);\n if (ability.length) {\n let obj = Object.assign(objTemplate, {\n name: `repeating_${category}_${rowId}_rank`,\n current: parseInt(ability[0].get(\"current\")) + rolltotal,\n });\n createObj(\"attribute\", obj);\n }\n }\n });\n }\n });\n });\n },\n handleBarValueChange = (obj, prev) => {\n pre_log(\"handleBarValueChange: \");\n log(obj);\n log(prev);\n\n let bar = \"bar\" + state[state_name].config.bar;\n\n if (\n !obj ||\n !prev ||\n !obj.get(\"represents\") ||\n obj.get(bar + \"_value\") === prev[bar + \"_value\"]\n ) {\n return;\n }\n\n // let attributes = {};\n let character = {},\n characterID = obj.get(\"represents\");\n character = getObj(\"character\", characterID);\n\n // obj.set(attributes);\n notifyObservers(\"tokenChange\", obj, prev);\n },\n getColor = (value) => {\n return hslToHex((1 - value) * 120, 75, 50);\n },\n hslToHex = (h, s, l) => {\n h /= 360;\n s /= 100;\n l /= 100;\n let r, g, b;\n if (s === 0) {\n r = g = b = l; // achromatic\n } else {\n const hue2rgb = (p, q, t) => {\n if (t < 0) t += 1;\n if (t > 1) t -= 1;\n if (t < 1 / 6) return p + (q - p) * 6 * t;\n if (t < 1 / 2) return q;\n if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;\n return p;\n };\n const q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n const p = 2 * l - q;\n r = hue2rgb(p, q, h + 1 / 3);\n g = hue2rgb(p, q, h);\n b = hue2rgb(p, q, h - 1 / 3);\n }\n const toHex = (x) => {\n const hex = Math.round(x * 255).toString(16);\n return hex.length === 1 ? \"0\" + hex : hex;\n };\n return `#${toHex(r)}${toHex(g)}${toHex(b)}`;\n },\n ucFirst = (string) => {\n return string.charAt(0).toUpperCase() + string.slice(1);\n },\n sendConfigMenu = (first, message) => {\n let commandButton = makeButton(\n \"!\" + state[state_name].config.command,\n \"!\" +\n state[state_name].config.command +\n \" config command|?{Command (without !)}\",\n styles.button + styles.float.right\n ),\n barButton = makeButton(\n \"bar \" + state[state_name].config.bar,\n \"!\" +\n state[state_name].config.command +\n \" config bar|?{Bar|Bar 1 (green),1|Bar 2 (blue),2|Bar 3 (red),3}\",\n styles.button + styles.float.right\n ),\n listItems = [\n '<span style=\"' +\n styles.float.left +\n '\">Command:</span> ' +\n commandButton,\n '<span style=\"' +\n styles.float.left +\n '\">HP Bar:</span> ' +\n barButton,\n ];\n\n let resetButton = makeButton(\n \"Reset\",\n \"!\" + state[state_name].config.command + \" reset\",\n styles.button + styles.fullWidth\n );\n\n let title_text = first\n ? script_name + \" First Time Setup\"\n : script_name + \" Config\";\n message = message ? \"<p>\" + message + \"</p>\" : \"\";\n let contents =\n message +\n makeList(\n listItems,\n styles.reset + styles.list + styles.overflow,\n styles.overflow\n ) +\n '<hr><p style=\"font-size: 80%\">You can always come back to this config by typing `!' +\n state[state_name].config.command +\n \" config`.</p><hr>\" +\n resetButton;\n makeAndSendMenu(contents, title_text, \"gm\");\n },\n makeAndSendMenu = (contents, title, whisper) => {\n title = title && title != \"\" && makeTitle(title);\n whisper = whisper && whisper !== \"\" && \"/w \" + whisper + \" \";\n sendChat(\n script_name,\n whisper +\n '<div style=\"' +\n styles.menu +\n styles.overflow +\n '\">' +\n title +\n contents +\n \"</div>\",\n null,\n {\n noarchive: true,\n }\n );\n },\n makeAndSendResult = (contents, title, whisper, id, type = \"player\") => {\n log(\"makeAndSendResult\");\n log(id);\n log(type);\n title = title && title != \"\" && makeTitle(title);\n whisper = whisper && whisper !== \"\" ? \"/w \" + whisper + \" \" : \"\";\n sendChat(\n `${type}|${id}`,\n whisper +\n '<div style=\"' +\n styles.menu +\n styles.overflow +\n '\">' +\n title +\n contents +\n \"</div>\",\n null,\n {\n noarchive: true,\n }\n );\n },\n makeTitle = (title) => {\n return (\n '<h3 style=\"margin-bottom: 10px; color: #ae6a00\"; font-family: \"Contrail One\";>' +\n title +\n \"</h3>\"\n );\n },\n makeButton = (title, href, style) => {\n return '<a style=\"' + style + '\" href=\"' + href + '\">' + title + \"</a>\";\n },\n makeList = (items, listStyle, itemStyle) => {\n let list = '<ul style=\"' + listStyle + '\">';\n items.forEach((item) => {\n list += '<li style=\"' + itemStyle + '\">' + item + \"</li>\";\n });\n list += \"</ul>\";\n return list;\n },\n makeResult = (colour, background, text, label, value, category = \"\") => {\n return `<div style=\"color:${colour}; background-color:${background}; border: 1px solid #aaa; border-radius: 5px; padding: 1rem; margin-bottom: 10px;\"><div>${category}</div><div style=\"font-variant:small-caps\">${text} (${label}: ${value})</div></div>`;\n },\n pre_log = (message) => {\n log(\n \"---------------------------------------------------------------------------------------------\"\n );\n log(message);\n log(\n \"---------------------------------------------------------------------------------------------\"\n );\n },\n checkInstall = () => {\n if (!_.has(state, state_name)) {\n state[state_name] = state[state_name] || {};\n }\n setDefaults();\n\n log(\n script_name + \" Ready! Command: !\" + state[state_name].config.command\n );\n if (state[state_name].config.debug) {\n makeAndSendMenu(script_name + \" Ready! Debug On.\", \"\", \"gm\");\n }\n },\n observeTokenChange = function (handler) {\n pre_log(\"token change: \");\n log(handler);\n if (handler && _.isFunction(handler)) {\n observers.tokenChange.push(handler);\n }\n },\n notifyObservers = function (event, obj, prev) {\n _.each(observers[event], function (handler) {\n handler(obj, prev);\n });\n },\n registerEventHandlers = () => {\n on(\"chat:message\", handleInput);\n on(\"change:graphic\", handleBarValueChange);\n if (\"undefined\" !== typeof TokenMod && TokenMod.ObserveTokenChange) {\n TokenMod.ObserveTokenChange(handleBarValueChange);\n }\n },\n setDefaults = (reset) => {\n const defaults = {\n config: {\n command: \"gw\",\n bar: 1,\n firsttime: reset ? false : true,\n },\n };\n\n if (!state[state_name].config) {\n state[state_name].config = defaults.config;\n } else {\n if (!state[state_name].config.hasOwnProperty(\"command\")) {\n state[state_name].config.command = defaults.config.command;\n }\n if (!state[state_name].config.hasOwnProperty(\"bar\")) {\n state[state_name].config.bar = defaults.config.bar;\n }\n }\n\n if (state[state_name].config.firsttime) {\n sendConfigMenu(true);\n state[state_name].config.firsttime = false;\n }\n },\n getData = () => {\n return compendium;\n // return {}\n };\n\n return {\n CheckInstall: checkInstall,\n ObserveTokenChange: observeTokenChange,\n RegisterEventHandlers: registerEventHandlers,\n GetData: getData,\n };\n })();\n\non(\"ready\", function () {\n \"use strict\";\n\n GW3Companion.CheckInstall();\n GW3Companion.RegisterEventHandlers();\n});\n\n\n//# sourceURL=webpack:///./src/api-scripts/companion.js?");
/***/ })
/******/ });