Skip to content
This repository has been archived by the owner on May 20, 2023. It is now read-only.

Enable gamestore to offers services/items for tournament coins #743

Merged
merged 16 commits into from
Aug 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions data/items/items.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45048,10 +45048,22 @@
<attribute key="duration" value="200"/>
<attribute key="decayTo" value="31464"/>
</item>
<item id="31466" article="a" name="tournament carpet"/>
<item id="31467" article="a" name="sublime tournament carpet"/>
<item id="31468" article="a" name="tournament carpet"/>
<item id="31469" article="a" name="sublime tournament carpet"/>
<item id="31466" article="a" name="rolled-up tournament carpet">
<attribute key="type" value="carpet"/>
<attribute key="wrapableto" value="23398"/>
</item>
<item id="31467" article="a" name="rolled-up sublime tournament carpet">
<attribute key="type" value="carpet"/>
<attribute key="wrapableto" value="23398"/>
</item>
<item id="31468" article="a" name="tournament carpet">
<attribute key="type" value="carpet"/>
<attribute key="wrapableto" value="23398"/>
</item>
<item id="31469" article="a" name="sublime tournament carpet">
<attribute key="type" value="carpet"/>
<attribute key="wrapableto" value="23398"/>
</item>
<item fromid="31470" toid="31471" article="a" name="tournament accolade"/>
<item fromid="31472" toid="31473" article="a" name="sublime tournament accolade"/>
<item fromid="31474" toid="31477" article="a" name="pillar"/>
Expand Down
8 changes: 7 additions & 1 deletion data/migrations/19.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
function onUpdateDatabase()
return false -- true = There are others migrations file | false = this is the last migration file
Spdlog.info("Updating database to version 20 (Gamestore accepting Tournament Coins)")

db.query("ALTER TABLE `accounts` ADD `tournament_coins` int(11) NOT NULL DEFAULT 0 AFTER `coins`")
db.query("ALTER TABLE `store_history` ADD `coin_type` tinyint(1) NOT NULL DEFAULT 0 AFTER `description`")
db.query("ALTER TABLE `store_history` DROP COLUMN `coins`") -- Not in use anywhere.

return true
end
3 changes: 3 additions & 0 deletions data/migrations/20.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
function onUpdateDatabase()
return false -- true = There are others migrations file | false = this is the last migration file
end
154 changes: 114 additions & 40 deletions data/modules/scripts/gamestore/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ function useOfferConfigure(type)
local types = {
[GameStore.OfferTypes.OFFER_TYPE_NAMECHANGE] = GameStore.ConfigureOffers.SHOW_CONFIGURE,
[GameStore.OfferTypes.OFFER_TYPE_HIRELING] = GameStore.ConfigureOffers.SHOW_CONFIGURE,
[GameStore.OfferTypes.OFFER_TYPE_HIRELING_NAMECHANGE] = GameStore.ConfigureOffers.SHOW_CONFIGURE
[GameStore.OfferTypes.OFFER_TYPE_HIRELING_NAMECHANGE] = GameStore.ConfigureOffers.SHOW_CONFIGURE,
[GameStore.OfferTypes.OFFER_TYPE_HIRELING_SEXCHANGE] = GameStore.ConfigureOffers.SHOW_CONFIGURE
}

if not types[type] then
Expand Down Expand Up @@ -261,8 +262,8 @@ function parseTransferCoins(playerId, msg)
addPlayerEvent(sendStorePurchaseSuccessful, 550, playerId, "You have transfered " .. amount .. " coins to " .. reciver .. " successfully")

-- Adding history for both reciver/sender
GameStore.insertHistory(accountId, GameStore.HistoryTypes.HISTORY_TYPE_NONE, player:getName() .. " transfered you this amount.", amount)
GameStore.insertHistory(player:getAccountId(), GameStore.HistoryTypes.HISTORY_TYPE_NONE, "You transfered this amount to " .. reciver, -1 * amount) -- negative
GameStore.insertHistory(accountId, GameStore.HistoryTypes.HISTORY_TYPE_NONE, player:getName() .. " transfered you this amount.", amount, GameStore.CointType.Coin)
GameStore.insertHistory(player:getAccountId(), GameStore.HistoryTypes.HISTORY_TYPE_NONE, "You transfered this amount to " .. reciver, -1 * amount, GameStore.CointType.Coin)
end

function parseOpenStore(playerId, msg)
Expand Down Expand Up @@ -366,8 +367,9 @@ function parseBuyStoreOffer(playerId, msg)

-- At this point the purchase is assumed to be formatted correctly
local offerPrice = offer.type == GameStore.OfferTypes.OFFER_TYPE_EXPBOOST and GameStore.ExpBoostValues[player:getStorageValue(GameStore.Storages.expBoostCount)] or offer.price

if not player:canRemoveCoins(offerPrice) then
local offerCoinType = offer.coinType
-- Check if offer can be honored
if not player:canPayForOffer(offerPrice, offerCoinType) then
return queueSendStoreAlertToUser("You don't have enough coins. Your purchase has been cancelled.", 250, playerId)
end

Expand All @@ -387,7 +389,7 @@ function parseBuyStoreOffer(playerId, msg)
elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_OUTFIT then GameStore.processOutfitPurchase(player, offer.sexId, offer.addon)
elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_OUTFIT_ADDON then GameStore.processOutfitPurchase(player, offer.sexId, offer.addon)
elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_MOUNT then GameStore.processMountPurchase(player, offer.id)
elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_NAMECHANGE then local newName = msg:getString(); GameStore.processNameChangePurchase(player, offer.id, productType, newName, offer.name, offerPrice)
elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_NAMECHANGE then local newName = msg:getString(); GameStore.processNameChangePurchase(player, offer, productType, newName)
elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_SEXCHANGE then GameStore.processSexChangePurchase(player)
elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_EXPBOOST then GameStore.processExpBoostPuchase(player)
elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_PREYSLOT then GameStore.processPreyThirdSlot(player)
Expand Down Expand Up @@ -419,10 +421,11 @@ function parseBuyStoreOffer(playerId, msg)

local configure = useOfferConfigure(offer.type)
if configure ~= GameStore.ConfigureOffers.SHOW_CONFIGURE then
player:removeCoinsBalance(offerPrice)
GameStore.insertHistory(player:getAccountId(), GameStore.HistoryTypes.HISTORY_TYPE_NONE, offer.name, (offerPrice) * -1)

player:makeCoinTransaction(offer)

local message = string.format("You have purchased %s for %d coins.", offer.name, offerPrice)
sendUpdateCoinBalance(playerId)
sendUpdatedStoreBalances(playerId)
return addPlayerEvent(sendStorePurchaseSuccessful, 650, playerId, message)
end
return true
Expand Down Expand Up @@ -491,7 +494,7 @@ function openStore(playerId)
end

msg:sendToPlayer(player)
sendCoinBalanceUpdating(playerId, true)
sendStoreBalanceUpdating(playerId, true)
end
end

Expand Down Expand Up @@ -840,9 +843,9 @@ function sendStoreTransactionHistory(playerId, page, entriesPerPage)
for k, entry in ipairs(entries) do
msg:addU32(0)
msg:addU32(entry.time)
msg:addByte(entry.mode)
msg:addByte(entry.mode) -- 0 = normal, 1 = gift, 2 = refund
msg:addU32(entry.amount)
msg:addByte(0x0) -- 0 = transferable tibia coin, 1 = normal tibia coin
msg:addByte(entry.type) -- 0 = transferable tibia coin, 1 = normal tibia coin, 2 = tournament coin
msg:addString(entry.description)
msg:addByte(0) -- details
end
Expand Down Expand Up @@ -878,7 +881,7 @@ function sendStoreError(playerId, errorType, message)
msg:sendToPlayer(player)
end

function sendCoinBalanceUpdating(playerId, updating)
function sendStoreBalanceUpdating(playerId, updating)
local player = Player(playerId)
if not player then
return false
Expand All @@ -890,11 +893,11 @@ function sendCoinBalanceUpdating(playerId, updating)
msg:sendToPlayer(player)

if updating == true then
sendUpdateCoinBalance(playerId)
sendUpdatedStoreBalances(playerId)
end
end

function sendUpdateCoinBalance(playerId)
function sendUpdatedStoreBalances(playerId)
local player = Player(playerId)
if not player then
return false
Expand All @@ -907,10 +910,10 @@ function sendUpdateCoinBalance(playerId)
msg:addByte(GameStore.SendingPackets.S_CoinBalance)
msg:addByte(0x01)

msg:addU32(player:getCoinsBalance())
msg:addU32(player:getCoinsBalance())
msg:addU32(player:getCoinsBalance())
msg:addU32(0) -- Tournament Coins
msg:addU32(player:getCoinsBalance()) -- Tibia Coins
msg:addU32(player:getCoinsBalance()) -- How many are Transferable
msg:addU32(0) -- How many are reserved for a Character Auction
msg:addU32(player:getTournamentBalance()) -- Tournament Coins

msg:sendToPlayer(player)
end
Expand Down Expand Up @@ -1043,8 +1046,8 @@ GameStore.haveOfferRook = function(id)
return nil
end

GameStore.insertHistory = function(accountId, mode, description, amount)
return db.query(string.format("INSERT INTO `store_history`(`account_id`, `mode`, `description`, `coin_amount`, `time`) VALUES (%s, %s, %s, %s, %s)", accountId, mode, db.escapeString(description), amount, os.time()))
GameStore.insertHistory = function(accountId, mode, description, coinAmount, coinType)
return db.query(string.format("INSERT INTO `store_history`(`account_id`, `mode`, `description`, `coin_type`, `coin_amount`, `time`) VALUES (%s, %s, %s, %s, %s, %s)", accountId, mode, db.escapeString(description), coinType, coinAmount, os.time()))
end

GameStore.retrieveHistoryTotalPages = function (accountId)
Expand All @@ -1069,6 +1072,7 @@ GameStore.retrieveHistoryEntries = function(accountId, currentPage, entriesPerPa
mode = result.getDataInt(resultId, "mode"),
description = result.getDataString(resultId, "description"),
amount = result.getDataInt(resultId, "coin_amount"),
type = result.getDataInt(resultId, "coin_type"),
time = result.getDataInt(resultId, "time"),
}
table.insert(entries, entry)
Expand Down Expand Up @@ -1400,7 +1404,7 @@ function GameStore.processMountPurchase(player, offerId)
player:addMount(offerId)
end

function GameStore.processNameChangePurchase(player, offerId, productType, newName, offerName, offerPrice)
function GameStore.processNameChangePurchase(player, offer, productType, newName)
local playerId = player:getId()

