SAI Scripting Tutorial

Before I show you some SAI samples I want to first inform you to write down exactly what you want to do and how your script will affect other npcs and players.

A block diagram of what you are exactly trying to do and you will have better success.

I am going to do this by showing you simple code for one task then we can later add some together.

Also when doing SAI please use the follow format for your comments:

NPC - On _event - action eg Joe - Out of beer - go to store

NOTE: I won’t be doing any combat AI for a while.

First I want to show you how to aura an NPC and why I do it the way I do.

I am only going to discuss SAI for creatures as Game Object SAI is not implemented yet.

First we should note the fields:

entryorguid: This is the entry or guid of the creature you are write the SAI for. If you use the creature entry the SAI will work for all creatures of that entry, EXCEPT any that have guid SAI set. If you wish to create SAI that only one guid of the entry uses you have to use a -guid value. Eg. You want to script guid 123456 you would put the value -123456 in this field.

id: Always 0 for creatures. When we start adding scripts to our SAI we will use value 9 for script entries.

Link: Will discuss later.

After this we have 3 sections [B]EVENT/B, [B]ACTION/B, [B]TARGET/B

You can write your SAI like this before you actually code it. We are going to start of with a simple “NPC aura self SAI”. “You will have to refer to wiki also”

EVENT (Aura not present)

So we set the event to 23 “SMART_EVENT_HAS_AURA” Chance at 100%. If you look at the wiki you will see this event has 4 parameters: SpellID,Stacks,RepeatMin,RepeatMax.

I set it to look for @SPELL with 0 stacks “not present” Start and repeat every 2 seconds. Easy enough. The npc’s SAI will check the npc every 2 seconds to see if the aura doesn’t exist and if it doesn’t then the event is true and will then do the action.

ACTION (add aura)

To add the aura the npc will need to cast the spell on its self using action 11. If you look at the wiki you will see this action has 2 parameters:

SpellId,CastFlags.

I set it to cast @SPELL with no castflags required.

TARGET (self)

Next I set the target. Target type self is very simple, you just set target_type = 1 with no extra parameters.

You may ask why did I do aura self like this rather than on spawn or reset? There are a couple reasons. One, if the npc evades combat the script will reset and it will recast the aura on itself which will, in some cases, remove the aura. Two, if the npc cast a 10 min aura in itself it will need to be recast after the 10 are up. So this is the best solution to handle auras.

[CODE]-- Add aura to NPC if aura not present
SET @ENTRY := XXXXX;
SET @SPELL := XXXXX;
UPDATE creature_template SET AIName=‘SmartAI’ WHERE entry=@ENTRY;
DELETE FROM smart_scripts WHERE source_type=0 AND entryorguid=@ENTRY;
INSERT INTO smart_scripts (entryorguid,source_type,id,link,event_type,event_phase_mask,event_chance,event_flags,event_param1,event_param2,event_param3,event_param4,action_type,action_param1,action_param2,action_param3,action_param4,action_param5,action_param6,target_type,target_param1,target_param2,target_param3,target_x,target_y,target_z,target_o,comment) VALUES
(@ENTRY,0,0,0,23,0,100,0,@SPELL,0,2000,2000,11,@SPELL,0,0,0,0,0,1,0,0,0,0,0,0,0, ‘NPC - Aura SPELL not present - Add Aura SPELL’);[/sql]

If you have a problem understanding this please let me know so I can adjust, I am not a teacher /emoticons/default_smile.png

[/CODE]

Two more examples of casting on spawn and reset. These are for visual channeling spells.

The first one would be used on an npc who is standing and casting a visual channel spell. the timers are set at one second only for a slight wait when returning to the home position after evade. These values can be zero and it would not effect the script working.

Notice that this event occurs out of combat with the event flag set to 1 “no repeat”. The script will reset on spawn and after evade so the script will run again when it is required too.

The second script is also a channeling spell but this one is channeled on a target. In this script the wait time of one second is very important. Because there is a chance that the caster may spawn before the trigger target without the wait time the npc may attempt to channel spell before the trigger is spawned and fail. So by adding a wait time of one second you give the trigger time to spawn before the spell is cast.

[CODE]-- Cast channeling spell no target
SET @ENTRY := XXXXX; – NPC entry
SET @SPELL := XXXXX; – Spell to cast
UPDATE creature_template SET AIName=‘SmartAI’ WHERE entry=@ENTRY;
DELETE FROM smart_scripts WHERE source_type=0 AND entryorguid=@ENTRY;
INSERT INTO smart_scripts (entryorguid,source_type,id,link,event_type,event_phase_mask,event_chance,event_flags,event_param1,event_param2,event_param3,event_param4,action_type,action_param1,action_param2,action_param3,action_param4,action_param5,action_param6,target_type,target_param1,target_param2,target_param3,target_x,target_y,target_z,target_o,comment) VALUES
(@ENTRY,0,0,0,1,0,100,1,1000,1000,1000,1000,11,@SPELL,2,0,0,0,0,1,0,0,0,0,0,0,0, ‘NPC - On spawn & reset - Channel Spell’);

