diff options
Diffstat (limited to 'src/game/CreatureAI.cpp')
-rw-r--r-- | src/game/CreatureAI.cpp | 197 |
1 files changed, 137 insertions, 60 deletions
diff --git a/src/game/CreatureAI.cpp b/src/game/CreatureAI.cpp index e5ed4cf894a..9f06ca38b56 100644 --- a/src/game/CreatureAI.cpp +++ b/src/game/CreatureAI.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * 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 @@ -19,56 +19,80 @@ */ #include "CreatureAI.h" +#include "CreatureAIImpl.h" #include "Creature.h" -#include "Player.h" -#include "Pet.h" -#include "SpellAuras.h" #include "World.h" +#include "SpellMgr.h" -void UnitAI::AttackStart(Unit *victim) +//Disable CreatureAI when charmed +void CreatureAI::OnCharmed(bool apply) { - if(!victim) + //me->IsAIEnabled = !apply;*/ + me->NeedChangeAI = true; + me->IsAIEnabled = false; +} + +AISpellInfoType * UnitAI::AISpellInfo; +TRINITY_DLL_SPEC AISpellInfoType * GetAISpellInfo(uint32 i) { return &CreatureAI::AISpellInfo[i]; } + +void CreatureAI::DoZoneInCombat(Creature* creature) +{ + if (!creature) + creature = me; + + if(!creature->CanHaveThreatList()) return; - if(me->Attack(victim, true)) + Map *map = creature->GetMap(); + if (!map->IsDungeon()) //use IsDungeon instead of Instanceable, in case battlegrounds will be instantiated { - //DEBUG_LOG("Creature %s tagged a victim to kill [guid=%u]", me->GetName(), victim->GetGUIDLow()); - me->GetMotionMaster()->MoveChase(victim); + sLog.outError("DoZoneInCombat call for map that isn't an instance (creature entry = %d)", creature->GetTypeId() == TYPEID_UNIT ? ((Creature*)creature)->GetEntry() : 0); + return; } -} -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(!creature->HasReactState(REACT_PASSIVE) && !creature->getVictim()) { - //If we are within range melee the target - if (me->IsWithinMeleeRange(me->getVictim())) + if(Unit *target = creature->SelectNearestTarget(50)) + creature->AI()->AttackStart(target); + else if(creature->isSummon()) { - me->AttackerStateUpdate(me->getVictim()); - me->resetAttackTimer(); + if(Unit *summoner = ((TempSummon*)creature)->GetSummoner()) + { + Unit *target = summoner->getAttackerForHelper(); + if(!target && summoner->CanHaveThreatList() && !summoner->getThreatManager().isThreatListEmpty()) + target = summoner->getThreatManager().getHostilTarget(); + if(target && (creature->IsFriendlyTo(summoner) || creature->IsHostileTo(target))) + creature->AI()->AttackStart(target); + } } } - if (me->haveOffhandWeapon() && me->isAttackReady(OFF_ATTACK) && !me->hasUnitState(UNIT_STAT_CASTING)) + + if(!creature->HasReactState(REACT_PASSIVE) && !creature->getVictim()) { - //If we are within range melee the target - if (me->IsWithinMeleeRange(me->getVictim())) - { - me->AttackerStateUpdate(me->getVictim(), OFF_ATTACK); - me->resetAttackTimer(OFF_ATTACK); - } + sLog.outError("DoZoneInCombat called for creature that has empty threat list (creature entry = %u)", creature->GetEntry()); + return; } -} -//Enable PlayerAI when charmed -void PlayerAI::OnCharmed(bool apply) { me->IsAIEnabled = apply; } + Map::PlayerList const &PlList = map->GetPlayers(); -//Disable CreatureAI when charmed -void CreatureAI::OnCharmed(bool apply) -{ - //me->IsAIEnabled = !apply;*/ - me->NeedChangeAI = true; - me->IsAIEnabled = false; + if(PlList.isEmpty()) + return; + + for(Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i) + { + if(Player* pPlayer = i->getSource()) + { + if(pPlayer->isGameMaster()) + continue; + + if(pPlayer->isAlive()) + { + creature->SetInCombatWith(pPlayer); + pPlayer->SetInCombatWith(creature); + creature->AddThreat(pPlayer, 0.0f); + } + } + } } void CreatureAI::MoveInLineOfSight(Unit *who) @@ -76,57 +100,110 @@ void CreatureAI::MoveInLineOfSight(Unit *who) if(me->getVictim()) return; - if(me->canStartAttack(who)) + if(me->canStartAttack(who, false)) AttackStart(who); else if(who->getVictim() && me->IsFriendlyTo(who) && me->IsWithinDistInMap(who, sWorld.getConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_RADIUS)) - && me->canAttack(who->getVictim())) + && me->canStartAttack(who->getVictim(), true)) AttackStart(who->getVictim()); } +void CreatureAI::SelectNearestTarget(Unit *who) +{ + if(me->getVictim() && me->GetDistanceOrder(who, me->getVictim()) && me->canAttack(who)) + { + me->getThreatManager().modifyThreatPercent(me->getVictim(), -100); + me->AddThreat(who, 1000000.0f); + } +} + +void CreatureAI::SetGazeOn(Unit *target) +{ + if(me->canAttack(target)) + { + AttackStart(target); + me->SetReactState(REACT_PASSIVE); + } +} + +bool CreatureAI::UpdateVictimWithGaze() +{ + if(!me->isInCombat()) + return false; + + if(me->HasReactState(REACT_PASSIVE)) + { + if(me->getVictim()) + return true; + else + me->SetReactState(REACT_AGGRESSIVE); + } + + if(Unit *victim = me->SelectVictim()) + AttackStart(victim); + return me->getVictim(); +} + bool CreatureAI::UpdateVictim() { if(!me->isInCombat()) return false; + if(Unit *victim = me->SelectVictim()) AttackStart(victim); return me->getVictim(); } -void CreatureAI::EnterEvadeMode() +bool CreatureAI::UpdateCombatState() { + if(!me->isInCombat()) + return false; + + if(!me->HasReactState(REACT_PASSIVE)) + { + if(Unit *victim = me->SelectVictim()) + AttackStart(victim); + return me->getVictim(); + } + else if(me->getThreatManager().isThreatListEmpty()) + { + EnterEvadeMode(); + return false; + } + + return true; +} + +bool CreatureAI::_EnterEvadeMode() +{ + if(me->IsInEvadeMode() || !me->isAlive()) + return false; + me->RemoveAllAuras(); me->DeleteThreatList(); - me->CombatStop(); + me->CombatStop(true); me->LoadCreaturesAddon(); me->SetLootRecipient(NULL); me->ResetPlayerDamageReq(); - if(me->isAlive()) - me->GetMotionMaster()->MoveTargetedHome(); + return true; } -void SimpleCharmedAI::UpdateAI(const uint32 /*diff*/) +void CreatureAI::EnterEvadeMode() { - Creature *charmer = (Creature*)me->GetCharmer(); - - //kill self if charm aura has infinite duration - if(charmer->IsInEvadeMode()) - { - Unit::AuraList const& auras = me->GetAurasByType(SPELL_AURA_MOD_CHARM); - for(Unit::AuraList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter) - if((*iter)->GetCasterGUID() == charmer->GetGUID() && (*iter)->IsPermanent()) - { - charmer->Kill(me); - return; - } - } + if(!_EnterEvadeMode()) + return; - if(!charmer->isInCombat()) - me->GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); + if(Unit *owner = me->GetCharmerOrOwner()) + me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE, MOTION_SLOT_IDLE); + else + me->GetMotionMaster()->MoveTargetedHome(); - Unit *target = me->getVictim(); - if(!target || !charmer->canAttack(target)) - AttackStart(charmer->SelectNearestTarget()); + Reset(); } +/*void CreatureAI::AttackedBy( Unit* attacker ) +{ + if(!m_creature->getVictim()) + AttackStart(attacker); +}*/ |