Ir para conteúdo

Pet System OOP


Oneshot

Posts Recomendados

Pet System OOP


Boa tarde, pessoal.

Depois de ver muitos sistemas de pet para Tibia, resolvi desenvolver o meu próprio sistema de pets. O diferencial do meu sistema é que ele é orientado a objetos. Sim, ele trata o pet do jogador como um objeto em Lua e suas ações como métodos.

Essa ainda é uma versão básica, que irei aprimorar aos poucos, igual fiz com meu Forge System e Refine System.

Por se tratar de uma biblioteca orientada a objetos, ele pode ser usado por qualquer scripter em diversos sistemas, e se bem adaptado, dá até para fazer um Poketibia orientado a objetos. Aliás, os comandos estão bastante semelhantes a Pokétibia.

Instalação

1. Crie um arquivo em data/lib com o nome pet-system.lua e cole o conteúdo abaixo:


-- This script is part of Pet System
-- Copyright (C) 2013 Oneshot
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.

-- storages for pet system
PET_UID = 80001
PET_SPECIE = 80002
PET_LEVEL = 80003
PET_EXPERIENCE = 80004
PET_HEALTH = 80005
PET_HEALTHMAX = 80006
PET_MANA = 80007
PET_MANAMAX = 80008
PET_EXHAUST = 80009
PET_ALIVE = 80010

Pets = {}

-- class for pet species
PetSpecie = {
type = "",

basehp = 0,
basemp = 0,

gainhp = 0,
gainmp = 0,

spells = {},

evolution = "",
evolve = 0,
}

-- class for pets
Pet = {
it = nil,

attributes = nil,

level = 0,
experience = 0,

health = 0,
healthmax = 0,

mana = 0,
manamax = 0,
}

-- create new instances of PetSpecie
function PetSpecie:new(type, basehp, basemp, gainhp, gainmp, spells, evolution, evolve)
local new_specie = {
type = type,
basehp = basehp,
basemp = basemp,
gainhp = gainhp,
gainmp = gainmp,
spells = spells,
evolution = evolution,
evolve = evolve,
}
local obj = setmetatable(new_specie, {__index = self})
Pets[type:lower()] = obj
return obj
end

-- create new instances of Pet
function PetSpecie:create()
local new_pet = {
it = nil,
attributes = self,
level = 1,
experience = 0,
health = self.basehp,
healthmax = self.basehp,
mana = self.basemp,
manamax = self.basemp,
}
return setmetatable(new_pet, {__index = Pet})
end

-- summon a player pet for the first time
function Pet:hatch(cid)
if getCreatureStorage(cid, PET_SPECIE) ~= -1 then
return doPlayerSendCancel(cid, "You already have a pet.")
end

local pet = doCreateMonster(self.attributes.type, getCreaturePosition(cid))
if not pet then
return false
end

if not doConvinceCreature(cid, pet) then
doRemoveCreature(pet)
return false
end

self:setit(pet)
setCreatureMaxHealth(pet, self.healthmax)
doCreatureAddHealth(pet, self.healthmax)
doCreatureSetStorage(cid, PET_SPECIE, self.attributes.type)
doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "Your new pet has born.")
self:save()
doSendMagicEffect(getCreaturePosition(pet), CONST_ME_HOLYDAMAGE)
return self
end

-- make player pet say something
function Pet:say(strt)
doCreatureSay(self.it, strt, TALKTYPE_ORANGE_1)
end

-- gather a summoned player pet back
function Pet:back()
self:save()
doSendMagicEffect(self:position(), CONST_ME_POFF)
doCreatureSay(getCreatureMaster(self.it), "It's enough, ".. getCreatureName(self.it))
doRemoveCreature(self.it)
end

