// Palladium: Bleach - SERVER Script v10 + v11 patches
// COPY THIS TO: .minecraft/kubejs/server_scripts/bleach_tags_server.js
// DELETE any old version first!
//
// v10: SECTION 2 expansion + Phase 4 progression.
//   - Hogyoku status adaptation: on top of the 7 damage vectors, the orb now
//     learns to shrug off harmful STATUS effects it survives - Toxin
//     (poison/wither), Gloom (blindness/darkness) and Kinetic Lock
//     (slowness/levitation). Once learned, that class of effect is cleansed
//     every couple seconds and answered with a counter buff (regen /
//     night vision / speed). Fall-adapted players also get a standing
//     absorption barrier (kinetic dampening).
//   - Phase 4 Bankai quest: while a Shikai is held, kills build a quest tracker
//     scaled to the blade's tier; at 100% the matching Bankai is granted for
//     free (no crafting). Non-destructive: the Shikai is kept.
//
// v9: HOGYOKU REACTIVE ADAPTATION - carrying the Hogyoku (or Aizen's fused
//     blade) evolves you: damage from a threat vector builds adaptation
//     points; at the threshold that damage type is CANCELLED from then on.
//
// v8: no NBT is ever written to a held sword (that resets item-granted powers).
//     The drawn blade is the palladiumbleach:drawn_blade render layer.
//
// v4: pb_kills / pb_hollow_kills / pb_zanpakuto_uses objectives + tag cleanup.

console.log('[Palladium: Bleach] Server script v10+v11 loading...')

// --- Scoreboard setup --------------------------------------------------------
ServerEvents.loaded(event => {
    const s = event.server
    // pb_total = raw lifetime kills (auto). pb_base = snapshot taken the moment a
    // player first holds a bleach zanpakuto. pb_kills (what all progression reads)
    // = pb_total - pb_base, recomputed each tick below, so Soul Kills only count
    // from when you pick up a bleach weapon - lifetime kills are ignored.
    s.runCommandSilent('scoreboard objectives add pb_total totalKillCount "Total Kills"')
    s.runCommandSilent('scoreboard objectives add pb_base dummy')
    s.runCommandSilent('scoreboard objectives add pb_prev dummy')
    s.runCommandSilent('scoreboard objectives add pb_delta dummy')
    s.runCommandSilent('scoreboard objectives add pb_meta dummy')
    s.runCommandSilent('execute unless score $pbmig pb_meta matches 4 run scoreboard objectives remove pb_kills')
    s.runCommandSilent('scoreboard objectives add pb_kills dummy "Soul Kills"')
    s.runCommandSilent('execute unless score $pbmig pb_meta matches 4 run scoreboard players set $pbmig pb_meta 4')
    s.runCommandSilent('scoreboard objectives add pb_hollow_kills totalKillCount "Hollow Kills"')
    s.runCommandSilent('scoreboard objectives add pb_zanpakuto_uses dummy "Zanpakuto Uses"')
    // v9: hogyoku damage-vector adaptation progress
    s.runCommandSilent('scoreboard objectives add pb_ad_fire dummy "Adaptation: Thermal"')
    s.runCommandSilent('scoreboard objectives add pb_ad_drown dummy "Adaptation: Aquatic"')
    s.runCommandSilent('scoreboard objectives add pb_ad_frost dummy "Adaptation: Cryo"')
    s.runCommandSilent('scoreboard objectives add pb_ad_blast dummy "Adaptation: Concussive"')
    s.runCommandSilent('scoreboard objectives add pb_ad_rei dummy "Adaptation: Reiatsu"')
    s.runCommandSilent('scoreboard objectives add pb_ad_fall dummy "Adaptation: Impact"')
    s.runCommandSilent('scoreboard objectives add pb_ad_wither dummy "Adaptation: Decay"')
    // v10: status-effect adaptation progress
    s.runCommandSilent('scoreboard objectives add pb_ad_venom dummy "Adaptation: Toxin"')
    s.runCommandSilent('scoreboard objectives add pb_ad_gloom dummy "Adaptation: Gloom"')
    s.runCommandSilent('scoreboard objectives add pb_ad_bind dummy "Adaptation: Kinetic Lock"')
    // v10: Bankai quest progress (mirrors the held Shikai's tracker)
    s.runCommandSilent('scoreboard objectives add pb_shikai_quest dummy "Bankai Attunement"')
})

