aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/server/game/Entities/Player/Player.cpp1
-rwxr-xr-xsrc/server/game/Entities/Player/Player.h29
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.cpp179
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.h7
-rwxr-xr-xsrc/server/game/Miscellaneous/SharedDefines.h56
5 files changed, 236 insertions, 36 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index beae47640e4..5c115e04652 100755
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -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()))
{
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 1e1bb283a20..e7493f57791 100755
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -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)
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;
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index ca6315b94ca..f3857c07cee 100755
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -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