Skip to content
This repository has been archived by the owner on Dec 4, 2020. It is now read-only.

Pathfind fix for NPC/MOB and poor old Novalmauge #548

Merged
merged 6 commits into from
Nov 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 149 additions & 0 deletions scripts/globals/pathfind.lua
Original file line number Diff line number Diff line change
Expand Up @@ -125,5 +125,154 @@ tpz.path =
i = i + 50
end
end
end,

-- run a basic path from start to end and repeat, the path will need to be linked back to start to loop correctly.
-- takes a point that is {x,y,z} extra option can be added: {x,y,z {delay = 4}} or {x,y,z{rot = 230}} or both {x,y,z{rot = 90, delay = 7}}
-- if a rotation is added "{x,y,z {rot = 35}}" then a delay will be added to allow for the rotation to execute.
general = function(entity, points, flags)
local path = points or {}
local point = entity:getPathPoint()
local pos = entity:getPos()
local pathFlags = tpz.path.flag.NONE
local canPath = false
local delay = 0
local rotation = 0

if flags ~= tpz.path.flag.NONE and flags ~= nil then
pathFlags = flags
end

local dx = path[point][1] - pos.x
local dz = path[point][3] - pos.z

local distToPoint = math.sqrt( dx * dx + dz * dz )

if distToPoint < 0.1 then
if path[point][4] then
local options = path[point][4] or {}
----------------------------------
-- Set delay if found
----------------------------------
if options.delay then
if options.delay > 0 then
delay = options.delay
end
end
--------------------------------------------
-- Auto delay if rotation and no delay found
--------------------------------------------
if options.rot then
if options.rot > 0 and delay == 0 then
delay = 3
end
end
end

if delay > 0 then
entity:setLocalVar("[PATHDELAY]", os.time() + delay)
else
if entity:getLocalVar("[PATHDELAY]") ~= 0 then
entity:setLocalVar("[PATHDELAY]", 0)
end
end
----------------------------------
-- Set next point
----------------------------------
if point == #path then
entity:setPathPoint(1)
else
entity:setPathPoint(point +1)
end
end

local lastPoint = point

if point > 1 and point < #path then
lastPoint = point -1
end

----------------------------------
-- Set rotation if one found
----------------------------------
if path[lastPoint][4] then
local rotateOptions = path[lastPoint][4] or {}
if rotateOptions.rot then
if rotateOptions.rot > 0 then
rotation = rotateOptions.rot
end
end
end

----------------------------------
-- Move if time is > delay
----------------------------------
if os.time() >= entity:getLocalVar("[PATHDELAY]") then
entity:pathTo(path[point][1], path[point][2], path[point][3], pos.rot, pathFlags)
else
if rotation > 0 then
entity:rotateToAngle(rotation)
end
end
end,

-- entity will move to last point then set the last position in the path
toPoint = function(entity, points, run)
local path = points or {}
local point = entity:getPathPoint()
local pos = entity:getPos()
local canPath = true

if path == {} then
return
end

if entity:atPoint(path[point]) then
if point == #path then
canPath = false
else
entity:setPathPoint(point +1)
canPath = true
end
end

if canPath then
entity:stepTo(path[point][1], path[point][2], path[point][3], run)
end
end,

-- entity will move between two points
pingPong = function(entity, points, flags)
local path = points or {}
local point = entity:getPathPoint()
local pos = entity:getPos()

if entity:atPoint(path[1]) then
entity:setPathPoint(2)
elseif entity:atPoint(path[2]) then
entity:setPathPoint(1)
end

entity:pathTo(path[point][1], path[point][2], path[point][3], 0, flags)
end,

-- pick a random point in the path and set random delay.
randomPoint = function(entity, points, run)
local path = points or {}
local point = entity:getPathPoint()
local pos = entity:getPos()
local dx = path[point][1] - pos.x
local dz = path[point][3] - pos.z

local distToPoint = math.sqrt( dx * dx + dz * dz )