// --- Fresh Soul Kills: baseline snapshot on first bleach weapon, then delta -----
// pb_kills (all progression reads this) = pb_total - pb_base. pb_base is captured
// the first time a player holds a bleach zanpakuto, so lifetime kills never count.
let pbTickCounter = 0
ServerEvents.tick(event => {
    pbTickCounter++
    if (pbTickCounter % 5 != 0) return
    const server = event.server
    if (!server) return
    server.runCommandSilent('execute as @a unless score @s pb_prev = @s pb_prev run scoreboard players operation @s pb_prev = @s pb_total')
    server.runCommandSilent('scoreboard players operation @a pb_delta = @a pb_total')
    server.runCommandSilent('scoreboard players operation @a pb_delta -= @a pb_prev')
    server.runCommandSilent('execute as @a if score @s pb_base matches 1 if score @s pb_delta matches 1.. run scoreboard players operation @s pb_kills += @s pb_delta')
    server.runCommandSilent('scoreboard players operation @a pb_prev = @a pb_total')
    server.runCommandSilent('execute as @a[predicate=palladiumbleach:holding_reiatsu] unless score @s pb_base matches 1 run scoreboard players set @s pb_base 1')
})

// --- Animation tag cleanup (legacy) ------------------------------------------
PlayerEvents.tick(event => {
    const player = event.player
    if (!player || !player.server) return

    const animTags = [
        { tag: 'pb_swing_10', ticks: 10 },
        { tag: 'pb_shunpo_8', ticks: 8 },
        { tag: 'pb_block_10', ticks: 10 },
        { tag: 'pb_reiatsu_20', ticks: 20 },
        { tag: 'pb_bankai_24', ticks: 24 },
        { tag: 'pb_ground_slash_14', ticks: 14 },
        { tag: 'pb_beam_charge_8', ticks: 8 },
    ]

    for (const a of animTags) {
        if (player.tags.contains(a.tag)) {
            const counterKey = 'pb_counter_' + a.tag
            const current = player.persistentData.getInt(counterKey)
            if (current === 0) {
                player.persistentData.putInt(counterKey, a.ticks)
            } else if (current <= 1) {
                player.tags.remove(a.tag)
                player.persistentData.remove(counterKey)
            } else {
                player.persistentData.putInt(counterKey, current - 1)
            }
        }
    }
})

// --- v5: THE LIVING ZANPAKUTO -------------------------------------------------
const PB_MILESTONES = [
    { at: 10,  gate: 'asauchi', sound: 'minecraft:block.amethyst_block.chime', pitch: 0.7,
      msg: '{"text":"...your Asauchi trembles faintly in its sheath.","color":"dark_aqua","italic":true}' },
    { at: 25,  gate: 'asauchi', sound: 'minecraft:block.amethyst_block.chime', pitch: 0.9,
      msg: '{"text":"...a faint voice echoes from within the blade.","color":"aqua","italic":true}' },
    { at: 40,  gate: 'asauchi', sound: 'minecraft:block.amethyst_block.chime', pitch: 1.1,
      msg: '{"text":"...the blade whispers. It has learned the shape of your soul.","color":"aqua","italic":true}' },
    { at: 399,  gate: 'asauchi', sound: 'minecraft:block.bell.resonate', pitch: 1.3,
      msg: '{"text":"One more soul... your Zanpakuto strains against its seal!","color":"gold","bold":true}' },
    { at: 400,  gate: 'asauchi', sound: 'minecraft:ui.toast.challenge_complete', pitch: 1.0, title: true,
      msg: '{"text":"IT CALLS YOUR NAME","color":"gold","bold":true}',
      sub: '{"text":"Use Awaken Zanpakuto to claim your Sealed Zanpakuto","color":"yellow"}' },
    { at: 250, gate: null, sound: 'minecraft:block.amethyst_block.resonate', pitch: 0.8,
      msg: '{"text":"Zanpakuto Bond deepens... [250/1000] The blade fights eagerly beside you.","color":"light_purple","italic":true}' },
    { at: 500, gate: null, sound: 'minecraft:block.amethyst_block.resonate', pitch: 1.0,
      msg: '{"text":"Zanpakuto Bond deepens... [500/1000] You begin to hear syllables of its True Name.","color":"light_purple","italic":true}' },
    { at: 750, gate: null, sound: 'minecraft:block.amethyst_block.resonate', pitch: 1.2,
      msg: '{"text":"Zanpakuto Bond deepens... [750/1000] The name is almost clear...","color":"light_purple","italic":true}' },
    { at: 1000, gate: null, sound: 'minecraft:ui.toast.challenge_complete', pitch: 0.8, title: true,
      msg: '{"text":"TRUE NAME REVEALED","color":"light_purple","bold":true}',
      sub: '{"text":"Your Zanpakuto Bond is complete (+20% damage)","color":"yellow"}' },
]

