Lua Guard NPC - separate distance and melee attacks | error

AdiMit

c(;
Joined
May 2, 2016
Messages
70
Best answers
2
Reaction score
3
Hello :)

I'm currently using the [8.60] The Forgotten Server 0.3.6 (Crying Damson) V8 by Printer, from the thread: [8.60] The Forgotten Server 0.3.6 (Crying Damson) V8;

I was trying to redo the guard NPC(s) so that they would attack the PKers with melee attacks at the range of <=1; and with distance attacks at the range of >=2...
However, I get the following error after implementing the 'distance' part (works just fine without it).
By the way, I want the distance attacks to be carried out even if there is an obstacle on the way (for example another player who blocks the way), which seems to bug the NPC at the momoment...

The error:
Lua:
[03/08/2017 13:22:15] [Error - Npc interface]
[03/08/2017 13:22:15] data/npc/scripts/guard.lua:onThink
[03/08/2017 13:22:15] Description:
[03/08/2017 13:22:15] data/npc/scripts/guard.lua:108: attempt to call global 'sendDistanceEffect' (a nil value)
[03/08/2017 13:22:15] stack traceback:
[03/08/2017 13:22:15]     data/npc/scripts/guard.lua:108: in function <data/npc/scripts/guard.lua:70>
The script.lua:
Lua:
local target = 0
local prevTarget = 0
local maxChaseDistance = 20
local origPos = 0
local lastAttack = 0
local followTimeout = 10

local function isSkulled(cid)
    if(getCreatureSkullType(cid) >= SKULL_WHITE and isPlayerPzLocked(cid)) then
        return true
    end

    return false
end

local function goToOrigPos()
    target = 0
    lastAttack  = 0
    selfFollow(0)
    doTeleportThing(getNpcCid(), origPos)
end

local function updateTarget()
    if(not isPlayer(target)) then
        goToOrigPos()
    elseif(not isSkulled(target)) then
        selfSay("Now, behave in the future.")
        goToOrigPos()
    end

    if(target == 0) then
        local list = getSpectators(getNpcPos(), 9, 9, false)
        for i = 1, table.getn(list) do
            local _target = list[i]
            if(_target ~= 0) then
                if(isPlayer(_target) and isSkulled(_target)) then
                    if(not getTilePzInfo(getCreaturePosition(_target))) then
                        if(selfFollow(_target)) then
                            target = _target
                            if(target ~= prevTarget) then
                                selfSay("We do not tolerate people like you here!")
                            end

                            prevTarget = target
                            break
                        end
                    end
                end
            end
        end
    end
end

function onCreatureAppear(cid)
    if(cid == getNpcCid()) then
        origPos = getNpcPos()
    end
end

function onCreatureDisappear(cid)
    if(cid == target) then
        goToOrigPos()
    end
end

function onCreatureMove(creature, oldPos, newPos)
    --
end

function onThink()
    updateTarget()

    if(target == 0) then
        return
    end

    local playerPos = getCreaturePosition(target)
    local myPos = getNpcPos()

    if(myPos.z ~= playerPos.z) then
        goToOrigPos()
        return
    end

    if(math.abs(myPos.x - origPos.x) > maxChaseDistance or math.abs(myPos.y - origPos.y) > maxChaseDistance) then
        selfSay("I'll catch you next time.")
        goToOrigPos()
        return
    end

    if(lastAttack == 0) then
        lastAttack = os.clock()
    end

    if(os.clock() - lastAttack > followTimeout) then
        selfSay("You got me this time, but just wait.")
        goToOrigPos()
        return
    end

    if((math.abs(playerPos.x - myPos.x) <= 1) and (math.abs(playerPos.y - myPos.y) <= 1)) then
        doTargetCombatHealth(getNpcCid(), target, COMBAT_LIFEDRAIN, -220, -330, CONST_ME_BLOCKHIT)
        lastAttack = os.clock()
    end

    if((math.abs(playerPos.x - myPos.x) >= 2) and (math.abs(playerPos.y - myPos.y) >= 2)) then
        doTargetCombatHealth(getNpcCid(), target, COMBAT_PHYSICAL, -110, -220, CONST_ME_HITAREA)
        sendDistanceEffect(target, CONST_ANI_WHIRLWINDSWORD)
        lastAttack = os.clock()
    end