– Cast channeling spell with target
SET @ENTRY := XXXXX; – NPC entry
SET @SPELL := XXXXX; – Spell to cast
SET @CGUID := XXXXX; – Target creature guid
SET @CENTRY := XXXXX; – Target creature entry
UPDATE creature_template SET AIName=‘SmartAI’ WHERE entry=@ENTRY;
DELETE FROM smart_scripts WHERE source_type=0 AND entryorguid=@ENTRY;
INSERT INTO smart_scripts (entryorguid,source_type,id,link,event_type,event_phase_mask,event_chance,event_flags,event_param1,event_param2,event_param3,event_param4,action_type,action_param1,action_param2,action_param3,action_param4,action_param5,action_param6,target_type,target_param1,target_param2,target_param3,target_x,target_y,target_z,target_o,comment) VALUES
(@ENTRY,0,0,0,1,0,100,1,1000,1000,1000,1000,11,@SPELL,2,0,0,0,0,10,@CGUID,@CENTRY,0,0,0,0,0, ‘NPC - On spawn & reset - Channel spell on target’);[/sql]

This will cause all creatures of an entry to cast the channeling spell. You may only want one creature to cast it. In this case you want to set the SAI to use -guid value of the creature you wish to cast the spell like the following:

[sql]-- Cast channeling spell no target
SET @ENTRY := XXXXX; – NPC entry
SET @SPELL := XXXXX; – Spell to cast
UPDATE creature_template SET AIName=‘SmartAI’ WHERE entry=@ENTRY;
DELETE FROM smart_scripts WHERE source_type=0 AND entryorguid=-123456;
INSERT INTO smart_scripts (entryorguid,source_type,id,link,event_type,event_phase_mask,event_chance,event_flags,event_param1,event_param2,event_param3,event_param4,action_type,action_param1,action_param2,action_param3,action_param4,action_param5,action_param6,target_type,target_param1,target_param2,target_param3,target_x,target_y,target_z,target_o,comment) VALUES
(-123456,0,0,0,1,0,100,1,1000,1000,1000,1000,11,@SPELL,2,0,0,0,0,1,0,0,0,0,0,0,0, ‘NPC - On spawn & reset - Channel Spell’);

– Cast channeling spell with target
SET @ENTRY := XXXXX; – NPC entry
SET @SPELL := XXXXX; – Spell to cast
SET @CGUID := XXXXX; – Target creature guid
SET @CENTRY := XXXXX; – Target creature entry
UPDATE creature_template SET AIName=‘SmartAI’ WHERE entry=@ENTRY;
DELETE FROM smart_scripts WHERE source_type=0 AND entryorguid=-123456;
INSERT INTO smart_scripts (entryorguid,source_type,id,link,event_type,event_phase_mask,event_chance,event_flags,event_param1,event_param2,event_param3,event_param4,action_type,action_param1,action_param2,action_param3,action_param4,action_param5,action_param6,target_type,target_param1,target_param2,target_param3,target_x,target_y,target_z,target_o,comment) VALUES
(-123456,0,0,0,1,0,100,1,1000,1000,1000,1000,11,@SPELL,2,0,0,0,0,10,@CGUID,@CENTRY,0,0,0,0,0, ‘NPC - On spawn & reset - Channel spell on target’);
[/CODE]

Where 123456 is the guid of the creature who is to cast the spell. You still need to set AIName=‘SmartAI’ in creature_template for the creature entry.

Another useful option is linking. Linking is used to allow more than one action per event.

Here is an example of linked actions.

[CODE]-- SAI for Grizzly Hill Giant for the quest Rallying the Troops
SET @ENTRYGIANT := 26261; – Grizzly Hill Giant
UPDATE creature_template SET AIname = ‘SmartAI’ WHERE entry=@ENTRYGIANT;
DELETE FROM smart_scripts WHERE entryorguid=@ENTRYGIANT AND source_type=0;
INSERT INTO smart_scripts (entryorguid,source_type,id,link,event_type,event_phase_mask,event_chance,event_flags,event_param1,event_param2,event_param3,event_param4,action_type,action_param1, action_param2,action_param3,action_param4,action_param5,action_param6,target_type,target_param1,target_param2,target_param3, target_x,target_y,target_z,target_o,comment) VALUES
(@ENTRYGIANT,0,0,0,0,0,100,0,0,0,0,0,22,1,0,0,0,0,0,1,0,0,0,0,0,0,0,‘Grizzly Hill Giant - When in combat, become ready to accept buff from item Shard of Earth by switching to event phase 1.’),
(@ENTRYGIANT,0,1,2,8,1,100,0,47394,0,0,0,33,26261,0,0,0,0,0,7,0,0,0,0,0,0,0,‘Grizzly Hill Giant - Give rallied credit to the caster (for quest Rallying the Troops) when hit with spell 47394.’),
(@ENTRYGIANT,0,2,0,61,1,100,0,0,0,0,0,22,2,0,0,0,0,0,1,0,0,0,0,0,0,0,‘Grizzly Hill Giant - Switch to event phase 2 so that it will not be affected by spell again and be ready to do the next part.’),
(@ENTRYGIANT,0,3,4,0,2,100,0,3000,3000,3000,3000,12,26786,1,120000,0,0,0,1,0,0,0,0,0,0,0,‘Grizzly Hill Giant - In event phase 2, summon a Iron Rune Avenger after 3s in combat.’),
(@ENTRYGIANT,0,4,0,61,2,100,0,0,0,0,0,78,0,0,0,0,0,0,1,0,0,0,0,0,0,0,‘Grizzly Hill Giant - After summoning a Iron Rune Avenger, reset script’);[/sql]