const PB_ASAUCHI_GATE = 'if entity @s[nbt={Inventory:[{id:"palladiumbleach:asauchi"}]}] '

EntityEvents.death(event => {
    const source = event.source
    if (!source) return
    const player = source.player
    if (!player || !player.username) return
    const server = event.server
    if (!server) return
    const name = player.username

    // v11: fire each milestone EXACTLY once (fired-tag dedup) + gate bond milestones on blade
    const _heldId = pbMainHandId(player)
    const _asauchiPhase = (_heldId === 'palladiumbleach:asauchi')
    const _bondPhase = (_heldId === 'palladiumbleach:zanpakuto_sealed') ||
        ['palladiumbleach:zangetsu','palladiumbleach:senbonzakura','palladiumbleach:katen_kyokotsu',
         'palladiumbleach:kyoka_suigetsu','palladiumbleach:kenpachi_sword','palladiumbleach:rukia_sword',
         'palladiumbleach:toshiro_sword','palladiumbleach:shinso','palladiumbleach:yamamoto_staff',
         'palladiumbleach:urahara_cane','palladiumbleach:ichibei_brush','palladiumbleach:yhwach_sword',
         'palladiumbleach:aizen_hogyoku_sword'].includes(_heldId)
    for (const m of PB_MILESTONES) {
        if (m.gate === 'asauchi' && !_asauchiPhase) continue
        if (m.gate === null && !_bondPhase) continue
        const firedTag = 'pb_ms_' + m.at
        if (player.tags.contains(firedTag)) continue
        const gate = m.gate === 'asauchi' ? PB_ASAUCHI_GATE : ''
        const base = 'execute as ' + name + ' at @s if score @s pb_kills matches ' + m.at + '.. ' + gate
        server.runCommandSilent(base + 'run tag @s add ' + firedTag)
        if (!player.tags.contains(firedTag)) continue
        if (m.title) {
            server.runCommandSilent(base + 'run title @s title ' + m.msg)
            server.runCommandSilent(base + 'run title @s subtitle ' + m.sub)
            server.runCommandSilent(base + 'run particle minecraft:end_rod ~ ~1 ~ 0.6 1.2 0.6 0.08 40')
        } else {
            server.runCommandSilent(base + 'run tellraw @s ' + m.msg)
        }
        server.runCommandSilent(base + 'run playsound ' + m.sound + ' master @s ~ ~ ~ 1 ' + m.pitch)
    }

    server.runCommandSilent(
        'execute as ' + name + ' at @s if score @s pb_kills matches ..399 ' + PB_ASAUCHI_GATE +
        'run title @s actionbar {"text":"Soul Kills: ","color":"gray","extra":[{"score":{"objective":"pb_kills","name":"@s"},"color":"white","bold":true},{"text":" / 400","color":"dark_gray"},{"text":"  -- your Zanpakuto stirs...","color":"dark_aqua","italic":true}]}')

    // v11: Sealed Zanpakuto actionbar progress (toward 1000 for unseal)
    const PB_SEALED_GATE = 'if entity @s[nbt={Inventory:[{id:"palladiumbleach:zanpakuto_sealed"}]}] '
    server.runCommandSilent(
        'execute as ' + name + ' at @s if score @s pb_kills matches ..999 ' + PB_SEALED_GATE +
        'run title @s actionbar {"text":"Soul Kills: ","color":"gray","extra":[{"score":{"objective":"pb_kills","name":"@s"},"color":"white","bold":true},{"text":" / 1000","color":"dark_gray"},{"text":"  -- the seal weakens...","color":"light_purple","italic":true}]}')
})

