Ir para conteúdo

Ayron5

Membro
  • Registro em

  • Última visita

Histórico de Curtidas

  1. Gostei
    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
     
  2. Gostei
    Ayron5 deu reputação a L3K0T em System Drop Global - L3K0T TFS 0.4   
    Sistema 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.
  3. Gostei
    Instalando o Sistema max_packets_per_seconds no Servidor 0.x
     
    Passo 1: Modificar o Connection.cpp
    Abra o arquivo Connection.cpp. Procure pela função: void Connection::parseHeader(const boost::system::error_code& error) Antes da linha:
    --m_pendingRead; try Adicione o seguinte código:
    uint32_t timePassed = std::max<uint32_t>(1, (time(NULL) - m_timeConnected) + 1); if ((++m_packetsSent / timePassed) > static_cast<uint32_t>(g_config.getNumber(ConfigManager::MAX_PACKETS_PER_SECOND))) { std::cout << convertIPAddress(getIP()) << " disconnected for exceeding packet per second limit." << std::endl; close(); m_connectionLock.unlock(); return; } if (timePassed > 2) { m_timeConnected = time(NULL); m_packetsSent = 0; }  
     
    Passo 2: Modificar o Connection.h
    Abra o arquivo Connection.h. Procure pela classe: class Connection : public boost::enable_shared_from_this<Connection>, boost::noncopyable Abaixo de:
    m_protocol = NULL; Adicione:
    m_packetsSent = 0; m_timeConnected = time(NULL); Abaixo de:
    uint32_t m_refCount; Adicione:
    time_t m_timeConnected; uint32_t m_packetsSent;  
    Passo 3: Modificar o ProtocolGame.cpp
    Abra o arquivo ProtocolGame.cpp. Procure pela função: void ProtocolGame::parsePacket(NetworkMessage &msg) Abaixo de:
    if(!player || !m_acceptPackets || g_game.getGameState() == GAME_STATE_SHUTDOWN || msg.getMessageLength() <= 0) return; Adicione:
    uint32_t now = time(NULL); if(m_packetTime != now) { m_packetTime = now; m_packetCount = 0; } ++m_packetCount; if(m_packetCount > (uint32_t)g_config.getNumber(ConfigManager::MAX_PACKETS_PER_SECOND)) return;  
    Passo 4: Modificar o ProtocolGame.h
    Abra o arquivo ProtocolGame.h. Procure por: ProtocolGame(Connection_ptr connection): Protocol(connection) Substitua:
    m_eventConnect = 0; por:
    m_eventConnect = m_packetCount = m_packetTime = 0; Procure por:
    uint32_t m_eventConnect Substitua por:
    uint32_t m_eventConnect, m_maxSizeCount, m_packetCount, m_packetTime;  
    Passo 5: Modificar o ConfigManager.cpp
    Abra o arquivo ConfigManager.cpp. Procure por: m_loaded = true; Acima disso, adicione:
    m_confNumber[MAX_PACKETS_PER_SECOND] = getGlobalNumber("max_packets_per_second", 500);  
    Passo 6: Modificar o ConfigManager.h
    Abra o arquivo ConfigManager.h. Procure por LAST_NUMBER_CONFIG /* this must be the last one */ Acima disso, adicione:
    MAX_PACKETS_PER_SECOND,  
    Passo 7: Modificar o config.lua
    No arquivo config.lua do seu servidor, adicione: max_packets_per_second = 80 Lembrando que, quanto maior o número, mais pacotes a pessoa pode enviar sem ser desconectada.  
     
    Medidas para ajudar a proteger o servidor contra ataques de "packet flood" ou "SYN flood". Esses ataques envolvem o envio de um grande número de pacotes ao servidor em um curto espaço de tempo, com a intenção de sobrecarregar os recursos do servidor e causar falhas ou degradação no desempenho. Implementando o sistema max_packets_per_seconds, você está limitando o número de pacotes que cada conexão pode enviar por segundo. Isso ajuda a mitigar o impacto de ataques de flood, desconectando automaticamente conexões que excedem o limite configurado de pacotes por segundo. Essas mudanças melhoram a resiliência do seu servidor contra certos tipos de ataques de negação de serviço (DoS), contribuindo para a estabilidade e segurança do seu  OTServer.
     
    Créditos
    @L3K0T por esse tutorial formatado.
    @Yan Liima [TFS 0.4 REV3996] pelo código
  4. Gostei
    Como Evitar Quedas no Servidor ao Exibir Mensagens de Admin
     (Error - void ServiceManager::run()) NETWORK: O endereço solicitado não é válido no contexto
     (Error - void ServicePort::open(IPAddressList, uint16_t)) NETWORK: O endereço solicitado não é válido no contexto
     
    Problema:
    Em determinadas situações, a exibição de mensagens de admin está causando a queda do servidor. Isso ocorre quando uma exceção não tratada é lançada ao tentar abrir portas de serviço.
     
    Solução:
    A solução envolve modificar o código em server.cpp para evitar que o servidor caia quando uma exceção é lançada. Vamos alterar o método ServicePort::open para tratar exceções de forma segura.
     
    Passos:
    Localize o Arquivo server.cpp:
    Abra o arquivo server.cpp no seu projeto. Você pode usar um editor de texto ou uma IDE de sua preferência.
    Encontre o Método ServicePort::open:
    Procure pelo método ServicePort::open no arquivo. O código original se parece com isto:
     
    void ServicePort::open(IPAddressList ips, uint16_t port) { m_pendingStart = false; m_serverPort = port; bool error = false; for(IPAddressList::iterator it = ips.begin(); it != ips.end(); ++it) { try { Acceptor_ptr tmp(new boost::asio::ip::tcp::acceptor(m_io_service, boost::asio::ip::tcp::endpoint(*it, m_serverPort))); accept(tmp); m_acceptors.push_back(tmp); } catch(std::exception& e) { m_pendingStart = true; Scheduler::getInstance().addEvent(createSchedulerTask(5000, boost::bind( &ServicePort::service, boost::weak_ptr<ServicePort>(shared_from_this()), *it, m_serverPort))); } } if(error) m_logError = false; }  
    3. Modifique o Método
     
    ServicePort::open  
    Vamos alterar o código para tratar exceções de maneira adequada, evitando a queda do servidor. A versão modificada do método fica assim:
     
    void ServicePort::open(IPAddressList ips, uint16_t port) { m_pendingStart = false; m_serverPort = port; bool error = false; for(IPAddressList::iterator it = ips.begin(); it != ips.end(); ++it) { try { Acceptor_ptr tmp(new boost::asio::ip::tcp::acceptor(m_io_service, boost::asio::ip::tcp::endpoint(*it, m_serverPort))); accept(tmp); m_acceptors.push_back(tmp); } catch(std::exception& e) { // Tratamento de exceção vazio para evitar a queda do servidor } } }  
    Recompile o Servidor
    Após fazer as modificações, salve o arquivo e recompile o servidor. Com essas mudanças, o servidor não deve mais cair quando uma exceção for lançada ao abrir portas de serviço. Este código foi testado e comprovado eficaz para evitar as quedas. Até mais by L3K0T
  5. Obrigado
    Ayron5 deu reputação a L3K0T em Tibia Ginius Versão 1.1 by L3K0T   
    Tibia 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
  6. Curtir
    Ayron5 deu reputação a L3K0T em Tela Estendida para OTClient V8 (TFS 0.4)   
    Tela Estendida para OTClient V8 (TFS 0.4)
    Olá pessoal, hoje estou trazendo uma tela estendida para o OTClient V8 na versão mais recente. Espero que isso seja útil para vocês! Esta versão vem com atualizações de código que são fáceis de entender. Testado em TFS 0.4.
     
     
     
    Passo 1: Modificações no const.h
    Abra o arquivo const.h e encontre:
     
    #define NETWORK_MAX_SIZE  ou
    #define NETWORKMESSAGE_MAXSIZE  
    Altere para:
     
    #define NETWORK_MAX_SIZE 49180 ou, dependendo da sua source, #define NETWORKMESSAGE_MAXSIZE 49180  
     
    Passo 2: Modificações no Protocollgame.cpp
    Encontre:
    ((x >= myPos.x - 8 + offsetz) && (x <= myPos.x + 9 + offsetz) && //(y >= myPos.y - 6 + offsetz) && (y <= myPos.y + 7 + offsetz));  
    Altere para:
     
    ((x >= myPos.x - Map::maxClientViewportX + offsetz) && (x <= myPos.x + (Map::maxClientViewportX+1) + offsetz) && (y >= myPos.y - Map::maxClientViewportY + offsetz) && (y <= myPos.y + (Map::maxClientViewportY+1) + offsetz));  
     
    Passo 3: Atualizações nas descrições do mapa
    Encontre:
     
    GetMapDescription(pos.x - 8, pos.y - 6, pos.z, 18, 14, msg);  
    Altere para:
     
    GetMapDescription(pos.x - Map::maxClientViewportX, pos.y - Map::maxClientViewportY, pos.z, (Map::maxClientViewportX+1)*2, (Map::maxClientViewportY+1)*2, msg);  
     
    Passo 4: Atualizações na movimentação do personagem
    Encontre:
     
    if(oldPos.y > newPos.y) // north, for old x { msg->put<char>(0x65); GetMapDescription(oldPos.x - 8, newPos.y - 6, newPos.z, 18, 1, msg); } else if(oldPos.y < newPos.y) // south, for old x { msg->put<char>(0x67); GetMapDescription(oldPos.x - 8, newPos.y + 7, newPos.z, 18, 1, msg); } if(oldPos.x < newPos.x) // east, [with new y] { msg->put<char>(0x66); GetMapDescription(newPos.x + 9, newPos.y - 6, newPos.z, 1, 14, msg); } else if(oldPos.x > newPos.x) // west, [with new y] { msg->put<char>(0x68); GetMapDescription(newPos.x - 8, newPos.y - 6, newPos.z, 1, 14, msg); }  
    Altere para:
     
    if (oldPos.y > newPos.y) { // north, for old x msg->put<char>(0x65); GetMapDescription(oldPos.x - Map::maxClientViewportX, newPos.y - Map::maxClientViewportY, newPos.z, (Map::maxClientViewportX+1)*2, 1, msg); } else if (oldPos.y < newPos.y) { // south, for old x msg->put<char>(0x67); GetMapDescription(oldPos.x - Map::maxClientViewportX, newPos.y + (Map::maxClientViewportY+1), newPos.z, (Map::maxClientViewportX+1)*2, 1, msg); } if (oldPos.x < newPos.x) { // east, [with new y] msg->put<char>(0x66); GetMapDescription(newPos.x + (Map::maxClientViewportX+1), newPos.y - Map::maxClientViewportY, newPos.z, 1, (Map::maxClientViewportY+1)*2, msg); } else if (oldPos.x > newPos.x) { // west, [with new y] msg->put<char>(0x68); GetMapDescription(newPos.x - Map::maxClientViewportX, newPos.y - Map::maxClientViewportY, newPos.z, 1, (Map::maxClientViewportY+1)*2, msg); }  
    Passo 5: Atualizações na descrição dos pisos
    Encontre:
     
    GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 5, 18, 14, 3, skip); GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 4, 18, 14, 4, skip); GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 3, 18, 14, 5, skip); GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 2, 18, 14, 6, skip); GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 1, 18, 14, 7, skip); GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 0, 18, 14, 8, skip);  
    Altere para:
     
    GetFloorDescription(msg, oldPos.x - Map::maxClientViewportX, oldPos.y - Map::maxClientViewportY, 5, (Map::maxClientViewportX+1)*2, (Map::maxClientViewportY+1)*2, 3, skip); GetFloorDescription(msg, oldPos.x - Map::maxClientViewportX, oldPos.y - Map::maxClientViewportY, 4, (Map::maxClientViewportX+1)*2, (Map::maxClientViewportY+1)*2, 4, skip); GetFloorDescription(msg, oldPos.x - Map::maxClientViewportX, oldPos.y - Map::maxClientViewportY, 3, (Map::maxClientViewportX+1)*2, (Map::maxClientViewportY+1)*2, 5, skip); GetFloorDescription(msg, oldPos.x - Map::maxClientViewportX, oldPos.y - Map::maxClientViewportY, 2, (Map::maxClientViewportX+1)*2, (Map::maxClientViewportY+1)*2, 6, skip); GetFloorDescription(msg, oldPos.x - Map::maxClientViewportX, oldPos.y - Map::maxClientViewportY, 1, (Map::maxClientViewportX+1)*2, (Map::maxClientViewportY+1)*2, 7, skip); GetFloorDescription(msg, oldPos.x - Map::maxClientViewportX, oldPos.y - Map::maxClientViewportY, 0, (Map::maxClientViewportX+1)*2, (Map::maxClientViewportY+1)*2, 8, skip);  
     
    Passo 6: Outras modificações
    Encontre:
     
    GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, oldPos.z - 3, 18, 14, 3, skip);  
    Altere para:
     
    GetFloorDescription(msg, oldPos.x - Map::maxClientViewportX, oldPos.y - Map::maxClientViewportY, oldPos.z - 3, (Map::maxClientViewportX+1)*2, (Map::maxClientViewportY+1)*2, 3, skip);  
     
    Passo 7: Modificações adicionais
    Encontre:
     
    GetMapDescription(oldPos.x - 8, oldPos.y + 1 - 6, newPos.z, 1, 14, msg);  
    Altere para:
     
    GetMapDescription(oldPos.x - Map::maxClientViewportX, oldPos.y - (Map::maxClientViewportY-1), newPos.z, 1, (Map::maxClientViewportY+1)*2, msg);  
     
    Passo 8: Atualizações finais
    Encontre:
     
    GetMapDescription(oldPos.x - 8, oldPos.y - 6, newPos.z, 18, 1, msg);  
    ALTERE PARA
    GetMapDescription(oldPos.x - Map::maxClientViewportX, oldPos.y - Map::maxClientViewportY, newPos.z, (Map::maxClientViewportX+1)*2, 1, msg);  
     
    Passo 9: Mais modificações nas descrições de pisos
    Encontre:
     
    GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, newPos.z, 18, 14, -1, skip); GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, newPos.z + 1, 18, 14, -2, skip); GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, newPos.z + 2, 18, 14, -3, skip);  
    Altere para:
     
    GetFloorDescription(msg, oldPos.x - Map::maxClientViewportX, oldPos.y - Map::maxClientViewportY, newPos.z, (Map::maxClientViewportX+1)*2, (Map::maxClientViewportY+1)*2, -1, skip); GetFloorDescription(msg, oldPos.x - Map::maxClientViewportX, oldPos.y - Map::maxClientViewportY, newPos.z + 1, (Map::maxClientViewportX+1)*2, (Map::maxClientViewportY+1)*2, -2, skip); GetFloorDescription(msg, oldPos.x - Map::maxClientViewportX, oldPos.y - Map::maxClientViewportY, newPos.z + 2, (Map::maxClientViewportX+1)*2, (Map::maxClientViewportY+1)*2, -3, skip);  
     
    Passo 10: Últimas modificações
    Encontre:
    GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, newPos.z + 2, 18, 14, -3, skip);  
    Altere para:
     
    GetFloorDescription(msg, oldPos.x - Map::maxClientViewportX, oldPos.y - Map::maxClientViewportY, newPos.z + 2, (Map::maxClientViewportX+1)*2, (Map::maxClientViewportY+1)*2, -3, skip);  
     
    Passo 11: Ajustes finais
    Encontre:
     
    GetMapDescription(oldPos.x + 9, oldPos.y - 1 - 6, newPos.z, 1, 14, msg);  
    Altere para:
     
    GetMapDescription(oldPos.x + Map::maxClientViewportX+1, oldPos.y - (Map::maxClientViewportY+1), newPos.z, 1, ((Map::maxClientViewportY+1)*2), msg);  
    Passo 12: Atualizações em MAP.H
    Abra o arquivo MAP.H do servidor e encontre:
     
    static const int32_t maxViewportX = 11; //min value: maxClientViewportX + 1 static const int32_t maxViewportY = 11; //min value: maxClientViewportY + 1 static const int32_t maxClientViewportX = 8; static const int32_t maxClientViewportY = 6;  
    Altere para:
     
    static const int32_t maxViewportX = 15; //min value: maxClientViewportX + 1 static const int32_t maxViewportY = 15; //min value: maxClientViewportY + 1 static const int32_t maxClientViewportX = 14; static const int32_t maxClientViewportY = 12;  
    Pronto, agora é só compilar as sources do seu servidor no modo Rebuild para apagar o cache.
     
     
     
    Parte 2: OTClient 0.6.6
    Abra o arquivo map.cpp das sources do OTClient V8 e encontre:
     
    void Map::resetAwareRange() { AwareRange range; range.left = 8; range.top = 6; range.bottom = 7; range.right = 9; setAwareRange(range); }  
    Altere para:
     
    void Map::resetAwareRange() { AwareRange range; range.left = 14; //Change this to = maxClientViewportX range.top = 12; //Change this to = maxClientViewportY range.bottom = range.top+1; range.right = range.left+1; setAwareRange(range); }  
    Compile a source do OTClient também no modo Rebuild e pronto!
     
  7. Gostei
    Ayron5 deu reputação a L3K0T em Ferramenta Windows Ginius   
    Windows 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
  8. Obrigado
    Ayron5 recebeu reputação de Nother em [Npc] Que vende Stones (itens) por diamonds   
    Antes de tudo quero deixar claro que pesquisei no fórum, Não encontrei. Resolvi fazer o meu  
    Este NPC faz oq o titulo diz  vende Stone ou Item por Diamond. Npc simples e configurável  Testado em Poketibia 8.54  tfs 0.3.6 
     
    Em data/npc, coloque um novo arquivo com o nome Ditem.xml e cole isso dentro:
     
    Na pasta data/npc/script, crie um arquivo chamado "Ditem.lua" e cole isso:
     
    Para adicionar mais itens:
     
    1º -  adiciona o nome do item para o player falar o nome dele, caso queira comprar - 
    selfSay('Eu vendo Fire stone, Water stone, Leaf stone. Diga qual voce quer adquirir.', cid) 2º - Após o ultimo 
    talkState[talkUser] = 3 Vc adiciona isso - 
    elseif(msgcontains(msg, '----NOME DO ITEM----') or msgcontains(msg, '---nome do item---')) then selfSay('O item Custa 3 Diamonds, Voce vai querer?', cid) talkState[talkUser] = 4 ----- Aqui coloca 4 pq ja tem a 3 3º - Na parte de  -- Confirmação da Compra -- Depois de  um      
    talkState[talkUser] = 0 end Adicione --  elseif(msgcontains(msg, 'yes') and talkState[talkUser] == 4) then ---Coloque 4 por causa da ---talkState[talkUser] = 4--- if(doPlayerRemoveItem(cid, 2145, 3) == true) then ----Item q sera removido no caso 2145 Diamonds e 3 é a quantidade. selfSay('Thanks!', cid) doPlayerAddItem(cid, 11447, 1) ----- 11447 é o item q será entregue no caso é a fire stone, o 1 é a quantidade de itens. talkState[talkUser] = 0 else selfSay('Voce nao tem diamonds suficiente.', cid) talkState[talkUser] = 0 end Bom é isso espero ajudar alguém rsrsrs  
  9. Obrigado
    Ayron5 recebeu reputação de DarkRed em Baú Que dá Outfit se tiver Level   
    Bom galera antes de tudo, pesquisei e não encontrei desse que dá a roupa se tiver o tal level pedido na script.
    Tou deixando bem explicado para melhor compreensão de todos. O script é simples e já foi testado, estando o mesmo 100% na minha base 8.54
    Vamos lá!
    Vá em data/actions/scripts e crie um arquivo Lua chamado > Outfitquest
    Feito isso dentro adicione esse código v
    Em actions.xml você adiciona v
    Explicação: 
    if item.uid == 12154 then 12154 é a unique id que você vai colocar no baú. Lembrando que vc pode mudar os valores. Obs: Mudando esse valor vc terá que deixar igual na da tag da actions.xml
    if getPlayerLevel(cid) >= 30 then 30 é o level que o player precisa ter para concluir a quest. Mude ao seu gosto! 
    questOut = getPlayerStorageValue(cid, 31503) 31503 é a storage da quest, recomendo não mudar/caso mude, deixe todos eles iguais pois eles se repetem no script.
    setPlayerStorageValue(cid, 181655, 1) 181655 é a storage da quest da roupa que vc vai querer que ele ganhe, mas vc me pergunta Ayron/Sepultura onde eu acho essa storage de roupa? 
    Simples, vá em data/XML e abra o outfits.xml Lá vc encontrará algo assim v
    <outfit id = "59" quest = "181655"> <list gender = "0" lookType = "1498" name = "Christmas" /> <!-- 0 mulher, 1 homem --> <list gender = "1" lookType = "1497" name = "Christmas" /> </ outfit> Note que o valor 181655 é o valor da quest que lista as roupas que deseja dar no baú 
    Atenção aqui ( o script dá a roupa automático de acordo com o sexo do player) ^ ^ 
     
    Bom se vc já fez tudo deixou as coisas OK falta a ultima parte. Abra o seu (rme map editor) e lá escolha o baú, feito isso aperte com o botão direito do mouse sobre ele
    e vá em propriedades, abrirá uma janelinha, na parte da Unique ID coloque o valor da unique da script que é o mesmo da tag na actions.xml = 12154 ficando assim v
    Pronto! salve o mapa e vá testar. ^ ^ 
    Espero ajudar alguém, e se ajudei deixa o Rep! aí para fortalecer a amizade  
    É isso, abraços!   
     
  10. Gostei
    Ayron5 recebeu reputação de Cat em [Lenhar System] Sistema De Lenhar / Adaptável Mina/Frutos   
    Bem legalzinho hehehe Irei usar ^ ^ 
  11. Curtir
    Ayron5 recebeu reputação de Thensus Warrior em [Npc] Que vende Stones (itens) por diamonds   
    Antes de tudo quero deixar claro que pesquisei no fórum, Não encontrei. Resolvi fazer o meu  
    Este NPC faz oq o titulo diz  vende Stone ou Item por Diamond. Npc simples e configurável  Testado em Poketibia 8.54  tfs 0.3.6 
     
    Em data/npc, coloque um novo arquivo com o nome Ditem.xml e cole isso dentro:
     
    Na pasta data/npc/script, crie um arquivo chamado "Ditem.lua" e cole isso:
     
    Para adicionar mais itens:
     
    1º -  adiciona o nome do item para o player falar o nome dele, caso queira comprar - 
    selfSay('Eu vendo Fire stone, Water stone, Leaf stone. Diga qual voce quer adquirir.', cid) 2º - Após o ultimo 
    talkState[talkUser] = 3 Vc adiciona isso - 
    elseif(msgcontains(msg, '----NOME DO ITEM----') or msgcontains(msg, '---nome do item---')) then selfSay('O item Custa 3 Diamonds, Voce vai querer?', cid) talkState[talkUser] = 4 ----- Aqui coloca 4 pq ja tem a 3 3º - Na parte de  -- Confirmação da Compra -- Depois de  um      
    talkState[talkUser] = 0 end Adicione --  elseif(msgcontains(msg, 'yes') and talkState[talkUser] == 4) then ---Coloque 4 por causa da ---talkState[talkUser] = 4--- if(doPlayerRemoveItem(cid, 2145, 3) == true) then ----Item q sera removido no caso 2145 Diamonds e 3 é a quantidade. selfSay('Thanks!', cid) doPlayerAddItem(cid, 11447, 1) ----- 11447 é o item q será entregue no caso é a fire stone, o 1 é a quantidade de itens. talkState[talkUser] = 0 else selfSay('Voce nao tem diamonds suficiente.', cid) talkState[talkUser] = 0 end Bom é isso espero ajudar alguém rsrsrs  
  12. Curtir
    Ayron5 recebeu reputação de DarkRed em [AJUDA] Efeito drop stone   
    @rask craft @Loouis Tenho esse aqui ele funciona certinho sem erros no meu servidor. 
     
    Apaga tudo dentro da Drop e cola esse:
     
    Obs: Coloque o effect de acordo com seu servidor. 
    Espero ter ajudado  
  13. Curtir
    Ayron5 deu reputação a WooX em Algumas funções Lua   
    Biblioteca de funções Lua
     
    Eu me recordo que alguns anos atrás quando iniciei meus estudos em Lua, a biblioteca de funções postada pelo @xWhiteWolf me ajudou muito com a escrita de alguns scripts, me fez economizar tempo e algumas linhas de código. Ter uma biblioteca de funções uteis é uma mão na roda para qualquer desenvolvedor pois poupa tempo que teria de ser gasto desenvolvendo algo que algum outro programador provavelmente já fez.
     
    Pensando nisso, hoje eu decidi trazer algumas funções Lua, tenho certeza que poderá ser útil pra alguém algum dia. Algumas dessas funções foram feitas por mim, outras por amigos meus e algumas eu já nem lembro mais onde encontrei. Irei postar aqui o conteúdo desta biblioteca porem ela também estará no final do tópico como anexo. As funções que me recordo a origem estará com os créditos do autor.
     
    Lib
     
    Explicação das funções:
     
    Por enquanto é isso... pretendo atualizar este tópico sempre que achar necessidade de escrever algo novo ou encontrar algo que possa ser útil a biblioteca.
     
    090-woox_functions.lua
  14. Curtir
    Ayron5 deu reputação a L3K0T em Fazer Player passar por dentro do outro (PVP)   
    Bom esse sistema tem a função de fazer o player passar por cima do outro sem uso de FLAG com PK ou mundo tipo PVP. É um sistema que pode ser usado tanto pra TIBIA ou DERIVADOS tfs 0.3.6... achei muito interessante esse system então trouxe para cá  espero que curtem muito.
     
    procure em player.cpp isso:
     
     
    troque para isso:
     
     
    pronto agora é só salvar ctrl+s, compilar e ó não esqueça de apagar tudo da pasta obj para que tudo ocorra como no tutorial.
     

     
    Créditos: BlackTibia.
     
  15. Curtir
    Ayron5 deu reputação a Yan Liima em Aumentando limite doShowTextDialog   
    Salve meus queridos, tudo bom? Hoje decidi trazer uma pequena alteração na source. Vi que muita galera tem problemas com o limite do caracter da função doShowTextDialog, pois se excender o limite maximo de caractere da debug no client.
    Isso ocorre principalmente pra galera do derivado que costuma utilizar !spells/!tecnicas/!jutsu para checar os ataques disponiveis que existe pra tal personagem. 
    Se você é GOD, você consegue visualizar todas as spells do servidor , e se no servidor existir muitas, irá causar debug.
    Diferente do doPlayerPopupFYI, não há uma proteção de limite para TextDialog...
     
    Primeiramente, como que eu descobri?
    Seguinte, eu coloquei o máximo de spells possiveis, ou seja, o máximo de caracteres possiveis na caixinha de texto.
    Quando eu vi que começou dar debug no cliente, eu retirei alguns caracteres e fui testando.

    Até que consigui achar o valor máximo!
    Eu copiei tudo que estava na janela, e em um site online colei todo o conteúdo de lá para saber quantos caracteres existiam ali.
    E esse foi o resultado:

     
    8192, descobrimos o máximo de caracteres no doShowTextDialog.
    Após descobrir este valor, eu procurei nas sources e achei!
     
    ENTÃO VAMOOOS LÁ!
    TFS
     
    OTX
     
    Prontinho! Simples, não? haha
  16. Curtir
    Ayron5 deu reputação a L3K0T em Função DoSetCreatureLight C++ TFS 0.4   
    L3K0Ttfs 0.4
     
    Bom galera hoje vim trazer para aqueles que não tem em seu tfs a função DoSetCreatureLight, é uma função de LUZ, alguns tfs tem e outros não tem então resolvi compartilhar.
     
    abra seu luascript.cpp e procure por:
     
    lua_register(m_luaState, "getCreatureHealth", LuaInterface::luaGetCreatureHealth); em baixo add
    //doSetCreatureLight(cid, lightLevel, lightColor, time) lua_register(m_luaState, "doSetCreatureLight", LuaInterface::luaDoSetCreatureLight); Procure;;
    int32_t LuaInterface::luaGetThingFromPos(lua_State* L) { //getThingFromPos(pos[, displayError = true]) //Note: // stackpos = 255- top thing (movable item or creature) // stackpos = 254- magic field // stackpos = 253- top creature bool displayError = true; if(lua_gettop(L) > 1) displayError = popNumber(L); PositionEx pos; popPosition(L, pos); ScriptEnviroment* env = getEnv(); Thing* thing = NULL; if(Tile* tile = g_game.getMap()->getTile(pos)) { if(pos.stackpos == 255) { if(!(thing = tile->getTopCreature())) { Item* item = tile->getTopDownItem(); if(item && item->isMovable()) thing = item; } } else if(pos.stackpos == 254) thing = tile->getFieldItem(); else if(pos.stackpos == 253) thing = tile->getTopCreature(); else thing = tile->__getThing(pos.stackpos); if(thing) pushThing(L, thing, env->addThing(thing)); else pushThing(L, NULL, 0); return 1; } if(displayError) errorEx(getError(LUA_ERROR_TILE_NOT_FOUND)); pushThing(L, NULL, 0); return 1; } em baixo add;;
     
    int32_t LuaInterface::luaDoSetCreatureLight(lua_State* L) { //doSetCreatureLight(cid, lightLevel, lightColor, time) uint32_t time = popNumber(L); uint8_t color = (uint8_t)popNumber(L); uint8_t level = (uint8_t)popNumber(L); uint32_t cid = popNumber(L); ScriptEnviroment* env = getEnv(); Creature* creature = env->getCreatureByUID(cid); if(creature) { Condition* condition = Condition::createCondition(CONDITIONID_COMBAT, CONDITION_LIGHT, time, level | (color << 8)); creature->addCondition(condition); lua_pushboolean(L, true); } else { errorEx(getError(LUA_ERROR_PLAYER_NOT_FOUND)); lua_pushboolean(L, false); } return 1; }  
    Agora em Luascript.h procure por:;;
    static int32_t luaCanPlayerWearOutfit(lua_State* L); em baixo add;;
    static int32_t luaDoSetCreatureLight(lua_State *L);  
    salva tudo em compila no modo rebuild.
     
     
    Usando em Summons;;
    doSetCreatureLight(getCreatureSummons(cid)[1], 10, 215, 60*1000) Usando em players;;
    doSetCreatureLight(cid, 9, 65, 10*60*1000) usando em Equipe;;
    function onEquip(cid, item, slot) doSetCreatureLight(cid, 9, 65, 10*60*1000) end function onDeEquip(cid, item, slot) doSetCreatureLight(cid, 7, 215, 1*1000) end Espero que gostem  
  17. Curtir
    Ayron5 deu reputação a L3K0T em First to Speak Summon System - talkactions   
    L3K0TTFS 04 e TFS 0.3.6
    Olá galera, hoje vim trazer um sistema chamado "First to Speak Summon" mais pera ai L3K0T, como funciona? Bom ele sumonar um monstro numa posição setada por sua preferencia, também verifica uma posxyz que você pode setar também e assim falar o comando "!fss"... mais pera ai L3K0T oque tem de diferente??? ... calma ... esse comando só pode ser pronunciado por 1 player somente, no caso se alguém falar o comando depois de você... não irá sumonar até que o tempo pra falar novamente acabe "configurado" e BORA PRO TUTORIAL???
     
     
    TUTORIAL;;
     
    1° vai na pasta Servidor\data\talkactions\scripts copia um arquivo.lua e renomeia para fss e dentro coloque;;
     
    local t = { sto = 565674, --Storage global; temp = 300, --Tempo para falar em milesimo 300 = 5 minutos // segundos o comando; monstro = "Demon", --Nome monstrinho que vá nascer; localmapa = {x=1569, y=214, z=7}, --Posição aonde o monstrinho vai nascer; pisomapa = {x=1565, y=215, z=7}, --Posição aonde o player precisa estar para falar o comando de sua preferencia; msgsucesso = "monstro foi criado!!!", --Mensagem que manda ao player ao criar o monstrinho; msgsono = "Demon Está dormindo zzzZZZ", --Mensagem ao tentar usar o comando com intervalo de espera do comando; msgnull = "Está acordado corra lá", --Mensagem quando o monstro acordar } function onSay(cid, words, param, channel) local tp = getThingPos(cid) --verficação --inicio if tp.x == t.pisomapa.x and tp.y == t.pisomapa.y and tp.z == t.pisomapa.z then --verificação if getPlayerStorageValue(cid, t.sto) > os.time() then --verificação tempo doPlayerSendTextMessage(cid, 27, t.msgsono) return true end for _, cid in ipairs(getPlayersOnline()) do --verificação players global setPlayerStorageValue(cid, t.sto, os.time() + t.temp) --seta storage end doCreateMonster(t.monstro, t.localmapa) doPlayerSendTextMessage(cid, 27, t.msgsucesso) else --fora do tile if getPlayerStorageValue(cid, t.sto) > os.time() then --verificação tempo doPlayerSendTextMessage(cid, 27, t.msgsono) return true end if getPlayerStorageValue(cid, t.sto) < os.time() then --verificação tempo doPlayerSendTextMessage(cid, 27, t.msgnull) return true end end --fim script BY L3K0T return true end tag xml;;
     
    <talkaction words="!fss" event="script" value="fss.lua"/> feito isso salva tudinho e use da melhor forma que achar.
     
    Video;;
     
     
    Créditos: @L3K0T
     
     
  18. Curtir
    Ayron5 recebeu reputação de L3K0T em Baú Que dá Outfit se tiver Level   
    Bom galera antes de tudo, pesquisei e não encontrei desse que dá a roupa se tiver o tal level pedido na script.
    Tou deixando bem explicado para melhor compreensão de todos. O script é simples e já foi testado, estando o mesmo 100% na minha base 8.54
    Vamos lá!
    Vá em data/actions/scripts e crie um arquivo Lua chamado > Outfitquest
    Feito isso dentro adicione esse código v
    Em actions.xml você adiciona v
    Explicação: 
    if item.uid == 12154 then 12154 é a unique id que você vai colocar no baú. Lembrando que vc pode mudar os valores. Obs: Mudando esse valor vc terá que deixar igual na da tag da actions.xml
    if getPlayerLevel(cid) >= 30 then 30 é o level que o player precisa ter para concluir a quest. Mude ao seu gosto! 
    questOut = getPlayerStorageValue(cid, 31503) 31503 é a storage da quest, recomendo não mudar/caso mude, deixe todos eles iguais pois eles se repetem no script.
    setPlayerStorageValue(cid, 181655, 1) 181655 é a storage da quest da roupa que vc vai querer que ele ganhe, mas vc me pergunta Ayron/Sepultura onde eu acho essa storage de roupa? 
    Simples, vá em data/XML e abra o outfits.xml Lá vc encontrará algo assim v
    <outfit id = "59" quest = "181655"> <list gender = "0" lookType = "1498" name = "Christmas" /> <!-- 0 mulher, 1 homem --> <list gender = "1" lookType = "1497" name = "Christmas" /> </ outfit> Note que o valor 181655 é o valor da quest que lista as roupas que deseja dar no baú 
    Atenção aqui ( o script dá a roupa automático de acordo com o sexo do player) ^ ^ 
     
    Bom se vc já fez tudo deixou as coisas OK falta a ultima parte. Abra o seu (rme map editor) e lá escolha o baú, feito isso aperte com o botão direito do mouse sobre ele
    e vá em propriedades, abrirá uma janelinha, na parte da Unique ID coloque o valor da unique da script que é o mesmo da tag na actions.xml = 12154 ficando assim v
    Pronto! salve o mapa e vá testar. ^ ^ 
    Espero ajudar alguém, e se ajudei deixa o Rep! aí para fortalecer a amizade  
    É isso, abraços!   
     
  19. Obrigado
    Muito bom! Tá inspirado em mano kkk 
  20. Curtir
    TUTORIAL BY L3K0T PT~EN
     
    Olá pessoal, trago a vocês uma atualização que fiz no sistema, contendo 3 novas funcionalidades de movimentação de itens e uma proteção contra Elf Bot. Estas adições foram cuidadosamente implementadas para aperfeiçoar a experiência de jogo e manter a integridade do seu servidor.
    As novas funcionalidades têm a função vital de impedir que jogadores deixem itens indesejados em locais inapropriados, como na entrada de sua casa, em cima de seus depósitos ou em teleportes. Agora, apenas proprietários, subproprietários e convidados têm permissão para manipular itens nesses locais.
    Este pacote de atualização foi meticulosamente revisado para evitar abusos por parte de jogadores mal-intencionados e garantir um ambiente de jogo justo e equilibrado para todos os usuários.
     
     
     
    Iniciando o Tutorial
    1Abra o arquivo "creatureevents.cpp" com o editor de sua preferência. Eu pessoalmente recomendo o Notepad++. 
     
     
    Em creatureevents.cpp:
    return "onPrepareDeath"; Adicione abaixo:
    case CREATURE_EVENT_MOVEITEM: return "onMoveItem"; case CREATURE_EVENT_MOVEITEM2: return "onMoveItem2";  
    Em:
    return "cid, deathList"; Adicione abaixo:
    case CREATURE_EVENT_MOVEITEM: return "moveItem, frompos, topos, cid"; case CREATURE_EVENT_MOVEITEM2: return "cid, item, count, toContainer, fromContainer, fromPos, toPos";  
    Em:
    m_type = CREATURE_EVENT_PREPAREDEATH; Adicione abaixo:
    else if(tmpStr == "moveitem") m_type = CREATURE_EVENT_MOVEITEM; else if(tmpStr == "moveitem2") m_type = CREATURE_EVENT_MOVEITEM2;  
    Procure por:
    bool CreatureEvents::playerLogout(Player* player, bool forceLogout) { //fire global event if is registered bool result = true; for(CreatureEventList::iterator it = m_creatureEvents.begin(); it != m_creatureEvents.end(); ++it) { if((*it)->getEventType() == CREATURE_EVENT_LOGOUT && (*it)->isLoaded() && !(*it)->executeLogout(player, forceLogout) && result) result = false; } return result; } Adicione abaixo:
    uint32_t CreatureEvents::executeMoveItems(Creature* actor, Item* item, const Position& frompos, const Position& pos) { // fire global event if is registered for(CreatureEventList::iterator it = m_creatureEvents.begin(); it != m_creatureEvents.end(); ++it) { if((*it)->getEventType() == CREATURE_EVENT_MOVEITEM) { if(!(*it)->executeMoveItem(actor, item, frompos, pos)) return 0; } } return 1; }  
    Em:
    bool CreatureEvents::playerLogin(Player* player) { //fire global event if is registered bool result = true; for(CreatureEventList::iterator it = m_creatureEvents.begin(); it != m_creatureEvents.end(); ++it) { if((*it)->getEventType() == CREATURE_EVENT_LOGIN && (*it)->isLoaded() && !(*it)->executeLogin(player) && result) result = false; } if (result) { for(CreatureEventList::iterator it = m_creatureEvents.begin(); it != m_creatureEvents.end(); ++it) { CreatureEvent* event = *it; if(event->isLoaded() && ( event->getRegister() == "player" || event->getRegister() == "all") ) player->registerCreatureEvent(event->getName()); } } return result; } Adicione Abaixo:
    uint32_t CreatureEvent::executeMoveItem(Creature* actor, Item* item, const Position& frompos, const Position& pos) { //onMoveItem(moveItem, frompos, position, cid) if(m_interface->reserveEnv()) { ScriptEnviroment* env = m_interface->getEnv(); if(m_scripted == EVENT_SCRIPT_BUFFER) { env->setRealPos(pos); std::stringstream scriptstream; env->streamThing(scriptstream, "moveItem", item, env->addThing(item)); env->streamPosition(scriptstream, "position", frompos, 0); env->streamPosition(scriptstream, "position", pos, 0); scriptstream << "local cid = " << env->addThing(actor) << std::endl; scriptstream << m_scriptData; bool result = true; if(m_interface->loadBuffer(scriptstream.str())) { lua_State* L = m_interface->getState(); result = m_interface->getGlobalBool(L, "_result", true); } m_interface->releaseEnv(); return result; } else { #ifdef __DEBUG_LUASCRIPTS__ char desc[35]; sprintf(desc, "%s", player->getName().c_str()); env->setEventDesc(desc); #endif env->setScriptId(m_scriptId, m_interface); env->setRealPos(pos); lua_State* L = m_interface->getState(); m_interface->pushFunction(m_scriptId); LuaInterface::pushThing(L, item, env->addThing(item)); LuaInterface::pushPosition(L, frompos, 0); LuaInterface::pushPosition(L, pos, 0); lua_pushnumber(L, env->addThing(actor)); bool result = m_interface->callFunction(4); m_interface->releaseEnv(); return result; } } else { std::clog << "[Error - CreatureEvent::executeMoveItem] Call stack overflow." << std::endl; return 0; } } uint32_t CreatureEvent::executeMoveItem2(Player* player, Item* item, uint8_t count, const Position& fromPos, const Position& toPos, Item* toContainer, Item* fromContainer, int16_t fstack) { //onMoveItem2(cid, item, count, toContainer, fromContainer, fromPos, toPos) if(m_interface->reserveEnv()) { ScriptEnviroment* env = m_interface->getEnv(); if(m_scripted == EVENT_SCRIPT_BUFFER) { env->setRealPos(player->getPosition()); std::stringstream scriptstream; scriptstream << "local cid = " << env->addThing(player) << std::endl; env->streamThing(scriptstream, "item", item, env->addThing(item)); scriptstream << "local count = " << count << std::endl; env->streamThing(scriptstream, "toContainer", toContainer, env->addThing(toContainer)); env->streamThing(scriptstream, "fromContainer", fromContainer, env->addThing(fromContainer)); env->streamPosition(scriptstream, "fromPos", fromPos, fstack); env->streamPosition(scriptstream, "toPos", toPos, 0); scriptstream << m_scriptData; bool result = true; if(m_interface->loadBuffer(scriptstream.str())) { lua_State* L = m_interface->getState(); result = m_interface->getGlobalBool(L, "_result", true); } m_interface->releaseEnv(); return result; } else { #ifdef __DEBUG_LUASCRIPTS__ char desc[30]; sprintf(desc, "%s", player->getName().c_str()); env->setEvent(desc); #endif env->setScriptId(m_scriptId, m_interface); env->setRealPos(player->getPosition()); lua_State* L = m_interface->getState(); m_interface->pushFunction(m_scriptId); lua_pushnumber(L, env->addThing(player)); LuaInterface::pushThing(L, item, env->addThing(item)); lua_pushnumber(L, count); LuaInterface::pushThing(L, toContainer, env->addThing(toContainer)); LuaInterface::pushThing(L, fromContainer, env->addThing(fromContainer)); LuaInterface::pushPosition(L, fromPos, fstack); LuaInterface::pushPosition(L, toPos, 0); //lua_pushnumber(L, env->addThing(actor)); bool result = m_interface->callFunction(7); m_interface->releaseEnv(); return result; } } else { std::clog << "[Error - CreatureEvent::executeMoveItem] Call stack overflow." << std::endl; return 0; } }  
     
     
    Agora em em creatureevents.h:
    CREATURE_EVENT_PREPAREDEATH, Adicione abaixo:
    CREATURE_EVENT_MOVEITEM, CREATURE_EVENT_MOVEITEM2  
    Em:
    uint32_t executePrepareDeath(Creature* creature, DeathList deathList); Adicione abaixo:
    uint32_t executeMoveItem(Creature* actor, Item* item, const Position& frompos, const Position& pos); uint32_t executeMoveItem2(Player* player, Item* item, uint8_t count, const Position& fromPos, const Position& toPos, Item* toContainer, Item* fromContainer, int16_t fstack);  
    Em:
    bool playerLogout(Player* player, bool forceLogout); Abaixo adicone também
    uint32_t executeMoveItems(Creature* actor, Item* item, const Position& frompos, const Position& pos); uint32_t executeMoveItem2(Player* player, Item* item, uint8_t count, const Position& fromPos, const Position& toPos, Item* toContainer, Item* fromContainer, int16_t fstack);  
     
    Agora em em game.cpp:
    if(!canThrowObjectTo(mapFromPos, mapToPos) && !player->hasCustomFlag(PlayerCustomFlag_CanThrowAnywhere)) { player->sendCancelMessage(RET_CANNOTTHROW); return false; } ReturnValue ret = internalMoveItem(player, fromCylinder, toCylinder, toIndex, item, count, NULL); if(ret == RET_NOERROR) return true; player->sendCancelMessage(ret); return false; } Altere para:
    if (!canThrowObjectTo(mapFromPos, mapToPos) && !player->hasCustomFlag(PlayerCustomFlag_CanThrowAnywhere)) { player->sendCancelMessage(RET_CANNOTTHROW); return false; } bool success = true; CreatureEventList moveitemEvents = player->getCreatureEvents(CREATURE_EVENT_MOVEITEM2); for (CreatureEventList::iterator it = moveitemEvents.begin(); it != moveitemEvents.end(); ++it) { Item* toContainer = toCylinder->getItem(); Item* fromContainer = fromCylinder->getItem(); if (!(*it)->executeMoveItem2(player, item, count, fromPos, toPos, (toContainer ? toContainer : 0), (fromContainer ? fromContainer : 0), fromStackpos) && success) success = false; } if (!success) return false; if (g_config.getBool(ConfigManager::ANTI_PUSH)) { std::string antiPushItems = g_config.getString(ConfigManager::ANTI_PUSH_ITEMS); IntegerVec tmpVec = vectorAtoi(explodeString(antiPushItems, ",")); if (tmpVec[0] != 0) { for (IntegerVec::iterator it = tmpVec.begin(); it != tmpVec.end(); ++it) { if (item->getID() == uint32_t(*it) && player->hasCondition(CONDITION_EXHAUST, 1)) { player->sendTextMessage(MSG_STATUS_SMALL, "Please wait a few seconds to move this item."); return false; } } } } int32_t delay = g_config.getNumber(ConfigManager::ANTI_PUSH_DELAY); if (Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_EXHAUST, delay, 0, false, 1)) player->addCondition(condition); if (!g_creatureEvents->executeMoveItems(player, item, mapFromPos, mapToPos)) return false; ReturnValue ret = internalMoveItem(player, fromCylinder, toCylinder, toIndex, item, count, NULL); if (ret != RET_NOERROR) { player->sendCancelMessage(ret); return false; } player->setNextAction(OTSYS_TIME() + g_config.getNumber(ConfigManager::ACTIONS_DELAY_INTERVAL) - 10); return true; }  
    Agora em configmanager.h
    ADMIN_ENCRYPTION_DATA Adicione abaixo:
    ANTI_PUSH_ITEMS,  
    em:
    STAMINA_DESTROY_LOOT, Adicione abaixo:
    ANTI_PUSH_DELAY,  
    em:
    ADDONS_PREMIUM, Adicione abaixo:
    ANTI_PUSH  
    Agora você pode compilar a Source.
     
     
    Configurando no servidor:
     
    Abra seu config.lua do servidor e adicione isso dentro qualquer lugar:
    -- Anti-Push useAntiPush = true antiPushItems = "2148,2152,2160,3976" antiPushDelay = 500  
     
    Navegue até o diretório 'creaturescripts' e localize o arquivo 'login.lua'.
    em resgistros de eventos adicione:
    login.lua
    registerCreatureEvent(cid, "MoveItem") registerCreatureEvent(cid, "MoveItem2")  
    Agora abra o aquivo creaturescript .xml
    <event type="moveitem" name="MoveItem" event="script" value="houseprotecao.lua"/> <event type="moveitem2" name="MoveItem2" event="script" value="moveitem2.lua"/>  
    Crie um novo arquivo lua em scripts com o nome houseprotecao.lua e adicione isso:
    function onMoveItem(moveItem, frompos, position, cid) if position.x == CONTAINER_POSITION then return true end local house = getHouseFromPos(frompos) or getHouseFromPos(position) --correção 100% if type(house) == "number" then local owner = getHouseOwner(house) if owner == 0 then return false, doPlayerSendCancel(cid, "Isso não é Possível.") end if owner ~= getPlayerGUID(cid) then local sub = getHouseAccessList(house, 0x101):explode("\n") local guest = getHouseAccessList(house, 0x100):explode("\n") local isInvited = false if (#sub > 0) and isInArray(sub, getCreatureName(cid)) then isInvited = true end if (#guest > 0) and isInArray(guest, getCreatureName(cid)) then isInvited = true end if not isInvited then return false, doPlayerSendCancel(cid, "Desculpe, você não está invitado.") end end end return true end  
    Crie um novo arquivo lua em scripts com o nome moveitem2.lua e adicione isso abaixo:
    local depottiles = {} --piso pra n jogar local depots = {2589} --id dos dps local group = 3 --id dos group 6 é todos. local function checkIfThrow(pos,topos) if topos.x == 0xffff then return false end local thing = getThingFromPos(pos) if isInArray(depottiles,thing.itemid) then if not isInArea(topos,{x=pos.x-1,y=pos.y-1,z=pos.z},{x=pos.x+1,y=pos.y+1, z=pos.z}) then return true end else for i = 1, #depots do if depots[i] == getTileItemById(topos,depots[i]).itemid or getTileInfo(topos).actionid == 7483 then return true end end end return false end function onMoveItem2(cid, item, count, toContainer, fromContainer, fromPos, toPos) if isPlayer(cid) then local pos = getThingPos(cid) if getPlayerGroupId(cid) > group then return true end if checkIfThrow({x=pos.x,y=pos.y,z=pos.z,stackpos=0},toPos) then doPlayerSendCancel(cid,"Não jogue item ai!!") doSendMagicEffect(getThingPos(cid),CONST_ME_POFF) return false end end return true end  
    ajudei?? REP+
    CRÉDITOS:
    @L3K0T
    Fir3element
    Summ
    Wise
    GOD Wille
    Yan Lima
     
     
     
     
  21. Gostei
    Ayron5 recebeu reputação de L3K0T em Saiba todas as funções do seu TFS   
    Irei usar ^ ^  
    O Mock ainda existe? Kk
  22. Curtir
    Ayron5 deu reputação a L3K0T em Saiba todas as funções do seu TFS   
    Como diz o titulo? você pode gerar suas funções do seu tfs em um arquivo texto, para fazer isso é só ir na lib 050 e adicionar isso no final, depois é só ligar o seu servidor e assim todas funções do seu server vai aparecer no arquivo txt. "Isso é bom pra resolver problemas de scripts e trabalhar de forma melhor, com a manipulação do mesmo."
     
    function getLuaFunctions() local str = "" for f,k in pairs(_G) do if type(k) == 'function' then str = str..f..',' elseif type(k) == 'table' then for d,o in pairs(k) do if type(o) == 'function' then if f ~= '_G' and d ~= "_G" and f ~= 'package' then str = str..f.."."..d..',' end elseif type(o) == 'table' then for m,n in pairs(o) do if type(n) == 'function' then if d == "_M" and m ~= "_M" and f ~= "_G" and f ~= 'package' then str = str..f.."."..m.."," elseif f ~= '_G' and m ~= "_G" and d ~= "_G" and f ~= 'package' then str = str..f.."."..d..'.'..m..',' end elseif type(n) == 'table' then for x,p in pairs(n) do if type(p) == 'function' then if m == "_M" and d ~= "_M" and f ~= "_G" and f ~= 'package' then str = str..f.."."..d..'.'..x..',' elseif m == "_M" and d == "_M" and f ~= "_G" and f ~= 'package' then str = str..f.."."..x..',' elseif m ~= "_M" and d == "_M" and f ~= "_G" and f ~= 'package' then str = str..f..'.'..m..'.'..x..',' elseif f ~= '_G' and m ~= "_G" and d ~= "_G" and f ~= 'package' then str = str..f.."."..d..'.'..m..'.'..x..',' end end end end end end end end end return string.explode(str,',') end local k = getLuaFunctions() local file__ = io.open('funcoes do seu servidor.txt','w') table.sort(k) for i=1,#k do if k[i] ~= "" then file__:write((i-1)..' - '..k[i]..'\n') end end file__:close() Créditos: Mock
  23. Obrigado
    Ayron5 recebeu reputação de ADM Flow em Baú Que dá Outfit se tiver Level   
    Ela é bem fácil de editar, é só usar a imaginação kkj 
  24. Obrigado
    Ayron5 recebeu reputação de ADM Flow em [Npc] Que vende Stones (itens) por diamonds   
    Faça bom proveito. 
  25. Obrigado
    Ayron5 recebeu reputação de L3K0T em Removendo Block Spawn   
    Massa, faz o blockspawn ^ ^

Informação Importante

Confirmação de Termo