PDA

View Full Version : [ArcEmu][C++] Scripting a Creature



Sdyess94
27-04-10, 12:13 AM
Hello everyone! Today I would like to teach you all how to script an NPC using C++ for the ArcEmu Emulator.

I don't see a super reasonable reason to add credits to the script unless its a fairly long script or you are releasing it. But for personal use, you can skip the credits. instead, we'll begin with the header files.

The header files contain the information you will be using. For example, the header file "base.h" includes a majority, if not all, of the methods you are soon to use.



#include "StdAfx.h"
#include "Setup.h"
#include "../Common/Base.h"
Okay. So now lets create our class and the framework along with it.


#include "StdAfx.h"
#include "Setup.h"
#include "../Common/Base.h"

class FirstNPC : public MoonScriptBossAI
{
MOONSCRIPT_FACTORY_FUNCTION(FirstNPC, MoonScriptBossAI);
FirstNPC(Creature* pCreature) : MoonScriptBossAI(pCreature)
{
}

void AIUpdate()
{
ParentClass::AIUpdate();
}

void Destroy()
{
delete this;
}

};
void SetupFirstNPC(ScriptMgr * mgr)
{
mgr->register_creature_script(npcid, FirstNPC::Create);
}

Okay time to explain this a bit. The part you see in the red, is the name of your class. It is case sensitive and it must be the same each time.

The piece you see in the dark green is the method where it will register your script to the server.

The method in the Dark Orange will delete the variables and such, to avoid overflow.

The method name AIUpdate in Dark Red is what the AI will continually check to see if any changes to the AI need to be made.

Next Section!!!1!(Teehee)

Aight so, I'm guessing you want to make the boss/npc say something when a certain event happens.

So we're going to take this snippet...


FirstNPC(Creature* pCreature) : MoonScriptBossAI(pCreature)
{
}
And We're going to setup a message on combat..


MOONSCRIPT_FACTORY_FUNCTION(FirstNPC, MoonScriptBossAI);
FirstNPC(Creature* pCreature) : MoonScriptBossAI(pCreature)
{
AddEmote(Event_OnCombatStart, "OMG SDYESS IS AMAZING AND IM IN COMBAT", Text_Yell);
}
Alright so the part in the red is what we've added.

Next, in the Dark Orange we have what event is going to cause the emote to happen. You're probably wondering...what other events are there..well, here is a list! :D



Event_OnCombatStart
Event_OnTargetDied
Event_OnDied
Event_OnTaunt
Yeah not many, but there are plenty of possibilities if you create your own methods in the class...which I'll get to at one point.

Dark green is the text that the npc will say when the event occurs.

And lastly, the color...uhm turquoise? is whether the npc will say the text, yell the text, or emote(?).

Here's the list.


Text_Say
Text_Yell
Text_Emote
So maybe you're thinking now..."What if I want a sound to play during that emote?" Well its simple.
Modify like below:


AddEmote(Event_OnCombatStart, "OMG SDYESS IS AMAZING AND IM IN COMBAT", Text_Yell);

CHANGE TO

AddEmote(Event_OnCombatStart, "OMG SDYESS IS AMAZING AND IM IN COMBAT", Text_Yell, soundid);
What I have now highlighted in red, is what the sound id would be.

Never gonna guess whats next are you...? Nah you probably did. Spells!

Well, lets take our method from before


MOONSCRIPT_FACTORY_FUNCTION(FirstNPC, MoonScriptBossAI);
FirstNPC(Creature* pCreature) : MoonScriptBossAI(pCreature)
{
AddEmote(Event_OnCombatStart, "OMG SDYESS IS AMAZING AND IM IN COMBAT"[/COLOR], Text_Yell);
AddSpell(spellid, target, chance, casttime, cooldown);
}
Okay so, the spellid of course, would be the id of the spell you'd like your creature to use.

target, is who the spell will be cast on. Here is a llist of the target types.


Target_Self
Target_Current
Target_SecondMostHated
Target_Destination
Target_Predefined
Target_RandomPlayer
Target_RandomPlayerNotCurrent
Target_RandomPlayerDestination
Target_RandomPlayerApplyAura
Target_RandomUnit
Target_RandomUnitNotCurrent
Target_RandomDestination
Target_RandomUnitApplyAura
Target_RandomFriendly
Target_WoundedPlayer
Target_WoundedUnit
Target_WoundedFriendly
Target_ClosestPlayer
Target_ClosestPlayerNotCurrent
Target_ClosestUnit
Target_ClosestUnitNotCurrent
Target_ClosestFriendly
Target_ClosestCorpse
Target_RandomCorpse
chance is the percent chance that the creature has to cast its spell
casttime is how long it takes the creature to the cast the added spell
and the cooldown is the amount of time until it can be cast again.

so here's an example


AddSpell(32659, Target_Current, 100, 0, 5);
You could do something defined previously:


#define SPELL_LOLZ 32569
*SCROLL DOWN*
AddSpell(SPELL_LOLZ, Target_current, 100, 0, 5);
I only recommend the above method when doing a large script.

So here is what you should have so far:


#include "StdAfx.h"
#include "Setup.h"
#include "../Common/Base.h"

class FirstNPC : public MoonScriptBossAI
{
MOONSCRIPT_FACTORY_FUNCTION(FirstNPC, MoonScriptBossAI);
FirstNPC(Creature* pCreature) : MoonScriptBossAI(pCreature)
{
AddEmote(Event_OnCombatStart, "OMG SDYESS IS AMAZING AND IM IN COMBAT", Text_Yell);
AddSpell(50000, Target_Current, 100, 0, 20);
}

void AIUpdate()
{
ParentClass::AIUpdate();
}

void Destroy()
{
delete this;
}

};
void SetupFirstNPC(ScriptMgr * mgr)
{
mgr->register_creature_script(npcid, FirstNPC::Create);
}
Next Section, AIUpdate and how it works.

Alright, so now, we're going to go ahead and move onto AIUpdate and how it works.

Essentially, this is what allows the creature to change what it does. Its like when you register an event a Lua I guess.

Okay so lets start of with some health percent phases.



void AIUpdate()
{
if(GetPhase() == 1)
{
if(_unit->GetHealthPct() <= 80 )
{
Emote("Now feel my wrath!, Text_Yell);
SetPhase(2);
}
}
else if(GetPhase() == 2)
{
if(_unit->GetHealthPct() <= 45 )
{
Emote("I require heals!, Text_Yell);
SetPhase(3);
}
}
else if(GetPhase() == 3)
{
if(_unit->GetHealthPct() <= 20 )
{
Emote("OH NOES!", Text_Yell);
}
}
ParentClass::AIUpdate();
}
Okay so maybe you're thinking, "You didnt even add any spells you loser!".. Well, this is where they get added in, its simple and practically just like the AddSpell method.

So we're going to go back to on of the blocks from earlier.


MOONSCRIPT_FACTORY_FUNCTION(FirstNPC, MoonScriptBossAI);
FirstNPC(Creature* pCreature) : MoonScriptBossAI(pCreature)
{
AddEmote(Event_OnCombatStart, "OMG SDYESS IS AMAZING AND IM IN COMBAT", Text_Yell);
AddSpell(50000, Target_Current, 100, 0, 20);
AddPhaseSpell(2, AddSpell(5, Target_RandomPlayer, 100, 0, 30));
AddPhaseSpell(3, AddSpell(5, Target_Current, 100, 0, 28));

}

What I have just added(the part in the red and piece below it) are spells that will only be used in the phase set.

The number that is Dark orange is the phase that the spell is used in.
The part in Turquiose, is where the spell is added. Its like the AddSpell before, except added into this one :)

And here is your end result:


#include "StdAfx.h"
#include "Setup.h"
#include "../Common/Base.h"

class FirstNPC : public MoonScriptBossAI
{
MOONSCRIPT_FACTORY_FUNCTION(FirstNPC, MoonScriptBossAI);
FirstNPC(Creature* pCreature) : MoonScriptBossAI(pCreature)
{
AddEmote(Event_OnCombatStart, "OMG SDYESS IS AMAZING AND IM IN COMBAT", Text_Yell);
AddSpell(50000, Target_Current, 100, 0, 20);
AddPhaseSpell(2, AddSpell(5, Target_RandomPlayer, 100, 0, 30));
AddPhaseSpell(3, AddSpell(5, Target_Current, 100, 0, 28));

}
void AIUpdate()
{
if(GetPhase() == 1)
{
if(_unit->GetHealthPct() <= 80 )
{
Emote("Now feel my wrath!, Text_Yell);
SetPhase(2);
}
}
else if(GetPhase() == 2)
{
if(_unit->GetHealthPct() <= 45 )
{
Emote("I require heals!, Text_Yell);
SetPhase(3);
}
}
else if(GetPhase() == 3)
{
if(_unit->GetHealthPct() <= 20 )
{
Emote("OH NOES!", Text_Yell);
}
}
ParentClass::AIUpdate();
}

void Destroy()
{
delete this;
}

};
void SetupFirstNPC(ScriptMgr * mgr)
{
mgr->register_creature_script(npcid, FirstNPC::Create);
}
If you currently have any Questions, comments, or concerns, please add me on msn at [email protected] or send me a PM

If theres something else you'd like to see added just reply :)

Posted in wrong section. Please move when you see it :P

Dimman
27-04-10, 10:44 AM
Thanks for this Sydess +Rep ;)

StickyIcky
02-05-10, 02:56 AM
I'll read this when I'm sober.

But looks nice, remind me to rep you in a few days for this, need to spread it around :P