Merge branch 'azerothcore:master' into Playerbot

This commit is contained in:
ZhengPeiRu21
2022-03-27 11:23:15 -06:00
committed by GitHub
52 changed files with 3865 additions and 281 deletions
+2
View File
@@ -177,6 +177,8 @@ public:
/// == Fields =======================================
virtual void PassengerBoarded(Unit* /*passenger*/, int8 /*seatId*/, bool /*apply*/) {}
virtual bool BeforeSpellClick(Unit* /*clicker*/) { return true; }
virtual void OnSpellClick(Unit* /*clicker*/, bool& /*result*/) { }
virtual bool CanSeeAlways(WorldObject const* /*obj*/) { return false; }
@@ -179,12 +179,6 @@ void SmartAI::GenerateWayPointArray(Movement::PointsArray* points)
void SmartAI::StartPath(bool run, uint32 path, bool repeat, Unit* invoker)
{
if (me->IsInCombat())// no wp movement in combat
{
LOG_ERROR("scripts.ai.sai", "SmartAI::StartPath: Creature entry {} wanted to start waypoint movement while in combat, ignoring.", me->GetEntry());
return;
}
if (HasEscortState(SMART_ESCORT_ESCORTING))
StopPath();
@@ -4400,6 +4400,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
{
if (e.event.quest.quest && var0 != e.event.quest.quest)
return;
RecalcTimer(e, e.event.quest.cooldownMin, e.event.quest.cooldownMax);
ProcessAction(e, unit, var0);
break;
}
@@ -1009,7 +1009,14 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_EVENT_ACCEPTED_QUEST:
case SMART_EVENT_REWARD_QUEST:
if (e.event.quest.quest && !IsQuestValid(e, e.event.quest.quest))
{
return false;
}
if (!IsMinMaxValid(e, e.event.quest.cooldownMin, e.event.quest.cooldownMax))
{
return false;
}
break;
case SMART_EVENT_RECEIVE_EMOTE:
{
@@ -123,8 +123,8 @@ enum SMART_EVENT
SMART_EVENT_FRIENDLY_MISSING_BUFF = 16, // SpellId, Radius, RepeatMin, RepeatMax
SMART_EVENT_SUMMONED_UNIT = 17, // CreatureId(0 all), CooldownMin, CooldownMax
SMART_EVENT_TARGET_MANA_PCT = 18, // ManaMin%, ManaMax%, RepeatMin, RepeatMax
SMART_EVENT_ACCEPTED_QUEST = 19, // QuestID(0any)
SMART_EVENT_REWARD_QUEST = 20, // QuestID(0any)
SMART_EVENT_ACCEPTED_QUEST = 19, // QuestID (0 = any), CooldownMin, CooldownMax
SMART_EVENT_REWARD_QUEST = 20, // QuestID (0 = any), CooldownMin, CooldownMax
SMART_EVENT_REACHED_HOME = 21, // NONE
SMART_EVENT_RECEIVE_EMOTE = 22, // EmoteId, CooldownMin, CooldownMax, condition, val1, val2, val3
SMART_EVENT_HAS_AURA = 23, // Param1 = SpellID, Param2 = Stack amount, Param3/4 RepeatMin, RepeatMax
@@ -293,6 +293,8 @@ struct SmartEvent
struct
{
uint32 quest;
uint32 cooldownMin;
uint32 cooldownMax;
} quest;
struct
@@ -476,9 +476,19 @@ void BattlefieldWG::OnBattleEnd(bool endByTimer)
m_PlayersInWar[TEAM_HORDE].clear();
if (!endByTimer) // win alli/horde
{
uint32 const worldStateId = GetDefenderTeam() == TEAM_ALLIANCE ? WORLDSTATE_ALLIANCE_KEEP_CAPTURED : WORLDSTATE_HORDE_KEEP_CAPTURED;
sWorld->setWorldState(worldStateId, sWorld->getWorldState(worldStateId) + 1);
SendWarning((GetDefenderTeam() == TEAM_ALLIANCE) ? BATTLEFIELD_WG_TEXT_WIN_KEEP : (BATTLEFIELD_WG_TEXT_WIN_KEEP + 2));
}
else // defend alli/horde
{
uint32 const worldStateId = GetDefenderTeam() == TEAM_ALLIANCE ? WORLDSTATE_ALLIANCE_KEEP_DEFENDED : WORLDSTATE_HORDE_KEEP_DEFENDED;
sWorld->setWorldState(worldStateId, sWorld->getWorldState(worldStateId) + 1);
SendWarning((GetDefenderTeam() == TEAM_ALLIANCE) ? BATTLEFIELD_WG_TEXT_DEFEND_KEEP : (BATTLEFIELD_WG_TEXT_DEFEND_KEEP + 2));
}
}
// *******************************************************
@@ -898,6 +908,11 @@ void BattlefieldWG::FillInitialWorldStates(WorldPacket& data)
data << uint32(BATTLEFIELD_WG_WORLD_STATE_VEHICLE_A) << uint32(GetData(BATTLEFIELD_WG_DATA_VEHICLE_A));
data << uint32(BATTLEFIELD_WG_WORLD_STATE_MAX_VEHICLE_A) << GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_A);
data << uint32(WORLDSTATE_HORDE_KEEP_CAPTURED) << uint32(sWorld->getWorldState(WORLDSTATE_HORDE_KEEP_CAPTURED));
data << uint32(WORLDSTATE_HORDE_KEEP_DEFENDED) << uint32(sWorld->getWorldState(WORLDSTATE_HORDE_KEEP_DEFENDED));
data << uint32(WORLDSTATE_ALLIANCE_KEEP_CAPTURED) << uint32(sWorld->getWorldState(WORLDSTATE_ALLIANCE_KEEP_CAPTURED));
data << uint32(WORLDSTATE_ALLIANCE_KEEP_DEFENDED) << uint32(sWorld->getWorldState(WORLDSTATE_ALLIANCE_KEEP_DEFENDED));
for (GameObjectBuilding::const_iterator itr = BuildingsInZone.begin(); itr != BuildingsInZone.end(); ++itr)
data << (*itr)->m_WorldState << (*itr)->m_State;
@@ -913,7 +928,7 @@ void BattlefieldWG::SendInitWorldStatesTo(Player* player)
data << uint32(m_MapId);
data << uint32(m_ZoneId);
data << uint32(0);
data << uint16(10 + BuildingsInZone.size() + WorkshopsList.size()); // Number of fields
data << uint16(14 + BuildingsInZone.size() + WorkshopsList.size()); // Number of fields
FillInitialWorldStates(data);
@@ -523,7 +523,11 @@ enum WintergraspWorldstates
WORLDSTATE_WORKSHOP_SE = 3703,
WORLDSTATE_WORKSHOP_SW = 3702,
WORLDSTATE_WORKSHOP_K_W = 3698,
WORLDSTATE_WORKSHOP_K_E = 3699
WORLDSTATE_WORKSHOP_K_E = 3699,
WORLDSTATE_HORDE_KEEP_CAPTURED = 4022,
WORLDSTATE_HORDE_KEEP_DEFENDED = 4024,
WORLDSTATE_ALLIANCE_KEEP_CAPTURED = 4023,
WORLDSTATE_ALLIANCE_KEEP_DEFENDED = 4025,
};
// TODO: Handle this with creature_text ?
+1 -1
View File
@@ -1045,7 +1045,7 @@ void MovementInfo::OutDebug()
}
WorldObject::WorldObject(bool isWorldObject) : WorldLocation(),
LastUsedScriptID(0), m_name(""), m_isActive(false), m_visibilityDistanceOverride(false), m_isWorldObject(isWorldObject), m_zoneScript(nullptr),
LastUsedScriptID(0), m_name(""), m_isActive(false), m_visibilityDistanceOverride(), m_isWorldObject(isWorldObject), m_zoneScript(nullptr),
_zoneId(0), _areaId(0), _floorZ(INVALID_HEIGHT), _outdoors(false), _liquidData(), _updatePositionData(false), m_transport(nullptr),
m_currMap(nullptr), m_InstanceId(0), m_phaseMask(PHASEMASK_NORMAL), m_useCombinedPhases(true), m_notifyflags(0), m_executed_notifies(0)
{
+2 -15
View File
@@ -737,22 +737,13 @@ void Player::SendMirrorTimer(MirrorTimerType Type, uint32 MaxValue, uint32 Curre
StopMirrorTimer(Type);
return;
}
WorldPacket data(SMSG_START_MIRROR_TIMER, (21));
data << (uint32)Type;
data << CurrentValue;
data << MaxValue;
data << Regen;
data << (uint8)0;
data << (uint32)0; // spell id
GetSession()->SendPacket(&data);
SendDirectMessage(WorldPackets::Misc::StartMirrorTimer(Type, CurrentValue, MaxValue, Regen, 0, 0).Write());
}
void Player::StopMirrorTimer(MirrorTimerType Type)
{
m_MirrorTimer[Type] = DISABLED_MIRROR_TIMER;
WorldPacket data(SMSG_STOP_MIRROR_TIMER, 4);
data << (uint32)Type;
GetSession()->SendPacket(&data);
SendDirectMessage(WorldPackets::Misc::StopMirrorTimer(Type).Write());
}
bool Player::IsImmuneToEnvironmentalDamage()
@@ -7132,10 +7123,6 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
continue;
}
// not allow proc extra attack spell at extra attack
if (m_extraAttacks && spellInfo->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS))
return;
float chance = (float)spellInfo->ProcChance;
if (spellData.SpellPPMRate)
+98 -28
View File
@@ -231,7 +231,6 @@ Unit::Unit(bool isWorldObject) : WorldObject(isWorldObject),
m_modAttackSpeedPct[OFF_ATTACK] = 1.0f;
m_modAttackSpeedPct[RANGED_ATTACK] = 1.0f;
m_extraAttacks = 0;
m_canDualWield = false;
m_rootTimes = 0;
@@ -316,6 +315,8 @@ Unit::Unit(bool isWorldObject) : WorldObject(isWorldObject),
_lastLiquid = nullptr;
_oldFactionId = 0;
_lastExtraAttackSpell = 0;
}
////////////////////////////////////////////////////////////
@@ -430,6 +431,23 @@ void Unit::Update(uint32 p_time)
}
}
_lastDamagedTargetGuid = ObjectGuid::Empty;
if (_lastExtraAttackSpell)
{
while (!extraAttacksTargets.empty())
{
auto itr = extraAttacksTargets.begin();
ObjectGuid targetGuid = itr->first;
uint32 count = itr->second;
extraAttacksTargets.erase(itr);
if (Unit* victim = ObjectAccessor::GetUnit(*this, targetGuid))
{
HandleProcExtraAttackFor(victim, count);
}
}
_lastExtraAttackSpell = 0;
}
// not implemented before 3.0.2
// xinef: if attack time > 0, reduce by diff
// if on next update, attack time < 0 assume player didnt attack - set to 0
@@ -2286,8 +2304,15 @@ void Unit::CalcHealAbsorb(HealInfo& healInfo)
void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extra)
{
if (HasUnitState(UNIT_STATE_CANNOT_AUTOATTACK) || HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED))
if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED))
{
return;
}
if (HasUnitState(UNIT_STATE_CANNOT_AUTOATTACK) && !extra)
{
return;
}
if (!victim->IsAlive())
return;
@@ -2304,6 +2329,11 @@ void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extr
if (attType != BASE_ATTACK && attType != OFF_ATTACK)
return; // ignore ranged case
if (!extra && _lastExtraAttackSpell)
{
_lastExtraAttackSpell = 0;
}
bool meleeAttack = true;
// melee attack spell casted at main hand attack only - no normal melee dmg dealt
@@ -2345,6 +2375,8 @@ void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extr
//TriggerAurasProcOnEvent(damageInfo);
_lastDamagedTargetGuid = victim->GetGUID();
DealMeleeDamage(&damageInfo, true);
DamageInfo dmgInfo(damageInfo);
@@ -2457,15 +2489,31 @@ bool Unit::GetMeleeAttackPoint(Unit* attacker, Position& pos)
return true;
}
void Unit::HandleProcExtraAttackFor(Unit* victim)
void Unit::HandleProcExtraAttackFor(Unit* victim, uint32 count)
{
while (m_extraAttacks)
while (count)
{
--count;
AttackerStateUpdate(victim, BASE_ATTACK, true);
--m_extraAttacks;
}
}
void Unit::AddExtraAttacks(uint32 count)
{
ObjectGuid targetGUID = _lastDamagedTargetGuid;
if (!targetGUID)
{
if (ObjectGuid selection = GetTarget())
{
targetGUID = selection; // Spell was cast directly (not triggered by aura)
}
else
return;
}
extraAttacksTargets[targetGUID] += count;
}
MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(Unit const* victim, WeaponAttackType attType) const
{
// This is only wrapper
@@ -8418,7 +8466,7 @@ bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, Sp
return false;
}
bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlags, uint32 procEx, uint32 cooldown, uint32 procPhase)
bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlags, uint32 procEx, uint32 cooldown, uint32 procPhase, ProcEventInfo& eventInfo)
{
// Get triggered aura spell info
SpellInfo const* auraSpellInfo = triggeredByAura->GetSpellInfo();
@@ -8904,8 +8952,23 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
}
// not allow proc extra attack spell at extra attack
if (m_extraAttacks && triggerEntry->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS))
return false;
if (triggerEntry->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS))
{
uint32 lastExtraAttackSpell = eventInfo.GetActor()->GetLastExtraAttackSpell();
// Patch 1.12.0(?) extra attack abilities can no longer chain proc themselves
if (lastExtraAttackSpell == trigger_spell_id)
{
return false;
}
// Patch 2.2.0 Sword Specialization (Warrior, Rogue) extra attack can no longer proc additional extra attacks
// 3.3.5 Sword Specialization (Warrior), Hack and Slash (Rogue)
if (lastExtraAttackSpell == 16459 || lastExtraAttackSpell == 66923)
{
return false;
}
}
// Custom requirements (not listed in procEx) Warning! damage dealing after this
// Custom triggered spells
@@ -10742,15 +10805,15 @@ void Unit::SendEnergizeSpellLog(Unit* victim, uint32 spellID, uint32 damage, Pow
void Unit::EnergizeBySpell(Unit* victim, uint32 spellID, uint32 damage, Powers powerType)
{
SendEnergizeSpellLog(victim, spellID, damage, powerType);
// needs to be called after sending spell log
victim->ModifyPower(powerType, damage);
victim->ModifyPower(powerType, damage, false);
if (powerType != POWER_HAPPINESS)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID);
victim->getHostileRefMgr().threatAssist(this, float(damage) * 0.5f, spellInfo);
}
SendEnergizeSpellLog(victim, spellID, damage, powerType);
}
float Unit::SpellPctDamageModsDone(Unit* victim, SpellInfo const* spellProto, DamageEffectType damagetype)
@@ -13440,7 +13503,7 @@ int32 Unit::GetHealthGain(int32 dVal)
}
// returns negative amount on power reduction
int32 Unit::ModifyPower(Powers power, int32 dVal)
int32 Unit::ModifyPower(Powers power, int32 dVal, bool withPowerUpdate /*= true*/)
{
if (dVal == 0)
return 0;
@@ -13452,7 +13515,7 @@ int32 Unit::ModifyPower(Powers power, int32 dVal)
int32 val = dVal + curPower;
if (val <= 0)
{
SetPower(power, 0);
SetPower(power, 0, withPowerUpdate);
return -curPower;
}
@@ -13460,12 +13523,12 @@ int32 Unit::ModifyPower(Powers power, int32 dVal)
if (val < maxPower)
{
SetPower(power, val);
SetPower(power, val, withPowerUpdate);
gain = val - curPower;
}
else if (curPower != maxPower)
{
SetPower(power, maxPower);
SetPower(power, maxPower, withPowerUpdate);
gain = maxPower - curPower;
}
@@ -14832,7 +14895,7 @@ void Unit::SetMaxHealth(uint32 val)
SetHealth(val);
}
void Unit::SetPower(Powers power, uint32 val)
void Unit::SetPower(Powers power, uint32 val, bool withPowerUpdate /*= true*/)
{
if (GetPower(power) == val)
return;
@@ -14843,11 +14906,14 @@ void Unit::SetPower(Powers power, uint32 val)
SetStatInt32Value(static_cast<uint16>(UNIT_FIELD_POWER1) + power, val);
WorldPacket data(SMSG_POWER_UPDATE);
data << GetPackGUID();
data << uint8(power);
data << uint32(val);
SendMessageToSet(&data, GetTypeId() == TYPEID_PLAYER);
if (withPowerUpdate)
{
WorldPacket data(SMSG_POWER_UPDATE);
data << GetPackGUID();
data << uint8(power);
data << uint32(val);
SendMessageToSet(&data, GetTypeId() == TYPEID_PLAYER);
}
// group update
if (GetTypeId() == TYPEID_PLAYER)
@@ -15841,7 +15907,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
{
LOG_DEBUG("spells.aura", "ProcDamageAndSpell: casting spell {} (triggered by {} aura of spell {})", spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId());
// Don`t drop charge or add cooldown for not started trigger
if (HandleProcTriggerSpell(target, damage, triggeredByAura, procSpellInfo, procFlag, procExtra, cooldown, procPhase))
if (HandleProcTriggerSpell(target, damage, triggeredByAura, procSpellInfo, procFlag, procExtra, cooldown, procPhase, eventInfo))
takeCharges = true;
break;
}
@@ -15900,7 +15966,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
{
LOG_DEBUG("spells.aura", "ProcDamageAndSpell: casting spell {} (triggered with value by {} aura of spell {})", spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId());
if (HandleProcTriggerSpell(target, damage, triggeredByAura, procSpellInfo, procFlag, procExtra, cooldown, procPhase))
if (HandleProcTriggerSpell(target, damage, triggeredByAura, procSpellInfo, procFlag, procExtra, cooldown, procPhase, eventInfo))
takeCharges = true;
break;
}
@@ -16303,10 +16369,6 @@ void Unit::AddComboPoints(Unit* target, int8 count)
return;
}
// remove Premed-like effects
// (NB: this Aura removes the already-added CP when it expires from duration - now that we've added CP, this shouldn't happen anymore)
RemoveAurasByType(SPELL_AURA_RETAIN_COMBO_POINTS);
if (target && target != m_comboTarget)
{
if (m_comboTarget)
@@ -18931,6 +18993,15 @@ void Unit::JumpTo(WorldObject* obj, float speedZ)
bool Unit::HandleSpellClick(Unit* clicker, int8 seatId)
{
Creature* creature = ToCreature();
if (creature && creature->IsAIEnabled)
{
if (!creature->AI()->BeforeSpellClick(clicker))
{
return false;
}
}
bool result = false;
uint32 spellClickEntry = GetVehicleKit() ? GetVehicleKit()->GetCreatureEntry() : GetEntry();
SpellClickInfoMapBounds clickPair = sObjectMgr->GetSpellClickInfoMapBounds(spellClickEntry);
@@ -18999,7 +19070,6 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId)
result = true;
}
Creature* creature = ToCreature();
if (creature && creature->IsAIEnabled)
creature->AI()->OnSpellClick(clicker, result);
+14 -4
View File
@@ -1416,10 +1416,10 @@ public:
void setPowerType(Powers power);
[[nodiscard]] uint32 GetPower(Powers power) const { return GetUInt32Value(static_cast<uint16>(UNIT_FIELD_POWER1) + power); }
[[nodiscard]] uint32 GetMaxPower(Powers power) const { return GetUInt32Value(static_cast<uint16>(UNIT_FIELD_MAXPOWER1) + power); }
void SetPower(Powers power, uint32 val);
void SetPower(Powers power, uint32 val, bool withPowerUpdate = true);
void SetMaxPower(Powers power, uint32 val);
// returns the change in power
int32 ModifyPower(Powers power, int32 val);
int32 ModifyPower(Powers power, int32 val, bool withPowerUpdate = true);
int32 ModifyPowerPct(Powers power, float pct, bool apply = true);
[[nodiscard]] uint32 GetAttackTime(WeaponAttackType att) const
@@ -1507,7 +1507,13 @@ public:
void CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* damageInfo, WeaponAttackType attackType = BASE_ATTACK, const bool sittingVictim = false);
void DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss);
void HandleProcExtraAttackFor(Unit* victim);
void HandleProcExtraAttackFor(Unit* victim, uint32 count);
void SetLastExtraAttackSpell(uint32 spellId) { _lastExtraAttackSpell = spellId; }
[[nodiscard]] uint32 GetLastExtraAttackSpell() const { return _lastExtraAttackSpell; }
void AddExtraAttacks(uint32 count);
void SetLastDamagedTargetGuid(ObjectGuid const& guid) { _lastDamagedTargetGuid = guid; }
[[nodiscard]] ObjectGuid const& GetLastDamagedTargetGuid() const { return _lastDamagedTargetGuid; }
void CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 damage, SpellInfo const* spellInfo, WeaponAttackType attackType = BASE_ATTACK, bool crit = false);
void DealSpellDamage(SpellNonMeleeDamage* damageInfo, bool durabilityLoss, Spell const* spell = nullptr);
@@ -2474,7 +2480,7 @@ private:
bool IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent, ProcEventInfo const& eventInfo);
bool HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, bool* handled);
bool HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, uint32 procPhase);
bool HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, uint32 procPhase, ProcEventInfo& eventInfo);
bool HandleOverrideClassScriptAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 cooldown);
bool HandleAuraRaidProcFromChargeWithValue(AuraEffect* triggeredByAura);
bool HandleAuraRaidProcFromCharge(AuraEffect* triggeredByAura);
@@ -2518,6 +2524,10 @@ private:
uint32 _oldFactionId; ///< faction before charm
[[nodiscard]] float processDummyAuras(float TakenTotalMod) const;
uint32 _lastExtraAttackSpell;
std::unordered_map<ObjectGuid /*guid*/, uint32 /*count*/> extraAttacksTargets;
ObjectGuid _lastDamagedTargetGuid;
};
namespace Acore
+4 -3
View File
@@ -35,6 +35,7 @@
#include "Log.h"
#include "LootMgr.h"
#include "MapMgr.h"
#include "MiscPackets.h"
#include "Object.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
@@ -1570,9 +1571,9 @@ void WorldSession::HandleWorldStateUITimerUpdate(WorldPacket& /*recv_data*/)
// empty opcode
LOG_DEBUG("network", "WORLD: CMSG_WORLD_STATE_UI_TIMER_UPDATE");
WorldPacket data(SMSG_WORLD_STATE_UI_TIMER_UPDATE, 4);
data << uint32(GameTime::GetGameTime().count());
SendPacket(&data);
WorldPackets::Misc::UITime response;
response.Time = GameTime::GetGameTime().count();
SendPacket(response.Write());
}
void WorldSession::HandleReadyForAccountDataTimes(WorldPacket& /*recv_data*/)
@@ -83,6 +83,33 @@ WorldPacket const* WorldPackets::Misc::RandomRoll::Write()
return &_worldPacket;
}
WorldPacket const* WorldPackets::Misc::StartMirrorTimer::Write()
{
_worldPacket << uint32(Timer);
_worldPacket << uint32(Value);
_worldPacket << uint32(MaxValue);
_worldPacket << int32(Scale);
_worldPacket << uint8(Paused);
_worldPacket << uint32(SpellID);
return &_worldPacket;
}
WorldPacket const* WorldPackets::Misc::PauseMirrorTimer::Write()
{
_worldPacket << uint32(Timer);
_worldPacket << uint8(Paused);
return &_worldPacket;
}
WorldPacket const* WorldPackets::Misc::StopMirrorTimer::Write()
{
_worldPacket << uint32(Timer);
return &_worldPacket;
}
WorldPacket const* WorldPackets::Misc::CrossedInebriationThreshold::Write()
{
_worldPacket << Guid;
@@ -91,3 +118,10 @@ WorldPacket const* WorldPackets::Misc::CrossedInebriationThreshold::Write()
return &_worldPacket;
}
WorldPacket const* WorldPackets::Misc::UITime::Write()
{
_worldPacket << uint32(Time);
return &_worldPacket;
}
@@ -114,6 +114,46 @@ namespace WorldPackets
ObjectGuid Roller;
};
class StartMirrorTimer final : public ServerPacket
{
public:
StartMirrorTimer() : ServerPacket(SMSG_START_MIRROR_TIMER, 21) { }
StartMirrorTimer(uint32 timer, uint32 value, uint32 maxValue, int32 scale, bool paused, uint32 spellID) :
ServerPacket(SMSG_START_MIRROR_TIMER, 21), Timer(timer), Value(value), MaxValue(maxValue), Scale(scale), Paused(paused), SpellID(spellID) { }
WorldPacket const* Write() override;
uint32 Timer = 0;
uint32 Value = 0;
uint32 MaxValue = 0;
int32 Scale = 0;
bool Paused = false;
uint32 SpellID = 0;
};
class PauseMirrorTimer final : public ServerPacket
{
public:
PauseMirrorTimer() : ServerPacket(SMSG_PAUSE_MIRROR_TIMER, 5) { }
PauseMirrorTimer(uint32 timer, bool paused) : ServerPacket(SMSG_PAUSE_MIRROR_TIMER, 5), Timer(timer), Paused(paused) { }
WorldPacket const* Write() override;
uint32 Timer = 0;
bool Paused = true;
};
class StopMirrorTimer final : public ServerPacket
{
public:
StopMirrorTimer() : ServerPacket(SMSG_STOP_MIRROR_TIMER, 4) { }
StopMirrorTimer(uint32 timer) : ServerPacket(SMSG_STOP_MIRROR_TIMER, 4), Timer(timer) { }
WorldPacket const* Write() override;
uint32 Timer = 0;
};
class DurabilityDamageDeath final : public ServerPacket
{
public:
@@ -134,6 +174,16 @@ namespace WorldPackets
uint32 ItemID = 0;
};
class UITime final : public ServerPacket
{
public:
UITime() : ServerPacket(SMSG_WORLD_STATE_UI_TIMER_UPDATE, 4) { }
WorldPacket const* Write() override;
uint32 Time = 0;
};
}
}
+25 -9
View File
@@ -2605,6 +2605,8 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
// Do damage and triggers
else if (m_damage > 0)
{
caster->SetLastDamagedTargetGuid(unitTarget->GetGUID());
// Fill base damage struct (unitTarget - is real spell target)
SpellNonMeleeDamage damageInfo(caster, unitTarget, m_spellInfo, m_spellSchoolMask);
@@ -4039,11 +4041,20 @@ void Spell::_handle_finish_phase()
// Real add combo points from effects
if (m_comboTarget && m_comboPointGain)
{
// remove Premed-like effects unless they were caused by ourselves
// (this Aura removes the already-added CP when it expires from duration - now that we've added CP, this shouldn't happen anymore!)
if (!m_spellInfo->HasAura(SPELL_AURA_RETAIN_COMBO_POINTS))
{
m_caster->RemoveAurasByType(SPELL_AURA_RETAIN_COMBO_POINTS);
}
m_caster->AddComboPoints(m_comboTarget, m_comboPointGain);
}
if (m_caster->m_extraAttacks && GetSpellInfo()->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS))
m_caster->HandleProcExtraAttackFor(m_caster->GetVictim());
if (m_spellInfo->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS))
{
m_caster->SetLastExtraAttackSpell(m_spellInfo->Id);
}
if (!IsAutoRepeat() && !IsNextMeleeSwingSpell())
if (m_caster->GetCharmerOrOwnerPlayerOrPlayerItself())
@@ -4461,10 +4472,12 @@ void Spell::SendSpellStart()
if (m_spellInfo->HasAttribute(SPELL_ATTR0_USES_RANGED_SLOT) || m_spellInfo->HasAttribute(SPELL_ATTR0_CU_NEEDS_AMMO_DATA))
castFlags |= CAST_FLAG_PROJECTILE;
if ((m_caster->GetTypeId() == TYPEID_PLAYER ||
(m_caster->GetTypeId() == TYPEID_UNIT && m_caster->IsPet()))
&& m_spellInfo->PowerType != POWER_HEALTH)
if ((m_caster->GetTypeId() == TYPEID_PLAYER || (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->IsPet()))
&& m_spellInfo->PowerType != POWER_HEALTH && m_powerCost != 0)
{
castFlags |= CAST_FLAG_POWER_LEFT_SELF;
}
if (m_spellInfo->RuneCostID && m_spellInfo->PowerType == POWER_RUNE)
castFlags |= CAST_FLAG_NO_GCD; // not needed, but Blizzard sends it
@@ -4518,10 +4531,11 @@ void Spell::SendSpellGo()
if (m_spellInfo->HasAttribute(SPELL_ATTR0_USES_RANGED_SLOT) || m_spellInfo->HasAttribute(SPELL_ATTR0_CU_NEEDS_AMMO_DATA))
castFlags |= CAST_FLAG_PROJECTILE; // arrows/bullets visual
if ((m_caster->GetTypeId() == TYPEID_PLAYER ||
(m_caster->GetTypeId() == TYPEID_UNIT && m_caster->IsPet()))
&& m_spellInfo->PowerType != POWER_HEALTH)
castFlags |= CAST_FLAG_POWER_LEFT_SELF; // should only be sent to self, but the current messaging doesn't make that possible
if ((m_caster->GetTypeId() == TYPEID_PLAYER || (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->IsPet()))
&& m_spellInfo->PowerType != POWER_HEALTH && m_powerCost != 0) // should only be sent to self, but the current messaging doesn't make that possible
{
castFlags |= CAST_FLAG_POWER_LEFT_SELF;
}
if ((m_caster->GetTypeId() == TYPEID_PLAYER)
&& (m_caster->getClass() == CLASS_DEATH_KNIGHT)
@@ -5052,7 +5066,9 @@ void Spell::TakePower()
// Set the five second timer
if (PowerType == POWER_MANA && m_powerCost > 0)
{
m_caster->SetLastManaUse(GameTime::GetGameTimeMS().count());
}
}
void Spell::TakeAmmo()
+7 -177
View File
@@ -1287,39 +1287,6 @@ void Spell::EffectTeleportUnits(SpellEffIndex /*effIndex*/)
}
return;
}
// Dimensional Ripper - Area 52
case 36890:
{
if (roll_chance_i(50)) // 50% success
{
int32 rand_eff = urand(1, 4);
switch (rand_eff)
{
case 1:
// soul split - evil
m_caster->CastSpell(m_caster, 36900, true);
break;
case 2:
// soul split - good
m_caster->CastSpell(m_caster, 36901, true);
break;
case 3:
// Increase the size
m_caster->CastSpell(m_caster, 36895, true);
break;
case 4:
// Transform
{
if (m_caster->ToPlayer()->GetTeamId() == TEAM_ALLIANCE)
m_caster->CastSpell(m_caster, 36897, true);
else
m_caster->CastSpell(m_caster, 36899, true);
break;
}
}
}
return;
}
}
}
@@ -1516,13 +1483,6 @@ void Spell::EffectHeal(SpellEffIndex /*effIndex*/)
addhealth += damageAmount;
}
// Runic Healing Injector (heal increased by 25% for engineers - 3.2.0 patch change)
else if (m_spellInfo->Id == 67489)
{
if (Player* player = m_caster->ToPlayer())
if (player->HasSkill(SKILL_ENGINEERING))
AddPct(addhealth, 25);
}
// Swiftmend - consumes Regrowth or Rejuvenation
else if (m_spellInfo->TargetAuraState == AURA_STATE_SWIFTMEND && unitTarget->HasAuraState(AURA_STATE_SWIFTMEND, m_spellInfo, m_caster))
{
@@ -3822,17 +3782,6 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex)
{
switch (m_spellInfo->Id)
{
// Bending Shinbone
case 8856:
{
if (!itemTarget && m_caster->GetTypeId() != TYPEID_PLAYER)
return;
uint32 spell_id = roll_chance_i(20) ? 8854 : 8855;
m_caster->CastSpell(m_caster, spell_id, true, nullptr);
return;
}
// Brittle Armor - need remove one 24575 Brittle Armor aura
case 24590:
unitTarget->RemoveAuraFromStack(24575);
@@ -3974,84 +3923,6 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex)
m_caster->TextEmote(buf);
break;
}
// Death Knight Initiate Visual
case 51519:
{
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
return;
uint32 iTmpSpellId = 0;
switch (unitTarget->GetDisplayId())
{
case 25369:
iTmpSpellId = 51552;
break; // bloodelf female
case 25373:
iTmpSpellId = 51551;
break; // bloodelf male
case 25363:
iTmpSpellId = 51542;
break; // draenei female
case 25357:
iTmpSpellId = 51541;
break; // draenei male
case 25361:
iTmpSpellId = 51537;
break; // dwarf female
case 25356:
iTmpSpellId = 51538;
break; // dwarf male
case 25372:
iTmpSpellId = 51550;
break; // forsaken female
case 25367:
iTmpSpellId = 51549;
break; // forsaken male
case 25362:
iTmpSpellId = 51540;
break; // gnome female
case 25359:
iTmpSpellId = 51539;
break; // gnome male
case 25355:
iTmpSpellId = 51534;
break; // human female
case 25354:
iTmpSpellId = 51520;
break; // human male
case 25360:
iTmpSpellId = 51536;
break; // nightelf female
case 25358:
iTmpSpellId = 51535;
break; // nightelf male
case 25368:
iTmpSpellId = 51544;
break; // orc female
case 25364:
iTmpSpellId = 51543;
break; // orc male
case 25371:
iTmpSpellId = 51548;
break; // tauren female
case 25366:
iTmpSpellId = 51547;
break; // tauren male
case 25370:
iTmpSpellId = 51545;
break; // troll female
case 25365:
iTmpSpellId = 51546;
break; // troll male
default:
return;
}
unitTarget->CastSpell(unitTarget, iTmpSpellId, true);
Creature* npc = unitTarget->ToCreature();
npc->LoadEquipment();
return;
}
// Deathbolt from Thalgran Blightbringer
// reflected by Freya's Ward
// Retribution by Sevenfold Retribution
@@ -4121,48 +3992,6 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex)
else
unitTarget->CastSpell(unitTarget, 59314, true);
return;
}
case 60123: // Lightwell
{
if (m_caster->GetTypeId() != TYPEID_UNIT || !m_caster->ToCreature()->IsSummon())
return;
uint32 spell_heal;
switch (m_caster->GetEntry())
{
case 31897:
spell_heal = 7001;
break;
case 31896:
spell_heal = 27873;
break;
case 31895:
spell_heal = 27874;
break;
case 31894:
spell_heal = 28276;
break;
case 31893:
spell_heal = 48084;
break;
case 31883:
spell_heal = 48085;
break;
default:
LOG_ERROR("spells.effect", "Unknown Lightwell spell caster {}", m_caster->GetEntry());
return;
}
// proc a spellcast
if (Aura* chargesAura = m_caster->GetAura(59907))
{
m_caster->CastSpell(unitTarget, spell_heal, true, nullptr, nullptr, m_caster->ToTempSummon()->GetSummonerGUID());
if (chargesAura->ModCharges(-1))
m_caster->ToTempSummon()->UnSummon();
}
return;
}
// Stoneclaw Totem
@@ -4835,17 +4664,18 @@ void Spell::EffectResurrect(SpellEffIndex effIndex)
void Spell::EffectAddExtraAttacks(SpellEffIndex effIndex)
{
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
{
return;
}
if (!unitTarget || !unitTarget->IsAlive() || !unitTarget->GetVictim())
if (!unitTarget || !unitTarget->IsAlive())
{
return;
}
if (unitTarget->m_extraAttacks)
return;
unitTarget->AddExtraAttacks(damage);
unitTarget->m_extraAttacks = damage;
ExecuteLogEffectExtraAttacks(effIndex, unitTarget->GetVictim(), damage);
ExecuteLogEffectExtraAttacks(effIndex, unitTarget, damage);
}
void Spell::EffectParry(SpellEffIndex /*effIndex*/)
@@ -4168,6 +4168,11 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->AttributesEx2 |= SPELL_ATTR2_IGNORE_LINE_OF_SIGHT;
});
ApplySpellFix({ 22247 }, [](SpellInfo* spellInfo)
{
spellInfo->AttributesCu |= SPELL_ATTR0_CU_DONT_BREAK_STEALTH;
});
// Manastorm
ApplySpellFix({ 21097 }, [](SpellInfo* spellInfo)
{