console.log('[Palladium: Bleach] v5 Living Zanpakuto milestones armed')

// --- v9/v10: HOGYOKU REACTIVE ADAPTATION -------------------------------------
// Damage vectors: `ids` are DamageSource msgIds.
const PB_ADAPT = [
    { obj: 'pb_ad_fire',   tag: 'pb_adapt_fire',   need: 1500, name: 'Thermal',
      ids: ['infire', 'onfire', 'lava', 'hotfloor', 'fireball', 'unattributedfireball'] },
    { obj: 'pb_ad_drown',  tag: 'pb_adapt_drown',  need: 900, name: 'Aquatic',
      ids: ['drown'] },
    { obj: 'pb_ad_frost',  tag: 'pb_adapt_frost',  need: 900, name: 'Cryo',
      ids: ['freeze'] },
    { obj: 'pb_ad_blast',  tag: 'pb_adapt_blast',  need: 1800, name: 'Concussive',
      ids: ['explosion', 'explosion.player', 'fireworks'] },
    { obj: 'pb_ad_rei',    tag: 'pb_adapt_reiatsu', need: 1200, name: 'Reiatsu',
      ids: ['magic', 'indirectmagic', 'sonic_boom'] },
    { obj: 'pb_ad_fall',   tag: 'pb_adapt_fall',   need: 1500, name: 'Impact',
      ids: ['fall', 'flyintowall'] },
    { obj: 'pb_ad_wither', tag: 'pb_adapt_wither', need: 900, name: 'Decay',
      ids: ['wither', 'witherskull'] },
]

// Status-effect vectors: adapt by SURVIVING the effect, then cleanse + counter.
// `match` = substrings of the effect's description id; `clear` = effects to strip
// once adapted; `grant` = the counter buff granted while the class is present.
const PB_STATUS = [
    { obj: 'pb_ad_venom', tag: 'pb_adapt_venom', need: 600, name: 'Toxin',
      match: ['poison', 'wither'], clear: ['minecraft:poison', 'minecraft:wither'],
      grant: 'minecraft:regeneration 4 1 true' },
    { obj: 'pb_ad_gloom', tag: 'pb_adapt_gloom', need: 450, name: 'Gloom',
      match: ['blindness', 'darkness'], clear: ['minecraft:blindness', 'minecraft:darkness'],
      grant: 'minecraft:night_vision 16 0 true' },
    { obj: 'pb_ad_bind',  tag: 'pb_adapt_bind',  need: 450, name: 'Kinetic Lock',
      match: ['slowness', 'levitation'], clear: ['minecraft:slowness', 'minecraft:levitation'],
      grant: 'minecraft:speed 6 0 true' },
]

const PB_HOGYOKU_IDS = ['palladiumbleach:hogyoku', 'palladiumbleach:aizen_hogyoku_sword']

function pbHasHogyoku(player) {
    // v11: adaptation also works AFTER absorbing the Hogyoku (permanent)
    try {
        if (player.tags && player.tags.contains('pb_hogyoku_absorbed')) return true
    } catch (e) {}
    try {
        const inv = player.inventory
        const size = inv.getContainerSize()
        for (let i = 0; i < size; i++) {
            const s = inv.getItem(i)
            if (s && !s.isEmpty() && PB_HOGYOKU_IDS.includes(String(s.id))) return true
        }
    } catch (e) {}
    return false
}

function pbDamageMsgId(source) {
    // v11: lowercase so campfire/fire/etc. match reliably
    let id = ''
    try { id = String(source.getMsgId()) } catch (e) {}
    if (!id) { try { id = String(source.type().msgId()) } catch (e) {} }
    return id ? id.toLowerCase() : ''
}

// Defensive: return lower-cased description ids of the player's active effects.
// Any API mismatch fails closed (empty list) without throwing.
function pbEffectKeys(player) {
    const out = []
    let coll = null
    try { coll = player.activeEffects } catch (e) {}
    if (!coll) { try { coll = player.getActiveEffects() } catch (e) {} }
    if (!coll) return out
    try {
        const it = coll.iterator()
        while (it.hasNext()) {
            const e = it.next()
            let k = ''
            try { k = String(e.getEffect().getDescriptionId()) } catch (er) {}
            if (!k) { try { k = String(e.getDescriptionId()) } catch (er) {} }
            if (k) out.push(k.toLowerCase())
        }
    } catch (e) {}
    return out
}

