[3.3.5] Mini Boss C ++ Tutorial

dokuro

Veteran Member
Verified Member
31
2020
8
Location
Paris
[3.3.5] Mini Boss C ++ Tutorial


In this tutorial we will then see how to just create a little boss.

The start script is as follows:


#include "ScriptMgr.h"

enum Spells
{
};

class World_Boss : public CreatureScript
{
public:
World_Boss() : CreatureScript("World_Boss") { } // script name onto the DB


struct World_BossAI : public ScriptedAI
{

World_BossAI(Creature* creature) : ScriptedAI(creature) {}

void JustEngagedWith(Unit* /*who*/) override
{
}


void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;

DoMeleeAttackIfReady();
}
};

CreatureAI* GetAI(Creature* creature) const
{
return new World_BossAI(creature);
}
};

void AddSC_World_Boss()
{
new World_Boss();
}

In the type enums Spells we will take some easy to use spell, a cleave, and an enrage, nothing more simple.


enum Spells
{
SPELL_CLEAVE = 15284,
SPELL_ENRAGE = 27680
};


Then there are several functions available like the one we are going to use:


void JustEngagedWith (Unit * / * who * /) // Function called when combat is engaged
void JustDied (Unit * / * killer * /) // Function called when the creature is dead
void KilledUnit (Unit * / * victim * /) // Function called when the creature kills someone

We will start by using the main function.

void UpdateAI(uint32 diff)


This function is performed approximately every 100ms or more. This is where the script will take place.
We start by adding 2-3 lines necessary.


void UpdateAI (uint32 diff) override
{
if (! UpdateVictim ()) // Required, otherwise the creature will not catch you
return;
DoMeleeAttackIfReady (); // To have the creature perform melee attacks
}


As the void UpdateAI (uint32 diff) function is "a timer" we will use it to create "a timer / counter" to tell when I want to cast a spell.
Let's start with the enrage technique why not launch it at 20% of the creature's life -> easy.

if (HealthBelowPct (20)) // IF 20% life
{
DoCast (me, SPELL_ENRAGE); // He casts a spell on him
}


Warning ! We must add a condition otherwise the creature cast the spell without stopping.


bool enraged;
void JustEngagedWith(Unit* /*who*/) override
{
enraged = false;
}

void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;

if(HealthBelowPct(20) && !enraged)
{
DoCast(me,SPELL_ENRAGE);
enraged = true;
}
DoMeleeAttackIfReady();
}


Then we will ask the creature to do some technique. We start by creating a new variable that will contain a value in milliseconds.

uint32 spell_cleave_timer;
bool enraged;

void JustEngagedWith(Unit* /*who*/) override
{
spell_cleave_timer = 10000; //10sec
enraged = false;
}

As we all know 1000ms = 1 sec, so 10000ms = 10 sec. So the moment the fight begins the creature will cast the spell about 10 sec later.

void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
if(spell_cleave_timer <= diff)
{
DoCastVictim(SPELL_CLEAVE);
spell_cleave_timer = 10000;
}
else spell_cleave_timer -= diff;
if(HealthBelowPct(20) && !enraged)
{
DoCast(me,SPELL_ENRAGE);
enraged = true;
}
DoMeleeAttackIfReady();
}

We use here, simply the function:

DoCastVictim(SPELL_CLEAVE);

The technique will be launched on that target.
We might as well have done it another way:

Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0);
DoCast(target,SPELL_ENRAGE);

Here he selects a target at random, but there is another possibility:

SELECT_TARGET_RANDOM, // choose a random target
SELECT_TARGET_MAXTHREAT, // Choose a target with a high threat level
SELECT_TARGET_MINTHREAT, // Choose a target with a low threat level
SELECT_TARGET_MAXDISTANCE, // Choose a target further
SELECT_TARGET_MINDISTANCE // Choose a closer target

Of course the "0" next to SELECT_TARGET_RANDOM is not insignificant, example:

(SELECT_TARGET_RANDOM, 0) // Choose a random target
(SELECT_TARGET_RANDOM, 1) // Choose a random target at close range
(SELECT_TARGET_RANDOM, 2) // Choose a random target at medium distance
(SELECT_TARGET_RANDOM, 3) // Choose a random target over long distances
(SELECT_TARGET_RANDOM, 4) // Choose a random target with mana
(SELECT_TARGET_RANDOM, 5) // Choose a random target with rage
(SELECT_TARGET_RANDOM, 6) // Choose a random target with energy




also complete this script by calling a new creature during combat.
Rebelote, we redeclare a new variable:

uint32 Spawn_Timer;
Spawn_Timer = 25000;//25sec
if(Spawn_Timer <= diff)
{
me->SummonCreature(17895, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,1000);
Spawn_Timer = 25000;
}
else Spawn_Timer -= diff;



the TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT function allows the creature to disappear 1 sec after the end of the fight. We also have another proposal:

TEMPSUMMON_TIMED_OR_DEAD_DESPAWN // Despawns after a specific time or when the boss disappears
TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN // Despawns after a specific time or when the creature dies
TEMPSUMMON_TIMED_DESPAWN // Despawns after a specific time
TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT // Despawns after a specific time or when the fight ends
TEMPSUMMON_CORPSE_DESPAWN // Despawns after death
TEMPSUMMON_CORPSE_TIMED_DESPAWN // Despawns after a specific time after death
TEMPSUMMON_DEAD_DESPAWN // Despawns when the creature disappears
TEMPSUMMON_MANUAL_DESPAWN // Despawns when the UnSummon () function is used

We can finish this tutorial by expanding it all with some word using the "Talk (ID)" function, as follows:
We need to create a new text in the DB, use "creature_text".
To know more about this DB I let you check here.
I give you a small SQL script as an example:


SET
@CreatureID = 45000,
@Text = "Que trépasse si je faiblis !",
@comment = "Boos Tutoriel";

INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
(@CreatureID, '0', '0', @Text, '12', '0', '100', '0', '0', '0', '0', '0', @comment);

We just need to put our function in the script.


void JustEngagedWith(Unit* /*who*/) override
{
Spawn_Timer = 25000;
spell_cleave_timer = 10000; //10sec
enraged = false;
Talk(0);
}

In the end, we have this little code:

#include "ScriptMgr.h"

enum Spells
{
SPELL_CLEAVE = 15284,
SPELL_ENRAGE = 27680
};

class World_Boss : public CreatureScript
{
public:
World_Boss() : CreatureScript("World_Boss") { } // script name onto the DB


struct World_BossAI : public ScriptedAI
{

World_BossAI(Creature* creature) : ScriptedAI(creature) {}

uint32 spell_cleave_timer;
uint32 Spawn_Timer;
bool enraged;

void JustEngagedWith(Unit* /*who*/) override
{
Spawn_Timer = 25000;
spell_cleave_timer = 10000; //10sec
enraged = false;
Talk(0);
}

void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
if(spell_cleave_timer <= diff)
{
DoCastVictim(SPELL_CLEAVE);
spell_cleave_timer = 10000;
}
else spell_cleave_timer -= diff;
if(Spawn_Timer <= diff)
{
me->SummonCreature(17895, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,1000);
Spawn_Timer = 25000;
}
else Spawn_Timer -= diff;
if(HealthBelowPct(20) && !enraged)
{
DoCast(me,SPELL_ENRAGE);
enraged = true;
}
DoMeleeAttackIfReady();
}

};

CreatureAI* GetAI(Creature* creature) const
{
return new World_BossAI(creature);
}
};

void AddSC_World_Boss()
{
new World_Boss();
}

Credit to : Killit from Open-Wow
 
Last edited by a moderator:
Top