Core/Entities: Add Unit::IsValidAssistTarget and Unit::IsValidAttackTarget functions for proper serverside checks of related entity flags.
This commit is contained in:
@@ -20612,6 +20612,7 @@ void Player::UpdateHomebindTime(uint32 time)
|
||||
void Player::UpdatePvPState(bool onlyFFA)
|
||||
{
|
||||
// TODO: should we always synchronize UNIT_FIELD_BYTES_2, 1 of controller and controlled?
|
||||
// no, we shouldn't, those are checked for affecting player by client
|
||||
if (!pvpInfo.inNoPvPArea && !isGameMaster()
|
||||
&& (pvpInfo.inFFAPvPArea || sWorld->IsFFAPvPRealm()))
|
||||
{
|
||||
|
||||
@@ -373,27 +373,32 @@ enum PlayerFlags
|
||||
PLAYER_FLAGS_GM = 0x00000008,
|
||||
PLAYER_FLAGS_GHOST = 0x00000010,
|
||||
PLAYER_FLAGS_RESTING = 0x00000020,
|
||||
PLAYER_FLAGS_UNK7 = 0x00000040,
|
||||
PLAYER_FLAGS_UNK8 = 0x00000080, // pre-3.0.3 PLAYER_FLAGS_FFA_PVP flag for FFA PVP state
|
||||
PLAYER_FLAGS_UNK6 = 0x00000040,
|
||||
PLAYER_FLAGS_UNK7 = 0x00000080, // pre-3.0.3 PLAYER_FLAGS_FFA_PVP flag for FFA PVP state
|
||||
PLAYER_FLAGS_CONTESTED_PVP = 0x00000100, // Player has been involved in a PvP combat and will be attacked by contested guards
|
||||
PLAYER_FLAGS_IN_PVP = 0x00000200,
|
||||
PLAYER_FLAGS_HIDE_HELM = 0x00000400,
|
||||
PLAYER_FLAGS_HIDE_CLOAK = 0x00000800,
|
||||
PLAYER_FLAGS_PLAYED_LONG_TIME = 0x00001000, // played long time
|
||||
PLAYER_FLAGS_PLAYED_TOO_LONG = 0x00002000, // played too long time
|
||||
PLAYER_FLAGS_PLAYED_LONG_TIME = 0x00001000, // played long time
|
||||
PLAYER_FLAGS_PLAYED_TOO_LONG = 0x00002000, // played too long time
|
||||
PLAYER_FLAGS_IS_OUT_OF_BOUNDS = 0x00004000,
|
||||
PLAYER_FLAGS_DEVELOPER = 0x00008000, // <Dev> prefix for something?
|
||||
PLAYER_FLAGS_UNK17 = 0x00010000, // pre-3.0.3 PLAYER_FLAGS_SANCTUARY flag for player entered sanctuary
|
||||
PLAYER_FLAGS_UNK16 = 0x00010000, // pre-3.0.3 PLAYER_FLAGS_SANCTUARY flag for player entered sanctuary
|
||||
PLAYER_FLAGS_TAXI_BENCHMARK = 0x00020000, // taxi benchmark mode (on/off) (2.0.1)
|
||||
PLAYER_FLAGS_PVP_TIMER = 0x00040000, // 3.0.2, pvp timer active (after you disable pvp manually)
|
||||
PLAYER_FLAGS_UNK20 = 0x00080000,
|
||||
PLAYER_FLAGS_UNK21 = 0x00100000,
|
||||
PLAYER_FLAGS_UNK22 = 0x00200000,
|
||||
PLAYER_FLAGS_UNK19 = 0x00080000,
|
||||
PLAYER_FLAGS_UNK20 = 0x00100000,
|
||||
PLAYER_FLAGS_UNK21 = 0x00200000,
|
||||
PLAYER_FLAGS_COMMENTATOR2 = 0x00400000,
|
||||
PLAYER_ALLOW_ONLY_ABILITY = 0x00800000, // used by bladestorm and killing spree
|
||||
PLAYER_FLAGS_UNK25 = 0x01000000, // disabled all melee ability on tab include autoattack
|
||||
|
||||
PLAYER_FLAGS_NO_XP_GAIN = 0x02000000
|
||||
PLAYER_ALLOW_ONLY_ABILITY = 0x00800000, // used by bladestorm and killing spree, allowed only spells with SPELL_ATTR0_REQ_AMMO, SPELL_EFFECT_ATTACK, checked only for active player
|
||||
PLAYER_FLAGS_UNK24 = 0x01000000, // disabled all melee ability on tab include autoattack
|
||||
PLAYER_FLAGS_NO_XP_GAIN = 0x02000000,
|
||||
PLAYER_FLAGS_UNK26 = 0x04000000,
|
||||
PLAYER_FLAGS_UNK27 = 0x08000000,
|
||||
PLAYER_FLAGS_UNK28 = 0x01000000,
|
||||
PLAYER_FLAGS_UNK29 = 0x02000000,
|
||||
PLAYER_FLAGS_UNK30 = 0x04000000,
|
||||
PLAYER_FLAGS_UNK31 = 0x08000000,
|
||||
};
|
||||
|
||||
// used for PLAYER__FIELD_KNOWN_TITLES field (uint64), (1<<bit_index) without (-1)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -2265,30 +2265,38 @@ enum CreatureFamily
|
||||
|
||||
enum CreatureTypeFlags
|
||||
{
|
||||
CREATURE_TYPEFLAGS_TAMEABLE = 0x000001, // Tameable by any hunter
|
||||
CREATURE_TYPEFLAGS_GHOST = 0x000002, // Creature are also visible for not alive player. Allow gossip interaction if npcflag allow?
|
||||
CREATURE_TYPEFLAGS_UNK3 = 0x000004,
|
||||
CREATURE_TYPEFLAGS_UNK4 = 0x000008,
|
||||
CREATURE_TYPEFLAGS_UNK5 = 0x000010,
|
||||
CREATURE_TYPEFLAGS_UNK6 = 0x000020,
|
||||
CREATURE_TYPEFLAGS_UNK7 = 0x000040,
|
||||
CREATURE_TYPEFLAGS_DEAD_INTERACT = 0x000080, // Player can interact with the creature if its dead (not player dead)
|
||||
CREATURE_TYPEFLAGS_HERBLOOT = 0x000100, // Can be looted by herbalist
|
||||
CREATURE_TYPEFLAGS_MININGLOOT = 0x000200, // Can be looted by miner
|
||||
CREATURE_TYPEFLAGS_UNK11 = 0x000400,
|
||||
CREATURE_TYPEFLAGS_MOUNTED_COMBAT = 0x000800, // Creature can remain mounted when entering combat
|
||||
CREATURE_TYPEFLAGS_AID_PLAYERS = 0x001000, // ? Can aid any player in combat if in range?
|
||||
CREATURE_TYPEFLAGS_UNK14 = 0x002000,
|
||||
CREATURE_TYPEFLAGS_UNK15 = 0x004000, // ? Possibly not in use
|
||||
CREATURE_TYPEFLAGS_ENGINEERLOOT = 0x008000, // Can be looted by engineer
|
||||
CREATURE_TYPEFLAGS_EXOTIC = 0x010000, // Can be tamed by hunter as exotic pet
|
||||
CREATURE_TYPEFLAGS_UNK18 = 0x020000, // ? Related to vehicles/pvp?
|
||||
CREATURE_TYPEFLAGS_UNK19 = 0x040000, // ? Related to vehicle/siege weapons?
|
||||
CREATURE_TYPEFLAGS_UNK20 = 0x080000,
|
||||
CREATURE_TYPEFLAGS_UNK21 = 0x100000,
|
||||
CREATURE_TYPEFLAGS_UNK22 = 0x200000,
|
||||
CREATURE_TYPEFLAGS_UNK23 = 0x400000,
|
||||
CREATURE_TYPEFLAGS_UNK24 = 0x800000 // ? First seen in 3.2.2. Related to banner/backpack of creature/companion?
|
||||
CREATURE_TYPEFLAGS_TAMEABLE = 0x00000001, // Tameable by any hunter
|
||||
CREATURE_TYPEFLAGS_GHOST = 0x00000002, // Creature are also visible for not alive player. Allow gossip interaction if npcflag allow?
|
||||
CREATURE_TYPEFLAGS_UNK2 = 0x00000004,
|
||||
CREATURE_TYPEFLAGS_UNK3 = 0x00000008,
|
||||
CREATURE_TYPEFLAGS_UNK4 = 0x00000010,
|
||||
CREATURE_TYPEFLAGS_UNK5 = 0x00000020,
|
||||
CREATURE_TYPEFLAGS_UNK6 = 0x00000040,
|
||||
CREATURE_TYPEFLAGS_DEAD_INTERACT = 0x00000080, // Player can interact with the creature if its dead (not player dead)
|
||||
CREATURE_TYPEFLAGS_HERBLOOT = 0x00000100, // Can be looted by herbalist
|
||||
CREATURE_TYPEFLAGS_MININGLOOT = 0x00000200, // Can be looted by miner
|
||||
CREATURE_TYPEFLAGS_UNK10 = 0x00000400,
|
||||
CREATURE_TYPEFLAGS_MOUNTED_COMBAT = 0x00000800, // Creature can remain mounted when entering combat
|
||||
CREATURE_TYPEFLAGS_AID_PLAYERS = 0x00001000, // ? Can aid any player in combat if in range?
|
||||
CREATURE_TYPEFLAGS_UNK13 = 0x00002000,
|
||||
CREATURE_TYPEFLAGS_UNK14 = 0x00004000, // ? Possibly not in use
|
||||
CREATURE_TYPEFLAGS_ENGINEERLOOT = 0x00008000, // Can be looted by engineer
|
||||
CREATURE_TYPEFLAGS_EXOTIC = 0x00010000, // Can be tamed by hunter as exotic pet
|
||||
CREATURE_TYPEFLAGS_UNK17 = 0x00020000, // ? Related to vehicles/pvp?
|
||||
CREATURE_TYPEFLAGS_UNK18 = 0x00040000, // ? Related to vehicle/siege weapons?
|
||||
CREATURE_TYPEFLAGS_UNK19 = 0x00080000,
|
||||
CREATURE_TYPEFLAGS_UNK20 = 0x00100000,
|
||||
CREATURE_TYPEFLAGS_UNK21 = 0x00200000,
|
||||
CREATURE_TYPEFLAGS_UNK22 = 0x00400000,
|
||||
CREATURE_TYPEFLAGS_UNK23 = 0x00800000, // ? First seen in 3.2.2. Related to banner/backpack of creature/companion?
|
||||
CREATURE_TYPEFLAGS_UNK24 = 0x01000000,
|
||||
CREATURE_TYPEFLAGS_UNK25 = 0x02000000,
|
||||
CREATURE_TYPEFLAGS_UNK26 = 0x04000000,
|
||||
CREATURE_TYPEFLAGS_UNK27 = 0x08000000,
|
||||
CREATURE_TYPEFLAGS_UNK28 = 0x10000000,
|
||||
CREATURE_TYPEFLAGS_UNK29 = 0x20000000,
|
||||
CREATURE_TYPEFLAGS_UNK30 = 0x40000000,
|
||||
CREATURE_TYPEFLAGS_UNK31 = 0x80000000,
|
||||
};
|
||||
|
||||
enum CreatureEliteType
|
||||
|
||||
Reference in New Issue
Block a user