forked from GitHub-Mirrors/foundry-sw5e
Updating to Push Class skills on level up
Update from DND5E beta for Class Skills on level up and other various fixups
This commit is contained in:
parent
67ba5b2d2d
commit
53d7284596
36 changed files with 1537 additions and 440 deletions
|
@ -150,7 +150,6 @@ export default class Item5e extends Item {
|
|||
|
||||
// Get the Item's data
|
||||
const itemData = this.data;
|
||||
const actorData = this.actor ? this.actor.data : {};
|
||||
const data = itemData.data;
|
||||
const C = CONFIG.SW5E;
|
||||
const labels = {};
|
||||
|
@ -228,16 +227,12 @@ export default class Item5e extends Item {
|
|||
// Item Actions
|
||||
if ( data.hasOwnProperty("actionType") ) {
|
||||
|
||||
// Save DC
|
||||
let save = data.save || {};
|
||||
if ( !save.ability ) save.dc = null;
|
||||
else if ( this.isOwned ) { // Actor owned items
|
||||
if ( save.scaling === "power" ) save.dc = actorData.data.attributes.powerdc;
|
||||
else if ( save.scaling !== "flat" ) save.dc = this.actor.getPowerDC(save.scaling);
|
||||
} else { // Un-owned items
|
||||
// Saving throws for unowned items
|
||||
const save = data.save;
|
||||
if ( save?.ability && !this.isOwned ) {
|
||||
if ( save.scaling !== "flat" ) save.dc = null;
|
||||
labels.save = game.i18n.format("SW5E.SaveDC", {dc: save.dc || "", ability: C.abilities[save.ability]});
|
||||
}
|
||||
labels.save = save.ability ? `${game.i18n.localize("SW5E.AbbreviationDC")} ${save.dc || ""} ${C.abilities[save.ability]}` : "";
|
||||
|
||||
// Damage
|
||||
let dam = data.damage || {};
|
||||
|
@ -303,13 +298,20 @@ export default class Item5e extends Item {
|
|||
user: game.user._id,
|
||||
type: CONST.CHAT_MESSAGE_TYPES.OTHER,
|
||||
content: html,
|
||||
flavor: this.name,
|
||||
speaker: {
|
||||
actor: this.actor._id,
|
||||
token: this.actor.token,
|
||||
alias: this.actor.name
|
||||
}
|
||||
},
|
||||
flags: {"core.canPopout": true}
|
||||
};
|
||||
|
||||
// If the consumable was destroyed in the process - embed the item data in the surviving message
|
||||
if ( (this.data.type === "consumable") && !this.actor.items.has(this.id) ) {
|
||||
chatData.flags["sw5e.itemData"] = this.data;
|
||||
}
|
||||
|
||||
// Toggle default roll mode
|
||||
rollMode = rollMode || game.settings.get("core", "rollMode");
|
||||
if ( ["gmroll", "blindroll"].includes(rollMode) ) chatData["whisper"] = ChatMessage.getWhisperRecipients("GM");
|
||||
|
@ -443,7 +445,7 @@ export default class Item5e extends Item {
|
|||
// Maybe initiate template placement workflow
|
||||
if ( this.hasAreaTarget && placeTemplate ) {
|
||||
const template = AbilityTemplate.fromItem(this);
|
||||
if ( template ) template.drawPreview(event);
|
||||
if ( template ) template.drawPreview();
|
||||
if ( this.owner && this.owner.sheet ) this.owner.sheet.minimize();
|
||||
}
|
||||
return true;
|
||||
|
@ -481,7 +483,7 @@ export default class Item5e extends Item {
|
|||
// Ability activation properties
|
||||
if ( data.hasOwnProperty("activation") ) {
|
||||
props.push(
|
||||
labels.activation + (data.activation.condition ? `(${data.activation.condition})` : ""),
|
||||
labels.activation + (data.activation?.condition ? ` (${data.activation.condition})` : ""),
|
||||
labels.target,
|
||||
labels.range,
|
||||
labels.duration
|
||||
|
@ -617,17 +619,15 @@ export default class Item5e extends Item {
|
|||
rollData["atk"] = [itemData.attackBonus, actorBonus.attack].filterJoin(" + ");
|
||||
}
|
||||
|
||||
// Ammunition Bonus
|
||||
delete this._ammo;
|
||||
const consume = itemData.consume;
|
||||
if ( consume?.type === "ammo" ) {
|
||||
if ( !consume.target ) {
|
||||
ui.notifications.warn(game.i18n.format("SW5E.ConsumeWarningNoResource", {name: this.name}));
|
||||
return false;
|
||||
}
|
||||
const ammo = this.actor.items.get(consume.target);
|
||||
// Ammunition Bonus
|
||||
delete this._ammo;
|
||||
const consume = itemData.consume;
|
||||
if ( consume?.type === "ammo" ) {
|
||||
const ammo = this.actor.items.get(consume.target);
|
||||
if(ammo?.data){
|
||||
const q = ammo.data.data.quantity;
|
||||
if ( q && (q - consume.amount >= 0) ) {
|
||||
const consumeAmount = consume.amount ?? 0;
|
||||
if ( q && (q - consumeAmount >= 0) ) {
|
||||
let ammoBonus = ammo.data.data.attackBonus;
|
||||
if ( ammoBonus ) {
|
||||
parts.push("@ammo");
|
||||
|
@ -636,7 +636,10 @@ export default class Item5e extends Item {
|
|||
this._ammo = ammo;
|
||||
}
|
||||
}
|
||||
//}else{
|
||||
// ui.notifications.error(game.i18n.format("SW5E.ConsumeWarningNoResource", {name: this.name, type: typeLabel}));
|
||||
}
|
||||
}
|
||||
|
||||
// Compose roll options
|
||||
const rollConfig = mergeObject({
|
||||
|
@ -856,7 +859,7 @@ export default class Item5e extends Item {
|
|||
* Place an attack roll using an item (weapon, feat, power, or equipment)
|
||||
* Rely upon the d20Roll logic for the core implementation
|
||||
*
|
||||
* @return {Promise.<Roll>} A Promise which resolves to the created Roll instance
|
||||
* @return {Promise<Roll>} A Promise which resolves to the created Roll instance
|
||||
*/
|
||||
async rollFormula(options={}) {
|
||||
if ( !this.data.data.formula ) {
|
||||
|
@ -941,7 +944,7 @@ export default class Item5e extends Item {
|
|||
// Maybe initiate template placement workflow
|
||||
if ( this.hasAreaTarget && placeTemplate ) {
|
||||
const template = AbilityTemplate.fromItem(this);
|
||||
if ( template ) template.drawPreview(event);
|
||||
if ( template ) template.drawPreview();
|
||||
if ( this.owner && this.owner.sheet ) this.owner.sheet.minimize();
|
||||
}
|
||||
return true;
|
||||
|
@ -1065,48 +1068,41 @@ export default class Item5e extends Item {
|
|||
const isTargetted = action === "save";
|
||||
if ( !( isTargetted || game.user.isGM || message.isAuthor ) ) return;
|
||||
|
||||
// Get the Actor from a synthetic Token
|
||||
// Recover the actor for the chat card
|
||||
const actor = this._getChatCardActor(card);
|
||||
if ( !actor ) return;
|
||||
|
||||
// Get the Item
|
||||
const item = actor.getOwnedItem(card.dataset.itemId);
|
||||
// Get the Item from stored flag data or by the item ID on the Actor
|
||||
const storedData = message.getFlag("sw5e", "itemData");
|
||||
const item = storedData ? this.createOwned(storedData, actor) : actor.getOwnedItem(card.dataset.itemId);
|
||||
if ( !item ) {
|
||||
return ui.notifications.error(game.i18n.format("SW5E.ActionWarningNoItem", {item: card.dataset.itemId, name: actor.name}))
|
||||
}
|
||||
const powerLevel = parseInt(card.dataset.powerLevel) || null;
|
||||
|
||||
// Get card targets
|
||||
let targets = [];
|
||||
if ( isTargetted ) {
|
||||
targets = this._getChatCardTargets(card);
|
||||
if ( !targets.length ) {
|
||||
ui.notifications.warn(game.i18n.localize("SW5E.ActionWarningNoToken"));
|
||||
return button.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Attack and Damage Rolls
|
||||
if ( action === "attack" ) await item.rollAttack({event});
|
||||
else if ( action === "damage" ) await item.rollDamage({event, powerLevel});
|
||||
else if ( action === "versatile" ) await item.rollDamage({event, powerLevel, versatile: true});
|
||||
else if ( action === "formula" ) await item.rollFormula({event, powerLevel});
|
||||
|
||||
// Saving Throws for card targets
|
||||
else if ( action === "save" ) {
|
||||
for ( let a of targets ) {
|
||||
const speaker = ChatMessage.getSpeaker({scene: canvas.scene, token: a.token});
|
||||
await a.rollAbilitySave(button.dataset.ability, { event, speaker });
|
||||
}
|
||||
}
|
||||
|
||||
// Tool usage
|
||||
else if ( action === "toolCheck" ) await item.rollToolCheck({event});
|
||||
|
||||
// Power Template Creation
|
||||
else if ( action === "placeTemplate") {
|
||||
const template = AbilityTemplate.fromItem(item);
|
||||
if ( template ) template.drawPreview(event);
|
||||
// Handle different actions
|
||||
switch ( action ) {
|
||||
case "attack":
|
||||
await item.rollAttack({event}); break;
|
||||
case "damage":
|
||||
await item.rollDamage({event, powerLevel}); break;
|
||||
case "versatile":
|
||||
await item.rollDamage({event, powerLevel, versatile: true}); break;
|
||||
case "formula":
|
||||
await item.rollFormula({event, powerLevel}); break;
|
||||
case "save":
|
||||
const targets = this._getChatCardTargets(card);
|
||||
for ( let token of targets ) {
|
||||
const speaker = ChatMessage.getSpeaker({scene: canvas.scene, token: token});
|
||||
await token.actor.rollAbilitySave(button.dataset.ability, { event, speaker });
|
||||
}
|
||||
break;
|
||||
case "toolCheck":
|
||||
await item.rollToolCheck({event}); break;
|
||||
case "placeTemplate":
|
||||
const template = AbilityTemplate.fromItem(item);
|
||||
if ( template ) template.drawPreview();
|
||||
break;
|
||||
}
|
||||
|
||||
// Re-enable the button
|
||||
|
@ -1164,10 +1160,9 @@ export default class Item5e extends Item {
|
|||
* @private
|
||||
*/
|
||||
static _getChatCardTargets(card) {
|
||||
const character = game.user.character;
|
||||
const controlled = canvas.tokens.controlled;
|
||||
const targets = controlled.reduce((arr, t) => t.actor ? arr.concat([t.actor]) : arr, []);
|
||||
if ( character && (controlled.length === 0) ) targets.push(character);
|
||||
let targets = canvas.tokens.controlled.filter(t => !!t.actor);
|
||||
if ( !targets.length && game.user.character ) targets = targets.concat(game.user.character.getActiveTokens());
|
||||
if ( !targets.length ) ui.notifications.warn(game.i18n.localize("SW5E.ActionWarningNoToken"));
|
||||
return targets;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue