Difference between revisions of "AI:BrainTutorialLua"

Line 75: Line 75:
 
-- Not in combat so lets put the NPC in combat
 
-- Not in combat so lets put the NPC in combat
 
SetInCombat(NPC, true)
 
SetInCombat(NPC, true)
 +
end
 +
</pre>
 +
 +
Now lets check the runback_distance to see if it exceeds the max distance. First we should define the max distance at the top of the script, we will set it to 80 to match the server core.
 +
<pre>
 +
local MAX_CHASE_DISTANCE = 80
 +
</pre>
 +
 +
Back to where we were we can now check the distance, if the distance is greater then the value we define we should clear the hate list with [[LUA:ClearHate|ClearHate()]] and clear the encounter list with [[LUA:ClearEncounter|ClearEncounter()]], this will bring the NPC out of combat.
 +
<pre>
 +
-- Check distance to run back location
 +
if runback_distance > MAX_CHASE_DISTANCE then
 +
-- Clear the hate list
 +
ClearHate(NPC)
 +
-- Clear the encounter list
 +
ClearEncounter(NPC)
 +
else
 +
</pre>
 +
 +
If we haven't exceeded the max distance we can now do combat stuff, first we should check to see if the NPC is casting a spell with [[LUA:IsCasting|IsCasting()]], if not casting we should check to see if it has recovered from casting with [[LUA:HasRecovered|HasRecovered()]] and finally we should try to cast a spell with [[LUA:ProcessSpell|ProcessSpell()]] if we failed to cast a spell we should try a melee attack with [[LUA:ProcessMelee|ProcessMelee()]], this will also cause the spawn to move closer to its target if it is outside melee range.  We will check all but melee in a single if.  We also need to get the distance between two spawns with [[LUA:GetDistance|GetDistance()]].
 +
<pre>
 +
else
 +
-- Get the distance between the spawns for combat calcs
 +
local distance = GetDistance(NPC, Target, 1)
 +
 +
-- Check if not currently casting and the NPC has not recovered from casting or can cast a spell
 +
if not IsCasting(NPC) and (not HasRecovered(NPC) or not ProcessSpell(NPC, mostHated, distance)) then
 +
FaceTarget(NPC, mostHated)
 +
-- Attempt a melee attack, will also make the NPC move close to its target if it is out of range
 +
ProcessMelee(NPC, mostHated, distance)
 +
end
 
end
 
end
 
</pre>
 
</pre>

Revision as of 20:45, 29 August 2013

Creating a new brain in lua will allow you to override the default AI, it will not allow you to extend the default AI however. You can change the script and reload it without having to recompile and restart the server however. LUA AI needs to cover every aspect of combat, including putting the NPC into combat. In this tutorial I will show you how to create a lua AI that will duplicate the default AI code in the server core.

Set Up the Spawn Script

First thing you need to do is tell the spawn to use the AI defined in the lua script, this is done by calling SetLuaBrain(), you can also tell the script how often the AI code needs to run with SetBrainTick()

function spawn(NPC)
	SetLuaBrain(NPC)
	SetBrainTick(NPC, 200)
end

You will also want to make sure the brain is set when they respawn

function respawn(NPC)
	spawn(NPC)
end

Finally you need to add the "Think" function, this will be called every time the AI code needs to be run. The server will pass 2 parameters to this function, the first is the NPC this spawn script is attached to, the second is the NPC's current target.

function Think(NPC, Target)

end

We are now ready to program the AI.

Programing The New Brain

The first thing we need to do is check to see if the NPC can do anything, if they are mezzed or stunned then they can't do anything and we can skip the rest of the code. We can check if this is the case by calling IsMezzedOrStunned(), this will return true if the NPC is mezzed or stunned

-- Make sure the NPC is not mezzed or stunned
if not IsMezzedOrStunned(NPC) then

end

If the NPC is not mezzed or stunned the code inside the if will execute, if it is all the code will be skipped. We will now check the NPC's hate list and get the spawn that this NPC hates the most

-- Get the most hated spawn
local mostHated = GetMostHated(NPC)

We will also need to get the distance the spawn is to its run back location, the run back location is set to the position the NPC is at when they are flagged for combat

-- Get runback distance
local runback_distance = GetRunbackDistance(NPC)

Now we should check to see if we got a hate target, if we don't have a hate target we will still do some stuff so we will use an else as well

-- Check to see if we got a mostHated
if mostHated ~= nil then

else
    -- nothing in hate list

end

We will work with the mostHated spawn first, so lets check to see if we have a current target, if we do we will compare it to the mostHated spawn with CompareSpawns(), if the spawns are not the same, or we don't have a target, we want to set the NPC's target to the mostHated spawn

-- Check to see if the target and the most hated are the same
if Target == nil or not CompareNPCs(mostHated, Target) then
		-- Not the same so lets make them the same
		SetTarget(NPC, mostHated)
		FaceTarget(NPC, mostHated)
end

We should now check to see if the NPC is flagged in combat with IsInCombat(), if it isn't we should put it into combat with SetInCombat(), also note that setting the NPC into combat will suspend scripted movement until it is no longer in combat.

-- We have a hate target so lets check if we are already in combat
if not IsInCombat(NPC) then
		-- Not in combat so lets put the NPC in combat
		SetInCombat(NPC, true)
end

Now lets check the runback_distance to see if it exceeds the max distance. First we should define the max distance at the top of the script, we will set it to 80 to match the server core.

local MAX_CHASE_DISTANCE = 80

Back to where we were we can now check the distance, if the distance is greater then the value we define we should clear the hate list with ClearHate() and clear the encounter list with ClearEncounter(), this will bring the NPC out of combat.

-- Check distance to run back location
if runback_distance > MAX_CHASE_DISTANCE then
	-- Clear the hate list
	ClearHate(NPC)
	-- Clear the encounter list
	ClearEncounter(NPC)
else

If we haven't exceeded the max distance we can now do combat stuff, first we should check to see if the NPC is casting a spell with IsCasting(), if not casting we should check to see if it has recovered from casting with HasRecovered() and finally we should try to cast a spell with ProcessSpell() if we failed to cast a spell we should try a melee attack with ProcessMelee(), this will also cause the spawn to move closer to its target if it is outside melee range. We will check all but melee in a single if. We also need to get the distance between two spawns with GetDistance().

else
	-- Get the distance between the spawns for combat calcs
	local distance = GetDistance(NPC, Target, 1)
				
	-- Check if not currently casting and the NPC has not recovered from casting or can cast a spell
	if not IsCasting(NPC) and (not HasRecovered(NPC) or not ProcessSpell(NPC, mostHated, distance)) then
		FaceTarget(NPC, mostHated)
		-- Attempt a melee attack, will also make the NPC move close to its target if it is out of range
		ProcessMelee(NPC, mostHated, distance)
	end
end