How to Move Npcs

From DSP Wiki
Jump to: navigation, search

Whats up? This will walk you through the process of making npcs and mobs move.

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;

Pathfind Interface

Pathfind Events

OnPath

OnMobRoamAction

OnMobRoam