if distToPoint < 0.1 then
entity:setLocalVar("[PATHDELAY]", os.time() + math.random(4, 8))
entity:setPathPoint(math.random(1, #path))
end

if os.time() >= entity:getLocalVar("[PATHDELAY]") then
entity:stepTo(path[point][1], path[point][2], path[point][3], run)
end
end
}
13 changes: 9 additions & 4 deletions scripts/globals/transport.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
-- Transport
------------------------------------
require("scripts/globals/zone")
require("scripts/globals/pathfind")
------------------------------------

tpz = tpz or {}
Expand Down Expand Up @@ -59,8 +60,8 @@ tpz.transport.pos =
{
mhaura =
{
ARRIVING = {7.06, -1.36, 2.20},
DEPARTING = {8.26, -1.36, 2.20}
ARRIVING = {{7.06, -1.36, 2.48}, {7.07, -1.36, 2.58}},
DEPARTING = {{8.26, -1.36, 2.20}, {8.26, -1.36, 2.30}},
}
}

Expand All @@ -78,8 +79,12 @@ end
tpz.transport.dockMessage = function(npc, triggerID, messages, dock)
npc:showText(npc, messages[triggerID])
if (triggerID % 2) == 0 then
npc:pathThrough(tpz.transport.pos[dock].ARRIVING, PATHFLAG_WALLHACK)
npc:setLocalVar("[PATHING]ARRIVING", 1)
npc:setPathPoint(1)
npc:pathResume()
else
npc:pathThrough(tpz.transport.pos[dock].DEPARTING, PATHFLAG_WALLHACK)
npc:setLocalVar("[PATHING]DEPARTING", 1)
npc:setPathPoint(1)
npc:pathResume()
end
end
39 changes: 21 additions & 18 deletions scripts/zones/Bostaunieux_Oubliette/npcs/Novalmauge.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
-----------------------------------
-- Area: Bostaunieux Obliette
-- NPC: Novalmauge
-- NPC: Novalmauge
-- Starts and Finishes Quest: The Rumor, Souls in Shadow
-- Involved in Quest: The Holy Crest, Trouble at the Sluice
-- !pos 70 -24 21 167
Expand All @@ -15,39 +15,35 @@ require("scripts/globals/quests")

local path =
{
41.169430, -24.000000, 19.860674,
42.256676, -24.000000, 19.885197,
41.168694, -24.000000, 19.904638,
21.859211, -24.010996, 19.792259,
51.917370, -23.924366, 19.970068,
74.570229, -24.024828, 20.103880,
44.533886, -23.947662, 19.926519
{20.000, -24.032, 20.023},
{21.000, -24.000, 20.054},
{74.835, -24.039, 20.250},
{74.373, -24.014, 19.999},
}

local wsQuest = tpz.wsquest.spiral_hell

function onSpawn(npc)
npc:initNpcAi()
npc:setPos(tpz.path.first(path))
npc:initNpcPathing(path[1][1], path[1][2], path[1][3])
onPath(npc)
end

function onPath(npc)
tpz.path.patrol(npc, path)
tpz.path.general(npc, path, tpz.path.flag.WALLHACK, false)
end

function onTrade(player, npc, trade)
local wsQuestEvent = tpz.wsquest.getTradeEvent(wsQuest, player, trade)

if player:getCharVar("troubleAtTheSluiceVar") == 2 and npcUtil.tradeHas(trade, 959) then -- Dahlia
player:startEvent(17)
npc:wait()
npc:pathStop()
elseif player:getQuestStatus(SANDORIA, tpz.quest.id.sandoria.THE_RUMOR) == QUEST_ACCEPTED and npcUtil.tradeHas(trade, 930) then -- Beastman Blood
player:startEvent(12)
npc:wait()
npc:pathStop()
elseif wsQuestEvent ~= nil then
player:startEvent(wsQuestEvent)
npc:wait()
npc:pathStop()
end
end

Expand All @@ -58,32 +54,39 @@ function onTrigger(player, npc)
local theHolyCrestStat = player:getCharVar("TheHolyCrest_Event")
local theRumor = player:getQuestStatus(SANDORIA, tpz.quest.id.sandoria.THE_RUMOR)

npc:wait()

if wsQuestEvent ~= nil then
player:startEvent(wsQuestEvent)
npc:pathStop()

-- THE HOLY CREST
elseif theHolyCrestStat == 1 then
player:startEvent(6)
npc:pathStop()
elseif theHolyCrestStat == 2 and player:getCharVar("theHolyCrestCheck") == 0 then
player:startEvent(7)
npc:pathStop()

-- TROUBLE AT THE SLUICE
elseif troubleAtTheSluiceStat == 1 then
player:startEvent(15)
npc:pathStop()
elseif troubleAtTheSluiceStat == 2 then
player:startEvent(16)
npc:pathStop()

-- THE RUMOR
elseif theRumor == QUEST_AVAILABLE and player:getFameLevel(SANDORIA) >= 3 and player:getMainLvl() >= 10 then
player:startEvent(13)
npc:pathStop()
elseif theRumor == QUEST_ACCEPTED then
player:startEvent(11)
npc:pathStop()
elseif theRumor == QUEST_COMPLETED then
player:startEvent(14) -- Standard dialog after "The Rumor"
npc:pathStop()
else
player:startEvent(10) -- Standard dialog
npc:pathStop()
end
end

Expand All @@ -109,5 +112,5 @@ function onEventFinish(player, csid, option, npc)
tpz.wsquest.handleEventFinish(wsQuest, player, csid, option, ID.text.SPIRAL_HELL_LEARNED)
end

npc:wait(0)
npc:pathResume()
end
73 changes: 36 additions & 37 deletions scripts/zones/Davoi/npcs/Quemaricond.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,58 +4,57 @@
-- Involved in Mission: Infiltrate Davoi
-- !pos 23 0.1 -23 149
-----------------------------------
require("scripts/globals/missions");
require("scripts/globals/keyitems");
local ID = require("scripts/zones/Davoi/IDs");
require("scripts/globals/pathfind");
local ID = require("scripts/zones/Davoi/IDs")
require("scripts/globals/missions")
require("scripts/globals/keyitems")
require("scripts/globals/pathfind")
-----------------------------------

local path =
{
20.6, 0, -23,
46, 0, -19,
53.5, -1.8, -19,
61, -1.1, -18.6,
67.3, -1.5, -18.6,
90, -0.5, -19
};
{20.600, -0.343, -23.000, {delay = 5}},
{35.431, -0.045, -20.227},
{51.795, -1.790, -18.843},
{58.037, -0.957, -18.724},
{65.919, -1.722, -18.767},
{92.143, -0.451, -16.231, {delay = 5}},
{65.919, -1.722, -18.767},
{58.037, -0.957, -18.724},
{51.795, -1.790, -18.843},
{35.431, -0.045, -20.227},
}
Comment on lines 13 to +25
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section really nicely highlights the benefits of this PR!


