aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/server/game/AI/CoreAI/PetAI.cpp61
-rwxr-xr-xsrc/server/game/AI/CoreAI/PetAI.h2
-rwxr-xr-xsrc/server/game/AI/CreatureAI.h6
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp18
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.h17
-rwxr-xr-xsrc/server/game/Chat/Commands/Level3.cpp6
-rwxr-xr-xsrc/server/game/Conditions/ConditionMgr.cpp16
-rwxr-xr-xsrc/server/game/Conditions/ConditionMgr.h2
-rwxr-xr-xsrc/server/game/DataStores/DBCStructure.h1
-rwxr-xr-xsrc/server/game/Entities/Creature/Creature.h1
-rwxr-xr-xsrc/server/game/Entities/Player/Player.cpp10
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.cpp47
-rwxr-xr-xsrc/server/game/Handlers/LFGHandler.cpp4
-rwxr-xr-xsrc/server/game/Handlers/PetHandler.cpp2
-rwxr-xr-xsrc/server/game/Handlers/TicketHandler.cpp2
-rwxr-xr-xsrc/server/game/Miscellaneous/SharedDefines.h2
-rwxr-xr-xsrc/server/game/Scripting/ScriptMgr.cpp16
-rwxr-xr-xsrc/server/game/Server/Protocol/Opcodes.h2
-rwxr-xr-xsrc/server/game/Spells/Auras/SpellAuraEffects.cpp36
-rwxr-xr-xsrc/server/game/Spells/Spell.cpp54
-rwxr-xr-xsrc/server/game/Spells/Spell.h16
-rw-r--r--src/server/game/Spells/SpellInfo.cpp4
-rwxr-xr-xsrc/server/game/Spells/SpellMgr.cpp14
-rwxr-xr-xsrc/server/game/Tickets/TicketMgr.cpp5
-rw-r--r--src/server/scripts/Commands/cs_tele.cpp4
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/boss_high_inquisitor_fairbanks.cpp8
-rw-r--r--src/server/scripts/EasternKingdoms/undercity.cpp95
-rw-r--r--src/server/scripts/Kalimdor/silithus.cpp28
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp5
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp59
-rw-r--r--src/server/scripts/Spells/spell_mage.cpp6
-rw-r--r--src/server/scripts/Spells/spell_quest.cpp4
-rw-r--r--src/server/scripts/Spells/spell_warrior.cpp46
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.cpp2
-rwxr-xr-xsrc/server/shared/Utilities/Util.h2
35 files changed, 449 insertions, 154 deletions
diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp
index 295768f9d3e..bcec8d273b9 100755
--- a/src/server/game/AI/CoreAI/PetAI.cpp
+++ b/src/server/game/AI/CoreAI/PetAI.cpp
@@ -109,17 +109,25 @@ void PetAI::UpdateAI(const uint32 diff)
}
else if (owner && me->GetCharmInfo()) //no victim
{
- Unit* nextTarget = SelectNextTarget();
+ // Only aggressive pets do target search every update.
+ // Defensive pets do target search only in these cases:
+ // * Owner attacks something - handled by OwnerAttacked()
+ // * Owner receives damage - handled by OwnerDamagedBy()
+ // * Pet is in combat and current target dies - handled by KilledUnit()
+ if (me->HasReactState(REACT_AGGRESSIVE))
+ {
+ Unit* nextTarget = SelectNextTarget();
- if (me->HasReactState(REACT_PASSIVE))
- _stopAttack();
- else if (nextTarget)
- AttackStart(nextTarget);
+ if (nextTarget)
+ AttackStart(nextTarget);
+ else
+ HandleReturnMovement();
+ }
else
HandleReturnMovement();
}
else if (owner && !me->HasUnitState(UNIT_STATE_FOLLOW)) // no charm info and no victim
- me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle());
+ HandleReturnMovement();
if (!me->GetCharmInfo())
return;
@@ -302,6 +310,47 @@ void PetAI::AttackStart(Unit* target)
DoAttack(target, true);
}
+void PetAI::OwnerDamagedBy(Unit* attacker)
+{
+ // Called when owner takes damage. Allows defensive pets to know
+ // that their owner might need help
+
+ if (!attacker)
+ return;
+
+ // Passive pets don't do anything
+ if (me->HasReactState(REACT_PASSIVE))
+ return;
+
+ // Prevent pet from disengaging from current target
+ if (me->getVictim() && me->getVictim()->isAlive())
+ return;
+
+ // Continue to evaluate and attack if necessary
+ AttackStart(attacker);
+}
+
+void PetAI::OwnerAttacked(Unit* target)
+{
+ // Called when owner attacks something. Allows defensive pets to know
+ // that they need to assist
+
+ // Target might be NULL if called from spell with invalid cast targets
+ if (!target)
+ return;
+
+ // Passive pets don't do anything
+ if (me->HasReactState(REACT_PASSIVE))
+ return;
+
+ // Prevent pet from disengaging from current target
+ if (me->getVictim() && me->getVictim()->isAlive())
+ return;
+
+ // Continue to evaluate and attack if necessary
+ AttackStart(target);
+}
+
Unit* PetAI::SelectNextTarget()
{
// Provides next target selection after current target death
diff --git a/src/server/game/AI/CoreAI/PetAI.h b/src/server/game/AI/CoreAI/PetAI.h
index 730ab12a3ca..ed3e2305556 100755
--- a/src/server/game/AI/CoreAI/PetAI.h
+++ b/src/server/game/AI/CoreAI/PetAI.h
@@ -40,6 +40,8 @@ class PetAI : public CreatureAI
void KilledUnit(Unit* /*victim*/);
void AttackStart(Unit* target);
void MovementInform(uint32 moveType, uint32 data);
+ void OwnerDamagedBy(Unit* attacker);
+ void OwnerAttacked(Unit* target);
private:
bool _isVisible(Unit*) const;
diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h
index 423b00291e7..94ac452b9f3 100755
--- a/src/server/game/AI/CreatureAI.h
+++ b/src/server/game/AI/CreatureAI.h
@@ -138,6 +138,12 @@ class CreatureAI : public UnitAI
// Called at text emote receive from player
virtual void ReceiveEmote(Player* /*player*/, uint32 /*emoteId*/) {}
+ // Called when owner takes damage
+ virtual void OwnerDamagedBy(Unit* /*attacker*/) {}
+
+ // Called when owner attacks something
+ virtual void OwnerAttacked(Unit* /*target*/) {}
+
/// == Triggered Actions Requested ==================
// Called when creature attack expected (if creature can and no have current victim)
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index b2c4fd29868..209eb38e13a 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -108,8 +108,11 @@ void SmartScript::OnReset()
ResetBaseObject();
for (SmartAIEventList::iterator i = mEvents.begin(); i != mEvents.end(); ++i)
{
- InitTimer((*i));
- (*i).runOnce = false;
+ if (!((*i).event.event_flags & SMART_EVENT_FLAG_DONT_RESET))
+ {
+ InitTimer((*i));
+ (*i).runOnce = false;
+ }
}
ProcessEventsFor(SMART_EVENT_RESET);
mLastInvoker = 0;
@@ -1862,19 +1865,26 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (!targets)
break;
+ ObjectList* storedTargets = GetTargetList(e.action.sendTargetToTarget.id);
+ if (!storedTargets)
+ {
+ delete targets;
+ return;
+ }
+
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
{
if (IsCreature(*itr))
{
if (SmartAI* ai = CAST_AI(SmartAI, (*itr)->ToCreature()->AI()))
- ai->GetScript()->StoreTargetList(GetTargetList(e.action.sendTargetToTarget.id), e.action.sendTargetToTarget.id);
+ ai->GetScript()->StoreTargetList(new ObjectList(*storedTargets), e.action.sendTargetToTarget.id); // store a copy of target list
else
sLog->outErrorDb("SmartScript: Action target for SMART_ACTION_SEND_TARGET_TO_TARGET is not using SmartAI, skipping");
}
else if (IsGameObject(*itr))
{
if (SmartGameObjectAI* ai = CAST_AI(SmartGameObjectAI, (*itr)->ToGameObject()->AI()))
- ai->GetScript()->StoreTargetList(GetTargetList(e.action.sendTargetToTarget.id), e.action.sendTargetToTarget.id);
+ ai->GetScript()->StoreTargetList(new ObjectList(*storedTargets), e.action.sendTargetToTarget.id); // store a copy of target list
else
sLog->outErrorDb("SmartScript: Action target for SMART_ACTION_SEND_TARGET_TO_TARGET is not using SmartGameObjectAI, skipping");
}
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
index e2cd75ee62c..8d3686a265d 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
@@ -1165,14 +1165,15 @@ const uint32 SmartAIEventMask[SMART_EVENT_END][2] =
enum SmartEventFlags
{
- SMART_EVENT_FLAG_NOT_REPEATABLE = 0x01, //Event can not repeat
- SMART_EVENT_FLAG_DIFFICULTY_0 = 0x02, //Event only occurs in instance difficulty 0
- SMART_EVENT_FLAG_DIFFICULTY_1 = 0x04, //Event only occurs in instance difficulty 1
- SMART_EVENT_FLAG_DIFFICULTY_2 = 0x08, //Event only occurs in instance difficulty 2
- SMART_EVENT_FLAG_DIFFICULTY_3 = 0x10, //Event only occurs in instance difficulty 3
- SMART_EVENT_FLAG_RESERVED_5 = 0x20,
- SMART_EVENT_FLAG_RESERVED_6 = 0x40,
- SMART_EVENT_FLAG_DEBUG_ONLY = 0x80, //Event only occurs in debug build
+ SMART_EVENT_FLAG_NOT_REPEATABLE = 0x001, //Event can not repeat
+ SMART_EVENT_FLAG_DIFFICULTY_0 = 0x002, //Event only occurs in instance difficulty 0
+ SMART_EVENT_FLAG_DIFFICULTY_1 = 0x004, //Event only occurs in instance difficulty 1
+ SMART_EVENT_FLAG_DIFFICULTY_2 = 0x008, //Event only occurs in instance difficulty 2
+ SMART_EVENT_FLAG_DIFFICULTY_3 = 0x010, //Event only occurs in instance difficulty 3
+ SMART_EVENT_FLAG_RESERVED_5 = 0x020,
+ SMART_EVENT_FLAG_RESERVED_6 = 0x040,
+ SMART_EVENT_FLAG_DEBUG_ONLY = 0x080, //Event only occurs in debug build
+ SMART_EVENT_FLAG_DONT_RESET = 0x100, //Event will not reset in SmartScript::OnReset()
SMART_EVENT_FLAG_DIFFICULTY_ALL = (SMART_EVENT_FLAG_DIFFICULTY_0|SMART_EVENT_FLAG_DIFFICULTY_1|SMART_EVENT_FLAG_DIFFICULTY_2|SMART_EVENT_FLAG_DIFFICULTY_3)
};
diff --git a/src/server/game/Chat/Commands/Level3.cpp b/src/server/game/Chat/Commands/Level3.cpp
index d3417705867..54a9edefc03 100755
--- a/src/server/game/Chat/Commands/Level3.cpp
+++ b/src/server/game/Chat/Commands/Level3.cpp
@@ -441,7 +441,7 @@ bool ChatHandler::HandleListItemCommand(const char *args)
Field* fields = result->Fetch();
uint32 item_guid = fields[0].GetUInt32();
uint32 item_bag = fields[1].GetUInt32();
- uint32 item_slot = fields[2].GetUInt32();
+ uint8 item_slot = fields[2].GetUInt8();
uint32 owner_guid = fields[3].GetUInt32();
uint32 owner_acc = fields[4].GetUInt32();
std::string owner_name = fields[5].GetString();
@@ -638,7 +638,7 @@ bool ChatHandler::HandleListObjectCommand(const char *args)
uint32 obj_count = 0;
result = WorldDatabase.PQuery("SELECT COUNT(guid) FROM gameobject WHERE id='%u'", go_id);
if (result)
- obj_count = (*result)[0].GetUInt32();
+ obj_count = (*result)[0].GetUInt64();
if (m_session)
{
@@ -710,7 +710,7 @@ bool ChatHandler::HandleListCreatureCommand(const char *args)
uint32 cr_count = 0;
result = WorldDatabase.PQuery("SELECT COUNT(guid) FROM creature WHERE id='%u'", cr_id);
if (result)
- cr_count = (*result)[0].GetUInt32();
+ cr_count = (*result)[0].GetUInt64();
if (m_session)
{
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index 3fcabea4c74..1fb0a78605b 100755
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -422,6 +422,9 @@ uint32 Condition::GetSearcherTypeMaskForCondition()
case CONDITION_PHASEMASK:
mask |= GRID_MAP_TYPE_MASK_ALL;
break;
+ case CONDITION_TITLE:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
default:
ASSERT(false && "Condition::GetSearcherTypeMaskForCondition - missing condition handling!");
break;
@@ -1826,9 +1829,16 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond)
sLog->outErrorDb("Phasemask condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
- case CONDITION_UNUSED_18:
- sLog->outErrorDb("Found ConditionTypeOrReference = CONDITION_UNUSED_18 in `conditions` table - ignoring");
- return false;
+ case CONDITION_TITLE:
+ {
+ CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(cond->ConditionValue1);
+ if (!titleEntry)
+ {
+ sLog->outErrorDb("Title condition has non existing title in value1 (%u), skipped", cond->ConditionValue1);
+ return false;
+ }
+ break;
+ }
case CONDITION_UNUSED_19:
sLog->outErrorDb("Found ConditionTypeOrReference = CONDITION_UNUSED_19 in `conditions` table - ignoring");
return false;
diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h
index 2df79eab088..130a23a0cb0 100755
--- a/src/server/game/Conditions/ConditionMgr.h
+++ b/src/server/game/Conditions/ConditionMgr.h
@@ -48,7 +48,7 @@ enum ConditionTypes
CONDITION_CLASS = 15, // class 0 0 true if player's class is equal to class
CONDITION_RACE = 16, // race 0 0 true if player's race is equal to race
CONDITION_ACHIEVEMENT = 17, // achievement_id 0 0 true if achievement is complete
- CONDITION_UNUSED_18 = 18, //
+ CONDITION_TITLE = 18, // title id 0 0 true if player has title
CONDITION_UNUSED_19 = 19, //
CONDITION_UNUSED_20 = 20, //
CONDITION_UNUSED_21 = 21, //
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index 38e8c957681..15792fd57da 100755
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -1292,6 +1292,7 @@ struct MapEntry
bool IsBattleground() const { return map_type == MAP_BATTLEGROUND; }
bool IsBattleArena() const { return map_type == MAP_ARENA; }
bool IsBattlegroundOrArena() const { return map_type == MAP_BATTLEGROUND || map_type == MAP_ARENA; }
+ bool IsWorldMap() const { return map_type == MAP_COMMON; }
bool GetEntrancePos(int32 &mapid, float &x, float &y) const
{
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index f100d391698..4b5b07fd8a5 100755
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -266,7 +266,6 @@ struct CreatureData
// `creature_addon` table
struct CreatureAddon
{
- uint32 guidOrEntry;
uint32 path_id;
uint32 mount;
uint32 bytes1;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index ca1795bb04a..100afd73b27 100755
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -2936,7 +2936,7 @@ void Player::GiveXP(uint32 xp, Unit* victim, float group_rate)
if (xp < 1)
return;
- if (!isAlive())
+ if (!isAlive() && !GetBattlegroundId())
return;
if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN))
@@ -8196,6 +8196,10 @@ void Player::_ApplyWeaponDependentAuraMods(Item* item, WeaponAttackType attackTy
void Player::_ApplyWeaponDependentAuraCritMod(Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply)
{
+ // don't apply mod if item is broken or cannot be used
+ if (item->IsBroken() || !CanUseAttackType(attackType))
+ return;
+
// generic not weapon specific case processes in aura code
if (aura->GetSpellInfo()->EquippedItemClass == -1)
return;
@@ -8209,13 +8213,13 @@ void Player::_ApplyWeaponDependentAuraCritMod(Item* item, WeaponAttackType attac
default: return;
}
- if (!item->IsBroken()&&item->IsFitToSpellRequirements(aura->GetSpellInfo()))
+ if (item->IsFitToSpellRequirements(aura->GetSpellInfo()))
HandleBaseModValue(mod, FLAT_MOD, float (aura->GetAmount()), apply);
}
void Player::_ApplyWeaponDependentAuraDamageMod(Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply)
{
- //don't apply mod if item is broken
+ // don't apply mod if item is broken or cannot be used
if (item->IsBroken() || !CanUseAttackType(attackType))
return;
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index d71f8e8dfc3..cf14bb02ed9 100755
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -572,6 +572,15 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
if (IsAIEnabled)
GetAI()->DamageDealt(victim, damage, damagetype);
+ // Signal to pets that their owner was attacked
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ {
+ Pet* pet = victim->ToPlayer()->GetPet();
+
+ if (pet && pet->isAlive())
+ pet->AI()->OwnerDamagedBy(this);
+ }
+
if (damagetype != NODAMAGE)
{
// interrupting auras with AURA_INTERRUPT_FLAG_DAMAGE before checking !damage (absorbed damage breaks that type of auras)
@@ -8663,6 +8672,26 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
}
break;
}
+ case SPELLFAMILY_ROGUE:
+ {
+ switch (auraSpellInfo->Id)
+ {
+ // Rogue T10 2P bonus, should only proc on caster
+ case 70805:
+ {
+ if (victim != this)
+ return false;
+ break;
+ }
+ // Rogue T10 4P bonus, should proc on victim
+ case 70803:
+ {
+ target = victim;
+ break;
+ }
+ }
+ break;
+ }
default:
break;
}
@@ -8827,7 +8856,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
}
// Blade Barrier
- if (auraSpellInfo->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && auraSpellInfo->SpellIconID == 85)
+ if (auraSpellInfo->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && auraSpellInfo->SpellIconID == 85 && procSpell)
{
Player* player = ToPlayer();
if (!player || player->getClass() != CLASS_DEATH_KNIGHT)
@@ -9515,6 +9544,16 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
if (meleeAttack)
SendMeleeAttackStart(victim);
+ // Let the pet know we've started attacking someting. Handles melee attacks only
+ // Spells such as auto-shot and others handled in WorldSession::HandleCastSpellOpcode
+ if (this->GetTypeId() == TYPEID_PLAYER)
+ {
+ Pet* playerPet = this->ToPlayer()->GetPet();
+
+ if (playerPet && playerPet->isAlive())
+ playerPet->AI()->OwnerAttacked(victim);
+ }
+
return true;
}
@@ -12487,6 +12526,12 @@ bool Unit::IsAlwaysVisibleFor(WorldObject const* seer) const
if (seer->GetGUID() == guid)
return true;
+ if (Player const* seerPlayer = seer->ToPlayer())
+ if (Unit* owner = GetOwner())
+ if (Player* ownerPlayer = owner->ToPlayer())
+ if (ownerPlayer->IsGroupVisibleFor(seerPlayer))
+ return true;
+
return false;
}
diff --git a/src/server/game/Handlers/LFGHandler.cpp b/src/server/game/Handlers/LFGHandler.cpp
index aea7499aaa9..aa6d208ad3a 100755
--- a/src/server/game/Handlers/LFGHandler.cpp
+++ b/src/server/game/Handlers/LFGHandler.cpp
@@ -525,9 +525,9 @@ void WorldSession::SendLfgBootPlayer(const LfgPlayerBoot* pBoot)
++agreeNum;
}
}
- sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_BOOT_PLAYER [" UI64FMTD "] inProgress: %u - didVote: %u - agree: %u - victim: [" UI64FMTD "] votes: %u - agrees: %u - left: %u - needed: %u - reason %s",
+ sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_BOOT_PROPOSAL_UPDATE [" UI64FMTD "] inProgress: %u - didVote: %u - agree: %u - victim: [" UI64FMTD "] votes: %u - agrees: %u - left: %u - needed: %u - reason %s",
guid, uint8(pBoot->inProgress), uint8(playerVote != LFG_ANSWER_PENDING), uint8(playerVote == LFG_ANSWER_AGREE), pBoot->victim, votesNum, agreeNum, secsleft, pBoot->votedNeeded, pBoot->reason.c_str());
- WorldPacket data(SMSG_LFG_BOOT_PLAYER, 1 + 1 + 1 + 8 + 4 + 4 + 4 + 4 + pBoot->reason.length());
+ WorldPacket data(SMSG_LFG_BOOT_PROPOSAL_UPDATE, 1 + 1 + 1 + 8 + 4 + 4 + 4 + 4 + pBoot->reason.length());
data << uint8(pBoot->inProgress); // Vote in progress
data << uint8(playerVote != LFG_ANSWER_PENDING); // Did Vote
data << uint8(playerVote == LFG_ANSWER_AGREE); // Agree
diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp
index 1fa6d9fc0ed..e54bee96b8b 100755
--- a/src/server/game/Handlers/PetHandler.cpp
+++ b/src/server/game/Handlers/PetHandler.cpp
@@ -153,8 +153,6 @@ void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint16 spellid
switch (spellid)
{
case COMMAND_STAY: //flat=1792 //STAY
- pet->AttackStop();
- pet->InterruptNonMeleeSpells(false);
pet->StopMoving();
pet->GetMotionMaster()->Clear(false);
pet->GetMotionMaster()->MoveIdle();
diff --git a/src/server/game/Handlers/TicketHandler.cpp b/src/server/game/Handlers/TicketHandler.cpp
index 9c4eba67426..d6675188f6e 100755
--- a/src/server/game/Handlers/TicketHandler.cpp
+++ b/src/server/game/Handlers/TicketHandler.cpp
@@ -176,6 +176,8 @@ void WorldSession::HandleReportLag(WorldPacket& recv_data)
stmt->setFloat (3, x);
stmt->setFloat (4, y);
stmt->setFloat (5, z);
+ stmt->setUInt32(6, GetLatency());
+ stmt->setUInt32(7, time(NULL));
CharacterDatabase.Execute(stmt);
}
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index bca896df38f..df524b1409e 100755
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -411,7 +411,7 @@ enum SpellAttr3
enum SpellAttr4
{
SPELL_ATTR4_UNK0 = 0x00000001, // 0
- SPELL_ATTR4_PROC_ONLY_ON_DUMMY = 0x00000002, // 1 proc only on SPELL_EFFECT_DUMMY?
+ SPELL_ATTR4_PROC_ONLY_ON_CASTER = 0x00000002, // 1 proc only on effects with TARGET_UNIT_CASTER?
SPELL_ATTR4_UNK2 = 0x00000004, // 2
SPELL_ATTR4_UNK3 = 0x00000008, // 3
SPELL_ATTR4_UNK4 = 0x00000010, // 4 This will no longer cause guards to attack on use??
diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp
index 012910210a5..aac615180c8 100755
--- a/src/server/game/Scripting/ScriptMgr.cpp
+++ b/src/server/game/Scripting/ScriptMgr.cpp
@@ -582,7 +582,7 @@ void ScriptMgr::OnCreateMap(Map* map)
{
ASSERT(map);
- SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsContinent);
+ SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsWorldMap);
itr->second->OnCreate(map);
SCR_MAP_END;
@@ -599,7 +599,7 @@ void ScriptMgr::OnDestroyMap(Map* map)
{
ASSERT(map);
- SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsContinent);
+ SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsWorldMap);
itr->second->OnDestroy(map);
SCR_MAP_END;
@@ -617,7 +617,7 @@ void ScriptMgr::OnLoadGridMap(Map* map, GridMap* gmap, uint32 gx, uint32 gy)
ASSERT(map);
ASSERT(gmap);
- SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsContinent);
+ SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsWorldMap);
itr->second->OnLoadGridMap(map, gmap, gx, gy);
SCR_MAP_END;
@@ -635,7 +635,7 @@ void ScriptMgr::OnUnloadGridMap(Map* map, GridMap* gmap, uint32 gx, uint32 gy)
ASSERT(map);
ASSERT(gmap);
- SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsContinent);
+ SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsWorldMap);
itr->second->OnUnloadGridMap(map, gmap, gx, gy);
SCR_MAP_END;
@@ -653,7 +653,7 @@ void ScriptMgr::OnPlayerEnterMap(Map* map, Player* player)
ASSERT(map);
ASSERT(player);
- SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsContinent);
+ SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsWorldMap);
itr->second->OnPlayerEnter(map, player);
SCR_MAP_END;
@@ -671,7 +671,7 @@ void ScriptMgr::OnPlayerLeaveMap(Map* map, Player* player)
ASSERT(map);
ASSERT(player);
- SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsContinent);
+ SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsWorldMap);
itr->second->OnPlayerLeave(map, player);
SCR_MAP_END;
@@ -688,7 +688,7 @@ void ScriptMgr::OnMapUpdate(Map* map, uint32 diff)
{
ASSERT(map);
- SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsContinent);
+ SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsWorldMap);
itr->second->OnUpdate(map, diff);
SCR_MAP_END;
@@ -1415,7 +1415,7 @@ FormulaScript::FormulaScript(const char* name)
WorldMapScript::WorldMapScript(const char* name, uint32 mapId)
: ScriptObject(name), MapScript<Map>(mapId)
{
- if (GetEntry() && !GetEntry()->IsContinent())
+ if (GetEntry() && !GetEntry()->IsWorldMap())
sLog->outError("WorldMapScript for map %u is invalid.", mapId);
ScriptRegistry<WorldMapScript>::AddScript(this);
diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h
index ab6ba7e7796..3c77ced6741 100755
--- a/src/server/game/Server/Protocol/Opcodes.h
+++ b/src/server/game/Server/Protocol/Opcodes.h
@@ -911,7 +911,7 @@ enum Opcodes
CMSG_LFG_SET_ROLES = 0x36A,
CMSG_LFG_SET_NEEDS = 0x36B,
CMSG_LFG_SET_BOOT_VOTE = 0x36C,
- SMSG_LFG_BOOT_PLAYER = 0x36D, // uint8, uint8, uint8, uint64, uint32, uint32, uint32, uint32
+ SMSG_LFG_BOOT_PROPOSAL_UPDATE = 0x36D, // uint8, uint8, uint8, uint64, uint32, uint32, uint32, uint32
CMSG_LFD_PLAYER_LOCK_INFO_REQUEST = 0x36E,
SMSG_LFG_PLAYER_INFO = 0x36F, // uint8, for (uint8) { uint32, uint8, uint32, uint32, uint32, uint32, uint8, for (uint8) {uint32, uint32, uint32}}, uint32, for (uint32) {uint32, uint32}
CMSG_LFG_TELEPORT = 0x370,
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 6383c7ff3ef..6fa6270c444 100755
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -4768,11 +4768,6 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->RemoveAmmo(); // not use ammo and not allow use
break;
- case 49028:
- if (caster)
- if (AuraEffect* aurEff = caster->GetAuraEffect(63330, 0)) // glyph of Dancing Rune Weapon
- GetBase()->SetDuration(GetBase()->GetDuration() + aurEff->GetAmount());
- break;
case 52916: // Honor Among Thieves
if (target->GetTypeId() == TYPEID_PLAYER)
if (Unit* spellTarget = ObjectAccessor::GetUnit(*target, target->ToPlayer()->GetComboTarget()))
@@ -5623,21 +5618,6 @@ void AuraEffect::HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const
caster->CastCustomSpell(66153, SPELLVALUE_MAX_TARGETS, urand(1, 6), target, true);
break;
}
- case 54798: // FLAMING Arrow Triggered Effect
- {
- if (!caster || !target || !target->ToCreature() || !caster->GetVehicle() || target->HasAura(54683))
- break;
-
- target->CastSpell(target, 54683, true);
-
- // Credit Frostworgs
- if (target->GetEntry() == 29358)
- caster->CastSpell(caster, 54896, true);
- // Credit Frost Giants
- else if (target->GetEntry() == 29351)
- caster->CastSpell(caster, 54893, true);
- break;
- }
case 62292: // Blaze (Pool of Tar)
// should we use custom damage?
target->CastSpell((Unit*)NULL, m_spellInfo->Effects[m_effIndex].TriggerSpell, true);
@@ -6272,7 +6252,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) const
{
- if (!caster || !caster->isAlive() || !target->isAlive())
+ if (!caster || !target->isAlive())
return;
if (target->HasUnitState(UNIT_STATE_ISOLATED) || target->IsImmunedToDamage(GetSpellInfo()))
@@ -6325,15 +6305,19 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
damage = (damage <= absorb+resist) ? 0 : (damage-absorb-resist);
if (damage)
procVictim |= PROC_FLAG_TAKEN_DAMAGE;
- caster->ProcDamageAndSpell(target, procAttacker, procVictim, procEx, damage, BASE_ATTACK, GetSpellInfo());
+ if (caster->isAlive())
+ caster->ProcDamageAndSpell(target, procAttacker, procVictim, procEx, damage, BASE_ATTACK, GetSpellInfo());
int32 new_damage = caster->DealDamage(target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), false);
- float gainMultiplier = GetSpellInfo()->Effects[GetEffIndex()].CalcValueMultiplier(caster);
+ if (caster->isAlive())
+ {
+ float gainMultiplier = GetSpellInfo()->Effects[GetEffIndex()].CalcValueMultiplier(caster);
- uint32 heal = uint32(caster->SpellHealingBonus(caster, GetSpellInfo(), uint32(new_damage * gainMultiplier), DOT, GetBase()->GetStackAmount()));
+ uint32 heal = uint32(caster->SpellHealingBonus(caster, GetSpellInfo(), uint32(new_damage * gainMultiplier), DOT, GetBase()->GetStackAmount()));
- int32 gain = caster->HealBySpell(caster, GetSpellInfo(), heal);
- caster->getHostileRefManager().threatAssist(caster, gain * 0.5f, GetSpellInfo());
+ int32 gain = caster->HealBySpell(caster, GetSpellInfo(), heal);
+ caster->getHostileRefManager().threatAssist(caster, gain * 0.5f, GetSpellInfo());
+ }
}
void AuraEffect::HandlePeriodicHealthFunnelAuraTick(Unit* target, Unit* caster) const
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 942f9dc7e86..c6d0784fcc1 100755
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -1008,7 +1008,7 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar
{
case TARGET_OBJECT_TYPE_UNIT:
if (Unit* unitTarget = target->ToUnit())
- AddUnitTarget(unitTarget, effMask, false);
+ AddUnitTarget(unitTarget, effMask, true, false);
break;
case TARGET_OBJECT_TYPE_GOBJ:
if (GameObject* gobjTarget = target->ToGameObject())
@@ -1544,7 +1544,7 @@ void Spell::SelectImplicitTargetObjectTargets(SpellEffIndex effIndex, SpellImpli
{
ASSERT((m_targets.GetObjectTarget() || m_targets.GetItemTarget()) && "Spell::SelectImplicitTargetObjectTargets - no explicit object or item target available!");
if (Unit* unit = m_targets.GetUnitTarget())
- AddUnitTarget(unit, 1 << effIndex);
+ AddUnitTarget(unit, 1 << effIndex, true, false);
else if (GameObject* gobj = m_targets.GetGOTarget())
AddGOTarget(gobj, 1 << effIndex);
else
@@ -2077,7 +2077,7 @@ void Spell::CleanupTargetList()
m_delayMoment = 0;
}
-void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= true*/)
+void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= true*/, bool implicit /*= true*/)
{
for (uint32 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
if (!m_spellInfo->Effects[effIndex].IsEffect() || !CheckEffectTarget(target, effIndex))
@@ -2088,7 +2088,7 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*=
return;
if (checkIfValid)
- if (m_spellInfo->CheckTarget(m_caster, target, true) != SPELL_CAST_OK)
+ if (m_spellInfo->CheckTarget(m_caster, target, implicit) != SPELL_CAST_OK)
return;
// Check for effect immune skip if immuned
@@ -2745,18 +2745,18 @@ void Spell::DoTriggersOnSpellHit(Unit* unit, uint8 effMask)
if (!m_hitTriggerSpells.empty())
{
int _duration = 0;
- for (HitTriggerSpells::const_iterator i = m_hitTriggerSpells.begin(); i != m_hitTriggerSpells.end(); ++i)
+ for (HitTriggerSpellList::const_iterator i = m_hitTriggerSpells.begin(); i != m_hitTriggerSpells.end(); ++i)
{
- if (CanExecuteTriggersOnHit(effMask, i->first) && roll_chance_i(i->second))
+ if (CanExecuteTriggersOnHit(effMask, i->triggeredByAura) && roll_chance_i(i->chance))
{
- m_caster->CastSpell(unit, i->first, true);
- sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell %d triggered spell %d by SPELL_AURA_ADD_TARGET_TRIGGER aura", m_spellInfo->Id, i->first->Id);
+ m_caster->CastSpell(unit, i->triggeredSpell, true);
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell %d triggered spell %d by SPELL_AURA_ADD_TARGET_TRIGGER aura", m_spellInfo->Id, i->triggeredSpell->Id);
// SPELL_AURA_ADD_TARGET_TRIGGER auras shouldn't trigger auras without duration
// set duration of current aura to the triggered spell
- if (i->first->GetDuration() == -1)
+ if (i->triggeredSpell->GetDuration() == -1)
{
- if (Aura* triggeredAur = unit->GetAura(i->first->Id, m_caster->GetGUID()))
+ if (Aura* triggeredAur = unit->GetAura(i->triggeredSpell->Id, m_caster->GetGUID()))
{
// get duration from aura-only once
if (!_duration)
@@ -3101,11 +3101,20 @@ void Spell::cast(bool skipCheck)
return;
}
- // now that we've done the basic check, now run the scripts
- // should be done before the spell is actually executed
if (Player* playerCaster = m_caster->ToPlayer())
+ {
+ // now that we've done the basic check, now run the scripts
+ // should be done before the spell is actually executed
sScriptMgr->OnPlayerSpellCast(playerCaster, this, skipCheck);
+ // Let any pets know we've attacked something. As of 3.0.2 pets begin
+ // attacking their owner's target immediately
+ if (Pet* playerPet = playerCaster->GetPet())
+ {
+ if (playerPet->isAlive() && playerPet->isControlled() && (m_targets.GetTargetMask() & TARGET_FLAG_UNIT))
+ playerPet->AI()->OwnerAttacked(m_targets.GetObjectTarget()->ToUnit());
+ }
+ }
SetExecutedCurrently(true);
if (m_caster->GetTypeId() != TYPEID_PLAYER && m_targets.GetUnitTarget() && m_targets.GetUnitTarget() != m_caster)
@@ -4331,10 +4340,9 @@ void Spell::TakePower()
for (std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
if (ihit->targetGUID == targetGUID)
{
- if (ihit->missCondition != SPELL_MISS_NONE && ihit->missCondition != SPELL_MISS_MISS/* && ihit->targetGUID != m_caster->GetGUID()*/)
- hit = false;
if (ihit->missCondition != SPELL_MISS_NONE)
{
+ hit = false;
//lower spell cost on fail (by talent aura)
if (Player* modOwner = m_caster->ToPlayer()->GetSpellModOwner())
modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_SPELL_COST_REFUND_ON_FAIL, m_powerCost);
@@ -7171,14 +7179,13 @@ void Spell::CallScriptAfterUnitTargetSelectHandlers(std::list<Unit*>& unitTarget
}
}
-bool Spell::CanExecuteTriggersOnHit(uint8 effMask, SpellInfo const* spellInfo) const
+bool Spell::CanExecuteTriggersOnHit(uint8 effMask, SpellInfo const* triggeredByAura) const
{
- bool only_on_dummy = (spellInfo && (spellInfo->AttributesEx4 & SPELL_ATTR4_PROC_ONLY_ON_DUMMY));
- // If triggered spell has SPELL_ATTR4_PROC_ONLY_ON_DUMMY then it can only proc on a casted spell with SPELL_EFFECT_DUMMY
- // If triggered spell doesn't have SPELL_ATTR4_PROC_ONLY_ON_DUMMY then it can NOT proc on SPELL_EFFECT_DUMMY (needs confirmation)
+ bool only_on_caster = (triggeredByAura && (triggeredByAura->AttributesEx4 & SPELL_ATTR4_PROC_ONLY_ON_CASTER));
+ // If triggeredByAura has SPELL_ATTR4_PROC_ONLY_ON_CASTER then it can only proc on a casted spell with TARGET_UNIT_CASTER
for (uint8 i = 0;i < MAX_SPELL_EFFECTS; ++i)
{
- if ((effMask & (1 << i)) && (only_on_dummy == (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_DUMMY)))
+ if ((effMask & (1 << i)) && (!only_on_caster || (m_spellInfo->Effects[i].TargetA.GetTarget() == TARGET_UNIT_CASTER)))
return true;
}
return false;
@@ -7230,9 +7237,14 @@ void Spell::PrepareTriggersExecutedOnHit()
// calculate the chance using spell base amount, because aura amount is not updated on combo-points change
// this possibly needs fixing
int32 auraBaseAmount = (*i)->GetBaseAmount();
- int32 chance = m_caster->CalculateSpellDamage(NULL, auraSpellInfo, auraSpellIdx, &auraBaseAmount);
// proc chance is stored in effect amount
- m_hitTriggerSpells.push_back(std::make_pair(spellInfo, chance * (*i)->GetBase()->GetStackAmount()));
+ int32 chance = m_caster->CalculateSpellDamage(NULL, auraSpellInfo, auraSpellIdx, &auraBaseAmount);
+ // build trigger and add to the list
+ HitTriggerSpell spellTriggerInfo;
+ spellTriggerInfo.triggeredSpell = spellInfo;
+ spellTriggerInfo.triggeredByAura = auraSpellInfo;
+ spellTriggerInfo.chance = chance * (*i)->GetBase()->GetStackAmount();
+ m_hitTriggerSpells.push_back(spellTriggerInfo);
}
}
}
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 37842433eb3..8f43b9b2290 100755
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -596,7 +596,7 @@ class Spell
SpellDestination m_destTargets[MAX_SPELL_EFFECTS];
- void AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid = true);
+ void AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid = true, bool implicit = true);
void AddGOTarget(GameObject* target, uint32 effectMask);
void AddItemTarget(Item* item, uint32 effectMask);
void AddDestTarget(SpellDestination const& dest, uint32 effIndex);
@@ -633,10 +633,18 @@ class Spell
void CallScriptAfterUnitTargetSelectHandlers(std::list<Unit*>& unitTargets, SpellEffIndex effIndex);
std::list<SpellScript*> m_loadedScripts;
- bool CanExecuteTriggersOnHit(uint8 effMask, SpellInfo const* spellInfo = NULL) const;
+ struct HitTriggerSpell
+ {
+ SpellInfo const* triggeredSpell;
+ SpellInfo const* triggeredByAura;
+ // uint8 triggeredByEffIdx This might be needed at a later stage - No need known for now
+ int32 chance;
+ };
+
+ bool CanExecuteTriggersOnHit(uint8 effMask, SpellInfo const* triggeredByAura = NULL) const;
void PrepareTriggersExecutedOnHit();
- typedef std::list< std::pair<SpellInfo const*, int32> > HitTriggerSpells;
- HitTriggerSpells m_hitTriggerSpells;
+ typedef std::list<HitTriggerSpell> HitTriggerSpellList;
+ HitTriggerSpellList m_hitTriggerSpells;
// effect helpers
void SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const* properties, uint32 numSummons);
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index b95ee766f38..07ab71207f1 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -2177,12 +2177,12 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const
switch (Id)
{
case 34700: // Allergic Reaction
- case 61716: // Rabbit Costume
- case 61734: // Noblegarden Bunny
case 61987: // Avenging Wrath Marker
case 61988: // Divine Shield exclude aura
case 62532: // Conservator's Grip
return false;
+ case 61716: // Rabbit Costume
+ case 61734: // Noblegarden Bunny
case 30877: // Tag Murloc
case 62344: // Fists of Stone
return true;
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 895dc9ab4b7..cf200f19010 100755
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -3238,6 +3238,10 @@ void SpellMgr::LoadDbcDataCorrections()
spellInfo->EffectDieSides[0] = 0; // was 1, that should probably mean seat 0, but instead it's treated as spell 1
spellInfo->EffectBasePoints[0] = 52391; // Ride Vehicle (forces seat 0)
break;
+ case 64745: // Item - Death Knight T8 Tank 4P Bonus
+ case 64936: // Item - Warrior T8 Protection 4P Bonus
+ spellInfo->EffectBasePoints[0] = 100; // 100% chance of procc'ing, not -10% (chance calculated in PrepareTriggersExecutedOnHit)
+ break;
case 19970: // Entangling Roots (Rank 6) -- Nature's Grasp Proc
case 19971: // Entangling Roots (Rank 5) -- Nature's Grasp Proc
case 19972: // Entangling Roots (Rank 4) -- Nature's Grasp Proc
@@ -3406,10 +3410,7 @@ void SpellMgr::LoadDbcDataCorrections()
spellInfo->EffectImplicitTargetA[0] = TARGET_DEST_CASTER;
break;
case 69846: // Frost Bomb
- spellInfo->speed = 10;
- spellInfo->EffectImplicitTargetA[0] = TARGET_DEST_TARGET_ANY;
- spellInfo->EffectImplicitTargetB[0] = TARGET_UNIT_TARGET_ANY;
- spellInfo->Effect[1] = 0;
+ spellInfo->speed = 0.0f; // This spell's summon happens instantly
break;
case 71614: // Ice Lock
spellInfo->Mechanic = MECHANIC_STUN;
@@ -3505,6 +3506,11 @@ void SpellMgr::LoadDbcDataCorrections()
case 40166: // Introspection
case 40167: // Introspection
spellInfo->Attributes |= SPELL_ATTR0_NEGATIVE_1;
+ break;
+ case 2378: // Minor Fortitude
+ spellInfo->manaCost = 0;
+ spellInfo->manaPerSecond = 0;
+ break;
default:
break;
}
diff --git a/src/server/game/Tickets/TicketMgr.cpp b/src/server/game/Tickets/TicketMgr.cpp
index 68e28014319..f82c01adf31 100755
--- a/src/server/game/Tickets/TicketMgr.cpp
+++ b/src/server/game/Tickets/TicketMgr.cpp
@@ -37,7 +37,10 @@ GmTicket::GmTicket(Player* player, WorldPacket& recv_data) : _createTime(time(NU
_playerName = player->GetName();
_playerGuid = player->GetGUID();
- recv_data >> _mapId;
+ uint32 mapId;
+ recv_data >> mapId; // Map is sent as UInt32!
+ _mapId = mapId;
+
recv_data >> _posX;
recv_data >> _posY;
recv_data >> _posZ;
diff --git a/src/server/scripts/Commands/cs_tele.cpp b/src/server/scripts/Commands/cs_tele.cpp
index 89646c23ea0..ca7c3af7fde 100644
--- a/src/server/scripts/Commands/cs_tele.cpp
+++ b/src/server/scripts/Commands/cs_tele.cpp
@@ -138,8 +138,8 @@ public:
if (resultDB)
{
Field* fieldsDB = resultDB->Fetch();
- uint32 mapId = fieldsDB[0].GetUInt32();
- uint32 zoneId = fieldsDB[1].GetUInt32();
+ uint32 mapId = fieldsDB[0].GetUInt16();
+ uint32 zoneId = fieldsDB[1].GetUInt16();
float posX = fieldsDB[2].GetFloat();
float posY = fieldsDB[3].GetFloat();
float posZ = fieldsDB[4].GetFloat();
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_high_inquisitor_fairbanks.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_high_inquisitor_fairbanks.cpp
index a64636a4223..1989c318c84 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_high_inquisitor_fairbanks.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_high_inquisitor_fairbanks.cpp
@@ -66,9 +66,15 @@ public:
Sleep_Timer = 30000;
Dispel_Timer = 20000;
PowerWordShield = false;
+ me->SetStandState(UNIT_STAND_STATE_DEAD);
+ me->SetUInt32Value(UNIT_FIELD_BYTES_1, 7);
}
- void EnterCombat(Unit* /*who*/) {}
+ void EnterCombat(Unit* /*who*/)
+ {
+ me->SetStandState(UNIT_STAND_STATE_STAND);
+ me->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
+ }
void UpdateAI(const uint32 diff)
{
diff --git a/src/server/scripts/EasternKingdoms/undercity.cpp b/src/server/scripts/EasternKingdoms/undercity.cpp
index 0522e214012..d5896812007 100644
--- a/src/server/scripts/EasternKingdoms/undercity.cpp
+++ b/src/server/scripts/EasternKingdoms/undercity.cpp
@@ -47,7 +47,15 @@ enum Sylvanas
SPELL_HIGHBORNE_AURA = 37090,
SPELL_SYLVANAS_CAST = 36568,
- SPELL_RIBBON_OF_SOULS = 34432, //the real one to use might be 37099
+ SPELL_RIBBON_OF_SOULS = 34432, // the real one to use might be 37099
+
+ // Combat spells
+ SPELL_BLACK_ARROW = 59712,
+ SPELL_FADE = 20672,
+ SPELL_FADE_BLINK = 29211,
+ SPELL_MULTI_SHOT = 59713,
+ SPELL_SHOT = 59710,
+ SPELL_SUMMON_SKELETON = 59711
};
float HighborneLoc[4][3]=
@@ -90,15 +98,27 @@ public:
{
npc_lady_sylvanas_windrunnerAI(Creature* creature) : ScriptedAI(creature) {}
- uint32 LamentEvent_Timer;
+ uint32 LamentEventTimer;
bool LamentEvent;
uint64 targetGUID;
+ uint32 FadeTimer;
+ uint32 SummonSkeletonTimer;
+ uint32 BlackArrowTimer;
+ uint32 ShotTimer;
+ uint32 MultiShotTimer;
+
void Reset()
{
- LamentEvent_Timer = 5000;
+ LamentEventTimer = 5000;
LamentEvent = false;
targetGUID = 0;
+
+ FadeTimer = 30000;
+ SummonSkeletonTimer = 20000;
+ BlackArrowTimer = 15000;
+ ShotTimer = 8000;
+ MultiShotTimer = 10000;
}
void EnterCombat(Unit* /*who*/) {}
@@ -123,23 +143,70 @@ public:
{
if (LamentEvent)
{
- if (LamentEvent_Timer <= diff)
+ if (LamentEventTimer <= diff)
{
DoSummon(ENTRY_HIGHBORNE_BUNNY, me, 10.0f, 3000, TEMPSUMMON_TIMED_DESPAWN);
- LamentEvent_Timer = 2000;
+ LamentEventTimer = 2000;
if (!me->HasAura(SPELL_SYLVANAS_CAST))
{
DoScriptText(SAY_LAMENT_END, me);
DoScriptText(EMOTE_LAMENT_END, me);
LamentEvent = false;
}
- } else LamentEvent_Timer -= diff;
+ } else LamentEventTimer -= diff;
}
if (!UpdateVictim())
return;
+ // Combat spells
+
+ if (FadeTimer <= diff)
+ {
+ DoCast(me, SPELL_FADE);
+ // add a blink to simulate a stealthed movement and reappearing elsewhere
+ DoCast(me, SPELL_FADE_BLINK);
+ FadeTimer = 30000 + rand()%5000;
+ // if the victim is out of melee range she cast multi shot
+ if (Unit* victim = me->getVictim())
+ if (me->GetDistance(victim) > 10.0f)
+ DoCast(victim, SPELL_MULTI_SHOT);
+ } else FadeTimer -= diff;
+
+ if (SummonSkeletonTimer <= diff)
+ {
+ DoCast(me, SPELL_SUMMON_SKELETON);
+ SummonSkeletonTimer = 20000 + rand()%10000;
+ } else SummonSkeletonTimer -= diff;
+
+ if (BlackArrowTimer <= diff)
+ {
+ if (Unit* victim = me->getVictim())
+ {
+ DoCast(me->getVictim(), SPELL_BLACK_ARROW);
+ BlackArrowTimer = 15000 + rand()%5000;
+ }
+ } else BlackArrowTimer -= diff;
+
+ if (ShotTimer <= diff)
+ {
+ if (Unit* victim = me->getVictim())
+ {
+ DoCast(me->getVictim(), SPELL_SHOT);
+ ShotTimer = 8000 + rand()%2000;
+ }
+ } else ShotTimer -= diff;
+
+ if (MultiShotTimer <= diff)
+ {
+ if (Unit* victim = me->getVictim())
+ {
+ DoCast(me->getVictim(), SPELL_MULTI_SHOT);
+ MultiShotTimer = 10000 + rand()%3000;
+ }
+ } else MultiShotTimer -= diff;
+
DoMeleeAttackIfReady();
}
};
@@ -163,15 +230,15 @@ public:
{
npc_highborne_lamenterAI(Creature* creature) : ScriptedAI(creature) {}
- uint32 EventMove_Timer;
- uint32 EventCast_Timer;
+ uint32 EventMoveTimer;
+ uint32 EventCastTimer;
bool EventMove;
bool EventCast;
void Reset()
{
- EventMove_Timer = 10000;
- EventCast_Timer = 17500;
+ EventMoveTimer = 10000;
+ EventCastTimer = 17500;
EventMove = true;
EventCast = true;
}
@@ -182,21 +249,21 @@ public:
{
if (EventMove)
{
- if (EventMove_Timer <= diff)
+ if (EventMoveTimer <= diff)
{
me->SetDisableGravity(true);
me->MonsterMoveWithSpeed(me->GetPositionX(), me->GetPositionY(), HIGHBORNE_LOC_Y_NEW, me->GetDistance(me->GetPositionX(), me->GetPositionY(), HIGHBORNE_LOC_Y_NEW) / (5000 * 0.001f));
me->SetPosition(me->GetPositionX(), me->GetPositionY(), HIGHBORNE_LOC_Y_NEW, me->GetOrientation());
EventMove = false;
- } else EventMove_Timer -= diff;
+ } else EventMoveTimer -= diff;
}
if (EventCast)
{
- if (EventCast_Timer <= diff)
+ if (EventCastTimer <= diff)
{
DoCast(me, SPELL_HIGHBORNE_AURA);
EventCast = false;
- } else EventCast_Timer -= diff;
+ } else EventCastTimer -= diff;
}
}
};
diff --git a/src/server/scripts/Kalimdor/silithus.cpp b/src/server/scripts/Kalimdor/silithus.cpp
index 66986ebd5ae..79c6f7172b5 100644
--- a/src/server/scripts/Kalimdor/silithus.cpp
+++ b/src/server/scripts/Kalimdor/silithus.cpp
@@ -373,8 +373,13 @@ static QuestCinematic EventAnim[]=
{0, 0, 0}
};
+struct Location
+{
+ float x, y, z, o;
+};
+
//Cordinates for Spawns
-static const Position SpawnLocation[]=
+static Location SpawnLocation[]=
{
{-8085.0f, 1528.0f, 2.61f, 3.141592f}, //Kaldorei Infantry
{-8080.0f, 1526.0f, 2.61f, 3.141592f}, //Kaldorei Infantry
@@ -485,9 +490,9 @@ class npc_anachronos_the_ancient : public CreatureScript
public:
npc_anachronos_the_ancient() : CreatureScript("npc_anachronos_the_ancient") { }
- CreatureAI* GetAI(Creature* c) const
+ CreatureAI* GetAI(Creature* creature) const
{
- return new npc_anachronos_the_ancientAI(c);
+ return new npc_anachronos_the_ancientAI(creature);
}
struct npc_anachronos_the_ancientAI : public ScriptedAI
@@ -813,9 +818,9 @@ class mob_qiraj_war_spawn : public CreatureScript
public:
mob_qiraj_war_spawn() : CreatureScript("mob_qiraj_war_spawn") { }
- CreatureAI* GetAI(Creature* c) const
+ CreatureAI* GetAI(Creature* creature) const
{
- return new mob_qiraj_war_spawnAI(c);
+ return new mob_qiraj_war_spawnAI(creature);
}
struct mob_qiraj_war_spawnAI : public ScriptedAI
@@ -928,9 +933,9 @@ class npc_anachronos_quest_trigger : public CreatureScript
public:
npc_anachronos_quest_trigger() : CreatureScript("npc_anachronos_quest_trigger") { }
- CreatureAI* GetAI(Creature* c) const
+ CreatureAI* GetAI(Creature* creature) const
{
- return new npc_anachronos_quest_triggerAI(c);
+ return new npc_anachronos_quest_triggerAI(creature);
}
struct npc_anachronos_quest_triggerAI : public ScriptedAI
@@ -974,7 +979,14 @@ public:
//uint8 QirajiWaspCount = 0;
for (uint8 i = 0; i < 67; ++i)
{
- if (Creature* spawn = me->SummonCreature(WavesInfo[WaveCount].CreatureId, SpawnLocation[locIndex + i], TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, WavesInfo[WaveCount].DespTimer))
+ float X = SpawnLocation[locIndex + i].x;
+ float Y = SpawnLocation[locIndex + i].y;
+ float Z = SpawnLocation[locIndex + i].z;
+ float O = SpawnLocation[locIndex + i].o;
+ uint32 desptimer = WavesInfo[WaveCount].DespTimer;
+ Creature* spawn = me->SummonCreature(WavesInfo[WaveCount].CreatureId, X, Y, Z, O, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, desptimer);
+
+ if (spawn)
{
spawn->LoadCreaturesAddon();
if (spawn->GetEntry() == 15423)
diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp
index a91951ca25e..70d72e52e67 100644
--- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp
@@ -240,12 +240,13 @@ class mob_geist_ambusher : public CreatureScript
_leapingFaceMaulCooldown = 9000;
}
- void MoveInLineOfSight(Unit* who)
+ void EnterCombat(Unit* who)
{
if (who->GetTypeId() != TYPEID_PLAYER)
return;
- if (me->IsWithinDistInMap(who, 30.0f))
+ // the max range is determined by aggro range
+ if (me->GetDistance(who) > 5.0f)
DoCast(who, SPELL_LEAPING_FACE_MAUL);
}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
index c88b3aa8b37..6bf94eeaed2 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
@@ -61,6 +61,7 @@ enum Spells
SPELL_ASPHYXIATION = 71665,
SPELL_FROST_BOMB_TRIGGER = 69846,
SPELL_FROST_BOMB_VISUAL = 70022,
+ SPELL_BIRTH_NO_VISUAL = 40031,
SPELL_FROST_BOMB = 69845,
SPELL_MYSTIC_BUFFET = 70128,
@@ -169,6 +170,23 @@ class FrostwyrmLandEvent : public BasicEvent
Position const& _dest;
};
+class FrostBombExplosion : public BasicEvent
+{
+ public:
+ FrostBombExplosion(Creature* owner, uint64 sindragosaGUID) : _owner(owner), _sindragosaGUID(sindragosaGUID) { }
+
+ bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/)
+ {
+ _owner->CastSpell((Unit*)NULL, SPELL_FROST_BOMB, true, NULL, NULL, _sindragosaGUID);
+ _owner->RemoveAurasDueToSpell(SPELL_FROST_BOMB_VISUAL);
+ return true;
+ }
+
+ private:
+ Creature* _owner;
+ uint64 _sindragosaGUID;
+};
+
class boss_sindragosa : public CreatureScript
{
public:
@@ -325,6 +343,12 @@ class boss_sindragosa : public CreatureScript
void JustSummoned(Creature* summon)
{
summons.Summon(summon);
+ if (summon->GetEntry() == NPC_FROST_BOMB)
+ {
+ summon->CastSpell(summon, SPELL_FROST_BOMB_VISUAL, true);
+ summon->CastSpell(summon, SPELL_BIRTH_NO_VISUAL, true);
+ summon->m_Events.AddEvent(new FrostBombExplosion(summon, me->GetGUID()), summon->m_Events.CalculateTime(5500));
+ }
}
void SummonedCreatureDespawn(Creature* summon)
@@ -337,18 +361,25 @@ class boss_sindragosa : public CreatureScript
void SpellHitTarget(Unit* target, SpellInfo const* spell)
{
if (uint32 spellId = sSpellMgr->GetSpellIdForDifficulty(70127, me))
+ {
if (spellId == spell->Id)
+ {
if (Aura const* mysticBuffet = target->GetAura(spell->Id))
_mysticBuffetStack = std::max<uint8>(_mysticBuffetStack, mysticBuffet->GetStackAmount());
+ return;
+ }
+ }
+
// Frost Infusion
if (Player* player = target->ToPlayer())
{
if (uint32 spellId = sSpellMgr->GetSpellIdForDifficulty(_isThirdPhase ? SPELL_FROST_BREATH_P2 : SPELL_FROST_BREATH_P1, me))
{
- if (player->GetQuestStatus(QUEST_FROST_INFUSION) == QUEST_STATUS_INCOMPLETE && spellId == spell->Id)
+ if (spellId == spell->Id)
{
- if (Item* shadowsEdge = player->GetWeaponForAttack(BASE_ATTACK, true))
+ Item* shadowsEdge = player->GetWeaponForAttack(BASE_ATTACK, true);
+ if (player->GetQuestStatus(QUEST_FROST_INFUSION) == QUEST_STATUS_INCOMPLETE && shadowsEdge)
{
if (!player->HasAura(SPELL_FROST_IMBUED_BLADE) && shadowsEdge->GetEntry() == ITEM_SHADOW_S_EDGE)
{
@@ -366,15 +397,11 @@ class boss_sindragosa : public CreatureScript
player->CastSpell(player, SPELL_FROST_INFUSION, true);
}
}
+
+ return;
}
}
}
-
- if (spell->Id == SPELL_FROST_BOMB_TRIGGER)
- {
- target->CastSpell(target, SPELL_FROST_BOMB, true);
- target->RemoveAurasDueToSpell(SPELL_FROST_BOMB_VISUAL);
- }
}
void UpdateAI(uint32 const diff)
@@ -458,21 +485,11 @@ class boss_sindragosa : public CreatureScript
case EVENT_FROST_BOMB:
{
float destX, destY, destZ;
- destX = float(rand_norm()) * 117.25f + 4339.25f;
- if (destX > 4371.5f && destX < 4432.0f)
- destY = float(rand_norm()) * 111.0f + 2429.0f;
- else
- destY = float(rand_norm()) * 31.23f + 2454.64f;
+ destX = float(rand_norm()) * 75.0f + 4350.0f;
+ destY = float(rand_norm()) * 75.0f + 2450.0f;
destZ = 205.0f; // random number close to ground, get exact in next call
me->UpdateGroundPositionZ(destX, destY, destZ);
- Position pos;
- pos.Relocate(destX, destY, destZ, 0.0f);
- if (TempSummon* summ = me->SummonCreature(NPC_FROST_BOMB, pos, TEMPSUMMON_TIMED_DESPAWN, 40000))
- {
- summ->CastSpell(summ, SPELL_FROST_BOMB_VISUAL, true);
- DoCast(summ, SPELL_FROST_BOMB_TRIGGER);
- //me->CastSpell(destX, destY, destZ, SPELL_FROST_BOMB_TRIGGER, false);
- }
+ me->CastSpell(destX, destY, destZ, SPELL_FROST_BOMB_TRIGGER, false);
events.ScheduleEvent(EVENT_FROST_BOMB, urand(5000, 10000));
break;
}
diff --git a/src/server/scripts/Spells/spell_mage.cpp b/src/server/scripts/Spells/spell_mage.cpp
index b746c37a090..050741ffaba 100644
--- a/src/server/scripts/Spells/spell_mage.cpp
+++ b/src/server/scripts/Spells/spell_mage.cpp
@@ -250,9 +250,11 @@ class spell_mage_frost_warding_trigger : public SpellScriptLoader
if (roll_chance_i(chance))
{
- absorbAmount = dmgInfo.GetDamage();
- int32 bp = absorbAmount;
+ int32 bp = dmgInfo.GetDamage();
+ dmgInfo.AbsorbDamage(bp);
target->CastCustomSpell(target, SPELL_MAGE_FROST_WARDING_TRIGGERED, &bp, NULL, NULL, true, NULL, aurEff);
+ absorbAmount = 0;
+ PreventDefaultAction();
}
}
}
diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp
index 278abcc0c0b..48faf83cd2f 100644
--- a/src/server/scripts/Spells/spell_quest.cpp
+++ b/src/server/scripts/Spells/spell_quest.cpp
@@ -636,6 +636,10 @@ class spell_q12851_going_bearback : public SpellScriptLoader
if (Unit* caster = GetCaster())
{
Unit* target = GetTarget();
+ // Already in fire
+ if (target->HasAura(SPELL_ABLAZE))
+ return;
+
if (Player* player = caster->GetCharmerOrOwnerPlayerOrPlayerItself())
{
switch (target->GetEntry())
diff --git a/src/server/scripts/Spells/spell_warrior.cpp b/src/server/scripts/Spells/spell_warrior.cpp
index 1084398c37d..c87c2e05289 100644
--- a/src/server/scripts/Spells/spell_warrior.cpp
+++ b/src/server/scripts/Spells/spell_warrior.cpp
@@ -413,6 +413,51 @@ class spell_warr_bloodthirst : public SpellScriptLoader
}
};
+enum Overpower
+{
+ SPELL_UNRELENTING_ASSAULT_RANK_1 = 46859,
+ SPELL_UNRELENTING_ASSAULT_RANK_2 = 46860,
+ SPELL_UNRELENTING_ASSAULT_TRIGGER_1 = 64849,
+ SPELL_UNRELENTING_ASSAULT_TRIGGER_2 = 64850,
+};
+
+class spell_warr_overpower : public SpellScriptLoader
+{
+public:
+ spell_warr_overpower() : SpellScriptLoader("spell_warr_overpower") { }
+
+ class spell_warr_overpower_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_warr_overpower_SpellScript);
+
+ void HandleEffect(SpellEffIndex /* effIndex */)
+ {
+ uint32 spellId = 0;
+ if (GetCaster()->HasAura(SPELL_UNRELENTING_ASSAULT_RANK_1))
+ spellId = SPELL_UNRELENTING_ASSAULT_TRIGGER_1;
+ else if (GetCaster()->HasAura(SPELL_UNRELENTING_ASSAULT_RANK_2))
+ spellId = SPELL_UNRELENTING_ASSAULT_TRIGGER_2;
+
+ if (!spellId)
+ return;
+
+ Unit* target = GetHitUnit();
+ if (target->HasUnitState(UNIT_STATE_CASTING))
+ GetCaster()->CastSpell(target, spellId, true);
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_warr_overpower_SpellScript::HandleEffect, EFFECT_0, SPELL_EFFECT_ANY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_warr_overpower_SpellScript();
+ }
+};
+
void AddSC_warrior_spell_scripts()
{
new spell_warr_last_stand();
@@ -424,4 +469,5 @@ void AddSC_warrior_spell_scripts()
new spell_warr_execute();
new spell_warr_concussion_blow();
new spell_warr_bloodthirst();
+ new spell_warr_overpower();
}
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
index 97207410159..a267a8b9d6d 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
@@ -335,7 +335,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
// GM Survey/subsurvey/lag report
PREPARE_STATEMENT(CHAR_INS_GM_SURVEY, "INSERT INTO gm_surveys (guid, surveyId, mainSurvey, overallComment, createTime) VALUES (?, ?, ?, ?, UNIX_TIMESTAMP(NOW()))", CONNECTION_ASYNC)
PREPARE_STATEMENT(CHAR_INS_GM_SUBSURVEY, "INSERT INTO gm_subsurveys (surveyId, subsurveyId, rank, comment) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC)
- PREPARE_STATEMENT(CHAR_INS_LAG_REPORT, "INSERT INTO lag_reports (guid, lagType, mapId, posX, posY, posZ) VALUES (?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC)
+ PREPARE_STATEMENT(CHAR_INS_LAG_REPORT, "INSERT INTO lag_reports (guid, lagType, mapId, posX, posY, posZ, latency, createTime) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC)
// For loading and deleting expired auctions at startup
PREPARE_STATEMENT(CHAR_SEL_EXPIRED_AUCTIONS, "SELECT id, auctioneerguid, itemguid, itemEntry, itemowner, buyoutprice, time, buyguid, lastbid, startbid, deposit FROM auctionhouse ah INNER JOIN item_instance ii ON ii.guid = ah.itemguid WHERE ah.time <= ?", CONNECTION_SYNCH)
diff --git a/src/server/shared/Utilities/Util.h b/src/server/shared/Utilities/Util.h
index 4c2c1936993..4434ed36645 100755
--- a/src/server/shared/Utilities/Util.h
+++ b/src/server/shared/Utilities/Util.h
@@ -73,7 +73,7 @@ inline uint32 secsToTimeBitFields(time_t secs)
double rand_norm(void);
/* Return a random double from 0.0 to 99.9999999999999. Floats support only 7 valid decimal digits.
- * A double supports up to 15 valid decimal digits and is used internaly (RAND32_MAX has 10 digits).
+ * A double supports up to 15 valid decimal digits and is used internally (RAND32_MAX has 10 digits).
* With an FPU, there is usually no difference in performance between float and double. */
double rand_chance(void);