From f4d02cf2964269fbd23b08a269ea10f22f1af376 Mon Sep 17 00:00:00 2001 From: Jack Condon Date: Sun, 17 Oct 2021 00:16:34 +1100 Subject: [PATCH 1/3] Added System doc System doc added and it loads --- src/systems/forbidden-lands.js | 213 +++++++++++++++++++++++++++++++++ src/systems/tokenHelper.js | 3 + 2 files changed, 216 insertions(+) create mode 100644 src/systems/forbidden-lands.js diff --git a/src/systems/forbidden-lands.js b/src/systems/forbidden-lands.js new file mode 100644 index 0000000..4608f94 --- /dev/null +++ b/src/systems/forbidden-lands.js @@ -0,0 +1,213 @@ +import {compatibleCore} from "../misc.js"; + +export class forbiddenlands{ + constructor(){ + + } + + getHP(token) { + const hp = token.actor.data.data.attributes.attribute.strength; + return { + value: hp.value, + max: hp.max + } + } + + getTempHP(token) { + return 0; + const hp = token.actor.data.data.attributes.hp; + return { + value: (hp.temp == null) ? 0 : hp.temp, + max: (hp.tempmax == null) ? 0 : hp.tempmax + } + } + + getAC(token) { + + const totalArmor = token.actor.itemTypes.armor.reduce((sum, armor) => { + if (armor.itemProperties.part === "shield") return sum; + const value = armor.itemProperties.bonus.value; + return (sum += value); + }, 0); + return totalArmor; + } + + getShieldHP(token) { + return; + } + + getSpeed(token) { + return 1; + const movement = token.actor.data.data.attributes.movement; + let speed = ""; + if (movement != undefined){ + if (movement.burrow > 0) speed += `${game.i18n.localize("DND5E.MovementBurrow")}: ${movement.burrow + movement.units}`; + if (movement.climb > 0) { + if (speed.length > 0) speed += '\n'; + speed += `${game.i18n.localize("DND5E.MovementClimb")}: ${movement.climb + movement.units}`; + } + if (movement.fly > 0) { + if (speed.length > 0) speed += '\n'; + speed += `${game.i18n.localize("DND5E.MovementFly")}: ${movement.fly + movement.units}`; + } + if (movement.hover > 0) { + if (speed.length > 0) speed += '\n'; + speed += `${game.i18n.localize("DND5E.MovementHover")}: ${movement.hover + movement.units}`; + } + if (movement.swim > 0) { + if (speed.length > 0) speed += '\n'; + speed += `${game.i18n.localize("DND5E.MovementSwim")}: ${movement.swim + movement.units}`; + } + if (movement.walk > 0) { + if (speed.length > 0) speed += '\n'; + speed += `${game.i18n.localize("DND5E.MovementWalk")}: ${movement.walk + movement.units}`; + } + } + else { + const spd = token.actor.data.data.attributes.speed; + speed = spd.value; + if (spd.special.length > 0) speed + "\n" + spd.special; + } + return speed; + } + + getInitiative(token) { + return 0; + let initiative = token.actor.data.data.attributes.init.total; + return (initiative >= 0) ? `+${initiative}` : initiative; + } + + toggleInitiative(token) { + return; + } + + getPassivePerception(token) { + return 0; + return token.actor.data.data.skills.prc.passive; + } + + getPassiveInvestigation(token) { + return; + return token.actor.data.data.skills.inv.passive; + } + + getAbility(token, ability) { + if (ability == undefined) ability = 'strength'; + return token.actor.data.data.attributes.attribute?.[ability].value; + } + + getAbilityModifier(token, ability) { + return; + } + + getAbilitySave(token, ability) { + return this.getAbility(token, ability); + } + + getSkill(token, skill) { + if (skill == undefined) skill = 'might'; + const val = token.actor.data.data.skills.skill?.[skill].value; + return (val >= 0) ? `+${val}` : val; + } + + getProficiency(token) { + return; + const val = token.actor.data.data.attributes.prof; + return (val >= 0) ? `+${val}` : val; + } + + getConditionIcon(condition) { + if (condition == undefined) condition = 'removeAll'; + if (condition == 'removeAll') return window.CONFIG.controlIcons.effects; + else return CONFIG.statusEffects.find(e => e.id === condition).icon; + } + + getConditionActive(token,condition) { + if (condition == undefined) condition = 'removeAll'; + return token.actor.effects.find(e => e.isTemporary === condition) != undefined; + } + + async toggleCondition(token,condition) { + if (condition == undefined) condition = 'removeAll'; + if (condition == 'removeAll'){ + for( let effect of token.actor.effects) + await effect.delete(); + } + else { + const effect = CONFIG.statusEffects.find(e => e.id === condition); + await token.toggleEffect(effect); + } + return true; + } + + /** + * Roll + */ + roll(token,roll,options,ability,skill,save) { + if (roll == undefined) roll = 'ability'; + if (ability == undefined) ability = 'strength'; + if (skill == undefined) skill = 'might'; + if (save == undefined) save = 'strength'; + + if (roll == 'ability') token.actor.rollAbilityTest(ability,options); + else if (roll == 'save') token.actor.rollAbilitySave(save,options); + else if (roll == 'skill') token.actor.rollSkill(skill,options); + else if (roll == 'initiative') token.actor.rollInitiative(options); + else if (roll == 'deathSave') token.actor.rollDeathSave(options); + } + + /** + * Items + */ + getItems(token,itemType) { + if (itemType == undefined) itemType = 'any'; + const allItems = token.actor.items; + if (itemType == 'any') return allItems.filter(i => i.type == 'weapon' || i.type == 'equipment' || i.type == 'consumable' || i.type == 'loot' || i.type == 'container'); + else return allItems.filter(i => i.type == itemType); + } + + getItemUses(item) { + return {available: item.data.data.quantity}; + } + + /** + * Features + */ + getFeatures(token,featureType) { + if (featureType == undefined) featureType = 'any'; + const allItems = token.actor.items; + if (featureType == 'any') return allItems.filter(i => i.type == 'class' || i.type == 'feat') + else return allItems.filter(i => i.type == featureType) + } + + getFeatureUses(item) { + if (item.data.type == 'class') return {available: item.data.data.levels}; + else return { + available: item.data.data.uses.value, + maximum: item.data.data.uses.max + }; + } + + /** + * Spells + */ + getSpells(token,level) { + if (level == undefined) level = 'any'; + const allItems = token.actor.items; + if (level == 'any') return allItems.filter(i => i.type == 'spell') + else return allItems.filter(i => i.type == 'spell' && i.data.data.level == level) + } + + getSpellUses(token,level,item) { + if (level == undefined) level = 'any'; + if (item.data.data.level == 0) return; + return { + available: token.actor.data.data.spells?.[`spell${level}`].value, + maximum: token.actor.data.data.spells?.[`spell${level}`].max + } + } + + rollItem(item) { + return item.roll() + } +} \ No newline at end of file diff --git a/src/systems/tokenHelper.js b/src/systems/tokenHelper.js index aaa7618..5b050f9 100644 --- a/src/systems/tokenHelper.js +++ b/src/systems/tokenHelper.js @@ -3,8 +3,10 @@ import {dnd35e} from "./dnd35e.js" import {pf2e} from "./pf2e.js" import {demonlord} from "./demonlord.js"; import {wfrp4e} from "./wfrp4e.js" +import {forbiddenlands} from "./forbidden-lands.js" import {compatibleCore} from "../misc.js"; + export class TokenHelper{ constructor(){ this.system; @@ -16,6 +18,7 @@ export class TokenHelper{ else if (game.system.id == 'pf2e') this.system = new pf2e(); else if (game.system.id == 'demonlord') this.system = new demonlord(); else if (game.system.id == 'wfrp4e') this.system = new wfrp4e(); + else if (game.system.id == 'forbidden-lands') this.system = new forbiddenlands(); else this.system = new dnd5e(); //default to dnd5e } From c74d27610a0510bcb60b8ac425c87fcbba8cdcfb Mon Sep 17 00:00:00 2001 From: Jack Condon Date: Tue, 19 Oct 2021 00:48:01 +1100 Subject: [PATCH 2/3] Push Finished Forbidden Lands, All stats have been added into the rolling --- src/systems/forbidden-lands.js | 103 +++++++++++++++++++-------------- src/systems/tokenHelper.js | 20 +++++++ src/token.js | 53 +++++++++++++++++ 3 files changed, 133 insertions(+), 43 deletions(-) diff --git a/src/systems/forbidden-lands.js b/src/systems/forbidden-lands.js index 4608f94..105febf 100644 --- a/src/systems/forbidden-lands.js +++ b/src/systems/forbidden-lands.js @@ -6,13 +6,47 @@ export class forbiddenlands{ } getHP(token) { - const hp = token.actor.data.data.attributes.attribute.strength; + const hp = token.actor.data.data.attribute.strength; return { value: hp.value, max: hp.max } } + + getAgility(token) { + const agility = token.actor.data.data.attribute.agility; + return { + value: agility.value, + max: agility.max + } + } + + + getWits(token) { + const wits = token.actor.data.data.attribute.wits; + return { + value: wits.value, + max: wits.max + } + } + + getEmpathy(token) { + const empathy = token.actor.data.data.attribute.empathy; + return { + value: empathy.value, + max: empathy.max + } + } + + getWillPower(token) { + const wp = token.actor.data.data.bio.willpower; + return { + value: wp.value, + max: wp.max + } + } + getTempHP(token) { return 0; const hp = token.actor.data.data.attributes.hp; @@ -38,37 +72,6 @@ export class forbiddenlands{ getSpeed(token) { return 1; - const movement = token.actor.data.data.attributes.movement; - let speed = ""; - if (movement != undefined){ - if (movement.burrow > 0) speed += `${game.i18n.localize("DND5E.MovementBurrow")}: ${movement.burrow + movement.units}`; - if (movement.climb > 0) { - if (speed.length > 0) speed += '\n'; - speed += `${game.i18n.localize("DND5E.MovementClimb")}: ${movement.climb + movement.units}`; - } - if (movement.fly > 0) { - if (speed.length > 0) speed += '\n'; - speed += `${game.i18n.localize("DND5E.MovementFly")}: ${movement.fly + movement.units}`; - } - if (movement.hover > 0) { - if (speed.length > 0) speed += '\n'; - speed += `${game.i18n.localize("DND5E.MovementHover")}: ${movement.hover + movement.units}`; - } - if (movement.swim > 0) { - if (speed.length > 0) speed += '\n'; - speed += `${game.i18n.localize("DND5E.MovementSwim")}: ${movement.swim + movement.units}`; - } - if (movement.walk > 0) { - if (speed.length > 0) speed += '\n'; - speed += `${game.i18n.localize("DND5E.MovementWalk")}: ${movement.walk + movement.units}`; - } - } - else { - const spd = token.actor.data.data.attributes.speed; - speed = spd.value; - if (spd.special.length > 0) speed + "\n" + spd.special; - } - return speed; } getInitiative(token) { @@ -93,7 +96,7 @@ export class forbiddenlands{ getAbility(token, ability) { if (ability == undefined) ability = 'strength'; - return token.actor.data.data.attributes.attribute?.[ability].value; + return token.actor.data.data.attribute?.[ability].value; } getAbilityModifier(token, ability) { @@ -106,8 +109,9 @@ export class forbiddenlands{ getSkill(token, skill) { if (skill == undefined) skill = 'might'; - const val = token.actor.data.data.skills.skill?.[skill].value; - return (val >= 0) ? `+${val}` : val; + let skillComp = token.actor.sheet.getSkill(skill); + const val = skillComp.skill.value + skillComp.attribute.value; + return game.i18n.localize(skillComp.skill.label)+`-${val}`; } getProficiency(token) { @@ -149,11 +153,15 @@ export class forbiddenlands{ if (skill == undefined) skill = 'might'; if (save == undefined) save = 'strength'; - if (roll == 'ability') token.actor.rollAbilityTest(ability,options); - else if (roll == 'save') token.actor.rollAbilitySave(save,options); - else if (roll == 'skill') token.actor.rollSkill(skill,options); - else if (roll == 'initiative') token.actor.rollInitiative(options); - else if (roll == 'deathSave') token.actor.rollDeathSave(options); + if (roll == 'ability') token.actor.sheet.rollAttribute(ability); + else if (roll == 'save') token.actor.sheet.rollAttribute(save); + else if (roll == 'skill') token.actor.sheet.rollSkill(skill); + else if (roll == 'rollFood') token.actor.sheet.rollConsumable('food'); + else if (roll == 'rollWater') token.actor.sheet.rollConsumable('water'); + else if (roll == 'rollArrows') token.actor.sheet.rollConsumable('arrows'); + else if (roll == 'rollTorches') token.actor.sheet.rollConsumable('torches'); + else if (roll == 'rollArmor') token.actor.sheet.rollArmor(); + //else if (roll == 'initiative') token.actor.rollInitiative(options); } /** @@ -167,7 +175,8 @@ export class forbiddenlands{ } getItemUses(item) { - return {available: item.data.data.quantity}; + return {available: item.data.data.bonus.value, + maximum: item.data.data.bonus.max}; } /** @@ -176,7 +185,7 @@ export class forbiddenlands{ getFeatures(token,featureType) { if (featureType == undefined) featureType = 'any'; const allItems = token.actor.items; - if (featureType == 'any') return allItems.filter(i => i.type == 'class' || i.type == 'feat') + if (featureType == 'any') return allItems.filter(i => i.type == 'talent') else return allItems.filter(i => i.type == featureType) } @@ -208,6 +217,14 @@ export class forbiddenlands{ } rollItem(item) { - return item.roll() + const sheet = item.actor.sheet; + if (item.type === "armor") + return sheet.rollSpecificArmor(item.id); + else if (item.type === "weapon") + return sheet.rollGear(item.id); + else if (item.type === "spell") + return sheet.rollSpell(item.id); + else + return item.sendToChat(); } } \ No newline at end of file diff --git a/src/systems/tokenHelper.js b/src/systems/tokenHelper.js index 5b050f9..eed2f70 100644 --- a/src/systems/tokenHelper.js +++ b/src/systems/tokenHelper.js @@ -230,6 +230,26 @@ export class TokenHelper{ return this.system.getPerception(token) } + /* forbidden-lands */ + getAgility(token) { + return this.system.getAgility(token) + } + + /* forbidden-lands */ + getWits(token) { + return this.system.getWits(token) + } + + /* forbidden-lands */ + getEmpathy(token) { + return this.system.getEmpathy(token) + } + /* forbidden-lands */ + getWillPower(token) { + return this.system.getWillPower(token) + } + + /** * Conditions */ diff --git a/src/token.js b/src/token.js index 617644a..5c0a197 100644 --- a/src/token.js +++ b/src/token.js @@ -106,6 +106,59 @@ export class TokenControl{ }; } + + if (stats == 'Agility') { /* forbidden-lands */ + const wits = tokenHelper.getAgility(token); + txt += wits.value + "/" + wits.max; + + if (icon == 'stats') + uses = { + available: wits.value, + maximum: wits.max, + heart: "#FF0000" + }; + + } + + if (stats == 'Wits') { /* forbidden-lands */ + const wits = tokenHelper.getWits(token); + txt += wits.value + "/" + wits.max; + + if (icon == 'stats') + uses = { + available: wits.value, + maximum: wits.max, + heart: "#FF0000" + }; + + } + + if (stats == 'Empathy') { /* forbidden-lands */ + const wits = tokenHelper.getEmpathy(token); + txt += wits.value + "/" + wits.max; + + if (icon == 'stats') + uses = { + available: wits.value, + maximum: wits.max, + heart: "#FF0000" + }; + + } + + if (stats == 'WillPower') { /* forbidden-lands */ + const wits = tokenHelper.getWillPower(token); + txt += wits.value + "/" + wits.max; + + if (icon == 'stats') + uses = { + available: wits.value, + maximum: wits.max, + heart: "#FF0000" + }; + + } + if (stats == 'CriticalWounds') { /* WFRP4e */ const criticalWounds = tokenHelper.getCriticalWounds(token); txt += criticalWounds.value + "/" + criticalWounds.max; From 888a2971fbcd294c573f8d2394de7fc894279fe9 Mon Sep 17 00:00:00 2001 From: Jack Condon Date: Tue, 19 Oct 2021 01:21:04 +1100 Subject: [PATCH 3/3] Support for monster attack and raw item quantity. --- src/systems/forbidden-lands.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/systems/forbidden-lands.js b/src/systems/forbidden-lands.js index 105febf..0eb1a00 100644 --- a/src/systems/forbidden-lands.js +++ b/src/systems/forbidden-lands.js @@ -161,6 +161,7 @@ export class forbiddenlands{ else if (roll == 'rollArrows') token.actor.sheet.rollConsumable('arrows'); else if (roll == 'rollTorches') token.actor.sheet.rollConsumable('torches'); else if (roll == 'rollArmor') token.actor.sheet.rollArmor(); + else if (roll == 'monsterAttack') token.actor.sheet.rollAttack(); //else if (roll == 'initiative') token.actor.rollInitiative(options); } @@ -170,11 +171,17 @@ export class forbiddenlands{ getItems(token,itemType) { if (itemType == undefined) itemType = 'any'; const allItems = token.actor.items; - if (itemType == 'any') return allItems.filter(i => i.type == 'weapon' || i.type == 'equipment' || i.type == 'consumable' || i.type == 'loot' || i.type == 'container'); - else return allItems.filter(i => i.type == itemType); + if (itemType == 'any') return allItems.filter(i => i.type == 'weapon' || i.type == 'armor' || i.type == 'gear' || i.type == 'rawMaterial'); + else if (token.actor.type == 'monster' && itemType == 'weapon') + { + return allItems.filter(i => i.type == 'monsterAttack'); + } + return allItems.filter(i => i.type == itemType); } getItemUses(item) { + if (item.type == 'monsterAttack') return; + if (item.type == 'rawMaterial') return {available: item.data.data.quantity}; return {available: item.data.data.bonus.value, maximum: item.data.data.bonus.max}; } @@ -224,7 +231,8 @@ export class forbiddenlands{ return sheet.rollGear(item.id); else if (item.type === "spell") return sheet.rollSpell(item.id); - else + else if (item.type === "monsterAttack") + sheet.rollSpecificAttack(item.id); return item.sendToChat(); } } \ No newline at end of file