From da1f6999eb52627cc49800989f024e00fa6cdd74 Mon Sep 17 00:00:00 2001 From: Johannes Loher Date: Mon, 14 Feb 2022 00:58:23 +0100 Subject: [PATCH] feat: only allow specific selectable values for the cooldown duration of spells World data (including compendium packs) is migrated automatically. In order to also migrate packs provided by modules, you can use the following macro: ```js const pack = game.packs.get("."); game.ds4.migration.migrateCompendiumFromTo(pack, 4, 5); ``` --- lang/de.json | 36 +- lang/en.json | 34 +- packs/creatures.json | 187 ++--- packs/spells.json | 645 ++++-------------- spec/item/type-specific-helpers/spell.spec.ts | 95 +-- src/common/time-helpers.ts | 8 - src/config.ts | 31 +- src/hooks/setup.ts | 9 +- src/item/item-data-source.ts | 10 +- src/item/item.ts | 10 +- src/item/type-specific-helpers/spell.ts | 50 +- src/migrations.ts | 79 ++- src/migrations/001.ts | 7 +- src/migrations/002.ts | 7 +- src/migrations/003.ts | 7 +- src/migrations/004.ts | 8 +- src/migrations/005.ts | 119 ++++ template.json | 5 +- templates/sheets/actor/tabs/spells.hbs | 30 +- .../item/components/properties/spell.hbs | 57 +- 20 files changed, 558 insertions(+), 876 deletions(-) delete mode 100644 src/common/time-helpers.ts create mode 100644 src/migrations/005.ts diff --git a/lang/de.json b/lang/de.json index 2bf3be49..d1a9e186 100644 --- a/lang/de.json +++ b/lang/de.json @@ -114,10 +114,12 @@ "DS4.ArmorMaterialTypeNaturalAbbr": "Natürlich", "DS4.SpellType": "Zauberspruchtyp", "DS4.SpellTypeAbbr": "T", + "DS4.SpellTypeDescription": "Der Typ des Zauberspruchs.", "DS4.SortBySpellType": "Nach Zauberspruchtyp sortieren", "DS4.SpellTypeSpellcasting": "Zaubern", "DS4.SpellTypeTargetedSpellcasting": "Zielzaubern", "DS4.SpellCategory": "Kategorie", + "DS4.SpellCategoryDescription": "Eine Kategorie, der der Zauberspruch zugehörig ist.", "DS4.SpellCategoryHealing": "Heilung", "DS4.SpellCategoryFire": "Feuer", "DS4.SpellCategoryIce": "Eis", @@ -127,18 +129,33 @@ "DS4.SpellCategoryElectricity": "Elektrizität", "DS4.SpellCategoryNone": "Keine", "DS4.SpellCategoryUnset": "Nicht gesetzt", - "DS4.SpellBonus": "Zauberbonus", - "DS4.SpellBonusAbbr": "ZB", - "DS4.SortBySpellBonus": "Nach Zauberbonus sortieren", - "DS4.SpellMaxDistance": "Reichweite", - "DS4.SpellEffectRadius": "Effektradius", - "DS4.SpellDuration": "Wirkdauer", - "DS4.SpellCooldownDuration": "Abklingzeit", + "DS4.SpellModifier": "Zauberbonus", + "DS4.SpellModifierAbbr": "ZB", + "DS4.SpellModifierDescription": "Der Zauberbonus auf die Probe.", + "DS4.SortBySpellModifier": "Nach Zauberbonus sortieren", + "DS4.SpellDistance": "Distanz", + "DS4.SpellDistanceDescription": "Die maximale Entfernung zum Ziel. „Selbst“ bedeutet, dass nur der Zauberwirker selbst das Ziel des Zaubers sein kann.", + "DS4.SpellEffectRadius": "Wirkungsradius", + "DS4.SpellEffectRadiusDescription": "Der Wirkungsradius des Zaubers.", + "DS4.SpellDuration": "Dauer", + "DS4.SpellDurationDescription": "Die Wirkungszeit des Zaubers.", + "DS4.CooldownDuration": "Abklingzeit", + "DS4.CooldownDurationDescription": "Die Dauer, die der Zauber nach erfolgreichem Wirken nicht einsetzbar ist.", + "DS4.CooldownDuration0R": "0 Kampfrunden", + "DS4.CooldownDuration1R": "1 Kampfrunde", + "DS4.CooldownDuration2R": "2 Kampfrunden", + "DS4.CooldownDuration5R": "5 Kampfrunden", + "DS4.CooldownDuration10R": "10 Kampfrunden", + "DS4.CooldownDuration100R": "100 Kampfrunden", + "DS4.CooldownDuration1D": "1 Tag", + "DS4.CooldownDurationD20D": "W20 Tage", "DS4.SpellMinimumLevel": "Zugangsstufe", + "DS4.SpellMinimumLevelDescription": "Die minimale Stufe, ab der ein Zauberwirker den Zauberspruch erlernen kann.", "DS4.SpellCasterClassHealer": "Heiler", "DS4.SpellCasterClassSorcerer": "Schwarzmagier", "DS4.SpellCasterClassWizard": "Zauberer", "DS4.SpellPrice": "Preis (Gold)", + "DS4.SpellPriceDescription": "Der Kaufpreis des Zauberspruchs.", "DS4.EffectEnabled": "Aktiv", "DS4.EffectEnabledAbbr": "A", "DS4.EffectEffectivelyEnabled": "Effektiv Aktiv (unter Betrachtung, ob ein eventuelles Quellen-Item ausgerüstet ist usw.)", @@ -240,6 +257,7 @@ "DS4.ErrorSlayingDiceRecursionLimitExceeded": "Die maximale Rekursionstiefe für slayende Würfelwürfe wurde überschritten.", "DS4.ErrorInvalidNumberOfDice": "Ungültige Anzahl an Würfeln.", "DS4.ErrorDuringMigration": "Fehler während der Aktualisierung des DS4 Systems von Migrationsversion {currentVersion} auf {targetVersion}. Der Fehler trat während der Ausführung des Migrationsskripts mit der Version {migrationVersion} auf. Spätere Migrationsskripte wurden nicht ausgeführt. Mehr Details finden Sie in der Entwicklerkonsole (F12).", + "DS4.ErrorDuringCompendiumMigration": "Fehler während der Aktualisierung Kompendiums '{pack}' für DS4 von Migrationsversion {currentVersion} auf {targetVersion}. Der Fehler trat während der Ausführung des Migrationsskripts mit der Version {migrationVersion} auf. Spätere Migrationsskripte wurden nicht ausgeführt. Mehr Details finden Sie in der Entwicklerkonsole (F12).", "DS4.ErrorCannotRollUnownedItem": "Für das Item '{name}' ({id}) kann nicht gewürfelt werden, da es keinem Aktor gehört.", "DS4.ErrorRollingForItemTypeNotPossible": "Würfeln ist für Items vom Typ '{type}' nicht möglich.", "DS4.ErrorWrongItemType": "Ein Item vom Type '{expectedType}' wurde erwartet aber das Item '{name}' ({id}) ist vom Typ '{actualType}'.", @@ -255,9 +273,11 @@ "DS4.WarningItemIsNotRollable": "Für das Item '{name}' ({id}) vom Typ '{type}' kann nicht gewürfelt werden.", "DS4.WarningMacrosCanOnlyBeCreatedForOwnedItems": "Makros können nur für besessene Items angelegt werden.", "DS4.WarningInvalidCheckDropped": "Eine ungültige Probe wurde auf die Hotbar gezogen.", - "DS4.InfoManuallyEnterSpellBonus": "Der korrekte Wert für den Zauberbonus '{spellBonus}' des Zaubers '{name}' muss manuell angegeben werden.", + "DS4.InfoManuallyEnterSpellModifier": "Der korrekte Wert für den Zauberbonus '{spellModifier}' des Zaubers '{name}' muss manuell angegeben werden.", "DS4.InfoSystemUpdateStart": "Aktualisiere DS4 System von Migrationsversion {currentVersion} auf {targetVersion}. Bitte haben Sie etwas Geduld, schließen Sie nicht das Spiel und fahren Sie nicht den Server herunter.", "DS4.InfoSystemUpdateCompleted": "Aktualisierung des DS4 Systems von Migrationsversion {currentVersion} auf {targetVersion} erfolgreich!", + "DS4.InfoCompendiumMigrationStart": "Aktualisiere Kompendium '{pack}' für DS4 von Migrationsversion {currentVersion} auf {targetVersion}. Bitte haben Sie etwas Geduld, schließen Sie nicht das Spiel und fahren Sie nicht den Server herunter.", + "DS4.InfoCompendiumMigrationCompleted": "Aktualisierung des Kompendiums '{pack}' für DS4 von Migrationsversion {currentVersion} auf {targetVersion} erfolgreich!", "DS4.UnitRounds": "Runden", "DS4.UnitRoundsAbbr": "Rnd", "DS4.UnitMinutes": "Minuten", diff --git a/lang/en.json b/lang/en.json index f6d6d59f..38640607 100644 --- a/lang/en.json +++ b/lang/en.json @@ -114,10 +114,12 @@ "DS4.ArmorMaterialTypeNaturalAbbr": "Natural", "DS4.SpellType": "Spell Type", "DS4.SpellTypeAbbr": "T", + "DS4.SpellTypeDescription": "The type of the spell.", "DS4.SortBySpellType": "Sort by Spell Type", "DS4.SpellTypeSpellcasting": "Spellcasting", "DS4.SpellTypeTargetedSpellcasting": "Targeted Spellcasting", "DS4.SpellCategory": "Category", + "DS4.SpellCategoryDescription": "A category which the spell belongs to.", "DS4.SpellCategoryHealing": "Healing", "DS4.SpellCategoryFire": "Fire", "DS4.SpellCategoryIce": "Ice", @@ -127,18 +129,33 @@ "DS4.SpellCategoryElectricity": "Electricity", "DS4.SpellCategoryNone": "None", "DS4.SpellCategoryUnset": "Unset", - "DS4.SpellBonus": "Spell Bonus", - "DS4.SpellBonusAbbr": "SB", - "DS4.SortBySpellBonus": "Sort by Spell Bonus", - "DS4.SpellMaxDistance": "Range", - "DS4.SpellEffectRadius": "Radius", + "DS4.SpellModifier": "Spell Modifier", + "DS4.SpellModifierAbbr": "SM", + "DS4.SpellModifierDescription": "The spell modifier for the corresponding check.", + "DS4.SortBySpellModifier": "Sort by Spell Modifier", + "DS4.SpellDistance": "Distance", + "DS4.SpellDistanceDescription": "The maximum distance to the target, “Self” meaning that only the caster can be the target of this spell.", + "DS4.SpellEffectRadius": "Area of Effect Radius", + "DS4.SpellEffectRadiusDescription": "The radius of the area of effect of the spell.", "DS4.SpellDuration": "Duration", - "DS4.SpellCooldownDuration": "Cooldown", + "DS4.SpellDurationDescription": "The spell’s duration.", + "DS4.CooldownDuration": "Cooldown Period", + "DS4.CooldownDurationDescription": "The length of time to wait after a successful casting before the spell can be cast again.", + "DS4.CooldownDuration0R": "0 Rounds", + "DS4.CooldownDuration1R": "1 Round", + "DS4.CooldownDuration2R": "2 Rounds", + "DS4.CooldownDuration5R": "5 Rounds", + "DS4.CooldownDuration10R": "10 Rounds", + "DS4.CooldownDuration100R": "100 Rounds", + "DS4.CooldownDuration1D": "1 Day", + "DS4.CooldownDurationD20D": "D20 Days", "DS4.SpellMinimumLevel": "Minimum Level", + "DS4.SpellMinimumLevelDescription": "The minimum level at which a spell caster may learn the spell.", "DS4.SpellCasterClassHealer": "Healer", "DS4.SpellCasterClassSorcerer": "Sorcerer", "DS4.SpellCasterClassWizard": "Wizard", "DS4.SpellPrice": "Price (Gold)", + "DS4.SpellPriceDescription": "The price to purchase the spell.", "DS4.EffectEnabled": "Enabled", "DS4.EffectEnabledAbbr": "E", "DS4.EffectEffectivelyEnabled": "Effectively Enabled (taking into account whether a potential source item is equipped etc.)", @@ -240,6 +257,7 @@ "DS4.ErrorSlayingDiceRecursionLimitExceeded": "Maximum recursion depth for slaying dice roll exceeded.", "DS4.ErrorInvalidNumberOfDice": "Invalid number of dice.", "DS4.ErrorDuringMigration": "Error while migrating DS4 system from migration version {currentVersion} to {targetVersion}. The error occurred during execution of migration script with version {migrationVersion}. Later migrations have not been executed. For more details, please look at the development console (F12).", + "DS4.ErrorDuringCompendiumMigration": "Error while migrating compendium '{pack}' for DS4 from migration version {currentVersion} to {targetVersion}. The error occurred during execution of migration script with version {migrationVersion}. Later migrations have not been executed. For more details, please look at the development console (F12).", "DS4.ErrorCannotRollUnownedItem": "Rolling for item '{name}' ({id})is not possible because it is not owned.", "DS4.ErrorRollingForItemTypeNotPossible": "Rolling is not possible for items of type '{type}'.", "DS4.ErrorWrongItemType": "Expected an item of type '{expectedType}' but item '{name}' ({id}) is of type '{actualType}'.", @@ -255,9 +273,11 @@ "DS4.WarningItemIsNotRollable": "Item '{name}' ({id}) of type '{type}' is not rollable.", "DS4.WarningMacrosCanOnlyBeCreatedForOwnedItems": "Macros can only be created for owned items.", "DS4.WarningInvalidCheckDropped": "An invalid check was dropped on the Hotbar.", - "DS4.InfoManuallyEnterSpellBonus": "The correct value of the spell bonus '{spellBonus}' of the spell '{name}' needs to be entered by manually.", + "DS4.InfoManuallyEnterSpellModifier": "The correct value of the spell modifier '{spellModifier}' of the spell '{name}' needs to be entered by manually.", "DS4.InfoSystemUpdateStart": "Migrating DS4 system from migration version {currentVersion} to {targetVersion}. Please be patient and do not close your game or shut down your server.", "DS4.InfoSystemUpdateCompleted": "Migration of DS4 system from migration version {currentVersion} to {targetVersion} successful!", + "DS4.InfoCompendiumMigrationStart": "Migrating compendium '{pack}' for DS4 from migration version {currentVersion} to {targetVersion}. Please be patient and do not close your game or shut down your server.", + "DS4.InfoCompendiumMigrationCompleted": "Migration of compendium '{pack}' for DS4 from migration version {currentVersion} to {targetVersion} successful!", "DS4.UnitRounds": "Rounds", "DS4.UnitRoundsAbbr": "rnd", "DS4.UnitMinutes": "Minutes", diff --git a/packs/creatures.json b/packs/creatures.json index fe7a9565..47ceb694 100644 --- a/packs/creatures.json +++ b/packs/creatures.json @@ -1881,10 +1881,7 @@ "value": "", "unit": "custom" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": null, "wizard": null, @@ -3584,10 +3581,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": 2, "wizard": 5, @@ -3629,10 +3623,7 @@ "value": "VE / 2", "unit": "rounds" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": null, "wizard": 12, @@ -3674,10 +3665,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "5", - "unit": "rounds" - }, + "cooldownDuration": "5r", "minimumLevels": { "healer": 16, "wizard": 10, @@ -3719,10 +3707,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": 16, "wizard": 12, @@ -3764,10 +3749,7 @@ "value": "Prb.", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": 4, "wizard": 8, @@ -3809,10 +3791,7 @@ "value": "Prb.", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": 4, "wizard": 8, @@ -3854,10 +3833,7 @@ "value": "Konzentration", "unit": "custom" }, - "cooldownDuration": { - "value": "0", - "unit": "rounds" - }, + "cooldownDuration": "0r", "minimumLevels": { "healer": null, "wizard": 6, @@ -3899,10 +3875,7 @@ "value": "Prb.", "unit": "minutes" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": 20, "wizard": 12, @@ -3944,10 +3917,7 @@ "value": "Prb.", "unit": "rounds" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": 8, "wizard": 5, @@ -3990,10 +3960,7 @@ "value": "Prb.", "unit": "rounds" }, - "cooldownDuration": { - "value": "5", - "unit": "rounds" - }, + "cooldownDuration": "5r", "minimumLevels": { "healer": 1, "wizard": 5, @@ -16049,10 +16016,7 @@ "value": "Prb.", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": 7, "wizard": 7, @@ -20114,10 +20078,7 @@ "value": "VE", "unit": "minutes" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": 5, "wizard": 9, @@ -21132,7 +21093,7 @@ "name": "Gedankenzehrerstrahl", "type": "spell", "data": { - "description": "

Gedankenzehrerstrahl (nicht sichtbar; verursacht mental Schaden und führt zu Werteverlust)

", + "description": "

Nicht sichtbar; verursacht mental Schaden und führt zu Werteverlust

", "equipped": true, "spellType": "targetedSpellcasting", "bonus": "", @@ -21149,10 +21110,7 @@ "value": "", "unit": "custom" }, - "cooldownDuration": { - "value": "", - "unit": "rounds" - }, + "cooldownDuration": "0r", "minimumLevels": { "healer": null, "wizard": null, @@ -25446,10 +25404,7 @@ "value": "VE x 2", "unit": "rounds" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": null, "wizard": 10, @@ -25491,10 +25446,7 @@ "value": "VE", "unit": "minutes" }, - "cooldownDuration": { - "value": "W20", - "unit": "days" - }, + "cooldownDuration": "d20d", "minimumLevels": { "healer": null, "wizard": 18, @@ -25536,10 +25488,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": 2, "wizard": 5, @@ -25581,10 +25530,7 @@ "value": "VE", "unit": "rounds" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": null, "wizard": 15, @@ -25626,10 +25572,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": null, "wizard": 12, @@ -25671,10 +25614,7 @@ "value": "Prb. x 5", "unit": "rounds" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": null, "wizard": 15, @@ -25716,10 +25656,7 @@ "value": "VE / 2", "unit": "rounds" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": null, "wizard": 12, @@ -25761,10 +25698,7 @@ "value": "Bis erlöst", "unit": "custom" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": null, "wizard": 8, @@ -25806,10 +25740,7 @@ "value": "Bis Schloss geöffnet", "unit": "custom" }, - "cooldownDuration": { - "value": "5", - "unit": "rounds" - }, + "cooldownDuration": "5r", "minimumLevels": { "healer": 3, "wizard": 1, @@ -25851,10 +25782,7 @@ "value": "Prb. / 2", "unit": "rounds" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": 4, "wizard": 9, @@ -25896,10 +25824,7 @@ "value": "Prb. / 2", "unit": "rounds" }, - "cooldownDuration": { - "value": "5", - "unit": "rounds" - }, + "cooldownDuration": "5r", "minimumLevels": { "healer": null, "wizard": 6, @@ -25941,10 +25866,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": null, "wizard": null, @@ -25986,10 +25908,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "0", - "unit": "rounds" - }, + "cooldownDuration": "0r", "minimumLevels": { "healer": null, "wizard": 15, @@ -26031,10 +25950,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": 5, "wizard": 2, @@ -26076,10 +25992,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": null, "wizard": 4, @@ -26121,10 +26034,7 @@ "value": "VE / 2", "unit": "hours" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": null, "wizard": 5, @@ -26166,10 +26076,7 @@ "value": "Prb.", "unit": "minutes" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": 20, "wizard": 12, @@ -26211,10 +26118,7 @@ "value": "Prb.", "unit": "rounds" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": 8, "wizard": 5, @@ -26256,10 +26160,7 @@ "value": "Prb. / 2", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": null, "wizard": 6, @@ -26301,10 +26202,7 @@ "value": "Prb. x 2", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": null, "wizard": null, @@ -26346,10 +26244,7 @@ "value": "Prb.", "unit": "rounds" }, - "cooldownDuration": { - "value": "W20", - "unit": "days" - }, + "cooldownDuration": "d20d", "minimumLevels": { "healer": null, "wizard": 15, @@ -28333,10 +28228,7 @@ "value": "VE / 2", "unit": "rounds" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": null, "wizard": null, @@ -28882,10 +28774,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "1", - "unit": "rounds" - }, + "cooldownDuration": "1r", "minimumLevels": { "healer": 10, "wizard": 7, diff --git a/packs/spells.json b/packs/spells.json index 2de37c0f..344870f4 100644 --- a/packs/spells.json +++ b/packs/spells.json @@ -22,10 +22,7 @@ "value": "1", "unit": "rounds" }, - "cooldownDuration": { - "value": "0", - "unit": "rounds" - }, + "cooldownDuration": "0r", "minimumLevels": { "healer": 1, "wizard": 4, @@ -63,10 +60,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": 4, "wizard": null, @@ -104,10 +98,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "1", - "unit": "rounds" - }, + "cooldownDuration": "1r", "minimumLevels": { "healer": 10, "wizard": 12, @@ -145,10 +136,7 @@ "value": "VE", "unit": "rounds" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": 2, "wizard": 6, @@ -186,10 +174,7 @@ "value": "VE", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": 10, "wizard": 10, @@ -227,10 +212,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "2", - "unit": "rounds" - }, + "cooldownDuration": "2r", "minimumLevels": { "healer": 12, "wizard": null, @@ -268,10 +250,7 @@ "value": "Prb. / 2", "unit": "hours" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": null, "wizard": 5, @@ -309,10 +288,7 @@ "value": "Prb. x 2", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": 2, "wizard": 4, @@ -350,10 +326,7 @@ "value": "Prb. / 2", "unit": "rounds" }, - "cooldownDuration": { - "value": "5", - "unit": "rounds" - }, + "cooldownDuration": "5r", "minimumLevels": { "healer": null, "wizard": 6, @@ -391,10 +364,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "1", - "unit": "rounds" - }, + "cooldownDuration": "1r", "minimumLevels": { "healer": 16, "wizard": 19, @@ -432,10 +402,7 @@ "value": "Prb. / 2", "unit": "rounds" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": 4, "wizard": 9, @@ -473,10 +440,7 @@ "value": "VE", "unit": "hours" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": 4, "wizard": 6, @@ -514,10 +478,7 @@ "value": "Prb. / 2", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": null, "wizard": 6, @@ -555,10 +516,7 @@ "value": "VE", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": null, "wizard": 8, @@ -596,10 +554,7 @@ "value": "VE", "unit": "rounds" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": null, "wizard": 15, @@ -637,10 +592,7 @@ "value": "Prb.", "unit": "hours" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": null, "wizard": 5, @@ -678,10 +630,7 @@ "value": "Prb.", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": 6, "wizard": null, @@ -719,10 +668,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "2", - "unit": "rounds" - }, + "cooldownDuration": "2r", "minimumLevels": { "healer": 4, "wizard": null, @@ -760,10 +706,7 @@ "value": "Bis erlöst", "unit": "custom" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": null, "wizard": 8, @@ -801,10 +744,7 @@ "value": "Prb.", "unit": "minutes" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": 1, "wizard": 1, @@ -842,10 +782,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": 20, "wizard": 10, @@ -883,10 +820,7 @@ "value": "VE", "unit": "minutes" }, - "cooldownDuration": { - "value": "1", - "unit": "rounds" - }, + "cooldownDuration": "1r", "minimumLevels": { "healer": 1, "wizard": 1, @@ -924,10 +858,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": null, "wizard": 10, @@ -965,10 +896,7 @@ "value": "Prb.", "unit": "rounds" }, - "cooldownDuration": { - "value": "W20", - "unit": "days" - }, + "cooldownDuration": "d20d", "minimumLevels": { "healer": null, "wizard": 15, @@ -1006,10 +934,7 @@ "value": "VE x 2", "unit": "rounds" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": null, "wizard": 4, @@ -1047,10 +972,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": 2, "wizard": 5, @@ -1088,10 +1010,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": 12, "wizard": 10, @@ -1129,10 +1048,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": 5, "wizard": null, @@ -1170,10 +1086,7 @@ "value": "Prb.", "unit": "days" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": null, "wizard": 6, @@ -1211,10 +1124,7 @@ "value": "Prb.", "unit": "minutes" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": 20, "wizard": 12, @@ -1252,10 +1162,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "0", - "unit": "rounds" - }, + "cooldownDuration": "0r", "minimumLevels": { "healer": 1, "wizard": null, @@ -1293,10 +1200,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": null, "wizard": 17, @@ -1334,10 +1238,7 @@ "value": "Prb.", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": null, "wizard": 4, @@ -1375,10 +1276,7 @@ "value": "VE", "unit": "hours" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": 1, "wizard": 7, @@ -1416,10 +1314,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": 18, "wizard": null, @@ -1457,10 +1352,7 @@ "value": "Prb.", "unit": "minutes" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": null, "wizard": 10, @@ -1498,10 +1390,7 @@ "value": "Prb.", "unit": "rounds" }, - "cooldownDuration": { - "value": "5", - "unit": "rounds" - }, + "cooldownDuration": "5r", "minimumLevels": { "healer": 1, "wizard": 5, @@ -1539,10 +1428,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": null, "wizard": 5, @@ -1580,10 +1466,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": null, "wizard": 4, @@ -1621,10 +1504,7 @@ "value": "Prb.", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": 7, "wizard": 7, @@ -1662,10 +1542,7 @@ "value": "VE min oder Konzentration", "unit": "minutes" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": 14, "wizard": 10, @@ -1703,10 +1580,7 @@ "value": "Prb.", "unit": "minutes" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": 1, "wizard": 1, @@ -1744,10 +1618,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": 5, "wizard": 2, @@ -1785,10 +1656,7 @@ "value": "VE", "unit": "minutes" }, - "cooldownDuration": { - "value": "W20", - "unit": "days" - }, + "cooldownDuration": "d20d", "minimumLevels": { "healer": null, "wizard": 18, @@ -1826,10 +1694,7 @@ "value": "Prb.", "unit": "rounds" }, - "cooldownDuration": { - "value": "5", - "unit": "rounds" - }, + "cooldownDuration": "5r", "minimumLevels": { "healer": 4, "wizard": null, @@ -1867,10 +1732,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": null, "wizard": 10, @@ -1908,10 +1770,7 @@ "value": "Prb.", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": 4, "wizard": 8, @@ -1949,10 +1808,7 @@ "value": "VE", "unit": "minutes" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": 6, "wizard": 7, @@ -1990,10 +1846,7 @@ "value": "Prb. x 5", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": 20, "wizard": 10, @@ -2031,10 +1884,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": 3, "wizard": 6, @@ -2072,10 +1922,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "W20", - "unit": "days" - }, + "cooldownDuration": "d20d", "minimumLevels": { "healer": null, "wizard": null, @@ -2113,10 +1960,7 @@ "value": "Prb. / 2", "unit": "minutes" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": 1, "wizard": null, @@ -2154,10 +1998,7 @@ "value": "Bis Strecke zurückgelegt", "unit": "custom" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": 2, "wizard": 3, @@ -2195,10 +2036,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "0", - "unit": "rounds" - }, + "cooldownDuration": "0r", "minimumLevels": { "healer": null, "wizard": 5, @@ -2236,10 +2074,7 @@ "value": "VE", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": 10, "wizard": null, @@ -2277,10 +2112,7 @@ "value": "Prb.", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": null, "wizard": 8, @@ -2318,10 +2150,7 @@ "value": "Prb.", "unit": "rounds" }, - "cooldownDuration": { - "value": "0", - "unit": "rounds" - }, + "cooldownDuration": "0r", "minimumLevels": { "healer": 7, "wizard": 5, @@ -2359,10 +2188,7 @@ "value": "VE x 2", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": null, "wizard": 2, @@ -2400,10 +2226,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "1", - "unit": "rounds" - }, + "cooldownDuration": "1r", "minimumLevels": { "healer": 10, "wizard": 7, @@ -2441,10 +2264,7 @@ "value": "VE", "unit": "minutes" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": 5, "wizard": 9, @@ -2482,10 +2302,7 @@ "value": "VE", "unit": "hours" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": 1, "wizard": null, @@ -2523,10 +2340,7 @@ "value": "Konzentration", "unit": "custom" }, - "cooldownDuration": { - "value": "W20", - "unit": "days" - }, + "cooldownDuration": "d20d", "minimumLevels": { "healer": 8, "wizard": 12, @@ -2564,10 +2378,7 @@ "value": "VE", "unit": "hours" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": null, "wizard": 9, @@ -2605,10 +2416,7 @@ "value": "Konzentration", "unit": "custom" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": 8, "wizard": 4, @@ -2646,10 +2454,7 @@ "value": "Konzentration", "unit": "custom" }, - "cooldownDuration": { - "value": "0", - "unit": "rounds" - }, + "cooldownDuration": "0r", "minimumLevels": { "healer": null, "wizard": 6, @@ -2687,10 +2492,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": 8, "wizard": 18, @@ -2728,10 +2530,7 @@ "value": "VE x 2", "unit": "rounds" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": null, "wizard": 10, @@ -2769,10 +2568,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": 10, "wizard": 6, @@ -2810,10 +2606,7 @@ "value": "VE x 2", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": 6, "wizard": 2, @@ -2851,10 +2644,7 @@ "value": "VE", "unit": "hours" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": 2, "wizard": null, @@ -2892,10 +2682,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "0", - "unit": "rounds" - }, + "cooldownDuration": "0r", "minimumLevels": { "healer": 3, "wizard": 7, @@ -2933,10 +2720,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": 4, "wizard": 8, @@ -2974,10 +2758,7 @@ "value": "Prb.", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": 1, "wizard": 6, @@ -3015,10 +2796,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "W20", - "unit": "days" - }, + "cooldownDuration": "d20d", "minimumLevels": { "healer": null, "wizard": null, @@ -3056,10 +2834,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "0", - "unit": "rounds" - }, + "cooldownDuration": "0r", "minimumLevels": { "healer": null, "wizard": 15, @@ -3097,10 +2872,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": null, "wizard": null, @@ -3138,10 +2910,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": 16, "wizard": 12, @@ -3179,10 +2948,7 @@ "value": "1", "unit": "rounds" }, - "cooldownDuration": { - "value": "0", - "unit": "rounds" - }, + "cooldownDuration": "0r", "minimumLevels": { "healer": 1, "wizard": 3, @@ -3220,10 +2986,7 @@ "value": "Prb.", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": 7, "wizard": 8, @@ -3261,10 +3024,7 @@ "value": "Prb.", "unit": "rounds" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": 1, "wizard": 1, @@ -3302,10 +3062,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": null, "wizard": null, @@ -3343,10 +3100,7 @@ "value": "Prb.", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": 4, "wizard": 8, @@ -3384,10 +3138,7 @@ "value": "VE", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": 2, "wizard": 6, @@ -3425,10 +3176,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": 10, "wizard": null, @@ -3466,10 +3214,7 @@ "value": "Bis Schloss geöffnet", "unit": "custom" }, - "cooldownDuration": { - "value": "5", - "unit": "rounds" - }, + "cooldownDuration": "5r", "minimumLevels": { "healer": 3, "wizard": 1, @@ -3507,10 +3252,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": 5, "wizard": 7, @@ -3548,10 +3290,7 @@ "value": "VE / 2", "unit": "hours" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": null, "wizard": 5, @@ -3589,10 +3328,7 @@ "value": "VE", "unit": "rounds" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": 7, "wizard": 3, @@ -3630,10 +3366,7 @@ "value": "1 Min & bis Distanz gefallen", "unit": "custom" }, - "cooldownDuration": { - "value": "0", - "unit": "rounds" - }, + "cooldownDuration": "0r", "minimumLevels": { "healer": 5, "wizard": 3, @@ -3671,10 +3404,7 @@ "value": "Prb.", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": null, "wizard": 4, @@ -3712,10 +3442,7 @@ "value": "bis zu VE / 2", "unit": "hours" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": null, "wizard": 5, @@ -3753,10 +3480,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "5", - "unit": "rounds" - }, + "cooldownDuration": "5r", "minimumLevels": { "healer": 16, "wizard": 10, @@ -3794,10 +3518,7 @@ "value": "VE", "unit": "hours" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": null, "wizard": 10, @@ -3835,10 +3556,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": 1, "wizard": 10, @@ -3876,10 +3594,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": null, "wizard": 12, @@ -3917,10 +3632,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": null, "wizard": 10, @@ -3958,10 +3670,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": 2, "wizard": 1, @@ -3999,10 +3708,7 @@ "value": "Prb.", "unit": "rounds" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": null, "wizard": 1, @@ -4040,10 +3746,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "0", - "unit": "rounds" - }, + "cooldownDuration": "0r", "minimumLevels": { "healer": null, "wizard": 1, @@ -4081,10 +3784,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": 2, "wizard": 7, @@ -4122,10 +3822,7 @@ "value": "VE / 2", "unit": "minutes" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": null, "wizard": 8, @@ -4163,10 +3860,7 @@ "value": "VE", "unit": "hours" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": 1, "wizard": 2, @@ -4204,10 +3898,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "1", - "unit": "rounds" - }, + "cooldownDuration": "1r", "minimumLevels": { "healer": 2, "wizard": 5, @@ -4245,10 +3936,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": null, "wizard": null, @@ -4286,10 +3974,7 @@ "value": "VE", "unit": "hours" }, - "cooldownDuration": { - "value": "0", - "unit": "rounds" - }, + "cooldownDuration": "0r", "minimumLevels": { "healer": 5, "wizard": 9, @@ -4327,10 +4012,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "1", - "unit": "rounds" - }, + "cooldownDuration": "1r", "minimumLevels": { "healer": null, "wizard": 20, @@ -4368,10 +4050,7 @@ "value": "Prb.", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": 10, "wizard": 12, @@ -4409,10 +4088,7 @@ "value": "Prb.", "unit": "rounds" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": 8, "wizard": 5, @@ -4450,10 +4126,7 @@ "value": "Prb x 2", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": 1, "wizard": null, @@ -4491,10 +4164,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "1", - "unit": "rounds" - }, + "cooldownDuration": "1r", "minimumLevels": { "healer": 5, "wizard": 1, @@ -4532,10 +4202,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": 10, "wizard": null, @@ -4573,10 +4240,7 @@ "value": "VE / 2", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": 12, "wizard": 10, @@ -4614,10 +4278,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": 4, "wizard": null, @@ -4655,10 +4316,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": null, "wizard": 20, @@ -4696,10 +4354,7 @@ "value": "VE Fragen, bzw. VE Minuten", "unit": "custom" }, - "cooldownDuration": { - "value": "W20", - "unit": "days" - }, + "cooldownDuration": "d20d", "minimumLevels": { "healer": null, "wizard": null, @@ -4737,10 +4392,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": 12, "wizard": 7, @@ -4778,10 +4430,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "0", - "unit": "rounds" - }, + "cooldownDuration": "0r", "minimumLevels": { "healer": null, "wizard": 6, @@ -4819,10 +4468,7 @@ "value": "Prb. x 5", "unit": "rounds" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": null, "wizard": 15, @@ -4860,10 +4506,7 @@ "value": "VE", "unit": "rounds" }, - "cooldownDuration": { - "value": "10", - "unit": "rounds" - }, + "cooldownDuration": "10r", "minimumLevels": { "healer": 3, "wizard": 8, @@ -4901,10 +4544,7 @@ "value": "Sofort", "unit": "custom" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": 10, "wizard": 5, @@ -4942,10 +4582,7 @@ "value": "Prb. / 2", "unit": "rounds" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": null, "wizard": 10, @@ -4983,10 +4620,7 @@ "value": "VE / 2", "unit": "rounds" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": null, "wizard": 12, @@ -5024,10 +4658,7 @@ "value": "Bis auformuliert", "unit": "custom" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": 8, "wizard": 6, @@ -5065,10 +4696,7 @@ "value": "VE x 2", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": 8, "wizard": 6, @@ -5106,10 +4734,7 @@ "value": "Prb. x 2", "unit": "rounds" }, - "cooldownDuration": { - "value": "100", - "unit": "rounds" - }, + "cooldownDuration": "100r", "minimumLevels": { "healer": null, "wizard": null, @@ -5147,10 +4772,7 @@ "value": "VE / 2", "unit": "rounds" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": null, "wizard": 10, @@ -5188,10 +4810,7 @@ "value": "VE x 2", "unit": "hours" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": null, "wizard": 17, @@ -5229,10 +4848,7 @@ "value": "Prb.", "unit": "rounds" }, - "cooldownDuration": { - "value": "24", - "unit": "hours" - }, + "cooldownDuration": "1d", "minimumLevels": { "healer": 8, "wizard": 8, @@ -5270,10 +4886,7 @@ "value": "Konzentration", "unit": "custom" }, - "cooldownDuration": { - "value": "W20", - "unit": "days" - }, + "cooldownDuration": "d20d", "minimumLevels": { "healer": 12, "wizard": null, diff --git a/spec/item/type-specific-helpers/spell.spec.ts b/spec/item/type-specific-helpers/spell.spec.ts index 9b520e5f..e454c959 100644 --- a/spec/item/type-specific-helpers/spell.spec.ts +++ b/spec/item/type-specific-helpers/spell.spec.ts @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: MIT -import { DS4SpellDataSourceData, TemporalUnit, UnitData } from "../../../src/item/item-data-source"; +import { CooldownDuration, DS4SpellDataSourceData } from "../../../src/item/item-data-source"; import { calculateSpellPrice } from "../../../src/item/type-specific-helpers/spell"; const defaultData: DS4SpellDataSourceData = { @@ -23,10 +23,7 @@ const defaultData: DS4SpellDataSourceData = { value: "", unit: "custom", }, - cooldownDuration: { - value: "", - unit: "rounds", - }, + cooldownDuration: "0r", minimumLevels: { healer: null, wizard: null, @@ -167,65 +164,41 @@ function buildCombinedTestCases(): CombinedTestCase[] { } describe("calculateSpellPrice", () => { - const cooldownDurations: (UnitData & { factor: number })[] = [ - { value: "", unit: "rounds", factor: 1 }, - { value: "foo", unit: "rounds", factor: 1 }, - { value: "0", unit: "rounds", factor: 1 }, - { value: "1", unit: "rounds", factor: 1 }, - { value: "17279", unit: "rounds", factor: 1 }, - { value: "17280", unit: "rounds", factor: 2 }, - { value: "34559", unit: "rounds", factor: 2 }, - { value: "34560", unit: "rounds", factor: 3 }, - - { value: "", unit: "minutes", factor: 1 }, - { value: "foo", unit: "minutes", factor: 1 }, - { value: "0", unit: "minutes", factor: 1 }, - { value: "1", unit: "minutes", factor: 1 }, - { value: "1439", unit: "minutes", factor: 1 }, - { value: "1440", unit: "minutes", factor: 2 }, - { value: "2879", unit: "minutes", factor: 2 }, - { value: "2880", unit: "minutes", factor: 3 }, - - { value: "", unit: "hours", factor: 1 }, - { value: "foo", unit: "hours", factor: 1 }, - { value: "0", unit: "hours", factor: 1 }, - { value: "1", unit: "hours", factor: 1 }, - { value: "23", unit: "hours", factor: 1 }, - { value: "24", unit: "hours", factor: 2 }, - { value: "47", unit: "hours", factor: 2 }, - { value: "48", unit: "hours", factor: 3 }, - - { value: "", unit: "days", factor: 3 }, - { value: "foo", unit: "days", factor: 3 }, - { value: "0", unit: "days", factor: 1 }, - { value: "1", unit: "days", factor: 2 }, - { value: "2", unit: "days", factor: 3 }, + const cooldownDurations: { cooldownDuration: CooldownDuration; factor: number }[] = [ + { cooldownDuration: "0r", factor: 1 }, + { cooldownDuration: "1r", factor: 1 }, + { cooldownDuration: "2r", factor: 1 }, + { cooldownDuration: "5r", factor: 1 }, + { cooldownDuration: "10r", factor: 1 }, + { cooldownDuration: "100r", factor: 1 }, + { cooldownDuration: "1d", factor: 2 }, + { cooldownDuration: "d20d", factor: 3 }, ]; - describe.each(cooldownDurations)("with cooldown duration set to $value $unit", ({ value, unit, factor }) => { - const dataWithCooldownDuration = { - ...defaultData, - cooldownDuration: { - value, - unit, - }, - }; + describe.each(cooldownDurations)( + "with cooldown duration set to $cooldownDuration", + ({ cooldownDuration, factor }) => { + const dataWithCooldownDuration = { + ...defaultData, + cooldownDuration, + }; - it.each(buildCombinedTestCases())( - `returns ${factor} × $expected if the minimum leves are $minimumLevels`, - ({ minimumLevels, expected }) => { - // given - const data: DS4SpellDataSourceData = { - ...dataWithCooldownDuration, - minimumLevels, - }; + it.each(buildCombinedTestCases())( + `returns ${factor} × $expected if the minimum leves are $minimumLevels`, + ({ minimumLevels, expected }) => { + // given + const data: DS4SpellDataSourceData = { + ...dataWithCooldownDuration, + minimumLevels, + }; - // when - const spellPrice = calculateSpellPrice(data); + // when + const spellPrice = calculateSpellPrice(data); - // then - expect(spellPrice).toBe(expected !== null ? expected * factor : expected); - }, - ); - }); + // then + expect(spellPrice).toBe(expected !== null ? expected * factor : expected); + }, + ); + }, + ); }); diff --git a/src/common/time-helpers.ts b/src/common/time-helpers.ts deleted file mode 100644 index fb32ae6f..00000000 --- a/src/common/time-helpers.ts +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-FileCopyrightText: 2021 Johannes Loher -// -// SPDX-License-Identifier: MIT - -export const secondsPerRound = 5; -export const secondsPerMinute = 60; -export const minutesPerHour = 60; -export const hoursPerDay = 24; diff --git a/src/config.ts b/src/config.ts index 2c79cf54..731744d8 100644 --- a/src/config.ts +++ b/src/config.ts @@ -106,6 +106,17 @@ const i18nKeys = { unset: "DS4.SpellCategoryUnset", }, + cooldownDurations: { + "0r": "DS4.CooldownDuration0R", + "1r": "DS4.CooldownDuration1R", + "2r": "DS4.CooldownDuration2R", + "5r": "DS4.CooldownDuration5R", + "10r": "DS4.CooldownDuration10R", + "100r": "DS4.CooldownDuration100R", + "1d": "DS4.CooldownDuration1D", + d20d: "DS4.CooldownDurationD20D", + }, + /** * Define the set of actor types */ @@ -276,16 +287,6 @@ const i18nKeys = { minutes: "DS4.UnitMinutes", hours: "DS4.UnitHours", days: "DS4.UnitDays", - }, - - /** - * Define translations for available duration units including "custom" - */ - customTemporalUnits: { - rounds: "DS4.UnitRounds", - minutes: "DS4.UnitMinutes", - hours: "DS4.UnitHours", - days: "DS4.UnitDays", custom: "DS4.UnitCustom", }, @@ -297,16 +298,6 @@ const i18nKeys = { minutes: "DS4.UnitMinutesAbbr", hours: "DS4.UnitHoursAbbr", days: "DS4.UnitDaysAbbr", - }, - - /** - * Define abbreviations for available duration units including "custom" - */ - customTemporalUnitsAbbr: { - rounds: "DS4.UnitRoundsAbbr", - minutes: "DS4.UnitMinutesAbbr", - hours: "DS4.UnitHoursAbbr", - days: "DS4.UnitDaysAbbr", custom: "DS4.UnitCustomAbbr", }, diff --git a/src/hooks/setup.ts b/src/hooks/setup.ts index d9105954..0a548f2c 100644 --- a/src/hooks/setup.ts +++ b/src/hooks/setup.ts @@ -18,7 +18,14 @@ export default function registerForSetupHooks(): void { * Localizes all objects in {@link DS4.i18n} and sorts them unless they are explicitly excluded. */ function localizeAndSortConfigObjects() { - const noSort = ["attributes", "traits", "combatValues", "creatureSizeCategories"]; + const noSort = [ + "attributes", + "combatValues", + "cooldownDurations", + "creatureSizeCategories", + "spellCategories", + "traits", + ]; const localizeObject = (obj: T, sort = true): T => { const localized = Object.entries(obj).map(([key, value]): [string, string] => { diff --git a/src/item/item-data-source.ts b/src/item/item-data-source.ts index dc7f4c4c..f75dafa5 100644 --- a/src/item/item-data-source.ts +++ b/src/item/item-data-source.ts @@ -136,14 +136,16 @@ export interface DS4ShieldDataSourceData DS4ItemDataSourceDataEquipable, DS4ItemDataSourceDataProtective {} +export type CooldownDuration = keyof typeof DS4.i18n.cooldownDurations; + export interface DS4SpellDataSourceData extends DS4ItemDataSourceDataBase, DS4ItemDataSourceDataEquipable { spellType: keyof typeof DS4.i18n.spellTypes; bonus: string; spellCategory: keyof typeof DS4.i18n.spellCategories; maxDistance: UnitData; effectRadius: UnitData; - duration: UnitData; - cooldownDuration: UnitData; + duration: UnitData; + cooldownDuration: CooldownDuration; minimumLevels: { healer: number | null; wizard: number | null; @@ -158,9 +160,7 @@ export interface UnitData { type DistanceUnit = keyof typeof DS4.i18n.distanceUnits; -type CustomTemporalUnit = keyof typeof DS4.i18n.customTemporalUnits; - -export type TemporalUnit = keyof typeof DS4.i18n.temporalUnits; +type TemporalUnit = keyof typeof DS4.i18n.temporalUnits; export interface DS4EquipmentDataSourceData extends DS4ItemDataSourceDataBase, diff --git a/src/item/item.ts b/src/item/item.ts index 822a68e7..ed875897 100644 --- a/src/item/item.ts +++ b/src/item/item.ts @@ -148,17 +148,17 @@ export class DS4Item extends Item { } const ownerDataData = this.actor.data.data; - const spellBonus = Number.isNumeric(this.data.data.bonus) ? parseInt(this.data.data.bonus) : undefined; - if (spellBonus === undefined) { + const spellModifier = Number.isNumeric(this.data.data.bonus) ? parseInt(this.data.data.bonus) : undefined; + if (spellModifier === undefined) { notifications.info( - getGame().i18n.format("DS4.InfoManuallyEnterSpellBonus", { + getGame().i18n.format("DS4.InfoManuallyEnterSpellModifier", { name: this.name, - spellBonus: this.data.data.bonus, + spellModifier: this.data.data.bonus, }), ); } const spellType = this.data.data.spellType; - const checkTargetNumber = ownerDataData.combatValues[spellType].total + (spellBonus ?? 0); + const checkTargetNumber = ownerDataData.combatValues[spellType].total + (spellModifier ?? 0); const speaker = ChatMessage.getSpeaker({ actor: this.actor, ...options.speaker }); await createCheckRoll(checkTargetNumber, { diff --git a/src/item/type-specific-helpers/spell.ts b/src/item/type-specific-helpers/spell.ts index 5af27f20..c9949996 100644 --- a/src/item/type-specific-helpers/spell.ts +++ b/src/item/type-specific-helpers/spell.ts @@ -2,8 +2,7 @@ // // SPDX-License-Identifier: MIT -import { hoursPerDay, minutesPerHour, secondsPerMinute, secondsPerRound } from "../../common/time-helpers"; -import { DS4SpellDataSourceData, TemporalUnit, UnitData } from "../item-data-source"; +import { CooldownDuration, DS4SpellDataSourceData } from "../item-data-source"; export function calculateSpellPrice(data: DS4SpellDataSourceData): number | null { const spellPriceFactor = calculateSpellPriceFactor(data.cooldownDuration); @@ -16,39 +15,18 @@ export function calculateSpellPrice(data: DS4SpellDataSourceData): number | null return baseSpellPrice === Infinity ? null : baseSpellPrice * spellPriceFactor; } -function calculateSpellPriceFactor(temporalData: UnitData): number { - let days: number; - if (Number.isNumeric(temporalData.value)) { - const value = Number.fromString(temporalData.value); - switch (temporalData.unit) { - case "days": { - days = value; - break; - } - case "hours": { - days = value / hoursPerDay; - break; - } - case "minutes": { - days = value / (hoursPerDay * minutesPerHour); - break; - } - case "rounds": { - days = (value * secondsPerRound) / (hoursPerDay * minutesPerHour * secondsPerMinute); - break; - } - } - } else { - switch (temporalData.unit) { - case "days": { - days = 2; - break; - } - default: { - days = 0; - break; - } - } +function calculateSpellPriceFactor(cooldownDuration: CooldownDuration): number { + switch (cooldownDuration) { + case "0r": + case "1r": + case "2r": + case "5r": + case "10r": + case "100r": + return 1; + case "1d": + return 2; + case "d20d": + return 3; } - return Math.clamped(Math.floor(days), 0, 2) + 1; } diff --git a/src/migrations.ts b/src/migrations.ts index 63d97697..4731e803 100644 --- a/src/migrations.ts +++ b/src/migrations.ts @@ -4,10 +4,11 @@ import { getGame } from "./helpers"; import logger from "./logger"; -import { migrate as migrate001 } from "./migrations/001"; -import { migrate as migrate002 } from "./migrations/002"; -import { migrate as migrate003 } from "./migrations/003"; -import { migrate as migrate004 } from "./migrations/004"; +import { migration as migration001 } from "./migrations/001"; +import { migration as migration002 } from "./migrations/002"; +import { migration as migration003 } from "./migrations/003"; +import { migration as migration004 } from "./migrations/004"; +import { migration as migration005 } from "./migrations/005"; import notifications from "./ui/notifications"; async function migrate(): Promise { @@ -43,11 +44,11 @@ async function migrateFromTo(oldMigrationVersion: number, targetMigrationVersion { permanent: true }, ); - for (const [i, migration] of migrationsToExecute.entries()) { + for (const [i, { migrate }] of migrationsToExecute.entries()) { const currentMigrationVersion = oldMigrationVersion + i + 1; logger.info("executing migration script ", currentMigrationVersion); try { - await migration(); + await migrate(); getGame().settings.set("ds4", "systemMigrationVersion", currentMigrationVersion); } catch (err) { notifications.error( @@ -73,18 +74,76 @@ async function migrateFromTo(oldMigrationVersion: number, targetMigrationVersion } } +async function migrateCompendiumFromTo( + pack: CompendiumCollection, + oldMigrationVersion: number, + targetMigrationVersion: number, +): Promise { + if (!getGame().user?.isGM) { + return; + } + + const migrationsToExecute = migrations.slice(oldMigrationVersion, targetMigrationVersion); + + if (migrationsToExecute.length > 0) { + notifications.info( + getGame().i18n.format("DS4.InfoCompendiumMigrationStart", { + pack: pack.title, + currentVersion: oldMigrationVersion, + targetVersion: targetMigrationVersion, + }), + { permanent: true }, + ); + + for (const [i, { migrateCompendium }] of migrationsToExecute.entries()) { + const currentMigrationVersion = oldMigrationVersion + i + 1; + logger.info("executing compendium migration ", currentMigrationVersion); + try { + await migrateCompendium(pack); + } catch (err) { + notifications.error( + getGame().i18n.format("DS4.ErrorDuringCompendiumMigration", { + pack: pack.title, + currentVersion: oldMigrationVersion, + targetVersion: targetMigrationVersion, + migrationVersion: currentMigrationVersion, + }), + { permanent: true }, + ); + logger.error("Failed ds4 compendium migration:", err); + return; + } + } + + notifications.info( + getGame().i18n.format("DS4.InfoCompendiumMigrationCompleted", { + pack: pack.title, + currentVersion: oldMigrationVersion, + targetVersion: targetMigrationVersion, + }), + { permanent: true }, + ); + } +} + function getTargetMigrationVersion(): number { return migrations.length; } -const migrations: Array<() => Promise> = [migrate001, migrate002, migrate003, migrate004]; +interface Migration { + migrate: () => Promise; + migrateCompendium: (pack: CompendiumCollection) => Promise; +} + +const migrations: Migration[] = [migration001, migration002, migration003, migration004, migration005]; function isFirstWorldStart(migrationVersion: number): boolean { return migrationVersion < 0; } export const migration = { - migrate: migrate, - migrateFromTo: migrateFromTo, - getTargetMigrationVersion: getTargetMigrationVersion, + migrate, + migrateFromTo, + getTargetMigrationVersion, + migrateCompendiumFromTo, }; diff --git a/src/migrations/001.ts b/src/migrations/001.ts index c8e2f7b3..c01252fa 100644 --- a/src/migrations/001.ts +++ b/src/migrations/001.ts @@ -10,7 +10,7 @@ import { migrateScenes, } from "./migrationHelpers"; -export async function migrate(): Promise { +async function migrate(): Promise { await migrateActors(getActorUpdateData); await migrateScenes(getSceneUpdateData); await migrateCompendiums(migrateCompendium); @@ -39,3 +39,8 @@ function getActorUpdateData(): Record { const getSceneUpdateData = getSceneUpdateDataGetter(getActorUpdateData); const migrateCompendium = getCompendiumMigrator({ getActorUpdateData, getSceneUpdateData }); + +export const migration = { + migrate, + migrateCompendium, +}; diff --git a/src/migrations/002.ts b/src/migrations/002.ts index 93ac4063..0c1ccb53 100644 --- a/src/migrations/002.ts +++ b/src/migrations/002.ts @@ -12,7 +12,7 @@ import { migrateScenes, } from "./migrationHelpers"; -export async function migrate(): Promise { +async function migrate(): Promise { await migrateItems(getItemUpdateData); await migrateActors(getActorUpdateData); await migrateScenes(getSceneUpdateData); @@ -32,3 +32,8 @@ const migrateCompendium = getCompendiumMigrator( { getItemUpdateData, getActorUpdateData, getSceneUpdateData }, { migrateToTemplateEarly: false }, ); + +export const migration = { + migrate, + migrateCompendium, +}; diff --git a/src/migrations/003.ts b/src/migrations/003.ts index 1ebc46f8..a2870ad5 100644 --- a/src/migrations/003.ts +++ b/src/migrations/003.ts @@ -12,7 +12,7 @@ import { migrateScenes, } from "./migrationHelpers"; -export async function migrate(): Promise { +async function migrate(): Promise { await migrateItems(getItemUpdateData); await migrateActors(getActorUpdateData); await migrateScenes(getSceneUpdateData); @@ -34,3 +34,8 @@ const migrateCompendium = getCompendiumMigrator( { getItemUpdateData, getActorUpdateData }, { migrateToTemplateEarly: false }, ); + +export const migration = { + migrate, + migrateCompendium, +}; diff --git a/src/migrations/004.ts b/src/migrations/004.ts index 97f3d155..e0483376 100644 --- a/src/migrations/004.ts +++ b/src/migrations/004.ts @@ -12,7 +12,7 @@ import { migrateScenes, } from "./migrationHelpers"; -export async function migrate(): Promise { +async function migrate(): Promise { await migrateItems(getItemUpdateData); await migrateActors(getActorUpdateData); await migrateScenes(getSceneUpdateData); @@ -21,6 +21,7 @@ export async function migrate(): Promise { function getItemUpdateData(itemData: Partial) { if (itemData.type !== "spell") return; + // @ts-expect-error the type of cooldownDuration was UnitData at the point for this migration, but it changed later on const cooldownDurationUnit: string | undefined = itemData.data?.cooldownDuration.unit; const updateData: Record = { @@ -38,3 +39,8 @@ function getItemUpdateData(itemData: Partial) const getActorUpdateData = getActorUpdateDataGetter(getItemUpdateData); const getSceneUpdateData = getSceneUpdateDataGetter(getActorUpdateData); const migrateCompendium = getCompendiumMigrator({ getItemUpdateData, getActorUpdateData, getSceneUpdateData }); + +export const migration = { + migrate, + migrateCompendium, +}; diff --git a/src/migrations/005.ts b/src/migrations/005.ts new file mode 100644 index 00000000..80d0fc8f --- /dev/null +++ b/src/migrations/005.ts @@ -0,0 +1,119 @@ +// SPDX-FileCopyrightText: 2021 Johannes Loher +// +// SPDX-License-Identifier: MIT + +import { CooldownDuration } from "../item/item-data-source"; +import { + getActorUpdateDataGetter, + getCompendiumMigrator, + getSceneUpdateDataGetter, + migrateActors, + migrateCompendiums, + migrateItems, + migrateScenes, +} from "./migrationHelpers"; + +const secondsPerRound = 5; +const secondsPerMinute = 60; +const roundsPerMinute = secondsPerMinute / secondsPerRound; +const minutesPerHour = 60; +const roundsPerHour = minutesPerHour / roundsPerMinute; +const hoursPerDay = 24; +const roundsPerDay = hoursPerDay / roundsPerHour; +const secondsPerDay = secondsPerMinute * minutesPerHour * hoursPerDay; + +async function migrate(): Promise { + await migrateItems(getItemUpdateData); + await migrateActors(getActorUpdateData); + await migrateScenes(getSceneUpdateData); + await migrateCompendiums(migrateCompendium); +} + +function getItemUpdateData(itemData: Partial) { + if (itemData.type !== "spell") return; + // @ts-expect-error the type of cooldownDuration is changed from UnitData to CooldownDuation with this migration + const cooldownDurationUnit: string | undefined = itemData.data?.cooldownDuration.unit; + // @ts-expect-error the type of cooldownDuration is changed from UnitData to CooldownDuation with this migration + const cooldownDurationValue: string | undefined = itemData.data?.cooldownDuration.value; + const cooldownDuration = migrateCooldownDuration(cooldownDurationValue, cooldownDurationUnit); + + const updateData: Record = { + data: { + cooldownDuration, + }, + }; + return updateData; +} + +function migrateCooldownDuration(cooldownDurationValue?: string, cooldownDurationUnit?: string) { + if (Number.isNumeric(cooldownDurationValue)) { + const value = Number.fromString(cooldownDurationValue!); + const rounds = getRounds(cooldownDurationUnit ?? "", value); + + if (rounds * secondsPerRound > secondsPerDay) { + return "d20d"; + } else if (rounds > 100) { + return "1d"; + } else if (rounds > 10) { + return "100r"; + } else if (rounds > 5) { + return "10r"; + } else if (rounds > 2) { + return "5r"; + } else if (rounds > 1) { + return "2r"; + } else if (rounds > 0) { + return "1r"; + } else { + return "0r"; + } + } else { + // if the value is not numeric, we can only make a best guess + switch (cooldownDurationUnit) { + case "rounds": { + return "10r"; + } + case "minutes": { + return "100r"; + } + case "hours": { + return "1d"; + } + case "days": { + return "d20d"; + } + default: { + return "0r"; + } + } + } +} + +function getRounds(unit: string, value: number): number { + switch (unit) { + case "rounds": { + return value; + } + case "minutes": { + return value * roundsPerMinute; + } + case "hours": { + return value * roundsPerHour; + } + case "days": { + return value * roundsPerDay; + } + default: { + return 0; + } + } +} + +const getActorUpdateData = getActorUpdateDataGetter(getItemUpdateData); +const getSceneUpdateData = getSceneUpdateDataGetter(getActorUpdateData); +const migrateCompendium = getCompendiumMigrator({ getItemUpdateData, getActorUpdateData, getSceneUpdateData }); + +export const migration = { + migrate, + migrateCompendium, +}; diff --git a/template.json b/template.json index b7378316..d4ec6bc3 100644 --- a/template.json +++ b/template.json @@ -187,10 +187,7 @@ "value": "", "unit": "custom" }, - "cooldownDuration": { - "value": "", - "unit": "rounds" - }, + "cooldownDuration": "0r", "minimumLevels": { "healer": null, "wizard": null, diff --git a/templates/sheets/actor/tabs/spells.hbs b/templates/sheets/actor/tabs/spells.hbs index 54ce2a0d..3f0df03c 100644 --- a/templates/sheets/actor/tabs/spells.hbs +++ b/templates/sheets/actor/tabs/spells.hbs @@ -25,7 +25,7 @@ SPDX-License-Identifier: MIT {{/inline}} {{!-- -!-- Three templates based on the "unit" template for displaying values with unit. +!-- Two templates based on the "unit" template for displaying values with unit. !-- Both accept a `config` object holding the unitNames and unitAbbr instead of !-- directly handing over the latter two. !-- @param titleKey: The key of the localized title to use. @@ -35,11 +35,6 @@ SPDX-License-Identifier: MIT titleKey=titleKey}} {{/inline}} -{{#*inline "customTemporalUnit"}} -{{> unit unitNames=config.i18n.customTemporalUnits unitAbbrs=config.i18n.customTemporalUnitsAbbr unitDatum=unitDatum -titleKey=titleKey}} -{{/inline}} - {{#*inline "distanceUnit"}} {{> unit unitNames=config.i18n.distanceUnits unitAbbrs=config.i18n.distanceUnitsAbbr unitDatum=unitDatum titleKey=titleKey}} @@ -60,16 +55,16 @@ titleKey=titleKey}} {{!-- spell bonus --}}
{{localize 'DS4.SpellBonusAbbr'}}
+ title="{{localize 'DS4.SortBySpellModifier'}}">{{localize 'DS4.SpellModifierAbbr'}} {{!-- max. distance --}} -
+
{{!-- duration --}}
{{!-- cooldown duration --}} -
+
{{/systems/ds4/templates/sheets/actor/components/item-list-header.hbs}} {{#each itemsByType.spell as |itemData id|}} @@ -77,23 +72,24 @@ titleKey=titleKey}} hideDescription=true}} {{!-- spell type --}} + src="{{lookup @root/config.icons.spellTypes itemData.data.spellType}}" + title="{{lookup @root/config.i18n.spellTypes itemData.data.spellType}}" /> {{!-- spell bonus --}} + data-property="data.bonus" value="{{itemData.data.bonus}}" title="{{localize 'DS4.SpellModifier'}}" /> {{!-- max. distance --}} - {{> distanceUnit titleKey='DS4.SpellMaxDistance' unitDatum=itemData.data.maxDistance - config=../../config}} + {{> distanceUnit titleKey='DS4.SpellDistance' unitDatum=itemData.data.maxDistance + config=@root/config}} {{!-- duration --}} - {{> customTemporalUnit titleKey='DS4.SpellDuration' unitDatum=itemData.data.duration config=../../config}} + {{> temporalUnit titleKey='DS4.SpellDuration' unitDatum=itemData.data.duration config=@root/config}} {{!-- cooldown duration --}} - {{> temporalUnit titleKey='DS4.SpellCooldownDuration' unitDatum=itemData.data.cooldownDuration - config=../../config}} +
{{lookup @root/config.i18n.cooldownDurations + itemData.data.cooldownDuration}}
+ {{/systems/ds4/templates/sheets/actor/components/item-list-entry.hbs}} {{/each}} diff --git a/templates/sheets/item/components/properties/spell.hbs b/templates/sheets/item/components/properties/spell.hbs index ea788cd9..eb48d9f2 100644 --- a/templates/sheets/item/components/properties/spell.hbs +++ b/templates/sheets/item/components/properties/spell.hbs @@ -7,12 +7,16 @@ SPDX-License-Identifier: MIT

{{localize 'DS4.ItemPropertiesSpell'}}

- - + +
+ +
- +
{{#select data.data.spellCategory}} @@ -36,7 +41,7 @@ SPDX-License-Identifier: MIT
- +
@@ -50,7 +55,7 @@ SPDX-License-Identifier: MIT
- +
@@ -64,25 +69,11 @@ SPDX-License-Identifier: MIT
- +
-
-
-
- -
- -
+
+ +
+ +
+
- +
- - {{data.data.price}} + +
+ {{data.data.price}} +