if productType == GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_NAMECHANGE then
Expand All @@ -1421,10 +1425,9 @@ function GameStore.processNameChangePurchase(player, offerId, productType, newNa
return error({code = 1, message = result.reason})
end

player:removeCoinsBalance(offerPrice)
GameStore.insertHistory(player:getAccountId(), GameStore.HistoryTypes.HISTORY_TYPE_NONE, offerName, (offerPrice) * -1)
player:makeCoinTransaction(offer)

local message = string.format("You have purchased %s for %d coins.", offerName, offerPrice)
local message = string.format("You have purchased %s for %d coins.", offer.name, offer.price)
addPlayerEvent(sendStorePurchaseSuccessful, 500, playerId, message)

newName = newName:lower():gsub("(%l)(%w*)", function(a, b) return string.upper(a) .. b end)
Expand All @@ -1440,7 +1443,7 @@ function GameStore.processNameChangePurchase(player, offerId, productType, newNa
end, 1000)
-- If not, we ask him to do!
else
return addPlayerEvent(sendRequestPurchaseData, 250, playerId, offerId, GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_NAMECHANGE)
return addPlayerEvent(sendRequestPurchaseData, 250, playerId, offer.id, GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_NAMECHANGE)
end
end

Expand Down Expand Up @@ -1512,8 +1515,7 @@ function GameStore.processHirelingPurchase(player, offer, productType, hirelingN
return error({code = 1, message = "Error delivering your hireling lamp, try again later."})
end

player:removeCoinsBalance(offer.price)
GameStore.insertHistory(player:getAccountId(), GameStore.HistoryTypes.HISTORY_TYPE_NONE, offer.name .. ' ('.. hirelingName ..')', (offer.price) * -1)
player:makeCoinTransaction(offer, hirelingName)
local message = "You have successfully bought " .. hirelingName
return addPlayerEvent(sendStorePurchaseSuccessful, 650, playerId, message)
-- If not, we ask him to do!
Expand Down Expand Up @@ -1541,7 +1543,7 @@ function GameStore.processHirelingChangeNamePurchase(player, offer, productType,
local message = 'Close the store window to select which hireling should be renamed to '.. newHirelingName
addPlayerEvent(sendStorePurchaseSuccessful, 200, playerId, message)

addPlayerEvent(HandleHirelingNameChange,550, playerId, offer, newHirelingName)
addPlayerEvent(HandleHirelingNameChange, 550, playerId, offer, newHirelingName)

else
return addPlayerEvent(sendRequestPurchaseData, 250, playerId, offerId, GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_NAMECHANGE)
Expand Down Expand Up @@ -1572,6 +1574,8 @@ function GameStore.processHirelingOutfitPurchase(player, offer)
end

--==Player==--

--- Tibia Coins
function Player.getCoinsBalance(self)
resultId = db.storeQuery("SELECT `coins` FROM `accounts` WHERE `id` = " .. self:getAccountId())
if not resultId then return 0 end
Expand Down Expand Up @@ -1600,10 +1604,80 @@ end

function Player.addCoinsBalance(self, coins, update)
self:setCoinsBalance(self:getCoinsBalance() + coins)
if update then sendCoinBalanceUpdating(self, true) end
if update then sendStoreBalanceUpdating(self, true) end
return true
end

--- Tournament Coins
function Player.getTournamentBalance(self)
resultId = db.storeQuery("SELECT `tournament_coins` FROM `accounts` WHERE `id` = " .. self:getAccountId())
if not resultId then
return 0
end
return result.getDataInt(resultId, "tournament_coins")
end

function Player.setTournamentBalance(self, tournament)
db.query("UPDATE `accounts` SET `tournament_coins` = " .. tournament .. " WHERE `id` = " .. self:getAccountId())
return true
end

function Player.canRemoveTournament(self, tournament)
if self:getTournamentBalance() < tournament then
return false
end
return true
end

function Player.removeTournamentBalance(self, tournament)
if self:canRemoveTournament(tournament) then
return self:setTournamentBalance(self:getTournamentBalance() - tournament)
end

return false
end

function Player.addTournamentBalance(self, tournament, update)
self:setTournamentBalance(self:getTournamentBalance() + tournament)
if update then sendStoreBalanceUpdating(self, true) end
return true
end

--- Support Functions
function Player.makeCoinTransaction(self, offer, desc)
local op = true

if desc then
desc = offer.name .. ' (' .. desc ..')'
else
desc = offer.name
end

-- Remove coins
if offer.coinType == GameStore.CointType.Tournament then
op = self:removeTournamentBalance(offer.price)
else
op = self:removeCoinsBalance(offer.price)
end

-- When the transaction is suscessfull add to the history
if op then
GameStore.insertHistory(self:getAccountId(), GameStore.HistoryTypes.HISTORY_TYPE_NONE, desc, (offer.price) * -1, offer.coinType)
end

return op
end

function Player.canPayForOffer(self, coins, type)
if type == GameStore.CointType.Tournament then
return self:canRemoveTournament(coins)
else
return self:canRemoveCoins(coins)
end
end

--- Other players functions

function Player.sendButtonIndication(self, value1, value2)
local msg = NetworkMessage()
msg:addByte(0x19)
Expand Down Expand Up @@ -1761,18 +1835,19 @@ function HandleHirelingNameChange(playerId, offer, newHirelingName)
return player:showInfoModal("Error", "Your hireling must be inside his/her lamp.")
end

if not player:removeCoinsBalance(offer.price) then
return player:showInfoModal("Error", "Transaction error")
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
GameStore.insertHistory(player:getAccountId(), GameStore.HistoryTypes.HISTORY_TYPE_NONE, offer.name .. ' ('.. oldName .. '->' .. newHirelingName ..')', (offer.price) * -1)

player:showInfoModal('Info',string.format('%s has been renamed to %s', oldName, newHirelingName))
Spdlog.debug(string.format('%s has been renamed to %s', oldName, newHirelingName))
sendUpdatedStoreBalances(playerId)
end

player:sendHirelingSelectionModal('Choose a Hireling', 'Select a hireling below', cb, {offer=offer, newHirelingName=newHirelingName})
Expand All @@ -1791,7 +1866,7 @@ function HandleHirelingSexChange(playerId, offer)
return player:showInfoModal("Error", "Your hireling must be inside his/her lamp.")
end

if not player:removeCoinsBalance(data.offer.price) then
if not player:makeCoinTransaction(data.offer, hireling:getName()) then
return player:showInfoModal("Error", "Transaction error")
end

Expand All @@ -1809,9 +1884,8 @@ function HandleHirelingSexChange(playerId, offer)
hireling.sex = changeTo
hireling.looktype = lookType

GameStore.insertHistory(player:getAccountId(), GameStore.HistoryTypes.HISTORY_TYPE_NONE, offer.name .. ' ('.. hireling:getName() ..')', (offer.price) * -1)

player:showInfoModal('Info',string.format('%s sex was changed to %s', hireling:getName(), sexString))
Spdlog.debug(string.format('%s sex was changed to %s', hireling:getName(), sexString))
sendUpdatedStoreBalances(playerId)
end

player:sendHirelingSelectionModal('Choose a Hireling', 'Select a hireling below', cb, {offer=offer})
Expand Down
Loading