-- WarEffort_Objectives.lua
-- War Effort objective definitions for the War Board.
--
-- Add a new objective by appending a table to WB.WarEffort.Objectives. Fields:
--   id        : UNIQUE, stable identifier — used for cross-realm
--               comms / verification later. Never reuse one.       (string)
--   faction   : "horde" or "alliance" — only that faction sees it.
--               Omit to show the objective to both factions.       (string)
--   title     : card heading                                       (string)
--   desc      : one-line description. Put "%s" wherever the ENEMY
--               faction ("Alliance"/"Horde") should appear — it is
--               filled in automatically from the player's faction.
--               Omit it for objectives that don't target players.  (string)
--   texture   : full background image path                         (string)
--   texCoord  : optional {l,r,t,b} UV crop for the card art — zoom
--               in to trim a black border baked into the image.
--               Omit for art that already fills the card.          (table)
--   mapID     : for PLAYER-kill objectives, credit kills only on this
--               exact UiMapID (use for expansion zones that share a
--               name with an old-world zone). Falls back to the
--               texture-derived zone name when omitted.            (number)
--   zones     : for PLAYER-kill objectives matched by name (no mapID),
--               extra zone/subzone names that ALSO count — needed when a
--               subzone reports its own map name (e.g. "Atal'Aman" inside
--               "Zul'Aman"). The texture-derived zone is always accepted. (table)
--   zoneLabel : custom card hover text (else the texture zone name). (string)
--   goal      : target count                                       (number)
--   gold      : gold awarded on completion                         (number)
--   warCredit : war credit awarded — fills the War Effort bar      (number)
--   daily     : daily by default — progress + completion clear at
--               the daily server reset. Set daily = false for a
--               permanent objective that never resets.             (bool)
--   elite     : true recolors the card border to the faction
--               colour (Horde red / Alliance blue) to flag an
--               elite-NPC objective.                               (bool)
--   retired   : true keeps the definition (so historical records still
--               validate) but stops offering it as a card.         (bool)
--   acquire   : true marks an ACQUISITION objective (gather a resource,
--               not a kill). Never touched by the kill tracker — pair
--               it with noKillTrack.                                (bool)
--   unlockSpell : spell ID that GATES this objective. Until the player
--               knows it (IsPlayerSpell), the card + map pin render
--               LOCKED (darkened, lock icon centered) and can't be
--               progressed. Omit → always unlocked.                (number)
--   lockedTip : hover text shown while locked — why it's locked and
--               how to unlock it.                                   (string)
--
-- Every objective is infinitely repeatable: the first completion pays the full
-- gold/war credit, each repeat pays 10%. Daily ones reset to full reward next day.
--
-- These feed the War Effort panel in UI/WarBoard_Frame.lua.
--
-- ►► FORWARD COMPATIBILITY ◄◄ — the Verifier audits records against these definitions,
-- and older clients won't have ones you ADD. The rules are append-only:
--   • New / changed objective → add a NEW unique id (never edit an existing one's
--     id/gold/warCredit/goal/faction in place — two versions would then disagree and
--     quarantine each other's honest records).
--   • Removing one → set retired = true; do NOT delete it.
--   • After ANY change here, bump WB.RULESVER (WarBoard_Core.lua) by 1, so out-of-date
--     clients ABSTAIN on the new content (show it, sync it, score it once they update)
--     instead of flagging it as suspicious.

local addonName, WB = ...

WB.WarEffort = WB.WarEffort or {}

-- Texture → zone resolver, shared by the card hover-tooltip and the kill tracker.
-- Keyed by a lowercase keyword in the texture path, so any Azshara art → "Azshara"
-- regardless of path/extension. Add zones here as you introduce new background art.
WB.WarEffort.ZONE_BY_TEXTURE = {
    { keyword = "azshara",         zone = "Azshara" },
    { keyword = "northernbarrens", zone = "Northern Barrens" },
    { keyword = "southernbarrens", zone = "Southern Barrens" },
    { keyword = "ashenvale",       zone = "Ashenvale" },
    { keyword = "hillsbrad",       zone = "Hillsbrad Foothills" },
    { keyword = "hinterlands",     zone = "The Hinterlands" },
    { keyword = "badlands",        zone = "Badlands" },
    { keyword = "eversongwoods",   zone = "Eversong Woods" },
    { keyword = "zulaman",         zone = "Zul'Aman" },
    { keyword = "harandar",        zone = "Harandar" },
    { keyword = "val.blp",         zone = "Val" },        -- specific ".blp" so it won't match "Ashenvale"
    { keyword = "naigtal",         zone = "Naigtal" },
}

function WB.WarEffort.ZoneFromTexture(texture)
    if type(texture) ~= "string" then return nil end
    local lower = texture:lower()
    for _, entry in ipairs(WB.WarEffort.ZONE_BY_TEXTURE) do
        if lower:find(entry.keyword, 1, true) then
            return entry.zone
        end
    end
    return nil
end

-- Weekly-flip objectives (the Val ⇄ Naigtal rotation) are only OFFERED while their zone is the
-- one currently up. Objectives without a `flipZone` are always available. Used by the War Effort
-- card list, the priority-zone check, and kill crediting — so only one of the pair shows/scores.
-- (Both stay in WB.WarEffort.ById permanently, so out-of-week records still validate.)
function WB.WarEffort.IsFlipZoneActive(obj)
    if type(obj) ~= "table" or obj.flipZone == nil then return true end
    if not (WB.Campaign and WB.Campaign.ActiveFlipZone) then return true end
    return obj.flipZone == WB.Campaign.ActiveFlipZone()
end

-- ── Acquisition lock state ────────────────────────────────────────────────────────────
-- An objective with `unlockSpell` is GATED: until the player knows that spell, its card and
-- map pin render LOCKED.

-- Has the player unlocked this objective? Non-gated objectives are always unlocked.
function WB.WarEffort.IsUnlocked(obj)
    if type(obj) ~= "table" or not obj.unlockSpell then return true end
    return (IsPlayerSpell and IsPlayerSpell(obj.unlockSpell)) and true or false
end

-- Is this objective currently LOCKED (gated AND not yet unlocked)?
function WB.WarEffort.IsLocked(obj)
    return type(obj) == "table" and obj.unlockSpell ~= nil and not WB.WarEffort.IsUnlocked(obj)
end

-- Short place name for an objective (used by the Alerts feed). Pulled from the
-- description's "... at the <place>." / "... at <place>." / "... in <place>." tail,
-- falling back to the objective title.
function WB.WarEffort.PlaceFromObjective(obj)
    if type(obj) ~= "table" then return nil end
    local d = obj.desc
    if type(d) == "string" then
        local place = d:match("[Aa]t the (.+)$") or d:match("[Aa]t (.+)$") or d:match("[Ii]n (.+)$")
        if place then
            return (place:gsub("%s*%.%s*$", ""))   -- trim a trailing period
        end
    end
    return obj.title
end



WB.WarEffort.Objectives = {

-- AZSHARA: "Interface\\QuestionFrame\\Answer-WarBoard-Classic-Azshara.blp"

    {
        id        = "azshara_skirmish_horde",
        marker    = { mapID = 76 },   -- map-link only (zone-wide, no pin)
        faction   = "horde",
        title     = "Azshara Skirmish",
        desc      = "Kill 10 %s players in Azshara.",
        texture   = "Interface\\QuestionFrame\\Answer-WarBoard-Classic-Azshara.blp",
        goal      = 10,
        gold      = 200,
        warCredit = 100,
    },
    {
        id        = "azshara_skirmish_alliance",
        marker    = { mapID = 76 },   -- map-link only (zone-wide, no pin)
        faction   = "alliance",
        title     = "Azshara Skirmish",
        desc      = "Kill 10 %s players in Azshara.",
        texture   = "Interface\\QuestionFrame\\Answer-WarBoard-Classic-Azshara.blp",
        goal      = 10,
        gold      = 200,
        warCredit = 100,
    },

-- NPC-kill objectives (no enemy-player %s). Reusing the Azshara art for now.

    {
        id        = "pleasure_in_peril_alliance",
        marker    = { mapID = 76, x = 0.2089, y = 0.5696 },
        faction   = "alliance",
        npcIDs    = { 52018, 50045, 52093, 52092 },  -- Palace Mook, Pleasure Palace Waitress, Zanagan/Izak Mixmaster
        title     = "Pleasure in Peril",
        desc      = "Kill 25 Bilgewater Cartel NPCs at the Gallywix Pleasure Palace.",
        texture   = "Interface\\QuestionFrame\\Answer-WarBoard-Classic-Azshara.blp",
        goal      = 25,
        gold      = 50,
        warCredit = 25,
        proximity = {
            radius                = 6,
            talkingHead           = "shandris_peril",
            cooldown              = 300,
            triggerOncePerSession = false,
        },
    },
    {
        id        = "mine_your_manners_horde",
        marker    = { mapID = 76, x = 0.2171, y = 0.6990 },
        faction   = "horde",
        npcIDs    = { 35312 },  -- Talrendis Saboteur
        title     = "Mine Your Manners",
        desc      = "Kill 25 Night Elf NPCs at the Mountainfoot Strip Mine.",
        texture   = "Interface\\QuestionFrame\\Answer-WarBoard-Classic-Azshara.blp",
        goal      = 25,
        gold      = 50,
        warCredit = 25,
        -- Proximity TalkingHead: Cromush hails you when you approach the strip mine in
        -- War Mode. radius is map-percent; talkingHead is a WB.UI.TalkingHeads key.
        proximity = {
            radius                = 6,                  -- ~6% of the Azshara map
            talkingHead           = "cromush_engage",
            cooldown              = 300,                -- don't replay for 5 min
            triggerOncePerSession = false,
        },
    },
-- BARRENS: "Interface\\QuestionFrame\\Answer-Warboard-Classic-NorthernBarrens.blp"

    {
        id        = "morshan_impossible_alliance",
        marker    = { mapID = 10, x = 0.4396, y = 0.1794 },
        faction   = "alliance",
        npcIDs    = { 43645, 33284, 8582, 33201, 33263, 34927, 43637, 33281, 14754, 14718, 14717, 19910 },
        title     = "Mor'shan Impossible",
        desc      = "Kill 25 Warsong NPCs at Mor'shan Base Camp or Mor'shan Ramparts.",
        texture   = "Interface\\QuestionFrame\\Answer-Warboard-Classic-NorthernBarrens.blp",
        goal      = 25,
        gold      = 50,
        warCredit = 25,
        proximity = {
            radius                = 7,
            talkingHead           = "shandris_morshan",
            cooldown              = 300,
            triggerOncePerSession = false,
        },
    },
    {
        id        = "secure_the_merchant_coast_horde",
        marker    = { mapID = 10, x = 0.7046, y = 0.8304 },
        faction   = "horde",
        npcIDs    = { 34707, 3385, 3386, 34706, 34753, 34752 },
        title     = "Secure the Merchant Coast",
        desc      = "Kill 25 Theramore NPCs at the Merchant Coast.",
        texture   = "Interface\\QuestionFrame\\Answer-Warboard-Classic-NorthernBarrens.blp",
        goal      = 25,
        gold      = 50,
        warCredit = 25,
        proximity = {
            radius                = 5,
            talkingHead           = "cromush_supply_lines",
            cooldown              = 300,
            triggerOncePerSession = false,
        },
    },
    {
        id        = "northern_barrens_offensive_alliance",
        marker    = { mapID = 10 },   -- map-link only (zone-wide, no pin)
        faction   = "alliance",
        title     = "Northern Barrens Offensive",
        desc      = "Kill 10 %s players in Northern Barrens.",
        texture   = "Interface\\QuestionFrame\\Answer-Warboard-Classic-NorthernBarrens.blp",
        goal      = 10,
        gold      = 200,
        warCredit = 100,
    },
    {
        id        = "northern_barrens_defense_horde",
        marker    = { mapID = 10 },   -- map-link only (zone-wide, no pin)
        faction   = "horde",
        title     = "Northern Barrens Defense",
        desc      = "Kill 10 %s players in Northern Barrens.",
        texture   = "Interface\\QuestionFrame\\Answer-Warboard-Classic-NorthernBarrens.blp",
        goal      = 10,
        gold      = 200,
        warCredit = 100,
    },

-- ACQUISITION objectives — gather a resource rather than kill. Gated behind a learned
-- spell (unlockSpell): until the player knows Find Lumber (1256697), the card + map pin
-- render LOCKED (darkened, lock icon centered) with a hint on how to unlock. Reusable —
-- drop another one in any zone with its own marker + texture. Collection/progress logic
-- lands later; this is the availability + locked-state layer only.
    {
        id          = "ironwood_lumber_northern_barrens",
        marker      = { mapID = 10, x = 0.4741, y = 0.7617 },   -- pin only (no radius/popup trigger)
        acquire     = true,
        unlockSpell = 1256697,   -- Find Lumber — the ability to collect lumber
        noKillTrack = true,      -- gathering, never a kill objective
        -- Subzone presence (AreaTable IDs) drives the popup + tracker, matched locale-safely by
        -- comparing GetMinimapZoneText() to C_Map.GetAreaInfo(id). Progress is one unit per loot
        -- interaction that yields lootItemID inside these subzones. See WarBoard_Acquire.lua.
        areaIDs     = { 387, 388 },   -- Lushwater Oasis (387), The Stagnant Oasis (388)
        lootItemID  = 245586,         -- Ironwood Lumber
        progressLabel = "Ironwood Lumber collected",
        title       = "Ironwood Lumber - Oasis Circuit",
        desc        = "Acquire Ironwood Lumber at the Lushwater or Stagnant Oasis in Northern Barrens.",
        lockedTip   = "Objective Locked: Unlock the ability to collect lumber by completing "
                    .. "the quest \"Lumber For You\" in the housing neighborhood.",
        texture     = "Interface\\QuestionFrame\\Answer-Warboard-Classic-NorthernBarrens.blp",
        goal        = 10,
        gold        = 75,
        warCredit   = 50,
    },

-- SOUTHERN BARRENS: "Interface\\QuestionFrame\\Answer-WarBoard-Classic-SouthernBarrens.blp"

    {
        id        = "battle_for_the_scar_alliance",
        marker    = { mapID = 199, x = 0.4531, y = 0.6981 },
        faction   = "alliance",
        npcIDs    = { 37925, 37922, 37971, 44305, 37974 },
        title     = "Battle for the Scar",
        desc      = "Kill 25 Horde NPCs at the Battlescar.",
        texture   = "Interface\\QuestionFrame\\Answer-WarBoard-Classic-SouthernBarrens.blp",
        goal      = 25,
        gold      = 50,
        warCredit = 25,
        proximity = {
            radius                = 7,
            talkingHead           = "wyrmbane_scar",
            cooldown              = 300,
            triggerOncePerSession = false,
        },
    },
    {
        id        = "battle_for_the_scar_horde",
        marker    = { mapID = 199, x = 0.4531, y = 0.6981 },
        faction   = "horde",
        npcIDs    = { 37978, 37923, 37926, 37924 },
        title     = "Battle for the Scar",
        desc      = "Kill 25 Alliance NPCs at the Battlescar.",
        texture   = "Interface\\QuestionFrame\\Answer-WarBoard-Classic-SouthernBarrens.blp",
        goal      = 25,
        gold      = 50,
        warCredit = 25,
        proximity = {
            radius                = 6,
            talkingHead           = "cromush_battlefield",
            cooldown              = 300,
            triggerOncePerSession = false,
        },
    },
    {
        id        = "battle_for_southern_barrens_alliance",
        marker    = { mapID = 199 },   -- map-link only (zone-wide, no pin)
        faction   = "alliance",
        title     = "Battle for Southern Barrens",
        desc      = "Kill 10 %s players in Southern Barrens.",
        texture   = "Interface\\QuestionFrame\\Answer-WarBoard-Classic-SouthernBarrens.blp",
        goal      = 10,
        gold      = 200,
        warCredit = 100,
    },
    {
        id        = "battle_for_southern_barrens_horde",
        marker    = { mapID = 199 },   -- map-link only (zone-wide, no pin)
        faction   = "horde",
        title     = "Battle for Southern Barrens",
        desc      = "Kill 10 %s players in Southern Barrens.",
        texture   = "Interface\\QuestionFrame\\Answer-WarBoard-Classic-SouthernBarrens.blp",
        goal      = 10,
        gold      = 200,
        warCredit = 100,
    },

-- ASHENVALE: "Interface\\QuestionFrame\\Answer-WarBoard-Classic-Ashenvale.blp"

    {
        id        = "dock_and_awe_alliance",
        marker    = { mapID = 63, x = 0.1255, y = 0.3277 },
        faction   = "alliance",
        npcIDs    = { 43653, 34122, 43617, 12717, 43606, 12863, 12719, 43619, 135086, 11901, 34303, 43615, 12962, 12961 },
        title     = "Dock and Awe",
        desc      = "Kill 35 Horde NPCs at Zoram'gar Outpost.",
        texture   = "Interface\\QuestionFrame\\Answer-WarBoard-Classic-Ashenvale.blp",
        goal      = 35,
        gold      = 75,
        warCredit = 35,
        proximity = {
            radius                = 6,
            talkingHead           = "shandris_dock",
            cooldown              = 300,
            triggerOncePerSession = false,
        },
    },
    {
        id        = "leaf_them_no_quarter_horde",
        marker    = { mapID = 63, x = 0.3606, y = 0.5064 },
        faction   = "horde",
        npcIDs    = { 6087, 3894, 10052, 34239, 3691, 3961, 3969, 3959, 6738, 3996, 3954, 11137, 3967, 3962, 17106, 33512, 4079, 3953, 3952, 3958, 3970, 33454, 4267 },
        title     = "Leaf Them No Quarter",
        desc      = "Kill 35 Alliance NPCs at Astranaar.",
        texture   = "Interface\\QuestionFrame\\Answer-WarBoard-Classic-Ashenvale.blp",
        goal      = 35,
        gold      = 75,
        warCredit = 35,
        proximity = {
            radius                = 3,                  -- ~5% of the Ashenvale map
            talkingHead           = "usha_simple_plan",
            cooldown              = 300,                -- don't replay for 5 min
            triggerOncePerSession = false,
        },
    },
    {
        id        = "barking_up_the_wrong_tree_horde",
        marker    = { mapID = 63, x = 0.8712, y = 0.5877 },
        faction   = "horde",
        npcIDs    = { 34177, 34204, 34208, 34294, 17303, 17287, 17310 },
        title     = "Barking Up the Wrong Tree",
        desc      = "Kill 35 Alliance NPCs at Warsong Lumber Camp.",
        texture   = "Interface\\QuestionFrame\\Answer-WarBoard-Classic-Ashenvale.blp",
        goal      = 35,
        gold      = 75,
        warCredit = 35,
        proximity = {
            radius                = 7,                  -- ~7% of the Ashenvale map
            talkingHead           = "usha_cornered",
            cooldown              = 300,                -- don't replay for 5 min
            triggerOncePerSession = false,
        },
    },
    {
        id        = "environmental_assessment_alliance",
        marker    = { mapID = 63, x = 0.8712, y = 0.5877 },
        faction   = "alliance",
        npcIDs    = { 11682, 33706, 11683, 11681, 11684, 34241, 34242, 17304, 34233 },
        title     = "Environmental Assessment",
        desc      = "Kill 35 Horde NPCs at Warsong Lumber Camp.",
        texture   = "Interface\\QuestionFrame\\Answer-WarBoard-Classic-Ashenvale.blp",
        goal      = 35,
        gold      = 75,
        warCredit = 35,
        proximity = {
            radius                = 6,
            talkingHead           = "shandris_environmental",
            cooldown              = 300,
            triggerOncePerSession = false,
        },
    },
    {
        id        = "battle_for_ashenvale_alliance",
        marker    = { mapID = 63 },   -- map-link only (zone-wide, no pin)
        faction   = "alliance",
        title     = "Battle for Ashenvale",
        desc      = "Kill 20 %s players in Ashenvale.",
        texture   = "Interface\\QuestionFrame\\Answer-WarBoard-Classic-Ashenvale.blp",
        goal      = 20,
        gold      = 400,
        warCredit = 200,
    },
    {
        id        = "battle_for_ashenvale_horde",
        marker    = { mapID = 63 },   -- map-link only (zone-wide, no pin)
        faction   = "horde",
        title     = "Battle for Ashenvale",
        desc      = "Kill 20 %s players in Ashenvale.",
        texture   = "Interface\\QuestionFrame\\Answer-WarBoard-Classic-Ashenvale.blp",
        goal      = 20,
        gold      = 400,
        warCredit = 200,
    },

-- HILLSBRAD FOOTHILLS: "Interface\\QuestionFrame\\Answer-Warboard-Classic-HillsbradFoothills.blp"
-- Elite NPC-kill objectives — flagged with a faction-coloured card border.

    {
        id        = "frostwolf_offensive_alliance",
        marker    = { mapID = 25, x = 0.5850, y = 0.3397 },
        faction   = "alliance",
        elite     = true,
        npcIDs    = { 14285 },  -- Frostwolf Battleguard
        title     = "Frostwolf Offensive",
        desc      = "Kill 5 Frostwolf Battleguard in Hillsbrad Foothills.",
        texture   = "Interface\\QuestionFrame\\Answer-Warboard-Classic-HillsbradFoothills.blp",
        goal      = 5,
        gold      = 200,
        warCredit = 100,
        proximity = {
            radius                = 6,
            talkingHead           = "falstad_frostwolf",
            cooldown              = 300,
            triggerOncePerSession = false,
        },
    },
    {
        id        = "stormpike_offensive_horde",
        marker    = { mapID = 25, x = 0.4480, y = 0.4597 },
        faction   = "horde",
        elite     = true,
        npcIDs    = { 14284 },  -- Stormpike Battleguard
        title     = "Stormpike Offensive",
        desc      = "Kill 5 Stormpike Battleguard in Hillsbrad Foothills.",
        texture   = "Interface\\QuestionFrame\\Answer-Warboard-Classic-HillsbradFoothills.blp",
        goal      = 5,
        gold      = 200,
        warCredit = 100,
        proximity = {
            radius                = 5,
            talkingHead           = "rokhan_make_us_proud",
            cooldown              = 300,
            triggerOncePerSession = false,
        },
    },
    {
        id        = "like_the_good_old_days_alliance",
        marker    = { mapID = 25 },   -- map-link only (zone-wide, no pin)
        faction   = "alliance",
        title     = "Like the Good Old Days",
        desc      = "Kill 10 %s players in Hillsbrad Foothills.",
        texture   = "Interface\\QuestionFrame\\Answer-Warboard-Classic-HillsbradFoothills.blp",
        goal      = 10,
        gold      = 200,
        warCredit = 100,
    },
    {
        id        = "like_the_good_old_days_horde",
        marker    = { mapID = 25 },   -- map-link only (zone-wide, no pin)
        faction   = "horde",
        title     = "Like the Good Old Days",
        desc      = "Kill 10 %s players in Hillsbrad Foothills.",
        texture   = "Interface\\QuestionFrame\\Answer-Warboard-Classic-HillsbradFoothills.blp",
        goal      = 10,
        gold      = 200,
        warCredit = 100,
    },

-- HINTERLANDS: "Interface\\QuestionFrame\\Answer-Warboard-Classic-Hinterlands.blp"

    {
        id        = "research_and_destroy_alliance",
        marker    = { mapID = 26, x = 0.3246, y = 0.5713 },
        faction   = "alliance",
        npcIDs    = { 43715, 43766, 43739, 42898, 42896, 43750, 129912, 43573, 43748, 51824 },
        -- Hiri'watha Deathguard, Roslyn Paxton, Bitsy, Darkcleric Marnal, Apothecary
        -- Surlis, Marvin Winters, Warchief's Herald, Kellen Kuhn, Janice Winters,
        -- Hiri'watha Deathguard (51824)
        title     = "Research and Destroy",
        desc      = "Kill 25 Horde NPCs at Hiri'watha Research Station.",
        texture   = "Interface\\QuestionFrame\\Answer-Warboard-Classic-Hinterlands.blp",
        goal      = 25,
        gold      = 50,
        warCredit = 25,
        proximity = {
            radius                = 5,
            talkingHead           = "falstad_research",
            cooldown              = 300,
            triggerOncePerSession = false,
        },
    },
    {
        id        = "quell_the_danil_horde",
        marker    = { mapID = 26, x = 0.3178, y = 0.4948 },
        faction   = "horde",
        npcIDs    = { 46478, 46475 },  -- Highvale Sentry, Anchorite Traska
        title     = "Quell the Danil",
        desc      = "Kill 25 Alliance NPCs at Quel'Danil Lodge.",
        texture   = "Interface\\QuestionFrame\\Answer-Warboard-Classic-Hinterlands.blp",
        goal      = 25,
        gold      = 50,
        warCredit = 25,
        proximity = {
            radius                = 5,
            talkingHead           = "rokhan_crush_insects",
            cooldown              = 300,
            triggerOncePerSession = false,
        },
    },
    {
        id        = "the_hinterlands_front_alliance",
        marker    = { mapID = 26 },   -- map-link only (zone-wide, no pin)
        faction   = "alliance",
        title     = "The Hinterlands Front",
        desc      = "Kill 10 %s players in The Hinterlands.",
        texture   = "Interface\\QuestionFrame\\Answer-Warboard-Classic-Hinterlands.blp",
        goal      = 10,
        gold      = 200,
        warCredit = 100,
    },
    {
        id        = "the_hinterlands_front_horde",
        marker    = { mapID = 26 },   -- map-link only (zone-wide, no pin)
        faction   = "horde",
        title     = "The Hinterlands Front",
        desc      = "Kill 10 %s players in The Hinterlands.",
        texture   = "Interface\\QuestionFrame\\Answer-Warboard-Classic-Hinterlands.blp",
        goal      = 10,
        gold      = 200,
        warCredit = 100,
    },

-- BADLANDS: "Interface\\QuestionFrame\\Answer-Warboard-Classic-Badlands.blp"

    {
        id        = "battle_for_badlands_alliance",
        marker    = { mapID = 15 },   -- map-link only (zone-wide, no pin)
        faction   = "alliance",
        title     = "Battle for Badlands",
        desc      = "Kill 10 %s players in Badlands.",
        texture   = "Interface\\QuestionFrame\\Answer-Warboard-Classic-Badlands.blp",
        goal      = 10,
        gold      = 200,
        warCredit = 100,
    },
    {
        id        = "battle_for_badlands_horde",
        marker    = { mapID = 15 },   -- map-link only (zone-wide, no pin)
        faction   = "horde",
        title     = "Battle for Badlands",
        desc      = "Kill 10 %s players in Badlands.",
        texture   = "Interface\\QuestionFrame\\Answer-Warboard-Classic-Badlands.blp",
        goal      = 10,
        gold      = 200,
        warCredit = 100,
    },

-- "Breaking Badlands" — a no-mounts foot race for BOTH factions. Not a kill objective: it's started
-- and completed through the Demolitions Analyst II (npc 50512) via WB.Race, so noKillTrack keeps the
-- kill tracker from ever crediting it. Elite frame + a pinned start-line marker; reward 200g/100wc
-- (plus the standard active-warfront bonus, since it's a real objective in a warfront zone).
    {
        id          = "breaking_badlands_race",
        marker      = { mapID = 15, x = 0.8273, y = 0.3351 },   -- pinned start line
        title       = "Breaking Badlands",
        desc        = "Complete the foot race near Fuselight-by-the-Sea before time runs out.",
        texture     = "Interface\\QuestionFrame\\Answer-Warboard-Classic-Badlands.blp",
        goal        = 1,
        gold        = 150,
        warCredit   = 75,
        elite       = true,      -- red (Horde) / blue (Alliance) frame
        noKillTrack = true,      -- a foot race, not a kill objective — enemy kills never advance it
    },

-- "Tomb It May Concern" — Badlands NPC-kill objectives (each faction culls the enemy's
-- dig crew). Horde players hit the Alliance Explorers' League; Alliance players hit the
-- Horde Reliquary.
    {
        id        = "tomb_it_may_concern_horde",
        marker    = { mapID = 15, x = 0.5019, y = 0.4670 },
        faction   = "horde",
        npcIDs    = { 46773, 51538, 46762, 46761, 2910, 46760 },
        -- Explorers' League Excavator, Dustwind Overseer, Kand Sandseeker,
        -- Olga Runesworn, Prospector Ryedol, Lead Prospector Durdin
        title     = "Tomb It May Concern",
        desc      = "Kill 25 Explorers' League NPCs near the Tomb of the Watchers.",
        texture   = "Interface\\QuestionFrame\\Answer-Warboard-Classic-Badlands.blp",
        alertPlace = "the Tomb of Watchers",   -- assault-alert wording (overrides the desc parse)
        alertZone  = "the Badlands",
        goal      = 25,
        gold      = 50,
        warCredit = 25,
        proximity = {
            radius                = 6,
            talkingHead           = "rexxar_prize_hunt",
            cooldown              = 300,
            triggerOncePerSession = false,
        },
    },
    {
        id        = "tomb_it_may_concern_alliance",
        marker    = { mapID = 15, x = 0.5019, y = 0.4670 },
        faction   = "alliance",
        npcIDs    = { 46772, 46758, 46759, 51536 },
        -- Reliquary Excavator, Aoren Sunglow, Lidia Sunglow, Reliquary Overseer
        title     = "Tomb It May Concern",
        desc      = "Kill 25 Reliquary NPCs near the Tomb of the Watchers.",
        texture   = "Interface\\QuestionFrame\\Answer-Warboard-Classic-Badlands.blp",
        alertPlace = "the Tomb of Watchers",
        alertZone  = "the Badlands",
        goal      = 25,
        gold      = 50,
        warCredit = 25,
        proximity = {
            radius                = 7,
            talkingHead           = "genn_tomb",
            cooldown              = 300,
            triggerOncePerSession = false,
        },
    },

-- EVERSONG WOODS (Midnight) — a current-expansion player-kill front. Matched by map id
-- (`mapID`) instead of zone name, so it only counts in the Midnight Eversong Woods and not
-- the old-world one that shares the name. Intentionally NOT in the warfront pool (C.ZONES),
-- so it never gets the +50% warfront bonus — it's purely extra incentive to PvP elsewhere.
-- `zoneLabel` is the card's hover text.

    {
        id        = "eversong_front_horde",
        faction   = "horde",
        title     = "The Eversong Front",
        desc      = "Kill 10 %s players in Eversong Woods.",
        texture   = "Interface\\QuestionFrame\\Answer-Warboard-Classic-EversongWoods.blp",
        mapID     = 2395,
        zoneLabel = "Eversong Woods (Midnight)",
        goal      = 10,
        gold      = 200,
        warCredit = 100,
    },
    {
        id        = "eversong_front_alliance",
        faction   = "alliance",
        title     = "The Eversong Front",
        desc      = "Kill 10 %s players in Eversong Woods.",
        texture   = "Interface\\QuestionFrame\\Answer-Warboard-Classic-EversongWoods.blp",
        mapID     = 2395,
        zoneLabel = "Eversong Woods (Midnight)",
        goal      = 10,
        gold      = 200,
        warCredit = 100,
    },

-- ZUL'AMAN (Midnight) — current-expansion player-kill front, same class as Eversong.
-- Matched by the texture-derived zone name ("Zul'Aman") for now; add `mapID = <UiMapID>`
-- (from `/dump C_Map.GetBestMapForUnit("player")` standing in the zone) to pin it exactly
-- like Eversong and stay collision-proof against the old Zul'Aman raid that shares the name.
-- NOT in the warfront pool (C.ZONES), so it never becomes the active warfront / +50% bonus.

    {
        id        = "drum_up_some_trouble_horde",
        marker    = { mapID = 2437 },   -- map-link only (zone-wide, no pin)
        faction   = "horde",
        title     = "Drum Up Some Trouble",
        desc      = "Kill 10 %s players in Zul'Aman.",
        texture   = "Interface\\AddOns\\WarBoard\\Media\\Images\\ZulAman.blp",
        texCoord  = { 0.05, 0.95, 0.05, 0.95 },   -- zoom in slightly to trim the art's black border
        zones     = { "Zul'Aman", "Atal'Aman" },  -- Atal'Aman is a subzone with its own map name
        goal      = 10,
        gold      = 200,
        warCredit = 100,
    },
    {
        id        = "drum_up_some_trouble_alliance",
        marker    = { mapID = 2437 },   -- map-link only (zone-wide, no pin)
        faction   = "alliance",
        title     = "Drum Up Some Trouble",
        desc      = "Kill 10 %s players in Zul'Aman.",
        texture   = "Interface\\AddOns\\WarBoard\\Media\\Images\\ZulAman.blp",
        texCoord  = { 0.05, 0.95, 0.05, 0.95 },
        zones     = { "Zul'Aman", "Atal'Aman" },
        goal      = 10,
        gold      = 200,
        warCredit = 100,
    },

-- HARANDAR (Midnight) — current-expansion player-kill front. Pinned to its UiMapID (2413) AND
-- matched by zone name, so kills count anywhere in the zone, including subzones that report
-- their own map. Unique Midnight name, so the zone-name match carries no old-world collision
-- risk. NOT in the warfront pool (C.ZONES), so it never becomes the active warfront / +50%.

    {
        id        = "root_cause_analysis_horde",
        faction   = "horde",
        title     = "Root Cause Analysis",
        desc      = "Kill 10 %s players in Harandar.",
        texture   = "Interface\\AddOns\\WarBoard\\Media\\Images\\Harandar.blp",
        texCoord  = { 0.05, 0.95, 0.05, 0.95 },   -- zoom in slightly to trim the art's black border
        mapID     = 2413,
        zones     = { "Harandar" },
        goal      = 10,
        gold      = 200,
        warCredit = 100,
    },
    {
        id        = "root_cause_analysis_alliance",
        faction   = "alliance",
        title     = "Root Cause Analysis",
        desc      = "Kill 10 %s players in Harandar.",
        texture   = "Interface\\AddOns\\WarBoard\\Media\\Images\\Harandar.blp",
        texCoord  = { 0.05, 0.95, 0.05, 0.95 },   -- zoom in slightly to trim the art's black border
        mapID     = 2413,
        zones     = { "Harandar" },
        goal      = 10,
        gold      = 200,
        warCredit = 100,
    },

-- VAL & NAIGTAL (Midnight) — two player-kill fronts that FLIP every weekly reset (Tuesday): only
-- one zone is up per week, so only its objective is offered (gated by C.ActiveFlipZone() via
-- WB.WarEffort.IsFlipZoneActive). NOT in the warfront pool (C.ZONES), so no +50% bonus.
-- Pinned to their UiMapIDs (Val 2599, Naigtal 2600) AND matched by zone name, like Harandar.

    {
        id        = "cold_blooded_horde",
        faction   = "horde",
        flipZone  = "Val",
        title     = "Cold Blooded",
        desc      = "Kill 10 %s players in Val.",
        texture   = "Interface\\AddOns\\WarBoard\\Media\\Images\\Val.blp",
        texCoord  = { 0.13, 0.87, 0.13, 0.87 },   -- crop into the art to fill the card (hide the baked-in black border)
        mapID     = 2599,
        zoneLabel = "Val",
        zones     = { "Val" },
        goal      = 10,
        gold      = 200,
        warCredit = 100,
    },
    {
        id        = "cold_blooded_alliance",
        faction   = "alliance",
        flipZone  = "Val",
        title     = "Cold Blooded",
        desc      = "Kill 10 %s players in Val.",
        texture   = "Interface\\AddOns\\WarBoard\\Media\\Images\\Val.blp",
        texCoord  = { 0.13, 0.87, 0.13, 0.87 },
        mapID     = 2599,
        zoneLabel = "Val",
        zones     = { "Val" },
        goal      = 10,
        gold      = 200,
        warCredit = 100,
    },
    {
        id        = "spore_losers_horde",
        faction   = "horde",
        flipZone  = "Naigtal",
        title     = "Spore Losers",
        desc      = "Kill 10 %s players in Naigtal.",
        texture   = "Interface\\AddOns\\WarBoard\\Media\\Images\\Naigtal.blp",
        texCoord  = { 0.13, 0.87, 0.16, 0.84 },   -- extra top/bottom crop to clear the remaining black edge
        mapID     = 2600,
        zoneLabel = "Naigtal",
        zones     = { "Naigtal" },
        goal      = 10,
        gold      = 200,
        warCredit = 100,
    },
    {
        id        = "spore_losers_alliance",
        faction   = "alliance",
        flipZone  = "Naigtal",
        title     = "Spore Losers",
        desc      = "Kill 10 %s players in Naigtal.",
        texture   = "Interface\\AddOns\\WarBoard\\Media\\Images\\Naigtal.blp",
        texCoord  = { 0.13, 0.87, 0.16, 0.84 },   -- extra top/bottom crop to clear the remaining black edge
        mapID     = 2600,
        zoneLabel = "Naigtal",
        zones     = { "Naigtal" },
        goal      = 10,
        gold      = 200,
        warCredit = 100,
    },

}

-- id → objective lookup, for cross-realm comms / verification later.
-- Warns if two objectives accidentally share an id.
WB.WarEffort.ById = {}
for _, obj in ipairs(WB.WarEffort.Objectives) do
    if obj.id then
        if WB.WarEffort.ById[obj.id] then
            print((WB.TAG.." duplicate objective id '%s' in WarEffort_Objectives.lua"):format(tostring(obj.id)))
        end
        WB.WarEffort.ById[obj.id] = obj
    end
end
