From 40030606992b29b8c3345f83458ecd11c61fdc5d Mon Sep 17 00:00:00 2001 From: xziino Date: Thu, 28 May 2026 12:53:58 +0200 Subject: [PATCH] Analyse+Planer: Phys/Mag-DR fix (Feint/Addle) + Plenary Indulgence (WHM) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ffxiv-data.js: abilityDr() für typabhängige DR — Feint 10% phys/5% mag, Addle 10% mag/5% phys - analysis.js + planner.js: abilityDr() in simulateDrMultiplier() und Debuff-Tooltip - analysis.php: Plenary Indulgence (statusId 1001219 "Confession", 10% DR, WHM) - ffxiv-data.js: Plenary Indulgence in JOB_ABILITIES/ABILITY_DR/MITIG_ICONS - Action.json: Eintrag 7433 (recast 600 = 60s) für Gantt-Diagramm - Icon: plenary-indulgence.png von XIVAPI - cache.php: v11 Co-Authored-By: Claude Sonnet 4.6 --- api/analysis.php | 1 + api/cache.php | 2 +- assets/icons/mitigation/plenary-indulgence.png | Bin 0 -> 5258 bytes assets/jsons/Action.json | 12 ++++++++++++ js/analysis.js | 5 +++-- js/ffxiv-data.js | 13 ++++++++++++- js/planner.js | 3 ++- 7 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 assets/icons/mitigation/plenary-indulgence.png diff --git a/api/analysis.php b/api/analysis.php index 61f86ac..ef81a15 100644 --- a/api/analysis.php +++ b/api/analysis.php @@ -88,6 +88,7 @@ const MITIGATION_ABILITIES = [ 'Dark Missionary' => ['dr' => 10, 'buffType' => 'buff', 'statusId' => 1001894, 'extraAbilityGameID' => 16471], 'Heart of Light' => ['dr' => 10, 'buffType' => 'buff', 'statusId' => 1001839, 'extraAbilityGameID' => 16160], 'Temperance' => ['dr' => 10, 'buffType' => 'buff', 'statusId' => 1001873, 'extraAbilityGameID' => 16536], + 'Plenary Indulgence' => ['dr' => 10, 'buffType' => 'buff', 'statusId' => 1001219, 'extraAbilityGameID' => 7433], // FFLogs: "Confession" 'Aquaveil' => ['dr' => 15, 'buffType' => 'buff', 'statusId' => 1002708, 'extraAbilityGameID' => 25861], // Personal, WHM auf Ziel 'Sacred Soil' => ['dr' => 10, 'buffType' => 'buff', 'statusId' => 1001944, 'extraAbilityGameID' => 188], 'Expedient' => ['dr' => 10, 'buffType' => 'buff', 'statusId' => 1002711, 'extraAbilityGameID' => 25868], // FFLogs: "Desperate Measures" diff --git a/api/cache.php b/api/cache.php index b06f825..d39879d 100644 --- a/api/cache.php +++ b/api/cache.php @@ -2,7 +2,7 @@ declare(strict_types=1); const CACHED_LOG_DIR = __DIR__ . '/../cached_logs'; -const CACHED_LOG_VERSION = 'v9'; +const CACHED_LOG_VERSION = 'v11'; function cache_language(string $language): string { $language = strtolower(trim($language)); diff --git a/assets/icons/mitigation/plenary-indulgence.png b/assets/icons/mitigation/plenary-indulgence.png new file mode 100644 index 0000000000000000000000000000000000000000..3aac192f371d986c0d845580438644763bcb3920 GIT binary patch literal 5258 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 OlYc$?n}J_ffAN3tEh0Mr literal 0 HcmV?d00001 diff --git a/assets/jsons/Action.json b/assets/jsons/Action.json index ddb34e8..0e85458 100644 --- a/assets/jsons/Action.json +++ b/assets/jsons/Action.json @@ -419,6 +419,18 @@ "icon": "https://xivapi.com/i/003000/003087_hr1.png", "shield": null }, + "7433": { + "cast": 0, + "recast": 600, + "names": { + "en": "Plenary Indulgence", + "de": "Vollkommener Ablass", + "fr": "Indulgence plénière", + "jp": "インドゥルゲンティア" + }, + "icon": null, + "shield": null + }, "16536": { "cast": 0, "recast": 1200, diff --git a/js/analysis.js b/js/analysis.js index 5b895dc..0f545e3 100644 --- a/js/analysis.js +++ b/js/analysis.js @@ -1,5 +1,5 @@ (function () { - const { MITIG_ICONS, JOB_ABBR, ABILITY_JOBS, JOB_ROLE, abilityTypeIsPhysical, abilityTypeIsMagical } = window.FF14_DATA; + const { MITIG_ICONS, JOB_ABBR, ABILITY_JOBS, JOB_ROLE, abilityTypeIsPhysical, abilityTypeIsMagical, abilityDr } = window.FF14_DATA; function dmgTypeBadge(abilityType) { if (abilityType == null) return ''; @@ -612,7 +612,8 @@ ].map(m => { const iconSrc = mitigationIcon(m); if (!iconSrc) return ''; - const dr = m.dr > 0 ? ` −${m.dr}%` : ''; + const drPct = Math.round(abilityDr(m.name, ev.abilityType) * 100) || m.dr || 0; + const dr = drPct > 0 ? ` −${drPct}%` : ''; const jobAbbr = m.sourcePlayerType ? (JOB_ABBR[m.sourcePlayerType] ?? '') : ''; const label = jobAbbr ? `${jobAbbr} · ${m.name}` : m.name; return m.missing diff --git a/js/ffxiv-data.js b/js/ffxiv-data.js index 3f43a77..15f1cea 100644 --- a/js/ffxiv-data.js +++ b/js/ffxiv-data.js @@ -10,6 +10,13 @@ function abilityTypeIsPhysical(type) { return (parseInt(type) & ABILITY_TYPE_PHYSICAL) !== 0; } function abilityTypeIsMagical(type) { return (parseInt(type) & ABILITY_TYPE_MAGICAL) !== 0; } + // Type-aware DR: Feint 10% phys / 5% mag, Addle 10% mag / 5% phys + function abilityDr(abilityName, abilityType) { + if (abilityName === 'Feint') return abilityTypeIsPhysical(abilityType) ? 0.10 : 0.05; + if (abilityName === 'Addle') return abilityTypeIsMagical(abilityType) ? 0.10 : 0.05; + return ABILITY_DR[abilityName] ?? 0; + } + const JOB_FROM_TYPE = { 'Paladin': 'PLD', 'Warrior': 'WAR', 'DarkKnight': 'DRK', 'Gunbreaker': 'GNB', 'WhiteMage': 'WHM', 'Scholar': 'SCH', 'Astrologian': 'AST', 'Sage': 'SGE', @@ -89,6 +96,7 @@ ], 'WHM': [ { name: 'Temperance', buffType: 'buff' }, + { name: 'Plenary Indulgence', buffType: 'buff', extraAbilityGameID: 7433, duration: 10 }, { name: 'Aquaveil', buffType: 'buff', extraAbilityGameID: 25861, duration: 8 }, // Personal, WHM auf Ziel { name: 'Divine Benison', buffType: 'shield', extraAbilityGameID: 7432, duration: 15 }, { name: 'Divine Caress', buffType: 'shield' }, @@ -177,7 +185,7 @@ 'Heart of Light': 'GNB', 'Superbolide': 'GNB', 'Nebula': 'GNB', 'Great Nebula': 'GNB', 'Camouflage': 'GNB', 'Heart of Stone': 'GNB', 'Heart of Corundum': 'GNB', 'Clarity of Corundum': 'GNB', - 'Temperance': 'WHM', 'Aquaveil': 'WHM', 'Divine Benison': 'WHM', 'Divine Caress': 'WHM', + 'Temperance': 'WHM', 'Plenary Indulgence': 'WHM', 'Aquaveil': 'WHM', 'Divine Benison': 'WHM', 'Divine Caress': 'WHM', 'Sacred Soil': 'SCH', 'Expedient': 'SCH', 'Fey Illumination': 'SCH', 'Galvanize': 'SCH', 'Seraphic Veil': 'SCH', 'Catalyze': 'SCH', 'Collective Unconscious': 'AST', 'Exaltation': 'AST', 'Neutral Sect': 'AST', @@ -204,6 +212,7 @@ 'Dark Missionary': 'assets/icons/mitigation/dark-missionary.png', 'Heart of Light': 'assets/icons/mitigation/heart-of-light.png', 'Temperance': 'assets/icons/mitigation/temperance.png', + 'Plenary Indulgence': 'assets/icons/mitigation/plenary-indulgence.png', 'Sacred Soil': 'assets/icons/mitigation/sacred-soil.png', 'Expedient': 'assets/icons/mitigation/expedient.png', 'Fey Illumination': 'assets/icons/mitigation/fey-illumination.png', @@ -258,6 +267,7 @@ 'Dark Missionary': 0.10, 'Heart of Light': 0.10, 'Temperance': 0.10, + 'Plenary Indulgence': 0.10, 'Sacred Soil': 0.10, 'Expedient': 0.10, 'Collective Unconscious': 0.10, @@ -323,5 +333,6 @@ ABILITY_TYPE_MAGICAL, abilityTypeIsPhysical, abilityTypeIsMagical, + abilityDr, }; })(); diff --git a/js/planner.js b/js/planner.js index 91cda55..78df6ee 100644 --- a/js/planner.js +++ b/js/planner.js @@ -651,7 +651,7 @@ function simulateDrMultiplier(mechanic, assignments = mechanic.assignments ?? [] if (a.buffType === 'shield') continue; // Persönliche Mitigation nur bei Tankbustern einrechnen if (!isTankbuster && TIMELINE_PERSONAL_ABILITIES.has(a.ability)) continue; - mult *= (1 - (ABILITY_DR[a.ability] ?? 0)); + mult *= (1 - abilityDr(a.ability, mechanic.abilityType)); } return mult; } @@ -2340,6 +2340,7 @@ const { TANK_JOBS, abilityTypeIsPhysical, abilityTypeIsMagical, + abilityDr, } = window.FF14_DATA; function dmgTypeBadge(abilityType) {