From c15430ade5b842bc8061c0fc7365dcd70dad1446 Mon Sep 17 00:00:00 2001 From: Jeswill David Bolivar Mendoza <76903590+jeswilldbm@users.noreply.github.com> Date: Thu, 4 Apr 2024 16:48:18 +0200 Subject: [PATCH 1/3] fix: forge convergence show all items with same class (#2521) --- src/server/network/protocol/protocolgame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 218fc857d3c..0d0d8e79f17 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -5021,7 +5021,7 @@ void ProtocolGame::sendOpenForge() { getForgeInfoMap(item, receiveTierItemMap); } if (itemClassification == 4) { - getForgeInfoMap(item, convergenceItemsMap[item->getSlotPosition()]); + getForgeInfoMap(item, convergenceItemsMap[item->getClassification()]); } } } From 167bae5c750d23bcec26b527279b32cb65db84cd Mon Sep 17 00:00:00 2001 From: Luan Luciano Date: Thu, 4 Apr 2024 11:48:45 -0300 Subject: [PATCH 2/3] fix: problem with casks items in the charge loop and adjustment without code (#2505) --- data/modules/scripts/gamestore/init.lua | 236 +++++++++++++----------- 1 file changed, 124 insertions(+), 112 deletions(-) diff --git a/data/modules/scripts/gamestore/init.lua b/data/modules/scripts/gamestore/init.lua index a927715cd93..6146f562307 100644 --- a/data/modules/scripts/gamestore/init.lua +++ b/data/modules/scripts/gamestore/init.lua @@ -402,7 +402,7 @@ function parseBuyStoreOffer(playerId, msg) -- All guarding conditions under which the offer should not be processed must be included here if - (table.contains(GameStore.OfferTypes, offer.type) == false) -- we've got an invalid offer type + not table.contains(GameStore.OfferTypes, offer.type) -- we've got an invalid offer type or not player or (player:getVocation():getId() == 0) and (not GameStore.haveOfferRook(id)) -- we don't have such offer or not offer @@ -620,7 +620,7 @@ end function Player.canBuyOffer(self, offer) local playerId = self:getId() local disabled, disabledReason = 0, "" - if offer.disabled == true or not offer.type then + if offer.disabled or not offer.type then disabled = 1 end @@ -692,8 +692,7 @@ function Player.canBuyOffer(self, offer) disabledReason = "The offer is fake." end elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_MOUNT then - local hasMount = self:hasMount(offer.id) - if hasMount == true then + if self:hasMount(offer.id) then disabled = 1 disabledReason = "You already have this mount." end @@ -723,12 +722,11 @@ function Player.canBuyOffer(self, offer) disabledReason = "You already have 3 slots released." end elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_EXPBOOST then - local remainingBoost = self:getExpBoostStamina() if self:getStorageValue(GameStore.Storages.expBoostCount) == 6 then disabled = 1 disabledReason = "You can't buy XP Boost for today." end - if remainingBoost > 0 then + if self:getExpBoostStamina() > 0 then disabled = 1 disabledReason = "You already have an active XP boost." end @@ -786,9 +784,9 @@ function Player.canReceiveStoreItems(self, offerId, offerCount) local inboxItems = inbox:getItems(true) local slotsOccupied = #inboxItems local maxCapacity = inbox:getMaxCapacity() - local slotsAvailable = maxCapacity - slotsOccupied if slotsOccupied + slotsNeeded > maxCapacity then + local slotsAvailable = maxCapacity - slotsOccupied return false, string.format("Not enough free slots in your store inbox. You need %d more slot(s). Currently occupied: %d/%d", slotsNeeded - slotsAvailable, slotsOccupied, maxCapacity) end @@ -1104,14 +1102,16 @@ function sendStoreTransactionHistory(playerId, page, entriesPerPage) if not player then return false end - local oldProtocol = player:getClient().version < 1200 - local totalEntries = GameStore.retrieveHistoryTotalPages(player:getAccountId()) - local totalPages = math.ceil(totalEntries / entriesPerPage) + local entries = GameStore.retrieveHistoryEntries(player:getAccountId(), page, entriesPerPage) -- this makes everything easy! if #entries == 0 then return addPlayerEvent(sendStoreError, 250, playerId, GameStore.StoreErrors.STORE_ERROR_HISTORY, "You don't have any entries yet.") end + local oldProtocol = player:getClient().version < 1200 + local totalEntries = GameStore.retrieveHistoryTotalPages(player:getAccountId()) + local totalPages = math.ceil(totalEntries / entriesPerPage) + local msg = NetworkMessage() msg:addByte(GameStore.SendingPackets.S_OpenTransactionHistory) msg:addU32(totalPages > 0 and page - 1 or 0x0) -- current page @@ -1165,10 +1165,8 @@ function sendStoreError(playerId, errorType, message) local msg = NetworkMessage() msg:addByte(GameStore.SendingPackets.S_StoreError) - msg:addByte(errorType) msg:addString(message, "sendStoreError - message") - msg:sendToPlayer(player) end @@ -1183,7 +1181,7 @@ function sendStoreBalanceUpdating(playerId, updating) msg:addByte(0x00) msg:sendToPlayer(player) - if updating == true then + if updating then sendUpdatedStoreBalances(playerId) end end @@ -1194,7 +1192,6 @@ function sendUpdatedStoreBalances(playerId) return false end - local oldProtocol = player:getClient().version < 1200 local msg = NetworkMessage() msg:addByte(GameStore.SendingPackets.S_CoinBalanceUpdating) msg:addByte(0x01) @@ -1205,6 +1202,8 @@ function sendUpdatedStoreBalances(playerId) -- Send total of coins (transferable and normal coin) msg:addU32(player:getTibiaCoins()) msg:addU32(player:getTransferableCoins()) -- How many are Transferable + + local oldProtocol = player:getClient().version < 1200 if not oldProtocol then -- How many are reserved for a Character Auction -- We currently do not have this system implemented, so we will send 0 @@ -1346,7 +1345,7 @@ end GameStore.retrieveHistoryTotalPages = function(accountId) local resultId = db.storeQuery("SELECT count(id) as total FROM store_history WHERE account_id = " .. accountId) - if resultId == false then + if not resultId then return 0 end @@ -1360,7 +1359,7 @@ GameStore.retrieveHistoryEntries = function(accountId, currentPage, entriesPerPa local offset = currentPage > 1 and entriesPerPage * (currentPage - 1) or 0 local resultId = db.storeQuery("SELECT * FROM `store_history` WHERE `account_id` = " .. accountId .. " ORDER BY `time` DESC LIMIT " .. offset .. ", " .. entriesPerPage .. ";") - if resultId ~= false then + if resultId then repeat local entry = { mode = Result.getNumber(resultId, "mode"), @@ -1602,7 +1601,7 @@ function GameStore.processStackablePurchase(player, offerId, offerCount, offerNa local countToAdd = math.min(remainingCount, stackSize) local inboxItem = inbox:addItem(offerId, countToAdd) if inboxItem then - if movable ~= true then + if not movable then inboxItem:setAttribute(ITEM_ATTRIBUTE_STORE, systemTime()) end else @@ -1631,21 +1630,32 @@ function GameStore.processHouseRelatedPurchase(player, offer) local inbox = player:getStoreInbox() if inbox then for _, itemId in ipairs(itemIds) do - for i = 1, offer.count do + if isCaskItem(itemId) then local decoKit = inbox:addItem(ITEM_DECORATION_KIT, 1) if decoKit then decoKit:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, "You bought this item in the Store.\nUnwrap it in your own house to create a <" .. ItemType(itemId):getName() .. ">.") decoKit:setCustomAttribute("unWrapId", itemId) - if isCaskItem(itemId) then - decoKit:setAttribute(ITEM_ATTRIBUTE_DATE, offer.count) - end + decoKit:setAttribute(ITEM_ATTRIBUTE_DATE, offer.count) - if offer.movable ~= true then + if not offer.movable then decoKit:setAttribute(ITEM_ATTRIBUTE_STORE, systemTime()) end end + player:sendUpdateContainer(inbox) + else + for i = 1, offer.count do + local decoKit = inbox:addItem(ITEM_DECORATION_KIT, 1) + if decoKit then + decoKit:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, "You bought this item in the Store.\nUnwrap it in your own house to create a <" .. ItemType(itemId):getName() .. ">.") + decoKit:setCustomAttribute("unWrapId", itemId) + + if not offer.movable then + decoKit:setAttribute(ITEM_ATTRIBUTE_STORE, systemTime()) + end + end + player:sendUpdateContainer(inbox) + end end - player:sendUpdateContainer(inbox) end end end @@ -1689,8 +1699,6 @@ function GameStore.processMountPurchase(player, offerId) end function GameStore.processNameChangePurchase(player, offer, productType, newName) - local playerId = player:getId() - if productType == GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_NAMECHANGE then local tile = Tile(player:getPosition()) if tile then @@ -1720,11 +1728,11 @@ function GameStore.processNameChangePurchase(player, offer, productType, newName else message = "Your character has been renamed successfully." end - addPlayerEvent(sendStorePurchaseSuccessful, 500, playerId, message) + addPlayerEvent(sendStorePurchaseSuccessful, 500, player:getId(), message) player:changeName(newName) else - return addPlayerEvent(sendRequestPurchaseData, 250, playerId, offer.id, GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_NAMECHANGE) + return addPlayerEvent(sendRequestPurchaseData, 250, player:getId(), offer.id, GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_NAMECHANGE) end end @@ -1780,9 +1788,6 @@ function GameStore.processTempleTeleportPurchase(player) end function GameStore.processHirelingPurchase(player, offer, productType, hirelingName, chosenSex) - local playerId = player:getId() - local offerId = offer.id - if player:getClient().version < 1200 then return error({ code = 1, message = "You cannot buy hirelings on client 10, please relog on client 12 and try again." }) end @@ -1804,7 +1809,7 @@ function GameStore.processHirelingPurchase(player, offer, productType, hirelingN player:makeCoinTransaction(offer, hirelingName) local message = "You have successfully bought " .. hirelingName - return addPlayerEvent(sendStorePurchaseSuccessful, 650, playerId, message) + return addPlayerEvent(sendStorePurchaseSuccessful, 650, player:getId(), message) -- If not, we ask him to do! else if player:getHirelingsCount() >= 10 then @@ -1812,14 +1817,50 @@ function GameStore.processHirelingPurchase(player, offer, productType, hirelingN end -- TODO: Use the correct dialog (byte 0xDB) on client 1205+ -- for compatibility, request name using the change name dialog - return addPlayerEvent(sendRequestPurchaseData, 250, playerId, offerId, GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_HIRELING) + return addPlayerEvent(sendRequestPurchaseData, 250, player:getId(), offer.id, GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_HIRELING) end end -function GameStore.processHirelingChangeNamePurchase(player, offer, productType, newHirelingName) - local playerId = player:getId() - local offerId = offer.id +-- Hireling Helpers +local function HandleHirelingNameChange(playerId, offer, newHirelingName) + local player = Player(playerId) + if not player then + return + end + + local functionCallback = function(playerIdInFunction, data, hireling) + local playerInFunction = Player(playerIdInFunction) + if not playerInFunction then + return + end + + if not hireling then + return playerInFunction:showInfoModal("Error", "Your must select a hireling.") + end + if hireling.active > 0 then + return playerInFunction:showInfoModal("Error", "Your hireling must be inside his/her lamp.") + end + + local oldName = hireling.name + hireling.name = data.newHirelingName + + if not playerInFunction:makeCoinTransaction(data.offer, oldName .. " to " .. hireling.name) then + return playerInFunction:showInfoModal("Error", "Transaction error") + end + + local lamp = playerInFunction:findHirelingLamp(hireling:getId()) + if lamp then + lamp:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, "This mysterious lamp summons your very own personal hireling.\nThis item cannot be traded.\nThis magic lamp is the home of " .. hireling:getName() .. ".") + end + logger.debug("{} has been renamed to {}", oldName, hireling.name) + sendUpdatedStoreBalances(playerIdInFunction) + end + + player:sendHirelingSelectionModal("Choose a Hireling", "Select a hireling below", functionCallback, { offer = offer, newHirelingName = newHirelingName }) +end + +function GameStore.processHirelingChangeNamePurchase(player, offer, productType, newHirelingName) if player:getClient().version < 1200 then return error({ code = 1, @@ -1838,17 +1879,60 @@ function GameStore.processHirelingChangeNamePurchase(player, offer, productType, end) local message = "Close the store window to select which hireling should be renamed to " .. newHirelingName + local playerId = player:getId() addPlayerEvent(sendStorePurchaseSuccessful, 200, playerId, message) - addPlayerEvent(HandleHirelingNameChange, 550, playerId, offer, newHirelingName) else - return addPlayerEvent(sendRequestPurchaseData, 250, playerId, offerId, GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_NAMECHANGE) + return addPlayerEvent(sendRequestPurchaseData, 250, player:getId(), offer.id, GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_NAMECHANGE) end end -function GameStore.processHirelingChangeSexPurchase(player, offer) - local playerId = player:getId() +local function HandleHirelingSexChange(playerId, offer) + local player = Player(playerId) + if not player then + return + end + + local functionCallback = function(playerIdInFunction, data, hireling) + local playerInFunction = Player(playerIdInFunction) + if not playerInFunction then + return + end + + if not hireling then + return playerInFunction:showInfoModal("Error", "Your must select a hireling.") + end + if hireling.active > 0 then + return playerInFunction:showInfoModal("Error", "Your hireling must be inside his/her lamp.") + end + + if not playerInFunction:makeCoinTransaction(data.offer, hireling:getName()) then + return playerInFunction:showInfoModal("Error", "Transaction error") + end + + local changeTo, sexString, lookType + if hireling.sex == HIRELING_SEX.FEMALE then + changeTo = HIRELING_SEX.MALE + sexString = "male" + lookType = HIRELING_OUTFIT_DEFAULT.male + else + changeTo = HIRELING_SEX.FEMALE + sexString = "female" + lookType = HIRELING_OUTFIT_DEFAULT.female + end + + hireling.sex = changeTo + hireling.looktype = lookType + + logger.debug("{} sex was changed to {}", hireling:getName(), sexString) + sendUpdatedStoreBalances(playerIdInFunction) + end + + player:sendHirelingSelectionModal("Choose a Hireling", "Select a hireling below", functionCallback, { offer = offer }) +end + +function GameStore.processHirelingChangeSexPurchase(player, offer) if player:getClient().version < 1200 then return error({ code = 1, @@ -1857,8 +1941,8 @@ function GameStore.processHirelingChangeSexPurchase(player, offer) end local message = "Close the store window to select which hireling should have the sex changed." + local playerId = player:getId() addPlayerEvent(sendStorePurchaseSuccessful, 200, playerId, message) - addPlayerEvent(HandleHirelingSexChange, 550, playerId, offer) end @@ -2154,75 +2238,3 @@ function Player:openStore(serviceName) --exporting the method so other scripts c addPlayerEvent(sendShowStoreOffers, 50, playerId, category) end end - --- Hireling Helpers -function HandleHirelingNameChange(playerId, offer, newHirelingName) - local player = Player(playerId) - - local cb = function(playerId, data, hireling) - local offer = data.offer - local newHirelingName = data.newHirelingName - local player = Player(playerId) - if not hireling then - return player:showInfoModal("Error", "Your must select a hireling.") - end - - if hireling.active > 0 then - return player:showInfoModal("Error", "Your hireling must be inside his/her lamp.") - end - - local oldName = hireling.name - hireling.name = newHirelingName - - if not player:makeCoinTransaction(data.offer, oldName .. " to " .. newHirelingName) then - return player:showInfoModal("Error", "Transaction error") - end - - local lamp = player:findHirelingLamp(hireling:getId()) - if lamp then - lamp:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, "This mysterious lamp summons your very own personal hireling.\nThis item cannot be traded.\nThis magic lamp is the home of " .. hireling:getName() .. ".") - end - logger.debug("{} has been renamed to {}", oldName, newHirelingName) - sendUpdatedStoreBalances(playerId) - end - - player:sendHirelingSelectionModal("Choose a Hireling", "Select a hireling below", cb, { offer = offer, newHirelingName = newHirelingName }) -end - -function HandleHirelingSexChange(playerId, offer) - local player = Player(playerId) - - local cb = function(playerId, data, hireling) - local player = Player(playerId) - if not hireling then - return player:showInfoModal("Error", "Your must select a hireling.") - end - - if hireling.active > 0 then - return player:showInfoModal("Error", "Your hireling must be inside his/her lamp.") - end - - if not player:makeCoinTransaction(data.offer, hireling:getName()) then - return player:showInfoModal("Error", "Transaction error") - end - - local changeTo, sexString, lookType - if hireling.sex == HIRELING_SEX.FEMALE then - changeTo = HIRELING_SEX.MALE - sexString = "male" - lookType = HIRELING_OUTFIT_DEFAULT.male - else - changeTo = HIRELING_SEX.FEMALE - sexString = "female" - lookType = HIRELING_OUTFIT_DEFAULT.female - end - - hireling.sex = changeTo - hireling.looktype = lookType - - logger.debug("{} sex was changed to {}", hireling:getName(), sexString) - sendUpdatedStoreBalances(playerId) - end - - player:sendHirelingSelectionModal("Choose a Hireling", "Select a hireling below", cb, { offer = offer }) -end From 0f6cc07b198da44bfa862fe111a0e5cded130ba3 Mon Sep 17 00:00:00 2001 From: Karin Date: Mon, 15 Apr 2024 21:44:55 -0300 Subject: [PATCH 3/3] fix: incorrect id of bolt on npss asnarus and hireling (#2541) --- data-otservbr-global/npc/asnarus.lua | 2 +- data-otservbr-global/npc/hireling.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data-otservbr-global/npc/asnarus.lua b/data-otservbr-global/npc/asnarus.lua index a733d90834b..3992d513e9b 100644 --- a/data-otservbr-global/npc/asnarus.lua +++ b/data-otservbr-global/npc/asnarus.lua @@ -56,7 +56,7 @@ npcConfig.shop = { { itemName = "animate dead rune", clientId = 3203, buy = 375 }, { itemName = "arrow", clientId = 3447, buy = 2 }, { itemName = "blue quiver", clientId = 35848, buy = 400 }, - { itemName = "bolt", clientId = 3483, buy = 4 }, + { itemName = "bolt", clientId = 3446, buy = 4 }, { itemName = "bow", clientId = 3350, buy = 400, sell = 100 }, { itemName = "bowl of terror sweat", clientId = 20204, sell = 500 }, { itemName = "broken visor", clientId = 20184, sell = 1900 }, diff --git a/data-otservbr-global/npc/hireling.lua b/data-otservbr-global/npc/hireling.lua index 145d846bd7e..aad7785079d 100644 --- a/data-otservbr-global/npc/hireling.lua +++ b/data-otservbr-global/npc/hireling.lua @@ -228,7 +228,7 @@ function createHirelingType(HirelingName) }, ["distance"] = { { itemName = "arrow", clientId = 3447, buy = 2 }, - { itemName = "bolt", clientId = 3483, buy = 4 }, + { itemName = "bolt", clientId = 3446, buy = 4 }, { itemName = "bow", clientId = 3350, buy = 400, sell = 100 }, { itemName = "crossbow", clientId = 3349, buy = 500, sell = 120 }, { itemName = "crystalline arrow", clientId = 15793, buy = 450 },