From 97296d2824da1e6199f50fead0ebfc770e59ad41 Mon Sep 17 00:00:00 2001 From: Xaver-DaRed Date: Wed, 19 Mar 2025 17:30:19 +0100 Subject: [PATCH] Einherjar files styling --- scripts/globals/einherjar/chambers.lua | 25 +++-- scripts/globals/einherjar/lamp.lua | 32 ++++--- scripts/globals/einherjar/planner.lua | 109 ++++++++++++---------- scripts/globals/einherjar/reservation.lua | 10 +- scripts/globals/einherjar/settings.lua | 3 +- scripts/globals/einherjar/system.lua | 35 ++++--- scripts/globals/einherjar/treasure.lua | 95 ++++++++++++------- 7 files changed, 183 insertions(+), 126 deletions(-) diff --git a/scripts/globals/einherjar/chambers.lua b/scripts/globals/einherjar/chambers.lua index 964cc0ab895..83a28ed2a78 100644 --- a/scripts/globals/einherjar/chambers.lua +++ b/scripts/globals/einherjar/chambers.lua @@ -4,8 +4,10 @@ xi = xi or {} xi.einherjar = xi.einherjar or {} -local chambersByTier = { - [xi.einherjar.wing.WING_1] = { +local chambersByTier = +{ + [xi.einherjar.wing.WING_1] = + { { id = xi.einherjar.chamber.ROSSWEISSE, ki = xi.ki.ROSSWEISSES_FEATHER, @@ -28,7 +30,8 @@ local chambersByTier = { ichor = 960, }, }, - [xi.einherjar.wing.WING_2] = { + [xi.einherjar.wing.WING_2] = + { { id = xi.einherjar.chamber.HELMWIGE, ki = xi.ki.HELMWIGES_FEATHER, @@ -51,7 +54,8 @@ local chambersByTier = { ichor = 1440, }, }, - [xi.einherjar.wing.WING_3] = { + [xi.einherjar.wing.WING_3] = + { { id = xi.einherjar.chamber.ORTLINDE, ki = xi.ki.ORTLINDES_FEATHER, @@ -74,7 +78,8 @@ local chambersByTier = { ichor = 1920, }, }, - [xi.einherjar.wing.VALGRIND] = { + [xi.einherjar.wing.VALGRIND] = + { { id = xi.einherjar.chamber.ODIN, ki = 0, @@ -92,7 +97,8 @@ local chambersByTier = { }, } -xi.einherjar.chambers = { +xi.einherjar.chambers = +{ [xi.einherjar.chamber.ROSSWEISSE] = chambersByTier[xi.einherjar.wing.WING_1][1], [xi.einherjar.chamber.GRIMGERDE] = chambersByTier[xi.einherjar.wing.WING_1][2], [xi.einherjar.chamber.SIEGRUNE] = chambersByTier[xi.einherjar.wing.WING_1][3], @@ -110,15 +116,16 @@ xi.einherjar.chambers = { -- Wing 1 is always accessible xi.einherjar.getChambersMenu = function(player) local mask = 0xFF0 - local wings = { + local wings = + { xi.einherjar.wing.WING_1, xi.einherjar.wing.WING_2, xi.einherjar.wing.WING_3, - -- xi.einherjar.wing.ODIN -- Not implemented + -- xi.einherjar.wing.ODIN, -- Not implemented } for i = 1, #wings do - local tierChambers = chambersByTier[wings[i]] + local tierChambers = chambersByTier[wings[i]] local nextTierChambers = chambersByTier[wings[i + 1]] -- Check if player owns all key items in the current tier diff --git a/scripts/globals/einherjar/lamp.lua b/scripts/globals/einherjar/lamp.lua index 055cc9d5c4a..b53a7870d37 100644 --- a/scripts/globals/einherjar/lamp.lua +++ b/scripts/globals/einherjar/lamp.lua @@ -7,11 +7,12 @@ xi.einherjar = xi.einherjar or {} xi.einherjar.makeLamp = function(player, chamberId, startTime, endTime) player:addItem({ id = xi.item.GLOWING_LAMP, - exdata = { - [0] = 0x1D + chamberId, - [2] = 0x01, - [8] = bit.band(endTime, 0xFF), - [9] = bit.band(bit.rshift(endTime, 8), 0xFF), + exdata = + { + [ 0] = 0x1D + chamberId, + [ 2] = 0x01, + [ 8] = bit.band(endTime, 0xFF), + [ 9] = bit.band(bit.rshift(endTime, 8), 0xFF), [10] = bit.band(bit.rshift(endTime, 16), 0xFF), [11] = bit.band(bit.rshift(endTime, 24), 0xFF), [12] = bit.band(startTime, 0xFF), @@ -39,11 +40,12 @@ xi.einherjar.voidLamp = function(player, lampObj) player:delItemAt(xi.item.GLOWING_LAMP, 1, lampObj:getLocationID(), lampObj:getSlotID()) player:addItem({ id = xi.item.GLOWING_LAMP, - exdata = { - [0] = 0x0, - [2] = 0x0, - [8] = 0x0, - [9] = 0x0, + exdata = + { + [ 0] = 0x0, + [ 2] = 0x0, + [ 8] = 0x0, + [ 9] = 0x0, [10] = 0x0, [11] = 0x0, [12] = 0x0, @@ -57,13 +59,15 @@ end -- Reads a given Glowing Lamp and returns the chamber, enter time, and exit time xi.einherjar.decypherLamp = function(lampObj) local exData = lampObj and lampObj:getExData() - - if not exData or #exData < 16 or exData[0] == 0 then + if + not exData or + #exData < 16 or + exData[0] == 0 + then return { chamber = 0, tier = 0, startTime = 0, endTime = 0 } end local chamber = exData[0] - 0x1D - local endTime = bit.bor( exData[8] or 0, bit.lshift(exData[9] or 0, 8), @@ -83,6 +87,7 @@ end xi.einherjar.isLampExpired = function(lampObj) local lampData = xi.einherjar.decypherLamp(lampObj) + return lampData and lampData.endTime and os.time() > lampData.endTime end @@ -156,7 +161,6 @@ xi.einherjar.onLampDrop = function(player, lampObj) end local lampData = xi.einherjar.decypherLamp(lampObj) - if lampData.chamber == 0 then return end diff --git a/scripts/globals/einherjar/planner.lua b/scripts/globals/einherjar/planner.lua index ed738181d0e..8ba1f4cce72 100644 --- a/scripts/globals/einherjar/planner.lua +++ b/scripts/globals/einherjar/planner.lua @@ -14,8 +14,10 @@ xi.einherjar.unlockMob = function(mobId) lockedMobs[mobId] = nil end -local mobPool = { - [xi.einherjar.wing.WING_1] = { +local mobPool = +{ + [xi.einherjar.wing.WING_1] = + { ID.mob.BUGARD_X, ID.mob.CHIGOE, ID.mob.CRAVEN_EINHERJAR, @@ -31,7 +33,8 @@ local mobPool = { ID.mob.ROTTING_HUSKARL_BLM, ID.mob.SJOKRAKJEN, }, - [xi.einherjar.wing.WING_2] = { + [xi.einherjar.wing.WING_2] = + { ID.mob.BATTLEMITE, ID.mob.CHIGOE, ID.mob.CORRUPT_EINHERJAR, @@ -53,7 +56,8 @@ local mobPool = { ID.mob.WALDGEIST, ID.mob.WINEBIBBER, }, - [xi.einherjar.wing.WING_3] = { + [xi.einherjar.wing.WING_3] = + { ID.mob.AUDHUMBLA, ID.mob.BERSERKR, ID.mob.CORRUPT_EINHERJAR, @@ -104,8 +108,10 @@ local function getRandomMobFamily(chamberTier) return selectedFamily end -local bossPool = { - [xi.einherjar.wing.WING_1] = { +local bossPool = +{ + [xi.einherjar.wing.WING_1] = + { ID.mob.HAKENMANN, ID.mob.HILDESVINI, ID.mob.HIMINRJOT, @@ -113,7 +119,8 @@ local bossPool = { ID.mob.MORBOL_EMPEROR, ID.mob.NIHHUS, }, - [xi.einherjar.wing.WING_2] = { + [xi.einherjar.wing.WING_2] = + { ID.mob.ANDHRIMNIR, ID.mob.ARIRI_SAMARIRI, ID.mob.BALRAHN, @@ -121,7 +128,8 @@ local bossPool = { ID.mob.MOKKURALFI, ID.mob.TANNGRISNIR, }, - [xi.einherjar.wing.WING_3] = { + [xi.einherjar.wing.WING_3] = + { ID.mob.DENDAINSONNE, ID.mob.FREKE, ID.mob.GORGIMERA, @@ -148,26 +156,28 @@ local function getRandomBoss(chamberTier) end -- Select a random boss - local index = math.random(#availableBosses) + local index = math.random(#availableBosses) local selectedBoss = availableBosses[index] -- Lock the selected boss and return it lockedMobs[selectedBoss] = true + return selectedBoss end -local specialPool = { - { ids = 0, chance = 2 }, -- Special mob may not spawn +local specialPool = +{ + { ids = 0, chance = 2 }, -- Special mob may not spawn { ids = ID.mob.HUGINN, chance = 30 }, { ids = ID.mob.MUNINN, chance = 30 }, - { ids = ID.mob.HEITHRUN, chance = 8 }, + { ids = ID.mob.HEITHRUN, chance = 8 }, { ids = ID.mob.SAEHRIMNIR, chance = 30 }, } -- Returns a random special mob -- No lock is necessary since 9 copies exist local function getRandomSpecial(chamberId) - local rand = math.random(100) + local rand = math.random(1, 100) local cumulative = 0 for _, choice in ipairs(specialPool) do @@ -188,16 +198,16 @@ local function generateDistribution(familyCount, waveCount) -- Distribute remaining families with a max limit of 2 per wave local remainingFamilies = familyCount - waveCount - local validWaves = {} + local validWaves = {} for i = 1, waveCount do table.insert(validWaves, i) end while remainingFamilies > 0 and #validWaves > 0 do - local waveIndex = validWaves[math.random(1, #validWaves)] + local waveIndex = validWaves[math.random(1, #validWaves)] distribution[waveIndex] = distribution[waveIndex] + 1 - remainingFamilies = remainingFamilies - 1 + remainingFamilies = remainingFamilies - 1 if distribution[waveIndex] == 2 then for i, v in ipairs(validWaves) do @@ -215,18 +225,19 @@ end local function getWaveCount(familyCount, chamberTier) if chamberTier == 1 then return 1 -- Always 1 wave - else - -- Generate wave count, but it cannot exceed family count - local maxWaves = math.min(familyCount, (chamberTier == 2 and 2) or 3) - - if chamberTier == 2 then - -- 1 or 2 waves (40%-60%) - return math.random(100) > 40 and maxWaves or 1 - elseif chamberTier == 3 then - -- 1 to 3 waves (5%-45%-45%), but max cannot exceed family count - local roll = math.random(100) - return (roll > 50 and maxWaves) or (roll > 5 and math.min(2, maxWaves)) or 1 - end + end + + -- Generate wave count, but it cannot exceed family count + local maxWaves = math.min(familyCount, (chamberTier == 2 and 2) or 3) + + if chamberTier == 2 then + -- 1 or 2 waves (40%-60%) + return math.random(1, 100) > 40 and maxWaves or 1 + elseif chamberTier == 3 then + -- 1 to 3 waves (5%-45%-45%), but max cannot exceed family count + local roll = math.random(1, 100) + + return (roll > 50 and maxWaves) or (roll > 5 and math.min(2, maxWaves)) or 1 end end @@ -234,10 +245,11 @@ end -- All selected mobs are locked until released by the chamber xi.einherjar.makeChamberPlan = function(chamberId) local chamberTier = math.ceil(chamberId / 3) - local chamberConfig = { - boss = getRandomBoss(chamberTier), + local chamberConfig = + { + boss = getRandomBoss(chamberTier), special = getRandomSpecial(chamberId), - waves = {} + waves = {} } -- If we didn't get a boss, abort @@ -250,13 +262,13 @@ xi.einherjar.makeChamberPlan = function(chamberId) local familyCount if chamberTier == 1 then -- 1 to 2 families (40%-60%) over 1 wave - familyCount = math.random(100) > 40 and 2 or 1 + familyCount = math.random(1, 100) > 40 and 2 or 1 elseif chamberTier == 2 then -- 2 to 3 families (75%-25%) over 1 or 2 waves (40%-60%) - familyCount = math.random(100) > 25 and 2 or 3 + familyCount = math.random(1, 100) > 25 and 2 or 3 elseif chamberTier == 3 then -- 2 to 4 families (25%-50%-25%) over 1, 2, or 3 waves (5%-45%-45%) - local roll = math.random(100) + local roll = math.random(1, 100) familyCount = (roll > 75 and 4) or (roll > 25 and 3) or 2 end @@ -268,8 +280,12 @@ xi.einherjar.makeChamberPlan = function(chamberId) local randomFamily = {} -- Special case: If the boss is MOTSOGNIR, last wave gets specific IDs - if chamberConfig.boss == ID.mob.MOTSOGNIR and j == familyCount then - randomFamily = { + if + chamberConfig.boss == ID.mob.MOTSOGNIR and + j == familyCount + then + randomFamily = + { ID.mob.HERVARTH, ID.mob.HJORVARTH, ID.mob.HRANI, @@ -331,15 +347,15 @@ end -- Subdivides a list of mob IDs into random-sized subgroups xi.einherjar.subDivideMobs = function(mobIds) local subdividedGroups = {} - local shuffled = utils.shuffle(mobIds) + local shuffled = utils.shuffle(mobIds) + local index = 1 -- Divide into random-sized subgroups (between 2 and 5) - local index = 1 while index <= #shuffled do local remaining = #shuffled - index + 1 -- Random group size between 2 and 5, but not exceeding remaining mobs local groupSize = math.min(math.random(2, 5), remaining) - local subGroup = {} + local subGroup = {} for i = 0, groupSize - 1 do table.insert(subGroup, shuffled[index + i]) @@ -353,22 +369,19 @@ xi.einherjar.subDivideMobs = function(mobIds) end xi.einherjar.getRandomPosForMobGroup = function(chamberId, min, max) - local function getGroupCenterOffset() - return math.random(min, max) - end - - local groupOffsetX = getGroupCenterOffset() - local groupOffsetZ = getGroupCenterOffset() + local groupOffsetX = math.random(min, max) + local groupOffsetZ = math.random(min, max) - if math.random() > 0.5 then + if math.random(1, 100) <= 50 then groupOffsetX = -groupOffsetX end - if math.random() > 0.5 then + if math.random(1, 100) <= 50 then groupOffsetZ = -groupOffsetZ end - return { + return + { xi.einherjar.chambers[chamberId].center[1] + groupOffsetX, xi.einherjar.chambers[chamberId].center[2], xi.einherjar.chambers[chamberId].center[3] + groupOffsetZ diff --git a/scripts/globals/einherjar/reservation.lua b/scripts/globals/einherjar/reservation.lua index 6fc1e4ce211..49d83d6688a 100644 --- a/scripts/globals/einherjar/reservation.lua +++ b/scripts/globals/einherjar/reservation.lua @@ -5,9 +5,9 @@ xi = xi or {} xi.einherjar = xi.einherjar or {} xi.einherjar.meetsRequirementsForReservation = function(player) - local texts = zones[xi.zone.HAZHALM_TESTING_GROUNDS].text + local texts = zones[xi.zone.HAZHALM_TESTING_GROUNDS].text local lockout = xi.einherjar.isLockedOut(player) - local toau = player:hasCompletedMission(xi.mission.log_id.TOAU, xi.mission.id.toau.IMMORTAL_SENTRIES) + local toau = player:hasCompletedMission(xi.mission.log_id.TOAU, xi.mission.id.toau.IMMORTAL_SENTRIES) -- 1. Player must be level EINHERJAR_LEVEL_MIN+ if player:getMainLvl() < xi.einherjar.settings.EINHERJAR_LEVEL_MIN then @@ -31,9 +31,9 @@ xi.einherjar.meetsRequirementsForReservation = function(player) end xi.einherjar.meetsRequirementsForEntry = function(player, chamberId) - local texts = zones[xi.zone.HAZHALM_TESTING_GROUNDS].text - local lockout = xi.einherjar.isLockedOut(player) - local toau = player:hasCompletedMission(xi.mission.log_id.TOAU, xi.mission.id.toau.IMMORTAL_SENTRIES) + local texts = zones[xi.zone.HAZHALM_TESTING_GROUNDS].text + local lockout = xi.einherjar.isLockedOut(player) + local toau = player:hasCompletedMission(xi.mission.log_id.TOAU, xi.mission.id.toau.IMMORTAL_SENTRIES) local chamberData = xi.einherjar.getChamber(chamberId) if not chamberData then diff --git a/scripts/globals/einherjar/settings.lua b/scripts/globals/einherjar/settings.lua index 534838aab81..4350d05b886 100644 --- a/scripts/globals/einherjar/settings.lua +++ b/scripts/globals/einherjar/settings.lua @@ -5,7 +5,8 @@ xi = xi or {} xi.einherjar = xi.einherjar or {} -- Retail defaults -xi.einherjar.settings = { +xi.einherjar.settings = +{ -- Should Einherjar be enabled? Entry gate interactions disabled if false EINHERJAR_ENABLED = xi.settings.main.EINHERJAR_ENABLED or false, diff --git a/scripts/globals/einherjar/system.lua b/scripts/globals/einherjar/system.lua index c7f47ee2621..16790669d43 100644 --- a/scripts/globals/einherjar/system.lua +++ b/scripts/globals/einherjar/system.lua @@ -6,7 +6,8 @@ xi.einherjar = xi.einherjar or {} local ID = zones[xi.zone.HAZHALM_TESTING_GROUNDS] -local mobType = { +local mobType = +{ REGULAR = 1, BOSS = 2, SPECIAL = 3, @@ -34,11 +35,11 @@ local function log(chamberId, msg) print(string.format('[einherjar][%s] ', getChamberNameById(chamberId)) .. msg) end ---============================= +----------------------------------- -- Chamber instances management ---============================= - -local chambersInstances = { +----------------------------------- +local chambersInstances = +{ [xi.einherjar.chamber.ROSSWEISSE] = nil, [xi.einherjar.chamber.GRIMGERDE] = nil, [xi.einherjar.chamber.SIEGRUNE] = nil, @@ -161,7 +162,8 @@ local function onArmouryCrateTrigger(chamberData, chestOpener, armouryCrate) end local function onSpecialMobDespawn(chamberData, mob) - local specialMobHandlers = { + local specialMobHandlers = + { ['Saehrimnir'] = function() -- TODO: The exact value is unknown but it appears to provide a certain amount of regain to all mobs -- Future mobs will have 30% regain @@ -184,7 +186,8 @@ local function onSpecialMobDespawn(chamberData, mob) end local function onSpecialMobDeath(chamberData, mob) - local specialMobHandlers = { + local specialMobHandlers = + { ['Saehrimnir'] = function() mob:removeListener('EINHERJAR_DESPAWN') end, @@ -253,7 +256,7 @@ local function onMobEngage(chamberData, mob) -- Unknown if that's the actual trigger for countdown -- Captures show special spawn as early as 1.5 minutes from engaging mobs chamberData.eventsQueue[os.time() + math.random(90, 300)] = function() - local x, y, z = unpack(xi.einherjar.getRandomPosForMobGroup(chamberData.id, 10, 30)) + local x, y, z = unpack(xi.einherjar.getRandomPosForMobGroup(chamberData.id, 10, 30)) local specialMob = GetMobByID(chamberData.encounters.special) if specialMob then specialMob:setSpawn(x, y, z, math.random(0, 255)) @@ -267,7 +270,8 @@ end xi.einherjar.new = function(chamberId, leaderId) local startTime = os.time() - local chamberData = { + local chamberData = + { id = chamberId, leaderId = leaderId, startTime = startTime, @@ -279,7 +283,8 @@ xi.einherjar.new = function(chamberId, leaderId) mobs = {}, deadMobs = {}, plannedMobs = 0, - mobMods = { + mobMods = + { [xi.mobMod.ALLI_HATE] = 100, [xi.mobMod.CHECK_AS_NM] = 1, [xi.mobMod.CHARMABLE] = 0, @@ -321,7 +326,8 @@ xi.einherjar.new = function(chamberId, leaderId) -- TODO: Create a chamber-scoped shared treasure pool - chamberData.eventsQueue = { + chamberData.eventsQueue = + { [chamberData.startTime + (xi.einherjar.settings.EINHERJAR_RESERVATION_TIMEOUT * 60)] = function() if not chamberData.players[chamberData.leaderId] then log(chamberId, 'Leader never entered chamber, cancelling reservation.') @@ -355,6 +361,7 @@ xi.einherjar.new = function(chamberId, leaderId) } log(chamberId, 'Created chamber with ' .. #chamberData.encounters.waves .. ' waves.') + return chamberData end @@ -480,6 +487,7 @@ xi.einherjar.cycleWave = function(chamberData) log(chamberData.id, 'All waves cleared! Showing armoury crate.') npcUtil.showCrate(chamberData.lootCrate) chamberData.lootCrate:setLocalVar('[ein]chamber', chamberData.id) + return end @@ -521,10 +529,9 @@ xi.einherjar.cycleWave = function(chamberData) end end ---============================= +----------------------------------- -- Zone events listeners ---============================= - +----------------------------------- local function onChamberTick(chamberData) if not chamberData.eventsQueue or next(chamberData.eventsQueue) == nil then return diff --git a/scripts/globals/einherjar/treasure.lua b/scripts/globals/einherjar/treasure.lua index 8e23de893d4..a6bd73e933e 100644 --- a/scripts/globals/einherjar/treasure.lua +++ b/scripts/globals/einherjar/treasure.lua @@ -5,87 +5,108 @@ local ID = zones[xi.zone.HAZHALM_TESTING_GROUNDS] local bossDrops = { -- Wing 1 - [ID.mob.HAKENMANN] = { + [ID.mob.HAKENMANN] = + { { item = xi.item.CHUNK_OF_OROBON_MEAT, rate = 1000 }, }, - [ID.mob.HILDESVINI] = { + [ID.mob.HILDESVINI] = + { { item = xi.item.MARID_HIDE, rate = 1000 }, { item = xi.item.MARID_HIDE, rate = 1000 }, { item = xi.item.LOCK_OF_MARID_HAIR, rate = 1000 }, }, - [ID.mob.HIMINRJOT] = { + [ID.mob.HIMINRJOT] = + { { item = xi.item.BUFFALO_HIDE, rate = 1000 }, { item = xi.item.SLICE_OF_BUFFALO_MEAT, rate = 1000 }, }, - [ID.mob.HRAESVELG] = { + [ID.mob.HRAESVELG] = + { { item = xi.item.MANTICORE_FANG, rate = 1000 }, { item = xi.item.LOCK_OF_MANTICORE_HAIR, rate = 1000 }, { item = xi.item.MANTICORE_HIDE, rate = 1000 }, }, - [ID.mob.MORBOL_EMPEROR] = { + [ID.mob.MORBOL_EMPEROR] = + { { item = xi.item.AMERETAT_VINE, rate = 1000 }, { item = xi.item.LACQUER_TREE_LOG, rate = 1000 }, }, - [ID.mob.NIHHUS] = { + [ID.mob.NIHHUS] = + { { item = xi.item.WIVRE_HORN, rate = 1000 }, { item = xi.item.WIVRE_HIDE, rate = 1000 }, { item = xi.item.WIVRE_MAUL, rate = 1000 }, }, + -- Wing 2 - [ID.mob.ANDHRIMNIR] = { + [ID.mob.ANDHRIMNIR] = + { { item = xi.item.CORSE_BRACELET, rate = 1000 }, { item = xi.item.CORSE_ROBE, rate = 1000 }, { item = xi.item.CORSE_BRACELET, rate = 1000 }, }, - [ID.mob.ARIRI_SAMARIRI] = { + [ID.mob.ARIRI_SAMARIRI] = + { { item = xi.item.POROGGO_HAT, rate = 1000 }, { item = xi.item.POROGGO_HAT, rate = 1000 }, { item = xi.item.POROGGO_HAT, rate = 1000 }, }, - [ID.mob.BALRAHN] = { + [ID.mob.BALRAHN] = + { { item = xi.item.SOULFLAYER_TENTACLE, rate = 1000 }, { item = xi.item.SOULFLAYER_STAFF, rate = 1000 }, { item = xi.item.SOULFLAYER_ROBE, rate = 1000 }, }, - [ID.mob.HRUNGNIR] = { + [ID.mob.HRUNGNIR] = + { { item = xi.item.CHUNK_OF_MYTHRIL_ORE, rate = 1000 }, { item = xi.item.GOLEM_SHARD, rate = 1000 }, { item = xi.item.GOLEM_SHARD, rate = 1000 }, }, - [ID.mob.MOKKURALFI] = { + [ID.mob.MOKKURALFI] = + { { item = xi.item.CHUNK_OF_FLAN_MEAT, rate = 1000 }, { item = xi.item.CHUNK_OF_FLAN_MEAT, rate = 1000 }, { item = xi.item.CHUNK_OF_FLAN_MEAT, rate = 1000 }, }, - [ID.mob.TANNGRISNIR] = { + [ID.mob.TANNGRISNIR] = + { { item = xi.item.HANDFUL_OF_DRAGON_SCALES, rate = 1000 }, { item = xi.item.HANDFUL_OF_DRAGON_SCALES, rate = 1000 }, { item = xi.item.DRAGON_TALON, rate = 1000 }, }, + -- Wing 3 - [ID.mob.DENDAINSONNE] = { + [ID.mob.DENDAINSONNE] = + { { item = xi.item.BEHEMOTH_HORN, rate = 1000 }, }, - [ID.mob.FREKE] = { + [ID.mob.FREKE] = + { { item = xi.item.SLICE_OF_CERBERUS_MEAT, rate = 1000 }, - { item = xi.item.CERBERUS_CLAW, rate = 50 }, -- 5% chance + { item = xi.item.CERBERUS_CLAW, rate = 50 }, -- 5% chance }, - [ID.mob.GORGIMERA] = { + [ID.mob.GORGIMERA] = + { { item = xi.item.KHIMAIRA_HORN, rate = 1000 }, - { item = xi.item.KHIMAIRA_MANE, rate = 50 }, -- 5% chance + { item = xi.item.KHIMAIRA_MANE, rate = 50 }, -- 5% chance }, - [ID.mob.MOTSOGNIR] = { + [ID.mob.MOTSOGNIR] = + { { item = xi.item.DEMON_SKULL, rate = 1000 }, }, - [ID.mob.STOORWORM] = { + [ID.mob.STOORWORM] = + { { item = xi.item.CHUNK_OF_HYDRA_MEAT, rate = 1000 }, }, - [ID.mob.VAMPYR_JARL] = { + [ID.mob.VAMPYR_JARL] = + { { item = xi.item.VIAL_OF_DRAGON_BLOOD, rate = 1000 }, }, } -local synthMaterials = { +local synthMaterials = +{ { item = xi.item.GOLD_INGOT, rate = 300, max = 4 }, { item = xi.item.PLATINUM_INGOT, rate = 300, max = 4 }, { item = xi.item.ANGELSTONE, rate = 100, max = 3 }, @@ -96,8 +117,10 @@ local synthMaterials = { { item = xi.item.CHUNK_OF_KHROMA_ORE, rate = 25, max = 1 } } -local abjurations = { - [xi.einherjar.wing.WING_1] = { +local abjurations = +{ + [xi.einherjar.wing.WING_1] = + { xi.item.HADEAN_ABJURATION_HANDS, xi.item.HADEAN_ABJURATION_FEET, xi.item.PHANTASMAL_ABJURATION_HANDS, @@ -108,7 +131,8 @@ local abjurations = { xi.item.NEPTUNAL_ABJURATION_LEGS, xi.item.DRYADIC_ABJURATION_FEET, }, - [xi.einherjar.wing.WING_2] = { + [xi.einherjar.wing.WING_2] = + { xi.item.EARTHEN_ABJURATION_HANDS, xi.item.PHANTASMAL_ABJURATION_HEAD, xi.item.HADEAN_ABJURATION_HEAD, @@ -118,7 +142,8 @@ local abjurations = { xi.item.WYRMAL_ABJURATION_HEAD, xi.item.MARTIAL_ABJURATION_LEGS, }, - [xi.einherjar.wing.WING_3] = { + [xi.einherjar.wing.WING_3] = + { xi.item.PHANTASMAL_ABJURATION_HEAD, xi.item.PHANTASMAL_ABJURATION_LEGS, xi.item.HADEAN_ABJURATION_LEGS, @@ -139,7 +164,7 @@ local function craftingMaterialRewards() local rewards = {} -- Step 1: Roll to determine the number of item types - local roll = math.random(1, 100) + local roll = math.random(1, 100) local numItems = 1 -- Default to 1 item type if roll <= 30 then @@ -155,19 +180,18 @@ local function craftingMaterialRewards() for _ = 1, numItems do -- Roll a random number within the total rate - local itemRoll = math.random(1, 1000) + local itemRoll = math.random(1, 1000) + local cumulativeRate = 0 -- Select item based on the weighted roll - local cumulativeRate = 0 for index, material in ipairs(availableMaterials) do cumulativeRate = cumulativeRate + material.rate if itemRoll <= cumulativeRate then -- Step 3: Apply linear decay formula to determine quantity - local totalWeight = (material.max * (material.max + 1)) / 2 - local quantityRoll = math.random(1, totalWeight) - + local totalWeight = material.max * (material.max + 1) / 2 + local quantityRoll = math.random(1, totalWeight) local cumulativeQuantityWeight = 0 - local quantity = 1 + local quantity = 1 for n = 1, material.max do cumulativeQuantityWeight = cumulativeQuantityWeight + (material.max + 1 - n) @@ -195,12 +219,12 @@ end -- Note: Only for Wing 1-3, no crate in Odin's Chamber xi.einherjar.getArmouryCrateRewards = function(bossId, chamberId) local rewards = {} - local tier = math.ceil(chamberId / 3) + local tier = math.ceil(chamberId / 3) -- 1. Boss specific drops (1-3 guaranteed items, some bosses also have non-guaranteed drops) for _, lootEntry in ipairs(bossDrops[bossId]) do -- Roll each item in the boss table - local itemId = lootEntry.item + local itemId = lootEntry.item local itemRate = lootEntry.rate if math.random(1, 1000) <= itemRate then @@ -226,7 +250,8 @@ end xi.einherjar.getAmpoulesReward = function(chamberId, defeatedCount, totalCount) local completionRate = defeatedCount / totalCount - local baseReward = xi.einherjar.chambers[chamberId].ichor * xi.einherjar.settings.EINHERJAR_ICHOR_RATE + local baseReward = xi.einherjar.chambers[chamberId].ichor * xi.einherjar.settings.EINHERJAR_ICHOR_RATE + return math.floor(baseReward * completionRate) end