Merge branch '101-opponent-defense-per-attack-type' into 'main'
Display opponent defense in attack rolls and make it adjustable via effects per attack type Closes #101 See merge request dungeonslayers/ds4!220
This commit is contained in:
commit
0ecfdbda02
20 changed files with 2801 additions and 1670 deletions
|
@ -28,6 +28,8 @@
|
|||
"DS4.OpponentDefense": "Gegnerabwehr",
|
||||
"DS4.OpponentDefenseAbbr": "GA",
|
||||
"DS4.SortByOpponentDefense": "Nach Gegnerabwehr sortieren",
|
||||
"DS4.OpponentDefenseMelee": "Gegnerabwehr für Schlagen",
|
||||
"DS4.OpponentDefenseRanged": "Gegnerabwehr für Schießen",
|
||||
"DS4.AttackTypeMelee": "Schlagen",
|
||||
"DS4.AttackTypeRanged": "Schießen",
|
||||
"DS4.AttackTypeMeleeRanged": "Schlagen + Schießen",
|
||||
|
@ -74,7 +76,9 @@
|
|||
"DS4.ItemTypeSpecialCreatureAbility": "Besondere Kreaturenfähigkeit",
|
||||
"DS4.ItemTypeSpecialCreatureAbilityPlural": "Besondere Kreaturenfähigkeiten",
|
||||
"DS4.ItemWeaponCheckFlavor": "{actor} greift mit {weapon} an.",
|
||||
"DS4.ItemWeaponCheckFlavorWithOpponentDefense": "{actor} greift mit {weapon} an.<br>Gegnerabwehr: {opponentDefense}",
|
||||
"DS4.ItemSpellCheckFlavor": "{actor} wirkt {spell}.",
|
||||
"DS4.ItemSpellCheckFlavorWithOpponentDefense": "{actor} wirkt {spell}.<br>Gegnerabwehr: {opponentDefense}",
|
||||
"DS4.ItemPropertiesArmor": "Panzerungseigenschaften",
|
||||
"DS4.ItemPropertiesEquipable": "Ausrüstungseigenschaften",
|
||||
"DS4.ItemPropertiesPhysical": "Physische Eigenschaften",
|
||||
|
@ -160,6 +164,8 @@
|
|||
"DS4.CooldownDuration100R": "100 Kampfrunden",
|
||||
"DS4.CooldownDuration1D": "1 Tag",
|
||||
"DS4.CooldownDurationD20D": "W20 Tage",
|
||||
"DS4.SpellAllowsDefense": "Erlaubt Abwehr",
|
||||
"DS4.SpellAllowsDefenseDescription": "Ist eine Abwehren-Probe gegen diesen Zauber erlaubt?",
|
||||
"DS4.SpellMinimumLevel": "Zugangsstufe",
|
||||
"DS4.SpellMinimumLevelDescription": "Die minimale Stufe, ab der ein Zauberwirker den Zauberspruch erlernen kann.",
|
||||
"DS4.SpellCasterClassHealer": "Heiler",
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
"DS4.OpponentDefense": "Opponent Defense",
|
||||
"DS4.OpponentDefenseAbbr": "OD",
|
||||
"DS4.SortByOpponentDefense": "Sort by Opponent Defense",
|
||||
"DS4.OpponentDefenseMelee": "Opponent Defense for melee attacks",
|
||||
"DS4.OpponentDefenseRanged": "Opponent Defense for ranged attacks",
|
||||
"DS4.AttackTypeMelee": "Melee",
|
||||
"DS4.AttackTypeRanged": "Ranged",
|
||||
"DS4.AttackTypeMeleeRanged": "Melee / Ranged",
|
||||
|
@ -74,7 +76,9 @@
|
|||
"DS4.ItemTypeSpecialCreatureAbility": "Special Creature Ability",
|
||||
"DS4.ItemTypeSpecialCreatureAbilityPlural": "Special Creature Abilities",
|
||||
"DS4.ItemWeaponCheckFlavor": "{actor} attacks with {weapon}.",
|
||||
"DS4.ItemWeaponCheckFlavorWithOpponentDefense": "{actor} attacks with {weapon}<br>Opponent defense: {opponentDefense}",
|
||||
"DS4.ItemSpellCheckFlavor": "{actor} casts {spell}.",
|
||||
"DS4.ItemSpellCheckFlavorWithOpponentDefense": "{actor} casts {spell}.<br>Opponent Defense: {opponentDefense}",
|
||||
"DS4.ItemPropertiesArmor": "Armor Properties",
|
||||
"DS4.ItemPropertiesEquipable": "Equipment Properties",
|
||||
"DS4.ItemPropertiesPhysical": "Physical Properties",
|
||||
|
@ -160,6 +164,8 @@
|
|||
"DS4.CooldownDuration100R": "100 Rounds",
|
||||
"DS4.CooldownDuration1D": "1 Day",
|
||||
"DS4.CooldownDurationD20D": "D20 Days",
|
||||
"DS4.SpellAllowsDefense": "Allows Defense",
|
||||
"DS4.SpellAllowsDefenseDescription": "Ist it alowed to perform a defense check against this spell?",
|
||||
"DS4.SpellMinimumLevel": "Minimum Level",
|
||||
"DS4.SpellMinimumLevelDescription": "The minimum level at which a spell caster may learn the spell.",
|
||||
"DS4.SpellCasterClassHealer": "Healer",
|
||||
|
|
3441
packs/creatures.json
3441
packs/creatures.json
File diff suppressed because it is too large
Load diff
320
packs/items.json
320
packs/items.json
File diff suppressed because it is too large
Load diff
|
@ -93,7 +93,7 @@
|
|||
"startTime": null
|
||||
},
|
||||
"icon": "icons/svg/aura.svg",
|
||||
"label": "Proben mit Agilität -1",
|
||||
"label": "Proben mit Agilität -4",
|
||||
"transfer": true,
|
||||
"flags": {},
|
||||
"tint": null
|
||||
|
|
|
@ -124,7 +124,7 @@
|
|||
"type": "specialCreatureAbility",
|
||||
"img": "systems/ds4/assets/icons/official/special-creature-abilities/petrification.png",
|
||||
"data": {
|
||||
"description": "<p>Bei einem erfolgreichen Blickangriff versteinert das Ziel, sofern diesem KÖR+AU misslingt. Eine Versteinerung kann durch den Zauber Allheilung aufgehoben werden.</p>",
|
||||
"description": "<p>Bei einem erfolgreichen Blickangriff versteinert das Ziel, sofern diesem KÖR+AU misslingt. Eine Versteinerung kann durch den Zauber @Compendium[ds4.spells.pmYcjLXv1EB9bM59]{Allheilung} aufgehoben werden.</p>",
|
||||
"experiencePoints": 50
|
||||
},
|
||||
"effects": [],
|
||||
|
@ -158,7 +158,7 @@
|
|||
"type": "specialCreatureAbility",
|
||||
"img": "systems/ds4/assets/icons/official/special-creature-abilities/attribute-loss.png",
|
||||
"data": {
|
||||
"description": "<p>Pro schadensverursachendem Treffer wird AGI um 1 gesenkt (bei AGI Null ist das Opfer bewegungsunfähig). Pro Tag oder Anwendung des Zaubers <em>Allheilung</em> wird 1 verlorener Attributspunkt regeneriert.</p>",
|
||||
"description": "<p>Pro schadensverursachendem Treffer wird AGI um 1 gesenkt (bei AGI Null ist das Opfer bewegungsunfähig). Pro Tag oder Anwendung des Zaubers @Compendium[ds4.spells.pmYcjLXv1EB9bM59]{Allheilung} wird 1 verlorener Attributspunkt regeneriert.</p>",
|
||||
"experiencePoints": 15
|
||||
},
|
||||
"effects": [],
|
||||
|
@ -294,7 +294,7 @@
|
|||
"type": "specialCreatureAbility",
|
||||
"img": "systems/ds4/assets/icons/official/special-creature-abilities/charm.png",
|
||||
"data": {
|
||||
"description": "<p>Kann Gegner mit einem „Lockruf“ bezaubern. Dieser Zauber funktioniert wie der Zauberspruch <em>Gehorche</em>. Abklingzeit des <em>Lockrufs</em>: 10 Kampfrunden</p>",
|
||||
"description": "<p>Kann Gegner mit einem „Lockruf“ bezaubern. Dieser Zauber funktioniert wie der Zauberspruch @Compendium[ds4.spells.wZYElRaDmhqgzUvQ]{Gehorche}. Abklingzeit des <em>Lockrufs</em>: 10 Kampfrunden</p>",
|
||||
"experiencePoints": 25
|
||||
},
|
||||
"effects": [],
|
||||
|
@ -447,7 +447,7 @@
|
|||
"type": "specialCreatureAbility",
|
||||
"img": "systems/ds4/assets/icons/official/special-creature-abilities/attribute-loss.png",
|
||||
"data": {
|
||||
"description": "<p>Pro schadensverursachendem Treffer wird KÖR um 1 gesenkt (bei KÖR Null ist das Opfer tot). Pro Tag oder Anwendung des Zaubers <em>Allheilung</em> wird 1 verlorener Attributspunkt regeneriert.</p>",
|
||||
"description": "<p>Pro schadensverursachendem Treffer wird KÖR um 1 gesenkt (bei KÖR Null ist das Opfer tot). Pro Tag oder Anwendung des Zaubers @Compendium[ds4.spells.pmYcjLXv1EB9bM59]{Allheilung} wird 1 verlorener Attributspunkt regeneriert.</p>",
|
||||
"experiencePoints": 15
|
||||
},
|
||||
"effects": [],
|
||||
|
@ -778,7 +778,7 @@
|
|||
"type": "specialCreatureAbility",
|
||||
"img": "systems/ds4/assets/icons/official/special-creature-abilities/attribute-loss.png",
|
||||
"data": {
|
||||
"description": "<p>Pro schadensverursachendem Treffer wird GEI um 1 gesenkt (bei GEI Null ist das Opfer wahnsinnig). Pro Tag oder Anwendung des Zaubers <em>Allheilung</em> wird 1 verlorener Attributspunkt regeneriert.</p>",
|
||||
"description": "<p>Pro schadensverursachendem Treffer wird GEI um 1 gesenkt (bei GEI Null ist das Opfer wahnsinnig). Pro Tag oder Anwendung des Zaubers @Compendium[ds4.spells.pmYcjLXv1EB9bM59]{Allheilung} wird 1 verlorener Attributspunkt regeneriert.</p>",
|
||||
"experiencePoints": 15
|
||||
},
|
||||
"effects": [],
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -21,6 +21,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "1VAiKGCnqKfNC8AE",
|
||||
"name": "Waffenloser Meister",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -38,8 +39,7 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "1VAiKGCnqKfNC8AE"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "2ASdMhcx0hN3ZpPc",
|
||||
|
@ -84,6 +84,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "2zY11r1tKxBzNB0e",
|
||||
"name": "Mächtige Erweckung",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -101,10 +102,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "2zY11r1tKxBzNB0e"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "3AkPGw4beW52LIAY",
|
||||
"name": "Rüstträger",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -122,8 +123,7 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "3AkPGw4beW52LIAY"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "42FNsShgm1B6MClC",
|
||||
|
@ -238,6 +238,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "61Dz3XpStwlMfsbL",
|
||||
"name": "Jäger",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -288,8 +289,7 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "61Dz3XpStwlMfsbL"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "6YJLvjCIUmhqlaFb",
|
||||
|
@ -313,6 +313,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "6oXmRM21CLfELqKv",
|
||||
"name": "Verheerer",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -324,14 +325,41 @@
|
|||
"mod": 0
|
||||
}
|
||||
},
|
||||
"effects": [],
|
||||
"effects": [
|
||||
{
|
||||
"_id": "aqgIfpGWXYeXn1y6",
|
||||
"changes": [
|
||||
{
|
||||
"key": "data.opponentDefense",
|
||||
"mode": 2,
|
||||
"value": "-1"
|
||||
}
|
||||
],
|
||||
"disabled": false,
|
||||
"duration": {
|
||||
"startTime": null
|
||||
},
|
||||
"icon": "icons/svg/aura.svg",
|
||||
"label": "Gegnerabwehr bei Zaubern/Zielzaubern -1",
|
||||
"transfer": true,
|
||||
"flags": {
|
||||
"ds4": {
|
||||
"itemEffectConfig": {
|
||||
"applyToItems": true,
|
||||
"itemName": "",
|
||||
"condition": "'@item.type' === 'spell' && @item.data.allowsDefense"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tint": null
|
||||
}
|
||||
],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "6oXmRM21CLfELqKv"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "6z0JXGEqdzDTWQ7f",
|
||||
|
@ -474,6 +502,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "8apgKsktW4pyWmMq",
|
||||
"name": "Hinterhältiger Angriff",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -491,8 +520,7 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "8apgKsktW4pyWmMq"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "8nkrwGAE0HPoAAEm",
|
||||
|
@ -537,6 +565,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "8wHCsoZEQp3rScWe",
|
||||
"name": "Parade",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -554,10 +583,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "8wHCsoZEQp3rScWe"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "9hpucJC8WArBiXUR",
|
||||
"name": "Tod entrinnen",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -575,8 +604,7 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "9hpucJC8WArBiXUR"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "9qdc56F4XTntYoo9",
|
||||
|
@ -622,7 +650,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"tint": ""
|
||||
"tint": null
|
||||
}
|
||||
],
|
||||
"folder": null,
|
||||
|
@ -696,6 +724,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "Bp7OVgurG40CR1Mw",
|
||||
"name": "Knechtschaft",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -713,10 +742,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "Bp7OVgurG40CR1Mw"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "DUexlPzqyH2xPxYP",
|
||||
"name": "Meister seiner Klasse",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -734,8 +763,7 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "DUexlPzqyH2xPxYP"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "DZcu8KQFWChBVPRR",
|
||||
|
@ -759,6 +787,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "FoY7VbBTatyHOrb8",
|
||||
"name": "Untote Horden",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -776,10 +805,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "FoY7VbBTatyHOrb8"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "G3fbdAorLMCa2hGu",
|
||||
"name": "Meucheln",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -797,10 +826,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "G3fbdAorLMCa2hGu"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "GVuVyP3uLw3Fkiwf",
|
||||
"name": "Prügler",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -818,10 +847,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "GVuVyP3uLw3Fkiwf"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "GWVLcfQ2fm3Hc0zP",
|
||||
"name": "Schütze",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -872,8 +901,7 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "GWVLcfQ2fm3Hc0zP"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "HFCY3fxIbeXapRan",
|
||||
|
@ -918,6 +946,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "IIvsBSAqFFUFqALo",
|
||||
"name": "Sattelschütze",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -935,10 +964,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "IIvsBSAqFFUFqALo"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "IfyKb7y4YoUTssTs",
|
||||
"name": "Tiermeister",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -984,8 +1013,7 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "IfyKb7y4YoUTssTs"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "JbGKvhxVEAdczQib",
|
||||
|
@ -1009,6 +1037,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "JldVU3O4mmDWqk8s",
|
||||
"name": "Spruchmeister",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -1026,8 +1055,7 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "JldVU3O4mmDWqk8s"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "KgOHPx5oQHKBuVPc",
|
||||
|
@ -1224,6 +1252,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "Mz5glQvRowlF5U8X",
|
||||
"name": "Manipulator",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -1269,10 +1298,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "Mz5glQvRowlF5U8X"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "NR3BzKbROxHjpGrs",
|
||||
"name": "Schlossknacker",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -1323,10 +1352,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "NR3BzKbROxHjpGrs"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "NSBiWy4FTIu6Y2Vv",
|
||||
"name": "Präziser Schuss",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -1344,10 +1373,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "NSBiWy4FTIu6Y2Vv"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "Nu7TKGp987s5mHA0",
|
||||
"name": "Instrument",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -1365,8 +1394,7 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "Nu7TKGp987s5mHA0"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "ODepf0g8Us5jBqLm",
|
||||
|
@ -1432,6 +1460,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "Q98LHOFZmKVoafp8",
|
||||
"name": "Todeskraft",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -1449,10 +1478,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "Q98LHOFZmKVoafp8"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "QAxxIGpwledNp0n1",
|
||||
"name": "Panzerung zerschmettern",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -1470,10 +1499,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "QAxxIGpwledNp0n1"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "RJauLusDDQWo77JU",
|
||||
"name": "Schwimmen",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -1519,8 +1548,7 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "RJauLusDDQWo77JU"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "RTLVQgPmjiPDdTFw",
|
||||
|
@ -1544,6 +1572,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "TQG9TbBb9S0nHogC",
|
||||
"name": "Schnelle Reflexe",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -1589,8 +1618,7 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "TQG9TbBb9S0nHogC"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "UUYS4u0DmEbGzXxI",
|
||||
|
@ -1711,6 +1739,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "WMXI5ckyEdlC29j4",
|
||||
"name": "Heldenglück",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -1728,8 +1757,7 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "WMXI5ckyEdlC29j4"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "Wwvj3V65hIe0JWul",
|
||||
|
@ -1753,6 +1781,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "XNjKX9xKkktkwAHk",
|
||||
"name": "Kann ich mal vorbei?",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -1770,8 +1799,7 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "XNjKX9xKkktkwAHk"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "XUyuomVVOxuSSKXl",
|
||||
|
@ -1837,6 +1865,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "YPFshcSE5pZS0dto",
|
||||
"name": "Schmerzhafter Wechsel",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -1854,8 +1883,7 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "YPFshcSE5pZS0dto"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "ZnT8LMCRqZS3zpJO",
|
||||
|
@ -1988,6 +2016,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "aojENPok9Guo3JN1",
|
||||
"name": "Wahrnehmung",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -2053,10 +2082,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "aojENPok9Guo3JN1"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "bA8wUU0bKouuxkQ5",
|
||||
"name": "Reiten",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -2102,10 +2131,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "bA8wUU0bKouuxkQ5"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "bu9alxaRfnzzTyX1",
|
||||
"name": "Macht des Blutes",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -2123,8 +2152,7 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "bu9alxaRfnzzTyX1"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "cLkCx5hxP7rVYUqD",
|
||||
|
@ -2169,6 +2197,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "dtynnRNkxg59Nqz4",
|
||||
"name": "Verletzen",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -2180,16 +2209,44 @@
|
|||
"mod": 0
|
||||
}
|
||||
},
|
||||
"effects": [],
|
||||
"effects": [
|
||||
{
|
||||
"_id": "x1FVRsSyjHwOfYRs",
|
||||
"changes": [
|
||||
{
|
||||
"key": "data.opponentDefenseForAttackType.melee",
|
||||
"mode": 2,
|
||||
"value": "-1"
|
||||
}
|
||||
],
|
||||
"disabled": false,
|
||||
"duration": {
|
||||
"startTime": null
|
||||
},
|
||||
"icon": "icons/svg/aura.svg",
|
||||
"label": "Gegnerabwehr bei Nahkampfangriffen -1",
|
||||
"transfer": true,
|
||||
"flags": {
|
||||
"ds4": {
|
||||
"itemEffectConfig": {
|
||||
"applyToItems": true,
|
||||
"itemName": "",
|
||||
"condition": "'@item.type' === 'weapon' && ('@item.data.attackType' === 'melee' || '@item.data.attackType' === 'meleeRanged')"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tint": null
|
||||
}
|
||||
],
|
||||
"folder": null,
|
||||
"sort": 0,
|
||||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "dtynnRNkxg59Nqz4"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "fIrcapAlXMqto18X",
|
||||
"name": "Unersättliches Beschwören",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -2207,10 +2264,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "fIrcapAlXMqto18X"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "g4XI9wikUdxoCFNg",
|
||||
"name": "Ritual der Narben",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -2271,8 +2328,7 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "g4XI9wikUdxoCFNg"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "gwCc6niwZL45wklE",
|
||||
|
@ -2429,6 +2485,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "iP5aZcqriVLjdVcd",
|
||||
"name": "Tiergestalt",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -2446,10 +2503,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "iP5aZcqriVLjdVcd"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "inRlUNgoiaHm4pf6",
|
||||
"name": "Verdrücken",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -2467,10 +2524,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "inRlUNgoiaHm4pf6"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "jmjtmMy7DnG205xR",
|
||||
"name": "Schlachtruf",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -2488,8 +2545,7 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "jmjtmMy7DnG205xR"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "kZti1KQIbf4UPvI7",
|
||||
|
@ -2723,6 +2779,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "ml6GkLIsqDII9Mcp",
|
||||
"name": "Untote zerschmettern",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -2740,8 +2797,7 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "ml6GkLIsqDII9Mcp"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "nMxDermxN1pUziUJ",
|
||||
|
@ -2765,6 +2821,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "nbDef1IPNyYcXmua",
|
||||
"name": "Meister aller Klassen",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -2782,10 +2839,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "nbDef1IPNyYcXmua"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "oxWYfqhbcsDoaaUJ",
|
||||
"name": "Nekromantie",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -2831,8 +2888,7 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "oxWYfqhbcsDoaaUJ"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "pAOP7wkvhtsNIPQ8",
|
||||
|
@ -2889,6 +2945,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "pC1K0VHWTpaJqwtt",
|
||||
"name": "Raserei",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -2939,10 +2996,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "pC1K0VHWTpaJqwtt"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "pDPVZpnhvlabmcvT",
|
||||
"name": "Langfinger",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -2960,10 +3017,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "pDPVZpnhvlabmcvT"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "pEH7q5M85j50f45J",
|
||||
"name": "Mächtige Beschwörung",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -2981,10 +3038,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "pEH7q5M85j50f45J"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "qnYeR3a3LNUJ329t",
|
||||
"name": "Zehrender Spurt",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -3002,10 +3059,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "qnYeR3a3LNUJ329t"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "rCRPchtSJye0K5nt",
|
||||
"name": "Zauberwaffe",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -3023,10 +3080,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "rCRPchtSJye0K5nt"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "rXXw5aS0pCr5amWa",
|
||||
"name": "Zwei Waffen",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -3044,10 +3101,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "rXXw5aS0pCr5amWa"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "rbHZFVutiQ25glBq",
|
||||
"name": "Totenrufer",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -3065,10 +3122,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "rbHZFVutiQ25glBq"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "s37iJhz4IQVhCWbe",
|
||||
"name": "Sehnenschneider",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -3086,8 +3143,7 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "s37iJhz4IQVhCWbe"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "sSKiZ5hdQMBnAYRA",
|
||||
|
@ -3132,6 +3188,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "soobr7uyQgDm3DoN",
|
||||
"name": "Stabbindung",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -3149,10 +3206,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "soobr7uyQgDm3DoN"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "sqGJRKlgFoD2vLCD",
|
||||
"name": "Heimlichkeit",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -3213,10 +3270,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "sqGJRKlgFoD2vLCD"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "sqWBOfkvuv7ZTrVM",
|
||||
"name": "Kreiszeichner",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -3234,8 +3291,7 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "sqWBOfkvuv7ZTrVM"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "srLA4jC8lsZbp3nT",
|
||||
|
@ -3280,6 +3336,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "tkLyvmSYvVslMXVE",
|
||||
"name": "Vertrautenband",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -3297,10 +3354,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "tkLyvmSYvVslMXVE"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "tmFeIA1PSVHqGGjx",
|
||||
"name": "Vernichtender Schlag",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -3346,8 +3403,7 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "tmFeIA1PSVHqGGjx"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "v5axYsQQ2w57Iu4p",
|
||||
|
@ -3399,6 +3455,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "v9ocoi91dKJahAe3",
|
||||
"name": "Waffenkenner",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -3416,8 +3473,7 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "v9ocoi91dKJahAe3"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "vnEDVqVCsZuf8NYN",
|
||||
|
@ -3462,6 +3518,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "w34myctr1EDmXSPI",
|
||||
"name": "Herr der Elemente",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -3507,10 +3564,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "w34myctr1EDmXSPI"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "wpZ1LCG8nLu4PSc9",
|
||||
"name": "Mächtige Herbeirufung",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -3528,10 +3585,10 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "wpZ1LCG8nLu4PSc9"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "yCHMzXoqCRrNU5Br",
|
||||
"name": "Schnutz vor Elementen",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -3549,8 +3606,7 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "yCHMzXoqCRrNU5Br"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "yIcgnr9Xr7Kwocaj",
|
||||
|
@ -3574,6 +3630,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "yMVciLvr77vbTw6r",
|
||||
"name": "Magieresistent",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -3591,8 +3648,7 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "yMVciLvr77vbTw6r"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "zhzVJz6WhSMMeTuY",
|
||||
|
@ -3644,6 +3700,7 @@
|
|||
"flags": {}
|
||||
},
|
||||
{
|
||||
"_id": "zvZelUv5qQz3adKN",
|
||||
"name": "Salve",
|
||||
"type": "talent",
|
||||
"img": "icons/svg/item-bag.svg",
|
||||
|
@ -3661,7 +3718,6 @@
|
|||
"permission": {
|
||||
"default": 0
|
||||
},
|
||||
"flags": {},
|
||||
"_id": "zvZelUv5qQz3adKN"
|
||||
"flags": {}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -16,6 +16,7 @@ const defaultData: DS4SpellDataSourceData = {
|
|||
numerical: 0,
|
||||
complex: "",
|
||||
},
|
||||
allowsDefense: false,
|
||||
spellGroups: {
|
||||
lightning: false,
|
||||
earth: false,
|
||||
|
|
|
@ -60,8 +60,8 @@ class CheckFactory {
|
|||
}
|
||||
|
||||
createCheckTargetNumberModifier(): string {
|
||||
const totalCheckTargetNumber = Math.max(this.checkTargetNumber + this.checkModifier, 0);
|
||||
return `v${totalCheckTargetNumber}`;
|
||||
const totalCheckTargetNumber = this.checkTargetNumber + this.checkModifier;
|
||||
return totalCheckTargetNumber >= 0 ? `v(${this.checkTargetNumber} + ${this.checkModifier})` : "v0";
|
||||
}
|
||||
|
||||
createCoupFumbleModifier(): string | null {
|
||||
|
|
|
@ -12,4 +12,5 @@ export interface DS4SpellDataProperties {
|
|||
|
||||
interface DS4SpellDataPropertiesData extends DS4SpellDataSourceData, DS4ItemDataPropertiesDataRollable {
|
||||
price: number | null;
|
||||
opponentDefense?: number;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ export interface DS4SpellDataSourceData extends DS4ItemDataSourceDataBase, DS4It
|
|||
numerical: number;
|
||||
complex: string;
|
||||
};
|
||||
allowsDefense: boolean;
|
||||
spellGroups: Record<keyof typeof DS4.i18n.spellGroups, boolean>;
|
||||
maxDistance: UnitData<DistanceUnit>;
|
||||
effectRadius: UnitData<DistanceUnit>;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { createCheckRoll } from "../../../dice/check-factory";
|
||||
import { createCheckRoll, DS4CheckFactoryOptions } from "../../../dice/check-factory";
|
||||
import { notifications } from "../../../ui/notifications";
|
||||
import { getGame } from "../../../utils/utils";
|
||||
import { DS4Item } from "../item";
|
||||
|
@ -12,6 +12,9 @@ export class DS4Spell extends DS4Item {
|
|||
override prepareDerivedData(): void {
|
||||
this.data.data.rollable = this.data.data.equipped;
|
||||
this.data.data.price = calculateSpellPrice(this.data.data);
|
||||
if (this.data.data.allowsDefense) {
|
||||
this.data.data.opponentDefense = 0;
|
||||
}
|
||||
}
|
||||
|
||||
override async roll(options: { speaker?: { token?: TokenDocument; alias?: string } } = {}): Promise<void> {
|
||||
|
@ -42,17 +45,29 @@ export class DS4Spell extends DS4Item {
|
|||
);
|
||||
}
|
||||
const spellType = this.data.data.spellType;
|
||||
const opponentDefense = this.data.data.opponentDefense;
|
||||
const checkTargetNumber =
|
||||
ownerDataData.combatValues[spellType].total +
|
||||
(hasComplexModifier ? 0 : this.data.data.spellModifier.numerical);
|
||||
|
||||
const speaker = ChatMessage.getSpeaker({ actor: this.actor, ...options.speaker });
|
||||
const flavor =
|
||||
opponentDefense !== undefined && opponentDefense !== 0
|
||||
? "DS4.ItemSpellCheckFlavorWithOpponentDefense"
|
||||
: "DS4.ItemSpellCheckFlavor";
|
||||
const flavorData: DS4CheckFactoryOptions["flavorData"] = {
|
||||
actor: speaker.alias ?? this.actor.name,
|
||||
spell: this.name,
|
||||
};
|
||||
if (opponentDefense !== undefined && opponentDefense !== 0) {
|
||||
flavorData.opponentDefense = (opponentDefense < 0 ? "" : "+") + opponentDefense;
|
||||
}
|
||||
|
||||
await createCheckRoll(checkTargetNumber, {
|
||||
rollMode: game.settings.get("core", "rollMode"),
|
||||
maximumCoupResult: ownerDataData.rolling.maximumCoupResult,
|
||||
minimumFumbleResult: ownerDataData.rolling.minimumFumbleResult,
|
||||
flavor: "DS4.ItemSpellCheckFlavor",
|
||||
flavorData: { actor: speaker.alias ?? this.actor.name, spell: this.name },
|
||||
flavor: flavor,
|
||||
flavorData: flavorData,
|
||||
speaker,
|
||||
});
|
||||
|
||||
|
|
|
@ -5,7 +5,12 @@
|
|||
import type { DS4ItemDataPropertiesDataRollable } from "../item-data-properties-base";
|
||||
import type { DS4WeaponDataSourceData } from "./weapon-data-source";
|
||||
|
||||
interface DS4WeaponDataPropertiesData extends DS4WeaponDataSourceData, DS4ItemDataPropertiesDataRollable {}
|
||||
interface DS4WeaponDataPropertiesData extends DS4WeaponDataSourceData, DS4ItemDataPropertiesDataRollable {
|
||||
opponentDefenseForAttackType: {
|
||||
melee?: number;
|
||||
ranged?: number;
|
||||
};
|
||||
}
|
||||
|
||||
export interface DS4WeaponDataProperties {
|
||||
type: "weapon";
|
||||
|
|
|
@ -3,16 +3,22 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { DS4 } from "../../../config";
|
||||
import { createCheckRoll } from "../../../dice/check-factory";
|
||||
import { createCheckRoll, DS4CheckFactoryOptions } from "../../../dice/check-factory";
|
||||
import { notifications } from "../../../ui/notifications";
|
||||
import { getGame } from "../../../utils/utils";
|
||||
import { DS4Item } from "../item";
|
||||
|
||||
import type { AttackType } from "./weapon-data-source";
|
||||
|
||||
export class DS4Weapon extends DS4Item {
|
||||
override prepareDerivedData(): void {
|
||||
this.data.data.rollable = this.data.data.equipped;
|
||||
const data = this.data.data;
|
||||
data.rollable = data.equipped;
|
||||
data.opponentDefenseForAttackType = {};
|
||||
if (data.attackType === "melee" || data.attackType === "meleeRanged") {
|
||||
data.opponentDefenseForAttackType.melee = data.opponentDefense;
|
||||
}
|
||||
if (data.attackType === "ranged" || data.attackType === "meleeRanged") {
|
||||
data.opponentDefenseForAttackType.ranged = data.opponentDefense;
|
||||
}
|
||||
}
|
||||
|
||||
override async roll(options: { speaker?: { token?: TokenDocument; alias?: string } } = {}): Promise<void> {
|
||||
|
@ -33,54 +39,67 @@ export class DS4Weapon extends DS4Item {
|
|||
|
||||
const ownerDataData = this.actor.data.data;
|
||||
const weaponBonus = this.data.data.weaponBonus;
|
||||
const combatValue = await this.getCombatValueKeyForAttackType(this.data.data.attackType);
|
||||
const attackType = await this.getPerformedAttackType();
|
||||
const opponentDefense = this.data.data.opponentDefenseForAttackType[attackType];
|
||||
const combatValue = `${attackType}Attack` as const;
|
||||
const checkTargetNumber = ownerDataData.combatValues[combatValue].total + weaponBonus;
|
||||
|
||||
const speaker = ChatMessage.getSpeaker({ actor: this.actor, ...options.speaker });
|
||||
const flavor =
|
||||
opponentDefense !== undefined && opponentDefense !== 0
|
||||
? "DS4.ItemWeaponCheckFlavorWithOpponentDefense"
|
||||
: "DS4.ItemWeaponCheckFlavor";
|
||||
const flavorData: DS4CheckFactoryOptions["flavorData"] = {
|
||||
actor: speaker.alias ?? this.actor.name,
|
||||
weapon: this.name,
|
||||
};
|
||||
if (opponentDefense !== undefined && opponentDefense !== 0) {
|
||||
flavorData.opponentDefense = (opponentDefense < 0 ? "" : "+") + opponentDefense;
|
||||
}
|
||||
|
||||
await createCheckRoll(checkTargetNumber, {
|
||||
rollMode: getGame().settings.get("core", "rollMode"),
|
||||
maximumCoupResult: ownerDataData.rolling.maximumCoupResult,
|
||||
minimumFumbleResult: ownerDataData.rolling.minimumFumbleResult,
|
||||
flavor: "DS4.ItemWeaponCheckFlavor",
|
||||
flavorData: { actor: speaker.alias ?? this.actor.name, weapon: this.name },
|
||||
speaker,
|
||||
flavor,
|
||||
flavorData,
|
||||
});
|
||||
|
||||
Hooks.callAll("ds4.rollItem", this);
|
||||
}
|
||||
|
||||
private async getCombatValueKeyForAttackType(attackType: AttackType): Promise<"meleeAttack" | "rangedAttack"> {
|
||||
if (attackType === "meleeRanged") {
|
||||
const { melee, ranged } = { ...DS4.i18n.attackTypes };
|
||||
const identifier = "attack-type-selection";
|
||||
return Dialog.prompt({
|
||||
title: getGame().i18n.localize("DS4.DialogAttackTypeSelection"),
|
||||
content: await renderTemplate("systems/ds4/templates/dialogs/simple-select-form.hbs", {
|
||||
selects: [
|
||||
{
|
||||
label: getGame().i18n.localize("DS4.AttackType"),
|
||||
identifier,
|
||||
options: { melee, ranged },
|
||||
},
|
||||
],
|
||||
}),
|
||||
label: getGame().i18n.localize("DS4.GenericOkButton"),
|
||||
callback: (html) => {
|
||||
const selectedAttackType = html.find(`#${identifier}`).val();
|
||||
if (selectedAttackType !== "melee" && selectedAttackType !== "ranged") {
|
||||
throw new Error(
|
||||
getGame().i18n.format("DS4.ErrorUnexpectedAttackType", {
|
||||
actualType: selectedAttackType,
|
||||
expectedTypes: "'melee', 'ranged'",
|
||||
}),
|
||||
);
|
||||
}
|
||||
return `${selectedAttackType}Attack` as const;
|
||||
},
|
||||
});
|
||||
} else {
|
||||
return `${attackType}Attack` as const;
|
||||
private async getPerformedAttackType(): Promise<"melee" | "ranged"> {
|
||||
if (this.data.data.attackType !== "meleeRanged") {
|
||||
return this.data.data.attackType;
|
||||
}
|
||||
|
||||
const { melee, ranged } = { ...DS4.i18n.attackTypes };
|
||||
const identifier = `attack-type-selection-${foundry.utils.randomID()}`;
|
||||
return Dialog.prompt({
|
||||
title: getGame().i18n.localize("DS4.DialogAttackTypeSelection"),
|
||||
content: await renderTemplate("systems/ds4/templates/dialogs/simple-select-form.hbs", {
|
||||
selects: [
|
||||
{
|
||||
label: getGame().i18n.localize("DS4.AttackType"),
|
||||
identifier,
|
||||
options: { melee, ranged },
|
||||
},
|
||||
],
|
||||
}),
|
||||
label: getGame().i18n.localize("DS4.GenericOkButton"),
|
||||
callback: (html) => {
|
||||
const selectedAttackType = html.find(`#${identifier}`).val();
|
||||
if (selectedAttackType !== "melee" && selectedAttackType !== "ranged") {
|
||||
throw new Error(
|
||||
getGame().i18n.format("DS4.ErrorUnexpectedAttackType", {
|
||||
actualType: selectedAttackType,
|
||||
expectedTypes: "'melee', 'ranged'",
|
||||
}),
|
||||
);
|
||||
}
|
||||
return selectedAttackType;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
39
src/migration/007.ts
Normal file
39
src/migration/007.ts
Normal file
|
@ -0,0 +1,39 @@
|
|||
// SPDX-FileCopyrightText: 2022 Johannes Loher
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import {
|
||||
getActorUpdateDataGetter,
|
||||
getCompendiumMigrator,
|
||||
getSceneUpdateDataGetter,
|
||||
migrateActors,
|
||||
migrateCompendiums,
|
||||
migrateItems,
|
||||
migrateScenes,
|
||||
} from "./migrationHelpers";
|
||||
|
||||
async function migrate(): Promise<void> {
|
||||
await migrateItems(getItemUpdateData);
|
||||
await migrateActors(getActorUpdateData);
|
||||
await migrateScenes(getSceneUpdateData);
|
||||
await migrateCompendiums(migrateCompendium);
|
||||
}
|
||||
|
||||
function getItemUpdateData(itemData: Partial<foundry.data.ItemData["_source"]>) {
|
||||
if (itemData.type !== "spell") return;
|
||||
|
||||
return {
|
||||
data: {
|
||||
allowsDefense: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const getActorUpdateData = getActorUpdateDataGetter(getItemUpdateData);
|
||||
const getSceneUpdateData = getSceneUpdateDataGetter(getActorUpdateData);
|
||||
const migrateCompendium = getCompendiumMigrator({ getItemUpdateData, getActorUpdateData, getSceneUpdateData });
|
||||
|
||||
export const migration = {
|
||||
migrate,
|
||||
migrateCompendium,
|
||||
};
|
|
@ -11,13 +11,14 @@ import { migration as migration003 } from "./003";
|
|||
import { migration as migration004 } from "./004";
|
||||
import { migration as migration005 } from "./005";
|
||||
import { migration as migration006 } from "./006";
|
||||
import { migration as migration007 } from "./007";
|
||||
|
||||
async function migrate(): Promise<void> {
|
||||
if (!getGame().user?.isGM) {
|
||||
return;
|
||||
}
|
||||
|
||||
const oldMigrationVersion = getGame().settings.get("ds4", "systemMigrationVersion");
|
||||
const oldMigrationVersion = getCurrentMigrationVersion();
|
||||
|
||||
const targetMigrationVersion = migrations.length;
|
||||
|
||||
|
@ -47,7 +48,7 @@ async function migrateFromTo(oldMigrationVersion: number, targetMigrationVersion
|
|||
|
||||
for (const [i, { migrate }] of migrationsToExecute.entries()) {
|
||||
const currentMigrationVersion = oldMigrationVersion + i + 1;
|
||||
logger.info("executing migration script ", currentMigrationVersion);
|
||||
logger.info("executing migration script", currentMigrationVersion);
|
||||
try {
|
||||
await migrate();
|
||||
getGame().settings.set("ds4", "systemMigrationVersion", currentMigrationVersion);
|
||||
|
@ -127,6 +128,10 @@ async function migrateCompendiumFromTo(
|
|||
}
|
||||
}
|
||||
|
||||
function getCurrentMigrationVersion(): number {
|
||||
return getGame().settings.get("ds4", "systemMigrationVersion");
|
||||
}
|
||||
|
||||
function getTargetMigrationVersion(): number {
|
||||
return migrations.length;
|
||||
}
|
||||
|
@ -136,7 +141,15 @@ interface Migration {
|
|||
migrateCompendium: (pack: CompendiumCollection<CompendiumCollection.Metadata>) => Promise<void>;
|
||||
}
|
||||
|
||||
const migrations: Migration[] = [migration001, migration002, migration003, migration004, migration005, migration006];
|
||||
const migrations: Migration[] = [
|
||||
migration001,
|
||||
migration002,
|
||||
migration003,
|
||||
migration004,
|
||||
migration005,
|
||||
migration006,
|
||||
migration007,
|
||||
];
|
||||
|
||||
function isFirstWorldStart(migrationVersion: number): boolean {
|
||||
return migrationVersion < 0;
|
||||
|
@ -145,6 +158,7 @@ function isFirstWorldStart(migrationVersion: number): boolean {
|
|||
export const migration = {
|
||||
migrate,
|
||||
migrateFromTo,
|
||||
getCurrentMigrationVersion,
|
||||
getTargetMigrationVersion,
|
||||
migrateCompendiumFromTo,
|
||||
};
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"numerical": 0,
|
||||
"complex": ""
|
||||
},
|
||||
"allowsDefense": false,
|
||||
"spellGroups": {
|
||||
"lightning": false,
|
||||
"earth": false,
|
||||
|
|
|
@ -36,14 +36,26 @@ SPDX-License-Identifier: MIT
|
|||
hasQuantity=true}}
|
||||
{{!-- attack type --}}
|
||||
<img class="ds4-embedded-document-list__image"
|
||||
src="{{lookup ../../config.icons.attackTypes itemData.data.attackType}}"
|
||||
title="{{lookup ../../config.i18n.attackTypes itemData.data.attackType}}" />
|
||||
src="{{lookup @root/config.icons.attackTypes itemData.data.attackType}}"
|
||||
title="{{lookup @root/config.i18n.attackTypes itemData.data.attackType}}" />
|
||||
|
||||
{{!-- weapon bonus --}}
|
||||
<div>{{ itemData.data.weaponBonus}}</div>
|
||||
|
||||
{{!-- opponent defense --}}
|
||||
<div>{{ itemData.data.opponentDefense}}</div>
|
||||
<div>
|
||||
{{#if itemData.data.opponentDefenseForAttackType.melee includeZero=true}}
|
||||
{{#if itemData.data.opponentDefenseForAttackType.ranged includeZero=true}}
|
||||
<span
|
||||
title="{{localize 'DS4.OpponentDefenseMelee'}}">{{itemData.data.opponentDefenseForAttackType.melee}}</span>/<span
|
||||
title="{{localize 'DS4.OpponentDefenseRanged'}}">{{itemData.data.opponentDefenseForAttackType.ranged}}</span>
|
||||
{{else}}
|
||||
{{itemData.data.opponentDefenseForAttackType.melee}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{itemData.data.opponentDefenseForAttackType.ranged}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/systems/ds4/templates/sheets/actor/components/item-list-entry.hbs}}
|
||||
{{/each}}
|
||||
</ol>
|
||||
|
@ -76,13 +88,13 @@ documentType='item' type='weapon'}}
|
|||
{{#> systems/ds4/templates/sheets/actor/components/item-list-entry.hbs itemData=itemData isEquipable=true
|
||||
hasQuantity=true}}
|
||||
{{!-- armor material type --}}
|
||||
<div title="{{lookup ../../config.i18n.armorMaterialTypes itemData.data.armorMaterialType}}">
|
||||
{{lookup ../../config.i18n.armorMaterialTypesAbbr itemData.data.armorMaterialType}}
|
||||
<div title="{{lookup @root/config.i18n.armorMaterialTypes itemData.data.armorMaterialType}}">
|
||||
{{lookup @root/config.i18n.armorMaterialTypesAbbr itemData.data.armorMaterialType}}
|
||||
</div>
|
||||
|
||||
{{!-- armor type --}}
|
||||
<div title="{{lookup ../../config.i18n.armorTypes itemData.data.armorType}}">
|
||||
{{lookup ../../config.i18n.armorTypesAbbr itemData.data.armorType}}
|
||||
<div title="{{lookup @root/config.i18n.armorTypes itemData.data.armorType}}">
|
||||
{{lookup @root/config.i18n.armorTypesAbbr itemData.data.armorType}}
|
||||
</div>
|
||||
|
||||
{{!-- armor value --}}
|
||||
|
|
|
@ -105,6 +105,14 @@ SPDX-License-Identifier: MIT
|
|||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="data.allowsDefense-{{data._id}}" title="{{localize 'DS4.SpellAllowsDefenseDescription'}}">{{localize
|
||||
"DS4.SpellAllowsDefense"}}</label>
|
||||
<div class="form-fields">
|
||||
<input id="data.allowsDefense-{{data._id}}" data-dtype="Boolean" type="checkbox" name="data.allowsDefense"
|
||||
{{checked data.data.allowsDefense}} />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group slim">
|
||||
<label title="{{localize 'DS4.SpellMinimumLevelDescription'}}">{{localize "DS4.SpellMinimumLevel"}}</label>
|
||||
<div class="form-fields">
|
||||
|
|
Loading…
Reference in a new issue