Merge branch 'master' into Playerbot

This commit is contained in:
Yunfan Li
2025-06-14 21:33:35 +08:00
138 changed files with 3510 additions and 1281 deletions
+1 -1
View File
@@ -31,7 +31,7 @@
int32 PetAI::Permissible(Creature const* creature)
{
if (creature->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN))
if (creature->HasUnitTypeMask(UNIT_MASK_CONTROLLABLE_GUARDIAN))
{
if (reinterpret_cast<Guardian const*>(creature)->GetOwner()->IsPlayer())
return PERMIT_BASE_PROACTIVE;
@@ -15,13 +15,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* ScriptData
SDName: Npc_EscortAI
SD%Complete: 100
SDComment:
SDCategory: Npc
EndScriptData */
#include "ScriptedEscortAI.h"
#include "Group.h"
#include "Player.h"
@@ -15,13 +15,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* ScriptData
SDName: FollowerAI
SD%Complete: 50
SDComment: This AI is under development
SDCategory: Npc
EndScriptData */
#include "ScriptedFollowerAI.h"
#include "Group.h"
#include "Player.h"
@@ -742,13 +742,16 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (e.action.cast.castFlags & SMARTCAST_COMBAT_MOVE)
{
// If cast flag SMARTCAST_COMBAT_MOVE is set combat movement will not be allowed unless target is outside spell range, out of mana, or LOS.
if (result == SPELL_FAILED_OUT_OF_RANGE)
// if we are just out of range, we only chase until we are back in spell range.
CAST_AI(SmartAI, me->AI())->SetCombatMove(true, std::max(spellMaxRange - NOMINAL_MELEE_RANGE, 0.0f));
else
// if spell fail for any other reason, we chase to melee range, or stay where we are if spellcast was successful.
CAST_AI(SmartAI, me->AI())->SetCombatMove(spellCastFailed);
if (!me->isMoving()) // Don't try to reposition while we are moving
{
// If cast flag SMARTCAST_COMBAT_MOVE is set combat movement will not be allowed unless target is outside spell range, out of mana, or LOS.
if (result == SPELL_FAILED_OUT_OF_RANGE)
// if we are just out of range, we only chase until we are back in spell range.
CAST_AI(SmartAI, me->AI())->SetCombatMove(true, std::max(spellMaxRange - NOMINAL_MELEE_RANGE, 0.0f));
else
// if spell fail for any other reason, we chase to melee range, or stay where we are if spellcast was successful.
CAST_AI(SmartAI, me->AI())->SetCombatMove(spellCastFailed);
}
}
if (spellCastFailed)
+2 -2
View File
@@ -1230,8 +1230,8 @@ void Channel::ToggleModeration(Player* player)
return;
}
const uint32 level = sWorld->getIntConfig(CONFIG_GM_LEVEL_CHANNEL_MODERATION);
const bool gm = (level && player->GetSession()->GetSecurity() >= level);
const AccountTypes level = static_cast<AccountTypes>(sWorld->getIntConfig(CONFIG_GM_LEVEL_CHANNEL_MODERATION));
const bool gm = (player->GetSession()->GetSecurity() >= level);
if (!playersStore[guid].IsModerator() && !gm)
{
@@ -422,6 +422,8 @@ namespace lfg
lockData = LFG_LOCKSTATUS_TOO_HIGH_LEVEL;
else if (dungeon->seasonal && !IsSeasonActive(dungeon->id))
lockData = LFG_LOCKSTATUS_NOT_IN_SEASON;
else if (player->IsClass(CLASS_DEATH_KNIGHT) && !player->IsGameMaster() &&!(player->IsQuestRewarded(13188) || player->IsQuestRewarded(13189)))
lockData = LFG_LOCKSTATUS_QUEST_NOT_COMPLETED;
else if (ar)
{
// Check required items
@@ -2591,7 +2591,7 @@ bool Creature::_IsTargetAcceptable(Unit const* target) const
void Creature::UpdateMoveInLineOfSightState()
{
// xinef: pets, guardians and units with scripts / smartAI should be skipped
if (IsPet() || HasUnitTypeMask(UNIT_MASK_MINION | UNIT_MASK_SUMMON | UNIT_MASK_GUARDIAN | UNIT_MASK_CONTROLABLE_GUARDIAN) ||
if (IsPet() || HasUnitTypeMask(UNIT_MASK_MINION | UNIT_MASK_SUMMON | UNIT_MASK_GUARDIAN | UNIT_MASK_CONTROLLABLE_GUARDIAN) ||
GetScriptId() || GetAIName() == "SmartAI")
{
m_moveInLineOfSightStrictlyDisabled = false;
@@ -3735,7 +3735,7 @@ uint8 Creature::GetLeashTimer() const
{ // Based on testing on Classic, seems to range from ~11s for low level mobs (1-5) to ~16s for high level mobs (70+)
uint8 timerOffset = 11;
uint8 timerModifier = uint8(GetLevel() / 10) - 2;
uint8 timerModifier = uint8(GetCreatureTemplate()->minlevel / 10) - 2;
// Formula is likely not quite correct, but better than flat timer
return std::max<uint8>(timerOffset, timerOffset + timerModifier);
@@ -422,7 +422,7 @@ Guardian::Guardian(SummonPropertiesEntry const* properties, ObjectGuid owner, bo
m_unitTypeMask |= UNIT_MASK_GUARDIAN;
if (properties && (properties->Type == SUMMON_TYPE_PET || properties->Category == SUMMON_CATEGORY_PET))
{
m_unitTypeMask |= UNIT_MASK_CONTROLABLE_GUARDIAN;
m_unitTypeMask |= UNIT_MASK_CONTROLLABLE_GUARDIAN;
InitCharmInfo();
}
}
@@ -435,7 +435,7 @@ void Guardian::InitStats(uint32 duration)
{
InitStatsForLevel(m_owner->GetLevel());
if (m_owner->IsPlayer() && HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN))
if (m_owner->IsPlayer() && HasUnitTypeMask(UNIT_MASK_CONTROLLABLE_GUARDIAN))
m_charmInfo->InitCharmCreateSpells();
}
+2 -2
View File
@@ -60,9 +60,9 @@ Pet::Pet(Player* owner, PetType type) : Guardian(nullptr, owner ? owner->GetGUID
if (type == HUNTER_PET)
m_unitTypeMask |= UNIT_MASK_HUNTER_PET;
if (!(m_unitTypeMask & UNIT_MASK_CONTROLABLE_GUARDIAN))
if (!(m_unitTypeMask & UNIT_MASK_CONTROLLABLE_GUARDIAN))
{
m_unitTypeMask |= UNIT_MASK_CONTROLABLE_GUARDIAN;
m_unitTypeMask |= UNIT_MASK_CONTROLLABLE_GUARDIAN;
InitCharmInfo();
}
+1 -3
View File
@@ -393,7 +393,6 @@ Player::Player(WorldSession* session): Unit(true), m_mover(this)
m_achievementMgr = new AchievementMgr(this);
m_reputationMgr = new ReputationMgr(this);
// Ours
m_NeedToSaveGlyphs = false;
m_MountBlockId = 0;
m_realDodge = 0.0f;
@@ -7188,8 +7187,7 @@ void Player::ApplyEquipSpell(SpellInfo const* spellInfo, Item* item, bool apply,
LOG_DEBUG("entities.player", "WORLD: cast {} Equip spellId - {}", (item ? "item" : "itemset"), spellInfo->Id);
//Ignore spellInfo->DurationEntry, cast with -1 duration
CastCustomSpell(spellInfo->Id, SPELLVALUE_AURA_DURATION, -1, this, true, item);
CastSpell(this, spellInfo, true, item);
}
else
{
-1
View File
@@ -2570,7 +2570,6 @@ public:
[[nodiscard]] bool CanFly() const override { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY); }
[[nodiscard]] bool CanEnterWater() const override { return true; }
// OURS
// saving
void AdditionalSavingAddMask(uint8 mask) { m_additionalSaveTimer = 2000; m_additionalSaveMask |= mask; }
// arena spectator
+30 -16
View File
@@ -424,7 +424,7 @@ void Unit::Update(uint32 p_time)
SendThreatListUpdate();
// update combat timer only for players and pets (only pets with PetAI)
if (IsInCombat() && (IsPlayer() || ((IsPet() || HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN)) && IsControlledByPlayer())))
if (IsInCombat() && (IsPlayer() || ((IsPet() || HasUnitTypeMask(UNIT_MASK_CONTROLLABLE_GUARDIAN)) && IsControlledByPlayer())))
{
// Check UNIT_STATE_MELEE_ATTACKING or UNIT_STATE_CHASE (without UNIT_STATE_FOLLOW in this case) so pets can reach far away
// targets without stopping half way there and running off.
@@ -10793,7 +10793,7 @@ void Unit::SetMinion(Minion* minion, bool apply)
}
}
if (minion->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN))
if (minion->HasUnitTypeMask(UNIT_MASK_CONTROLLABLE_GUARDIAN))
{
AddGuidValue(UNIT_FIELD_SUMMON, minion->GetGUID());
}
@@ -10888,7 +10888,7 @@ void Unit::SetMinion(Minion* minion, bool apply)
}
ASSERT((*itr)->IsCreature());
if (!(*itr)->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN))
if (!(*itr)->HasUnitTypeMask(UNIT_MASK_CONTROLLABLE_GUARDIAN))
continue;
if (AddGuidValue(UNIT_FIELD_SUMMON, (*itr)->GetGUID()))
@@ -11703,7 +11703,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
int32 DoneTotal = 0;
float DoneTotalMod = TotalMod ? TotalMod : SpellPctDamageModsDone(victim, spellProto, damagetype);
// Config : RATE_CREATURE_X_SPELLDAMAGE & Do Not Modify Pet/Guardian/Mind Controled Damage
// Config : RATE_CREATURE_X_SPELLDAMAGE & Do Not Modify Pet/Guardian/Mind Controlled Damage
if (IsCreature() && (!ToCreature()->IsPet() || !ToCreature()->IsGuardian() || !ToCreature()->IsControlledByPlayer()))
DoneTotalMod *= ToCreature()->GetSpellDamageMod(ToCreature()->GetCreatureTemplate()->rank);
@@ -13520,7 +13520,7 @@ float Unit::GetPPMProcChance(uint32 WeaponSpeed, float PPM, SpellInfo const* spe
if (Player* modOwner = GetSpellModOwner())
modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_PROC_PER_MINUTE, PPM);
return std::floor((WeaponSpeed * PPM) / 600.0f); // result is chance in percents (probability = Speed_in_sec * (PPM / 60))
return (WeaponSpeed * PPM) / 600.0f; // result is chance in percents (probability = Speed_in_sec * (PPM / 60))
}
void Unit::Mount(uint32 mount, uint32 VehicleId, uint32 creatureEntry)
@@ -14698,7 +14698,7 @@ bool Unit::CanHaveThreatList(bool skipAliveCheck) const
return false;
// summons can not have a threat list, unless they are controlled by a creature
if (HasUnitTypeMask(UNIT_MASK_MINION | UNIT_MASK_GUARDIAN | UNIT_MASK_CONTROLABLE_GUARDIAN) && ((Pet*)this)->GetOwnerGUID().IsPlayer())
if (HasUnitTypeMask(UNIT_MASK_MINION | UNIT_MASK_GUARDIAN | UNIT_MASK_CONTROLLABLE_GUARDIAN) && ((Pet*)this)->GetOwnerGUID().IsPlayer())
return false;
return true;
@@ -14854,7 +14854,7 @@ Unit* Creature::SelectVictim()
// it in combat but attacker not make any damage and not enter to aggro radius to have record in threat list
// Note: creature does not have targeted movement generator but has attacker in this case
for (AttackerSet::const_iterator itr = m_attackers.begin(); itr != m_attackers.end(); ++itr)
if ((*itr) && CanCreatureAttack(*itr) && !(*itr)->IsPlayer() && !(*itr)->ToCreature()->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN))
if ((*itr) && CanCreatureAttack(*itr) && !(*itr)->IsPlayer() && !(*itr)->ToCreature()->HasUnitTypeMask(UNIT_MASK_CONTROLLABLE_GUARDIAN))
return nullptr;
if (GetVehicle())
@@ -17572,16 +17572,30 @@ bool Unit::IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, WeaponAttackTyp
// If PPM exist calculate chance from PPM
if (spellProcEvent && spellProcEvent->ppmRate != 0)
{
uint32 attackSpeed = 0;
Unit* attacker = nullptr;
if (!isVictim)
{
uint32 WeaponSpeed = GetAttackTime(attType);
chance = GetPPMProcChance(WeaponSpeed, spellProcEvent->ppmRate, spellProto);
}
attacker = this;
else if (victim)
attacker = victim;
if (attacker)
{
uint32 WeaponSpeed = victim->GetAttackTime(attType);
chance = victim->GetPPMProcChance(WeaponSpeed, spellProcEvent->ppmRate, spellProto);
if (!procSpell || procSpell->DmgClass == SPELL_DAMAGE_CLASS_MELEE || procSpell->IsRangedWeaponSpell())
{
attackSpeed = attacker->GetAttackTime(attType);
}
else //spells user their casttime for ppm calculations
{
if (procSpell->CastTimeEntry)
attackSpeed = procSpell->CastTimeEntry->CastTime;
//instants and fast spells use 1.5s castspeed
if (attackSpeed < 1500)
attackSpeed = 1500;
}
}
chance = GetPPMProcChance(attackSpeed, spellProcEvent->ppmRate, spellProto);
}
// Custom chances
@@ -20011,11 +20025,11 @@ void Unit::StopAttackingInvalidTarget()
attacker->ToPlayer()->SendAttackSwingCancelAttack();
}
for (Unit* controled : attacker->m_Controlled)
for (Unit* controlled : attacker->m_Controlled)
{
if (controled->GetVictim() == this && !controled->IsValidAttackTarget(this))
if (controlled->GetVictim() == this && !controlled->IsValidAttackTarget(this))
{
controled->AttackStop();
controlled->AttackStop();
}
}
+1 -1
View File
@@ -743,7 +743,7 @@ public:
// Unit type methods
[[nodiscard]] bool IsSummon() const { return m_unitTypeMask & UNIT_MASK_SUMMON; }
[[nodiscard]] bool IsGuardian() const { return m_unitTypeMask & UNIT_MASK_GUARDIAN; }
[[nodiscard]] bool IsControllableGuardian() const { return m_unitTypeMask & UNIT_MASK_CONTROLABLE_GUARDIAN; }
[[nodiscard]] bool IsControllableGuardian() const { return m_unitTypeMask & UNIT_MASK_CONTROLLABLE_GUARDIAN; }
[[nodiscard]] bool IsPet() const { return m_unitTypeMask & UNIT_MASK_PET; }
[[nodiscard]] bool IsHunterPet() const { return m_unitTypeMask & UNIT_MASK_HUNTER_PET; }
[[nodiscard]] bool IsTotem() const { return m_unitTypeMask & UNIT_MASK_TOTEM; }
+1 -1
View File
@@ -161,7 +161,7 @@ enum UnitTypeMask
UNIT_MASK_VEHICLE = 0x00000020,
UNIT_MASK_PUPPET = 0x00000040,
UNIT_MASK_HUNTER_PET = 0x00000080,
UNIT_MASK_CONTROLABLE_GUARDIAN = 0x00000100,
UNIT_MASK_CONTROLLABLE_GUARDIAN = 0x00000100,
UNIT_MASK_ACCESSORY = 0x00000200
};
+1 -1
View File
@@ -1473,7 +1473,7 @@ void Guild::HandleInviteMember(WorldSession* session, std::string const& name)
if (pInvitee->GetSocial()->HasIgnore(player->GetGUID()))
return;
uint32 memberLimit = sConfigMgr->GetOption<uint32>("Guild.MemberLimit", 0);
uint32 memberLimit = sWorld->getIntConfig(CONFIG_GUILD_MEMBER_LIMIT);
if (memberLimit > 0 && player->GetGuild()->GetMemberCount() >= memberLimit)
{
ChatHandler(player->GetSession()).PSendSysMessage("Your guild has reached the maximum amount of members ({}). You cannot send another invite until the guild member count is lower.", memberLimit);
+1 -1
View File
@@ -701,7 +701,7 @@ public:
void HandleSetEmblem(EmblemInfo const& emblemInfo);
void HandleSetLeader(WorldSession* session, std::string_view name);
void HandleSetBankTabInfo(WorldSession* session, uint8 tabId, std::string_view name, std::string_view icon);
void HandleSetMemberNote(WorldSession* session, std::string_view name, std::string_view note, bool officer);
void HandleSetMemberNote(WorldSession* session, std::string_view name, std::string_view note, bool isPublic);
void HandleSetRankInfo(WorldSession* session, uint8 rankId, std::string_view name, uint32 rights, uint32 moneyPerDay, std::array<GuildBankRightsAndSlots, GUILD_BANK_MAX_TABS> const& rightsAndSlots);
void HandleSetRankInfo(uint8 rankId, uint32 rights = 0, std::string_view name = "", uint32 moneyPerDay = 0);
void HandleBuyBankTab(WorldSession* session, uint8 tabId);
+1 -1
View File
@@ -300,7 +300,7 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe
//dismissing a summoned pet is like killing them (this prevents returning a soulshard...)
pet->setDeathState(DeathState::Corpse);
}
else if (pet->HasUnitTypeMask(UNIT_MASK_MINION | UNIT_MASK_SUMMON | UNIT_MASK_GUARDIAN | UNIT_MASK_CONTROLABLE_GUARDIAN))
else if (pet->HasUnitTypeMask(UNIT_MASK_MINION | UNIT_MASK_SUMMON | UNIT_MASK_GUARDIAN | UNIT_MASK_CONTROLLABLE_GUARDIAN))
{
pet->ToTempSummon()->UnSummon();
}
@@ -58,11 +58,7 @@ uint32 ScriptMgr::DealDamage(Unit* AttackerUnit, Unit* pVictim, uint32 damage, D
for (auto const& [scriptID, script] : ScriptRegistry<UnitScript>::ScriptPointerList)
{
auto const& dmg = script->DealDamage(AttackerUnit, pVictim, damage, damagetype);
if (dmg != damage)
{
return damage;
}
damage = script->DealDamage(AttackerUnit, pVictim, damage, damagetype);
}
return damage;
@@ -6852,8 +6852,10 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
heal = uint32(caster->SpellHealingBonusTaken(caster, GetSpellInfo(), heal, DOT, GetBase()->GetStackAmount()));
HealInfo healInfo(caster, caster, heal, GetSpellInfo(), GetSpellInfo()->GetSchoolMask());
int32 gain = caster->HealBySpell(healInfo);
caster->getHostileRefMgr().threatAssist(caster, gain * 0.5f, GetSpellInfo());
float threat = float(caster->HealBySpell(healInfo)) * 0.5f;
if (caster->IsClass(CLASS_PALADIN))
threat *= 0.5f;
caster->getHostileRefMgr().threatAssist(caster, threat, GetSpellInfo());
}
void AuraEffect::HandlePeriodicHealthFunnelAuraTick(Unit* target, Unit* caster) const
@@ -7000,7 +7002,13 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
target->SendPeriodicAuraLog(&pInfo);
if (caster)
target->getHostileRefMgr().threatAssist(caster, float(gain) * 0.5f, GetSpellInfo());
{
float threat = float(gain) * 0.5f;
if (caster->IsClass(CLASS_PALADIN))
threat *= 0.5f;
target->getHostileRefMgr().threatAssist(caster, threat, GetSpellInfo());
}
bool haveCastItem = GetBase()->GetCastItemGUID();
+6 -2
View File
@@ -2808,7 +2808,11 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
}
int32 gain = caster->HealBySpell(healInfo, crit);
unitTarget->getHostileRefMgr().threatAssist(caster, float(gain) * 0.5f, m_spellInfo);
float threat = float(gain) * 0.5f;
if (caster->IsClass(CLASS_PALADIN))
threat *= 0.5f;
unitTarget->getHostileRefMgr().threatAssist(caster, threat, m_spellInfo);
m_healing = gain;
// Xinef: if heal acutally healed something, add no overheal flag
@@ -3451,7 +3455,7 @@ bool Spell::UpdateChanneledTargetList()
continue;
}
// Xinef: Update Orientation server side (non players wont sent appropriate packets)
else if (m_spellInfo->HasAttribute(SPELL_ATTR1_TRACK_TARGET_IN_CHANNEL))
else if (!m_caster->IsPlayer() && m_spellInfo->HasAttribute(SPELL_ATTR1_TRACK_TARGET_IN_CHANNEL))
m_caster->UpdateOrientation(m_caster->GetAngle(unit));
}
}
+18 -33
View File
@@ -3428,11 +3428,6 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
spell_bonus += int32(0.08f * m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
spell_bonus += int32(0.13f * m_caster->SpellBaseDamageBonusDone(m_spellInfo->GetSchoolMask()));
break;
case 42463: // Seals of the Pure for Seal of Vengeance/Corruption
case 53739:
if (AuraEffect const* sealsOfPure = m_caster->GetAuraEffect(SPELL_AURA_ADD_PCT_MODIFIER, SPELLFAMILY_PALADIN, 25, 0))
AddPct(totalDamagePercentMod, sealsOfPure->GetAmount());
break;
case 53385: // Divine Storm deals normalized damage
normalized = true;
break;
@@ -3532,9 +3527,7 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
// Blood-Caked Strike - Blood-Caked Blade
if (m_spellInfo->SpellIconID == 1736)
{
int32 weaponDamage = m_caster->CalculateDamage(m_attackType, false, true);
ApplyPct(weaponDamage, std::min(uint32(3), unitTarget->GetDiseasesByCaster(m_caster->GetGUID())) * 12.5f);
spell_bonus = weaponDamage;
AddPct(totalDamagePercentMod, unitTarget->GetDiseasesByCaster(m_caster->GetGUID()) * 50.0f);
break;
}
// Heart Strike
@@ -3581,30 +3574,26 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
}
}
// apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
if (fixed_bonus || spell_bonus)
bool const isPhysical = (m_spellSchoolMask & SPELL_SCHOOL_MASK_NORMAL);
if (isPhysical && (fixed_bonus || spell_bonus))
{
UnitMods unitMod;
switch (m_attackType)
{
default:
case BASE_ATTACK:
unitMod = UNIT_MOD_DAMAGE_MAINHAND;
break;
case OFF_ATTACK:
unitMod = UNIT_MOD_DAMAGE_OFFHAND;
break;
case RANGED_ATTACK:
unitMod = UNIT_MOD_DAMAGE_RANGED;
break;
}
if (m_spellSchoolMask & SPELL_SCHOOL_MASK_NORMAL)
{
float weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
fixed_bonus = int32(fixed_bonus * weapon_total_pct);
spell_bonus = int32(spell_bonus * weapon_total_pct);
default:
case BASE_ATTACK:
unitMod = UNIT_MOD_DAMAGE_MAINHAND;
break;
case OFF_ATTACK:
unitMod = UNIT_MOD_DAMAGE_OFFHAND;
break;
case RANGED_ATTACK:
unitMod = UNIT_MOD_DAMAGE_RANGED;
break;
}
float weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
fixed_bonus = int32(fixed_bonus * weapon_total_pct);
spell_bonus = int32(spell_bonus * weapon_total_pct);
}
int32 weaponDamage = 0;
@@ -3612,15 +3601,11 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
if (m_caster->GetEntry() == 27893)
{
if (Unit* owner = m_caster->GetOwner())
weaponDamage = owner->CalculateDamage(m_attackType, normalized, true);
}
else if (m_spellInfo->Id == 5019) // Wands
{
weaponDamage = m_caster->CalculateDamage(m_attackType, true, false);
weaponDamage = owner->CalculateDamage(m_attackType, normalized, isPhysical);
}
else
{
weaponDamage = m_caster->CalculateDamage(m_attackType, normalized, true);
weaponDamage = m_caster->CalculateDamage(m_attackType, normalized, isPhysical);
}
// Sequence is important
+1 -11
View File
@@ -2126,6 +2126,7 @@ AuraStateType SpellInfo::LoadAuraState() const
case 20656:
case 25602:
case 32129:
case 49163: // Perpetual Instability (Element 115)
return AURA_STATE_FAERIE_FIRE;
default:
break;
@@ -2644,14 +2645,6 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const
switch (Effects[effIndex].Effect)
{
case SPELL_EFFECT_DUMMY:
// some explicitly required dummy effect sets
switch (Id)
{
default:
break;
}
break;
// always positive effects (check before target checks that provided non-positive result in some case for positive effects)
case SPELL_EFFECT_HEAL:
case SPELL_EFFECT_LEARN_SPELL:
@@ -2661,10 +2654,8 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const
return true;
case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY:
return false;
case SPELL_EFFECT_GAMEOBJECT_DAMAGE:
return false;
case SPELL_EFFECT_SCHOOL_DAMAGE:
{
bool only = true;
@@ -2688,7 +2679,6 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const
return false;
break;
}
// non-positive aura use
case SPELL_EFFECT_APPLY_AURA:
case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND:
@@ -230,15 +230,6 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->MaxAffectedTargets = 4;
});
ApplySpellFix({
20424, // Seal of Command
42463, // Seal of Vengeance
53739 // Seal of Corruption
}, [](SpellInfo* spellInfo)
{
spellInfo->AttributesEx3 |= SPELL_ATTR3_IGNORE_CASTER_MODIFIERS;
});
// Spitfire Totem
ApplySpellFix({ 38296 }, [](SpellInfo* spellInfo)
{
@@ -3580,7 +3571,7 @@ void SpellMgr::LoadSpellInfoCorrections()
// That's Abominable
ApplySpellFix({ 59565 }, [](SpellInfo* spellInfo)
{
spellInfo->Effects[EFFECT_0].MiscValueB = 1721; // controlable guardian
spellInfo->Effects[EFFECT_0].MiscValueB = 1721; // controllable guardian
});
// Investigate the Blue Recluse (1920)
@@ -5140,6 +5131,12 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->ChannelInterruptFlags &= ~AURA_INTERRUPT_FLAG_TURNING;
});
// The Green Tower
ApplySpellFix({ 18097 }, [](SpellInfo* spellInfo)
{
spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(21); // -1
});
for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
{
SpellInfo* spellInfo = mSpellInfoMap[i];
+1
View File
@@ -412,6 +412,7 @@ enum WorldIntConfigs
CONFIG_GUILD_BANK_TAB_COST_3,
CONFIG_GUILD_BANK_TAB_COST_4,
CONFIG_GUILD_BANK_TAB_COST_5,
CONFIG_GUILD_MEMBER_LIMIT,
CONFIG_GM_LEVEL_CHANNEL_MODERATION,
CONFIG_TOGGLE_XP_COST,
CONFIG_NPC_EVADE_IF_NOT_REACHABLE,
+2
View File
@@ -845,6 +845,8 @@ void World::LoadConfigSettings(bool reload)
_int_configs[CONFIG_GUILD_BANK_TAB_COST_4] = sConfigMgr->GetOption<int32>("Guild.BankTabCost4", 25000000);
_int_configs[CONFIG_GUILD_BANK_TAB_COST_5] = sConfigMgr->GetOption<int32>("Guild.BankTabCost5", 50000000);
_int_configs[CONFIG_GUILD_MEMBER_LIMIT] = sConfigMgr->GetOption<uint32>("Guild.MemberLimit", 0);
_bool_configs[CONFIG_DETECT_POS_COLLISION] = sConfigMgr->GetOption<bool>("DetectPosCollision", true);
_bool_configs[CONFIG_RESTRICTED_LFG_CHANNEL] = sConfigMgr->GetOption<bool>("Channel.RestrictedLfg", true);