-- free a player pet forever
function Pet:release()
local cid = getCreatureMaster(self.it)
doCreatureSay(cid, "Good bye, ".. getCreatureName(self.it) .."... :'(")
doCreatureSetStorage(cid, PET_UID, -1)
doCreatureSetStorage(cid, PET_SPECIE, -1)
doCreatureSetStorage(cid, PET_LEVEL, -1)
doCreatureSetStorage(cid, PET_EXPERIENCE, -1)
doCreatureSetStorage(cid, PET_HEALTH, -1)
doCreatureSetStorage(cid, PET_HEALTHMAX, -1)
doCreatureSetStorage(cid, PET_MANA, -1)
doCreatureSetStorage(cid, PET_MANAMAX, -1)
doSendMagicEffect(self:position(), CONST_ME_POFF)
doRemoveCreature(self.it)
end

-- add experience to player pet
function Pet:addexperience(value)
local prevLevel = self.level
local nextLevelExp = getExperienceForLevel(self.level + 1)

self.experience = self.experience + value
while self.experience >= nextLevelExp do
self.healthmax = self.healthmax + self.attributes.gainhp
self.manamax = self.manamax + self.attributes.gainmp

self.level = self.level + 1
nextLevelExp = getExperienceForLevel(self.level + 1)
end

if prevLevel ~= self.level then
self.mana = self.manamax
self.health = self.healthmax
doPlayerSendTextMessage(getCreatureMaster(self.it), MESSAGE_STATUS_CONSOLE_BLUE, "Your pet advanced from level ".. prevLevel .." to level ".. self.level ..".")
setCreatureMaxHealth(self.it, self.healthmax)
doCreatureAddHealth(self.it, getCreatureMaxHealth(self.it))
self:save()
if self.attributes.evolution then
if self.attributes.evolve and self.level >= self.attributes.evolve then
doCreatureSay(getCreatureMaster(self.it), "What's happening?!")
addEvent(function()
local cid = getCreatureMaster(self.it)
local position = self:position()
doRemoveCreature(self.it)
local pet = doCreateMonster(self.attributes.evolution, position)

if not doConvinceCreature(cid, pet) then
doRemoveCreature(pet)
call_pet(cid)
return
end

doCreatureSetStorage(cid, PET_UID, pet)
setCreatureMaxHealth(pet, self.healthmax)
doCreatureAddHealth(pet, getCreatureMaxHealth(pet))
doSendMagicEffect(getCreaturePosition(pet), CONST_ME_MORTAREA)
doCreatureSetStorage(cid, PET_SPECIE, self.attributes.evolution)
end, 100)
end
end
end
end

-- make pet cast a spell
function Pet:cast(index)
local cid = getCreatureMaster(self.it)
if not self.attributes.spells[index] then
return doPlayerSendCancel(cid, "This spell is unknown.")
end

local spell = self.attributes.spells[index]

if self.level < spell.level then
doPlayerSendCancel(cid, "Your pet doesn't have enough level to cast this spell.")
return
end

if self.mana < spell.mana then
doPlayerSendCancel(cid, "Your pet doesn't have enough mana to cast this spell.")
return
end

if getCreatureStorage(cid, PET_EXHAUST) > os.clock() then
doSendMagicEffect(self:position(), CONST_ME_POFF)
doPlayerSendCancel(cid, "Your pet is exhausted.")
return
end

if spell.target then
local target = getCreatureTarget(self.it)
if target == 0 then
doPlayerSendCancel(cid, "First, select a target.")
return
end

spell.range = spell.range or 1
if getDistanceBetween(self:position(), getCreaturePosition(target)) > spell.range then
doPlayerSendCancel(cid, "Too far to cast spell.")
return
end
doSendDistanceShoot(self:position(), getCreaturePosition(target), spell.shooteffect)
doTargetCombatHealth(self.it, target, spell.type, -spell.min, -spell.max, spell.effect)
else
doAreaCombatHealth(self.it, spell.type, self:position(), (spell.area or 0), -min, -max, spell.effect)
end
self.mana = self.mana - spell.mana
doCreatureSetStorage(cid, PET_EXHAUST, os.clock() + (spell.exhaust / 1000))
doCreatureSay(cid, getCreatureName(self.it) ..", use ".. spell.name .."!")
self:say(spell.name)
end

