Ir para conteúdo

Npc Criando Novos Monstros


Posts Recomendados

Faaaala galera! Tudo bom? Desde ontem eu estou tentando fazer npc, foi bem chatinho de corrigir os bugs e etc. Enfim, o importante é que ele está pronto, e pelo que eu testei, não há nenhum bug comprometedor.

 

Como funciona: Como é um npc, eu vou mostrar como pode ser a conversa:

 

Jogador: Info

Npc: Eu posso criar seu monstro, apenas diga criar e siga as instruções. Diga reset para recomeçar.

 

Jogador: Criar

Npc: Diga o nome do seu monstro. Lembre-se, é melhor ter tantos gps com você.

 

Jogador [Nome do Monstro]

Npc: O nome está correto, agora seleciona a raça para o seu monstro. A raça é o que vai definir os ataques e a aparencia do seu monstro, escolha entre: venom, undead, blood e fire.

 

Jogador: [Venom ou Undead ou Blood ou Fire]

Npc: A raça do seu monstro foi escolhida como [Raça escolhida], agora escolha a aparencia do seu monstro.

Npc: A lista de aparencias é esta: [Lista de aparências para raça escolhida].

 

Jogador: [Nome do monstro da aparência]

Npc: A aparencia do seu monstro foi escolhida, agora diga até 3 voses para seu monstro e para finalizar, diga fim.

 

Jogador: [Voz]

Npc: [Nada]

 

Jogador: fim

Npc: Parabéns! Seu monstro foi criado. Em breve ele poderá ser usado.

 

Jogador: reset

Npc: O sistema foi resetado para você.

 

Feito, entenderam? Vamos ao npc...

 

 

NPC

 

 

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

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 race = {
['venom'] = {['attacks'] = {1, 2}, ['looktype'] = {['slime'] = '<look type="19" head="20" body="30" legs="40" feet="50" corpse="1496"/>'}},
['undead'] = {['attacks'] = {3, 4}, ['looktype'] = {['undead dragon'] = '<look type="231" corpse="6306"/>'}},
['fire'] = {['attacks'] = {5, 6}, ['looktype'] = {['demon'] = '<look type="35" corpse="5995"/>'}},
['blood'] = {['attacks'] = {7, 8}, ['looktype'] = {['vampire'] = '<look type="68" head="20" body="30" legs="40" feet="50" corpse="6006"/>'}}
}
local cost = 1000 -- custo para criar o monstro
local one = FALSE -- um monstro por jogador? TRUE para sim e FALSE para não

if talkState[talkUser] == nil and msg == "info" then
selfSay("Eu posso criar seu monstro, apenas diga criar e siga as instruções. Diga reset para recomeçar.", cid)
elseif talkState[talkUser] == nil and msg == "criar" then
if getPlayerStorageValue(cid, 40000) == 1 and one == TRUE then
selfSay("Você já criou seu monstro, não pode criar outro.", cid)
else
selfSay("Diga o nome do seu monstro. Lembre-se, é melhor ter " .. cost .. " gps com você.", cid)
talkState[talkUser] = 0
return TRUE
end
elseif msg == "reset" then
table.remove(info, table.find(info, cid))
selfSay("O sistema foi resetado para você.", cid)
talkState[talkUser] = nil
return TRUE
end

if talkState[talkUser] == 0 then
if isValid(msg) then
if monsterExist(msg) == FALSE then 
info["'" .. cid .. "'"] = {}
table.insert(info["'" .. cid .. "'"], msg)
talkState[talkUser] = 1
selfSay("O nome está correto, agora seleciona a raça para o seu monstro. A raça é o que vai definir os ataques e a aparencia do seu monstro, escolha entre: venom, undead, blood e fire.", cid)
else
selfSay("Desculpe, este monstro já existe.", cid)
end
else
selfSay("Nome invalido.", cid)
end
elseif talkState[talkUser] == 1 then
if race[msg] then
table.insert(info["'" .. cid .. "'"], msg)
talkState[talkUser] = 2
selfSay("A raça do seu monstro foi escolhida como " .. msg .. ", agora escolha a aparencia do seu monstro.", cid)
selfSay("A lista de aparencias é esta: " .. getoutfit(race[info["'" .. cid .. "'"][2]]['looktype']) .. ".", cid) 
else
selfSay("Esta raça não pode ser escolhida.", cid)
end
elseif talkState[talkUser] == 2 then
if race[info["'" .. cid .. "'"][2]]['looktype'][msg] then 
talkState[talkUser] = 3
table.insert(info["'" .. cid .. "'"], race[info["'" .. cid .. "'"][2]]['looktype'][msg])
selfSay("A aparencia do seu monstro foi escolhida, agora diga até 3 voses para seu monstro e para finalizar, diga fim.", cid)
else
selfSay("Este outfit não pode ser escolhido.")
end
elseif talkState[talkUser] == 3 and msg ~= "fim" then
if #info["'" .. cid .. "'"] == 3 or #info["'" .. cid .. "'"][4] < 3 then
if #info["'" .. cid .. "'"] == 3 then
info["'" .. cid .. "'"][4] = {}
end
table.insert(info["'" .. cid .. "'"][4], msg)
else
selfSay("Você já alcançou o máximo de voses.", cid)
end
elseif talkState[talkUser] == 3 and msg == "fim" then
if doPlayerRemoveMoney(cid, cost) then
table.insert(info["'" .. cid .. "'"], race[info["'" .. cid .. "'"][2]]['attacks'])
doCreateMonsterIn(info["'" .. cid .. "'"])                
talkState[talkUser] = nil
setPlayerStorageValue(cid, 40000, 1)
selfSay("Parabéns! Seu monstro foi criado. Em breve ele poderá ser usado.", cid)
table.remove(info, table.find(info, cid))
else
selfSay("Desculpe, você não tem dinheiro.", cid)
end
end

