From 71e7cd35c89ab7f4b1e8be1cbefc7702eafcb788 Mon Sep 17 00:00:00 2001 From: Xaver-DaRed Date: Tue, 27 Jan 2026 04:07:12 +0100 Subject: [PATCH] Add rank check to Imperial standing npcs --- scripts/globals/besieged.lua | 260 +++++++++++++++++------------------ 1 file changed, 130 insertions(+), 130 deletions(-) diff --git a/scripts/globals/besieged.lua b/scripts/globals/besieged.lua index 33966613710..616909ab662 100644 --- a/scripts/globals/besieged.lua +++ b/scripts/globals/besieged.lua @@ -8,6 +8,78 @@ require('scripts/globals/extravaganza') xi = xi or {} xi.besieged = xi.besieged or {} +---@class imperialStandingItems : { [integer]: { id: xi.item, price: integer, rank: integer } } +local imperialStandingItems = +{ + -- Common Items + [ 1] = { id = xi.item.SCROLL_OF_INSTANT_RERAISE, price = 7, rank = 0 }, + [ 4097] = { id = xi.item.SCROLL_OF_INSTANT_WARP, price = 10, rank = 0 }, + [ 8193] = { id = xi.item.LAMBENT_FIRE_CELL, price = 100, rank = 0 }, + [12289] = { id = xi.item.LAMBENT_WATER_CELL, price = 100, rank = 0 }, + [16385] = { id = xi.item.LAMBENT_EARTH_CELL, price = 100, rank = 0 }, + [20481] = { id = xi.item.LAMBENT_WIND_CELL, price = 100, rank = 0 }, + [24577] = { id = xi.item.KATANA_STRAP, price = 20000, rank = 0 }, + [28673] = { id = xi.item.AXE_GRIP, price = 20000, rank = 0 }, + [32769] = { id = xi.item.STAFF_STRAP, price = 20000, rank = 0 }, + [36865] = { id = xi.item.HEAT_CAPACITOR, price = 5000, rank = 0 }, + [40961] = { id = xi.item.POWER_COOLER, price = 5000, rank = 0 }, + [45057] = { id = xi.item.BARRAGE_TURBINE, price = 5000, rank = 0 }, + [53249] = { id = xi.item.GALVANIZER, price = 5000, rank = 0 }, + [57345] = { id = xi.item.EPHRAMADIAN_THRONE, price = 50000, rank = 0 }, + [69633] = { id = xi.item.CIPHER_OF_MIHLIS_ALTER_EGO, price = 5000, rank = 0 }, + + -- Private Second Class + -- Map Key Items (handled separately) + -- Private First Class + [ 33] = { id = xi.item.VOLUNTEERS_DART, price = 2000, rank = 2 }, + [ 289] = { id = xi.item.MERCENARYS_DART, price = 2000, rank = 2 }, + [ 545] = { id = xi.item.IMPERIAL_DART, price = 2000, rank = 2 }, + + -- Superior Private + [ 49] = { id = xi.item.MAMOOLBANE, price = 4000, rank = 3 }, + [ 305] = { id = xi.item.LAMIABANE, price = 4000, rank = 3 }, + [ 561] = { id = xi.item.TROLLBANE, price = 4000, rank = 3 }, + [ 817] = { id = xi.item.LUZAFS_RING, price = 4000, rank = 3 }, + + -- Lance Corporal + [ 65] = { id = xi.item.SNEAKING_BOOTS, price = 8000, rank = 4 }, + [ 321] = { id = xi.item.TROOPERS_RING, price = 8000, rank = 4 }, + [ 577] = { id = xi.item.SENTINEL_SHIELD, price = 8000, rank = 4 }, + + -- Corporal + [ 81] = { id = xi.item.SHARK_GUN, price = 16000, rank = 5 }, + [ 337] = { id = xi.item.PUPPET_CLAWS, price = 16000, rank = 5 }, + [ 593] = { id = xi.item.SINGH_KILIJ, price = 16000, rank = 5 }, + + -- Sergeant + [ 97] = { id = xi.item.MERCENARYS_TROUSERS, price = 24000, rank = 6 }, + [ 353] = { id = xi.item.MULTIPLE_RING, price = 24000, rank = 6 }, + [ 609] = { id = xi.item.HATEN_EARRING, price = 24000, rank = 6 }, + + -- Sergeant Major + [ 113] = { id = xi.item.VOLUNTEERS_BRAIS, price = 32000, rank = 7 }, + [ 369] = { id = xi.item.PRIESTS_EARRING, price = 32000, rank = 7 }, + [ 625] = { id = xi.item.CHAOTIC_EARRING, price = 32000, rank = 7 }, + + -- Chief Sergeant + [ 129] = { id = xi.item.PERDU_HANGER, price = 40000, rank = 8 }, + [ 385] = { id = xi.item.PERDU_SICKLE, price = 40000, rank = 8 }, + [ 641] = { id = xi.item.PERDU_WAND, price = 40000, rank = 8 }, + [ 897] = { id = xi.item.PERDU_BOW, price = 40000, rank = 8 }, + + -- Second Lieutenant + [ 145] = { id = xi.item.PERDU_SWORD, price = 48000, rank = 9 }, + [ 401] = { id = xi.item.PERDU_BLADE, price = 48000, rank = 9 }, + [ 657] = { id = xi.item.PERDU_VOULGE, price = 48000, rank = 9 }, + [ 913] = { id = xi.item.PERDU_STAFF, price = 48000, rank = 9 }, + [ 1169] = { id = xi.item.PERDU_CROSSBOW, price = 48000, rank = 9 }, + + -- First Lieutenant + [ 161] = { id = xi.item.LIEUTENANTS_GORGET, price = 56000, rank = 10 }, + [ 417] = { id = xi.item.LIEUTENANTS_SASH, price = 56000, rank = 10 }, + [ 673] = { id = xi.item.LIEUTENANTS_CAPE, price = 56000, rank = 10 }, +} + xi.besieged.cipherValue = function() local active = xi.extravaganza.campaignActive() @@ -21,6 +93,39 @@ xi.besieged.cipherValue = function() end end +-- TODO: Implement Astral Candescence +xi.besieged.getAstralCandescence = function() + return 1 -- Hardcoded to 1 for now +end + +xi.besieged.badges = +{ + xi.ki.PSC_WILDCAT_BADGE, + xi.ki.PFC_WILDCAT_BADGE, + xi.ki.SP_WILDCAT_BADGE, + xi.ki.LC_WILDCAT_BADGE, + xi.ki.C_WILDCAT_BADGE, + xi.ki.S_WILDCAT_BADGE, + xi.ki.SM_WILDCAT_BADGE, + xi.ki.CS_WILDCAT_BADGE, + xi.ki.SL_WILDCAT_BADGE, + xi.ki.FL_WILDCAT_BADGE, + xi.ki.CAPTAIN_WILDCAT_BADGE +} + +xi.besieged.getMercenaryRank = function(player) + local rank = 0 + + for k = #xi.besieged.badges, 1, -1 do + if player:hasKeyItem(xi.besieged.badges[k]) then + rank = k + break + end + end + + return rank +end + local function getMapBitmask(player) local mamook = player:hasKeyItem(xi.ki.MAP_OF_MAMOOK) and 1 or 0 -- Map of Mammok local halvung = player:hasKeyItem(xi.ki.MAP_OF_HALVUNG) and 2 or 0 -- Map of Halvung @@ -40,96 +145,11 @@ end ----------------------------------- local function getImperialDefenseStats() local successiveWins = 0 - local defenseBonus = 0 - local imperialWins = 0 - local beastmanWins = 0 - return { successiveWins, defenseBonus, imperialWins, beastmanWins } -end - ------------------------------------ --- function getISPItem(i) returns the item ID and cost of the imperial standing --- points item indexed by i (the same value as that used by the vendor event.) --- TODO: Separate packed data into something more logical ------------------------------------ -local function getISPItem(i) - ---@class imperialStandingItems : { [integer]: { id: xi.item, price: integer } } - local imperialStandingItems = - { - -- Common Items - [ 1] = { id = xi.item.SCROLL_OF_INSTANT_RERAISE, price = 7 }, - [ 4097] = { id = xi.item.SCROLL_OF_INSTANT_WARP, price = 10 }, - [ 8193] = { id = xi.item.LAMBENT_FIRE_CELL, price = 100 }, - [12289] = { id = xi.item.LAMBENT_WATER_CELL, price = 100 }, - [16385] = { id = xi.item.LAMBENT_EARTH_CELL, price = 100 }, - [20481] = { id = xi.item.LAMBENT_WIND_CELL, price = 100 }, - [24577] = { id = xi.item.KATANA_STRAP, price = 20000 }, - [28673] = { id = xi.item.AXE_GRIP, price = 20000 }, - [32769] = { id = xi.item.STAFF_STRAP, price = 20000 }, - [36865] = { id = xi.item.HEAT_CAPACITOR, price = 5000 }, - [40961] = { id = xi.item.POWER_COOLER, price = 5000 }, - [45057] = { id = xi.item.BARRAGE_TURBINE, price = 5000 }, - [53249] = { id = xi.item.GALVANIZER, price = 5000 }, - [57345] = { id = xi.item.EPHRAMADIAN_THRONE, price = 50000 }, - [69633] = { id = xi.item.CIPHER_OF_MIHLIS_ALTER_EGO, price = 5000 }, - - -- Private Second Class - -- Map Key Items (handled separately) - -- Private First Class - [ 33] = { id = xi.item.VOLUNTEERS_DART, price = 2000 }, - [289] = { id = xi.item.MERCENARYS_DART, price = 2000 }, - [545] = { id = xi.item.IMPERIAL_DART, price = 2000 }, - - -- Superior Private - [ 49] = { id = xi.item.MAMOOLBANE, price = 4000 }, - [305] = { id = xi.item.LAMIABANE, price = 4000 }, - [561] = { id = xi.item.TROLLBANE, price = 4000 }, - [817] = { id = xi.item.LUZAFS_RING, price = 4000 }, - - -- Lance Corporal - [ 65] = { id = xi.item.SNEAKING_BOOTS, price = 8000 }, - [321] = { id = xi.item.TROOPERS_RING, price = 8000 }, - [577] = { id = xi.item.SENTINEL_SHIELD, price = 8000 }, - - -- Corporal - [ 81] = { id = xi.item.SHARK_GUN, price = 16000 }, - [337] = { id = xi.item.PUPPET_CLAWS, price = 16000 }, - [593] = { id = xi.item.SINGH_KILIJ, price = 16000 }, - - -- Sergeant - [ 97] = { id = xi.item.MERCENARYS_TROUSERS, price = 24000 }, - [353] = { id = xi.item.MULTIPLE_RING, price = 24000 }, - [609] = { id = xi.item.HATEN_EARRING, price = 24000 }, - - -- Sergeant Major - [113] = { id = xi.item.VOLUNTEERS_BRAIS, price = 32000 }, - [369] = { id = xi.item.PRIESTS_EARRING, price = 32000 }, - [625] = { id = xi.item.CHAOTIC_EARRING, price = 32000 }, - - -- Chief Sergeant - [129] = { id = xi.item.PERDU_HANGER, price = 40000 }, - [385] = { id = xi.item.PERDU_SICKLE, price = 40000 }, - [641] = { id = xi.item.PERDU_WAND, price = 40000 }, - [897] = { id = xi.item.PERDU_BOW, price = 40000 }, - - -- Second Lieutenant - [ 145] = { id = xi.item.PERDU_SWORD, price = 48000 }, - [ 401] = { id = xi.item.PERDU_BLADE, price = 48000 }, - [ 657] = { id = xi.item.PERDU_VOULGE, price = 48000 }, - [ 913] = { id = xi.item.PERDU_STAFF, price = 48000 }, - [1169] = { id = xi.item.PERDU_CROSSBOW, price = 48000 }, - - -- First Lieutenant - [161] = { id = xi.item.LIEUTENANTS_GORGET, price = 56000 }, - [417] = { id = xi.item.LIEUTENANTS_SASH, price = 56000 }, - [673] = { id = xi.item.LIEUTENANTS_CAPE, price = 56000 }, - } - - local item = imperialStandingItems[i] - if item then - return item.id, item.price - end + local defenseBonus = 0 + local imperialWins = 0 + local beastmanWins = 0 - return nil + return { successiveWins, defenseBonus, imperialWins, beastmanWins } end ----------------------------------- @@ -163,16 +183,21 @@ xi.besieged.onTrigger = function(player, npc, eventBase) end xi.besieged.onEventUpdate = function(player, csid, option, npc) - local itemId = getISPItem(option) - if itemId and option < 0x40000000 then + local entry = imperialStandingItems[option] + if not entry then + return + end + + if option < 0x40000000 then local maps = getMapBitmask(player) - player:updateEvent(player:getCurrency('imperial_standing'), (maps + xi.besieged.cipherValue()), xi.besieged.getMercenaryRank(player), player:canEquipItem(itemId) and 2 or 1, unpack(getImperialDefenseStats())) + player:updateEvent(player:getCurrency('imperial_standing'), (maps + xi.besieged.cipherValue()), xi.besieged.getMercenaryRank(player), player:canEquipItem(entry.id) and 2 or 1, unpack(getImperialDefenseStats())) end end xi.besieged.onEventFinish = function(player, csid, option, npc) local ID = zones[player:getZoneID()] local imperialStanding = player:getCurrency('imperial_standing') + local mercenaryRank = xi.besieged.getMercenaryRank(player) -- Sanction if option == 0 or option == 16 or option == 32 or option == 48 then @@ -195,6 +220,10 @@ xi.besieged.onEventFinish = function(player, csid, option, npc) -- Player bought a map elseif bit.band(option, 0xFF) == 17 then + if mercenaryRank < 1 then + return + end + if imperialStanding < 1000 then return end @@ -205,17 +234,21 @@ xi.besieged.onEventFinish = function(player, csid, option, npc) -- Player bought an item elseif option < 0x40000000 then - local item, itemCost = getISPItem(option) - if not item then + local entry = imperialStandingItems[option] + if not entry.id then return end - if imperialStanding < itemCost then + if mercenaryRank < entry.rank then return end - if npcUtil.giveItem(player, item) then - player:delCurrency('imperial_standing', itemCost) + if imperialStanding < entry.price then + return + end + + if npcUtil.giveItem(player, entry.id) then + player:delCurrency('imperial_standing', entry.price) end end end @@ -246,36 +279,3 @@ xi.besieged.hasAssaultOrders = function(player) return event, keyitem end - --- TODO: Implement Astral Candescence -xi.besieged.getAstralCandescence = function() - return 1 -- Hardcoded to 1 for now -end - -xi.besieged.badges = -{ - xi.ki.PSC_WILDCAT_BADGE, - xi.ki.PFC_WILDCAT_BADGE, - xi.ki.SP_WILDCAT_BADGE, - xi.ki.LC_WILDCAT_BADGE, - xi.ki.C_WILDCAT_BADGE, - xi.ki.S_WILDCAT_BADGE, - xi.ki.SM_WILDCAT_BADGE, - xi.ki.CS_WILDCAT_BADGE, - xi.ki.SL_WILDCAT_BADGE, - xi.ki.FL_WILDCAT_BADGE, - xi.ki.CAPTAIN_WILDCAT_BADGE -} - -xi.besieged.getMercenaryRank = function(player) - local rank = 0 - - for k = #xi.besieged.badges, 1, -1 do - if player:hasKeyItem(xi.besieged.badges[k]) then - rank = k - break - end - end - - return rank -end