Detalhes: Como cada servidor é
bem diferente, acredito que muitos erros vão aparecer devido a diferença
de IDs das polas por exemplo, mas vou ajudar no que posso.
Primeiro passo: crie um arquivo com o nome gymlib.lua na pasta data/lib/, e coloque isso dentro do arquivo:
Spoiler
funcpokemon = {2220, 2222} -- ID das pokebolas (o pokemon tem que estar vivo nessas IDs)
bpslot = CONST_SLOT_BACKPACK --em outros servers, pode ser que seja CONST_SLOT_AMMO o lugar onde fica a backpack no inventory
ginasios = {
["Brock"] = { storage = 990,
msgdefeat = "You lost! You aren't strong enough yet, don't come back until you get stronger!",
msgafk = "Go away if you don't have any pokemons!",
msgwin = "Congratulations, you were strong enough to win this battle fairly! Take this Earth Badge as reward.",
[1] = { msggo = "Lets fight then! I choose you, Geodude!",
msgba = "That's enough, Geodude!",
pokem = "Brock Geodude",
nextp = "Brock Graveler"},
[2] = { msggo = "It's your turn, Graveler!",
msgba = "Come back, Graveler!",
pokem = "Brock Graveler",
nextp = "Brock Golem"},
[3] = { msggo = "Crush'em, Golem!",
msgba = "You did well, Golem!",
pokem = "Brock Golem",
nextp = "finish"}
}
}
function noPokeAtAll(cid, gympoke, npcname, msgafk)
if not isCreature(cid) then
return false
end
if not isCreature(gympoke) then
return false
end
if #getCreatureSummons(cid) == 0 and getPlayerStorageValue(cid, 991) == 0 and getPlayerStorageValue(cid, ginasios[npcname].storage) ~= 2 then
setPlayerStorageValue(cid, 991, -1)
doCreatureSay(getCreatureByName(npcname), msgafk, 1)
doSendMagicEffect(getThingPos(gympoke), 10)
setPlayerStorageValue(cid, ginasios[npcname].storage, 0)
doRemoveCreature(gympoke)
return true
end
end
function gymChecker(cid, duel, nb, npcname)
if not isCreature(cid) then
return true
end
if not isCreature(duel) then
doSendMagicEffect(getThingPos(cid), 10)
doRemoveCreature(cid)
return true
end
if getDistanceBetween(getThingPos(getCreatureByName(npcname)), getThingPos(duel)) >= 8 then
doSendMagicEffect(getThingPos(cid), 10)
doRemoveCreature(cid)
setPlayerStorageValue(duel, ginasios[npcname].storage, 0)
return true
end
if isCreature(duel) and getPlayerStorageValue(duel, 991) == 0 then
addEvent(noPokeAtAll, 6000, duel, cid, npcname, ginasios[npcname].msgafk)
end
if isCreature(duel) and getPlayerStorageValue(duel, 991) == -1 then
doSendMagicEffect(getThingPos(cid), 10)
doRemoveCreature(cid)
setPlayerStorageValue(duel, ginasios[npcname].storage, 0)
doCreatureSay(getCreatureByName(npcname), ginasios[npcname].msgdefeat, 1)
return true
end
if isCreature(duel) and not hasPokemon(duel) then
setPlayerStorageValue(duel, 991, -1)
end
if not isCreature(getCreatureTarget(cid)) then
if nb == 0 then
addEvent(gymChecker, 200, cid, duel, 1, npcname)
else
doSendMagicEffect(getThingPos(cid), 10)
doRemoveCreature(cid)
if isCreature(duel) then
setPlayerStorageValue(duel, ginasios[npcname].storage, 0)
end
end
return true
end
addEvent(gymChecker, 1000, cid, duel, 0, npcname)
end
function hasPokemon(cid)
if #getCreatureSummons(cid) >= 1 then
return true
end
if isInArray(funcpokemon, getPlayerSlotItem(cid, CONST_SLOT_FEET).itemid) then
return true
end
local bp = getPlayerSlotItem(cid, bpslot)
for cc = 1, #funcpokemon do
if #getItemsInContainerById(bp.uid, funcpokemon[cc]) >= 1 then
return true
end
end
return false
end
function doGymBattle(npcname, gympoke, cid, turn)
doCreatureSay(getCreatureByName(npcname), ginasios[npcname][turn].msggo, 1)
local x = doSummonCreature(gympoke, getThingPos(getCreatureByName(npcname)))
registerCreatureEvent(x, "Gym1")
registerCreatureEvent(x, "Gym2")
registerCreatureEvent(x, "Gym3")
registerCreatureEvent(x, "Gym4")
setPlayerStorageValue(x, 201, ".")
setPlayerStorageValue(x, 201, npcname)
setPlayerStorageValue(x, 202, turn)
doSendMagicEffect(getThingPos(x), 10)
setPlayerStorageValue(x, ginasios[npcname].storage, 1)
addEvent(gymChecker, 1000, x, cid, 0, npcname)
end
--ex: doGymBattle("Brock", "Brock Geodude", cid, 1)
Segundo passo: crie um arquivo chamado gym.lua na pasta data/creaturescripts/scripts/ e coloque isso dentro:
Spoiler
function onDeath(cid, corpse)
doSendMagicEffect(getThingPos(cid), 10)
local npc = ""..getPlayerStorageValue(cid, 201)..""
local turn = getPlayerStorageValue(cid, 202)
local nturn = ((turn) + 1)
local nxt = ginasios[npc][turn].nextp
doCreatureSay(getCreatureByName(npc), ginasios[npc][turn].msgba, 1)
if nxt == "finish" then
local killer = getItemAttribute(corpse.uid, "corpseowner")
addEvent(doCreatureSay, 1200, getCreatureByName(npc), ginasios[npc].msgwin, 1)
setPlayerStorageValue(getCreatureMaster(killer), ginasios[npc].storage, 2)
--local item = getPlayerItemById(killer, true, 2307)
--doTransformItem(item.uid, 2294)
doRemoveCreature(cid)
return false
end
local function summonNext(poke, pos, gym, msg, cid)
local x = doSummonCreature(poke, pos)
addEvent(gymChecker, 1000, x, cid, 0)
doSendMagicEffect(getThingPos(x), 10)
doCreatureSay(getCreatureByName(gym), msg, 1)
end
local killer = getItemAttribute(corpse.uid, "corpseowner")
addEvent(doGymBattle, 1200, npc, ginasios[npc][turn].nextp, killer, nturn)
doRemoveCreature(cid)
return false
end
local fightconditionnn = createConditionObject(CONDITION_INFIGHT)
setConditionParam(fightconditionnn, CONDITION_PARAM_TICKS, 18 * 1000)
function onAttack(cid, target)
if getPlayerStorageValue(getCreatureMaster(target), ginasios[getPlayerStorageValue(cid, 201)].storage) ~= 1 then
doMonsterChangeTarget(cid)
doChangeSpeed(cid, -getCreatureSpeed(cid))
return true
end
if isPlayer(target) then
if #getCreatureSummons(target) == 0 then
doMonsterChangeTarget(cid)
doChangeSpeed(cid, -getCreatureSpeed(cid))
return true
end
if #getCreatureSummons(target) >= 1 then
doMonsterSetTarget(cid, getCreatureSummons(target)[1])
end
end
if getCreatureSpeed(cid) == 0 then
doChangeSpeed(cid, -getCreatureSpeed(cid))
doChangeSpeed(cid, 200)
end
doAddCondition(getCreatureMaster(target), fightconditionnn)
return true
end
function onCast(cid, target)
if isPlayer(target) then
return false
end
local targete = getCreatureTarget(cid)
if isPlayer(getCreatureMaster(targete)) and getPlayerStorageValue(getCreatureMaster(targete), ginasios[getPlayerStorageValue(cid, 201)].storage) ~= 1 then
return false
end
return true
end
function onDirection(cid, old, current)
if isCreature(getCreatureTarget(cid)) and not isPlayer(getCreatureTarget(cid)) and getPlayerStorageValue(getCreatureMaster(getCreatureTarget(cid)), ginasios[getPlayerStorageValue(cid, 201)].storage) == 1 then
return true
end
return false
end
Terceiro passo: abra o arquivo creaturescripts.xml (localizado em data/creaturescripts) e adicione essas 4 tags:
Quarto passo: crie um arquivo chamado brock.xml em data/npc e crie um chamado brock.lua em data/npc/scripts e coloque isso dentro:
Spoiler
local focus = 0
local talk_start = 0
local target = 0
local following = false
local attacking = false
local talkState = {}
function onThingMove(creature, thing, oldpos, oldstackpos)
end
function onCreatureAppear(creature)
end
function onCreatureDisappear(cid, pos)
if focus == cid then
selfSay('Good bye sir!')
focus = 0
talk_start = 0
end
end
function onCreatureTurn(creature)
end
function msgcontains(txt, str)
return (string.find(txt, str) and not string.find(txt, '(%w+)' .. str) and not string.find(txt, str .. '(%w+)'))
end
function onCreatureSay(cid, type, msg)
local msg = string.lower(msg)
local talkUser = NPCHANDLER_CONVBEHAVIOR == CONVERSATION_DEFAULT and 0 or cid
if getPlayerStorageValue(cid, ginasios["Brock"].storage) >= 1 then
return true
end
if (msgcontains(msg, 'hi') and (focus == 0) and (focus ~= cid) and (getDistanceToCreature(cid) <= 4)) then
focus = cid
talkState[talkUser] = 1
selfSay("Welcome to the gym of Pewter City. My name is Brock and I am the leader of this gym. Would you like to battle me?")
elseif (msgcontains(msg, "no") or msgcontains(msg, "bye")) and focus == cid and talkState[talkUser] ~= 3 then
selfSay("Bye then, tell strong friends to come here and try to beat me!")
focus = 0
elseif (msgcontains(msg, "yes") or msgcontains(msg, "battle")) and focus == cid and talkState[talkUser] == 1 then
if not hasPokemon(cid) then
selfSay("You don't have any pokemon to battle me!")
focus = 0
return true
end
talkState[talkUser] = 3
doGymBattle("Brock", "Brock Geodude", cid, 1)
setPlayerStorageValue(cid, ginasios["Brock"].storage, 1)
setPlayerStorageValue(cid, 991, 0)
local function focusCheck(cid)
if not isCreature(cid) then
focus = 0
return true
end
if getPlayerStorageValue(cid, 991) == -1 then
focus = 0
return true
end
addEvent(focusCheck, 500, cid)
end
addEvent(focusCheck, 1000, cid)
end
end
function onThink()
if focus ~= 0 then
a, b, c = selfGetPosition()
if c ~= getThingPos(focus).z then
focus = 0
end
end
if focus ~= 0 then
if getDistanceToCreature(focus) > 6 then
focus = 0
end
end
return true
end
Quinto passo: se você usar o pokemon dash, vá no arquivo playerattack.lua (data/creatureevents/scripts) e adicione esses códigos embaixo da linha "function onAttack(cid, target)":
if getPlayerStorageValue(target, 201) ~= -1 then
for a, b in pairs(ginasios) do
if getPlayerStorageValue(target, ginasios[getPlayerStorageValue(target, 201)].storage) == 1 then
if getPlayerStorageValue(cid, ginasios[getPlayerStorageValue(target, 201)].storage) ~= 1 then
doPlayerSendCancel(cid, "You can't attack this pokemon.")
return false
end
end
end
end
end
Se você não usa o pokemon dash, crie um arquivo chamado playerattack.lua na pasta data/creatureevents/scripts e coloque isso dentro:
function onAttack(cid, target)
if getPlayerStorageValue(target, 201) ~= -1 then
for a, b in pairs(ginasios) do
if getPlayerStorageValue(target, ginasios[getPlayerStorageValue(target, 201)].storage) == 1 then
if getPlayerStorageValue(cid, ginasios[getPlayerStorageValue(target, 201)].storage) ~= 1 then
doPlayerSendCancel(cid, "You can't attack this pokemon.")
return false
end
end
end
end
return true
end
e adicione essa tag no creaturescripts.xml (data/creaturescripts):
e ainda, abra o arquivo login.lua e embaixo dessa linha: "function onLogin(cid)" adicione esse código:
registerCreatureEvent(cid, "PlayerAttack")
Último passo: vá em data/creaturescripts/scripts e abra o arquivo goback.lua (aqui por exemplo, pode ser que haja uma particulariedade de servidor para servidor), e procure pela linha:
function onDeath(cid, deathList)
e abaixo dela, adicione esse código:
local owner = getCreatureMaster(cid)
for x, y in pairs(ginasios) do
if getPlayerStorageValue(owner, y.storage) == 1 then
if getPlayerStorageValue(owner, 991) == 5 or not hasPokemon(owner) then
setPlayerStorageValue(owner, 991, -1)
else
local number = tonumber(getPlayerStorageValue(owner, 991))
setPlayerStorageValue(owner, 991, number + 1)
end
end
end
Configuração dos NPCs:
Abrindo o arquivo brock.lua na pasta data/npc/scripts, procure por esta linha:
"doGymBattle("Brock", "Brock Geodude", cid, 1)"
o "Brock" precisa ser o nome do NPC e o "Brock Geodude" precisa ser o nome do primeiro pokemon a ser usado.
Agora nessa parte, no script do seu NPC, você também deve editar o nome do NPC no lugar de "brock".
Se quiser que o player possa lutar com o NPC mesmo depois de tê-lo vencido, é só remover a mesma parte:
if getPlayerStorageValue(cid, ginasios["Brock"].storage) >= 1 then
return true
end
Ao abrir o arquivo gymlib.lua, você encontra essas duas linhas (são as primeiras):
funcpokemon = {2220, 2222} -- ID das pokebolas (o pokemon tem que estar vivo nessas IDs)
bpslot = CONST_SLOT_BACKPACK --em outros servers, pode ser que seja CONST_SLOT_AMMO o lugar onde fica a backpack no inventoryOnde está funcpokemon,
você coloca o ID de todas as pokebolas do seu server, mas esse ID tem
que ser o ID da pokebola com algum pokemon vivo dentro, e esses IDs
devem ser separados por vírgula.
Onde está bpslot, você escreve onde fica a
BACKPACK do seu server de pokemon. Se ficar no lugar normal de BPs,
deixe como está, mas se sua BP fica no slot da munição (ammunition),
você deve estar para CONST_SLOT_AMMO. Isso é
tudo, agora vocês podem configurar os IDs e localização da BP
facilmente, sem precisar conhecimentos mais avançados sobre scripting, e
evitar erros no sistema.
Abrindo o arquivo gymlib.lua, localizado em data/lib/ você encontra essa tabela:
ginasios = {
["Brock"] = { storage = 900,
msgdefeat = "You lost! You aren't strong enough yet, don't come back until you get stronger!",
msgafk = "Go away if you don't have any pokemons!",
msgwin = "Congratulations, you were strong enough to win this battle fairly! Take this Earth Badge as reward.",
[1] = { msggo = "Lets fight then! I choose you, Geodude!",
msgba = "That's enough, Geodude!",
pokem = "Brock Geodude",
nextp = "Brock Graveler"},
[2] = { msggo = "It's your turn, Graveler!",
msgba = "Come back, Graveler!",
pokem = "Brock Graveler",
nextp = "Brock Golem"},
[3] = { msggo = "Crush'em, Golem!",
msgba = "You did well, Golem!",
pokem = "Brock Golem",
nextp = "finish"}
}
}
• storage significa a
única storage que deve variar de NPC para NPC, tenha certeza de que
essa storage não está sendo usada, é você não deve usar a storage 901 aqui, pois a mesma já está em uso pelo próprio sistema.
• msgdefeat significa o que o NPC irá dizer quando o player perder o duelo.
• msgafk significa o que o NPC irá dizer caso o player comece o duelo, mas não faça nada depois.
• msgwin significa o que o NPC irá dizer quando o player vencer o duelo.
• msggo / msgba significam os textos que o NPC irá dizer ao sumonar o pokemon dele, ou quando o mesmo morrer, respectivamente.• pokem / nextp significam o nome do pokemon que será utilizado, e o próximo pokemon a ser sumonado pelo NPC, respectivamente. Caso o nextp seja especificado como "finish", não haverá um próximo pokemon.
• o número entre [] significa a ordem utilizada pelo líder para usar o tal pokemon, sendo 1 o primeiro pokemon, 2 o segundo e assim vai...
Uma tabela detalhada sobre a configuração:
Spoiler
ginasios = {
["nome do npc"] = { storage = xxx (algum número para a storage),
msgdefeat = "texto quando o player perder",
msgafk = "texto caso o player fique afk",
msgwin = "texto caso o player ganhe",
[1] = { msggo = "texto quando o npc sumonar o primeiro pokemon",
msgba = "texto quando o primeiro pokemon morrer",
pokem = "nome do primeiro pokemon a ser sumonado",
nextp = "nome do próximo pokemon a ser sumonado"},
[2] = { msggo = "texto quando o npc sumonar o segundo pokemon",
msgba = "texto quando o segundo pokemon morrer",
pokem = "nome do segundo pokemon a ser sumonado",
nextp = "nome do próximo pokemon a ser sumonado"},
[3] = { msggo = "texto quando o npc sumonar o terceiro pokemon",
msgba = "texto quando o terceiro pokemon morrer",
pokem = "nome do terceiro pokemon a ser sumonado",
nextp = "nome do próximo pokemon a ser sumonado"},
[4] = { msggo = "texto quando o npc sumonar o quarto pokemon",
msgba = "texto quando o quarto pokemon morrer",
pokem = "nome do quarto pokemon a ser sumonado",
nextp = "nome do próximo pokemon a ser sumonado"},
[5] = { msggo = "texto quando o npc sumonar o quinto pokemon",
msgba = "texto quando o quinto pokemon morrer",
pokem = "nome do quinto pokemon a ser sumonado",
nextp = "nome do próximo pokemon a ser sumonado"},
[6] = { msggo = "texto quando o npc sumonar o sexto pokemon",
msgba = "texto quando o sexto pokemon morrer",
pokem = "nome do sexto pokemon a ser sumonado",
nextp = "nome do próximo pokemon a ser sumonado (finish, caso queria que só hajam 6"},
},
["nome de outro npc"] = { storage = xxx (algum número para a storage),
msgdefeat = "texto quando o player perder",
msgafk = "texto caso o player fique afk",
msgwin = "texto caso o player ganhe",
[1] = { msggo = "texto quando o npc sumonar o primeiro pokemon",
msgba = "texto quando o primeiro pokemon morrer",
pokem = "nome do primeiro pokemon a ser sumonado",
nextp = "nome do próximo pokemon a ser sumonado"},
[2] = { msggo = "texto quando o npc sumonar o segundo pokemon",
msgba = "texto quando o segundo pokemon morrer",
pokem = "nome do segundo pokemon a ser sumonado",
nextp = "nome do próximo pokemon a ser sumonado"},
[3] = { msggo = "texto quando o npc sumonar o terceiro pokemon",
msgba = "texto quando o terceiro pokemon morrer",
pokem = "nome do terceiro pokemon a ser sumonado",
nextp = "nome do próximo pokemon a ser sumonado"},
[4] = { msggo = "texto quando o npc sumonar o quarto pokemon",
msgba = "texto quando o quarto pokemon morrer",
pokem = "nome do quarto pokemon a ser sumonado",
nextp = "nome do próximo pokemon a ser sumonado"},
[5] = { msggo = "texto quando o npc sumonar o quinto pokemon",
msgba = "texto quando o quinto pokemon morrer",
pokem = "nome do quinto pokemon a ser sumonado",
nextp = "nome do próximo pokemon a ser sumonado"},
[6] = { msggo = "texto quando o npc sumonar o sexto pokemon",
msgba = "texto quando o sexto pokemon morrer",
pokem = "nome do sexto pokemon a ser sumonado",
nextp = "nome do próximo pokemon a ser sumonado"},
}
}
Importante: caso for testar o sistema como foi postado aqui, é necessário criar antes os monstros Brock Geodude, Brock Graveler e Brock Golem, assim como adicioná-los no monsters.xml.
Recomendações: é bom você impedir
que o pokemon consiga retornar para a pokebola durante duelos (assim
como foi feito no SvkE), para isso, basta adicionar esse código no
arquivo goback.lua (data/actions) na parte inicial de retornar o pokemon:
for a, b in pairs(ginasios) do
if getPlayerStorageValue(cid, b.storage) == 1 then -- GYM
doPlayerSendCancel(cid, "You can't return your pokemon during gym battles.")
return true
end
endAconselho fazer o mesmo caso seu server tenha script de revive.
Deve-se também checar pelos storages usado em players, somente o 990 e o 991.
No servidor testado, é utilizado apenas pokeballs e ultraballs, com IDs 2220 e 2222 (outra particularidade).
Após ter instalado os arquivos, entre no jogo e use o comando /n Brock para testar o NPC.
Último aviso: o prêmio ainda não foi adicionado (que seria a badge), pois esse sim é bem variado de servidor pra servidor.
Já que nenhum servidor base já vem com os IDs das badges, cada um
adicionou elas de modo diferente, por isso não pude fazer, mas existe
uma parte sobre um prêmio no arquivo gym.lua (data/creaturescripts/scripts), procure por isso:
--local item = getPlayerItemById(killer, true, 2307)
--doTransformItem(item.uid, 2294)Você pode modificar para adicionar dinheiro ou outra coisa, e pode também desenvolver um sistema de badges.
Eu não vou fazer badge aqui, mas se vocês tentarem, posso ajudar com problemas.
Quaisquer erros, tentarei responder o mais rápido possível.
bem diferente, acredito que muitos erros vão aparecer devido a diferença
de IDs das polas por exemplo, mas vou ajudar no que posso.
Primeiro passo: crie um arquivo com o nome gymlib.lua na pasta data/lib/, e coloque isso dentro do arquivo:
Spoiler
funcpokemon = {2220, 2222} -- ID das pokebolas (o pokemon tem que estar vivo nessas IDs)
bpslot = CONST_SLOT_BACKPACK --em outros servers, pode ser que seja CONST_SLOT_AMMO o lugar onde fica a backpack no inventory
ginasios = {
["Brock"] = { storage = 990,
msgdefeat = "You lost! You aren't strong enough yet, don't come back until you get stronger!",
msgafk = "Go away if you don't have any pokemons!",
msgwin = "Congratulations, you were strong enough to win this battle fairly! Take this Earth Badge as reward.",
[1] = { msggo = "Lets fight then! I choose you, Geodude!",
msgba = "That's enough, Geodude!",
pokem = "Brock Geodude",
nextp = "Brock Graveler"},
[2] = { msggo = "It's your turn, Graveler!",
msgba = "Come back, Graveler!",
pokem = "Brock Graveler",
nextp = "Brock Golem"},
[3] = { msggo = "Crush'em, Golem!",
msgba = "You did well, Golem!",
pokem = "Brock Golem",
nextp = "finish"}
}
}
function noPokeAtAll(cid, gympoke, npcname, msgafk)
if not isCreature(cid) then
return false
end
if not isCreature(gympoke) then
return false
end
if #getCreatureSummons(cid) == 0 and getPlayerStorageValue(cid, 991) == 0 and getPlayerStorageValue(cid, ginasios[npcname].storage) ~= 2 then
setPlayerStorageValue(cid, 991, -1)
doCreatureSay(getCreatureByName(npcname), msgafk, 1)
doSendMagicEffect(getThingPos(gympoke), 10)
setPlayerStorageValue(cid, ginasios[npcname].storage, 0)
doRemoveCreature(gympoke)
return true
end
end
function gymChecker(cid, duel, nb, npcname)
if not isCreature(cid) then
return true
end
if not isCreature(duel) then
doSendMagicEffect(getThingPos(cid), 10)
doRemoveCreature(cid)
return true
end
if getDistanceBetween(getThingPos(getCreatureByName(npcname)), getThingPos(duel)) >= 8 then
doSendMagicEffect(getThingPos(cid), 10)
doRemoveCreature(cid)
setPlayerStorageValue(duel, ginasios[npcname].storage, 0)
return true
end
if isCreature(duel) and getPlayerStorageValue(duel, 991) == 0 then
addEvent(noPokeAtAll, 6000, duel, cid, npcname, ginasios[npcname].msgafk)
end
if isCreature(duel) and getPlayerStorageValue(duel, 991) == -1 then
doSendMagicEffect(getThingPos(cid), 10)
doRemoveCreature(cid)
setPlayerStorageValue(duel, ginasios[npcname].storage, 0)
doCreatureSay(getCreatureByName(npcname), ginasios[npcname].msgdefeat, 1)
return true
end
if isCreature(duel) and not hasPokemon(duel) then
setPlayerStorageValue(duel, 991, -1)
end
if not isCreature(getCreatureTarget(cid)) then
if nb == 0 then
addEvent(gymChecker, 200, cid, duel, 1, npcname)
else
doSendMagicEffect(getThingPos(cid), 10)
doRemoveCreature(cid)
if isCreature(duel) then
setPlayerStorageValue(duel, ginasios[npcname].storage, 0)
end
end
return true
end
addEvent(gymChecker, 1000, cid, duel, 0, npcname)
end
function hasPokemon(cid)
if #getCreatureSummons(cid) >= 1 then
return true
end
if isInArray(funcpokemon, getPlayerSlotItem(cid, CONST_SLOT_FEET).itemid) then
return true
end
local bp = getPlayerSlotItem(cid, bpslot)
for cc = 1, #funcpokemon do
if #getItemsInContainerById(bp.uid, funcpokemon[cc]) >= 1 then
return true
end
end
return false
end
function doGymBattle(npcname, gympoke, cid, turn)
doCreatureSay(getCreatureByName(npcname), ginasios[npcname][turn].msggo, 1)
local x = doSummonCreature(gympoke, getThingPos(getCreatureByName(npcname)))
registerCreatureEvent(x, "Gym1")
registerCreatureEvent(x, "Gym2")
registerCreatureEvent(x, "Gym3")
registerCreatureEvent(x, "Gym4")
setPlayerStorageValue(x, 201, ".")
setPlayerStorageValue(x, 201, npcname)
setPlayerStorageValue(x, 202, turn)
doSendMagicEffect(getThingPos(x), 10)
setPlayerStorageValue(x, ginasios[npcname].storage, 1)
addEvent(gymChecker, 1000, x, cid, 0, npcname)
end
--ex: doGymBattle("Brock", "Brock Geodude", cid, 1)
Segundo passo: crie um arquivo chamado gym.lua na pasta data/creaturescripts/scripts/ e coloque isso dentro:
Spoiler
function onDeath(cid, corpse)
doSendMagicEffect(getThingPos(cid), 10)
local npc = ""..getPlayerStorageValue(cid, 201)..""
local turn = getPlayerStorageValue(cid, 202)
local nturn = ((turn) + 1)
local nxt = ginasios[npc][turn].nextp
doCreatureSay(getCreatureByName(npc), ginasios[npc][turn].msgba, 1)
if nxt == "finish" then
local killer = getItemAttribute(corpse.uid, "corpseowner")
addEvent(doCreatureSay, 1200, getCreatureByName(npc), ginasios[npc].msgwin, 1)
setPlayerStorageValue(getCreatureMaster(killer), ginasios[npc].storage, 2)
--local item = getPlayerItemById(killer, true, 2307)
--doTransformItem(item.uid, 2294)
doRemoveCreature(cid)
return false
end
local function summonNext(poke, pos, gym, msg, cid)
local x = doSummonCreature(poke, pos)
addEvent(gymChecker, 1000, x, cid, 0)
doSendMagicEffect(getThingPos(x), 10)
doCreatureSay(getCreatureByName(gym), msg, 1)
end
local killer = getItemAttribute(corpse.uid, "corpseowner")
addEvent(doGymBattle, 1200, npc, ginasios[npc][turn].nextp, killer, nturn)
doRemoveCreature(cid)
return false
end
local fightconditionnn = createConditionObject(CONDITION_INFIGHT)
setConditionParam(fightconditionnn, CONDITION_PARAM_TICKS, 18 * 1000)
function onAttack(cid, target)
if getPlayerStorageValue(getCreatureMaster(target), ginasios[getPlayerStorageValue(cid, 201)].storage) ~= 1 then
doMonsterChangeTarget(cid)
doChangeSpeed(cid, -getCreatureSpeed(cid))
return true
end
if isPlayer(target) then
if #getCreatureSummons(target) == 0 then
doMonsterChangeTarget(cid)
doChangeSpeed(cid, -getCreatureSpeed(cid))
return true
end
if #getCreatureSummons(target) >= 1 then
doMonsterSetTarget(cid, getCreatureSummons(target)[1])
end
end
if getCreatureSpeed(cid) == 0 then
doChangeSpeed(cid, -getCreatureSpeed(cid))
doChangeSpeed(cid, 200)
end
doAddCondition(getCreatureMaster(target), fightconditionnn)
return true
end
function onCast(cid, target)
if isPlayer(target) then
return false
end
local targete = getCreatureTarget(cid)
if isPlayer(getCreatureMaster(targete)) and getPlayerStorageValue(getCreatureMaster(targete), ginasios[getPlayerStorageValue(cid, 201)].storage) ~= 1 then
return false
end
return true
end
function onDirection(cid, old, current)
if isCreature(getCreatureTarget(cid)) and not isPlayer(getCreatureTarget(cid)) and getPlayerStorageValue(getCreatureMaster(getCreatureTarget(cid)), ginasios[getPlayerStorageValue(cid, 201)].storage) == 1 then
return true
end
return false
end
Terceiro passo: abra o arquivo creaturescripts.xml (localizado em data/creaturescripts) e adicione essas 4 tags:
Quarto passo: crie um arquivo chamado brock.xml em data/npc e crie um chamado brock.lua em data/npc/scripts e coloque isso dentro:
Spoiler
local focus = 0
local talk_start = 0
local target = 0
local following = false
local attacking = false
local talkState = {}
function onThingMove(creature, thing, oldpos, oldstackpos)
end
function onCreatureAppear(creature)
end
function onCreatureDisappear(cid, pos)
if focus == cid then
selfSay('Good bye sir!')
focus = 0
talk_start = 0
end
end
function onCreatureTurn(creature)
end
function msgcontains(txt, str)
return (string.find(txt, str) and not string.find(txt, '(%w+)' .. str) and not string.find(txt, str .. '(%w+)'))
end
function onCreatureSay(cid, type, msg)
local msg = string.lower(msg)
local talkUser = NPCHANDLER_CONVBEHAVIOR == CONVERSATION_DEFAULT and 0 or cid
if getPlayerStorageValue(cid, ginasios["Brock"].storage) >= 1 then
return true
end
if (msgcontains(msg, 'hi') and (focus == 0) and (focus ~= cid) and (getDistanceToCreature(cid) <= 4)) then
focus = cid
talkState[talkUser] = 1
selfSay("Welcome to the gym of Pewter City. My name is Brock and I am the leader of this gym. Would you like to battle me?")
elseif (msgcontains(msg, "no") or msgcontains(msg, "bye")) and focus == cid and talkState[talkUser] ~= 3 then
selfSay("Bye then, tell strong friends to come here and try to beat me!")
focus = 0
elseif (msgcontains(msg, "yes") or msgcontains(msg, "battle")) and focus == cid and talkState[talkUser] == 1 then
if not hasPokemon(cid) then
selfSay("You don't have any pokemon to battle me!")
focus = 0
return true
end
talkState[talkUser] = 3
doGymBattle("Brock", "Brock Geodude", cid, 1)
setPlayerStorageValue(cid, ginasios["Brock"].storage, 1)
setPlayerStorageValue(cid, 991, 0)
local function focusCheck(cid)
if not isCreature(cid) then
focus = 0
return true
end
if getPlayerStorageValue(cid, 991) == -1 then
focus = 0
return true
end
addEvent(focusCheck, 500, cid)
end
addEvent(focusCheck, 1000, cid)
end
end
function onThink()
if focus ~= 0 then
a, b, c = selfGetPosition()
if c ~= getThingPos(focus).z then
focus = 0
end
end
if focus ~= 0 then
if getDistanceToCreature(focus) > 6 then
focus = 0
end
end
return true
end
Quinto passo: se você usar o pokemon dash, vá no arquivo playerattack.lua (data/creatureevents/scripts) e adicione esses códigos embaixo da linha "function onAttack(cid, target)":
if getPlayerStorageValue(target, 201) ~= -1 then
for a, b in pairs(ginasios) do
if getPlayerStorageValue(target, ginasios[getPlayerStorageValue(target, 201)].storage) == 1 then
if getPlayerStorageValue(cid, ginasios[getPlayerStorageValue(target, 201)].storage) ~= 1 then
doPlayerSendCancel(cid, "You can't attack this pokemon.")
return false
end
end
end
end
end
Se você não usa o pokemon dash, crie um arquivo chamado playerattack.lua na pasta data/creatureevents/scripts e coloque isso dentro:
function onAttack(cid, target)
if getPlayerStorageValue(target, 201) ~= -1 then
for a, b in pairs(ginasios) do
if getPlayerStorageValue(target, ginasios[getPlayerStorageValue(target, 201)].storage) == 1 then
if getPlayerStorageValue(cid, ginasios[getPlayerStorageValue(target, 201)].storage) ~= 1 then
doPlayerSendCancel(cid, "You can't attack this pokemon.")
return false
end
end
end
end
return true
end
e adicione essa tag no creaturescripts.xml (data/creaturescripts):
e ainda, abra o arquivo login.lua e embaixo dessa linha: "function onLogin(cid)" adicione esse código:
registerCreatureEvent(cid, "PlayerAttack")
Último passo: vá em data/creaturescripts/scripts e abra o arquivo goback.lua (aqui por exemplo, pode ser que haja uma particulariedade de servidor para servidor), e procure pela linha:
function onDeath(cid, deathList)
e abaixo dela, adicione esse código:
local owner = getCreatureMaster(cid)
for x, y in pairs(ginasios) do
if getPlayerStorageValue(owner, y.storage) == 1 then
if getPlayerStorageValue(owner, 991) == 5 or not hasPokemon(owner) then
setPlayerStorageValue(owner, 991, -1)
else
local number = tonumber(getPlayerStorageValue(owner, 991))
setPlayerStorageValue(owner, 991, number + 1)
end
end
end
Configuração dos NPCs:
Abrindo o arquivo brock.lua na pasta data/npc/scripts, procure por esta linha:
"doGymBattle("Brock", "Brock Geodude", cid, 1)"
o "Brock" precisa ser o nome do NPC e o "Brock Geodude" precisa ser o nome do primeiro pokemon a ser usado.
Agora nessa parte, no script do seu NPC, você também deve editar o nome do NPC no lugar de "brock".
Se quiser que o player possa lutar com o NPC mesmo depois de tê-lo vencido, é só remover a mesma parte:
if getPlayerStorageValue(cid, ginasios["Brock"].storage) >= 1 then
return true
end
Ao abrir o arquivo gymlib.lua, você encontra essas duas linhas (são as primeiras):
funcpokemon = {2220, 2222} -- ID das pokebolas (o pokemon tem que estar vivo nessas IDs)
bpslot = CONST_SLOT_BACKPACK --em outros servers, pode ser que seja CONST_SLOT_AMMO o lugar onde fica a backpack no inventoryOnde está funcpokemon,
você coloca o ID de todas as pokebolas do seu server, mas esse ID tem
que ser o ID da pokebola com algum pokemon vivo dentro, e esses IDs
devem ser separados por vírgula.
Onde está bpslot, você escreve onde fica a
BACKPACK do seu server de pokemon. Se ficar no lugar normal de BPs,
deixe como está, mas se sua BP fica no slot da munição (ammunition),
você deve estar para CONST_SLOT_AMMO. Isso é
tudo, agora vocês podem configurar os IDs e localização da BP
facilmente, sem precisar conhecimentos mais avançados sobre scripting, e
evitar erros no sistema.
Abrindo o arquivo gymlib.lua, localizado em data/lib/ você encontra essa tabela:
ginasios = {
["Brock"] = { storage = 900,
msgdefeat = "You lost! You aren't strong enough yet, don't come back until you get stronger!",
msgafk = "Go away if you don't have any pokemons!",
msgwin = "Congratulations, you were strong enough to win this battle fairly! Take this Earth Badge as reward.",
[1] = { msggo = "Lets fight then! I choose you, Geodude!",
msgba = "That's enough, Geodude!",
pokem = "Brock Geodude",
nextp = "Brock Graveler"},
[2] = { msggo = "It's your turn, Graveler!",
msgba = "Come back, Graveler!",
pokem = "Brock Graveler",
nextp = "Brock Golem"},
[3] = { msggo = "Crush'em, Golem!",
msgba = "You did well, Golem!",
pokem = "Brock Golem",
nextp = "finish"}
}
}
• storage significa a
única storage que deve variar de NPC para NPC, tenha certeza de que
essa storage não está sendo usada, é você não deve usar a storage 901 aqui, pois a mesma já está em uso pelo próprio sistema.
• msgdefeat significa o que o NPC irá dizer quando o player perder o duelo.
• msgafk significa o que o NPC irá dizer caso o player comece o duelo, mas não faça nada depois.
• msgwin significa o que o NPC irá dizer quando o player vencer o duelo.
• msggo / msgba significam os textos que o NPC irá dizer ao sumonar o pokemon dele, ou quando o mesmo morrer, respectivamente.• pokem / nextp significam o nome do pokemon que será utilizado, e o próximo pokemon a ser sumonado pelo NPC, respectivamente. Caso o nextp seja especificado como "finish", não haverá um próximo pokemon.
• o número entre [] significa a ordem utilizada pelo líder para usar o tal pokemon, sendo 1 o primeiro pokemon, 2 o segundo e assim vai...
Uma tabela detalhada sobre a configuração:
Spoiler
ginasios = {
["nome do npc"] = { storage = xxx (algum número para a storage),
msgdefeat = "texto quando o player perder",
msgafk = "texto caso o player fique afk",
msgwin = "texto caso o player ganhe",
[1] = { msggo = "texto quando o npc sumonar o primeiro pokemon",
msgba = "texto quando o primeiro pokemon morrer",
pokem = "nome do primeiro pokemon a ser sumonado",
nextp = "nome do próximo pokemon a ser sumonado"},
[2] = { msggo = "texto quando o npc sumonar o segundo pokemon",
msgba = "texto quando o segundo pokemon morrer",
pokem = "nome do segundo pokemon a ser sumonado",
nextp = "nome do próximo pokemon a ser sumonado"},
[3] = { msggo = "texto quando o npc sumonar o terceiro pokemon",
msgba = "texto quando o terceiro pokemon morrer",
pokem = "nome do terceiro pokemon a ser sumonado",
nextp = "nome do próximo pokemon a ser sumonado"},
[4] = { msggo = "texto quando o npc sumonar o quarto pokemon",
msgba = "texto quando o quarto pokemon morrer",
pokem = "nome do quarto pokemon a ser sumonado",
nextp = "nome do próximo pokemon a ser sumonado"},
[5] = { msggo = "texto quando o npc sumonar o quinto pokemon",
msgba = "texto quando o quinto pokemon morrer",
pokem = "nome do quinto pokemon a ser sumonado",
nextp = "nome do próximo pokemon a ser sumonado"},
[6] = { msggo = "texto quando o npc sumonar o sexto pokemon",
msgba = "texto quando o sexto pokemon morrer",
pokem = "nome do sexto pokemon a ser sumonado",
nextp = "nome do próximo pokemon a ser sumonado (finish, caso queria que só hajam 6"},
},
["nome de outro npc"] = { storage = xxx (algum número para a storage),
msgdefeat = "texto quando o player perder",
msgafk = "texto caso o player fique afk",
msgwin = "texto caso o player ganhe",
[1] = { msggo = "texto quando o npc sumonar o primeiro pokemon",
msgba = "texto quando o primeiro pokemon morrer",
pokem = "nome do primeiro pokemon a ser sumonado",
nextp = "nome do próximo pokemon a ser sumonado"},
[2] = { msggo = "texto quando o npc sumonar o segundo pokemon",
msgba = "texto quando o segundo pokemon morrer",
pokem = "nome do segundo pokemon a ser sumonado",
nextp = "nome do próximo pokemon a ser sumonado"},
[3] = { msggo = "texto quando o npc sumonar o terceiro pokemon",
msgba = "texto quando o terceiro pokemon morrer",
pokem = "nome do terceiro pokemon a ser sumonado",
nextp = "nome do próximo pokemon a ser sumonado"},
[4] = { msggo = "texto quando o npc sumonar o quarto pokemon",
msgba = "texto quando o quarto pokemon morrer",
pokem = "nome do quarto pokemon a ser sumonado",
nextp = "nome do próximo pokemon a ser sumonado"},
[5] = { msggo = "texto quando o npc sumonar o quinto pokemon",
msgba = "texto quando o quinto pokemon morrer",
pokem = "nome do quinto pokemon a ser sumonado",
nextp = "nome do próximo pokemon a ser sumonado"},
[6] = { msggo = "texto quando o npc sumonar o sexto pokemon",
msgba = "texto quando o sexto pokemon morrer",
pokem = "nome do sexto pokemon a ser sumonado",
nextp = "nome do próximo pokemon a ser sumonado"},
}
}
Importante: caso for testar o sistema como foi postado aqui, é necessário criar antes os monstros Brock Geodude, Brock Graveler e Brock Golem, assim como adicioná-los no monsters.xml.
Recomendações: é bom você impedir
que o pokemon consiga retornar para a pokebola durante duelos (assim
como foi feito no SvkE), para isso, basta adicionar esse código no
arquivo goback.lua (data/actions) na parte inicial de retornar o pokemon:
for a, b in pairs(ginasios) do
if getPlayerStorageValue(cid, b.storage) == 1 then -- GYM
doPlayerSendCancel(cid, "You can't return your pokemon during gym battles.")
return true
end
endAconselho fazer o mesmo caso seu server tenha script de revive.
Deve-se também checar pelos storages usado em players, somente o 990 e o 991.
No servidor testado, é utilizado apenas pokeballs e ultraballs, com IDs 2220 e 2222 (outra particularidade).
Após ter instalado os arquivos, entre no jogo e use o comando /n Brock para testar o NPC.
Último aviso: o prêmio ainda não foi adicionado (que seria a badge), pois esse sim é bem variado de servidor pra servidor.
Já que nenhum servidor base já vem com os IDs das badges, cada um
adicionou elas de modo diferente, por isso não pude fazer, mas existe
uma parte sobre um prêmio no arquivo gym.lua (data/creaturescripts/scripts), procure por isso:
--local item = getPlayerItemById(killer, true, 2307)
--doTransformItem(item.uid, 2294)Você pode modificar para adicionar dinheiro ou outra coisa, e pode também desenvolver um sistema de badges.
Eu não vou fazer badge aqui, mas se vocês tentarem, posso ajudar com problemas.
Quaisquer erros, tentarei responder o mais rápido possível.