Ir para conteúdo

vitor vieira

Membro
  • Registro em

  • Última visita

  1. vitor vieira alterou sua foto pessoal
  2. Olá pessoal aqui da comunidade, ja estou batendo cabeça aqui sobre um sistema de caça de pk ou hunted sistem ja faz quase uma semana recorrendo a todos os forums e sem sucesso, ja vi que tem aqui um post sobre este sistema , ja tentei por em pratica ele mas sem sucesso. pois a versão que estou é a 13x e os codigos não funciona na minha versão, tentei por diversas vezes fazer as modificações trazendo para o client mais atual mas nada... Alguem por gentileza tem algo ja funcionando nesta versão e que possa compartilhar? Volto a repetir, ja vi varios aqui mas tudo nas versoes antigas, que não esta dando certo para minha versão mais recente. cheguei ate este ponto aqui, mas daqui ja não estou conseguindo progredir... é erro atras de erro... segue a criação da tabela de banco do banco de dados: CREATE TABLE `busque_cabeca` ( `id` INT AUTO_INCREMENT PRIMARY KEY, -- ID único para cada entrada `fp_id` INT NOT NULL, -- ID do jogador que ofereceu a recompensa `sp_id` INT NOT NULL, -- ID do jogador caçado `k_id` INT DEFAULT 0, -- ID do jogador que matou o alvo (0 se ainda vivo) `added` INT NOT NULL, -- Timestamp de quando a recompensa foi adicionada `prize` BIGINT NOT NULL, -- Valor total da recompensa `fp_ids` TEXT, -- Lista de IDs dos jogadores que contribuíram para a recompensa `killed` TINYINT DEFAULT 0, -- Status: 0 = vivo, 1 = morto `kill_time` INT DEFAULT 0 -- Timestamp de quando o jogador foi morto ); SEGUE O CODIGO .LUA -- Definição das constantes de mensagem (ajuste conforme necessário) local MESSAGE_STATUS_CONSOLE_BLUE = 17 local MESSAGE_STATUS_CONSOLE_ORANGE = 18 -- Função auxiliar para dividir strings function string:split(sep) local fields = {} local pattern = string.format("([^%s]+)", sep) self:gsub(pattern, function(c) fields[#fields + 1] = c end) return fields end -- Função para obter o GUID do jogador pelo nome function getPlayerGUIDByName(name) print("[DEBUG] getPlayerGUIDByName called for name: " .. name) local resultId = db.storeQuery("SELECT `id` FROM `players` WHERE `name` = " .. db.escapeString(name)) if not resultId then print("[DEBUG] Player not found in database.") return nil end local guid = result.getNumber(resultId, "id") result.free(resultId) print("[DEBUG] Found player GUID: " .. guid) return guid end -- Função para verificar o dinheiro total do jogador (em mãos + banco) function getPlayerTotalMoney(player) local moneyInHand = player:getMoney() local bankBalance = player:getBankBalance() print("[DEBUG] Money in hand: " .. moneyInHand .. ", Bank balance: " .. bankBalance) return moneyInHand + bankBalance end -- Função para remover dinheiro total do jogador (priorizando o banco) function removePlayerTotalMoney(player, amount) local moneyInHand = player:getMoney() local bankBalance = player:getBankBalance() if bankBalance >= amount then -- Retira todo o valor do banco player:setBankBalance(bankBalance - amount) print("[DEBUG] Removed " .. amount .. " coins from bank.") else -- Retira o que puder do banco e o restante da bag local remainingAmount = amount - bankBalance player:setBankBalance(0) if moneyInHand >= remainingAmount then player:removeMoney(remainingAmount) print("[DEBUG] Removed " .. bankBalance .. " coins from bank and " .. remainingAmount .. " coins from hand.") else print("[DEBUG] Insufficient funds after attempting to remove money.") return false end end return true end -- Comando !busque local busque = TalkAction("!busque") busque:separator(" ") function busque.onSay(player, words, param) print("[DEBUG] !busque called by player: " .. player:getName()) local t = param:split(" ") if #t < 2 then print("[DEBUG] Insufficient parameters provided.") player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "[BUSQUE A CABEÇA] Use: \"!busque [valor] [nick]\" Exemplo de prêmio: 1(k).") return true end local prize = tonumber(t[1]) local targetName = t[2] print("[DEBUG] Prize: " .. tostring(prize) .. ", Target Name: " .. targetName) if not prize or prize < 1 or prize >= 100000000000000000000 then print("[DEBUG] Invalid prize value.") player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "[BUSQUE A CABEÇA] Valor de prêmio inválido.") return true end local sp_id = getPlayerGUIDByName(targetName) if not sp_id then print("[DEBUG] Target player does not exist.") player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "[BUSQUE A CABEÇA] Este jogador não existe.") return true end if sp_id == player:getGuid() then print("[DEBUG] Player tried to add themselves to the list.") player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "[BUSQUE A CABEÇA] Você não pode colocar a si mesmo na lista de caçados.") return true end local totalMoney = getPlayerTotalMoney(player) print("[DEBUG] Total money available: " .. totalMoney .. ", Required amount: " .. prize) if totalMoney < prize then print("[DEBUG] Player does not have enough money.") player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "[BUSQUE A CABEÇA] Você não tem dinheiro suficiente.") return true end -- Verifica se o jogador já está na lista de caçados local result_plr = db.storeQuery("SELECT `id`, `prize`, `fp_ids` FROM `busque_cabeca` WHERE `sp_id` = " .. sp_id .. " AND `killed` = 0;") if result_plr then -- Jogador já está na lista, verifica se o jogador atual já fez uma oferta local id = result.getNumber(result_plr, "id") local currentPrize = result.getNumber(result_plr, "prize") local fp_ids = result.getString(result_plr, "fp_ids") or "" result.free(result_plr) print("[DEBUG] Current prize: " .. currentPrize) print("[DEBUG] Current fp_ids: " .. fp_ids) -- Verifica se o jogador atual já fez uma oferta local fp_id = player:getGuid() if fp_ids:find(tostring(fp_id)) then print("[DEBUG] Player already made an offer for this target.") player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "[BUSQUE A CABEÇA] Você já fez uma oferta para este jogador.") return true end -- Acumula o valor da recompensa e atualiza a lista de IDs local newPrize = currentPrize + prize local updatedFpIds = fp_ids .. (fp_ids == "" and "" or ",") .. fp_id print("[DEBUG] Updated prize: " .. newPrize) print("[DEBUG] Updated fp_ids: " .. updatedFpIds) local updateQuery = string.format( "UPDATE `busque_cabeca` SET `prize` = %d, `fp_ids` = '%s' WHERE `id` = %d;", newPrize, updatedFpIds, id ) db.asyncQuery(updateQuery) print("[DEBUG] Bounty updated for player ID: " .. sp_id .. ". New prize: " .. newPrize) -- Remove o dinheiro do jogador if not removePlayerTotalMoney(player, prize) then print("[DEBUG] Failed to remove money from player.") player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "[BUSQUE A CABEÇA] Erro ao processar o pagamento. Tente novamente.") return true end player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "[BUSQUE A CABEÇA] Recompensa acumulada! Novo valor total: " .. newPrize .. " moedas.") return true end -- Jogador não está na lista, cria uma nova entrada local query = string.format( "INSERT INTO `busque_cabeca` (`fp_id`, `sp_id`, `k_id`, `added`, `prize`, `fp_ids`, `killed`, `kill_time`) VALUES (%d, %d, 0, %d, %d, '%d', 0, 0);", player:getGuid(), sp_id, os.time(), prize, player:getGuid() ) db.asyncQuery(query) print("[DEBUG] Bounty added successfully for player ID: " .. sp_id) -- Remove o dinheiro do jogador if not removePlayerTotalMoney(player, prize) then print("[DEBUG] Failed to remove money from player.") player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "[BUSQUE A CABEÇA] Erro ao processar o pagamento. Tente novamente.") return true end player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "[BUSQUE A CABEÇA] Mandato de caçada criado com sucesso!") end -- Registra o comando !busque busque:groupType("normal") -- Permite apenas jogadores do grupo "normal" a usar o comando busque:register() -- Função para processar a morte do jogador function processPlayerDeath(playerId, killed_by) print("[DEBUG] Processing death for player ID: " .. playerId .. ", Killed by: " .. killed_by) -- Consulta o banco de dados para verificar se o jogador está na lista de caçados local result_plr = db.storeQuery("SELECT `id`, `prize`, `killed` FROM `busque_cabeca` WHERE `sp_id` = " .. playerId .. " AND `killed` = 0;") if not result_plr then print("[DEBUG] Player is not on the bounty list.") return true end local id = result.getNumber(result_plr, "id") local prize = result.getNumber(result_plr, "prize") local killed = result.getNumber(result_plr, "killed") result.free(result_plr) print("[DEBUG] Player is on the bounty list. ID: " .. id .. ", Prize: " .. prize .. ", Killed: " .. killed) -- Obtém o ID do assassino pelo nome local killer_id = getPlayerGUIDByName(killed_by) if not killer_id then print("[DEBUG] Failed to retrieve killer ID.") return true end print("[DEBUG] Killer ID: " .. killer_id) -- Atualiza o banco de dados para marcar o jogador como morto local updateQuery = string.format( "UPDATE `busque_cabeca` SET `k_id` = %d, `killed` = 1, `kill_time` = %d WHERE `id` = %d;", killer_id, os.time(), id ) db.asyncQuery(updateQuery) print("[DEBUG] Player marked as killed in database. ID: " .. id) -- Obtém o objeto do assassino local killer = Player(killer_id) if not killer then print("[DEBUG] Killer player object not found.") return true end -- Deposita o prêmio diretamente no banco do assassino local currentBankBalance = killer:getBankBalance() killer:setBankBalance(currentBankBalance + prize) print("[DEBUG] Awarded " .. prize .. " coins to killer's bank account: " .. killer:getName()) killer:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "[BUSQUE A CABEÇA] Você recebeu " .. prize .. " moedas no seu banco por matar este jogador!") -- Mensagem para o assassino informando que o alvo foi marcado como inativo killer:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "[BUSQUE A CABEÇA] O jogador " .. getPlayerNameById(playerId) .. " foi removido da lista de caçados.") return true end -- Função auxiliar para obter o nome do jogador pelo ID function getPlayerNameById(playerId) local resultId = db.storeQuery("SELECT `name` FROM `players` WHERE `id` = " .. playerId) if not resultId then return "Unknown" end local name = result.getString(resultId, "name") result.free(resultId) return name end -- Função principal para verificar mortes periodicamente function checkForDeaths() print("[DEBUG] Checking for recent deaths...") -- Determina o formato do campo `time` e ajusta a consulta SQL local query if isUnixTimestampFormat() then -- Caso 1: `time` é armazenado em segundos desde a época Unix query = "SELECT `player_id`, `killed_by`, `is_player` FROM `player_deaths` WHERE `time` > UNIX_TIMESTAMP() - 60;" elseif isDatetimeFormat() then -- Caso 2: `time` é armazenado no formato MySQL (`DATETIME` ou `TIMESTAMP`) query = "SELECT `player_id`, `killed_by`, `is_player` FROM `player_deaths` WHERE `time` > NOW() - INTERVAL 60 SECOND;" else -- Caso 3: Formato personalizado (ajuste conforme necessário) print("[DEBUG] Unknown `time` format in `player_deaths`. Cannot process deaths.") return true end print("[DEBUG] Executing query: " .. query) local result = db.storeQuery(query) if not result then print("[DEBUG] No recent deaths found or query failed.") return true end -- Verifica se o resultado é válido antes de iterar if type(result) ~= "userdata" then print("[DEBUG] Invalid result type returned by db.storeQuery: " .. type(result)) return true end -- Verifica se há linhas no resultado if not result.next(result) then print("[DEBUG] Query returned no rows.") result.free(result) return true end -- Itera sobre os resultados da consulta repeat local playerId = result.getNumber(result, "player_id") local killedBy = result.getString(result, "killed_by") local isPlayer = result.getNumber(result, "is_player") if playerId then print("[DEBUG] Found recent death for player ID: " .. playerId) if killedBy and isPlayer == 1 then print("[DEBUG] Player was killed by: " .. killedBy) processPlayerDeath(playerId, killedBy) else print("[DEBUG] Killer is not a player or data is invalid.") end else print("[DEBUG] Invalid player ID found in death records.") end until not result.next(result) -- Libera o resultado para evitar vazamentos de memória if result.free then result.free(result) print("[DEBUG] Result freed successfully.") else print("[DEBUG] Result object does not have a 'free' method.") end return true end -- Função para verificar o formato do campo `time` function isUnixTimestampFormat() local result = db.storeQuery("SELECT `time` FROM `player_deaths` LIMIT 1;") if not result then return false end local timeValue = result.getNumber(result, "time") result.free(result) -- Verifica se o valor é um número inteiro return type(timeValue) == "number" and math.floor(timeValue) == timeValue end function isDatetimeFormat() local result = db.storeQuery("SELECT `time` FROM `player_deaths` LIMIT 1;") if not result then return false end local timeValue = result.getString(result, "time") result.free(result) -- Verifica se o valor é uma string no formato `YYYY-MM-DD HH:MM:SS` return type(timeValue) == "string" and timeValue:match("%d%d%d%d%-%d%d%-%d%d %d%d:%d%d:%d%d") end -- Registra a verificação de mortes como um evento periódico local deathCheckEvent = GlobalEvent("death_check_event") function deathCheckEvent.onThink(interval) checkForDeaths() return true end deathCheckEvent:interval(60000) -- Executa a cada 60 segundos deathCheckEvent:register() Se alguem tiver alguma sulução para me ajudar pois realmente estou a desistir ja. Estes são os erros..... Interface: Scripts Interface Script ID: C:\otserv\data/scripts\talkactions\player\busque.lua:callback Error Description: C:\otserv\data/scripts\talkactions\player\busque.lua:311: attempt to index local 'result' (a number value) stack traceback: [C]: in function '__index' C:\otserv\data/scripts\talkactions\player\busque.lua:311: in function 'isUnixTimestampFormat' C:\otserv\data/scripts\talkactions\player\busque.lua:241: in function 'checkForDeaths' C:\otserv\data/scripts\talkactions\player\busque.lua:334: in function <C:\otserv\data/scripts\talkactions\player\busque.lua:333> --------------------------------------- [2025-03-02 20:05:11.708] [error] [GlobalEvents::think] - Failed to execute event: death_check_event Vamos lá só resumindo aqui... o que esta funcionando: - char usa o comando !busque (valor a ser pago) (nome do personagem) - Não permite o mesmo player colocar mais que uma vez a oferta.. mas deixa outros jogadores colocarem mais oferta, onde a recompensa por busca deste personagem vai ficando cada vez mais alta (se acumulando).... - o dinheiro esta saindo da conta do banco ou da bag, primeiro ele veja se tem no banco se tiver ja pega de la o valor, senão checa a BP. o que não esta funcionando e não estou conseguindo finalizar... - a pessoa que mata o personagem (char) não esta recebendo a recompensa e retirando o personagem morto da lista de hunted.... Agradeço muito quem puder ajudar ou a resolver este problema, ou me fornecer algo ja pronto funcional, para versão 13x. Att.

Informação Importante

Confirmação de Termo