You will notice that Event 2 is linked to Event 1. Event 1 has “2” in the linked field and Event 2 is an Event 61 “Linked”. In this arrangement the action in Event 2 will be executed immediately after the action in Event 1 if Event 1 is true.

For those of you used to EAI which allows 3 actions per Event you will need to use linking to do the same.

[/CODE]

Gossip Options:

You can script an npc to perform an action when a gossip option is clicked very easily.

[CODE]-- Librarian Tiare SAI
SET @ENTRY := 30051;
SET @GOSSIP := 9626;
SET @OPTION := 0;
UPDATE creature_template SET AIName= ‘SmartAI’ WHERE entry=@ENTRY;
DELETE FROM smart_scripts WHERE entryorguid=@ENTRY;
INSERT INTO smart_scripts (entryorguid,source_type,id,link,event_type,event_phase_mask,event_chance,event_flags,event_param1,event_param2,event_param3,event_param4,action_type,action_param1,action_param2,action_param3,action_param4,action_param5,action_param6,target_type,target_param1,target_param2,target_param3,target_x,target_y,target_z,target_o,comment) VALUES
(@ENTRY,0,0,0,62,0,100,0,@GOSSIP,@OPTION,0,0,11,50135,0,0,0,0,0,7,0,0,0,0,0,0,0, ‘Librarian Tiare - On gossip option select - Cast Teleport - Coldarra, Transitus Shield to Amber Ledge on player’);[/sql]

In the above example the npc will cast a spell on the action invoker when option 0 from gossip 9626 is selected. Note that I did not include a close gossip command as the player will fly away and the gossip will automatically close.

If you have a situation where the player will stay next to the npc after clicking the option you may want to add a close gossip and link them together as in below:

[sql]-- Librarian Tiare SAI
SET @ENTRY := 30051;
SET @GOSSIP := 9626;
SET @OPTION := 0;
UPDATE creature_template SET AIName= ‘SmartAI’ WHERE entry=@ENTRY;
DELETE FROM smart_scripts WHERE entryorguid=@ENTRY;
INSERT INTO smart_scripts (entryorguid,source_type,id,link,event_type,event_phase_mask,event_chance,event_flags,event_param1,event_param2,event_param3,event_param4,action_type,action_param1,action_param2,action_param3,action_param4,action_param5,action_param6,target_type,target_param1,target_param2,target_param3,target_x,target_y,target_z,target_o,comment) VALUES
(@ENTRY,0,0,1,62,0,100,0,@GOSSIP,@OPTION,0,0,72,0,0,0,0,0,0,7,0,0,0,0,0,0,0, ‘Librarian Tiare - On gossip option select - Close gossip’),
(@ENTRY,0,1,0,61,0,100,0,0,0,0,0,11,50135,0,0,0,0,0,7,0,0,0,0,0,0,0, ‘Librarian Tiare - On gossip option select - Cast Teleport - Coldarra, Transitus Shield to Amber Ledge on player’);
[/CODE]

You can easily add a gossip option to a gossip entry like so:

[CODE]-- add gossip menu options
SET @MENUID := XXXX; – Put the gossip id here.
SET @OPTION := XXXX; – Put the gossip option id here.
DELETE FROM gossip_menu_option WHERE menu_id=@MENUID AND id=@OPTION;;
INSERT INTO gossip_menu_option (menu_id,id,option_icon,option_text,option_id,npc_option_npcflag,action_menu_id,action_poi_id,action_script_id,box_coded,box_money,box_text) VALUES
(@MENUID,@OPTION,0,‘Put the text you wish here’,1,1,0,0,0,0,0,‘’);[/sql]

Just insert the gossip id and the text you want and you now have a gossip option.

You may wish to have a condition for your option to show if used in a quest or for another reason.

Here is an example of a gossip option condition where the player would be required to have an item on his person. You can change the ConditionTypeOrReference by referring to the condition table on the wiki.

[sql]-- add condition for gossip option
SET @MENUID := XXXX; – Put the gossip id here.
SET @OPTION := XXXX; – Put the gossip option id here.
DELETE FROM conditions WHERE SourceTypeOrReferenceId=15 AND SourceGroup=@MENUID AND SourceEntry=@OPTION;
INSERT INTO conditions (SourceTypeOrReferenceId,SourceGroup,SourceEntry,ElseGroup,ConditionTypeOrReference,ConditionValue1,ConditionValue2,ConditionValue3,ErrorTextId,ScriptName,Comment) VALUES
(15,@MENUID,@OPTION,0,2,22628,1,0,0,‘’,‘Show gossip option 0 if player has Renzithen’‘s Restorative Draught’);
[/CODE]