diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/server/game/Entities/Player/Player.cpp | 1 | ||||
-rwxr-xr-x | src/server/game/Entities/Player/Player.h | 29 | ||||
-rwxr-xr-x | src/server/game/Entities/Unit/Unit.cpp | 179 | ||||
-rwxr-xr-x | src/server/game/Entities/Unit/Unit.h | 7 | ||||
-rwxr-xr-x | src/server/game/Miscellaneous/SharedDefines.h | 56 |
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 |