Postado Fevereiro 3 Fev 3 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.
Participe da conversa
Você pode postar agora e se cadastrar mais tarde. Se você tem uma conta, faça o login para postar com sua conta.