
Histórico de Curtidas
-
L3K0T recebeu reputação de BrownDeveloper 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 deu reputação a Forged em Apresentamos com orgulho: VERTUS SPRITERApresentamos com orgulho: VERTUS SPRITER – O Mestre da Pixel Art no Universo OTServ!
Quem é Vertus Spriter?
É com grande honra que o TibiaKing apresenta oficialmente Vertus Spriter como parceiro e artista recomendado da comunidade!
Se você é desenvolvedor de servidores de Tibia (OTServ), seja 8x, 14x ou versões personalizadas, com certeza já ouviu falar sobre o talento absurdo de Vertus. Ele não é apenas um "spriter", mas sim um verdadeiro artista digital, com anos de experiência transformando pixels em obras-primas que dão vida aos mundos mais imersivos dos servidores OT.
Com um portfólio de respeito e contribuições em grandes projetos nacionais e internacionais, Vertus traz um padrão técnico, estético e profissional digno de jogos comerciais. Ele domina desde a criação de sets de equipamentos completos, outfits originais, Itens, Boxes e efeitos visuais, que encantam jogadores à primeira vista.
Profissionalismo que vai além da arte
Vertus não é apenas técnico — ele é estrategista visual. Ao trabalhar com ele, você conta com:
Análise de estilo visual do seu servidor para criar sprites compatíveis com a identidade do projeto
Criação de conteúdos únicos, com inspiração em lore, temáticas de RPG, mitologia, sci-fi, fantasia sombria e muito mais
Sprites otimizados, com peso leve e encaixe perfeito nas engines utilizadas (OTClient, OTClientV8, OTCv2 etc.)
Entrega ágil e com documentação, facilitando a implementação dos assets na base do seu servidor
Comunicação profissional, com cronograma claro e abertura para revisões quando necessário
Experiência com trabalhos encomendados por empresas e servidores internacionais
Vertus é 100% confiável, pontual, e respeita cada detalhe do que o seu projeto precisa. Se você procura excelência visual, chegou no lugar certo.
SHOWCASE DE OUTFITS – Inovação, Detalhe e Personalidade
Prepare- se para ver outfits únicos, com animações fluídas, detalhes impactantes e silhuetas marcantes. Todos criados exclusivamente por Vertus.
Cada um desses outfits carrega identidade, lore visual e um nível de detalhamento que aumenta drasticamente a percepção de qualidade do servidor.
SHOWCASE DE SETS – Armas, Armaduras, Shields, Wings e Acessórios
Vertus também é especialista em sets: conjuntos completos de armaduras, armas e acessórios que dão aquele toque épico à gameplay visual.
Cada pixel é desenhado com propósito e harmonia, garantindo um visual balanceado e coerente no ambiente do jogo.
ENTRE EM CONTATO COM VERTUS SPRITER
E-mail Profissional: [email protected]
WhatsApp: CLIQUE AQUI E FALE COMIGO!
Pedidos personalizados? Vertus está aberto para novas parcerias!
Quer um pacote de outfits/set exclusivos? Ele cria sob medida para o seu projeto!
CONCLUSÃO
Se você está investindo tempo e recursos no seu servidor de Tibia, não entregue uma experiência visual genérica. Aposte no que realmente faz diferença: personalidade visual, qualidade artística e identidade única.
Vertus Spriter é hoje uma das maiores referências em Pixel Art para OTServ.
E o TibiaKing tem orgulho de apoiar, recomendar e reconhecer o trabalho desse verdadeiro mestre dos pixels.
A revolução visual do seu servidor começa aqui. Com Vertus.
-
L3K0T recebeu reputação de Felipew11 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 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 Underewar em APK - ServerStatusV2 – Monitoramento de portas em tempo realtop!
-
L3K0T recebeu reputação de Underewar 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 [15.00] Crystal Server 4.0 | Mapa Global | Monk ReadyA 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 [15.00] Crystal Server 4.0 | Mapa Global | Monk ReadyCrystal 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