diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bindings/scripts/include/sc_creature.cpp | 24 | ||||
-rw-r--r-- | src/bindings/scripts/include/sc_creature.h | 3 | ||||
-rw-r--r-- | src/game/Creature.cpp | 14 | ||||
-rw-r--r-- | src/game/Creature.h | 4 | ||||
-rw-r--r-- | src/game/CreatureAI.cpp | 25 | ||||
-rw-r--r-- | src/game/CreatureAI.h | 3 | ||||
-rw-r--r-- | src/game/NullCreatureAI.cpp | 25 | ||||
-rw-r--r-- | src/game/NullCreatureAI.h | 12 | ||||
-rw-r--r-- | src/game/PetAI.cpp | 97 | ||||
-rw-r--r-- | src/game/PetAI.h | 2 | ||||
-rw-r--r-- | src/game/PetHandler.cpp | 4 | ||||
-rw-r--r-- | src/game/PossessedAI.cpp | 102 | ||||
-rw-r--r-- | src/game/PossessedAI.h | 28 | ||||
-rw-r--r-- | src/game/Unit.cpp | 31 | ||||
-rw-r--r-- | src/game/Unit.h | 3 |
15 files changed, 118 insertions, 259 deletions
diff --git a/src/bindings/scripts/include/sc_creature.cpp b/src/bindings/scripts/include/sc_creature.cpp index 47bc01f183c..be37c66c740 100644 --- a/src/bindings/scripts/include/sc_creature.cpp +++ b/src/bindings/scripts/include/sc_creature.cpp @@ -169,30 +169,6 @@ void ScriptedAI::DoStartNoMovement(Unit* victim) m_creature->StopMoving(); } - -void ScriptedAI::DoMeleeAttackIfReady() -{ - //Make sure our attack is ready and we aren't currently casting before checking distance - if (m_creature->isAttackReady() && !m_creature->hasUnitState(UNIT_STAT_CASTING)) - { - //If we are within range melee the target - if (m_creature->IsWithinMeleeRange(m_creature->getVictim())) - { - m_creature->AttackerStateUpdate(m_creature->getVictim()); - m_creature->resetAttackTimer(); - } - } - if (m_creature->haveOffhandWeapon() && m_creature->isAttackReady(OFF_ATTACK) && !m_creature->hasUnitState(UNIT_STAT_CASTING)) - { - //If we are within range melee the target - if (m_creature->IsWithinMeleeRange(m_creature->getVictim())) - { - m_creature->AttackerStateUpdate(m_creature->getVictim(), OFF_ATTACK); - m_creature->resetAttackTimer(OFF_ATTACK); - } - } -} - void ScriptedAI::DoStopAttack() { if (m_creature->getVictim() != NULL) diff --git a/src/bindings/scripts/include/sc_creature.h b/src/bindings/scripts/include/sc_creature.h index f9eb8c716d5..5e0e185a9dd 100644 --- a/src/bindings/scripts/include/sc_creature.h +++ b/src/bindings/scripts/include/sc_creature.h @@ -113,9 +113,6 @@ struct TRINITY_DLL_DECL ScriptedAI : public CreatureAI //Start no movement on victim void DoStartNoMovement(Unit* victim); - //Do melee swing of current victim if in rnage and ready and not casting - void DoMeleeAttackIfReady(); - //Stop attack of current victim void DoStopAttack(); diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 00e826404e6..ed2f3f2ee54 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -46,7 +46,6 @@ #include "CellImpl.h" #include "OutdoorPvPMgr.h" #include "GameEvent.h" -#include "PossessedAI.h" #include "CreatureGroups.h" // apply implementation of the singletons #include "Policies/SingletonImp.h" @@ -141,7 +140,7 @@ bool AssistDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) } Creature::Creature() : -Unit(), i_AI(NULL), +Unit(), lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), lootingGroupLeaderGUID(0), m_lootMoney(0), m_lootRecipient(0), m_deathTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_respawnradius(0.0f), @@ -424,7 +423,7 @@ void Creature::Update(uint32 diff) setDeathState( JUST_ALIVED ); //Call AI respawn virtual function - i_AI->JustRespawned(); + AI()->JustRespawned(); GetMap()->Add(this); } @@ -484,6 +483,9 @@ void Creature::Update(uint32 diff) if(!isAlive()) break; + // if creature is charmed, switch to charmed AI + UpdateCharmAI(); + if(!IsInEvadeMode() && IsAIEnabled) { // do not allow the AI to be changed during update @@ -596,11 +598,9 @@ bool Creature::AIM_Initialize(CreatureAI* ai) return false; } - CreatureAI * oldAI = i_AI; - i_motionMaster.Initialize(); + if(i_AI) delete i_AI; i_AI = ai ? ai : FactorySelector::selectAI(this); - if (oldAI) - delete oldAI; + i_motionMaster.Initialize(); IsAIEnabled = true; return true; } diff --git a/src/game/Creature.h b/src/game/Creature.h index fc5318c1cdb..b477ea00f1d 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -401,8 +401,6 @@ typedef std::map<uint32,time_t> CreatureSpellCooldowns; class TRINITY_DLL_SPEC Creature : public Unit { - CreatureAI *i_AI; - public: explicit Creature(); @@ -468,7 +466,7 @@ class TRINITY_DLL_SPEC Creature : public Unit bool AIM_Initialize(CreatureAI* ai = NULL); void AI_SendMoveToPacket(float x, float y, float z, uint32 time, uint32 MovementFlags, uint8 type); - CreatureAI* AI() { return i_AI; } + CreatureAI* AI() { return (CreatureAI*)i_AI; } uint32 GetShieldBlockValue() const //dunno mob block value { diff --git a/src/game/CreatureAI.cpp b/src/game/CreatureAI.cpp index fa512fce726..2d7eeeb18ff 100644 --- a/src/game/CreatureAI.cpp +++ b/src/game/CreatureAI.cpp @@ -36,11 +36,34 @@ void UnitAI::AttackStart(Unit *victim) } } +void UnitAI::DoMeleeAttackIfReady() +{ + //Make sure our attack is ready and we aren't currently casting before checking distance + if (me->isAttackReady() && !me->hasUnitState(UNIT_STAT_CASTING)) + { + //If we are within range melee the target + if (me->IsWithinMeleeRange(me->getVictim())) + { + me->AttackerStateUpdate(me->getVictim()); + me->resetAttackTimer(); + } + } + if (me->haveOffhandWeapon() && me->isAttackReady(OFF_ATTACK) && !me->hasUnitState(UNIT_STAT_CASTING)) + { + //If we are within range melee the target + if (me->IsWithinMeleeRange(me->getVictim())) + { + me->AttackerStateUpdate(me->getVictim(), OFF_ATTACK); + me->resetAttackTimer(OFF_ATTACK); + } + } +} + //Enable PlayerAI when charmed void PlayerAI::OnCharmed(bool apply) { me->IsAIEnabled = apply; } //Disable CreatureAI when charmed -void CreatureAI::OnCharmed(bool apply) { me->IsAIEnabled = !apply; } +void CreatureAI::OnCharmed(bool apply) { /*me->IsAIEnabled = !apply;*/ } void CreatureAI::MoveInLineOfSight(Unit *who) { diff --git a/src/game/CreatureAI.h b/src/game/CreatureAI.h index fbfb8605866..1cfeb6555f2 100644 --- a/src/game/CreatureAI.h +++ b/src/game/CreatureAI.h @@ -81,6 +81,9 @@ class TRINITY_DLL_SPEC UnitAI // Called when unit is charmed virtual void OnCharmed(bool apply) = 0; + + //Do melee swing of current victim if in rnage and ready and not casting + void DoMeleeAttackIfReady(); }; class TRINITY_DLL_SPEC PlayerAI : public UnitAI diff --git a/src/game/NullCreatureAI.cpp b/src/game/NullCreatureAI.cpp index 0814e348a80..1bb787b25c3 100644 --- a/src/game/NullCreatureAI.cpp +++ b/src/game/NullCreatureAI.cpp @@ -27,6 +27,30 @@ void PassiveAI::UpdateAI(const uint32) EnterEvadeMode(); } +void PossessedAI::UpdateAI(const uint32 diff) +{ + if(me->getVictim()) + { + if(!me->canAttack(me->getVictim())) + me->AttackStop(); + else + DoMeleeAttackIfReady(); + } +} + +void PossessedAI::JustDied(Unit *u) +{ + // We died while possessed, disable our loot + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); +} + +void PossessedAI::KilledUnit(Unit* victim) +{ + // We killed a creature, disable victim's loot + if (victim->GetTypeId() == TYPEID_UNIT) + victim->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); +} + void CritterAI::DamageTaken(Unit *done_by, uint32 &) { if(!me->hasUnitState(UNIT_STAT_FLEEING)) @@ -39,4 +63,3 @@ void CritterAI::EnterEvadeMode() me->SetControlled(false, UNIT_STAT_FLEEING); CreatureAI::EnterEvadeMode(); } - diff --git a/src/game/NullCreatureAI.h b/src/game/NullCreatureAI.h index 3c9c35cdc9d..b64bf43ce5f 100644 --- a/src/game/NullCreatureAI.h +++ b/src/game/NullCreatureAI.h @@ -36,6 +36,18 @@ class TRINITY_DLL_DECL PassiveAI : public CreatureAI static int Permissible(const Creature *) { return PERMIT_BASE_IDLE; } }; +class TRINITY_DLL_DECL PossessedAI : public PassiveAI +{ + public: + PossessedAI(Creature *c) : PassiveAI(c) {} + + void UpdateAI(const uint32); + void EnterEvadeMode() {} + + void JustDied(Unit*); + void KilledUnit(Unit* victim); +}; + class TRINITY_DLL_DECL NullCreatureAI : public PassiveAI { public: diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp index cf639f84db5..72c8c1e760b 100644 --- a/src/game/PetAI.cpp +++ b/src/game/PetAI.cpp @@ -44,44 +44,6 @@ PetAI::PetAI(Creature *c) : CreatureAI(c), i_pet(*c), i_tracker(TIME_INTERVAL_LO UpdateAllies(); } -void PetAI::MoveInLineOfSight(Unit *u) -{ - if( !i_pet.getVictim() && i_pet.GetCharmInfo() && - i_pet.IsHostileTo( u ) && i_pet.canAttack(u) && - u->isInAccessiblePlaceFor(&i_pet)) - { - float attackRadius = i_pet.GetAttackDistance(u); - if(i_pet.IsWithinDistInMap(u, attackRadius) && i_pet.GetDistanceZ(u) <= CREATURE_Z_ATTACK_RANGE) - { - if(i_pet.IsWithinLOSInMap(u)) - { - AttackStart(u); - //u->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); - } - } - } -} - -void PetAI::AttackStart(Unit *u) -{ - if( !u || (i_pet.isPet() && ((Pet&)i_pet).getPetType() == MINI_PET) ) - return; - - if (inCombat && i_pet.getVictim() && u != i_pet.getVictim()) - i_pet.AttackStop(); - - if(i_pet.Attack(u,true)) - { - i_pet.clearUnitState(UNIT_STAT_FOLLOW); - // TMGs call CreatureRelocation which via MoveInLineOfSight can call this function - // thus with the following clear the original TMG gets invalidated and crash, doh - // hope it doesn't start to leak memory without this :-/ - //i_pet->Clear(); - i_pet.GetMotionMaster()->MoveChase(u); - inCombat = true; - } -} - void PetAI::EnterEvadeMode() { } @@ -138,11 +100,8 @@ void PetAI::UpdateAI(const uint32 diff) else m_updateAlliesTimer -= diff; - if (inCombat && i_pet.getVictim() == NULL) - _stopAttack(); - // i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc. - if( i_pet.getVictim() != NULL ) + if( i_pet.getVictim() ) { if( _needToStop() ) { @@ -150,50 +109,23 @@ void PetAI::UpdateAI(const uint32 diff) _stopAttack(); return; } - else if( i_pet.IsStopped() || i_pet.IsWithinMeleeRange(i_pet.getVictim())) - { - // required to be stopped cases - if ( i_pet.IsStopped() && i_pet.IsNonMeleeSpellCasted(false) ) - { - if( i_pet.hasUnitState(UNIT_STAT_FOLLOW) ) - i_pet.InterruptNonMeleeSpells(false); - else - return; - } - // not required to be stopped case - else if( i_pet.isAttackReady() && i_pet.IsWithinMeleeRange(i_pet.getVictim()) ) - { - i_pet.AttackerStateUpdate(i_pet.getVictim()); - i_pet.resetAttackTimer(); - - if ( !i_pet.getVictim() ) - return; - - //if pet misses its target, it will also be the first in threat list - i_pet.getVictim()->AddThreat(&i_pet,0.0f); - - if( _needToStop() ) - _stopAttack(); - } - } + DoMeleeAttackIfReady(); } - else if(owner && i_pet.GetCharmInfo()) + else { - if(owner->isInCombat() && !(i_pet.HasReactState(REACT_PASSIVE) || i_pet.GetCharmInfo()->HasCommandState(COMMAND_STAY))) + if(me->isInCombat()) + _stopAttack(); + else if(owner && i_pet.GetCharmInfo()) //no victim { - AttackStart(owner->getAttackerForHelper()); - } - else if(i_pet.GetCharmInfo()->HasCommandState(COMMAND_FOLLOW)) - { - if (!i_pet.hasUnitState(UNIT_STAT_FOLLOW) ) - { + if(owner->isInCombat() && !(i_pet.HasReactState(REACT_PASSIVE) || i_pet.GetCharmInfo()->HasCommandState(COMMAND_STAY))) + AttackStart(owner->getAttackerForHelper()); + else if(i_pet.GetCharmInfo()->HasCommandState(COMMAND_FOLLOW) && !i_pet.hasUnitState(UNIT_STAT_FOLLOW)) i_pet.GetMotionMaster()->MoveFollow(owner,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE); - } } } - if (i_pet.GetGlobalCooldown() == 0 && !i_pet.IsNonMeleeSpellCasted(false)) + if (i_pet.GetGlobalCooldown() == 0 && !i_pet.hasUnitState(UNIT_STAT_CASTING)) { //Autocast for (uint8 i = 0; i < i_pet.GetPetAutoSpellSize(); i++) @@ -323,12 +255,3 @@ void PetAI::UpdateAllies() else //remove group m_AllySet.insert(owner->GetGUID()); } - -/*void PetAI::AttackedBy(Unit *attacker) -{ - //when attacked, fight back in case 1)no victim already AND 2)not set to passive AND 3)not set to stay, unless can it can reach attacker with melee attack anyway - if(!i_pet.getVictim() && i_pet.GetCharmInfo() && !i_pet.GetCharmInfo()->HasReactState(REACT_PASSIVE) && - (!i_pet.GetCharmInfo()->HasCommandState(COMMAND_STAY) || i_pet.IsWithinMeleeRange(attacker))) - AttackStart(attacker); -}*/ - diff --git a/src/game/PetAI.h b/src/game/PetAI.h index 017627d73f0..eebd1e27a67 100644 --- a/src/game/PetAI.h +++ b/src/game/PetAI.h @@ -33,8 +33,6 @@ class TRINITY_DLL_DECL PetAI : public CreatureAI PetAI(Creature *c); - void MoveInLineOfSight(Unit *); - void AttackStart(Unit *); void EnterEvadeMode(); void JustDied(Unit* who) { _stopAttack(); } diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp index b87193b7e9f..49a3bb95cb7 100644 --- a/src/game/PetHandler.cpp +++ b/src/game/PetHandler.cpp @@ -85,13 +85,15 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) switch(spellid) { case COMMAND_STAY: //flat=1792 //STAY + pet->AttackStop(); + pet->InterruptNonMeleeSpells(false); pet->StopMoving(); - pet->GetMotionMaster()->Clear(); pet->GetMotionMaster()->MoveIdle(); charmInfo->SetCommandState( COMMAND_STAY ); break; case COMMAND_FOLLOW: //spellid=1792 //FOLLOW pet->AttackStop(); + pet->InterruptNonMeleeSpells(false); pet->GetMotionMaster()->MoveFollow(_player,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE); charmInfo->SetCommandState( COMMAND_FOLLOW ); break; diff --git a/src/game/PossessedAI.cpp b/src/game/PossessedAI.cpp index 23ac5fae43e..bda0de88882 100644 --- a/src/game/PossessedAI.cpp +++ b/src/game/PossessedAI.cpp @@ -18,105 +18,3 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "PossessedAI.h" -#include "Creature.h" -#include "World.h" - -void PossessedAI::AttackStart(Unit *u) -{ - if( !u || i_pet.GetCharmer()->HasAuraType(SPELL_AURA_MOD_PACIFY)) - return; - - if (i_pet.getVictim() && u != i_pet.getVictim()) - i_pet.AttackStop(); - - if(i_pet.Attack(u, true)) - i_victimGuid = u->GetGUID(); - - // Do not autochase our target, and also make sure our current movement generator - // is removed since the motion master is reset before this function is called - i_pet.GetMotionMaster()->Clear(false); - i_pet.GetMotionMaster()->MoveIdle(); -} - -bool PossessedAI::_needToStop() const -{ - if(!i_pet.getVictim() || !i_pet.isAlive()) - return true; - - // This is needed for charmed creatures, as once their target was reset other effects can trigger threat - if(i_pet.getVictim() == i_pet.GetCharmer()) - return true; - - return !i_pet.canAttack(i_pet.getVictim()); -} - -void PossessedAI::_stopAttack() -{ - if( !i_victimGuid ) - return; - - Unit* victim = Unit::GetUnit(i_pet, i_victimGuid ); - - if ( !victim ) - return; - - assert(!i_pet.getVictim() || i_pet.getVictim() == victim); - - if( !i_pet.isAlive() ) - { - i_pet.StopMoving(); - i_pet.GetMotionMaster()->Clear(false); - i_pet.GetMotionMaster()->MoveIdle(); - i_victimGuid = 0; - i_pet.CombatStop(); - i_pet.getHostilRefManager().deleteReferences(); - - return; - } - - i_pet.GetMotionMaster()->Clear(false); - i_pet.GetMotionMaster()->MoveIdle(); - i_victimGuid = 0; - i_pet.AttackStop(); -} - -void PossessedAI::UpdateAI(const uint32 diff) -{ - // update i_victimGuid if i_pet.getVictim() !=0 and changed - if(i_pet.getVictim()) - i_victimGuid = i_pet.getVictim()->GetGUID(); - - // i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc. - if( i_victimGuid ) - { - if( _needToStop() ) - { - _stopAttack(); // i_victimGuid == 0 && i_pet.getVictim() == NULL now - return; - } - else if(i_pet.IsWithinMeleeRange(i_pet.getVictim()) && i_pet.isAttackReady() && !i_pet.GetCharmer()->HasAuraType(SPELL_AURA_MOD_PACIFY)) - { - i_pet.AttackerStateUpdate(i_pet.getVictim()); - - i_pet.resetAttackTimer(); - - if( _needToStop() ) - _stopAttack(); - } - } -} - -void PossessedAI::JustDied(Unit *u) -{ - // We died while possessed, disable our loot - i_pet.RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); -} - -void PossessedAI::KilledUnit(Unit* victim) -{ - // We killed a creature, disable victim's loot - if (victim->GetTypeId() == TYPEID_UNIT) - victim->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); -} - diff --git a/src/game/PossessedAI.h b/src/game/PossessedAI.h index c9ad643eea1..bbfacb6454c 100644 --- a/src/game/PossessedAI.h +++ b/src/game/PossessedAI.h @@ -21,33 +21,5 @@ #ifndef MANGOS_POSSESSEDAI_H #define MANGOS_POSSESSEDAI_H -#include "CreatureAI.h" -class Creature; - -class TRINITY_DLL_DECL PossessedAI : public CreatureAI -{ - public: - PossessedAI(Creature *c) : CreatureAI(c), i_pet(*c), i_victimGuid(0) {} - - // Possessed creatures shouldn't aggro by themselves - void MoveInLineOfSight(Unit *) {} - void AttackStart(Unit *); - void EnterEvadeMode() {} - void JustDied(Unit*); - void KilledUnit(Unit* victim); - - void UpdateAI(const uint32); - // Never permit this to be used, it must always be initialized with Creature::InitPossessedAI() - static int Permissible(const Creature *) { return PERMIT_BASE_NO; } - - private: - bool _isVisible(Unit *) const; - bool _needToStop(void) const; - void _stopAttack(void); - - Creature &i_pet; - uint64 i_victimGuid; -}; #endif - diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index d7b3305c55d..e3e11c2e840 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -47,6 +47,8 @@ #include "CellImpl.h" #include "Path.h" #include "CreatureGroups.h" +#include "PetAI.h" +#include "NullCreatureAI.h" #include <math.h> @@ -150,6 +152,7 @@ bool IsPassiveStackableSpell( uint32 spellId ) Unit::Unit() : WorldObject(), i_motionMaster(this), m_ThreatManager(this), m_HostilRefManager(this) , m_IsInNotifyList(false), m_Notified(false), IsAIEnabled(false) +, i_AI(NULL), i_disabledAI(NULL) { m_objectType |= TYPEMASK_UNIT; m_objectTypeId = TYPEID_UNIT; @@ -11250,10 +11253,38 @@ void Unit::CleanupsBeforeDelete() RemoveFromWorld(); } +void Unit::UpdateCharmAI() +{ + if(GetTypeId() == TYPEID_PLAYER) + return; + + if(i_disabledAI) // disabled AI must be primary AI + { + if(!isCharmed()) + { + if(i_AI) delete i_AI; + i_AI = i_disabledAI; + i_disabledAI = NULL; + } + } + else + { + if(isCharmed()) + { + i_disabledAI = i_AI; + if(isPossessed()) + i_AI = new PossessedAI((Creature*)this); + else + i_AI = new PetAI((Creature*)this); + } + } +} + CharmInfo* Unit::InitCharmInfo() { if(!m_charmInfo) m_charmInfo = new CharmInfo(this); + return m_charmInfo; } diff --git a/src/game/Unit.h b/src/game/Unit.h index d103525208c..f73a5386aef 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1109,6 +1109,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject CharmInfo* GetCharmInfo() { return m_charmInfo; } CharmInfo* InitCharmInfo(); void DeleteCharmInfo(); + void UpdateCharmAI(); SharedVisionList const& GetSharedVisionList() { return m_sharedVision; } void AddPlayerToVision(Player* plr); void RemovePlayerFromVision(Player* plr); @@ -1424,6 +1425,8 @@ class TRINITY_DLL_SPEC Unit : public WorldObject protected: explicit Unit (); + UnitAI *i_AI, *i_disabledAI; + void _UpdateSpells(uint32 time); void _UpdateAutoRepeatSpell(); |