DND5e Core 1.2.2
DND5e Core 1.2.2 modded to SW5e system
|
@ -1323,7 +1323,7 @@
|
|||
}
|
||||
.sw5e.chat-card .card-footer span {
|
||||
border-right: 2px groove #FFF;
|
||||
padding: 0 5px 0 0;
|
||||
padding: 0 3px 0 0;
|
||||
font-size: 10px;
|
||||
}
|
||||
.sw5e.chat-card .card-footer span:last-child {
|
||||
|
@ -1491,6 +1491,7 @@
|
|||
}
|
||||
.sw5e.sheet.actor.character .characteristics textarea {
|
||||
font-family: "Signika", serif;
|
||||
font-size: 13px;
|
||||
border: 1px solid #c9c7b8;
|
||||
resize: none;
|
||||
}
|
||||
|
|
7
dnd5e.js
|
@ -78,6 +78,9 @@ Hooks.once("init", function() {
|
|||
CONFIG.Item.entityClass = Item5e;
|
||||
CONFIG.time.roundTime = 6;
|
||||
|
||||
// 5e cone RAW should be 53.13 degrees
|
||||
CONFIG.MeasuredTemplate.defaults.angle = 53.13;
|
||||
|
||||
// Register System Settings
|
||||
registerSystemSettings();
|
||||
|
||||
|
@ -127,7 +130,7 @@ Hooks.once("setup", function() {
|
|||
"abilities", "abilityAbbreviations", "abilityActivationTypes", "abilityConsumptionTypes", "actorSizes", "alignments",
|
||||
"armorProficiencies", "conditionTypes", "consumableTypes", "cover", "currencies", "damageResistanceTypes",
|
||||
"damageTypes", "distanceUnits", "equipmentTypes", "healingTypes", "itemActionTypes", "languages",
|
||||
"limitedUsePeriods", "movementUnits", "polymorphSettings", "proficiencyLevels", "senses", "skills",
|
||||
"limitedUsePeriods", "movementTypes", "movementUnits", "polymorphSettings", "proficiencyLevels", "senses", "skills",
|
||||
"powerComponents", "powerLevels", "powerPreparationModes", "powerScalingModes", "powerSchools", "targetTypes",
|
||||
"timePeriods", "toolProficiencies", "weaponProficiencies", "weaponProperties", "weaponTypes"
|
||||
];
|
||||
|
@ -164,7 +167,7 @@ Hooks.once("ready", function() {
|
|||
// Determine whether a system migration is required and feasible
|
||||
if ( !game.user.isGM ) return;
|
||||
const currentVersion = game.settings.get("sw5e", "systemMigrationVersion");
|
||||
const NEEDS_MIGRATION_VERSION = "1.2.0";
|
||||
const NEEDS_MIGRATION_VERSION = "1.2.1";
|
||||
const COMPATIBLE_MIGRATION_VERSION = 0.80;
|
||||
const needsMigration = currentVersion && isNewerVersion(NEEDS_MIGRATION_VERSION, currentVersion);
|
||||
if ( !needsMigration ) return;
|
||||
|
|
|
@ -653,6 +653,7 @@
|
|||
"SW5E.WeaponMartialProficiency": "Martial Weapons",
|
||||
"SW5E.WeaponMartialR": "Martial Ranged",
|
||||
"SW5E.WeaponNatural": "Natural",
|
||||
"SW5E.WeaponPropertiesAda": "Adamantine",
|
||||
"SW5E.WeaponPropertiesAmm": "Ammunition",
|
||||
"SW5E.WeaponPropertiesFin": "Finesse",
|
||||
"SW5E.WeaponPropertiesFir": "Firearm",
|
||||
|
@ -660,9 +661,11 @@
|
|||
"SW5E.WeaponPropertiesHvy": "Heavy",
|
||||
"SW5E.WeaponPropertiesLgt": "Light",
|
||||
"SW5E.WeaponPropertiesLod": "Loading",
|
||||
"SW5E.WeaponPropertiesMgc": "Magical",
|
||||
"SW5E.WeaponPropertiesRch": "Reach",
|
||||
"SW5E.WeaponPropertiesRel": "Reload",
|
||||
"SW5E.WeaponPropertiesRet": "Returning",
|
||||
"SW5E.WeaponPropertiesSil": "Silvered",
|
||||
"SW5E.WeaponPropertiesSpc": "Special",
|
||||
"SW5E.WeaponPropertiesThr": "Thrown",
|
||||
"SW5E.WeaponPropertiesTwo": "Two-Handed",
|
||||
|
|
|
@ -426,11 +426,6 @@
|
|||
border: none;
|
||||
margin-right: 5px;
|
||||
}
|
||||
h4 {
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -168,6 +168,7 @@
|
|||
}
|
||||
textarea {
|
||||
font-family: "Signika", serif;
|
||||
font-size: 13px;
|
||||
border: 1px solid @colorFaint;
|
||||
resize: none;
|
||||
}
|
||||
|
|
|
@ -93,8 +93,14 @@ export default class Actor5e extends Actor {
|
|||
init.total = init.mod + init.prof + init.bonus;
|
||||
|
||||
// Prepare power-casting data
|
||||
this._computePowercastingDC(this.data);
|
||||
data.attributes.powerdc = data.attributes.powercasting ? data.abilities[data.attributes.powercasting].dc : 10;
|
||||
this._computePowercastingProgression(this.data);
|
||||
|
||||
// Compute owned item attributes which depend on prepared Actor data
|
||||
this.items.forEach(item => {
|
||||
item.getSaveDC();
|
||||
item.getAttackToHit();
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
@ -169,7 +175,10 @@ export default class Actor5e extends Actor {
|
|||
}
|
||||
|
||||
// Load item data for all identified features
|
||||
const features = await Promise.all(ids.map(id => fromUuid(id)));
|
||||
const features = [];
|
||||
for ( let id of ids ) {
|
||||
features.push(await fromUuid(id));
|
||||
}
|
||||
|
||||
// Class powers should always be prepared
|
||||
for ( const feature of features ) {
|
||||
|
@ -313,19 +322,22 @@ export default class Actor5e extends Actor {
|
|||
const joat = flags.jackOfAllTrades;
|
||||
const observant = flags.observantFeat;
|
||||
const skillBonus = Number.isNumeric(bonuses.skill) ? parseInt(bonuses.skill) : 0;
|
||||
let round = Math.floor;
|
||||
for (let [id, skl] of Object.entries(data.skills)) {
|
||||
skl.value = parseFloat(skl.value || 0);
|
||||
skl.value = Math.clamped(Number(skl.value).toNearest(0.5), 0, 2) ?? 0;
|
||||
let round = Math.floor;
|
||||
|
||||
// Apply Remarkable Athlete or Jack of all Trades
|
||||
let multi = skl.value;
|
||||
if ( athlete && (skl.value === 0) && feats.remarkableAthlete.abilities.includes(skl.ability) ) {
|
||||
multi = 0.5;
|
||||
// Remarkable
|
||||
if ( athlete && (skl.value < 0.5) && feats.remarkableAthlete.abilities.includes(skl.ability) ) {
|
||||
skl.value = 0.5;
|
||||
round = Math.ceil;
|
||||
}
|
||||
if ( joat && (skl.value === 0 ) ) multi = 0.5;
|
||||
|
||||
// Retain the maximum skill proficiency when skill proficiencies are merged
|
||||
// Jack of All Trades
|
||||
if ( joat && (skl.value < 0.5) ) {
|
||||
skl.value = 0.5;
|
||||
}
|
||||
|
||||
// Polymorph Skill Proficiencies
|
||||
if ( originalSkills ) {
|
||||
skl.value = Math.max(skl.value, originalSkills[id].value);
|
||||
}
|
||||
|
@ -333,7 +345,7 @@ export default class Actor5e extends Actor {
|
|||
// Compute modifier
|
||||
skl.bonus = checkBonus + skillBonus;
|
||||
skl.mod = data.abilities[skl.ability].mod;
|
||||
skl.prof = round(multi * data.attributes.prof);
|
||||
skl.prof = round(skl.value * data.attributes.prof);
|
||||
skl.total = skl.mod + skl.prof + skl.bonus;
|
||||
|
||||
// Compute passive bonus
|
||||
|
@ -344,23 +356,6 @@ export default class Actor5e extends Actor {
|
|||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Compute the powercasting DC for all item abilities which use power DC scaling
|
||||
* @param {object} actorData The actor data being prepared
|
||||
* @private
|
||||
*/
|
||||
_computePowercastingDC(actorData) {
|
||||
|
||||
// Compute the powercasting DC
|
||||
const data = actorData.data;
|
||||
data.attributes.powerdc = data.attributes.powercasting ? data.abilities[data.attributes.powercasting].dc : 10;
|
||||
|
||||
// Compute ability save DCs that depend on the calling actor
|
||||
this.items.forEach(i => i.getSaveDC());
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Prepare data related to the power-casting capabilities of the Actor
|
||||
* @private
|
||||
|
@ -420,9 +415,9 @@ export default class Actor5e extends Actor {
|
|||
for ( let [n, lvl] of Object.entries(powers) ) {
|
||||
let i = parseInt(n.slice(-1));
|
||||
if ( Number.isNaN(i) ) continue;
|
||||
if ( Number.isNumeric(lvl.override) ) lvl.max = Math.max(parseInt(lvl.override), 1);
|
||||
if ( Number.isNumeric(lvl.override) ) lvl.max = Math.max(parseInt(lvl.override), 0);
|
||||
else lvl.max = slots[i-1] || 0;
|
||||
lvl.value = Math.min(parseInt(lvl.value), lvl.max);
|
||||
lvl.value = parseInt(lvl.value);
|
||||
}
|
||||
|
||||
// Determine the Actor's pact magic level (if any)
|
||||
|
@ -1113,8 +1108,7 @@ export default class Actor5e extends Actor {
|
|||
|
||||
// Recover power slots
|
||||
for ( let [k, v] of Object.entries(data.powers) ) {
|
||||
if ( !v.max && !v.override ) continue;
|
||||
updateData[`data.powers.${k}.value`] = v.override || v.max;
|
||||
updateData[`data.powers.${k}.value`] = !Number.isNaN(v.override) ? v.override : (v.max ?? 0);
|
||||
}
|
||||
|
||||
// Recover pact slots.
|
||||
|
@ -1238,10 +1232,10 @@ export default class Actor5e extends Actor {
|
|||
}
|
||||
|
||||
// Get the original Actor data and the new source data
|
||||
const o = duplicate(this.data);
|
||||
const o = this.toJSON();
|
||||
o.flags.sw5e = o.flags.sw5e || {};
|
||||
o.flags.sw5e.transformOptions = {mergeSkills, mergeSaves};
|
||||
const source = duplicate(target.data);
|
||||
const source = target.toJSON();
|
||||
|
||||
// Prepare new data to merge from the source
|
||||
const d = {
|
||||
|
@ -1249,6 +1243,7 @@ export default class Actor5e extends Actor {
|
|||
name: `${o.name} (${source.name})`, // Append the new shape to your old name
|
||||
data: source.data, // Get the data model of your new form
|
||||
items: source.items, // Get the items of your new form
|
||||
effects: o.effects.concat(source.effects), // Combine active effects from both forms
|
||||
token: source.token, // New token configuration
|
||||
img: source.img, // New appearance
|
||||
permission: o.permission, // Use the original actor permissions
|
||||
|
|
|
@ -119,22 +119,44 @@ export default class ActorSheet5e extends ActorSheet {
|
|||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Prepare the display of movement speed data for the Actor
|
||||
* @param {object} actorData
|
||||
* Prepare the display of movement speed data for the Actor*
|
||||
* @param {object} actorData The Actor data being prepared.
|
||||
* @param {boolean} [largestPrimary=false] Show the largest movement speed as "primary", otherwise show "walk"
|
||||
* @returns {{primary: string, special: string}}
|
||||
* @private
|
||||
*/
|
||||
_getMovementSpeed(actorData) {
|
||||
_getMovementSpeed(actorData, largestPrimary=false) {
|
||||
const movement = actorData.data.attributes.movement || {};
|
||||
const speeds = [
|
||||
|
||||
// Prepare an array of available movement speeds
|
||||
let speeds = [
|
||||
[movement.burrow, `${game.i18n.localize("SW5E.MovementBurrow")} ${movement.burrow}`],
|
||||
[movement.climb, `${game.i18n.localize("SW5E.MovementClimb")} ${movement.climb}`],
|
||||
[movement.fly, `${game.i18n.localize("SW5E.MovementFly")} ${movement.fly}` + (movement.hover ? ` (${game.i18n.localize("SW5E.MovementHover")})` : "")],
|
||||
[movement.swim, `${game.i18n.localize("SW5E.MovementSwim")} ${movement.swim}`]
|
||||
].filter(s => !!s[0]).sort((a, b) => b[0] - a[0]);
|
||||
return {
|
||||
primary: `${movement.walk || 0} ${movement.units}`,
|
||||
special: speeds.length ? speeds.map(s => s[1]).join(", ") : ""
|
||||
]
|
||||
if ( largestPrimary ) {
|
||||
speeds.push([movement.walk, `${game.i18n.localize("SW5E.MovementWalk")} ${movement.walk}`]);
|
||||
}
|
||||
|
||||
// Filter and sort speeds on their values
|
||||
speeds = speeds.filter(s => !!s[0]).sort((a, b) => b[0] - a[0]);
|
||||
|
||||
// Case 1: Largest as primary
|
||||
if ( largestPrimary ) {
|
||||
let primary = speeds.shift();
|
||||
return {
|
||||
primary: `${primary ? primary[1] : "0"} ${movement.units}`,
|
||||
special: speeds.map(s => s[1]).join(", ")
|
||||
}
|
||||
}
|
||||
|
||||
// Case 2: Walk as primary
|
||||
else {
|
||||
return {
|
||||
primary: `${movement.walk || 0} ${movement.units}`,
|
||||
special: speeds.length ? speeds.map(s => s[1]).join(", ") : ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -352,7 +374,7 @@ export default class ActorSheet5e extends ActorSheet {
|
|||
1: '<i class="fas fa-check"></i>',
|
||||
2: '<i class="fas fa-check-double"></i>'
|
||||
};
|
||||
return icons[level];
|
||||
return icons[level] || icons[0];
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
|
|
@ -46,6 +46,9 @@ export default class ActorSheet5eCharacter extends ActorSheet5e {
|
|||
// Experience Tracking
|
||||
sheetData["disableExperience"] = game.settings.get("sw5e", "disableExperienceTracking");
|
||||
sheetData["classLabels"] = this.actor.itemTypes.class.map(c => c.name).join(", ");
|
||||
sheetData["multiclassLabels"] = this.actor.itemTypes.class.map(c => {
|
||||
return [c.data.data.archetype, c.name, c.data.data.levels].filterJoin(' ')
|
||||
}).join(', ');
|
||||
|
||||
// Return data for rendering
|
||||
return sheetData;
|
||||
|
@ -76,12 +79,12 @@ export default class ActorSheet5eCharacter extends ActorSheet5e {
|
|||
item.img = item.img || DEFAULT_TOKEN;
|
||||
item.isStack = Number.isNumeric(item.data.quantity) && (item.data.quantity !== 1);
|
||||
item.attunement = {
|
||||
1: {
|
||||
[CONFIG.SW5E.attunementTypes.REQUIRED]: {
|
||||
icon: "fa-sun",
|
||||
cls: "not-attuned",
|
||||
title: "SW5E.AttunementRequired"
|
||||
},
|
||||
2: {
|
||||
[CONFIG.SW5E.attunementTypes.ATTUNED]: {
|
||||
icon: "fa-sun",
|
||||
cls: "attuned",
|
||||
title: "SW5E.AttunementAttuned"
|
||||
|
|
|
@ -56,6 +56,13 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
|
|||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
_getMovementSpeed(actorData, largestPrimary=true) {
|
||||
return super._getMovementSpeed(actorData, largestPrimary);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Prepare items that are mounted to a vehicle and require one or more crew
|
||||
* to operate.
|
||||
|
@ -86,13 +93,6 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
|
|||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
_getMovementSpeed(actorData) {
|
||||
return {primary: "", special: ""};
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Organize Owned Items for rendering the Vehicle sheet.
|
||||
* @private
|
||||
|
|
|
@ -127,10 +127,13 @@ export default class AbilityUseDialog extends Dialog {
|
|||
});
|
||||
}
|
||||
const canCast = powerLevels.some(l => l.hasSlots);
|
||||
if ( !canCast ) data.errors.push(game.i18n.format("SW5E.PowerCastNoSlots", {
|
||||
level: CONFIG.SW5E.powerLevels[lvl],
|
||||
name: data.item.name
|
||||
}));
|
||||
|
||||
// Return merged data
|
||||
data = mergeObject(data, { isPower: true, consumePowerSlot, powerLevels });
|
||||
if ( !canCast ) data.errors.push("SW5E.PowerCastNoSlots");
|
||||
// Merge power casting data
|
||||
return mergeObject(data, { isPower: true, consumePowerSlot, powerLevels });
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
|
|
@ -13,7 +13,7 @@ export const _getInitiativeFormula = function(combatant) {
|
|||
let nd = 1;
|
||||
let mods = "";
|
||||
|
||||
if (actor.getFlag("sw5e", "halflingLucky")) mods += "r=1";
|
||||
if (actor.getFlag("sw5e", "halflingLucky")) mods += "r1=1";
|
||||
if (actor.getFlag("sw5e", "initiativeAdv")) {
|
||||
nd = 2;
|
||||
mods += "kh";
|
||||
|
|
|
@ -56,6 +56,16 @@ SW5E.alignments = {
|
|||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* An enumeration of item attunement types
|
||||
* @enum {number}
|
||||
*/
|
||||
SW5E.attunementTypes = {
|
||||
NONE: 0,
|
||||
REQUIRED: 1,
|
||||
ATTUNED: 2,
|
||||
}
|
||||
|
||||
/**
|
||||
* An enumeration of item attunement states
|
||||
* @type {{"0": string, "1": string, "2": string}}
|
||||
|
@ -303,6 +313,18 @@ SW5E.damageResistanceTypes = mergeObject(duplicate(SW5E.damageTypes), {
|
|||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* The valid units of measure for movement distances in the game system.
|
||||
* By default this uses the imperial units of feet and miles.
|
||||
* @type {Object<string,string>}
|
||||
*/
|
||||
SW5E.movementTypes = {
|
||||
"burrow": "SW5E.MovementBurrow",
|
||||
"climb": "SW5E.MovementClimb",
|
||||
"fly": "SW5E.MovementFly",
|
||||
"swim": "SW5E.MovementSwim",
|
||||
"walk": "SW5E.MovementWalk",
|
||||
}
|
||||
|
||||
/**
|
||||
* The valid units of measure for movement distances in the game system.
|
||||
|
@ -506,16 +528,19 @@ SW5E.weaponTypes = {
|
|||
* @type {Object}
|
||||
*/
|
||||
SW5E.weaponProperties = {
|
||||
"ada": "SW5E.WeaponPropertiesAda",
|
||||
"amm": "SW5E.WeaponPropertiesAmm",
|
||||
"hvy": "SW5E.WeaponPropertiesHvy",
|
||||
"fin": "SW5E.WeaponPropertiesFin",
|
||||
"fir": "SW5E.WeaponPropertiesFir",
|
||||
"foc": "SW5E.WeaponPropertiesFoc",
|
||||
"hvy": "SW5E.WeaponPropertiesHvy",
|
||||
"lgt": "SW5E.WeaponPropertiesLgt",
|
||||
"lod": "SW5E.WeaponPropertiesLod",
|
||||
"mgc": "SW5E.WeaponPropertiesMgc",
|
||||
"rch": "SW5E.WeaponPropertiesRch",
|
||||
"rel": "SW5E.WeaponPropertiesRel",
|
||||
"ret": "SW5E.WeaponPropertiesRet",
|
||||
"sil": "SW5E.WeaponPropertiesSil",
|
||||
"spc": "SW5E.WeaponPropertiesSpc",
|
||||
"thr": "SW5E.WeaponPropertiesThr",
|
||||
"two": "SW5E.WeaponPropertiesTwo",
|
||||
|
|
|
@ -1,3 +1,69 @@
|
|||
/**
|
||||
* A standardized helper function for simplifying the constant parts of a multipart roll formula
|
||||
*
|
||||
* @param {string} formula The original Roll formula
|
||||
* @param {Object} data Actor or item data against which to parse the roll
|
||||
* @param {Object} options Formatting options
|
||||
* @param {boolean} options.constantFirst Puts the constants before the dice terms in the resulting formula
|
||||
*
|
||||
* @return {string} The resulting simplified formula
|
||||
*/
|
||||
export function simplifyRollFormula(formula, data, {constantFirst = false} = {}) {
|
||||
const roll = new Roll(formula, data); // Parses the formula and replaces any @properties
|
||||
const terms = roll.terms;
|
||||
|
||||
// Some terms are "too complicated" for this algorithm to simplify
|
||||
// In this case, the original formula is returned.
|
||||
if (terms.some(_isUnsupportedTerm)) return roll.formula;
|
||||
|
||||
const rollableTerms = []; // Terms that are non-constant, and their associated operators
|
||||
const constantTerms = []; // Terms that are constant, and their associated operators
|
||||
let operators = []; // Temporary storage for operators before they are moved to one of the above
|
||||
|
||||
for (let term of terms) { // For each term
|
||||
if (["+", "-"].includes(term)) operators.push(term); // If the term is an addition/subtraction operator, push the term into the operators array
|
||||
else { // Otherwise the term is not an operator
|
||||
if (term instanceof DiceTerm) { // If the term is something rollable
|
||||
rollableTerms.push(...operators); // Place all the operators into the rollableTerms array
|
||||
rollableTerms.push(term); // Then place this rollable term into it as well
|
||||
} //
|
||||
else { // Otherwise, this must be a constant
|
||||
constantTerms.push(...operators); // Place the operators into the constantTerms array
|
||||
constantTerms.push(term); // Then also add this constant term to that array.
|
||||
} //
|
||||
operators = []; // Finally, the operators have now all been assigend to one of the arrays, so empty this before the next iteration.
|
||||
}
|
||||
}
|
||||
|
||||
const constantFormula = Roll.cleanFormula(constantTerms); // Cleans up the constant terms and produces a new formula string
|
||||
const rollableFormula = Roll.cleanFormula(rollableTerms); // Cleans up the non-constant terms and produces a new formula string
|
||||
|
||||
const constantPart = roll._safeEval(constantFormula); // Mathematically evaluate the constant formula to produce a single constant term
|
||||
|
||||
const parts = constantFirst ? // Order the rollable and constant terms, either constant first or second depending on the optional argumen
|
||||
[constantPart, rollableFormula] : [rollableFormula, constantPart];
|
||||
|
||||
// Join the parts with a + sign, pass them to `Roll` once again to clean up the formula
|
||||
return new Roll(parts.filterJoin(" + ")).formula;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Only some terms are supported by simplifyRollFormula, this method returns true when the term is not supported.
|
||||
* @param {*} term - A single Dice term to check support on
|
||||
* @return {Boolean} True when unsupported, false if supported
|
||||
*/
|
||||
function _isUnsupportedTerm(term) {
|
||||
const diceTerm = term instanceof DiceTerm;
|
||||
const operator = ["+", "-"].includes(term);
|
||||
const number = !isNaN(Number(term));
|
||||
|
||||
return !(diceTerm || operator || number);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* A standardized helper function for managing core 5e "d20 rolls"
|
||||
*
|
||||
|
@ -53,7 +119,7 @@ export async function d20Roll({parts=[], data={}, event={}, rollMode=null, templ
|
|||
|
||||
// Determine the d20 roll and modifiers
|
||||
let nd = 1;
|
||||
let mods = halflingLucky ? "r=1" : "";
|
||||
let mods = halflingLucky ? "r1=1" : "";
|
||||
|
||||
// Handle advantage
|
||||
if (adv === 1) {
|
||||
|
@ -109,6 +175,8 @@ export async function d20Roll({parts=[], data={}, event={}, rollMode=null, templ
|
|||
if (d.faces === 20) {
|
||||
d.options.critical = critical;
|
||||
d.options.fumble = fumble;
|
||||
if ( adv === 1 ) d.options.advantage = true;
|
||||
else if ( adv === -1 ) d.options.disadvantage = true;
|
||||
if (targetValue) d.options.target = targetValue;
|
||||
}
|
||||
}
|
||||
|
@ -131,7 +199,6 @@ export async function d20Roll({parts=[], data={}, event={}, rollMode=null, templ
|
|||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
|
||||
/**
|
||||
* Present a Dialog form which creates a d20 roll once submitted
|
||||
* @return {Promise<Roll>}
|
||||
|
@ -175,7 +242,6 @@ async function _d20RollDialog({template, title, parts, data, rollMode, dialogOpt
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
|
@ -235,14 +301,15 @@ export async function damageRoll({parts, actor, data, event={}, rollMode=null, t
|
|||
roll.terms[0].alter(1, criticalBonusDice);
|
||||
roll._formula = roll.formula;
|
||||
}
|
||||
roll.dice.forEach(d => d.options.critical = true);
|
||||
messageData.flavor += ` (${game.i18n.localize("SW5E.Critical")})`;
|
||||
if ( "flags.sw5e.roll" in messageData ) messageData["flags.sw5e.roll"].critical = true;
|
||||
}
|
||||
|
||||
// Execute the roll
|
||||
try {
|
||||
return roll.roll();
|
||||
roll.evaluate()
|
||||
if ( crit ) roll.dice.forEach(d => d.options.critical = true); // TODO workaround core bug which wipes Roll#options on roll
|
||||
return roll;
|
||||
} catch(err) {
|
||||
console.error(err);
|
||||
ui.notifications.error(`Dice roll evaluation failed: ${err.message}`);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import {d20Roll, damageRoll} from "../dice.js";
|
||||
import {simplifyRollFormula, d20Roll, damageRoll} from "../dice.js";
|
||||
import AbilityUseDialog from "../apps/ability-use-dialog.js";
|
||||
import AbilityTemplate from "../pixi/ability-template.js";
|
||||
|
||||
/**
|
||||
* Override and extend the basic :class:`Item` implementation
|
||||
|
@ -227,6 +226,9 @@ export default class Item5e extends Item {
|
|||
// Saving throws
|
||||
this.getSaveDC();
|
||||
|
||||
// To Hit
|
||||
this.getAttackToHit();
|
||||
|
||||
// Damage
|
||||
let dam = data.damage || {};
|
||||
if ( dam.parts ) {
|
||||
|
@ -274,6 +276,74 @@ export default class Item5e extends Item {
|
|||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Update a label to the Item detailing its total to hit bonus.
|
||||
* Sources:
|
||||
* - item entity's innate attack bonus
|
||||
* - item's actor's proficiency bonus if applicable
|
||||
* - item's actor's global bonuses to the given item type
|
||||
* - item's ammunition if applicable
|
||||
*
|
||||
* @returns {Object} returns `rollData` and `parts` to be used in the item's Attack roll
|
||||
*/
|
||||
getAttackToHit() {
|
||||
const itemData = this.data.data;
|
||||
if ( !this.hasAttack || !itemData ) return;
|
||||
const rollData = this.getRollData();
|
||||
|
||||
// Define Roll bonuses
|
||||
const parts = [];
|
||||
|
||||
// Include the item's innate attack bonus as the initial value and label
|
||||
if ( itemData.attackBonus ) {
|
||||
parts.push(itemData.attackBonus)
|
||||
this.labels.toHit = itemData.attackBonus;
|
||||
}
|
||||
|
||||
// Take no further action for un-owned items
|
||||
if ( !this.isOwned ) return {rollData, parts};
|
||||
|
||||
// Ability score modifier
|
||||
parts.push(`@mod`);
|
||||
|
||||
// Add proficiency bonus if an explicit proficiency flag is present or for non-item features
|
||||
if ( !["weapon", "consumable"].includes(this.data.type) || itemData.proficient ) {
|
||||
parts.push("@prof");
|
||||
}
|
||||
|
||||
// Actor-level global bonus to attack rolls
|
||||
const actorBonus = this.actor.data.data.bonuses?.[itemData.actionType] || {};
|
||||
if ( actorBonus.attack ) parts.push(actorBonus.attack);
|
||||
|
||||
// One-time bonus provided by consumed ammunition
|
||||
if ( (itemData.consume?.type === 'ammo') && !!this.actor.items ) {
|
||||
const ammoItemData = this.actor.items.get(itemData.consume.target)?.data;
|
||||
|
||||
if (ammoItemData) {
|
||||
const ammoItemQuantity = ammoItemData.data.quantity;
|
||||
const ammoCanBeConsumed = ammoItemQuantity && (ammoItemQuantity - (itemData.consume.amount ?? 0) >= 0);
|
||||
const ammoItemAttackBonus = ammoItemData.data.attackBonus;
|
||||
const ammoIsTypeConsumable = (ammoItemData.type === "consumable") && (ammoItemData.data.consumableType === "ammo")
|
||||
if ( ammoCanBeConsumed && ammoItemAttackBonus && ammoIsTypeConsumable ) {
|
||||
parts.push("@ammo");
|
||||
rollData["ammo"] = ammoItemAttackBonus;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Condense the resulting attack bonus formula into a simplified label
|
||||
let toHitLabel = simplifyRollFormula(parts.join('+'), rollData).trim();
|
||||
if (toHitLabel.charAt(0) !== '-') {
|
||||
toHitLabel = '+ ' + toHitLabel
|
||||
}
|
||||
this.labels.toHit = toHitLabel;
|
||||
|
||||
// Update labels and return the prepared roll data
|
||||
return {rollData, parts};
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Roll the item to Chat, creating a chat card which contains follow up attack or damage roll options
|
||||
* @param {boolean} [configureDialog] Display a configuration dialog for the item roll, if applicable?
|
||||
|
@ -344,7 +414,7 @@ export default class Item5e extends Item {
|
|||
|
||||
// Initiate measured template creation
|
||||
if ( createMeasuredTemplate ) {
|
||||
const template = AbilityTemplate.fromItem(item);
|
||||
const template = game.sw5e.canvas.AbilityTemplate.fromItem(item);
|
||||
if ( template ) template.drawPreview();
|
||||
}
|
||||
|
||||
|
@ -414,8 +484,8 @@ export default class Item5e extends Item {
|
|||
itemUpdates["data.uses.value"] = remaining;
|
||||
}
|
||||
|
||||
// Otherwise reduce quantity
|
||||
if ( consumeQuantity && !used ) {
|
||||
// Reduce quantity if not reducing usages or if usages hit 0 and we are set to consumeQuantity
|
||||
if ( consumeQuantity && (!used || (remaining === 0)) ) {
|
||||
const q = Number(id.quantity ?? 1);
|
||||
if ( q >= 1 ) {
|
||||
used = true;
|
||||
|
@ -593,7 +663,7 @@ export default class Item5e extends Item {
|
|||
|
||||
// Equipment properties
|
||||
if ( data.hasOwnProperty("equipped") && !["loot", "tool"].includes(this.data.type) ) {
|
||||
if ( data.attunement === 1 ) props.push(game.i18n.localize(CONFIG.SW5E.attunements[1]));
|
||||
if ( data.attunement === CONFIG.SW5E.attunementTypes.REQUIRED ) props.push(game.i18n.localize(CONFIG.SW5E.attunements[CONFIG.SW5E.attunementTypes.REQUIRED]));
|
||||
props.push(
|
||||
game.i18n.localize(data.equipped ? "SW5E.Equipped" : "SW5E.Unequipped"),
|
||||
game.i18n.localize(data.proficient ? "SW5E.Proficient" : "SW5E.NotProficient"),
|
||||
|
@ -718,43 +788,28 @@ export default class Item5e extends Item {
|
|||
*/
|
||||
async rollAttack(options={}) {
|
||||
const itemData = this.data.data;
|
||||
const actorData = this.actor.data.data;
|
||||
const flags = this.actor.data.flags.sw5e || {};
|
||||
if ( !this.hasAttack ) {
|
||||
throw new Error("You may not place an Attack Roll with this Item.");
|
||||
}
|
||||
let title = `${this.name} - ${game.i18n.localize("SW5E.AttackRoll")}`;
|
||||
const rollData = this.getRollData();
|
||||
|
||||
// Define Roll bonuses
|
||||
const parts = [`@mod`];
|
||||
if ( !["weapon", "consumable"].includes(this.data.type) || itemData.proficient ) {
|
||||
parts.push("@prof");
|
||||
}
|
||||
// get the parts and rollData for this item's attack
|
||||
const {parts, rollData} = this.getAttackToHit();
|
||||
|
||||
// Attack Bonus
|
||||
if ( itemData.attackBonus ) parts.push(itemData.attackBonus);
|
||||
const actorBonus = actorData?.bonuses?.[itemData.actionType] || {};
|
||||
if ( actorBonus.attack ) parts.push(actorBonus.attack);
|
||||
|
||||
// Ammunition Bonus
|
||||
// Handle ammunition consumption
|
||||
delete this._ammo;
|
||||
let ammo = null;
|
||||
let ammoUpdate = null;
|
||||
const consume = itemData.consume;
|
||||
if ( consume?.type === "ammo" ) {
|
||||
ammo = this.actor.items.get(consume.target);
|
||||
if(ammo?.data){
|
||||
if (ammo?.data) {
|
||||
const q = ammo.data.data.quantity;
|
||||
const consumeAmount = consume.amount ?? 0;
|
||||
if ( q && (q - consumeAmount >= 0) ) {
|
||||
this._ammo = ammo;
|
||||
let ammoBonus = ammo.data.data.attackBonus;
|
||||
if ( ammoBonus ) {
|
||||
parts.push("@ammo");
|
||||
rollData["ammo"] = ammoBonus;
|
||||
title += ` [${ammo.name}]`;
|
||||
}
|
||||
title += ` [${ammo.name}]`;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -874,10 +929,13 @@ export default class Item5e extends Item {
|
|||
parts.push(actorBonus.damage);
|
||||
}
|
||||
|
||||
// Add ammunition damage
|
||||
if ( this._ammo ) {
|
||||
// Handle ammunition damage
|
||||
const ammoData = this._ammo?.data;
|
||||
|
||||
// only add the ammunition damage if the ammution is a consumable with type 'ammo'
|
||||
if ( this._ammo && (ammoData.type === "consumable") && (ammoData.data.consumableType === "ammo") ) {
|
||||
parts.push("@ammo");
|
||||
rollData["ammo"] = this._ammo.data.data.damage.parts.map(p => p[0]).join("+");
|
||||
rollData["ammo"] = ammoData.data.damage.parts.map(p => p[0]).join("+");
|
||||
rollConfig.flavor += ` [${this._ammo.name}]`;
|
||||
delete this._ammo;
|
||||
}
|
||||
|
@ -1039,6 +1097,7 @@ export default class Item5e extends Item {
|
|||
left: window.innerWidth - 710,
|
||||
},
|
||||
halflingLucky: this.actor.getFlag("sw5e", "halflingLucky" ) || false,
|
||||
reliableTalent: (this.data.data.proficient >= 1) && this.actor.getFlag("sw5e", "reliableTalent"),
|
||||
messageData: {"flags.sw5e.roll": {type: "tool", itemId: this.id }}
|
||||
}, options);
|
||||
rollConfig.event = options.event;
|
||||
|
@ -1140,7 +1199,7 @@ export default class Item5e extends Item {
|
|||
case "toolCheck":
|
||||
await item.rollToolCheck({event}); break;
|
||||
case "placeTemplate":
|
||||
const template = AbilityTemplate.fromItem(item);
|
||||
const template = game.sw5e.canvas.AbilityTemplate.fromItem(item);
|
||||
if ( template ) template.drawPreview();
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -234,8 +234,8 @@ export const migrateSceneData = function(scene) {
|
|||
*/
|
||||
function _migrateActorMovement(actor, updateData) {
|
||||
const ad = actor.data;
|
||||
const old = ad?.attributes?.speed?.value;
|
||||
if ( old === undefined ) return;
|
||||
const old = actor.type === 'vehicle' ? ad?.attributes?.speed : ad?.attributes?.speed?.value;
|
||||
if ( typeof old !== "string" ) return;
|
||||
const s = (old || "").split(" ");
|
||||
if ( s.length > 0 ) updateData["data.attributes.movement.walk"] = Number.isNumeric(s[0]) ? parseInt(s[0]) : null;
|
||||
updateData["data.attributes.-=speed"] = null;
|
||||
|
@ -287,7 +287,7 @@ function _migrateActorSenses(actor, updateData) {
|
|||
*/
|
||||
function _migrateItemAttunement(item, updateData) {
|
||||
if ( item.data.attuned === undefined ) return;
|
||||
updateData["data.attunement"] = 0;
|
||||
updateData["data.attunement"] = CONFIG.SW5E.attunementTypes.NONE;
|
||||
updateData["data.-=attuned"] = null;
|
||||
return updateData;
|
||||
}
|
||||
|
|
|
@ -29,8 +29,8 @@ export default class AbilityTemplate extends MeasuredTemplate {
|
|||
|
||||
// Additional type-specific data
|
||||
switch ( templateShape ) {
|
||||
case "cone": // 5e cone RAW should be 53.13 degrees
|
||||
templateData.angle = 53.13;
|
||||
case "cone":
|
||||
templateData.angle = CONFIG.MeasuredTemplate.defaults.angle;
|
||||
break;
|
||||
case "rect": // 5e rectangular AoEs are always cubes
|
||||
templateData.distance = Math.hypot(target.value, target.value);
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
{"_id":"5Rxo4K9cgpwgW9vZ","name":"Wand of Enemy Detection","permission":{"default":0},"type":"consumable","data":{"description":{"value":"<p><em>(Requires attunement)</em></p>\n<p>This wand has 7 charges. While holding it, you can use an action and expend 1 charge to speak its command word. For the next minute, you know the direction of the nearest creature hostile to you within 60 feet, but not its distance from you. The wand can sense the presence of hostile creatures that are ethereal, invisible, disguised, or hidden, as well as those in plain sight. The effect ends if you stop holding the wand.</p>\n<p>The wand regains 1d6 + 1 expended charges daily at dawn. If you expend the wand's last charge, roll a d20. On a 1, the wand crumbles into ashes and is destroyed.</p>","chat":"","unidentified":""},"source":"DMG pg. 210","quantity":1,"weight":1,"price":4000,"attunement":0,"equipped":false,"rarity":"Rare","identified":true,"activation":{"type":"action","cost":1,"condition":"Command word."},"duration":{"value":null,"units":""},"target":{"value":null,"width":null,"units":"","type":""},"range":{"value":60,"long":null,"units":"ft"},"uses":{"value":7,"max":7,"per":"charges","autoDestroy":false,"autoUse":true},"consume":{"type":"","target":null,"amount":null},"ability":"","actionType":"util","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"1d6 +1","save":{"ability":"wis","dc":null,"scaling":"flat"},"consumableType":"wand","attributes":{"powerdc":10}},"sort":300000,"flags":{},"img":"systems/sw5e/icons/items/weapons/staff-green.jpg","effects":[]}
|
||||
{"_id":"5SorTMl8NKDO9Yge","name":"Ring of Poison Resistance","permission":{"default":0},"type":"equipment","data":{"description":{"value":"<p><em>(Requires attunement)</em></p>\n<p><em>This ring has been inlaid with an amethyst stone that glitters when it catches the light.</em></p>\n<p>You have resistance to poison damage while wearing this ring.</p>","chat":"","unidentified":""},"source":"DMG pg. 192","quantity":1,"weight":0,"price":6000,"attunement":0,"equipped":false,"rarity":"Rare","identified":true,"activation":{"type":"none","cost":0,"condition":""},"duration":{"value":0,"units":""},"target":{"value":null,"width":null,"units":null,"type":"self"},"range":{"value":null,"long":null,"units":"self"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":null,"amount":null},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":0,"type":"trinket","dex":0},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"speed":{"value":null,"conditions":""},"strength":0,"stealth":false,"proficient":false,"attributes":{"powerdc":10}},"sort":800000,"flags":{},"img":"systems/sw5e/icons/items/jewelry/ring-purple.jpg","effects":[]}
|
||||
{"_id":"5fJn3LQ2eQG7luEO","name":"Chalk","permission":{"default":0},"type":"loot","data":{"description":{"value":"<p>It is soft white porous sedimentary acarbonate rock, a form of limestone composed of the mineral calcite. Can be used to draw shapes. </p>","chat":"","unidentified":""},"source":null,"quantity":1,"weight":0,"price":"0.01","attunement":0,"equipped":false,"rarity":"Common","identified":true},"flags":{},"img":"systems/sw5e/icons/items/inventory/monster-bones.jpg","effects":[]}
|
||||
{"_id":"5m9ErO9In8Uc5yyf","name":"Potion of Superior Healing","permission":{"default":0},"type":"consumable","data":{"description":{"value":"<p><em>Agitating the potion the red liquid glimmers with it's motion.</em></p>\n<p>You regain 8d4+8 hit points when you drink this potion.</p>","chat":"","unidentified":""},"source":"DMG pg. 187","quantity":1,"weight":0.1,"price":450,"attunement":0,"equipped":false,"rarity":"Very rare","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":0,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":"touch"},"uses":{"value":1,"max":1,"per":"charges","autoDestroy":true,"autoUse":true},"consume":{"type":"","target":null,"amount":null},"ability":"","actionType":"heal","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["8d4 + 8","healing"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"consumableType":"potion","attributes":{"powerdc":10}},"sort":300001,"flags":{},"img":"systems/sw5e/icons/items/potions/grand-red.jpg","effects":[]}
|
||||
{"_id":"5m9ErO9In8Uc5yyf","name":"Potion of Superior Healing","permission":{"default":0},"type":"consumable","data":{"description":{"value":"<p><em>The potion's red liquid glimmers when agitated.</em></p>\n<p>You regain 8d4+8 hit points when you drink this potion.</p>","chat":"","unidentified":""},"source":"DMG pg. 187","quantity":1,"weight":0.1,"price":450,"attunement":0,"equipped":false,"rarity":"Rare","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":0,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":"touch"},"uses":{"value":1,"max":"1","per":"charges","autoDestroy":true,"autoUse":true},"consume":{"type":"","target":"","amount":null,"value":"","_deprecated":true},"ability":"","actionType":"heal","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["8d4 + 8","healing"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"consumableType":"potion","attributes":{"powerdc":10},"consumes":{"type":"","target":null,"amount":null},"charges":{"value":1,"max":1,"_deprecated":true},"autoUse":{"value":true,"_deprecated":true},"autoDestroy":{"value":true,"_deprecated":true},"attuned":false},"sort":300001,"flags":{"exportSource":{"world":"fresh","system":"sw5e","coreVersion":"0.7.9","systemVersion":"1.2.0"}},"img":"systems/sw5e/icons/items/potions/grand-red.jpg","effects":[]}
|
||||
{"_id":"5mIeX824uMklU3xq","name":"Map or Scroll Case","permission":{"default":0},"type":"backpack","data":{"description":{"value":"<p>This cylindrical leather case can hold up to ten rolled-up sheets of paper or five rolled-up sheets of parchment.</p>","chat":"","unidentified":""},"source":"PHB pg. 151","quantity":1,"weight":1,"price":1,"attunement":0,"equipped":false,"rarity":"Common","identified":true,"capacity":{"type":"items","value":10,"weightless":false},"currency":{"cp":0,"sp":0,"ep":0,"gp":0,"pp":0},"damage":{"parts":[]}},"sort":2000001,"flags":{},"img":"systems/sw5e/icons/items/inventory/briefcase.jpg","effects":[]}
|
||||
{"_id":"6067acDZGv7KNOkP","name":"Elven Chain","permission":{"default":0},"type":"equipment","data":{"description":{"value":"<p>You gain a +1 bonus to AC while you wear this armor. You are considered proficient with this armor even if you lack proficiency with medium armor.</p>","chat":"","unidentified":""},"source":"DMG pg. 168","quantity":1,"weight":20,"price":4000,"attunement":0,"equipped":false,"rarity":"Rare","identified":true,"activation":{"type":"","cost":0,"condition":""},"duration":{"value":null,"units":""},"target":{"value":null,"width":null,"units":"","type":""},"range":{"value":null,"long":null,"units":""},"uses":{"value":0,"max":0,"per":null},"consume":{"type":"","target":null,"amount":null},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":14,"type":"medium","dex":2},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"speed":{"value":null,"conditions":""},"strength":null,"stealth":false,"proficient":true,"attributes":{"powerdc":10}},"sort":1900000,"flags":{},"img":"systems/sw5e/icons/items/armor/leather-forest.jpg","effects":[]}
|
||||
{"_id":"62EaozKvcA0aSy2q","name":"Spear +3","permission":{"default":0},"type":"weapon","data":{"description":{"value":"<p><em>Whether through demonic blessing, celestial bequeathment, crazed experiment, or skillful craft, this weapon has been enhanced to bring more bloodshed by the bearer.</em></p>\n<p>You have a bonus to attack and damage rolls made with this magic weapon.</p>","chat":"","unidentified":""},"source":"DMG pg. 213","quantity":1,"weight":3,"price":16000,"attunement":0,"equipped":false,"rarity":"Very rare","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":null,"width":null,"units":"","type":""},"range":{"value":20,"long":60,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":null,"amount":null},"ability":null,"actionType":"mwak","attackBonus":3,"chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod +3","piercing"]],"versatile":"1d8 + @mod +3"},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleM","properties":{"thr":true,"ver":true,"amm":false,"hvy":false,"fin":false,"fir":false,"foc":false,"lgt":false,"lod":false,"rch":false,"rel":false,"ret":false,"spc":false,"two":false},"proficient":false,"attributes":{"powerdc":10}},"sort":2700000,"flags":{},"img":"systems/sw5e/icons/items/weapons/spear.jpg","effects":[]}
|
||||
|
@ -241,7 +241,7 @@
|
|||
{"_id":"IuVaBrq17AqxpXc4","name":"Wand of the War Mage +3","permission":{"default":0},"type":"equipment","data":{"description":{"value":"<p><em>(Requires attunement by a powercaster)</em></p>\n<p>While holding this wand, you gain a bonus to power attack rolls of +3. In addition, you ignore half cover when making a power attack.</p>","chat":"","unidentified":""},"source":"DMG pg. 212","quantity":1,"weight":1,"price":19200,"attunement":0,"equipped":false,"rarity":"Uncommon","identified":true,"activation":{"type":"","cost":0,"condition":""},"duration":{"value":null,"units":""},"target":{"value":null,"width":null,"units":"","type":""},"range":{"value":null,"long":null,"units":""},"uses":{"value":0,"max":0,"per":null,"autoUse":false,"autoDestroy":false},"consume":{"type":"","target":null,"amount":null},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":0,"type":"trinket","dex":null},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"speed":{"value":null,"conditions":""},"strength":0,"stealth":false,"proficient":false,"attributes":{"powerdc":10}},"folder":"oENpm3Crialw50Y1","sort":100001,"flags":{},"img":"systems/sw5e/icons/items/weapons/staff-red.jpg","effects":[]}
|
||||
{"_id":"J8gQdJJi5e8LmD7H","name":"Rope of Entanglement","permission":{"default":0},"type":"consumable","data":{"description":{"value":"<p><em>Wondrous item</em></p>\n<p>This rope is 30 feet long and weighs 3 pounds. If you hold one end of the rope and use an action to speak its command word, the other end darts forward to entangle a creature you can see within 20 feet of you. The target must succeed on a DC 15 Dexterity saving throw or become restrained.</p>","chat":"","unidentified":""},"source":"DMG pg. 197","quantity":1,"weight":3,"price":4000,"attunement":0,"equipped":false,"rarity":"Rare","identified":true,"activation":{"type":"action","cost":1,"condition":"Command word."},"duration":{"value":0,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":20,"long":0,"units":"ft"},"uses":{"value":0,"max":0,"per":"","autoDestroy":false,"autoUse":false},"consume":{"type":"","target":null,"amount":null},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"dex","dc":15,"scaling":"flat"},"consumableType":"trinket","attributes":{"powerdc":10}},"sort":900000,"flags":{},"img":"systems/sw5e/icons/skills/green_17.jpg","effects":[]}
|
||||
{"_id":"JDTO996oInbiZGHW","name":"Breastplate +3","permission":{"default":0},"type":"equipment","data":{"description":{"value":"<p><em>This armor has been embellished with powerful runes, crafted in sorcerous fires, blessed by a powerful being, or some other event has seen it bequeathed with enhanced protection for the wearer.</em></p>\n<p>You have a bonus to AC while wearing this armor.</p>","chat":"","unidentified":""},"source":"DMG pg. 152","quantity":1,"weight":20,"price":24400,"attunement":0,"equipped":false,"rarity":"Legendary","identified":true,"activation":{"type":"","cost":0,"condition":""},"duration":{"value":null,"units":""},"target":{"value":null,"width":null,"units":"","type":""},"range":{"value":null,"long":null,"units":""},"uses":{"value":0,"max":0,"per":null},"consume":{"type":"","target":null,"amount":null},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":17,"type":"medium","dex":2},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"speed":{"value":null,"conditions":""},"strength":null,"stealth":false,"proficient":false},"sort":650000,"flags":{},"img":"systems/sw5e/icons/items/armor/halfplate.png","effects":[]}
|
||||
{"_id":"JFiSlgcm3uSSBM5t","name":"Potion of Supreme Healing","permission":{"default":0},"type":"consumable","data":{"description":{"value":"<p><em>Agitating the potion the red liquid glimmers with it's motion.</em></p>\n<p>You regain 10d4+20 hit points when you drink this potion.</p>","chat":"","unidentified":""},"source":"DMG pg. 187","quantity":1,"weight":0.1,"price":1350,"attunement":0,"equipped":false,"rarity":"Very rare","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":0,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":"touch"},"uses":{"value":1,"max":1,"per":"charges","autoDestroy":true,"autoUse":true},"consume":{"type":"","target":null,"amount":null},"ability":"","actionType":"heal","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["10d4 + 20","healing"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"consumableType":"potion","attributes":{"powerdc":10}},"sort":400001,"flags":{},"img":"systems/sw5e/icons/items/potions/grand-red.jpg","effects":[]}
|
||||
{"_id":"JFiSlgcm3uSSBM5t","name":"Potion of Supreme Healing","permission":{"default":0},"type":"consumable","data":{"description":{"value":"<p><em>The potion's red liquid glimmers when agitated.</em></p>\n<p>You regain 10d4+20 hit points when you drink this potion.</p>","chat":"","unidentified":""},"source":"DMG pg. 187","quantity":1,"weight":0.1,"price":1350,"attunement":0,"equipped":false,"rarity":"Very rare","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":0,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":"touch"},"uses":{"value":1,"max":"1","per":"charges","autoDestroy":true,"autoUse":true},"consume":{"type":"","target":"","amount":null,"value":"","_deprecated":true},"ability":"","actionType":"heal","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["10d4 + 20","healing"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"consumableType":"potion","attributes":{"powerdc":10},"consumes":{"type":"","target":null,"amount":null},"charges":{"value":1,"max":1,"_deprecated":true},"autoUse":{"value":true,"_deprecated":true},"autoDestroy":{"value":true,"_deprecated":true},"attuned":false},"sort":400001,"flags":{"exportSource":{"world":"fresh","system":"sw5e","coreVersion":"0.7.9","systemVersion":"1.2.0"}},"img":"systems/sw5e/icons/items/potions/magic-red.jpg","effects":[]}
|
||||
{"_id":"JNkjtTxYmEC7W34O","name":"Splint Armor of Resistance","permission":{"default":0},"type":"equipment","data":{"description":{"value":"<p><em>(Requires attunement)</em></p>\n<p>You have resistance to one type of damage while you wear this armor. The GM chooses the type or determines it randomly from the options below.</p>\n<table border=\"1\">\n<tbody>\n<tr>\n<td><strong>d10</strong></td>\n<td><strong>Damage</strong> <strong>Type</strong></td>\n</tr>\n<tr>\n<td>1</td>\n<td>Acid</td>\n</tr>\n<tr>\n<td>2</td>\n<td>Cold</td>\n</tr>\n<tr>\n<td>3</td>\n<td>Fire</td>\n</tr>\n<tr>\n<td>4</td>\n<td>Force</td>\n</tr>\n<tr>\n<td>5</td>\n<td>Lightning</td>\n</tr>\n<tr>\n<td>6</td>\n<td>Necrotic</td>\n</tr>\n<tr>\n<td>7</td>\n<td>Poison</td>\n</tr>\n<tr>\n<td>8</td>\n<td>Psychic</td>\n</tr>\n<tr>\n<td>9</td>\n<td>Radiant</td>\n</tr>\n<tr>\n<td>10</td>\n<td>Thunder</td>\n</tr>\n</tbody>\n</table>\n<p> </p>","chat":"","unidentified":"","type":"String","label":"Description"},"source":"DMG pg. 152","quantity":1,"weight":60,"price":6200,"attunement":0,"equipped":false,"rarity":"Rare","identified":true,"activation":{"type":"","cost":0,"condition":""},"duration":{"value":null,"units":""},"target":{"value":null,"width":null,"units":"","type":""},"range":{"value":null,"long":null,"units":""},"uses":{"value":0,"max":0,"per":null},"consume":{"type":"","target":null,"amount":null},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":17,"type":"heavy","dex":0,"label":"Armor Value"},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"speed":{"value":null,"conditions":""},"strength":15,"stealth":true,"proficient":false,"attributes":{"powerdc":10}},"sort":4100000,"flags":{},"img":"systems/sw5e/icons/items/armor/splint.png","effects":[]}
|
||||
{"_id":"JRJpKZyamkpa7awv","name":"Robe of Scintillating Colors","permission":{"default":0},"type":"equipment","data":{"description":{"value":"<p><em>Wondrous item, (requires attunement)</em></p>\n<p>This robe has 3 charges, and it regains 1d3 expended charges daily at dawn. While you wear it, you can use an action and expend 1 charge to cause the garment to display a shifting pattern of dazzling hues until the end of your next turn. During this time, the robe sheds bright light in a 30-foot radius and dim light for an additional 30 feet. Creatures that can see you have disadvantage on attack rolls against you. In addition, any creature in the bright light that can see you when the robe's power is activated must succeed on a DC 15 Wisdom saving throw or become stunned until the effect ends.</p>","chat":"","unidentified":""},"source":"DMG pg. 194","quantity":1,"weight":1,"price":6000,"attunement":0,"equipped":false,"rarity":"Very rare","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":0,"units":""},"target":{"value":null,"width":null,"units":null,"type":"self"},"range":{"value":30,"long":60,"units":"ft"},"uses":{"value":3,"max":3,"per":"charges"},"consume":{"type":"","target":null,"amount":null},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"1d3","save":{"ability":"wis","dc":15,"scaling":"flat"},"armor":{"value":0,"type":"clothing","dex":0},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"speed":{"value":null,"conditions":""},"strength":0,"stealth":false,"proficient":false,"attributes":{"powerdc":10}},"sort":800000,"flags":{},"img":"systems/sw5e/icons/skills/violet_26.jpg","effects":[]}
|
||||
{"_id":"Jj4iFQQGvckx8Wsj","name":"Potion of Fire Resistance","permission":{"default":0},"type":"consumable","data":{"description":{"value":"<p><em>The potion is a plain indescriminate color and smells slightly foul.</em></p>\n<p>When you drink this potion, you gain resistance to Fire type damage for 1 hour.</p>\n<p> </p>","chat":"","unidentified":""},"source":"DMG pg. 188","quantity":1,"weight":0.1,"price":300,"attunement":0,"equipped":false,"rarity":"Uncommon","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"hour"},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":"touch"},"uses":{"value":1,"max":1,"per":"charges","autoDestroy":true,"autoUse":true},"consume":{"type":"","target":null,"amount":null},"ability":"","actionType":"util","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"consumableType":"potion","attributes":{"powerdc":10}},"sort":2100000,"flags":{},"img":"systems/sw5e/icons/items/potions/major-red.jpg","effects":[]}
|
||||
|
@ -257,7 +257,7 @@
|
|||
{"_id":"KndVe2insuctjIaj","name":"Smith's Tools","permission":{"default":0},"type":"tool","data":{"description":{"value":"<p>These special tools include the items needed to pursue a craft or trade in smithing.</p>\n<p>Proficiency with a set of artisan’s tools lets you add your proficiency bonus to any ability checks you make using the tools in your craft. Each type of artisan’s tools requires a separate proficiency.</p>","chat":"","unidentified":""},"source":"PHB pg. 154","quantity":1,"weight":8,"price":20,"attunement":0,"equipped":false,"rarity":"Common","identified":true,"ability":"str","chatFlavor":"","proficient":0,"damage":{"parts":[]}},"sort":2800000,"flags":{},"img":"systems/sw5e/icons/items/inventory/hammer.jpg","effects":[]}
|
||||
{"_id":"KvIlZssYEtQ4bvSE","name":"Warhammer +2","permission":{"default":0},"type":"weapon","data":{"description":{"value":"<p><em>Whether through demonic blessing, celestial bequeathment, crazed experiment, or skillful craft, this weapon has been enhanced to bring more bloodshed by the bearer.</em></p>\n<p>You have a bonus to attack and damage rolls made with this magic weapon.</p>","chat":"","unidentified":""},"source":"DMG pg. 213","quantity":1,"weight":2,"price":4000,"attunement":0,"equipped":false,"rarity":"Rare","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":null,"width":null,"units":"","type":""},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":null,"amount":null},"ability":null,"actionType":"mwak","attackBonus":2,"chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod +2","bludgeoning"]],"versatile":"1d10 + @mod +2"},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialM","properties":{"ver":true,"amm":false,"hvy":false,"fin":false,"fir":false,"foc":false,"lgt":false,"lod":false,"rch":false,"rel":false,"ret":false,"spc":false,"thr":false,"two":false},"proficient":false,"attributes":{"powerdc":10}},"sort":900000,"flags":{},"img":"systems/sw5e/icons/items/weapons/warhammer.png","effects":[]}
|
||||
{"_id":"L4PxYPtYca283sju","name":"Scimitar of Wounding","permission":{"default":0},"type":"weapon","data":{"description":{"value":"<p><em>(Requires attunement)</em></p>\n<p>Hit points lost to this weapon's damage can be regained only through a short or long rest, rather than by regeneration, magic, or any other means.</p>\n<p>Once per turn, when you hit a creature with an attack using this magic weapon, you can wound the target. At the start of each of the wounded creature's turns, it takes 1d4 necrotic damage for each time you've wounded it, and it can then make a DC 15 Constitution saving throw, ending the effect of all such wounds on itself on a success. Alternatively, the wounded creature, or a creature within 5 feet of it, can use an action to make a DC 15 Wisdom (Medicine) check, ending the effect of such wounds on it on a success.</p>","chat":"","unidentified":""},"source":"DMG pg. 207","quantity":1,"weight":3,"price":2000,"attunement":0,"equipped":false,"rarity":"Rare","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":null,"width":null,"units":"","type":""},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":null,"amount":null},"ability":null,"actionType":"mwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","slashing"]],"versatile":""},"formula":"1d4","save":{"ability":"con","dc":15,"scaling":"flat"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialM","properties":{"amm":false,"hvy":false,"fin":true,"fir":false,"foc":false,"lgt":true,"lod":false,"rch":false,"rel":false,"ret":false,"spc":false,"thr":false,"two":false,"ver":false},"proficient":false,"attributes":{"powerdc":10}},"sort":300000,"flags":{},"img":"systems/sw5e/icons/skills/affliction_01.jpg","effects":[]}
|
||||
{"_id":"L887NdWEP5NqHCrQ","name":"Potion of Greater Healing","permission":{"default":0},"type":"consumable","data":{"description":{"value":"<p><em>Agitating the potion the red liquid glimmers with it's motion.</em></p>\n<p>You regain 4d4+4 hit points when you drink this potion.</p>\n<p> </p>\n<p> </p>","chat":"","unidentified":""},"source":"DMG pg. 187","quantity":1,"weight":0.1,"price":150,"attunement":0,"equipped":false,"rarity":"Uncommon","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":"inst"},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":"touch"},"uses":{"value":1,"max":1,"per":"charges","autoDestroy":true,"autoUse":true},"consume":{"type":"","target":null,"amount":null},"ability":"","actionType":"heal","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["4d4 + 4","healing"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"consumableType":"potion","attributes":{"powerdc":10}},"sort":100001,"flags":{},"img":"systems/sw5e/icons/items/potions/major-red.jpg","effects":[]}
|
||||
{"_id":"L887NdWEP5NqHCrQ","name":"Potion of Greater Healing","permission":{"default":0},"type":"consumable","data":{"description":{"value":"<p><em>The potion's red liquid glimmers when agitated.</em></p>\n<p>You regain 4d4+4 hit points when you drink this potion.</p>\n<p> </p>\n<p> </p>","chat":"","unidentified":""},"source":"DMG pg. 187","quantity":1,"weight":0.1,"price":150,"attunement":0,"equipped":false,"rarity":"Uncommon","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":"inst"},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":"touch"},"uses":{"value":1,"max":"1","per":"charges","autoDestroy":true,"autoUse":true},"consume":{"type":"","target":"","amount":null,"value":"","_deprecated":true},"ability":"","actionType":"heal","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["4d4 + 4","healing"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"consumableType":"potion","attributes":{"powerdc":10},"consumes":{"type":"","target":null,"amount":null},"charges":{"value":1,"max":1,"_deprecated":true},"autoUse":{"value":true,"_deprecated":true},"autoDestroy":{"value":true,"_deprecated":true},"attuned":false},"sort":100001,"flags":{"core":{"sheetClass":""},"exportSource":{"world":"fresh","system":"sw5e","coreVersion":"0.7.9","systemVersion":"1.2.0"}},"img":"systems/sw5e/icons/items/potions/major-red.jpg","effects":[]}
|
||||
{"_id":"L9KBLub5vfb3mTDz","name":"Ring of Fire Elemental Command","permission":{"default":0},"type":"equipment","data":{"description":{"value":"<p><em>(Requires attunement)</em></p>\n<p>This ring is linked to the Elemental Plane of Fire.</p>\n<p>While wearing this ring, you have advantage on attack rolls against @Compendium[sw5e.monsters.8SMQl75HLjhuSeau]{Fire Elemental}s, and they have disadvantage on attack rolls against you. In addition, you have access to properties based on the linked plane.</p>\n<p>The ring has 5 charges. It regains 1d4 + 1 expended charges daily at dawn. Powers cast from the ring have a save DC of 17.</p>\n<p><strong>Ring of Fire Elemental Command</strong>. You can expend 2 of the ring's charges to cast @Compendium[sw5e.powers.eEpy1ONlXumKS1mp]{Dominate Monster} on a Fire Elemental. In addition, you have resistance to fire damage. You can also speak and understand Ignan.</p>\n<p>If you help slay a Fire Elemental while attuned to the ring, you gain access to the following additional properties:</p>\n<ul>\n<li>You are immune to fire damage.</li>\n<li>You can cast the following powers from the ring, expending the necessary number of charges: @Compendium[sw5e.powers.5SuJewoa1CRWaj1F]{Burning Hands} (1 charge), @Compendium[sw5e.powers.ztgcdrWPshKRpFd0]{Fireball} (2 charges), or @Compendium[sw5e.powers.X3DrXgxjwI2dvkD6]{Wall of Fire} (3 charges).</li>\n</ul>","chat":"","unidentified":""},"source":"DMG pg. 190","quantity":1,"weight":0,"price":17000,"attunement":0,"equipped":false,"rarity":"Legendary","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":0,"units":""},"target":{"value":0,"width":null,"units":"","type":""},"range":{"value":null,"long":null,"units":""},"uses":{"value":5,"max":5,"per":"charges"},"consume":{"type":"","target":null,"amount":null},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"flat"},"armor":{"value":0,"type":"trinket","dex":0},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"speed":{"value":null,"conditions":""},"strength":0,"stealth":false,"proficient":false,"attributes":{"powerdc":10}},"sort":600000,"flags":{},"img":"systems/sw5e/icons/items/jewelry/ring-red.jpg","effects":[]}
|
||||
{"_id":"LBQWNqX6hZOKhQ8a","name":"Potion of Radiant Resistance","permission":{"default":0},"type":"consumable","data":{"description":{"value":"<p><em>The potion is a plain indescriminate color and smells slightly foul.</em></p>\n<p>When you drink this potion, you gain resistance to Radiant type damage for 1 hour.</p>\n<p> </p>","chat":"","unidentified":""},"source":"DMG pg. 188","quantity":1,"weight":0.1,"price":300,"attunement":0,"equipped":false,"rarity":"Uncommon","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"hour"},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":"touch"},"uses":{"value":1,"max":1,"per":"charges","autoDestroy":true,"autoUse":true},"consume":{"type":"","target":null,"amount":null},"ability":"","actionType":"util","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"consumableType":"potion","attributes":{"powerdc":10}},"sort":2600000,"flags":{},"img":"systems/sw5e/icons/items/potions/grand-yellow.jpg","effects":[]}
|
||||
{"_id":"LBajgahniRJbAgDr","name":"Powerbook","permission":{"default":0},"type":"loot","data":{"description":{"value":"<p>Essential for wizards, a powerbook is a leather-bound tome with 100 blank vellum pages suitable for recording powers.</p>\n<p> </p>","chat":"","unidentified":""},"source":"PHB pg. 153","quantity":1,"weight":3,"price":50,"attunement":0,"equipped":false,"rarity":"Common","identified":true,"damage":{"parts":[]},"details":{"description":"<p>Essential for wizards, a powerbook is a leather-bound tome with 100 blank vellum pages suitable for recording powers.</p>\n<p>The powers that you add to your powerbook as you gain levels reflect the arcane research you conduct on your own, as well as intellectual breakthroughs you have had about the nature of the multiverse. You might find other powers during your adventures. You could discover a power recorded on a scroll in an evil wizard's chest, for example, or in a dusty tome in an ancient library. </p>\n<p><strong>Copying a Power into the Book</strong></p>\n<p>When you find a wizard power of 1st level or higher, you can add it to your powerbook if it is of a power level you can prepare and if you can spare the time to decipher and copy it. Copying that power into your powerbook involves reproducing the basic form of the power, then deciphering the unique system of notation used by the wizard who wrote it. You must practice the power until you understand the sounds or gestures required, then transcribe it into your powerbook using your own notation. For each level of the power, the process takes 2 hours and costs 50 gp. The cost represents material components you expend as you experiment with the power to master it, as well as the fine inks you need to record it. Once you have spent this time and money, you can prepare the power just like your other powers. </p>\n<p><strong>Replacing the Book</strong> </p>\n<p>You can copy a power from your own powerbook into another book - for example, if you want to make a backup copy of your powerbook. This is just like copying a new power into your powerbook, but faster and easier, since you understand your own notation and already know how to cast the power. You need spend only 1 hour and 10 gp for each level of the copied power. </p>\n<p>If you lose your powerbook, you can use the same procedure to transcribe the powers that you have prepared into a new powerbook. Filling out the remainder of your powerbook requires you to find new powers to do so, as normal. For this reason, many wizards keep backup powerbooks in a safe place. The Book's Appearance. Your powerbook is a unique compilation of powers, with its own decorative flourishes and margin notes. It might be a plain, functional leather volume that you received as a gift from your master, a finely bound gilt-edged tome you found in an ancient library, or even a loose collection of notes scrounged together after you lost your previous powerbook in a mishap.</p>"}},"sort":4600000,"flags":{},"img":"systems/sw5e/icons/items/inventory/book-purple.jpg","effects":[]}
|
||||
|
@ -782,7 +782,7 @@
|
|||
{"_id":"ykB6UKv5BuQnSRSL","name":"Frost Brand Greatsword","permission":{"default":0},"type":"weapon","data":{"description":{"value":"<p><em>(Requires attunement)</em></p>\n<p>When you hit with an attack using this magic sword, the target takes an extra 1d6 cold damage. In addition, while you hold the sword, you have resistance to fire damage.</p>\n<p>In freezing temperatures, the blade sheds bright light in a 10-foot radius and dim light for an additional 10 feet.</p>\n<p>When you draw this weapon, you can extinguish all nonmagical flames within 30 feet of you. This property can be used no more than once per hour.</p>","chat":"","unidentified":""},"source":"DMG pg. 171","quantity":1,"weight":6,"price":2200,"attunement":0,"equipped":false,"rarity":"Very rare","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":0,"units":""},"target":{"value":0,"width":null,"units":"","type":""},"range":{"value":5,"long":0,"units":"ft"},"uses":{"value":1,"max":1,"per":"charges"},"consume":{"type":"","target":null,"amount":null},"ability":null,"actionType":"mwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["2d6 + @mod","slashing"],["1d6","cold"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialM","properties":{"amm":false,"hvy":true,"fin":false,"fir":false,"foc":false,"lgt":false,"lod":false,"rch":false,"rel":false,"ret":false,"spc":false,"thr":false,"two":true,"ver":false},"proficient":false,"attributes":{"powerdc":10}},"sort":1700000,"flags":{},"img":"systems/sw5e/icons/skills/weapon_07.jpg","effects":[]}
|
||||
{"_id":"ykefWXBjq3y6y9Se","name":"Manual of Gainful Exercise","permission":{"default":0},"type":"consumable","data":{"description":{"value":"<p><em>Wondrous item</em></p>\n<p>This book describes fitness exercises, and its words are charged with magic. If you spend 48 hours over a period of 6 days or fewer studying the book's contents and practicing its guidelines, your Strength score increases by 2, as does your maximum for that score. The manual then loses its magic, but regains it in a century.</p>","chat":"","unidentified":""},"source":"DMG pg. 180","quantity":1,"weight":1,"price":100000,"attunement":0,"equipped":false,"rarity":"Very rare","identified":true,"activation":{"type":"hour","cost":48,"condition":"The book must be completed in 6 days or less."},"duration":{"value":0,"units":""},"target":{"value":null,"width":null,"units":null,"type":"self"},"range":{"value":null,"long":null,"units":""},"uses":{"value":1,"max":1,"per":"charges","autoDestroy":true,"autoUse":false},"consume":{"type":"","target":null,"amount":null},"ability":"","actionType":"util","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"consumableType":"trinket","attributes":{"powerdc":10}},"sort":1700000,"flags":{},"img":"systems/sw5e/icons/items/inventory/book-purple.jpg","effects":[]}
|
||||
{"_id":"yoFff2zdTloKx1if","name":"Pike +1","permission":{"default":0},"type":"weapon","data":{"description":{"value":"<p><em>Whether through demonic blessing, celestial bequeathment, crazed experiment, or skillful craft, this weapon has been enhanced to bring more bloodshed by the bearer.</em></p>\n<p>You have a bonus to attack and damage rolls made with this magic weapon.</p>","chat":"","unidentified":""},"source":"DMG pg. 213","quantity":1,"weight":18,"price":1000,"attunement":0,"equipped":false,"rarity":"Uncommon","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":null,"width":null,"units":"","type":""},"range":{"value":10,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":null,"amount":null},"ability":null,"actionType":"mwak","attackBonus":1,"chatFlavor":"","critical":null,"damage":{"parts":[["1d10 + @mod +1","piercing"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialM","properties":{"hvy":true,"rch":true,"two":true,"amm":false,"fin":false,"fir":false,"foc":false,"lgt":false,"lod":false,"rel":false,"ret":false,"spc":false,"thr":false,"ver":false},"proficient":false,"attributes":{"powerdc":10}},"sort":600000,"flags":{},"img":"systems/sw5e/icons/items/weapons/pike.jpg","effects":[]}
|
||||
{"_id":"ytlsBjYsZ7OBSEBs","name":"Potion of Healing","permission":{"default":0},"type":"consumable","data":{"description":{"value":"<p><em>Agitating the potion the red liquid glimmers with it's motion.</em></p>\n<p>You regain 2d4+2 hit points when you drink this potion.</p>\n<p> </p>\n<p> </p>","chat":"","unidentified":""},"source":"DMG pg. 187","quantity":1,"weight":0.1,"price":50,"attunement":0,"equipped":false,"rarity":"Common","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":0,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":"touch"},"uses":{"value":1,"max":1,"per":"charges","autoDestroy":true,"autoUse":true},"consume":{"type":"","target":null,"amount":null},"ability":"","actionType":"heal","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["2d4 + 2","healing"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"consumableType":"potion","attributes":{"powerdc":10}},"sort":200001,"flags":{},"img":"systems/sw5e/icons/items/potions/minor-red.jpg","effects":[]}
|
||||
{"_id":"ytlsBjYsZ7OBSEBs","name":"Potion of Healing","permission":{"default":0},"type":"consumable","data":{"description":{"value":"<p><em>The potion's red liquid glimmers when agitated.</em></p>\n<p>You regain 2d4+2 hit points when you drink this potion.</p>\n<p> </p>\n<p> </p>","chat":"","unidentified":""},"source":"DMG pg. 187","quantity":1,"weight":0.1,"price":50,"attunement":0,"equipped":false,"rarity":"Common","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":0,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":"touch"},"uses":{"value":1,"max":"1","per":"charges","autoDestroy":true,"autoUse":true},"consume":{"type":"","target":"","amount":null,"value":"","_deprecated":true},"ability":"","actionType":"heal","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["2d4 + 2","healing"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"consumableType":"potion","attributes":{"powerdc":10},"consumes":{"type":"","target":null,"amount":null},"charges":{"value":1,"max":1,"_deprecated":true},"autoUse":{"value":true,"_deprecated":true},"autoDestroy":{"value":true,"_deprecated":true},"attuned":false},"sort":200001,"flags":{"exportSource":{"world":"fresh","system":"sw5e","coreVersion":"0.7.9","systemVersion":"1.2.0"}},"img":"systems/sw5e/icons/items/potions/minor-red.jpg","effects":[]}
|
||||
{"_id":"yxHi57T5mmVt0oDr","name":"Bagpipes","permission":{"default":0},"type":"tool","data":{"description":{"value":"<p>A set of bagpipes to evoke awe, wonder, or fear in your audience.</p>\n<p>If you have proficiency with a given musical instrument, you can add your proficiency bonus to any ability checks you make to play music with the instrument. A bard can use a musical instrument as a powercasting focus. Each type of musical instrument requires a separate proficiency. </p>","chat":"","unidentified":""},"source":"PHB pg. 154","quantity":1,"weight":6,"price":30,"attunement":0,"equipped":false,"rarity":"Common","identified":true,"ability":"cha","chatFlavor":"","proficient":0,"damage":{"parts":[]}},"sort":900000,"flags":{},"img":"systems/sw5e/icons/items/inventory/flask.jpg","effects":[]}
|
||||
{"_id":"z0lIRURcyDYt1kLK","name":"Flail +2","permission":{"default":0},"type":"weapon","data":{"description":{"value":"<p><em>Whether through demonic blessing, celestial bequeathment, crazed experiment, or skillful craft, this weapon has been enhanced to bring more bloodshed by the bearer.</em></p>\n<p>You have a bonus to attack and damage rolls made with this magic weapon.</p>","chat":"","unidentified":""},"source":"DMG pg. 213","quantity":1,"weight":2,"price":4000,"attunement":0,"equipped":false,"rarity":"Rare","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":0,"units":""},"target":{"value":0,"width":null,"units":"","type":""},"range":{"value":5,"long":0,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":null,"amount":null},"ability":null,"actionType":"mwak","attackBonus":2,"chatFlavor":"","critical":null,"damage":{"parts":[["1d8 +@mod +2","bludgeoning"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialM","properties":{"value":"","amm":false,"hvy":false,"fin":false,"fir":false,"foc":false,"lgt":false,"rch":false,"rel":false,"ret":false,"spc":false,"thr":false,"two":false,"ver":false,"lod":false},"proficient":false,"attributes":{"powerdc":10}},"sort":1200001,"flags":{},"img":"systems/sw5e/icons/items/weapons/morningstar.jpg","effects":[]}
|
||||
{"_id":"z67d1DZzqDPmgEwP","name":"Signal Whistle","permission":{"default":0},"type":"loot","data":{"description":{"value":"<p>A whistle can produce specific noise. It can be heard half a mile away.</p>","chat":"","unidentified":""},"source":"PHB pg. 150","quantity":1,"weight":0,"price":0.05,"attunement":0,"equipped":false,"rarity":"Common","identified":true,"damage":{"parts":[]}},"sort":4600000,"flags":{},"img":"systems/sw5e/icons/items/inventory/trinket-carving.jpg","effects":[]}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"name": "sw5e",
|
||||
"title": "SW5e - Fifth Edition System",
|
||||
"description": "A system for playing the fifth edition of the worlds most popular role-playing game in the Foundry Virtual Tabletop environment.",
|
||||
"version": "1.2.0",
|
||||
"version": "1.2.2",
|
||||
"author": "Atropos",
|
||||
"scripts": [],
|
||||
"esmodules": ["sw5e.js"],
|
||||
|
@ -95,5 +95,5 @@
|
|||
"compatibleCoreVersion": "0.7.9",
|
||||
"url": "https://gitlab.com/foundrynet/sw5e",
|
||||
"manifest": "https://gitlab.com/foundrynet/sw5e/raw/master/system.json",
|
||||
"download": "https://gitlab.com/foundrynet/sw5e/-/archive/release-1.2.0/sw5e-release-1.2.0.zip"
|
||||
"download": "https://gitlab.com/foundrynet/sw5e/-/archive/release-1.2.2/sw5e-release-1.2.2.zip"
|
||||
}
|
||||
|
|
|
@ -43,6 +43,15 @@
|
|||
"init": {
|
||||
"value": 0,
|
||||
"bonus": 0
|
||||
},
|
||||
"movement": {
|
||||
"burrow": 0,
|
||||
"climb": 0,
|
||||
"fly": 0,
|
||||
"swim": 0,
|
||||
"walk": 30,
|
||||
"units": "ft",
|
||||
"hover": false
|
||||
}
|
||||
},
|
||||
"details": {
|
||||
|
@ -80,15 +89,6 @@
|
|||
},
|
||||
"creature": {
|
||||
"attributes": {
|
||||
"movement": {
|
||||
"burrow": 0,
|
||||
"climb": 0,
|
||||
"fly": 0,
|
||||
"swim": 0,
|
||||
"walk": 30,
|
||||
"units": "ft",
|
||||
"hover": false
|
||||
},
|
||||
"senses": {
|
||||
"darkvision": 0,
|
||||
"blindsight": 0,
|
||||
|
@ -379,8 +379,7 @@
|
|||
"capacity": {
|
||||
"creature": "",
|
||||
"cargo": 0
|
||||
},
|
||||
"speed": ""
|
||||
}
|
||||
},
|
||||
"traits": {
|
||||
"size": "lg",
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
</h1>
|
||||
|
||||
<aside class="header-exp flexcol">
|
||||
<div class="charlevel">
|
||||
<div class="charlevel" title="{{multiclassLabels}}">
|
||||
<label>{{ localize "SW5E.Level" }} {{data.details.level}}</label>
|
||||
<span class="levels">{{classLabels}}</span>
|
||||
</div>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
{{#unless isVehicle}}
|
||||
<div class="form-group">
|
||||
<label>{{localize "SW5E.Senses"}}</label>
|
||||
<a class="config-button" data-action="senses" title="{{localize 'SW5E.MovementConfig'}}"><i class="fas fa-cog"></i></a>
|
||||
<a class="config-button" data-action="senses" title="{{localize 'SW5E.SensesConfig'}}"><i class="fas fa-cog"></i></a>
|
||||
<ul class="traits-list">
|
||||
{{#each senses as |v k|}}
|
||||
<li class="tag {{k}}">{{v}}</li>
|
||||
|
|
|
@ -55,11 +55,17 @@
|
|||
placeholder="—" value="{{data.attributes.ac.motionless}}">
|
||||
</footer>
|
||||
</li>
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title">{{localize 'SW5E.Speed'}}</h4>
|
||||
<li class="attribute movement">
|
||||
<h4 class="attribute-name box-title">
|
||||
{{ localize "SW5E.Movement" }}
|
||||
<a class="config-button" data-action="movement" title="{{localize 'SW5E.MovementConfig'}}"><i class="fas fa-cog"></i></a>
|
||||
</h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.attributes.speed" type="text" placeholder="—" value="{{data.attributes.speed}}"/>
|
||||
<span>{{movement.primary}}</span>
|
||||
</div>
|
||||
<footer class="attribute-footer">
|
||||
<span>{{movement.special}}</span>
|
||||
</footer>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<p>{{ title }}</p>
|
||||
<p class="notes">{{note}}</p>
|
||||
{{#each errors}}
|
||||
<p class="notification error">{{localize this}}</p>
|
||||
<p class="notification error">{{this}}</p>
|
||||
{{/each}}
|
||||
|
||||
{{#if consumePowerSlot}}
|
||||
|
|
BIN
tokens/aberration/GibberingMouther.png
Normal file
After Width: | Height: | Size: 268 KiB |
BIN
tokens/beast/GiantOctopus.png
Normal file
After Width: | Height: | Size: 635 KiB |
BIN
tokens/beast/GiantOctopusUnderwater.png
Normal file
After Width: | Height: | Size: 666 KiB |
BIN
tokens/beast/HunterShark.png
Normal file
After Width: | Height: | Size: 232 KiB |
BIN
tokens/beast/HunterSharkUnderwater.png
Normal file
After Width: | Height: | Size: 282 KiB |
BIN
tokens/beast/KillerWhale.png
Normal file
After Width: | Height: | Size: 284 KiB |
BIN
tokens/beast/KillerWhaleUnderwater.png
Normal file
After Width: | Height: | Size: 368 KiB |
BIN
tokens/beast/Plesiosaurus.png
Normal file
After Width: | Height: | Size: 284 KiB |
BIN
tokens/beast/PlesiosaurusUnderwater.png
Normal file
After Width: | Height: | Size: 322 KiB |
BIN
tokens/beast/Rhinoceros.png
Normal file
After Width: | Height: | Size: 409 KiB |
BIN
tokens/beast/SaberToothedTiger.png
Normal file
After Width: | Height: | Size: 366 KiB |
BIN
tokens/celestial/Unicorn.png
Normal file
After Width: | Height: | Size: 364 KiB |
BIN
tokens/construct/RugOfSmothering.png
Normal file
After Width: | Height: | Size: 675 KiB |
BIN
tokens/construct/RugOfSmotheringIdle.png
Normal file
After Width: | Height: | Size: 1.2 MiB |
BIN
tokens/fey/SeaHag.png
Normal file
After Width: | Height: | Size: 182 KiB |
BIN
tokens/fiend/Imp.png
Normal file
After Width: | Height: | Size: 65 KiB |
BIN
tokens/fiend/Nightmare.png
Normal file
After Width: | Height: | Size: 311 KiB |
BIN
tokens/humanoid/BanditCaptain.png
Normal file
After Width: | Height: | Size: 190 KiB |
BIN
tokens/humanoid/CultFanatic.png
Normal file
After Width: | Height: | Size: 148 KiB |
BIN
tokens/humanoid/Cultist.png
Normal file
After Width: | Height: | Size: 142 KiB |
Before Width: | Height: | Size: 129 KiB |
BIN
tokens/humanoid/Druid.png
Normal file
After Width: | Height: | Size: 168 KiB |
BIN
tokens/humanoid/GnollHunter.png
Normal file
After Width: | Height: | Size: 185 KiB |
BIN
tokens/humanoid/Lizardfolk.png
Normal file
After Width: | Height: | Size: 216 KiB |
BIN
tokens/humanoid/Priest.png
Normal file
After Width: | Height: | Size: 201 KiB |
BIN
tokens/humanoid/Spy.png
Normal file
After Width: | Height: | Size: 122 KiB |
BIN
tokens/monstrosity/Bulette.png
Normal file
After Width: | Height: | Size: 643 KiB |
BIN
tokens/monstrosity/DeathDog.png
Normal file
After Width: | Height: | Size: 157 KiB |
BIN
tokens/monstrosity/Grick.png
Normal file
After Width: | Height: | Size: 183 KiB |
BIN
tokens/monstrosity/Harpy.png
Normal file
After Width: | Height: | Size: 255 KiB |
BIN
tokens/monstrosity/PhaseSpider.png
Normal file
After Width: | Height: | Size: 389 KiB |
BIN
tokens/ooze/GelatinousCube.png
Normal file
After Width: | Height: | Size: 1.4 MiB |
BIN
tokens/undead/Ghast.png
Normal file
After Width: | Height: | Size: 184 KiB |