R.I.P SimpleAI

- Convert SimpleAI to (DB) SmartAI
- Spell ids corrected (and completed some of the scripts)
- Random cleanup (code style) in some scripts
This commit is contained in:
Nay
2012-03-11 16:59:17 +00:00
parent 036dae5a36
commit 2b2d054f64
10 changed files with 373 additions and 938 deletions
@@ -1,280 +0,0 @@
/*
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
* Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* ScriptData
SDName: SimpleAI
SD%Complete: 100
SDComment: Base Class for SimpleAI creatures
SDCategory: Creatures
EndScriptData */
#include "ScriptPCH.h"
#include "ScriptedSimpleAI.h"
SimpleAI::SimpleAI(Creature* c) : ScriptedAI(c)
{
//Clear all data
Aggro_TextId[0] = 0;
Aggro_TextId[1] = 0;
Aggro_TextId[2] = 0;
Aggro_Sound[0] = 0;
Aggro_Sound[1] = 0;
Aggro_Sound[2] = 0;
Death_TextId[0] = 0;
Death_TextId[1] = 0;
Death_TextId[2] = 0;
Death_Sound[0] = 0;
Death_Sound[1] = 0;
Death_Sound[2] = 0;
Death_Spell = 0;
Death_Target_Type = 0;
Kill_TextId[0] = 0;
Kill_TextId[1] = 0;
Kill_TextId[2] = 0;
Kill_Sound[0] = 0;
Kill_Sound[1] = 0;
Kill_Sound[2] = 0;
Kill_Spell = 0;
Kill_Target_Type = 0;
memset(Spell, 0, sizeof(Spell));
EnterEvadeMode();
}
void SimpleAI::Reset()
{
}
void SimpleAI::EnterCombat(Unit* who)
{
//Reset cast timers
if (Spell[0].First_Cast >= 0)
Spell_Timer[0] = Spell[0].First_Cast;
else Spell_Timer[0] = 1000;
if (Spell[1].First_Cast >= 0)
Spell_Timer[1] = Spell[1].First_Cast;
else Spell_Timer[1] = 1000;
if (Spell[2].First_Cast >= 0)
Spell_Timer[2] = Spell[2].First_Cast;
else Spell_Timer[2] = 1000;
if (Spell[3].First_Cast >= 0)
Spell_Timer[3] = Spell[3].First_Cast;
else Spell_Timer[3] = 1000;
if (Spell[4].First_Cast >= 0)
Spell_Timer[4] = Spell[4].First_Cast;
else Spell_Timer[4] = 1000;
if (Spell[5].First_Cast >= 0)
Spell_Timer[5] = Spell[5].First_Cast;
else Spell_Timer[5] = 1000;
if (Spell[6].First_Cast >= 0)
Spell_Timer[6] = Spell[6].First_Cast;
else Spell_Timer[6] = 1000;
if (Spell[7].First_Cast >= 0)
Spell_Timer[7] = Spell[7].First_Cast;
else Spell_Timer[7] = 1000;
if (Spell[8].First_Cast >= 0)
Spell_Timer[8] = Spell[8].First_Cast;
else Spell_Timer[8] = 1000;
if (Spell[9].First_Cast >= 0)
Spell_Timer[9] = Spell[9].First_Cast;
else Spell_Timer[9] = 1000;
uint8 random_text = urand(0, 2);
//Random text
if (Aggro_TextId[random_text])
DoScriptText(Aggro_TextId[random_text], me, who);
//Random sound
if (Aggro_Sound[random_text])
DoPlaySoundToSet(me, Aggro_Sound[random_text]);
}
void SimpleAI::KilledUnit(Unit* victim)
{
uint8 random_text = urand(0, 2);
//Random yell
if (Kill_TextId[random_text])
DoScriptText(Kill_TextId[random_text], me, victim);
//Random sound
if (Kill_Sound[random_text])
DoPlaySoundToSet(me, Kill_Sound[random_text]);
if (!Kill_Spell)
return;
Unit* target = NULL;
switch (Kill_Target_Type)
{
case CAST_SELF:
target = me;
break;
case CAST_HOSTILE_TARGET:
target = me->getVictim();
break;
case CAST_HOSTILE_SECOND_AGGRO:
target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1);
break;
case CAST_HOSTILE_LAST_AGGRO:
target = SelectTarget(SELECT_TARGET_BOTTOMAGGRO, 0);
break;
case CAST_HOSTILE_RANDOM:
target = SelectTarget(SELECT_TARGET_RANDOM, 0);
break;
case CAST_KILLEDUNIT_VICTIM:
target = victim;
break;
}
//Target is ok, cast a spell on it
if (target)
DoCast(target, Kill_Spell);
}
void SimpleAI::DamageTaken(Unit* killer, uint32& damage)
{
//Return if damage taken won't kill us
if (me->GetHealth() > damage)
return;
uint8 random_text = urand(0, 2);
//Random yell
if (Death_TextId[random_text])
DoScriptText(Death_TextId[random_text], me, killer);
//Random sound
if (Death_Sound[random_text])
DoPlaySoundToSet(me, Death_Sound[random_text]);
if (!Death_Spell)
return;
Unit* target = NULL;
switch (Death_Target_Type)
{
case CAST_SELF:
target = me;
break;
case CAST_HOSTILE_TARGET:
target = me->getVictim();
break;
case CAST_HOSTILE_SECOND_AGGRO:
target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1);
break;
case CAST_HOSTILE_LAST_AGGRO:
target = SelectTarget(SELECT_TARGET_BOTTOMAGGRO, 0);
break;
case CAST_HOSTILE_RANDOM:
target = SelectTarget(SELECT_TARGET_RANDOM, 0);
break;
case CAST_JUSTDIED_KILLER:
target = killer;
break;
}
//Target is ok, cast a spell on it
if (target)
DoCast(target, Death_Spell);
}
void SimpleAI::UpdateAI(const uint32 diff)
{
//Return since we have no target
if (!UpdateVictim())
return;
//Spells
for (uint32 i = 0; i < MAX_SIMPLEAI_SPELLS; ++i)
{
//Spell not valid
if (!Spell[i].Enabled || !Spell[i].Spell_Id)
continue;
if (Spell_Timer[i] <= diff)
{
//Check if this is a percentage based
if (Spell[i].First_Cast < 0 && Spell[i].First_Cast > -100 && HealthAbovePct(uint32(-Spell[i].First_Cast)))
continue;
//Check Current spell
if (!(Spell[i].InterruptPreviousCast && me->IsNonMeleeSpellCasted(false)))
{
Unit* target = NULL;
switch (Spell[i].Cast_Target_Type)
{
case CAST_SELF:
target = me;
break;
case CAST_HOSTILE_TARGET:
target = me->getVictim();
break;
case CAST_HOSTILE_SECOND_AGGRO:
target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1);
break;
case CAST_HOSTILE_LAST_AGGRO:
target = SelectTarget(SELECT_TARGET_BOTTOMAGGRO, 0);
break;
case CAST_HOSTILE_RANDOM:
target = SelectTarget(SELECT_TARGET_RANDOM, 0);
break;
}
//Target is ok, cast a spell on it and then do our random yell
if (target)
{
if (me->IsNonMeleeSpellCasted(false))
me->InterruptNonMeleeSpells(false);
DoCast(target, Spell[i].Spell_Id);
//Yell and sound use the same number so that you can make
//the Creature yell with the correct sound effect attached
uint8 random_text = urand(0, 2);
//Random yell
if (Spell[i].TextId[random_text])
DoScriptText(Spell[i].TextId[random_text], me, target);
//Random sound
if (Spell[i].Text_Sound[random_text])
DoPlaySoundToSet(me, Spell[i].Text_Sound[random_text]);
}
}
//Spell will cast agian when the cooldown is up
if (Spell[i].CooldownRandomAddition)
Spell_Timer[i] = Spell[i].Cooldown + (rand() % Spell[i].CooldownRandomAddition);
else Spell_Timer[i] = Spell[i].Cooldown;
} else Spell_Timer[i] -= diff;
}
DoMeleeAttackIfReady();
}
@@ -1,73 +0,0 @@
/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
* This program is free software licensed under GPL version 2
* Please see the included DOCS/LICENSE.TXT for more information */
#ifndef SC_SIMPLEAI_H
#define SC_SIMPLEAI_H
enum CastTarget
{
CAST_SELF = 0, //Self cast
CAST_HOSTILE_TARGET, //Our current target (ie: highest aggro)
CAST_HOSTILE_SECOND_AGGRO, //Second highest aggro (generaly used for cleaves and some special attacks)
CAST_HOSTILE_LAST_AGGRO, //Dead last on aggro (no idea what this could be used for)
CAST_HOSTILE_RANDOM, //Just any random target on our threat list
CAST_FRIENDLY_RANDOM, //NOT YET IMPLEMENTED
//Special cases
CAST_KILLEDUNIT_VICTIM, //Only works within KilledUnit function
CAST_JUSTDIED_KILLER, //Only works within JustDied function
};
#define MAX_SIMPLEAI_SPELLS 10
struct SimpleAI : public ScriptedAI
{
SimpleAI(Creature* c);// : ScriptedAI(c);
void Reset();
void EnterCombat(Unit* /*who*/);
void KilledUnit(Unit* /*victim*/);
void DamageTaken(Unit* killer, uint32& damage);
void UpdateAI(const uint32 diff);
public:
int32 Aggro_TextId[3];
uint32 Aggro_Sound[3];
int32 Death_TextId[3];
uint32 Death_Sound[3];
uint32 Death_Spell;
uint32 Death_Target_Type;
int32 Kill_TextId[3];
uint32 Kill_Sound[3];
uint32 Kill_Spell;
uint32 Kill_Target_Type;
struct SimpleAI_Spell
{
uint32 Spell_Id; //Spell ID to cast
int32 First_Cast; //Delay for first cast
uint32 Cooldown; //Cooldown between casts
uint32 CooldownRandomAddition; //Random addition to cooldown (in range from 0 - CooldownRandomAddition)
uint32 Cast_Target_Type; //Target type (note that certain spells may ignore this)
bool InterruptPreviousCast; //Interrupt a previous cast if this spell needs to be cast
bool Enabled; //Spell enabled or disabled (default: false)
//3 texts to many?
int32 TextId[3];
uint32 Text_Sound[3];
}Spell[MAX_SIMPLEAI_SPELLS];
protected:
uint32 Spell_Timer[MAX_SIMPLEAI_SPELLS];
};
#endif