Tudo que Mateus Robeerto postou
- Perfect Autoloot System Talkaction
-
[BOOSTED CREATURE] Vamos melhorar esse código ? TFS 1x
Using onStatsChange in TFS 1.x? That's completely incorrect — the proper way is to use onHealthChange and onManaChange. However, there is an alternative that doesn't require using two separate functions. It's working — I did it for OTG Global. Take a look at this: https://github.com/otg-br/global-11x/blob/main/data/scripts/custom_system_event/boosted_creature_system_full.lua#L192 @Under, dá uma olhada nesse sistema. O que eu fiz é bem diferente do seu, mas está funcionando 100%. Ele exibe monstros como estátuas, mostra informações de boost, porcentagem de XP e loot. Também envia mensagens com essas informações ao logar. Além disso, dá pra colocar em um piso com actionID, e quando o jogador pisa, aparece a mensagem ou executa um comando. Tudo está funcionando perfeitamente, inclusive o loot e a experiência. Se quiser, fique à vontade para dar uma olhada, adaptar para o seu GitHub ou até tornar público.
-
TFS 1.4+ Guild System – Classic Style!
Eu estava trabalhando neste sistema apenas por diversão, mas acabei gostando muito dele. Quem se lembra dos velhos dias do TFS 0.x, 0.3.6 e 0.4, quando você podia usar o comando !create guild name para convidar outros jogadores? Bons tempos! Decidi compartilhá-lo com a comunidade tibiaking. Está funcionando e foi testado na versão 1.4.2 (build 1098). Acredito que deve funcionar a partir da versão 1.3+ em diante. Aqui estão as imagens.. .Guild_System _ Classic_Style.lua
- [8.6] TFS 1.5 Downgrade - Mapa Thunder com montaria e modal widow, apenas OTCLIENT.
-
(PEDIDO) Task system (Killing in the name of) grizzly addans com boss room tfs 0.4
- HEUPE
local function doPlayerAddResets(player, count) local playerId = player:getId() local currentResets = db.storeQuery("SELECT resets FROM players WHERE id = " .. player:getGuid()) if currentResets then local newResets = result.getNumber(currentResets, "resets") + count db.query("UPDATE players SET resets = " .. newResets .. " WHERE id = " .. player:getGuid()) result.free(currentResets) else print("Erro ao obter os resets do jogador.") end end- [15.00] Crystal Server 4.0 | Mapa Global | Monk Ready
- TFS 1.5 {8.6} Nekiro Downgrade com montarias e modal window apenas para OTClient.
É bem simples e direto. Pegue o items.otb e o xml do servidor, coloque-os em data/860/. Depois, abra e selecione o SPR do cliente do servidor, edite conforme necessário, e pronto! Qualquer versão do RME abre esse mapa do Thunder normalmente, porém recomendo o OTAcademy.- [TFS 1.x+] GameStore
Apresentarei o sistema da gamestore, semelhante ao do Canary/otservBrasil, que está funcionando perfeitamente com o TFS 1.x+. A gamestore foi testada com o TFS 1.4.2, utilizando o protocolo 1098. Basta clicar nos links abaixo para ver os GIFs de como funciona: Tibia client cip 1098. https://imgur.com/6GkEKYY OtClient v8 (Kondra ou OTAcademy). https://imgur.com/z1Mr9Lr OTClient com um módulo personalizado (também vou disponibilizá-lo gratuitamente). https://imgur.com/3wSwiba Para exibir as imagens in game, você precisa configurar seu site, seja Gesior, MyAcc ou Znote. Lembre-se de definir corretamente o local das imagens e verificar o config.lua. -- Store configuration storeImagesUrl = "http://localhost/images/store/" storeCoinsPacketSize = 25 Incluí o repositório com dois commits que exigem alterações na source e no Lua. O primeiro e o segundo commits trazem correções para entrega de itens, outfits premium, etc. 1 = https://github.com/Mateuzkl/forgottenserver-1.4.2-clean/commit/25907d1e472911f69a2dffb3cd73f599d0655d90 2 = https://github.com/Mateuzkl/forgottenserver-1.4.2-clean/commit/2c5aec16c6407035d4b515cfd594548496ca42f9 É só baixar store.rar e adicionar ao seu site, seja MyAcc, Gesior, etc. https://github.com/Mateuzkl/forgottenserver-1.4.2-clean/commit/2c5aec16c6407035d4b515cfd594548496ca42f9 module game_store.rar. https://github.com/Mateuzkl/forgottenserver-1.4.2-clean/blob/main/game_store.rar Fiz as alterações necessárias para o TFS 1.3+ Nekiro e agora está funcionando bem. Vou enviar o commit, então acompanhe. Boa sorte! Depois disso, você deve adicionar o otc feature.lua e incluír. g_game.enableFeature(GameIngameStore) g_game.enableFeature(GameIngameStoreServiceType) g_game.enableFeature(GameIngameStoreHighlights) commit tfs 1.3 + downgrade nekiro. https://github.com/Mateuzkl/TFS-1.5-Downgrades-8.60/commit/873dd0a98dbe4b82a556107f2aa95b8820a3a9c7 Aproveite! OBS: Alguém, mod ou administrador, não sei como adicionar GIFs neste fórum. Tentei adicionar e não apareceu nada, então coloquei apenas links. Alguém pode explicar como fazer isso?- Teleport Problem
<!-- StepIn for multiple action IDs leading to the PVP arena --> <movevent event="StepIn" actionid="7400" script="arenaPVP.lua" /> <movevent event="StepIn" actionid="7401" script="arenaPVP.lua" /> <!-- StepIn for returning to the saved position --> <movevent event="StepIn" actionid="7402" script="backsavedposition.lua" /> arenaPVP.lua function onStepIn(creature, item, position, fromPosition) local player = creature:getPlayer() if not player then return true end -- Save the player's current position to storage local playerPosition = player:getPosition() -- Save the exact X, Y, Z coordinates in player's storage player:setStorageValue(50001, playerPosition.x) -- Save X position player:setStorageValue(50002, playerPosition.y) -- Save Y position player:setStorageValue(50003, playerPosition.z) -- Save Z position -- Teleport the player to the PVP area local pvpPosition = Position(158, 122, 7) -- Coordinates of the PVP area player:teleportTo(pvpPosition) player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) -- Send a welcome message player:sendTextMessage(MESSAGE_INFO_DESCR, "Welcome to the PVP area. Fight with honor!") return true end backsavedposition.lua function onStepIn(creature, item, position, fromPosition) local player = creature:getPlayer() if not player then return true end -- Retrieve the player's original position from storage local x = player:getStorageValue(50001) local y = player:getStorageValue(50002) local z = player:getStorageValue(50003) -- Check if the position is valid (storage returns -1 if nothing was saved) if x == -1 or y == -1 or z == -1 then player:sendTextMessage(MESSAGE_STATUS_WARNING, "Error: No original position found.") return true end -- Increment Y by 1 to move the player down one tile y = y + 1 -- Create the corrected original position object using the stored values local originalPosition = Position(x, y, z) -- Teleport the player back to their adjusted original position player:teleportTo(originalPosition) player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) return true end- TODAS AS SPRITES DO CLIENT 11.46
- Item updade - Oen
- TFS 1.5 {8.6} Nekiro Downgrade com montarias e modal window apenas para OTClient.
Eu recomendo que você baixe o otclient da Academy, é bem melhor do que o Kondra. Eu sei que o otclient da Mehah é mais atualizado sim. Tente seguir o que o L3K0T disse. Se não funcionar, vou me empenhar para resolver o caso e fazer com que funcione tanto o otclient da Academy quanto o da Mehah. Desista da minha base TFS que tem montaria e modal widow... e baixe a base da Sarah, muito melhor e mais atualizada. Ela possui montaria e suporta opcode através do config.lua do servidor para ativar a montaria, entre outras coisas. Vale a pena experimentar a base da Sarah!- (Resolvido)-=[TFS]=- 0.3.6 - 8.60 CRITICAL STONE and BOOSTER ATTACK STONE DANDO ERRO [AJUDA]
como ta tag XML?? local criticalConfig = { normal = { storage = 48913, damage = 100, chanceMultiplier = 3, effect = 54, text = "+BOOSTER!", textColor = 31, combatEffect = 255 }, danger = { storage = 48904, damage = 150, chanceMultiplier = 3, effect = 52, text = "DANGER!", textColor = 190, combatEffect = 255 } } function onCombat(cid, target) if isPlayer(cid) and isCreature(target) then local chance = math.random(1, 1000) local function applyCritical(criticalType) local config = criticalConfig[criticalType] local criticalChance = getPlayerStorageValue(cid, config.storage) or 0 print("Tentando aplicar crítico do tipo:", criticalType) -- Debug if chance <= (criticalChance * config.chanceMultiplier) then local combat = createCombatObject() if combat then print("Combat criado com sucesso") -- Debug else print("Erro ao criar combat") -- Debug return false end setCombatParam(combat, COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE) setCombatParam(combat, COMBAT_PARAM_EFFECT, config.combatEffect) setCombatFormula(combat, COMBAT_FORMULA_LEVELMAGIC, -config.damage, -config.damage, 0, 0) local result = doCombat(cid, combat, numberToVariant(target)) if result == RETURNVALUE_NOERROR then print("Combat executado com sucesso") -- Debug else print("Erro ao executar combat, código de retorno:", result) -- Debug end doSendAnimatedText(getCreaturePosition(target), config.text, config.textColor) doSendMagicEffect(getCreaturePosition(cid), config.effect) return true end return false end -- Tenta aplicar o crítico 'normal' e se falhar, tenta aplicar o 'danger' if not applyCritical('normal') then applyCritical('danger') end else print("Erro: cid não é jogador ou target não é criatura.") -- Debug end return true end XML <event type="combat" name="CriticalSam" script="criticalsam.lua"/>- (Resolvido)-=[TFS]=- 0.3.6 - 8.60 CRITICAL STONE and BOOSTER ATTACK STONE DANDO ERRO [AJUDA]
Eu só dei uma melhorada no script e limpei a sintaxe em LUA. local criticalConfig = { normal = { storage = 48913, damage = 100, chanceMultiplier = 3, effect = 54, text = "+BOOSTER!", textColor = 31, combatEffect = 255 }, danger = { storage = 48904, damage = 150, chanceMultiplier = 3, effect = 52, text = "DANGER!", textColor = 190, combatEffect = 255 } } function onCombat(cid, target) if isPlayer(cid) and isCreature(target) then local chance = math.random(1, 1000) local function applyCritical(criticalType) local config = criticalConfig[criticalType] local criticalChance = getPlayerStorageValue(cid, config.storage) or 0 if chance <= (criticalChance * config.chanceMultiplier) then local combat = createCombatObject() setCombatParam(combat, COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE) setCombatParam(combat, COMBAT_PARAM_EFFECT, config.combatEffect) setCombatFormula(combat, COMBAT_FORMULA_LEVELMAGIC, -config.damage, -config.damage, 0, 0) doCombat(cid, combat, numberToVariant(target)) doSendAnimatedText(getCreaturePosition(target), config.text, config.textColor) doSendMagicEffect(getCreaturePosition(cid), config.effect) return true end return false end -- Tenta aplicar o crítico 'normal' e se falhar, tenta aplicar o 'danger' if not applyCritical('normal') then applyCritical('danger') end end return true end- TFS 1.5 {8.6} Nekiro Downgrade com montarias e modal window apenas para OTClient.
Call me on Discord, I'll guide you on how to compile the source code. The other items.xml have already been fixed, so I can send them to you 82mateusroberto- [TFS 1.4.2] Reward Chest System!!
Com esse sistema desenvolvido pelo TFS 0.4 8.60 do @Luan Luciano, peguei e adaptei para TFS 1x. Basicamente, o sistema funciona da seguinte forma : Você determina as criaturas que funcionarão com este sistema (geralmente chefes). Durante a batalha com a criatura, o sistema concede pontos aos jogadores por atacar, bloquear e apoiar (curar) aqueles em batalha. Quando a criatura é morta, o sistema cria o saque com base nos pontos e o envia para o depósito do jogador em uma sacola especificada nas configurações Aqui está o GIF, mostrando quando o chefe é morto e o saque é enviado pelo correio. https://imgur.com/AJiM1mh registre o evento em determinado arquivo de monstro. XML. <script> <event name="RewardChestDeath"/> <event name="RewardChestMonster"/> </script> defina o cadáver do chefe como 0. <look type="201" corpse="0" /> Isto é RevScripts. Coloque o script em qualquer lugar da pasta data/scripts, seja uma subpasta ou seu local preferido . Reward_Chest_System.lua local function addRewardLoot(uid, bossName, rewardTable) local money = math.random(10, 40) local msg = "The following items are available in your reward chest:" local player = Player(uid) local chest = Game.createItem(REWARDCHEST.rewardBagId) if not player or not chest then return end chest:setAttribute("description", "Reward System has kill the boss " .. bossName .. ".") for _, reward in ipairs(rewardTable) do if math.random(100) <= reward[3] then local count = math.random(1, reward[2]) chest:addItem(reward[1], count) msg = msg .. " " .. (count > 1 and count or "") .. " " .. ItemType(reward[1]):getName() .. "," end end chest:addItem(2152, money) chest:moveTo(player:getInbox()) player:sendTextMessage(MESSAGE_INFO_DESCR, msg .. " and " .. money .. " platinum coins.") local boss = REWARDCHEST.bosses[bossName] player:setStorageValue(boss.storage, 0) player:getPosition():sendMagicEffect(CONST_ME_MAGIC_BLUE) end local function addLoot(lootTable, rewardTable, allLoot) if allLoot then for _, loot in ipairs(lootTable) do table.insert(rewardTable, loot) end else table.insert(rewardTable, lootTable[math.random(#lootTable)]) end end local function rewardChestSystem(bossName) local players = {} local boss = REWARDCHEST.bosses[bossName] for _, player in ipairs(Game.getPlayers()) do local points = player:getStorageValue(boss.storage) if points > 0 then table.insert(players, {player = player, points = points}) end end table.sort(players, function(a, b) return a.points > b.points end) local topPoints = players[1] and players[1].points or 0 for i, playerData in ipairs(players) do local player = playerData.player local points = playerData.points local rewardTable = {} if i == 1 then addLoot(boss.common, rewardTable, false) addLoot(boss.semiRare, rewardTable, false) addLoot(boss.rare, rewardTable, false) addLoot(boss.always, rewardTable, true) elseif points >= math.ceil(topPoints * 0.8) then addLoot(boss.common, rewardTable, false) addLoot(boss.semiRare, rewardTable, false) addLoot(boss.rare, rewardTable, false) addLoot(boss.veryRare, rewardTable, false) elseif points >= math.ceil(topPoints * 0.6) then addLoot(boss.common, rewardTable, false) addLoot(boss.semiRare, rewardTable, false) addLoot(boss.rare, rewardTable, false) elseif points >= math.ceil(topPoints * 0.4) then addLoot(boss.common, rewardTable, false) addLoot(boss.semiRare, rewardTable, false) elseif points >= math.ceil(topPoints * 0.1) then addLoot(boss.common, rewardTable, false) end addRewardLoot(player:getId(), bossName, rewardTable) end end local RewardChestDeath = CreatureEvent("RewardChestDeath") function RewardChestDeath.onDeath(creature, corpse, killer) local boss = REWARDCHEST.bosses[creature:getName():lower()] if boss then addEvent(rewardChestSystem, 1000, creature:getName():lower()) end return true end RewardChestDeath:register() local RewardChestMonster = CreatureEvent("RewardChestMonster") function RewardChestMonster.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin) if creature:isMonster() and primaryType == COMBAT_PHYSICALDAMAGE and attacker:isPlayer() then local boss = REWARDCHEST.bosses[creature:getName():lower()] if boss then local currentPoints = attacker:getStorageValue(boss.storage) local newPoints = currentPoints + math.ceil(primaryDamage / REWARDCHEST.formula.hit) attacker:setStorageValue(boss.storage, newPoints) end end return primaryDamage, primaryType end RewardChestMonster:register() local LoginPlayer = CreatureEvent("LoginPlayer") function LoginPlayer.onLogin(player) for _, value in pairs(REWARDCHEST.bosses) do if player:getStorageValue(value.storage) > 0 then player:setStorageValue(value.storage, 0) end end player:registerEvent("RewardChestStats") return true end LoginPlayer:register() local RewardChestStats = CreatureEvent("RewardChestStats") function RewardChestStats.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin) if attacker and attacker:isMonster() and (primaryType == COMBAT_PHYSICALDAMAGE or secondaryType == COMBAT_PHYSICALDAMAGE) then local boss = REWARDCHEST.bosses[attacker:getName():lower()] if boss then local currentPoints = creature:getStorageValue(boss.storage) local newPoints = currentPoints + math.ceil(math.abs(primaryDamage) / REWARDCHEST.formula.block) creature:setStorageValue(boss.storage, newPoints) creature:setStorageValue(REWARDCHEST.storageExaust, os.time() + 5) end elseif attacker and attacker:isPlayer() and (primaryType == COMBAT_HEALING or secondaryType == COMBAT_HEALING) and (creature:getHealth() < creature:getMaxHealth()) and (creature:getStorageValue(REWARDCHEST.storageExaust) >= os.time()) then for _, valor in pairs(REWARDCHEST.bosses) do if creature:getStorageValue(valor.storage) > 0 then local add = math.min(primaryDamage, creature:getMaxHealth() - creature:getHealth()) local currentPoints = attacker:getStorageValue(valor.storage) local newPoints = currentPoints + math.ceil(add / REWARDCHEST.formula.suport) attacker:setStorageValue(valor.storage, newPoints) end end end return primaryDamage, primaryType end RewardChestStats:register() Agora, esta parte sobre raridades de loot de monstros... deve ser adicionada ao data/lib e criar um arquivo.lua chamado RewardChestSystem.lua e adicionar tudo isso. -- Reward system created by luanluciano93 for TFS 0.4, function adapted by Mateus Roberto for TFS 1.3+ using RevScripts. REWARDCHEST = { rewardBagId = 2595, formula = {hit = 3, block = 1, support = 9}, storageExhaust = 60000, town_id = 1, bosses = { ["ghazbaran"] = -- the boss's entire name in lower case. { common = { {2143, 10, 100}, -- white pearl {2146, 10, 100}, -- small sapphire {2145, 10, 100}, -- small diamond {2144, 10, 100}, -- black pearl {2149, 10, 100}, -- small emeralds {5954, 3, 100}, -- demon horn {7896, 1, 100}, -- glacier kilt {7590, 1, 100}, -- great mana potion {2179, 1, 100}, -- gold ring {2151, 1, 100}, -- talon }, semiRare = { {2152, 90, 100}, -- platinum coin {7368, 50, 100}, -- assassin star {2130, 1, 100}, -- golden amulet {2436, 1, 100}, -- skull staff {2447, 1, 100}, -- twin axe {2171, 1, 100}, -- platinum amulet {2158, 1, 100}, -- blue gem {2393, 1, 100}, -- giant sword {2164, 1, 100}, -- might ring {7454, 1, 100}, -- glorious axe {6553, 1, 100}, -- ruthless axe {9971, 1, 100}, -- gold ingot }, rare = { {2160, 3, 100}, -- crystal coin {8887, 1, 100}, -- frozen plate {2470, 1, 100}, -- golden legs {2472, 1, 100}, -- magic plate armor {7431, 1, 100}, -- demonbone {2520, 1, 100}, -- demon shield {5943, 1, 100}, -- morgaroth heart {2466, 1, 100}, -- golden armor {2514, 1, 100}, -- mastermind shield {2142, 1, 100}, -- ancient amulet {2123, 1, 100}, -- ring of the sky {1984, 1, 100}, -- blue tome }, veryRare = { {8866, 1, 100}, -- robe of the ice queen {6553, 1, 100}, -- ruthless axe {8884, 1, 100}, -- oceanborn leviathan armor {2421, 1, 100}, -- thunder hammer {2646, 1, 100}, -- golden boots {7455, 1, 100}, -- mythril axe }, always = { {2148, 90, 100}, -- gold coin {6500, 9, 100}, -- demonic essence {2177, 1, 100}, -- life crystal {2214, 1, 100}, -- ring of healing }, storage = 65479, }, ["orshabaal"] = -- the boss's entire name in lower case. { common = { {2143, 10, 100}, -- white pearl {2146, 10, 100}, -- small sapphire {2145, 10, 100}, -- small diamond {2144, 10, 100}, -- black pearl {2149, 10, 100}, -- small emeralds {5954, 3, 100}, -- demon horn {7896, 1, 100}, -- glacier kilt {2432, 1, 100}, -- fire axe {2462, 1, 100}, -- devil helmet {7590, 1, 100}, -- great mana potion {2179, 1, 100}, -- gold ring {2151, 1, 100}, -- talon }, semiRare = { {2195, 1, 100}, -- boots of haste {2436, 1, 100}, -- skull staff {2393, 1, 100}, -- giant sword {5954, 5, 100}, -- demon horn }, rare = { {2470, 1, 100}, -- golden legs {2472, 1, 100}, -- magic plate armor {2514, 1, 100}, -- mastermind shield {2520, 1, 100}, -- demon shield {1982, 1, 100}, -- purple tome {2123, 1, 100}, -- ring of the sky }, veryRare = { {8890, 1, 100}, -- robe of the underworld {2421, 1, 100}, -- thunder hammer }, always = { {5808, 1, 100}, -- orshabaal's brain {2171, 1, 100}, -- platinum amulet {2148, 90, 100}, -- gold coin {2146, 10, 100}, -- small sapphire }, storage = 65480, }, ["ferumbras"] = -- the boss's entire name in lower case. { common = { {2143, 10, 100}, -- white pearl {2146, 10, 100}, -- small sapphire {2145, 10, 100}, -- small diamond {2144, 10, 100}, -- black pearl {2149, 10, 100}, -- small emeralds {7416, 1, 100}, -- bloody edge {7896, 1, 100}, -- glacier kilt {2432, 1, 100}, -- fire axe {2462, 1, 100}, -- devil helmet {7590, 1, 100}, -- great mana potion {2179, 1, 100}, -- gold ring {2151, 1, 100}, -- talon }, semiRare = { {2195, 1, 100}, -- boots of haste {2472, 1, 100}, -- magic plate armor {2393, 1, 100}, -- giant sword {2470, 1, 100}, -- golden legs {2514, 1, 100}, -- mastermind shield }, rare = { {8885, 1, 100}, -- divine plate {2520, 1, 100}, -- demon shield {8930, 1, 100}, -- emerald sword {2522, 1, 100}, -- great shield {2421, 1, 100}, -- thunder hammer }, veryRare = { {5903, 1, 100}, -- ferumbras' hat }, always = { {2171, 1, 100}, -- platinum amulet {2148, 90, 100}, -- gold coin {2146, 10, 100}, -- small sapphire }, storage = 65481, }, ["zulazza the corruptor"] = --- the boss's entire name in lower case. { common = { {2158, 1, 100}, -- blue gem {2156, 1, 100}, -- red gem {2155, 1, 100}, -- green gem {2154, 1, 100}, -- yellow gem {2153, 1, 100}, -- violet gem }, semiRare = { {5944, 5, 100}, -- soul orb }, rare = { {2514, 1, 100}, -- mastermind shield }, veryRare = { {11114, 1, 100}, -- dragon scale boots {8882, 1, 100}, -- earthborn titan armor }, always = { {2152, 90, 100}, -- platinum coin {9971, 5, 100}, -- gold ingot }, storage = 65482, }, ["morgaroth"] = -- the boss's entire name in lower case. { common = { {2143, 10, 100}, -- white pearl {2146, 10, 100}, -- small sapphire {2145, 10, 100}, -- small diamond {2144, 10, 100}, -- black pearl {2149, 10, 100}, -- small emeralds {5954, 3, 100}, -- demon horn {7896, 1, 100}, -- glacier kilt {2432, 1, 100}, -- fire axe {2462, 1, 100}, -- devil helmet {7590, 1, 100}, -- great mana potion {2179, 1, 100}, -- gold ring {2151, 1, 100}, -- talon }, semiRare = { {2195, 1, 100}, -- boots of haste {2393, 1, 100}, -- giant sword {5954, 5, 100}, -- demon horn {2123, 1, 100}, -- ring of the sky }, rare = { {8886, 1, 100}, -- molten plate {2472, 1, 100}, -- magic plate armor {8867, 1, 100}, -- dragon robe {2514, 1, 100}, -- mastermind shield {2520, 1, 100}, -- demon shield {1982, 1, 100}, -- purple tome {8851, 1, 100}, -- royal crossbow }, veryRare = { {2421, 1, 100}, -- thunder hammer {2522, 1, 100}, -- great shield {8850, 1, 100}, -- chain bolter }, always = { {5943, 1, 100}, -- morgaroth's brain {2171, 1, 100}, -- platinum amulet {2148, 90, 100}, -- gold coin {2146, 10, 100}, -- small sapphire }, storage = 65483, }, } } Por último, adicione isto a data/lib/lib.lua e inclua-o. ----Reward Chest System dofile('data/lib/RewardChestSystem.lua') Incrível, você pode configurar os itens de saque de cada chefe individualmente. Está dentro da lib/RewardChestSystem, então aproveite. Para quem usa Nekiro ou qualquer base TFS 1.x Downgrades, basta alterar esta linha. chest:moveTo(player:getInbox()) para. local depotChest = player:getDepotChest(REWARDCHEST.town_id, true) chest:moveTo(depotChest)- [8.0] [TFS 1.2] - Server Global Full [Real Map com quest log em todas as quests e missoes]
.. É válido afirmar que o Nekiro apresenta vantagens significativas em relação ao TFS 1.2, estando mais atualizado. O sucesso depende da habilidade em manipular o projeto, incluindo aspectos como vocações, poções e outros similares à versão 8.0, garantindo assim resultados positivos. É essencial focar no desenvolvimento do projeto, pesquisar soluções relevantes e manter a fonte atualizada para garantir sua estabilidade. Quanto ao TFS 1.5, confirma-se que o Nekiro é uma opção que vale a pena considerar. Obs:: Eu abandonei o Nekiro e migrei para o 1.4.2 com 1098.- [TFS 1.3] Task System + Daily Task System and Rank Look System.
Os scripts já foram corrigidos e atualizados. O que fiz? Além disso, adicionei duas verificações para evitar abusos por parte de terceiros. local creaturePos = member:getPosition() local killedMobPos = target:getPosition() local tile = Tile(creaturePos) if not tile:hasFlag(TILESTATE_PROTECTIONZONE) and killedMobPos:getDistance(creaturePos) < 25 then Também corrigi outro NPC que, antes, não respondia quando se dizia 'hi' e 'reward'. Agora ele responde normalmente.!! OBS: Para quem quer diminuir ou aumentar esse SQM, basta procurar essa linha e ajustá-la conforme desejado killedMobPos:getDistance(creaturePos) < 25 then- TFS 1.5 {8.6} Nekiro Downgrade com montarias e modal window apenas para OTClient.
Acredito que seu RME Editor está desatualizado. É melhor baixar a versão mais recente, pois ela abriu o mapa normalmente, sem problemas- TFS 1.5 {8.6} Nekiro Downgrade com montarias e modal window apenas para OTClient.
Abrimos normalmente aqui, mas você marcou o SPR como estendido? Segue a imagem. Recomendo usar os arquivos items.otb e XML, pois são mais recentes e corrigem as coisas aqui. Basta baixar e ser feliz. https://drive.google.com/file/d/1QRSvVnl4NxlytdPrdSh0_DDETTWrGTx-/view- talkaction !comprar skill tfs 1.4
Esse script que eu postei é apenas para TFS 1x+, funcionando sem modificações no OTX/OTG misturado, e está tudo funcionando normalmente. O usuário @mane stick me procurou pelo Discord e, depois de pensar sobre isso, aceitei. Fiz as alterações necessárias para torná-lo compatível com OTX/OTG, e agora está funcionando perfeitamente. Ele disse que está tudo ok após os testes. data/scripts -- Definição das habilidades e suas características local skills = { ["magiclevel"] = {vocations = {1, 5, 2, 6, 11, 12}, voc_msg= "Somente Sorcerers, Druids e Infernalists podem comprar magic level.", lim = 200, lim_msg = "Você não pode ter magic level acima de 200.", price= 3, incre = 1, skill = SKILL_MAGLEVEL}, ["skillclub"] = {vocations = {1, 10}, voc_msg= "Somente Drunous podem comprar skill de club.", lim = 350, lim_msg = "Você não pode ter skill club acima de 350.", price= 1, incre = 1, skill = SKILL_CLUB}, ["skillsword"] = {vocations = {4, 8}, voc_msg= "Somente Knights podem comprar skill de sword.", lim = 350, lim_msg = "Você não pode ter skill sword acima de 350.", price= 1, incre = 1, skill = SKILL_SWORD}, ["skillaxe"] = {vocations = {4, 8}, voc_msg= "Somente Knights podem comprar skill de axe.", lim = 350, lim_msg = "Você não pode ter skill axe acima de 350.", price= 1, incre = 1, skill = SKILL_AXE}, ["skilldistance"] = {vocations = {3, 7}, voc_msg= "Somente Paladins podem comprar skill de distance.", lim = 350, lim_msg = "Você não pode ter skill distance acima de 350.", price= 1, incre = 1, skill = SKILL_DISTANCE}, ["skillshielding"] = {vocations = {3, 7, 4, 8, 9, 10}, voc_msg= "Somente Paladins, Knights e Drunous podem comprar skill de shield.", lim = 350, lim_msg = "Você não pode ter skill shielding acima de 350.", price= 1, incre = 1, skill = SKILL_SHIELD}, ["magiclevel5"] = {vocations = {1, 5, 2, 6, 11, 12}, voc_msg= "Somente Sorcerers, Druids e Infernalists podem comprar magic level.", lim = 200, lim_msg = "Você não pode pode ter magic level acima de 200.", price= 15, incre = 5, skill = SKILL_MAGLEVEL}, ["skillclub10"] = {vocations = {9, 10}, voc_msg= "Somente Drunous podem comprar skill de club.", lim = 350, lim_msg = "Você não pode ter skill club acima de 350.", price= 10, incre = 10, skill = SKILL_CLUB}, ["skillsword10"] = {vocations = {4, 8}, voc_msg= "Somente Knights podem comprar skill de sword.", lim = 350, lim_msg = "Você não pode ter skill sword acima de 350.", price= 10, incre = 10, skill = SKILL_SWORD}, ["skillaxe10"] = {vocations = {4, 8}, voc_msg= "Somente Knights podem comprar skill de axe.", lim = 350, lim_msg = "Você não pode ter skill axe acima de 350.", price= 10, incre = 10, skill = SKILL_AXE}, ["skilldistance10"] = {vocations = {3, 7}, voc_msg= "Somente Paladins podem comprar skill de distance.", lim = 350, lim_msg = "Você não pode ter skill distance acima de 350.", price= 10, incre = 10, skill = SKILL_DISTANCE}, ["skillshielding10"] = {vocations = {3, 7, 4, 8, 9, 10}, voc_msg= "Somente Paladins, Knights e Drunous podem comprar skill de shield.", lim = 350, lim_msg = "Você não pode ter skill shielding acima de 350.", price= 10, incre = 10, skill = SKILL_SHIELD}, } -- Função para obter o nome da habilidade com base no ID local function getPlayerSkillName(skillId) local skillNames = { [SKILL_CLUB] = "Club", [SKILL_SWORD] = "Sword", [SKILL_AXE] = "Axe", [SKILL_DISTANCE] = "Distance", [SKILL_SHIELD] = "Shielding", [SKILL_MAGLEVEL] = "Magic Level" } return skillNames[skillId] or "Unknown" end local function buySkill(player, skillData) local coinID = 9971 -- ID da moeda utilizada para compra local storage = 45611 -- Valor de armazenamento para controle de tempo if player:getItemCount(coinID) < skillData.price then player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "Você não possui a quantidade necessária para comprar.") return false end local skillId = skillData.skill local skillName = getPlayerSkillName(skillId) local currentSkill if skillId == SKILL_MAGLEVEL then currentSkill = player:getMagicLevel() else currentSkill = player:getSkillLevel(skillId) end if currentSkill == nil then player:sendCancelMessage("Você não possui essa habilidade.") return false end if skillId == SKILL_MAGLEVEL then local newMagLevel = currentSkill + skillData.incre if newMagLevel > skillData.lim then player:sendCancelMessage(skillData.lim_msg) return false end local target = player target:addManaSpent(target:getVocation():getRequiredManaSpent(target:getBaseMagicLevel() + 1) - target:getManaSpent()) print("Player: " .. player:getName() .. " adquiriu " .. skillData.incre .. " níveis de magic level. Novo magic level: " .. newMagLevel) else local target = player target:addSkillTries(skillId, target:getVocation():getRequiredSkillTries(skillId, target:getSkillLevel(skillId) + 1) - target:getSkillTries(skillId)) print("Player: " .. player:getName() .. " adquiriu " .. skillData.incre .. " níveis em " .. skillName) end if not isInArray(skillData.vocations, player:getVocation():getId()) then player:sendCancelMessage(skillData.voc_msg) return false end player:removeItem(coinID, skillData.price) player:setStorageValue(storage, os.time() + 1) player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "Você comprou " .. skillData.incre .. " níveis em " .. skillName .. " por " .. skillData.price .. " moedas.") return true end local buyComprar = TalkAction("!comprar") function buyComprar.onSay(player, words, param) local param = param:lower() local tile = player:getTile() if not tile or not tile:hasFlag(TILESTATE_PROTECTIONZONE) then player:sendCancelMessage("Você precisa estar em área protegida para utilizar este comando.") return false end local storage = 45611 -- Valor de armazenamento para controle de tempo if player:getStorageValue(storage) >= os.time() then player:sendCancelMessage("Por medidas de segurança você só pode utilizar este comando em " .. (player:getStorageValue(storage) - os.time()) .. " segundos.") return false end if param == "" or not skills[param] then player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "Comando inválido ou habilidade não encontrada. Use !comprar <habilidade> para comprar.") return false end local skillData = skills[param] local playerVocation = player:getVocation():getId() if not isInArray(skillData.vocations, playerVocation) then player:sendCancelMessage("Sua vocação não pode comprar essa habilidade.") return false end return buySkill(player, skillData) end buyComprar:separator(" ") buyComprar:register()- [TFS 1.4.2] Boss Reward Chest System!!
Este sistema é baseado em Reward Chests. Confira o Tibia Wiki para saber mais sobre como funciona. É simples! Em relação à Reward, ela será enviada para o depósito designado. Basta localizar a linha 'depotId' e especificar o numero que você deseja enviar para a cidade correspondente; isso garantirá a entrega direta ao depósito. Por exemplo, atribuir o número 1 para a cidade principal e 2 para Thais, e assim por diante, facilita esse processo. Confira o GIF aqui, basta clicar para ver. https://imgur.com/wNtfnS4 Este script está configurado para ativar um temporizador de 5 minutos após a expiração, removendo automaticamente o Reward Chest Id 21584. Caso deseje estender a duração ou ajustá-la com base nas diretrizes do Tibia Wiki, ele oferece versatilidade. Este sistema é particularmente adequado para salas de chefes onde a derrota do chefe resulta na transformação de seu cadáver no RewardChestId. Os jogadores interagem com ele e, após um período designado, o baú se dissipa. Quando você mata o chefe, ele morre e se transforma em um Baú de Recompensa com ID 21584. Siga o guia de instalação passo a passo fornecido aqui. Registre o evento no arquivo XML do monstro fornecido: <script> <event name="BossDeath"/> </script> Defina o cadáver do chefe como 0, caso contrário você receberá uma mensagem de loot adicional. <look type="201" corpse="0" /> Este é o RevScripts. Coloque o script em qualquer lugar na pasta data/scripts, seja em uma subpasta ou em sua localização preferida. local bossesList = { { name = "Orshabaal", storage = 6655, expirationTime = 5 * 60, loot = { {item = 2160, count = 5, chance = 100000}, {item = 2494, count = 1, chance = 50000}, }, RewardChestId = 21584, depotID = 1 }, { name = "Cave Rat", storage = 6656, expirationTime = 5 * 60, loot = { {item = 2160, count = 10, chance = 100000}, {item = 2498, count = 1, chance = 75000}, }, RewardChestId = 21584, depotID = 1 }, -- Add more bosses as needed } local STORAGE_KEYS = { bossData = "boss_data", } local function createRewardChest(bossPosition, rewardChestId, expirationTime) local rewardItem = Game.createItem(rewardChestId, 1, bossPosition) if rewardItem then rewardItem:setAttribute(ITEM_ATTRIBUTE_ACTIONID, ACTION_ID) addEvent(function() if rewardItem and rewardItem:getPosition() then rewardItem:remove() local players = Game.getPlayers() for _, player in ipairs(players) do player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The reward chest has disappeared!") end end end, expirationTime * 1000) else print("Error creating reward chest.") end end local function hasRewardExpired(player, storageKey) local expirationTime = player:getStorageValue(storageKey) return expirationTime ~= -1 and expirationTime <= os.time() end local creatureEvent = CreatureEvent("BossDeath") function creatureEvent.onDeath(creature, corpse) local bossPosition = creature:getPosition() local rewardChestId = 0 local depotID = 0 local bossName = "" for _, boss in ipairs(bossesList) do if creature:getName():lower() == boss.name:lower() then rewardChestId = boss.RewardChestId depotID = boss.depotID bossName = boss.name break end end if rewardChestId ~= 0 then createRewardChest(bossPosition, rewardChestId, bossesList[1].expirationTime) creature:say("The reward chest will disappear in 5 minutes!", TALKTYPE_MONSTER_SAY) else print("Reward chest ID not found.") end for _, player in ipairs(Game.getPlayers()) do if player:isPlayer() then for _, boss in ipairs(bossesList) do if creature:getName():lower() == boss.name:lower() then player:setStorageValue(boss.storage, 1) local expirationTime = os.time() + boss.expirationTime player:setStorageValue(STORAGE_KEYS.bossData, expirationTime) local message = "You contributed to defeating " .. boss.name .. ". Now go to the chest to claim your reward! Expiration time: " .. os.date("%c", expirationTime) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, message) end end end end end creatureEvent:register() local function sendRewardMessage(player, bossName, receivedItems) local message if #receivedItems > 0 then message = "From " .. bossName .. ": " .. table.concat(receivedItems, ", ") player:sendTextMessage(MESSAGE_EVENT_ADVANCE, message) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your reward has been sent to your depot.") else message = "From " .. bossName .. ": Unfortunately, you did not receive any items." player:sendTextMessage(MESSAGE_EVENT_ADVANCE, message) end end local rewardAction = Action() function rewardAction.onUse(player, item, fromPosition, target, toPosition, isHotkey) if not player or not player:isPlayer() or not item then return false end local depotID = 0 for _, boss in ipairs(bossesList) do if item:getId() == boss.RewardChestId and player:getStorageValue(boss.storage) == 1 then depotID = boss.depotID local storageKey = "boss_reward_time" if hasRewardExpired(player, storageKey) then player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Your reward from " .. boss.name .. " has expired.") else local depot = player:getDepotChest(depotID, true) -- Using depotID from the boss configuration if not depot then return false end local bag = depot:addItem(7343, 1) if not bag then print("Failed to add the reward bag to the player's depot.") return false end local receivedItems = {} for _, lootItem in ipairs(boss.loot) do if math.random(100000) <= lootItem.chance then local itemAdded = bag:addItem(lootItem.item, lootItem.count or 1) if itemAdded then local itemName = ItemType(lootItem.item):getPluralName() or ItemType(lootItem.item):getName() table.insert(receivedItems, (lootItem.count or 1) .. "x " .. itemName) end end end sendRewardMessage(player, boss.name, receivedItems) end player:setStorageValue(boss.storage, 0) player:setStorageValue(storageKey, -1) break end end return true end rewardAction:aid(ACTION_ID) rewardAction:register() Este script é a segunda versão. No Baú de Recompensa (por exemplo, no templo ou na sala do chefe), você deve configurá-lo usando o ID de Ação conforme mostrado na imagem. Confira o GIF aqui, basta clicar para ver. https://imgur.com/B9EezSM O indivíduo que infligiu o maior dano e outro que infligiu uma quantidade menor ambos recebem uma recompensa. Por outro lado, aqueles que não contribuíram com nenhum dano não recebem nenhuma recompensa. Este sistema opera de forma direta. Espero que você tenha achado esta explicação satisfatória. data/scripts. -- Define a table listing the bosses and their respective properties local bossesList = { { name = "Orshabaal", storage = 6655, expirationTime = 7 * 24 * 60 * 60, -- 7 days loot = { {item = 2160, count = 5, chance = 100000}, -- 100% chance {item = 2494, count = 1, chance = 50000}, -- 50% chance }, rewardChestId = 21584, -- Reward chest ID depotId = 1, -- Depot ID of the main city where the items will be sent }, { name = "Cave Rat", storage = 6656, expirationTime = 7 * 24 * 60 * 60, loot = { {item = 2160, count = 10, chance = 100000}, -- 100% chance {item = 2498, count = 1, chance = 75000}, -- 75% chance }, rewardChestId = 21584, -- Reward chest ID depotId = 1, -- Depot ID of the main city where the items will be sent }, -- Add more bosses as needed } local ACTION_ID = 2550 -- You need to open the RME Editor and set it to 2550, then save. local STORAGE_KEYS = { bossData = "boss_data" } -- Function to check if a reward has expired local function hasRewardExpired(player, storageKey) local expirationTime = player:getStorageValue(storageKey) return expirationTime ~= -1 and expirationTime <= os.time() end local creatureEvent = CreatureEvent("BossDeath") function creatureEvent.onDeath(creature, corpse, killer, mostDamageKiller) if killer and killer:isPlayer() then local creatureName = creature:getName():lower() for _, boss in ipairs(bossesList) do if creatureName == boss.name:lower() then -- Set reward data for the killer killer:setStorageValue(boss.storage, 1) local expirationTime = os.time() + boss.expirationTime killer:setStorageValue(STORAGE_KEYS.bossData, expirationTime) local message = "You contributed to defeating " .. boss.name .. ". Now go to the chest to claim your reward! Expiration time: " .. os.date("%c", expirationTime) killer:sendTextMessage(MESSAGE_EVENT_ADVANCE, message) -- Check if there's a most damage killer if mostDamageKiller and mostDamageKiller:isPlayer() and mostDamageKiller:getId() ~= killer:getId() then mostDamageKiller:setStorageValue(boss.storage, 1) mostDamageKiller:setStorageValue(STORAGE_KEYS.bossData, expirationTime) local messageMostDamage = "You dealt the most damage to " .. boss.name .. ". Now go to the chest to claim your reward! Expiration time: " .. os.date("%c", expirationTime) mostDamageKiller:sendTextMessage(MESSAGE_EVENT_ADVANCE, messageMostDamage) end break end end end end creatureEvent:register() -- Function to send reward message to player local function sendRewardMessage(player, bossName, receivedItems) if #receivedItems > 0 then local message = "From " .. bossName .. ": " .. table.concat(receivedItems, ", ") player:sendTextMessage(MESSAGE_EVENT_ADVANCE, message) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your reward has been sent to your depot.") else local message = "From " .. bossName .. ": Unfortunately, you did not receive any items." player:sendTextMessage(MESSAGE_EVENT_ADVANCE, message) end end local rewardAction = Action() function rewardAction.onUse(player, item, fromPosition, target, toPosition, isHotkey) if not player or not player:isPlayer() or not item then return false end local rewardsClaimed = false for _, boss in ipairs(bossesList) do if item:getId() == boss.rewardChestId and player:getStorageValue(boss.storage) == 1 then local storageKey = STORAGE_KEYS.bossData if hasRewardExpired(player, storageKey) then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your reward from " .. boss.name .. " has expired.") else local depot = player:getDepotChest(boss.depotId, true) if not depot then return false end local bag = depot:addItem(7343, 1) if not bag then print("Failed to add the reward bag to the player's depot.") return false end local receivedItems = {} for _, lootItem in ipairs(boss.loot) do if math.random(100000) <= lootItem.chance then local itemAdded = bag:addItem(lootItem.item, lootItem.count or 1) if itemAdded then local itemName = ItemType(lootItem.item):getPluralName() or ItemType(lootItem.item):getName() table.insert(receivedItems, (lootItem.count or 1) .. "x " .. itemName) end end end if #receivedItems > 0 then sendRewardMessage(player, boss.name, receivedItems) player:setStorageValue(boss.storage, 0) player:setStorageValue(storageKey, -1) rewardsClaimed = true else player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You did not receive any items from " .. boss.name .. ".") end end end end if not rewardsClaimed then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need to defeat the corresponding boss first to receive the reward.") return false end return true end rewardAction:aid(ACTION_ID) rewardAction:register() O que eu fiz foi reescrever o script do zero, créditos para mim mesmo. Espero que gostem deste conteúdo!- Storage Temporaria Em Spell
function onCastSpell(cid, var) local waittime = 310 -- Tempo de exaustão local storage = 55512 -- Storage para controlar a spell local stages = { {time = 20, value = 1}, -- 20 segundos, storage = 1 {time = 30, value = 2}, -- 30 segundos adicionais, storage = 2 {time = 40, value = 3} -- 40 segundos adicionais, storage = 3 } if not isCreature(cid) then return false end -- Verificar se o jogador já usou a spell if getCreatureStorageValue(cid, storage) > 0 then doSendCancel(cid, "Você já está sob o efeito da spell.") return false end -- Definir a exaustão e a storage inicial doSetExhaustion(cid, storage, waittime) setCreatureStorageValue(cid, storage, 1) -- Função para alterar a storage e verificar se o jogador está online local function changeStorage(cidGUID, newValue) local creature = getCreatureByGUID(cidGUID) if creature and isCreature(creature) then setCreatureStorageValue(creature, storage, newValue) if newValue == -1 then doSendTextMessage(creature, MESSAGE_STATUS_CONSOLE_BLUE, "O efeito da spell terminou.") else local creaturePos = getCreaturePosition(creature) for i = 1, 5 do doSendMagicEffect(creaturePos, CONST_ME_FIREWORK_RED) end doSendTextMessage(creature, MESSAGE_INFO_DESCR, "Você recebeu os atributos ML, FIST, SWORD, CLUB e AXE!") doAddCondition(creature, createConditionObject(CONDITION_ATTRIBUTES, 60 * 1000, { [CONDITION_PARAM_STAT_MAGICLEVEL] = 3, [CONDITION_PARAM_STAT_MAXHITPOINTS] = 3, [CONDITION_PARAM_STAT_MAXMANAPOINTS] = 3, [CONDITION_PARAM_STAT_SOULPOINTS] = 3, [CONDITION_PARAM_STAT_MAGICPOINTS] = 3 })) end end end -- Obter o GUID do jogador local cidGUID = getPlayerGUID(cid) -- Agendar as mudanças de storage local accumulatedTime = 0 for i, stage in ipairs(stages) do accumulatedTime = accumulatedTime + stage.time addEvent(changeStorage, accumulatedTime * 1000, cidGUID, stage.value) end -- Agendar o reset da storage para o valor -1 após o último estágio accumulatedTime = accumulatedTime + stages[#stages].time addEvent(changeStorage, accumulatedTime * 1000, cidGUID, -1) -- Verificar se o jogador já está transformado if not getCreatureCondition(cid, CONDITION_ATTRIBUTES) then OpenGate(cid, Select_Stages(getCreatureOutfit(cid).lookType), 1) return true else doSendCancel(cid, "Você já está transformado.") return false end end- [Ajuda] Salve familia, estou criando um poketibia e sou iniciante, queria saber pra que serve essa pasta chamanda sources.
Esta source é para edição, modificando coisas, por exemplo, adicionando novos sistemas, funções, mudando para uma nova versão, entre outras coisas. - HEUPE
Informação Importante
Confirmação de Termo