function pbKeysMatch(keys, needles) {
    for (const k of keys) {
        for (const n of needles) {
            if (k.indexOf(n) >= 0) return true
        }
    }
    return false
}

function pbMainHandId(player) {
    try {
        const s = player.mainHandItem
        if (s && !s.isEmpty()) return String(s.id)
    } catch (e) {}
    return ''
}

EntityEvents.hurt(event => {
    const ent = event.entity
    if (!ent || String(ent.type) != 'minecraft:player') return
    const server = event.server
    if (!server) return
    if (!pbHasHogyoku(ent)) return

    const msgId = pbDamageMsgId(event.source)
    if (!msgId) return
    let row = null
    for (const r of PB_ADAPT) {
        if (r.ids.includes(msgId)) { row = r; break }
    }
    if (row == null) return
    const name = ent.username

    if (ent.tags.contains(row.tag)) {
        event.cancel()
        server.runCommandSilent('execute as ' + name + ' at @s run particle minecraft:dust_color_transition 0.6 0.1 0.9 1.2 0.95 0.85 1.0 ~ ~1 ~ 0.4 0.7 0.4 0 6')
        return
    }

    const pts = Math.max(1, Math.ceil(event.damage))
    const cur = ent.persistentData.getInt(row.obj)
    const next = cur + pts
    ent.persistentData.putInt(row.obj, next)
    server.runCommandSilent('scoreboard players set ' + name + ' ' + row.obj + ' ' + next)

    if (next >= row.need) {
        ent.tags.add(row.tag)
        server.runCommandSilent('execute as ' + name + ' at @s run title @s title {"text":"THE HOGYOKU ADAPTS","color":"light_purple","bold":true}')
        server.runCommandSilent('execute as ' + name + ' at @s run title @s subtitle {"text":"' + row.name + ' damage can no longer harm you","color":"yellow"}')
        server.runCommandSilent('execute as ' + name + ' at @s run playsound minecraft:ui.toast.challenge_complete master @a ~ ~ ~ 1 0.7')
        server.runCommandSilent('execute as ' + name + ' at @s run playsound minecraft:block.amethyst_block.resonate master @a ~ ~ ~ 1 0.5')
        server.runCommandSilent('execute as ' + name + ' at @s run particle minecraft:flash ~ ~1 ~ 0 0 0 0 1')
        server.runCommandSilent('execute as ' + name + ' at @s run particle minecraft:dust_color_transition 0.6 0.1 0.9 2.2 0.95 0.85 1.0 ~ ~1 ~ 1.2 1.4 1.2 0 40')
    } else if (next >= Math.ceil(row.need / 2) && cur < Math.ceil(row.need / 2)) {
        server.runCommandSilent('execute as ' + name + ' at @s run tellraw @s {"text":"...the Hogyoku stirs. It is learning the shape of ' + row.name + ' damage.","color":"light_purple","italic":true}')
        server.runCommandSilent('execute as ' + name + ' at @s run playsound minecraft:block.amethyst_block.chime master @s ~ ~ ~ 1 0.6')
    }
})

