forked from GitHub-Mirrors/foundry-sw5e
Update Core to 1.4.2
Update Core to 1.4.2 and internal Version to 1.4.2.R1-A8
This commit is contained in:
parent
48b6ab8e18
commit
76e4d74508
10 changed files with 146 additions and 70 deletions
|
@ -146,11 +146,6 @@ export default class ActorSheet5e extends ActorSheet {
|
|||
// Prepare warnings
|
||||
data.warnings = this.actor._preparationWarnings;
|
||||
|
||||
// Prepare property attributions
|
||||
this.attribution = {
|
||||
"attributes.ac": this._prepareArmorClassAttribution(actorData.data)
|
||||
};
|
||||
|
||||
// Return data to the sheet
|
||||
return data;
|
||||
}
|
||||
|
@ -217,6 +212,30 @@ export default class ActorSheet5e extends ActorSheet {
|
|||
return tags;
|
||||
}
|
||||
|
||||
/* --------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Break down all of the Active Effects affecting a given target property.
|
||||
* @param {string} target The data property being targeted.
|
||||
* @return {AttributionDescription[]}
|
||||
* @protected
|
||||
*/
|
||||
_prepareActiveEffectAttributions(target) {
|
||||
return this.actor.effects.reduce((arr, e) => {
|
||||
let source = e.sourceName;
|
||||
if (e.data.origin === this.actor.uuid) source = e.data.label;
|
||||
if (!source) return arr;
|
||||
const value = e.data.changes.reduce((n, change) => {
|
||||
if (change.key !== target || !Number.isNumeric(change.value)) return n;
|
||||
if (change.mode !== CONST.ACTIVE_EFFECT_MODES.ADD) return n;
|
||||
return n + Number(change.value);
|
||||
}, 0);
|
||||
if (!value) return arr;
|
||||
arr.push({value, label: source, mode: CONST.ACTIVE_EFFECT_MODES.ADD});
|
||||
return arr;
|
||||
}, []);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
|
@ -299,12 +318,7 @@ export default class ActorSheet5e extends ActorSheet {
|
|||
});
|
||||
|
||||
// Bonus
|
||||
if (ac.bonus !== 0)
|
||||
attribution.push({
|
||||
label: game.i18n.localize("SW5E.Bonus"),
|
||||
mode: CONST.ACTIVE_EFFECT_MODES.ADD,
|
||||
value: ac.bonus
|
||||
});
|
||||
if (ac.bonus !== 0) attribution.push(...this._prepareActiveEffectAttributions("data.attributes.ac.bonus"));
|
||||
|
||||
// Cover
|
||||
if (ac.cover !== 0)
|
||||
|
@ -1036,9 +1050,16 @@ export default class ActorSheet5e extends ActorSheet {
|
|||
async _onPropertyAttribution(event) {
|
||||
const existingTooltip = event.currentTarget.querySelector("div.tooltip");
|
||||
const property = event.currentTarget.dataset.property;
|
||||
if (existingTooltip || !property || !this.attribution) return;
|
||||
|
||||
let html = await new PropertyAttribution(this.object, this.attribution, property).renderTooltip();
|
||||
if (existingTooltip || !property) return;
|
||||
const data = this.actor.data.data;
|
||||
let attributions;
|
||||
switch (property) {
|
||||
case "attributes.ac":
|
||||
attributions = this._prepareArmorClassAttribution(data);
|
||||
break;
|
||||
}
|
||||
if (!attributions) return;
|
||||
const html = await new PropertyAttribution(this.actor, attributions, property).renderTooltip();
|
||||
event.currentTarget.insertAdjacentElement("beforeend", html[0]);
|
||||
}
|
||||
|
||||
|
|
|
@ -138,11 +138,6 @@ export default class ActorSheet5e extends ActorSheet {
|
|||
// Prepare warnings
|
||||
data.warnings = this.actor._preparationWarnings;
|
||||
|
||||
// Prepare property attributions
|
||||
this.attribution = {
|
||||
"attributes.ac": this._prepareArmorClassAttribution(actorData.data)
|
||||
};
|
||||
|
||||
// Return data to the sheet
|
||||
return data;
|
||||
}
|
||||
|
@ -209,6 +204,30 @@ export default class ActorSheet5e extends ActorSheet {
|
|||
return tags;
|
||||
}
|
||||
|
||||
/* --------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Break down all of the Active Effects affecting a given target property.
|
||||
* @param {string} target The data property being targeted.
|
||||
* @return {AttributionDescription[]}
|
||||
* @protected
|
||||
*/
|
||||
_prepareActiveEffectAttributions(target) {
|
||||
return this.actor.effects.reduce((arr, e) => {
|
||||
let source = e.sourceName;
|
||||
if (e.data.origin === this.actor.uuid) source = e.data.label;
|
||||
if (!source) return arr;
|
||||
const value = e.data.changes.reduce((n, change) => {
|
||||
if (change.key !== target || !Number.isNumeric(change.value)) return n;
|
||||
if (change.mode !== CONST.ACTIVE_EFFECT_MODES.ADD) return n;
|
||||
return n + Number(change.value);
|
||||
}, 0);
|
||||
if (!value) return arr;
|
||||
arr.push({value, label: source, mode: CONST.ACTIVE_EFFECT_MODES.ADD});
|
||||
return arr;
|
||||
}, []);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
|
@ -291,12 +310,7 @@ export default class ActorSheet5e extends ActorSheet {
|
|||
});
|
||||
|
||||
// Bonus
|
||||
if (ac.bonus !== 0)
|
||||
attribution.push({
|
||||
label: game.i18n.localize("SW5E.Bonus"),
|
||||
mode: CONST.ACTIVE_EFFECT_MODES.ADD,
|
||||
value: ac.bonus
|
||||
});
|
||||
if (ac.bonus !== 0) attribution.push(...this._prepareActiveEffectAttributions("data.attributes.ac.bonus"));
|
||||
|
||||
// Cover
|
||||
if (ac.cover !== 0)
|
||||
|
@ -967,9 +981,16 @@ export default class ActorSheet5e extends ActorSheet {
|
|||
async _onPropertyAttribution(event) {
|
||||
const existingTooltip = event.currentTarget.querySelector("div.tooltip");
|
||||
const property = event.currentTarget.dataset.property;
|
||||
if (existingTooltip || !property || !this.attribution) return;
|
||||
|
||||
let html = await new PropertyAttribution(this.object, this.attribution, property).renderTooltip();
|
||||
if (existingTooltip || !property) return;
|
||||
const data = this.actor.data.data;
|
||||
let attributions;
|
||||
switch (property) {
|
||||
case "attributes.ac":
|
||||
attributions = this._prepareArmorClassAttribution(data);
|
||||
break;
|
||||
}
|
||||
if (!attributions) return;
|
||||
const html = await new PropertyAttribution(this.actor, attributions, property).renderTooltip();
|
||||
event.currentTarget.insertAdjacentElement("beforeend", html[0]);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,14 +16,14 @@
|
|||
*/
|
||||
export default class PropertyAttribution extends Application {
|
||||
/**
|
||||
* @param {Document} object - Object containing the property to be attributed.
|
||||
* @param {object.<string, AttributionDescription[]>} attribution - Object containing all of the attribution data.
|
||||
* @param {string} property - Dot separated path to the property.
|
||||
* @param {Document} object The Document that owns the property being attributed.
|
||||
* @param {AttributionDescription[]} attributions An array of all the attribution data.
|
||||
* @param {string} property Dot separated path to the property.
|
||||
*/
|
||||
constructor(object, attribution, property, options = {}) {
|
||||
constructor(object, attributions, property, options = {}) {
|
||||
super(options);
|
||||
this.object = object;
|
||||
this.attribution = attribution;
|
||||
this.attributions = attributions;
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ export default class PropertyAttribution extends Application {
|
|||
total = property.value;
|
||||
}
|
||||
|
||||
const sources = foundry.utils.duplicate(this.attribution[this.property]);
|
||||
const sources = foundry.utils.duplicate(this.attributions);
|
||||
return {
|
||||
sources: sources.map((entry) => {
|
||||
if (entry.label.startsWith("@")) {
|
||||
|
|
|
@ -70,6 +70,10 @@ export default class ItemSheet5e extends ItemSheet {
|
|||
data.isCrewed = itemData.data.activation?.type === "crew";
|
||||
data.isMountable = this._isItemMountable(itemData);
|
||||
|
||||
// Armor Class
|
||||
data.isArmor = itemData.data.armor?.type in data.config.armorTypes;
|
||||
data.hasAC = data.isArmor || data.isMountable;
|
||||
|
||||
// Prepare Active Effects
|
||||
data.effects = ActiveEffect5e.prepareActiveEffectCategories(this.item.effects);
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ export const migrateWorld = async function () {
|
|||
);
|
||||
|
||||
// Migrate World Actors
|
||||
for await (let a of game.actors.contents) {
|
||||
for await (let a of game.actors) {
|
||||
try {
|
||||
console.log(`Checking Actor entity ${a.name} for migration needs`);
|
||||
const updateData = await migrateActorData(a.toObject());
|
||||
|
@ -24,7 +24,7 @@ export const migrateWorld = async function () {
|
|||
}
|
||||
|
||||
// Migrate World Items
|
||||
for (let i of game.items.contents) {
|
||||
for (let i of game.items) {
|
||||
try {
|
||||
const updateData = migrateItemData(i.toObject());
|
||||
if (!foundry.utils.isObjectEmpty(updateData)) {
|
||||
|
@ -38,7 +38,7 @@ export const migrateWorld = async function () {
|
|||
}
|
||||
|
||||
// Migrate Actor Override Tokens
|
||||
for (let s of game.scenes.contents) {
|
||||
for (let s of game.scenes) {
|
||||
try {
|
||||
const updateData = await migrateSceneData(s.data);
|
||||
if (!foundry.utils.isObjectEmpty(updateData)) {
|
||||
|
@ -46,7 +46,7 @@ export const migrateWorld = async function () {
|
|||
await s.update(updateData, {enforceTypes: false});
|
||||
// If we do not do this, then synthetic token actors remain in cache
|
||||
// with the un-updated actorData.
|
||||
s.tokens.contents.forEach((t) => (t._actor = null));
|
||||
s.tokens.forEach((t) => (t._actor = null));
|
||||
}
|
||||
} catch (err) {
|
||||
err.message = `Failed sw5e system migration for Scene ${s.name}: ${err.message}`;
|
||||
|
@ -260,6 +260,7 @@ export const migrateItemData = function (item) {
|
|||
_migrateItemClassPowerCasting(item, updateData);
|
||||
_migrateItemAttunement(item, updateData);
|
||||
_migrateItemRarity(item, updateData);
|
||||
_migrateArmorType(item, updateData);
|
||||
return updateData;
|
||||
};
|
||||
|
||||
|
@ -276,6 +277,7 @@ export const migrateActorItemData = async function (item, actor) {
|
|||
_migrateItemAttunement(item, updateData);
|
||||
_migrateItemRarity(item, updateData);
|
||||
await _migrateItemPower(item, actor, updateData);
|
||||
_migrateArmorType(item, updateData);
|
||||
return updateData;
|
||||
};
|
||||
|
||||
|
@ -601,6 +603,7 @@ function _migrateActorType(actor, updateData) {
|
|||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Migrate the Class item powercasting field to allow powercasting to properly calculate
|
||||
* @private
|
||||
*/
|
||||
function _migrateItemClassPowerCasting(item, updateData) {
|
||||
|
@ -649,9 +652,18 @@ function _migrateItemClassPowerCasting(item, updateData) {
|
|||
*/
|
||||
function _migrateActorAC(actorData, updateData) {
|
||||
const ac = actorData.data?.attributes?.ac;
|
||||
if (!Number.isNumeric(ac?.value)) return;
|
||||
updateData["data.attributes.ac.flat"] = ac.value;
|
||||
updateData["data.attributes.ac.-=value"] = null;
|
||||
// If the actor has a numeric ac.value, then their AC has not been migrated to the auto-calculation schema yet.
|
||||
if (Number.isNumeric(ac?.value)) {
|
||||
updateData["data.attributes.ac.flat"] = ac.value;
|
||||
updateData["data.attributes.ac.calc"] = actorData.type === "npc" ? "natural" : "flat";
|
||||
updateData["data.attributes.ac.-=value"] = null;
|
||||
return updateData;
|
||||
}
|
||||
|
||||
// If the actor is already on the AC auto-calculation schema, but is using a flat value, they must now have their
|
||||
// calculation updated to an appropriate value.
|
||||
if (!Number.isNumeric(ac?.flat)) return updateData;
|
||||
updateData["data.attributes.ac.calc"] = actorData.type === "npc" ? "natural" : "flat";
|
||||
return updateData;
|
||||
}
|
||||
|
||||
|
@ -742,6 +754,22 @@ function _migrateItemRarity(item, updateData) {
|
|||
return updateData;
|
||||
}
|
||||
|
||||
/* --------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Convert equipment items of type 'bonus' to 'trinket'.
|
||||
*
|
||||
* @param {object} item Item data to migrate
|
||||
* @param {object} updateData Existing update to expand upon
|
||||
* @return {object} The updateData to apply
|
||||
* @private
|
||||
*/
|
||||
function _migrateArmorType(item, updateData) {
|
||||
if (item.type !== "equipment") return updateData;
|
||||
if (item.data?.armor?.type === "bonus") updateData["data.armor.type"] = "trinket";
|
||||
return updateData;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
|
|
|
@ -18,7 +18,7 @@ export default class AbilityTemplate extends MeasuredTemplate {
|
|||
// Prepare template data
|
||||
const templateData = {
|
||||
t: templateShape,
|
||||
user: game.user.data._id,
|
||||
user: game.user.id,
|
||||
distance: target.value,
|
||||
direction: 0,
|
||||
x: 0,
|
||||
|
@ -96,7 +96,7 @@ export default class AbilityTemplate extends MeasuredTemplate {
|
|||
|
||||
// Cancel the workflow (right-click)
|
||||
handlers.rc = (event) => {
|
||||
this.layer.preview.removeChildren();
|
||||
this.layer._onDragLeftCancel(event);
|
||||
canvas.stage.off("mousemove", handlers.mm);
|
||||
canvas.stage.off("mousedown", handlers.lc);
|
||||
canvas.app.view.oncontextmenu = null;
|
||||
|
|
2
sw5e.js
2
sw5e.js
|
@ -290,7 +290,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.4.1.R1-A8";
|
||||
const NEEDS_MIGRATION_VERSION = "1.4.2.R1-A8";
|
||||
// Check for R1 SW5E versions
|
||||
const SW5E_NEEDS_MIGRATION_VERSION = "R1-A8";
|
||||
const COMPATIBLE_MIGRATION_VERSION = 0.8;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"name": "sw5e",
|
||||
"title": "SW 5th Edition",
|
||||
"description": "A comprehensive game system for running games of SW 5th Edition in the Foundry VTT environment.",
|
||||
"version": "1.4.1.R1-A8",
|
||||
"version": "1.4.2.R1-A8",
|
||||
"author": "Dev Team",
|
||||
"scripts": [],
|
||||
"esmodules": ["sw5e.js"],
|
||||
|
|
|
@ -945,7 +945,7 @@
|
|||
],
|
||||
"armor": {
|
||||
"type": "light",
|
||||
"value": 10,
|
||||
"value": null,
|
||||
"dex": null
|
||||
},
|
||||
"speed": {
|
||||
|
|
|
@ -121,36 +121,38 @@
|
|||
</div>
|
||||
|
||||
{{!-- Armor Class --}}
|
||||
<div class="form-group">
|
||||
<label>{{ localize "SW5E.ArmorClass" }}</label>
|
||||
<div class="form-fields">
|
||||
<input type="text" name="data.armor.value" value="{{data.armor.value}}" data-dtype="Number"/>
|
||||
{{#if hasAC}}
|
||||
<div class="form-group">
|
||||
<label>{{ localize "SW5E.ArmorClass" }}</label>
|
||||
<div class="form-fields">
|
||||
<input type="text" name="data.armor.value" value="{{data.armor.value}}" data-dtype="Number"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#unless isMountable}}
|
||||
{{!-- Dexterity Modifier --}}
|
||||
<div class="form-group">
|
||||
<label>{{ localize "SW5E.ItemEquipmentDexMod" }}</label>
|
||||
<div class="form-fields">
|
||||
<input type="text" name="data.armor.dex" value="{{data.armor.dex}}" data-dtype="Number" placeholder="{{ localize 'SW5E.Unlimited' }}"/>
|
||||
{{#if isArmor}}
|
||||
{{!-- Dexterity Modifier --}}
|
||||
<div class="form-group">
|
||||
<label>{{ localize "SW5E.ItemEquipmentDexMod" }}</label>
|
||||
<div class="form-fields">
|
||||
<input type="text" name="data.armor.dex" value="{{data.armor.dex}}" data-dtype="Number" placeholder="{{ localize 'SW5E.Unlimited' }}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{!-- Required Strength --}}
|
||||
<div class="form-group">
|
||||
<label>{{ localize "SW5E.ItemRequiredStr" }}</label>
|
||||
<div class="form-fields">
|
||||
<input type="text" name="data.strength" value="{{data.strength}}" data-dtype="Number" placeholder="{{ localize 'SW5E.None' }}"/>
|
||||
{{!-- Required Strength --}}
|
||||
<div class="form-group">
|
||||
<label>{{ localize "SW5E.ItemRequiredStr" }}</label>
|
||||
<div class="form-fields">
|
||||
<input type="text" name="data.strength" value="{{data.strength}}" data-dtype="Number" placeholder="{{ localize 'SW5E.None' }}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{!-- Stealth Disadvantage --}}
|
||||
<div class="form-group">
|
||||
<label>{{ localize "SW5E.ItemEquipmentStealthDisav" }}</label>
|
||||
<input type="checkbox" name="data.stealth" value="1" {{checked data.stealth}}/>
|
||||
</div>
|
||||
{{/unless}}
|
||||
{{!-- Stealth Disadvantage --}}
|
||||
<div class="form-group">
|
||||
<label>{{ localize "SW5E.ItemEquipmentStealthDisav" }}</label>
|
||||
<input type="checkbox" name="data.stealth" value="1" {{checked data.stealth}}/>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if isMountable}}
|
||||
{{> 'systems/sw5e/templates/items/parts/item-mountable.html'}}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue