Jump to content

McSorriso309

Campones
  • Posts

    7
  • Joined

  • Last visited

About McSorriso309

Informações

  • Char no Tibia
    Sir Feel
  • Forma que conheci o xTibia
    Otservs
  • Sou
    Scripter

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

McSorriso309's Achievements

  1. Boas Guys, estou tendo problema com a store ingame no Canary 2.6.0 versão 13.10, os itens não chegando no Inbox dos chars, e não mostra nenhum erro no debug do server ou do mysql... Obs.: sistema de Inbox funcionando 100% Obs2.: ao comprar o item não aparece nenhuma mensagem e desconta o cap do player sem receber o item. init.lua: GameStore = { ModuleName = "GameStore", Developers = { "Cjaker", "metabob", "Rick" }, Version = "1.1", LastUpdated = "25-07-2020 11:52AM" } --== Enums ==-- GameStore.OfferTypes = { OFFER_TYPE_NONE = 0, OFFER_TYPE_ITEM = 1, OFFER_TYPE_STACKABLE = 2, OFFER_TYPE_CHARGES = 3, OFFER_TYPE_OUTFIT = 4, OFFER_TYPE_OUTFIT_ADDON = 5, OFFER_TYPE_MOUNT = 6, OFFER_TYPE_NAMECHANGE = 7, OFFER_TYPE_SEXCHANGE = 8, OFFER_TYPE_HOUSE = 9, OFFER_TYPE_EXPBOOST = 10, OFFER_TYPE_PREYSLOT = 11, OFFER_TYPE_PREYBONUS = 12, OFFER_TYPE_TEMPLE = 13, OFFER_TYPE_BLESSINGS = 14, OFFER_TYPE_PREMIUM = 15, OFFER_TYPE_POUNCH = 16, OFFER_TYPE_ALLBLESSINGS = 17, OFFER_TYPE_INSTANT_REWARD_ACCESS = 18, OFFER_TYPE_CHARMS = 19, OFFER_TYPE_HIRELING = 20, OFFER_TYPE_HIRELING_NAMECHANGE = 21, OFFER_TYPE_HIRELING_SEXCHANGE = 22, OFFER_TYPE_HIRELING_SKILL = 23, OFFER_TYPE_HIRELING_OUTFIT = 24, OFFER_TYPE_HUNTINGSLOT = 25 } GameStore.SubActions = { PREY_THIRDSLOT_REAL = 0, PREY_WILDCARD = 1, INSTANT_REWARD = 2, BLESSING_TWIST = 3, BLESSING_SOLITUDE = 4, BLESSING_PHOENIX = 5, BLESSING_SUNS = 6, BLESSING_SPIRITUAL = 7, BLESSING_EMBRACE = 8, BLESSING_HEART = 9, BLESSING_BLOOD = 10, BLESSING_ALL_PVE = 11, BLESSING_ALL_PVP = 12, CHARM_EXPANSION = 13, TASKHUNTING_THIRDSLOT = 14, PREY_THIRDSLOT_REDIRECT = 15 } GameStore.ActionType = { OPEN_HOME = 0, OPEN_PREMIUM_BOOST = 1, OPEN_CATEGORY = 2, OPEN_USEFUL_THINGS = 3, OPEN_OFFER = 4, } GameStore.CointType = { Coin = 0, Transferable = 1, Tournament = 2, } GameStore.Storages = { expBoostCount = 51052 } GameStore.ConverType = { SHOW_NONE = 0, SHOW_MOUNT = 1, SHOW_OUTFIT = 2, SHOW_ITEM = 3, SHOW_HIRELING = 4 } GameStore.ConfigureOffers = { SHOW_NORMAL = 0, SHOW_CONFIGURE = 1 } function convertType(type) local types = { [GameStore.OfferTypes.OFFER_TYPE_OUTFIT] = GameStore.ConverType.SHOW_OUTFIT, [GameStore.OfferTypes.OFFER_TYPE_OUTFIT_ADDON] = GameStore.ConverType.SHOW_OUTFIT, [GameStore.OfferTypes.OFFER_TYPE_MOUNT] = GameStore.ConverType.SHOW_MOUNT, [GameStore.OfferTypes.OFFER_TYPE_ITEM] = GameStore.ConverType.SHOW_ITEM, [GameStore.OfferTypes.OFFER_TYPE_STACKABLE] = GameStore.ConverType.SHOW_ITEM, [GameStore.OfferTypes.OFFER_TYPE_HOUSE] = GameStore.ConverType.SHOW_ITEM, [GameStore.OfferTypes.OFFER_TYPE_CHARGES] = GameStore.ConverType.SHOW_ITEM, [GameStore.OfferTypes.OFFER_TYPE_HIRELING] = GameStore.ConverType.SHOW_HIRELING, } if not types[type] then return GameStore.ConverType.SHOW_NONE end return types[type] end 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_SEXCHANGE] = GameStore.ConfigureOffers.SHOW_CONFIGURE } if not types[type] then return GameStore.ConfigureOffers.SHOW_NORMAL end return types[type] end GameStore.ClientOfferTypes = { CLIENT_STORE_OFFER_OTHER = 0, CLIENT_STORE_OFFER_NAMECHANGE = 1, CLIENT_STORE_OFFER_HIRELING = 3, } GameStore.HistoryTypes = { HISTORY_TYPE_NONE = 0, HISTORY_TYPE_GIFT = 1, HISTORY_TYPE_REFUND = 2 } GameStore.States = { STATE_NONE = 0, STATE_NEW = 1, STATE_SALE = 2, STATE_TIMED = 3 } GameStore.StoreErrors = { STORE_ERROR_PURCHASE = 0, STORE_ERROR_NETWORK = 1, STORE_ERROR_HISTORY = 2, STORE_ERROR_TRANSFER = 3, STORE_ERROR_INFORMATION = 4 } GameStore.ServiceTypes = { SERVICE_STANDERD = 0, SERVICE_OUTFITS = 3, SERVICE_MOUNTS = 4, SERVICE_BLESSINGS = 5 } GameStore.SendingPackets = { S_CoinBalance = 0xDF, -- 223 S_StoreError = 0xE0, -- 224 S_RequestPurchaseData = 0xE1, -- 225 S_CoinBalanceUpdating = 0xF2, -- 242 S_OpenStore = 0xFB, -- 251 S_StoreOffers = 0xFC, -- 252 S_OpenTransactionHistory = 0xFD, -- 253 S_CompletePurchase = 0xFE -- 254 } GameStore.RecivedPackets = { C_StoreEvent = 0xE9, -- 233 --(transfer-off) C_TransferCoins = 0xEF, -- 239 C_ParseHirelingName = 0xEC, -- 236 C_OpenStore = 0xFA, -- 250 C_RequestStoreOffers = 0xFB, -- 251 C_BuyStoreOffer = 0xFC, -- 252 C_OpenTransactionHistory = 0xFD, -- 253 C_RequestTransactionHistory = 0xFE, -- 254 } GameStore.ExpBoostValues = { [1] = 30, [2] = 45, [3] = 90, [4] = 180, [5] = 360 } GameStore.DefaultValues = { DEFAULT_VALUE_ENTRIES_PER_PAGE = 26 } GameStore.DefaultDescriptions = { OUTFIT = { "This outfit looks nice. Only high-class people are able to wear it!", "An outfit that was created to suit you. We are sure you'll like it.", "Legend says only smart people should wear it, otherwise you will burn!" }, MOUNT = { "This is a fantastic mount that helps to become faster, try it!", "The first rider of this mount became the leader of his country! legends say that." }, NAMECHANGE = { "Are you hunted? Tired of that? Get a new name, a new life!", "A new name to suit your needs!" }, SEXCHANGE = { "Bored of your character's sex? Get a new sex for him now!!" }, EXPBOOST = { "Are you tired of leveling slow? try it!" }, PREYSLOT = { "It's hunting season! Activate a prey to gain a bonus when hunting a certain monster. Every character can purchase one Permanent Prey Slot, which enables the activation of an additional prey. \nIf you activate a prey, you can select one monster out of nine. The bonus for your prey will be selected randomly from one of the following: damage boost, damage reduction, bonus XP, improved loot. The bonus value may range from 5% to 50%. Your prey will be active for 2 hours hunting time: the duration of an active prey will only be reduced while you are hunting." }, PREYBONUS = { "You activated a prey but do not like the randomly selected bonus? Roll for a new one! Here you can purchase five Prey Bonus Rerolls! \nA Bonus Reroll allows you to get a bonus with a higher value (max. 50%). The bonus for your prey will be selected randomly from one of the following: damage boost, damage reduction, bonus XP, improved loot. The 2 hours hunting time will start anew once you have rolled for a new bonus. Your prey monster will stay the same." }, TEMPLE = { "Need a quick way home? Buy this transportation service to get instantly teleported to your home temple. \n\nNote, you cannot use this service while having a battle sign or a protection zone block. Further, the service will not work in no-logout zones or close to your home temple." } } --==Parsing==-- GameStore.isItsPacket = function(byte) for k, v in pairs(GameStore.RecivedPackets) do if v == byte then return true end end return false end local function queueSendStoreAlertToUser(message, delay, playerId, storeErrorCode) storeErrorCode = storeErrorCode and storeErrorCode or GameStore.StoreErrors.STORE_ERROR_NETWORK addPlayerEvent(sendStoreError, delay, playerId, storeErrorCode, message) end function onRecvbyte(player, msg, byte) if not configManager.getBoolean(STOREMODULES) then return true end if player:getVocation():getId() == 0 and not GameStore.haveCategoryRook() then return player:sendCancelMessage("Store don't have offers for rookgaard citizen.") end local exaust = player:getStorageValue(Storage.StoreExaust) local currentTime = os.time() if byte == GameStore.RecivedPackets.C_StoreEvent then elseif byte == GameStore.RecivedPackets.C_TransferCoins then parseTransferCoins(player:getId(), msg) elseif byte == GameStore.RecivedPackets.C_OpenStore then if exaust > currentTime then player:sendCancelMessage("You are exhausted") return false end local num = currentTime + 1 player:setStorageValue(Storage.StoreExaust, num) parseOpenStore(player:getId(), msg) elseif byte == GameStore.RecivedPackets.C_RequestStoreOffers then parseRequestStoreOffers(player:getId(), msg) elseif byte == GameStore.RecivedPackets.C_BuyStoreOffer then parseBuyStoreOffer(player:getId(), msg) elseif byte == GameStore.RecivedPackets.C_OpenTransactionHistory then parseOpenTransactionHistory(player:getId(), msg) elseif byte == GameStore.RecivedPackets.C_RequestTransactionHistory then parseRequestTransactionHistory(player:getId(), msg) end return true end function parseTransferCoins(playerId, msg) local player = Player(playerId) if not player then return false end local reciver = msg:getString() local amount = msg:getU32() if (player:getCoinsBalance() < amount) then return addPlayerEvent(sendStoreError, 350, playerId, GameStore.StoreErrors.STORE_ERROR_TRANSFER, "You don't have this amount of coins.") end if reciver:lower() == player:getName():lower() then return addPlayerEvent(sendStoreError, 350, playerId, GameStore.StoreErrors.STORE_ERROR_TRANSFER, "You can't transfer coins to yourself.") end local resultId = db.storeQuery("SELECT `account_id` FROM `players` WHERE `name` = " .. db.escapeString(reciver:lower()) .. "") if not resultId then return addPlayerEvent(sendStoreError, 350, playerId, GameStore.StoreErrors.STORE_ERROR_TRANSFER, "We couldn't find that player.") end local accountId = result.getNumber(resultId, "account_id") if accountId == player:getAccountId() then return addPlayerEvent(sendStoreError, 350, playerId, GameStore.StoreErrors.STORE_ERROR_TRANSFER, "You cannot transfer coin to a character in the same account.") end db.query("UPDATE `accounts` SET `coins` = `coins` + " .. amount .. " WHERE `id` = " .. accountId) player:removeCoinsBalance(amount) 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.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) openStore(playerId) local category = GameStore.Categories and GameStore.Categories[1] or nil if category then addPlayerEvent(parseRequestStoreOffers, 50, playerId) end end function parseRequestStoreOffers(playerId, msg) local player = Player(playerId) if not player then return false end local actionType = msg:getByte() if actionType == GameStore.ActionType.OPEN_CATEGORY then local categoryName = msg:getString() local category = GameStore.getCategoryByName(categoryName) if category then addPlayerEvent(sendShowStoreOffers, 50, playerId, category) end elseif actionType == GameStore.ActionType.OPEN_HOME then sendHomePage(player:getId()) if category then addPlayerEvent(sendShowStoreOffers, 50, playerId, "Home Offers") end elseif actionType == GameStore.ActionType.OPEN_PREMIUM_BOOST then local subAction = msg:getByte() local category = nil if subAction == 0 then category = GameStore.getCategoryByName("Premium Time") else category = GameStore.getCategoryByName("Boosts") end if category then addPlayerEvent(sendShowStoreOffers, 50, playerId, category) end elseif actionType == GameStore.ActionType.OPEN_USEFUL_THINGS then local subAction = msg:getByte() local offerId = subAction local category = nil if subAction >= GameStore.SubActions.BLESSING_TWIST and subAction <= GameStore.SubActions.BLESSING_ALL_PVP then category = GameStore.getCategoryByName("Blessings") else category = GameStore.getCategoryByName("Useful Things") end if subAction == GameStore.SubActions.PREY_THIRDSLOT_REAL then offerId = GameStore.SubActions.PREY_THIRDSLOT_REDIRECT end if category then addPlayerEvent(sendShowStoreOffers, 50, playerId, category, offerId) end elseif actionType == GameStore.ActionType.OPEN_OFFER then local offerId = msg:getU32() local category = GameStore.getCategoryByOffer(offerId) if category then addPlayerEvent(sendShowStoreOffers, 50, playerId, category, offerId) end end end function parseBuyStoreOffer(playerId, msg) local player = Player(playerId) local id = msg:getU32() local offer = GameStore.getOfferById(id) local productType = msg:getByte() -- 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 or (not player) -- player not found or (player:getVocation():getId() == 0) and (not GameStore.haveOfferRook(id)) -- we don't have such offer or (not offer) -- we could not find the offer or (offer.type == GameStore.OfferTypes.OFFER_TYPE_NONE) -- offer is disabled or (offer.type ~= GameStore.OfferTypes.OFFER_TYPE_NAMECHANGE and offer.type ~= GameStore.OfferTypes.OFFER_TYPE_EXPBOOST and offer.type ~= GameStore.OfferTypes.OFFER_TYPE_PREYBONUS and offer.type ~= GameStore.OfferTypes.OFFER_TYPE_PREYSLOT and offer.type ~= GameStore.OfferTypes.OFFER_TYPE_TEMPLE and offer.type ~= GameStore.OfferTypes.OFFER_TYPE_SEXCHANGE and offer.type ~= GameStore.OfferTypes.OFFER_TYPE_INSTANT_REWARD_ACCESS and offer.type ~= GameStore.OfferTypes.OFFER_TYPE_POUNCH and offer.type ~= GameStore.OfferTypes.OFFER_TYPE_HIRELING and offer.type ~= GameStore.OfferTypes.OFFER_TYPE_HIRELING_NAMECHANGE and offer.type ~= GameStore.OfferTypes.OFFER_TYPE_HIRELING_SEXCHANGE and offer.type ~= GameStore.OfferTypes.OFFER_TYPE_HIRELING_SKILL and offer.type ~= GameStore.OfferTypes.OFFER_TYPE_HIRELING_OUTFIT and not offer.id) then return queueSendStoreAlertToUser("This offer is unavailable [1]", 350, playerId, GameStore.StoreErrors.STORE_ERROR_INFORMATION) end -- 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 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 -- Use pcall to catch unhandled errors and send an alert to the user because the client expects it at all times; (OTClient will unlock UI) -- Handled errors are thrown to indicate that the purchase has failed; -- Handled errors have a code index and unhandled errors do not local pcallOk, pcallError = pcall(function() if offer.type == GameStore.OfferTypes.OFFER_TYPE_ITEM then GameStore.processItemPurchase(player, offer.itemtype, offer.count) elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_POUNCH then GameStore.processItemPurchase(player, offer.itemtype, offer.count) elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_INSTANT_REWARD_ACCESS then GameStore.processInstantRewardAccess(player, offer.count) elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_CHARMS then GameStore.processCharmsPurchase(player) elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_BLESSINGS then GameStore.processSignleBlessingPurchase(player, offer.blessid, offer.count) elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_ALLBLESSINGS then GameStore.processAllBlessingsPurchase(player, offer.count) elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_PREMIUM then GameStore.processPremiumPurchase(player, offer.id) elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_STACKABLE then GameStore.processStackablePurchase(player, offer.itemtype, offer.count, offer.name) elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_HOUSE then GameStore.processHouseRelatedPurchase(player, offer.itemtype, offer.count) 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, 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) elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_HUNTINGSLOT then GameStore.processTaskHuntingThirdSlot(player) elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_PREYBONUS then GameStore.processPreyBonusReroll(player, offer.count) elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_TEMPLE then GameStore.processTempleTeleportPurchase(player) elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_CHARGES then GameStore.processChargesPurchase(player, offer.itemtype, offer.name, offer.charges) elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_HIRELING then local hirelingName = msg:getString(); local sex = msg:getByte(); GameStore.processHirelingPurchase(player, offer, productType, hirelingName, sex) elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_HIRELING_NAMECHANGE then local hirelingName = msg:getString(); GameStore.processHirelingChangeNamePurchase(player, offer, productType, hirelingName) elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_HIRELING_SEXCHANGE then GameStore.processHirelingChangeSexPurchase(player, offer) elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_HIRELING_SKILL then GameStore.processHirelingSkillPurchase(player, offer) elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_HIRELING_OUTFIT then GameStore.processHirelingOutfitPurchase(player, offer) else -- This should never happen by our convention, but just in case the guarding condition is messed up... error({code = 0, message = "This offer is unavailable [2]"}) end end) if not pcallOk then local alertMessage = pcallError.code and pcallError.message or "Something went wrong. Your purchase has been cancelled." if not pcallError.code then -- unhandled error -- log some debugging info Spdlog.warn("[parseBuyStoreOffer] - Purchase failed due to an unhandled script error. Stacktrace: ".. pcallError) end return queueSendStoreAlertToUser(alertMessage, 500, playerId) end local configure = useOfferConfigure(offer.type) if configure ~= GameStore.ConfigureOffers.SHOW_CONFIGURE then player:makeCoinTransaction(offer) local message = string.format("You have purchased %s for %d coins.", offer.name, offerPrice) sendUpdatedStoreBalances(playerId) return addPlayerEvent(sendStorePurchaseSuccessful, 650, playerId, message) end return true end -- Both functions use same formula! function parseOpenTransactionHistory(playerId, msg) local page = 1 GameStore.DefaultValues.DEFAULT_VALUE_ENTRIES_PER_PAGE = msg:getByte() sendStoreTransactionHistory(playerId, page, GameStore.DefaultValues.DEFAULT_VALUE_ENTRIES_PER_PAGE) end function parseRequestTransactionHistory(playerId, msg) local page = msg:getU32() sendStoreTransactionHistory(playerId, page + 1, GameStore.DefaultValues.DEFAULT_VALUE_ENTRIES_PER_PAGE) end local function getCategoriesRook() local tmpTable, count = {}, 0 for i, v in pairs(GameStore.Categories) do if (v.rookgaard) then tmpTable[#tmpTable + 1] = v count = count + 1 end end return tmpTable, count end --==Sending==-- function openStore(playerId) local player = Player(playerId) if not player then return false end if not GameStore.Categories then return false end local msg = NetworkMessage() msg:addByte(GameStore.SendingPackets.S_OpenStore) local GameStoreCategories, GameStoreCount = nil, 0 if (player:getVocation():getId() == 0) then GameStoreCategories, GameStoreCount = getCategoriesRook() else GameStoreCategories, GameStoreCount = GameStore.Categories, #GameStore.Categories end if (GameStoreCategories) then msg:addU16(GameStoreCount) for k, category in ipairs(GameStoreCategories) do msg:addString(category.name) msg:addByte(category.state or GameStore.States.STATE_NONE) msg:addByte(#category.icons) for m, icon in ipairs(category.icons) do msg:addString(icon) end if category.parent then msg:addString(category.parent) else msg:addU16(0) end end msg:sendToPlayer(player) sendStoreBalanceUpdating(playerId, true) end end function sendOfferDescription(player, offerId, description) local msg = NetworkMessage() msg:addByte(0xEA) msg:addU32(offerId) msg:addString(description) msg:sendToPlayer(player) end function Player.canBuyOffer(self, offer) local playerId = self:getId() local disabled, disabledReason = 0, "" if offer.disabled == true or not offer.type then disabled = 1 end if offer.type ~= GameStore.OfferTypes.OFFER_TYPE_NAMECHANGE and offer.type ~= GameStore.OfferTypes.OFFER_TYPE_EXPBOOST and offer.type ~= GameStore.OfferTypes.OFFER_TYPE_PREYSLOT and offer.type ~= GameStore.OfferTypes.OFFER_TYPE_PREYBONUS and offer.type ~= GameStore.OfferTypes.OFFER_TYPE_TEMPLE and offer.type ~= GameStore.OfferTypes.OFFER_TYPE_SEXCHANGE and offer.type ~= GameStore.OfferTypes.OFFER_TYPE_POUNCH and offer.type ~= GameStore.OfferTypes.OFFER_TYPE_HIRELING_SKILL and offer.type ~= GameStore.OfferTypes.OFFER_TYPE_HIRELING_OUTFIT and not offer.id then disabled = 1 end if disabled == 1 and offer.disabledReason then -- dynamic disable disabledReason = offer.disabledReason end if disabled ~= 1 then if offer.type == GameStore.OfferTypes.OFFER_TYPE_POUNCH then local pounch = self:getItemById(23721, true) if pounch then disabled = 1 disabledReason = "You already have Loot Pouch." end elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_BLESSINGS then if self:getBlessingCount(offer.blessid) >= 5 then disabled = 1 disabledReason = "You reached the maximum amount for this blessing." end elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_ALLBLESSINGS then for i = 1, 8 do if self:getBlessingCount(i) >= 5 then disabled = 1 disabledReason = "You already have all Blessings." break end end elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_OUTFIT or offer.type == GameStore.OfferTypes.OFFER_TYPE_OUTFIT_ADDON then local outfitLookType if self:getSex() == PLAYERSEX_MALE then outfitLookType = offer.sexId.male else outfitLookType = offer.sexId.female end if outfitLookType then if offer.type == GameStore.OfferTypes.OFFER_TYPE_OUTFIT and self:hasOutfit(outfitLookType) then disabled = 1 disabledReason = "You already have this outfit." elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_OUTFIT_ADDON then if self:hasOutfit(outfitLookType) then if self:hasOutfit(outfitLookType, offer.addon) then disabled = 1 disabledReason = "You already have this addon." end else disabled = 1 disabledReason = "You don't have the outfit, you can't buy the addon." end end else disabled = 1 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 disabled = 1 disabledReason = "You already have this mount." end elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_INSTANT_REWARD_ACCESS then if self:getCollectionTokens() >= 90 then disabled = 1 disabledReason = "You already have maximum of reward tokens." end elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_PREYBONUS then if self:getPreyCards() >= 50 then disabled = 1 disabledReason = "You already have maximum of prey wildcards." end elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_CHARMS then if self:charmExpansion() then disabled = 1 disabledReason = "You already have charm expansion." end elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_HUNTINGSLOT then if self:taskHuntingThirdSlot() then disabled = 1 disabledReason = "You already have 3 slots released." end elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_PREYSLOT then if self:preyThirdSlot() then disabled = 1 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 disabled = 1 disabledReason = "You already have an active XP boost." end elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_HIRELING then if self:getHirelingsCount() >= 10 then disabled = 1 disabledReason = "You already have bought the maximum number of allowed hirelings." end elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_HIRELING_SKILL then local skill = (HIRELING_STORAGE.SKILL + offer.id) if self:hasHirelingSkill(skill) then disabled = 1 disabledReason = "This skill is already unlocked." end if self:getHirelingsCount() <= 0 then disabled = 1 disabledReason = "You need to have a hireling." end elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_HIRELING_OUTFIT then local outfit = offer.id - HIRELING_STORAGE.OUTFIT if self:hasHirelingOutfit(outfit) then disabled = 1 disabledReason = "This hireling outfit is already unlocked." end if self:getHirelingsCount() <= 0 then disabled = 1 disabledReason = "You need to have a hireling." end elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_HIRELING_NAMECHANGE then if self:getHirelingsCount() <= 0 then disabled = 1 disabledReason = "You need to have a hireling." end elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_HIRELING_SEXCHANGE then if self:getHirelingsCount() <= 0 then disabled = 1 disabledReason = "You need to have a hireling." end end end return {disabled = disabled, disabledReason = disabledReason} end function sendShowStoreOffers(playerId, category, redirectId) local player = Player(playerId) if not player then return false end local msg = NetworkMessage() local haveSaleOffer = 0 msg:addByte(GameStore.SendingPackets.S_StoreOffers) msg:addString(category.name) msg:addU32(redirectId or 0) msg:addByte(0) -- Window Type msg:addByte(0) -- Collections Size msg:addU16(0) -- Collection Name if not category.offers then msg:addU16(0) -- Disable reasons msg:addU16(0) -- Offers msg:sendToPlayer(player) return end local disableReasons = {} local offers = {} local count = 0 for k, offer in ipairs(category.offers) do local name = offer.name or "Something Special" if not offers[name] then offers[name] = {} count = count + 1 offers[name].offers = {} offers[name].state = offer.state offers[name].id = offer.id offers[name].type = offer.type offers[name].icons = offer.icons offers[name].basePrice = offer.basePrice offers[name].description = offer.description if offer.sexId then offers[name].sexId = offer.sexId end if offer.itemtype then offers[name].itemtype = offer.itemtype end end local canBuy = player:canBuyOffer(offer) if (canBuy.disabled == 1) then for index, disableTable in ipairs(disableReasons) do if (canBuy.disabledReason == disableTable.reason) then offer.disabledReadonIndex = index end end if (offer.disabledReadonIndex == nil) then offer.disabledReadonIndex = #disableReasons table.insert(disableReasons, canBuy.disabledReason) end end table.insert(offers[name].offers, offer) end -- If player doesn't have hireling if category.name == "Hirelings" then if player:getHirelingsCount() < 1 then offers["Hireling Name Change"] = nil offers["Hireling Sex Change"] = nil offers["Hireling Trader"] = nil offers["Hireling Steward"] = nil offers["Hireling Banker"] = nil offers["Hireling Cook"] = nil count = count - 6 end end msg:addU16(#disableReasons) for _, reason in ipairs(disableReasons) do msg:addString(reason) end msg:addU16(count) if count > 0 then for name, offer in pairs(offers) do msg:addString(name) msg:addByte(#offer.offers) sendOfferDescription(player, offer.id and offer.id or 0xFFFF, offer.description) for _, off in ipairs(offer.offers) do xpBoostPrice = nil if offer.type == GameStore.OfferTypes.OFFER_TYPE_EXPBOOST then xpBoostPrice = GameStore.ExpBoostValues[player:getStorageValue(GameStore.Storages.expBoostCount)] end msg:addU32(off.id) msg:addU16(off.count) msg:addU32(xpBoostPrice or off.price) msg:addByte(off.coinType or 0x00) msg:addByte((off.disabledReadonIndex ~= nil) and 1 or 0) if (off.disabledReadonIndex ~= nil) then msg:addByte(0x01); msg:addU16(off.disabledReadonIndex) off.disabledReadonIndex = nil -- Reseting the table to nil disable reason end if (off.state) then if (off.state == GameStore.States.STATE_SALE) then local daySub = off.validUntil - os.date("*t").day if (daySub >= 0) then msg:addByte(off.state) msg:addU32(os.time() + daySub * 86400) msg:addU32(off.basePrice) haveSaleOffer = 1 else msg:addByte(GameStore.States.STATE_NONE) end else msg:addByte(off.state) end else msg:addByte(GameStore.States.STATE_NONE) end end local tryOnType = 0 local type = convertType(offer.type) msg:addByte(type); if type == GameStore.ConverType.SHOW_NONE then msg:addString(offer.icons[1]) elseif type == GameStore.ConverType.SHOW_MOUNT then local mount = Mount(offer.id) msg:addU16(mount:getClientId()) tryOnType = 1 elseif type == GameStore.ConverType.SHOW_ITEM then msg:addU16(offer.itemtype) elseif type == GameStore.ConverType.SHOW_OUTFIT then msg:addU16(player:getSex() == PLAYERSEX_FEMALE and offer.sexId.female or offer.sexId.male) local outfit = player:getOutfit() msg:addByte(outfit.lookHead) msg:addByte(outfit.lookBody) msg:addByte(outfit.lookLegs) msg:addByte(outfit.lookFeet) tryOnType = 1 elseif type == GameStore.ConverType.SHOW_HIRELING then if player:getSex() == PLAYERSEX_MALE then msg:addByte(1) else msg:addByte(2) end msg:addU16(offer.sexId.male) msg:addU16(offer.sexId.female) local outfit = player:getOutfit() msg:addByte(outfit.lookHead) msg:addByte(outfit.lookBody) msg:addByte(outfit.lookLegs) msg:addByte(outfit.lookFeet) end msg:addByte(tryOnType) -- TryOn Type msg:addU16(0) -- Collection (to-do) msg:addU16(0) -- Popularity Score (to-do) msg:addU32(0) -- State New Until (timestamp) local configure = useOfferConfigure(offer.type) if configure == GameStore.ConfigureOffers.SHOW_CONFIGURE then msg:addByte(1) else msg:addByte(0) end msg:addU16(0) -- Products Capacity (unnused) end end player:sendButtonIndication(haveSaleOffer, 1) msg:sendToPlayer(player) msg:delete() end function sendStoreTransactionHistory(playerId, page, entriesPerPage) local player = Player(playerId) if not player then return false end 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 msg = NetworkMessage() msg:addByte(GameStore.SendingPackets.S_OpenTransactionHistory) msg:addU32(totalPages > 0 and page - 1 or 0x0) -- current page msg:addU32(totalPages > 0 and totalPages or 0x0) -- total page msg:addByte(#entries) for k, entry in ipairs(entries) do msg:addU32(0) msg:addU32(entry.time) msg:addByte(entry.mode) -- 0 = normal, 1 = gift, 2 = refund msg:addU32(entry.amount) msg:addByte(entry.type) -- 0 = transferable tibia coin, 1 = normal tibia coin, 2 = tournament coin msg:addString(entry.description) msg:addByte(0) -- details end msg:sendToPlayer(player) end function sendStorePurchaseSuccessful(playerId, message) local player = Player(playerId) if not player then return false end local msg = NetworkMessage() msg:addByte(GameStore.SendingPackets.S_CompletePurchase) msg:addByte(0x00) msg:addString(message) msg:sendToPlayer(player) end function sendStoreError(playerId, errorType, message) local player = Player(playerId) if not player then return false end local msg = NetworkMessage() msg:addByte(GameStore.SendingPackets.S_StoreError) msg:addByte(errorType) msg:addString(message) msg:sendToPlayer(player) end function sendStoreBalanceUpdating(playerId, updating) local player = Player(playerId) if not player then return false end local msg = NetworkMessage() msg:addByte(GameStore.SendingPackets.S_CoinBalanceUpdating) msg:addByte(0x00) msg:sendToPlayer(player) if updating == true then sendUpdatedStoreBalances(playerId) end end function sendUpdatedStoreBalances(playerId) local player = Player(playerId) if not player then return false end local msg = NetworkMessage() msg:addByte(GameStore.SendingPackets.S_CoinBalanceUpdating) msg:addByte(0x01) msg:addByte(GameStore.SendingPackets.S_CoinBalance) msg:addByte(0x01) 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 function sendRequestPurchaseData(playerId, offerId, type) local player = Player(playerId) if not player then return false end local msg = NetworkMessage() msg:addByte(GameStore.SendingPackets.S_RequestPurchaseData) msg:addU32(offerId) msg:addByte(type) msg:sendToPlayer(player) end --==GameStoreFunctions==-- GameStore.getCategoryByName = function(name) for k, category in ipairs(GameStore.Categories) do if category.name:lower() == name:lower() then if not category.offers then return GameStore.getCategoryByName(category.subclasses[1]) end return category end end return nil end GameStore.getCategoryByOffer = function(id) for Cat_k, category in ipairs(GameStore.Categories) do if category.offers then for Off_k, offer in ipairs(category.offers) do if type(offer.id) == "number" then if offer.id == id then if not category.offers then return GameStore.getCategoryByName(category.subclasses[1]) end return category end elseif type(offer.id) == "table" then for m, offerId in pairs(offer.id) do -- in case of outfits we have offer.id = {male = ..., female = ...} if offerId == id then if not category.offers then return GameStore.getCategoryByName(category.subclasses[1]) end return category end end end end end end return nil end GameStore.getOfferById = function(id) for Cat_k, category in ipairs(GameStore.Categories) do if category.offers then for Off_k, offer in ipairs(category.offers) do if type(offer.id) == "number" then if offer.id == id then return offer end elseif type(offer.id) == "table" and (offer.type == GameStore.OfferTypes.OFFER_TYPE_OUTFIT or offer.type == GameStore.OfferTypes.OFFER_TYPE_OUTFIT_ADDON) then for m, offerId in pairs(offer.id) do -- in case of outfits we have offer.id = {male = ..., female = ...} if offerId == id then return offer end end -- case multi offer elseif type(offer.id) == "table" then local newoffer = offer for i = 1, #offer.id do local offerId = offer.id[i] if offerId == id then newoffer.id = offerId newoffer.price = offer.price[i] return newoffer end end end end end end return nil end -- Using for multi offer function GameStore.getOffersByName(name) local offers = {} for Cat_k, category in ipairs(GameStore.Categories) do if category.offers then for Off_k, offer in ipairs(category.offers) do if offer.name:lower() == name:lower() then table.insert(offers, offer) end end end end return offers end GameStore.haveCategoryRook = function() for Cat_k, category in ipairs(GameStore.Categories) do if category.offers and category.rookgaard then return true end end return false end GameStore.haveOfferRook = function(id) for Cat_k, category in ipairs(GameStore.Categories) do if category.offers and category.rookgaard then for Off_k, offer in ipairs(category.offers) do if offer.id == id then return true end end end end return nil end 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) local resultId = db.storeQuery("SELECT count(id) as total FROM store_history WHERE account_id = " .. accountId) if resultId == false then return 0 end local totalPages = result.getNumber(resultId, "total") result.free(resultId) return totalPages end GameStore.retrieveHistoryEntries = function(accountId, currentPage, entriesPerPage) local entries = {} 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 repeat local entry = { mode = result.getNumber(resultId, "mode"), description = result.getString(resultId, "description"), amount = result.getNumber(resultId, "coin_amount"), type = result.getNumber(resultId, "coin_type"), time = result.getNumber(resultId, "time"), } table.insert(entries, entry) until not result.next(resultId) result.free(resultId) end return entries end GameStore.getDefaultDescription = function(offerType, count) local t, descList = GameStore.OfferTypes if offerType == t.OFFER_TYPE_OUTFIT or offerType == t.OFFER_TYPE_OUTFIT_ADDON then descList = GameStore.DefaultDescriptions.OUTFIT elseif offerType == t.OFFER_TYPE_MOUNT then descList = GameStore.DefaultDescriptions.MOUNT elseif offerType == t.OFFER_TYPE_NAMECHANGE then descList = GameStore.DefaultDescriptions.NAMECHANGE elseif offerType == t.OFFER_TYPE_SEXCHANGE then descList = GameStore.DefaultDescriptions.SEXCHANGE elseif offerType == t.OFFER_TYPE_EXPBOOST then descList = GameStore.DefaultDescriptions.EXPBOOST elseif offerType == t.OFFER_TYPE_PREYSLOT then descList = GameStore.DefaultDescriptions.PREYSLOT elseif offerType == t.OFFER_TYPE_PREYBONUS then descList = GameStore.DefaultDescriptions.PREYBONUS elseif offerType == t.OFFER_TYPE_TEMPLE then descList = GameStore.DefaultDescriptions.TEMPLE end return descList[math.floor(math.random(1, #descList))] or "" end GameStore.canUseHirelingName = function(name) local result = { ability = false } if name:len() < 3 or name:len() > 14 then result.reason = "The length of the hireling name must be between 3 and 14 characters." return result end local match = name:gmatch("%s+") local count = 0 for v in match do count = count + 1 end local matchtwo = name:match("^%s+") if (matchtwo) then result.reason = "The hireling name can't have whitespace at begin." return result end local matchthree = name:match("[^a-zA-Z ]") if (matchthree) then result.reason = "The hireling name has invalid characters" return result end if (count > 1) then result.reason = "The hireling name have more than 1 whitespace." return result end -- just copied from znote aac. local words = { "owner", "gamemaster", "hoster", "admin", "staff", "tibia", "account", "god", "anal", "ass", "fuck", "sex", "hitler", "pussy", "dick", "rape", "adm", "cm", "gm", "tutor", "counsellor" } local split = name:split(" ") for k, word in ipairs(words) do for k, nameWord in ipairs(split) do if nameWord:lower() == word then result.reason = "You can't use word \"" .. word .. "\" in your hireling name." return result end end end local tmpName = name:gsub("%s+", "") for i = 1, #words do if (tmpName:lower():find(words[i])) then result.reason = "You can't use word \"" .. words[i] .. "\" with whitespace in your hireling name." return result end end result.ability = true return result end GameStore.canChangeToName = function(name) local result = { ability = false } if name:len() < 3 or name:len() > 14 then result.reason = "The length of your new name must be between 3 and 14 characters." return result end local match = name:gmatch("%s+") local count = 0 for v in match do count = count + 1 end local matchtwo = name:match("^%s+") if (matchtwo) then result.reason = "Your new name can't have whitespace at begin." return result end if (count > 1) then result.reason = "Your new name have more than 1 whitespace." return result end -- just copied from znote aac. local words = { "owner", "gamemaster", "hoster", "admin", "staff", "tibia", "account", "god", "anal", "ass", "fuck", "sex", "hitler", "pussy", "dick", "rape", "adm", "cm", "gm", "tutor", "counsellor" } local split = name:split(" ") for k, word in ipairs(words) do for k, nameWord in ipairs(split) do if nameWord:lower() == word then result.reason = "You can't use word \"" .. word .. "\" in your new name." return result end end end local tmpName = name:gsub("%s+", "") for i = 1, #words do if (tmpName:lower():find(words[i])) then result.reason = "You can't use word \"" .. words[i] .. "\" with whitespace in your new name." return result end end if MonsterType(name) then result.reason = "Your new name \"" .. name .. "\" can't be a monster's name." return result elseif Npc(name) then result.reason = "Your new name \"" .. name .. "\" can't be a npc's name." return result end local letters = "{}|_*+-=<>0123456789@#%^&()/*'\\.,:;~!\"$" for i = 1, letters:len() do local c = letters:sub(i, i) for i = 1, name:len() do local m = name:sub(i, i) if m == c then result.reason = "You can't use this letter \"" .. c .. "\" in your new name." return result end end end result.ability = true return result end -- -- PURCHASE PROCESSOR FUNCTIONS -- Must throw an error when the purchase has not been made. The error must of -- take a table {code = ..., message = ...} if the error is handled. When no code -- index is present the error is assumed to be unhandled. function GameStore.processItemPurchase(player, offerId, offerCount) if player:getFreeCapacity() < ItemType(offerId):getWeight(offerCount) then return error({ code = 0, message = "Please make sure you have free capacity to hold this item."}) end local inbox = player:getSlotItem(CONST_SLOT_STORE_INBOX) if inbox and inbox:getEmptySlots() > offerCount then for t = 1, offerCount do inbox:addItem(offerId, offerCount or 1) end else return error({ code = 0, message = "Please make sure you have free slots in your store inbox."}) end end function GameStore.processChargesPurchase(player, itemtype, name, charges) if player:getFreeCapacity() < ItemType(itemtype):getWeight(1) then return error({ code = 0, message = "Please make sure you have free capacity to hold this item."}) end local inbox = player:getSlotItem(CONST_SLOT_STORE_INBOX) if inbox and inbox:getEmptySlots() > 1 then inbox:addItem(itemtype, charges) else return error({ code = 0, message = "Please make sure you have free slots in your store inbox."}) end end function GameStore.processSignleBlessingPurchase(player, blessId, count) player:addBlessing(blessId, count) end function GameStore.processAllBlessingsPurchase(player, count) player:addBlessing(1, count) player:addBlessing(2, count) player:addBlessing(3, count) player:addBlessing(4, count) player:addBlessing(5, count) player:addBlessing(6, count) player:addBlessing(7, count) player:addBlessing(8, count) end function GameStore.processInstantRewardAccess(player, offerCount) if player:getCollectionTokens() + offerCount >= 91 then return error({code = 1, message = "You cannot own more than 90 reward tokens."}) end player:setCollectionTokens(player:getCollectionTokens() + offerCount) end function GameStore.processCharmsPurchase(player) player:charmExpansion(true) end function GameStore.processPremiumPurchase(player, offerId) player:addPremiumDays(offerId - 3000) end function GameStore.processStackablePurchase(player, offerId, offerCount, offerName) local function isKegItem(itemId) return itemId >= ITEM_KEG_START and itemId <= ITEM_KEG_END end local PARCEL_ID = 3504 local isKeg = isKegItem(offerId) if isKeg then if player:getFreeCapacity() < ItemType(offerId):getWeight(1) + ItemType(PARCEL_ID):getWeight() then return error({code = 0, message = "Please make sure you have free capacity to hold this item."}) end elseif player:getFreeCapacity() < ItemType(offerId):getWeight(offerCount) + ItemType(PARCEL_ID):getWeight() then return error({code = 0, message = "Please make sure you have free capacity to hold this item."}) end local inbox = player:getSlotItem(CONST_SLOT_STORE_INBOX) if inbox and inbox:getEmptySlots() > 0 then if (isKeg and offerCount > 500) or offerCount > 100 then local parcel = inbox:addItem(PARCEL_ID, 1) if parcel then parcel:setAttribute(ITEM_ATTRIBUTE_NAME, '' .. offerCount .. 'x ' .. offerName .. ' package.') local pendingCount = offerCount local limit = isKeg and 500 or 100 while (pendingCount > 0) do local pack if (pendingCount > limit) then pack = limit else pack = pendingCount end if isKeg then local kegItem = parcel:addItem(offerId, 1) kegItem:setAttribute(ITEM_ATTRIBUTE_CHARGES, pack) else parcel:addItem(offerId, pack) end pendingCount = pendingCount - pack end end else local item = inbox:addItem(offerId, isKeg and 1 or offerCount) if item and isKeg then item:setAttribute(ITEM_ATTRIBUTE_CHARGES, offerCount) end end else return error({code = 0, message = "Please make sure you have free slots in your store inbox."}) end end function GameStore.processHouseRelatedPurchase(player, offerId, offerCount) local function isCaskItem(itemId) return (itemId >= ITEM_HEALTH_CASK_START and itemId <= ITEM_HEALTH_CASK_END) or (itemId >= ITEM_MANA_CASK_START and itemId <= ITEM_MANA_CASK_END) or (itemId >= ITEM_SPIRIT_CASK_START and itemId <= ITEM_SPIRIT_CASK_END) end local inbox = player:getSlotItem(CONST_SLOT_STORE_INBOX) if inbox and inbox:getEmptySlots() > 0 then local decoKit = inbox:addItem(23398, 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(offerId):getName() .. ">.") decoKit:setCustomAttribute("unWrapId", offerId) if isCaskItem(offerId) then decoKit:setAttribute(ITEM_ATTRIBUTE_DATE, offerCount) end end else return error({code = 0, message = "Please make sure you have free slots in your store inbox."}) end end function GameStore.processOutfitPurchase(player, offerSexIdTable, addon) local looktype local _addon = addon and addon or 0 if player:getSex() == PLAYERSEX_MALE then looktype = offerSexIdTable.male elseif player:getSex() == PLAYERSEX_FEMALE then looktype = offerSexIdTable.female end if not looktype then return error({code = 0, message = "This outfit seems not to suit your sex, we are sorry for that!"}) elseif (not player:hasOutfit(looktype, 0)) and (_addon == 1 or _addon == 2) then return error({code = 0, message = "You must own the outfit before you can buy its addon."}) elseif player:hasOutfit(looktype, _addon) then return error({code = 0, message = "You already own this outfit."}) else if not (player:addOutfitAddon(looktype, _addon)) -- TFS call failed or (not player:hasOutfit(looktype, _addon)) -- Additional check; if the looktype doesn't match player sex for example, -- then the TFS check will still pass... bug? (TODO) then error({ code = 0, message = "There has been an issue with your outfit purchase. Your purchase has been cancelled."}) else player:addOutfitAddon(offerSexIdTable.male, _addon) player:addOutfitAddon(offerSexIdTable.female, _addon) end end end function GameStore.processMountPurchase(player, offerId) if player:hasMount(offerId) then return error({code = 0, message = "You already own this mount."}) end player:addMount(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 if (not tile:hasFlag(TILESTATE_PROTECTIONZONE)) then return error({code = 1, message = "You can change name only in Protection Zone."}) end end local resultId = db.storeQuery("SELECT * FROM `players` WHERE `name` = " .. db.escapeString(newName) .. "") if resultId ~= false then return error({code = 1, message = "This name is already used, please try again!"}) end local result = GameStore.canChangeToName(newName) if not result.ability then return error({code = 1, message = result.reason}) end player:makeCoinTransaction(offer) 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) db.query("UPDATE `players` SET `name` = " .. db.escapeString(newName) .. " WHERE `id` = " .. player:getGuid()) message = "You have successfully changed you name, relogin!" addEvent(function() local player = Player(playerId) if not player then return false end player:remove() end, 1000) -- If not, we ask him to do! else return addPlayerEvent(sendRequestPurchaseData, 250, playerId, offer.id, GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_NAMECHANGE) end end function GameStore.processSexChangePurchase(player) player:toggleSex() end function GameStore.processExpBoostPuchase(player) local currentExpBoostTime = player:getExpBoostStamina() local expBoostCount = player:getStorageValue(GameStore.Storages.expBoostCount) player:setStoreXpBoost(50) player:setExpBoostStamina(currentExpBoostTime + 3600) if (player:getStorageValue(GameStore.Storages.expBoostCount) == -1 or expBoostCount == 6) then player:setStorageValue(GameStore.Storages.expBoostCount, 1) end player:setStorageValue(GameStore.Storages.expBoostCount, expBoostCount + 1) end function GameStore.processPreyThirdSlot(player) if player:preyThirdSlot() then return error({code = 1, message = "You already have unlocked all prey slots."}) end player:preyThirdSlot(true) end function GameStore.processTaskHuntingThirdSlot(player) if player:taskHuntingThirdSlot() then return error({code = 1, message = "You already have unlocked all task hunting slots."}) end player:taskHuntingThirdSlot(true) end function GameStore.processPreyBonusReroll(player, offerCount) if player:getPreyCards() + offerCount >= 51 then return error({code = 1, message = "You cannot own more than 50 prey wildcards."}) end player:addPreyCards(offerCount) end function GameStore.processTempleTeleportPurchase(player) if player:getCondition(CONDITION_INFIGHT, CONDITIONID_DEFAULT) or player:isPzLocked() then return error({code = 0, message = "You can't use temple teleport in fight!"}) end player:teleportTo(player:getTown():getTemplePosition()) player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, 'You have been teleported to your hometown.') end function GameStore.processHirelingPurchase(player, offer, productType, hirelingName, chosenSex) local playerId = player:getId() local offerId = offer.id if productType == GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_HIRELING then local result = GameStore.canUseHirelingName(hirelingName) if not result.ability then return error({code = 1, message = result.reason}) end hirelingName = hirelingName:lower():gsub("(%l)(%w*)", function(a, b) return string.upper(a) .. b end) local hireling = player:addNewHireling(hirelingName, chosenSex) if not hireling then return error({code = 1, message = "Error delivering your hireling lamp, try again later."}) end player:makeCoinTransaction(offer, hirelingName) local message = "You have successfully bought " .. hirelingName return addPlayerEvent(sendStorePurchaseSuccessful, 650, playerId, message) -- If not, we ask him to do! else if player:getHirelingsCount() >= 10 then return error({code = 1, message = "You cannot have more than 10 hirelings."}) 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) end end function GameStore.processHirelingChangeNamePurchase(player, offer, productType, newHirelingName) local playerId = player:getId() local offerId = offer.id if productType == GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_NAMECHANGE then local result = GameStore.canUseHirelingName(newHirelingName) if not result.ability then return error({code = 1, message = result.reason}) end newHirelingName = newHirelingName:lower():gsub("(%l)(%w*)", function(a, b) return string.upper(a) .. b end) 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) else return addPlayerEvent(sendRequestPurchaseData, 250, playerId, offerId, GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_NAMECHANGE) end end function GameStore.processHirelingChangeSexPurchase(player, offer) local playerId = player:getId() local message = 'Close the store window to select which hireling should have the sex changed.' addPlayerEvent(sendStorePurchaseSuccessful, 200, playerId, message) addPlayerEvent(HandleHirelingSexChange, 550, playerId, offer) end function GameStore.processHirelingSkillPurchase(player, offer) player:getPosition():sendMagicEffect(CONST_ME_MAGIC_BLUE) local skill = offer.id - HIRELING_STORAGE.SKILL player:enableHirelingSkill(skill) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, 'A new hireling skill has been added to all your hirelings') end function GameStore.processHirelingOutfitPurchase(player, offer) player:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN) local outfit = offer.id - HIRELING_STORAGE.OUTFIT player:enableHirelingOutfit(outfit) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, 'A new hireling outfit has been added to all your hirelings') 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 return result.getNumber(resultId, "coins") end function Player.setCoinsBalance(self, coins) db.query("UPDATE `accounts` SET `coins` = " .. coins .. " WHERE `id` = " .. self:getAccountId()) return true end function Player.canRemoveCoins(self, coins) if self:getCoinsBalance() < coins then return false end return true end function Player.removeCoinsBalance(self, coins) if self:canRemoveCoins(coins) then return self:setCoinsBalance(self:getCoinsBalance() - coins) end return false end function Player.addCoinsBalance(self, coins, update) self:setCoinsBalance(self:getCoinsBalance() + coins) 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.getNumber(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) msg:addByte(value1) -- Sale msg:addByte(value2) -- New Item msg:sendToPlayer(self) end function Player.toggleSex(self) local currentSex = self:getSex() local playerOutfit = self:getOutfit() playerOutfit.lookAddons = 0 if currentSex == PLAYERSEX_FEMALE then self:setSex(PLAYERSEX_MALE) playerOutfit.lookType = 128 else self:setSex(PLAYERSEX_FEMALE) playerOutfit.lookType = 136 end self:setOutfit(playerOutfit) end local function getHomeOffers(playerId) local player = Player(playerId) if not player then return {} end local GameStoreCategories = GameStore.Categories local offers = {} if (GameStoreCategories) then for k, category in ipairs(GameStoreCategories) do if category.offers then for _, offer in ipairs(category.offers) do if offer.home then table.insert(offers, offer) end end end end end return offers end function sendHomePage(playerId) local player = Player(playerId) if not player then return end local msg = NetworkMessage() msg:addByte(GameStore.SendingPackets.S_StoreOffers) msg:addString("Home") msg:addU32(0x0) -- Redirect ID (not used here) msg:addByte(0x0) -- Window Type msg:addByte(0x0) -- Collections Size msg:addU16(0x00) -- Collection Name local homeOffers = getHomeOffers(player:getId()) local disableReasons = {} for p, offer in pairs(homeOffers)do local canBuy = player:canBuyOffer(offer) if (canBuy.disabled == 1) then for index, disableTable in ipairs(disableReasons) do if (canBuy.disabledReason == disableTable.reason) then offer.disabledReadonIndex = index end end if (offer.disabledReadonIndex == nil) then offer.disabledReadonIndex = #disableReasons table.insert(disableReasons, canBuy.disabledReason) end end end msg:addU16(#disableReasons) for _, reason in ipairs(disableReasons) do msg:addString(reason) end msg:addU16(#homeOffers) -- offers for p, offer in pairs(homeOffers)do msg:addString(offer.name) msg:addByte(0x1) -- ? msg:addU32(offer.id or 0) -- id msg:addU16(0x1) msg:addU32(offer.price) msg:addByte(offer.coinType or 0x00) msg:addByte((offer.disabledReadonIndex ~= nil) and 1 or 0) if (offer.disabledReadonIndex ~= nil) then msg:addByte(0x01); msg:addU16(offer.disabledReadonIndex) offer.disabledReadonIndex = nil -- Reseting the table to nil disable reason end msg:addByte(0x00) local type = convertType(offer.type) msg:addByte(type); if type == GameStore.ConverType.SHOW_NONE then msg:addString(offer.icons[1]) elseif type == GameStore.ConverType.SHOW_MOUNT then local mount = Mount(offer.id) msg:addU16(mount:getClientId()) elseif type == GameStore.ConverType.SHOW_ITEM then msg:addU16(offer.itemtype) elseif type == GameStore.ConverType.SHOW_OUTFIT then msg:addU16(player:getSex() == PLAYERSEX_FEMALE and offer.sexId.female or offer.sexId.male) local outfit = player:getOutfit() msg:addByte(outfit.lookHead) msg:addByte(outfit.lookBody) msg:addByte(outfit.lookLegs) msg:addByte(outfit.lookFeet) end msg:addByte(0) -- TryOn Type msg:addU16(0) -- Collection msg:addU16(0) -- Popularity Score msg:addU32(0) -- State New Until msg:addByte(0) -- User Configuration msg:addU16(0) -- Products Capacity end local banner = HomeBanners msg:addByte(#banner.images) for m, image in ipairs(banner.images) do msg:addString(image) msg:addByte(0x04) -- Banner Type (offer) msg:addU32(0x00) -- Offer Id msg:addByte(0) msg:addByte(0) end msg:addByte(banner.delay) -- Delay to swtich images msg:sendToPlayer(player) end function Player:openStore(serviceName) --exporting the method so other scripts can use to open store openStore(self:getId()) --local serviceType = msg:getByte() local category = GameStore.Categories and GameStore.Categories[1] or nil if serviceName and serviceName:lower() == "home" then return sendHomePage(self:getId()) end if serviceName and GameStore.getCategoryByName(serviceName) then category = GameStore.getCategoryByName(serviceName) end if category then 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 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}) 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 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}) end Resolvido Guys
  2. Eu tenho um OT Styller de windows e queria fazer ele rodar no linux (CentOS), ja vi vários tutoriais sobre compilação só que todos eram para ubuntu... Alguém me ajuda PLOX!
  3. Um amigo meu ele deu uma olhada no script do pagseguro e ele achou ums erros e arrumou: donate.php By henrique moura.
  4. Servidor novo no mercado, dedicado na Itália. [24hrs] Versão do servidor: 9.60 Map Base: Yourots Edited e Mix Yourots (Azeroth Server) Ip do servidor: phxot.sytes.net Porta: 7171 Site: phxot.sytes.net ]________________________[ Informations: • Exp Rate: 150x (Stages) • Skills Rate: 40x • Magic Rate: 30x • Loot Rate: 1x • Spawn Rate: 1x • Protection Level: 60 ]________________________[ > O servidor contém 7 cidades: Azeroth Avalon Zatur Liberty Bay Gloria Sand Trap Tiquanda > Sistema de Offline Training. > Mapa RPG bem detalhado para Ots Low e Mid rate. > Inúmeras invasões automáticas, Low e High lvl (ou iniciadas pelo comando /raid "nome"). > NPCs de Travel/Boat diferentes para cada cidade. > Mais de 100 quests (além das principais) espalhadas pelo mapa. > Quests especiais com NPCs. > Arena PvP sem perda de items. > Sistema de Guerras pelo Castelo [entre guilds] (mais detalhes abaixo) > Sistema de Refinamento e Slot (mais detalhes abaixo). > Sistema de Mineração (mais detalhes abaixo) > Scripts e sistemas aprimorados para o servidor > Equipamentos 9.60 funcionando corretamente > Novas Hunts > Raids de bosses 9.60 > Montarias por quest ]________________________[ > Sistema de Guerras pelo Castelo: Evento automático. Quando a guerra é anunciada as guilds podem batalhar pelo controle do castelo, dando use no monumento do último andar e permanecendo assim até a guerra acabar. O último jogador a ter o controle do castelo antes do tempo acabar será o vencedor, e sua guild se tornará dona do castelo. Todos os membros da Guild ganharão uma recompensa e poderão acessar o mapa do subsolo. Os membros de outras Guilds serão teleportados para o templo e não poderão acessar o castelo. O sistema envia mensagens a todos antes de o evento começar, quando começar, quando o dono do castelo muda, antes de se finalizar e ao finalizar, relatando o conquistador do castelo e a guild vencedora. ]________________________[ Não há teleports diretos para hunts ou quests. Não há items ou monstros editados(além dos trainers). Não há sistema VIP, VIP 2, VIP 3 e etc. Não há raids com monstros excessivamente fortes nas cidades iniciais. ]________________________[ > Upgrade & Slot System: • Os items podem ser refinados, tendo seu ataque, defesa e armadura aumentados. Existem 2 items para melhorar os equipamentos: Upgrade Powder que pode ser obtido em quests, drops de monstros e por mineração, possui chance de falha. Quando o upgrade falha o equipamento não é perdido, apenas voltará 1 level (de +3 para +2 por exemplo). Também há o Perfect Powder, que é muito raro de se encontrar e é obtido de quests difíceis e drop de bosses das raids. Este possui 100% de chance de sucesso; • Os jogadores também poderão abrir Slots em seus equipamentos e, de forma aleatória, criar equipamentos únicos com bônus de Hp, Mp, Ml, Shielding, Cas (Club, Axe e Sword Skill) e Distance. Enjoy!
  5. - XTIBIANOS - Parece Zuera Bless E Soul No Tibia Nao? Mais + Pura Verdade ! Vá Na Pasta Do Seu Otserv Data/Actions/Scripts Abra QualQuer Um Dos Scripts Cole Esse Codigo Re : -- By ADM Sorriso local gain = { gainArmor='&p+2',loseArmor='&p-2', gainShield='&s+#',loseShield='&s-(#+2)', gainAttack='&a+#+2',loseAttack='&a-(#+2)-2', gainDefense='&d+#+2',loseDefense='&d-(#+2)-2', chance='1000/((#*(2/(@/2)))*(@/2))', maxlvl = 8, blocked_ids = {2488,8881} } -- &a = weapon attack -- &d = weapon defense -- &s = shield defense -- &p = armor defense -- # = nivel do item -- @ = max level function isArmor(uid) uid = uid or 0 if getItemArmor(uid) > 0 and getItemAttack(uid) == 0 and getItemDefense(uid) == 0 and getItemWeaponType(uid) == 0 then return TRUE end return FALSE end function isWeapon(uid) uid = uid or 0 local f = getItemWeaponType(uid) if f == 1 or f == 2 or f == 3 then return TRUE end return FALSE end function isShield(uid) uid = uid or 0 if getItemWeaponType(uid) == 4 then return TRUE end return FALSE end function getWeaponLevel(uid) uid = uid or 0 local name = getItemName(uid) local _,_,lvl = string.find(name,'+(%d)') return tonumber(lvl) or 0 end function doTransform(s,uid) local c = string.gsub(s,'@',gain.maxlvl) local c = string.gsub(c,'&a',getItemAttack(uid)) local c = string.gsub(c,'&d',getItemDefense(uid)) local c = string.gsub(c,'&s',getItemDefense(uid)) local c = string.gsub(c,'&p',getItemArmor(uid)) local c = string.gsub(c,'#',getWeaponLevel(uid)) local q,err = loadstring('return '..c) assert(q,err) return assert(q()) end function onUse(cid, item, fromPosition, itemEx, toPosition) toPosition.stackpos = 255 if isInArray(gain.blocked_ids, itemEx.itemid) == TRUE or getItemWeaponType(itemEx.uid) > 4 or (getItemWeaponType(itemEx.uid) == 0 and isArmor(itemEx.uid) == FALSE) or itemEx.itemid == 0 then doPlayerSendTextMessage(cid, 24,"You cant refine this item.") return TRUE end if isCreature(itemEx.uid) == TRUE then return FALSE end local level = getWeaponLevel(itemEx.uid) local chance = doTransform(gain.chance,itemEx.uid) if chance >= math.random(0,100) or item.actionid >= 1000 then if level+1 > gain.maxlvl then doSendMagicEffect(toPosition, 2) return doPlayerSendTextMessage(cid, 24,"Your item is on max level, you can't upgrade it.") else setItemName(itemEx.uid, getItemNameById(itemEx.itemid)..' +'..(level+1)) doPlayerSendTextMessage(cid, 24,"Your item has been upgrated to +"..(level+1)..".") doSendMagicEffect(toPosition, 12) if isArmor(itemEx.uid) == TRUE then local get = doTransform(gain.gainArmor,itemEx.uid) setItemArmor(itemEx.uid,get) elseif isWeapon(itemEx.uid) == TRUE then setItemAttack(itemEx.uid, doTransform(gain.gainAttack,itemEx.uid)) setItemDefense(itemEx.uid, doTransform(gain.gainDefense,itemEx.uid)) elseif isShield(itemEx.uid) == TRUE then setItemDefense(itemEx.uid, doTransform(gain.gainShield,itemEx.uid)) end end else if level == 0 then doPlayerSendTextMessage(cid, 24,"No effect.") doSendMagicEffect(toPosition, 2) elseif level == gain.maxlvl then doSendMagicEffect(toPosition, 2) return doPlayerSendTextMessage(cid, 24,"Your item is on max level, you can't upgrade it.") elseif level > 0 then if level == 1 then setItemName(itemEx.uid, getItemNameById(itemEx.itemid)) doPlayerSendTextMessage(cid, 24,"Your item back to normal.") else setItemName(itemEx.uid, getItemNameById(itemEx.itemid)..' +'..(level-1)) doPlayerSendTextMessage(cid, 24,"Your item back to +"..(level-1)..".") end if isArmor(itemEx.uid) == TRUE then setItemArmor(itemEx.uid,doTransform(gain.loseArmor,itemEx.uid)) elseif isWeapon(itemEx.uid) == TRUE then setItemAttack(itemEx.uid, doTransform(gain.loseAttack,itemEx.uid)) setItemDefense(itemEx.uid, doTransform(gain.loseDefense,itemEx.uid)) elseif isShield(itemEx.uid) == TRUE then setItemDefense(itemEx.uid, doTransform(gain.loseShield,itemEx.uid)) end end doSendMagicEffect(toPosition, 9) end doRemoveItem(item.uid,1) return TRUE end Vermelho = É O Maximo De Skill Q Vc Pode Adicionar Em Uma Armor , Bom Se Vc Por 10 Ow + Vc Buga A Soul xD Azul = As Chances Da Soul Adicionar Skill Em Uma Armor Agora Vai Em Salvar Como... Bote O Nome De : Soul.lua Agora Faz A Mesma Coisa Com O Script Da Bless: -- By ADM Sorriso local gain = { gainArmor='&p+1',loseArmor='&p-1', gainShield='&s+#',loseShield='&s-(#+1)', gainAttack='&a+#+1',loseAttack='&a-(#+1)-1', gainDefense='&d+#+1',loseDefense='&d-(#+1)-1', chance='500/((#*(1/(@/2)))*(@/2))', maxlvl = 4, blocked_ids = {2488,8881} } -- &a = weapon attack -- &d = weapon defense -- &s = shield defense -- &p = armor defense -- # = nivel do item -- @ = max level function isArmor(uid) uid = uid or 0 if getItemArmor(uid) > 0 and getItemAttack(uid) == 0 and getItemDefense(uid) == 0 and getItemWeaponType(uid) == 0 then return TRUE end return FALSE end function isWeapon(uid) uid = uid or 0 local f = getItemWeaponType(uid) if f == 1 or f == 2 or f == 3 then return TRUE end return FALSE end function isShield(uid) uid = uid or 0 if getItemWeaponType(uid) == 4 then return TRUE end return FALSE end function getWeaponLevel(uid) uid = uid or 0 local name = getItemName(uid) local _,_,lvl = string.find(name,'+(%d)') return tonumber(lvl) or 0 end function doTransform(s,uid) local c = string.gsub(s,'@',gain.maxlvl) local c = string.gsub(c,'&a',getItemAttack(uid)) local c = string.gsub(c,'&d',getItemDefense(uid)) local c = string.gsub(c,'&s',getItemDefense(uid)) local c = string.gsub(c,'&p',getItemArmor(uid)) local c = string.gsub(c,'#',getWeaponLevel(uid)) local q,err = loadstring('return '..c) assert(q,err) return assert(q()) end function onUse(cid, item, fromPosition, itemEx, toPosition) toPosition.stackpos = 255 if isInArray(gain.blocked_ids, itemEx.itemid) == TRUE or getItemWeaponType(itemEx.uid) > 4 or (getItemWeaponType(itemEx.uid) == 0 and isArmor(itemEx.uid) == FALSE) or itemEx.itemid == 0 then doPlayerSendTextMessage(cid, 24,"You cant refine this item.") return TRUE end if isCreature(itemEx.uid) == TRUE then return FALSE end local level = getWeaponLevel(itemEx.uid) local chance = doTransform(gain.chance,itemEx.uid) if chance >= math.random(0,100) or item.actionid >= 1000 then if level+1 > gain.maxlvl then doSendMagicEffect(toPosition, 2) return doPlayerSendTextMessage(cid, 24,"Your item is on max level, you can't upgrade it.") else setItemName(itemEx.uid, getItemNameById(itemEx.itemid)..' +'..(level+1)) doPlayerSendTextMessage(cid, 24,"Your item has been upgrated to +"..(level+1)..".") doSendMagicEffect(toPosition, 12) if isArmor(itemEx.uid) == TRUE then local get = doTransform(gain.gainArmor,itemEx.uid) setItemArmor(itemEx.uid,get) elseif isWeapon(itemEx.uid) == TRUE then setItemAttack(itemEx.uid, doTransform(gain.gainAttack,itemEx.uid)) setItemDefense(itemEx.uid, doTransform(gain.gainDefense,itemEx.uid)) elseif isShield(itemEx.uid) == TRUE then setItemDefense(itemEx.uid, doTransform(gain.gainShield,itemEx.uid)) end end else if level == 0 then doPlayerSendTextMessage(cid, 24,"No effect.") doSendMagicEffect(toPosition, 2) elseif level == gain.maxlvl then doSendMagicEffect(toPosition, 2) return doPlayerSendTextMessage(cid, 24,"Your item is on max level, you can't upgrade it.") elseif level > 0 then if level == 1 then setItemName(itemEx.uid, getItemNameById(itemEx.itemid)) doPlayerSendTextMessage(cid, 24,"Your item back to normal.") else setItemName(itemEx.uid, getItemNameById(itemEx.itemid)..' +'..(level-1)) doPlayerSendTextMessage(cid, 24,"Your item back to +"..(level-1)..".") end if isArmor(itemEx.uid) == TRUE then setItemArmor(itemEx.uid,doTransform(gain.loseArmor,itemEx.uid)) elseif isWeapon(itemEx.uid) == TRUE then setItemAttack(itemEx.uid, doTransform(gain.loseAttack,itemEx.uid)) setItemDefense(itemEx.uid, doTransform(gain.loseDefense,itemEx.uid)) elseif isShield(itemEx.uid) == TRUE then setItemDefense(itemEx.uid, doTransform(gain.loseShield,itemEx.uid)) end end doSendMagicEffect(toPosition, 9) end doRemoveItem(item.uid,1) return TRUE end Vá Em Salvar Como... Bote O Nome De Bless.lua Agora Vá Em Actions.xml Cole Esse Script: <action itemid="8306" script="Soul.lua"/> <action itemid="8305" script="Bless.lua"/> Vermelho = Os Items Q Vao Ser A Bless E A Soul Bugs? Bom No Mw OT Extreme Nao Deu Bug + QualQer Coisa To Aki :smile_positivo: By ADM Sorriso
  6. - XTIBIANOS - Hoje Vou Ensinar Como Banir O Ip Dos Players Vá Na Pasta Do Seu Otserv Data/Talkactions/scripts Crie Um Bloco De Notas .lua Com O Nome Banip Agora Cole O Script: function onSay(cid, words, param) if(param == "") then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "Command param required.") return TRUE end local pid = getPlayerByNameWildcard(param) local tmp = getPlayerIp(pid) if(doAddIpBanishment(tmp) or pid == 0 or (isPlayerGhost(pid) == TRUE)) then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "Player " .. param .. " is not currently online.") end if isPlayerGhost(pid) == FALSE then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_RED, getCreatureName(pid) .. " has been banned.") doAddIpBanishment(tmp, 30 * 24 * 60 * 60) doRemoveCreature(pid) end return TRUE end Vermelho = Os Dias Que O Player Vai Ser Banido Agora Vá No Arquivo Talkactions.xml Cole Esse Script La: <talkaction log="yes" access="3" words="/B" script="Banip.lua"/> E Pronto ! By ADM Sorriso! :positive:
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...