• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

TFS 1.X+ Exiva "NPC

darcioantonio

www.adventurerpg.com.br
Joined
Jul 30, 2013
Messages
165
Solutions
1
Reaction score
4
Location
Brasil
Twitch
darcio_
YouTube
UCEXCOEw_dYchojHNz
Hello everyone, good evening. I used to have a TFS 0.4 server and had a talkaction "!exiva" for NPCs. However, I'm currently migrating the server to version 10.98 TFS 1.4, and I would like to know if it's possible to adapt the "exiva" spell to use for NPCs. I used this talkaction in version 0.4.

Lua:
<talkaction words="!EXIVA" event="script" value="find_npc.lua"/>

local config =
{
  cost = 0
}

function onSay(cid, words, param, channel)
  if(param == "" or param == nil) then
    return false
  end

  if doPlayerRemoveMoney(cid, config.cost) == FALSE then
    doPlayerSendCancel(cid, "Você não tem dinheiro.")
    doSendMagicEffect(getCreaturePosition(cid), CONST_ME_POFF)
    return true
  end

  local getNpc = getCreatureByName(param)
  if isNpc(getNpc) == TRUE then

    local playerPos, npcPos = getCreaturePosition(cid), getCreaturePosition(getNpc)
    local px, py = 0, 0
    local pS = ""
    local text = ""

    if(playerPos.x == npcPos.x) and (playerPos.y < npcPos.y) then
      px = 1
      py = npcPos.y - playerPos.y
      pS = "sul"
    elseif(playerPos.x == npcPos.x) and (playerPos.y > npcPos.y) then
      px = 1
      py = playerPos.y - npcPos.y
      pS = "norte"
    elseif(playerPos.x < npcPos.x) and (playerPos.y == npcPos.y) then
      px = npcPos.x - playerPos.x
      py = 1
      pS = "direita"
    elseif(playerPos.x > npcPos.x) and (playerPos.y == npcPos.y) then
      px = playerPos.x - npcPos.x
      py = 1
      pS = "esquerda"
    elseif(playerPos.x > npcPos.x) and (playerPos.y > npcPos.y) then
      px = playerPos.x - npcPos.x
      py = playerPos.y - npcPos.y
      pS = "norte-esquerda"
    elseif(playerPos.x > npcPos.x) and (playerPos.y < npcPos.y) then
      px = playerPos.x - npcPos.x
      py = npcPos.y - playerPos.y
      pS = "sul-esquerda"
    elseif(playerPos.x < npcPos.x) and (playerPos.y < npcPos.y) then
      px = npcPos.x - playerPos.x
      py = npcPos.y - playerPos.y
      pS = "sul-direita"
    elseif(playerPos.x < npcPos.x) and (playerPos.y > npcPos.y) then
      px = npcPos.x - playerPos.x
      ps = playerPos.y - npcPos.y
      pS = "norte-direita"
    end

    if(px <= 4 and py <= 4) then
      text = "" .. getCreatureName(getNpc) .. " esta ao seu lado."
    elseif((px > 4 and px <= 100) and (py > 4 and py <= 100)) or ((px > 4 and px <= 100) and (py <= 4)) or ((px <= 4) and (py > 4 and py <= 100)) then
      text = "" .. getCreatureName(getNpc) .. " esta a " .. pS .. "."
    elseif((px > 100 and px <= 274) and (py > 100 and py <= 274)) or ((px > 100 and px <= 274) and (py <= 100)) or ((px <= 100) and (py > 100 and py <= 274)) then
      text = "" .. getCreatureName(getNpc) .. " esta muito longe para " .. pS .. "."
    elseif((px > 274 and px <= 280) and (py > 274 and py <= 280)) or ((px > 274 and px <= 280) and (py < 274)) or ((px < 274) and (py > 274 and py <= 280)) then
      text = "" .. getCreatureName(getNpc) .. " esta muito longe para " .. pS .. "."
    elseif(px > 280 and py > 280) or (px > 280 and py < 280) or (px < 280 and py > 280) then
      text = "" .. getCreatureName(getNpc) .. " para o " .. pS .. "."
    end

    doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, text)
    doSendMagicEffect(getCreaturePosition(cid), CONST_ME_MAGIC_GREEN)
    return false
  else
    doPlayerSendCancel(cid, "O NPC não existe.")
    doSendMagicEffect(getCreaturePosition(cid), CONST_ME_POFF)
    return true
  end
