Isso não é inédito em OTS, mas fiz o meu sistema de Caçador de Recompensa (Bounty Hunter)
1. Informações sobre o sistema
- Sistema de pontos por recompensa incluído (configurável)
- Rank de maiores caçadores
- Rank de maiores recompensas
- Lista de jogadores com recompensa online
2. Funcionamento
- Você fala com o NPC, que oferece várias opções
22:24 Tyrion: Yess, I am the masster of the assasssinsss. What do you want with the guild? Post a bounty on someone? Get your reward, check the most wanted or your points? Or maybe some information about our bounty system?
Você pode colocar uma recompensa para a morte de alguém (post), pegar seu dinheiro por caçar alguém (reward), checar as maiores recompensas (most wanted), checar seus pontos de caçador (points) ou obter informações gerais sobre o funcionamento (information)
Para colocar uma recompensa, você deve fornecer um nome. Se esse jogador existir, você deverá oferecer um valor (mínimo configurável). Depois, desse valor será descontada a taxa da guilda dos assassinos (configurável). Se você tiver esse dinheiro, ele será removido e o nome dessa pessoa estará na lista de procurados, para que o jogador que a matar (não funciona para o jogador que colocou a recompensa) ganhe a recompensa devida
Quando um jogador mata outro procurado, ele é avisado de que ganhou a recompensa e os pontos (se estiver ativado). Para pegar a recompensa, ele deve falar com o NPC
Para saber quais jogadores procurados estão online e quais são suas recompensas, foi adicionado um quadro especial que lista esses jogadores, assim como um outro quadro que lista os maiores caçadores do servidor
3. Códigos
3.1. Tags
- Creaturescripts.xml:
<event type="kill" name="bountykill" event="script" value="bountykill.lua"/> <event type="look" name="bountyboard" event="script" value="bountyboard.lua"/>
- talkactions.xml:
<talkaction words="/installbounty" access="5" event="script" value="bountyinstall.lua"/>
3.2. NPC
- Crie um arquivo: npcs/Tyrion.xml
<?xml version="1.0" encoding="UTF-8"?> <npc name="Tyrion" script="data/npc/scripts/assguild.lua" walkinterval="2000" floorchange="0"> <health now="100" max="100"/> <look type="152" head="0" body="94" legs="113" feet="114" addons="3"/> <parameters> <parameter key="message_greet" value="I am Tyoric, leader of the {assassin guild}."/> <parameter key="message_walkaway" value="I'll have your head for that!"/> <parameter key="message_farewell" value="Farewell, my friend."/> <parameter key="message_alreadyfocused" value="..."/> </parameters> </npc>
3.3. Códigos lua
- Adicionar em creaturescripts/login.lua, junto com os demais registerCreatureEvent
registerCreatureEvent(cid, "bountyboard") registerCreatureEvent(cid, "bountykill")
- lib/bountylib.lua
--[[ SISTEMA DE CAÇADOR DE RECOMPENSAS FEITO POR LEORIC [OMEGA] ]]-- bountyReward = 7050 bountyPoints = 7051 bountyRank = 7052 bountyHire = 7053 bountyConfig = { min = 10000, -- Mínimo aceito para adicionar uma recompensa fee = 10, -- Taxa para adicionar uma recompensa por algum jogador omegaPointSystem = true, -- [true -> cálculo automático dos pontos de acordo com a recompensa / false -> desabilitado] points = false, -- [false -> desabilitado / número de pontos que o jogador receberá por caçar um procurado] } function isHunted(cid) if isPlayer(cid) then local id = getPlayerGUID(cid) local bounty = db.getResult("SELECT `bounty` FROM `players` WHERE `id` = "..id..";") return bounty:getDataInt("bounty") > 0 and true or false end return false end function getPlayerBounty(playername) if playerExists(playername) then local id = getPlayerGUIDByName(playername) local bounty = db.getResult("SELECT `bounty` FROM `players` WHERE `id` = "..id..";") return bounty:getDataInt("bounty") ~= 0 and bounty:getDataInt("bounty") or 0 end return false end function doPlayerAddBounty(playername, bounty) if not tonumber(bounty) or tonumber(bounty) < 1 or tonumber(bounty) == nil then return false end if getPlayerBounty(playername) then local pid = getPlayerGUIDByName(playername) local bounty_ = bounty + getPlayerBounty(playername) if db.query("UPDATE `players` SET `bounty` = "..bounty_.." WHERE `id` = "..pid..";") then return true end end return false end function doPlayerClearBounty(playername) if playerExists(playername) then local pid = getPlayerGUIDByName(playername) if db.query("UPDATE `players` SET `bounty` = 0 WHERE `id` = "..pid..";") then return true end end return false end function getTopBounties(max) local query = db.getResult("SELECT `id` FROM `players` WHERE `bounty` > 0 ORDER BY `bounty` DESC;") if query:getID() == -1 then return false end local tabela = {} i = 0 repeat table.insert(tabela, query:getDataInt("id")) i = i + 1 until i >= max or not query:next() return tabela end function doPlayerAddBountyPoints(cid, bounty) local points = 0 if bountyConfig.omegaPointSystem then points = math.ceil(bounty / 10000) elseif bountyConfig.points == true then points = 1 elseif type(bountyConfig.points) == 'number' then points = bountyConfig.points end if points > 0 then setPlayerStorageValue(cid, bountyPoints, getPlayerStorageValue(cid, bountyPoints) + points) end return points > 0 and points or false end function playerExist(playername) exist = db.getResult("SELECT `id` FROM `players` WHERE `name` = '"..playername.."';") return exist:getID() ~= -1 and true or false end
- creaturescripts/scripts/bountykill.lua
--[[ SISTEMA DE CAÇADOR DE RECOMPENSAS FEITO POR LEORIC [OMEGA] ]]-- function onKill(cid, target, damage, flags) if isHunted(target) then if getGlobalStorageValue(getPlayerGUID(target) + 20000) == getPlayerGUID(cid) then return true end local bounty = getPlayerBounty(getCreatureName(target)) local prev_reward = getPlayerStorageValue(cid, bountyReward) > 0 and getPlayerStorageValue(cid, bountyReward) or 0 local prev_rank = getPlayerStorageValue(cid, bountyRank) > 0 and getPlayerStorageValue(cid, bountyRank) or 0 setPlayerStorageValue(cid, bountyReward, prev_reward + bounty) setPlayerStorageValue(cid, bountyRank, prev_rank + bounty) doPlayerClearBounty(getCreatureName(target)) if bountyConfig.points == false and bountyConfig.omegaPointSystem == false then doPlayerSendTextMessage(cid, 21, 'You have killed a hunted target and won '..bounty..'gps.') return true end local points = doPlayerAddBountyPoints(cid, bounty) doPlayerSendTextMessage(cid, 21, 'You have killed a hunted target and won '..bounty..'gps and '..points..' bounty points. Talk to the Assassin leader to withdraw your money.') end return true end
- creaturescripts/scripts/bountyboard.lua
--[[ SISTEMA DE CAÇADOR DE RECOMPENSAS FEITO POR LEORIC [OMEGA] ]]-- function onLook(cid, thing, position, lookDistance) if thing.actionid == 3550 then local hunted = {} for _,pid in ipairs(getPlayersOnline()) do if isHunted(pid) then local bounty = getPlayerBounty(getCreatureName(pid)) table.insert(hunted, getCreatureName(pid)..' [Bounty: '..bounty..'] <Level '..getPlayerLevel(pid)..'>') end end if #hunted < 1 then doPlayerSendTextMessage(cid,25,'There is no bounty posted for current online players.') return false end local str = "" for _, string in ipairs(hunted) do str = str..''..string..'\n' end str = str ~= '' and 'Hunted Players Online:\n'..str or false if str then doPlayerPopupFYI(cid, str) end return false elseif thing.actionid == 3551 then local query = db.getResult("SELECT `player_id`, `value` FROM `player_storage` WHERE `key` = 7052 and `value` > 0 ORDER BY `value` DESC") if query:getID() == -1 then doPlayerSendTextMessage(cid, 25, 'There are no registered bounty hunters.') return false end local str = "BOUNTY HUNTER RANK\n" local j = 0 repeat str = str..""..getPlayerNameByGUID(query:getDataInt("player_id")).." ["..query:getDataInt("value").."]\n" j = j + 1 until not query:next() or j >= 10 doPlayerPopupFYI(cid, str) return false end return true end
- npcs/scripts/assguild.lua
--[[ SISTEMA DE CAÇADOR DE RECOMPENSAS FEITO POR LEORIC [OMEGA] ]]-- local keywordHandler = KeywordHandler:new() local npcHandler = NpcHandler:new(keywordHandler) NpcSystem.parseParameters(npcHandler) local talkState = {} function onCreatureAppear(cid) npcHandler:onCreatureAppear(cid) end function onCreatureDisappear(cid) npcHandler:onCreatureDisappear(cid) end function onCreatureSay(cid, type, msg) npcHandler:onCreatureSay(cid, type, msg) end function onThink() npcHandler:onThink() end function creatureSayCallback(cid, type, msg) if(not npcHandler:isFocused(cid)) then return false end local talkUser = NPCHANDLER_CONVBEHAVIOR == CONVERSATION_DEFAULT and 0 or cid local playerReward = getPlayerStorageValue(cid, bountyReward) local points = getPlayerStorageValue(cid, bountyPoints) > 0 and getPlayerStorageValue(cid, bountyPoints) or 0 if msgcontains(msg,'assassin guild') then selfSay('Yess, I am the masster of the assasssinsss. What do you want with the guild? {Post} a bounty on someone? Get your {reward}, check the {most wanted} or your {points}? Or maybe some {information} about our bounty system?',cid) talkState[talkUser] = 1 elseif talkState[talkUser] == 1 then if msgcontains(msg,'post') then selfSay('Yesss, a bounty?! Good for businessss. The death of whom do you wish? Give me a {name}.',cid) talkState[talkUser] = 2 elseif msgcontains(msg,'information') then selfSay('It isss very sssimple. You give me a name and money and I\'ll put it at the bounty board. You can check who hasss an active bounty there too. Who kills that person, gets the money. Ssssimple. And, of course, you don\'t get paid to kill a person whose bounty you posted.',cid) elseif msgcontains(msg, 'points') then if bountyConfig.points == false and bountyConfig.omegaPointSystem == false then selfSay('Point system is currently disabled.',cid) else selfSay('You have '..points..' bounty points.',cid) end elseif msgcontains(msg,'reward') then if playerReward > 0 then doPlayerAddMoney(cid, playerReward) selfSay('Here you go, my bounty hunter friend, '..playerReward..' gps.', cid) setPlayerStorageValue(cid, bountyReward, 0) talkState[talkUser] = 1 else selfSay('Nope, you have no reward to collect.',cid) talkState[talkUser] = 1 end elseif msgcontains(msg, 'most wanted') then local players = getTopBounties(10) local names = {} local str = '' if not players then selfSay('There are no active bounties at this moment.',cid) return true end for index, pid in ipairs(players) do table.insert(names,'{'..index..'} '..getPlayerNameByGUID(pid)..' ['..getPlayerBounty(getPlayerNameByGUID(pid))..']\n') end str = table.concat(names) doPlayerPopupFYI(cid, str) end elseif talkState[talkUser] == 2 then if not playerExist(msg) then selfSay('No, no, no. That is not a valid target. Give me a {name}!',cid) elseif string.lower(msg) == string.lower(getCreatureName(cid)) then selfSay('You can\'t post a bounty on yourself, stupid!', cid) else playername = {} playername[cid] = msg selfSay('Very well. The service has a minimum cost of '..bountyConfig.min..' and we take a '..bountyConfig.fee..'% fee of your bounty. How much do you want to deposit on your bounty?',cid) talkState[talkUser] = 3 end elseif talkState[talkUser] == 3 then if tonumber(msg) ~= nil and tonumber(msg) and tonumber(msg) >= bountyConfig.min then bounty = tonumber(msg) if doPlayerRemoveMoney(cid, bounty) then doPlayerAddBounty(playername[cid], math.ceil(((1-(bountyConfig.fee/100))*bounty))) setGlobalStorageValue(getPlayerGUIDByName(playername[cid])+20000, getPlayerGUIDByName(getCreatureName(cid))) selfSay('You have sssuccessfully posted a bounty for '..playername[cid]..'.',cid) selfSay('Would you like anything else? Maybe {post} a bounty on someone, check the {most wand} or your {points}? Get your {reward}? Or maybe some {information} about our bounty system?',cid) playername[cid] = nil talkState[talkUser] = 1 else selfSay('You can\'t fool me, you basssstard! You don\'t pay, I add no bounty!',cid) talkState[talkUser] = 1 end else selfSay('I\'m still expecting a real bounty, my friend... it has to be bigger than '..bountyConfig.min..'.',cid) end end return true end npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback) npcHandler:addModule(FocusModule:new())
- talkactions/scripts/bountyinstall.lua
function onSay(cid, words, param) local func = db.query or db.executeQuery if not func then doPlayerSendTextMessage(cid, 27, 'Omega Bounty Hunter System installation failed.') elseif func("ALTER TABLE `players` ADD `bounty` INT(15) NOT NULL DEFAULT 0") then doPlayerSendTextMessage(cid, 27, 'Omega Bounty Hunter System installation sucessful!.') else doPlayerSendTextMessage(cid, 27, 'Omega Bounty Hunter System installation failed.') end return true end
4. Configuração / Instalação
- Você deve usar o comando /installbounty pelo GOD para que o sistema adicione a coluna necessária no seu banco de dados
- As configurações disponíveis estão no bountylib.lua
- O sistema de pontos apenas adiciona e conta os pontos. Cabe a sua imaginação/habilidade fazer algo a partir deles
- Para adicionar o rank de melhores caçadores e a lista de procurados online, você deve criar dois itens (eu recomendo o quadro negro - id 1810, por exemplo) e colocar os actionids 3550 e 3551. Assim, quando alguém der look, aparecerão as respectivas listas
- [óbvio] O sistema depende de que você adicione o NPC no mapa [/óbvio]
5. Bugs
- Apesar de ter testado bastante, ainda há espaço para alguns bugs. Caso você os encontre, por favor poste DETALHADAMENTE qual é o erro para que eu possa consertar
6. Considerações Finais
- Espero críticas/sugestões/elogios sobre o código e seu funcionamento