Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- (function (root, factory) {
- if(typeof define === 'function' && define.amd) {
- // AMD. Register as an anonymous module.
- define(['lodash'], factory);
- } else if(typeof exports === 'object') {
- // Node, CommonJS-like
- module.exports = factory(require('lodash'));
- } else if(typeof setup === 'object') {
- // SugarCube globals
- setup.Skills = factory(root._);
- } else {
- // Browser globals
- root.Skills = factory(root._);
- }
- }(typeof self !== 'undefined' ? self : this, function(_) {
- var _autoFail = { roll: -50, result: -50, critical: false, fumble: false, success: false, failure: true };
- var _skills = {};
- var calcModdedValue = function(base, mod) {
- if(!_.isFinite(base)) {
- return undefined;
- }
- if(_.isUndefined(mod)) {
- return {value: base, mod: {add: 0, mult: 0, baseAdd: 0, baseMult: 0}};
- }
- var unifiedMod = Object.values(mod).reduce(function(result, m) {
- if(_.isFinite(m)) {
- result.add += m;
- } else {
- result.add += m.add || 0;
- result.mult += m.mult || 0;
- result.baseAdd += m.baseAdd || 0;
- result.baseMult += m.baseMult || 0;
- }
- return result;
- }, {add: 0, mult: 0, baseAdd: 0, baseMult: 0});
- return {
- value: (base * (1 + unifiedMod.baseMult) + unifiedMod.baseAdd) * (1 + unifiedMod.mult) + unifiedMod.add,
- mod: unifiedMod,
- };
- };
- var Skill = function(skill, attribute, options) {
- options = options || {};
- this.id = skill;
- this.attribute = attribute;
- this.options = Object.assign({}, options);
- this.tags = options.tags || [];
- delete this.options.tags;
- this.hasTag = (t => this.tags.includes(t));
- this.hasAnyTag = (ts => this.tags.includesAny(ts));
- };
- var Skills = {
- init: function(character) {
- if(!_.isObject(character)) {
- return;
- }
- character.attributes = character.attributes || {};
- character.skills = character.skills || {};
- },
- define: function(skill, attribute, options) {
- if(_.isString(skill) && _.isString(attribute)) {
- return _skills[skill] = new Skill(skill, attribute, options);
- }
- },
- byId: function(skill) {
- return _skills[skill];
- },
- get all() {
- return Object.values(_skills);
- },
- raw: function(character, skill) {
- if(skill instanceof Skill) {
- skill = skill.id;
- }
- if(!_.isObject(character) || !_.isString(skill) || !_.isObject(character.skills)) {
- return undefined;
- }
- if(!_.isFinite(character.skills[skill])) {
- return undefined;
- }
- var baseValue = character.skills[skill];
- var result = { baseValue: character.skills[skill] };
- return Object.assign(result, calcModdedValue(result.baseValue, character.skills[skill + "Mods"]));
- },
- get: function(character, skill) {
- var raw = this.raw(character, skill);
- return raw ? raw.value : undefined;
- },
- has: function(character, skill) {
- return !_.isUndefined(this.raw(character, skill));
- },
- getAll: function(character) {
- if(!_.isObject(character) || !_.isObject(character.skills)) {
- return {};
- }
- var result = Object.keys(character).filter(s => !s.endsWith('Mods'));
- return _.fromPairs(result.map(s => [s, this.get(character, s)]));
- },
- addMod: function(character, mod, value) {
- if(!_.isObject(character) || !_.isString(mod) || !_.isObject(value)) {
- return;
- }
- this.init(character);
- Object.keys(value).forEach(function(skill) {
- var key = skill + "Mods";
- character.skills[key] = character.skills[key] || {};
- character.skills[key][mod] = value[skill];
- });
- },
- removeMod: function(character, mod) {
- if(!_.isObject(character) || !_.isString(mod) || !_.isObject(character.skills)) {
- return;
- }
- Object.keys(character.skills).filter(k => k.endsWith("Mods"))
- .forEach(k => { delete character.skills[k][mod]; });
- },
- check: function(character, skill, mod) {
- if(!_.isObject(character) && !_.isFinite(character)) {
- return _.clone(this._autoFail);
- }
- var skillLevel = Number(character); /* NaN if character is an object */
- if(_.isObject(character) && _.isString(skill)) {
- /* We are called with character, skill and optional modificator */
- skillLevel = this.get(character, skill) + (mod || 0);
- }
- if(!_.isFinite(skillLevel)) {
- return _.clone(this._autoFail);
- }
- /* Generating a Gaussian random variable using Box-Muller transform */
- var u = 1 - Math.random();
- var v = 1 - Math.random();
- var roll = 50 + Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v) * 25;
- var rawCritLimit = Math.min(0, skillLevel);
- var rawFumbleLimit = Math.max(100, skillLevel);
- var rawResult = skillLevel - roll;
- return {
- roll: roll,
- result: rawResult,
- critical: (roll <= rawCritLimit || rawResult >= 80),
- fumble: (roll >= rawFumbleLimit || rawResult <= -80),
- success: (roll <= rawCritLimit || rawResult >= 0),
- failure: (roll >= rawFumbleLimit || rawResult < 0)
- };
- },
- };
- return Skills;
- }));
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement