diff options
| author | megamage <none@none> | 2009-01-31 13:58:33 -0600 |
|---|---|---|
| committer | megamage <none@none> | 2009-01-31 13:58:33 -0600 |
| commit | d20eaef1d6c7b8d629347b51583cbcf954ff96ed (patch) | |
| tree | 0387ea5eed3569d49ffcac9553ada179fba645f0 /src/game | |
| parent | be27bd230cbefc8241ab8704bef8894252403ea2 (diff) | |
| parent | 1f2292af796d4b424bf45711ae8c50e764cf0d61 (diff) | |
*Merge.
--HG--
branch : trunk
Diffstat (limited to 'src/game')
| -rw-r--r-- | src/game/AggressorAI.cpp | 49 | ||||
| -rw-r--r-- | src/game/AggressorAI.h | 3 | ||||
| -rw-r--r-- | src/game/Creature.h | 2 | ||||
| -rw-r--r-- | src/game/CreatureAI.cpp | 37 | ||||
| -rw-r--r-- | src/game/CreatureAI.h | 32 | ||||
| -rw-r--r-- | src/game/DestinationHolderImp.h | 2 | ||||
| -rw-r--r-- | src/game/GuardAI.cpp | 21 | ||||
| -rw-r--r-- | src/game/GuardAI.h | 1 | ||||
| -rw-r--r-- | src/game/NullCreatureAI.h | 3 | ||||
| -rw-r--r-- | src/game/OutdoorPvPObjectiveAI.cpp | 29 | ||||
| -rw-r--r-- | src/game/OutdoorPvPObjectiveAI.h | 12 | ||||
| -rw-r--r-- | src/game/PetAI.cpp | 16 | ||||
| -rw-r--r-- | src/game/PetAI.h | 1 | ||||
| -rw-r--r-- | src/game/PossessedAI.cpp | 6 | ||||
| -rw-r--r-- | src/game/PossessedAI.h | 3 | ||||
| -rw-r--r-- | src/game/ReactorAI.cpp | 20 | ||||
| -rw-r--r-- | src/game/ReactorAI.h | 3 | ||||
| -rw-r--r-- | src/game/Spell.cpp | 35 | ||||
| -rw-r--r-- | src/game/Spell.h | 3 | ||||
| -rw-r--r-- | src/game/SpellEffects.cpp | 37 | ||||
| -rw-r--r-- | src/game/SpellMgr.cpp | 11 | ||||
| -rw-r--r-- | src/game/SpellMgr.h | 3 | ||||
| -rw-r--r-- | src/game/TotemAI.cpp | 2 | ||||
| -rw-r--r-- | src/game/Unit.cpp | 35 | ||||
| -rw-r--r-- | src/game/Unit.h | 3 |
25 files changed, 151 insertions, 218 deletions
diff --git a/src/game/AggressorAI.cpp b/src/game/AggressorAI.cpp index 99e39618f53..65dd1849217 100644 --- a/src/game/AggressorAI.cpp +++ b/src/game/AggressorAI.cpp @@ -38,29 +38,10 @@ AggressorAI::Permissible(const Creature *creature) return PERMIT_BASE_NO; } -AggressorAI::AggressorAI(Creature *c) : i_creature(*c), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK) +AggressorAI::AggressorAI(Creature *c) : CreatureAI(c), i_creature(*c), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK) { } -void -AggressorAI::MoveInLineOfSight(Unit *u) -{ - if(!i_creature.getVictim() && i_creature.canStartAttack(u)) - AttackStart(u); - - /* - if(!i_creature.getVictim()) - { - AttackStart(u); - } - else if(sMapStore.LookupEntry(i_creature.GetMapId())->IsDungeon()) - { - u->SetInCombatWith(&i_creature); - i_creature.AddThreat(u, 0.0f); - } - */ -} - void AggressorAI::EnterEvadeMode() { if( !i_creature.isAlive() ) @@ -118,7 +99,7 @@ void AggressorAI::UpdateAI(const uint32 /*diff*/) { // update i_victimGuid if i_creature.getVictim() !=0 and changed - if(!i_creature.SelectHostilTarget() || !i_creature.getVictim()) + if(!UpdateVictim()) return; i_victimGuid = i_creature.getVictim()->GetGUID(); @@ -132,29 +113,3 @@ AggressorAI::UpdateAI(const uint32 /*diff*/) } } } - -bool -AggressorAI::IsVisible(Unit *pl) const -{ - return i_creature.GetDistance(pl) < sWorld.getConfig(CONFIG_SIGHT_MONSTER) - && pl->isVisibleForOrDetect(&i_creature,true); -} - -void -AggressorAI::AttackStart(Unit *u) -{ - if( !u ) - return; - - if(i_creature.Attack(u,true)) - { - i_creature.SetInCombatWith(u); - u->SetInCombatWith(&i_creature); - - i_creature.AddThreat(u, 0.0f); - // DEBUG_LOG("Creature %s tagged a victim to kill [guid=%u]", i_creature.GetName(), u->GetGUIDLow()); - i_victimGuid = u->GetGUID(); - - i_creature.GetMotionMaster()->MoveChase(u); - } -} diff --git a/src/game/AggressorAI.h b/src/game/AggressorAI.h index f6e2a649c8a..e50a4c0ece3 100644 --- a/src/game/AggressorAI.h +++ b/src/game/AggressorAI.h @@ -38,10 +38,7 @@ class TRINITY_DLL_DECL AggressorAI : public CreatureAI AggressorAI(Creature *c); - void MoveInLineOfSight(Unit *); - void AttackStart(Unit *); void EnterEvadeMode(); - bool IsVisible(Unit *) const; void UpdateAI(const uint32); static int Permissible(const Creature *); diff --git a/src/game/Creature.h b/src/game/Creature.h index 59475e27618..f445fde400f 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -637,7 +637,7 @@ class TRINITY_DLL_SPEC Creature : public Unit bool IsFormationLeader() {return (GetDBTableGUIDLow() && GetDBTableGUIDLow() == m_formationID);} uint32 GetFormationID(){return m_formationID;} - Unit *SelectHostilTarget(); + Unit *SelectVictim(); protected: bool CreateFromProto(uint32 guidlow,uint32 Entry,uint32 team, const CreatureData *data = NULL); bool InitEntry(uint32 entry, uint32 team=ALLIANCE, const CreatureData* data=NULL); diff --git a/src/game/CreatureAI.cpp b/src/game/CreatureAI.cpp index 66c9d5af0b0..8682bf064a5 100644 --- a/src/game/CreatureAI.cpp +++ b/src/game/CreatureAI.cpp @@ -20,17 +20,39 @@ #include "CreatureAI.h" #include "Creature.h" +#include "Player.h" #include "Pet.h" #include "SpellAuras.h" -CreatureAI::~CreatureAI() +void UnitAI::AttackStart(Unit *victim) { + if(!victim) + return; + + if(me->Attack(victim, true)) + { + //DEBUG_LOG("Creature %s tagged a victim to kill [guid=%u]", me->GetName(), victim->GetGUIDLow()); + me->GetMotionMaster()->MoveChase(victim); + } } -void CreatureAI::EnterEvadeMode() +void CreatureAI::MoveInLineOfSight(Unit *who) { - if(!me) return; + if(!me->getVictim() && me->canStartAttack(who)) + AttackStart(who); +} +bool CreatureAI::UpdateVictim() +{ + if(!me->isInCombat()) + return false; + if(Unit *victim = me->SelectVictim()) + AttackStart(victim); + return me->getVictim(); +} + +void CreatureAI::EnterEvadeMode() +{ me->RemoveAllAuras(); me->DeleteThreatList(); me->CombatStop(); @@ -62,12 +84,5 @@ void SimpleCharmedAI::UpdateAI(const uint32 /*diff*/) Unit *target = me->getVictim(); if(!target || !charmer->canAttack(target)) - { - target = charmer->SelectNearestTarget(); - if(!target) - return; - - me->GetMotionMaster()->MoveChase(target); - me->Attack(target, true); - } + AttackStart(charmer->SelectNearestTarget()); } diff --git a/src/game/CreatureAI.h b/src/game/CreatureAI.h index 72e911cceaf..5a8126f24d4 100644 --- a/src/game/CreatureAI.h +++ b/src/game/CreatureAI.h @@ -29,6 +29,7 @@ class Unit; class Creature; +class Player; struct SpellEntry; #define TIME_INTERVAL_LOOK 5000 @@ -71,34 +72,41 @@ enum SelectAggroTarget class TRINITY_DLL_SPEC UnitAI { + protected: + Unit *me; public: UnitAI(Unit *u) : me(u) {} + virtual void AttackStart(Unit *); virtual void UpdateAI(const uint32 diff) = 0; +}; + +class TRINITY_DLL_SPEC PlayerAI : public UnitAI +{ protected: - Unit *me; + Player *me; + public: + PlayerAI(Player *p) : UnitAI((Unit*)p), me(p) {} }; -class TRINITY_DLL_SPEC SimpleCharmedAI : public UnitAI +class TRINITY_DLL_SPEC SimpleCharmedAI : public PlayerAI { public: - virtual void UpdateAI(const uint32 diff); + void UpdateAI(const uint32 diff); }; class TRINITY_DLL_SPEC CreatureAI : public UnitAI { protected: Creature *me; + + bool UpdateVictim(); public: - CreatureAI() : UnitAI(NULL), me(NULL) {} CreatureAI(Creature *c) : UnitAI((Unit*)c), me(c) {} - virtual ~CreatureAI(); + virtual ~CreatureAI() {} // Called if IsVisible(Unit *who) is true at each *who move - virtual void MoveInLineOfSight(Unit *) = 0; - - // Called at each attack of m_creature by any victim - virtual void AttackStart(Unit *) = 0; + virtual void MoveInLineOfSight(Unit *); // Called at stopping attack by any attacker virtual void EnterEvadeMode(); @@ -106,12 +114,6 @@ class TRINITY_DLL_SPEC CreatureAI : public UnitAI // Called at any Damage from any attacker (before damage apply) virtual void DamageTaken(Unit *done_by, uint32 & /*damage*/) {} - // Is unit visible for MoveInLineOfSight - virtual bool IsVisible(Unit *) const = 0; - - // Called at World update tick - virtual void UpdateAI(const uint32 diff ) = 0; - // Called when the creature is killed virtual void JustDied(Unit *) {} diff --git a/src/game/DestinationHolderImp.h b/src/game/DestinationHolderImp.h index f30768e7993..984b643538a 100644 --- a/src/game/DestinationHolderImp.h +++ b/src/game/DestinationHolderImp.h @@ -98,7 +98,7 @@ DestinationHolder<TRAVELLER>::StartTravel(TRAVELLER &traveller, bool sendMove) float speed; if(traveller.GetTraveller().hasUnitState(UNIT_STAT_CHARGING)) - speed = 0.025f; // assume it is 25 yard per second + speed = SPEED_CHARGE * 0.001f; else speed = traveller.Speed() * 0.001f; // speed is in seconds so convert from second to millisecond i_totalTravelTime = static_cast<uint32>(dist/speed); diff --git a/src/game/GuardAI.cpp b/src/game/GuardAI.cpp index e5a7ce87092..d3c3d9a7330 100644 --- a/src/game/GuardAI.cpp +++ b/src/game/GuardAI.cpp @@ -33,7 +33,7 @@ int GuardAI::Permissible(const Creature *creature) return PERMIT_BASE_NO; } -GuardAI::GuardAI(Creature *c) : i_creature(*c), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK) +GuardAI::GuardAI(Creature *c) : CreatureAI(c), i_creature(*c), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK) { } @@ -110,7 +110,7 @@ void GuardAI::EnterEvadeMode() void GuardAI::UpdateAI(const uint32 /*diff*/) { // update i_victimGuid if i_creature.getVictim() !=0 and changed - if(!i_creature.SelectHostilTarget() || !i_creature.getVictim()) + if(!UpdateVictim()) return; i_victimGuid = i_creature.getVictim()->GetGUID(); @@ -131,23 +131,6 @@ bool GuardAI::IsVisible(Unit *pl) const && pl->isVisibleForOrDetect(&i_creature,true); } -void GuardAI::AttackStart(Unit *u) -{ - if( !u ) - return; - - // DEBUG_LOG("Creature %s tagged a victim to kill [guid=%u]", i_creature.GetName(), u->GetGUIDLow()); - if(i_creature.Attack(u,true)) - { - i_creature.SetInCombatWith(u); - u->SetInCombatWith(&i_creature); - - i_creature.AddThreat(u, 0.0f); - i_victimGuid = u->GetGUID(); - i_creature.GetMotionMaster()->MoveChase(u); - } -} - void GuardAI::JustDied(Unit *killer) { if(Player* pkiller = killer->GetCharmerOrOwnerPlayerOrPlayerItself()) diff --git a/src/game/GuardAI.h b/src/game/GuardAI.h index 16e0c6e8bd6..30f76dd509a 100644 --- a/src/game/GuardAI.h +++ b/src/game/GuardAI.h @@ -39,7 +39,6 @@ class TRINITY_DLL_DECL GuardAI : public CreatureAI GuardAI(Creature *c); void MoveInLineOfSight(Unit *); - void AttackStart(Unit *); void EnterEvadeMode(); void JustDied(Unit *); bool IsVisible(Unit *) const; diff --git a/src/game/NullCreatureAI.h b/src/game/NullCreatureAI.h index 821b42f7e76..a9814c9c5e0 100644 --- a/src/game/NullCreatureAI.h +++ b/src/game/NullCreatureAI.h @@ -32,8 +32,6 @@ class TRINITY_DLL_DECL PassiveAI : public CreatureAI void MoveInLineOfSight(Unit *) {} void AttackStart(Unit *) {} - bool IsVisible(Unit *) const { return false; } - void UpdateAI(const uint32); static int Permissible(const Creature *) { return PERMIT_BASE_IDLE; } }; @@ -43,6 +41,7 @@ class TRINITY_DLL_DECL NullCreatureAI : public PassiveAI public: NullCreatureAI(Creature *c) : PassiveAI(c) {} + void UpdateAI(const uint32) {} void EnterEvadeMode() {} }; diff --git a/src/game/OutdoorPvPObjectiveAI.cpp b/src/game/OutdoorPvPObjectiveAI.cpp index a99afbfbe5a..aa7778ef105 100644 --- a/src/game/OutdoorPvPObjectiveAI.cpp +++ b/src/game/OutdoorPvPObjectiveAI.cpp @@ -25,18 +25,18 @@ #define MAX_OUTDOOR_PVP_DISTANCE 200 // the max value in capture point type go data0 is 100 currently, so use twice that much to handle leaving as well -OutdoorPvPObjectiveAI::OutdoorPvPObjectiveAI(Creature *c) : i_creature(*c) +OutdoorPvPObjectiveAI::OutdoorPvPObjectiveAI(Creature *c) : NullCreatureAI(c) { - sLog.outDebug("OutdoorPvP objective AI assigned to creature guid %u", i_creature.GetGUIDLow()); - i_creature.SetReactState(REACT_AGGRESSIVE); + sLog.outDebug("OutdoorPvP objective AI assigned to creature guid %u", me->GetGUIDLow()); + me->SetReactState(REACT_AGGRESSIVE); } void OutdoorPvPObjectiveAI::MoveInLineOfSight(Unit *u) { // IsVisible only passes for players in range, so no need to check again // leaving/entering distance will be checked based on go range data - if((u->GetTypeId() == TYPEID_PLAYER) && i_creature.IsWithinDistInMap(u, MAX_OUTDOOR_PVP_DISTANCE)) - sOutdoorPvPMgr.HandleCaptureCreaturePlayerMoveInLos(((Player*)u),&i_creature); + if((u->GetTypeId() == TYPEID_PLAYER) && me->IsWithinDistInMap(u, MAX_OUTDOOR_PVP_DISTANCE)) + sOutdoorPvPMgr.HandleCaptureCreaturePlayerMoveInLos(((Player*)u), me); } int OutdoorPvPObjectiveAI::Permissible(const Creature * c) @@ -45,22 +45,3 @@ int OutdoorPvPObjectiveAI::Permissible(const Creature * c) return PERMIT_BASE_NO; } -bool OutdoorPvPObjectiveAI::IsVisible(Unit *pl) const -{ - return (pl->GetTypeId() == TYPEID_PLAYER) && (i_creature.GetDistance(pl) < MAX_OUTDOOR_PVP_DISTANCE); -} - -void OutdoorPvPObjectiveAI::AttackStart(Unit *) -{ - //EnterEvadeMode(); -} - -void OutdoorPvPObjectiveAI::EnterEvadeMode() -{ -// i_creature.DeleteThreatList(); -// i_creature.CombatStop(); -} - -void OutdoorPvPObjectiveAI::UpdateAI(const uint32 diff) -{ -} diff --git a/src/game/OutdoorPvPObjectiveAI.h b/src/game/OutdoorPvPObjectiveAI.h index 2da9086dbd3..c8e4844cd5a 100644 --- a/src/game/OutdoorPvPObjectiveAI.h +++ b/src/game/OutdoorPvPObjectiveAI.h @@ -19,25 +19,17 @@ #ifndef TRINITY_OUTDOORPVPOBJECTIVEAI_H #define TRINITY_OUTDOORPVPOBJECTIVEAI_H -#include "CreatureAI.h" +#include "NullCreatureAI.h" class Creature; -class TRINITY_DLL_DECL OutdoorPvPObjectiveAI : public CreatureAI +class TRINITY_DLL_DECL OutdoorPvPObjectiveAI : public NullCreatureAI { public: - OutdoorPvPObjectiveAI(Creature *c); void MoveInLineOfSight(Unit *); - bool IsVisible(Unit *) const; - void AttackStart(Unit *); - void EnterEvadeMode(); - void UpdateAI(const uint32 diff); static int Permissible(const Creature *); - - private: - Creature &i_creature; }; #endif diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp index 0a93bea158d..398861d8d37 100644 --- a/src/game/PetAI.cpp +++ b/src/game/PetAI.cpp @@ -38,7 +38,7 @@ int PetAI::Permissible(const Creature *creature) return PERMIT_BASE_NO; } -PetAI::PetAI(Creature *c) : i_pet(*c), i_tracker(TIME_INTERVAL_LOOK), inCombat(false) +PetAI::PetAI(Creature *c) : CreatureAI(c), i_pet(*c), i_tracker(TIME_INTERVAL_LOOK), inCombat(false) { m_AllySet.clear(); UpdateAllies(); @@ -73,8 +73,6 @@ void PetAI::AttackStart(Unit *u) if(i_pet.Attack(u,true)) { - i_pet.SetInCombatWith(u); - 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 @@ -89,11 +87,6 @@ void PetAI::EnterEvadeMode() { } -bool PetAI::IsVisible(Unit *pl) const -{ - return _isVisible(pl); -} - bool PetAI::_needToStop() const { // This is needed for charmed creatures, as once their target was reset other effects can trigger threat @@ -293,13 +286,6 @@ void PetAI::UpdateAI(const uint32 diff) } } -bool PetAI::_isVisible(Unit *u) const -{ - //return false; //( ((Creature*)&i_pet)->GetDistanceSq(u) * 1.0<= sWorld.getConfig(CONFIG_SIGHT_GUARDER) && !u->m_stealth && u->isAlive()); - return i_pet.GetDistance(u) < sWorld.getConfig(CONFIG_SIGHT_GUARDER) - && u->isVisibleForOrDetect(&i_pet,true); -} - void PetAI::UpdateAllies() { Unit* owner = i_pet.GetCharmerOrOwner(); diff --git a/src/game/PetAI.h b/src/game/PetAI.h index 8583404b669..b81bdd8e14f 100644 --- a/src/game/PetAI.h +++ b/src/game/PetAI.h @@ -36,7 +36,6 @@ class TRINITY_DLL_DECL PetAI : public CreatureAI void MoveInLineOfSight(Unit *); void AttackStart(Unit *); void EnterEvadeMode(); - bool IsVisible(Unit *) const; void JustDied(Unit* who) { _stopAttack(); } void UpdateAI(const uint32); diff --git a/src/game/PossessedAI.cpp b/src/game/PossessedAI.cpp index 4292a2bd22b..f291221216a 100644 --- a/src/game/PossessedAI.cpp +++ b/src/game/PossessedAI.cpp @@ -107,12 +107,6 @@ void PossessedAI::UpdateAI(const uint32 diff) } } -bool PossessedAI::_isVisible(Unit *u) const -{ - return i_pet.GetDistance(u) < sWorld.getConfig(CONFIG_SIGHT_MONSTER) - && u->isVisibleForOrDetect(&i_pet,true); -} - void PossessedAI::JustDied(Unit *u) { // We died while possessed, disable our loot diff --git a/src/game/PossessedAI.h b/src/game/PossessedAI.h index 16c3172b6bf..5c4a670c200 100644 --- a/src/game/PossessedAI.h +++ b/src/game/PossessedAI.h @@ -28,7 +28,7 @@ class Creature; class TRINITY_DLL_DECL PossessedAI : public CreatureAI { public: - PossessedAI(Creature *c) : i_pet(*c), i_victimGuid(0) {} + PossessedAI(Creature *c) : CreatureAI(c), i_pet(*c), i_victimGuid(0) {} // Possessed creatures shouldn't aggro by themselves void MoveInLineOfSight(Unit *) {} @@ -36,7 +36,6 @@ class TRINITY_DLL_DECL PossessedAI : public CreatureAI void EnterEvadeMode() {} void JustDied(Unit*); void KilledUnit(Unit* victim); - bool IsVisible(Unit * u) const { return _isVisible(u); } void UpdateAI(const uint32); // Never permit this to be used, it must always be initialized with Creature::InitPossessedAI() diff --git a/src/game/ReactorAI.cpp b/src/game/ReactorAI.cpp index dd796b74f38..29b07f60b00 100644 --- a/src/game/ReactorAI.cpp +++ b/src/game/ReactorAI.cpp @@ -41,24 +41,6 @@ ReactorAI::MoveInLineOfSight(Unit *) { } -void -ReactorAI::AttackStart(Unit *p) -{ - if(!p) - return; - - if(i_creature.Attack(p,true)) - { - DEBUG_LOG("Tag unit GUID: %u (TypeId: %u) as a victim", p->GetGUIDLow(), p->GetTypeId()); - i_creature.SetInCombatWith(p); - p->SetInCombatWith(&i_creature); - - i_creature.AddThreat(p, 0.0f); - i_victimGuid = p->GetGUID(); - i_creature.GetMotionMaster()->MoveChase(p); - } -} - bool ReactorAI::IsVisible(Unit *) const { @@ -69,7 +51,7 @@ void ReactorAI::UpdateAI(const uint32 /*time_diff*/) { // update i_victimGuid if i_creature.getVictim() !=0 and changed - if(!i_creature.SelectHostilTarget() || !i_creature.getVictim()) + if(!UpdateVictim()) return; i_victimGuid = i_creature.getVictim()->GetGUID(); diff --git a/src/game/ReactorAI.h b/src/game/ReactorAI.h index b2bfa3501c2..cea1e8dcdb5 100644 --- a/src/game/ReactorAI.h +++ b/src/game/ReactorAI.h @@ -29,10 +29,9 @@ class TRINITY_DLL_DECL ReactorAI : public CreatureAI { public: - ReactorAI(Creature *c) : i_creature(*c), i_victimGuid(0) {} + ReactorAI(Creature *c) : CreatureAI(c), i_creature(*c), i_victimGuid(0) {} void MoveInLineOfSight(Unit *); - void AttackStart(Unit *); void EnterEvadeMode(); bool IsVisible(Unit *) const; diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 3890f97dd9c..4f658bb1c08 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -290,13 +290,14 @@ void SpellCastTargets::write ( WorldPacket * data ) *data << m_strTarget; } -Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 originalCasterGUID, Spell** triggeringContainer ) +Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 originalCasterGUID, Spell** triggeringContainer, bool skipCheck ) { ASSERT( Caster != NULL && info != NULL ); ASSERT( info == sSpellStore.LookupEntry( info->Id ) && "`info` must be pointer to sSpellStore element"); m_spellInfo = info; m_customAttr = spellmgr.GetSpellCustomAttr(m_spellInfo->Id); + m_skipCheck = skipCheck; m_caster = Caster; m_selfContainer = NULL; m_triggeringContainer = triggeringContainer; @@ -442,7 +443,7 @@ void Spell::FillTargetMap() { if(effectTargetType == SPELL_REQUIRE_CASTER) AddUnitTarget(m_caster, i); - if(effectTargetType == SPELL_REQUIRE_DEST) + /*else if(effectTargetType == SPELL_REQUIRE_DEST) { if(m_targets.HasDest() && m_spellInfo->speed > 0.0f) { @@ -450,7 +451,7 @@ void Spell::FillTargetMap() if (dist < 5.0f) dist = 5.0f; m_delayMoment = (uint64) floor(dist / m_spellInfo->speed * 1000.0f); } - } + }*/ else if(effectTargetType == SPELL_REQUIRE_ITEM) { if(m_targets.getItemTarget()) @@ -633,6 +634,16 @@ void Spell::FillTargetMap() for(std::list<Unit*>::iterator iunit= tmpUnitMap.begin();iunit != tmpUnitMap.end();++iunit) AddUnitTarget((*iunit), i); } + + if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) + { + if(m_spellInfo->speed > 0.0f && m_targets.HasDest()) + { + float dist = m_caster->GetDistance(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ); + if (dist < 5.0f) dist = 5.0f; + m_delayMoment = (uint64) floor(dist / m_spellInfo->speed * 1000.0f); + } + } } void Spell::prepareDataForTriggerSystem() @@ -763,7 +774,11 @@ void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex) // Calculate hit result if(m_originalCaster) + { target.missCondition = m_originalCaster->SpellHitResult(pVictim, m_spellInfo, m_canReflect); + if(m_skipCheck && target.missCondition != SPELL_MISS_IMMUNE) + target.missCondition = SPELL_MISS_NONE; + } else target.missCondition = SPELL_MISS_EVADE; //SPELL_MISS_NONE; @@ -923,7 +938,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) if (target->reflectResult == SPELL_MISS_NONE) // If reflected spell hit caster -> do all effect on him DoSpellHitOnUnit(m_caster, mask); } - else //TODO: This is a hack. need fix + /*else //TODO: This is a hack. need fix { uint32 tempMask = 0; for(uint32 i = 0; i < 3; ++i) @@ -932,7 +947,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) tempMask |= 1<<i; if(tempMask &= mask) DoSpellHitOnUnit(unit, tempMask); - } + }*/ // All calculated do it! // Do healing and triggers @@ -2206,6 +2221,8 @@ void Spell::cast(bool skipCheck) // Okay, everything is prepared. Now we need to distinguish between immediate and evented delayed spells if (m_spellInfo->speed > 0.0f && !IsChanneledSpell(m_spellInfo)) { + if(m_customAttr & SPELL_ATTR_CU_CHARGE) + EffectCharge(0); // Remove used for cast item if need (it can be already NULL after TakeReagents call // in case delayed spell remove item at cast delay start @@ -2288,12 +2305,14 @@ uint64 Spell::handle_delayed(uint64 t_offset) m_immediateHandled = true; } + bool single_missile = (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION); + // now recheck units targeting correctness (need before any effects apply to prevent adding immunity at first effect not allow apply second spell effect and similar cases) for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end();++ihit) { if (ihit->processed == false) { - if ( ihit->timeDelay <= t_offset ) + if ( single_missile || ihit->timeDelay <= t_offset ) DoAllEffectOnTarget(&(*ihit)); else if( next_time == 0 || ihit->timeDelay < next_time ) next_time = ihit->timeDelay; @@ -2305,7 +2324,7 @@ uint64 Spell::handle_delayed(uint64 t_offset) { if (ighit->processed == false) { - if ( ighit->timeDelay <= t_offset ) + if ( single_missile || ighit->timeDelay <= t_offset ) DoAllEffectOnTarget(&(*ighit)); else if( next_time == 0 || ighit->timeDelay < next_time ) next_time = ighit->timeDelay; @@ -3486,7 +3505,7 @@ void Spell::TriggerSpell() { for(TriggerSpells::iterator si=m_TriggerSpells.begin(); si!=m_TriggerSpells.end(); ++si) { - Spell* spell = new Spell(m_caster, (*si), true, m_originalCasterGUID, m_selfContainer); + Spell* spell = new Spell(m_caster, (*si), true, m_originalCasterGUID, m_selfContainer, true); spell->prepare(&m_targets); // use original spell original targets } } diff --git a/src/game/Spell.h b/src/game/Spell.h index c5e3841c0f1..ac7f8c8c7ea 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -351,7 +351,7 @@ class Spell void EffectActivateRune(uint32 i); void EffectTitanGrip(uint32 i); - Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 originalCasterGUID = 0, Spell** triggeringContainer = NULL ); + Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 originalCasterGUID = 0, Spell** triggeringContainer = NULL, bool skipCheck = false ); ~Spell(); void prepare(SpellCastTargets const* targets, Aura* triggeredByAura = NULL); @@ -611,6 +611,7 @@ class Spell SpellEntry const* m_triggeredByAuraSpell; uint32 m_customAttr; + bool m_skipCheck; }; namespace Trinity diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 114458db6b9..9bd4ae1def0 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -160,7 +160,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectUnused, // 93 SPELL_EFFECT_SUMMON_PHANTASM &Spell::EffectSelfResurrect, // 94 SPELL_EFFECT_SELF_RESURRECT &Spell::EffectSkinning, // 95 SPELL_EFFECT_SKINNING - &Spell::EffectCharge, // 96 SPELL_EFFECT_CHARGE + &Spell::EffectUnused, // 96 SPELL_EFFECT_CHARGE &Spell::EffectUnused, // 97 SPELL_EFFECT_97 &Spell::EffectKnockBack, // 98 SPELL_EFFECT_KNOCK_BACK &Spell::EffectDisEnchant, // 99 SPELL_EFFECT_DISENCHANT @@ -655,6 +655,9 @@ void Spell::EffectDummy(uint32 i) if(!unitTarget && !gameObjTarget && !itemTarget) return; + uint32 spell_id = 0; + int32 bp = 0; + // selection by spell family switch(m_spellInfo->SpellFamilyName) { @@ -1306,9 +1309,9 @@ void Spell::EffectDummy(uint32 i) if (Aura *aura = m_caster->GetDummyAura(58367)) rage+=aura->GetModifier()->m_amount; - int32 basePoints0 = damage+int32(rage * m_spellInfo->DmgMultiplier[i] + + spell_id = 20647; + int32 bp = damage+int32(rage * m_spellInfo->DmgMultiplier[i] + m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f); - m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0); m_caster->SetPower(POWER_RAGE,0); return; } @@ -1807,6 +1810,24 @@ void Spell::EffectDummy(uint32 i) break; } + //spells triggered by dummy effect should not miss + if(spell_id) + { + SpellEntry const *spellInfo = sSpellStore.LookupEntry( spell_id ); + + if(!spellInfo) + { + sLog.outError("EffectDummy of spell %u: triggering unknown spell id %i\n", m_spellInfo->Id, spell_id); + return; + } + + Spell* spell = new Spell(m_caster, spellInfo, true, m_originalCasterGUID, NULL, true); + if(bp) spell->m_currentBasePoints[0] = bp; + SpellCastTargets targets; + targets.setUnitTarget(unitTarget); + spell->prepare(&targets); + } + // pet auras if(PetAura const* petSpell = spellmgr.GetPetAura(m_spellInfo->Id)) { @@ -6006,16 +6027,20 @@ void Spell::EffectSkinning(uint32 /*i*/) void Spell::EffectCharge(uint32 /*i*/) { - if(!unitTarget || !m_caster) + if(!m_caster) + return; + + Unit *target = m_targets.getUnitTarget(); + if(!target) return; float x, y, z; - unitTarget->GetContactPoint(m_caster, x, y, z); + target->GetContactPoint(m_caster, x, y, z); m_caster->GetMotionMaster()->MoveCharge(x, y, z); // not all charge effects used in negative spells if ( !IsPositiveSpell(m_spellInfo->Id) && m_caster->GetTypeId() == TYPEID_PLAYER) - m_caster->Attack(unitTarget,true); + m_caster->Attack(target, true); } void Spell::EffectSummonCritter(uint32 i) diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 39ed6f6b77d..3b3ccad2ad4 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -27,6 +27,8 @@ #include "Chat.h" #include "Spell.h" +bool IsAreaEffectTarget[TOTAL_SPELL_TARGETS]; + SpellMgr::SpellMgr() { for(int i = 0; i < TOTAL_SPELL_EFFECTS; ++i) @@ -2170,6 +2172,15 @@ void SpellMgr::LoadSpellCustomAttr() case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: case SPELL_EFFECT_HEAL: mSpellCustomAttr[i] |= SPELL_ATTR_CU_DIRECT_DAMAGE; + break; + case SPELL_EFFECT_CHARGE: + if(!spellInfo->speed) + spellInfo->speed = SPEED_CHARGE; + mSpellCustomAttr[i] |= SPELL_ATTR_CU_CHARGE; + case SPELL_EFFECT_TRIGGER_SPELL: + if(spellInfo->Targets & (TARGET_FLAG_SOURCE_LOCATION|TARGET_FLAG_DEST_LOCATION)) + spellInfo->Effect[j] = SPELL_EFFECT_TRIGGER_MISSILE; + break; } } diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index eb9ce0637dc..5ff1e28da9e 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -396,7 +396,7 @@ bool IsAuraAddedBySpell(uint32 auraType, uint32 spellId); uint8 GetSpellAllowedInLocationError(SpellEntry const *spellInfo,uint32 map_id,uint32 zone_id,uint32 area_id); -static bool IsAreaEffectTarget[TOTAL_SPELL_TARGETS]; +extern bool IsAreaEffectTarget[TOTAL_SPELL_TARGETS]; inline bool IsAreaOfEffectSpell(SpellEntry const *spellInfo) { @@ -773,6 +773,7 @@ inline bool IsProfessionSkill(uint32 skill) #define SPELL_ATTR_CU_AURA_CC 0x00000040 #define SPELL_ATTR_CU_AURA_SPELL 0x00000080 #define SPELL_ATTR_CU_DIRECT_DAMAGE 0x00000100 +#define SPELL_ATTR_CU_CHARGE 0x00000200 typedef std::vector<uint32> SpellCustomAttribute; diff --git a/src/game/TotemAI.cpp b/src/game/TotemAI.cpp index 72a43cfc97b..4d7b45eba8e 100644 --- a/src/game/TotemAI.cpp +++ b/src/game/TotemAI.cpp @@ -40,7 +40,7 @@ TotemAI::Permissible(const Creature *creature) return PERMIT_BASE_NO; } -TotemAI::TotemAI(Creature *c) : i_totem(static_cast<Totem&>(*c)), i_victimGuid(0) +TotemAI::TotemAI(Creature *c) : CreatureAI(c), i_totem(static_cast<Totem&>(*c)), i_victimGuid(0) { } diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index e6497e13505..5fd2fa69bc5 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -7296,6 +7296,12 @@ bool Unit::Attack(Unit *victim, bool meleeAttack) ((WorldObject*)this)->SendMessageToSet(&data, true); ((Creature*)this)->CallAssistance(); + + // should not let player enter combat by right clicking target + SetInCombatWith(victim); + if(victim->GetTypeId() == TYPEID_PLAYER) + victim->SetInCombatWith(this); + AddThreat(victim, 0.0f); } // delay offhand weapon attack to next attack time @@ -9735,7 +9741,7 @@ void Unit::TauntFadeOut(Unit *taunter) //====================================================================== -Unit* Creature::SelectHostilTarget() +Unit* Creature::SelectVictim() { //function provides main threat functionality //next-victim-selection algorithm and evade mode are called @@ -9746,13 +9752,8 @@ Unit* Creature::SelectHostilTarget() //otherwise enterevademode every update - if (!this->isAlive()) - return false; - //This function only useful once AI has been initialized - if (!AI()) - return NULL; - Unit* target = NULL; + Unit* target = NULL; // First checking if we have some taunt on us const AuraList& tauntAuras = GetAurasByType(SPELL_AURA_MOD_TAUNT); if ( !tauntAuras.empty() ) @@ -9792,18 +9793,15 @@ Unit* Creature::SelectHostilTarget() { if(!hasUnitState(UNIT_STAT_STUNNED)) SetInFront(target); - AI()->AttackStart(target); - return getVictim(); + return target; } - // no target but something prevent go to evade mode - if( !isInCombat() /*|| HasAuraType(SPELL_AURA_MOD_TAUNT)*/ ) - return NULL; - // last case when creature don't must go to evade mode: // it in combat but attacker not make any damage and not enter to aggro radius to have record in threat list // for example at owner command to pet attack some far away creature // Note: creature not have targeted movement generator but have attacker in this case + if(m_attackers.size()) + return NULL; /*if( GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE ) { for(AttackerSet::const_iterator itr = m_attackers.begin(); itr != m_attackers.end(); ++itr) @@ -9816,14 +9814,9 @@ Unit* Creature::SelectHostilTarget() // search nearby enemy before enter evade mode if(HasReactState(REACT_AGGRESSIVE)) { - if(target = SelectNearestTarget()) - { - if(!IsOutOfThreatArea(target)) - { - AI()->AttackStart(target); - return getVictim(); - } - } + target = SelectNearestTarget(); + if(target && !IsOutOfThreatArea(target)) + return target; } if(m_invisibilityMask) diff --git a/src/game/Unit.h b/src/game/Unit.h index cbb61eb3c32..08b1b8c2bf6 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -406,6 +406,8 @@ enum UnitMoveType #define MAX_MOVE_TYPE 9 extern float baseMoveSpeed[MAX_MOVE_TYPE]; +// assume it is 25 yard per 0.6 second +#define SPEED_CHARGE 42.0f enum WeaponAttackType { @@ -1275,7 +1277,6 @@ class TRINITY_DLL_SPEC Unit : public WorldObject void AddThreat(Unit* pVictim, float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellEntry const *threatSpell = NULL); float ApplyTotalThreatModifier(float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL); void DeleteThreatList(); - //bool SelectHostilTarget(); void TauntApply(Unit* pVictim); void TauntFadeOut(Unit *taunter); ThreatManager& getThreatManager() { return m_ThreatManager; } |