// comfort effects + status adaptation + transcendence check (every 2 seconds)
PlayerEvents.tick(event => {
    const player = event.player
    if (!player || !player.server) return
    if (player.tickCount % 40 != 0) return
    if (!pbHasHogyoku(player)) return
    const server = player.server
    const name = player.username

    // damage-vector comfort effects
    if (player.tags.contains('pb_adapt_fire')) {
        server.runCommandSilent('effect give ' + name + ' minecraft:fire_resistance 15 0 true')
    }
    if (player.tags.contains('pb_adapt_drown')) {
        server.runCommandSilent('effect give ' + name + ' minecraft:water_breathing 15 0 true')
    }
    // kinetic dampening: fall-adapted bodies carry a standing absorption barrier
    if (player.tags.contains('pb_adapt_fall')) {
        server.runCommandSilent('effect give ' + name + ' minecraft:absorption 4 0 true')
    }

    // status-effect adaptation
    const keys = pbEffectKeys(player)
    for (const st of PB_STATUS) {
        if (player.tags.contains(st.tag)) {
            // adapted: cleanse the class and answer with the counter buff
            if (pbKeysMatch(keys, st.match)) {
                for (const c of st.clear) server.runCommandSilent('effect clear ' + name + ' ' + c)
                server.runCommandSilent('effect give ' + name + ' ' + st.grant)
            }
        } else if (pbKeysMatch(keys, st.match)) {
            const cur = player.persistentData.getInt(st.obj) + 1
            player.persistentData.putInt(st.obj, cur)
            server.runCommandSilent('scoreboard players set ' + name + ' ' + st.obj + ' ' + cur)
            if (cur >= st.need) {
                player.tags.add(st.tag)
                server.runCommandSilent('execute as ' + name + ' at @s run title @s title {"text":"THE HOGYOKU ADAPTS","color":"light_purple","bold":true}')
                server.runCommandSilent('execute as ' + name + ' at @s run title @s subtitle {"text":"' + st.name + ' can no longer hold you","color":"yellow"}')
                server.runCommandSilent('execute as ' + name + ' at @s run playsound minecraft:ui.toast.challenge_complete master @a ~ ~ ~ 1 0.7')
                server.runCommandSilent('execute as ' + name + ' at @s run particle minecraft:flash ~ ~1 ~ 0 0 0 0 1')
                server.runCommandSilent('execute as ' + name + ' at @s run particle minecraft:dust_color_transition 0.6 0.1 0.9 2.2 0.95 0.85 1.0 ~ ~1 ~ 1.2 1.4 1.2 0 40')
            }
        }
    }

    // transcendence: all 7 damage vectors
    if (!player.tags.contains('pb_transcended')) {
        let all = true
        for (const r of PB_ADAPT) {
            if (!player.tags.contains(r.tag)) { all = false; break }
        }
        if (all) {
            player.tags.add('pb_transcended')
            server.runCommandSilent('execute as ' + name + ' at @s run title @s title {"text":"TRANSCENDENCE","color":"gold","bold":true}')
            server.runCommandSilent('execute as ' + name + ' at @s run title @s subtitle {"text":"The Hogyoku has made you a perfect being","color":"light_purple"}')
            server.runCommandSilent('execute as ' + name + ' at @s run playsound minecraft:ui.toast.challenge_complete master @a ~ ~ ~ 1 0.5')
            server.runCommandSilent('execute as ' + name + ' at @s run playsound minecraft:entity.warden.roar master @a ~ ~ ~ 0.7 1.8')
            server.runCommandSilent('execute as ' + name + ' at @s run particle minecraft:end_rod ~ ~1 ~ 1 1.5 1 0.15 120')
        }
    } else {
        server.runCommandSilent('effect give ' + name + ' minecraft:strength 15 0 true')
        server.runCommandSilent('effect give ' + name + ' minecraft:resistance 15 0 true')
    }
})

console.log('[Palladium: Bleach] v9/v10 Hogyoku adaptation armed (7 damage vectors + 3 status + transcendence)')

// --- v10: PHASE 4 - AUTONOMOUS BANKAI QUEST ----------------------------------
// While a Shikai is held, kills build a per-blade tracker scaled to its tier.
// At 100% the matching Bankai is granted for free. The Shikai is never removed.
const PB_BANKAI_QUEST = []

