/* Copyright (C) 2006,2007 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../sc_defines.h"
#define generic_creature_beta_COOLDOWN 5000
struct MANGOS_DLL_DECL generic_creature_betaAI : public ScriptedAI
{
generic_creature_betaAI(Creature *c) : ScriptedAI(c) {Reset();}
uint32 GlobalCooldown; //This variable acts like the global cooldown that players have (1.5 seconds)
uint32 BuffTimer; //This variable keeps track of buffs
bool InCombat;
bool IsFeared; //This variable keeps track of fear asura
bool IsFlee; //This variable keeps track of fleeing humanoids
bool HasFled; //This variable keeps track of fleeing humanoids make sure only 1 chance
bool SlowSpell; //This variable keeps track of auras that increase casting times
bool CanFlee; //This variable keeps of creatures that can flee from battle
bool IsHuman; //This variable states with creature is human.
void Reset()
{
GlobalCooldown = 0;
BuffTimer = 0; //Rebuff as soon as we can
InCombat = false;
IsFeared = false;
IsFlee = false;
SlowSpell = false;
HasFled = false;
CanFlee = false;
if (m_creature->GetCreatureType() == CREATURE_TYPE_HUMANOID)
{IsHuman = true;}
else
{IsHuman = false;}
m_creature->RemoveAllAuras();
m_creature->DeleteThreatList();
m_creature->CombatStop();
DoGoHome();
}
void AttackStart(Unit *who)
{
if (!who)
return;
if (who->isTargetableForAttack() && who!= m_creature)
{
//Begin melee attack if we are within range
DoStartMeleeAttack(who);
InCombat = true;
}
}
void MoveInLineOfSight(Unit *who)
{
if (!who || m_creature->getVictim())
return;
// detect family member that needs help
//here need to add check for freindly move in line of sight with fear aura & same familiy
//then attack what make freindly unit flee.
if (m_creature->IsFriendlyTo(who) && who->hasUnitState(UNIT_STAT_FLEEING) && m_creature->GetDistanceZ(who) <= 1 && m_creature->IsWithinLOSInMap(who) && !InCombat)
{
float attackRadius = (m_creature->GetAttackDistance(who) /3);
if (m_creature->IsWithinDistInMap(who, attackRadius))
{
Unit* target = NULL;
target = who->getVictim();
DoStartMeleeAttack(target);
if (rand() % 3 == 0)
{
who->RemoveSpellsCausingAura(SPELL_AURA_MOD_FEAR);
}
}
}
if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who))
{
float attackRadius = m_creature->GetAttackDistance(who);
if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who))
{
if(who->HasStealthAura())
who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
//Begin melee attack if we are within range
DoStartMeleeAttack(who);
InCombat = true;
}
}
}
void UpdateAI(const uint32 diff)
{
//Always decrease our global cooldown first
if (GlobalCooldown > diff)
{GlobalCooldown -= diff;}
else
{ GlobalCooldown = 0;}
//Check to see if creature is able to flee from battle or not
if ((m_creature->GetHealth()*6.66 < m_creature->GetMaxHealth()) && IsHuman)
{CanFlee = true;}
else
{CanFlee = false;}
// other checked need adding for other auras that effect creature spell casting times with possible rank support
if (m_creature->HasAuraType(SPELL_AURA_HASTE_SPELLS)
|| m_creature->HasAuraType(SPELL_AURA_MOD_LANGUAGE))
{
if (!SlowSpell)
{GlobalCooldown *= 2;
SlowSpell = true;}
else
{SlowSpell = false;}
}
// Check for fear, may need to add other things here like polymorph and others that render creature useless for XX seconds
if ((m_creature->HasAuraType(SPELL_AURA_MOD_FEAR))
|| (m_creature->HasAuraType(SPELL_AURA_MOD_CHARM))
|| (m_creature->HasAuraType(SPELL_AURA_MOD_POSSESS)))
//set IsFeared = true dissables all spell casting abilities last on int he script
{IsFeared = true;}
else
{IsFeared = false;}
// Make humaniod flee for 6-10 seconds, @ 15% HP give 30% chance to flee aslong as not stuned
if (!HasFled)
{
if (!IsFlee && !IsFeared && CanFlee && (!m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE)) && ((!m_creature->hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNDED | UNIT_STAT_ROOT)) || !m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED) || (!m_creature->HasAuraType(SPELL_AURA_PREVENTS_FLEEING) )) )
{
if (rand() % 3 == 0)
{
//Cancel our current spell
m_creature->InterruptSpell(CURRENT_GENERIC_SPELL);
//This is a semi work around, core needs a Flee_Movement_Gen
m_creature->CastSpell(m_creature,8225, true); // self cast run away
IsFeared = true;
IsFlee = true;
HasFled = true;
}
else
{HasFled = true;} //prevent multi checks to flee
}
}
if (!IsFeared)
{
//Buff timer (only buff when we are alive and not in combat
if (!InCombat && m_creature->isAlive())
{
if (BuffTimer < diff )
{
//Find a spell that targets friendly and applies an aura (these are generally buffs)
SpellEntry const *info = SelectSpell(m_creature, -1, -1, SELECT_TARGET_ANY_FRIEND, 0, 0, 0, 0, SELECT_EFFECT_AURA);
if (info && !GlobalCooldown && !m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED) )
{
//Cast the buff spell
DoCastSpell(m_creature, info);
//Set our global cooldown
GlobalCooldown = generic_creature_beta_COOLDOWN;
//Set our timer to 10 minutes before rebuff
BuffTimer = 600000;
}//Try agian in 30 seconds
else BuffTimer = 30000;
} else BuffTimer -= diff;
}
//Return since we have no target
if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() )
return;
//If we are within range melee the target
if( m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE))
{
//Make sure our attack is ready and we arn't currently casting
if( m_creature->isAttackReady() && !m_creature->IsNonMeleeSpellCasted(false) && !m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED) )
{
bool Healing = false;
SpellEntry const *info = NULL;
//Select a healing spell if less than 30% hp
if (m_creature->GetHealth()*3.33 < m_creature->GetMaxHealth())
info = SelectSpell(m_creature, -1, -1, SELECT_TARGET_ANY_FRIEND, 0, 0, 0, 0, SELECT_EFFECT_HEALING);
//No healing spell available, select a hostile spell
if (info)
Healing = true;
else
info = SelectSpell(m_creature->getVictim(), -1, -1, SELECT_TARGET_ANY_ENEMY, 0, 0, 0, 0, SELECT_EFFECT_DONTCARE);
//50% chance if elite or higher, 20% chance if not, to replace our white hit with a spell
if (info && (rand() % (m_creature->GetCreatureInfo()->rank > 1 ? 2 : 5) == 0) && !GlobalCooldown)
{
//Cast the spell
if (Healing)
DoCastSpell(m_creature, info);
else
DoCastSpell(m_creature->getVictim(), info);
//Set our global cooldown
GlobalCooldown = generic_creature_beta_COOLDOWN;
} else
{
m_creature->AttackerStateUpdate(m_creature->getVictim());
}
m_creature->resetAttackTimer();
}
} else
{
//Only run this code if we arn't already casting
if (!m_creature->IsNonMeleeSpellCasted(false) && !m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED) )
{
bool Healing = false;
SpellEntry const *info = NULL;
//Select a healing spell if less than 30% hp ONLY 33% of the time
if (m_creature->GetHealth()*3.33 < m_creature->GetMaxHealth() && rand() % 3 == 0)
info = SelectSpell(m_creature, -1, -1, SELECT_TARGET_ANY_FRIEND, 0, 0, 0, 0, SELECT_EFFECT_HEALING);
//No healing spell available, See if we can cast a ranged spell (Range must be greater than ATTACK_DISTANCE)
if (info)
Healing = true;
else
info = SelectSpell(m_creature->getVictim(), -1, -1, SELECT_TARGET_ANY_ENEMY, 0, 0, ATTACK_DISTANCE, 0, SELECT_EFFECT_DONTCARE);
//Found a spell, check if we arn't on cooldown
if (info && !GlobalCooldown)
{
//If we are currently moving stop us and set the movement generator
/* if (!IsSelfRooted)
{
IsSelfRooted = true;
}*/
//Face target
DoFaceTarget(m_creature->getVictim());
//Cast spell
if (Healing)
DoCastSpell(m_creature,info);
else
DoCastSpell(m_creature->getVictim(),info);
//Set our global cooldown
GlobalCooldown = generic_creature_beta_COOLDOWN;
}
}
}
}
}
};
CreatureAI* GetAI_generic_creature_beta(Creature *_Creature)
{
return new generic_creature_betaAI (_Creature);
}
void AddSC_generic_creature_beta()
{
Script *newscript;
newscript = new Script;
newscript->Name="generic_creature_beta";
newscript->GetAI = GetAI_generic_creature_beta;
m_scripts[nrscripts++] = newscript;
}