function onSpawn(npc)
npc:initNpcAi();
npc:setPos(tpz.path.first(path));
onPath(npc);
end;
npc:initNpcPathing()
onPath(npc)
end

function onPath(npc)
tpz.path.general(npc, path, tpz.path.flag.WALLHACK, false)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at this "in the wild", I wonder if general is really the right name for the default, regular, general call?

Now that I say the other options, I guess it's as good as all the others 🤷

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe refactor to tpz.pathing.path(), I don't know how much work that would be?

end

tpz.path.patrol(npc, path);
end;

function onTrade(player,npc,trade)
end;

function onTrigger(player,npc)
function onTrade(player, npc, trade)
end

function onTrigger(player, npc)
if (player:getCurrentMission(SANDORIA) == tpz.mission.id.sandoria.INFILTRATE_DAVOI and player:getCharVar("MissionStatus") == 3) then
player:startEvent(117);
npc:wait();
player:startEvent(117)
npc:pathStop()
else
player:showText(npc, ID.text.QUEMARICOND_DIALOG);
npc:wait(2000);
player:showText(npc, ID.text.QUEMARICOND_DIALOG)
npc:clearTargID()
end
end

end;

function onEventUpdate(player,csid,option)
end;

function onEventFinish(player,csid,option,npc)
function onEventUpdate(player, csid, option)
end

function onEventFinish(player, csid, option, npc)
if (csid == 117) then
player:setCharVar("MissionStatus",4);
player:addKeyItem(tpz.ki.ROYAL_KNIGHTS_DAVOI_REPORT);
player:messageSpecial(ID.text.KEYITEM_OBTAINED,tpz.ki.ROYAL_KNIGHTS_DAVOI_REPORT);
player:setCharVar("MissionStatus",4)
player:addKeyItem(tpz.ki.ROYAL_KNIGHTS_DAVOI_REPORT)
player:messageSpecial(ID.text.KEYITEM_OBTAINED,tpz.ki.ROYAL_KNIGHTS_DAVOI_REPORT)
end

npc:wait(0);
end;
npc:pathResume()
end
2 changes: 1 addition & 1 deletion scripts/zones/Ilrusi_Atoll/npcs/Excaliace.lua
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ local startToChoice1 = {
};

function onSpawn(npc)
npc:initNpcAi();
npc:initNpcPathing();
npc:pathThrough(start, PATHFLAG_REPEAT);
end;

Expand Down
Loading