end
The NPC.xml:
Lua:
<?xml version="1.0" encoding="UTF-8"?>
<npc name="Guardsman" script="guard.lua" walkinterval="0" floorchange="0" speed="1100">
    <health now="100000" max="100000"/>
    <look type="131" head="95" body="132" legs="96" feet="116" addons="3"/>

  <interaction range="3" idletime="60">

    <interact keywords="hi" focus="1">
      <keywords>hello</keywords>

      <response text="Nothing to see here, move along.">
        <action name="idle" value="1"/>
      </response>
    </interact>

    <interact keywords="bye" focus="0">
      <keywords>farewell</keywords>

      <response text="Good bye."/>
    </interact>
  </interaction>

</npc>
Do you have any ideas how to resolve the issue?

Thanks in advance! ;)
Best regards.
 

Xikini

I whore myself out for likes
Premium User
Joined
Nov 17, 2010
Messages
4,172
Best answers
174
Reaction score
2,235
Code:
attempt to call global 'sendDistanceEffect' (a nil value)
call global -> this means it's trying to call a function or local
nil -> means it doesn't exist.

So basically, the function 'sendDistanceEffect' does not exist.
You either spelt the function incorrectly, or it truly does not exist.

The first thing I thought was "doSendDistanceEffect".. as all functions basically use do in front of them..
But after checking luascript.cpp, I realised the function is named a bit differently.

---

tl:dr -> Use the correct function.
//doSendDistanceShoot(fromPos, toPos, type[, player])
 
OP
AdiMit

AdiMit

