landsandboat/scripts/globals/salvage.lua
2026-02-20 18:42:33 -07:00

557 lines
19 KiB
Lua

-----------------------------------
-- Salvage Global Functions
-----------------------------------
xi = xi or {}
xi.salvage = xi.salvage or {}
-----------------------------------
xi.salvage.onCellItemCheck = function(target, effect, value)
if target:getCurrentRegion() ~= xi.region.ALZADAAL then
return xi.msg.basic.CANT_BE_USED_IN_AREA
end
local statusEffect = target:getStatusEffect(effect)
if statusEffect then
local power = statusEffect:getPower()
if bit.band(power, value) > 0 then
return 0
end
end
return xi.msg.basic.ITEM_UNABLE_TO_USE
end
xi.salvage.onCellItemUse = function(target, effect, value, offset)
local statusEffect = target:getStatusEffect(effect)
local power = statusEffect:getPower()
local duration = math.floor(statusEffect:getTimeRemaining() / 1000)
local newpower = bit.band(power, bit.bnot(value))
local pet = target:getPet()
local instance = target:getInstance()
target:delStatusEffectSilent(effect)
if newpower > 0 then
target:addStatusEffect(effect, { power = newpower, duration = duration, origin = target })
end
if
pet ~= nil and
(
effect == xi.effect.DEBILITATION or
effect == xi.effect.IMPAIRMENT or
effect == xi.effect.OMERTA
)
then
pet:delStatusEffectSilent(effect)
if newpower > 0 then
pet:addStatusEffect(effect, { power = newpower, duration = duration, origin = target })
end
end
target:messageText(target, zones[target:getZoneID()].text.CELL_OFFSET + offset)
instance:setLocalVar('cellsUsed', instance:getLocalVar('cellsUsed') + 1)
end
xi.salvage.instanceRegister = function(player, fireFlies)
for i = xi.slot.MAIN, xi.slot.BACK do
player:unequipItem(i)
end
player:addStatusEffect(xi.effect.ENCUMBRANCE_I, { power = 65535, duration = 6000, origin = player })
player:addStatusEffect(xi.effect.OBLIVISCENCE, { power = 1, duration = 6000, origin = player })
player:addStatusEffect(xi.effect.OMERTA, { power = 63, duration = 6000, origin = player })
player:addStatusEffect(xi.effect.IMPAIRMENT, { power = 3, duration = 6000, origin = player })
player:addStatusEffect(xi.effect.DEBILITATION, { power = 511, duration = 6000, origin = player })
player:addTempItem(fireFlies)
player:delKeyItem(xi.ki.REMNANTS_PERMIT)
end
xi.salvage.onFailure = function(instance)
local chars = instance:getChars()
local mobs = instance:getMobs()
for _, mob in pairs(mobs) do
DespawnMob(mob:getID(), instance)
end
if #chars > 0 then
for _, player in ipairs(chars) do
local ID = zones[player:getZoneID()]
player:messageSpecial(ID.text.MISSION_FAILED, 10, 10)
player:startCutscene(1)
end
end
end
xi.salvage.onTransportUpdate = function(player, instance)
if instance:getLocalVar('transportUser') == 0 then
local chars = instance:getChars()
instance:setLocalVar('transportUser', player:getID())
instance:setLocalVar('stageComplete', 0)
xi.salvage.resetTempBoxes(player)
xi.salvage.deSpawnStage(instance)
for _, target in pairs(chars) do
if target:getID() ~= player:getID() then
if target:isInEvent() then
target:release()
end
end
end
player:timer(10000, function(playerArg)
instance:setLocalVar('transportUser', 0)
end)
else
return
end
end
xi.salvage.teleportGroup = function(target)
local instance = target:getInstance()
local chars = instance:getChars()
local pos = target:getPos()
local csid = target:getZoneID() == xi.zone.BHAFLAU_REMNANTS and 4 or 3
for _, players in pairs(chars) do
if players:getID() ~= target:getID() then
players:startCutscene(csid)
players:timer(4000, function(targetArg)
targetArg:setPos(pos.x, pos.y, pos.z, pos.rot)
targetArg:setHP(targetArg:getMaxHP())
targetArg:setMP(targetArg:getMaxMP())
local pet = targetArg:getPet()
if pet then
pet:setPos(pos.x, pos.y, pos.z, pos.rot)
pet:setHP(pet:getMaxHP())
pet:setMP(pet:getMaxMP())
end
end)
end
end
end
xi.salvage.onDoorOpen = function(npc, stage, progress)
local instance = npc:getInstance()
local result = false
if
npc:getAnimation() == xi.animation.CLOSE_DOOR and
npc:getLocalVar('unSealed') == 1
then
npc:setLocalVar('unSealed', 0)
if stage ~= nil then
instance:setStage(stage)
end
if progress ~= nil then
instance:setProgress(progress)
end
npc:setAnimation(xi.animation.OPEN_DOOR)
npc:setUntargetable(true)
result = true
end
return result
end
xi.salvage.sealDoors = function(instance, indexID)
if type(indexID) == 'table' then
for _, id in pairs(indexID) do
local door = GetNPCByID(id, instance)
if door then
door:setLocalVar('unSealed', 0)
end
end
else
local door = GetNPCByID(indexID, instance)
if door then
door:setLocalVar('unSealed', 0)
end
end
end
xi.salvage.unsealDoors = function(instance, indexID)
if type(indexID) == 'table' then
for _, id in pairs(indexID) do
local door = GetNPCByID(id, instance)
if door then
door:setLocalVar('unSealed', 1)
end
end
else
local door = GetNPCByID(indexID, instance)
if door then
door:setLocalVar('unSealed', 1)
end
end
end
xi.salvage.openBossDoor = function(npc)
if npc:getAnimation() == xi.anim.CLOSE_DOOR then
local instance = npc:getInstance()
npc:openDoor(15)
npc:queue(3000, function(npcArg)
GetNPCByID(npcArg:getID() -1, instance):openDoor(10)
end)
end
end
xi.salvage.onTriggerCrate = function(player, npc)
if npc:getLocalVar('open') == 0 then
npc:setLocalVar('open', 1)
local firstRandom =
{
xi.item.CUMULUS_CELL,
xi.item.UNDULATUS_CELL,
xi.item.HUMILUS_CELL,
xi.item.SPISSATUS_CELL
}
local secondRandom =
{
xi.item.CASTELLANUS_CELL,
xi.item.RADIATUS_CELL,
xi.item.STRATUS_CELL,
xi.item.CIRROCUMULUS_CELL,
xi.item.VIRGA_CELL,
xi.item.PANNUS_CELL,
xi.item.FRACTUS_CELL,
xi.item.CONGESTUS_CELL,
xi.item.NIMBUS_CELL,
xi.item.VELUM_CELL,
xi.item.PILEUS_CELL,
xi.item.MEDIOCRIS_CELL
}
player:addTreasure(xi.item.INCUS_CELL, npc)
player:addTreasure(xi.item.INCUS_CELL, npc)
player:addTreasure(xi.item.DUPLICATUS_CELL, npc)
player:addTreasure(xi.item.PRAECIPITATIO_CELL, npc)
player:addTreasure(xi.item.OPACUS_CELL, npc)
player:addTreasure(firstRandom[math.random(#firstRandom)], npc)
player:addTreasure(firstRandom[math.random(#firstRandom)], npc)
player:addTreasure(secondRandom[math.random(#secondRandom)], npc)
player:addTreasure(secondRandom[math.random(#secondRandom)], npc)
if math.random(1, 2) == 1 then
player:addTreasure(xi.item.PRAECIPITATIO_CELL, npc)
else
player:addTreasure(xi.item.OPACUS_CELL, npc)
end
npc:entityAnimationPacket('open')
npc:timer(15000, function(npcArg)
npcArg:entityAnimationPacket('kesu')
end)
npc:timer(16000, function(npcArg)
npcArg:setStatus(xi.status.DISAPPEAR)
end)
end
end
xi.salvage.handleSlot = function(player, npc, trade, card, mobID)
if npcUtil.tradeHasExactly(trade, card) then
local instance = npc:getInstance()
SpawnMob(mobID, instance):updateClaim(player)
player:confirmTrade()
npc:setStatus(xi.status.DISAPPEAR)
end
end
xi.salvage.handleSocket = function(player, npc, trade, mobID)
local instance = npc:getInstance()
local mob = GetMobByID(mobID, instance)
local cellCount = trade:getItemCount()
for cellType = xi.item.INCUS_CELL, xi.item.SPISSATUS_CELL do
if cellCount <= 5 and trade:hasItemQty(cellType, cellCount) then
player:tradeComplete()
if mob then
SpawnMob(mobID, instance):updateClaim(player)
mob:setLocalVar('tradedCell', cellType)
mob:setLocalVar('cellCount', cellCount)
npc:setStatus(xi.status.DISAPPEAR)
end
end
end
end
xi.salvage.handleSocketCells = function(mob, player)
local amount = mob:getLocalVar('cellCount') * 2
while amount > 0 do
player:addTreasure(mob:getLocalVar('tradedCell'), mob)
amount = amount - 1
end
end
xi.salvage.spawnGroup = function(instance, indexID)
if indexID then
for _, enemies in pairs(indexID) do
if type(enemies) == 'table' then
for _, groups in pairs(enemies) do
if type(groups) == 'table' then
for _, subGroups in pairs(groups) do
SpawnMob(subGroups, instance)
GetMobByID(subGroups, instance):setLocalVar('spawned', 1)
end
else
SpawnMob(groups, instance)
GetMobByID(groups, instance):setLocalVar('spawned', 1)
end
end
else
SpawnMob(enemies, instance)
GetMobByID(enemies, instance):setLocalVar('spawned', 1)
end
end
end
end
xi.salvage.groupKilled = function(instance, indexID)
for _, enemies in pairs(indexID) do
if type(enemies) == 'table' then
for _, groups in pairs(enemies) do
if type(groups) == 'table' then
for _, subGroups in pairs(groups) do
local mob = GetMobByID(subGroups, instance)
if mob and mob:getLocalVar('spawned') == 0 then
return false
elseif mob and mob:isAlive() then
return false
end
end
else
local mob = GetMobByID(groups, instance)
if mob and mob:getLocalVar('spawned') == 0 then
return false
elseif mob and mob:isAlive() then
return false
end
end
end
else
local mob = GetMobByID(enemies, instance)
if mob and mob:getLocalVar('spawned') == 0 then
return false
elseif mob and mob:isAlive() then
return false
end
end
end
return true
end
xi.salvage.deSpawnStage = function(instance)
local mobs = instance:getMobs()
for _, enemy in pairs(mobs) do
DespawnMob(enemy:getID(), instance)
end
end
xi.salvage.resetTempBoxes = function(player)
local ID = zones[player:getZoneID()]
local instance = player:getInstance()
local tempBoxes = utils.slice(ID.npc.ARMOURY_CRATE, 2, #ID.npc.ARMOURY_CRATE)
local staticBoxes = ID.npc.STATIC_TEMP_BOX
if tempBoxes then
for _, casketID in ipairs(tempBoxes) do
local casket = GetNPCByID(casketID, instance)
if casket and casket:getStatus() == xi.status.NORMAL then
casket:setStatus(xi.status.DISAPPEAR)
casket:resetLocalVars()
casket:setAnimationSub(8)
end
end
end
if staticBoxes then
for _, casketID in ipairs(staticBoxes) do
local casket = GetNPCByID(casketID, instance)
if casket and casket:getStatus() == xi.status.NORMAL then
casket:setStatus(xi.status.DISAPPEAR)
casket:resetLocalVars()
casket:setAnimationSub(8)
end
end
end
end
xi.salvage.spawnTempChest = function(mob, params)
local ID = zones[mob:getZoneID()]
local instance = mob:getInstance()
-- default params
if not params then
params = {}
end
if params.rate == nil then
if mob:getZoneID() == xi.zone.ARRAPAGO_REMNANTS then
params.rate = 300
else
params.rate = 40
end
end
if params.rate ~= 0 then
if params.rate < math.random(1, 1000) then
return
end
end
if params.itemID_1 == nil or type(params.itemID_1) ~= 'number' then
params.itemID_1 = false
end
for _, casketID in ipairs(utils.slice(ID.npc.ARMOURY_CRATE, 2, #ID.npc.ARMOURY_CRATE)) do
local casket = GetNPCByID(casketID, instance)
if casket and casket:getStatus() == xi.status.DISAPPEAR then
local pos = mob:getPos()
casket:setPos(pos.x, pos.y, pos.z, pos.rot)
casket:resetLocalVars()
casket:setStatus(xi.status.NORMAL)
if params.itemID_1 then
casket:setLocalVar('prePicked', 1)
casket:setLocalVar('itemID_1', params.itemID_1)
casket:setLocalVar('itemAmount_1', params.itemAmount_1)
end
if params.specialAmount then
casket:setLocalVar(params.special, params.specialAmount)
end
break
end
end
end
xi.salvage.tempBoxTrigger = function(player, npc)
if npc:getLocalVar('itemsPicked') == 0 then
npc:setLocalVar('itemsPicked', 1)
npc:entityAnimationPacket('open')
npc:setAnimationSub(13)
if npc:getLocalVar('prePicked') == 0 then
xi.salvage.tempBoxPickItems(npc)
end
end
player:startEvent(2,
{
[0] = (npc:getLocalVar('itemID_1') + (npc:getLocalVar('itemAmount_1') * 65536)),
[1] = (npc:getLocalVar('itemID_2') + (npc:getLocalVar('itemAmount_2') * 65536)),
[2] = (npc:getLocalVar('itemID_3') + (npc:getLocalVar('itemAmount_3') * 65536)),
[3] = (npc:getLocalVar('itemID_4') + (npc:getLocalVar('itemAmount_4') * 65536)),
[4] = (npc:getLocalVar('itemID_5') + (npc:getLocalVar('itemAmount_5') * 65536)),
[5] = (npc:getLocalVar('itemID_6') + (npc:getLocalVar('itemAmount_6') * 65536)),
[6] = (npc:getLocalVar('itemID_7') + (npc:getLocalVar('itemAmount_7') * 65536))
})
end
xi.salvage.tempBoxPickItems = function(npc)
local tempBoxItems =
{
[1] = { itemID = xi.item.BOTTLE_OF_BARBARIANS_DRINK, amount = math.random(1, 3) },
[2] = { itemID = xi.item.BOTTLE_OF_FIGHTERS_DRINK, amount = math.random(1, 3) },
[3] = { itemID = xi.item.BOTTLE_OF_ORACLES_DRINK, amount = math.random(1, 3) },
[4] = { itemID = xi.item.BOTTLE_OF_ASSASSINS_DRINK, amount = math.random(1, 3) },
[5] = { itemID = xi.item.BOTTLE_OF_SPYS_DRINK, amount = math.random(1, 3) },
[6] = { itemID = xi.item.BOTTLE_OF_BRAVERS_DRINK, amount = math.random(1, 3) },
[7] = { itemID = xi.item.BOTTLE_OF_SOLDIERS_DRINK, amount = math.random(1, 3) },
[8] = { itemID = xi.item.BOTTLE_OF_CHAMPIONS_DRINK, amount = math.random(1, 3) },
[9] = { itemID = xi.item.BOTTLE_OF_MONARCHS_DRINK, amount = math.random(1, 3) },
[10] = { itemID = xi.item.BOTTLE_OF_GNOSTICS_DRINK, amount = math.random(1, 3) },
[11] = { itemID = xi.item.BOTTLE_OF_CLERICS_DRINK, amount = math.random(1, 3) },
[12] = { itemID = xi.item.BOTTLE_OF_SHEPHERDS_DRINK, amount = math.random(1, 3) },
[13] = { itemID = xi.item.BOTTLE_OF_SPRINTERS_DRINK, amount = math.random(1, 3) },
[14] = { itemID = xi.item.FLASK_OF_STRANGE_MILK, amount = math.random(1, 5) },
[15] = { itemID = xi.item.BOTTLE_OF_STRANGE_JUICE, amount = math.random(1, 5) },
[16] = { itemID = xi.item.BOTTLE_OF_FANATICS_DRINK, amount = 1 },
[17] = { itemID = xi.item.BOTTLE_OF_FOOLS_DRINK, amount = 1 },
[18] = { itemID = xi.item.DUSTY_WING, amount = 1 },
[19] = { itemID = xi.item.BOTTLE_OF_VICARS_DRINK, amount = math.random(1, 3) },
[20] = { itemID = xi.item.DUSTY_POTION, amount = math.random(1, 10) },
[21] = { itemID = xi.item.DUSTY_ETHER, amount = math.random(1, 10) },
[22] = { itemID = xi.item.DUSTY_ELIXIR, amount = 1 }
}
local chosen1 = math.random(1, #tempBoxItems)
local item1 = tempBoxItems[chosen1]
local item2random = math.random(1, 10) > 4
local item3random = math.random(1, 10) > 8
if npc:getLocalVar('itemID_1') == 0 then
npc:setLocalVar('itemID_1', item1.itemID)
npc:setLocalVar('itemAmount_1', item1.amount)
table.remove(tempBoxItems, chosen1)
end
if item2random then
local chosen2 = math.random(1, #tempBoxItems)
local item2 = tempBoxItems[chosen2]
npc:setLocalVar('itemID_2', item2.itemID)
npc:setLocalVar('itemAmount_2', item2.amount)
table.remove(tempBoxItems, chosen2)
end
if item3random then
local chosen3 = math.random(1, #tempBoxItems)
local item3 = tempBoxItems[chosen3]
npc:setLocalVar('itemID_3', item3.itemID)
npc:setLocalVar('itemAmount_3', item3.amount)
table.remove(tempBoxItems, chosen3)
end
end
xi.salvage.tempBoxFinish = function(player, csid, option, npc)
local ID = zones[player:getZoneID()]
if csid == 2 then
for choice = 1, 8 do
if option == choice then
local item = npc:getLocalVar('itemID_'..choice)
local itemQnty = npc:getLocalVar('itemAmount_'..choice)
if item > 0 and itemQnty > 0 then
if not player:hasItem(item, xi.inventoryLocation.TEMPITEMS) then
player:addTempItem(item)
player:messageSpecial(ID.text.TEMP_ITEM, item)
npc:setLocalVar('itemAmount_'..choice, itemQnty - 1)
else
player:messageSpecial(ID.text.HAVE_TEMP_ITEM)
end
end
end
end
-- despawn box if no items left
if
npc:getLocalVar('itemAmount_1') == 0 and
npc:getLocalVar('itemAmount_2') == 0 and
npc:getLocalVar('itemAmount_3') == 0 and
npc:getLocalVar('itemAmount_4') == 0 and
npc:getLocalVar('itemAmount_5') == 0 and
npc:getLocalVar('itemAmount_6') == 0 and
npc:getLocalVar('itemAmount_7') == 0
then
npc:queue(10000, function(npcArg)
npcArg:entityAnimationPacket('kesu')
end)
npc:queue(12000, function(npcArg)
npcArg:setStatus(xi.status.DISAPPEAR)
npc:setAnimationSub(8)
end)
end
end
end