aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Entities/Unit
diff options
context:
space:
mode:
authorQAston <qaston@gmail.com>2011-09-16 22:16:14 +0200
committerQAston <qaston@gmail.com>2011-09-16 22:17:48 +0200
commit31e755c2910d26c1616c098a39b343101c398e96 (patch)
tree3a5e350903afea05c0476ba1062d59eb85afc8d9 /src/server/game/Entities/Unit
parentbf38cd8f3e4bf2137b8a583fdd6457c1f6b8dec3 (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-xsrc/server/game/Entities/Unit/Unit.cpp179
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.h7
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;