Ir para conteúdo

NPC Mirror


iunix

Posts Recomendados

Olá, venho aqui para trazer um sistema que eu e o Skyen fizemos.

 

 

Explicações;

divisor.png

É um NPC que se move exatamente como você, onde você tem que "leva-lo" para um certo SQM, assim abrindo a passagem escondida.

 

b7kB7.png

 

 

 

Mapa

divisor.png

 

Terá que criar uma sala com 7x7 SQMs, com os seguintes obstáculos:



 

 

1-2g95.png

 

 


Amarelo = NPC
Verde = Onde irá nascer a escada
Azul = Pressure Plates
Rosa = Statua que brilha (So gaaaay)
Vermelho = Pedras ou qualquer coisa que você vá usar de obstaculo.
Azul = Parede
Branco = Passagem Livre.

 

 

 

Código e instalação

divisor.png

Código miragem.lua:

 

local pos_start  = {x = 447, y = 552, z = 7} -- pos do NPC
local pos_stairs = {x = 448, y = 555, z = 7, stackpos=0} -- Pos da escada
local pos_plate1 = {x = 445, y = 553, z = 7} -- Pos da 1º plate
local pos_plate2 = {x = 448, y = 556, z = 7} -- Pos da 2º plate
local pos_device = {x = 447, y = 555, z = 7} -- Pos da Statua que brilha
local area_start = {x = 444, y = 552, z = 7} -- Pos do canto esquerdo superior da sala
local area_final = {x = 450, y = 558, z = 7} -- Pos do Canto Direito inferior da sala
local id_stairs  = 4836 -- Id da Escada
local id_floor   = 4413 -- Id do chão que vai ser colocado no lugar da escada

local target = 0
local stairs = false
local ignore = false
local outfit = {
       lookType = 0,
       lookHead = 0,
       lookBody = 0,
       lookLegs = 0,
       lookFeet = 0,
}

local function get_player_in_area(start, final)
       for x = start.x, final.x do
               for y = start.y, final.y do
                       for z = start.z, final.z do
                               local pos = {x=x, y=y, z=z, stackpos=253}
                               local thing = getThingFromPos(pos, false)

                               if isPlayer(thing.uid) then
                                       return thing
                               end
                       end
               end
       end

       return {uid=0}
end

local function is_pos_in_area(pos, start, final)
       return pos.x >= start.x and pos.x <= final.x and pos.y >= start.y and pos.y <= final.y and pos.z >= start.z and pos.z <= final.z
end

local function is_player_in_area(cid, start, final)
       return is_pos_in_area(getCreaturePosition(cid), start, final)
end

local function inverse_direction(direction)
       local map = {
               [NORTH] = SOUTH,
               [sOUTH] = NORTH,
               [EAST] = WEST,
               [WEST] = EAST,
               [NORTHEAST] = SOUTHWEST,
               [sOUTHEAST] = NORTHWEST,
               [NORTHWEST] = SOUTHEAST,
               [sOUTHWEST] = NORTHEAST,
       }

       return map[direction] or NORTH
end

local function compare_pos(pos1, pos2)
       return pos1.x == pos2.x and pos1.y == pos2.y and pos1.z == pos2.z
end

local function turn_stairs(open)
       if stairs == open then
               return true
       end

       local thing = getThingFromPos(pos_stairs, false)

       if thing.uid > 0 then
               if open then
                       doTransformItem(thing.uid, id_stairs)
               else
                       doTransformItem(thing.uid, id_floor)
               end
       end

       doSendMagicEffect(pos_stairs, CONST_ME_POFF)

       stairs = open

       return true
end

function onCreatureMove(cid, oldPos, newPos)
       if ignore or cid == getNpcId() then
               ignore = false
               return true
       end