c(;
Joined
May 2, 2016
Messages
70
Best answers
2
Reaction score
3
Code:
attempt to call global 'sendDistanceEffect' (a nil value)
call global -> this means it's trying to call a function or local
nil -> means it doesn't exist.

So basically, the function 'sendDistanceEffect' does not exist.
You either spelt the function incorrectly, or it truly does not exist.

The first thing I thought was "doSendDistanceEffect".. as all functions basically use do in front of them..
But after checking luascript.cpp, I realised the function is named a bit differently.

---

tl:dr -> Use the correct function.
//doSendDistanceShoot(fromPos, toPos, type[, player])
Now I get this error:
Lua:
[03/08/2017 14:40:24] [Error - LuaScriptInterface::loadFile] data/npc/scripts/guard.lua:108: unexpected symbol near ','
[03/08/2017 14:40:24] [Warning - NpcScript::NpcScript] Cannot load script: data/npc/scripts/guard.lua
[03/08/2017 14:40:24] data/npc/scripts/guard.lua:108: unexpected symbol near ','
By the way, where in this script do I specify the distance effect?

Best regards.
 

WibbenZ

Global Moderator
Staff member
Global Moderator
Joined
Oct 16, 2008
Messages
6,212
Best answers
224
Reaction score
1,168
Location
Sweden
Now I get this error:
Lua:
[03/08/2017 14:40:24] [Error - LuaScriptInterface::loadFile] data/npc/scripts/guard.lua:108: unexpected symbol near ','
[03/08/2017 14:40:24] [Warning - NpcScript::NpcScript] Cannot load script: data/npc/scripts/guard.lua
[03/08/2017 14:40:24] data/npc/scripts/guard.lua:108: unexpected symbol near ','
By the way, where in this script do I specify the distance effect?

Best regards.
The function is:
Lua:
doSendDistanceShoot
First variable is fromPosition = location the effect is sent from.
Second variable is toPosition = location the effect should go to.
Third variable is the effect, in your case CONST_ANI_WHIRLWINDSWORD

I guess you can try this;
Lua:
doSendDistanceShoot(myPos, playerPos, CONST_ANI_WHIRLWINDSWORD)
Ref; forgottenserver036pl1/luascript.cpp at master · peonso/forgottenserver036pl1 · GitHub
 
Last edited:
OP
AdiMit

AdiMit

c(;
Joined
May 2, 2016
Messages
70
Best answers
2
Reaction score
3
The function is:
Lua:
doSendDistanceShoot
First variable is fromPosition = location the effect is sent from.
Second variable is toPosition = location the effect should go to.
Third variable is the effect, in your case CONST_ANI_WHIRLWINDSWORD

I guess you can try this;
Lua:
doSendDistanceShoot(origPos, target, CONST_ANI_WHIRLWINDSWORD)
Ref; forgottenserver036pl1/luascript.cpp at master · peonso/forgottenserver036pl1 · GitHub
Now, when the path is blocked by another player and the NPC is supposed to attack the PKer, I get this:
Lua:
[03/08/2017 14:51:34] [Error - Npc interface]
[03/08/2017 14:51:34] data/npc/scripts/guard.lua:onThink
[03/08/2017 14:51:34] Description:
[03/08/2017 14:51:34] attempt to index a number value
[03/08/2017 14:51:34] stack traceback:
[03/08/2017 14:51:34]     [C]: in function 'doSendDistanceShoot'
[03/08/2017 14:51:34]     data/npc/scripts/guard.lua:108: in function <data/npc/scripts/guard.lua:70>
The whole script looks as follows:
Lua:
local target = 0
local prevTarget = 0
local maxChaseDistance = 20
local origPos = 0
local lastAttack = 0
local followTimeout = 10

local function isSkulled(cid)
    if(getCreatureSkullType(cid) >= SKULL_WHITE and isPlayerPzLocked(cid)) then
        return true
    end

    return false
end

local function goToOrigPos()
    target = 0
    lastAttack  = 0
    selfFollow(0)
    doTeleportThing(getNpcCid(), origPos)
end

local function updateTarget()
    if(not isPlayer(target)) then
        goToOrigPos()
    elseif(not isSkulled(target)) then
        selfSay("Now, behave in the future.")
        goToOrigPos()
    end

    if(target == 0) then
        local list = getSpectators(getNpcPos(), 9, 9, false)
        for i = 1, table.getn(list) do
            local _target = list[i]
            if(_target ~= 0) then
                if(isPlayer(_target) and isSkulled(_target)) then
                    if(not getTilePzInfo(getCreaturePosition(_target))) then
                        if(selfFollow(_target)) then
                            target = _target
                            if(target ~= prevTarget) then
                                selfSay("We do not tolerate people like you here!")
                            end

                            prevTarget = target
                            break
                        end
                    end
                end
            end
        end
    end
end

function onCreatureAppear(cid)
    if(cid == getNpcCid()) then
        origPos = getNpcPos()
    end
end

function onCreatureDisappear(cid)
    if(cid == target) then
        goToOrigPos()
    end
end

function onCreatureMove(creature, oldPos, newPos)
    --
end

function onThink()
    updateTarget()

    if(target == 0) then
        return
    end

    local playerPos = getCreaturePosition(target)
    local myPos = getNpcPos()

    if(myPos.z ~= playerPos.z) then
        goToOrigPos()
        return
    end

    if(math.abs(myPos.x - origPos.x) > maxChaseDistance or math.abs(myPos.y - origPos.y) > maxChaseDistance) then
        selfSay("I'll catch you next time.")
        goToOrigPos()
        return
    end

    if(lastAttack == 0) then
        lastAttack = os.clock()
    end

    if(os.clock() - lastAttack > followTimeout) then
        selfSay("You got me this time, but just wait.")
        goToOrigPos()
        return
    end

    if((math.abs(playerPos.x - myPos.x) <= 1) and (math.abs(playerPos.y - myPos.y) <= 1)) then
        doTargetCombatHealth(getNpcCid(), target, COMBAT_LIFEDRAIN, -220, -330, CONST_ME_BLOCKHIT)
        lastAttack = os.clock()
    end

    if((math.abs(playerPos.x - myPos.x) >= 2) and (math.abs(playerPos.y - myPos.y) >= 2)) then
        doTargetCombatHealth(getNpcCid(), target, COMBAT_PHYSICAL, -110, -220, CONST_ME_HITAREA)
        doSendDistanceShoot(getNpcPos(), target, CONST_ANI_WHIRLWINDSWORD)
        lastAttack = os.clock()
    end
end
 

WibbenZ

Global Moderator
Staff member
Global Moderator
Joined
Oct 16, 2008
Messages
6,212
Best answers
224
Reaction score
1,168
Location
Sweden
Now, when the path is blocked by another player and the NPC is supposed to attack the PKer, I get this:
Lua:
[03/08/2017 14:51:34] [Error - Npc interface]
[03/08/2017 14:51:34] data/npc/scripts/guard.lua:onThink
[03/08/2017 14:51:34] Description:
[03/08/2017 14:51:34] attempt to index a number value
[03/08/2017 14:51:34] stack traceback:
[03/08/2017 14:51:34]     [C]: in function 'doSendDistanceShoot'
[03/08/2017 14:51:34]     data/npc/scripts/guard.lua:108: in function <data/npc/scripts/guard.lua:70>
The whole script looks as follows:
Lua:
local target = 0
local prevTarget = 0
local maxChaseDistance = 20
local origPos = 0
local lastAttack = 0
local followTimeout = 10

local function isSkulled(cid)
    if(getCreatureSkullType(cid) >= SKULL_WHITE and isPlayerPzLocked(cid)) then
        return true
    end

    return false
end

local function goToOrigPos()
    target = 0
    lastAttack  = 0
    selfFollow(0)
    doTeleportThing(getNpcCid(), origPos)
end

local function updateTarget()
    if(not isPlayer(target)) then
        goToOrigPos()
    elseif(not isSkulled(target)) then
        selfSay("Now, behave in the future.")
        goToOrigPos()
    end

    if(target == 0) then
        local list = getSpectators(getNpcPos(), 9, 9, false)
        for i = 1, table.getn(list) do
            local _target = list[i]
            if(_target ~= 0) then
                if(isPlayer(_target) and isSkulled(_target)) then
                    if(not getTilePzInfo(getCreaturePosition(_target))) then
                        if(selfFollow(_target)) then
                            target = _target
                            if(target ~= prevTarget) then
                                selfSay("We do not tolerate people like you here!")
                            end

                            prevTarget = target
                            break
                        end
                    end
                end
            end
        end
    end
end

function onCreatureAppear(cid)
    if(cid == getNpcCid()) then
        origPos = getNpcPos()
    end
end

function onCreatureDisappear(cid)
    if(cid == target) then
        goToOrigPos()
    end
end

function onCreatureMove(creature, oldPos, newPos)
    --
end

function onThink()
    updateTarget()

    if(target == 0) then
        return
    end

    local playerPos = getCreaturePosition(target)
    local myPos = getNpcPos()

    if(myPos.z ~= playerPos.z) then
        goToOrigPos()
        return
    end

    if(math.abs(myPos.x - origPos.x) > maxChaseDistance or math.abs(myPos.y - origPos.y) > maxChaseDistance) then
        selfSay("I'll catch you next time.")
        goToOrigPos()
        return
    end

    if(lastAttack == 0) then
        lastAttack = os.clock()
    end

    if(os.clock() - lastAttack > followTimeout) then
        selfSay("You got me this time, but just wait.")
        goToOrigPos()
        return
    end

    if((math.abs(playerPos.x - myPos.x) <= 1) and (math.abs(playerPos.y - myPos.y) <= 1)) then
        doTargetCombatHealth(getNpcCid(), target, COMBAT_LIFEDRAIN, -220, -330, CONST_ME_BLOCKHIT)
        lastAttack = os.clock()
    end

    if((math.abs(playerPos.x - myPos.x) >= 2) and (math.abs(playerPos.y - myPos.y) >= 2)) then
        doTargetCombatHealth(getNpcCid(), target, COMBAT_PHYSICAL, -110, -220, CONST_ME_HITAREA)
        doSendDistanceShoot(getNpcPos(), target, CONST_ANI_WHIRLWINDSWORD)
        lastAttack = os.clock()
    end
end
Use playerPos insted of target
 
OP
AdiMit

AdiMit

c(;
Joined
May 2, 2016
Messages
70
Best answers
2
Reaction score
3
Use playerPos insted of target
Lua:
    if((math.abs(playerPos.x - myPos.x) >= 2) and (math.abs(playerPos.y - myPos.y) >= 2)) then
        doTargetCombatHealth(getNpcCid(), target, COMBAT_LIFEDRAIN, -110, -220, CONST_ME_BLOCKHIT)
        doSendDistanceShoot(getNpcPos(), playerPos, CONST_ANI_WHIRLWINDSWORD)
        lastAttack = os.clock()
    end
end
Works! :D

Thank you kindly! :)
 

WibbenZ

Global Moderator
Staff member
Global Moderator
Joined
Oct 16, 2008
Messages
6,212
Best answers
224
Reaction score
1,168
Location
Sweden
Lua:
    if((math.abs(playerPos.x - myPos.x) >= 2) and (math.abs(playerPos.y - myPos.y) >= 2)) then
        doTargetCombatHealth(getNpcCid(), target, COMBAT_LIFEDRAIN, -110, -220, CONST_ME_BLOCKHIT)
        doSendDistanceShoot(getNpcPos(), playerPos, CONST_ANI_WHIRLWINDSWORD)
        lastAttack = os.clock()
    end
end
Works! :D

Thank you kindly! :)
A tip use
Lua:
myPos
insted, since
Lua:
getNpcPos()
has already been called on line 77
 
Top