aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/AI/CoreAI/GameObjectAI.h23
-rwxr-xr-xsrc/server/game/AI/CreatureAISelector.cpp3
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.cpp2
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.h2
-rwxr-xr-xsrc/server/game/Battlegrounds/Battleground.cpp39
-rwxr-xr-xsrc/server/game/Battlegrounds/Battleground.h4
-rwxr-xr-xsrc/server/game/Battlegrounds/BattlegroundMgr.cpp28
-rwxr-xr-xsrc/server/game/Battlegrounds/BattlegroundMgr.h1
-rwxr-xr-xsrc/server/game/Entities/Pet/Pet.cpp7
-rwxr-xr-xsrc/server/game/Entities/Player/Player.cpp9
-rwxr-xr-xsrc/server/game/Entities/Unit/StatSystem.cpp2
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.cpp83
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.h2
-rwxr-xr-xsrc/server/game/Miscellaneous/SharedDefines.h28
-rwxr-xr-xsrc/server/game/Movement/MotionMaster.cpp3
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp2
-rwxr-xr-xsrc/server/game/Reputation/ReputationMgr.h4
-rwxr-xr-xsrc/server/game/Scripting/ScriptMgr.cpp8
-rwxr-xr-xsrc/server/game/Scripting/ScriptMgr.h5
-rwxr-xr-xsrc/server/game/Spells/Auras/SpellAuraEffects.cpp34
-rwxr-xr-xsrc/server/game/Spells/Spell.cpp30
-rwxr-xr-xsrc/server/game/Spells/SpellMgr.cpp6
-rw-r--r--src/server/game/Warden/Warden.cpp4
-rw-r--r--src/server/game/Warden/WardenCheckMgr.cpp11
-rw-r--r--src/server/game/Warden/WardenCheckMgr.h2
-rw-r--r--src/server/scripts/Commands/cs_modify.cpp2
-rwxr-xr-xsrc/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp158
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp1
-rw-r--r--src/server/scripts/Spells/spell_shaman.cpp19
-rw-r--r--src/server/scripts/Spells/spell_warrior.cpp2
-rw-r--r--src/server/scripts/World/npcs_special.cpp48
-rwxr-xr-xsrc/server/shared/Database/DatabaseWorkerPool.h4
32 files changed, 400 insertions, 176 deletions
diff --git a/src/server/game/AI/CoreAI/GameObjectAI.h b/src/server/game/AI/CoreAI/GameObjectAI.h
index b9d385ba675..f4555649210 100644
--- a/src/server/game/AI/CoreAI/GameObjectAI.h
+++ b/src/server/game/AI/CoreAI/GameObjectAI.h
@@ -33,21 +33,24 @@ class GameObjectAI
explicit GameObjectAI(GameObject* g) : go(g) {}
virtual ~GameObjectAI() {}
- virtual void UpdateAI(const uint32 /*diff*/) {}
+ virtual void UpdateAI(uint32 /*diff*/) {}
virtual void InitializeAI() { Reset(); }
virtual void Reset() {};
- static int Permissible(const GameObject* go);
+ static int Permissible(GameObject const* go);
- virtual bool GossipHello(Player* /*player*/) {return false;}
- virtual bool GossipSelect(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/) {return false;}
- virtual bool GossipSelectCode(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/, const char* /*code*/) {return false;}
- virtual bool QuestAccept(Player* /*player*/, Quest const* /*quest*/) {return false;}
- virtual bool QuestReward(Player* /*player*/, Quest const* /*quest*/, uint32 /*opt*/) {return false;}
- virtual uint32 GetDialogStatus(Player* /*player*/) {return 100;}
+ virtual bool GossipHello(Player* /*player*/) { return false; }
+ virtual bool GossipSelect(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/) { return false; }
+ virtual bool GossipSelectCode(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/, char const* /*code*/) { return false; }
+ virtual bool QuestAccept(Player* /*player*/, Quest const* /*quest*/) { return false; }
+ virtual bool QuestReward(Player* /*player*/, Quest const* /*quest*/, uint32 /*opt*/) { return false; }
+ virtual uint32 GetDialogStatus(Player* /*player*/) { return 100; }
virtual void Destroyed(Player* /*player*/, uint32 /*eventId*/) {}
+ virtual uint32 GetData(uint32 /*id*/) { return 0; }
+ virtual void SetData64(uint32 /*id*/, uint64 /*value*/) {}
+ virtual uint64 GetData64(uint32 /*id*/) { return 0; }
virtual void SetData(uint32 /*id*/, uint32 /*value*/) {}
virtual void OnGameEvent(bool /*start*/, uint16 /*eventId*/) {}
virtual void OnStateChanged(uint32 /*state*/, Unit* /*unit*/) { }
@@ -58,8 +61,8 @@ class NullGameObjectAI : public GameObjectAI
public:
explicit NullGameObjectAI(GameObject* g);
- void UpdateAI(const uint32 /*diff*/) {}
+ void UpdateAI(uint32 /*diff*/) {}
- static int Permissible(const GameObject* /*go*/) { return PERMIT_BASE_IDLE; }
+ static int Permissible(GameObject const* /*go*/) { return PERMIT_BASE_IDLE; }
};
#endif
diff --git a/src/server/game/AI/CreatureAISelector.cpp b/src/server/game/AI/CreatureAISelector.cpp
index ebe14c0d7d0..1a0c6652e74 100755
--- a/src/server/game/AI/CreatureAISelector.cpp
+++ b/src/server/game/AI/CreatureAISelector.cpp
@@ -133,6 +133,9 @@ namespace FactorySelector
const GameObjectAICreator* ai_factory = NULL;
GameObjectAIRegistry& ai_registry(*GameObjectAIRepository::instance());
+ if (GameObjectAI* scriptedAI = sScriptMgr->GetGameObjectAI(go))
+ return scriptedAI;
+
ai_factory = ai_registry.GetRegistryItem(go->GetAIName());
//future goAI types go here
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp
index 4eb7f8a7f50..2a412bffb22 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.cpp
+++ b/src/server/game/AI/SmartScripts/SmartAI.cpp
@@ -854,7 +854,7 @@ int SmartGameObjectAI::Permissible(const GameObject* g)
return PERMIT_BASE_NO;
}
-void SmartGameObjectAI::UpdateAI(const uint32 diff)
+void SmartGameObjectAI::UpdateAI(uint32 diff)
{
GetScript()->OnUpdate(diff);
}
diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h
index 94e5e65cf8b..bfd1c7b9d41 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.h
+++ b/src/server/game/AI/SmartScripts/SmartAI.h
@@ -239,7 +239,7 @@ public:
SmartGameObjectAI(GameObject* g) : GameObjectAI(g), go(g) {}
~SmartGameObjectAI() {}
- void UpdateAI(const uint32 diff);
+ void UpdateAI(uint32 diff);
void InitializeAI();
void Reset();
SmartScript* GetScript() { return &mScript; }
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index d6bfde021e7..44192a74123 100755
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -144,6 +144,7 @@ Battleground::Battleground()
m_Winner = 2;
m_StartTime = 0;
m_ResetStatTimer = 0;
+ m_ValidStartPositionTimer = 0;
m_Events = 0;
m_IsRated = false;
m_BuffChange = false;
@@ -177,6 +178,8 @@ Battleground::Battleground()
m_ArenaTeamIds[BG_TEAM_ALLIANCE] = 0;
m_ArenaTeamIds[BG_TEAM_HORDE] = 0;
+ m_StartMaxDist = 0.0f;
+
m_ArenaTeamRatingChanges[BG_TEAM_ALLIANCE] = 0;
m_ArenaTeamRatingChanges[BG_TEAM_HORDE] = 0;
@@ -291,6 +294,7 @@ void Battleground::Update(uint32 diff)
// Update start time and reset stats timer
m_StartTime += diff;
m_ResetStatTimer += diff;
+ m_ValidStartPositionTimer += diff;
PostUpdateImpl(diff);
}
@@ -422,7 +426,7 @@ inline void Battleground::_ProcessJoin(uint32 diff)
// *********************************************************
ModifyStartDelayTime(diff);
- if (m_ResetStatTimer <= 5000)
+ if (m_ResetStatTimer > 5000)
{
m_ResetStatTimer = 0;
for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
@@ -453,19 +457,19 @@ inline void Battleground::_ProcessJoin(uint32 diff)
// First start warning - 2 or 1 minute
SendMessageToAll(StartMessageIds[BG_STARTING_EVENT_FIRST], CHAT_MSG_BG_SYSTEM_NEUTRAL);
}
- // After 1 minute or 30 seconds, warning is signalled
+ // After 1 minute or 30 seconds, warning is signaled
else if (GetStartDelayTime() <= StartDelayTimes[BG_STARTING_EVENT_SECOND] && !(m_Events & BG_STARTING_EVENT_2))
{
m_Events |= BG_STARTING_EVENT_2;
SendMessageToAll(StartMessageIds[BG_STARTING_EVENT_SECOND], CHAT_MSG_BG_SYSTEM_NEUTRAL);
}
- // After 30 or 15 seconds, warning is signalled
+ // After 30 or 15 seconds, warning is signaled
else if (GetStartDelayTime() <= StartDelayTimes[BG_STARTING_EVENT_THIRD] && !(m_Events & BG_STARTING_EVENT_3))
{
m_Events |= BG_STARTING_EVENT_3;
SendMessageToAll(StartMessageIds[BG_STARTING_EVENT_THIRD], CHAT_MSG_BG_SYSTEM_NEUTRAL);
}
- // Delay expired (atfer 2 or 1 minute)
+ // Delay expired (after 2 or 1 minute)
else if (GetStartDelayTime() <= 0 && !(m_Events & BG_STARTING_EVENT_4))
{
m_Events |= BG_STARTING_EVENT_4;
@@ -526,6 +530,33 @@ inline void Battleground::_ProcessJoin(uint32 diff)
sWorld->SendWorldText(LANG_BG_STARTED_ANNOUNCE_WORLD, GetName(), GetMinLevel(), GetMaxLevel());
}
}
+
+ // Find if the player left our start zone; if so, teleport it back
+ if (m_ValidStartPositionTimer > 1000)
+ {
+ m_ValidStartPositionTimer = 0;
+ float maxDist = GetStartMaxDist();
+ if (maxDist > 0.0f)
+ {
+ for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
+ {
+ if (Player *plr = ObjectAccessor::FindPlayer(itr->first))
+ {
+ float x, y, z, o;
+ uint32 team = plr->GetBGTeam();
+ GetTeamStartLoc(team, x, y, z, o);
+
+ float dist = plr->GetDistance(x, y, z);
+
+ if (dist >= maxDist)
+ {
+ sLog->outError("BATTLEGROUND: Sending %s back to start location (possible exploit)", plr->GetName());
+ plr->TeleportTo(GetMapId(), x, y, z, o);
+ }
+ }
+ }
+ }
+ }
}
inline void Battleground::_ProcessLeave(uint32 diff)
diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h
index 32f6ebc92de..01dfbb23033 100755
--- a/src/server/game/Battlegrounds/Battleground.h
+++ b/src/server/game/Battlegrounds/Battleground.h
@@ -443,6 +443,8 @@ class Battleground
Z = m_TeamStartLocZ[idx];
O = m_TeamStartLocO[idx];
}
+ void SetStartMaxDist(float startMaxDist) { m_StartMaxDist = startMaxDist; }
+ float GetStartMaxDist() const { return m_StartMaxDist; }
// Packet Transfer
// method that should fill worldpacket with actual world states (not yet implemented for all battlegrounds!)
@@ -617,6 +619,7 @@ class Battleground
uint32 m_ClientInstanceID; // the instance-id which is sent to the client and without any other internal use
uint32 m_StartTime;
uint32 m_ResetStatTimer;
+ uint32 m_ValidStartPositionTimer;
int32 m_EndTime; // it is set to 120000 when bg is ending and it decreases itself
uint32 m_LastResurrectTime;
BattlegroundBracketId m_BracketId;
@@ -698,6 +701,7 @@ class Battleground
float m_TeamStartLocY[BG_TEAMS_COUNT];
float m_TeamStartLocZ[BG_TEAMS_COUNT];
float m_TeamStartLocO[BG_TEAMS_COUNT];
+ float m_StartMaxDist;
uint32 ScriptId;
};
#endif
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
index e1b99cbdcb9..a106f11ae82 100755
--- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
@@ -660,6 +660,7 @@ uint32 BattlegroundMgr::CreateBattleground(CreateBattlegroundData& data)
bg->SetName(data.BattlegroundName);
bg->SetTeamStartLoc(ALLIANCE, data.Team1StartLocX, data.Team1StartLocY, data.Team1StartLocZ, data.Team1StartLocO);
bg->SetTeamStartLoc(HORDE, data.Team2StartLocX, data.Team2StartLocY, data.Team2StartLocZ, data.Team2StartLocO);
+ bg->SetStartMaxDist(data.StartMaxDist);
bg->SetLevelRange(data.LevelMin, data.LevelMax);
bg->SetScriptId(data.scriptId);
@@ -677,8 +678,8 @@ void BattlegroundMgr::CreateInitialBattlegrounds()
uint8 selectionWeight;
BattlemasterListEntry const* bl;
- // 0 1 2 3 4 5 6 7 8 9 10
- QueryResult result = WorldDatabase.Query("SELECT id, MinPlayersPerTeam, MaxPlayersPerTeam, MinLvl, MaxLvl, AllianceStartLoc, AllianceStartO, HordeStartLoc, HordeStartO, Weight, ScriptName FROM battleground_template");
+ // 0 1 2 3 4 5 6 7 8 9 10 11
+ QueryResult result = WorldDatabase.Query("SELECT id, MinPlayersPerTeam, MaxPlayersPerTeam, MinLvl, MaxLvl, AllianceStartLoc, AllianceStartO, HordeStartLoc, HordeStartO, StartMaxDist, Weight, ScriptName FROM battleground_template");
if (!result)
{
@@ -712,17 +713,20 @@ void BattlegroundMgr::CreateInitialBattlegrounds()
data.MaxPlayersPerTeam = fields[2].GetUInt16();
data.LevelMin = fields[3].GetUInt8();
data.LevelMax = fields[4].GetUInt8();
- //check values from DB
- if (data.MaxPlayersPerTeam == 0 || data.MinPlayersPerTeam == 0 || data.MinPlayersPerTeam > data.MaxPlayersPerTeam)
+
+ // check values from DB
+ if (data.MaxPlayersPerTeam == 0 || data.MinPlayersPerTeam > data.MaxPlayersPerTeam)
{
- data.MinPlayersPerTeam = 0; // by default now expected strong full bg requirement
- data.MaxPlayersPerTeam = 40;
+ sLog->outErrorDb("Table `battleground_template` for id %u has bad values for MinPlayersPerTeam (%u) and MaxPlayersPerTeam(%u)",
+ data.bgTypeId, data.MinPlayersPerTeam, data.MaxPlayersPerTeam);
+ continue;
}
+
if (data.LevelMin == 0 || data.LevelMax == 0 || data.LevelMin > data.LevelMax)
{
- //TO-DO: FIX ME
- data.LevelMin = 0;//bl->minlvl;
- data.LevelMax = 80;//bl->maxlvl;
+ sLog->outErrorDb("Table `battleground_template` for id %u has bad values for LevelMin (%u) and LevelMax(%u)",
+ data.bgTypeId, data.LevelMin, data.LevelMax);
+ continue;
}
startId = fields[5].GetUInt32();
@@ -767,8 +771,10 @@ void BattlegroundMgr::CreateInitialBattlegrounds()
continue;
}
- selectionWeight = fields[9].GetUInt8();
- data.scriptId = sObjectMgr->GetScriptId(fields[10].GetCString());
+ data.StartMaxDist = fields[9].GetFloat();
+
+ selectionWeight = fields[10].GetUInt8();
+ data.scriptId = sObjectMgr->GetScriptId(fields[11].GetCString());
data.BattlegroundName = bl->name[sWorld->GetDefaultDbcLocale()];
data.MapID = bl->mapid[0];
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.h b/src/server/game/Battlegrounds/BattlegroundMgr.h
index 88559d07993..7afb83da0a6 100755
--- a/src/server/game/Battlegrounds/BattlegroundMgr.h
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.h
@@ -50,6 +50,7 @@ struct CreateBattlegroundData
float Team2StartLocY;
float Team2StartLocZ;
float Team2StartLocO;
+ float StartMaxDist;
uint32 scriptId;
};
diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index fcb89e33dc1..586f09bd79c 100755
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -1041,6 +1041,13 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)));
break;
}
+ case 28017: // Bloodworms
+ {
+ SetCreateHealth(4 * petlevel);
+ SetBonusDamage(int32(m_owner->GetTotalAttackPowerValue(BASE_ATTACK) * 0.006f));
+ SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - 30 - (petlevel / 4)));
+ SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel - 30 + (petlevel / 4)));
+ }
}
break;
}
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 26ea7c110d2..31bd17ffc8f 100755
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -6830,11 +6830,6 @@ bool Player::UpdatePosition(float x, float y, float z, float orientation, bool t
if (GetGroup())
SetGroupUpdateFlag(GROUP_UPDATE_FLAG_POSITION);
- // code block for underwater state update
- // Unit::UpdatePosition() checks for validity and updates our coordinates
- // so we re-fetch them instead of using "raw" coordinates from function params
- UpdateUnderwaterState(GetMap(), GetPositionX(), GetPositionY(), GetPositionZ());
-
if (GetTrader() && !IsWithinDistInMap(GetTrader(), INTERACTION_DISTANCE))
GetSession()->SendCancelTrade();
@@ -17657,7 +17652,7 @@ void Player::_LoadInventory(PreparedQueryResult result, uint32 timeDiff)
ItemPosCountVec dest;
err = CanStoreItem(itr->second->GetSlot(), slot, dest, item);
if (err == EQUIP_ERR_OK)
- itr->second->StoreItem(slot, item, true);
+ item = StoreItem(dest, item, true);
}
}
@@ -18318,10 +18313,10 @@ void Player::UnbindInstance(BoundInstancesMap::iterator &itr, Difficulty difficu
CharacterDatabase.Execute(stmt);
}
- itr->second.save->RemovePlayer(this); // save can become invalid
if (itr->second.perm)
GetSession()->SendCalendarRaidLockout(itr->second.save, false);
+ itr->second.save->RemovePlayer(this); // save can become invalid
m_boundInstances[difficulty].erase(itr++);
}
}
diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp
index 69771129ac9..2da1c1b88cb 100755
--- a/src/server/game/Entities/Unit/StatSystem.cpp
+++ b/src/server/game/Entities/Unit/StatSystem.cpp
@@ -1068,6 +1068,7 @@ void Creature::UpdateDamagePhysical(WeaponAttackType attType)
#define ENTRY_TREANT 1964
#define ENTRY_FIRE_ELEMENTAL 15438
#define ENTRY_GHOUL 26125
+#define ENTRY_BLOODWORM 28017
bool Guardian::UpdateStats(Stats stat)
{
@@ -1229,6 +1230,7 @@ void Guardian::UpdateMaxHealth()
case ENTRY_SUCCUBUS: multiplicator = 9.1f; break;
case ENTRY_FELHUNTER: multiplicator = 9.5f; break;
case ENTRY_FELGUARD: multiplicator = 11.0f; break;
+ case ENTRY_BLOODWORM: multiplicator = 1.0f; break;
default: multiplicator = 10.0f; break;
}
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index eebfd25e3d4..da23a7ba010 100755
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -252,6 +252,7 @@ m_HostileRefManager(this)
_focusSpell = NULL;
_targetLocked = false;
+ _lastLiquid = NULL;
}
////////////////////////////////////////////////////////////
@@ -1542,7 +1543,7 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
// Magic damage, check for resists
// Ignore spells that cant be resisted
- if ((schoolMask & SPELL_SCHOOL_MASK_NORMAL) == 0 && (spellInfo && (spellInfo->AttributesEx4 & SPELL_ATTR4_IGNORE_RESISTANCES) == 0))
+ if ((schoolMask & SPELL_SCHOOL_MASK_NORMAL) == 0 && (!spellInfo || (spellInfo->AttributesEx4 & SPELL_ATTR4_IGNORE_RESISTANCES) == 0))
{
float victimResistance = float(victim->GetResistance(schoolMask));
victimResistance += float(GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask));
@@ -3089,6 +3090,48 @@ bool Unit::IsUnderWater() const
return GetBaseMap()->IsUnderWater(GetPositionX(), GetPositionY(), GetPositionZ());
}
+void Unit::UpdateUnderwaterState(Map* m, float x, float y, float z)
+{
+ if (!isPet() && !IsVehicle())
+ return;
+
+ LiquidData liquid_status;
+ ZLiquidStatus res = m->getLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &liquid_status);
+ if (!res)
+ {
+ if (_lastLiquid && _lastLiquid->SpellId)
+ RemoveAurasDueToSpell(_lastLiquid->SpellId);
+
+ RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_NOT_UNDERWATER);
+ _lastLiquid = NULL;
+ return;
+ }
+
+ if (uint32 liqEntry = liquid_status.entry)
+ {
+ LiquidTypeEntry const* liquid = sLiquidTypeStore.LookupEntry(liqEntry);
+ if (_lastLiquid && _lastLiquid->SpellId && _lastLiquid->Id != liqEntry)
+ RemoveAurasDueToSpell(_lastLiquid->SpellId);
+
+ if (liquid && liquid->SpellId)
+ {
+ if (res & (LIQUID_MAP_UNDER_WATER | LIQUID_MAP_IN_WATER))
+ CastSpell(this, liquid->SpellId, true);
+ else
+ RemoveAurasDueToSpell(liquid->SpellId);
+ }
+
+ RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_NOT_ABOVEWATER);
+ _lastLiquid = liquid;
+ }
+ else if (_lastLiquid && _lastLiquid->SpellId)
+ {
+ RemoveAurasDueToSpell(_lastLiquid->SpellId);
+ RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_NOT_UNDERWATER);
+ _lastLiquid = NULL;
+ }
+}
+
void Unit::DeMorph()
{
SetDisplayId(GetNativeDisplayId());
@@ -6000,6 +6043,8 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
// Siphon Life
case 63108:
{
+ if (!damage)
+ break;
// Glyph of Siphon Life
if (HasAura(56216))
triggerAmount += triggerAmount / 4;
@@ -7354,20 +7399,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
triggered_spell_id = 63685;
break;
}
- // Storm, Earth and Fire
- if (dummySpell->SpellIconID == 3063)
- {
- // Earthbind Totem summon only
- if (procSpell->Id != 2484)
- return false;
-
- float chance = (float)triggerAmount;
- if (!roll_chance_f(chance))
- return false;
-
- triggered_spell_id = 64695;
- break;
- }
// Ancestral Awakening
if (dummySpell->SpellIconID == 3065)
{
@@ -7396,8 +7427,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
if (GetTypeId() != TYPEID_PLAYER || !victim || !victim->isAlive() || !castItem || !castItem->IsEquipped())
return false;
- Player* player = ToPlayer();
- WeaponAttackType attType = WeaponAttackType(player->GetAttackBySlot(castItem->GetSlot()));
+ WeaponAttackType attType = WeaponAttackType(Player::GetAttackBySlot(castItem->GetSlot()));
if ((attType != BASE_ATTACK && attType != OFF_ATTACK)
|| (attType == BASE_ATTACK && procFlag & PROC_FLAG_DONE_OFFHAND_ATTACK)
|| (attType == OFF_ATTACK && procFlag & PROC_FLAG_DONE_MAINHAND_ATTACK))
@@ -7985,11 +8015,7 @@ bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, Sp
for (uint8 i = 1; i < stack; ++i)
dmg += mod * stack;
if (Unit* caster = triggeredByAura->GetCaster())
- {
caster->CastCustomSpell(70701, SPELLVALUE_BASE_POINT0, dmg);
- if (Creature* creature = caster->ToCreature())
- creature->DespawnOrUnsummon(1);
- }
break;
}
// Ball of Flames Proc
@@ -8200,6 +8226,16 @@ bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, Sp
CastCustomSpell(this, 70845, &basepoints0, NULL, NULL, true);
break;
}
+ // Recklessness
+ case 1719:
+ {
+ //! Possible hack alert
+ //! Don't drop charges on proc, they will be dropped on SpellMod removal
+ //! Before this change, it was dropping two charges per attack, one in ProcDamageAndSpellFor, and one in RemoveSpellMods.
+ //! The reason of this behaviour is Recklessness having three auras, 2 of them can not proc (isTriggeredAura array) but the other one can, making the whole spell proc.
+ *handled = true;
+ break;
+ }
default:
break;
}
@@ -17262,6 +17298,9 @@ bool Unit::UpdatePosition(float x, float y, float z, float orientation, bool tel
else if (turn)
UpdateOrientation(orientation);
+ // code block for underwater state update
+ UpdateUnderwaterState(GetMap(), x, y, z);
+
return (relocated || turn);
}
@@ -17566,7 +17605,7 @@ bool Unit::SetWalk(bool enable)
return true;
}
-bool Unit::SetDisableGravity(bool disable, bool packetOnly /*= false*/)
+bool Unit::SetDisableGravity(bool disable, bool /*packetOnly = false*/)
{
if (disable == IsLevitating())
return false;
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 00d66518d3f..828d87216df 100755
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1580,6 +1580,7 @@ class Unit : public WorldObject
virtual bool IsInWater() const;
virtual bool IsUnderWater() const;
+ virtual void UpdateUnderwaterState(Map* m, float x, float y, float z);
bool isInAccessiblePlaceFor(Creature const* c) const;
void SendHealSpellLog(Unit* victim, uint32 SpellID, uint32 Damage, uint32 OverHeal, uint32 Absorb, bool critical = false);
@@ -2353,6 +2354,7 @@ class Unit : public WorldObject
uint32 m_state; // Even derived shouldn't modify
uint32 m_CombatTimer;
uint32 m_lastManaUse; // msecs
+ LiquidTypeEntry const* _lastLiquid;
TimeTrackerSmall m_movesplineTimer;
Diminishing m_Diminishing;
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index 22f0ea35413..0386e6b4214 100755
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -3294,20 +3294,20 @@ enum BanReturn
// indexes of BattlemasterList.dbc
enum BattlegroundTypeId
{
- BATTLEGROUND_TYPE_NONE = 0,
- BATTLEGROUND_AV = 1,
- BATTLEGROUND_WS = 2,
- BATTLEGROUND_AB = 3,
- BATTLEGROUND_NA = 4,
- BATTLEGROUND_BE = 5,
- BATTLEGROUND_AA = 6,
- BATTLEGROUND_EY = 7,
- BATTLEGROUND_RL = 8,
- BATTLEGROUND_SA = 9,
- BATTLEGROUND_DS = 10,
- BATTLEGROUND_RV = 11,
- BATTLEGROUND_IC = 30,
- BATTLEGROUND_RB = 32
+ BATTLEGROUND_TYPE_NONE = 0, // None
+ BATTLEGROUND_AV = 1, // Alterac Valley
+ BATTLEGROUND_WS = 2, // Warsong Gulch
+ BATTLEGROUND_AB = 3, // Arathi Basin
+ BATTLEGROUND_NA = 4, // Nagrand Arena
+ BATTLEGROUND_BE = 5, // Blade's Edge Arena
+ BATTLEGROUND_AA = 6, // All Arenas
+ BATTLEGROUND_EY = 7, // Eye of the Storm
+ BATTLEGROUND_RL = 8, // Ruins of Lordaernon
+ BATTLEGROUND_SA = 9, // Strand of the Ancients
+ BATTLEGROUND_DS = 10, // Dalaran Sewers
+ BATTLEGROUND_RV = 11, // Ring of Valor
+ BATTLEGROUND_IC = 30, // Isle of Conquest
+ BATTLEGROUND_RB = 32 // Random Battleground
};
#define MAX_BATTLEGROUND_TYPE_ID 33
diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp
index b0ac0b710c1..c0e1eb842ae 100755
--- a/src/server/game/Movement/MotionMaster.cpp
+++ b/src/server/game/Movement/MotionMaster.cpp
@@ -114,6 +114,9 @@ void MotionMaster::UpdateMotion(uint32 diff)
_cleanFlag &= ~MMCF_RESET;
}
+
+ // probably not the best place to pu this but im not really sure where else to put it.
+ _owner->UpdateUnderwaterState(_owner->GetMap(), _owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ());
}
void MotionMaster::DirectClean(bool reset)
diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
index eb61db8b4ba..fdff5a92564 100755
--- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
@@ -135,7 +135,7 @@ bool TargetedMovementGeneratorMedium<T,D>::Update(T &owner, const uint32 & time_
}
// prevent movement while casting spells with cast time or channel time
- if (owner.IsNonMeleeSpellCasted(false, false, true))
+ if (owner.HasUnitState(UNIT_STATE_CASTING))
{
if (!owner.IsStopped())
owner.StopMoving();
diff --git a/src/server/game/Reputation/ReputationMgr.h b/src/server/game/Reputation/ReputationMgr.h
index 401503783b9..a073845ea73 100755
--- a/src/server/game/Reputation/ReputationMgr.h
+++ b/src/server/game/Reputation/ReputationMgr.h
@@ -132,6 +132,9 @@ class ReputationMgr
void ApplyForceReaction(uint32 faction_id, ReputationRank rank, bool apply);
+ //! Public for chat command needs
+ bool SetOneFactionReputation(FactionEntry const* factionEntry, int32 standing, bool incremental);
+
public: // senders
void SendInitialReputations();
void SendForceReactions();
@@ -142,7 +145,6 @@ class ReputationMgr
void Initialize();
uint32 GetDefaultStateFlags(FactionEntry const* factionEntry) const;
bool SetReputation(FactionEntry const* factionEntry, int32 standing, bool incremental);
- bool SetOneFactionReputation(FactionEntry const* factionEntry, int32 standing, bool incremental);
void SetVisible(FactionState* faction);
void SetAtWar(FactionState* faction, bool atWar) const;
void SetInactive(FactionState* faction, bool inactive) const;
diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp
index aac615180c8..01d56cf8060 100755
--- a/src/server/game/Scripting/ScriptMgr.cpp
+++ b/src/server/game/Scripting/ScriptMgr.cpp
@@ -954,6 +954,14 @@ bool ScriptMgr::OnDummyEffect(Unit* caster, uint32 spellId, SpellEffIndex effInd
return tmpscript->OnDummyEffect(caster, spellId, effIndex, target);
}
+GameObjectAI* ScriptMgr::GetGameObjectAI(GameObject* go)
+{
+ ASSERT(go);
+
+ GET_SCRIPT_RET(GameObjectScript, go->GetScriptId(), tmpscript, NULL);
+ return tmpscript->GetAI(go);
+}
+
bool ScriptMgr::OnAreaTrigger(Player* player, AreaTriggerEntry const* trigger)
{
ASSERT(player);
diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h
index 3b65a5cf256..6fe058d336a 100755
--- a/src/server/game/Scripting/ScriptMgr.h
+++ b/src/server/game/Scripting/ScriptMgr.h
@@ -39,6 +39,7 @@ class Creature;
class CreatureAI;
class DynamicObject;
class GameObject;
+class GameObjectAI;
class Guild;
class GridMap;
class Group;
@@ -471,6 +472,9 @@ class GameObjectScript : public ScriptObject, public UpdatableScript<GameObject>
// Called when the game object is damaged (destructible buildings only).
virtual void OnDamaged(GameObject* /*go*/, Player* /*player*/) { }
+
+ // Called when a GameObjectAI object is needed for the gameobject.
+ virtual GameObjectAI* GetAI(GameObject* /*go*/) const { return NULL; }
};
class AreaTriggerScript : public ScriptObject
@@ -911,6 +915,7 @@ class ScriptMgr
void OnGameObjectDestroyed(GameObject* go, Player* player);
void OnGameObjectDamaged(GameObject* go, Player* player);
void OnGameObjectUpdate(GameObject* go, uint32 diff);
+ GameObjectAI* GetGameObjectAI(GameObject* go);
public: /* AreaTriggerScript */
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 1ad6fe557f9..dbbd89c7533 100755
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -1474,6 +1474,23 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
if (spellInfo->Stances & (1<<(GetMiscValue()-1)))
target->CastSpell(target, itr->first, true, NULL, this);
}
+
+ // Also do it for Glyphs
+ for (uint32 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i)
+ {
+ if (uint32 glyphId = target->ToPlayer()->GetGlyph(i))
+ {
+ if (GlyphPropertiesEntry const* glyph = sGlyphPropertiesStore.LookupEntry(glyphId))
+ {
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(glyph->SpellId);
+ if (!spellInfo || !(spellInfo->Attributes & (SPELL_ATTR0_PASSIVE | SPELL_ATTR0_HIDDEN_CLIENTSIDE)))
+ continue;
+ if (spellInfo->Stances & (1<<(GetMiscValue()-1)))
+ target->CastSpell(target, glyph->SpellId, true, NULL, this);
+ }
+ }
+ }
+
// Leader of the Pack
if (target->ToPlayer()->HasSpell(17007))
{
@@ -1583,10 +1600,25 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
}
}
+ const Unit::AuraEffectList& shapeshifts = target->GetAuraEffectsByType(SPELL_AURA_MOD_SHAPESHIFT);
+ AuraEffect* newAura = NULL;
+ // Iterate through all the shapeshift auras that the target has, if there is another aura with SPELL_AURA_MOD_SHAPESHIFT, then this aura is being removed due to that one being applied
+ for (Unit::AuraEffectList::const_iterator itr = shapeshifts.begin(); itr != shapeshifts.end(); ++itr)
+ {
+ if ((*itr) != this)
+ {
+ newAura = *itr;
+ break;
+ }
+ }
Unit::AuraApplicationMap& tAuras = target->GetAppliedAuras();
for (Unit::AuraApplicationMap::iterator itr = tAuras.begin(); itr != tAuras.end();)
{
- if (itr->second->GetBase()->IsRemovedOnShapeLost(target))
+ // Use the new aura to see on what stance the target will be
+ uint32 newStance = (1<<((newAura ? newAura->GetMiscValue() : 0)-1));
+
+ // If the stances are not compatible with the spell, remove it
+ if (itr->second->GetBase()->IsRemovedOnShapeLost(target) && !(itr->second->GetBase()->GetSpellInfo()->Stances & newStance))
target->RemoveAura(itr);
else
++itr;
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index af3f53e2369..df2b9c35320 100755
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -3427,36 +3427,6 @@ void Spell::_handle_immediate_phase()
// process items
for (std::list<ItemTargetInfo>::iterator ihit= m_UniqueItemInfo.begin(); ihit != m_UniqueItemInfo.end(); ++ihit)
DoAllEffectOnTarget(&(*ihit));
-
- if (!m_originalCaster)
- return;
- // Handle procs on cast
- // TODO: finish new proc system:P
- if (m_UniqueTargetInfo.empty())
- {
- uint32 procAttacker = m_procAttacker;
- if (!procAttacker)
- {
- bool positive = m_spellInfo->IsPositive();
- switch (m_spellInfo->DmgClass)
- {
- case SPELL_DAMAGE_CLASS_MAGIC:
- if (positive)
- procAttacker |= PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS;
- else
- procAttacker |= PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG;
- break;
- case SPELL_DAMAGE_CLASS_NONE:
- if (positive)
- procAttacker |= PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS;
- else
- procAttacker |= PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_NEG;
- break;
- }
- }
- // Proc damage for spells which have only dest targets (2484 should proc 51486 for example)
- m_originalCaster->ProcDamageAndSpell(NULL, procAttacker, 0, m_procEx | PROC_EX_NORMAL_HIT, 0, BASE_ATTACK, m_spellInfo, m_triggeredByAuraSpell);
- }
}
void Spell::_handle_finish_phase()
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 80ed1972a5d..05431ef0a16 100755
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -3347,9 +3347,9 @@ void SpellMgr::LoadDbcDataCorrections()
case 70460: // Coldflame Jets (Traps after Saurfang)
spellInfo->DurationIndex = 1; // 10 seconds
break;
- case 71413: // Green Ooze Summon (Professor Putricide)
- case 71414: // Orange Ooze Summon (Professor Putricide)
- spellInfo->EffectImplicitTargetA[0] = TARGET_DEST_DEST;
+ case 71412: // Green Ooze Summon (Professor Putricide)
+ case 71415: // Orange Ooze Summon (Professor Putricide)
+ spellInfo->EffectImplicitTargetA[0] = TARGET_UNIT_TARGET_ANY;
break;
case 71159: // Awaken Plagued Zombies
spellInfo->DurationIndex = 21;
diff --git a/src/server/game/Warden/Warden.cpp b/src/server/game/Warden/Warden.cpp
index fa30adde72a..0734e0a0f63 100644
--- a/src/server/game/Warden/Warden.cpp
+++ b/src/server/game/Warden/Warden.cpp
@@ -187,7 +187,9 @@ std::string Warden::Penalty(WardenCheck* check /*= NULL*/)
duration << sWorld->getIntConfig(CONFIG_WARDEN_CLIENT_BAN_DURATION) << "s";
std::string accountName;
AccountMgr::GetName(_session->GetAccountId(), accountName);
- sWorld->BanAccount(BAN_ACCOUNT, accountName, duration.str(), "Warden Anticheat violation","Server");
+ std::stringstream banReason;
+ banReason << "Warden Anticheat Violation: " << check->Comment << " (CheckId: " << check->CheckId << ")";
+ sWorld->BanAccount(BAN_ACCOUNT, accountName, duration.str(), banReason.str(),"Server");
return "Ban";
break;
diff --git a/src/server/game/Warden/WardenCheckMgr.cpp b/src/server/game/Warden/WardenCheckMgr.cpp
index 90d1cfc0140..f4c7a5069cf 100644
--- a/src/server/game/Warden/WardenCheckMgr.cpp
+++ b/src/server/game/Warden/WardenCheckMgr.cpp
@@ -63,8 +63,8 @@ void WardenCheckMgr::LoadWardenChecks()
CheckStore.resize(maxCheckId + 1);
- // 0 1 2 3 4 5 6
- result = WorldDatabase.Query("SELECT id, type, data, result, address, length, str FROM warden_checks ORDER BY id ASC");
+ // 0 1 2 3 4 5 6 7
+ result = WorldDatabase.Query("SELECT id, type, data, result, address, length, str, comment FROM warden_checks ORDER BY id ASC");
uint32 count = 0;
do
@@ -78,9 +78,11 @@ void WardenCheckMgr::LoadWardenChecks()
uint32 address = fields[4].GetUInt32();
uint8 length = fields[5].GetUInt8();
std::string str = fields[6].GetString();
+ std::string comment = fields[7].GetString();
WardenCheck* wardenCheck = new WardenCheck();
wardenCheck->Type = checkType;
+ wardenCheck->CheckId = id;
// Initialize action with default action from config
wardenCheck->Action = WardenActions(sWorld->getIntConfig(CONFIG_WARDEN_CLIENT_FAIL_ACTION));
@@ -134,6 +136,11 @@ void WardenCheckMgr::LoadWardenChecks()
CheckResultStore[id] = wr;
}
+ if (comment.empty())
+ wardenCheck->Comment = "Undocumented Check";
+ else
+ wardenCheck->Comment = comment;
+
++count;
}
while (result->NextRow());
diff --git a/src/server/game/Warden/WardenCheckMgr.h b/src/server/game/Warden/WardenCheckMgr.h
index 45de18081c2..7a83d8f0c6d 100644
--- a/src/server/game/Warden/WardenCheckMgr.h
+++ b/src/server/game/Warden/WardenCheckMgr.h
@@ -36,6 +36,8 @@ struct WardenCheck
uint32 Address; // PROC_CHECK, MEM_CHECK, PAGE_CHECK
uint8 Length; // PROC_CHECK, MEM_CHECK, PAGE_CHECK
std::string Str; // LUA, MPQ, DRIVER
+ std::string Comment;
+ uint16 CheckId;
enum WardenActions Action;
};
diff --git a/src/server/scripts/Commands/cs_modify.cpp b/src/server/scripts/Commands/cs_modify.cpp
index 32ee96dacfe..bb3a4d65b76 100644
--- a/src/server/scripts/Commands/cs_modify.cpp
+++ b/src/server/scripts/Commands/cs_modify.cpp
@@ -1234,7 +1234,7 @@ public:
return false;
}
- target->GetReputationMgr().SetReputation(factionEntry, amount);
+ target->GetReputationMgr().SetOneFactionReputation(factionEntry, amount, false);
handler->PSendSysMessage(LANG_COMMAND_MODIFY_REP, factionEntry->name[handler->GetSessionDbcLocale()], factionId,
handler->GetNameLink(target).c_str(), target->GetReputationMgr().GetReputation(factionEntry));
return true;
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
index 541e52fb922..273f2a20b4b 100755
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
@@ -64,6 +64,9 @@ enum Spells
SPELL_MALLEABLE_GOO = 70852,
SPELL_UNSTABLE_EXPERIMENT = 70351,
SPELL_TEAR_GAS = 71617, // phase transition
+ SPELL_TEAR_GAS_CREATURE = 71618,
+ SPELL_TEAR_GAS_CANCEL = 71620,
+ SPELL_TEAR_GAS_PERIODIC_TRIGGER = 73170,
SPELL_CREATE_CONCOCTION = 71621,
SPELL_GUZZLE_POTIONS = 71893,
SPELL_OOZE_TANK_PROTECTION = 71770, // protects the tank
@@ -86,6 +89,7 @@ enum Spells
SPELL_GASEOUS_BLOAT_PROC = 70215,
SPELL_GASEOUS_BLOAT = 70672,
SPELL_GASEOUS_BLOAT_PROTECTION = 70812,
+ SPELL_EXPUNGED_GAS = 70701,
// Volatile Ooze
SPELL_OOZE_ERUPTION = 70492,
@@ -595,13 +599,15 @@ class boss_professor_putricide : public CreatureScript
break;
case EVENT_TEAR_GAS:
me->GetMotionMaster()->MovePoint(POINT_TABLE, tablePos);
+ DoCast(me, SPELL_TEAR_GAS_PERIODIC_TRIGGER, true);
break;
case EVENT_RESUME_ATTACK:
me->SetReactState(REACT_DEFENSIVE);
AttackStart(me->getVictim());
// remove Tear Gas
+ me->RemoveAurasDueToSpell(SPELL_TEAR_GAS_PERIODIC_TRIGGER);
instance->DoRemoveAurasDueToSpellOnPlayers(71615);
- instance->DoRemoveAurasDueToSpellOnPlayers(71618);
+ DoCastAOE(SPELL_TEAR_GAS_CANCEL);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_GAS_VARIABLE);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_OOZE_VARIABLE);
break;
@@ -699,27 +705,36 @@ class npc_volatile_ooze : public CreatureScript
public:
npc_volatile_ooze() : CreatureScript("npc_volatile_ooze") { }
- struct npc_volatile_oozeAI : public ScriptedAI
+ struct npc_putricide_oozeAI : public ScriptedAI
{
- npc_volatile_oozeAI(Creature* creature) : ScriptedAI(creature)
+ npc_putricide_oozeAI(Creature* creature) : ScriptedAI(creature)
{
_newTargetSelectTimer = 0;
}
void SpellHitTarget(Unit* /*target*/, SpellInfo const* spell)
{
- if (!_newTargetSelectTimer && sSpellMgr->GetSpellDifficultyId(spell->Id) == sSpellMgr->GetSpellDifficultyId(SPELL_OOZE_ERUPTION))
+ if (!_newTargetSelectTimer && spell->Id == sSpellMgr->GetSpellIdForDifficulty(SPELL_OOZE_ERUPTION, me))
+ _newTargetSelectTimer = 1000;
+ }
+
+ void SpellHit(Unit* /*caster*/, SpellInfo const* spell)
+ {
+ if (spell->Id == SPELL_TEAR_GAS_CREATURE)
_newTargetSelectTimer = 1000;
}
void UpdateAI(uint32 const diff)
{
- if (!UpdateVictim())
+ if (!UpdateVictim() && !_newTargetSelectTimer)
return;
if (!_newTargetSelectTimer)
return;
+ if (me->HasAura(SPELL_TEAR_GAS_CREATURE))
+ return;
+
if (_newTargetSelectTimer <= diff)
{
_newTargetSelectTimer = 0;
@@ -730,13 +745,68 @@ class npc_volatile_ooze : public CreatureScript
}
private:
- // no need to use EventMap for just one event
uint32 _newTargetSelectTimer;
};
CreatureAI* GetAI(Creature* creature) const
{
- return GetIcecrownCitadelAI<npc_volatile_oozeAI>(creature);
+ return GetIcecrownCitadelAI<npc_putricide_oozeAI>(creature);
+ }
+};
+
+class npc_gas_cloud : public CreatureScript
+{
+ public:
+ npc_gas_cloud() : CreatureScript("npc_gas_cloud") { }
+
+ struct npc_gas_cloudAI : public ScriptedAI
+ {
+ npc_gas_cloudAI(Creature* creature) : ScriptedAI(creature)
+ {
+ _newTargetSelectTimer = 0;
+ }
+
+ void SpellHitTarget(Unit* /*target*/, SpellInfo const* spell)
+ {
+ if (!_newTargetSelectTimer && spell->Id == sSpellMgr->GetSpellIdForDifficulty(SPELL_EXPUNGED_GAS, me))
+ _newTargetSelectTimer = 1000;
+ }
+
+ void SpellHit(Unit* /*caster*/, SpellInfo const* spell)
+ {
+ if (spell->Id == SPELL_TEAR_GAS_CREATURE)
+ _newTargetSelectTimer = 1000;
+ }
+
+ void UpdateAI(uint32 const diff)
+ {
+ if (!UpdateVictim() && !_newTargetSelectTimer)
+ return;
+
+ DoMeleeAttackIfReady();
+
+ if (!_newTargetSelectTimer)
+ return;
+
+ if (me->HasAura(SPELL_TEAR_GAS_CREATURE))
+ return;
+
+ if (_newTargetSelectTimer <= diff)
+ {
+ _newTargetSelectTimer = 0;
+ me->CastCustomSpell(SPELL_GASEOUS_BLOAT, SPELLVALUE_AURA_STACK, 10, me, false);
+ }
+ else
+ _newTargetSelectTimer -= diff;
+ }
+
+ private:
+ uint32 _newTargetSelectTimer;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetIcecrownCitadelAI<npc_gas_cloudAI>(creature);
}
};
@@ -755,8 +825,8 @@ class spell_putricide_gaseous_bloat : public SpellScriptLoader
if (Unit* caster = GetCaster())
{
target->RemoveAuraFromStack(GetSpellInfo()->Id, GetCasterGUID());
- if (!target->HasAura(GetId())&& caster->GetTypeId() == TYPEID_UNIT)
- caster->ToCreature()->DespawnOrUnsummon();
+ if (!target->HasAura(GetId()))
+ caster->CastCustomSpell(SPELL_GASEOUS_BLOAT, SPELLVALUE_AURA_STACK, 10, caster, false);
}
}
@@ -823,7 +893,19 @@ class spell_putricide_ooze_channel : public SpellScriptLoader
void StartAttack()
{
GetCaster()->ClearUnitState(UNIT_STATE_CASTING);
+ GetCaster()->DeleteThreatList();
GetCaster()->ToCreature()->AI()->AttackStart(GetHitUnit());
+ GetCaster()->AddThreat(GetHitUnit(), 500000000.0f); // value seen in sniff
+ }
+
+ // temporary, until SelectTarget are not called on empty lists
+ void CheckTarget()
+ {
+ if (_target)
+ return;
+
+ FinishCast(SPELL_FAILED_NO_VALID_TARGETS);
+ GetCaster()->ToCreature()->DespawnOrUnsummon(1); // despawn next update
}
void Register()
@@ -832,6 +914,7 @@ class spell_putricide_ooze_channel : public SpellScriptLoader
OnUnitTargetSelect += SpellUnitTargetFn(spell_putricide_ooze_channel_SpellScript::SetTarget, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY);
OnUnitTargetSelect += SpellUnitTargetFn(spell_putricide_ooze_channel_SpellScript::SetTarget, EFFECT_2, TARGET_UNIT_SRC_AREA_ENEMY);
AfterHit += SpellHitFn(spell_putricide_ooze_channel_SpellScript::StartAttack);
+ OnCast += SpellCastFn(spell_putricide_ooze_channel_SpellScript::CheckTarget);
}
Unit* _target;
@@ -931,13 +1014,13 @@ class spell_putricide_unstable_experiment : public SpellScriptLoader
uint32 stage = GetCaster()->ToCreature()->AI()->GetData(DATA_EXPERIMENT_STAGE);
Creature* target = NULL;
std::list<Creature*> creList;
- GetCreatureListWithEntryInGrid(creList, GetCaster(), NPC_ABOMINATION_WING_MAD_SCIENTIST_STALKER, 100.0f);
+ GetCreatureListWithEntryInGrid(creList, GetCaster(), NPC_ABOMINATION_WING_MAD_SCIENTIST_STALKER, 200.0f);
// 2 of them are spawned at green place - weird trick blizz
for (std::list<Creature*>::iterator itr = creList.begin(); itr != creList.end(); ++itr)
{
target = *itr;
std::list<Creature*> tmp;
- GetCreatureListWithEntryInGrid(tmp, target, NPC_ABOMINATION_WING_MAD_SCIENTIST_STALKER, 1.0f);
+ GetCreatureListWithEntryInGrid(tmp, target, NPC_ABOMINATION_WING_MAD_SCIENTIST_STALKER, 10.0f);
if ((!stage && tmp.size() > 1) || (stage && tmp.size() == 1))
break;
}
@@ -957,42 +1040,6 @@ class spell_putricide_unstable_experiment : public SpellScriptLoader
}
};
-class spell_putricide_ooze_summon : public SpellScriptLoader
-{
- public:
- spell_putricide_ooze_summon() : SpellScriptLoader("spell_putricide_ooze_summon") { }
-
- class spell_putricide_ooze_summon_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_putricide_ooze_summon_AuraScript);
-
- void HandleTriggerSpell(AuraEffect const* aurEff)
- {
- PreventDefaultAction();
- if (Unit* caster = GetCaster())
- {
- uint32 triggerSpellId = GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell;
- float x, y, z;
- GetTarget()->GetPosition(x, y, z);
- z = GetTarget()->GetMap()->GetHeight(GetTarget()->GetPhaseMask(), x, y, z, true, 25.0f);
- x += 10.0f * cosf(caster->GetOrientation());
- y += 10.0f * sinf(caster->GetOrientation());
- caster->CastSpell(x, y, z, triggerSpellId, true, NULL, NULL, GetCasterGUID());
- }
- }
-
- void Register()
- {
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_putricide_ooze_summon_AuraScript::HandleTriggerSpell, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
- }
- };
-
- AuraScript* GetAuraScript() const
- {
- return new spell_putricide_ooze_summon_AuraScript();
- }
-};
-
class spell_putricide_ooze_eruption_searcher : public SpellScriptLoader
{
public:
@@ -1455,14 +1502,15 @@ class spell_putricide_regurgitated_ooze : public SpellScriptLoader
}
};
-class spell_putricide_clear_mutated_plague : public SpellScriptLoader
+// Removes aura with id stored in effect value
+class spell_putricide_clear_aura_effect_value : public SpellScriptLoader
{
public:
- spell_putricide_clear_mutated_plague() : SpellScriptLoader("spell_putricide_clear_mutated_plague") { }
+ spell_putricide_clear_aura_effect_value() : SpellScriptLoader("spell_putricide_clear_aura_effect_value") { }
- class spell_putricide_clear_mutated_plague_SpellScript : public SpellScript
+ class spell_putricide_clear_aura_effect_value_SpellScript : public SpellScript
{
- PrepareSpellScript(spell_putricide_clear_mutated_plague_SpellScript);
+ PrepareSpellScript(spell_putricide_clear_aura_effect_value_SpellScript);
void HandleScript(SpellEffIndex effIndex)
{
@@ -1473,13 +1521,13 @@ class spell_putricide_clear_mutated_plague : public SpellScriptLoader
void Register()
{
- OnEffectHitTarget += SpellEffectFn(spell_putricide_clear_mutated_plague_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ OnEffectHitTarget += SpellEffectFn(spell_putricide_clear_aura_effect_value_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
SpellScript* GetSpellScript() const
{
- return new spell_putricide_clear_mutated_plague_SpellScript();
+ return new spell_putricide_clear_aura_effect_value_SpellScript();
}
};
@@ -1518,12 +1566,12 @@ void AddSC_boss_professor_putricide()
{
new boss_professor_putricide();
new npc_volatile_ooze();
+ new npc_gas_cloud();
new spell_putricide_gaseous_bloat();
new spell_putricide_ooze_channel();
new spell_putricide_slime_puddle();
new spell_putricide_slime_puddle_aura();
new spell_putricide_unstable_experiment();
- new spell_putricide_ooze_summon();
new spell_putricide_ooze_eruption_searcher();
new spell_putricide_choking_gas_bomb();
new spell_putricide_unbound_plague();
@@ -1534,6 +1582,6 @@ void AddSC_boss_professor_putricide()
new spell_putricide_mutated_transformation();
new spell_putricide_mutated_transformation_dmg();
new spell_putricide_regurgitated_ooze();
- new spell_putricide_clear_mutated_plague();
+ new spell_putricide_clear_aura_effect_value();
new spell_stinky_precious_decimate();
}
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
index e12393f047f..22858cf69e5 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
@@ -234,7 +234,6 @@ class instance_ulduar : public InstanceMapScript
case NPC_ALGALON:
AlgalonGUID = creature->GetGUID();
break;
-
// Hodir's Helper NPCs
case NPC_EIVI_NIGHTFEATHER:
if (TeamInInstance == HORDE)
diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp
index 1a0f4576fea..84e3bd8d604 100644
--- a/src/server/scripts/Spells/spell_shaman.cpp
+++ b/src/server/scripts/Spells/spell_shaman.cpp
@@ -35,6 +35,9 @@ enum ShamanSpells
SHAMAN_SPELL_FIRE_NOVA_TRIGGERED_R1 = 8349,
SHAMAN_SPELL_SATED = 57724,
SHAMAN_SPELL_EXHAUSTION = 57723,
+
+ SHAMAN_SPELL_STORM_EARTH_AND_FIRE = 51483,
+ EARTHBIND_TOTEM_SPELL_EARTHGRAB = 64695,
// For Earthen Power
SHAMAN_TOTEM_SPELL_EARTHBIND_TOTEM = 6474,
@@ -221,9 +224,25 @@ class spell_sha_earthbind_totem : public SpellScriptLoader
caster->CastSpell(caster, SHAMAN_TOTEM_SPELL_EARTHEN_POWER, true, NULL, aurEff);
}
+ void Apply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (!GetCaster())
+ return;
+ Player* owner = GetCaster()->GetCharmerOrOwnerPlayerOrPlayerItself();
+ if (!owner)
+ return;
+ // Storm, Earth and Fire
+ if (AuraEffect* aurEff = owner->GetAuraEffectOfRankedSpell(SHAMAN_SPELL_STORM_EARTH_AND_FIRE, EFFECT_1))
+ {
+ if (roll_chance_i(aurEff->GetAmount()))
+ GetCaster()->CastSpell(GetCaster(), EARTHBIND_TOTEM_SPELL_EARTHGRAB, false);
+ }
+ }
+
void Register()
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_sha_earthbind_totem_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ OnEffectApply += AuraEffectApplyFn(spell_sha_earthbind_totem_AuraScript::Apply, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
}
};
diff --git a/src/server/scripts/Spells/spell_warrior.cpp b/src/server/scripts/Spells/spell_warrior.cpp
index 66e44112b8a..3e4c043ae47 100644
--- a/src/server/scripts/Spells/spell_warrior.cpp
+++ b/src/server/scripts/Spells/spell_warrior.cpp
@@ -365,7 +365,7 @@ class spell_warr_concussion_blow : public SpellScriptLoader
void HandleDummy(SpellEffIndex /* effIndex */)
{
- SetHitDamage(GetHitDamage() + CalculatePctF(GetHitDamage(),GetCaster()->GetTotalAttackPowerValue(BASE_ATTACK)));
+ SetHitDamage(CalculatePctN(GetCaster()->GetTotalAttackPowerValue(BASE_ATTACK), GetEffectValue()));
}
void Register()
diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp
index 6858827ed8e..61b997bba35 100644
--- a/src/server/scripts/World/npcs_special.cpp
+++ b/src/server/scripts/World/npcs_special.cpp
@@ -2400,6 +2400,9 @@ enum eLockSmith
QUEST_HOTTER_THAN_HELL_H = 10764,
QUEST_RETURN_TO_KHAGDAR = 9837,
QUEST_CONTAINMENT = 13159,
+ QUEST_ETERNAL_VIGILANCE = 11011,
+ QUEST_KEY_TO_THE_FOCUSING_IRIS = 13372,
+ QUEST_HC_KEY_TO_THE_FOCUSING_IRIS = 13375,
ITEM_ARCATRAZ_KEY = 31084,
ITEM_SHADOWFORGE_KEY = 11000,
@@ -2407,21 +2410,28 @@ enum eLockSmith
ITEM_SHATTERED_HALLS_KEY = 28395,
ITEM_THE_MASTERS_KEY = 24490,
ITEM_VIOLET_HOLD_KEY = 42482,
+ ITEM_ESSENCE_INFUSED_MOONSTONE = 32449,
+ ITEM_KEY_TO_THE_FOCUSING_IRIS = 44582,
+ ITEM_HC_KEY_TO_THE_FOCUSING_IRIS = 44581,
SPELL_ARCATRAZ_KEY = 54881,
SPELL_SHADOWFORGE_KEY = 54882,
SPELL_SKELETON_KEY = 54883,
SPELL_SHATTERED_HALLS_KEY = 54884,
SPELL_THE_MASTERS_KEY = 54885,
- SPELL_VIOLET_HOLD_KEY = 67253
+ SPELL_VIOLET_HOLD_KEY = 67253,
+ SPELL_ESSENCE_INFUSED_MOONSTONE = 40173,
};
-#define GOSSIP_LOST_ARCATRAZ_KEY "I've lost my key to the Arcatraz."
-#define GOSSIP_LOST_SHADOWFORGE_KEY "I've lost my key to the Blackrock Depths."
-#define GOSSIP_LOST_SKELETON_KEY "I've lost my key to the Scholomance."
-#define GOSSIP_LOST_SHATTERED_HALLS_KEY "I've lost my key to the Shattered Halls."
-#define GOSSIP_LOST_THE_MASTERS_KEY "I've lost my key to the Karazhan."
-#define GOSSIP_LOST_VIOLET_HOLD_KEY "I've lost my key to the Violet Hold."
+#define GOSSIP_LOST_ARCATRAZ_KEY "I've lost my key to the Arcatraz."
+#define GOSSIP_LOST_SHADOWFORGE_KEY "I've lost my key to the Blackrock Depths."
+#define GOSSIP_LOST_SKELETON_KEY "I've lost my key to the Scholomance."
+#define GOSSIP_LOST_SHATTERED_HALLS_KEY "I've lost my key to the Shattered Halls."
+#define GOSSIP_LOST_THE_MASTERS_KEY "I've lost my key to the Karazhan."
+#define GOSSIP_LOST_VIOLET_HOLD_KEY "I've lost my key to the Violet Hold."
+#define GOSSIP_LOST_ESSENCE_INFUSED_MOONSTONE "I've lost my Essence-Infused Moonstone."
+#define GOSSIP_LOST_KEY_TO_THE_FOCUSING_IRIS "I've lost my Key to the Focusing Iris."
+#define GOSSIP_LOST_HC_KEY_TO_THE_FOCUSING_IRIS "I've lost my Heroic Key to the Focusing Iris."
class npc_locksmith : public CreatureScript
{
@@ -2456,6 +2466,18 @@ public:
if (player->GetQuestRewardStatus(QUEST_CONTAINMENT) && !player->HasItemCount(ITEM_VIOLET_HOLD_KEY, 1, true))
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_VIOLET_HOLD_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6);
+ // Essence-Infused Moonstone
+ if (player->GetQuestRewardStatus(QUEST_ETERNAL_VIGILANCE) && !player->HasItemCount(ITEM_ESSENCE_INFUSED_MOONSTONE, 1, true))
+ player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_ESSENCE_INFUSED_MOONSTONE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7);
+
+ // Key to the Focusing Iris
+ if (player->GetQuestRewardStatus(QUEST_KEY_TO_THE_FOCUSING_IRIS) && !player->HasItemCount(ITEM_KEY_TO_THE_FOCUSING_IRIS, 1, true))
+ player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_KEY_TO_THE_FOCUSING_IRIS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8);
+
+ // Heroic Key to the Focusing Iris
+ if (player->GetQuestRewardStatus(QUEST_HC_KEY_TO_THE_FOCUSING_IRIS) && !player->HasItemCount(ITEM_HC_KEY_TO_THE_FOCUSING_IRIS, 1, true))
+ player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_HC_KEY_TO_THE_FOCUSING_IRIS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9);
+
player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
return true;
@@ -2490,6 +2512,18 @@ public:
player->CLOSE_GOSSIP_MENU();
player->CastSpell(player, SPELL_VIOLET_HOLD_KEY, false);
break;
+ case GOSSIP_ACTION_INFO_DEF + 7:
+ player->CLOSE_GOSSIP_MENU();
+ player->CastSpell(player, SPELL_ESSENCE_INFUSED_MOONSTONE, false);
+ break;
+ case GOSSIP_ACTION_INFO_DEF + 8:
+ player->CLOSE_GOSSIP_MENU();
+ player->AddItem(ITEM_KEY_TO_THE_FOCUSING_IRIS,1);
+ break;
+ case GOSSIP_ACTION_INFO_DEF + 9:
+ player->CLOSE_GOSSIP_MENU();
+ player->AddItem(ITEM_HC_KEY_TO_THE_FOCUSING_IRIS,1);
+ break;
}
return true;
}
diff --git a/src/server/shared/Database/DatabaseWorkerPool.h b/src/server/shared/Database/DatabaseWorkerPool.h
index 8b69accfc23..314d196cc06 100755
--- a/src/server/shared/Database/DatabaseWorkerPool.h
+++ b/src/server/shared/Database/DatabaseWorkerPool.h
@@ -102,7 +102,7 @@ class DatabaseWorkerPool
//! Shuts down delaythreads for this connection pool by underlying deactivate().
//! The next dequeue attempt in the worker thread tasks will result in an error,
- //! ultimately ending the worker thread task.
+ //! ultimately ending the worker thread task.
_queue->queue()->close();
for (uint8 i = 0; i < _connectionCount[IDX_ASYNC]; ++i)
@@ -114,7 +114,7 @@ class DatabaseWorkerPool
t->Close(); //! Closes the actualy MySQL connection.
}
- sLog->outSQLDriver("Asynchronous connections on DatabasePool '%s' terminated. Proceeding with synchronous connections.",
+ sLog->outSQLDriver("Asynchronous connections on DatabasePool '%s' terminated. Proceeding with synchronous connections.",
GetDatabaseName());
//! Shut down the synchronous connections