landsandboat/scripts/globals/znm.lua

771 lines
24 KiB
Lua

-----------------------------------
-- Zeni NM System + Helpers
--
-- Soultrapper : !additem 18721
-- Blank Soul Plate : !additem 18722
-- Soultrapper 2000 : !additem 18724
-- Blank HS Soul Plate : !additem 18725
-- Soul Plate : !additem 2477
-- Sanraku & Ryo : !pos -127.0 0.9 22.6 50
-----------------------------------
local ID = zones[xi.zone.AHT_URHGAN_WHITEGATE]
-----------------------------------
xi = xi or {}
xi.znm = xi.znm or {}
-----------------------------------
-- Sanraku's Interest and Recommended Fauna
-- Applies bonuses to soul plate zeni-value
-----------------------------------
-- Called during JstMidnight tick
xi.znm.UpdateSanrakusMobs = function()
SetServerVariable('[ZNM][Sanraku]Interest', math.random(#xi.znm.SANRAKUS_INTEREST))
SetServerVariable('[ZNM][Sanraku]Fauna', math.random(#xi.znm.SANRAKUS_FAUNA))
SetServerVariable('[ZNM][Sanraku]Trades', math.random(0, 250))
end
xi.znm.serverPlateTrades = function()
local currentTrades = GetServerVariable('[ZNM][Sanraku]Trades')
if currentTrades >= 500 then
xi.znm.UpdateSanrakusMobs()
else
SetServerVariable('[ZNM][Sanraku]Trades', currentTrades + 1)
end
end
-- Get Sanraku's 'Subject of Interest'
xi.znm.getSanrakusInterest = function()
local interest = GetServerVariable('[ZNM][Sanraku]Interest')
-- Initialize the server var if it hasn't been already
if interest == nil or interest == 0 then
interest = math.random(#xi.znm.SANRAKUS_INTEREST)
SetServerVariable('[ZNM][Sanraku]Interest', interest)
end
return interest
end
-- Get Sanraku's 'Recommended Fauna'
xi.znm.getSanrakusFauna = function()
local fauna = GetServerVariable('[ZNM][Sanraku]Fauna')
-- Initialize the server var if it hasn't been already
if fauna == nil or fauna == 0 then
fauna = math.random(#xi.znm.SANRAKUS_FAUNA)
SetServerVariable('[ZNM][Sanraku]Fauna', fauna)
end
return fauna
end
--- Is this mob Sanraku's current 'Recommended Fauna'?
xi.znm.isCurrentFauna = function(plateData)
local zoneID = plateData.zoneId
local mobName = plateData.signature
local faunaRow = xi.znm.SANRAKUS_FAUNA[xi.znm.getSanrakusFauna()]
if faunaRow.zone ~= zoneID then
return false
else
if type(faunaRow.name) == 'table' then
for iter = 1, #faunaRow.name do
if faunaRow.name[iter] == mobName then
return true
end
end
else
if faunaRow.name == mobName then
return true
end
end
end
return false
end
-- Main interest objective
xi.znm.isCurrentFamily = function(plateData)
local family = plateData.familyId
local currectInterest = xi.znm.getSanrakusInterest()
local interestRow = xi.znm.SANRAKUS_INTEREST[currectInterest]
if family == interestRow.family then
-- Handle elementals as all have same family
if currectInterest >= 45 and currectInterest <= 51 then
if plateData.signature ~= interestRow.name then
return false
end
end
return true
end
return false
end
-- Secondary interest objective
xi.znm.isCurrentEcosystem = function(plateData)
local family = plateData.familyId
local currectInterest = xi.znm.getSanrakusInterest()
local interestRow = xi.znm.SANRAKUS_INTEREST[currectInterest]
if utils.contains(family, interestRow.ecoSystem) then
return true
end
return false
end
xi.znm.calculatePlateZeni = function(player, plateData)
-- Cache the soulplate value on the player
local zeni = plateData.quality
local bonus = 'none'
if xi.znm.isCurrentFauna(plateData) then
zeni = zeni + xi.znm.SOULPLATE_FAUNA
bonus = 'Fauna'
elseif xi.znm.isCurrentFamily(plateData) then
zeni = zeni + xi.znm.SOULPLATE_INTEREST
bonus = 'family'
elseif xi.znm.isCurrentEcosystem(plateData) then
zeni = zeni + xi.znm.SOULPLATE_ECOSYSTEM
bonus = 'ecoSystem'
end
utils.unused(bonus)
-- to avoid pictures being handed to low level chars, adding this check
-- low level chars get 1/3 less when they take the pic, customizing to also affect trade in.
if player:getMainLvl() <= 10 then
zeni = zeni / 3
end
zeni = utils.clamp(zeni, xi.znm.SOULPLATE_MIN_VALUE, xi.znm.SOULPLATE_MAX_VALUE)
-- if player:getDebugMode() then
-- player:printToPlayer(string.format('name: %s zeni %i, bonus: %s', plateData.signature, zeni, bonus))
-- end
return zeni
end
-----------------------------------
-- Soultrapper
-----------------------------------
xi.znm.soultrapper = xi.znm.soultrapper or {}
-----------------------------------
-- onItemCheck
-----------------------------------
xi.znm.soultrapper.onItemCheck = function(target, item, caster)
-- can not be used on non mobs or Structure type mobs
if
not target:isMob() or
(target:getSpecies() >= 370 and target:getSpecies() <= 379) -- All structures
then
return xi.msg.basic.ITEM_CANNOT_USE_TARGET
end
if
caster:hasStatusEffect(xi.effect.INVISIBLE) or
caster:hasStatusEffect(xi.effect.SNEAK) or
caster:hasStatusEffect(xi.effect.DEODORIZE) or
caster:hasStatusEffect(xi.effect.HIDE) or
caster:hasStatusEffect(xi.effect.CAMOUFLAGE)
then
return xi.msg.basic.ITEM_NO_USE_SNEAK, caster:getEquipID(xi.slot.RANGED)
end
local id = caster:getEquipID(xi.slot.AMMO)
if
id ~= xi.item.BLANK_SOUL_PLATE and
id ~= xi.item.BLANK_HIGH_SPEED_SOUL_PLATE
then
return xi.msg.basic.ITEM_NO_ITEMS_EQUIPPED
end
if caster:getFreeSlotsCount() == 0 then
return xi.msg.basic.FULL_INVENTORY
end
return 0
end
-----------------------------------
-- onItemUse
-----------------------------------
xi.znm.soultrapper.onItemUse = function(target, player, item)
-- Soul plate not guaranteed
-- to validate long term: some posts hint at level correction on success rate vs. higher level mobs.
if math.random(100) > xi.znm.SOULTRAPPER_SUCCESS * xi.znm.SOULPLATE_HS_MULT then
-- todo, message should show to all in area
player:timer(4000, function(playerArg)
playerArg:messageBasic(xi.msg.basic.SOULTRAPPER_FAILED)
end)
player:removeAmmo(1)
else
-- Deduct blank soul plate
player:removeAmmo(1)
-- Determine quality starting value
local quality = xi.znm.soultrapper.getZeniValue(target, player)
-- Pick a skill totally at random...
local skillIndex, skillEntry = xi.pankration.getRandomFeralSkill(target)
-- Add plate
local plate = player:addItem({ id = xi.item.SOUL_PLATE, silent = true })
if plate then
plate:setExData({
signature = target:getName(),
zoneId = target:getZoneID(),
familyId = target:getFamily(),
poolId = target:getPool(),
level = target:getMainLvl(),
quality = quality,
feralSkill = skillIndex,
feralPoints = skillEntry.fp,
})
end
-- todo, message should show to all in area
player:timer(4000, function(playerArg)
playerArg:messageBasic(xi.msg.basic.SOULTRAPPER_SUCCESS, 0, xi.item.SOUL_PLATE)
end)
end
end
-----------------------------------
-- onItemUse Helpers
-----------------------------------
xi.znm.soultrapper.getZeniValue = function(target, player)
local hpp = target:getHPP()
local isNM = target:isNM()
local distance = player:checkDistance(target)
local isFacing = target:isFacing(player)
local level = target:getMainLvl()
-- Starting value
local zeni = 10
-- Distance Component
zeni = zeni * utils.clamp((1 / distance) * 8, 1, 1.5)
-- Size Component
zeni = zeni + (target:getHitboxSize() * 5) -- needs verification
-- Angle/Facing Component
if isFacing then
zeni = zeni * xi.znm.SOULPLATE_FACING_MULT
end
-- HP% Component
zeni = zeni * 1 + math.abs(hpp - 100) / 6
if
target:getSpecies() == xi.mobSpecies.EUVHI and
target:getZoneID() == 33
then -- Dahak and Aw'euvhi
zeni = zeni + xi.znm.SOULPLATE_UNIQUE_AMOUNT
elseif
target:getSpecies() == xi.mobSpecies.CHIGOE or
target:getSpecies() == xi.mobSpecies.DJIGGA
then -- chigoe penalty
zeni = zeni - xi.znm.SOULPLATE_UNIQUE_AMOUNT
-- Generic NM/Rarity Component
elseif isNM then
if level >= 80 then
zeni = zeni * xi.znm.SOULPLATE_HNM_MULT
else
zeni = zeni * xi.znm.SOULPLATE_NM_MULT
end
end
-- level component. dependent on mob level, not player. need to validate level above 75 to see if the values are the same to prove/disprove
if level < 75 then
zeni = zeni - (75 - level)
else
zeni = zeni + (level - 75)
end
zeni = utils.clamp(zeni, xi.znm.SOULPLATE_MIN_VALUE, xi.znm.SOULPLATE_MAX_VALUE)
-- Add a little randomness
zeni = zeni + math.random(6)
-- Having claim on the mob you take pictures of increases Zeni reward significantly.
-- If another party has claim on the mob, you will only receive 1-5 Zeni for the pictures you take, even in the best possible situation.
if not player:hasClaim(target) then
zeni = math.max(1, zeni * 0.01)
end
if player:getMainLvl() <= 10 then
zeni = zeni / 3
end
-- Sanitize Zeni
zeni = math.floor(zeni) -- Remove any floating point information
zeni = utils.clamp(zeni, xi.znm.SOULPLATE_MIN_VALUE, xi.znm.SOULPLATE_MAX_VALUE)
return zeni
end
-----------------------------------
-- Ryo
-----------------------------------
xi.znm.ryo = xi.znm.ryo or {}
-----------------------------------
-- onTrade
-----------------------------------
xi.znm.ryo.onTrade = function(player, npc, trade)
if npcUtil.tradeHasExactly(trade, xi.item.SOUL_PLATE) then
-- Cache the soulplate value on the player
local item = trade:getItem(0)
local zeni = xi.znm.calculatePlateZeni(player, item:getExData())
xi.znm.ryo.setTradedPlateValue(player, zeni)
player:startEvent(914)
end
end
-----------------------------------
-- onTrigger
-----------------------------------
xi.znm.ryo.onTrigger = function(player, npc)
if xi.znm.playerHasSpokenToSanrakuBefore(player) then
player:startEvent(913)
else
player:showText(npc, ID.text.MASTER_FORBID)
end
end
-----------------------------------
-- onEventUpdate
-----------------------------------
xi.znm.ryo.onEventUpdate = function(player, csid, option, npc)
if csid == 914 then -- Get approximate value of traded soulplate
local zeniValue = xi.znm.ryo.tradedPlateValue(player)
xi.znm.ryo.setTradedPlateValue(player, 0)
player:updateEvent(zeniValue)
elseif csid == 913 then
if option == 200 then -- 'Sanraku's subject of interest'
local param = xi.znm.getSanrakusInterest()
player:updateEvent(param, 0)
elseif option == 201 then -- 'Sanraku's recommended fauna'
local param = xi.znm.getSanrakusFauna()
player:updateEvent(param, 0)
elseif option == 300 then -- 'My zeni balance'
player:updateEvent(player:getCurrency('zeni_point'), 0)
elseif option == 401 and player:getVar('ZeniStatus') == 1 then
player:setVar('ZeniStatus', 2)
elseif option == 402 and player:getVar('ZeniStatus') == 2 then -- ask about gaining access to islet's
player:setVar('ZeniStatus', 3)
elseif option == 404 then
local menuOptions = 175
local zeni = player:getCurrency('zeni_point')
if player:getVar('ZeniStatus') >= 2 then -- add 'sanrakus subject of interest' and 'recommended fauna'
menuOptions = menuOptions - 12
end
if zeni ~= 0 then -- add 'whats zeni' and 'my zeni balance' and 'islet's'
menuOptions = menuOptions - 131
if zeni >= 1000 then
menuOptions = menuOptions - 32
end
end
player:updateEvent(menuOptions)
else
player:updateEvent(0, 0)
end
end
end
xi.znm.ryo.onEventFinish = function(player, csid, option, npc)
if csid == 914 then
local item = player:getTrade():getItem()
if item then
item:setReservedValue(0)
end
player:getTrade():clean()
end
end
-----------------------------------
-- Ryo General Helpers
-----------------------------------
xi.znm.ryo.tradedPlateValue = function(player)
return player:getLocalVar('[ZNM][Ryo]SoulPlateValue')
end
xi.znm.ryo.setTradedPlateValue = function(player, zeni)
player:setLocalVar('[ZNM][Ryo]SoulPlateValue', zeni)
end
-----------------------------------
-- Sanraku
-----------------------------------
xi.znm.sanraku = xi.znm.sanraku or {}
-----------------------------------
-- onTrade
-----------------------------------
xi.znm.sanraku.onTrade = function(player, npc, trade)
if trade:getItemCount() == 1 then -- One soul plate or trophy at a time
local item = trade:getItem(0)
if trade:getItemId() == xi.item.SOUL_PLATE then
xi.znm.sanraku.handleTradeWithPlate(player, npc, item)
else -- Check Trophy trading (for ZNM seals)
xi.znm.sanraku.handleTradeWithTrophy(player, npc, item)
end
end
end
-----------------------------------
-- onTrade Helpers
-----------------------------------
xi.znm.sanraku.handleTradeWithPlate = function(player, npc, item)
if not player:hasKeyItem(xi.ki.RHAPSODY_IN_AZURE) then
local tradeLimit = xi.znm.SOULPLATE_TRADE_LIMIT
if xi.znm.sanraku.platesTradedToday(player) >= tradeLimit then
player:showText(npc, ID.text.APPRECIATE_MORE, 1, xi.item.SOUL_PLATE, tradeLimit)
local tradeItem = player:getTrade():getItem()
if tradeItem then
tradeItem:setReservedValue(0)
end
player:getTrade():clean()
return
end
else -- If you have the KI, clear out the tracking vars!
xi.znm.resetDailyTrackingVars(player)
end
-- Cache the soulplate value on the player
local zeni = xi.znm.calculatePlateZeni(player, item:getExData())
xi.znm.sanraku.setTradedPlateValue(player, zeni)
xi.znm.serverPlateTrades()
player:startEvent(910, zeni)
end
xi.znm.sanraku.platesTradedToday = function(player)
local currentDay = VanadielUniqueDay()
local storedDay = xi.znm.playerTradingDay(player)
if currentDay ~= storedDay then
xi.znm.resetDailyTrackingVars(player)
return 0
end
return xi.znm.numberOfTradedPlates(player)
end
xi.znm.sanraku.handleTradeWithTrophy = function(player, npc, item)
local znmSeal = xi.znm.TROPHIES[item:getID()]
if znmSeal ~= nil then
if player:hasKeyItem(znmSeal) then
player:showText(npc, ID.text.SINGLE_TALLY)
else
xi.znm.sanraku.setTradedTrophySeal(player, znmSeal)
player:startEvent(912, 0, 0, 1, znmSeal)
end
end
end
-----------------------------------
-- onTrigger
-----------------------------------
xi.znm.sanraku.onTrigger = function(player, npc)
-- ZNM and Zeni Ineractions
if xi.znm.playerHasSpokenToSanrakuBefore(player) then
if player:getCurrency('zeni_point') ~= 0 then
local param = xi.znm.sanraku.menu(player)
player:startEvent(909, param)
else
player:showText(npc, ID.text.HOPES_REST)
end
else -- First time introduction
player:startEvent(908)
end
end
-----------------------------------
-- onTrigger Helpers
-----------------------------------
-- Update Sanraku's ZNM menu (csid 909) based on owned seals
xi.znm.sanraku.menu = function(player)
-- Default: Tier 1 ZNMs + 'Don't Ask'
-- (if bit = 0: add ZNM to Sanraku's Menu)
local param = xi.znm.DefaultMenu
for bitmask, seal in pairs(xi.znm.MENU_BITMASKS) do
-- Check for each key item
if type(seal) == 'table' then -- Higher tier ZNMs require 3 seals
if
player:hasKeyItem(seal[1]) and
player:hasKeyItem(seal[2]) and
player:hasKeyItem(seal[3])
then
param = bit.band(param, bit.bnot(bitmask))
end
else
if player:hasKeyItem(seal) then
param = bit.band(param, bit.bnot(bitmask))
end
end
end
return param
end
-----------------------------------
-- onEventUpdate
-----------------------------------
xi.znm.sanraku.onEventUpdate = function(player, csid, option, npc)
if csid == 909 then
if option == 1 or option == 500 then -- adding islets menu
local param = player:getVar('ZeniStatus') >= 3 and 1 or 0
player:updateEvent(param)
elseif option >= 300 and option <= 302 then -- 'Gaining access to islets'
xi.znm.sanraku.handleGainingAccessToIslets(player, option)
elseif option >= 100 and option <= 130 then -- Are you sure you want info on <ZNM_mob>?
xi.znm.sanraku.handleConfirmingDesiredZNMInfo(player, option)
elseif option >= 400 and option <= 440 then -- Yes, I want info on <ZNM_mob>
xi.znm.sanraku.handleConfirmedZNMInfo(player, option)
end
end
end
-----------------------------------
-- onEventUpdate Helpers
-----------------------------------
xi.znm.sanraku.handleGainingAccessToIslets = function(player, option)
local zeniCost = 500 -- Base cost charged by Sanraku
if player:hasKeyItem(xi.keyItem.RHAPSODY_IN_AZURE) then -- Reduced zeni cost
zeniCost = 50
end
-- Give the correct island's information + salt
local keyItem = xi.ki.SICKLEMOON_SALT + option - 300
if player:getCurrency('zeni_point') < zeniCost then -- Not enough zeni
player:updateEvent(2)
elseif player:hasKeyItem(keyItem) then -- Already have the salt
player:showText(GetNPCByID(ID.npc.SANRAKU), ID.text.ALREADY_IN_POSSESSION)
else
player:addKeyItem(keyItem)
player:delCurrency('zeni_point', zeniCost)
player:updateEvent(1, zeniCost, 0, keyItem)
end
end
xi.znm.sanraku.handleConfirmingDesiredZNMInfo = function(player, option)
-- Give the correct ZNM's zeni cost
local diff = option - 99
local zeniCost = xi.znm.getPopPrice(xi.znm.POP_ITEMS[diff].mob, xi.znm.POP_ITEMS[diff].tier)
player:updateEvent(0, 0, 0, 0, 0, 0, zeniCost)
end
xi.znm.sanraku.handleConfirmedZNMInfo = function(player, option)
-- (440 because Warden's option is offset by 10 for some reason)
local diff = math.min(option - 399, 31) -- Determine the desired ZNM
local popItem = xi.znm.POP_ITEMS[diff].item
local znmTier = xi.znm.POP_ITEMS[diff].tier
local mob = xi.znm.POP_ITEMS[diff].mob
local zeniCost = xi.znm.getPopPrice(mob, znmTier)
if player:getCurrency('zeni_point') < zeniCost then -- Not enough zeni
player:updateEvent(2)
elseif player:getFreeSlotsCount() == 0 then -- No inventory space
player:updateEvent(4)
elseif player:hasItem(popItem) then -- Own pop already
player:updateEvent(4)
else
-- Deduct zeni from player, increase future pop-item costs
player:delCurrency('zeni_point', zeniCost)
xi.znm.updatePopPrice(mob, znmTier)
-- Give the pop item and remove the corresponding seal(s), if applicable
player:addItem(popItem)
local seal = xi.znm.POP_ITEMS[diff].seal
if type(seal) == 'table' then -- Three-seal ZNMs (Tinnin, etc.)
player:delKeyItem(seal[1])
player:delKeyItem(seal[2])
player:delKeyItem(seal[3])
player:updateEvent(1, zeniCost, popItem, seal[1], seal[2], seal[3])
elseif seal == 0 then -- Tier 1s have no seal
player:updateEvent(1, zeniCost, popItem)
else -- One-seal ZNMs
player:delKeyItem(seal)
player:updateEvent(1, zeniCost, popItem, seal)
end
end
end
-----------------------------------
-- onEventFinish
-----------------------------------
xi.znm.sanraku.onEventFinish = function(player, csid, option, npc)
if csid == 910 then
xi.znm.sanraku.handleCompletedTradeWithPlate(player)
elseif csid == 908 then
xi.znm.setPlayerHasSpokenToSanrakuBefore(player)
elseif csid == 912 then
xi.znm.sanraku.handleCompletedTradeWithTrophy(player)
end
end
-----------------------------------
-- onEventFinish Helpers
-----------------------------------
xi.znm.sanraku.handleCompletedTradeWithPlate = function(player)
player:tradeComplete()
xi.znm.setPlayerTradingDay(player, VanadielUniqueDay())
xi.znm.incrementTradedPlates(player)
local zeniValue = xi.znm.sanraku.tradedPlateValue(player)
xi.znm.sanraku.setTradedPlateValue(player, 0)
player:addCurrency('zeni_point', zeniValue)
end
xi.znm.sanraku.handleCompletedTradeWithTrophy = function(player)
player:tradeComplete()
player:addKeyItem(xi.znm.sanraku.tradedTrophySeal(player))
xi.znm.sanraku.setTradedTrophySeal(player, 0)
end
-----------------------------------
-- Sanraku General Helpers
-----------------------------------
xi.znm.sanraku.tradedPlateValue = function(player)
return player:getLocalVar('[ZNM][Sanraku]SoulPlateValue')
end
xi.znm.sanraku.setTradedPlateValue = function(player, zeni)
player:setLocalVar('[ZNM][Sanraku]SoulPlateValue', zeni)
end
xi.znm.sanraku.tradedTrophySeal = function(player)
return player:getLocalVar('[ZNM]TrophyTrade')
end
xi.znm.sanraku.setTradedTrophySeal = function(player, trophy)
player:setLocalVar('[ZNM]TrophyTrade', trophy)
end
-----------------------------------
---- ZNM Pop-Item Prices
-----------------------------------
xi.znm.getPopPrice = function(mob, znmTier)
local popCost = GetServerVariable('[ZNM][' .. mob .. ']PopCost')
-- Check to make sure the pop prices have a set value
if
popCost == nil or
popCost == 0
then
popCost = xi.znm.ZNM_POP_COSTS[znmTier].minPrice
SetServerVariable('[ZNM][' .. mob .. ']PopCost', popCost)
end
return popCost
end
-- pop prices update per purchase at the mob level
xi.znm.updatePopPrice = function(mob, znmTier)
if not xi.znm.ZNM_STATIC_POP_PRICES then
local popCost = math.min(xi.znm.getPopPrice(mob, znmTier) + xi.znm.ZNM_POP_COSTS[znmTier].addedPrice,
xi.znm.ZNM_POP_COSTS[znmTier].maxPrice)
SetServerVariable('[ZNM][' .. mob .. ']PopCost', popCost)
end
end
-- Prices decay over time (called every 2 hours)
xi.znm.ZNMPopPriceDecay = function()
if not xi.znm.ZNM_STATIC_POP_PRICES then
local popCost = 0
local mob = nil
local znmTier = 1
for i = 1, 31 do
mob = xi.znm.POP_ITEMS[i].mob
znmTier = xi.znm.POP_ITEMS[i].tier
popCost = math.max(xi.znm.getPopPrice(mob, znmTier) - xi.znm.ZNM_POP_COSTS[znmTier].decayPrice,
xi.znm.ZNM_POP_COSTS[znmTier].minPrice)
SetServerVariable('[ZNM][' .. mob .. ']PopCost', popCost)
end
end
end
-----------------------------------
---- General Utility Helpers
-----------------------------------
xi.znm.playerHasSpokenToSanrakuBefore = function(player)
return player:getVar('ZeniStatus') >= 1
end
xi.znm.setPlayerHasSpokenToSanrakuBefore = function(player)
player:setVar('ZeniStatus', 1)
end
xi.znm.playerTradingDay = function(player)
return player:getVar('[ZNM][Sanraku]TradingDay')
end
xi.znm.setPlayerTradingDay = function(player, day)
player:setVar('[ZNM][Sanraku]TradingDay', day)
end
xi.znm.numberOfTradedPlates = function(player)
return player:getVar('[ZNM][Sanraku]TradedPlates')
end
xi.znm.incrementTradedPlates = function(player)
player:incrementCharVar('[ZNM][Sanraku]TradedPlates', 1)
end
xi.znm.resetDailyTrackingVars = function(player)
player:setVar('[ZNM][Sanraku]TradingDay', 0)
player:setVar('[ZNM][Sanraku]TradedPlates', 0)
end