aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/AI/CreatureAI.cpp5
-rw-r--r--src/server/game/AI/CreatureAI.h1
-rw-r--r--src/server/game/AI/CreatureAIImpl.h68
-rw-r--r--src/server/game/Accounts/AccountMgr.cpp2
-rw-r--r--src/server/game/Entities/Player/Player.cpp31
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp218
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp1
-rw-r--r--src/server/game/Handlers/TicketHandler.cpp12
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h2
-rw-r--r--src/server/game/Server/WorldSession.cpp16
-rw-r--r--src/server/game/Server/WorldSession.h2
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp7
-rw-r--r--src/server/game/Spells/Spell.cpp2
-rw-r--r--src/server/game/Spells/SpellMgr.cpp3
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp2
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h2
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp35
-rw-r--r--src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp5
18 files changed, 215 insertions, 199 deletions
diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp
index dd8b42deb9f..ac9de00cd10 100644
--- a/src/server/game/AI/CreatureAI.cpp
+++ b/src/server/game/AI/CreatureAI.cpp
@@ -43,6 +43,11 @@ void CreatureAI::Talk(uint8 id, WorldObject const* whisperTarget /*= NULL*/)
sCreatureTextMgr->SendChat(me, id, whisperTarget);
}
+void CreatureAI::TalkToMap(uint8 id, WorldObject const* whisperTarget /*= NULL*/)
+{
+ sCreatureTextMgr->SendChat(me, id, whisperTarget, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_MAP);
+}
+
void CreatureAI::DoZoneInCombat(Creature* creature /*= NULL*/, float maxRangeToNearestTarget /* = 50.0f*/)
{
if (!creature)
diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h
index 6357ac33f1e..209995d359d 100644
--- a/src/server/game/AI/CreatureAI.h
+++ b/src/server/game/AI/CreatureAI.h
@@ -79,6 +79,7 @@ class CreatureAI : public UnitAI
public:
void Talk(uint8 id, WorldObject const* whisperTarget = NULL);
+ void TalkToMap(uint8 id, WorldObject const* whisperTarget = NULL);
explicit CreatureAI(Creature* creature) : UnitAI(creature), me(creature), m_MoveInLineOfSight_locked(false) { }
virtual ~CreatureAI() { }
diff --git a/src/server/game/AI/CreatureAIImpl.h b/src/server/game/AI/CreatureAIImpl.h
index 7447e290ba9..378d3ca18ab 100644
--- a/src/server/game/AI/CreatureAIImpl.h
+++ b/src/server/game/AI/CreatureAIImpl.h
@@ -327,7 +327,7 @@ class EventMap
typedef std::multimap<uint32, uint32> EventStore;
public:
- EventMap() : _time(0), _phase(0) { }
+ EventMap() : _time(0), _phase(0), _lastEvent(0) { }
/**
* @name Reset
@@ -447,27 +447,22 @@ class EventMap
/**
* @name RepeatEvent
- * @brief Cancels the closest event and reschedules it.
+ * @brief Repeats the mostly recently executed event.
* @param time Time until the event occurs.
*/
- void RepeatEvent(uint32 time)
+ void Repeat(uint32 time)
{
- if (Empty())
- return;
-
- uint32 eventId = _eventMap.begin()->second;
- _eventMap.erase(_eventMap.begin());
- ScheduleEvent(eventId, time);
+ _eventMap.insert(EventStore::value_type(_time + time, _lastEvent));
}
/**
- * @name PopEvent
- * @brief Remove the first event in the map.
+ * @name RepeatEvent
+ * @brief Repeats the mostly recently executed event.
+ * @param time Time until the event occurs. Equivalent to Repeat(urand(minTime, maxTime).
*/
- void PopEvent()
+ void Repeat(uint32 minTime, uint32 maxTime)
{
- if (!Empty())
- _eventMap.erase(_eventMap.begin());
+ Repeat(urand(minTime, maxTime));
}
/**
@@ -488,6 +483,7 @@ class EventMap
else
{
uint32 eventId = (itr->second & 0x0000FFFF);
+ _lastEvent = itr->second; // include phase/group
_eventMap.erase(itr);
return eventId;
}
@@ -497,28 +493,6 @@ class EventMap
}
/**
- * @name GetEvent
- * @brief Returns the next event to execute.
- * @return Id of the event to execute.
- */
- uint32 GetEvent()
- {
- while (!Empty())
- {
- EventStore::iterator itr = _eventMap.begin();
-
- if (itr->first > _time)
- return 0;
- else if (_phase && (itr->second & 0xFF000000) && !(itr->second & (_phase << 24)))
- _eventMap.erase(itr);
- else
- return (itr->second & 0x0000FFFF);
- }
-
- return 0;
- }
-
- /**
* @name DelayEvents
* @brief Delays all events in the map. If delay is greater than or equal internal timer, delay will be 0.
* @param delay Amount of delay.
@@ -631,6 +605,21 @@ class EventMap
return phase <= 8 && (!phase || _phase & (1 << (phase - 1)));
}
+ /**
+ * @name GetTimeUntilEvent
+ * @brief Returns time in milliseconds until next event.
+ * @param Id of the event.
+ * @return Time of next event.
+ */
+ uint32 GetTimeUntilEvent(uint32 eventId) const
+ {
+ for (EventStore::const_iterator itr = _eventMap.begin(); itr != _eventMap.end(); ++itr)
+ if (eventId == (itr->second & 0x0000FFFF))
+ return itr->first - _time;
+
+ return std::numeric_limits<uint32>::max();
+ }
+
private:
/**
* @name _time
@@ -662,6 +651,13 @@ class EventMap
* details.
*/
EventStore _eventMap;
+
+
+ /**
+ * @name _lastEvent
+ * @brief Stores information on the most recently executed event
+ */
+ uint32 _lastEvent;
};
enum AITarget
diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp
index d8f61a22314..773e169e5c2 100644
--- a/src/server/game/Accounts/AccountMgr.cpp
+++ b/src/server/game/Accounts/AccountMgr.cpp
@@ -517,7 +517,7 @@ bool AccountMgr::HasPermission(uint32 accountId, uint32 permissionId, uint32 rea
return false;
}
- rbac::RBACData rbac(accountId, "", realmId);
+ rbac::RBACData rbac(accountId, "", realmId, GetSecurity(accountId));
rbac.LoadFromDB();
bool hasPermission = rbac.HasPermission(permissionId);
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 5ab77a6bb34..ac6b6a97fbb 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -708,7 +708,7 @@ Player::Player(WorldSession* session): Unit(true), phaseMgr(this)
m_areaUpdateId = 0;
m_team = 0;
-
+
m_needsZoneUpdate = false;
m_nextSave = sWorld->getIntConfig(CONFIG_INTERVAL_SAVE);
@@ -5930,31 +5930,30 @@ float Player::OCTRegenMPPerSpirit()
void Player::ApplyRatingMod(CombatRating cr, int32 value, bool apply)
{
- m_baseRatingValue[cr] +=(apply ? value : -value);
+ m_baseRatingValue[cr] += (apply ? value : -value);
// explicit affected values
+ float const mult = GetRatingMultiplier(cr);
+ float const oldVal = m_baseRatingValue[cr] * mult;
+ float const newVal = m_baseRatingValue[cr] * mult;
+
switch (cr)
{
case CR_HASTE_MELEE:
- {
- float RatingChange = value * GetRatingMultiplier(cr);
- ApplyAttackTimePercentMod(BASE_ATTACK, RatingChange, apply);
- ApplyAttackTimePercentMod(OFF_ATTACK, RatingChange, apply);
- if (getClass() == CLASS_DEATH_KNIGHT)
- UpdateAllRunesRegen();
+ ApplyAttackTimePercentMod(BASE_ATTACK, oldVal, false);
+ ApplyAttackTimePercentMod(OFF_ATTACK, oldVal, false);
+ ApplyAttackTimePercentMod(BASE_ATTACK, newVal, true);
+ ApplyAttackTimePercentMod(OFF_ATTACK, newVal, true);
break;
- }
case CR_HASTE_RANGED:
- {
- ApplyAttackTimePercentMod(RANGED_ATTACK, value * GetRatingMultiplier(cr), apply);
+ ApplyAttackTimePercentMod(RANGED_ATTACK, oldVal, false);
+ ApplyAttackTimePercentMod(RANGED_ATTACK, newVal, true);
break;
- }
case CR_HASTE_SPELL:
- {
- ApplyCastTimePercentMod(value * GetRatingMultiplier(cr), apply);
+ ApplyCastTimePercentMod(oldVal, false);
+ ApplyCastTimePercentMod(newVal, true);
break;
- }
- default:
+ default: // shut up compiler warnings
break;
}
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 038db352edd..30c20b08cac 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -957,79 +957,85 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
SpellSchoolMask damageSchoolMask = SpellSchoolMask(damageInfo->schoolMask);
- if (IsDamageReducedByArmor(damageSchoolMask, spellInfo))
- damage = CalcArmorReducedDamage(victim, damage, spellInfo, attackType);
-
- bool blocked = false;
- // Per-school calc
- switch (spellInfo->DmgClass)
+ // Spells with SPELL_ATTR4_FIXED_DAMAGE ignore resilience because their damage is based off another spell's damage.
+ if (!(spellInfo->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE))
{
- // Melee and Ranged Spells
- case SPELL_DAMAGE_CLASS_RANGED:
- case SPELL_DAMAGE_CLASS_MELEE:
+ if (IsDamageReducedByArmor(damageSchoolMask, spellInfo))
+ damage = CalcArmorReducedDamage(victim, damage, spellInfo, attackType);
+
+ bool blocked = false;
+ // Per-school calc
+ switch (spellInfo->DmgClass)
{
- // Physical Damage
- if (damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL)
+ // Melee and Ranged Spells
+ case SPELL_DAMAGE_CLASS_RANGED:
+ case SPELL_DAMAGE_CLASS_MELEE:
{
- // Get blocked status
- blocked = isSpellBlocked(victim, spellInfo, attackType);
- }
+ // Physical Damage
+ if (damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL)
+ {
+ // Get blocked status
+ blocked = isSpellBlocked(victim, spellInfo, attackType);
+ }
- if (crit)
- {
- damageInfo->HitInfo |= SPELL_HIT_TYPE_CRIT;
-
- // Calculate crit bonus
- uint32 crit_bonus = damage;
- // Apply crit_damage bonus for melee spells
- if (Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CRIT_DAMAGE_BONUS, crit_bonus);
- damage += crit_bonus;
-
- // Apply SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE or SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE
- float critPctDamageMod = 0.0f;
- if (attackType == RANGED_ATTACK)
- critPctDamageMod += victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE);
- else
- critPctDamageMod += victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE);
+ if (crit)
+ {
+ damageInfo->HitInfo |= SPELL_HIT_TYPE_CRIT;
+
+ // Calculate crit bonus
+ uint32 crit_bonus = damage;
+ // Apply crit_damage bonus for melee spells
+ if (Player* modOwner = GetSpellModOwner())
+ modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CRIT_DAMAGE_BONUS, crit_bonus);
+ damage += crit_bonus;
+
+ // Apply SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE or SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE
+ float critPctDamageMod = 0.0f;
+ if (attackType == RANGED_ATTACK)
+ critPctDamageMod += victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE);
+ else
+ critPctDamageMod += victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE);
- // Increase crit damage from SPELL_AURA_MOD_CRIT_DAMAGE_BONUS
- critPctDamageMod += (GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS, spellInfo->GetSchoolMask()) - 1.0f) * 100;
+ // Increase crit damage from SPELL_AURA_MOD_CRIT_DAMAGE_BONUS
+ critPctDamageMod += (GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS, spellInfo->GetSchoolMask()) - 1.0f) * 100;
- if (critPctDamageMod != 0)
- AddPct(damage, critPctDamageMod);
- }
+ if (critPctDamageMod != 0)
+ AddPct(damage, critPctDamageMod);
+ }
- // Spell weapon based damage CAN BE crit & blocked at same time
- if (blocked)
- {
- // double blocked amount if block is critical
- uint32 value = victim->GetBlockPercent();
- if (victim->isBlockCritical())
- value *= 2; // double blocked percent
- damageInfo->blocked = CalculatePct(damage, value);
- damage -= damageInfo->blocked;
- }
+ // Spell weapon based damage CAN BE crit & blocked at same time
+ if (blocked)
+ {
+ // double blocked amount if block is critical
+ uint32 value = victim->GetBlockPercent();
+ if (victim->isBlockCritical())
+ value *= 2; // double blocked percent
+ damageInfo->blocked = CalculatePct(damage, value);
+ damage -= damageInfo->blocked;
+ }
- ApplyResilience(victim, &damage);
- break;
- }
- // Magical Attacks
- case SPELL_DAMAGE_CLASS_NONE:
- case SPELL_DAMAGE_CLASS_MAGIC:
- {
- // If crit add critical bonus
- if (crit)
- {
- damageInfo->HitInfo |= SPELL_HIT_TYPE_CRIT;
- damage = SpellCriticalDamageBonus(spellInfo, damage, victim);
+ ApplyResilience(victim, &damage);
+ break;
}
+ // Magical Attacks
+ case SPELL_DAMAGE_CLASS_NONE:
+ case SPELL_DAMAGE_CLASS_MAGIC:
+ {
+ // If crit add critical bonus
+ if (crit)
+ {
+ damageInfo->HitInfo |= SPELL_HIT_TYPE_CRIT;
+ damage = SpellCriticalDamageBonus(spellInfo, damage, victim);
- ApplyResilience(victim, &damage);
- break;
+ }
+
+ ApplyResilience(victim, &damage);
+ break;
+
+ }
+ default:
+ break;
}
- default:
- break;
}
// Script Hook For CalculateSpellDamageTaken -- Allow scripts to change the Damage post class mitigation calculations
@@ -8409,11 +8415,6 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
if (spellProto->AttributesEx3 & SPELL_ATTR3_NO_DONE_BONUS)
return pdamage;
- // small exception for Deep Wounds, can't find any general rule
- // should ignore ALL damage mods, they already calculated in trigger spell
- if (spellProto->Id == 12721) // Deep Wounds
- return pdamage;
-
// For totems get damage bonus from owner
if (GetTypeId() == TYPEID_UNIT && ToCreature()->IsTotem())
if (Unit* owner = GetOwner())
@@ -8429,7 +8430,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
DoneTotalMod *= ToCreature()->GetSpellDamageMod(ToCreature()->GetCreatureTemplate()->rank);
// Some spells don't benefit from pct done mods
- if (!(spellProto->AttributesEx6 & SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS) && !spellProto->IsRankOf(sSpellMgr->GetSpellInfo(12162)))
+ if (!(spellProto->AttributesEx6 & SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS))
{
AuraEffectList const& mModDamagePercentDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
for (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i)
@@ -8680,18 +8681,15 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui
float TakenTotalMod = 1.0f;
float TakenTotalCasterMod = 0.0f;
- // get all auras from caster that allow the spell to ignore resistance (sanctified wrath)
- AuraEffectList const& IgnoreResistAuras = caster->GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST);
- for (AuraEffectList::const_iterator i = IgnoreResistAuras.begin(); i != IgnoreResistAuras.end(); ++i)
+ // Mod damage from spell mechanic
+ if (uint32 mechanicMask = spellProto->GetAllEffectsMechanicMask())
{
- if ((*i)->GetMiscValue() & spellProto->GetSchoolMask())
- TakenTotalCasterMod += (float((*i)->GetAmount()));
+ AuraEffectList const& mDamageDoneMechanic = GetAuraEffectsByType(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT);
+ for (AuraEffectList::const_iterator i = mDamageDoneMechanic.begin(); i != mDamageDoneMechanic.end(); ++i)
+ if (mechanicMask & uint32(1 << ((*i)->GetMiscValue())))
+ AddPct(TakenTotalMod, (*i)->GetAmount());
}
- // from positive and negative SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN
- // multiplicative bonus, for example Dispersion + Shadowform (0.10*0.85=0.085)
- TakenTotalMod *= GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, spellProto->GetSchoolMask());
-
//.. taken pct: dummy auras
AuraEffectList const& mDummyAuras = GetAuraEffectsByType(SPELL_AURA_DUMMY);
for (AuraEffectList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
@@ -8709,45 +8707,47 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui
break;
}
}
-
- // From caster spells
- AuraEffectList const& mOwnerTaken = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_FROM_CASTER);
- for (AuraEffectList::const_iterator i = mOwnerTaken.begin(); i != mOwnerTaken.end(); ++i)
- if ((*i)->GetCasterGUID() == caster->GetGUID() && (*i)->IsAffectingSpell(spellProto))
- AddPct(TakenTotalMod, (*i)->GetAmount());
-
- // Mod damage from spell mechanic
- if (uint32 mechanicMask = spellProto->GetAllEffectsMechanicMask())
+ // Spells with SPELL_ATTR4_FIXED_DAMAGE should only benefit from mechanic damage mod auras.
+ if (!(spellProto->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE))
{
- AuraEffectList const& mDamageDoneMechanic = GetAuraEffectsByType(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT);
- for (AuraEffectList::const_iterator i = mDamageDoneMechanic.begin(); i != mDamageDoneMechanic.end(); ++i)
- if (mechanicMask & uint32(1<<((*i)->GetMiscValue())))
- AddPct(TakenTotalMod, (*i)->GetAmount());
- }
+ // get all auras from caster that allow the spell to ignore resistance (sanctified wrath)
+ AuraEffectList const& IgnoreResistAuras = caster->GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST);
+ for (AuraEffectList::const_iterator i = IgnoreResistAuras.begin(); i != IgnoreResistAuras.end(); ++i)
+ {
+ if ((*i)->GetMiscValue() & spellProto->GetSchoolMask())
+ TakenTotalCasterMod += (float((*i)->GetAmount()));
+ }
- int32 TakenAdvertisedBenefit = SpellBaseDamageBonusTaken(spellProto->GetSchoolMask());
+ // From caster spells
+ AuraEffectList const& mOwnerTaken = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_FROM_CASTER);
+ for (AuraEffectList::const_iterator i = mOwnerTaken.begin(); i != mOwnerTaken.end(); ++i)
+ if ((*i)->GetCasterGUID() == caster->GetGUID() && (*i)->IsAffectingSpell(spellProto))
+ AddPct(TakenTotalMod, (*i)->GetAmount());
- // Check for table values
- float coeff = 0;
- SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id);
- if (bonus)
- coeff = (damagetype == DOT) ? bonus->dot_damage : bonus->direct_damage;
+ int32 TakenAdvertisedBenefit = SpellBaseDamageBonusTaken(spellProto->GetSchoolMask());
- // Default calculation
- if (TakenAdvertisedBenefit)
- {
- if (!bonus || coeff < 0)
- coeff = CalculateDefaultCoefficient(spellProto, damagetype) * int32(stack);
+ // Check for table values
+ float coeff = 0;
+ SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id);
+ if (bonus)
+ coeff = (damagetype == DOT) ? bonus->dot_damage : bonus->direct_damage;
- float factorMod = CalculateLevelPenalty(spellProto) * stack;
- // level penalty still applied on Taken bonus - is it blizzlike?
- if (Player* modOwner = GetSpellModOwner())
+ // Default calculation
+ if (TakenAdvertisedBenefit)
{
- coeff *= 100.0f;
- modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_BONUS_MULTIPLIER, coeff);
- coeff /= 100.0f;
+ if (!bonus || coeff < 0)
+ coeff = CalculateDefaultCoefficient(spellProto, damagetype) * int32(stack);
+
+ float factorMod = CalculateLevelPenalty(spellProto) * stack;
+ // level penalty still applied on Taken bonus - is it blizzlike?
+ if (Player* modOwner = GetSpellModOwner())
+ {
+ coeff *= 100.0f;
+ modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_BONUS_MULTIPLIER, coeff);
+ coeff /= 100.0f;
+ }
+ TakenTotal += int32(TakenAdvertisedBenefit * coeff * factorMod);
}
- TakenTotal+= int32(TakenAdvertisedBenefit * coeff * factorMod);
}
float tmpDamage = 0.0f;
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 737197878fb..5345113d106 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -788,6 +788,7 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPacket& recvData)
if (PlayerLoading() || GetPlayer() != NULL)
{
TC_LOG_ERROR("network", "Player tries to login again, AccountId = %d", GetAccountId());
+ KickPlayer();
return;
}
diff --git a/src/server/game/Handlers/TicketHandler.cpp b/src/server/game/Handlers/TicketHandler.cpp
index 4ea4d835ae9..53cde5e8e5a 100644
--- a/src/server/game/Handlers/TicketHandler.cpp
+++ b/src/server/game/Handlers/TicketHandler.cpp
@@ -187,6 +187,8 @@ void WorldSession::HandleGMSurveySubmit(WorldPacket& recvData)
uint32 mainSurvey; // GMSurveyCurrentSurvey.dbc, column 1 (all 9) ref to GMSurveySurveys.dbc
recvData >> mainSurvey;
+ std::unordered_set<uint32> surveyIds;
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
// sub_survey1, r1, comment1, sub_survey2, r2, comment2, sub_survey3, r3, comment3, sub_survey4, r4, comment4, sub_survey5, r5, comment5, sub_survey6, r6, comment6, sub_survey7, r7, comment7, sub_survey8, r8, comment8, sub_survey9, r9, comment9, sub_survey10, r10, comment10,
for (uint8 i = 0; i < 15; i++)
{
@@ -200,12 +202,16 @@ void WorldSession::HandleGMSurveySubmit(WorldPacket& recvData)
std::string comment; // comment ("Usage: GMSurveyAnswerSubmit(question, rank, comment)")
recvData >> comment;
+ // make sure the same sub survey is not added to DB twice
+ if (!surveyIds.insert(subSurveyId).second)
+ continue;
+
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GM_SUBSURVEY);
stmt->setUInt32(0, nextSurveyID);
stmt->setUInt32(1, subSurveyId);
stmt->setUInt32(2, rank);
stmt->setString(3, comment);
- CharacterDatabase.Execute(stmt);
+ trans->Append(stmt);
}
std::string comment; // just a guess
@@ -217,7 +223,9 @@ void WorldSession::HandleGMSurveySubmit(WorldPacket& recvData)
stmt->setUInt32(2, mainSurvey);
stmt->setString(3, comment);
- CharacterDatabase.Execute(stmt);
+ trans->Append(stmt);
+
+ CharacterDatabase.CommitTransaction(trans);
}
void WorldSession::HandleReportLag(WorldPacket& recvData)
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index 8a17536c9cc..cbcf509747b 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -436,7 +436,7 @@ enum SpellAttr4
SPELL_ATTR4_UNK5 = 0x00000020, // 5
SPELL_ATTR4_NOT_STEALABLE = 0x00000040, // 6 although such auras might be dispellable, they cannot be stolen
SPELL_ATTR4_TRIGGERED = 0x00000080, // 7 spells forced to be triggered
- SPELL_ATTR4_FIXED_DAMAGE = 0x00000100, // 8 ignores taken percent damage mods?
+ SPELL_ATTR4_FIXED_DAMAGE = 0x00000100, // 8 Ignores resilience and any (except mechanic related) damage or % damage taken auras on target.
SPELL_ATTR4_TRIGGER_ACTIVATE = 0x00000200, // 9 initially disabled / trigger activate from event (Execute, Riposte, Deep Freeze end other)
SPELL_ATTR4_SPELL_VS_EXTEND_COST = 0x00000400, // 10 Rogue Shiv have this flag
SPELL_ATTR4_UNK11 = 0x00000800, // 11
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index 7c7c2613592..e40470c5cdb 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -124,7 +124,9 @@ WorldSession::WorldSession(uint32 id, WorldSocket* sock, AccountTypes sec, uint8
_filterAddonMessages(false),
recruiterId(recruiter),
isRecruiter(isARecruiter),
- _RBACData(NULL)
+ _RBACData(NULL),
+ expireTime(60000), // 1 min after socket loss, session is deleted
+ forceExit(false)
{
memset(m_Tutorials, 0, sizeof(m_Tutorials));
@@ -449,8 +451,12 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
///- Cleanup socket pointer if need
if (m_Socket && m_Socket->IsClosed())
{
- m_Socket->RemoveReference();
- m_Socket = NULL;
+ expireTime -= expireTime > diff ? diff : expireTime;
+ if (expireTime < diff || forceExit)
+ {
+ m_Socket->RemoveReference();
+ m_Socket = NULL;
+ }
}
if (!m_Socket)
@@ -476,7 +482,6 @@ void WorldSession::LogoutPlayer(bool save)
DoLootRelease(lguid);
///- If the player just died before logging out, make him appear as a ghost
- //FIXME: logout must be delayed in case lost connection with client in time of combat
if (_player->GetDeathTimer())
{
_player->getHostileRefManager().deleteReferences();
@@ -606,7 +611,10 @@ void WorldSession::LogoutPlayer(bool save)
void WorldSession::KickPlayer()
{
if (m_Socket)
+ {
m_Socket->CloseSocket();
+ forceExit = true;
+ }
}
void WorldSession::SendNotification(const char *format, ...)
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index a34c614f7e1..ae32f48f622 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -1081,6 +1081,8 @@ class WorldSession
ACE_Based::LockedQueue<WorldPacket*, ACE_Thread_Mutex> _recvQueue;
z_stream_s* _compressionStream;
rbac::RBACData* _RBACData;
+ uint32 expireTime;
+ bool forceExit;
WorldSession(WorldSession const& right) = delete;
WorldSession& operator=(WorldSession const& right) = delete;
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 61a1ea40120..efc24792a7c 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -5833,7 +5833,9 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
damage = caster->SpellCriticalDamageBonus(m_spellInfo, damage, target);
int32 dmg = damage;
- caster->ApplyResilience(target, &dmg);
+
+ if (!(GetSpellInfo()->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE))
+ caster->ApplyResilience(target, &dmg);
damage = dmg;
caster->CalcAbsorbResist(target, GetSpellInfo()->GetSchoolMask(), DOT, damage, &absorb, &resist, GetSpellInfo());
@@ -5900,7 +5902,8 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
}
int32 dmg = damage;
- caster->ApplyResilience(target, &dmg);
+ if (!(GetSpellInfo()->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE))
+ caster->ApplyResilience(target, &dmg);
damage = dmg;
caster->CalcAbsorbResist(target, GetSpellInfo()->GetSchoolMask(), DOT, damage, &absorb, &resist, m_spellInfo);
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 661c1ec340a..b64ee454e2e 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -569,7 +569,7 @@ m_caster((info->AttributesEx6 & SPELL_ATTR6_CAST_BY_CHARMER && caster->GetCharme
m_spellState = SPELL_STATE_NULL;
_triggeredCastFlags = triggerFlags;
if (info->AttributesEx4 & SPELL_ATTR4_TRIGGERED)
- _triggeredCastFlags = TRIGGERED_FULL_MASK;
+ _triggeredCastFlags = TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_EQUIPPED_ITEM_REQUIREMENT);
m_CastItem = NULL;
m_castItemGUID = 0;
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 33a2bd2d41a..218f7b5a37d 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -3244,6 +3244,9 @@ void SpellMgr::LoadSpellInfoCorrections()
case 63675: // Improved Devouring Plague
spellInfo->AttributesEx3 |= SPELL_ATTR3_NO_DONE_BONUS;
break;
+ case 12721: // Deep Wounds shouldnt ignore resillience or damage taken auras because its damage is not based off a spell.
+ spellInfo->AttributesEx4 = 0;
+ break;
case 8145: // Tremor Totem (instant pulse)
case 6474: // Earthbind Totem (instant pulse)
spellInfo->AttributesEx5 |= SPELL_ATTR5_START_PERIODIC_AT_APPLY;
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp
index dbd844aa34c..503166e0b12 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp
@@ -187,7 +187,7 @@ class instance_culling_of_stratholme : public InstanceMapScript
// Summon Chromie and global whisper
if (Creature* chromie = instance->SummonCreature(NPC_CHROMIE_2, ChromieSummonPos))
if (!instance->GetPlayers().isEmpty())
- sCreatureTextMgr->SendChat(chromie, SAY_CRATES_COMPLETED, NULL, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_MAP);
+ chromie->AI()->TalkToMap(SAY_CRATES_COMPLETED);
}
DoUpdateWorldState(WORLDSTATE_CRATES_REVEALED, _crateCount);
break;
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h
index 562105c0866..8a62453d7c1 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h
@@ -40,7 +40,7 @@ enum SpellIds
enum MiscData
{
- DESPAWN_TIME = 300000,
+ DESPAWN_TIME = 1200000,
DISPLAYID_DESTROYED_FLOOR = 9060
};
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp
index 8b3ac64fb89..c5c70cf3957 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp
@@ -368,38 +368,33 @@ public:
if (Phase == 1)
{
- while (uint32 eventId = events.GetEvent())
+ while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_WASTE:
DoSummon(NPC_WASTE, Pos[RAND(0, 3, 6, 9)]);
- events.RepeatEvent(urand(2000, 5000));
+ events.Repeat(2000, 5000);
break;
case EVENT_ABOMIN:
if (nAbomination < 8)
{
DoSummon(NPC_ABOMINATION, Pos[RAND(1, 4, 7, 10)]);
nAbomination++;
- events.RepeatEvent(20000);
+ events.Repeat(20000);
}
- else
- events.PopEvent();
break;
case EVENT_WEAVER:
if (nWeaver < 8)
{
DoSummon(NPC_WEAVER, Pos[RAND(0, 3, 6, 9)]);
nWeaver++;
- events.RepeatEvent(25000);
+ events.Repeat(25000);
}
- else
- events.PopEvent();
break;
case EVENT_TRIGGER:
if (GameObject* trigger = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_KELTHUZAD_TRIGGER)))
trigger->SetPhaseMask(2, true);
- events.PopEvent();
break;
case EVENT_PHASE:
events.Reset();
@@ -419,7 +414,6 @@ public:
Phase = 2;
break;
default:
- events.PopEvent();
break;
}
}
@@ -461,17 +455,17 @@ public:
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
- if (uint32 eventId = events.GetEvent())
+ if (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_BOLT:
DoCastVictim(SPELL_FROST_BOLT);
- events.RepeatEvent(urand(5000, 10000));
+ events.Repeat(5000, 10000);
break;
case EVENT_NOVA:
DoCastAOE(SPELL_FROST_BOLT_AOE);
- events.RepeatEvent(urand(15000, 30000));
+ events.Repeat(15000, 30000);
break;
case EVENT_CHAIN:
{
@@ -490,7 +484,7 @@ public:
}
if (!chained.empty())
Talk(SAY_CHAIN);
- events.RepeatEvent(urand(100000, 180000));
+ events.Repeat(100000, 180000);
break;
}
case EVENT_CHAINED_SPELL:
@@ -565,10 +559,8 @@ public:
++itr;
}
- if (chained.empty())
- events.PopEvent();
- else
- events.RepeatEvent(5000);
+ if (!chained.empty())
+ events.Repeat(5000);
break;
}
@@ -596,23 +588,22 @@ public:
Talk(SAY_SPECIAL);
}
- events.RepeatEvent(urand(20000, 50000));
+ events.Repeat(20000, 50000);
break;
}
case EVENT_FISSURE:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
DoCast(target, SPELL_SHADOW_FISURE);
- events.RepeatEvent(urand(10000, 45000));
+ events.Repeat(10000, 45000);
break;
case EVENT_BLAST:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, RAID_MODE(1, 0), 0, true))
DoCast(target, SPELL_FROST_BLAST);
if (rand()%2)
Talk(SAY_FROST_BLAST);
- events.RepeatEvent(urand(30000, 90000));
+ events.Repeat(30000, 90000);
break;
default:
- events.PopEvent();
break;
}
}
diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
index 169d942e536..5291e4baed3 100644
--- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
+++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
@@ -664,7 +664,7 @@ public:
Talk(SAY_BUFF_SPARK);
}
else if (spell->Id == SPELL_MALYGOS_BERSERK)
- sCreatureTextMgr->SendChat(me, EMOTE_HIT_BERSERKER_TIMER, NULL, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_MAP);
+ TalkToMap(EMOTE_HIT_BERSERKER_TIMER);
}
void MoveInLineOfSight(Unit* who) override
@@ -1113,8 +1113,7 @@ public:
npc_power_sparkAI(Creature* creature) : ScriptedAI(creature)
{
_instance = creature->GetInstanceScript();
- // Talk range was not enough for this encounter
- sCreatureTextMgr->SendChat(me, EMOTE_POWER_SPARK_SUMMONED, NULL, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_MAP);
+ TalkToMap(EMOTE_POWER_SPARK_SUMMONED);
MoveToMalygos();
}