diff options
author | megamage <none@none> | 2009-05-02 13:30:55 -0500 |
---|---|---|
committer | megamage <none@none> | 2009-05-02 13:30:55 -0500 |
commit | 9f0f239e60e2c7f0b8d36d1984f459102022164e (patch) | |
tree | 45e7629371e903fdd429a1bf449c9c53bf46d9ec /src | |
parent | 8a05a5b91cf884c87c9ada5b0bd0ab872a3167e0 (diff) | |
parent | f303ee08c5888170ad1509b89413af1e2a321f5c (diff) |
*Merge.
*Also fix build in VC7 and VC8.
--HG--
branch : trunk
Diffstat (limited to 'src')
-rw-r--r-- | src/bindings/scripts/VC71/71ScriptDev2.vcproj | 2 | ||||
-rw-r--r-- | src/bindings/scripts/VC80/80ScriptDev2.vcproj | 2 | ||||
-rw-r--r-- | src/bindings/scripts/include/sc_creature.cpp | 46 | ||||
-rw-r--r-- | src/game/ConfusedMovementGenerator.cpp | 4 | ||||
-rw-r--r-- | src/game/DestinationHolder.h | 2 | ||||
-rw-r--r-- | src/game/DestinationHolderImp.h | 59 | ||||
-rw-r--r-- | src/game/FleeingMovementGenerator.cpp | 2 | ||||
-rw-r--r-- | src/game/GridNotifiersImpl.h | 2 | ||||
-rw-r--r-- | src/game/HomeMovementGenerator.cpp | 2 | ||||
-rw-r--r-- | src/game/IdleMovementGenerator.cpp | 9 | ||||
-rw-r--r-- | src/game/PetHandler.cpp | 2 | ||||
-rw-r--r-- | src/game/PointMovementGenerator.cpp | 3 | ||||
-rw-r--r-- | src/game/RandomMovementGenerator.cpp | 4 | ||||
-rw-r--r-- | src/game/SharedDefines.h | 71 | ||||
-rw-r--r-- | src/game/Spell.cpp | 1040 | ||||
-rw-r--r-- | src/game/Spell.h | 49 | ||||
-rw-r--r-- | src/game/SpellEffects.cpp | 10 | ||||
-rw-r--r-- | src/game/SpellMgr.cpp | 139 | ||||
-rw-r--r-- | src/game/SpellMgr.h | 20 | ||||
-rw-r--r-- | src/game/TargetedMovementGenerator.cpp | 2 | ||||
-rw-r--r-- | src/game/Unit.cpp | 8 | ||||
-rw-r--r-- | src/game/Unit.h | 3 | ||||
-rw-r--r-- | src/game/WaypointMovementGenerator.cpp | 4 |
23 files changed, 772 insertions, 713 deletions
diff --git a/src/bindings/scripts/VC71/71ScriptDev2.vcproj b/src/bindings/scripts/VC71/71ScriptDev2.vcproj index 3f8ea7f0c58..eacdacec170 100644 --- a/src/bindings/scripts/VC71/71ScriptDev2.vcproj +++ b/src/bindings/scripts/VC71/71ScriptDev2.vcproj @@ -525,7 +525,7 @@ > </File> <File - RelativePath="..\scripts\zone\eastern_plaguelands\scarlet_enclave.cpp" + RelativePath="..\scripts\zone\eastern_plaguelands\the_scarlet_enclave.cpp" > </File> </Filter> diff --git a/src/bindings/scripts/VC80/80ScriptDev2.vcproj b/src/bindings/scripts/VC80/80ScriptDev2.vcproj index a1efa4952bc..ace2ac54ca3 100644 --- a/src/bindings/scripts/VC80/80ScriptDev2.vcproj +++ b/src/bindings/scripts/VC80/80ScriptDev2.vcproj @@ -694,7 +694,7 @@ > </File> <File - RelativePath="..\scripts\zone\eastern_plaguelands\scarlet_enclave.cpp" + RelativePath="..\scripts\zone\eastern_plaguelands\the_scarlet_enclave.cpp" > </File> </Filter> diff --git a/src/bindings/scripts/include/sc_creature.cpp b/src/bindings/scripts/include/sc_creature.cpp index 6d1fbc73dd5..1942fdadd71 100644 --- a/src/bindings/scripts/include/sc_creature.cpp +++ b/src/bindings/scripts/include/sc_creature.cpp @@ -552,49 +552,49 @@ void FillSpellSummary() for (int j=0; j<3; j++) { //Spell targets self - if ( TempSpell->EffectImplicitTargetA[j] == TARGET_SELF ) + if ( TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_CASTER ) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SELF-1); //Spell targets a single enemy - if ( TempSpell->EffectImplicitTargetA[j] == TARGET_CHAIN_DAMAGE || - TempSpell->EffectImplicitTargetA[j] == TARGET_CURRENT_ENEMY_COORDINATES ) + if ( TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_TARGET_ENEMY || + TempSpell->EffectImplicitTargetA[j] == TARGET_DST_TARGET_ENEMY ) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_ENEMY-1); //Spell targets AoE at enemy - if ( TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA || - TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_INSTANT || - TempSpell->EffectImplicitTargetA[j] == TARGET_DEST_CASTER || + if ( TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_AREA_ENEMY_SRC || + TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_AREA_ENEMY_DST || + TempSpell->EffectImplicitTargetA[j] == TARGET_SRC_CASTER || TempSpell->EffectImplicitTargetA[j] == TARGET_DEST_DYNOBJ_ENEMY ) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_ENEMY-1); //Spell targets an enemy - if ( TempSpell->EffectImplicitTargetA[j] == TARGET_CHAIN_DAMAGE || - TempSpell->EffectImplicitTargetA[j] == TARGET_CURRENT_ENEMY_COORDINATES || - TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA || - TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_INSTANT || - TempSpell->EffectImplicitTargetA[j] == TARGET_DEST_CASTER || + if ( TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_TARGET_ENEMY || + TempSpell->EffectImplicitTargetA[j] == TARGET_DST_TARGET_ENEMY || + TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_AREA_ENEMY_SRC || + TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_AREA_ENEMY_DST || + TempSpell->EffectImplicitTargetA[j] == TARGET_SRC_CASTER || TempSpell->EffectImplicitTargetA[j] == TARGET_DEST_DYNOBJ_ENEMY ) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_ENEMY-1); //Spell targets a single friend(or self) - if ( TempSpell->EffectImplicitTargetA[j] == TARGET_SELF || - TempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_FRIEND || - TempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_PARTY ) + if ( TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_CASTER || + TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_TARGET_ALLY || + TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_TARGET_PARTY ) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_FRIEND-1); //Spell targets aoe friends - if ( TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_PARTY_AROUND_CASTER || - TempSpell->EffectImplicitTargetA[j] == TARGET_AREAEFFECT_PARTY || - TempSpell->EffectImplicitTargetA[j] == TARGET_DEST_CASTER) + if ( TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_PARTY_CASTER || + TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_PARTY_TARGET || + TempSpell->EffectImplicitTargetA[j] == TARGET_SRC_CASTER) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_FRIEND-1); //Spell targets any friend(or self) - if ( TempSpell->EffectImplicitTargetA[j] == TARGET_SELF || - TempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_FRIEND || - TempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_PARTY || - TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_PARTY_AROUND_CASTER || - TempSpell->EffectImplicitTargetA[j] == TARGET_AREAEFFECT_PARTY || - TempSpell->EffectImplicitTargetA[j] == TARGET_DEST_CASTER) + if ( TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_CASTER || + TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_TARGET_ALLY || + TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_TARGET_PARTY || + TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_PARTY_CASTER || + TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_PARTY_TARGET || + TempSpell->EffectImplicitTargetA[j] == TARGET_SRC_CASTER) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_FRIEND-1); //Make sure that this spell includes a damage effect diff --git a/src/game/ConfusedMovementGenerator.cpp b/src/game/ConfusedMovementGenerator.cpp index bbb0b9ebc6a..da383cc8a07 100644 --- a/src/game/ConfusedMovementGenerator.cpp +++ b/src/game/ConfusedMovementGenerator.cpp @@ -114,12 +114,12 @@ ConfusedMovementGenerator<T>::Update(T &unit, const uint32 &diff) { // currently moving, update location Traveller<T> traveller(unit); - if( i_destinationHolder.UpdateTraveller(traveller, diff, false)) + if( i_destinationHolder.UpdateTraveller(traveller, diff)) { if( i_destinationHolder.HasArrived()) { // arrived, stop and wait a bit - unit.StopMoving(); + unit.clearUnitState(UNIT_STAT_MOVE); i_nextMove = urand(1,MAX_CONF_WAYPOINTS); i_nextMoveTime.Reset(urand(0, 1500-1)); // TODO: check the minimum reset time, should be probably higher diff --git a/src/game/DestinationHolder.h b/src/game/DestinationHolder.h index 94e12a1757d..c37b60e8b54 100644 --- a/src/game/DestinationHolder.h +++ b/src/game/DestinationHolder.h @@ -51,7 +51,7 @@ class TRINITY_DLL_DECL DestinationHolder bool HasDestination(void) const { return i_destSet; } float GetDestinationDiff(float x, float y, float z) const; bool HasArrived(void) const { return (i_totalTravelTime == 0 || i_timeElapsed >= i_totalTravelTime); } - bool UpdateTraveller(TRAVELLER &traveller, uint32 diff, bool force_update=false, bool micro_movement=false); + bool UpdateTraveller(TRAVELLER &traveller, uint32 diff, bool micro_movement=false); uint32 StartTravel(TRAVELLER &traveller, bool sendMove = true); void GetLocationNow(uint32 mapid, float &x, float &y, float &z, bool is3D = false) const; void GetLocationNowNoMicroMovement(float &x, float &y, float &z) const; // For use without micro movement diff --git a/src/game/DestinationHolderImp.h b/src/game/DestinationHolderImp.h index 384ad9621a3..0286851cbb7 100644 --- a/src/game/DestinationHolderImp.h +++ b/src/game/DestinationHolderImp.h @@ -93,37 +93,29 @@ DestinationHolder<TRAVELLER>::StartTravel(TRAVELLER &traveller, bool sendMove) template<typename TRAVELLER> bool -DestinationHolder<TRAVELLER>::UpdateTraveller(TRAVELLER &traveller, uint32 diff, bool force_update, bool micro_movement) +DestinationHolder<TRAVELLER>::UpdateTraveller(TRAVELLER &traveller, uint32 diff, bool micro_movement) { + i_timeElapsed += diff; + + // Update every TRAVELLER_UPDATE_INTERVAL + i_tracker.Update(diff); + if(!i_tracker.Passed()) + return false; + else + ResetUpdate(); + + if(!i_destSet) return true; + + float x, y, z; if(!micro_movement) { - i_tracker.Update(diff); - i_timeElapsed += diff; - if( i_tracker.Passed() || force_update ) - { - ResetUpdate(); - if(!i_destSet) return true; - float x,y,z; - GetLocationNowNoMicroMovement(x, y, z); - if( x == -431602080 ) - return false; - if( traveller.GetTraveller().GetPositionX() != x || traveller.GetTraveller().GetPositionY() != y ) - { - float ori = traveller.GetTraveller().GetAngle(x, y); - traveller.Relocation(x, y, z, ori); - } - return true; - } - return false; + GetLocationNowNoMicroMovement(x, y, z); + + if( x == -431602080 ) + return false; } - i_tracker.Update(diff); - i_timeElapsed += diff; - if( i_tracker.Passed() || force_update ) + else { - ResetUpdate(); - if(!i_destSet) return true; - float x,y,z; - if(!traveller.GetTraveller().hasUnitState(UNIT_STAT_MOVING | UNIT_STAT_IN_FLIGHT)) return true; @@ -135,11 +127,6 @@ DestinationHolder<TRAVELLER>::UpdateTraveller(TRAVELLER &traveller, uint32 diff, if( x == -431602080 ) return false; - if( traveller.GetTraveller().GetPositionX() != x || traveller.GetTraveller().GetPositionY() != y ) - { - float ori = traveller.GetTraveller().GetAngle(x, y); - traveller.Relocation(x, y, z, ori); - } // Change movement computation to micro movement based on last tick coords, this makes system work // even on multiple floors zones without hugh vmaps usage ;) @@ -153,9 +140,15 @@ DestinationHolder<TRAVELLER>::UpdateTraveller(TRAVELLER &traveller, uint32 diff, i_fromX = x; // and change origine i_fromY = y; // then I take into account only micro movement i_fromZ = z; - return true; } - return false; + + if( traveller.GetTraveller().GetPositionX() != x || traveller.GetTraveller().GetPositionY() != y ) + { + float ori = traveller.GetTraveller().GetAngle(x, y); + traveller.Relocation(x, y, z, ori); + } + + return true; } template<typename TRAVELLER> diff --git a/src/game/FleeingMovementGenerator.cpp b/src/game/FleeingMovementGenerator.cpp index 0b499168538..538d513b298 100644 --- a/src/game/FleeingMovementGenerator.cpp +++ b/src/game/FleeingMovementGenerator.cpp @@ -383,7 +383,7 @@ FleeingMovementGenerator<T>::Update(T &owner, const uint32 & time_diff) return true; } - if (i_destinationHolder.UpdateTraveller(traveller, time_diff, false)) + if (i_destinationHolder.UpdateTraveller(traveller, time_diff)) { i_destinationHolder.ResetUpdate(50); if(i_nextCheckTime.Passed() && i_destinationHolder.HasArrived()) diff --git a/src/game/GridNotifiersImpl.h b/src/game/GridNotifiersImpl.h index 54cbff2c7bb..62cae5b33a0 100644 --- a/src/game/GridNotifiersImpl.h +++ b/src/game/GridNotifiersImpl.h @@ -181,7 +181,7 @@ inline void Trinity::DynamicObjectUpdater::VisitHelper(Unit* target) SpellEntry const *spellInfo = sSpellStore.LookupEntry(i_dynobject.GetSpellId()); uint32 eff_index = i_dynobject.GetEffIndex(); if(spellInfo->EffectImplicitTargetB[eff_index] == TARGET_DEST_DYNOBJ_ALLY - || spellInfo->EffectImplicitTargetB[eff_index] == TARGET_UNIT_AREA_ALLY_GROUND) + || spellInfo->EffectImplicitTargetB[eff_index] == TARGET_UNIT_AREA_ALLY_DST) { if(!i_check->IsFriendlyTo(target)) return; diff --git a/src/game/HomeMovementGenerator.cpp b/src/game/HomeMovementGenerator.cpp index 4f0ca2f8cec..a2bad0b0db7 100644 --- a/src/game/HomeMovementGenerator.cpp +++ b/src/game/HomeMovementGenerator.cpp @@ -60,7 +60,7 @@ bool HomeMovementGenerator<Creature>::Update(Creature &owner, const uint32& time_diff) { CreatureTraveller traveller( owner); - i_destinationHolder.UpdateTraveller(traveller, time_diff, false); + i_destinationHolder.UpdateTraveller(traveller, time_diff); if (time_diff > i_travel_timer) { diff --git a/src/game/IdleMovementGenerator.cpp b/src/game/IdleMovementGenerator.cpp index 67f89303e40..2428c49a77a 100644 --- a/src/game/IdleMovementGenerator.cpp +++ b/src/game/IdleMovementGenerator.cpp @@ -23,14 +23,19 @@ IdleMovementGenerator si_idleMovement; +// StopMoving is needed to make unit stop if its last movement generator expires +// But it should not be sent otherwise there are many redundent packets void IdleMovementGenerator::Initialize(Unit &owner) { - owner.StopMoving(); + if(owner.hasUnitState(UNIT_STAT_MOVE)) + owner.StopMoving(); } void -IdleMovementGenerator::Reset(Unit& /*owner*/) +IdleMovementGenerator::Reset(Unit& owner) { + if(owner.hasUnitState(UNIT_STAT_MOVE)) + owner.StopMoving(); } void diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp index 71ae527e7d7..15dac10688f 100644 --- a/src/game/PetHandler.cpp +++ b/src/game/PetHandler.cpp @@ -209,7 +209,7 @@ void WorldSession::HandlePetActionHelper(Unit *pet, uint64 guid1, uint16 spellid for(uint32 i = 0; i < 3;++i) { - if(spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_ENEMY_IN_AREA || spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_ENEMY_IN_AREA_INSTANT || spellInfo->EffectImplicitTargetA[i] == TARGET_DEST_DYNOBJ_ENEMY) + if(spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_AREA_ENEMY_SRC || spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_AREA_ENEMY_DST || spellInfo->EffectImplicitTargetA[i] == TARGET_DEST_DYNOBJ_ENEMY) return; } diff --git a/src/game/PointMovementGenerator.cpp b/src/game/PointMovementGenerator.cpp index 084dad7cfa8..0c3758bfc5e 100644 --- a/src/game/PointMovementGenerator.cpp +++ b/src/game/PointMovementGenerator.cpp @@ -53,10 +53,11 @@ bool PointMovementGenerator<T>::Update(T &unit, const uint32 &diff) Traveller<T> traveller(unit); - i_destinationHolder.UpdateTraveller(traveller, diff, false); + i_destinationHolder.UpdateTraveller(traveller, diff); if(i_destinationHolder.HasArrived()) { + unit.clearUnitState(UNIT_STAT_MOVE); arrived = true; return false; } diff --git a/src/game/RandomMovementGenerator.cpp b/src/game/RandomMovementGenerator.cpp index 0081c702abd..6d147f15b8d 100644 --- a/src/game/RandomMovementGenerator.cpp +++ b/src/game/RandomMovementGenerator.cpp @@ -164,14 +164,14 @@ RandomMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff i_nextMoveTime.Update(diff); if(i_destinationHolder.HasArrived() && !creature.IsStopped() && !creature.canFly()) - creature.clearUnitState(UNIT_STAT_ROAMING); + creature.clearUnitState(UNIT_STAT_ROAMING | UNIT_STAT_MOVE); if(!i_destinationHolder.HasArrived() && creature.IsStopped()) creature.addUnitState(UNIT_STAT_ROAMING); CreatureTraveller traveller(creature); - if( i_destinationHolder.UpdateTraveller(traveller, diff, false, true) ) + if( i_destinationHolder.UpdateTraveller(traveller, diff, true) ) { if(i_nextMoveTime.Passed()) { diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 8628107b4e2..f497e4c709a 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -995,63 +995,43 @@ enum SpellImmunity enum Targets { - TARGET_SELF = 1, TARGET_UNIT_CASTER = 1, - TARGET_UNIT_NEARBY_ENEMY = 2, + TARGET_UNIT_NEARBY_ENEMY = 2, // only one spell has that, but regardless, it's a target type after all TARGET_UNIT_NEARBY_ALLY = 3, TARGET_UNIT_NEARBY_ALLY_UNK = 4, - TARGET_PET = 5, TARGET_UNIT_PET = 5, - TARGET_CHAIN_DAMAGE = 6, TARGET_UNIT_TARGET_ENEMY = 6, - TARGET_UNIT_AREA_ENTRY = 7, - TARGET_AREAEFFECT_CUSTOM = 8, - TARGET_UNIT_AREA_ENTRY_GROUND = 8, - TARGET_INNKEEPER_COORDINATES = 9, // uses in teleport to innkeeper spells - //TARGET_DEST_HOME + TARGET_UNIT_AREA_ENTRY_SRC = 7, + TARGET_UNIT_AREA_ENTRY_DST = 8, + TARGET_DST_HOME = 9, // uses in teleport to innkeeper spells TARGET_UNIT_TARGET_DEST_CASTER = 11, // teleport target to caster - TARGET_ALL_ENEMY_IN_AREA = 15, - TARGET_UNIT_AREA_ENEMY = 15, - TARGET_ALL_ENEMY_IN_AREA_INSTANT = 16, - TARGET_UNIT_AREA_ENEMY_GROUND = 16, - TARGET_TABLE_X_Y_Z_COORDINATES = 17, // uses in teleport spells and some other - //TARGET_DEST_TABLE - TARGET_EFFECT_SELECT = 18, // highly depends on the spell effect - TARGET_DEST_CASTER_GROUND = 18, + TARGET_UNIT_AREA_ENEMY_SRC = 15, + TARGET_UNIT_AREA_ENEMY_DST = 16, + TARGET_DST_DB = 17, // uses in teleport spells and some other + TARGET_DST_CASTER = 18, TARGET_PREV_EFFECT_SUMMON = 18, - TARGET_ALL_PARTY_AROUND_CASTER = 20, TARGET_UNIT_PARTY_CASTER = 20, - TARGET_SINGLE_FRIEND = 21, TARGET_UNIT_TARGET_ALLY = 21, - TARGET_DEST_CASTER = 22, + TARGET_SRC_CASTER = 22, TARGET_GAMEOBJECT = 23, //TARGET_OBJECT_OPEN - TARGET_IN_FRONT_OF_CASTER = 24, TARGET_UNIT_CONE_ENEMY = 24, - TARGET_DUELVSPLAYER = 25, TARGET_UNIT_TARGET_ANY = 25, TARGET_GAMEOBJECT_ITEM = 26, //TARGET_OBJECT_ITEM_PICKLOCK TARGET_UNIT_MASTER = 27, TARGET_DEST_DYNOBJ_ENEMY = 28, TARGET_DEST_DYNOBJ_ALLY = 29, // only for effect 27 - TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER = 30, // in TargetB used only with TARGET_ALL_AROUND_CASTER and in self casting range in TargetA - TARGET_UNIT_AREA_ALLY = 30, - TARGET_ALL_FRIENDLY_UNITS_IN_AREA = 31, - TARGET_UNIT_AREA_ALLY_GROUND = 31, + TARGET_UNIT_AREA_ALLY_SRC = 30, // in TargetB used only with TARGET_SRC_CASTER and in self casting range in TargetA + TARGET_UNIT_AREA_ALLY_DST = 31, TARGET_MINION = 32, //TARGET_DEST_SUMMON - TARGET_ALL_PARTY = 33, - TARGET_UNIT_AREA_PARTY = 33, - TARGET_ALL_PARTY_AROUND_CASTER_2 = 34, // used in Tranquility - TARGET_UNIT_AREA_PARTY_GROUND = 34, - TARGET_SINGLE_PARTY = 35, + TARGET_UNIT_AREA_PARTY_SRC = 33, + TARGET_UNIT_AREA_PARTY_DST = 34, // used in Tranquility TARGET_UNIT_TARGET_PARTY = 35, TARGET_DEST_CASTER_RANDOM_UNKNOWN = 36, //unknown - TARGET_AREAEFFECT_PARTY = 37, TARGET_UNIT_PARTY_TARGET = 37, - TARGET_SCRIPT = 38, - //TARGET_UNIT_NEARBY_ENTRY + TARGET_UNIT_NEARBY_ENTRY = 38, TARGET_UNIT_CASTER_FISHING = 39, TARGET_OBJECT_USE = 40, TARGET_DEST_CASTER_FRONT_LEFT = 41, //earth totem @@ -1059,28 +1039,23 @@ enum Targets TARGET_DEST_CASTER_BACK_RIGHT = 43, //air totem TARGET_DEST_CASTER_FRONT_RIGHT = 44, //fire totem TARGET_UNIT_CHAINHEAL = 45, - TARGET_SCRIPT_COORDINATES = 46, - //TARGET_DEST_NEARBY_ENTRY + TARGET_DST_NEARBY_ENTRY = 46, TARGET_DEST_CASTER_FRONT = 47, TARGET_DEST_CASTER_BACK = 48, TARGET_DEST_CASTER_RIGHT = 49, TARGET_DEST_CASTER_LEFT = 50, - TARGET_OBJECT_AREA = 51, - TARGET_AREAEFFECT_CUSTOM_2 = 52, - //TARGET_DUMMY - TARGET_CURRENT_ENEMY_COORDINATES = 53, // set unit coordinates as dest, only 16 target B imlemented - TARGET_DEST_TARGET_ENEMY = 53, - TARGET_UNIT_CONE_ENEMY_UNKNOWN = 54, + TARGET_OBJECT_AREA_SRC = 51, + TARGET_OBJECT_AREA_DST = 52, + TARGET_DST_TARGET_ENEMY = 53, // set unit coordinates as dest, only 16 target B imlemented + TARGET_UNIT_CONE_ENEMY_UNKNOWN = 54, // 180 degree, or different angle TARGET_DEST_CASTER_FRONT_LEAP = 55, // for a leap spell - TARGET_UNIT_RAID = 56, - TARGET_SINGLE_FRIEND_2 = 57, + TARGET_UNIT_RAID_CASTER = 56, TARGET_UNIT_TARGET_RAID = 57, + TARGET_UNIT_NEARBY_RAID = 58, TARGET_UNIT_CONE_ALLY = 59, - TARGET_UNIT_AREA_SCRIPT = 60, - TARGET_AREAEFFECT_PARTY_AND_CLASS = 61, + TARGET_UNIT_CONE_ENTRY = 60, TARGET_UNIT_CLASS_TARGET = 61, TARGET_TEST = 62, // for a test spell - TARGET_DUELVSPLAYER_COORDINATES = 63, TARGET_DEST_TARGET_ANY = 63, TARGET_DEST_TARGET_FRONT = 64, TARGET_DEST_TARGET_BACK = 65, // uses in teleport behind spells @@ -1106,7 +1081,7 @@ enum Targets TARGET_DEST_DEST_FRONT_RIGHT = 85, TARGET_DEST_DEST_RANDOM = 86, TARGET_DEST_DEST = 87, - TARGET_UNIT_AREA_ALL_CHANNEL = 88, + TARGET_DEST_DYNOBJ_NONE = 88, TARGET_DEST_TRAJ = 89, TARGET_UNIT_MINIPET = 90, TARGET_CORPSE_AREA_ENEMY_PLAYER = 93, diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 3113beac3f6..8817854971e 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -75,7 +75,6 @@ SpellCastTargets::SpellCastTargets() m_itemTargetEntry = 0; m_srcX = m_srcY = m_srcZ = m_destX = m_destY = m_destZ = 0; - m_hasDest = false; m_strTarget = ""; m_targetMask = 0; } @@ -94,38 +93,49 @@ void SpellCastTargets::setUnitTarget(Unit *target) m_targetMask |= TARGET_FLAG_UNIT; } -void SpellCastTargets::setDestination(float x, float y, float z, bool send, int32 mapId) +void SpellCastTargets::setSrc(float x, float y, float z) +{ + m_srcX = x; + m_srcY = y; + m_srcZ = z; + m_targetMask |= TARGET_FLAG_SOURCE_LOCATION; +} + +void SpellCastTargets::setSrc(WorldObject *target) +{ + if(!target) + return; + + target->GetPosition(m_srcX, m_srcY, m_srcZ); + m_targetMask |= TARGET_FLAG_SOURCE_LOCATION; +} + +void SpellCastTargets::setDestination(float x, float y, float z, int32 mapId) { m_destX = x; m_destY = y; m_destZ = z; - m_hasDest = true; - if(send) - m_targetMask |= TARGET_FLAG_DEST_LOCATION; + m_targetMask |= TARGET_FLAG_DEST_LOCATION; if(mapId >= 0) m_mapId = mapId; } -void SpellCastTargets::setDestination(Unit *target, bool send) +void SpellCastTargets::setDestination(WorldObject *target) { if(!target) return; - m_destX = target->GetPositionX(); - m_destY = target->GetPositionY(); - m_destZ = target->GetPositionZ(); - m_hasDest = true; - if(send) - m_targetMask |= TARGET_FLAG_DEST_LOCATION; + target->GetPosition(m_destX, m_destY, m_destZ); + m_targetMask |= TARGET_FLAG_DEST_LOCATION; } -void SpellCastTargets::setSource(float x, float y, float z) +/*void SpellCastTargets::setSource(float x, float y, float z) { m_srcX = x; m_srcY = y; m_srcZ = z; m_targetMask |= TARGET_FLAG_SOURCE_LOCATION; -} +}*/ void SpellCastTargets::setGOTarget(GameObject *target) { @@ -211,8 +221,6 @@ bool SpellCastTargets::read ( WorldPacket * data, Unit *caster ) *data >> m_srcX >> m_srcY >> m_srcZ; if(!Trinity::IsValidMapCoord(m_srcX, m_srcY, m_srcZ)) return false; - - m_hasDest = true; } if( m_targetMask & TARGET_FLAG_DEST_LOCATION ) @@ -226,8 +234,6 @@ bool SpellCastTargets::read ( WorldPacket * data, Unit *caster ) *data >> m_destX >> m_destY >> m_destZ; if(!Trinity::IsValidMapCoord(m_destX, m_destY, m_destZ)) return false; - - m_hasDest = true; } if( m_targetMask & TARGET_FLAG_STRING ) @@ -435,28 +441,18 @@ void Spell::FillTargetMap() if(effectTargetType == SPELL_REQUIRE_NONE) continue; - std::list<Unit*> tmpUnitMap; uint32 targetA = m_spellInfo->EffectImplicitTargetA[i]; uint32 targetB = m_spellInfo->EffectImplicitTargetB[i]; if(targetA) - SetTargetMap(i, targetA, tmpUnitMap); + SetTargetMap(i, targetA); if(targetB) // In very rare case !A && B - SetTargetMap(i, targetB, tmpUnitMap); + SetTargetMap(i, targetB); if(effectTargetType != SPELL_REQUIRE_UNIT) { if(effectTargetType == SPELL_REQUIRE_CASTER) AddUnitTarget(m_caster, i); - /*else if(effectTargetType == SPELL_REQUIRE_DEST) - { - if(m_targets.HasDest() && m_spellInfo->speed > 0.0f) - { - 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); - } - }*/ else if(effectTargetType == SPELL_REQUIRE_ITEM) { if(m_targets.getItemTarget()) @@ -465,7 +461,7 @@ void Spell::FillTargetMap() continue; } - if(tmpUnitMap.empty() && m_spellInfo->Targets & TARGET_FLAG_CASTER) + if(/*tmpUnitMap.empty() && */m_spellInfo->Targets & TARGET_FLAG_CASTER) { AddUnitTarget(m_caster, i); continue; @@ -507,12 +503,12 @@ void Spell::FillTargetMap() { case TYPEID_UNIT: case TYPEID_PLAYER: - tmpUnitMap.push_back((Unit*)result); + AddUnitTarget((Unit*)result, i); break; case TYPEID_CORPSE: m_targets.setCorpseTarget((Corpse*)result); if(Player* owner = ObjectAccessor::FindPlayer(((Corpse*)result)->GetOwnerGUID())) - tmpUnitMap.push_back(owner); + AddUnitTarget(owner, i); break; } } @@ -536,7 +532,7 @@ void Spell::FillTargetMap() } default: if(m_targets.getUnitTarget()) - tmpUnitMap.push_back(m_targets.getUnitTarget()); + AddUnitTarget(m_targets.getUnitTarget(), i); break; } break; @@ -551,22 +547,22 @@ void Spell::FillTargetMap() case SPELL_EFFECT_REPUTATION: case SPELL_EFFECT_LEARN_SPELL: if(m_targets.getUnitTarget()) - tmpUnitMap.push_back(m_targets.getUnitTarget()); + AddUnitTarget(m_targets.getUnitTarget(), i); // Triggered spells have additional spell targets - cast them even if no explicit unit target is given (required for spell 50516 for example) else if(m_spellInfo->Effect[i] == SPELL_EFFECT_TRIGGER_SPELL) - tmpUnitMap.push_back(m_caster); + AddUnitTarget(m_caster, i); break; case SPELL_EFFECT_SUMMON_PLAYER: if(m_caster->GetTypeId()==TYPEID_PLAYER && ((Player*)m_caster)->GetSelection()) { Player* target = objmgr.GetPlayer(((Player*)m_caster)->GetSelection()); if(target) - tmpUnitMap.push_back(target); + AddUnitTarget(target, i); } break; case SPELL_EFFECT_RESURRECT_NEW: if(m_targets.getUnitTarget()) - tmpUnitMap.push_back(m_targets.getUnitTarget()); + AddUnitTarget(m_targets.getUnitTarget(), i); if(m_targets.getCorpseTargetGUID()) { Corpse *corpse = ObjectAccessor::GetCorpse(*m_caster,m_targets.getCorpseTargetGUID()); @@ -574,7 +570,7 @@ void Spell::FillTargetMap() { Player* owner = ObjectAccessor::FindPlayer(corpse->GetOwnerGUID()); if(owner) - tmpUnitMap.push_back(owner); + AddUnitTarget(owner, i); } } break; @@ -584,11 +580,11 @@ void Spell::FillTargetMap() case SPELL_EFFECT_STUCK: case SPELL_EFFECT_FEED_PET: case SPELL_EFFECT_DESTROY_ALL_TOTEMS: - tmpUnitMap.push_back(m_caster); + AddUnitTarget(m_caster, i); break; case SPELL_EFFECT_LEARN_PET_SPELL: if(Guardian* pet = m_caster->GetGuardianPet()) - tmpUnitMap.push_back(pet); + AddUnitTarget(pet, i); break; /*case SPELL_EFFECT_ENCHANT_ITEM: case SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY: @@ -602,9 +598,9 @@ void Spell::FillTargetMap() case SPELL_EFFECT_APPLY_AURA: switch(m_spellInfo->EffectApplyAuraName[i]) { - case SPELL_AURA_ADD_FLAT_MODIFIER: // some spell mods auras have 0 target modes instead expected TARGET_SELF(1) (and present for other ranks for same spell for example) + case SPELL_AURA_ADD_FLAT_MODIFIER: // some spell mods auras have 0 target modes instead expected TARGET_UNIT_CASTER(1) (and present for other ranks for same spell for example) case SPELL_AURA_ADD_PCT_MODIFIER: - tmpUnitMap.push_back(m_caster); + AddUnitTarget(m_caster, i); break; default: // apply to target in other case break; @@ -613,12 +609,12 @@ void Spell::FillTargetMap() case SPELL_EFFECT_APPLY_AREA_AURA_PARTY: // AreaAura if(m_spellInfo->Attributes == 0x9050000 || m_spellInfo->Attributes == 0x10000) - SetTargetMap(i,TARGET_AREAEFFECT_PARTY,tmpUnitMap); + SetTargetMap(i, TARGET_UNIT_PARTY_TARGET); break; case SPELL_EFFECT_SKIN_PLAYER_CORPSE: if(m_targets.getUnitTarget()) { - tmpUnitMap.push_back(m_targets.getUnitTarget()); + AddUnitTarget(m_targets.getUnitTarget(), i); } else if (m_targets.getCorpseTargetGUID()) { @@ -627,7 +623,7 @@ void Spell::FillTargetMap() { Player* owner = ObjectAccessor::FindPlayer(corpse->GetOwnerGUID()); if(owner) - tmpUnitMap.push_back(owner); + AddUnitTarget(owner, i); } } break; @@ -636,27 +632,23 @@ void Spell::FillTargetMap() } } - if(IsChanneledSpell(m_spellInfo) && !tmpUnitMap.empty()) - m_needAliveTargetMask |= (1<<i); - - for (std::list<Unit*>::iterator itr = tmpUnitMap.begin() ; itr != tmpUnitMap.end();) + if(IsChanneledSpell(m_spellInfo)) { - if(!CheckTarget(*itr, i)) + uint8 mask = (1<<i); + for(std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) { - itr = tmpUnitMap.erase(itr); - continue; + if(ihit->effectMask & mask) + { + m_needAliveTargetMask |= mask; + break; + } } - else - ++itr; } - - 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()) + if(m_spellInfo->speed > 0.0f && m_targets.HasDst()) { float dist = m_caster->GetDistance(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ); if (dist < 5.0f) dist = 5.0f; @@ -728,6 +720,9 @@ void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex) if( m_spellInfo->Effect[effIndex]==0 ) return; + if(!CheckTarget(pVictim, effIndex)) + return; + // Check for effect immune skip if immuned bool immuned = pVictim->IsImmunedToSpellEffect(m_spellInfo, effIndex); @@ -1375,13 +1370,13 @@ void Spell::SearchChainTarget(std::list<Unit*> &TagUnitMap, float max_range, uin std::list<Unit*> tempUnitMap; if(TargetType == SPELL_TARGETS_CHAINHEAL) { - SearchAreaTarget(tempUnitMap, max_range, PUSH_TARGET_CENTER, SPELL_TARGETS_ALLY); + SearchAreaTarget(tempUnitMap, max_range, PUSH_CHAIN, SPELL_TARGETS_ALLY); tempUnitMap.sort(ChainHealingOrder(m_caster)); //if(cur->GetHealth() == cur->GetMaxHealth() && tempUnitMap.size()) // cur = tempUnitMap.front(); } else - SearchAreaTarget(tempUnitMap, max_range, PUSH_TARGET_CENTER, TargetType); + SearchAreaTarget(tempUnitMap, max_range, PUSH_CHAIN, TargetType); tempUnitMap.remove(cur); while(num) @@ -1431,34 +1426,38 @@ void Spell::SearchChainTarget(std::list<Unit*> &TagUnitMap, float max_range, uin void Spell::SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, SpellNotifyPushType type, SpellTargets TargetType, uint32 entry) { float x, y, z; - if(type == PUSH_DEST_CENTER) - { - if(!m_targets.HasDest()) - { - sLog.outError( "SPELL: cannot find destination for spell ID %u\n", m_spellInfo->Id ); - return; - } - x = m_targets.m_destX; - y = m_targets.m_destY; - z = m_targets.m_destZ; - } - else if(type == PUSH_TARGET_CENTER) + switch(type) { - Unit *target = m_targets.getUnitTarget(); - if(!target) + case PUSH_DST_CENTER: + CheckDst(); + x = m_targets.m_destX; + y = m_targets.m_destY; + z = m_targets.m_destZ; + break; + case PUSH_SRC_CENTER: + CheckSrc(); + x = m_targets.m_srcX; + y = m_targets.m_srcY; + z = m_targets.m_srcZ; + break; + case PUSH_CHAIN: { - sLog.outError( "SPELL: cannot find unit target for spell ID %u\n", m_spellInfo->Id ); - return; + Unit *target = m_targets.getUnitTarget(); + if(!target) + { + sLog.outError( "SPELL: cannot find unit target for spell ID %u\n", m_spellInfo->Id ); + return; + } + x = target->GetPositionX(); + y = target->GetPositionY(); + z = target->GetPositionZ(); + break; } - x = target->GetPositionX(); - y = target->GetPositionY(); - z = target->GetPositionZ(); - } - else - { - x = m_caster->GetPositionX(); - y = m_caster->GetPositionY(); - z = m_caster->GetPositionZ(); + default: + x = m_caster->GetPositionX(); + y = m_caster->GetPositionY(); + z = m_caster->GetPositionZ(); + break; } Trinity::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, type, TargetType, entry, x, y, z); @@ -1469,83 +1468,112 @@ void Spell::SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, SpellNo m_caster->GetMap()->VisitAll(x, y, radius, notifier); } -Unit* Spell::SearchNearbyTarget(float radius, SpellTargets TargetType, uint32 entry) +WorldObject* Spell::SearchNearbyTarget(float range, SpellTargets TargetType) { - Unit* target = NULL; switch(TargetType) { case SPELL_TARGETS_ENTRY: { - if(entry) + SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(m_spellInfo->Id); + SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(m_spellInfo->Id); + if(lower == upper) { - Creature* target = NULL; - Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*m_caster, entry, true, radius); - Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(m_caster, target, u_check); - m_caster->VisitNearbyObject(radius, searcher); - return target; + sLog.outErrorDb("Spell (ID: %u) (caster Entry: %u) does not have record in `spell_script_target`", m_spellInfo->Id, m_caster->GetEntry()); + if(IsPositiveSpell(m_spellInfo->Id)) + return SearchNearbyTarget(range, SPELL_TARGETS_ALLY); + else + return SearchNearbyTarget(range, SPELL_TARGETS_ENEMY); } - else + + Creature* creatureScriptTarget = NULL; + GameObject* goScriptTarget = NULL; + + for(SpellScriptTarget::const_iterator i_spellST = lower; i_spellST != upper; ++i_spellST) { - //TODO: nearest player - return NULL; + switch(i_spellST->second.type) + { + case SPELL_TARGET_TYPE_GAMEOBJECT: + { + GameObject* p_GameObject = NULL; + + if(i_spellST->second.targetEntry) + { + Trinity::NearestGameObjectEntryInObjectRangeCheck go_check(*m_caster,i_spellST->second.targetEntry,range); + Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck> checker(m_caster,p_GameObject,go_check); + m_caster->VisitNearbyGridObject(range, checker); + + if(p_GameObject) + { + // remember found target and range, next attempt will find more near target with another entry + creatureScriptTarget = NULL; + goScriptTarget = p_GameObject; + range = go_check.GetLastRange(); + } + } + else if( focusObject ) //Focus Object + { + float frange = m_caster->GetDistance(focusObject); + if(range >= frange) + { + creatureScriptTarget = NULL; + goScriptTarget = focusObject; + range = frange; + } + } + break; + } + case SPELL_TARGET_TYPE_CREATURE: + case SPELL_TARGET_TYPE_DEAD: + default: + { + Creature *p_Creature = NULL; + + Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*m_caster,i_spellST->second.targetEntry,i_spellST->second.type!=SPELL_TARGET_TYPE_DEAD,range); + Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(m_caster,p_Creature, u_check); + m_caster->VisitNearbyObject(range, searcher); + + if(p_Creature ) + { + creatureScriptTarget = p_Creature; + goScriptTarget = NULL; + range = u_check.GetLastRange(); + } + break; + } + } } + + if(creatureScriptTarget) + return creatureScriptTarget; + else + return goScriptTarget; } default: case SPELL_TARGETS_ENEMY: { - Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, radius); + Unit *target = NULL; + Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, range); Trinity::UnitLastSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(m_caster, target, u_check); - m_caster->VisitNearbyObject(radius, searcher); - }break; + m_caster->VisitNearbyObject(range, searcher); + return target; + } case SPELL_TARGETS_ALLY: { - Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, radius); + Unit *target = NULL; + Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, range); Trinity::UnitLastSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(m_caster, target, u_check); - m_caster->VisitNearbyObject(radius, searcher); - }break; + m_caster->VisitNearbyObject(range, searcher); + return target; + } } - return target; } -void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) +void Spell::SetTargetMap(uint32 i, uint32 cur) { - float radius_h, radius_f; - if (m_spellInfo->EffectRadiusIndex[i]) - { - radius_h = GetSpellRadiusForHostile(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])) * m_spellValue->RadiusMod; - radius_f = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])) * m_spellValue->RadiusMod; - } - else - { - radius_h = GetSpellMaxRangeForHostile(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex)); - radius_f = GetSpellMaxRangeForFriend(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex)); - } - - //Chain: 2, 6, 22, 25, 45, 77 - uint32 EffectChainTarget = m_spellInfo->EffectChainTarget[i]; - uint32 unMaxTargets = m_spellValue->MaxAffectedTargets; - - Unit::AuraEffectList const& Auras = m_caster->GetAurasByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS); - for(Unit::AuraEffectList::const_iterator j = Auras.begin();j != Auras.end(); ++j) - { - if((*j)->isAffectedOnSpell(m_spellInfo)) - unMaxTargets+=(*j)->GetAmount(); - } - + SpellNotifyPushType pushType = PUSH_NONE; + Player *modOwner = NULL; if(m_originalCaster) - if (Player* modOwner = m_caster->GetSpellModOwner()) - { - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius_f,this); - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius_h,this); - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, EffectChainTarget, this); - } - - if(EffectChainTarget > 1) - { - //otherwise, this multiplier is used for something else - m_damageMultipliers[i] = 1.0f; - m_applyMultiplierMask |= 1 << i; - } + modOwner = m_originalCaster->GetSpellModOwner(); switch(spellmgr.SpellTargetType[cur]) { @@ -1555,361 +1583,135 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) { case TARGET_UNIT_CASTER: case TARGET_UNIT_CASTER_FISHING: - TagUnitMap.push_back(m_caster); + AddUnitTarget(m_caster, i); break; case TARGET_UNIT_MASTER: if(Unit* owner = m_caster->GetCharmerOrOwner()) - TagUnitMap.push_back(owner); + AddUnitTarget(owner, i); break; case TARGET_UNIT_PET: if(Guardian* pet = m_caster->GetGuardianPet()) - TagUnitMap.push_back(pet); + AddUnitTarget(pet, i); break; case TARGET_UNIT_PARTY_CASTER: - m_caster->GetPartyMember(TagUnitMap, radius_f); - break; - case TARGET_UNIT_RAID: - //if(Unit *target = m_targets.getUnitTarget()) - // TagUnitMap.push_back(target); - //else - m_caster->GetRaidMember(TagUnitMap, radius_f); + case TARGET_UNIT_RAID_CASTER: + pushType = PUSH_CASTER_CENTER; break; } - }break; + break; + } case TARGET_TYPE_UNIT_TARGET: { Unit *target = m_targets.getUnitTarget(); if(!target) { - sLog.outError("SPELL: no unit target for spell ID %u\n", m_spellInfo->Id); + sLog.outError("SPELL: no unit target for spell ID %u", m_spellInfo->Id); break; } - if(!IsPositiveSpell(m_spellInfo->Id)) - if(Unit *magnet = m_caster->SelectMagnetTarget(target)) - if(magnet != target) - m_targets.setUnitTarget(magnet); - switch(cur) { - case TARGET_UNIT_MINIPET: - if(target->GetGUID() == m_caster->m_SummonSlot[4]) - TagUnitMap.push_back(target); + case TARGET_UNIT_TARGET_ENEMY: + if(Unit *magnet = m_caster->SelectMagnetTarget(target)) + if(magnet != target) + m_targets.setUnitTarget(magnet); + pushType = PUSH_CHAIN; break; - case TARGET_UNIT_TARGET_ALLY: - case TARGET_UNIT_TARGET_RAID: case TARGET_UNIT_TARGET_ANY: - case TARGET_UNIT_TARGET_PARTY: - TagUnitMap.push_back(target); - break; - case TARGET_UNIT_PARTY_TARGET: - target->GetPartyMember(TagUnitMap, radius_f); - break; - case TARGET_UNIT_TARGET_ENEMY: - if(EffectChainTarget <= 1) - TagUnitMap.push_back(target); - else - SearchChainTarget(TagUnitMap, radius_h, EffectChainTarget, SPELL_TARGETS_ENEMY); + if(!IsPositiveSpell(m_spellInfo->Id)) + if(Unit *magnet = m_caster->SelectMagnetTarget(target)) + if(magnet != target) + m_targets.setUnitTarget(magnet); + pushType = PUSH_CHAIN; break; case TARGET_UNIT_CHAINHEAL: - if(EffectChainTarget <= 1) - TagUnitMap.push_back(target); - else - SearchChainTarget(TagUnitMap, radius_f, EffectChainTarget, SPELL_TARGETS_CHAINHEAL); + pushType = PUSH_CHAIN; break; - } - }break; - - case TARGET_TYPE_CHANNEL: - { - if(!m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL]) - { - sLog.outError( "SPELL: no current channeled spell for spell ID %u\n", m_spellInfo->Id ); - break; - } - - switch(cur) - { - case TARGET_UNIT_CHANNEL: - if(Unit* target = m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->m_targets.getUnitTarget()) - TagUnitMap.push_back(target); - else - sLog.outError( "SPELL: cannot find channel spell target for spell ID %u\n", m_spellInfo->Id ); + case TARGET_UNIT_TARGET_ALLY: + case TARGET_UNIT_TARGET_RAID: + case TARGET_UNIT_TARGET_PARTY: + case TARGET_UNIT_MINIPET: + AddUnitTarget(target, i); break; - case TARGET_DEST_CHANNEL: - if(m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->m_targets.HasDest()) - m_targets = m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->m_targets; - else - sLog.outError( "SPELL: cannot find channel spell destination for spell ID %u\n", m_spellInfo->Id ); + case TARGET_UNIT_PARTY_TARGET: + case TARGET_UNIT_CLASS_TARGET: + pushType = PUSH_CASTER_CENTER; // not real break; } - }break; + break; + } - case TARGET_TYPE_AREA_DEST: + case TARGET_TYPE_UNIT_NEARBY: { - if(!m_targets.HasDest()) - { - sLog.outError( "SPELL: cannot find destination for spell ID %u\n", m_spellInfo->Id ); - return; - } - - // Dummy for client - if(spellmgr.EffectTargetType[m_spellInfo->Effect[i]] == SPELL_REQUIRE_DEST) - break; + WorldObject *target = NULL; + float range; switch(cur) { - case TARGET_UNIT_AREA_ENEMY_GROUND: - m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION; - case TARGET_UNIT_AREA_ENEMY: - SearchAreaTarget(TagUnitMap, radius_h, PUSH_DEST_CENTER, SPELL_TARGETS_ENEMY); + case TARGET_UNIT_NEARBY_ENEMY: + range = GetSpellMaxRange(m_spellInfo, false); + if(modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this); + target = SearchNearbyTarget(range, SPELL_TARGETS_ENEMY); break; - case TARGET_UNIT_AREA_ALLY_GROUND: - m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION; - case TARGET_UNIT_AREA_ALLY: - SearchAreaTarget(TagUnitMap, radius_f, PUSH_DEST_CENTER, SPELL_TARGETS_ALLY); + case TARGET_UNIT_NEARBY_ALLY: + case TARGET_UNIT_NEARBY_ALLY_UNK: + case TARGET_UNIT_NEARBY_RAID: + range = GetSpellMaxRange(m_spellInfo, true); + if(modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this); + target = SearchNearbyTarget(range, SPELL_TARGETS_ALLY); break; - case TARGET_UNIT_AREA_PARTY_GROUND: - m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION; - case TARGET_UNIT_AREA_PARTY: - m_caster->GetPartyMember(TagUnitMap, radius_f); + case TARGET_UNIT_NEARBY_ENTRY: + range = GetSpellMaxRange(m_spellInfo, IsPositiveSpell(m_spellInfo->Id)); + if(modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this); + target = SearchNearbyTarget(range, SPELL_TARGETS_ENTRY); break; - case TARGET_UNIT_AREA_ENTRY_GROUND: - m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION; - case TARGET_UNIT_AREA_ENTRY: - { - SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(m_spellInfo->Id); - SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(m_spellInfo->Id); - if(lower==upper) - { - SearchAreaTarget(TagUnitMap, radius_h, PUSH_DEST_CENTER, SPELL_TARGETS_ENEMY); - sLog.outErrorDb("Spell (ID: %u) (caster Entry: %u) does not have record in `spell_script_target`", m_spellInfo->Id, m_caster->GetEntry()); - break; - } - // let it be done in one check? - for(SpellScriptTarget::const_iterator i_spellST = lower; i_spellST != upper; ++i_spellST) - { - if(i_spellST->second.type != SPELL_TARGET_TYPE_CREATURE) - { - sLog.outError( "SPELL: spell ID %u requires non-creature target\n", m_spellInfo->Id ); - continue; - } - SearchAreaTarget(TagUnitMap, radius_f, PUSH_DEST_CENTER, SPELL_TARGETS_ENTRY, i_spellST->second.targetEntry); - } - } - break; } - }break; - case TARGET_TYPE_DEFAULT: - { - switch(cur) + if(!target) + return; + else if(target->GetTypeId() == TYPEID_UNIT) { + pushType = PUSH_CHAIN; - case TARGET_GAMEOBJECT: - { - if(m_targets.getGOTarget()) - AddGOTarget(m_targets.getGOTarget(), i); - }break; - case TARGET_GAMEOBJECT_ITEM: - { - if(m_targets.getGOTargetGUID()) - AddGOTarget(m_targets.getGOTarget(), i); - else if(m_targets.getItemTarget()) - AddItemTarget(m_targets.getItemTarget(), i); - }break; - - case TARGET_TABLE_X_Y_Z_COORDINATES: - if(SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id)) - { - //TODO: fix this check - if(m_spellInfo->Effect[0] == SPELL_EFFECT_TELEPORT_UNITS - || m_spellInfo->Effect[1] == SPELL_EFFECT_TELEPORT_UNITS - || m_spellInfo->Effect[2] == SPELL_EFFECT_TELEPORT_UNITS) - m_targets.setDestination(st->target_X, st->target_Y, st->target_Z, true, (int32)st->target_mapId); - else if(st->target_mapId == m_caster->GetMapId()) - m_targets.setDestination(st->target_X, st->target_Y, st->target_Z); + if(!m_targets.getUnitTarget()) + m_targets.setUnitTarget((Unit*)target); } - else - sLog.outError( "SPELL: unknown target coordinates for spell ID %u\n", m_spellInfo->Id ); - break; - case TARGET_INNKEEPER_COORDINATES: - if(m_caster->GetTypeId() == TYPEID_PLAYER) - m_targets.setDestination(((Player*)m_caster)->m_homebindX,((Player*)m_caster)->m_homebindY,((Player*)m_caster)->m_homebindZ, true, ((Player*)m_caster)->m_homebindMapId); - break; + else if(target->GetTypeId() == TYPEID_GAMEOBJECT) + AddGOTarget((GameObject*)target, i); - case TARGET_IN_FRONT_OF_CASTER: - case TARGET_UNIT_CONE_ENEMY_UNKNOWN: - if(m_customAttr & SPELL_ATTR_CU_CONE_BACK) - SearchAreaTarget(TagUnitMap, radius_h, PUSH_IN_BACK, SPELL_TARGETS_ENEMY); - else if(m_customAttr & SPELL_ATTR_CU_CONE_LINE) - SearchAreaTarget(TagUnitMap, radius_h, PUSH_IN_LINE, SPELL_TARGETS_ENEMY); - else - SearchAreaTarget(TagUnitMap, radius_h, PUSH_IN_FRONT, SPELL_TARGETS_ENEMY); - break; - case TARGET_UNIT_CONE_ALLY: - SearchAreaTarget(TagUnitMap, radius_f, PUSH_IN_FRONT, SPELL_TARGETS_ALLY); break; + } - // nearby target - case TARGET_UNIT_NEARBY_ALLY: - case TARGET_UNIT_NEARBY_ALLY_UNK: - if(!m_targets.getUnitTarget()) - m_targets.setUnitTarget(SearchNearbyTarget(radius_f, SPELL_TARGETS_ALLY)); - if(m_targets.getUnitTarget()) - { - if(EffectChainTarget <= 1) - TagUnitMap.push_back(m_targets.getUnitTarget()); - else - SearchChainTarget(TagUnitMap, radius_f, EffectChainTarget, SPELL_TARGETS_ALLY); - } + case TARGET_TYPE_AREA_SRC: + CheckSrc(); + pushType = PUSH_SRC_CENTER; break; - case TARGET_UNIT_NEARBY_ENEMY: - if(!m_targets.getUnitTarget()) - m_targets.setUnitTarget(SearchNearbyTarget(radius_h, SPELL_TARGETS_ENEMY)); - if(m_targets.getUnitTarget()) - { - if(EffectChainTarget <= 1) - TagUnitMap.push_back(m_targets.getUnitTarget()); - else - SearchChainTarget(TagUnitMap, radius_h, EffectChainTarget, SPELL_TARGETS_ENEMY); - } - break; - case TARGET_SCRIPT: - case TARGET_SCRIPT_COORDINATES: - case TARGET_UNIT_AREA_SCRIPT: - { - SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(m_spellInfo->Id); - SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(m_spellInfo->Id); - if(lower==upper) - { - sLog.outErrorDb("Spell (ID: %u) (caster Entry: %u) does not have record in `spell_script_target`", m_spellInfo->Id, m_caster->GetEntry()); - TagUnitMap.push_back(m_caster); - break; - } - - SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex); - float range = GetSpellMaxRangeForHostile(srange); - - Creature* creatureScriptTarget = NULL; - GameObject* goScriptTarget = NULL; - - for(SpellScriptTarget::const_iterator i_spellST = lower; i_spellST != upper; ++i_spellST) - { - switch(i_spellST->second.type) - { - case SPELL_TARGET_TYPE_GAMEOBJECT: - { - GameObject* p_GameObject = NULL; - - if(i_spellST->second.targetEntry) - { - Trinity::NearestGameObjectEntryInObjectRangeCheck go_check(*m_caster,i_spellST->second.targetEntry,range); - Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck> checker(m_caster, p_GameObject,go_check); - m_caster->VisitNearbyGridObject(range, checker); - - if(p_GameObject) - { - // remember found target and range, next attempt will find more near target with another entry - creatureScriptTarget = NULL; - goScriptTarget = p_GameObject; - range = go_check.GetLastRange(); - } - } - else if( focusObject ) //Focus Object - { - float frange = m_caster->GetDistance(focusObject); - if(range >= frange) - { - creatureScriptTarget = NULL; - goScriptTarget = focusObject; - range = frange; - } - } - break; - } - case SPELL_TARGET_TYPE_CREATURE: - case SPELL_TARGET_TYPE_DEAD: - default: - { - Creature *p_Creature = NULL; - - Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*m_caster,i_spellST->second.targetEntry,i_spellST->second.type!=SPELL_TARGET_TYPE_DEAD,range); - Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(m_caster, p_Creature, u_check); - m_caster->VisitNearbyObject(range, searcher); - - if(p_Creature ) - { - creatureScriptTarget = p_Creature; - goScriptTarget = NULL; - range = u_check.GetLastRange(); - } - break; - } - } - } - - if(cur == TARGET_SCRIPT_COORDINATES) - { - if(creatureScriptTarget) - m_targets.setDestination(creatureScriptTarget->GetPositionX(),creatureScriptTarget->GetPositionY(),creatureScriptTarget->GetPositionZ()); - else if(goScriptTarget) - m_targets.setDestination(goScriptTarget->GetPositionX(),goScriptTarget->GetPositionY(),goScriptTarget->GetPositionZ()); - } - else - { - if(creatureScriptTarget) - TagUnitMap.push_back(creatureScriptTarget); - else if(goScriptTarget) - AddGOTarget(goScriptTarget, i); - } - }break; - // dummy - case TARGET_AREAEFFECT_CUSTOM_2: - { - TagUnitMap.push_back(m_caster); + case TARGET_TYPE_AREA_DST: + CheckDst(); + pushType = PUSH_DST_CENTER; break; - } - case TARGET_AREAEFFECT_PARTY_AND_CLASS: - { - Player* targetPlayer = m_targets.getUnitTarget() && m_targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER - ? (Player*)m_targets.getUnitTarget() : NULL; - - Group* pGroup = targetPlayer ? targetPlayer->GetGroup() : NULL; - if(pGroup) - { - for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player* Target = itr->getSource(); - // IsHostileTo check duel and controlled by enemy - if( Target && targetPlayer->IsWithinDistInMap(Target, radius_f) && - targetPlayer->getClass() == Target->getClass() && - !m_caster->IsHostileTo(Target) ) - { - TagUnitMap.push_back(Target); - } - } - } - else if(m_targets.getUnitTarget()) - TagUnitMap.push_back(m_targets.getUnitTarget()); + case TARGET_TYPE_AREA_CONE: + if(m_customAttr & SPELL_ATTR_CU_CONE_BACK) + pushType = PUSH_IN_BACK; + else if(m_customAttr & SPELL_ATTR_CU_CONE_LINE) + pushType = PUSH_IN_LINE; + else + pushType = PUSH_IN_FRONT; break; - } - } - }break; - - case TARGET_TYPE_DEST_CASTER: + + case TARGET_TYPE_DEST_CASTER: //4+8+2 { - if(cur == TARGET_DEST_CASTER_GROUND) + if(cur == TARGET_SRC_CASTER) { - m_targets.setDestination(m_caster, true); + m_targets.setSrc(m_caster); break; } - else if(cur == TARGET_DEST_CASTER) + else if(cur == TARGET_DST_CASTER) { - m_targets.setDestination(m_caster, false); + m_targets.setDestination(m_caster); break; } @@ -1938,10 +1740,11 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) } m_caster->GetGroundPointAroundUnit(x, y, z, dist, angle); - m_targets.setDestination(x, y, z); // do not know if has ground visual - }break; + m_targets.setDestination(x, y, z); + break; + } - case TARGET_TYPE_DEST_TARGET: + case TARGET_TYPE_DEST_TARGET: //2+8+2 { Unit *target = m_targets.getUnitTarget(); if(!target) @@ -1950,9 +1753,9 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) break; } - if(cur == TARGET_DEST_TARGET_ENEMY || cur == TARGET_DEST_TARGET_ANY) + if(cur == TARGET_DST_TARGET_ENEMY || cur == TARGET_DEST_TARGET_ANY) { - m_targets.setDestination(target, true); + m_targets.setDestination(target); break; } @@ -1979,12 +1782,13 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) } target->GetGroundPointAroundUnit(x, y, z, dist, angle); - m_targets.setDestination(x, y, z); // do not know if has ground visual - }break; + m_targets.setDestination(x, y, z); + break; + } - case TARGET_TYPE_DEST_DEST: + case TARGET_TYPE_DEST_DEST: //5+8+1 { - if(!m_targets.HasDest()) + if(!m_targets.HasDst()) { sLog.outError("SPELL: no destination for spell ID %u\n", m_spellInfo->Id); break; @@ -1995,7 +1799,9 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) { case TARGET_DEST_DYNOBJ_ENEMY: case TARGET_DEST_DYNOBJ_ALLY: + case TARGET_DEST_DYNOBJ_NONE: case TARGET_DEST_DEST: + case TARGET_DEST_TRAJ: return; case TARGET_DEST_DEST_FRONT: angle = 0.0f; break; case TARGET_DEST_DEST_BACK: angle = M_PI; break; @@ -2017,45 +1823,269 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) y = m_targets.m_destY; z = m_targets.m_destZ; m_caster->GetGroundPoint(x, y, z, dist, angle); - m_targets.setDestination(x, y, z); // do not know if has ground visual - }break; + m_targets.setDestination(x, y, z); + break; + } + + case TARGET_TYPE_DEST_SPECIAL: + { + switch(cur) + { + case TARGET_DST_DB: + if(SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id)) + { + //TODO: fix this check + if(m_spellInfo->Effect[0] == SPELL_EFFECT_TELEPORT_UNITS + || m_spellInfo->Effect[1] == SPELL_EFFECT_TELEPORT_UNITS + || m_spellInfo->Effect[2] == SPELL_EFFECT_TELEPORT_UNITS) + m_targets.setDestination(st->target_X, st->target_Y, st->target_Z, (int32)st->target_mapId); + else if(st->target_mapId == m_caster->GetMapId()) + m_targets.setDestination(st->target_X, st->target_Y, st->target_Z); + } + else + sLog.outError( "SPELL: unknown target coordinates for spell ID %u\n", m_spellInfo->Id ); + break; + case TARGET_DST_HOME: + if(m_caster->GetTypeId() == TYPEID_PLAYER) + m_targets.setDestination(((Player*)m_caster)->m_homebindX,((Player*)m_caster)->m_homebindY,((Player*)m_caster)->m_homebindZ, ((Player*)m_caster)->m_homebindMapId); + break; + case TARGET_DST_NEARBY_ENTRY: + { + float range = GetSpellMaxRange(m_spellInfo, IsPositiveSpell(m_spellInfo->Id)); + if(modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this); + + WorldObject *target = SearchNearbyTarget(range, SPELL_TARGETS_ENTRY); + if(target) + m_targets.setDestination(target); + break; + } + } + break; + } + + case TARGET_TYPE_CHANNEL: + { + if(!m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL]) + { + sLog.outError( "SPELL: no current channeled spell for spell ID %u", m_spellInfo->Id ); + break; + } + + switch(cur) + { + case TARGET_UNIT_CHANNEL: + if(Unit* target = m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->m_targets.getUnitTarget()) + AddUnitTarget(target, i); + else + sLog.outError( "SPELL: cannot find channel spell target for spell ID %u", m_spellInfo->Id ); + break; + case TARGET_DEST_CHANNEL: + if(m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->m_targets.HasDst()) + m_targets = m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->m_targets; + else + sLog.outError( "SPELL: cannot find channel spell destination for spell ID %u", m_spellInfo->Id ); + break; + } + break; + } default: + { + switch(cur) + { + case TARGET_GAMEOBJECT: + case TARGET_OBJECT_USE: + if(m_targets.getGOTarget()) + AddGOTarget(m_targets.getGOTarget(), i); + break; + case TARGET_GAMEOBJECT_ITEM: + if(m_targets.getGOTargetGUID()) + AddGOTarget(m_targets.getGOTarget(), i); + else if(m_targets.getItemTarget()) + AddItemTarget(m_targets.getItemTarget(), i); + break; + default: + sLog.outError("Unhandled spell target %u", cur); + break; + } break; + } } - if(unMaxTargets && !EffectChainTarget && TagUnitMap.size() > 1) + if(pushType == PUSH_CHAIN) // Chain { - if(m_spellInfo->Id == 5246) //Intimidating Shout - TagUnitMap.remove(m_targets.getUnitTarget()); + Unit *target = m_targets.getUnitTarget(); + if(!target) + { + sLog.outError("SPELL: no chain unit target for spell ID %u", m_spellInfo->Id); + return; + } + + //Chain: 2, 6, 22, 25, 45, 77 + uint32 maxTargets = m_spellInfo->EffectChainTarget[i]; + if(modOwner) + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, maxTargets, this); + + if(maxTargets > 1) + { + //otherwise, this multiplier is used for something else + m_damageMultipliers[i] = 1.0f; + m_applyMultiplierMask |= 1 << i; + + float radius; + std::list<Unit*> unitList; - Trinity::RandomResizeList(TagUnitMap, unMaxTargets); + switch(cur) + { + case TARGET_UNIT_NEARBY_ENEMY: + case TARGET_UNIT_TARGET_ENEMY: + case TARGET_UNIT_NEARBY_ENTRY: // fix me + radius = GetSpellRadius(m_spellInfo, i, false); + if(modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius, this); + SearchChainTarget(unitList, radius, maxTargets, SPELL_TARGETS_ENEMY); + break; + case TARGET_UNIT_CHAINHEAL: + case TARGET_UNIT_NEARBY_ALLY: // fix me + case TARGET_UNIT_NEARBY_ALLY_UNK: + case TARGET_UNIT_NEARBY_RAID: + radius = GetSpellRadius(m_spellInfo, i, true); + if(modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius, this); + SearchChainTarget(unitList, radius, maxTargets, SPELL_TARGETS_CHAINHEAL); + break; + } + + for(std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr) + AddUnitTarget(*itr, i); + } + else + AddUnitTarget(target, i); } -} + else if(pushType) + { + // Dummy, just for client + if(spellmgr.EffectTargetType[m_spellInfo->Effect[i]] == SPELL_REQUIRE_DEST) + return; -class PrioritizeManaPlayerWraper -{ - friend struct PrioritizeMana; + float radius; + SpellTargets targetType; + switch(cur) + { + case TARGET_UNIT_AREA_ENEMY_SRC: + case TARGET_UNIT_AREA_ENEMY_DST: + case TARGET_UNIT_CONE_ENEMY: + case TARGET_UNIT_CONE_ENEMY_UNKNOWN: + radius = GetSpellRadius(m_spellInfo, i, false); + targetType = SPELL_TARGETS_ENEMY; + break; + case TARGET_UNIT_AREA_ALLY_SRC: + case TARGET_UNIT_AREA_ALLY_DST: + case TARGET_UNIT_CONE_ALLY: + radius = GetSpellRadius(m_spellInfo, i, true); + targetType = SPELL_TARGETS_ALLY; + break; + case TARGET_UNIT_AREA_ENTRY_SRC: + case TARGET_UNIT_AREA_ENTRY_DST: + case TARGET_UNIT_CONE_ENTRY: // fix me + radius = GetSpellRadius(m_spellInfo, i, IsPositiveSpell(m_spellInfo->Id)); + targetType = SPELL_TARGETS_ENTRY; + break; + default: + radius = GetSpellRadius(m_spellInfo, i, true); + targetType = SPELL_TARGETS_NONE; + break; + } + + if(modOwner) + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius, this); - public: - explicit PrioritizeManaPlayerWraper(Player* player) : player(player) + std::list<Unit*> unitList; + if(targetType == SPELL_TARGETS_ENTRY) { - uint32 maxmana = player->GetMaxPower(POWER_MANA); - percentMana = maxmana ? player->GetPower(POWER_MANA) * 100 / maxmana : 101; + SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(m_spellInfo->Id); + SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(m_spellInfo->Id); + if(lower == upper) + { + sLog.outErrorDb("Spell (ID: %u) (caster Entry: %u) does not have record in `spell_script_target`", m_spellInfo->Id, m_caster->GetEntry()); + + if(IsPositiveEffect(m_spellInfo->Id, i)) + SearchAreaTarget(unitList, radius, PUSH_DST_CENTER, SPELL_TARGETS_ALLY); + else + SearchAreaTarget(unitList, radius, PUSH_DST_CENTER, SPELL_TARGETS_ENEMY); + } + // let it be done in one check? + else + { + for(SpellScriptTarget::const_iterator i_spellST = lower; i_spellST != upper; ++i_spellST) + { + if(i_spellST->second.type == SPELL_TARGET_TYPE_CREATURE) + SearchAreaTarget(unitList, radius, PUSH_DST_CENTER, SPELL_TARGETS_ENTRY, i_spellST->second.targetEntry); + } + } } - Player* getPlayer() const { return player; } - private: - Player* player; - uint32 percentMana; -}; + else if(targetType) + SearchAreaTarget(unitList, radius, pushType, targetType); + else + { + switch(cur) + { + case TARGET_UNIT_AREA_PARTY_SRC: + case TARGET_UNIT_AREA_PARTY_DST: + m_caster->GetPartyMember(unitList, radius); //fix me + break; + case TARGET_OBJECT_AREA_SRC: // fix me + case TARGET_OBJECT_AREA_DST: + break; + case TARGET_UNIT_PARTY_TARGET: + m_targets.getUnitTarget()->GetPartyMember(unitList, radius); + break; + case TARGET_UNIT_PARTY_CASTER: + m_caster->GetPartyMember(unitList, radius); + break; + case TARGET_UNIT_RAID_CASTER: + m_caster->GetRaidMember(unitList, radius); + break; + case TARGET_UNIT_CLASS_TARGET: + { + Player* targetPlayer = m_targets.getUnitTarget() && m_targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER + ? (Player*)m_targets.getUnitTarget() : NULL; -struct PrioritizeMana -{ - int operator()( PrioritizeManaPlayerWraper const& x, PrioritizeManaPlayerWraper const& y ) const - { - return x.percentMana < y.percentMana; - } -}; + Group* pGroup = targetPlayer ? targetPlayer->GetGroup() : NULL; + if(pGroup) + { + for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player* Target = itr->getSource(); + + // IsHostileTo check duel and controlled by enemy + if( Target && targetPlayer->IsWithinDistInMap(Target, radius) && + targetPlayer->getClass() == Target->getClass() && + !m_caster->IsHostileTo(Target) ) + { + AddUnitTarget(Target, i); + } + } + } + else if(m_targets.getUnitTarget()) + AddUnitTarget(m_targets.getUnitTarget(), i); + break; + } + } + } + + if(!unitList.empty()) + { + if(m_spellValue->MaxAffectedTargets) + { + if(m_spellInfo->Id == 5246) //Intimidating Shout + unitList.remove(m_targets.getUnitTarget()); + Trinity::RandomResizeList(unitList, m_spellValue->MaxAffectedTargets); + } + + for(std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr) + AddUnitTarget(*itr, i); + } + } // Chain or Area +} void Spell::prepare(SpellCastTargets const* targets, AuraEffect* triggeredByAura) { @@ -2485,8 +2515,8 @@ void Spell::_handle_immediate_phase() { if(spellmgr.EffectTargetType[m_spellInfo->Effect[j]] == SPELL_REQUIRE_DEST) { - if(!m_targets.HasDest()) - m_targets.setDestination(m_caster, false); + if(!m_targets.HasDst()) + m_targets.setDestination(m_caster); HandleEffects(m_originalCaster, NULL, NULL, j); } else if(spellmgr.EffectTargetType[m_spellInfo->Effect[j]] == SPELL_REQUIRE_NONE) @@ -3701,7 +3731,7 @@ SpellCastResult Spell::CheckCast(bool strict) // If 0 spell effect empty - client not send target data (need use selection) // TODO: check it on next client version if (m_targets.m_targetMask == TARGET_FLAG_SELF && - m_spellInfo->EffectImplicitTargetA[1] == TARGET_CHAIN_DAMAGE) + m_spellInfo->EffectImplicitTargetA[1] == TARGET_UNIT_TARGET_ENEMY) { if (target = m_caster->GetUnit(*m_caster, ((Player *)m_caster)->GetSelection())) m_targets.setUnitTarget(target); @@ -3713,7 +3743,7 @@ SpellCastResult Spell::CheckCast(bool strict) // check pet presents for(int j=0;j<3;j++) { - if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_PET) + if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_UNIT_PET) { target = m_caster->GetGuardianPet(); if(!target) @@ -3831,15 +3861,15 @@ SpellCastResult Spell::CheckCast(bool strict) { for(uint8 j = 0; j < 3; j++) { - if( m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT || - m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT && m_spellInfo->EffectImplicitTargetA[j] != TARGET_SELF || - m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES || - m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT_COORDINATES ) + if( m_spellInfo->EffectImplicitTargetA[j] == TARGET_UNIT_NEARBY_ENTRY || + m_spellInfo->EffectImplicitTargetB[j] == TARGET_UNIT_NEARBY_ENTRY && m_spellInfo->EffectImplicitTargetA[j] != TARGET_UNIT_CASTER || + m_spellInfo->EffectImplicitTargetA[j] == TARGET_DST_NEARBY_ENTRY || + m_spellInfo->EffectImplicitTargetB[j] == TARGET_DST_NEARBY_ENTRY ) { SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(m_spellInfo->Id); SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(m_spellInfo->Id); if(lower==upper) - sLog.outErrorDb("Spell (ID: %u) has effect EffectImplicitTargetA/EffectImplicitTargetB = TARGET_SCRIPT or TARGET_SCRIPT_COORDINATES, but does not have record in `spell_script_target`",m_spellInfo->Id); + sLog.outErrorDb("Spell (ID: %u) has effect EffectImplicitTargetA/EffectImplicitTargetB = TARGET_UNIT_NEARBY_ENTRY or TARGET_DST_NEARBY_ENTRY, but does not have record in `spell_script_target`",m_spellInfo->Id); SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex); float range = GetSpellMaxRange(srange); @@ -3920,31 +3950,31 @@ SpellCastResult Spell::CheckCast(bool strict) if(creatureScriptTarget) { - // store coordinates for TARGET_SCRIPT_COORDINATES - if (m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES || - m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT_COORDINATES ) + // store coordinates for TARGET_DST_NEARBY_ENTRY + if (m_spellInfo->EffectImplicitTargetA[j] == TARGET_DST_NEARBY_ENTRY || + m_spellInfo->EffectImplicitTargetB[j] == TARGET_DST_NEARBY_ENTRY ) { m_targets.setDestination(creatureScriptTarget->GetPositionX(),creatureScriptTarget->GetPositionY(),creatureScriptTarget->GetPositionZ()); - if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES && m_spellInfo->EffectImplicitTargetB[j] == 0 && m_spellInfo->Effect[j]!=SPELL_EFFECT_PERSISTENT_AREA_AURA) + if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_DST_NEARBY_ENTRY && m_spellInfo->EffectImplicitTargetB[j] == 0 && m_spellInfo->Effect[j]!=SPELL_EFFECT_PERSISTENT_AREA_AURA) AddUnitTarget(creatureScriptTarget, j); } - // store explicit target for TARGET_SCRIPT + // store explicit target for TARGET_UNIT_NEARBY_ENTRY else AddUnitTarget(creatureScriptTarget, j); } else if(goScriptTarget) { - // store coordinates for TARGET_SCRIPT_COORDINATES - if (m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES || - m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT_COORDINATES ) + // store coordinates for TARGET_DST_NEARBY_ENTRY + if (m_spellInfo->EffectImplicitTargetA[j] == TARGET_DST_NEARBY_ENTRY || + m_spellInfo->EffectImplicitTargetB[j] == TARGET_DST_NEARBY_ENTRY ) { m_targets.setDestination(goScriptTarget->GetPositionX(),goScriptTarget->GetPositionY(),goScriptTarget->GetPositionZ()); - if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES && m_spellInfo->EffectImplicitTargetB[j] == 0 && m_spellInfo->Effect[j]!=SPELL_EFFECT_PERSISTENT_AREA_AURA) + if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_DST_NEARBY_ENTRY && m_spellInfo->EffectImplicitTargetB[j] == 0 && m_spellInfo->Effect[j]!=SPELL_EFFECT_PERSISTENT_AREA_AURA) AddGOTarget(goScriptTarget, j); } - // store explicit target for TARGET_SCRIPT + // store explicit target for TARGET_UNIT_NEARBY_ENTRY else AddGOTarget(goScriptTarget, j); } @@ -4008,7 +4038,7 @@ SpellCastResult Spell::CheckCast(bool strict) if (m_caster->GetTypeId() != TYPEID_PLAYER) return SPELL_FAILED_BAD_TARGETS; - if(m_spellInfo->EffectImplicitTargetA[i] != TARGET_PET) + if(m_spellInfo->EffectImplicitTargetA[i] != TARGET_UNIT_PET) break; Pet* pet = ((Player*)m_caster)->GetPet(); @@ -4430,7 +4460,7 @@ SpellCastResult Spell::CheckPetCast(Unit* target) bool need = false; for(uint32 i = 0;i<3;i++) { - if(m_spellInfo->EffectImplicitTargetA[i] == TARGET_CHAIN_DAMAGE || m_spellInfo->EffectImplicitTargetA[i] == TARGET_SINGLE_FRIEND || m_spellInfo->EffectImplicitTargetA[i] == TARGET_DUELVSPLAYER || m_spellInfo->EffectImplicitTargetA[i] == TARGET_SINGLE_PARTY || m_spellInfo->EffectImplicitTargetA[i] == TARGET_CURRENT_ENEMY_COORDINATES) + if(m_spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_TARGET_ENEMY || m_spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_TARGET_ALLY || m_spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_TARGET_ANY || m_spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_TARGET_PARTY || m_spellInfo->EffectImplicitTargetA[i] == TARGET_DST_TARGET_ENEMY) { need = true; if(!target) @@ -4797,8 +4827,8 @@ SpellCastResult Spell::CheckItems() SpellCastResult failReason = SPELL_CAST_OK; for (int i = 0; i < 3; i++) { - // skip check, pet not required like checks, and for TARGET_PET m_targets.getUnitTarget() is not the real target but the caster - if (m_spellInfo->EffectImplicitTargetA[i] == TARGET_PET) + // skip check, pet not required like checks, and for TARGET_UNIT_PET m_targets.getUnitTarget() is not the real target but the caster + if (m_spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_PET) continue; if (m_spellInfo->Effect[i] == SPELL_EFFECT_HEAL) @@ -5356,10 +5386,10 @@ CurrentSpellTypes Spell::GetCurrentContainer() return(CURRENT_GENERIC_SPELL); } -bool Spell::CheckTarget( Unit* target, uint32 eff ) +bool Spell::CheckTarget(Unit* target, uint32 eff) { // Check targets for creature type mask and remove not appropriate (skip explicit self target case, maybe need other explicit targets) - if(m_spellInfo->EffectImplicitTargetA[eff]!=TARGET_SELF) + if(m_spellInfo->EffectImplicitTargetA[eff]!=TARGET_UNIT_CASTER) { if (!CheckTargetCreatureType(target)) return false; @@ -5379,11 +5409,11 @@ bool Spell::CheckTarget( Unit* target, uint32 eff ) if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) return false; - // unselectable targets skipped in all cases except TARGET_SCRIPT targeting - // in case TARGET_SCRIPT target selected by server always and can't be cheated + // unselectable targets skipped in all cases except TARGET_UNIT_NEARBY_ENTRY targeting + // in case TARGET_UNIT_NEARBY_ENTRY target selected by server always and can't be cheated /*if( target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE) && - m_spellInfo->EffectImplicitTargetA[eff] != TARGET_SCRIPT && - m_spellInfo->EffectImplicitTargetB[eff] != TARGET_SCRIPT ) + m_spellInfo->EffectImplicitTargetA[eff] != TARGET_UNIT_NEARBY_ENTRY && + m_spellInfo->EffectImplicitTargetB[eff] != TARGET_UNIT_NEARBY_ENTRY ) return false;*/ } diff --git a/src/game/Spell.h b/src/game/Spell.h index 64aa7f24eb0..4b630ce8dc9 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -101,11 +101,14 @@ enum SpellRangeFlag enum SpellNotifyPushType { + PUSH_NONE = 0, PUSH_IN_FRONT, PUSH_IN_BACK, PUSH_IN_LINE, - PUSH_DEST_CENTER, - PUSH_TARGET_CENTER, + PUSH_SRC_CENTER, + PUSH_DST_CENTER, + PUSH_CASTER_CENTER, + PUSH_CHAIN, }; bool IsQuestTameSpell(uint32 spellId); @@ -137,29 +140,30 @@ class SpellCastTargets m_itemTargetEntry = target.m_itemTargetEntry; - //m_srcX = target.m_srcX; - //m_srcY = target.m_srcY; - //m_srcZ = target.m_srcZ; + m_srcX = target.m_srcX; + m_srcY = target.m_srcY; + m_srcZ = target.m_srcZ; - m_mapId = -1; m_destX = target.m_destX; m_destY = target.m_destY; m_destZ = target.m_destZ; - m_hasDest = target.m_hasDest; m_strTarget = target.m_strTarget; m_targetMask = target.m_targetMask; + m_mapId = -1; + return *this; } uint64 getUnitTargetGUID() const { return m_unitTargetGUID; } Unit *getUnitTarget() const { return m_unitTarget; } void setUnitTarget(Unit *target); - void setDestination(float x, float y, float z, bool send = true, int32 mapId = -1); - void setDestination(Unit *target, bool send = true); - void setSource(float x, float y, float z); + void setSrc(float x, float y, float z); + void setSrc(WorldObject *target); + void setDestination(float x, float y, float z, int32 mapId = -1); + void setDestination(WorldObject *target); uint64 getGOTargetGUID() const { return m_GOTargetGUID; } GameObject *getGOTarget() const { return m_GOTarget; } @@ -181,14 +185,14 @@ class SpellCastTargets } bool IsEmpty() const { return m_GOTargetGUID==0 && m_unitTargetGUID==0 && m_itemTarget==0 && m_CorpseTargetGUID==0; } - bool HasDest() const { return m_hasDest; } + bool HasSrc() const { return m_targetMask & TARGET_FLAG_SOURCE_LOCATION; } + bool HasDst() const { return m_targetMask & TARGET_FLAG_DEST_LOCATION; } void Update(Unit* caster); float m_srcX, m_srcY, m_srcZ; - int32 m_mapId; float m_destX, m_destY, m_destZ; - bool m_hasDest; + int32 m_mapId; std::string m_strTarget; uint32 m_targetMask; @@ -240,6 +244,7 @@ enum ReplenishType enum SpellTargets { + SPELL_TARGETS_NONE = 0, SPELL_TARGETS_ALLY, SPELL_TARGETS_ENEMY, SPELL_TARGETS_ENTRY, @@ -405,10 +410,12 @@ class Spell void WriteAmmoToPacket( WorldPacket * data ); void FillTargetMap(); - void SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap); + void SetTargetMap(uint32 i, uint32 cur); bool CheckTarget( Unit* target, uint32 eff ); bool CanAutoCast(Unit* target); + void CheckSrc() { if(!m_targets.HasSrc()) m_targets.setSrc(m_caster); } + void CheckDst() { if(!m_targets.HasDst()) m_targets.setDestination(m_caster); } void SendCastResult(SpellCastResult result); void SendSpellStart(); @@ -593,11 +600,9 @@ class Spell void DoAllEffectOnTarget(GOTargetInfo *target); void DoAllEffectOnTarget(ItemTargetInfo *target); bool UpdateChanneledTargetList(); - void SearchAreaTarget(std::list<Unit*> &data, float radius, SpellNotifyPushType type, - SpellTargets TargetType, uint32 entry = 0); - void SearchChainTarget(std::list<Unit*> &data, float radius, uint32 unMaxTargets, - SpellTargets TargetType); - Unit* SearchNearbyTarget(float radius, SpellTargets TargetType, uint32 entry = 0); + void SearchAreaTarget(std::list<Unit*> &unitList, float radius, SpellNotifyPushType type, SpellTargets TargetType, uint32 entry = 0); + void SearchChainTarget(std::list<Unit*> &unitList, float radius, uint32 unMaxTargets, SpellTargets TargetType); + WorldObject* SearchNearbyTarget(float range, SpellTargets TargetType); bool IsValidSingleTargetEffect(Unit const* target, Targets type) const; bool IsValidSingleTargetSpell(Unit const* target) const; void CalculateDamageDoneForAllTargets(); @@ -696,8 +701,10 @@ namespace Trinity switch(i_push_type) { - case PUSH_DEST_CENTER: - case PUSH_TARGET_CENTER: + case PUSH_SRC_CENTER: + case PUSH_DST_CENTER: + case PUSH_CHAIN: + default: if((target->GetDistanceSq(i_x, i_y, i_z) < i_radiusSq)) i_data->push_back(target); break; diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index f749da89711..33beae157d5 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -2110,7 +2110,7 @@ void Spell::EffectTriggerSpell(uint32 i) bool instant = false; for(uint32 j = i+1; j < 3; ++j) { - if(m_spellInfo->Effect[j]==SPELL_EFFECT_INSTAKILL && m_spellInfo->EffectImplicitTargetA[j]==TARGET_SELF) + if(m_spellInfo->Effect[j]==SPELL_EFFECT_INSTAKILL && m_spellInfo->EffectImplicitTargetA[j]==TARGET_UNIT_CASTER) { instant = true; break; @@ -2153,7 +2153,7 @@ void Spell::EffectJump(uint32 i) // Init dest coordinates float x,y,z,o; - if(m_targets.HasDest()) + if(m_targets.HasDst()) { x = m_targets.m_destX; y = m_targets.m_destY; @@ -2210,7 +2210,7 @@ void Spell::EffectTeleportUnits(uint32 i) return; // If not exist data for dest location - return - if(!m_targets.HasDest()) + if(!m_targets.HasDst()) { sLog.outError( "Spell::EffectTeleportUnits - does not have destination for spell ID %u\n", m_spellInfo->Id ); return; @@ -2230,7 +2230,7 @@ void Spell::EffectTeleportUnits(uint32 i) else if(unitTarget->GetTypeId() == TYPEID_PLAYER) ((Player*)unitTarget)->TeleportTo(mapid, x, y, z, orientation, unitTarget==m_caster ? TELE_TO_SPELL : 0); - // post effects for TARGET_TABLE_X_Y_Z_COORDINATES + // post effects for TARGET_DST_DB switch ( m_spellInfo->Id ) { // Dimensional Ripper - Everlook @@ -5674,7 +5674,7 @@ void Spell::EffectMomentMove(uint32 i) if(unitTarget->isInFlight()) return; - if(!m_targets.HasDest()) + if(!m_targets.HasDst()) return; uint32 mapid = m_caster->GetMapId(); diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 200cc98d803..c23d6aae43f 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -94,7 +94,7 @@ SpellMgr::SpellMgr() case TARGET_UNIT_MASTER: case TARGET_UNIT_PET: case TARGET_UNIT_PARTY_CASTER: - case TARGET_UNIT_RAID: + case TARGET_UNIT_RAID_CASTER: SpellTargetType[i] = TARGET_TYPE_UNIT_CASTER; break; case TARGET_UNIT_MINIPET: @@ -104,24 +104,54 @@ SpellMgr::SpellMgr() case TARGET_UNIT_TARGET_ENEMY: case TARGET_UNIT_TARGET_PARTY: case TARGET_UNIT_PARTY_TARGET: + case TARGET_UNIT_CLASS_TARGET: case TARGET_UNIT_CHAINHEAL: SpellTargetType[i] = TARGET_TYPE_UNIT_TARGET; break; - case TARGET_UNIT_CHANNEL: - case TARGET_DEST_CHANNEL: - SpellTargetType[i] = TARGET_TYPE_CHANNEL; + case TARGET_UNIT_NEARBY_ENEMY: + case TARGET_UNIT_NEARBY_ALLY: + case TARGET_UNIT_NEARBY_ALLY_UNK: + case TARGET_UNIT_NEARBY_ENTRY: + case TARGET_UNIT_NEARBY_RAID: + SpellTargetType[i] = TARGET_TYPE_UNIT_NEARBY; break; - case TARGET_UNIT_AREA_ENEMY_GROUND: - case TARGET_UNIT_AREA_ENEMY: - case TARGET_UNIT_AREA_ALLY_GROUND: - case TARGET_UNIT_AREA_ALLY: - case TARGET_UNIT_AREA_ENTRY_GROUND: - case TARGET_UNIT_AREA_ENTRY: - case TARGET_UNIT_AREA_PARTY_GROUND: - case TARGET_UNIT_AREA_PARTY: - SpellTargetType[i] = TARGET_TYPE_AREA_DEST; + case TARGET_UNIT_AREA_ENEMY_SRC: + case TARGET_UNIT_AREA_ALLY_SRC: + case TARGET_UNIT_AREA_ENTRY_SRC: + case TARGET_UNIT_AREA_PARTY_SRC: + case TARGET_OBJECT_AREA_SRC: + SpellTargetType[i] = TARGET_TYPE_AREA_SRC; break; - case TARGET_DEST_TARGET_ENEMY: + case TARGET_UNIT_AREA_ENEMY_DST: + case TARGET_UNIT_AREA_ALLY_DST: + case TARGET_UNIT_AREA_ENTRY_DST: + case TARGET_UNIT_AREA_PARTY_DST: + case TARGET_OBJECT_AREA_DST: + SpellTargetType[i] = TARGET_TYPE_AREA_DST; + break; + case TARGET_UNIT_CONE_ENEMY: + case TARGET_UNIT_CONE_ALLY: + case TARGET_UNIT_CONE_ENTRY: + case TARGET_UNIT_CONE_ENEMY_UNKNOWN: + SpellTargetType[i] = TARGET_TYPE_AREA_CONE; + break; + case TARGET_DST_CASTER: + case TARGET_SRC_CASTER: + case TARGET_MINION: + case TARGET_DEST_CASTER_FRONT_LEAP: + case TARGET_DEST_CASTER_FRONT: + case TARGET_DEST_CASTER_BACK: + case TARGET_DEST_CASTER_RIGHT: + case TARGET_DEST_CASTER_LEFT: + case TARGET_DEST_CASTER_FRONT_LEFT: + case TARGET_DEST_CASTER_BACK_LEFT: + case TARGET_DEST_CASTER_BACK_RIGHT: + case TARGET_DEST_CASTER_FRONT_RIGHT: + case TARGET_DEST_CASTER_RANDOM: + case TARGET_DEST_CASTER_RADIUS: + SpellTargetType[i] = TARGET_TYPE_DEST_CASTER; + break; + case TARGET_DST_TARGET_ENEMY: case TARGET_DEST_TARGET_ANY: case TARGET_DEST_TARGET_FRONT: case TARGET_DEST_TARGET_BACK: @@ -135,25 +165,11 @@ SpellMgr::SpellMgr() case TARGET_DEST_TARGET_RADIUS: SpellTargetType[i] = TARGET_TYPE_DEST_TARGET; break; - case TARGET_DEST_CASTER_GROUND: - case TARGET_DEST_CASTER: - case TARGET_DEST_CASTER_FRONT_LEFT: - case TARGET_DEST_CASTER_BACK_LEFT: - case TARGET_DEST_CASTER_BACK_RIGHT: - case TARGET_DEST_CASTER_FRONT_RIGHT: - case TARGET_DEST_CASTER_FRONT: - case TARGET_MINION: - case TARGET_DEST_CASTER_FRONT_LEAP: - case TARGET_DEST_CASTER_BACK: - case TARGET_DEST_CASTER_RIGHT: - case TARGET_DEST_CASTER_LEFT: - case TARGET_DEST_CASTER_RANDOM: - case TARGET_DEST_CASTER_RADIUS: - SpellTargetType[i] = TARGET_TYPE_DEST_CASTER; - break; case TARGET_DEST_DYNOBJ_ENEMY: case TARGET_DEST_DYNOBJ_ALLY: + case TARGET_DEST_DYNOBJ_NONE: case TARGET_DEST_DEST: + case TARGET_DEST_TRAJ: case TARGET_DEST_DEST_FRONT_LEFT: case TARGET_DEST_DEST_BACK_LEFT: case TARGET_DEST_DEST_BACK_RIGHT: @@ -165,6 +181,15 @@ SpellMgr::SpellMgr() case TARGET_DEST_DEST_RANDOM: SpellTargetType[i] = TARGET_TYPE_DEST_DEST; break; + case TARGET_DST_DB: + case TARGET_DST_HOME: + case TARGET_DST_NEARBY_ENTRY: + SpellTargetType[i] = TARGET_TYPE_DEST_SPECIAL; + break; + case TARGET_UNIT_CHANNEL: + case TARGET_DEST_CHANNEL: + SpellTargetType[i] = TARGET_TYPE_CHANNEL; + break; default: SpellTargetType[i] = TARGET_TYPE_DEFAULT; } @@ -174,20 +199,20 @@ SpellMgr::SpellMgr() { switch(i) { - case TARGET_UNIT_AREA_ENEMY_GROUND: - case TARGET_UNIT_AREA_ENEMY: - case TARGET_UNIT_AREA_ALLY_GROUND: - case TARGET_UNIT_AREA_ALLY: - case TARGET_UNIT_AREA_ENTRY_GROUND: - case TARGET_UNIT_AREA_ENTRY: - case TARGET_UNIT_AREA_PARTY_GROUND: - case TARGET_UNIT_AREA_PARTY: + case TARGET_UNIT_AREA_ENEMY_DST: + case TARGET_UNIT_AREA_ENEMY_SRC: + case TARGET_UNIT_AREA_ALLY_DST: + case TARGET_UNIT_AREA_ALLY_SRC: + case TARGET_UNIT_AREA_ENTRY_DST: + case TARGET_UNIT_AREA_ENTRY_SRC: + case TARGET_UNIT_AREA_PARTY_DST: + case TARGET_UNIT_AREA_PARTY_SRC: case TARGET_UNIT_PARTY_TARGET: case TARGET_UNIT_PARTY_CASTER: case TARGET_UNIT_CONE_ENEMY: case TARGET_UNIT_CONE_ALLY: case TARGET_UNIT_CONE_ENEMY_UNKNOWN: - case TARGET_UNIT_RAID: + case TARGET_UNIT_RAID_CASTER: IsAreaEffectTarget[i] = true; break; default: @@ -494,12 +519,12 @@ bool IsPositiveTarget(uint32 targetA, uint32 targetB) // non-positive targets switch(targetA) { - case TARGET_CHAIN_DAMAGE: - case TARGET_ALL_ENEMY_IN_AREA: - case TARGET_ALL_ENEMY_IN_AREA_INSTANT: - case TARGET_IN_FRONT_OF_CASTER: + case TARGET_UNIT_TARGET_ENEMY: + case TARGET_UNIT_AREA_ENEMY_SRC: + case TARGET_UNIT_AREA_ENEMY_DST: + case TARGET_UNIT_CONE_ENEMY: case TARGET_DEST_DYNOBJ_ENEMY: - case TARGET_CURRENT_ENEMY_COORDINATES: + case TARGET_DST_TARGET_ENEMY: case TARGET_UNIT_CHANNEL: return false; default: @@ -622,12 +647,12 @@ bool IsPositiveEffect(uint32 spellId, uint32 effIndex, bool deep) return false; case SPELL_AURA_PERIODIC_DAMAGE: // used in positive spells also. // part of negative spell if casted at self (prevent cancel) - if(spellproto->EffectImplicitTargetA[effIndex] == TARGET_SELF) + if(spellproto->EffectImplicitTargetA[effIndex] == TARGET_UNIT_CASTER) return false; break; case SPELL_AURA_MOD_DECREASE_SPEED: // used in positive spells also // part of positive spell if casted at self - if(spellproto->EffectImplicitTargetA[effIndex] != TARGET_SELF) + if(spellproto->EffectImplicitTargetA[effIndex] != TARGET_UNIT_CASTER) return false; // but not this if this first effect (don't found batter check) if(spellproto->Attributes & 0x4000000 && effIndex==0) @@ -918,7 +943,7 @@ void SpellMgr::LoadSpellTargetPositions() bool found = false; for(int i = 0; i < 3; ++i) { - if( spellInfo->EffectImplicitTargetA[i]==TARGET_TABLE_X_Y_Z_COORDINATES || spellInfo->EffectImplicitTargetB[i]==TARGET_TABLE_X_Y_Z_COORDINATES ) + if( spellInfo->EffectImplicitTargetA[i]==TARGET_DST_DB || spellInfo->EffectImplicitTargetB[i]==TARGET_DST_DB ) { found = true; break; @@ -926,7 +951,7 @@ void SpellMgr::LoadSpellTargetPositions() } if(!found) { - sLog.outErrorDb("Spell (Id: %u) listed in `spell_target_position` does not have target TARGET_TABLE_X_Y_Z_COORDINATES (17).",Spell_ID); + sLog.outErrorDb("Spell (Id: %u) listed in `spell_target_position` does not have target TARGET_DST_DB (17).",Spell_ID); continue; } @@ -2023,7 +2048,7 @@ void SpellMgr::LoadSpellLearnSpells() // talent or passive spells or skill-step spells auto-casted and not need dependent learning, // pet teaching spells don't must be dependent learning (casted) // other required explicit dependent learning - dbc_node.autoLearned = entry->EffectImplicitTargetA[i]==TARGET_PET || GetTalentSpellCost(spell) > 0 || IsPassiveSpell(spell) || IsSpellHaveEffect(entry,SPELL_EFFECT_SKILL_STEP); + dbc_node.autoLearned = entry->EffectImplicitTargetA[i] == TARGET_UNIT_PET || GetTalentSpellCost(spell) > 0 || IsPassiveSpell(spell) || IsSpellHaveEffect(entry,SPELL_EFFECT_SKILL_STEP); SpellLearnSpellMap::const_iterator db_node_begin = GetBeginSpellLearnSpell(spell); SpellLearnSpellMap::const_iterator db_node_end = GetEndSpellLearnSpell(spell); @@ -2095,10 +2120,10 @@ void SpellMgr::LoadSpellScriptTarget() /*bool targetfound = false; for(int i = 0; i <3; ++i) { - if( spellProto->EffectImplicitTargetA[i]==TARGET_SCRIPT || - spellProto->EffectImplicitTargetB[i]==TARGET_SCRIPT || - spellProto->EffectImplicitTargetA[i]==TARGET_SCRIPT_COORDINATES || - spellProto->EffectImplicitTargetB[i]==TARGET_SCRIPT_COORDINATES ) + if( spellProto->EffectImplicitTargetA[i]==TARGET_UNIT_NEARBY_ENTRY || + spellProto->EffectImplicitTargetB[i]==TARGET_UNIT_NEARBY_ENTRY || + spellProto->EffectImplicitTargetA[i]==TARGET_DST_NEARBY_ENTRY || + spellProto->EffectImplicitTargetB[i]==TARGET_DST_NEARBY_ENTRY ) { targetfound = true; break; @@ -2106,7 +2131,7 @@ void SpellMgr::LoadSpellScriptTarget() } if(!targetfound) { - sLog.outErrorDb("Table `spell_script_target`: spellId %u listed for TargetEntry %u does not have any implicit target TARGET_SCRIPT(38) or TARGET_SCRIPT_COORDINATES (46).",spellId,targetEntry); + sLog.outErrorDb("Table `spell_script_target`: spellId %u listed for TargetEntry %u does not have any implicit target TARGET_UNIT_NEARBY_ENTRY(38) or TARGET_DST_NEARBY_ENTRY (46).",spellId,targetEntry); continue; }*/ @@ -2172,13 +2197,13 @@ void SpellMgr::LoadSpellScriptTarget() bool found = false; for(int j=0; j<3; ++j) { - if( spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT || spellInfo->EffectImplicitTargetA[j] != TARGET_SELF && spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT ) + if( spellInfo->EffectImplicitTargetA[j] == TARGET_UNIT_NEARBY_ENTRY || spellInfo->EffectImplicitTargetA[j] != TARGET_UNIT_CASTER && spellInfo->EffectImplicitTargetB[j] == TARGET_UNIT_NEARBY_ENTRY ) { SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(spellInfo->Id); SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(spellInfo->Id); if(lower==upper) { - sLog.outErrorDb("Spell (ID: %u) has effect EffectImplicitTargetA/EffectImplicitTargetB = %u (TARGET_SCRIPT), but does not have record in `spell_script_target`",spellInfo->Id,TARGET_SCRIPT); + sLog.outErrorDb("Spell (ID: %u) has effect EffectImplicitTargetA/EffectImplicitTargetB = %u (TARGET_UNIT_NEARBY_ENTRY), but does not have record in `spell_script_target`",spellInfo->Id,TARGET_UNIT_NEARBY_ENTRY); break; // effects of spell } } @@ -2255,7 +2280,7 @@ void SpellMgr::LoadSpellPetAuras() continue; } - PetAura pa(pet, aura, spellInfo->EffectImplicitTargetA[i] == TARGET_PET, spellInfo->CalculateSimpleValue(i)); + PetAura pa(pet, aura, spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_PET, spellInfo->CalculateSimpleValue(i)); mSpellPetAuraMap[spell] = pa; } diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 8913eb84c2a..315fdc1ae17 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -89,11 +89,15 @@ enum SpellSelectTargetTypes TARGET_TYPE_DEFAULT, TARGET_TYPE_UNIT_CASTER, TARGET_TYPE_UNIT_TARGET, - TARGET_TYPE_CHANNEL, - TARGET_TYPE_AREA_DEST, + TARGET_TYPE_UNIT_NEARBY, + TARGET_TYPE_AREA_SRC, + TARGET_TYPE_AREA_DST, + TARGET_TYPE_AREA_CONE, TARGET_TYPE_DEST_CASTER, TARGET_TYPE_DEST_TARGET, TARGET_TYPE_DEST_DEST, + TARGET_TYPE_DEST_SPECIAL, + TARGET_TYPE_CHANNEL, }; //Some SpellFamilyFlags @@ -161,6 +165,18 @@ inline uint32 GetSpellRangeType(SpellRangeEntry const *range) { return (range ? inline uint32 GetSpellRecoveryTime(SpellEntry const *spellInfo) { return spellInfo->RecoveryTime > spellInfo->CategoryRecoveryTime ? spellInfo->RecoveryTime : spellInfo->CategoryRecoveryTime; } int32 GetSpellDuration(SpellEntry const *spellInfo); int32 GetSpellMaxDuration(SpellEntry const *spellInfo); +inline float GetSpellRadius(SpellEntry const *spellInfo, uint32 effectIdx, bool positive) +{ + return positive + ? GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(spellInfo->EffectRadiusIndex[effectIdx])) + : GetSpellRadiusForHostile(sSpellRadiusStore.LookupEntry(spellInfo->EffectRadiusIndex[effectIdx])); +} +inline float GetSpellMaxRange(SpellEntry const *spellInfo, bool positive) +{ + return positive + ? GetSpellMaxRangeForFriend(sSpellRangeStore.LookupEntry(spellInfo->rangeIndex)) + : GetSpellMaxRangeForHostile(sSpellRangeStore.LookupEntry(spellInfo->rangeIndex)); +} /*struct DispelEntry { diff --git a/src/game/TargetedMovementGenerator.cpp b/src/game/TargetedMovementGenerator.cpp index 6aa4be19765..fcbdb8b30e5 100644 --- a/src/game/TargetedMovementGenerator.cpp +++ b/src/game/TargetedMovementGenerator.cpp @@ -155,7 +155,7 @@ TargetedMovementGenerator<T>::Update(T &owner, const uint32 & time_diff) return true; } - if (i_destinationHolder.UpdateTraveller(traveller, time_diff, false)) + if (i_destinationHolder.UpdateTraveller(traveller, time_diff)) { // put targeted movement generators on a higher priority if (owner.GetObjectSize()) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 458fb466cef..3142e742dcf 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -289,6 +289,8 @@ void Unit::SendMonsterStop() data << getMSTime(); data << uint8(1); SendMessageToSet(&data, true); + + clearUnitState(UNIT_STAT_MOVE); } void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 Time, Player* player) @@ -310,6 +312,8 @@ void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 T player->GetSession()->SendPacket(&data); else SendMessageToSet( &data, true ); + + addUnitState(UNIT_STAT_MOVE); } void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 MoveFlags, uint32 time, float speedZ, Player *player) @@ -399,6 +403,8 @@ void Unit::SendMonsterMoveByPath(Path const& path, uint32 start, uint32 end) data << uint32( pathSize ); data.append( (char*)path.GetNodes(start), pathSize * 4 * 3 ); SendMessageToSet(&data, true); + + addUnitState(UNIT_STAT_MOVE); } void Unit::resetAttackTimer(WeaponAttackType type) @@ -11533,7 +11539,7 @@ void CharmInfo::InitCharmCreateSpells() if(!spellInfo) onlyselfcast = false; for(uint32 i = 0;i<3 && onlyselfcast;++i) //non existent spell will not make any problems as onlyselfcast would be false -> break right away { - if(spellInfo->EffectImplicitTargetA[i] != TARGET_SELF && spellInfo->EffectImplicitTargetA[i] != 0) + if(spellInfo->EffectImplicitTargetA[i] != TARGET_UNIT_CASTER && spellInfo->EffectImplicitTargetA[i] != 0) onlyselfcast = false; } diff --git a/src/game/Unit.h b/src/game/Unit.h index bf3f41bb1d1..82c7eb88695 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -443,11 +443,12 @@ enum UnitState UNIT_STAT_CHARGING = 0x00020000, UNIT_STAT_JUMPING = 0x00040000, UNIT_STAT_ONVEHICLE = 0x00080000, + UNIT_STAT_MOVE = 0x00100000, UNIT_STAT_UNATTACKABLE = (UNIT_STAT_IN_FLIGHT | UNIT_STAT_ONVEHICLE), UNIT_STAT_MOVING = (UNIT_STAT_ROAMING | UNIT_STAT_CHASE), UNIT_STAT_CONTROLLED = (UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING), UNIT_STAT_LOST_CONTROL = (UNIT_STAT_CONTROLLED | UNIT_STAT_JUMPING | UNIT_STAT_CHARGING), - UNIT_STAT_SIGHTLESS = (UNIT_STAT_LOST_CONTROL | UNIT_STAT_CHASE), + UNIT_STAT_SIGHTLESS = (UNIT_STAT_LOST_CONTROL), UNIT_STAT_CANNOT_AUTOATTACK = (UNIT_STAT_LOST_CONTROL | UNIT_STAT_CASTING), UNIT_STAT_ALL_STATE = 0xffffffff //(UNIT_STAT_STOPPED | UNIT_STAT_MOVING | UNIT_STAT_IN_COMBAT | UNIT_STAT_IN_FLIGHT) }; diff --git a/src/game/WaypointMovementGenerator.cpp b/src/game/WaypointMovementGenerator.cpp index 397b4adadab..6aba7def916 100644 --- a/src/game/WaypointMovementGenerator.cpp +++ b/src/game/WaypointMovementGenerator.cpp @@ -151,7 +151,7 @@ WaypointMovementGenerator<Creature>::Update(Creature &unit, const uint32 &diff) Traveller<Creature> traveller(unit); i_nextMoveTime.Update(diff); - i_destinationHolder.UpdateTraveller(traveller, diff, false, true); + i_destinationHolder.UpdateTraveller(traveller, diff, true); if(i_nextMoveTime.Passed()) { @@ -291,7 +291,7 @@ FlightPathMovementGenerator::Update(Player &player, const uint32 &diff) if( MovementInProgress() ) { Traveller<Player> traveller(player); - if( i_destinationHolder.UpdateTraveller(traveller, diff, false) ) + if( i_destinationHolder.UpdateTraveller(traveller, diff) ) { i_destinationHolder.ResetUpdate(FLIGHT_TRAVEL_UPDATE); if( i_destinationHolder.HasArrived() ) |