Core/Entities: Add Unit::IsValidAssistTarget and Unit::IsValidAttackTarget functions for proper serverside checks of related entity flags.

This commit is contained in:
QAston
2011-09-16 22:17:48 +02:00
parent bf38cd8f3e
commit 31e755c291
5 changed files with 236 additions and 36 deletions
+179
View File
@@ -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;
+7
View File
@@ -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;