-- set pet uid
function Pet:setit(uid)
self.it = uid
end

-- get player pet position
function Pet:position()
return getCreaturePosition(self.it)
end

-- move player pet to a direction
function Pet:move(direction)
local toPosition = getPosByDir(self:position(), direction, 1)

if getCreatureStorage(getCreatureMaster(self.it), PET_EXHAUST) > os.clock() then
doSendMagicEffect(self:position(), CONST_ME_POFF)
doPlayerSendCancel(cid, "Your pet is exhausted.")
return
end

if queryTileAddThing(self.it, toPosition) == RETURNVALUE_NOERROR then
doMoveCreature(self.it, direction)
doCreatureSetStorage(cid, PET_EXHAUST, os.clock() + 0.5)
doCreatureSay(cid, "Move, ".. getCreatureName(self.it) .."!")
end
end

-- save player pet attributes
function Pet:save()
local cid = getCreatureMaster(self.it)
doCreatureSetStorage(cid, PET_UID, self.it)
doCreatureSetStorage(cid, PET_SPECIE, getCreatureName(self.it))
doCreatureSetStorage(cid, PET_LEVEL, self.level)
doCreatureSetStorage(cid, PET_EXPERIENCE, self.experience)
doCreatureSetStorage(cid, PET_HEALTH, self.health)
doCreatureSetStorage(cid, PET_HEALTHMAX, self.healthmax)
doCreatureSetStorage(cid, PET_MANA, self.mana)
doCreatureSetStorage(cid, PET_MANAMAX, self.manamax)
end

-- get player pet and return instance
function get_pet(cid)
local uid, it = getCreatureStorage(cid, PET_UID)
for _, pet in ipairs(getCreatureSummons(cid)) do
if pet == uid then
it = pet
break
end
end

if not it then
return false
end

local this_pet = {
it = it,
attributes = Pets[getCreatureName(it):lower()],
level = getCreatureStorage(cid, PET_LEVEL),
experience = getCreatureStorage(cid, PET_EXPERIENCE),
health = getCreatureHealth(it),
healthmax = getCreatureMaxHealth(it),
mana = getCreatureStorage(cid, PET_MANA),
manamax = getCreatureStorage(cid, PET_MANAMAX),
}
return setmetatable(this_pet, {__index = Pet})
end

-- summon a existing player pet
function call_pet(cid)
if get_pet(cid) then
return doPlayerSendCancel(cid, "You cannot summon your pet more than one time.")
end

if getCreatureStorage(cid, PET_SPECIE) == -1 then
return doPlayerSendCancel(cid, "You don't have a pet.")
end

if getCreatureStorage(cid, PET_ALIVE) == 0 then
return doPlayerSendCancel(cid, "You need to revive your pet")
end

local pet = doCreateMonster(getCreatureStorage(cid, PET_SPECIE), getCreaturePosition(cid))
if not pet then
return false
end

if not doConvinceCreature(cid, pet) then
doRemoveCreature(pet)
return false
end

local health, healthmax = getCreatureStorage(cid, PET_HEALTH), getCreatureStorage(cid, PET_HEALTHMAX)
setCreatureMaxHealth(pet, healthmax)
doCreatureAddHealth(pet, healthmax)
doCreatureAddHealth(pet, (health - healthmax))
doCreatureSay(cid, "Go, ".. getCreatureName(pet) .."!")
doSendMagicEffect(getCreaturePosition(pet), CONST_ME_MAGIC_GREEN)
doCreatureSetStorage(cid, PET_UID, pet)

return true
end

-- is pet

function is_pet(cid)
return getCreatureMaster(cid) == 0 and false or isPlayer(getCreatureMaster(cid))
end

dofile(getDataDir() .."/lib/pet-spells.lua")

