diff --git a/config.lua.dist b/config.lua.dist index 6c882bd4b47..65bd1cb1102 100644 --- a/config.lua.dist +++ b/config.lua.dist @@ -6,6 +6,7 @@ useAnyDatapackFolder = false dataPackDirectory = "data-otservbr-global" -- Don't change this unless you know what you're doing coreDirectory = "data" +tournamentCoinsName = "Tournament Coins" -- Set log level -- It can be trace, debug, info, warning, error, critical, off (default: info). diff --git a/data-otservbr-global/npc/jeronimo.lua b/data-otservbr-global/npc/jeronimo.lua index 5f9fdc122e3..c1801ddf46b 100644 --- a/data-otservbr-global/npc/jeronimo.lua +++ b/data-otservbr-global/npc/jeronimo.lua @@ -23,10 +23,13 @@ npcConfig.flags = { floorchange = false, } +local tournamentCoinName = configManager.getString(configKeys.TOURNAMENT_COINS_NAME) + npcConfig.voices = { interval = 15000, chance = 50, - { text = "Change your Bar of Gold's for Items here!" }, + { text = "Change your " .. tournamentCoinName .. " for Items here!" }, + { text = "Visit our Game Store -> Tournament Shopp to check the offers" }, } local keywordHandler = KeywordHandler:new() @@ -56,15 +59,58 @@ npcType.onCloseChannel = function(npc, creature) npcHandler:onCloseChannel(npc, creature) end --- ID, Count, Price +-- ID, Count, Price, Wrappable, Charges local eventShopItems = { - ["small stamina refill"] = { 22473, 1, 100 }, - ["zaoan chess box"] = { 18339, 1, 100 }, - ["pannier backpack"] = { 19159, 1, 70 }, - ["green light"] = { 21217, 1, 70 }, - ["blood herb"] = { 3734, 3, 10 }, - ["draken doll"] = { 12044, 1, 70 }, - ["bear doll"] = { 3001, 1, 70 }, + ["exercise sword"] = { 28552, 1, 25, false, 500 }, + ["exercise axe"] = { 28553, 1, 25, false, 500 }, + ["exercise club"] = { 28554, 1, 25, false, 500 }, + ["exercise bow"] = { 28555, 1, 25, false, 500 }, + ["exercise rod"] = { 28556, 1, 25, false, 500 }, + ["exercise wand"] = { 28557, 1, 25, false, 500 }, + + ["baby brain squid"] = { 32909, 1, 800, true }, + ["baby vulcongra"] = { 32908, 1, 800, true }, + ["cerberus champion puppy"] = { 31464, 1, 800, true }, + ["guzzlemaw grub"] = { 32907, 1, 800, true }, + ["jousting eagle baby"] = { 31462, 1, 800, true }, + ["demon doll"] = { 32918, 1, 400, true }, + ["ogre rowdy doll"] = { 32944, 1, 400, true }, + ["retching horror doll"] = { 32945, 1, 400, true }, + ["vexclaw doll"] = { 32943, 1, 400, true }, + + ["gilded blessed shield"] = { 37165, 1, 1500, true }, + ["gilded crown"] = { 34332, 1, 1500, true }, + ["gilded horned helmet"] = { 38640, 1, 1500, true }, + ["gilded magic longsword"] = { 36995, 1, 1500, true }, + ["gilded warlord sword"] = { 39767, 1, 1500, true }, + + ["sublime tournament accolade"] = { 31472, 1, 500, true }, + ["tournament accolade"] = { 31470, 1, 500, true }, + + ["sublime tournament carpet"] = { 31467, 1, 100, true }, + ["tournament carpet"] = { 31466, 1, 100, true }, + + ["carved table"] = { 32972, 1, 100, true }, + ["carved table centre"] = { 32974, 1, 100, true }, + ["carved table corner"] = { 32969, 1, 100, true }, + + ["cozy couch"] = { 32948, 1, 100, true }, + ["cozy couch left end"] = { 32948, 1, 100, true }, + ["cozy couch right end"] = { 32956, 1, 100, true }, + ["cozy couch corner"] = { 32964, 1, 100, true }, + + ["zaoan chess box"] = { 18339, 1, 200, false }, + ["pannier backpack"] = { 19159, 1, 150, false }, + ["green light"] = { 21217, 1, 80, false }, + ["blood herb"] = { 3734, 3, 30, false }, + + ["cerberus champion"] = { 146, 1, 1250, false, 9999999 }, + ["jousting eagle"] = { 145, 1, 1250, false, 9999999 }, + + ["full dragon slayer"] = { 1289, 1288, 5000, false, 8888888 }, + ["full lion of war"] = { 1207, 1206, 1750, false, 8888888 }, + ["full veteran paladin"] = { 1205, 1204, 750, false, 8888888 }, + ["full void master"] = { 1203, 1202, 750, false, 8888888 }, } local function creatureSayCallback(npc, creature, type, message) @@ -75,43 +121,169 @@ local function creatureSayCallback(npc, creature, type, message) return false end + local amountTournamentCoins = player:getTournamentCoins() message = string.lower(message) - if message == "event shop" then - npcHandler:say("In our website enter in {Events} => {Events Shop}.", npc, creature) + if message == "help" or message == tournamentCoinName:lower() then + npcHandler:say("In our game store -> Tournament Shop", npc, creature) + return true + elseif message == "balance" then + npcHandler:say(string.format("Your balance is %i %s%s!", amountTournamentCoins, tournamentCoinName:lower(), amountTournamentCoins > 1 and "s" or ""), npc, creature) + return true + elseif MsgContains(message, "categor") then + npcHandler:say("You can see items by category: {Exercise Weapons}, {Dolls}, {House Decorations}, {Utils}, {Outfits} or {Mounts}.", npc, creature) + npcHandler:setTopic(playerId, 1) + return true end - if eventShopItems[message] then + if (npcHandler:getTopic(playerId) == 2 or npcHandler:getTopic(playerId) == 0) and eventShopItems[message] == nil then npcHandler:setTopic(playerId, 0) - local itemId, itemCount, itemPrice = eventShopItems[message][1], eventShopItems[message][2], eventShopItems[message][3] - if player:getItemCount(14112) > 0 then - npcHandler:say("You want buy {" .. message .. "} for " .. itemPrice .. "x?", npc, creature) - npcHandler:setTopic(message) + npcHandler:say("We can't find the item that you want, try again or access https://thorfinn.com.br/?thorfinncoins", npc, creature) + return true + end + + if npcHandler:getTopic(playerId) == 1 then + npcHandler:setTopic(playerId, 2) + local text = "We can't find the {category} that you want, try again or access https://thorfinn.com.br/?thorfinncoins" + if message == "exercise weapons" then + text = "{exercise sword} (25), {exercise axe} (25), {exercise club} (25), {exercise bow} (25), {exercise rod} (25), {exercise wand} (25). Each one with 500 charges" + elseif message == "dolls" then + text = "{baby brain squid} (800), {baby vulcongra} (800), {cerberus champion puppy} (800), {guzzlemaw grub} (800), {jousting eagle baby} (800), {demon doll} (400), {ogre rowdy doll} (400), {retching horror doll} (400), {vexclaw doll} (400)." + elseif message == "house decorations" then + text = "\nGilded: {gilded blessed shield} (1500), {gilded crown} (1500), {gilded horned helmet} (1500), {gilded magic longsword} (1500), {gilded warlord sword} (1500).\n" + .. "Accolade: {sublime tournament accolade} (500), {tournament accolade} (500).\n" + .. "Carpet: {sublime tournament carpet} (100), {tournament carpet} (100).\n" + .. "Table: {carved table} (100), {carved table centre} (100), {carved table corner} (100).\n" + .. "Cozy: {cozy couch} (100), {cozy couch left end} (100), {cozy couch right end} (100), {cozy couch corner} (100)." + elseif message == "utils" then + text = "{stamina extension} (300), {zaoan chess box} (200), {pannier backpack} (150), {green light} (80), {blood herb} (30)." + elseif message == "mounts" then + text = "{jousting eagle} (1500), {foxmouse} (2500), {doom skull} (4000), {corpsefire skull} (4000), {cerberus champion} (4000), {spirit of purity} (4000)." + elseif message == "outfits" then + text = "{full lion of war} (2000), {full veteran paladin} (2000), {full void master} (2000), {full dragon slayer} (5000)." + end + npcHandler:say(text, npc, creature) + return true + end + + if (npcHandler:getTopic(playerId) == 2 or npcHandler:getTopic(playerId) == 0) and eventShopItems[message] ~= nil then + local selected = eventShopItems[message] + local itemCount, itemPrice, itemCharge = selected[2], selected[3], selected[5] or 0 + local descCharge = "" + if itemCharge > 0 and (itemCharge ~= 9999999 and itemCharge ~= 8888888) then + descCharge = " with " .. itemCharge .. " charges" + end + + if amountTournamentCoins > 0 and amountTournamentCoins >= itemPrice then + if itemCharge == 9999999 then + npcHandler:say(string.format("You want buy %s mount for %i %s? {yes} or {no}", message, itemPrice, tournamentCoinName:lower()), npc, creature) + npcHandler:setTopic("mount", message) + elseif itemCharge == 8888888 then + npcHandler:say(string.format("You want buy %s outfit for %i %s? {yes} or {no}", message, itemPrice, tournamentCoinName:lower()), npc, creature) + npcHandler:setTopic("outfit", message) + else + npcHandler:say(string.format("You want buy %ix %s%s for %i %s? {yes} or {no}", itemCount, message, descCharge, itemPrice, tournamentCoinName:lower()), npc, creature) + end + npcHandler:setTopic(playerId, 3) + npcHandler:setTopic("selected", selected) else - npcHandler:say("You don't have " .. itemPrice .. " {Bar of Gold(s)}!", npc, creature) - return true + npcHandler:say(string.format("You don't have %i {%s}!", itemPrice, tournamentCoinName), npc, creature) + npcHandler:setTopic(playerId, 0) + npcHandler:setTopic("selected", {}) + npcHandler:setTopic("outfit", {}) + npcHandler:setTopic("mount", {}) end + return true end - if eventShopItems[npcHandler:getTopic(playerId)] then - local itemId, itemCount, itemPrice = eventShopItems[npcHandler:getTopic(playerId)][1], eventShopItems[npcHandler:getTopic(playerId)][2], eventShopItems[npcHandler:getTopic(playerId)][3] - if message == "no" then + if npcHandler:getTopic(playerId) == 3 then + if message ~= "yes" then npcHandler:say("So... what you want?", npc, creature) npcHandler:setTopic(playerId, 0) - elseif message == "yes" then - if player:getItemCount(14112) >= itemPrice then - npcHandler:say("You bought {" .. npcHandler:getTopic(playerId) .. "} " .. itemCount .. "x for " .. itemPrice .. " {Bar of Gold(s)}!", npc, creature) - player:removeItem(14112, itemPrice) - player:addItem(itemId, itemCount) - else - npcHandler:say("You don't have enough bar's.", npc, creature) + npcHandler:setTopic("selected", {}) + return true + else + local selected = npcHandler:getTopic("selected") + if not selected or selected == nil then + npcHandler:setTopic(playerId, 0) + npcHandler:setTopic("selected", {}) + logger.error("[jeronimo]: item not selected") return true end + + local itemId, itemCount, itemPrice, isWrappable, itemCharge = selected[1], selected[2], selected[3], selected[4] or false, selected[5] or 0 + + if itemCharge == 9999999 then + if player:hasMount(itemId) then + npcHandler:say("You already own this mount.", npc, creature) + return true + end + player:updateTournamentCoins(itemPrice, "remove") + player:addMount(itemId) + local mountName = npcHandler:getTopic("mount") + local msg = string.format("You bought %s mount for %i {%s}!", mountName, itemPrice, tournamentCoinName) + player:getPosition():sendMagicEffect(CONST_ME_HOLYDAMAGE) + npcHandler:say(msg, npc, creature) + npcHandler:setTopic(playerId, 0) + npcHandler:setTopic("selected", {}) + npcHandler:setTopic("mount", {}) + elseif itemCharge == 8888888 then + local female, male = itemCount, itemId + if player:hasOutfit(female) or player:hasOutfit(male) then + npcHandler:say("You already own this outfit.", npc, creature) + return true + end + player:updateTournamentCoins(itemPrice, "remove") + player:addOutfitAddon(female, 3) + player:addOutfitAddon(male, 3) + local outfitName = npcHandler:getTopic("outfit") + local msg = string.format("You bought %s outfit for %i {%s}!", outfitName, itemPrice, tournamentCoinName) + player:getPosition():sendMagicEffect(CONST_ME_HOLYDAMAGE) + npcHandler:say(msg, npc, creature) + npcHandler:setTopic(playerId, 0) + npcHandler:setTopic("selected", {}) + npcHandler:setTopic("outfit", {}) + else + local inbox = player:getSlotItem(CONST_SLOT_STORE_INBOX) + local itemT = ItemType(itemId) + if amountTournamentCoins >= itemPrice then + if inbox and inbox:getEmptySlots() > 0 and player:getFreeCapacity() >= itemT:getCapacity() then + player:updateTournamentCoins(itemPrice, "remove") + + if itemCharge > 0 then + local addedItem = player:addItem(itemId, itemCount, true) + addedItem:setAttribute("charges", itemCharge) + else + if isWrappable then + local decoKit = inbox:addItem(ITEM_DECORATION_KIT, 1) + if decoKit then + decoKit:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, "Unwrap it in your own house to create a <" .. itemT:getName() .. ">.") + decoKit:setCustomAttribute("unWrapId", itemId) + decoKit:setAttribute(ITEM_ATTRIBUTE_STORE, systemTime()) + player:sendUpdateContainer(inbox) + end + else + player:addItem(itemId, itemCount) + end + end + local descCharge = itemCharge > 0 and " with " .. itemCharge .. " charges" or "" + local msg = string.format("You bought %ix %s%s for %i {%s} and received in your store inbox!", itemCount, itemT:getName(), descCharge, itemPrice, tournamentCoinName) + player:getPosition():sendMagicEffect(CONST_ME_HOLYDAMAGE) + npcHandler:say(msg, npc, creature) + npcHandler:setTopic(playerId, 0) + npcHandler:setTopic("selected", {}) + else + npcHandler:say("You need to have capacity and empty slots to receive.", npc, creature) + end + else + npcHandler:say(string.format("You don't have enough {%s}.", tournamentCoinName), npc, creature) + end + end end end + return true end +npcHandler:setMessage(MESSAGE_GREET, "Welcome |PLAYERNAME|! You can see my offers by {categories} or if you want to change your " .. tournamentCoinName:lower() .. " to items, just say the item name! If you want help, say {help}! Or do you want know your {balance}?") npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback) npcHandler:addModule(FocusModule:new(), npcConfig.name, true, true, true) - --- npcType registering the npcConfig table npcType:register(npcConfig) diff --git a/data-otservbr-global/scripts/actions/custom/tournament_tokens.lua b/data-otservbr-global/scripts/actions/custom/tournament_tokens.lua new file mode 100644 index 00000000000..5aef9deaf67 --- /dev/null +++ b/data-otservbr-global/scripts/actions/custom/tournament_tokens.lua @@ -0,0 +1,17 @@ +local token = Action() + +local tokenId = 14112 -- bar of gold (if you don't use custom item, you need to verify all drops in monsters) + +function token.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if player:getItemCount(tokenId) > 0 then + local tournamentCoins = player:getItemCount(tokenId) + db.query("UPDATE `accounts` SET `tournament_coins` = `tournament_coins` + '" .. tournamentCoins .. "' WHERE `id` = '" .. player:getAccountId() .. "';") + player:sendTextMessage(MESSAGE_INFO_DESCR, string.format("You added %d %s to your account.", tournamentCoins, configManager.getString(configKeys.TOURNAMENT_COINS_NAME):lower())) + player:removeItem(tokenId, tournamentCoins) + player:getPosition():sendMagicEffect(CONST_ME_HOLYAREA) + end + return true +end + +token:id(tokenId) +token:register() diff --git a/data-otservbr-global/scripts/globalevents/vip/online_coins.lua b/data-otservbr-global/scripts/globalevents/vip/online_coins.lua index 074df6d6be3..7479f07db27 100644 --- a/data-otservbr-global/scripts/globalevents/vip/online_coins.lua +++ b/data-otservbr-global/scripts/globalevents/vip/online_coins.lua @@ -8,7 +8,7 @@ local config = { -- per hour | system will calculate how many coins will be given and when -- put 0 in coinsPerHour.free to disable free from receiving coins coinsPerHour = { - free = 1, + free = 0, vip = 5, }, @@ -31,7 +31,7 @@ function onlineCoinsEvent.onThink(interval) local checkIp = {} for _, player in pairs(players) do - if player:getAccountType() >= ACCOUNT_TYPE_GAMEMASTER then + if player:getGroup():getId() >= GROUP_TYPE_SENIORTUTOR or (config.coinsPerHour.free < 1 and not player:isVip()) then goto continue end @@ -43,7 +43,7 @@ function onlineCoinsEvent.onThink(interval) player:setStorageValue(config.storage, coins * 10000000) if coins >= config.awardOn then local coinsMath = math.floor(coins) - player:addTibiaCoins(coinsMath, true) + player:addTibiaCoins(coinsMath, false) player:sendTextMessage(MESSAGE_STATUS_SMALL, string.format("Congratulations %s!\z You have received %d %s for being online.", player:getName(), coinsMath, "tibia coins")) player:setStorageValue(config.storage, (coins - coinsMath) * 10000000) end diff --git a/data-otservbr-global/scripts/globalevents/vip/online_tokens.lua b/data-otservbr-global/scripts/globalevents/vip/online_tokens.lua index 8733f4fa0d3..f6694dbce0b 100644 --- a/data-otservbr-global/scripts/globalevents/vip/online_tokens.lua +++ b/data-otservbr-global/scripts/globalevents/vip/online_tokens.lua @@ -3,9 +3,9 @@ local config = { storage = Storage.VipSystem.OnlineTokensGain, checkDuplicateIps = false, - tokenItemId = 14112, -- bar of gold + tokenItemId = 14112, -- bar of gold (if you don't use custom item, you need to verify all drops in monsters) - interval = 60 * 1000, + interval = 60 * 1000, -- 1 hora -- per hour | system will calculate how many tokens will be given and when -- put 0 in tokensPerHour.free to disable free from receiving tokens @@ -30,9 +30,10 @@ function onlineTokensEvent.onThink(interval) return true end + local tournamentCoinName = configManager.getString(configKeys.TOURNAMENT_COINS_NAME) local checkIp = {} for _, player in pairs(players) do - if player:getAccountType() >= ACCOUNT_TYPE_GAMEMASTER then + if player:getGroup():getId() >= GROUP_TYPE_SENIORTUTOR then goto continue end @@ -46,7 +47,7 @@ function onlineTokensEvent.onThink(interval) local tokensMath = math.floor(tokens) local item = player:addItem(config.tokenItemId, tokensMath) if item then - player:sendTextMessage(MESSAGE_STATUS_SMALL, string.format("Congratulations %s!\z You have received %d %s for being online.", player:getName(), tokensMath, "tokens")) + player:sendTextMessage(MESSAGE_STATUS_SMALL, string.format("Congratulations %s!\z You have received %d %s for being online.", player:getName(), tokensMath, tournamentCoinName)) end player:setStorageValue(config.storage, (tokens - tokensMath) * 10000000) end diff --git a/data/scripts/talkactions/god/create_item.lua b/data/scripts/talkactions/god/create_item.lua index 7a6285ef101..723a7f047dd 100644 --- a/data/scripts/talkactions/god/create_item.lua +++ b/data/scripts/talkactions/god/create_item.lua @@ -23,16 +23,22 @@ function createItem.onSay(player, words, param) local count = tonumber(split[2]) if count then if itemType:isStackable() then - local item = Game.createItem(itemType:getId(), count) - if not item then - player:sendCancelMessage("Cannot create item") - return true - end + local stackSize = itemType:getStackSize() + local container = Game.createItem(2854) + local remainingCount = count - local ret = player:addItemEx(item, INDEX_WHEREEVER, FLAG_NOLIMIT) - if ret ~= RETURNVALUE_NOERROR then - player:sendCancelMessage(ret) + while remainingCount > 0 do + local countToAdd = math.min(remainingCount, stackSize) + local tmpItem = container:addItem(itemType:getId(), countToAdd, INDEX_WHEREEVER, FLAG_NOLIMIT) + if tmpItem then + remainingCount = remainingCount - countToAdd + else + logger.warn("Failed to add item: {}, to container", itemType:getName()) + end end + + player:addItemEx(container) + player:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN) return true elseif not itemType:isFluidContainer() then local min = 100 diff --git a/src/account/account.cpp b/src/account/account.cpp index 881b9491406..cae500428d3 100644 --- a/src/account/account.cpp +++ b/src/account/account.cpp @@ -84,7 +84,7 @@ namespace account { return { coins, ERROR_NO }; } - error_t Account::addCoins(const CoinType &type, const uint32_t &amount, const std::string &detail) { + error_t Account::addCoins(const CoinType &type, const uint32_t &amount, const std::string &detail, bool registerHistory /* = true*/) { if (!m_accLoaded) { return ERROR_NOT_INITIALIZED; } @@ -103,7 +103,9 @@ namespace account { return ERROR_STORAGE; } - registerCoinTransaction(CoinTransactionType::ADD, type, amount, detail); + if (registerHistory) { + registerCoinTransaction(CoinTransactionType::ADD, type, amount, detail); + } return ERROR_NO; } diff --git a/src/account/account.hpp b/src/account/account.hpp index 839b9928383..5ade61d48b5 100644 --- a/src/account/account.hpp +++ b/src/account/account.hpp @@ -35,9 +35,11 @@ namespace account { * * @param type Type of the coin * @param amount Amount of coins to be added + * @param detail + * @param registerHistory * @return error_t ERROR_NO(0) Success, otherwise Fail. */ - error_t addCoins(const CoinType &type, const uint32_t &amount, const std::string &detail = "ADD Coins"); + error_t addCoins(const CoinType &type, const uint32_t &amount, const std::string &detail = "ADD Coins", bool registerHistory = true); /** * @brief Removes coins from the account. diff --git a/src/config/config_definitions.hpp b/src/config/config_definitions.hpp index dc7f1caac24..0aa8b0cd770 100644 --- a/src/config/config_definitions.hpp +++ b/src/config/config_definitions.hpp @@ -118,6 +118,7 @@ enum ConfigKey_t : uint16_t { GLOBAL_SERVER_SAVE_TIME, DATA_DIRECTORY, CORE_DIRECTORY, + TOURNAMENT_COINS_NAME, FORGE_FIENDISH_INTERVAL_TYPE, FORGE_FIENDISH_INTERVAL_TIME, TIBIADROME_CONCOCTION_TICK_TYPE, diff --git a/src/config/configmanager.cpp b/src/config/configmanager.cpp index 2931464270a..c4f0f140d62 100644 --- a/src/config/configmanager.cpp +++ b/src/config/configmanager.cpp @@ -150,6 +150,7 @@ bool ConfigManager::load() { loadStringConfig(L, GLOBAL_SERVER_SAVE_TIME, "globalServerSaveTime", "06:00"); loadStringConfig(L, DATA_DIRECTORY, "dataPackDirectory", "data-otservbr-global"); loadStringConfig(L, CORE_DIRECTORY, "coreDirectory", "data"); + loadStringConfig(L, TOURNAMENT_COINS_NAME, "tournamentCoinsName", "Tournament Coins"); loadStringConfig(L, FORGE_FIENDISH_INTERVAL_TYPE, "forgeFiendishIntervalType", "hour"); loadStringConfig(L, FORGE_FIENDISH_INTERVAL_TIME, "forgeFiendishIntervalTime", "1"); diff --git a/src/lua/functions/creatures/player/player_functions.cpp b/src/lua/functions/creatures/player/player_functions.cpp index f328f3369ef..d40ea60deb7 100644 --- a/src/lua/functions/creatures/player/player_functions.cpp +++ b/src/lua/functions/creatures/player/player_functions.cpp @@ -2514,7 +2514,7 @@ int PlayerFunctions::luaPlayerGetTibiaCoins(lua_State* L) { } int PlayerFunctions::luaPlayerAddTibiaCoins(lua_State* L) { - // player:addTibiaCoins(coins) + // player:addTibiaCoins(coins[, registerHistory = true]) std::shared_ptr player = getUserdataShared(L, 1); if (!player || !player->getAccount()) { reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); @@ -2522,7 +2522,7 @@ int PlayerFunctions::luaPlayerAddTibiaCoins(lua_State* L) { return 1; } - if (player->account->addCoins(account::CoinType::COIN, getNumber(L, 2)) != account::ERROR_NO) { + if (player->account->addCoins(account::CoinType::COIN, getNumber(L, 2), "", getBoolean(L, 3, true)) != account::ERROR_NO) { reportErrorFunc("Failed to add coins"); lua_pushnil(L); return 1; @@ -2634,6 +2634,59 @@ int PlayerFunctions::luaPlayerRemoveTransferableCoins(lua_State* L) { return 1; } +int PlayerFunctions::luaPlayerGetTournamentCoins(lua_State* L) { + // player:getTournamentCoins() + std::shared_ptr player = getUserdataShared(L, 1); + if (!player || !player->getAccount()) { + reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + lua_pushnil(L); + return 1; + } + + auto [coins, result] = player->getAccount()->getCoins(account::CoinType::TOURNAMENT); + + if (result == account::ERROR_NO) { + lua_pushnumber(L, coins); + } + + return 1; +} + +int PlayerFunctions::luaPlayerUpdateTournamentCoins(lua_State* L) { + // player:updateTournamentCoins(coins, action: 'add' | 'remove') + std::shared_ptr player = getUserdataShared(L, 1); + if (!player || !player->getAccount()) { + reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + lua_pushnil(L); + return 1; + } + + std::string tournamentCoinName = asLowerCaseString(g_configManager().getString(TOURNAMENT_COINS_NAME, __FUNCTION__)); + const std::string &action = getString(L, 3); + uint32_t amount = getNumber(L, 2); + if (action == "add" && player->account->addCoins(account::CoinType::TOURNAMENT, amount, "", false) != account::ERROR_NO) { + reportErrorFunc(fmt::format("Failed to update (add) {}", tournamentCoinName)); + lua_pushnil(L); + return 1; + } else if (action == "remove" && player->account->removeCoins(account::CoinType::TOURNAMENT, amount) != account::ERROR_NO) { + if (player->account->removeCoins(account::CoinType::COIN, getNumber(L, 2)) != account::ERROR_NO) { + reportErrorFunc(fmt::format("Failed to update (remove) {}", tournamentCoinName)); + lua_pushnil(L); + return 1; + } + } + + if (player->getAccount()->save() != account::ERROR_NO) { + reportErrorFunc("Failed to save account"); + lua_pushnil(L); + return 1; + } + + pushBoolean(L, true); + + return 1; +} + int PlayerFunctions::luaPlayerHasBlessing(lua_State* L) { // player:hasBlessing(blessing) uint8_t blessing = getNumber(L, 2); diff --git a/src/lua/functions/creatures/player/player_functions.hpp b/src/lua/functions/creatures/player/player_functions.hpp index 89bf59b2740..07957120c01 100644 --- a/src/lua/functions/creatures/player/player_functions.hpp +++ b/src/lua/functions/creatures/player/player_functions.hpp @@ -225,6 +225,9 @@ class PlayerFunctions final : LuaScriptInterface { registerMethod(L, "Player", "addTransferableCoins", PlayerFunctions::luaPlayerAddTransferableCoins); registerMethod(L, "Player", "removeTransferableCoins", PlayerFunctions::luaPlayerRemoveTransferableCoins); + registerMethod(L, "Player", "getTournamentCoins", PlayerFunctions::luaPlayerGetTournamentCoins); + registerMethod(L, "Player", "updateTournamentCoins", PlayerFunctions::luaPlayerUpdateTournamentCoins); + registerMethod(L, "Player", "hasBlessing", PlayerFunctions::luaPlayerHasBlessing); registerMethod(L, "Player", "addBlessing", PlayerFunctions::luaPlayerAddBlessing); registerMethod(L, "Player", "removeBlessing", PlayerFunctions::luaPlayerRemoveBlessing); @@ -566,6 +569,9 @@ class PlayerFunctions final : LuaScriptInterface { static int luaPlayerAddTransferableCoins(lua_State* L); static int luaPlayerRemoveTransferableCoins(lua_State* L); + static int luaPlayerGetTournamentCoins(lua_State* L); + static int luaPlayerUpdateTournamentCoins(lua_State* L); + static int luaPlayerHasBlessing(lua_State* L); static int luaPlayerAddBlessing(lua_State* L); static int luaPlayerRemoveBlessing(lua_State* L);