Hey guys. Was a while since I actually made a thread here, well..
I am working on my first C++ script for TrinityCore and I would like some feedback in order to make it better, and since I am very new to this, it would be awesome if you actually provide me some hints or code to actually complete it.
Here is the code:
Code:
enum Spells
{
// List of spells.
// Not required to define them in this way, but will make it easier to maintain in case spellId change
SPELL_SHADOWBOLT = 70281,
SPELL_DOOM = 64157,
SPELL_SUMMON = 71031,
//Transform to Bonelord
SPELL_TRANSFORM = 72498,
//Melee Form Abilities
SPELL_SOULSTRIKE = 70211,
SPELL_NECROTICSTRIKE = 70659,
SPELL_ICYTOUCH = 66021,
SPELL_FRENZY = 47774,
//Global Abilities
SPELL_MIGHT = 74507
};
//List of gossip item texts. Items will appear in the gossip window.
class Boss_Forgotten_AmirThezad : public CreatureScript
{
public:
Boss_Forgotten_AmirThezad()
: CreatureScript("Boss_Forgotten_AmirThezad")
{
}
struct Boss_Forgotten_AmirThezadAI : public ScriptedAI
{
// *** HANDLED FUNCTION ***
//This is the constructor, called only once when the Creature is first created
Boss_Forgotten_AmirThezadAI(Creature* creature) : ScriptedAI(creature) {}
// *** CUSTOM VARIABLES ****
//These variables are for use only by this individual script.
//Nothing else will ever call them but us.
uint32 Shadowbolt_Timer;
uint32 Doom_Timer;
uint32 Summon_Timer;
uint32 Transform_Timer;
uint32 Soulstrike_Timer;
uint32 Necroticstrike_Timer;
uint32 Icytouch_Timer;
uint32 Frenzy_Timer;
uint32 Phase;
// *** HANDLED FUNCTION ***
//This is called after spawn and whenever the core decides we need to evade
void Reset()
{
Phase = 1;
Shadowbolt_Timer = 5000;
Doom_Timer = 16000;
Summon_Timer = 45000;
Soulstrike_Timer = 8000;
Necroticstrike_Timer = 4000;
Icytouch_Timer = 13000;
Transform_Timer = 0;
Frenzy_Timer = 9000;
}
// *** HANDLED FUNCTION ***
// Enter Combat called once per combat
void EnterCombat(Unit* who)
{
//Say some stuff
me->MonsterYell("Welcome to my domain, adventurers. Your stay will not be long, as you will be within my command soon..", LANG_UNIVERSAL, NULL);
}
// *** HANDLED FUNCTION ***
// Attack Start is called when victim change (including at start of combat)
// By default, attack who and start movement toward the victim.
//void AttackStart(Unit* who)
//{
// ScriptedAI::AttackStart(who);
//}
// *** HANDLED FUNCTION ***
// Called when going out of combat. Reset is called just after.
void EnterEvadeMode()
{
}
// *** HANDLED FUNCTION ***
//Our Receive emote function
// *** HANDLED FUNCTION ***
//Update AI is called Every single map update (roughly once every 50ms if a player is within the grid)
void UpdateAI(const uint32 uiDiff)
{
//Out of combat timers
if (!me->getVictim())
{
}
//Return since we have no target
if (!UpdateVictim())
return;
if (((me->GetHealth()*100 / me->GetMaxHealth()) < 50) && (Phase == 1))
{
me->MonsterYell("This body can't hold out much longer, I must change!", LANG_UNIVERSAL, NULL);
Phase = 2;
}
if (((me->GetHealth()*100 / me->GetMaxHealth()) < 47) && (Phase == 2))
{
Phase = 3;
}
if (((me->GetHealth()*100 / me->GetMaxHealth()) < 1) && (Phase == 3))
{
Phase = 4;
me->MonsterYell("I have lost.. Loyal warriors of the Scourge, slay them all!", LANG_UNIVERSAL, NULL);
}
if (Phase == 1)
{
if (Shadowbolt_Timer <= uiDiff)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
DoCast(target, SPELL_SHADOWBOLT);
Shadowbolt_Timer = 5000;
}
else
Shadowbolt_Timer -= uiDiff;
if (Doom_Timer <= uiDiff)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
DoCast(target, SPELL_DOOM);
Doom_Timer = 16000;
}
else Doom_Timer -= uiDiff;
if (Summon_Timer <= uiDiff)
{
DoCast(me->getVictim(), SPELL_SUMMON);
Summon_Timer = 45000;
}
else
Summon_Timer -= uiDiff;
}
if(Phase == 2)
{
if (Transform_Timer <= uiDiff)
{
DoCast(me->getVictim(), SPELL_TRANSFORM);
Transform_Timer = 45000;
}
else Transform_Timer -= uiDiff;
}
if(Phase == 3)
{
if (Frenzy_Timer <= uiDiff)
{
DoCast(me, SPELL_FRENZY);
Frenzy_Timer = 9000;
}
else Frenzy_Timer -= uiDiff;
if (Soulstrike_Timer <= uiDiff)
{
DoCast(me->getVictim(), SPELL_SOULSTRIKE);
Soulstrike_Timer = 8000;
}
else
Soulstrike_Timer -= uiDiff;
if (Necroticstrike_Timer <= uiDiff)
{
DoCast(me->getVictim(), SPELL_NECROTICSTRIKE);
Necroticstrike_Timer = 4000;
}
else
Necroticstrike_Timer -= uiDiff;
if (Icytouch_Timer <= uiDiff)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
DoCast(target, SPELL_ICYTOUCH);
Icytouch_Timer = 13000;
}
else Icytouch_Timer -= uiDiff;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const
{
return new Boss_Forgotten_AmirThezadAI(creature);
}
};
//This is the actual function called only once durring InitScripts()
//It must define all handled functions that are to be run in this script
void AddSC_Boss_Forgotten_AmirThezad()
{
new Boss_Forgotten_AmirThezad();
}
Now to the questions:
Have I done anything wrong? (even that the script works in the-game itself)
What can I do to make it better?
Additional spells?
Additional phases?
I am asking this because I would like to make it a boss very similar to a one Blizzard would make, with tactics and so on.
Thanks for reading & I appreciate every answer I get.
Regards,
Moffeman