Pet_Rat = PetSpecie:new("Rat", 20, 0, 5, 5, {[1] = Rock_Throw, [2] = Dark_Bite}, "Cave Rat", 14)
Pet_Cave_Rat = PetSpecie:new("Cave Rat", 40, 20, 10, 10, {[1] = Dark_Bite}, "Munster", 32)
Pet_Munster = PetSpecie:new("Munster", 100, 50, 20, 20, {[1] = Dark_Bite}, false, false)

2. Crie um arquivo em data/lib com o nome pet-spells.lua e cole o código abaixo:


-- This script is part of Pet System
-- Copyright (C) 2013 Oneshot
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.

dofile("data/spells/lib/spells.lua")

Dark_Bite = {
name = "Dark Bite",
level = 1,
mana = 100,
type = COMBAT_PHYSICALDAMAGE,
effect = CONST_ME_BLOCKHIT,
shooteffect = CONST_ANI_SMALLSTONE,
target = true,
range = 1,
min = 300,
max = 500,
area = 0,
exhaust = 1000,
}

Rock_Throw = {
name = "Rock Throw",
level = 1,
mana = 10,
type = COMBAT_PHYSICALDAMAGE,
effect = CONST_ME_BLOCKHIT,
shooteffect = CONST_ANI_NONE,
target = true,
range = 1,
min = 20,
max = 25,
area = 0,
exhaust = 1000,
}

3. Crie um arquivo em data/talkactions/scripts, chamado pet-talkactions.lua e cole o conteúdo abaixo:


-- This script is part of Pet System
-- Copyright (C) 2013 Oneshot
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.

function onSay(cid, words, param, channel)
param = string.explode(param, ":")

if param[1]:lower() == "go" then
if getTilePzInfo(getCreaturePosition(cid)) then
return doPlayerSendCancel(cid, "You cannot call your pet at protection zone.")
end

local pet = get_pet(cid)
if pet then
return doPlayerSendCancel(cid, "You cannot call your pet two times.")
end

call_pet(cid)
return true
elseif param[1]:lower() == "back" then
local pet = get_pet(cid)
if not pet then
return doPlayerSendCancel(cid, "Please call your pet first.")
end

pet:back()
return true
elseif param[1]:lower() == "release" then
local pet = get_pet(cid)
if not pet then
return doPlayerSendCancel(cid, "Please call your pet first.")
end

pet:release()
return true
elseif param[1]:lower() == "cast" then
local pet = get_pet(cid)
if not pet then
return doPlayerSendCancel(cid, "Please call your pet first.")
end

local index = tonumber(param[2]) or 1
pet:cast(index)
return true
elseif param[1]:lower() == "say" then
local pet = get_pet(cid)
if not pet then
return doPlayerSendCancel(cid, "Please call your pet first.")
end

pet:say(param[2])
return true
elseif param[1]:lower() == "move" then
local pet = get_pet(cid)
if not pet then
return doPlayerSendCancel(cid, "Please call your pet first.")
end

if not isInArray({"north", "south", "east", "west"}, param[2]:lower()) then
return doPlayerSendCancel(cid, "Invalid direction.")
end

pet:move((_G[param[2]:upper()] or NORTH))
return true
elseif param[1]:lower() == "addexp" then
local pet = get_pet(cid)
if not pet then
return doPlayerSendCancel(cid, "Please call your pet first.")
end

if getPlayerGroupId(cid) < 3 then
return doPlayerSendCancel(cid, "You cannot use this command.")
end

pet:addexperience(tonumber(param[2]) or 0)
return true
end
return true
end

4. No talkactions.xml

<talkaction words="/pet" event="script" value="pet-talkactions.lua"/>

5. Crie um arquivo em data/creaturescripts/scripts com o nome pet-creaturescripts.lua e adicione o conteúdo abaixo:


-- This script is part of Pet System
-- Copyright (C) 2013 Oneshot
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.

function onKill(cid, target, lastHit)
local pet = get_pet(cid)

