diff --git a/README.md b/README.md index 0b960436d..9e0297591 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Warhammer Fantasy Roleplay 4th Ed. (FoundryVTT) ![](https://user-images.githubusercontent.com/28637157/97379891-e4a1cc00-1893-11eb-9e0c-d93b92844d5b.jpg) -**[Current Version]**: `6.1.1` +**[Current Version]**: `6.1.2` **[Compatibility]**: `FoundryVTT V10` diff --git a/modules/actor/actor-wfrp4e.js b/modules/actor/actor-wfrp4e.js index 362b4e5e1..8a82f237c 100644 --- a/modules/actor/actor-wfrp4e.js +++ b/modules/actor/actor-wfrp4e.js @@ -118,8 +118,8 @@ export default class ActorWfrp4e extends Actor { // Treat the custom default token as a true default token // If you change the actor image from the default token, it will automatically set the same image to be the token image - if (updateData.prototypeToken?.img == "systems/wfrp4e/tokens/unknown.png" && updateData.img) { - updateData["token.img"] = updateData.img; + if (this.prototypeToken?.texture?.src == "systems/wfrp4e/tokens/unknown.png" && updateData.img) { + updateData["prototypeToken.texture.src"] = updateData.img; } if (hasProperty(updateData, "system.details.experience") && !hasProperty(updateData, "system.details.experience.log")) { @@ -1329,7 +1329,7 @@ export default class ActorWfrp4e extends Actor { }, title: title, template: template, - flags: { img: this.prototypeToken.randomImg ? this.img : this.prototypeToken.img } + flags: { img: this.prototypeToken.randomImg ? this.img : this.prototypeToken.texture.src } // img to be displayed next to the name on the test card - if it's a wildcard img, use the actor image } @@ -1338,7 +1338,7 @@ export default class ActorWfrp4e extends Actor { cardOptions.speaker.alias = this.token.name; // Use the token name instead of the actor name cardOptions.speaker.token = this.token.id; cardOptions.speaker.scene = canvas.scene.id - cardOptions.flags.img = this.token.img; // Use the token image instead of the actor image + cardOptions.flags.img = this.token.texture.src; // Use the token image instead of the actor image if (this.token.getFlag("wfrp4e", "mask")) { cardOptions.speaker.alias = "???" @@ -1352,7 +1352,7 @@ export default class ActorWfrp4e extends Actor { cardOptions.speaker.alias = speaker.alias cardOptions.speaker.token = speaker.token cardOptions.speaker.scene = speaker.scene - cardOptions.flags.img = speaker.token ? canvas.tokens.get(speaker.token).img : cardOptions.flags.img + cardOptions.flags.img = speaker.token ? canvas.tokens.get(speaker.token)?.document.texture.src : cardOptions.flags.img } if (getProperty(this.prototypeToken, "flags.wfrp4e.mask")) { @@ -1362,7 +1362,7 @@ export default class ActorWfrp4e extends Actor { } if (this.isMounted && this.mount) { - cardOptions.flags.mountedImg = this.mount.prototypeToken.img; + cardOptions.flags.mountedImg = this.mount.prototypeToken.texture.src; cardOptions.flags.mountedName = this.mount.prototypeToken.name; } @@ -1550,9 +1550,13 @@ export default class ActorWfrp4e extends Actor { let tokenData = {} let tokenSize = game.wfrp4e.config.tokenSizes[this.details.size.value]; if (tokenSize < 1) - tokenData.scale = tokenSize; + { + tokenData.texture = {scaleX: tokenSize, scaleY: tokenSize}; + tokenData.width = 1; + tokenData.height = 1; + } else { - tokenData.scale = 1; + tokenData.texture = {scaleX : 1, scaleY: 1} tokenData.height = tokenSize; tokenData.width = tokenSize; } @@ -1985,7 +1989,7 @@ export default class ActorWfrp4e extends Actor { if (applyAP) { modifiedDamage -= this.status.armour[loc].value - msg += `(${this.status.armour[loc].value} ${game.i18n.localize("AP")})` + msg += ` (${this.status.armour[loc].value} ${game.i18n.localize("AP")}` if (!applyTB) msg += ")" else @@ -1995,7 +1999,7 @@ export default class ActorWfrp4e extends Actor { if (applyTB) { modifiedDamage -= this.characteristics.t.bonus; if (!applyAP) - msg += "(" + msg += " (" msg += `${this.characteristics.t.bonus} ${game.i18n.localize("TBRed")})` } @@ -2020,7 +2024,7 @@ export default class ActorWfrp4e extends Actor { /** * Display changes to health as scrolling combat text. * Adapt the font size relative to the Actor's HP total to emphasize more significant blows. - * @param {number} daamge + * @param {number} damage * @private */ _displayScrollingChange(change, options = {}) { diff --git a/modules/actor/sheet/actor-sheet.js b/modules/actor/sheet/actor-sheet.js index 3c095cada..c223c2a1b 100644 --- a/modules/actor/sheet/actor-sheet.js +++ b/modules/actor/sheet/actor-sheet.js @@ -642,19 +642,20 @@ export default class ActorSheetWfrp4e extends ActorSheet { html.on("dragleave", ".mount-drop", ev => { ev.target.classList.remove("dragover") }) - html.on("drop", ".mount-drop", ev => { + html.on("drop", ".mount-drop", async ev => { ev.target.classList.remove("dragover") let dragData = JSON.parse(ev.originalEvent.dataTransfer.getData("text/plain")) - let mount = game.actors.get(dragData.id); + + let mount = await Actor.implementation.fromDropData(dragData) if (game.wfrp4e.config.actorSizeNums[mount.details.size.value] < game.wfrp4e.config.actorSizeNums[this.actor.details.size.value]) return ui.notifications.error(game.i18n.localize("MountError")) let mountData = { - id: dragData.id, + id: mount.id, mounted: true, isToken: false } - if(this.actor.prototypeToken.actorLink && !game.actors.get(dragData.id).prototypeToken.actorLink) + if(this.actor.prototypeToken.actorLink && !mount.prototypeToken.actorLink) ui.notifications.warn(game.i18n.localize("WarnUnlinkedMount")) this.actor.update({ "system.status.mount": mountData }) @@ -949,7 +950,7 @@ export default class ActorSheetWfrp4e extends ActorSheet { if (!location) return; let armourTraits = this.actor.getItemTypes("trait").filter(i => i.name.toLowerCase() == game.i18n.localize("NAME.Armour").toLowerCase()).map(i => i.toObject()); - let armourItems = this.actor.getItemTypes("armour").filter(i => i.isEquipped).map(i => i.toObject()).sort((a, b) => a.sort - b.sort) + let armourItems = this.actor.getItemTypes("armour").filter(i => i.isEquipped).sort((a, b) => a.sort - b.sort) let armourToDamage; let usedTrait = false; // Damage traits first @@ -987,17 +988,18 @@ export default class ActorSheetWfrp4e extends ActorSheet { } } else if (ev.button == 0) { - if (a.AP[location] > 0 && a.APdamage[location] > 0) + if (a.AP[location] > 0 && a.APdamage[location] > 0) { armourToDamage = a; break } } } - if (!armourToDamage) - return - let durable = armourToDamage.properties.qualities.durable; - armourToDamage = armourToDamage.toObject() - + } + if (!armourToDamage) + return + let durable = armourToDamage.properties.qualities.durable; + armourToDamage = armourToDamage.toObject() + // Damage on right click if (ev.button == 2) { // Damage shouldn't go past AP max (accounting for durable) armourToDamage.system.APdamage[location] = Math.min(armourToDamage.system.AP[location] + (Number(durable?.value) || 0), armourToDamage.system.APdamage[location] + 1) @@ -1716,7 +1718,7 @@ export default class ActorSheetWfrp4e extends ActorSheet { let dragData = JSON.parse(ev.dataTransfer.getData("text/plain")); let dropID = $(ev.target).parents(".item").attr("data-item-id"); - let item = await Item.implementation.fromDropData(dragData) + let item = (await Item.implementation.fromDropData(dragData))?.toObject() item.system.location.value = dropID; // Change location value of item to the id of the container it is in @@ -1729,7 +1731,7 @@ export default class ActorSheetWfrp4e extends ActorSheet { item.system.worn = false; - return this.actor.updateEmbeddedDocuments("Item", [item.toObject()]); + return this.actor.updateEmbeddedDocuments("Item", [item]); } // Dropping a character creation result diff --git a/modules/actor/sheet/character-sheet.js b/modules/actor/sheet/character-sheet.js index 333ffd27d..a6386d85a 100644 --- a/modules/actor/sheet/character-sheet.js +++ b/modules/actor/sheet/character-sheet.js @@ -216,7 +216,7 @@ export default class ActorSheetWfrp4eCharacter extends ActorSheetWfrp4e { { label: game.i18n.localize("Yes"), callback: dlg => { - this.actor.createEmbeddedDocuments("Item", [skill.data]); + this.actor.createEmbeddedDocuments("Item", [skill.toObject()]); } }, cancel: diff --git a/modules/hooks/token.js b/modules/hooks/token.js index 53ecedbca..f5e570950 100644 --- a/modules/hooks/token.js +++ b/modules/hooks/token.js @@ -87,8 +87,11 @@ export default function() { ); button.mousedown(event => { - let token1 = canvas.tokens.controlled[0]; - let token2 = canvas.tokens.controlled[1]; + let token1 = canvas.tokens.controlled[0].document; + let token2 = canvas.tokens.controlled[1].document; + + if (!token1 || !token2) + return let mountee = hud.object; let mounter = hud.object.id == token1.id ? token2 : token1 diff --git a/modules/item/item-sheet.js b/modules/item/item-sheet.js index 90b0115ca..173ffbc1e 100644 --- a/modules/item/item-sheet.js +++ b/modules/item/item-sheet.js @@ -94,9 +94,7 @@ export default class ItemSheetWfrp4e extends ItemSheet { else if (this.item.type == "career") { data['skills'] = this.item.system.skills.join(", ").toString(); - data['earningSkills'] = this.item.system.incomeSkill.map(skillIndex=> { - this.item.system.skills[skillIndex]; - }); + data['earningSkills'] = this.item.system.incomeSkill.map(skillIndex=> this.item.system.skills[skillIndex]); data['talents'] = this.item.system.talents.toString(); data['trappings'] = this.item.system.trappings.toString(); let characteristicList = duplicate(game.wfrp4e.config.characteristicsAbbrev); diff --git a/modules/item/item-wfrp4e.js b/modules/item/item-wfrp4e.js index b1444ca4d..c0e02038b 100644 --- a/modules/item/item-wfrp4e.js +++ b/modules/item/item-wfrp4e.js @@ -17,6 +17,7 @@ export default class ItemWfrp4e extends Item { if (!isEmpty(migration)) { + this.updateSource(migration) WFRP_Utility.log("Migrating Item: " + this.name, true, migration) } diff --git a/modules/system/chat-wfrp4e.js b/modules/system/chat-wfrp4e.js index c98e842fb..030e1fcef 100644 --- a/modules/system/chat-wfrp4e.js +++ b/modules/system/chat-wfrp4e.js @@ -28,6 +28,9 @@ export default class ChatWFRP { conditions = conditions.concat(matches.map(m => m[1].toLowerCase())).filter(i => game.wfrp4e.config.conditions[i]) + // Dedup + conditions = conditions.filter((c, i) => conditions.indexOf(c) == i) + if (conditions.length) { let html = `
` @@ -421,10 +424,14 @@ export default class ChatWFRP { let value = parseInt($(event.currentTarget).attr("data-value")); let name = $(event.currentTarget).attr("data-name"); + let targets = canvas.tokens.controlled.concat(Array.from(game.user.targets)) + if (canvas.scene) game.user.updateTokenTargets([]); + + if (game.user.isGM) { - if (!game.user.targets.size) + if (!targets.length) return ui.notifications.warn(game.i18n.localize("ErrorTarget")) - game.user.targets.forEach(t => { + targets.forEach(t => { t.actor.applyFear(value, name) if (canvas.scene) game.user.updateTokenTargets([]); }) @@ -439,14 +446,16 @@ export default class ChatWFRP { static _onTerrorButtonClicked(event) { let value = parseInt($(event.currentTarget).attr("data-value")); let name = parseInt($(event.currentTarget).attr("data-name")); + + let targets = canvas.tokens.controlled.concat(Array.from(game.user.targets)) + if (canvas.scene) game.user.updateTokenTargets([]); if (game.user.isGM) { - if (!game.user.targets.size) + if (!targets.length) return ui.notifications.warn(game.i18n.localize("ErrorTarget")) - game.user.targets.forEach(t => { + targets.forEach(t => { t.actor.applyTerror(value, name) }) - if (canvas.scene) game.user.updateTokenTargets([]); } else { if (!game.user.character) diff --git a/modules/system/config-wfrp4e.js b/modules/system/config-wfrp4e.js index cd2f7a33a..76c9993d1 100644 --- a/modules/system/config-wfrp4e.js +++ b/modules/system/config-wfrp4e.js @@ -923,7 +923,7 @@ WFRP4E.PrepareSystemItems = function() { reload : { type: "extendedTest", name: "", - data: { + system: { SL: { }, test: { @@ -943,7 +943,7 @@ WFRP4E.PrepareSystemItems = function() { name: game.i18n.localize("NAME.Improvised"), type: "weapon", effects : [], - data: { + system: { damage: { value: "SB + 1" }, reach: { value: "personal" }, weaponGroup: { value: "basic" }, @@ -960,7 +960,7 @@ WFRP4E.PrepareSystemItems = function() { name: game.i18n.localize("NAME.Stomp"), type: "trait", effects : [], - data: { + system: { specification: { value: "4" }, rollable: { value: true, rollCharacteristic: "ws", bonusCharacteristic: "s", defaultDifficulty: "challenging", damage : true, skill : game.i18n.localize("NAME.MeleeBrawling") }, } @@ -969,7 +969,7 @@ WFRP4E.PrepareSystemItems = function() { name: game.i18n.localize("NAME.Unarmed"), type: "weapon", effects : [], - data: { + system: { damage: { value: "SB + 0" }, reach: { value: "personal" }, weaponGroup: { value: "brawling" }, @@ -986,7 +986,7 @@ WFRP4E.PrepareSystemItems = function() { fear : { name : game.i18n.localize("NAME.Fear"), type : "extendedTest", - data : { + system : { completion:{value: 'remove'}, description:{type: 'String', label: 'Description', value: ''}, failingDecreases:{value: true}, diff --git a/modules/system/effect-wfrp4e.js b/modules/system/effect-wfrp4e.js index b969cc68c..b78bbc298 100644 --- a/modules/system/effect-wfrp4e.js +++ b/modules/system/effect-wfrp4e.js @@ -34,7 +34,7 @@ export default class EffectWfrp4e extends ActiveEffect { } } if (this.flags.wfrp4e.script) - (0, eval)(this.flags.wfrp4e.script) + new Function(this.flags.wfrp4e.script).bind(this)() return this.flags.wfrp4e.effectData } diff --git a/modules/system/opposed-wfrp4e.js b/modules/system/opposed-wfrp4e.js index 393e00a01..85d02baf2 100644 --- a/modules/system/opposed-wfrp4e.js +++ b/modules/system/opposed-wfrp4e.js @@ -227,7 +227,7 @@ export default class OpposedWFRP { attacker: attackerAlias, SL: opposeResult.differenceSL }) - opposeResult.img = this.defenderMessage ? this.defenderMessage.flags.img : this.defenderTest.actor.prototypeToken.img + opposeResult.img = this.defenderMessage ? this.defenderMessage.flags.img : this.defenderTest.actor.prototypeToken.texture.src } return opposeResult; diff --git a/modules/system/tables-wfrp4e.js b/modules/system/tables-wfrp4e.js index 69036b23f..101e91edc 100644 --- a/modules/system/tables-wfrp4e.js +++ b/modules/system/tables-wfrp4e.js @@ -275,19 +275,19 @@ export default class WFRP_Tables { { } // If the roll is an item, don't post the link to chat, post the item to chat - if (result.object?.collection && result.object?.resultId) + if (result.object?.documentCollection && result.object?.documentId) { - let collection = game.packs.get(result.object.collection) + let collection = game.packs.get(result.object.documentCollection) if (collection) await collection.getDocuments() if (!collection) - collection = game.collections.get(result.object.collection) + collection = game.collections.get(result.object.documentCollection) if (collection) { - let item = collection.get(result.object.resultId) + let item = collection.get(result.object.documentId) if (item && item.documentName == "Item") { item.postItem(); diff --git a/static/css/wfrp4e.css b/static/css/wfrp4e.css index fbda34b64..7f7721ec4 100644 --- a/static/css/wfrp4e.css +++ b/static/css/wfrp4e.css @@ -1109,7 +1109,8 @@ visibility: hidden; } - #sidebar-tabs > .item.active .fas { + #sidebar-tabs > .item.active .fa-solid, + #sidebar-tabs > .item.active .fas { position: relative; top: 0px; left: 0px; @@ -1122,6 +1123,21 @@ text-shadow: 0 0 10px #ff000000; visibility: visible; } + + + #sidebar-tabs > .item.active .notification-pip { + position: absolute; + top: 5px; + right: -20px; + width: unset; + background: none; + height: unset; + border: unset; + box-shadow: unset; + border-radius: unset; + text-shadow: none; + } + #sidebar-tabs > [data-tab~="chat"].active i { background: url(../ui/sidebar-button-chat-active.webp); } diff --git a/system.json b/system.json index b96f64a9d..d0a506c96 100644 --- a/system.json +++ b/system.json @@ -3,7 +3,7 @@ "name": "wfrp4e", "title": "Warhammer Fantasy Roleplay 4th Edition", "description": "A comprehensive system for running grim and perilous games of Warhammer Fantasy Roleplay in the Foundry VTT environment.", - "version": "6.1.1", + "version": "6.1.2", "author": "Moo Man, CatoThe1stElder", "authors" : [ { @@ -57,6 +57,6 @@ "templateVersion":3, "socket": true, "manifest" : "https://github.com/moo-man/WFRP4e-FoundryVTT/releases/latest/download/system.json", - "download" : "https://github.com/moo-man/WFRP4e-FoundryVTT/releases/download/6.1.1/wfrp4e.zip", + "download" : "https://github.com/moo-man/WFRP4e-FoundryVTT/releases/download/6.1.2/wfrp4e.zip", "url" : "https://github.com/moo-man/WFRP4e-FoundryVTT" }