return true
end

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

function monsterExist(s)

local info = io.open("data/monster/monsters.xml", "r")
local re = info:read("*all")

if string.find(string.lower(re), "'" .. string.lower(s) .. "'") or string.find(string.lower(re), '"' .. string.lower(s) .. '"') then
return TRUE
end

return FALSE
end

function doCreateMonsterIn(tab)

local attacks = {
[1] = '<attack name="melee" interval="2000" skill="30" attack="35"/>',
[2] = '<attack name="earth" interval="1000" chance="14" range="4" target="1" min="-100" max="-200">             <attribute key="areaEffect" value="plantattack"/>       </attack>',
[3] = '<attack name="melee" interval="2000" min="-0" max="-185"/>',
[4] = '<attack name="lifedrain" interval="1000" chance="14" radius="4" target="0" min="-50" max="-225">      <attribute key="areaEffect" value="smallclouds"/>  </attack>',
[5] = '<attack name="melee" interval="2000" skill="30" attack="35"/>',
[6] = '<attack name="fire" interval="1000" chance="11" range="7" radius="4" target="1" min="-150" max="-175">      <attribute key="shootEffect" value="fire"/>      <attribute key="areaEffect" value="firearea"/>    </attack>',
[7] = '<attack name="melee" interval="2000" min="-50" max="-150"/>',
[8] = '<attack name="energy" interval="1000" chance="14" range="7" min="-65" max="-175">      <attribute key="shootEffect" value="energy"/>    </attack>'
}

local info = io.open("data/lib/model.txt", "r")
local re = info:read("*all")
local arquive = io.open("data/monster/" .. tab[1] .. ".xml", "w+")
arquive:write(re)
arquive:close()

local arq = io.open("data/monster/" .. tab[1] .. ".xml", "r")
local ri = arq:read("*all")
local sub = string.gsub(ri, "-- NAME", tab[1])
local sub2 = string.gsub(sub, "-- RACE", tab[2])
local sub3 = string.gsub(sub2, "-- LOOK", tab[3])
local sub4, sub5 = nil, nil

if #tab == 5 then
for n, voice in pairs(tab[4]) do
sub4 = sub4 and string.gsub(sub4, "-- VOICE" .. n, '<voice sentence="' .. voice .. '"/>') or string.gsub(sub3, "-- VOICE1", '<voice sentence="' .. voice .. '"/>')
end
end

local fo = #tab == 5 and tab[5] or tab[4]
sub4 = sub4 or sub3

for n, atid in pairs(fo) do
sub5 = sub5 and string.gsub(sub5, "-- ATTACK" .. n, attacks[atid]) or string.gsub(sub4, "-- ATTACK1", attacks[atid])
end

sub5 = sub5 or sub4

local file = io.open("data/monster/monsters.xml", "r")
local re = file:read("*all")
local new = io.open("data/monster/monsters.xml", "w+")
local su, sub2 = string.gsub(re, '-- XML', '<monster name="' .. tab[1] .. '" file="' .. tab[1] .. '.xml"/>\n-- XML')

new:write(su)
local arquive = io.open("data/monster/" .. tab[1] .. ".xml", "w+")
arquive:write(sub5)
arquive:close()
addEvent(doReloadInfo, 180 * 1000, RELOAD_MONSTERS)


end 

function getoutfit(tab)

local s = nil

for opt, _ in pairs(tab) do
s = s and s .. ", " .. opt or opt
end

return s
end

function isValid(msg)

if #msg < 3 or #msg > 10 then
return nil
end