EntityEvents.death(event => {
    const source = event.source
    if (!source) return
    const player = source.player
    if (!player || !player.username) return
    const server = event.server
    if (!server) return

    const heldId = pbMainHandId(player)
    if (!heldId) return
    let q = null
    for (const row of PB_BANKAI_QUEST) {
        if (row.shikai === heldId) { q = row; break }
    }
    if (q == null) return
    const name = player.username

    // already earned this Bankai: nothing more to do
    if (player.tags.contains(q.tag)) return

    const cur = player.persistentData.getInt('pb_bq_' + q.tag) + 1
    player.persistentData.putInt('pb_bq_' + q.tag, cur)
    server.runCommandSilent('scoreboard players set ' + name + ' pb_shikai_quest ' + cur)

    if (cur >= q.need) {
        player.tags.add(q.tag)
        server.runCommandSilent('give ' + name + ' ' + q.bankai + ' 1')
        server.runCommandSilent('execute as ' + name + ' at @s run title @s title {"text":"BANKAI","color":"gold","bold":true}')
        server.runCommandSilent('execute as ' + name + ' at @s run title @s subtitle {"text":"' + q.name + ' has awakened within you","color":"light_purple"}')
        server.runCommandSilent('execute as ' + name + ' at @s run playsound minecraft:ui.toast.challenge_complete master @a ~ ~ ~ 1 0.6')
        server.runCommandSilent('execute as ' + name + ' at @s run playsound minecraft:entity.warden.roar master @a ~ ~ ~ 0.8 1.5')
        server.runCommandSilent('execute as ' + name + ' at @s run particle minecraft:end_rod ~ ~1 ~ 1 1.6 1 0.15 120')
    } else {
        server.runCommandSilent('execute as ' + name + ' run title @s actionbar {"text":"Bankai Attunement [' + q.tier + ']: ","color":"gray","extra":[{"score":{"objective":"pb_shikai_quest","name":"@s"},"color":"aqua","bold":true},{"text":" / ' + q.need + '","color":"dark_gray"}]}')
        // milestone whispers at the quarter marks
        if (cur == Math.floor(q.need / 2)) {
            server.runCommandSilent('execute as ' + name + ' at @s run tellraw @s {"text":"...your Shikai hungers for its final form. Halfway to Bankai.","color":"light_purple","italic":true}')
            server.runCommandSilent('execute as ' + name + ' at @s run playsound minecraft:block.amethyst_block.resonate master @s ~ ~ ~ 1 0.7')
        }
    }
})

console.log('[Palladium: Bleach] v10 Bankai quest armed (' + PB_BANKAI_QUEST.length + ' Shikai tracked)')

// --- v11: /pbhogadaption list - the adaptation readout as a chat command ------
function pbPrintAdaptations(source) {
    let player = null
    try { player = source.player } catch (e) {}
    if (!player) { try { player = source.getPlayer() } catch (e) {} }
    if (!player) { try { player = source.getEntity() } catch (e) {} }
    if (!player || !player.username) return 0
    const server = player.server
    if (!server) return 0
    const name = player.username
    server.runCommandSilent('tellraw ' + name + ' {"text":"     HOGYOKU - REACTIVE ADAPTATION","color":"light_purple","bold":true}')
    for (const r of PB_ADAPT) {
        server.runCommandSilent('execute as ' + name + ' if entity @s[tag=' + r.tag + '] run tellraw @s {"text":" ADAPTED  ' + r.name + '","color":"gold"}')
        server.runCommandSilent('execute as ' + name + ' unless entity @s[tag=' + r.tag + '] run tellraw @s [{"text":" evolving ' + r.name + ':  ","color":"gray"},{"score":{"name":"@s","objective":"' + r.obj + '"},"color":"white","bold":true},{"text":" / ' + r.need + ' damage","color":"dark_gray"}]')
    }
    for (const st of PB_STATUS) {
        server.runCommandSilent('execute as ' + name + ' if entity @s[tag=' + st.tag + '] run tellraw @s {"text":" ADAPTED  ' + st.name + '","color":"dark_green"}')
        server.runCommandSilent('execute as ' + name + ' unless entity @s[tag=' + st.tag + '] run tellraw @s [{"text":" evolving ' + st.name + ':  ","color":"gray"},{"score":{"name":"@s","objective":"' + st.obj + '"},"color":"white","bold":true},{"text":" / ' + st.need + ' endured","color":"dark_gray"}]')
    }
    server.runCommandSilent('execute as ' + name + ' if entity @s[tag=pb_transcended] run tellraw @s {"text":" TRANSCENDENCE COMPLETE - a perfect being","color":"gold","bold":true}')
    server.runCommandSilent('playsound minecraft:block.amethyst_block.resonate master ' + name + ' ~ ~ ~ 1 1.4')
    return 1
}

ServerEvents.commandRegistry(event => {
    const { commands: Commands } = event
    event.register(
        Commands.literal('pbhogadaption')
            .then(Commands.literal('list').executes(ctx => pbPrintAdaptations(ctx.source)))
            .executes(ctx => pbPrintAdaptations(ctx.source))
    )
})

console.log('[Palladium: Bleach] v11 /pbhogadaption list command registered')
