diff options
| author | QAston <qaston@gmail.com> | 2011-09-16 22:16:14 +0200 |
|---|---|---|
| committer | QAston <qaston@gmail.com> | 2011-09-16 22:17:48 +0200 |
| commit | 31e755c2910d26c1616c098a39b343101c398e96 (patch) | |
| tree | 3a5e350903afea05c0476ba1062d59eb85afc8d9 /src/server/game/Entities/Unit | |
| parent | bf38cd8f3e4bf2137b8a583fdd6457c1f6b8dec3 (diff) | |
Core/Entities: Add Unit::IsValidAssistTarget and Unit::IsValidAttackTarget functions for proper serverside checks of related entity flags.
Diffstat (limited to 'src/server/game/Entities/Unit')
| -rwxr-xr-x | src/server/game/Entities/Unit/Unit.cpp | 179 | ||||
| -rwxr-xr-x | src/server/game/Entities/Unit/Unit.h | 7 |
2 files changed, 186 insertions, 0 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index e9b5a75d279..fea4ac29085 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -12363,6 +12363,95 @@ bool Unit::isTargetableForAttack(bool checkFakeDeath) const return !HasUnitState(UNIT_STAT_UNATTACKABLE) && (!checkFakeDeath || !HasUnitState(UNIT_STAT_DIED)); } +bool Unit::IsValidAttackTarget(Unit const* target) const +{ + return _IsValidAttackTarget(target, NULL); +} + +bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell) const +{ + // can't attack self + if (this == target) + return false; + + // can't attack unattackable units or GMs + if (target->HasUnitState(UNIT_STAT_UNATTACKABLE) + || target->GetTypeId() == TYPEID_PLAYER && target->ToPlayer()->isGameMaster()) + return false; + + // can't attack own vehicle or passenger + if (m_vehicle) + if (IsOnVehicle(target) || m_vehicle->GetBase()->IsOnVehicle(target)) + return false; + + // can't attack invisible + if ((!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && !canSeeOrDetect(target)) + return false; + + // can't attack dead + if ((!bySpell || !bySpell->IsAllowingDeadTarget()) && !target->isAlive()) + return false; + + // can't attack untargetable + if ((!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_CAN_TARGET_UNTARGETABLE)) + && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) + return false; + + if (Player const* playerAttacker = ToPlayer()) + { + if (playerAttacker->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_UNK19)) + return false; + } + // check flags + if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_TAXI_FLIGHT | UNIT_FLAG_NOT_ATTACKABLE_1 | UNIT_FLAG_UNK_16) + || (!HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE)) + || (!target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE)) + || (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE)) + || (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE))) + return false; + + // CvC case - can attack each other only when one of them is hostile + if (!HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && !target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE)) + return GetReactionTo(target) <= REP_HOSTILE || target->GetReactionTo(this) <= REP_HOSTILE; + + // PvP, PvC, CvP case + // can't attack friendly targets + if ( GetReactionTo(target) > REP_NEUTRAL + || target->GetReactionTo(this) > REP_NEUTRAL) + return false; + + Creature const* creatureAttacker = ToCreature(); + if (creatureAttacker && creatureAttacker->GetCreatureInfo()->type_flags & CREATURE_TYPEFLAGS_UNK26) + return false; + + Player const* playerAffectingAttacker = HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) ? GetAffectingPlayer() : NULL; + Player const* playerAffectingTarget = target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) ? target->GetAffectingPlayer() : NULL; + + // check duel - before sanctuary checks + if (playerAffectingAttacker && playerAffectingTarget) + if (playerAffectingAttacker->duel && playerAffectingAttacker->duel->opponent == playerAffectingTarget && playerAffectingAttacker->duel->startTime != 0) + return true; + + if ((target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && (target->GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_SANCTUARY)) + || (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && (GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_SANCTUARY))) + return false; + + // additional checks - only PvP case + if (playerAffectingAttacker && playerAffectingTarget) + { + if (target->GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_PVP) + return true; + + if (GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_FFA_PVP + && target->GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_FFA_PVP) + return true; + + return (GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_UNK1) + || (target->GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_UNK1); + } + return true; +} + bool Unit::canAttack(Unit const* target, bool force) const { ASSERT(target); @@ -12410,6 +12499,96 @@ bool Unit::canAttack(Unit const* target, bool force) const return true; } +bool Unit::IsValidAssistTarget(Unit const* target) const +{ + return _IsValidAssistTarget(target, NULL); +} + +bool Unit::_IsValidAssistTarget(Unit const* target, SpellInfo const* bySpell) const +{ + // can assist to self + if (this == target) + return true; + + // can't assist unattackable units or GMs + if (target->HasUnitState(UNIT_STAT_UNATTACKABLE) + || target->GetTypeId() == TYPEID_PLAYER && target->ToPlayer()->isGameMaster()) + return false; + + // can't assist own vehicle or passenger + if (m_vehicle) + if (IsOnVehicle(target) || m_vehicle->GetBase()->IsOnVehicle(target)) + return false; + + // can't assist invisible + if ((!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && !canSeeOrDetect(target)) + return false; + + // can't assist dead + if ((!bySpell || !bySpell->IsAllowingDeadTarget()) && !target->isAlive()) + return false; + + // can't assist untargetable + if ((!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_CAN_TARGET_UNTARGETABLE)) + && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) + return false; + + if (!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_UNK3)) + { + if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE)) + { + if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE)) + return false; + } + else + { + if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE)) + return false; + } + } + + // can't assist non-friendly targets + if (GetReactionTo(target) <= REP_NEUTRAL + && target->GetReactionTo(this) <= REP_NEUTRAL + && (!ToCreature() || !(ToCreature()->GetCreatureInfo()->type_flags & CREATURE_TYPEFLAGS_UNK26))) + return false; + + // PvP case + if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE)) + { + Player const* targetPlayerOwner = target->GetAffectingPlayer(); + if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE)) + { + Player const* selfPlayerOwner = GetAffectingPlayer(); + if (selfPlayerOwner && targetPlayerOwner) + { + // can't assist player which is dueling someone + if (selfPlayerOwner != targetPlayerOwner + && targetPlayerOwner->duel) + return false; + } + // can't assist player in ffa_pvp zone from outside + if ((target->GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_FFA_PVP) + && !(GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_FFA_PVP)) + return false; + // can't assist player out of sanctuary from sanctuary if has pvp enabled + if (target->GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_PVP) + if ((GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_SANCTUARY) && !(target->GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_SANCTUARY)) + return false; + } + } + // PvC case - player can assist creature only if has specific type flags + // !target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && + else if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) + && (!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_UNK3)) + && !((target->GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_PVP))) + { + if (Creature const* creatureTarget = target->ToCreature()) + return creatureTarget->GetCreatureInfo()->type_flags & CREATURE_TYPEFLAGS_UNK26 || creatureTarget->GetCreatureInfo()->type_flags & CREATURE_TYPEFLAGS_AID_PLAYERS; + } + return true; +} + int32 Unit::ModifyHealth(int32 dVal) { int32 gain = 0; diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index a1566f14434..429531aad97 100755 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1553,7 +1553,14 @@ class Unit : public WorldObject bool isFrozen() const; bool isTargetableForAttack(bool checkFakeDeath = true) const; + + bool IsValidAttackTarget(Unit const* target) const; + bool _IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell) const; bool canAttack(Unit const* target, bool force = true) const; + + bool IsValidAssistTarget(Unit const* target) const; + bool _IsValidAssistTarget(Unit const* target, SpellInfo const* bySpell) const; + virtual bool IsInWater() const; virtual bool IsUnderWater() const; bool isInAccessiblePlaceFor(Creature const* c) const; |