for i = 1, #msg do
if not(string.match(msg, "%a", i)) or (string.match(msg, "%a", i) ~= string.sub(msg, i, i) and string.match(msg, "%s", i) ~= string.sub(msg, i, i)) then
return nil
end
end

return TRUE
end

 

 

Feito isso, vá em data/lib, crie um arquivo chamado model.txt.

 

 

Lib

 

 

<?xml version="1.0" encoding="UTF-8"?>
<monster name="-- NAME" nameDescription="a -- NAME" race="-- RACE" experience="0" speed="225" manacost="0">
 <health now="3000" max="3000"/>
-- LOOK
 <targetchange interval="5000" chance="0"/>
 <strategy attack="90" defense="10"/>
 <flags>
   <flag summonable="0"/>
   <flag attackable="1"/>
   <flag hostile="0"/>
   <flag illusionable="0"/>
   <flag convinceable="0"/>
   <flag pushable="0"/>
   <flag canpushitems="0"/>
   <flag canpushcreatures="0"/>
   <flag targetdistance="1"/>
   <flag staticattack="90"/>
   <flag runonhealth="0"/>
 </flags>
 <attacks>
-- ATTACK1
-- ATTACK2
 </attacks>
<defenses armor="30" defense="35"/>
 <voices interval="10000" chance="10">
-- VOICE1
-- VOICE2
-- VOICE3
 </voices>
 <loot>
</loot>
</monster>

 

 

Por ultimo vá em data/monster, abra o arquivo monsters.xml e abaixo de <monsters> cole isto:

 

-- XML

 

Feito, o npc está instalado.

 

O npc vai criar um novo monstro no otserv, todas as raças estão balanceadas. Depois de 3 minutos ele irá executar o reload para os monstros e o novo monstro estará disponível.

 

Eu aconselho que apenas os mais experientes mudem o script, mas eu vou ensinar como adicionar mais looktypes para cada raça.

 

Vá nesta tabela:

 

local race = {
['venom'] = {['attacks'] = {1, 2}, ['looktype'] = {['slime'] = '<look type="19" head="20" body="30" legs="40" feet="50" corpse="1496"/>'}},
['undead'] = {['attacks'] = {3, 4}, ['looktype'] = {['undead dragon'] = '<look type="231" corpse="6306"/>'}},
['fire'] = {['attacks'] = {5, 6}, ['looktype'] = {['demon'] = '<look type="35" corpse="5995"/>'}},
['blood'] = {['attacks'] = {7, 8}, ['looktype'] = {['vampire'] = '<look type="68" head="20" body="30" legs="40" feet="50" corpse="6006"/>'}}
}

 

Observe esta parte:

 

{['slime'] = '<look type="19" head="20" body="30" legs="40" feet="50" corpse="1496"/>'}

 

Agora, observe como poderia ser adicionada:

 

{['slime'] = '<look type="19" head="20" body="30" legs="40" feet="50" corpse="1496"/>', ['wasp'] = '<look type="44" head="20" body="30" legs="40" feet="50" corpse="5989"/>'}

 

E assim você pode adicionar quantas mais desejar.

 

 

Video

 

 

http://www.youtube.com/watch?v=Bmg37YQLJ00

 

 

--

 

Espero que gostem do npc, demorei bastante para fazer. Abraços. Se houver algum bug, por favor avisem.

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

Não, não tem nada a ver com pet. É um npc que cria um monstro de acordo com as informações que o jogador da pra ele.

 

Ele realmente cria um monstro, não é sumonar, mas sim criar um novo monstro no seu Ot Server.

 

Algumas ideias:

 

-- Concurso de melhor monstro.

-- Fazer um pet com base no npc.

 

Abraço.

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

A ideia de concurso para melhor monstro no otserve, foi a 1° que pensei, e os premios podem ser em crystal coins (kk), ou em itens, caso seu otserve tenha algum set vip

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

@ Demonbholder

 

Sempre Você Inovando, Criando, e Querendo Ajudar Cada Vez Mas.

 

Não sei De Onde Sai Tanta Idéias Loucas Que Dão Certo.

 

Deve Ter Demorado Pra Fazer Em.

 

Continue Trazendo Mas Coisas Para Nós :D

Link para o comentário
Compartilhar em outros sites

Recebi algumas mensagens apontando falhas quanto ao reload. Nesta linha do script:

 

addEvent(doReloadInfo, 180 * 1000, RELOAD_MONSTERS)

 

Aqui eu coloquei para executar o reload 180 segundos, ou 3 minutos depois. Caso o seu processador não seja muito bom, é aconselhável colocar mais, ou remover está linha e executar o reload manualmente.

 

Abraços.

Link para o comentário
Compartilhar em outros sites

  • 1 month later...
×
×
  • Criar Novo...