mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-31 09:33:47 +00:00
Merge branch 'master' of https://github.com/ZhengPeiRu21/azerothcore-wotlk into Playerbot
This commit is contained in:
@@ -197,3 +197,65 @@ void Corpse::ResetGhostTime()
|
||||
{
|
||||
m_time = GameTime::GetGameTime().count();
|
||||
}
|
||||
|
||||
void Corpse::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target) const
|
||||
{
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
ByteBuffer fieldBuffer;
|
||||
UpdateMask updateMask;
|
||||
updateMask.SetCount(m_valuesCount);
|
||||
|
||||
uint32* flags = nullptr;
|
||||
uint32 visibleFlag = GetUpdateFieldData(target, flags);
|
||||
|
||||
for (uint16 index = 0; index < m_valuesCount; ++index)
|
||||
{
|
||||
if (_fieldNotifyFlags & flags[index] || ((updateType == UPDATETYPE_VALUES ? _changesMask.GetBit(index) : m_uint32Values[index]) && (flags[index] & visibleFlag)))
|
||||
{
|
||||
updateMask.SetBit(index);
|
||||
|
||||
if (index == CORPSE_FIELD_BYTES_1 || index == CORPSE_FIELD_BYTES_2)
|
||||
{
|
||||
Player* owner = ObjectAccessor::GetPlayer(*this, GetOwnerGUID());
|
||||
if (owner && owner != target && sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && owner->IsInRaidWith(target) && owner->GetTeamId() != target->GetTeamId())
|
||||
{
|
||||
uint32 playerBytes = target->GetUInt32Value(PLAYER_BYTES);
|
||||
uint32 playerBytes2 = target->GetUInt32Value(PLAYER_BYTES_2);
|
||||
|
||||
uint8 race = target->getRace();
|
||||
uint8 skin = (uint8)(playerBytes);
|
||||
uint8 face = (uint8)(playerBytes >> 8);
|
||||
uint8 hairstyle = (uint8)(playerBytes >> 16);
|
||||
uint8 haircolor = (uint8)(playerBytes >> 24);
|
||||
uint8 facialhair = (uint8)(playerBytes2);
|
||||
|
||||
uint32 corpseBytes1 = ((0x00) | (race << 8) | (target->GetByteValue(PLAYER_BYTES_3, 0) << 16) | (skin << 24));
|
||||
uint32 corpseBytes2 = ((face) | (hairstyle << 8) | (haircolor << 16) | (facialhair << 24));
|
||||
|
||||
if (index == CORPSE_FIELD_BYTES_1)
|
||||
{
|
||||
fieldBuffer << corpseBytes1;
|
||||
}
|
||||
else
|
||||
{
|
||||
fieldBuffer << corpseBytes2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fieldBuffer << m_uint32Values[index];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fieldBuffer << m_uint32Values[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*data << uint8(updateMask.GetBlockCount());
|
||||
updateMask.AppendToPacket(data);
|
||||
data->append(fieldBuffer);
|
||||
}
|
||||
|
||||
@@ -54,6 +54,8 @@ public:
|
||||
void AddToWorld() override;
|
||||
void RemoveFromWorld() override;
|
||||
|
||||
void BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target) const override;
|
||||
|
||||
bool Create(ObjectGuid::LowType guidlow);
|
||||
bool Create(ObjectGuid::LowType guidlow, Player* owner);
|
||||
|
||||
|
||||
@@ -215,13 +215,13 @@ bool TemporaryThreatModifierEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
|
||||
return true;
|
||||
}
|
||||
|
||||
Creature::Creature(bool isWorldObject): Unit(isWorldObject), MovableMapObject(), m_groupLootTimer(0), lootingGroupLowGUID(0), m_PlayerDamageReq(0), m_lootRecipientGroup(0),
|
||||
Creature::Creature(bool isWorldObject): Unit(isWorldObject), MovableMapObject(), m_groupLootTimer(0), lootingGroupLowGUID(0), m_lootRecipientGroup(0),
|
||||
m_corpseRemoveTime(0), m_respawnTime(0), m_respawnDelay(300), m_corpseDelay(60), m_wanderDistance(0.0f), m_boundaryCheckTime(2500),
|
||||
m_transportCheckTimer(1000), lootPickPocketRestoreTime(0), m_reactState(REACT_AGGRESSIVE), m_defaultMovementType(IDLE_MOTION_TYPE),
|
||||
m_spawnId(0), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false),
|
||||
m_AlreadySearchedAssistance(false), m_regenHealth(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_moveInLineOfSightDisabled(false), m_moveInLineOfSightStrictlyDisabled(false),
|
||||
m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), m_detectionDistance(20.0f), m_waypointID(0), m_path_id(0), m_formation(nullptr), _lastDamagedTime(nullptr), m_cannotReachTimer(0),
|
||||
_isMissingSwimmingFlagOutOfCombat(false), m_assistanceTimer(0)
|
||||
m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), m_detectionDistance(20.0f), m_waypointID(0), m_path_id(0), m_formation(nullptr), _lastDamagedTime(nullptr), m_cannotReachTarget(false), m_cannotReachTimer(0),
|
||||
_isMissingSwimmingFlagOutOfCombat(false), m_assistanceTimer(0), _playerDamageReq(0), _damagedByPlayer(false)
|
||||
{
|
||||
m_regenTimer = CREATURE_REGEN_INTERVAL;
|
||||
m_valuesCount = UNIT_END;
|
||||
@@ -526,7 +526,7 @@ bool Creature::UpdateEntry(uint32 Entry, const CreatureData* data, bool changele
|
||||
|
||||
uint32 previousHealth = GetHealth();
|
||||
uint32 previousMaxHealth = GetMaxHealth();
|
||||
uint32 previousPlayerDamageReq = m_PlayerDamageReq;
|
||||
uint32 previousPlayerDamageReq = _playerDamageReq;
|
||||
|
||||
SelectLevel(changelevel);
|
||||
if (previousHealth > 0)
|
||||
@@ -535,11 +535,11 @@ bool Creature::UpdateEntry(uint32 Entry, const CreatureData* data, bool changele
|
||||
|
||||
if (previousMaxHealth && previousMaxHealth > GetMaxHealth())
|
||||
{
|
||||
m_PlayerDamageReq = (uint32)(previousPlayerDamageReq * GetMaxHealth() / previousMaxHealth);
|
||||
_playerDamageReq = (uint32)(previousPlayerDamageReq * GetMaxHealth() / previousMaxHealth);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_PlayerDamageReq = previousPlayerDamageReq;
|
||||
_playerDamageReq = previousPlayerDamageReq;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1831,14 +1831,14 @@ bool Creature::CanStartAttack(Unit const* who) const
|
||||
return false;
|
||||
|
||||
// This set of checks is should be done only for creatures
|
||||
if ((HasUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC) && who->GetTypeId() != TYPEID_PLAYER) || // flag is valid only for non player characters
|
||||
(HasUnitFlag(UNIT_FLAG_IMMUNE_TO_PC) && who->GetTypeId() == TYPEID_PLAYER)) // immune to PC and target is a player, return false
|
||||
if ((IsImmuneToNPC() && who->GetTypeId() != TYPEID_PLAYER) || // flag is valid only for non player characters
|
||||
(IsImmuneToPC() && who->GetTypeId() == TYPEID_PLAYER)) // immune to PC and target is a player, return false
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Unit* owner = who->GetOwner())
|
||||
if (owner->GetTypeId() == TYPEID_PLAYER && HasUnitFlag(UNIT_FLAG_IMMUNE_TO_PC)) // immune to PC and target has player owner
|
||||
if (owner->GetTypeId() == TYPEID_PLAYER && IsImmuneToPC()) // immune to PC and target has player owner
|
||||
return false;
|
||||
|
||||
// Do not attack non-combat pets
|
||||
@@ -2369,7 +2369,7 @@ bool Creature::CanAssistTo(Unit const* u, Unit const* enemy, bool checkfaction /
|
||||
if (IsCivilian())
|
||||
return false;
|
||||
|
||||
if (HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_NPC))
|
||||
if (HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE) || IsImmuneToNPC())
|
||||
return false;
|
||||
|
||||
// skip fighting creature
|
||||
@@ -3578,3 +3578,30 @@ void Creature::ModifyThreatPercentTemp(Unit* victim, int32 percent, Milliseconds
|
||||
m_Events.AddEvent(pEvent, m_Events.CalculateTime(duration.count()));
|
||||
}
|
||||
}
|
||||
|
||||
bool Creature::IsDamageEnoughForLootingAndReward() const
|
||||
{
|
||||
return (m_creatureInfo->flags_extra & CREATURE_FLAG_EXTRA_NO_PLAYER_DAMAGE_REQ) || (_playerDamageReq == 0 && _damagedByPlayer);
|
||||
}
|
||||
|
||||
void Creature::LowerPlayerDamageReq(uint32 unDamage, bool damagedByPlayer /*= true*/)
|
||||
{
|
||||
if (_playerDamageReq)
|
||||
_playerDamageReq > unDamage ? _playerDamageReq -= unDamage : _playerDamageReq = 0;
|
||||
|
||||
if (!_damagedByPlayer)
|
||||
{
|
||||
_damagedByPlayer = damagedByPlayer;
|
||||
}
|
||||
}
|
||||
|
||||
void Creature::ResetPlayerDamageReq()
|
||||
{
|
||||
_playerDamageReq = GetHealth() / 2;
|
||||
_damagedByPlayer = false;
|
||||
}
|
||||
|
||||
uint32 Creature::GetPlayerDamageReq() const
|
||||
{
|
||||
return _playerDamageReq;
|
||||
}
|
||||
|
||||
@@ -340,14 +340,10 @@ public:
|
||||
|
||||
void SetDisableReputationGain(bool disable) { DisableReputationGain = disable; }
|
||||
[[nodiscard]] bool IsReputationGainDisabled() const { return DisableReputationGain; }
|
||||
[[nodiscard]] bool IsDamageEnoughForLootingAndReward() const { return (m_creatureInfo->flags_extra & CREATURE_FLAG_EXTRA_NO_PLAYER_DAMAGE_REQ) || (m_PlayerDamageReq == 0); }
|
||||
void LowerPlayerDamageReq(uint32 unDamage)
|
||||
{
|
||||
if (m_PlayerDamageReq)
|
||||
m_PlayerDamageReq > unDamage ? m_PlayerDamageReq -= unDamage : m_PlayerDamageReq = 0;
|
||||
}
|
||||
void ResetPlayerDamageReq() { m_PlayerDamageReq = GetHealth() / 2; }
|
||||
uint32 m_PlayerDamageReq;
|
||||
[[nodiscard]] bool IsDamageEnoughForLootingAndReward() const;
|
||||
void LowerPlayerDamageReq(uint32 unDamage, bool damagedByPlayer = true);
|
||||
void ResetPlayerDamageReq();
|
||||
[[nodiscard]] uint32 GetPlayerDamageReq() const;
|
||||
|
||||
[[nodiscard]] uint32 GetOriginalEntry() const { return m_originalEntry; }
|
||||
void SetOriginalEntry(uint32 entry) { m_originalEntry = entry; }
|
||||
@@ -468,6 +464,8 @@ private:
|
||||
|
||||
uint32 m_assistanceTimer;
|
||||
|
||||
uint32 _playerDamageReq;
|
||||
bool _damagedByPlayer;
|
||||
};
|
||||
|
||||
class AssistDelayEvent : public BasicEvent
|
||||
|
||||
@@ -270,6 +270,11 @@ void CreatureGroup::MemberEvaded(Creature* member)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (itr.second.HasGroupFlag(std::underlying_type_t<GroupAIFlags>(GroupAIFlags::GROUP_AI_FLAG_DONT_RESPAWN_LEADER_ON_EVADE)) && pMember == m_leader)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
pMember->Respawn();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,10 +28,11 @@ class CreatureGroup;
|
||||
|
||||
enum class GroupAIFlags : uint16
|
||||
{
|
||||
GROUP_AI_FLAG_MEMBER_ASSIST_LEADER = 0x001,
|
||||
GROUP_AI_FLAG_LEADER_ASSIST_MEMBER = 0x002,
|
||||
GROUP_AI_FLAG_EVADE_TOGETHER = 0x004,
|
||||
GROUP_AI_FLAG_RESPAWN_ON_EVADE = 0x008,
|
||||
GROUP_AI_FLAG_MEMBER_ASSIST_LEADER = 0x001,
|
||||
GROUP_AI_FLAG_LEADER_ASSIST_MEMBER = 0x002,
|
||||
GROUP_AI_FLAG_EVADE_TOGETHER = 0x004,
|
||||
GROUP_AI_FLAG_RESPAWN_ON_EVADE = 0x008,
|
||||
GROUP_AI_FLAG_DONT_RESPAWN_LEADER_ON_EVADE = 0x010,
|
||||
//GROUP_AI_FLAG_UNK3 = 0x010,
|
||||
//GROUP_AI_FLAG_UNK4 = 0x020,
|
||||
//GROUP_AI_FLAG_UNK5 = 0x040,
|
||||
|
||||
@@ -2089,7 +2089,7 @@ void GameObject::CastSpell(Unit* target, uint32 spellId)
|
||||
trigger->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
|
||||
|
||||
// xinef: Remove Immunity flags
|
||||
trigger->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC);
|
||||
trigger->SetImmuneToNPC(false);
|
||||
// xinef: set proper orientation, fixes cast against stealthed targets
|
||||
if (target)
|
||||
trigger->SetInFront(target);
|
||||
|
||||
@@ -183,46 +183,64 @@ bool ItemCanGoIntoBag(ItemTemplate const* pProto, ItemTemplate const* pBagProto)
|
||||
switch (pBagProto->Class)
|
||||
{
|
||||
case ITEM_CLASS_CONTAINER:
|
||||
switch (pBagProto->SubClass)
|
||||
{
|
||||
if (pBagProto->SubClass == ITEM_SUBCLASS_CONTAINER)
|
||||
{
|
||||
case ITEM_SUBCLASS_CONTAINER:
|
||||
return true;
|
||||
case ITEM_SUBCLASS_SOUL_CONTAINER:
|
||||
if (!(pProto->BagFamily & BAG_FAMILY_MASK_SOUL_SHARDS))
|
||||
return false;
|
||||
return true;
|
||||
case ITEM_SUBCLASS_HERB_CONTAINER:
|
||||
if (!(pProto->BagFamily & BAG_FAMILY_MASK_HERBS))
|
||||
return false;
|
||||
return true;
|
||||
case ITEM_SUBCLASS_ENCHANTING_CONTAINER:
|
||||
if (!(pProto->BagFamily & BAG_FAMILY_MASK_ENCHANTING_SUPP))
|
||||
return false;
|
||||
return true;
|
||||
case ITEM_SUBCLASS_MINING_CONTAINER:
|
||||
if (!(pProto->BagFamily & BAG_FAMILY_MASK_MINING_SUPP))
|
||||
return false;
|
||||
return true;
|
||||
case ITEM_SUBCLASS_ENGINEERING_CONTAINER:
|
||||
if (!(pProto->BagFamily & BAG_FAMILY_MASK_ENGINEERING_SUPP))
|
||||
return false;
|
||||
return true;
|
||||
case ITEM_SUBCLASS_GEM_CONTAINER:
|
||||
if (!(pProto->BagFamily & BAG_FAMILY_MASK_GEMS))
|
||||
return false;
|
||||
return true;
|
||||
case ITEM_SUBCLASS_LEATHERWORKING_CONTAINER:
|
||||
if (!(pProto->BagFamily & BAG_FAMILY_MASK_LEATHERWORKING_SUPP))
|
||||
return false;
|
||||
return true;
|
||||
case ITEM_SUBCLASS_INSCRIPTION_CONTAINER:
|
||||
if (!(pProto->BagFamily & BAG_FAMILY_MASK_INSCRIPTION_SUPP))
|
||||
return false;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pProto->Class == ITEM_CLASS_CONTAINER)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (pBagProto->SubClass)
|
||||
{
|
||||
case ITEM_SUBCLASS_SOUL_CONTAINER:
|
||||
if (!(pProto->BagFamily & BAG_FAMILY_MASK_SOUL_SHARDS))
|
||||
return false;
|
||||
return true;
|
||||
case ITEM_SUBCLASS_HERB_CONTAINER:
|
||||
if (!(pProto->BagFamily & BAG_FAMILY_MASK_HERBS))
|
||||
return false;
|
||||
return true;
|
||||
case ITEM_SUBCLASS_ENCHANTING_CONTAINER:
|
||||
if (!(pProto->BagFamily & BAG_FAMILY_MASK_ENCHANTING_SUPP))
|
||||
return false;
|
||||
return true;
|
||||
case ITEM_SUBCLASS_MINING_CONTAINER:
|
||||
if (!(pProto->BagFamily & BAG_FAMILY_MASK_MINING_SUPP))
|
||||
return false;
|
||||
return true;
|
||||
case ITEM_SUBCLASS_ENGINEERING_CONTAINER:
|
||||
if (!(pProto->BagFamily & BAG_FAMILY_MASK_ENGINEERING_SUPP))
|
||||
return false;
|
||||
return true;
|
||||
case ITEM_SUBCLASS_GEM_CONTAINER:
|
||||
if (!(pProto->BagFamily & BAG_FAMILY_MASK_GEMS))
|
||||
return false;
|
||||
return true;
|
||||
case ITEM_SUBCLASS_LEATHERWORKING_CONTAINER:
|
||||
if (!(pProto->BagFamily & BAG_FAMILY_MASK_LEATHERWORKING_SUPP))
|
||||
return false;
|
||||
return true;
|
||||
case ITEM_SUBCLASS_INSCRIPTION_CONTAINER:
|
||||
if (!(pProto->BagFamily & BAG_FAMILY_MASK_INSCRIPTION_SUPP))
|
||||
return false;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
case ITEM_CLASS_QUIVER:
|
||||
{
|
||||
if (pProto->Class == ITEM_CLASS_QUIVER)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (pBagProto->SubClass)
|
||||
{
|
||||
case ITEM_SUBCLASS_QUIVER:
|
||||
@@ -236,7 +254,9 @@ bool ItemCanGoIntoBag(ItemTemplate const* pProto, ItemTemplate const* pBagProto)
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -2643,12 +2643,13 @@ void Player::InitStatsForLevel(bool reapplyMods)
|
||||
|
||||
// cleanup unit flags (will be re-applied if need at aura load).
|
||||
RemoveFlag(UNIT_FIELD_FLAGS,
|
||||
UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_ATTACKABLE_1 |
|
||||
UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_LOOTING |
|
||||
UNIT_FLAG_PET_IN_COMBAT | UNIT_FLAG_SILENCED | UNIT_FLAG_PACIFIED |
|
||||
UNIT_FLAG_STUNNED | UNIT_FLAG_IN_COMBAT | UNIT_FLAG_DISARMED |
|
||||
UNIT_FLAG_CONFUSED | UNIT_FLAG_FLEEING | UNIT_FLAG_NOT_SELECTABLE |
|
||||
UNIT_FLAG_SKINNABLE | UNIT_FLAG_MOUNT | UNIT_FLAG_TAXI_FLIGHT );
|
||||
UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_ATTACKABLE_1 |
|
||||
UNIT_FLAG_LOOTING | UNIT_FLAG_PET_IN_COMBAT | UNIT_FLAG_SILENCED |
|
||||
UNIT_FLAG_PACIFIED | UNIT_FLAG_STUNNED | UNIT_FLAG_IN_COMBAT |
|
||||
UNIT_FLAG_DISARMED | UNIT_FLAG_CONFUSED | UNIT_FLAG_FLEEING |
|
||||
UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_SKINNABLE | UNIT_FLAG_MOUNT |
|
||||
UNIT_FLAG_TAXI_FLIGHT);
|
||||
SetImmuneToAll(false);
|
||||
SetUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED); // must be set
|
||||
|
||||
SetUnitFlag2(UNIT_FLAG2_REGENERATE_POWER);// must be set
|
||||
|
||||
@@ -1000,7 +1000,11 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage
|
||||
victim->ToCreature()->SetLootRecipient(attacker);
|
||||
|
||||
if (!attacker || attacker->IsControlledByPlayer() || attacker->IsCreatedByPlayer())
|
||||
victim->ToCreature()->LowerPlayerDamageReq(health < damage ? health : damage);
|
||||
{
|
||||
uint32 unDamage = health < damage ? health : damage;
|
||||
bool damagedByPlayer = unDamage && attacker && attacker->m_movedByPlayer != nullptr;
|
||||
victim->ToCreature()->LowerPlayerDamageReq(unDamage, damagedByPlayer);
|
||||
}
|
||||
}
|
||||
|
||||
if (health <= damage)
|
||||
@@ -3867,7 +3871,11 @@ bool Unit::isInAccessiblePlaceFor(Creature const* c) const
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsInWater())
|
||||
LiquidStatus liquidStatus = GetLiquidData().Status;
|
||||
bool isInWater = (liquidStatus & MAP_LIQUID_STATUS_SWIMMING) != 0;
|
||||
|
||||
// In water or jumping in water
|
||||
if (isInWater || (liquidStatus == LIQUID_MAP_ABOVE_WATER && (IsFalling() || (ToPlayer() && ToPlayer()->IsFalling()))))
|
||||
{
|
||||
return c->CanEnterWater();
|
||||
}
|
||||
@@ -13045,6 +13053,24 @@ void Unit::SetInCombatWith(Unit* enemy, uint32 duration)
|
||||
SetInCombatState(false, enemy, duration);
|
||||
}
|
||||
|
||||
void Unit::SetImmuneToPC(bool apply, bool keepCombat)
|
||||
{
|
||||
(void)keepCombat;
|
||||
if (apply)
|
||||
SetUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
|
||||
else
|
||||
RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
|
||||
}
|
||||
|
||||
void Unit::SetImmuneToNPC(bool apply, bool keepCombat)
|
||||
{
|
||||
(void)keepCombat;
|
||||
if (apply)
|
||||
SetUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC);
|
||||
else
|
||||
RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC);
|
||||
}
|
||||
|
||||
void Unit::CombatStart(Unit* victim, bool initialAggro)
|
||||
{
|
||||
// Xinef: Dont allow to start combat with triggers
|
||||
@@ -13158,8 +13184,8 @@ void Unit::SetInCombatState(bool PvP, Unit* enemy, uint32 duration)
|
||||
return;
|
||||
|
||||
// xinef: if we somehow engage in combat (scripts, dunno) with player, remove this flag so he can fight back
|
||||
if (GetTypeId() == TYPEID_UNIT && enemy && HasUnitFlag(UNIT_FLAG_IMMUNE_TO_PC) && enemy->GetCharmerOrOwnerPlayerOrPlayerItself())
|
||||
RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_PC); // unit has engaged in combat, remove immunity so players can fight back
|
||||
if (GetTypeId() == TYPEID_UNIT && enemy && IsImmuneToPC() && enemy->GetCharmerOrOwnerPlayerOrPlayerItself())
|
||||
SetImmuneToPC(true); // unit has engaged in combat, remove immunity so players can fight back
|
||||
|
||||
if (IsInCombat())
|
||||
return;
|
||||
@@ -13225,7 +13251,7 @@ void Unit::ClearInCombat()
|
||||
if (Creature* creature = ToCreature())
|
||||
{
|
||||
if (creature->GetCreatureTemplate() && creature->GetCreatureTemplate()->unit_flags & UNIT_FLAG_IMMUNE_TO_PC)
|
||||
SetUnitFlag(UNIT_FLAG_IMMUNE_TO_PC); // set immunity state to the one from db on evade
|
||||
SetImmuneToPC(true); // set immunity state to the one from db on evade
|
||||
|
||||
ClearUnitState(UNIT_STATE_ATTACK_PLAYER);
|
||||
if (HasDynamicFlag(UNIT_DYNFLAG_TAPPED))
|
||||
@@ -13269,7 +13295,7 @@ bool Unit::isTargetableForAttack(bool checkFakeDeath, Unit const* byWho) const
|
||||
if (HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE))
|
||||
return false;
|
||||
|
||||
if (HasUnitFlag(UNIT_FLAG_IMMUNE_TO_PC) && byWho && byWho->GetCharmerOrOwnerPlayerOrPlayerItself())
|
||||
if (IsImmuneToPC() && byWho && byWho->GetCharmerOrOwnerPlayerOrPlayerItself())
|
||||
return false;
|
||||
|
||||
if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->IsGameMaster())
|
||||
@@ -13324,11 +13350,11 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo
|
||||
}
|
||||
// check flags
|
||||
if (target->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_TAXI_FLIGHT | UNIT_FLAG_NOT_ATTACKABLE_1 | UNIT_FLAG_NON_ATTACKABLE_2)
|
||||
|| (!HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) && target->HasUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC))
|
||||
|| (!target->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) && HasUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC))
|
||||
|| (HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) && target->HasUnitFlag(UNIT_FLAG_IMMUNE_TO_PC))
|
||||
|| (!HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) && target->IsImmuneToNPC())
|
||||
|| (!target->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) && IsImmuneToNPC())
|
||||
|| (HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) && target->IsImmuneToPC())
|
||||
// check if this is a world trigger cast - GOs are using world triggers to cast their spells, so we need to ignore their immunity flag here, this is a temp workaround, needs removal when go cast is implemented properly
|
||||
|| ((GetEntry() != WORLD_TRIGGER && (!obj || !obj->isType(TYPEMASK_GAMEOBJECT | TYPEMASK_DYNAMICOBJECT))) && target->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) && HasUnitFlag(UNIT_FLAG_IMMUNE_TO_PC)))
|
||||
|| ((GetEntry() != WORLD_TRIGGER && (!obj || !obj->isType(TYPEMASK_GAMEOBJECT | TYPEMASK_DYNAMICOBJECT))) && target->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) && IsImmuneToPC()))
|
||||
return false;
|
||||
|
||||
// CvC case - can attack each other only when one of them is hostile
|
||||
@@ -13443,12 +13469,12 @@ bool Unit::_IsValidAssistTarget(Unit const* target, SpellInfo const* bySpell) co
|
||||
|
||||
if (HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
|
||||
{
|
||||
if (target->HasUnitFlag(UNIT_FLAG_IMMUNE_TO_PC))
|
||||
if (target->IsImmuneToPC())
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (target->HasUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC))
|
||||
if (target->IsImmuneToNPC())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -15737,9 +15763,9 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
|
||||
else // For attacker
|
||||
{
|
||||
// Overpower on victim dodge
|
||||
if (procExtra & PROC_EX_DODGE )
|
||||
if (procExtra & PROC_EX_DODGE)
|
||||
{
|
||||
if (GetTypeId() == TYPEID_PLAYER && getClass() == CLASS_WARRIOR)
|
||||
if (getClass() == CLASS_WARRIOR)
|
||||
{
|
||||
AddComboPoints(target, 1);
|
||||
StartReactiveTimer(REACTIVE_OVERPOWER);
|
||||
@@ -16530,8 +16556,10 @@ void Unit::UpdateReactives(uint32 p_time)
|
||||
ModifyAuraState(AURA_STATE_HUNTER_PARRY, false);
|
||||
break;
|
||||
case REACTIVE_OVERPOWER:
|
||||
if (getClass() == CLASS_WARRIOR && GetTypeId() == TYPEID_PLAYER)
|
||||
if (getClass() == CLASS_WARRIOR)
|
||||
{
|
||||
ClearComboPoints();
|
||||
}
|
||||
break;
|
||||
case REACTIVE_WOLVERINE_BITE:
|
||||
if (IsHunterPet())
|
||||
|
||||
@@ -1648,6 +1648,13 @@ public:
|
||||
|
||||
[[nodiscard]] bool IsInFlight() const { return HasUnitState(UNIT_STATE_IN_FLIGHT); }
|
||||
|
||||
void SetImmuneToAll(bool apply, bool keepCombat = false) { SetImmuneToPC(apply, keepCombat); SetImmuneToNPC(apply, keepCombat); }
|
||||
bool IsImmuneToAll() const { return IsImmuneToPC() && IsImmuneToNPC(); }
|
||||
void SetImmuneToPC(bool apply, bool keepCombat = false);
|
||||
bool IsImmuneToPC() const { return HasUnitFlag(UNIT_FLAG_IMMUNE_TO_PC); }
|
||||
void SetImmuneToNPC(bool apply, bool keepCombat = false);
|
||||
bool IsImmuneToNPC() const { return HasUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC); }
|
||||
|
||||
bool IsEngaged() const { return IsInCombat(); }
|
||||
bool IsEngagedBy(Unit const* who) const { return IsInCombatWith(who); }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user