if not isMonster(target) or getMonsterInfo(getCreatureName(target)) and getMonsterInfo(getCreatureName(target)).experience == 0 then
return true
end

if not pet then
return true
end

pet:addexperience(getMonsterInfo(getCreatureName(target)).experience)
return true
end

function onDeath(cid, corpse, deathList)
if not is_pet(cid) then
return true
end

local master = getCreatureMaster(cid)
doPlayerSendTextMessage(master, MESSAGE_EVENT_ADVANCE, "Your pet is dead.")
doCreatureSetStorage(master, PET_ALIVE, 0)
doCreatureSetStorage(master, PET_HEALTH, getCreatureMaxHealth(cid))
return true
end

6. No arquivo login.lua de data/creaturescripts/scripts, adicione:

registerCreatureEvent(cid, "PetKill")

7. No arquivo creaturescripts.xml, adicione:


<event type="kill" name="PetKill" event="script" value="pet-creaturescripts.lua"/>
<event type="death" name="PetDeath" event="script" value="pet-creaturescripts.lua"/>

8. Em cada arquivo XML de cada monstro que servirá como pet, adicione:


<script>
<event name="PetDeath"/>
</script>

9. Mude o flag convinceable de cada monstro que será um tipo de pet.

<flag convinceable="1"/>

10. Crie um arquivo chamado pet trainer.lua em data/npc/scripts, adicione:


local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)
local talkState = {}
local petState = {}

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

local PetPrices = {
["rat"] = {1000, 200},
}

function creatureSayCallback(cid, type, msg)
if(not npcHandler:isFocused(cid)) then
return false
end

local talkUser = NPCHANDLER_CONVBEHAVIOR == CONVERSATION_PRIVATE and 0 or cid

if msgcontains(msg, "sell") then
local say = "I can offer you these pet species: "
for pet_name, k in pairs(PetPrices) do
local first = true
if Pets[pet_name] then
say = say .. (first == true and "" or ", ") .."{".. pet_name .. "}"
first = false
end
end
selfSay(say, cid)
talkState[talkUser] = 1
elseif msgcontains(msg, "revive") then
if getCreatureStorage(cid, PET_SPECIE) == -1 then
selfSay("You don't have a pet", cid)
return true
end

if getCreatureStorage(cid, PET_ALIVE) == 0 then
if doPlayerRemoveMoney(cid, PetPrices[getCreatureStorage(cid, PET_SPECIE):lower()][2]) then
selfSay("Your pet is now alive.", cid)
doCreatureSetStorage(cid, PET_ALIVE, 1)
else
selfSay("Sorry, you need ".. PetPrices[getCreatureStorage(cid, PET_SPECIE)][2] .." gold.", cid)
end
else
selfSay("Sorry, your pet is alive.", cid)
end
elseif talkState[talkUser] == 1 then
if PetPrices[msg] then
selfSay("A good choice, so do you want to buy a ".. msg .." pet? It will cost ".. PetPrices[msg][1] .." gold.", cid)
talkState[talkUser] = 2
petState[talkUser] = msg
else
selfSay("Sorry, I don't know this pet specie", cid)
end
elseif talkState[talkUser] == 2 then
if msgcontains(msg, "yes") then
if get_pet(cid) or getCreatureStorage(cid, PET_SPECIE) ~= -1 then
selfSay("Sorry, you already have a pet.", cid)
return true
end

local pet = petState[talkUser]
if getPlayerMoney(cid) < PetPrices[pet][1] then
selfSay("Sorry, you don't have enough money", cid)
return true
end

selfSay("This is your new pet, take care of it.", cid)
Pets[pet]:create():hatch(cid)
elseif msgcontains(msg, "no") then
selfSay("Then not.", cid)
talkState[talkUser] = 0
end
end
return true
end

npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())

11. Crie um arquivo chamado Pet Trainer.xml em data/npc, adicione:


<?xml version="1.0" encoding="UTF-8"?>
<npc name="Pet Trainer" script="pet trainer.lua" walkinterval="0" floorchange="0">
<health now="100" max="100"/>
<look type="128" head="17" body="54" legs="114" feet="0" addons="2"/>
<parameters>
<parameter key="message_greet" value="Hello |PLAYERNAME|, I {sell} and {revive} pets."/>
</parameters>
</npc>

Configuração

O Pet System OOP é todo orientado a objetos. Para criar novas raças de pet é muito, mas muito simples mesmo. Basta uma linha:

PetSpecie:new("Rat", 20, 0, 5, 5, {[1] = Rock_Throw, [2] = Dark_Bite}, "Cave Rat", 14)

Como segue o modelo abaixo:

PetSpecie:new(NOME_DO_MONSTRO, HP_INICIAL, MP_INICIAL, HP_POR_LEVEL, MP_POR_LEVEL, {[1] = MAGIA_1, [2] = MAGIA_2, [3] = MAGIA_3, ...}, NOME_DA_EVOLUÇÃO, LEVEL_DA_EVOLUÇÃO)

Caso você não queira que o pet evolua, coloque os dois parâmetros como false.

E para criar novas magias, é só seguir o mesmo modelo das duas magias padrão dentro de pet-spells.lua.

Demonstração


Este sistema está no Github sob a licença Gnu GPL v3.

Você pode baixar os scripts aqui.

Abraços.

Editado por CyberBot
Link para o comentário
Compartilhar em outros sites

E incrível o sistema

Você manipula a criatura de um jeito espetacular salvando a criatura com o pet:setit

A única coisa chata seria as storages.

 

 

Mais ta incrível

Parabéns.

Link para o comentário
Compartilhar em outros sites

E incrível o sistema

Você manipula a criatura de um jeito espetacular salvando a criatura com o pet:setit

A única coisa chata seria as storages.

 

 

Mais ta incrível

Parabéns.

 

Então, cara, eu até fiz enquanto na fase de desenvolvimento por querys na database. O problema é que se toda hora eu tenho que salvar o pet na database e obter dados dela, acabei notando o pequeno lag que se criava na execução dos comandos, aí fiz por storage.

 

Obrigado a todos.

Link para o comentário
Compartilhar em outros sites

Perfeito, simples e muito funcional!

Pode até abrir novas possibilidades para o mundo Poketibiano!

Vou ver o que já consigo fazer com isso aê !

 

Parabens One!

Já levou meu REP+

Editado por DoGoZ
Link para o comentário
Compartilhar em outros sites

Bankayo, certifique se ter instalado o npc corretamente.

 

O pet trainer.lua em data/npc/scripts e o Pet Trainer.xml em data/npc.

 

Lembrando que para colocar o npc no mapa é através do remere's é necessário importa-lo para aparecer na lista de npcs, para importar faça o seguinte,

 

File > Import > Import Monsters/NPC, e escolha o arquivo Pet Trainer.xml(que deverá estar na pasta do seu servidor).

 

npc.png

 

Depois vá em Pallete > Creature Pallete > NPC

Escolha o Pet Trainer e coloque em um local desejado no mapa.

Editado por DoGoZ
Link para o comentário
Compartilhar em outros sites

Está sim, tudo de acordo com o que você explicou no tutorial.

 

Criei o respawn pelo Remere's e coloquei o NPC.

Reiniciei o server, mas o NPC não apareceu no lugar devido.

 

A versão do OT é 8.6.

Link para o comentário
Compartilhar em outros sites

Aparece algum erro no console?

 

@EDIT

 

Bankayo a solução é simples, ali na postagem antes do tag do xml tem um uma linha vazia,

É só excluir ela, deixar apenas o script, testado aqui!

Editado por DoGoZ
Link para o comentário
Compartilhar em outros sites

Visitante
Este tópico está impedido de receber novos posts.
×
×
  • Criar Novo...