end
 
All code you need is currently in TFS:

Just combine this with talkaction:
Lua:
local talk = TalkAction("/exiva", "!exiva")

local LEVEL_LOWER = 1
local LEVEL_SAME = 2
local LEVEL_HIGHER = 3

local DISTANCE_BESIDE = 1
local DISTANCE_CLOSE = 2
local DISTANCE_FAR = 3
local DISTANCE_VERYFAR = 4

local directions = {
    [DIRECTION_NORTH] = "north",
    [DIRECTION_SOUTH] = "south",
    [DIRECTION_EAST] = "east",
    [DIRECTION_WEST] = "west",
    [DIRECTION_NORTHEAST] = "north-east",
    [DIRECTION_NORTHWEST] = "north-west",
    [DIRECTION_SOUTHEAST] = "south-east",
    [DIRECTION_SOUTHWEST] = "south-west"
}

local descriptions = {
    [DISTANCE_BESIDE] = {
        [LEVEL_LOWER] = "is below you",
        [LEVEL_SAME] = "is standing next to you",
        [LEVEL_HIGHER] = "is above you"
    },
    [DISTANCE_CLOSE] = {
        [LEVEL_LOWER] = "is on a lower level to the",
        [LEVEL_SAME] = "is to the",
        [LEVEL_HIGHER] = "is on a higher level to the"
    },
    [DISTANCE_FAR] = "is far to the",
    [DISTANCE_VERYFAR] = "is very far to the"
}

function talk.onSay(player, words, param)
    local npcName = param
    local playerPosition = player:getPosition()
    local target = Npc(npcName)
    if not target then
        player:sendCancelMessage(RETURNVALUE_CREATUREDOESNOTEXIST)
        playerPosition:sendMagicEffect(CONST_ME_POFF)
        return false
    end

    local targetPosition = target:getPosition()
    local positionDifference = {
        x = playerPosition.x - targetPosition.x,
        y = playerPosition.y - targetPosition.y,
        z = playerPosition.z - targetPosition.z
    }

    local maxPositionDifference, direction = math.max(math.abs(positionDifference.x), math.abs(positionDifference.y))
    if maxPositionDifference >= 5 then
        local positionTangent = positionDifference.x ~= 0 and positionDifference.y / positionDifference.x or 10
        if math.abs(positionTangent) < 0.4142 then
            direction = positionDifference.x > 0 and DIRECTION_WEST or DIRECTION_EAST
        elseif math.abs(positionTangent) < 2.4142 then
            direction = positionTangent > 0 and (positionDifference.y > 0 and DIRECTION_NORTHWEST or DIRECTION_SOUTHEAST) or positionDifference.x > 0 and DIRECTION_SOUTHWEST or DIRECTION_NORTHEAST
        else
            direction = positionDifference.y > 0 and DIRECTION_NORTH or DIRECTION_SOUTH
        end
    end

    local level = positionDifference.z > 0 and LEVEL_HIGHER or positionDifference.z < 0 and LEVEL_LOWER or LEVEL_SAME
    local distance = maxPositionDifference < 5 and DISTANCE_BESIDE or maxPositionDifference < 101 and DISTANCE_CLOSE or maxPositionDifference < 275 and DISTANCE_FAR or DISTANCE_VERYFAR
    local description = descriptions[distance][level] or descriptions[distance]

    if distance ~= DISTANCE_BESIDE then
        description = description .. " " .. directions[direction]
    end

    player:sendTextMessage(MESSAGE_INFO_DESCR, target:getName() .. " " .. description .. ".")
    playerPosition:sendMagicEffect(CONST_ME_MAGIC_BLUE)

    return false
end

talk:separator(" ")
talk:register()

But as there's a lot of common logic there I'd suggest to define these constants globally somewhere so you have single source of truth for that (not to duplicate the code). Or even create some util methods not to write same logic twice.
 
Back
Top