landsandboat/scripts/globals/brigands_chart.lua
2026-03-27 11:29:03 -04:00

260 lines
8.7 KiB
Lua

-----------------------------------
-- Brigand's Chart Quest (hidden)
-----------------------------------
-- !additem 1873 -- Brigand's Chart
-- qm1 : !pos -87.5 20 -330.9 118
-----------------------------------
local ID = zones[xi.zone.BUBURIMU_PENINSULA]
-----------------------------------
xi = xi or {}
xi.brigandsChart = xi.brigandsChart or {}
local function removeChest(npc)
npc:setAnimationSub(0, false)
npc:setStatus(xi.status.DISAPPEAR)
npc:resetLocalVars()
end
local function clearChests()
for _, chestId in pairs(ID.npc.JADE_ETUI_TABLE) do
local chest = GetNPCByID(chestId)
if chest then
removeChest(chest)
end
end
end
local function resetEvent()
local qm1 = GetNPCByID(ID.npc.BRIGAND_CHART_QM)
local npcHume = GetNPCByID(ID.npc.BRIGAND_CHART_HUME)
local shimmering = GetNPCByID(ID.npc.SHIMMERING_POINT)
if qm1 then
local player = GetPlayerByID(qm1:getLocalVar('bChartSpawnerID'))
if player and player:getLocalVar('bChartActive') == 1 then
player:setLocalVar('bChartActive', 0)
player:delStatusEffect(xi.effect.LEVEL_RESTRICTION)
player:changeMusic(0, 0)
player:changeMusic(1, 0)
player:changeMusic(2, 101)
player:changeMusic(3, 102)
end
qm1:resetLocalVars()
qm1:setStatus(xi.status.NORMAL)
end
if npcHume then
npcHume:setStatus(xi.status.DISAPPEAR)
npcHume:setAnimation(xi.animation.NONE)
end
if shimmering then
shimmering:setStatus(xi.status.DISAPPEAR)
shimmering:entityAnimationPacket(xi.animationString.STATUS_DISAPPEAR)
end
-- Disappear Jade Etuis
clearChests()
end
local eventTable =
{
-- Event times taken from capture: https://www.youtube.com/watch?v=aQXSByinBn4
[1] = { time = 60, text = ID.text.WHAT_CAN_I_DO + 0 },
[2] = { time = 90, text = ID.text.WHAT_CAN_I_DO + 1 },
[3] = { time = 120, text = ID.text.WHAT_CAN_I_DO + 2 },
[4] = { time = 150, text = ID.text.WHAT_CAN_I_DO + 3 },
[5] = { time = 170, text = ID.text.WHAT_CAN_I_DO + 4 },
[6] = { time = 180, text = ID.text.WHAT_CAN_I_DO + 5 },
}
local function emoteChecking(npc, timeRemaining, timeOfLastCheck, phase)
-- Event continues if player leaves zone
-- https://www.youtube.com/watch?v=_opqVW-HIu0
-- https://discord.com/channels/443544205206355968/446401624102010901/650072608922009660
local currentTime = GetSystemTime()
local newTimeRemaining = timeRemaining - (currentTime - timeOfLastCheck)
local totalTimeElapsed = 180 - newTimeRemaining
-- Check time. Show text and move phase if enough time has passed.
if totalTimeElapsed > eventTable[phase].time then
local spawner = GetPlayerByID(npc:getLocalVar('bChartSpawnerID'))
if spawner then
spawner:showText(npc, eventTable[phase].text)
end
phase = phase + 1
end
if newTimeRemaining > 0 then
npc:timer(1000, function(npcArg)
emoteChecking(npcArg, newTimeRemaining, currentTime, phase)
end)
else
resetEvent()
end
end
xi.brigandsChart.onTrade = function(player, npc, trade)
if
npc:getStatus() == xi.status.NORMAL and
npc:getLocalVar('bChartSpawnerID') == 0 and
npcUtil.tradeHasExactly(trade, xi.item.BRIGANDS_CHART)
then
player:messageSpecial(ID.text.RETURN_TO_SEA, xi.item.BRIGANDS_CHART)
player:startEvent(902)
end
end
xi.brigandsChart.onEventUpdate = function(player, csid, option, npc)
if csid == 902 and option == 0 then
player:confirmTrade()
clearChests()
npc:setLocalVar('bChartSpawnerID', player:getID())
player:setLocalVar('bChartActive', 1)
player:changeMusic(0, 136)
player:changeMusic(1, 136)
player:changeMusic(2, 136)
player:changeMusic(3, 136)
player:addStatusEffect(xi.effect.LEVEL_RESTRICTION, { power = 20, origin = player }) -- level restriction removed by event end
end
end
xi.brigandsChart.onEventFinish = function(player, csid, option, npc)
if csid == 902 and option == 0 then
local npcHume = GetNPCByID(ID.npc.BRIGAND_CHART_HUME)
if not npcHume then
return
end
local shimmering = GetNPCByID(ID.npc.SHIMMERING_POINT)
if not shimmering then
return
end
-- Setup starting conditions
npcHume:setStatus(xi.status.NORMAL)
npcHume:setAnimation(xi.animation.NONE)
npc:setStatus(xi.status.DISAPPEAR)
shimmering:setStatus(xi.status.NORMAL)
-- Appearing packet needs time to finish before another packet can be sent successfully
shimmering:timer(2000, function(shimmerArg)
shimmerArg:entityAnimationPacket(xi.animationString.SHIMMER)
end)
player:showText(npc, ID.text.MY_ITEM, xi.item.PENGUIN_RING)
-- Events will occur for the next 180 seconds according to eventTable
emoteChecking(npc, 180, GetSystemTime(), 1)
end
end
xi.brigandsChart.rewards =
{
common =
{
{
{ itemId = xi.item.BEASTCOIN, weight = xi.loot.weight.NORMAL },
{ itemId = xi.item.BLUE_PITCHER, weight = xi.loot.weight.NORMAL },
{ itemId = xi.item.COPY_OF_LINES_AND_SPACE, weight = xi.loot.weight.VERY_LOW },
{ itemId = xi.item.DWARF_PUGIL, weight = xi.loot.weight.NORMAL },
{ itemId = xi.item.GOLD_BEASTCOIN, weight = xi.loot.weight.LOW },
{ itemId = xi.item.MYTHRIL_BEASTCOIN, weight = xi.loot.weight.LOW },
{ itemId = xi.item.MYTHRIL_SWORD, weight = xi.loot.weight.LOW },
{ itemId = xi.item.ORDELLE_BRONZEPIECE, weight = xi.loot.weight.LOW },
{ itemId = xi.item.ONE_BYNE_BILL, weight = xi.loot.weight.VERY_LOW },
{ itemId = xi.item.PLATINUM_BEASTCOIN, weight = xi.loot.weight.VERY_LOW },
{ itemId = xi.item.RUSTY_CAP, weight = xi.loot.weight.LOW },
{ itemId = xi.item.RUSTY_LEGGINGS, weight = xi.loot.weight.NORMAL },
{ itemId = xi.item.SILVER_BEASTCOIN, weight = xi.loot.weight.NORMAL },
{ itemId = xi.item.SKY_POT, weight = xi.loot.weight.LOW },
{ itemId = xi.item.WOODEN_FLOWERPOT, weight = xi.loot.weight.VERY_LOW },
},
},
special =
{
{
{ itemId = xi.item.NONE, weight = xi.loot.weight.NORMAL },
{ itemId = xi.item.PENGUIN_RING, weight = xi.loot.weight.NORMAL },
},
},
}
xi.brigandsChart.jadeEtuiOnTrigger = function(player, npc)
local qm1 = GetNPCByID(ID.npc.BRIGAND_CHART_QM)
if not qm1 then
return
end
local spawnerID = qm1:getLocalVar('bChartSpawnerID')
if spawnerID == 0 then
-- Event has been reset since this chest spawned, remove it
removeChest(npc)
return
end
if
player:getID() ~= spawnerID or
npc:getLocalVar(xi.animationString.OPEN_CRATE_GLOW) ~= 0
then
return
end
npc:entityAnimationPacket(xi.animationString.OPEN_CRATE_GLOW)
npc:setLocalVar(xi.animationString.OPEN_CRATE_GLOW, 1)
local chestNumber = player:getLocalVar('bChartChestNum')
local rewardTable = {}
local penguinFound = false
-- Fourth or fifth chest, chance to give penguin ring
if chestNumber >= 3 then
local specialReward = utils.selectFromLootGroups(player, xi.brigandsChart.rewards.special)[1]
if
specialReward and
specialReward.itemId == xi.item.PENGUIN_RING
then
table.insert(rewardTable, specialReward.itemId)
table.insert(rewardTable, xi.item.YELLOW_GLOBE)
table.insert(rewardTable, xi.item.YELLOW_GLOBE)
table.insert(rewardTable, xi.item.YELLOW_GLOBE)
penguinFound = true
end
end
if #rewardTable == 0 then
local commonReward = utils.selectFromLootGroups(player, xi.brigandsChart.rewards.common)[1]
table.insert(rewardTable, commonReward.itemId)
end
for _, reward in pairs(rewardTable) do
if reward ~= nil then
player:addTreasure(reward, npc)
end
end
if
penguinFound or
chestNumber > 4
then
-- Event automatically ends once the ring has been found
resetEvent()
else
player:setLocalVar('bChartChestNum', chestNumber + 1)
npc:timer(15000, function(npcArg)
npcArg:entityAnimationPacket(xi.animationString.STATUS_DISAPPEAR)
end)
npc:timer(16000, function(npcArg)
removeChest(npcArg)
end)
end
end