
Histórico de Curtidas
-
L3K0T recebeu reputação de Aksz em Como criar um OTCLIENT próprio para servidor Poketibia!Esta é uma mensagem automática! Este tópico foi movido para a área correta.
Pedimos que você leia as regras do fórum.
-
L3K0T recebeu reputação de arcaydecom em WebSite Poketibia 1.0site pago ou free ? se for free e pelo xammp faça uma conta no-ip e cria uma dns, baixa o programinha do no-ip loga nele como se dosse no site do no-ip, deixa a porta do xammp 80 n muda por q se muda vc vai ter q usar exemplo.no-ip.org:8090 ou 8080 deixa 80 ele vai char seu site do gesior ou modern acc fui Rep+ http://www.noip.com
-
L3K0T recebeu reputação de arawnzz em Sprite Stones, Badges e Gyns para PoketibiaDisponibilizo pra vocês sprites dos gyns e badges deles no total de 16 gyns.
Alguma stones também!
tem pra adicionar no Object Builder e pra Dat editor sua preferencia!
Download
SCAN
-
L3K0T deu reputação a Under em APK - ServerStatusV2 – Monitoramento de portas em tempo realtop!
-
L3K0T recebeu reputação de Under em APK - ServerStatusV2 – Monitoramento de portas em tempo realV2
O ServerStatusV2 é um app Android leve e eficiente para monitorar o status de portas TCP de qualquer servidor remoto, com notificações instantâneas de queda mesmo quando o app está fechado. Veja como ele funciona:
Configuração de IP
Ao abrir o app, basta digitar o endereço IP ou hostname do seu servidor na caixinha de texto.
Toque em “MONITORAR” e o app grava o IP em cache (SharedPreferences), iniciando imediatamente o monitoramento.
Um botão “ALTERAR IP” permite trocar de servidor sem reinstalar o app: ele para o serviço, limpa o IP salvo e volta para o modo de input.
Monitoramento em segundo plano
Internamente, o app inicia um Foreground Service que roda em background, exibindo uma notificação fixa (“Rodando em background…”).
Mesmo se a Activity for fechada ou removida dos apps recentes, o serviço é reiniciado automaticamente, garantindo vigilância 24/7.
Polling inteligente com Kotlin Coroutines
A cada 10 segundos, o serviço tenta abrir conexão (socket) com as portas configuradas (80, 443, 7171, 7172, 587).
Se qualquer porta cair (conexão falha após 1 000 ms), o app dispara uma notificação heads-up com som e vibração, alertando imediatamente.
Interface de Status
A Activity exibe um relatório agrupado por categoria (Site, Servidor e E-mail), mostrando “Online ✔️” ou “Offline ❌” para cada porta.
Logo no primeiro ciclo, o app já exibe o status real sem precisar aguardar.
Personalização e robustez
O host fica salvo entre execuções, portanto você não precisa redigitar o IP sempre que abrir o app.
O código usa ConcurrentHashMap e CoroutineScope, garantindo thread-safety e fácil cancelamento.
Foi pensado para não sobrecarregar o servidor nem gerar bloqueio de IP, mantendo o polling num intervalo seguro de 10 s.
Com o ServerStatusV2 você terá uma visão clara e confiável do uptime do seu OTServ (ou de qualquer outro serviço TCP), notificando quedas em tempo real e mantendo histórico local enquanto quiser.
App: app.apk
Scan: https://www.virustotal.com/gui/file/d0bdba516afc3634101b234e24e624302f7f850c892d6275e2c9f552e0db49db?nocache=1
BY L3K0T
V4
Além dos recursos já descritos, nesta versão v4 o ServerStatusV2 agora monitora também:
OTServ nas portas 7171, 7172 e 7173
Site na porta 80 e 443
E-mail nas portas 25, 587 e 465
Veja o que foi adicionado e aprimorado:
Categorias de portas estendidas
Antes víamos apenas “Site”, “Servidor” e “E-mail” com portas básicas. Agora há uma categoria “OTServ” para as três portas de jogo/login/console (7171, 7172, 7173), e a categoria “E-mail” cobre SMTP clássico (25), Submission com STARTTLS (587) e SMTPS legacy (465).
Máscara de IP automática
Ao digitar ou colar algo como 192168011, o campo transforma em 192.168.0.11 automaticamente, facilitando a entrada sem precisar digitar os pontos.
Persistência com SharedPreferences e “ALTERAR IP”
O IP fica salvo entre execuções. Se precisar trocar de servidor, basta tocar em ALTERAR IP, que interrompe o serviço, limpa o cache e permite nova edição.
Foreground Service resiliente
Serviço roda em background com notificação fixa, resiste a remoção de apps recentes e, em v4, inclui:
Ignorar otimizações de bateria (Battery Saver/Doze Mode).
WakeLock parcial para manter o CPU acordado enquanto monitora, evitando ser suspenso.
Polling inteligente a cada 10 s
Usando Kotlin Coroutines, cada porta é testada via socket com timeout de 1 000 ms. Se qualquer uma delas falhar, uma notificação heads-up com som e vibração alerta instantaneamente.
Interface de Status
Relatório agrupado por categoria, com bolinha (“●”), ícone e texto “Online ✔️” ou “Offline ❌”.
Atualização logo no primeiro ciclo, sem esperar o polling inicial.
Leve e robusto
Usa ConcurrentHashMap para status thread-safe e cancelamento fácil de coroutines.
Mantém intervalo de 10 s para evitar sobrecarga ou bloqueio de IP pelo servidor.
App: app.apk
Scan: https://www.virustotal.com/gui/file/d0bdba516afc3634101b234e24e624302f7f850c892d6275e2c9f552e0db49db?nocache=1
BY L3K0T
-
L3K0T recebeu reputação de Soleister em Shop System.lua Personalizado para OTX no LINUX Ubuntu (MELHORADO)Bom, como todos sabem, existe o shop.lua em servidores 0.4 para receber itens. Muitos deles têm loops infinitos ou fazem uma varredura completa no banco de dados, o que pode deixá-los instáveis. Isso ocorre principalmente quando o script não verifica adequadamente se há itens para processar ou se o banco de dados está sobrecarregado com consultas desnecessárias.
No entanto, com algumas melhorias, podemos otimizar esse processo, garantindo que o servidor se mantenha estável e eficiente. No nosso exemplo, aplicamos algumas mudanças importantes:
Checagem eficiente de itens pendentes: A consulta ao banco de dados foi otimizada para verificar se existem realmente itens pendentes para o jogador. Se não houver itens, o script termina sua execução rapidamente, evitando sobrecarga.
Evitar loops infinitos: O loop foi ajustado para garantir que, se não houver mais itens para processar, o script saia sem continuar verificando o banco de dados, prevenindo loops desnecessários.
Logs: Foi adicionado um sistema de logs, onde cada transação bem sucedida do jogador é registrada com data e hora, além de informações sobre o jogador e os itens recebidos.
Execução controlada com intervalos: Ao invés de fazer consultas contínuas ao banco de dados, o script executa checagens de tempos em tempos, configuráveis pelo parâmetro SQL_interval. Isso distribui as verificações ao longo do tempo e evita que o servidor fique sobrecarregado com solicitações simultâneas.
Segue o scripts:
data/globalevents/scripts/shop.lua
function getCurrentDateTime() local currentDateTime = os.date("%Y-%m-%d %H:%M:%S") return currentDateTime end function createDirectoryIfNotExists(dir) local command = "mkdir -p " .. dir os.execute(command) end function saveLog(message) local logFilePath = "data/logs/shop/shop.txt" local logDir = "data/logs/shop/" createDirectoryIfNotExists(logDir) local currentDateTime = getCurrentDateTime() local logMessage = string.format("[%s] %s\n", currentDateTime, message) local file = io.open(logFilePath, "a") if file then file:write(logMessage) file:close() else print("Erro ao tentar escrever no arquivo de log.") end end SHOP_MSG_TYPE = 19 SQL_interval = 5 function onThink(interval, lastExecution) local result_plr = db.getResult("SELECT * FROM z_ots_comunication WHERE `type` = 'login';") if result_plr:getID() == -1 then return true end local hasMoreItems = false while true do local id = tonumber(result_plr:getDataInt("id")) local cid = getCreatureByName(tostring(result_plr:getDataString("name"))) if isPlayer(cid) then hasMoreItems = true local itemtogive_id = tonumber(result_plr:getDataInt("param1")) local itemtogive_count = tonumber(result_plr:getDataInt("param2")) local add_item_name = tostring(result_plr:getDataString("param6")) local received_item = 0 local full_weight = 0 if isItemRune(itemtogive_id) then full_weight = getItemWeightById(itemtogive_id, 1) else full_weight = getItemWeightById(itemtogive_id, itemtogive_count) end local free_cap = getPlayerFreeCap(cid) if full_weight <= free_cap then local new_item = doCreateItemEx(itemtogive_id, itemtogive_count) received_item = doPlayerAddItemEx(cid, new_item) if received_item == RETURNVALUE_NOERROR then doPlayerSendTextMessage(cid, SHOP_MSG_TYPE, string.format("Você recebeu >> %s << da loja.", add_item_name)) doPlayerSave(cid) db.executeQuery("DELETE FROM `z_ots_comunication` WHERE `id` = " .. id .. ";") db.executeQuery("UPDATE `z_shop_history` SET `trans_state`='realized', `trans_real`=" .. os.time() .. " WHERE id = " .. id .. ";") saveLog(string.format("[%s] %s (ID: %d), Você recebeu >> %s << da loja.", getCurrentDateTime(), tostring(result_plr:getDataString("name")), id, add_item_name)) end else doPlayerSendTextMessage(cid, SHOP_MSG_TYPE, string.format("Você não tem capacidade suficiente para >> %s <<. Necessário: %.2f oz. Disponível: %.2f oz.", add_item_name, full_weight, free_cap)) saveLog(string.format("[%s] %s (ID: %d), Tentou comprar >> %s <<, mas não tinha capacidade suficiente. Necessário: %.2f oz. Disponível: %.2f oz.", getCurrentDateTime(), tostring(result_plr:getDataString("name")), id, add_item_name, full_weight, free_cap)) end end if not result_plr:next() then break end end result_plr:free() if not hasMoreItems then return false end return true end
data/globalevents/globalevents.xml
<globalevent name="shop" interval="30000" script="shop.lua"/>
*Testado em Myaac
*Testado em OTX2 8.60
*Testado em Ubuntu 20.04
*Não precisa criar pasta, ele mesmo cria.
Com essas melhorias, a performance do servidor foi significativamente melhorada, garantindo que o sistema de loja funcione de forma mais estável e eficiente, sem sobrecarregar o banco de dados ou causar lags. Agora, a transação de itens na loja ocorre de forma mais controlada e com menos chance de erros ou travamentos. by @L3K0T
-
L3K0T recebeu reputação de Ayron5 em Shop System.lua Personalizado para OTX no LINUX Ubuntu (MELHORADO)Bom, como todos sabem, existe o shop.lua em servidores 0.4 para receber itens. Muitos deles têm loops infinitos ou fazem uma varredura completa no banco de dados, o que pode deixá-los instáveis. Isso ocorre principalmente quando o script não verifica adequadamente se há itens para processar ou se o banco de dados está sobrecarregado com consultas desnecessárias.
No entanto, com algumas melhorias, podemos otimizar esse processo, garantindo que o servidor se mantenha estável e eficiente. No nosso exemplo, aplicamos algumas mudanças importantes:
Checagem eficiente de itens pendentes: A consulta ao banco de dados foi otimizada para verificar se existem realmente itens pendentes para o jogador. Se não houver itens, o script termina sua execução rapidamente, evitando sobrecarga.
Evitar loops infinitos: O loop foi ajustado para garantir que, se não houver mais itens para processar, o script saia sem continuar verificando o banco de dados, prevenindo loops desnecessários.
Logs: Foi adicionado um sistema de logs, onde cada transação bem sucedida do jogador é registrada com data e hora, além de informações sobre o jogador e os itens recebidos.
Execução controlada com intervalos: Ao invés de fazer consultas contínuas ao banco de dados, o script executa checagens de tempos em tempos, configuráveis pelo parâmetro SQL_interval. Isso distribui as verificações ao longo do tempo e evita que o servidor fique sobrecarregado com solicitações simultâneas.
Segue o scripts:
data/globalevents/scripts/shop.lua
function getCurrentDateTime() local currentDateTime = os.date("%Y-%m-%d %H:%M:%S") return currentDateTime end function createDirectoryIfNotExists(dir) local command = "mkdir -p " .. dir os.execute(command) end function saveLog(message) local logFilePath = "data/logs/shop/shop.txt" local logDir = "data/logs/shop/" createDirectoryIfNotExists(logDir) local currentDateTime = getCurrentDateTime() local logMessage = string.format("[%s] %s\n", currentDateTime, message) local file = io.open(logFilePath, "a") if file then file:write(logMessage) file:close() else print("Erro ao tentar escrever no arquivo de log.") end end SHOP_MSG_TYPE = 19 SQL_interval = 5 function onThink(interval, lastExecution) local result_plr = db.getResult("SELECT * FROM z_ots_comunication WHERE `type` = 'login';") if result_plr:getID() == -1 then return true end local hasMoreItems = false while true do local id = tonumber(result_plr:getDataInt("id")) local cid = getCreatureByName(tostring(result_plr:getDataString("name"))) if isPlayer(cid) then hasMoreItems = true local itemtogive_id = tonumber(result_plr:getDataInt("param1")) local itemtogive_count = tonumber(result_plr:getDataInt("param2")) local add_item_name = tostring(result_plr:getDataString("param6")) local received_item = 0 local full_weight = 0 if isItemRune(itemtogive_id) then full_weight = getItemWeightById(itemtogive_id, 1) else full_weight = getItemWeightById(itemtogive_id, itemtogive_count) end local free_cap = getPlayerFreeCap(cid) if full_weight <= free_cap then local new_item = doCreateItemEx(itemtogive_id, itemtogive_count) received_item = doPlayerAddItemEx(cid, new_item) if received_item == RETURNVALUE_NOERROR then doPlayerSendTextMessage(cid, SHOP_MSG_TYPE, string.format("Você recebeu >> %s << da loja.", add_item_name)) doPlayerSave(cid) db.executeQuery("DELETE FROM `z_ots_comunication` WHERE `id` = " .. id .. ";") db.executeQuery("UPDATE `z_shop_history` SET `trans_state`='realized', `trans_real`=" .. os.time() .. " WHERE id = " .. id .. ";") saveLog(string.format("[%s] %s (ID: %d), Você recebeu >> %s << da loja.", getCurrentDateTime(), tostring(result_plr:getDataString("name")), id, add_item_name)) end else doPlayerSendTextMessage(cid, SHOP_MSG_TYPE, string.format("Você não tem capacidade suficiente para >> %s <<. Necessário: %.2f oz. Disponível: %.2f oz.", add_item_name, full_weight, free_cap)) saveLog(string.format("[%s] %s (ID: %d), Tentou comprar >> %s <<, mas não tinha capacidade suficiente. Necessário: %.2f oz. Disponível: %.2f oz.", getCurrentDateTime(), tostring(result_plr:getDataString("name")), id, add_item_name, full_weight, free_cap)) end end if not result_plr:next() then break end end result_plr:free() if not hasMoreItems then return false end return true end
data/globalevents/globalevents.xml
<globalevent name="shop" interval="30000" script="shop.lua"/>
*Testado em Myaac
*Testado em OTX2 8.60
*Testado em Ubuntu 20.04
*Não precisa criar pasta, ele mesmo cria.
Com essas melhorias, a performance do servidor foi significativamente melhorada, garantindo que o sistema de loja funcione de forma mais estável e eficiente, sem sobrecarregar o banco de dados ou causar lags. Agora, a transação de itens na loja ocorre de forma mais controlada e com menos chance de erros ou travamentos. by @L3K0T
-
L3K0T deu reputação a StrikersBR122 em [TFS 0.3.6 - 8.60] - Servidor ta Dando Esse Erro "not enough memory"Esse erro é na source, ta compilando em 32bits tem que compilar em modo 64bits
-
L3K0T deu reputação a Aksz em (Resolvido)Player nao salva quando deslogaVerifica se tem a tabela player_autoloot
se tiver, ela esta faltando colunas,
Caso tenha essa tabela apaga ela e executa esse script.
CREATE TABLE player_autoloot ( id int NOT NULL AUTO_INCREMENT, player_id int NOT NULL, autoloot_list blob, PRIMARY KEY (id) );
-
L3K0T recebeu reputação de Fluppe Naves em Tibia Ginius Versão 1.1 by L3K0TTibia Ginius Versão 1.1 by L3K0T
O Tibia Genius, desenvolvido por L3K0T, é uma ferramenta essencial para desenvolvedores de OTServ que desejam otimizar e simplificar o processo de desenvolvimento dos seus servidores. Essa ferramenta integra diversas funcionalidades que eliminam a necessidade de utilizar múltiplos programas para tarefas distintas. Entre suas principais funcionalidades, destacam-se:
Item Editor: Permite a edição detalhada dos itens do jogo, facilitando a criação e modificação de itens conforme a necessidade do servidor. RME (Remere's Map Editor): Um editor de mapas completo que oferece uma interface intuitiva para criar e modificar mapas do jogo. Object Builder: Ferramenta para a construção e edição de objetos no jogo, essencial para personalizar a experiência do jogador. Mapa Converter: Utilitário que converte mapas entre diferentes formatos, garantindo compatibilidade e facilitando a integração de mapas em diversos servidores. Servidor Integrado: Opção para iniciar o servidor diretamente no ambiente Windows para testes, eliminando a necessidade de configurar servidores externos para verificações rápidas. Acesso Facilitado às Pastas: Botões dedicados para acessar rapidamente as pastas do servidor, aumentando a eficiência no gerenciamento dos arquivos do servidor.
Antes de utilizar o Tibia Genius, é necessário importar o servidor. Isso é feito através do botão "Selecionar Servidor", onde o usuário deve especificar a pasta do servidor para que todas as funcionalidades possam ser utilizadas de forma integrada. Da mesma forma, para utilizar o RME e o Item Editor, é preciso importar os arquivos SPR e DAT do cliente do jogo.
Com o Tibia Genius, l3k0t proporciona uma solução tudo-em-um para desenvolvedores de OTServ, tornando o processo de desenvolvimento mais ágil e centralizado, ao mesmo tempo que oferece ferramentas poderosas e de fácil acesso para a criação e manutenção de servidores personalizados.
Espero que ajude os preguiçosos risos, qualquer coisa reporte e ajude a melhorar, ideias são todas bem vindas!
Download GitHub: https://github.com/l3k0t/Tibia_Ginius
Scan Virus Total: https://www.virustotal.com/gui/file/f406f1310f8c5f403c35115eaaddc609ccdff2ff56b4a96b619ac7df914829e1?nocache=1
Discord do Projeto: https://discord.gg/MGD55hPWYf
-
L3K0T recebeu reputação de Doidodepeda em Adicionada verificação de pisos 11069, 11060 e atravessamento em PVP em área PZ.Alterei a função canWalkthrough para Impedir o atravessamento de pisos específicos (como 11059 e 11060) se já houver um jogador sobre eles e assim ninguem entra no mesmo depot que é comum em pvp então vamos retirar isso.
Verificar o tipo de mundo (PVP / non-PVP / etc..) e zonas de proteção.
No PVP, jogadores podem atravessar se estiverem fora de uma zona de proteção ou quando ambos não estiverem em combate.
Segue as alterações:
vá em Player.cpp e ache:
bool Player::canWalkthrough(const Creature* creature) const { if(creature == this || hasFlag(PlayerFlag_CanPassThroughAllCreatures) || creature->isWalkable() || std::find(forceWalkthrough.begin(), forceWalkthrough.end(), creature->getID()) != forceWalkthrough.end() || (creature->getMaster() && creature->getMaster() != this && canWalkthrough(creature->getMaster()))) return true; const Player* player = creature->getPlayer(); if(!player) return false; if((((g_game.getWorldType() == WORLDTYPE_OPTIONAL && #ifdef __WAR_SYSTEM__ !player->isEnemy(this, true) && #endif player->getVocation()->isAttackable()) || player->getTile()->hasFlag(TILESTATE_PROTECTIONZONE) || (player->getVocation()->isAttackable() && player->getLevel() < (uint32_t)g_config.getNumber(ConfigManager::PROTECTION_LEVEL))) && player->getTile()->ground && Item::items[player->getTile()->ground->getID()].walkStack) && (!player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges) || player->getAccess() <= getAccess())) return true; return (player->isGhost() && getGhostAccess() < player->getGhostAccess()) || (isGhost() && getGhostAccess() > player->getGhostAccess()); }
altere para
bool Player::canWalkthrough(const Creature* creature) const { if(creature == this || hasCustomFlag(PlayerCustomFlag_CanTurnhop) || creature->isWalkable() || (creature->getMaster() && creature->getMaster() != this && canWalkthrough(creature->getMaster()))) return true; const Player* player = creature->getPlayer(); if(!player) return false; const Tile* tile = player->getTile(); if(tile && tile->ground) { // Verifica se o tile e o chão existem uint16_t groundID = tile->ground->getID(); if(groundID == 11059 || groundID == 11060) { return false; // Bloqueia atravessamento para esses pisos } } if((((g_game.getWorldType() == WORLDTYPE_OPTIONAL && !player->isEnemy(this, true) && #ifdef __WAR_SYSTEM__ !player->isEnemy(this, true) && #endif player->getVocation()->isAttackable()) || player->getTile()->hasFlag(TILESTATE_PROTECTIONZONE) || (player->getVocation()->isAttackable() && player->getLevel() < (uint32_t)g_config.getNumber(ConfigManager::PROTECTION_LEVEL))) && player->getTile()->ground && Item::items[player->getTile()->ground->getID()].walkStack) && (!player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges) || player->getAccess() <= getAccess())) return true; return (player->isGhost() && getGhostAccess() < player->getGhostAccess()) || (isGhost() && getGhostAccess() > player->getGhostAccess()); }
pronto só recompilar e testar.
-
L3K0T recebeu reputação de Rodrigo94 em System Drop Global - L3K0T TFS 0.4Sistema de Drop Personalizado
Esse sistema de loot foi projetado para adicionar um elemento de sorte e surpresa ao derrotar monstros. Sempre que um jogador derrota um monstro, há uma chance configurada para que ele solte entre 1 a 3 itens especiais, garantindo recompensas valiosas ao jogador.
O sistema realiza as seguintes ações:
Chance de Drop: A cada morte de um monstro, há uma chance configurada para dropar itens específicos. O sistema permite que sejam dropados entre 1 a 3 unidades do item, tornando o sistema mais dinâmico.
Efeito Visual: Quando o loot é bem-sucedido, um efeito visual especial (ID 231) é exibido na posição exata onde o monstro foi derrotado, criando uma animação visual que destaca a recompensa.
Notificação ao Jogador: Após o drop, o jogador recebe uma mensagem personalizada informando a quantidade de itens obtidos. Essa notificação aparece após 3 segundos, adicionando uma camada de imersão e evitando sobrecarregar o chat imediatamente após a morte do monstro.
*Ótimo para fazer eventos de dropar certo itens para alguma missão ou resgates.
*Uso no meu TIBIA HARRY POTTER ORIGIN
VAi em creaturescripts/scripts.lua
local function findCorpse(position) for i = 1, 255 do position.stackpos = i local corpse = getThingfromPos(position) if isCorpse(corpse.uid) then return corpse.uid end end return false end local function dropLoot(position, killer) local corpse = findCorpse(position) if not corpse then return false end local itemId = 2160 local chance = 23 if math.random(100) <= chance then local amountToDrop = math.random(1, 3) doAddContainerItem(corpse, itemId, amountToDrop) local corpsePosition = getThingPos(corpse) doSendMagicEffect(corpsePosition, 7) local function sendMessage() if isPlayer(killer) then local message = string.format("Você dropou %d Crystal Coin(s).", amountToDrop) doPlayerSendTextMessage(killer, MESSAGE_INFO_DESCR, message) end end addEvent(sendMessage, 2500) end return true end function onKill(cid, target) local position = getCreaturePosition(target) addEvent(dropLoot, 100, position, cid) return true end
creaturescripts.xml
<event type="kill" name="GlobalDrops" registerTo ="GlobalDrops" event="script" value="globalDrops.lua"/> ou depende do tfs
<event type="kill" name="GlobalDrops" event="script" value="globalDrops.lua"/>
Para ambos TFS registra o evento no login.lua
registerTo ="GlobalDrops"
feito isso.. agora todos os monstros do mapa vai cair os crystal coins de 1 há 3.
-
L3K0T recebeu reputação de Muvukaa em Adicionada verificação de pisos 11069, 11060 e atravessamento em PVP em área PZ.Alterei a função canWalkthrough para Impedir o atravessamento de pisos específicos (como 11059 e 11060) se já houver um jogador sobre eles e assim ninguem entra no mesmo depot que é comum em pvp então vamos retirar isso.
Verificar o tipo de mundo (PVP / non-PVP / etc..) e zonas de proteção.
No PVP, jogadores podem atravessar se estiverem fora de uma zona de proteção ou quando ambos não estiverem em combate.
Segue as alterações:
vá em Player.cpp e ache:
bool Player::canWalkthrough(const Creature* creature) const { if(creature == this || hasFlag(PlayerFlag_CanPassThroughAllCreatures) || creature->isWalkable() || std::find(forceWalkthrough.begin(), forceWalkthrough.end(), creature->getID()) != forceWalkthrough.end() || (creature->getMaster() && creature->getMaster() != this && canWalkthrough(creature->getMaster()))) return true; const Player* player = creature->getPlayer(); if(!player) return false; if((((g_game.getWorldType() == WORLDTYPE_OPTIONAL && #ifdef __WAR_SYSTEM__ !player->isEnemy(this, true) && #endif player->getVocation()->isAttackable()) || player->getTile()->hasFlag(TILESTATE_PROTECTIONZONE) || (player->getVocation()->isAttackable() && player->getLevel() < (uint32_t)g_config.getNumber(ConfigManager::PROTECTION_LEVEL))) && player->getTile()->ground && Item::items[player->getTile()->ground->getID()].walkStack) && (!player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges) || player->getAccess() <= getAccess())) return true; return (player->isGhost() && getGhostAccess() < player->getGhostAccess()) || (isGhost() && getGhostAccess() > player->getGhostAccess()); }
altere para
bool Player::canWalkthrough(const Creature* creature) const { if(creature == this || hasCustomFlag(PlayerCustomFlag_CanTurnhop) || creature->isWalkable() || (creature->getMaster() && creature->getMaster() != this && canWalkthrough(creature->getMaster()))) return true; const Player* player = creature->getPlayer(); if(!player) return false; const Tile* tile = player->getTile(); if(tile && tile->ground) { // Verifica se o tile e o chão existem uint16_t groundID = tile->ground->getID(); if(groundID == 11059 || groundID == 11060) { return false; // Bloqueia atravessamento para esses pisos } } if((((g_game.getWorldType() == WORLDTYPE_OPTIONAL && !player->isEnemy(this, true) && #ifdef __WAR_SYSTEM__ !player->isEnemy(this, true) && #endif player->getVocation()->isAttackable()) || player->getTile()->hasFlag(TILESTATE_PROTECTIONZONE) || (player->getVocation()->isAttackable() && player->getLevel() < (uint32_t)g_config.getNumber(ConfigManager::PROTECTION_LEVEL))) && player->getTile()->ground && Item::items[player->getTile()->ground->getID()].walkStack) && (!player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges) || player->getAccess() <= getAccess())) return true; return (player->isGhost() && getGhostAccess() < player->getGhostAccess()) || (isGhost() && getGhostAccess() > player->getGhostAccess()); }
pronto só recompilar e testar.
-
L3K0T recebeu reputação de Doidodepeda em BANK SYSTEMPara permitir que os jogadores usem o dinheiro em seu banco para comprar itens de NPCs, você precisará modificar o arquivo modules/shop/shop.lua. Vamos supor que você tenha uma tabela player_data que armazena as informações do banco do jogador.
Primeiro, você precisará adicionar uma nova função que verifica se o jogador tem dinheiro suficiente no banco para comprar um item. Adicione este código ao final do arquivo shop.lua:
function getPlayerBankBalance(cid)
local resultId = db.storeQuery("SELECT `balance` FROM `player_data` WHERE `id` = " .. getPlayerGUID(cid))
if resultId == false then
return false
end
local balance = result.getNumber(resultId, "balance")
result.free(resultId)
return balance
end
function getPlayerBankBalanceString(cid)
local balance = getPlayerBankBalance(cid)
if balance == false then
return "Not available"
else
return formatNumber(balance) .. " gold coins"
end
end
function doPlayerWithdrawFromBank(cid, amount)
if amount <= 0 then
return false
end
local balance = getPlayerBankBalance(cid)
if balance == false or balance < amount then
return false
end
db.query("UPDATE `player_data` SET `balance` = `balance` - " .. amount .. " WHERE `id` = " .. getPlayerGUID(cid))
doPlayerAddMoney(cid, amount)
return true
end
Agora, você precisará modificar a função onBuy para permitir que o jogador compre o item usando o dinheiro do banco. Aqui está o código modificado:
function onBuy(cid, item, subType, amount, ignoreCap, inBackpacks)
local cost = getItemPrice(item.itemid) * amount
if(getPlayerMoney(cid) + getPlayerBalance(cid) < cost) then
return doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "You do not have enough money.")
end
if(inBackpacks) then
local container = doPlayerAddItem(cid, 2000, 1)
if(container == 0) then
return doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "You do not have any container to put the item.")
end
doAddContainerItem(container, item.itemid, amount)
item = container
else
doPlayerAddItem(cid, item.itemid, amount)
end
doPlayerRemoveMoney(cid, cost - getPlayerBalance(cid))
doPlayerRemoveBalance(cid, math.min(cost, getPlayerBalance(cid)))
doSendAnimatedText(getThingPos(cid), "$-"..cost, TEXTCOLOR_ORANGE)
doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "You bought ".. amount .." ".. getItemNameById(item.itemid) .." for ".. cost .." gold.")
return true
end
Agora que você identificou onde o dinheiro do jogador está sendo verificado, você pode fazer a seguinte modificação:
Antes:
if getPlayerMoney(cid) < item.price then npcHandler:say('Desculpe, você não tem dinheiro suficiente.', cid) return false end
Depois:
if getPlayerMoney(cid) + getPlayerBalance(cid) < item.price then npcHandler:say('Desculpe, você não tem dinheiro suficiente.', cid) return false end
-
L3K0T recebeu reputação de Doidodepeda em REVS TFS 0.4Estou com algumas "revs não alteradas" e gostaria de compartilhar com vocês pois pode ajudar em alguma coisa.
https://www.mediafire.com/folder/t3y80vqcnow4d/sources_revs_l3k0t
-
L3K0T deu reputação a Tryller em [13.40] Crystal Server 4.0 | Mapa GlobalA versão que esta publicada é client 13.40
A versão 14 esta em uma branch que esta sendo desenvolvida
Quanto ao site pode usar o myacc
-
L3K0T deu reputação a Tryller em [13.40] Crystal Server 4.0 | Mapa GlobalCrystal Server - Changelog Versão 4.0
Olá, pessoal! Temos o prazer de anunciar o lançamento da versão 4.0 do Crystal Server. Confira abaixo as principais novidades, correções de bugs e alterações importantes.
GitHub
visite o GitHub e colabore com o projeto: GitHub - Crystal Server.
Novidades
Sistema de Surprise Bags: Agora é possível configurar o sistema de sacolas-surpresa no arquivo data/items/bags.xml. (Tryller, dguprado). Sistema de Cadeia (Chain System): Agora os jogadores podem usar o sistema de cadeia com o comando !chain. Configurável no config.lua com as novas opções para armas como estrela assassina, flechas, bastões e varinhas. (Tryller). Função playerAlwaysLoginMounted: Agora configurável no config.lua, permitindo que o jogador sempre entre montado no servidor. (Tryller). Atualização dos NPCs: O NPC hireling.lua agora vende pacotes de imbuement e compra todos os itens dentro da Loot Pouch. (Tryller). Novo Sistema de Insígnias (Badges): Introduzido um sistema de insígnias para jogadores. (elsongabriel). Aprimoramentos no Imbuement e Augments: Aumentamos a personalização com o sistema de imbuement e a adição de novos augments. (phacUFPE). Título de Personagens na Cyclopedia: Agora você pode configurar títulos para os personagens na Cyclopedia. (Tryller). Atualização de Monstros e NPCs: Melhorias nas atualizações de monstros e NPCs para se aproximarem da experiência de Tibia RL. (Tryller). Sistema de V.I.P. Grupos: Agora você pode configurar grupos V.I.P no servidor. (phacUFPE). Correções de Bugs
Sistema de Cadeia Corrigido: Agora o sistema de cadeia funciona corretamente para Mages e Paladins. (Tryller). Lista de V.I.P Corrigida: O sistema de lista de V.I.P agora está funcionando perfeitamente. (Tryller). Correção de Reflexão de Dano: O sistema de reflexão de dano estava com falhas e foi corrigido. (Tryller). Correção no Sistema de Imbuement: O sistema de imbuement agora atualiza corretamente quando o jogador adiciona ou cancela imbuiements enquanto a janela está aberta. (Tryller). Otimização de Código: A função onPlayerSellAllLoot foi otimizada para evitar travamentos longos. (Tryller). Correção de Problemas em Talkactions: O script refill.lua foi corrigido para verificar se o jogador tem capacidade de receber itens. (Tryller). Alterações Importantes
Remoção de "useAnyDatapackFolder": A opção foi removida do config.lua e agora é habilitada por padrão. (Tryller). Remoção do Download de Mapas: Não é mais necessário fazer o download do mapa, agora compartilhamos o mapa comprimido em formato .7z. Para extrair o mapa compactado, será necessário baixar e instalar o 7zip. (Tryller). Observação: Para mais detalhes sobre as mudanças e melhorias, confira o histórico de commits ou as notas de lançamento.
Fiquem à vontade para deixar suas sugestões e feedbacks! O servidor está cada vez mais forte com as contribuições de todos. Vamos continuar evoluindo juntos!
Equipe Crystal Server
Links para Download
Download do Crystal Server: Clique aqui para baixar o arquivo RAR. Scan de Vírus: Verifique o arquivo no VirusTotal. -
L3K0T deu reputação a cleitonbandeira em Ajuda Com Site erro HTTP ERROR 500Provavelmente a versão do php que você esta utilizando não é compatível com seu site.
-
L3K0T recebeu reputação de Emooooo em mudar esse script para tfs 0.3.6function onStatsChange(cid, attacker, type, combat, value) if isMonster(cid) and isMonster(attacker) then local master = getCreatureMaster(cid) if not master or not isPlayer(master) then return false end end return true end
<event type="statschange" name="BlockMonsterDamage" script="seu_script.lua"/>
registerCreatureEvent(cid, "BlockMonsterDamage")
-
L3K0T deu reputação a Tryller em Adicionando Surprise Bags no Drop de MonstrosValeu! Andei trabalhando em um servidor 8.60 com algumas coisas e me lembrei que no OT do Zorzin 7.9 tinha algo parecido. Resolvi criar um onde o jogador consiga editar os itens através de um XML
-
L3K0T recebeu reputação de Tryller em Adicionando Surprise Bags no Drop de MonstrosAdorei!!! Fiz um em creaturescripts por on kill, tabalha da mesma forma, mais esse é sensacional tbm obg
-
L3K0T deu reputação a Tryller em Adicionando Surprise Bags no Drop de MonstrosTutorial: Adicionando Surprise Bags no Drop de Monstros
Código foi criado para uma versão 8.60 do Crystal Server. provavelmente funciona em TFS 0.4/0.3
Passo 1: Atualize o configmanager.cpp
No arquivo configmanager.cpp, adicione o seguinte código para permitir que a configuração de SURPRISE_BAGS seja ativada/desativada no config.lua:
m_confBool[SURPRISE_BAGS] = getGlobalBool("dropSurpriseBagsFromMonsters", false);
Passo 2: Atualize o configmanager.h
No arquivo configmanager.h, defina a variável SURPRISE_BAGS na parte dos booleans:
SURPRISE_BAGS,
Passo 3: Modifique o items.cpp
No arquivo items.cpp, na função bool Items::reload(), adicione a chamada para a nova função loadSurpriseBags() para carregar as configurações das Surprise Bags.
Coloque essa linha de código logo acima da função void Items::parseRandomizationBlock(...):
if(!loadSurpriseBags()) return false;
Passo 4: Crie a Função loadSurpriseBags
Ainda em items.cpp, adicione a implementação da função bool Items::loadSurpriseBags() para carregar as informações das bags a partir do XML:
bool Items::loadSurpriseBags() { xmlDocPtr doc = xmlParseFile(getFilePath(FILE_TYPE_OTHER, "items/bags.xml").c_str()); if(!doc) { std::clog << "[Warning - Items::loadBags] Cannot load bags file." << std::endl << getLastXMLError() << std::endl; return false; } xmlNodePtr root = xmlDocGetRootElement(doc); if(xmlStrcmp(root->name,(const xmlChar*)"bags")) { xmlFreeDoc(doc); std::clog << "[Warning - Items::loadBags] Malformed bags file." << std::endl; return false; } std::string strValue; int32_t intValue; for(xmlNodePtr node = root->children; node; node = node->next) { if(xmlStrcmp(node->name, (const xmlChar*)"bag")) continue; uint16_t itemId = 0; std::string itemName; uint32_t chance = 0, minAmount = 1, maxAmount = 1; uint64_t minRange = 0, maxRange = 0; if(readXMLString(node, "name", strValue)) itemName = strValue; if(readXMLInteger(node, "itemid", intValue)) itemId = intValue; if(readXMLInteger(node, "chance", intValue)) chance = intValue; if(readXMLInteger(node, "minAmount", intValue)) minAmount = intValue; if(readXMLInteger(node, "maxAmount", intValue)) maxAmount = intValue; if(readXMLInteger(node, "minRange", intValue)) minRange = intValue; if(readXMLInteger(node, "maxRange", intValue)) maxRange = intValue; setItemBag(itemId, itemName, chance, minAmount, maxAmount, minRange, maxRange); } xmlFreeDoc(doc); return true; }
Passo 5: Atualize o items.h
Em items.h, defina a estrutura BagItemInfo para armazenar as informações dos itens de bag:
struct BagItemInfo { std::string name; uint16_t id; uint32_t chance; uint32_t minAmount; uint32_t maxAmount; uint64_t minRange; uint64_t maxRange; };
Adicione a função loadSurpriseBags() e métodos adicionais para gerenciar as Surprise Bags:
bool loadSurpriseBags(); std::vector<const BagItemInfo*> getAllBagItems() const { std::vector<const BagItemInfo*> allBagItems; for(std::map<int32_t, BagItemInfo>::const_iterator it = bagItems.begin(); it != bagItems.end(); ++it) allBagItems.push_back(&(it->second)); return allBagItems; } void setItemBag(uint16_t itemId, const std::string &itemName, uint32_t chance, uint32_t minAmount, uint32_t maxAmount, uint64_t minRange, uint64_t maxRange) { BagItemInfo itemInfo; itemInfo.name = itemName; itemInfo.id = itemId; itemInfo.chance = chance; itemInfo.minAmount = minAmount; itemInfo.maxAmount = maxAmount; itemInfo.minRange = minRange; itemInfo.maxRange = maxRange; bagItems[itemId] = itemInfo; }
Adicione o mapa bagItems na classe Items abaixo de RandomizationMap randomizationMap;:
std::map<int32_t, BagItemInfo> bagItems;
Passo 6: Modifique o otserv.cpp
Em otserv.cpp, adicione o carregamento das bags no início da execução, logo acima de std::clog << "Loading groups" << std::endl;:
if(g_config.getBool(ConfigManager::SURPRISE_BAGS)) { std::clog << "Loading surprise bags" << std::endl; if(!Item::items.loadSurpriseBags()) { std::clog << "Unable to load surprise bags! Continue? (y/N)" << std::endl; char buffer = OTSYS_getch(); if(buffer != 121 && buffer != 89) startupErrorMessage("Unable to load surprise bags!"); } }
Passo 7: Atualize monsters.cpp
No arquivo monsters.cpp, na função void MonsterType::dropLoot(Container* corpse), adicione o código para verificar e adicionar as Surprise Bags ao loot. Coloque-o logo após o código abaixo
Item* tmpItem = *iit; if(Container* container = tmpItem->getContainer()) { if(createChildLoot(container, *it)) corpse->__internalAddThing(tmpItem); else delete container; } else corpse->__internalAddThing(tmpItem);
Adicione
if(g_config.getBool(ConfigManager::SURPRISE_BAGS)) { const std::vector<const Items::BagItemInfo*> allBagItems = Item::items.getAllBagItems(); std::vector<const Items::BagItemInfo*> validBagItems; for(std::vector<const Items::BagItemInfo*>::const_iterator it = allBagItems.begin(); it != allBagItems.end(); ++it) { const Items::BagItemInfo* bagItem = *it; if(bagItem->chance > 0) validBagItems.push_back(bagItem); } if(!validBagItems.empty()) { for(std::vector<const Items::BagItemInfo*>::const_iterator it = validBagItems.begin(); it != validBagItems.end(); ++it) { const Items::BagItemInfo* bagItem = *it; uint64_t minChance = bagItem->minRange; uint64_t maxChance = bagItem->maxRange; if(random_range(minChance, maxChance) <= bagItem->chance) { uint16_t chosenBagId = bagItem->id; uint32_t minAmount = bagItem->minAmount; uint32_t maxAmount = bagItem->maxAmount; uint16_t dropAmount = static_cast<uint16_t>(random_range(minAmount, maxAmount, DISTRO_UNIFORM)); if(chosenBagId != 0) { Item* newItem = NULL; if(dropAmount > 1) { newItem = Item::CreateItem(chosenBagId, dropAmount); if(newItem) { if(g_game.internalAddItem(NULL, corpse, newItem) != RET_NOERROR) corpse->__internalAddThing(newItem); } } else { newItem = Item::CreateItem(chosenBagId, 1); if(newItem) { if(g_game.internalAddItem(NULL, corpse, newItem) != RET_NOERROR) corpse->__internalAddThing(newItem); } } } } } } } Passo 8: Atualize o config.lua
Por fim, no arquivo config.lua, adicione a configuração que permite ativar ou desativar o drop das Surprise Bags:
-- Surprise Bags -- NOTE: Set dropSurpriseBagsFromMonsters to false to disable surprise bag drops from monsters.. dropSurpriseBagsFromMonsters = false
Para finalizar
va na pasta data/items e crie um arquivo bags.xml e cole isso dentro
<?xml version="1.0" encoding="UTF-8"?> <bags> <!-- If chance and maxRange have the same value, the item will always drop. --> <bag name="Blue Surprise Bag" itemid="6570" chance="100" maxRange="10000"/> <bag name="Red Surprise Bag" itemid="6571" chance="100" maxRange="1000"/> </bags>
Explicação do Funcionamento
O sistema lê as informações de cada itens do arquivo XML bags.xml, que segue a seguinte estrutura acima:
Cada <bag> representa uma bag/item que pode ser dropada de monstros com as seguintes propriedades:
name: Nome descritivo da bag/item (opcional para identificação). itemid: ID do item representando a bag/item no jogo. chance: Chance de dropar a sacola. Valores mais altos aumentam a chance. maxRange: Define o intervalo máximo de chance. Se chance for igual a maxRange, a sacola sempre será derrubada. Quando menor o a distancia da chance para o range, mais fácil o item dropa.
Créditos:
Zorzin pela ideia do código na versão 7.9
Tryller: Criação do código do tópico
-
L3K0T recebeu reputação de Nogard em Ferramenta Windows GiniusWindows Ginius
Criei a ferramenta "Windows Ginius" para ajudar usuários e desenvolvedores de OTServ (Open Tibia Server) a manterem seus sistemas limpos e otimizados. Esta ferramenta possui três funcionalidades principais:
1. Remoção de Arquivos Temporários do Windows
2. Remoção de Arquivos Temporários do OTClient
3. Combinação das Duas Funções Anteriores
Além disso, a ferramenta ajuda a evitar que desenvolvedores de OTServ acumulem pastas e arquivos temporários desnecessários, contribuindo para um ambiente de desenvolvimento mais organizado e eficiente.
Funcionalidades
1. Remoção de Arquivos Temporários do Windows:
Botão "Limpar Cache Windows": Ao clicar neste botão, a ferramenta limpa os arquivos temporários que se acumulam nos diretórios do sistema e do usuário. Esses arquivos, ao longo do tempo, podem ocupar espaço desnecessário e impactar negativamente o desempenho do sistema.
2. Remoção de Arquivos Temporários do OTClient:
Botão "Limpar Cache OTClient": Este botão remove pastas específicas relacionadas ao OTClient localizadas no diretório Roaming do usuário. Esta função é particularmente útil para desenvolvedores e jogadores de OTServ que desejam manter suas configurações limpas e evitar a acumulação de dados temporários. Use esta opção especialmente se o OTClient estiver apresentando problemas ou bugs, pois a limpeza dessas pastas pode resolver muitos problemas comuns.
3. Combinação de Limpeza:
Botão "Limpar Cache OTClient e Windows": Esta opção executa as duas funcionalidades anteriores em conjunto, limpando tanto os arquivos temporários do Windows quanto as pastas específicas do OTClient. Isso garante uma limpeza completa, liberando espaço em disco e melhorando o desempenho geral do sistema.
Benefícios
Liberação de Espaço em Disco:
A ferramenta remove arquivos e pastas temporárias que podem consumir espaço significativo no disco rígido, liberando recursos valiosos para outras atividades.
Melhoria no Desempenho do Sistema:
Ao limpar regularmente os arquivos temporários, a ferramenta previne a lentidão causada pela acumulação de dados inúteis, garantindo que o sistema opere de maneira mais rápida e eficiente.
Ambiente de Desenvolvimento Organizado:
Para desenvolvedores de OTServ, manter as pastas do OTClient limpas é crucial para evitar problemas com configurações antigas ou dados corrompidos. A ferramenta ajuda a manter um ambiente de desenvolvimento limpo e organizado.
Facilidade de Uso:
A interface simples e intuitiva permite que qualquer usuário, independentemente de sua experiência técnica, utilize a ferramenta com facilidade. Com apenas alguns cliques, é possível realizar a limpeza necessária.
Resumo:
A ferramenta "Windows Ginius" foi desenvolvida por mim, L3K0T, com o objetivo de oferecer uma solução prática e eficiente para a manutenção do sistema. Especialmente útil para desenvolvedores e jogadores de OTServ, ela facilita a limpeza de arquivos temporários do Windows e do OTClient, além de oferecer uma opção de limpeza combinada. Utilize "Windows Ginius" regularmente para garantir que seu ambiente de trabalho ou jogo esteja sempre otimizado e livre de resíduos desnecessários. Se o OTClient estiver apresentando bugs ou problemas de desempenho, use a opção de limpeza de arquivos temporários do OTClient para resolver esses problemas rapidamente.
Download: app.publish (4).rar
Virus Total: https://www.virustotal.com/gui/file/e03b7a4fd7482b21117172949c9eed6a066db5502c16b5e64c5caf7436b15bda?nocache=1
-
L3K0T recebeu reputação de S H I O N em OTClient PersonalOTCLIENT PERSONAL
O OTClient Personal é uma fusão exclusiva dos recursos do OTClient MeHah, OTClient V8 e OTClient Edubard. Com uma interface totalmente alterada e personalizada, esta versão proporciona uma experiência de jogo singular e adaptável. Além disso, o OTClient Personal recebe atualizações constantes através do GitHub https://github.com/l3k0t/OTClient_Personal, assegurando que os administradores de servidores OTS estejam sempre atualizados com as últimas melhorias e correções na interface e no código-fonte.
Cores nos nomes, isso é só o começo:
Download: https://github.com/l3k0t/OTClient_Personal
Queremos ouvir você! Sua voz é fundamental para tornar nossa comunidade ainda mais vibrante e dinâmica. Convidamos você a contribuir compartilhando suas ideias, sugestões e feedback. Juntos, podemos criar algo verdadeiramente especial. Não hesite em participar e fazer parte desta jornada conosco!
RELEASES DOWNLOADS:
11/05/2024 - Download OTClient 5.1 https://github.com/l3k0t/OTClient_Personal/releases/tag/otclient_5.1
10/05/2024 - Download OTClient 5.0 https://github.com/l3k0t/OTClient_Personal/releases/tag/otclient_5.0
-
L3K0T recebeu reputação de Ayron5 em System Drop Global - L3K0T TFS 0.4Sistema de Drop Personalizado
Esse sistema de loot foi projetado para adicionar um elemento de sorte e surpresa ao derrotar monstros. Sempre que um jogador derrota um monstro, há uma chance configurada para que ele solte entre 1 a 3 itens especiais, garantindo recompensas valiosas ao jogador.
O sistema realiza as seguintes ações:
Chance de Drop: A cada morte de um monstro, há uma chance configurada para dropar itens específicos. O sistema permite que sejam dropados entre 1 a 3 unidades do item, tornando o sistema mais dinâmico.
Efeito Visual: Quando o loot é bem-sucedido, um efeito visual especial (ID 231) é exibido na posição exata onde o monstro foi derrotado, criando uma animação visual que destaca a recompensa.
Notificação ao Jogador: Após o drop, o jogador recebe uma mensagem personalizada informando a quantidade de itens obtidos. Essa notificação aparece após 3 segundos, adicionando uma camada de imersão e evitando sobrecarregar o chat imediatamente após a morte do monstro.
*Ótimo para fazer eventos de dropar certo itens para alguma missão ou resgates.
*Uso no meu TIBIA HARRY POTTER ORIGIN
VAi em creaturescripts/scripts.lua
local function findCorpse(position) for i = 1, 255 do position.stackpos = i local corpse = getThingfromPos(position) if isCorpse(corpse.uid) then return corpse.uid end end return false end local function dropLoot(position, killer) local corpse = findCorpse(position) if not corpse then return false end local itemId = 2160 local chance = 23 if math.random(100) <= chance then local amountToDrop = math.random(1, 3) doAddContainerItem(corpse, itemId, amountToDrop) local corpsePosition = getThingPos(corpse) doSendMagicEffect(corpsePosition, 7) local function sendMessage() if isPlayer(killer) then local message = string.format("Você dropou %d Crystal Coin(s).", amountToDrop) doPlayerSendTextMessage(killer, MESSAGE_INFO_DESCR, message) end end addEvent(sendMessage, 2500) end return true end function onKill(cid, target) local position = getCreaturePosition(target) addEvent(dropLoot, 100, position, cid) return true end
creaturescripts.xml
<event type="kill" name="GlobalDrops" registerTo ="GlobalDrops" event="script" value="globalDrops.lua"/> ou depende do tfs
<event type="kill" name="GlobalDrops" event="script" value="globalDrops.lua"/>
Para ambos TFS registra o evento no login.lua
registerTo ="GlobalDrops"
feito isso.. agora todos os monstros do mapa vai cair os crystal coins de 1 há 3.