Difference between revisions of "How to Move Npcs"
(→= Making NPCs Movable) |
(→= Creating a Path) |
||
(4 intermediate revisions by one other user not shown) | |||
Line 16: | Line 16: | ||
Migrate the table and you're done. | Migrate the table and you're done. | ||
+ | |||
+ | === Simple NPC Movement === | ||
+ | |||
+ | This is a really simple script that will make the npc loop through the path. This is 'scripts/zones/Port_Jeuno/npcs/Red_Ghost.lua' | ||
+ | <pre> | ||
+ | -- includes pathfind methods | ||
+ | require("scripts/globals/pathfind"); | ||
+ | |||
+ | -- total path, you can have multiple | ||
+ | path = { | ||
+ | -96.823616, 0.001000, -3.722488, -- x1, y1, z1 | ||
+ | -96.761887, 0.001000, -2.632236, -- x2, y2, z2 | ||
+ | -96.698341, 0.001000, -1.490001, -- etc | ||
+ | -96.636963, 0.001000, -0.363672, | ||
+ | -96.508736, 0.001000, 2.080966, | ||
+ | -96.290009, 0.001000, 6.895948, | ||
+ | -96.262505, 0.001000, 7.935584, | ||
+ | -96.282127, 0.001000, 6.815756, | ||
+ | -96.569176, 0.001000, -7.781419, | ||
+ | -96.256729, 0.001000, 8.059505, | ||
+ | -96.568405, 0.001000, -7.745419, | ||
+ | -96.254066, 0.001000, 8.195477, | ||
+ | -96.567200, 0.001000, -7.685426 | ||
+ | }; | ||
+ | |||
+ | function onSpawn(npc) | ||
+ | -- pathfind.first(path) will retrieve the first point in the path | ||
+ | -- that will be {-96.823616, 0.001000, -3.722488} | ||
+ | -- npc:setPos will set the npc to the first point | ||
+ | -- this should be done for safety | ||
+ | npc:setPos(pathfind.first(path)); | ||
+ | -- this calls onPath and starts moving the npc to the first point through the whole path | ||
+ | onPath(npc); | ||
+ | end; | ||
+ | |||
+ | -- onPath is called everytime the npc hits a point on the path | ||
+ | -- so this will be called 12 times through the entire walk | ||
+ | -- the first point isn't called because you are already there | ||
+ | function onPath(npc) | ||
+ | -- patrol will keep looping through the path when it finishes | ||
+ | pathfind.patrol(npc, path); | ||
+ | end; | ||
+ | </pre> | ||
+ | |||
+ | === Creating a Path == | ||
+ | |||
+ | An easy way of getting points is to use the Ashitaplugin, Navi. Which can be downloaded via the launcher. | ||
+ | Then go in game and run around. You can then export the points and use it in lua. | ||
+ | |||
+ | If you are on linux you can use this command to output all points: ack 'x="([\-0-9\.]+)" y="([\-0-9\.]+)" z="([\-0-9\.]+)"' west.xml --output='$1, $2, $3,' > west_points.asc | ||
== Examples == | == Examples == | ||
=== NPC Example === | === NPC Example === | ||
+ | |||
+ | This is a more complex example than red ghost. Raminel is the little boy that delivers stuff in south sandy. At certain points he stops and says something to npcs. This isn't too hard to do. | ||
+ | |||
+ | <pre> | ||
+ | require("scripts/globals/pathfind"); | ||
+ | |||
+ | path = { | ||
+ | -138.436340, -2.000000, 16.227097, | ||
+ | -137.395432, -2.000000, 15.831898, | ||
+ | -136.317108, -2.000000, 15.728185, | ||
+ | -134.824036, -2.000000, 15.816396, | ||
+ | -108.897049, -2.000000, 16.508110, | ||
+ | -107.823288, -2.000000, 16.354126, | ||
+ | -106.804962, -2.000000, 15.973084, | ||
+ | -105.844963, -2.000000, 15.462379, | ||
+ | -104.922585, -2.000000, 14.885456, | ||
+ | -104.020050, -2.000000, 14.277813, | ||
+ | -103.138374, -2.000000, 13.640303, | ||
+ | -101.501289, -2.000000, 12.422975, | ||
+ | -77.636841, 2.000000, -5.771687, | ||
+ | -59.468536, 2.000000, -19.632719, | ||
+ | -58.541172, 2.000000, -20.197826, | ||
+ | -57.519985, 2.000000, -20.570829, | ||
+ | -56.474659, 2.000000, -20.872238, | ||
+ | -55.417450, 2.000000, -21.129019, | ||
+ | -54.351425, 2.000000, -21.365578, | ||
+ | -53.286743, 2.000000, -21.589529, | ||
+ | -23.770412, 2.000000, -27.508755, | ||
+ | -13.354427, 1.700000, -29.593290, | ||
+ | -14.421194, 1.700000, -29.379389, -- auction house | ||
+ | -43.848141, 2.000000, -23.492155, | ||
+ | -56.516224, 2.000000, -20.955723, | ||
+ | -57.555450, 2.000000, -20.638817, | ||
+ | -58.514832, 2.000000, -20.127840, | ||
+ | -59.426712, 2.000000, -19.534536, | ||
+ | -60.322998, 2.000000, -18.917839, | ||
+ | -61.203823, 2.000000, -18.279247, | ||
+ | -62.510002, 2.000000, -17.300892, | ||
+ | -86.411278, 2.000000, 0.921999, | ||
+ | -105.625214, -2.000000, 15.580724, | ||
+ | -106.582047, -2.000000, 16.089426, | ||
+ | -107.647263, -2.000000, 16.304668, | ||
+ | -108.732132, -2.000000, 16.383970, | ||
+ | -109.819397, -2.000000, 16.423687, | ||
+ | -110.907364, -2.000000, 16.429226, | ||
+ | -111.995232, -2.000000, 16.411282, | ||
+ | -140.205811, -2.000000, 15.668728, -- package Lusiane | ||
+ | -139.296539, -2.000000, 16.786556 | ||
+ | }; | ||
+ | |||
+ | |||
+ | function onSpawn(npc) | ||
+ | -- move to first point on path | ||
+ | npc:setPos(pathfind.first(path)); | ||
+ | -- start walking | ||
+ | onPath(npc); | ||
+ | end; | ||
+ | |||
+ | function onPath(npc) | ||
+ | -- this check if raminel is at point 23 in the path | ||
+ | -- remember lua starts counting from 1 not 0 | ||
+ | if(npc:atPoint(pathfind.get(path, 23))) then | ||
+ | -- if i'm at this point look at this npc and wait. Default wait time is 4 seconds. | ||
+ | -- you can also enter in a number | ||
+ | local arp = GetNPCByID(17719409); | ||
+ | |||
+ | npc:lookAt(arp:getPos()); | ||
+ | npc:wait(); | ||
+ | -- you can also get points starting from the end of the path | ||
+ | -- this will get you the second last point | ||
+ | elseif(npc:atPoint(pathfind.get(path, -1))) then | ||
+ | local lus = GetNPCByID(17719350); | ||
+ | |||
+ | -- give package to Lusiane | ||
+ | lus:showText(npc, RAMINEL_DELIVERY); | ||
+ | npc:showText(lus, LUSIANE_THANK); | ||
+ | |||
+ | -- wait default duration 4 seconds | ||
+ | -- then continue path | ||
+ | npc:wait(); | ||
+ | elseif(npc:atPoint(pathfind.last(path))) then | ||
+ | local lus = GetNPCByID(17719350); | ||
+ | |||
+ | -- when I walk away stop looking at me | ||
+ | lus:clearTargID(); | ||
+ | end | ||
+ | |||
+ | -- go back and forth the set path | ||
+ | pathfind.patrol(npc, path); | ||
+ | |||
+ | end; | ||
+ | </pre> | ||
=== Mob Example === | === Mob Example === | ||
+ | |||
+ | Mobs can also have defined paths. Mobs will only listen to custom paths when roaming and must be of type event! | ||
+ | |||
+ | <pre> | ||
+ | require("scripts/globals/pathfind"); | ||
+ | |||
+ | ----------------------------------- | ||
+ | -- onMobDeath | ||
+ | ----------------------------------- | ||
+ | |||
+ | local path = { | ||
+ | -408, -21, -90, | ||
+ | -423.6, -22.9, -100.5, | ||
+ | -439.9, -24.6, -105.6, | ||
+ | -449.5, -23.9, -109.7, | ||
+ | -455, -24, -117.8, | ||
+ | -451.3, -24.7, -125.8, | ||
+ | -445.6, -24.3, -132.4, | ||
+ | -417.3, -22.6, -143 | ||
+ | }; | ||
+ | |||
+ | function onMobSpawn(mob) | ||
+ | -- start roaming on spawn | ||
+ | OnMobRoam(mob); | ||
+ | end; | ||
+ | |||
+ | -- this is called when a mob is ready to move | ||
+ | -- this will only be called after a mob is finished moving | ||
+ | -- this mob keeps moving so its never called | ||
+ | function OnMobRoamAction(mob) | ||
+ | -- go back and forth | ||
+ | -- reverse means start the path in reverse | ||
+ | pathfind.patrol(mob, path, PATHFLAG_REVERSE); | ||
+ | |||
+ | end; | ||
+ | |||
+ | -- called for every point | ||
+ | function OnMobRoam(mob) | ||
+ | -- move to start position if not moving | ||
+ | if(mob:isFollowingPath() == false) then | ||
+ | mob:pathThrough(pathfind.first(path)); | ||
+ | end | ||
+ | end; | ||
+ | </pre> | ||
== Pathfind Interface == | == Pathfind Interface == |
Latest revision as of 21:42, 12 August 2014
Whats up? This will walk you through the process of making npcs and mobs move.
Contents
Making NPCs Walkable
Making NPCs Movable
By default a npc will not be in the server update loop. This means the npc cannot move around.
First find the id of the npc you want to update. Find your npc by looking in 'sql/npc_list.sql'. Search for your npcs name and copy the id.
npc_dummies currently uses the old npc format so you'll have to transform the npc id through this function: npcid + (4096 * zoneid) + 0x1000000).
Then put that inside a new row:
INSERT INTO `npc_dummies` VALUES('your_id_here');
Migrate the table and you're done.
Simple NPC Movement
This is a really simple script that will make the npc loop through the path. This is 'scripts/zones/Port_Jeuno/npcs/Red_Ghost.lua'
-- includes pathfind methods require("scripts/globals/pathfind"); -- total path, you can have multiple path = { -96.823616, 0.001000, -3.722488, -- x1, y1, z1 -96.761887, 0.001000, -2.632236, -- x2, y2, z2 -96.698341, 0.001000, -1.490001, -- etc -96.636963, 0.001000, -0.363672, -96.508736, 0.001000, 2.080966, -96.290009, 0.001000, 6.895948, -96.262505, 0.001000, 7.935584, -96.282127, 0.001000, 6.815756, -96.569176, 0.001000, -7.781419, -96.256729, 0.001000, 8.059505, -96.568405, 0.001000, -7.745419, -96.254066, 0.001000, 8.195477, -96.567200, 0.001000, -7.685426 }; function onSpawn(npc) -- pathfind.first(path) will retrieve the first point in the path -- that will be {-96.823616, 0.001000, -3.722488} -- npc:setPos will set the npc to the first point -- this should be done for safety npc:setPos(pathfind.first(path)); -- this calls onPath and starts moving the npc to the first point through the whole path onPath(npc); end; -- onPath is called everytime the npc hits a point on the path -- so this will be called 12 times through the entire walk -- the first point isn't called because you are already there function onPath(npc) -- patrol will keep looping through the path when it finishes pathfind.patrol(npc, path); end;
= Creating a Path
An easy way of getting points is to use the Ashitaplugin, Navi. Which can be downloaded via the launcher. Then go in game and run around. You can then export the points and use it in lua.
If you are on linux you can use this command to output all points: ack 'x="([\-0-9\.]+)" y="([\-0-9\.]+)" z="([\-0-9\.]+)"' west.xml --output='$1, $2, $3,' > west_points.asc
Examples
NPC Example
This is a more complex example than red ghost. Raminel is the little boy that delivers stuff in south sandy. At certain points he stops and says something to npcs. This isn't too hard to do.
require("scripts/globals/pathfind"); path = { -138.436340, -2.000000, 16.227097, -137.395432, -2.000000, 15.831898, -136.317108, -2.000000, 15.728185, -134.824036, -2.000000, 15.816396, -108.897049, -2.000000, 16.508110, -107.823288, -2.000000, 16.354126, -106.804962, -2.000000, 15.973084, -105.844963, -2.000000, 15.462379, -104.922585, -2.000000, 14.885456, -104.020050, -2.000000, 14.277813, -103.138374, -2.000000, 13.640303, -101.501289, -2.000000, 12.422975, -77.636841, 2.000000, -5.771687, -59.468536, 2.000000, -19.632719, -58.541172, 2.000000, -20.197826, -57.519985, 2.000000, -20.570829, -56.474659, 2.000000, -20.872238, -55.417450, 2.000000, -21.129019, -54.351425, 2.000000, -21.365578, -53.286743, 2.000000, -21.589529, -23.770412, 2.000000, -27.508755, -13.354427, 1.700000, -29.593290, -14.421194, 1.700000, -29.379389, -- auction house -43.848141, 2.000000, -23.492155, -56.516224, 2.000000, -20.955723, -57.555450, 2.000000, -20.638817, -58.514832, 2.000000, -20.127840, -59.426712, 2.000000, -19.534536, -60.322998, 2.000000, -18.917839, -61.203823, 2.000000, -18.279247, -62.510002, 2.000000, -17.300892, -86.411278, 2.000000, 0.921999, -105.625214, -2.000000, 15.580724, -106.582047, -2.000000, 16.089426, -107.647263, -2.000000, 16.304668, -108.732132, -2.000000, 16.383970, -109.819397, -2.000000, 16.423687, -110.907364, -2.000000, 16.429226, -111.995232, -2.000000, 16.411282, -140.205811, -2.000000, 15.668728, -- package Lusiane -139.296539, -2.000000, 16.786556 }; function onSpawn(npc) -- move to first point on path npc:setPos(pathfind.first(path)); -- start walking onPath(npc); end; function onPath(npc) -- this check if raminel is at point 23 in the path -- remember lua starts counting from 1 not 0 if(npc:atPoint(pathfind.get(path, 23))) then -- if i'm at this point look at this npc and wait. Default wait time is 4 seconds. -- you can also enter in a number local arp = GetNPCByID(17719409); npc:lookAt(arp:getPos()); npc:wait(); -- you can also get points starting from the end of the path -- this will get you the second last point elseif(npc:atPoint(pathfind.get(path, -1))) then local lus = GetNPCByID(17719350); -- give package to Lusiane lus:showText(npc, RAMINEL_DELIVERY); npc:showText(lus, LUSIANE_THANK); -- wait default duration 4 seconds -- then continue path npc:wait(); elseif(npc:atPoint(pathfind.last(path))) then local lus = GetNPCByID(17719350); -- when I walk away stop looking at me lus:clearTargID(); end -- go back and forth the set path pathfind.patrol(npc, path); end;
Mob Example
Mobs can also have defined paths. Mobs will only listen to custom paths when roaming and must be of type event!
require("scripts/globals/pathfind"); ----------------------------------- -- onMobDeath ----------------------------------- local path = { -408, -21, -90, -423.6, -22.9, -100.5, -439.9, -24.6, -105.6, -449.5, -23.9, -109.7, -455, -24, -117.8, -451.3, -24.7, -125.8, -445.6, -24.3, -132.4, -417.3, -22.6, -143 }; function onMobSpawn(mob) -- start roaming on spawn OnMobRoam(mob); end; -- this is called when a mob is ready to move -- this will only be called after a mob is finished moving -- this mob keeps moving so its never called function OnMobRoamAction(mob) -- go back and forth -- reverse means start the path in reverse pathfind.patrol(mob, path, PATHFLAG_REVERSE); end; -- called for every point function OnMobRoam(mob) -- move to start position if not moving if(mob:isFollowingPath() == false) then mob:pathThrough(pathfind.first(path)); end end;