Event Explorer: masterData.abilities.type + ABILITY_TYPE_PHYSICAL/MAGICAL Konstanten

- debug-events.php: masterData { abilities { gameID name type } } mitabfragen,
  Ergebnis als ability_meta-Tabelle + _ability-Feld pro Event im Output
- ffxiv-data.js: ABILITY_TYPE_PHYSICAL (128) / ABILITY_TYPE_MAGICAL (1024)
  als verifizierte Bitmask-Konstanten + abilityTypeIsPhysical/abilityTypeIsMagical
  Hilfsfunktionen -- Grundlage fuer dynamische Feint/Addle DR-Berechnung

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
xziino 2026-05-25 12:39:36 +02:00
parent fce55c5bb6
commit 89d1ac0df1
2 changed files with 44 additions and 12 deletions

View File

@ -87,13 +87,20 @@ if ($playerName !== '') {
}
}
// Fetch events
// Fetch events + masterData abilities (incl. type)
$includeResources = in_array($dataType, ['DamageTaken', 'DamageDone']) ? 'includeResources: true,' : '';
$result = dbg_gql(<<<GQL
{
reportData {
report(code: "$reportCode") {
masterData(translate: false) {
abilities {
gameID
name
type
}
}
events(
fightIDs: [$fightId],
dataType: $dataType,
@ -111,7 +118,14 @@ GQL);
$events = $result['data']['reportData']['report']['events']['data'] ?? [];
// Build abilityGameID → { name, type } lookup
$abilityMeta = [];
foreach ($result['data']['reportData']['report']['masterData']['abilities'] ?? [] as $ab) {
$abilityMeta[(int)$ab['gameID']] = ['name' => $ab['name'], 'type' => $ab['type'] ?? null];
}
// Filter by raw event type, player (source OR target), then apply limit
// Enrich each event with ability meta (name + type) from masterData
$filtered = [];
foreach ($events as $ev) {
if ($eventType !== '' && ($ev['type'] ?? '') !== $eventType) continue;
@ -121,6 +135,11 @@ foreach ($events as $ev) {
$tgtId = (int)($ev['targetID'] ?? -1);
if (!in_array($srcId, $playerIds) && !in_array($tgtId, $playerIds)) continue;
}
// Inject ability meta so ability.type is visible directly on the event
$gid = (int)($ev['abilityGameID'] ?? 0);
if ($gid && isset($abilityMeta[$gid])) {
$ev['_ability'] = $abilityMeta[$gid];
}
$filtered[] = $ev;
if (count($filtered) >= $limit) break;
}
@ -131,11 +150,9 @@ echo json_encode([
'ability_id' => $abilityId ?: null,
'player_name' => $playerName ?: null,
'player_ids' => $playerIds ?: null,
'time_range' => [
'from_ms' => (int)$queryStart,
'to_ms' => (int)$queryEnd,
],
'time_range' => ['from_ms' => (int)$queryStart, 'to_ms' => (int)$queryEnd],
'total_before_limit' => count($events),
'count' => count($filtered),
'ability_meta' => $abilityMeta, // vollständige Lookup-Tabelle: gameID → {name, type}
'events' => $filtered,
], JSON_PRETTY_PRINT);

View File

@ -1,4 +1,15 @@
(function () {
// FFLogs ability type bitmask values for FFXIV
// Verified via XIVAPI AttackType cross-reference:
// 128 = Physical (all subtypes: Slashing/Piercing/Blunt/Shot)
// 1024 = Magical
// Used for Feint/Addle DR calculation (Feint: 10% phys / 5% mag, Addle: 10% mag / 5% phys)
const ABILITY_TYPE_PHYSICAL = 128;
const ABILITY_TYPE_MAGICAL = 1024;
function abilityTypeIsPhysical(type) { return (parseInt(type) & ABILITY_TYPE_PHYSICAL) !== 0; }
function abilityTypeIsMagical(type) { return (parseInt(type) & ABILITY_TYPE_MAGICAL) !== 0; }
const JOB_FROM_TYPE = {
'Paladin': 'PLD', 'Warrior': 'WAR', 'DarkKnight': 'DRK', 'Gunbreaker': 'GNB',
'WhiteMage': 'WHM', 'Scholar': 'SCH', 'Astrologian': 'AST', 'Sage': 'SGE',
@ -308,5 +319,9 @@
TANK_JOBS: new Set(['PLD', 'WAR', 'DRK', 'GNB']),
MELEE_JOBS: new Set(['MNK', 'DRG', 'NIN', 'SAM', 'RPR', 'VPR']),
CASTER_JOBS: new Set(['BLM', 'SMN', 'RDM', 'PCT']),
ABILITY_TYPE_PHYSICAL,
ABILITY_TYPE_MAGICAL,
abilityTypeIsPhysical,
abilityTypeIsMagical,
};
})();