557 lines
19 KiB
Lua
557 lines
19 KiB
Lua
-----------------------------------
|
|
-- Synergy
|
|
-----------------------------------
|
|
xi = xi or {}
|
|
xi.synergy = xi.synergy or {}
|
|
|
|
-----------------------------------
|
|
-- Synergy Furnace
|
|
-----------------------------------
|
|
|
|
-- NOTE: These are baked into every zone
|
|
local synergyMessages =
|
|
{
|
|
-- TODO: Remove the 32k offset here
|
|
CLAIM_EXPIRE = 32786, -- (White) Your claim over the synergy furnace will expire in ten seconds.
|
|
CLAIM_WARNING = 32946, -- (Yellow) Warning! Your claim over the synergy furnace will be nullified if you venture any further away.
|
|
CLAIM_SET = 32787, -- (White) {Synergy crucible} set. Please deposit your ingredients inside the furnace and initiate the synergy process within 0 minutes.
|
|
UNSUITABLE_ITEMS = 32788, -- (White) Please be aware that certain items are not suitable for use as synergy ingredients.
|
|
CLAIM_RELINQUISHED = 32944, -- (Cream) Your claim to the synergy furnace has been relinquished.
|
|
SYNERGY_COMMENCE = 32837, -- (White) Commencing synergy process.
|
|
TOO_FAR_AWAY = 32945, -- (Yellow) You are too far away to operate the synergy furnace.
|
|
SYNERGY_IMAGE_ELUSIVE = 32841, -- (White) The synergy image eludes you.
|
|
FEED_FEWELL = 32855, -- (White) You feed the furnace <n> portion of (fire) fewell. (fire) elemental power climbs to <n>.
|
|
ELEMENTAL_POWER_CLIMB = 32840, -- (White) (fire) elemental power climbs to 9.
|
|
INTERNAL_PRESSURE = 32842, -- (White) Internal pressure: <n> Pz/lm. Impurity ratio: <n>%.
|
|
ELEMENTAL_POWER_LEAKING = 32922, -- (White) (fire) elemental power has begun leaking from the furnace.
|
|
INTERNAL_PRESSURE_FALL = 32890, -- (White) Internal pressure has fallen to <n> Pz/lm.
|
|
SYNERGY_IMAGE_FORMED = 32848, -- (White) The synergy image has taken form.
|
|
END_SYNERGY = 32849, -- (White) Select 'End synergy' now to retrieve it!
|
|
ELEMENTAL_POWER_NO_LEAK = 32923, -- (White) (fire) elemental power is no longer leaking.
|
|
SYNERGY_COMPLETE = 32929, -- (White) Synergy complete!
|
|
SMOOTH_SYNERGIZING = 32932, -- (Yellow) Smooth synergizing! A {item} has been successfully synergized!
|
|
OBTAIN_PONZES = 32935, -- (Yellow) {player} obtains <n> ponzes of cinder. Total: <n> Pz.
|
|
REMOVE_FROM_FURNACE = 169, -- You remove % from the furnace.
|
|
REMOVE_FROM_FURNACE_N = 170, -- You remove # % from the furnace.
|
|
REMOVE_INGREDIENTS = 171, -- You remove the ingredients from the furnace.
|
|
}
|
|
|
|
local furnaceStates =
|
|
{
|
|
AVAILABLE = 0,
|
|
CLAIMED = 1,
|
|
ACTIVE = 2,
|
|
COMPLETED = 3,
|
|
}
|
|
|
|
local vars =
|
|
{
|
|
SYNERGY_FURNACE_NPC_ID = 'synergyFurnaceNPCID',
|
|
SYNERGY_FURNACE_PLAYER_ID = 'synergyFurnacePlayerID',
|
|
SYNERGY_FURNACE_STATE = 'synergyFurnaceState',
|
|
SYNERGY_FURNACE_CURRENT_RECIPE = 'synergyFurnaceCurrentRecipe',
|
|
}
|
|
|
|
-- NOTE: The animation states for furnaces can be moved between 1-3 in
|
|
-- any order, but use of 0 seems broken.
|
|
-- : 0 = closed (flashes out, broken?)
|
|
-- : 1 (or 5) = open
|
|
-- : 2 (or 6) = closed, active
|
|
-- : 3 (or 7) = closed, very active
|
|
local setFurnaceOpen = function(npc)
|
|
npc:setAnimationSub(5)
|
|
end
|
|
|
|
local setFurnaceClosed = function(npc)
|
|
npc:setAnimationSub(6)
|
|
end
|
|
|
|
local setFurnaceVeryActive = function(npc)
|
|
npc:setAnimationSub(7)
|
|
|
|
-- TODO: What are the conditions for 'very active'?
|
|
npc:timer(1000, function(npcArg)
|
|
setFurnaceClosed(npcArg)
|
|
end)
|
|
end
|
|
|
|
xi.synergy.relinquishFurnaceClaim = function(player)
|
|
print('relinquishFurnaceClaim')
|
|
|
|
local npcID = player:getLocalVar(vars.SYNERGY_FURNACE_NPC_ID)
|
|
if npcID == 0 then
|
|
print('No furnace claimed')
|
|
return
|
|
end
|
|
|
|
player:setLocalVar(vars.SYNERGY_FURNACE_NPC_ID, 0)
|
|
|
|
local npc = GetNPCByID(npcID)
|
|
if npc == nil then
|
|
print('NPC not found:', npcID)
|
|
return
|
|
end
|
|
|
|
npc:setLocalVar(vars.SYNERGY_FURNACE_PLAYER_ID, 0)
|
|
|
|
setFurnaceOpen(npc)
|
|
|
|
npc:setLocalVar(vars.SYNERGY_FURNACE_STATE, furnaceStates.AVAILABLE)
|
|
|
|
player:messageSpecial(synergyMessages.CLAIM_RELINQUISHED)
|
|
end
|
|
|
|
xi.synergy.synergyDistanceChecker = function(player)
|
|
-- TODO: Ensure sure multiple of this can't be attached to player/npc
|
|
|
|
local npcID = player:getLocalVar(vars.SYNERGY_FURNACE_NPC_ID)
|
|
if npcID == 0 then
|
|
return
|
|
end
|
|
|
|
local npc = GetNPCByID(npcID)
|
|
if npc == nil then
|
|
return
|
|
end
|
|
|
|
local distance = player:checkDistance(npc)
|
|
-- print('Distance:', distance)
|
|
|
|
if distance > 6 then -- TODO: What are these actual distances
|
|
player:messageSpecial(synergyMessages.CLAIM_EXPIRE)
|
|
|
|
-- TODO: Limit how often this message triggers
|
|
|
|
player:timer(10000, function(playerArg)
|
|
xi.synergy.relinquishFurnaceClaim(playerArg)
|
|
end)
|
|
|
|
return
|
|
elseif distance > 3 then -- TODO: What are these actual distances
|
|
-- (Yellow) Warning! Your claim over the synergy furnace will be nullified if you venture any further away.
|
|
player:messageSpecial(synergyMessages.CLAIM_WARNING)
|
|
|
|
-- TODO: Limit how often this message triggers
|
|
end
|
|
|
|
-- Check every second
|
|
player:timer(1000, function(playerArg)
|
|
xi.synergy.synergyDistanceChecker(playerArg)
|
|
end)
|
|
end
|
|
|
|
xi.synergy.attachToSynergyFurnace = function(player, npc)
|
|
-- TODO: Start 1 minute timer
|
|
|
|
-- Pair these together so we can easily find them
|
|
player:setLocalVar(vars.SYNERGY_FURNACE_NPC_ID, npc:getID())
|
|
npc:setLocalVar(vars.SYNERGY_FURNACE_PLAYER_ID, player:getID())
|
|
npc:setLocalVar(vars.SYNERGY_FURNACE_STATE, furnaceStates.CLAIMED)
|
|
|
|
xi.synergy.synergyDistanceChecker(player)
|
|
end
|
|
|
|
xi.synergy.synergyFurnaceOnTrade = function(player, npc, trade)
|
|
if not xi.settings.main.ENABLE_SYNERGY then
|
|
return
|
|
end
|
|
|
|
local furnaceState = npc:getLocalVar(vars.SYNERGY_FURNACE_STATE)
|
|
|
|
if furnaceState ~= furnaceStates.CLAIMED then
|
|
return
|
|
end
|
|
|
|
local claimedByYou = npc:getLocalVar(vars.SYNERGY_FURNACE_PLAYER_ID) == player:getID()
|
|
if not claimedByYou then
|
|
return
|
|
end
|
|
|
|
local recipe = GetSynergyRecipeByTrade(trade)
|
|
if recipe == nil then
|
|
print('Recipe not found')
|
|
return
|
|
end
|
|
|
|
for i = 0, 7 do
|
|
trade:confirmSlot(i)
|
|
end
|
|
|
|
local recipeId = recipe['id'] -- This is for writing to the furnace so it can be pulled out later with GetSynergyRecipeByID()
|
|
local recipeItemId = recipe['result']
|
|
local recipeItemQty = recipe['resultQty']
|
|
local recipeRank = recipe['primary_rank']
|
|
|
|
npc:setLocalVar(vars.SYNERGY_FURNACE_CURRENT_RECIPE, recipeId)
|
|
|
|
-- NOTE: Remember that FIRE is 1, so we're going to offset with -1 later
|
|
-- NOTE: If the value is zero, the icon won't be shown
|
|
local fewellCosts =
|
|
{
|
|
[xi.element.FIRE] = recipe['cost_fire_fewell'],
|
|
[xi.element.ICE] = recipe['cost_ice_fewell'],
|
|
[xi.element.WIND] = recipe['cost_wind_fewell'],
|
|
[xi.element.EARTH] = recipe['cost_earth_fewell'],
|
|
[xi.element.THUNDER] = recipe['cost_lightning_fewell'],
|
|
[xi.element.WATER] = recipe['cost_water_fewell'],
|
|
[xi.element.LIGHT] = recipe['cost_light_fewell'],
|
|
[xi.element.DARK] = recipe['cost_dark_fewell'],
|
|
}
|
|
|
|
local fewellMask = 0x00
|
|
for key, value in pairs(fewellCosts) do
|
|
if value > 0 then
|
|
fewellMask = bit.bor(fewellMask, bit.lshift(1, key - 1)) -- The offset inside xi.element because of NONE
|
|
end
|
|
end
|
|
|
|
local fewellCosts0 = bit.bor(
|
|
bit.lshift(fewellCosts[xi.element.FIRE], 0),
|
|
bit.lshift(fewellCosts[xi.element.ICE], 8),
|
|
bit.lshift(fewellCosts[xi.element.WIND], 16),
|
|
bit.lshift(fewellCosts[xi.element.EARTH], 24))
|
|
|
|
local fewellCosts1 = bit.bor(
|
|
bit.lshift(fewellCosts[xi.element.THUNDER], 0),
|
|
bit.lshift(fewellCosts[xi.element.WATER], 8),
|
|
bit.lshift(fewellCosts[xi.element.LIGHT], 16),
|
|
bit.lshift(fewellCosts[xi.element.DARK], 24))
|
|
|
|
local itemInfo = bit.bor(
|
|
bit.lshift(recipeItemId, 0),
|
|
bit.lshift(recipeItemQty, 16))
|
|
|
|
player:startEvent(4521, fewellMask, fewellCosts0, fewellCosts1, itemInfo, recipeRank)
|
|
end
|
|
|
|
xi.synergy.synergyFurnaceOnTrigger = function(player, npc)
|
|
if not xi.settings.main.ENABLE_SYNERGY then
|
|
return
|
|
end
|
|
|
|
local fireFewell = 99
|
|
local iceFewell = 99
|
|
local windFewell = 99
|
|
local earthFewell = 99
|
|
local lightningFewell = 99
|
|
local waterFewell = 99
|
|
local lightFewell = 99
|
|
local darkFewell = 99
|
|
|
|
local claimedByYou = npc:getLocalVar(vars.SYNERGY_FURNACE_PLAYER_ID) == player:getID()
|
|
|
|
local furnaceState = npc:getLocalVar(vars.SYNERGY_FURNACE_STATE)
|
|
print('Furnace state:', furnaceState)
|
|
|
|
local handleFurnaceState =
|
|
{
|
|
[furnaceStates.AVAILABLE] = function()
|
|
player:messageSpecial(synergyMessages.CLAIM_SET, xi.ki.SYNERGY_CRUCIBLE, 1)
|
|
|
|
xi.synergy.attachToSynergyFurnace(player, npc)
|
|
end,
|
|
|
|
[furnaceStates.CLAIMED] = function()
|
|
if not claimedByYou then
|
|
-- TODO: Message
|
|
return
|
|
end
|
|
|
|
player:startEvent(4520,
|
|
fireFewell, iceFewell, windFewell, earthFewell,
|
|
lightningFewell, waterFewell, lightFewell, darkFewell)
|
|
end,
|
|
|
|
[furnaceStates.ACTIVE] = function()
|
|
if not claimedByYou then
|
|
-- TODO: Message
|
|
return
|
|
end
|
|
|
|
if player:checkDistance(npc) > 1.5 then
|
|
player:messageSpecial(synergyMessages.TOO_FAR_AWAY)
|
|
return
|
|
end
|
|
|
|
player:startEvent(4518, 0, 1, 0, 0, 0, 0, 0, 0)
|
|
end,
|
|
|
|
[furnaceStates.COMPLETED] = function()
|
|
if not claimedByYou then
|
|
-- TODO: Message
|
|
return
|
|
end
|
|
|
|
local recipeId = npc:getLocalVar(vars.SYNERGY_FURNACE_CURRENT_RECIPE)
|
|
local recipe = GetSynergyRecipeByID(recipeId)
|
|
if recipe == nil then
|
|
print('Recipe not found:', recipeId)
|
|
return
|
|
end
|
|
|
|
local resultId = recipe['result']
|
|
local resultQty = recipe['resultQty']
|
|
|
|
-- TODO: Look up and see if this HQ'd
|
|
|
|
player:addItem(resultId, resultQty)
|
|
|
|
if resultQty > 1 then
|
|
player:messageSpecial(synergyMessages.REMOVE_FROM_FURNACE_N, resultId, resultQty)
|
|
else
|
|
player:messageSpecial(synergyMessages.REMOVE_FROM_FURNACE, resultId)
|
|
end
|
|
|
|
xi.synergy.relinquishFurnaceClaim(player)
|
|
end,
|
|
}
|
|
|
|
handleFurnaceState[furnaceState]()
|
|
end
|
|
|
|
xi.synergy.synergyFurnaceOnEventUpdate = function(player, csid, option, npc)
|
|
if not xi.settings.main.ENABLE_SYNERGY then
|
|
return
|
|
end
|
|
|
|
-- print('> Update CSID:', csid, 'Option:', option)
|
|
|
|
local optionByte0, _, optionByte2, _ = utils.toBytes(option)
|
|
-- print('Bytes:', optionByte0, optionByte1, optionByte2, optionByte3)
|
|
|
|
local fireFewell = 0
|
|
local iceFewell = 1
|
|
local windFewell = 2
|
|
local earthFewell = 3
|
|
local lightningFewell = 4
|
|
local waterFewell = 5
|
|
local lightFewell = 6
|
|
local darkFewell = 7
|
|
|
|
if csid == 4518 then
|
|
local updateOperations =
|
|
{
|
|
[100] = function() -- Feed fewell: Fire
|
|
npc:entityAnimationPacket(xi.animationString.SYNERGY_FIRE_FEWELL)
|
|
|
|
player:messageSpecial(synergyMessages.ELEMENTAL_POWER_LEAKING, 0)
|
|
npc:entityAnimationPacket(xi.animationString.SYNERGY_FIRE_LEAK)
|
|
end,
|
|
|
|
[101] = function() -- Feed fewell: Ice
|
|
npc:entityAnimationPacket(xi.animationString.SYNERGY_ICE_FEWELL)
|
|
end,
|
|
|
|
[102] = function() -- Feed fewell: Wind
|
|
npc:entityAnimationPacket(xi.animationString.SYNERGY_WIND_FEWELL)
|
|
end,
|
|
|
|
[103] = function() -- Feed fewell: Earth
|
|
npc:entityAnimationPacket(xi.animationString.SYNERGY_EARTH_FEWELL)
|
|
end,
|
|
|
|
[104] = function() -- Feed fewell: Lightning
|
|
npc:entityAnimationPacket(xi.animationString.SYNERGY_LIGHTNING_FEWELL)
|
|
end,
|
|
|
|
[105] = function() -- Feed fewell: Water
|
|
npc:entityAnimationPacket(xi.animationString.SYNERGY_WATER_FEWELL)
|
|
end,
|
|
|
|
[106] = function() -- Feed fewell: Light
|
|
npc:entityAnimationPacket(xi.animationString.SYNERGY_LIGHT_FEWELL)
|
|
end,
|
|
|
|
[107] = function() -- Feed fewell: Dark
|
|
npc:entityAnimationPacket(xi.animationString.SYNERGY_DARK_FEWELL)
|
|
end,
|
|
|
|
[120] = function() -- Operate furnace: Thwack furnace
|
|
end,
|
|
|
|
[121] = function() -- Operate furnace: Operate pressure handle
|
|
npc:entityAnimationPacket(xi.animationString.SYNERGY_STEAM)
|
|
setFurnaceVeryActive(npc)
|
|
npc:timer(500, function(npcArg)
|
|
-- TODO: Look up what kind of leak we've just fixed
|
|
player:messageSpecial(synergyMessages.ELEMENTAL_POWER_LEAKING + 1, 0)
|
|
setFurnaceClosed(npcArg)
|
|
end)
|
|
end,
|
|
|
|
[123] = function() -- Operate furnace: Operate safety lever
|
|
end,
|
|
|
|
[122] = function() -- Operate furnace: Repair furnace
|
|
end,
|
|
|
|
[124] = function() -- Operate furnace: Recycle strewn fewell
|
|
end,
|
|
|
|
[125] = function() -- Operate furnace: Fishing: Lunar Smarts
|
|
end,
|
|
|
|
[126] = function() -- Operate furnace: Fishing: Precision Thwack
|
|
end,
|
|
|
|
[127] = function() -- Operate furnace: Woodworking: Cyclical Smarts
|
|
end,
|
|
|
|
[128] = function() -- Operate furnace: Woodworking: Earth Affinity
|
|
end,
|
|
|
|
[129] = function() -- Operate furnace: Smithing: Combustive Smarts
|
|
end,
|
|
|
|
[130] = function() -- Operate furnace: Smithing: Fire Affinity
|
|
end,
|
|
|
|
[131] = function() -- Operate furnace: Goldsmithing: Engraver's Touch
|
|
end,
|
|
|
|
[132] = function() -- Operate furnace: Goldsmithing: Wind Affinity
|
|
end,
|
|
|
|
[133] = function() -- Operate furnace: Clothcraft: Restorer's Touch
|
|
end,
|
|
|
|
[134] = function() -- Operate furnace: Clothcraft: Lightning Affinity
|
|
end,
|
|
|
|
[135] = function() -- Operate furnace: Leathercraft: Pressurization Smarts
|
|
end,
|
|
|
|
[136] = function() -- Operate furnace: Leathercraft: Ice Affinity
|
|
end,
|
|
|
|
[137] = function() -- Operate furnace: Bonecraft: Carbonization Smarts
|
|
end,
|
|
|
|
[138] = function() -- Operate furnace: Bonecraft: Dark Affinity
|
|
end,
|
|
|
|
[139] = function() -- Operate furnace: Alchemy: Alchemical Smarts
|
|
end,
|
|
|
|
[140] = function() -- Operate furnace: Alchemy: Light Affinity
|
|
end,
|
|
|
|
[141] = function() -- Operate furnace: Cooking: Healing Smarts
|
|
end,
|
|
|
|
[142] = function() -- Operate furnace: Cooking: Water Affinity
|
|
end,
|
|
|
|
[145] = function() -- Operate furnace: DEBUG: Forced perfection
|
|
end,
|
|
|
|
[148] = function() -- Operate furnace: DEBUG: Set level (Requires a {Judge's arrow})
|
|
local menuValue = optionByte2
|
|
utils.unused(menuValue)
|
|
end,
|
|
|
|
[165] = function() -- Operate furnace: DEBUG: Set pressure/impurities -> pressure
|
|
local menuValue = optionByte2
|
|
utils.unused(menuValue)
|
|
end,
|
|
|
|
[166] = function() -- Operate furnace: DEBUG: Set pressure/impurities -> impurities
|
|
local menuValue = optionByte2
|
|
utils.unused(menuValue)
|
|
end,
|
|
|
|
[167] = function() -- Operate furnace: DEBUG: Something good
|
|
local menuValue = optionByte2
|
|
utils.unused(menuValue)
|
|
end,
|
|
|
|
[112] = function() -- View furnace readings 1
|
|
end,
|
|
|
|
[111] = function() -- View furnace readings 2
|
|
end,
|
|
|
|
[110] = function() -- End synergy (goes to finish)
|
|
end,
|
|
|
|
[163] = function() -- Review objective: LOCKS THE CLIENT, NEEDS TO BE PROPERLY POPULATED
|
|
end,
|
|
|
|
[164] = function() -- Toggle command confirmation off
|
|
end,
|
|
|
|
[143] = function() -- Populating fewell data
|
|
player:updateEvent(
|
|
fireFewell, iceFewell, windFewell, earthFewell,
|
|
lightningFewell, waterFewell, lightFewell, darkFewell)
|
|
end,
|
|
|
|
[147] = function() -- first update when interacting with synergy action menu
|
|
end,
|
|
}
|
|
|
|
--Execute
|
|
updateOperations[optionByte0]()
|
|
end
|
|
end
|
|
|
|
xi.synergy.synergyFurnaceOnEventFinish = function(player, csid, option, npc)
|
|
if not xi.settings.main.ENABLE_SYNERGY then
|
|
return
|
|
end
|
|
|
|
-- print('> Finish CSID:', csid, 'Option:', option)
|
|
|
|
if csid == 4520 and option == 146 then -- Relinquish csid
|
|
print('Relinquish furnace')
|
|
|
|
xi.synergy.relinquishFurnaceClaim(player)
|
|
elseif csid == 4521 and option == 150 then -- Commence synergy (150 yes, 151 no)
|
|
print('Commence synergy')
|
|
|
|
player:messageSpecial(synergyMessages.SYNERGY_COMMENCE)
|
|
|
|
player:confirmTrade() -- items are taken!
|
|
|
|
local npcId = player:getLocalVar(vars.SYNERGY_FURNACE_NPC_ID)
|
|
local furnaceNpc = GetNPCByID(npcId)
|
|
if furnaceNpc == nil then
|
|
print('NPC not found:', npcId)
|
|
return
|
|
end
|
|
|
|
setFurnaceClosed(furnaceNpc)
|
|
npc:timer(2000, function(furnaceNpcArg)
|
|
furnaceNpcArg:entityAnimationPacket(xi.animationString.SYNERGY_STEAM)
|
|
end)
|
|
|
|
furnaceNpc:setLocalVar(vars.SYNERGY_FURNACE_STATE, furnaceStates.ACTIVE)
|
|
elseif csid == 4521 and option == 151 then -- Cancel after trade
|
|
print('Cancel synergy')
|
|
|
|
player:getTrade():clean()
|
|
elseif csid == 4518 and option == 110 then -- Finish Synergy
|
|
print('Finish synergy')
|
|
|
|
local npcId = player:getLocalVar(vars.SYNERGY_FURNACE_NPC_ID)
|
|
local furnaceNpc = GetNPCByID(npcId)
|
|
if furnaceNpc == nil then
|
|
print('NPC not found:', npcId)
|
|
return
|
|
end
|
|
|
|
local recipeId = furnaceNpc:getLocalVar(vars.SYNERGY_FURNACE_CURRENT_RECIPE)
|
|
local recipe = GetSynergyRecipeByID(recipeId)
|
|
if recipe == nil then
|
|
print('Recipe not found:', recipeId)
|
|
return
|
|
end
|
|
|
|
player:messageSpecial(synergyMessages.SMOOTH_SYNERGIZING, recipe['result'])
|
|
player:messageSpecial(synergyMessages.OBTAIN_PONZES, 1, 1)
|
|
|
|
setFurnaceOpen(furnaceNpc)
|
|
|
|
furnaceNpc:setLocalVar(vars.SYNERGY_FURNACE_STATE, furnaceStates.COMPLETED)
|
|
end
|
|
end
|