--[[ if (isPlayer(cid) and isWatchingTv(cid)) or isMonster(cid) then
	return true
end
       ]]--
       if not isPlayer(cid) then
               ignore = true
	doTeleportThing(cid, oldPos)
               return true
       end

       if not is_pos_in_area(oldPos, area_start, area_final) and is_pos_in_area(newPos, area_start, area_final) then

               if target == 0 then
                       target = cid
                       doChangeSpeed(getNpcId(), getCreatureSpeed(target) - getCreatureSpeed(getNpcId()))
                       doSetCreatureOutfit(getNpcId(), getCreatureOutfit(target), -1)
                       doSendMagicEffect(pos_device, CONST_ME_MAGIC_BLUE)
               else
                       ignore = true
                       doTeleportThing(cid, oldPos)
                       doSendMagicEffect(getCreaturePosition(cid), CONST_ME_POFF)
               end
       elseif is_pos_in_area(oldPos, area_start, area_final) and not is_pos_in_area(newPos, area_start, area_final) then
               target = 0
               doChangeSpeed(getNpcId(), -getCreatureSpeed(getNpcId()))
               doSetCreatureOutfit(getNpcId(), outfit, -1)
               doTeleportThing(getNpcId(), pos_start)
               doSendMagicEffect(pos_device, CONST_ME_MAGIC_BLUE)
               turn_stairs(false)
       elseif is_pos_in_area(oldPos, area_start, area_final) and is_pos_in_area(newPos, area_start, area_final) then
               selfMove(inverse_direction(getDirectionTo(oldPos, newPos)))
       end

       return true
end

function onThink()
       if target == 0 then
               return true
       end
if get_player_in_area (area_start, area_final).uid == 0 then
	target = 0
	doChangeSpeed(getNpcId(), -getCreatureSpeed(getNpcId()))
	doSetCreatureOutfit(getNpcId(), outfit, -1)
	doTeleportThing(getNpcId(), pos_start)
	doSendMagicEffect(pos_device, CONST_ME_MAGIC_BLUE)
	turn_stairs(false)
	return true
end
       selfTurn(inverse_direction(getCreatureLookDirection(target)))
       if (compare_pos(getCreaturePosition(getNpcId()), pos_plate1) and compare_pos(getCreaturePosition(target), pos_plate2))
       or (compare_pos(getCreaturePosition(getNpcId()), pos_plate2) and compare_pos(getCreaturePosition(target), pos_plate1)) then
               turn_stairs(true)
       else
               turn_stairs(false)
       end

       return true
end

 

Código Miragem.xml

 

<!--?xml version="1.0" encoding="UTF-8"?-->
<npc name="Miragem" namedescription="a miragem" script="miragem.lua" walkinterval="0" floorchange="0">
   <health now="100" max="100">
</health></npc>

 

 

 

Agradecimentos

divisor.png

 

Agradecimentos ao Skyen que deu a ideia e fez quase tudo e por ser meu grande mestre <3

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

Arrumei um bug que dava quando o player que estava resolvendo o puzzle era removido forçadamente de lá (com, por exemplo, /r):

Na onThink, troque isto:

if target == 0 then
 return true
end

 

Por isto:

if target == 0 then
 return true
end
if not isPlayer(target) then
 target = 0
 doChangeSpeed(getNpcId(), -getCreatureSpeed(getNpcId()))
 doSetCreatureOutfit(getNpcId(), outfit, -1)
 doTeleportThing(getNpcId(), pos_start)
 doSendMagicEffect(pos_device, CONST_ME_MAGIC_BLUE)
 turn_stairs(false)
 return true
end

 

Recomendo colocar a sala inteira do puzzle como no-logout zone, mas o fix acima resolve o problema do player sair do jogo no meio do puzzle.

 

Também fiz o NPC copiar o que o player fala, só que ao contrário. Quem quiser, adicione isto no final do script:

function onCreatureSay(cid, type, msg)
 if cid == target then
   selfSay(msg:reverse())
 end
end

 

Divirtam-se.

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

OMG, Skyen fazendo códigos pra OT novamente? O que tú fez iuniX? rairiaria.

 

@thread

Parabéns aos dois, muito bem bolado isso ai, xD. Curti :p. Grande Raposa :p

 

iuniX, você adicionou isso na source né?


function onCreatureMove(cid, oldPos, newPos)

Link para o comentário
Compartilhar em outros sites

OMG, Skyen fazendo códigos pra OT novamente? O que tú fez iuniX? rairiaria.

 

@thread

Parabéns aos dois, muito bem bolado isso ai, xD. Curti :p. Grande Raposa :p

 

iuniX, você adicionou isso na source né?


function onCreatureMove(cid, oldPos, newPos)

 

É padrão.

Link para o comentário
Compartilhar em outros sites

×
×
  • Criar Novo...