diff options
Diffstat (limited to 'src')
85 files changed, 1707 insertions, 1418 deletions
diff --git a/src/server/game/AI/CoreAI/CombatAI.cpp b/src/server/game/AI/CoreAI/CombatAI.cpp index da55a073679..943919451a9 100644 --- a/src/server/game/AI/CoreAI/CombatAI.cpp +++ b/src/server/game/AI/CoreAI/CombatAI.cpp @@ -23,6 +23,10 @@ #include "ObjectAccessor.h" #include "Player.h" +///////////////// +// AggressorAI +///////////////// + int AggressorAI::Permissible(const Creature* creature) { // have some hostile factions, it will be selected by IsHostileTo check at MoveInLineOfSight @@ -40,26 +44,9 @@ void AggressorAI::UpdateAI(uint32 /*diff*/) DoMeleeAttackIfReady(); } -// some day we will delete these useless things -int CombatAI::Permissible(const Creature* /*creature*/) -{ - return PERMIT_BASE_NO; -} - -int ArcherAI::Permissible(const Creature* /*creature*/) -{ - return PERMIT_BASE_NO; -} - -int TurretAI::Permissible(const Creature* /*creature*/) -{ - return PERMIT_BASE_NO; -} - -int VehicleAI::Permissible(const Creature* /*creature*/) -{ - return PERMIT_BASE_NO; -} +///////////////// +// CombatAI +///////////////// void CombatAI::InitializeAI() { @@ -118,7 +105,7 @@ void CombatAI::SpellInterrupted(uint32 spellId, uint32 unTimeMs) } ///////////////// -//CasterAI +// CasterAI ///////////////// void CasterAI::InitializeAI() @@ -182,7 +169,7 @@ void CasterAI::UpdateAI(uint32 diff) } ////////////// -//ArcherAI +// ArcherAI ////////////// ArcherAI::ArcherAI(Creature* c) : CreatureAI(c) @@ -231,7 +218,7 @@ void ArcherAI::UpdateAI(uint32 /*diff*/) } ////////////// -//TurretAI +// TurretAI ////////////// TurretAI::TurretAI(Creature* c) : CreatureAI(c) @@ -269,17 +256,17 @@ void TurretAI::UpdateAI(uint32 /*diff*/) } ////////////// -//VehicleAI +// VehicleAI ////////////// -VehicleAI::VehicleAI(Creature* c) : CreatureAI(c), m_IsVehicleInUse(false), m_ConditionsTimer(VEHICLE_CONDITION_CHECK_TIME) +VehicleAI::VehicleAI(Creature* creature) : CreatureAI(creature), m_ConditionsTimer(VEHICLE_CONDITION_CHECK_TIME) { LoadConditions(); m_DoDismiss = false; m_DismissTimer = VEHICLE_DISMISS_TIME; } -//NOTE: VehicleAI::UpdateAI runs even while the vehicle is mounted +// NOTE: VehicleAI::UpdateAI runs even while the vehicle is mounted void VehicleAI::UpdateAI(uint32 diff) { CheckConditions(diff); @@ -289,7 +276,6 @@ void VehicleAI::UpdateAI(uint32 diff) if (m_DismissTimer < diff) { m_DoDismiss = false; - me->SetVisible(false); me->DespawnOrUnsummon(); } else @@ -297,24 +283,16 @@ void VehicleAI::UpdateAI(uint32 diff) } } -void VehicleAI::Reset() -{ - me->SetVisible(true); -} - void VehicleAI::OnCharmed(bool apply) { - if (m_IsVehicleInUse && !apply && !conditions.empty())//was used and has conditions + if (!me->GetVehicleKit()->IsVehicleInUse() && !apply && !conditions.empty()) // was used and has conditions { - m_DoDismiss = true;//needs reset - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE); - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + m_DoDismiss = true; // needs reset } else if (apply) - m_DoDismiss = false;//in use again + m_DoDismiss = false; // in use again - m_DismissTimer = VEHICLE_DISMISS_TIME;//reset timer - m_IsVehicleInUse = apply; + m_DismissTimer = VEHICLE_DISMISS_TIME; // reset timer } void VehicleAI::LoadConditions() @@ -324,7 +302,7 @@ void VehicleAI::LoadConditions() TC_LOG_DEBUG("condition", "VehicleAI::LoadConditions: loaded %u conditions", uint32(conditions.size())); } -void VehicleAI::CheckConditions(const uint32 diff) +void VehicleAI::CheckConditions(uint32 diff) { if (m_ConditionsTimer < diff) { @@ -339,7 +317,7 @@ void VehicleAI::CheckConditions(const uint32 diff) if (!sConditionMgr->IsObjectMeetToConditions(player, me, conditions)) { player->ExitVehicle(); - return;//check other pessanger in next tick + return; // check other pessanger in next tick } } } diff --git a/src/server/game/AI/CoreAI/CombatAI.h b/src/server/game/AI/CoreAI/CombatAI.h index 10716627e85..f73daa2d720 100644 --- a/src/server/game/AI/CoreAI/CombatAI.h +++ b/src/server/game/AI/CoreAI/CombatAI.h @@ -47,7 +47,9 @@ class CombatAI : public CreatureAI void JustDied(Unit* killer); void UpdateAI(uint32 diff); void SpellInterrupted(uint32 spellId, uint32 unTimeMs); - static int Permissible(const Creature*); + + static int Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; } + protected: EventMap events; SpellVct spells; @@ -72,7 +74,8 @@ struct ArcherAI : public CreatureAI void AttackStart(Unit* who); void UpdateAI(uint32 diff); - static int Permissible(Creature const*); + static int Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; } + protected: float m_minRange; }; @@ -85,29 +88,30 @@ struct TurretAI : public CreatureAI void AttackStart(Unit* who); void UpdateAI(uint32 diff); - static int Permissible(Creature const*); + static int Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; } + protected: float m_minRange; }; #define VEHICLE_CONDITION_CHECK_TIME 1000 #define VEHICLE_DISMISS_TIME 5000 + struct VehicleAI : public CreatureAI { public: - explicit VehicleAI(Creature* c); + explicit VehicleAI(Creature* creature); void UpdateAI(uint32 diff); - static int Permissible(Creature const*); - void Reset(); void MoveInLineOfSight(Unit*) { } void AttackStart(Unit*) { } void OnCharmed(bool apply); + static int Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; } + private: - bool m_IsVehicleInUse; void LoadConditions(); - void CheckConditions(const uint32 diff); + void CheckConditions(uint32 diff); ConditionList conditions; uint32 m_ConditionsTimer; bool m_DoDismiss; diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index d6aa30dff23..a203aeb6b97 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -439,6 +439,8 @@ void SmartAI::EnterEvadeMode() me->LoadCreaturesAddon(); me->SetLootRecipient(NULL); me->ResetPlayerDamageReq(); + me->SetLastDamagedTime(0); + GetScript()->ProcessEventsFor(SMART_EVENT_EVADE);//must be after aura clear so we can cast spells from db SetRun(mRun); @@ -574,7 +576,7 @@ void SmartAI::JustReachedHome() GetScript()->ProcessEventsFor(SMART_EVENT_REACHED_HOME); if (!UpdateVictim() && me->GetMotionMaster()->GetCurrentMovementGeneratorType() == IDLE_MOTION_TYPE && me->GetWaypointPath()) - me->ToCreature()->GetMotionMaster()->MovePath(me->GetWaypointPath(), true); + me->GetMotionMaster()->MovePath(me->GetWaypointPath(), true); } mJustReset = false; @@ -904,12 +906,6 @@ bool SmartGameObjectAI::QuestReward(Player* player, Quest const* quest, uint32 o return false; } -// Called when the dialog status between a player and the gameobject is requested. -uint32 SmartGameObjectAI::GetDialogStatus(Player* /*player*/) -{ - return DIALOG_STATUS_SCRIPTED_NO_STATUS; -} - // Called when the gameobject is destroyed (destructible buildings only). void SmartGameObjectAI::Destroyed(Player* player, uint32 eventId) { diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h index 83f2ae0b4d9..dcf64b657f8 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.h +++ b/src/server/game/AI/SmartScripts/SmartAI.h @@ -236,7 +236,7 @@ class SmartAI : public CreatureAI class SmartGameObjectAI : public GameObjectAI { public: - SmartGameObjectAI(GameObject* g) : GameObjectAI(g), go(g) { } + SmartGameObjectAI(GameObject* g) : GameObjectAI(g) { } ~SmartGameObjectAI() { } void UpdateAI(uint32 diff); @@ -250,7 +250,6 @@ class SmartGameObjectAI : public GameObjectAI bool GossipSelectCode(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/, const char* /*code*/); bool QuestAccept(Player* player, Quest const* quest); bool QuestReward(Player* player, Quest const* quest, uint32 opt); - uint32 GetDialogStatus(Player* /*player*/); void Destroyed(Player* player, uint32 eventId); void SetData(uint32 id, uint32 value); void SetScript9(SmartScriptHolder& e, uint32 entry, Unit* invoker); @@ -258,8 +257,7 @@ class SmartGameObjectAI : public GameObjectAI void OnStateChanged(uint32 state, Unit* unit); void EventInform(uint32 eventId); - protected: - GameObject* const go; + private: SmartScript mScript; }; #endif diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 5efab2214b6..bd51fe0a85b 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -2551,7 +2551,10 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* { ObjectListMap::iterator itr = mTargetStorage->find(e.target.stored.id); if (itr != mTargetStorage->end()) - l->assign(itr->second->begin(), itr->second->end()); + { + ObjectList* objectList = itr->second->GetObjectList(); + l->assign(objectList->begin(), objectList->end()); + } return l; } diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index 56b3674bd73..2e1068d1bff 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -99,13 +99,13 @@ class SmartScript if (mTargetStorage->find(id) != mTargetStorage->end()) { // check if already stored - if ((*mTargetStorage)[id] == targets) + if ((*mTargetStorage)[id]->Equals(targets)) return; delete (*mTargetStorage)[id]; } - (*mTargetStorage)[id] = targets; + (*mTargetStorage)[id] = new ObjectGuidList(targets, GetBaseObject()); } bool IsSmart(Creature* c = NULL) @@ -141,7 +141,7 @@ class SmartScript { ObjectListMap::iterator itr = mTargetStorage->find(id); if (itr != mTargetStorage->end()) - return (*itr).second; + return (*itr).second->GetObjectList(); return NULL; } diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index be074c2939f..9ba5ccc578e 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -1321,7 +1321,58 @@ struct SmartScriptHolder typedef UNORDERED_MAP<uint32, WayPoint*> WPPath; typedef std::list<WorldObject*> ObjectList; -typedef UNORDERED_MAP<uint32, ObjectList*> ObjectListMap; +typedef std::list<uint64> GuidList; +class ObjectGuidList +{ + ObjectList* m_objectList; + GuidList* m_guidList; + WorldObject* m_baseObject; + +public: + ObjectGuidList(ObjectList* objectList, WorldObject* baseObject) + { + ASSERT(objectList != NULL); + m_objectList = objectList; + m_baseObject = baseObject; + m_guidList = new GuidList(); + + for (ObjectList::iterator itr = objectList->begin(); itr != objectList->end(); ++itr) + { + m_guidList->push_back((*itr)->GetGUID()); + } + } + + ObjectList* GetObjectList() + { + if (m_baseObject) + { + //sanitize list using m_guidList + m_objectList->clear(); + + for (GuidList::iterator itr = m_guidList->begin(); itr != m_guidList->end(); ++itr) + { + if (WorldObject* obj = ObjectAccessor::GetWorldObject(*m_baseObject, *itr)) + m_objectList->push_back(obj); + else + TC_LOG_DEBUG("scripts.ai", "SmartScript::mTargetStorage stores a guid to an invalid object: " UI64FMTD, *itr); + } + } + + return m_objectList; + } + + bool Equals(ObjectList* objectList) + { + return m_objectList == objectList; + } + + ~ObjectGuidList() + { + delete m_objectList; + delete m_guidList; + } +}; +typedef UNORDERED_MAP<uint32, ObjectGuidList*> ObjectListMap; class SmartWaypointMgr { diff --git a/src/server/game/Battlefield/BattlefieldMgr.cpp b/src/server/game/Battlefield/BattlefieldMgr.cpp index 300bf44c8a7..8aa58f0ac4b 100644 --- a/src/server/game/Battlefield/BattlefieldMgr.cpp +++ b/src/server/game/Battlefield/BattlefieldMgr.cpp @@ -16,125 +16,130 @@ */ #include "BattlefieldMgr.h" -#include "Zones/BattlefieldWG.h" +#include "BattlefieldWG.h" #include "ObjectMgr.h" #include "Player.h" BattlefieldMgr::BattlefieldMgr() { - m_UpdateTimer = 0; - //TC_LOG_DEBUG("bg.battlefield", "Instantiating BattlefieldMgr"); + _updateTimer = 0; } BattlefieldMgr::~BattlefieldMgr() { - //TC_LOG_DEBUG("bg.battlefield", "Deleting BattlefieldMgr"); - for (BattlefieldSet::iterator itr = m_BattlefieldSet.begin(); itr != m_BattlefieldSet.end(); ++itr) + for (BattlefieldSet::iterator itr = _battlefieldSet.begin(); itr != _battlefieldSet.end(); ++itr) delete *itr; + + _battlefieldMap.clear(); } void BattlefieldMgr::InitBattlefield() { - Battlefield* pBf = new BattlefieldWG; + Battlefield* wg = new BattlefieldWG(); // respawn, init variables - if (!pBf->SetupBattlefield()) + if (!wg->SetupBattlefield()) { - TC_LOG_INFO("misc", "Battlefield : Wintergrasp init failed."); - delete pBf; + TC_LOG_INFO("bg.battlefield", "Battlefield: Wintergrasp init failed."); + delete wg; } else { - m_BattlefieldSet.push_back(pBf); - TC_LOG_INFO("misc", "Battlefield : Wintergrasp successfully initiated."); + _battlefieldSet.push_back(wg); + TC_LOG_INFO("bg.battlefield", "Battlefield: Wintergrasp successfully initiated."); } - /* For Cataclysm: Tol Barad - pBf = new BattlefieldTB; - // respawn, init variables - if (!pBf->SetupBattlefield()) - { - TC_LOG_DEBUG("bg.battlefield", "Battlefield : Tol Barad init failed."); - delete pBf; - } - else - { - m_BattlefieldSet.push_back(pBf); - TC_LOG_DEBUG("bg.battlefield", "Battlefield : Tol Barad successfully initiated."); - } */ + /* + For Cataclysm: Tol Barad + Battlefield* tb = new BattlefieldTB; + // respawn, init variables + if (!tb->SetupBattlefield()) + { + TC_LOG_DEBUG("bg.battlefield", "Battlefield: Tol Barad init failed."); + delete tb; + } + else + { + _battlefieldSet.push_back(tb); + TC_LOG_DEBUG("bg.battlefield", "Battlefield: Tol Barad successfully initiated."); + } + */ } -void BattlefieldMgr::AddZone(uint32 zoneid, Battlefield *handle) +void BattlefieldMgr::AddZone(uint32 zoneId, Battlefield* bf) { - m_BattlefieldMap[zoneid] = handle; + _battlefieldMap[zoneId] = bf; } -void BattlefieldMgr::HandlePlayerEnterZone(Player* player, uint32 zoneid) +void BattlefieldMgr::HandlePlayerEnterZone(Player* player, uint32 zoneId) { - BattlefieldMap::iterator itr = m_BattlefieldMap.find(zoneid); - if (itr == m_BattlefieldMap.end()) + BattlefieldMap::iterator itr = _battlefieldMap.find(zoneId); + if (itr == _battlefieldMap.end()) return; Battlefield* bf = itr->second; - if (bf->HasPlayer(player) || !bf->IsEnabled()) + if (!bf->IsEnabled() || bf->HasPlayer(player)) return; - bf->HandlePlayerEnterZone(player, zoneid); - TC_LOG_DEBUG("bg.battlefield", "Player %u entered outdoorpvp id %u", player->GetGUIDLow(), bf->GetTypeId()); + bf->HandlePlayerEnterZone(player, zoneId); + TC_LOG_DEBUG("bg.battlefield", "Player %u entered battlefield id %u", player->GetGUIDLow(), bf->GetTypeId()); } -void BattlefieldMgr::HandlePlayerLeaveZone(Player* player, uint32 zoneid) +void BattlefieldMgr::HandlePlayerLeaveZone(Player* player, uint32 zoneId) { - BattlefieldMap::iterator itr = m_BattlefieldMap.find(zoneid); - if (itr == m_BattlefieldMap.end()) + BattlefieldMap::iterator itr = _battlefieldMap.find(zoneId); + if (itr == _battlefieldMap.end()) return; // teleport: remove once in removefromworld, once in updatezone if (!itr->second->HasPlayer(player)) return; - itr->second->HandlePlayerLeaveZone(player, zoneid); - TC_LOG_DEBUG("bg.battlefield", "Player %u left outdoorpvp id %u", player->GetGUIDLow(), itr->second->GetTypeId()); + + itr->second->HandlePlayerLeaveZone(player, zoneId); + TC_LOG_DEBUG("bg.battlefield", "Player %u left battlefield id %u", player->GetGUIDLow(), itr->second->GetTypeId()); } -Battlefield *BattlefieldMgr::GetBattlefieldToZoneId(uint32 zoneid) +Battlefield* BattlefieldMgr::GetBattlefieldToZoneId(uint32 zoneId) { - BattlefieldMap::iterator itr = m_BattlefieldMap.find(zoneid); - if (itr == m_BattlefieldMap.end()) + BattlefieldMap::iterator itr = _battlefieldMap.find(zoneId); + if (itr == _battlefieldMap.end()) { // no handle for this zone, return return NULL; } + if (!itr->second->IsEnabled()) return NULL; + return itr->second; } -Battlefield *BattlefieldMgr::GetBattlefieldByBattleId(uint32 battleid) +Battlefield* BattlefieldMgr::GetBattlefieldByBattleId(uint32 battleId) { - for (BattlefieldSet::iterator itr = m_BattlefieldSet.begin(); itr != m_BattlefieldSet.end(); ++itr) + for (BattlefieldSet::iterator itr = _battlefieldSet.begin(); itr != _battlefieldSet.end(); ++itr) { - if ((*itr)->GetBattleId() == battleid) - return (*itr); + if ((*itr)->GetBattleId() == battleId) + return *itr; } return NULL; } +ZoneScript* BattlefieldMgr::GetZoneScript(uint32 zoneId) +{ + BattlefieldMap::iterator itr = _battlefieldMap.find(zoneId); + if (itr != _battlefieldMap.end()) + return itr->second; + + return NULL; +} + void BattlefieldMgr::Update(uint32 diff) { - m_UpdateTimer += diff; - if (m_UpdateTimer > BATTLEFIELD_OBJECTIVE_UPDATE_INTERVAL) + _updateTimer += diff; + if (_updateTimer > BATTLEFIELD_OBJECTIVE_UPDATE_INTERVAL) { - for (BattlefieldSet::iterator itr = m_BattlefieldSet.begin(); itr != m_BattlefieldSet.end(); ++itr) + for (BattlefieldSet::iterator itr = _battlefieldSet.begin(); itr != _battlefieldSet.end(); ++itr) if ((*itr)->IsEnabled()) - (*itr)->Update(m_UpdateTimer); - m_UpdateTimer = 0; + (*itr)->Update(_updateTimer); + _updateTimer = 0; } } - -ZoneScript* BattlefieldMgr::GetZoneScript(uint32 zoneId) -{ - BattlefieldMap::iterator itr = m_BattlefieldMap.find(zoneId); - if (itr != m_BattlefieldMap.end()) - return itr->second; - else - return NULL; -} diff --git a/src/server/game/Battlefield/BattlefieldMgr.h b/src/server/game/Battlefield/BattlefieldMgr.h index 74ef4a4b2bf..bb8a076d5d0 100644 --- a/src/server/game/Battlefield/BattlefieldMgr.h +++ b/src/server/game/Battlefield/BattlefieldMgr.h @@ -19,60 +19,51 @@ #define BATTLEFIELD_MGR_H_ #include "Battlefield.h" -#include "ace/Singleton.h" +#include <ace/Singleton.h> class Player; -class GameObject; -class Creature; class ZoneScript; -struct GossipMenuItems; // class to handle player enter / leave / areatrigger / GO use events class BattlefieldMgr { - public: - // ctor - BattlefieldMgr(); - // dtor - ~BattlefieldMgr(); + public: + // ctor + BattlefieldMgr(); + // dtor + ~BattlefieldMgr(); - // create battlefield events - void InitBattlefield(); - // called when a player enters an battlefield area - void HandlePlayerEnterZone(Player* player, uint32 areaflag); - // called when player leaves an battlefield area - void HandlePlayerLeaveZone(Player* player, uint32 areaflag); - // called when player resurrects - void HandlePlayerResurrects(Player* player, uint32 areaflag); - // return assigned battlefield - Battlefield* GetBattlefieldToZoneId(uint32 zoneid); - Battlefield* GetBattlefieldByBattleId(uint32 battleid); + // create battlefield events + void InitBattlefield(); - ZoneScript* GetZoneScript(uint32 zoneId); + // called when a player enters an battlefield area + void HandlePlayerEnterZone(Player* player, uint32 zoneId); + // called when player leaves an battlefield area + void HandlePlayerLeaveZone(Player* player, uint32 zoneId); - void AddZone(uint32 zoneid, Battlefield * handle); + // return assigned battlefield + Battlefield* GetBattlefieldToZoneId(uint32 zoneId); + Battlefield* GetBattlefieldByBattleId(uint32 battleId); - void Update(uint32 diff); + ZoneScript* GetZoneScript(uint32 zoneId); - void HandleGossipOption(Player* player, uint64 guid, uint32 gossipid); + void AddZone(uint32 zoneId, Battlefield* bf); - bool CanTalkTo(Player* player, Creature* creature, GossipMenuItems gso); + void Update(uint32 diff); - void HandleDropFlag(Player* player, uint32 spellId); - - typedef std::vector < Battlefield * >BattlefieldSet; - typedef std::map < uint32 /* zoneid */, Battlefield * >BattlefieldMap; - private: - // contains all initiated battlefield events - // used when initing / cleaning up - BattlefieldSet m_BattlefieldSet; - // maps the zone ids to an battlefield event - // used in player event handling - BattlefieldMap m_BattlefieldMap; - // update interval - uint32 m_UpdateTimer; + private: + typedef std::vector<Battlefield*> BattlefieldSet; + typedef std::map<uint32 /*zoneId*/, Battlefield*> BattlefieldMap; + // contains all initiated battlefield events + // used when initing / cleaning up + BattlefieldSet _battlefieldSet; + // maps the zone ids to an battlefield event + // used in player event handling + BattlefieldMap _battlefieldMap; + // update interval + uint32 _updateTimer; }; #define sBattlefieldMgr ACE_Singleton<BattlefieldMgr, ACE_Null_Mutex>::instance() -#endif +#endif // BATTLEFIELD_MGR_H_ diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp index b82b5ae3a9c..7ec5a09508a 100644 --- a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp +++ b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp @@ -30,14 +30,6 @@ #include "Vehicle.h" #include "WorldSession.h" -enum WGVehicles -{ - NPC_WG_SEIGE_ENGINE_ALLIANCE = 28312, - NPC_WG_SEIGE_ENGINE_HORDE = 32627, - NPC_WG_DEMOLISHER = 28094, - NPC_WG_CATAPULT = 27881 -}; - BattlefieldWG::~BattlefieldWG() { for (Workshop::const_iterator itr = WorkshopsList.begin(); itr != WorkshopsList.end(); ++itr) @@ -192,7 +184,7 @@ bool BattlefieldWG::SetupBattlefield() if (GameObject* go = SpawnGameObject(WGPortalDefenderData[i].entry, WGPortalDefenderData[i].x, WGPortalDefenderData[i].y, WGPortalDefenderData[i].z, WGPortalDefenderData[i].o)) { DefenderPortalList.insert(go->GetGUID()); - go->SetUInt32Value(GAMEOBJECT_FACTION, WintergraspFaction[GetDefenderTeam()]); + go->SetFaction(WintergraspFaction[GetDefenderTeam()]); } } @@ -222,7 +214,7 @@ void BattlefieldWG::OnBattleStart() if (GameObject* relic = SpawnGameObject(GO_WINTERGRASP_TITAN_S_RELIC, 5440.0f, 2840.8f, 430.43f, 0)) { // Update faction of relic, only attacker can click on - relic->SetUInt32Value(GAMEOBJECT_FACTION, WintergraspFaction[GetAttackerTeam()]); + relic->SetFaction(WintergraspFaction[GetAttackerTeam()]); // Set in use (not allow to click on before last door is broken) relic->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE); m_titansRelicGUID = relic->GetGUID(); @@ -360,7 +352,7 @@ void BattlefieldWG::OnBattleEnd(bool endByTimer) // Update portal defender faction for (GuidSet::const_iterator itr = DefenderPortalList.begin(); itr != DefenderPortalList.end(); ++itr) if (GameObject* portal = GetGameObject(*itr)) - portal->SetUInt32Value(GAMEOBJECT_FACTION, WintergraspFaction[GetDefenderTeam()]); + portal->SetFaction(WintergraspFaction[GetDefenderTeam()]); // Saving data for (GameObjectBuilding::const_iterator itr = BuildingsInZone.begin(); itr != BuildingsInZone.end(); ++itr) @@ -813,6 +805,9 @@ uint32 BattlefieldWG::GetData(uint32 data) const // Graveyards and Workshops are controlled by the same team. if (BfGraveyard const* graveyard = GetGraveyardById(GetSpiritGraveyardId(data))) return graveyard->GetControlTeamId(); + break; + default: + break; } return Battlefield::GetData(data); diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.h b/src/server/game/Battlefield/Zones/BattlefieldWG.h index b349aa80318..c54d8915a33 100644 --- a/src/server/game/Battlefield/Zones/BattlefieldWG.h +++ b/src/server/game/Battlefield/Zones/BattlefieldWG.h @@ -1133,7 +1133,7 @@ struct BfWGGameObjectBuilding m_WG->SendUpdateWorldState(m_WorldState, m_State); } UpdateCreatureAndGo(); - build->SetUInt32Value(GAMEOBJECT_FACTION, WintergraspFaction[m_Team]); + build->SetFaction(WintergraspFaction[m_Team]); } } diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index 58aba1429af..3fcfab81c73 100644 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -976,6 +976,8 @@ void Battleground::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac player->SpawnCorpseBones(); } } + else // try to resurrect the offline player. If he is alive nothing will happen + sObjectAccessor->ConvertCorpseForPlayer(guid); RemovePlayer(player, guid, team); // BG subclass specific code diff --git a/src/server/game/Chat/ChatLink.h b/src/server/game/Chat/ChatLink.h index c151bbd4b8e..cc86cb538ea 100644 --- a/src/server/game/Chat/ChatLink.h +++ b/src/server/game/Chat/ChatLink.h @@ -57,7 +57,7 @@ class ItemChatLink : public ChatLink { public: ItemChatLink() : ChatLink(), _item(NULL), _suffix(NULL), _property(NULL) - { + { memset(_data, 0, sizeof(_data)); } virtual bool Initialize(std::istringstream& iss); @@ -102,7 +102,7 @@ class AchievementChatLink : public ChatLink { public: AchievementChatLink() : ChatLink(), _guid(0), _achievement(NULL) - { + { memset(_data, 0, sizeof(_data)); } virtual bool Initialize(std::istringstream& iss); diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index 648b2a435d7..a4b3ded80e5 100644 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -482,7 +482,8 @@ void LoadDBCStores(const std::string& dataPath) continue; for (int x = 0; x < MAX_DIFFICULTY; ++x) - sSpellMgr->SetSpellDifficultyId(uint32(newEntry.SpellID[x]), spellDiff->ID); + if (newEntry.SpellID[x]) + sSpellMgr->SetSpellDifficultyId(uint32(newEntry.SpellID[x]), spellDiff->ID); } // create talent spells set diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index d5ccaab27da..e4bdc2d58fe 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -182,8 +182,8 @@ void Creature::AddToWorld() ///- Register the creature for guid lookup if (!IsInWorld()) { - if (m_zoneScript) - m_zoneScript->OnCreatureCreate(this); + if (GetZoneScript()) + GetZoneScript()->OnCreatureCreate(this); sObjectAccessor->AddObject(this); Unit::AddToWorld(); SearchFormation(); @@ -197,8 +197,8 @@ void Creature::RemoveFromWorld() { if (IsInWorld()) { - if (m_zoneScript) - m_zoneScript->OnCreatureRemove(this); + if (GetZoneScript()) + GetZoneScript()->OnCreatureRemove(this); if (m_formation) sFormationMgr->RemoveCreatureFromGroup(m_formation, this); Unit::RemoveFromWorld(); @@ -312,7 +312,7 @@ bool Creature::InitEntry(uint32 entry, uint32 /*team*/, const CreatureData* data CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelRandomGender(&displayID); if (!minfo) // Cancel load if no model defined { - TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has no model defined in table `creature_template`, can't load. ", entry); + TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has invalid model %u defined in table `creature_template`, can't load.", entry, displayID); return false; } @@ -367,7 +367,6 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData* data) if (!GetCreatureAddon()) SetSheath(SHEATH_STATE_MELEE); - SelectLevel(GetCreatureTemplate()); if (team == HORDE) setFaction(cInfo->faction_H); else @@ -381,10 +380,6 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData* data) else SetUInt32Value(UNIT_NPC_FLAGS, npcflag); - SetAttackTime(BASE_ATTACK, cInfo->baseattacktime); - SetAttackTime(OFF_ATTACK, cInfo->baseattacktime); - SetAttackTime(RANGED_ATTACK, cInfo->rangeattacktime); - SetUInt32Value(UNIT_FIELD_FLAGS, unit_flags); SetUInt32Value(UNIT_FIELD_FLAGS_2, cInfo->unit_flags2); @@ -392,6 +387,12 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData* data) RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); + SetAttackTime(BASE_ATTACK, cInfo->baseattacktime); + SetAttackTime(OFF_ATTACK, cInfo->baseattacktime); + SetAttackTime(RANGED_ATTACK, cInfo->rangeattacktime); + + SelectLevel(); + SetMeleeDamageSchool(SpellSchools(cInfo->dmgschool)); CreatureBaseStats const* stats = sObjectMgr->GetCreatureBaseStats(getLevel(), cInfo->unit_class); float armor = (float)stats->GenerateArmor(cInfo); /// @todo Why is this treated as uint32 when it's a float? @@ -1038,22 +1039,24 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask) WorldDatabase.CommitTransaction(trans); } -void Creature::SelectLevel(const CreatureTemplate* cinfo) +void Creature::SelectLevel() { - uint32 rank = IsPet()? 0 : cinfo->rank; + CreatureTemplate const* cInfo = GetCreatureTemplate(); + + uint32 rank = IsPet() ? 0 : cInfo->rank; // level - uint8 minlevel = std::min(cinfo->maxlevel, cinfo->minlevel); - uint8 maxlevel = std::max(cinfo->maxlevel, cinfo->minlevel); + uint8 minlevel = std::min(cInfo->maxlevel, cInfo->minlevel); + uint8 maxlevel = std::max(cInfo->maxlevel, cInfo->minlevel); uint8 level = minlevel == maxlevel ? minlevel : urand(minlevel, maxlevel); SetLevel(level); - CreatureBaseStats const* stats = sObjectMgr->GetCreatureBaseStats(level, cinfo->unit_class); + CreatureBaseStats const* stats = sObjectMgr->GetCreatureBaseStats(level, cInfo->unit_class); // health float healthmod = _GetHealthMod(rank); - uint32 basehp = stats->GenerateHealth(cinfo); + uint32 basehp = stats->GenerateHealth(cInfo); uint32 health = uint32(basehp * healthmod); SetCreateHealth(health); @@ -1062,10 +1065,10 @@ void Creature::SelectLevel(const CreatureTemplate* cinfo) ResetPlayerDamageReq(); // mana - uint32 mana = stats->GenerateMana(cinfo); + uint32 mana = stats->GenerateMana(cInfo); SetCreateMana(mana); - SetMaxPower(POWER_MANA, mana); //MAX Mana + SetMaxPower(POWER_MANA, mana); // MAX Mana SetPower(POWER_MANA, mana); /// @todo set UNIT_FIELD_POWER*, for some creature class case (energy, etc) @@ -1073,19 +1076,24 @@ void Creature::SelectLevel(const CreatureTemplate* cinfo) SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, (float)health); SetModifierValue(UNIT_MOD_MANA, BASE_VALUE, (float)mana); - //damage + // damage + + float basedamage = stats->GenerateBaseDamage(cInfo); - float basedamage = stats->GenerateBaseDamage(cinfo); + float weaponBaseMinDamage = basedamage; + float weaponBaseMaxDamage = basedamage * 1.5; - SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, ((basedamage + (stats->AttackPower / 14)) * cinfo->dmg_multiplier) * (cinfo->baseattacktime / 1000)); - SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (((basedamage * 1.5) + (stats->AttackPower / 14)) * cinfo->dmg_multiplier) * (cinfo->baseattacktime / 1000)); - SetBaseWeaponDamage(RANGED_ATTACK, MINDAMAGE, (basedamage + (stats->RangedAttackPower / 14)) * (cinfo->rangeattacktime / 1000)); - SetBaseWeaponDamage(RANGED_ATTACK, MAXDAMAGE, ((basedamage * 1.5) + (stats->RangedAttackPower / 14)) * (cinfo->rangeattacktime / 1000)); + SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, weaponBaseMinDamage); + SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, weaponBaseMaxDamage); - float damagemod = 1.0f;//_GetDamageMod(rank); + SetBaseWeaponDamage(OFF_ATTACK, MINDAMAGE, weaponBaseMinDamage); + SetBaseWeaponDamage(OFF_ATTACK, MAXDAMAGE, weaponBaseMaxDamage); - SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, stats->AttackPower * damagemod); + SetBaseWeaponDamage(RANGED_ATTACK, MINDAMAGE, weaponBaseMinDamage); + SetBaseWeaponDamage(RANGED_ATTACK, MAXDAMAGE, weaponBaseMaxDamage); + SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, stats->AttackPower); + SetModifierValue(UNIT_MOD_ATTACK_POWER_RANGED, BASE_VALUE, stats->RangedAttackPower); } float Creature::_GetHealthMod(int32 Rank) @@ -1154,9 +1162,9 @@ float Creature::GetSpellDamageMod(int32 Rank) const bool Creature::CreateFromProto(uint32 guidlow, uint32 Entry, uint32 vehId, uint32 team, const CreatureData* data) { SetZoneScript(); - if (m_zoneScript && data) + if (GetZoneScript() && data) { - Entry = m_zoneScript->GetCreatureEntry(guidlow, data); + Entry = GetZoneScript()->GetCreatureEntry(guidlow, data); if (!Entry) return false; } @@ -1258,6 +1266,12 @@ bool Creature::LoadCreatureFromDB(uint32 guid, Map* map, bool addToMap) return true; } +void Creature::SetCanDualWield(bool value) +{ + Unit::SetCanDualWield(value); + UpdateDamagePhysical(OFF_ATTACK); +} + void Creature::LoadEquipment(int8 id, bool force /*= true*/) { if (id == 0) @@ -1517,8 +1531,7 @@ void Creature::Respawn(bool force) if (m_originalEntry != GetEntry()) UpdateEntry(m_originalEntry); - CreatureTemplate const* cinfo = GetCreatureTemplate(); - SelectLevel(cinfo); + SelectLevel(); setDeathState(JUST_RESPAWNED); @@ -1965,7 +1978,7 @@ bool Creature::CanCreatureAttack(Unit const* victim, bool /*force*/) const if (IsAIEnabled && !AI()->CanAIAttack(victim)) return false; - if (sMapStore.LookupEntry(GetMapId())->IsDungeon()) + if (GetMap()->IsDungeon()) return true; //Use AttackDistance in distance check if threat radius is lower. This prevents creature bounce in and out of combat every update tick. @@ -2427,7 +2440,7 @@ void Creature::SetPosition(float x, float y, float z, float o) return; } - GetMap()->CreatureRelocation(ToCreature(), x, y, z, o); + GetMap()->CreatureRelocation(this, x, y, z, o); if (IsVehicle()) GetVehicleKit()->RelocatePassengers(); } diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 2f78d29a968..737e3072091 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -173,11 +173,6 @@ struct CreatureTemplate // Benchmarked: Faster than std::map (insert/find) typedef UNORDERED_MAP<uint32, CreatureTemplate> CreatureTemplateContainer; -// Represents max amount of expansions. -/// @todo: Add MAX_EXPANSION constant. -#define MAX_CREATURE_BASE_HP 3 -#define MAX_CREATURE_BASE_DAMAGE 3 - // GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push, N), also any gcc version not support it at some platform #if defined(__GNUC__) #pragma pack(1) @@ -188,12 +183,12 @@ typedef UNORDERED_MAP<uint32, CreatureTemplate> CreatureTemplateContainer; // Defines base stats for creatures (used to calculate HP/mana/armor/attackpower/rangedattackpower/all damage). struct CreatureBaseStats { - uint32 BaseHealth[MAX_CREATURE_BASE_HP]; + uint32 BaseHealth[MAX_EXPANSIONS]; uint32 BaseMana; uint32 BaseArmor; uint32 AttackPower; uint32 RangedAttackPower; - float BaseDamage[MAX_CREATURE_BASE_DAMAGE]; + float BaseDamage[MAX_EXPANSIONS]; // Helpers @@ -444,7 +439,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject bool Create(uint32 guidlow, Map* map, uint32 phaseMask, uint32 Entry, uint32 vehId, uint32 team, float x, float y, float z, float ang, const CreatureData* data = NULL); bool LoadCreaturesAddon(bool reload = false); - void SelectLevel(const CreatureTemplate* cinfo); + void SelectLevel(); void LoadEquipment(int8 id = 1, bool force = false); uint32 GetDBTableGUIDLow() const { return m_DBTableGuid; } @@ -521,8 +516,9 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject void UpdateMaxHealth(); void UpdateMaxPower(Powers power); void UpdateAttackPowerAndDamage(bool ranged = false); - void UpdateDamagePhysical(WeaponAttackType attType); + void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) OVERRIDE; + void SetCanDualWield(bool value) OVERRIDE; int8 GetOriginalEquipmentId() const { return m_originalEquipmentId; } uint8 GetCurrentEquipmentId() { return m_equipmentId; } void SetCurrentEquipmentId(uint8 id) { m_equipmentId = id; } diff --git a/src/server/game/Entities/Creature/TemporarySummon.h b/src/server/game/Entities/Creature/TemporarySummon.h index 5455bad904a..e93f66ed726 100644 --- a/src/server/game/Entities/Creature/TemporarySummon.h +++ b/src/server/game/Entities/Creature/TemporarySummon.h @@ -95,7 +95,7 @@ class Guardian : public Minion void UpdateMaxHealth(); void UpdateMaxPower(Powers power); void UpdateAttackPowerAndDamage(bool ranged = false); - void UpdateDamagePhysical(WeaponAttackType attType); + void UpdateDamagePhysical(WeaponAttackType attType) OVERRIDE; int32 GetBonusDamage() const { return m_bonusSpellDamage; } void SetBonusDamage(int32 damage); diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index 67e8c94f927..0ef03723cb4 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -816,6 +816,9 @@ class GameObject : public WorldObject, public GridObject<GameObject>, public Map void SetDisplayId(uint32 displayid); uint32 GetDisplayId() const { return GetUInt32Value(GAMEOBJECT_DISPLAYID); } + uint32 GetFaction() const { return GetUInt32Value(GAMEOBJECT_FACTION); } + void SetFaction(uint32 faction) { SetUInt32Value(GAMEOBJECT_FACTION, faction); } + GameObjectModel* m_model; void GetRespawnPosition(float &x, float &y, float &z, float* ori = NULL) const; diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index f18c6fdd977..8af48f277bd 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -480,7 +480,10 @@ void Object::BuildMovementUpdate(ByteBuffer* data, uint16 flags) const { /// @todo Allow players to aquire this updateflag. *data << uint32(unit->GetVehicleKit()->GetVehicleInfo()->m_ID); - *data << float(unit->GetOrientation()); + if (unit->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + *data << float(unit->GetTransOffsetO()); + else + *data << float(unit->GetOrientation()); } // 0x200 diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index edcdf25ba33..8d3b1ff9554 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -537,7 +537,7 @@ class MapObject protected: MapObject() : _moveState(MAP_OBJECT_CELL_MOVE_NONE) - { + { _newPosition.Relocate(0.0f, 0.0f, 0.0f, 0.0f); } diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h index c375cd30ad3..ef5e792e939 100644 --- a/src/server/game/Entities/Pet/Pet.h +++ b/src/server/game/Entities/Pet/Pet.h @@ -95,7 +95,7 @@ class Pet : public Guardian void UpdateMaxHealth(); void UpdateMaxPower(Powers power); void UpdateAttackPowerAndDamage(bool ranged = false); - void UpdateDamagePhysical(WeaponAttackType attType); + void UpdateDamagePhysical(WeaponAttackType attType) OVERRIDE; */ void ToggleAutocast(SpellInfo const* spellInfo, bool apply); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index d8218ff9689..4dab652d732 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -759,7 +759,6 @@ Player::Player(WorldSession* session): Unit(true) m_ArmorProficiency = 0; m_canParry = false; m_canBlock = false; - m_canDualWield = false; m_canTitanGrip = false; m_ammoDPS = 0.0f; @@ -7284,8 +7283,8 @@ bool Player::RewardHonor(Unit* victim, uint32 groupsize, int32 honor, bool pvpto { // Check if allowed to receive it in current map uint8 MapType = sWorld->getIntConfig(CONFIG_PVP_TOKEN_MAP_TYPE); - if ((MapType == 1 && !InBattleground() && !HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) - || (MapType == 2 && !HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) + if ((MapType == 1 && !InBattleground() && !IsFFAPvP()) + || (MapType == 2 && !IsFFAPvP()) || (MapType == 3 && !InBattleground())) return true; @@ -15092,11 +15091,11 @@ bool Player::CanRewardQuest(Quest const* quest, uint32 reward, bool msg) if (!CanRewardQuest(quest, msg)) return false; + ItemPosCountVec dest; if (quest->GetRewChoiceItemsCount() > 0) { if (quest->RewardChoiceItemId[reward]) { - ItemPosCountVec dest; InventoryResult res = CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, quest->RewardChoiceItemId[reward], quest->RewardChoiceItemCount[reward]); if (res != EQUIP_ERR_OK) { @@ -15112,7 +15111,6 @@ bool Player::CanRewardQuest(Quest const* quest, uint32 reward, bool msg) { if (quest->RewardItemId[i]) { - ItemPosCountVec dest; InventoryResult res = CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, quest->RewardItemId[i], quest->RewardItemIdCount[i]); if (res != EQUIP_ERR_OK) { @@ -17346,49 +17344,56 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder) // NOW player must have valid map // load the player's map here if it's not already loaded Map* map = sMapMgr->CreateMap(mapId, this); + AreaTrigger const* areaTrigger = NULL; + bool check = false; if (!map) { - instanceId = 0; - AreaTrigger const* at = sObjectMgr->GetGoBackTrigger(mapId); - if (at) + areaTrigger = sObjectMgr->GetGoBackTrigger(mapId); + check = true; + } + else if (map->IsDungeon()) // if map is dungeon... + { + if (!((InstanceMap*)map)->CanEnter(this)) // ... and can't enter map, then look for entry point. { - TC_LOG_ERROR("entities.player", "Player (guidlow %d) is teleported to gobacktrigger (Map: %u X: %f Y: %f Z: %f O: %f).", guid, mapId, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation()); - Relocate(at->target_X, at->target_Y, at->target_Z, GetOrientation()); - mapId = at->target_mapId; + areaTrigger = sObjectMgr->GetGoBackTrigger(mapId); + check = true; } - else + else if (instanceId && !sInstanceSaveMgr->GetInstanceSave(instanceId)) // ... and instance is reseted then look for entrance. { - TC_LOG_ERROR("entities.player", "Player (guidlow %d) is teleported to home (Map: %u X: %f Y: %f Z: %f O: %f).", guid, mapId, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation()); - RelocateToHomebind(); + areaTrigger = sObjectMgr->GetMapEntranceTrigger(mapId); + check = true; } + } - map = sMapMgr->CreateMap(mapId, this); - if (!map) + if (check) // in case of special event when creating map... + { + if (areaTrigger) // ... if we have an areatrigger, then relocate to new map/coordinates. { - PlayerInfo const* info = sObjectMgr->GetPlayerInfo(getRace(), getClass()); - mapId = info->mapId; - Relocate(info->positionX, info->positionY, info->positionZ, 0.0f); - TC_LOG_ERROR("entities.player", "Player (guidlow %d) have invalid coordinates (X: %f Y: %f Z: %f O: %f). Teleport to default race/class locations.", guid, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation()); - map = sMapMgr->CreateMap(mapId, this); - if (!map) + Relocate(areaTrigger->target_X, areaTrigger->target_Y, areaTrigger->target_Z, GetOrientation()); + if (mapId != areaTrigger->target_mapId) { - TC_LOG_ERROR("entities.player", "Player (guidlow %d) has invalid default map coordinates (X: %f Y: %f Z: %f O: %f). or instance couldn't be created", guid, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation()); - return false; + mapId = areaTrigger->target_mapId; + map = sMapMgr->CreateMap(mapId, this); } } + else + { + TC_LOG_ERROR("entities.player", "Player %s (guid: %d) Map: %u, X: %f, Y: %f, Z: %f, O: %f. Areatrigger not found.", m_name.c_str(), guid, mapId, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation()); + map = NULL; + } } - // if the player is in an instance and it has been reset in the meantime teleport him to the entrance - if (instanceId && !sInstanceSaveMgr->GetInstanceSave(instanceId) && !map->IsBattlegroundOrArena()) + if (!map) { - AreaTrigger const* at = sObjectMgr->GetMapEntranceTrigger(mapId); - if (at) - Relocate(at->target_X, at->target_Y, at->target_Z, at->target_Orientation); - else + PlayerInfo const* info = sObjectMgr->GetPlayerInfo(getRace(), getClass()); + mapId = info->mapId; + Relocate(info->positionX, info->positionY, info->positionZ, 0.0f); + map = sMapMgr->CreateMap(mapId, this); + if (!map) { - TC_LOG_ERROR("entities.player", "Player %s(GUID: %u) logged in to a reset instance (map: %u) and there is no area-trigger leading to this map. Thus he can't be ported back to the entrance. This _might_ be an exploit attempt.", GetName().c_str(), GetGUIDLow(), mapId); - RelocateToHomebind(); + TC_LOG_ERROR("entities.player", "Player %s (guid: %d) Map: %u, X: %f, Y: %f, Z: %f, O: %f. Invalid default map coordinates or instance couldn't be created.", m_name.c_str(), guid, mapId, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation()); + return false; } } @@ -17435,6 +17440,12 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder) m_atLoginFlags = fields[33].GetUInt16(); + if (HasAtLoginFlag(AT_LOGIN_RENAME)) + { + TC_LOG_ERROR("entities.player", "Player (GUID: %u) tried to login while forced to rename, can't load.'", GetGUIDLow()); + return false; + } + // Honor system // Update Honor kills data m_lastHonorUpdateTime = logoutTime; @@ -21674,14 +21685,14 @@ void Player::UpdatePvPState(bool onlyFFA) if (!pvpInfo.IsInNoPvPArea && !IsGameMaster() && (pvpInfo.IsInFFAPvPArea || sWorld->IsFFAPvPRealm())) { - if (!HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) + if (!IsFFAPvP()) { SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); for (ControlList::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr) (*itr)->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); } } - else if (HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) + else if (IsFFAPvP()) { RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); for (ControlList::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr) @@ -23757,14 +23768,18 @@ void Player::ResurectUsingRequestData() SpawnCorpseBones(); } -void Player::SetClientControl(Unit* target, uint8 allowMove) +void Player::SetClientControl(Unit* target, bool allowMove) { WorldPacket data(SMSG_CLIENT_CONTROL_UPDATE, target->GetPackGUID().size()+1); data.append(target->GetPackGUID()); - data << uint8(allowMove); + data << uint8(allowMove ? 1 : 0); GetSession()->SendPacket(&data); - if (target == this) - SetMover(this); + + if (this != target) + SetViewpoint(target, allowMove); + + if (allowMove) + SetMover(target); } void Player::SetMover(Unit* target) diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index f7658f73321..cd73f38823e 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1643,6 +1643,7 @@ class Player : public Unit, public GridObject<Player> void RemoveAllSpellCooldown(); void _LoadSpellCooldowns(PreparedQueryResult result); void _SaveSpellCooldowns(SQLTransaction& trans); + uint32 GetLastPotionId() { return m_lastPotionId; } void SetLastPotionId(uint32 item_id) { m_lastPotionId = item_id; } void UpdatePotionCooldown(Spell* spell = NULL); @@ -1747,14 +1748,13 @@ class Player : public Unit, public GridObject<Player> void ApplyFeralAPBonus(int32 amount, bool apply); void UpdateAttackPowerAndDamage(bool ranged = false); void UpdateShieldBlockValue(); - void UpdateDamagePhysical(WeaponAttackType attType); void ApplySpellPowerBonus(int32 amount, bool apply); void UpdateSpellDamageAndHealingBonus(); void ApplyRatingMod(CombatRating cr, int32 value, bool apply); void UpdateRating(CombatRating cr); void UpdateAllRatings(); - void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& min_damage, float& max_damage); + void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) OVERRIDE; void UpdateDefenseBonusesMod(); inline void RecalculateRating(CombatRating cr) { ApplyRatingMod(cr, 0, true);} @@ -2088,7 +2088,7 @@ class Player : public Unit, public GridObject<Player> bool IsKnowHowFlyIn(uint32 mapid, uint32 zone) const; - void SetClientControl(Unit* target, uint8 allowMove); + void SetClientControl(Unit* target, bool allowMove); void SetMover(Unit* target); diff --git a/src/server/game/Entities/Totem/Totem.h b/src/server/game/Entities/Totem/Totem.h index d20a58abd01..6364157982e 100644 --- a/src/server/game/Entities/Totem/Totem.h +++ b/src/server/game/Entities/Totem/Totem.h @@ -53,7 +53,7 @@ class Totem : public Minion void UpdateMaxHealth() { } void UpdateMaxPower(Powers /*power*/) { } void UpdateAttackPowerAndDamage(bool /*ranged*/) { } - void UpdateDamagePhysical(WeaponAttackType /*attType*/) { } + void UpdateDamagePhysical(WeaponAttackType /*attType*/) OVERRIDE { } bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const; diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp index 3077b143bb0..3afa6b016d2 100644 --- a/src/server/game/Entities/Unit/StatSystem.cpp +++ b/src/server/game/Entities/Unit/StatSystem.cpp @@ -48,6 +48,43 @@ inline bool _ModifyUInt32(bool apply, uint32& baseValue, int32& amount) /*####################################### ######## ######## +######## UNIT STAT SYSTEM ######## +######## ######## +#######################################*/ + +void Unit::UpdateAllResistances() +{ + for (uint8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i) + UpdateResistances(i); +} + +void Unit::UpdateDamagePhysical(WeaponAttackType attType) +{ + float minDamage = 0.0f; + float maxDamage = 0.0f; + + CalculateMinMaxDamage(attType, false, true, minDamage, maxDamage); + + switch (attType) + { + case BASE_ATTACK: + default: + SetStatFloatValue(UNIT_FIELD_MINDAMAGE, minDamage); + SetStatFloatValue(UNIT_FIELD_MAXDAMAGE, maxDamage); + break; + case OFF_ATTACK: + SetStatFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE, minDamage); + SetStatFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE, maxDamage); + break; + case RANGED_ATTACK: + SetStatFloatValue(UNIT_FIELD_MINRANGEDDAMAGE, minDamage); + SetStatFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE, maxDamage); + break; + } +} + +/*####################################### +######## ######## ######## PLAYERS STAT SYSTEM ######## ######## ######## #######################################*/ @@ -178,8 +215,7 @@ bool Player::UpdateAllStats() UpdateExpertise(BASE_ATTACK); UpdateExpertise(OFF_ATTACK); RecalculateRating(CR_ARMOR_PENETRATION); - for (int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i) - UpdateResistances(i); + UpdateAllResistances(); return true; } @@ -477,7 +513,7 @@ void Player::UpdateShieldBlockValue() SetUInt32Value(PLAYER_SHIELD_BLOCK, GetShieldBlockValue()); } -void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& min_damage, float& max_damage) +void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) { UnitMods unitMod; @@ -495,70 +531,45 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo break; } - float att_speed = GetAPMultiplier(attType, normalized); + float attackSpeedMod = GetAPMultiplier(attType, normalized); - float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType)/ 14.0f * att_speed; - float base_pct = GetModifierValue(unitMod, BASE_PCT); - float total_value = GetModifierValue(unitMod, TOTAL_VALUE); - float total_pct = addTotalPct ? GetModifierValue(unitMod, TOTAL_PCT) : 1.0f; + float baseValue = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 14.0f * attackSpeedMod; + float basePct = GetModifierValue(unitMod, BASE_PCT); + float totalValue = GetModifierValue(unitMod, TOTAL_VALUE); + float totalPct = addTotalPct ? GetModifierValue(unitMod, TOTAL_PCT) : 1.0f; - float weapon_mindamage = GetWeaponDamageRange(attType, MINDAMAGE); - float weapon_maxdamage = GetWeaponDamageRange(attType, MAXDAMAGE); + float weaponMinDamage = GetWeaponDamageRange(attType, MINDAMAGE); + float weaponMaxDamage = GetWeaponDamageRange(attType, MAXDAMAGE); - if (IsInFeralForm()) //check if player is druid and in cat or bear forms + if (IsInFeralForm()) // check if player is druid and in cat or bear forms { uint8 lvl = getLevel(); if (lvl > 60) lvl = 60; - weapon_mindamage = lvl*0.85f*att_speed; - weapon_maxdamage = lvl*1.25f*att_speed; + weaponMinDamage = lvl * 0.85f * attackSpeedMod; + weaponMaxDamage = lvl * 1.25f * attackSpeedMod; } - else if (!CanUseAttackType(attType)) //check if player not in form but still can't use (disarm case) + else if (!CanUseAttackType(attType)) // check if player not in form but still can't use (disarm case) { - //cannot use ranged/off attack, set values to 0 + // cannot use ranged/off attack, set values to 0 if (attType != BASE_ATTACK) { - min_damage = 0; - max_damage = 0; + minDamage = 0; + maxDamage = 0; return; } - weapon_mindamage = BASE_MINDAMAGE; - weapon_maxdamage = BASE_MAXDAMAGE; + weaponMinDamage = BASE_MINDAMAGE; + weaponMaxDamage = BASE_MAXDAMAGE; } - else if (attType == RANGED_ATTACK) //add ammo DPS to ranged damage + else if (attType == RANGED_ATTACK) // add ammo DPS to ranged damage { - weapon_mindamage += GetAmmoDPS() * att_speed; - weapon_maxdamage += GetAmmoDPS() * att_speed; + weaponMinDamage += GetAmmoDPS() * attackSpeedMod; + weaponMaxDamage += GetAmmoDPS() * attackSpeedMod; } - min_damage = ((base_value + weapon_mindamage) * base_pct + total_value) * total_pct; - max_damage = ((base_value + weapon_maxdamage) * base_pct + total_value) * total_pct; -} - -void Player::UpdateDamagePhysical(WeaponAttackType attType) -{ - float mindamage; - float maxdamage; - - CalculateMinMaxDamage(attType, false, true, mindamage, maxdamage); - - switch (attType) - { - case BASE_ATTACK: - default: - SetStatFloatValue(UNIT_FIELD_MINDAMAGE, mindamage); - SetStatFloatValue(UNIT_FIELD_MAXDAMAGE, maxdamage); - break; - case OFF_ATTACK: - SetStatFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE, mindamage); - SetStatFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE, maxdamage); - break; - case RANGED_ATTACK: - SetStatFloatValue(UNIT_FIELD_MINRANGEDDAMAGE, mindamage); - SetStatFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE, maxdamage); - break; - } + minDamage = ((weaponMinDamage + baseValue) * basePct + totalValue) * totalPct; + maxDamage = ((weaponMaxDamage + baseValue) * basePct + totalValue) * totalPct; } void Player::UpdateDefenseBonusesMod() @@ -841,9 +852,14 @@ void Player::UpdateExpertise(WeaponAttackType attack) switch (attack) { - case BASE_ATTACK: SetUInt32Value(PLAYER_EXPERTISE, expertise); break; - case OFF_ATTACK: SetUInt32Value(PLAYER_OFFHAND_EXPERTISE, expertise); break; - default: break; + case BASE_ATTACK: + SetUInt32Value(PLAYER_EXPERTISE, expertise); + break; + case OFF_ATTACK: + SetUInt32Value(PLAYER_OFFHAND_EXPERTISE, expertise); + break; + default: + break; } } @@ -950,8 +966,7 @@ bool Creature::UpdateAllStats() for (uint8 i = POWER_MANA; i < MAX_POWERS; ++i) UpdateMaxPower(Powers(i)); - for (int8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i) - UpdateResistances(i); + UpdateAllResistances(); return true; } @@ -976,7 +991,7 @@ void Creature::UpdateArmor() void Creature::UpdateMaxHealth() { float value = GetTotalAuraModValue(UNIT_MOD_HEALTH); - SetMaxHealth((uint32)value); + SetMaxHealth(uint32(value)); } void Creature::UpdateMaxPower(Powers power) @@ -992,25 +1007,25 @@ void Creature::UpdateAttackPowerAndDamage(bool ranged) UnitMods unitMod = ranged ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER; uint16 index = UNIT_FIELD_ATTACK_POWER; - uint16 index_mod = UNIT_FIELD_ATTACK_POWER_MODS; - uint16 index_mult = UNIT_FIELD_ATTACK_POWER_MULTIPLIER; + uint16 indexMod = UNIT_FIELD_ATTACK_POWER_MODS; + uint16 indexMulti = UNIT_FIELD_ATTACK_POWER_MULTIPLIER; if (ranged) { index = UNIT_FIELD_RANGED_ATTACK_POWER; - index_mod = UNIT_FIELD_RANGED_ATTACK_POWER_MODS; - index_mult = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER; + indexMod = UNIT_FIELD_RANGED_ATTACK_POWER_MODS; + indexMulti = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER; } - float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT); - float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE); - float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f; + float baseAttackPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT); + float attackPowerMod = GetModifierValue(unitMod, TOTAL_VALUE); + float attackPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f; - SetInt32Value(index, (uint32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER field - SetInt32Value(index_mod, (uint32)attPowerMod); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field - SetFloatValue(index_mult, attPowerMultiplier); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field + SetInt32Value(index, uint32(baseAttackPower)); // UNIT_FIELD_(RANGED)_ATTACK_POWER + SetInt32Value(indexMod, uint32(attackPowerMod)); // UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS + SetFloatValue(indexMulti, attackPowerMultiplier); // UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER - //automatically update weapon damage after attack power modification + // automatically update weapon damage after attack power modification if (ranged) UpdateDamagePhysical(RANGED_ATTACK); else @@ -1020,7 +1035,7 @@ void Creature::UpdateAttackPowerAndDamage(bool ranged) } } -void Creature::UpdateDamagePhysical(WeaponAttackType attType) +void Creature::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) { UnitMods unitMod; switch (attType) @@ -1037,44 +1052,32 @@ void Creature::UpdateDamagePhysical(WeaponAttackType attType) break; } - //float att_speed = float(GetAttackTime(attType))/1000.0f; - - float weapon_mindamage = GetWeaponDamageRange(attType, MINDAMAGE); - float weapon_maxdamage = GetWeaponDamageRange(attType, MAXDAMAGE); - - /* difference in AP between current attack power and base value from DB */ - float att_pwr_change = GetTotalAttackPowerValue(attType) - GetCreatureTemplate()->attackpower; - float base_value = GetModifierValue(unitMod, BASE_VALUE) + (att_pwr_change * GetAPMultiplier(attType, false) / 14.0f); - float base_pct = GetModifierValue(unitMod, BASE_PCT); - float total_value = GetModifierValue(unitMod, TOTAL_VALUE); - float total_pct = GetModifierValue(unitMod, TOTAL_PCT); - float dmg_multiplier = GetCreatureTemplate()->dmg_multiplier; - - if (!CanUseAttackType(attType)) + if (attType == OFF_ATTACK && !haveOffhandWeapon()) { - weapon_mindamage = 0; - weapon_maxdamage = 0; + minDamage = 0.0f; + maxDamage = 0.0f; + return; } - float mindamage = ((base_value + weapon_mindamage) * dmg_multiplier * base_pct + total_value) * total_pct; - float maxdamage = ((base_value + weapon_maxdamage) * dmg_multiplier * base_pct + total_value) * total_pct; + float weaponMinDamage = GetWeaponDamageRange(attType, MINDAMAGE); + float weaponMaxDamage = GetWeaponDamageRange(attType, MAXDAMAGE); - switch (attType) + if (!CanUseAttackType(attType)) // disarm case { - case BASE_ATTACK: - default: - SetStatFloatValue(UNIT_FIELD_MINDAMAGE, mindamage); - SetStatFloatValue(UNIT_FIELD_MAXDAMAGE, maxdamage); - break; - case OFF_ATTACK: - SetStatFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE, mindamage); - SetStatFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE, maxdamage); - break; - case RANGED_ATTACK: - SetStatFloatValue(UNIT_FIELD_MINRANGEDDAMAGE, mindamage); - SetStatFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE, maxdamage); - break; + weaponMinDamage = 0.0f; + weaponMaxDamage = 0.0f; } + + float attackPower = GetTotalAttackPowerValue(attType); + float attackSpeedMulti = GetAPMultiplier(attType, normalized); + float baseValue = GetModifierValue(unitMod, BASE_VALUE) + (attackPower / 14.0f); + float basePct = GetModifierValue(unitMod, BASE_PCT) * attackSpeedMulti; + float totalValue = GetModifierValue(unitMod, TOTAL_VALUE); + float totalPct = addTotalPct ? GetModifierValue(unitMod, TOTAL_PCT) : 1.0f; + float dmgMultiplier = GetCreatureTemplate()->dmg_multiplier; // = dmg_multiplier * _GetDamageMod(rank); + + minDamage = ((weaponMinDamage + baseValue) * dmgMultiplier * basePct + totalValue) * totalPct; + maxDamage = ((weaponMaxDamage + baseValue) * dmgMultiplier * basePct + totalValue) * totalPct; } /*####################################### @@ -1197,8 +1200,7 @@ bool Guardian::UpdateAllStats() for (uint8 i = POWER_MANA; i < MAX_POWERS; ++i) UpdateMaxPower(Powers(i)); - for (uint8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i) - UpdateResistances(i); + UpdateAllResistances(); return true; } @@ -1436,6 +1438,7 @@ void Guardian::UpdateDamagePhysical(WeaponAttackType attType) } } + /// @todo: remove this Unit::AuraEffectList const& mDummy = GetAuraEffectsByType(SPELL_AURA_MOD_ATTACKSPEED); for (Unit::AuraEffectList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr) { diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index e5fb575d8eb..3de062148e9 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -258,6 +258,8 @@ Unit::Unit(bool isWorldObject) : m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE); _lastLiquid = NULL; + + _oldFactionId = 0; _isWalkingBeforeCharm = false; } @@ -368,10 +370,10 @@ void Unit::Update(uint32 p_time) bool Unit::haveOffhandWeapon() const { - if (GetTypeId() == TYPEID_PLAYER) - return ToPlayer()->GetWeaponForAttack(OFF_ATTACK, true); - else - return m_canDualWield; + if (Player const* player = ToPlayer()) + return player->GetWeaponForAttack(OFF_ATTACK, true); + + return CanDualWield(); } void Unit::MonsterMoveWithSpeed(float x, float y, float z, float speed, bool generatePath, bool forceDestination) @@ -405,7 +407,7 @@ void Unit::UpdateSplinePosition() m_movesplineTimer.Reset(positionUpdateDelay); Movement::Location loc = movespline->ComputePosition(); - if (HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + if (movespline->onTransport) { Position& pos = m_movementInfo.transport.pos; pos.m_positionX = loc.x; @@ -2160,41 +2162,39 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit* victim, WeaponAttackT uint32 Unit::CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct) { - float min_damage, max_damage; + float minDamage = 0.0f; + float maxDamage = 0.0f; - if (GetTypeId() == TYPEID_PLAYER && (normalized || !addTotalPct)) - ToPlayer()->CalculateMinMaxDamage(attType, normalized, addTotalPct, min_damage, max_damage); + if (normalized || !addTotalPct) + CalculateMinMaxDamage(attType, normalized, addTotalPct, minDamage, maxDamage); else { switch (attType) { case RANGED_ATTACK: - min_damage = GetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE); - max_damage = GetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE); + minDamage = GetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE); + maxDamage = GetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE); break; case BASE_ATTACK: - min_damage = GetFloatValue(UNIT_FIELD_MINDAMAGE); - max_damage = GetFloatValue(UNIT_FIELD_MAXDAMAGE); + minDamage = GetFloatValue(UNIT_FIELD_MINDAMAGE); + maxDamage = GetFloatValue(UNIT_FIELD_MAXDAMAGE); break; case OFF_ATTACK: - min_damage = GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE); - max_damage = GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE); + minDamage = GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE); + maxDamage = GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE); break; - // Just for good manner default: - min_damage = 0.0f; - max_damage = 0.0f; break; } } - if (min_damage > max_damage) - std::swap(min_damage, max_damage); + if (minDamage > maxDamage) + std::swap(minDamage, maxDamage); - if (max_damage == 0.0f) - max_damage = 5.0f; + if (maxDamage == 0.0f) + maxDamage = 5.0f; - return urand((uint32)min_damage, (uint32)max_damage); + return urand(uint32(minDamage), uint32(maxDamage)); } float Unit::CalculateLevelPenalty(SpellInfo const* spellProto) const @@ -4832,7 +4832,7 @@ GameObject* Unit::GetGameObject(uint32 spellId) const void Unit::AddGameObject(GameObject* gameObj) { - if (!gameObj || !gameObj->GetOwnerGUID() == 0) + if (!gameObj || gameObj->GetOwnerGUID() != 0) return; m_gameObj.push_back(gameObj); @@ -9221,17 +9221,17 @@ void Unit::SetOwnerGUID(uint64 owner) Unit* Unit::GetOwner() const { - if (uint64 ownerid = GetOwnerGUID()) - { - return ObjectAccessor::GetUnit(*this, ownerid); - } + if (uint64 ownerGUID = GetOwnerGUID()) + return ObjectAccessor::GetUnit(*this, ownerGUID); + return NULL; } Unit* Unit::GetCharmer() const { - if (uint64 charmerid = GetCharmerGUID()) - return ObjectAccessor::GetUnit(*this, charmerid); + if (uint64 charmerGUID = GetCharmerGUID()) + return ObjectAccessor::GetUnit(*this, charmerGUID); + return NULL; } @@ -9567,8 +9567,8 @@ void Unit::SetCharm(Unit* charm, bool apply) } if (charm->GetTypeId() == TYPEID_PLAYER - || !charm->ToCreature()->HasUnitTypeMask(UNIT_MASK_MINION) - || charm->GetOwnerGUID() != GetGUID()) + || !charm->ToCreature()->HasUnitTypeMask(UNIT_MASK_MINION) + || charm->GetOwnerGUID() != GetGUID()) { m_Controlled.erase(charm); } @@ -11628,7 +11628,7 @@ bool Unit::IsServiceProvider() const void Unit::SetInCombatWith(Unit* enemy) { Unit* eOwner = enemy->GetCharmerOrOwnerOrSelf(); - if (eOwner->IsPvP()) + if (eOwner->IsPvP() || eOwner->IsFFAPvP()) { SetInCombatState(true, enemy); return; @@ -13579,9 +13579,8 @@ CharmInfo::~CharmInfo() { } void CharmInfo::RestoreState() { - if (_unit->GetTypeId() == TYPEID_UNIT) - if (Creature* creature = _unit->ToCreature()) - creature->SetReactState(_oldReactState); + if (Creature* creature = _unit->ToCreature()) + creature->SetReactState(_oldReactState); } void CharmInfo::InitPetActionBar() @@ -15526,7 +15525,7 @@ void Unit::SetStunned(bool apply) // Creature specific if (GetTypeId() != TYPEID_PLAYER) - ToCreature()->StopMoving(); + StopMoving(); else SetStandState(UNIT_STAND_STATE_STAND); @@ -15584,7 +15583,7 @@ void Unit::SetRooted(bool apply) WorldPacket data(SMSG_SPLINE_MOVE_ROOT, 8); data.append(GetPackGUID()); SendMessageToSet(&data, true); - ToCreature()->StopMoving(); + StopMoving(); } } else @@ -15635,8 +15634,8 @@ void Unit::SetFeared(bool apply) } } - if (GetTypeId() == TYPEID_PLAYER) - ToPlayer()->SetClientControl(this, !apply); + if (Player* player = ToPlayer()) + player->SetClientControl(this, !apply); } void Unit::SetConfused(bool apply) @@ -15657,8 +15656,8 @@ void Unit::SetConfused(bool apply) } } - if (GetTypeId() == TYPEID_PLAYER) - ToPlayer()->SetClientControl(this, !apply); + if (Player* player = ToPlayer()) + player->SetClientControl(this, !apply); } bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* aurApp) @@ -15704,11 +15703,13 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au CombatStop(); /// @todo CombatStop(true) may cause crash (interrupt spells) DeleteThreatList(); + Player* playerCharmer = charmer->ToPlayer(); + // Charmer stop charming - if (charmer->GetTypeId() == TYPEID_PLAYER) + if (playerCharmer) { - charmer->ToPlayer()->StopCastingCharm(); - charmer->ToPlayer()->StopCastingBindSight(); + playerCharmer->StopCastingCharm(); + playerCharmer->StopCastingBindSight(); } // Charmed stop charming @@ -15730,11 +15731,10 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au if (aurApp && aurApp->GetRemoveMode()) return false; - // Set charmed - Map* map = GetMap(); - if (!IsVehicle() || (IsVehicle() && map && !map->IsBattleground())) - setFaction(charmer->getFaction()); + _oldFactionId = getFaction(); + setFaction(charmer->getFaction()); + // Set charmed charmer->SetCharm(this, true); if (GetTypeId() == TYPEID_UNIT) @@ -15747,7 +15747,7 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au Player* player = ToPlayer(); if (player->isAFK()) player->ToggleAFK(); - player->SetClientControl(this, 0); + player->SetClientControl(this, false); } // charm is set by aura, and aura effect remove handler was called during apply handler execution @@ -15765,25 +15765,21 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au GetCharmInfo()->InitCharmCreateSpells(); } - if (charmer->GetTypeId() == TYPEID_PLAYER) + if (playerCharmer) { switch (type) { case CHARM_TYPE_VEHICLE: SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); - charmer->ToPlayer()->SetClientControl(this, 1); - charmer->ToPlayer()->SetMover(this); - charmer->ToPlayer()->SetViewpoint(this, true); - charmer->ToPlayer()->VehicleSpellInitialize(); + playerCharmer->SetClientControl(this, true); + playerCharmer->VehicleSpellInitialize(); break; case CHARM_TYPE_POSSESS: AddUnitState(UNIT_STATE_POSSESSED); SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); charmer->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - charmer->ToPlayer()->SetClientControl(this, 1); - charmer->ToPlayer()->SetMover(this); - charmer->ToPlayer()->SetViewpoint(this, true); - charmer->ToPlayer()->PossessSpellInitialize(); + playerCharmer->SetClientControl(this, true); + playerCharmer->PossessSpellInitialize(); break; case CHARM_TYPE_CHARM: if (GetTypeId() == TYPEID_UNIT && charmer->getClass() == CLASS_WARLOCK) @@ -15802,7 +15798,7 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(NULL))); // cast can't be helped } } - charmer->ToPlayer()->CharmSpellInitialize(); + playerCharmer->CharmSpellInitialize(); break; default: case CHARM_TYPE_CONVERT: @@ -15839,16 +15835,16 @@ void Unit::RemoveCharmedBy(Unit* charmer) CombatStop(); /// @todo CombatStop(true) may cause crash (interrupt spells) getHostileRefManager().deleteReferences(); DeleteThreatList(); - Map* map = GetMap(); - if (!IsVehicle() || (IsVehicle() && map && !map->IsBattleground())) - RestoreFaction(); - GetMotionMaster()->InitDefault(); - if (type == CHARM_TYPE_POSSESS) + if (_oldFactionId) { - ClearUnitState(UNIT_STATE_POSSESSED); - RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); + setFaction(_oldFactionId); + _oldFactionId = 0; } + else + RestoreFaction(); + + GetMotionMaster()->InitDefault(); if (Creature* creature = ToCreature()) { @@ -15860,8 +15856,6 @@ void Unit::RemoveCharmedBy(Unit* charmer) if (type != CHARM_TYPE_VEHICLE) LastCharmerGUID = charmer->GetGUID(); } - else - ToPlayer()->SetClientControl(this, 1); // If charmer still exists if (!charmer) @@ -15872,24 +15866,23 @@ void Unit::RemoveCharmedBy(Unit* charmer) charmer->SetCharm(this, false); - if (charmer->GetTypeId() == TYPEID_PLAYER) + Player* playerCharmer = charmer->ToPlayer(); + + if (playerCharmer) { switch (type) { case CHARM_TYPE_VEHICLE: - charmer->ToPlayer()->SetClientControl(charmer, 1); - charmer->ToPlayer()->SetViewpoint(this, false); - charmer->ToPlayer()->SetClientControl(this, 0); - if (GetTypeId() == TYPEID_PLAYER) - ToPlayer()->SetMover(this); + playerCharmer->SetClientControl(this, false); + playerCharmer->SetClientControl(charmer, true); + RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); break; case CHARM_TYPE_POSSESS: - charmer->ToPlayer()->SetClientControl(charmer, 1); - charmer->ToPlayer()->SetViewpoint(this, false); - charmer->ToPlayer()->SetClientControl(this, 0); + playerCharmer->SetClientControl(this, false); + playerCharmer->SetClientControl(charmer, true); charmer->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - if (GetTypeId() == TYPEID_PLAYER) - ToPlayer()->SetMover(this); + RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); + ClearUnitState(UNIT_STATE_POSSESSED); break; case CHARM_TYPE_CHARM: if (GetTypeId() == TYPEID_UNIT && charmer->getClass() == CLASS_WARLOCK) @@ -15910,9 +15903,12 @@ void Unit::RemoveCharmedBy(Unit* charmer) } } + if (Player* player = ToPlayer()) + player->SetClientControl(this, true); + // a guardian should always have charminfo - if (charmer->GetTypeId() == TYPEID_PLAYER && this != charmer->GetFirstControlled()) - charmer->ToPlayer()->SendRemoveControlBar(); + if (playerCharmer && this != charmer->GetFirstControlled()) + playerCharmer->SendRemoveControlBar(); else if (GetTypeId() == TYPEID_PLAYER || (GetTypeId() == TYPEID_UNIT && !ToCreature()->IsGuardian())) DeleteCharmInfo(); } @@ -15969,8 +15965,7 @@ void Unit::RemoveVehicleKit() m_updateFlag &= ~UPDATEFLAG_VEHICLE; m_unitTypeMask &= ~UNIT_MASK_VEHICLE; - RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE); + RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK | UNIT_NPC_FLAG_PLAYER_VEHICLE); } bool Unit::IsOnVehicle(const Unit* vehicle) const diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index eb236666976..151f20d09f9 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1292,7 +1292,7 @@ class Unit : public WorldObject bool isAttackReady(WeaponAttackType type = BASE_ATTACK) const { return m_attackTimer[type] == 0; } bool haveOffhandWeapon() const; bool CanDualWield() const { return m_canDualWield; } - void SetCanDualWield(bool value) { m_canDualWield = value; } + virtual void SetCanDualWield(bool value) { m_canDualWield = value; } float GetCombatReach() const { return m_floatValues[UNIT_FIELD_COMBATREACH]; } float GetMeleeReach() const; bool IsWithinCombatRange(const Unit* obj, float dist2compare) const; @@ -1404,6 +1404,7 @@ class Unit : public WorldObject void GetPartyMembers(std::list<Unit*> &units); bool IsContestedGuard() const; bool IsPvP() const { return HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP); } + bool IsFFAPvP() const { return HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); } void SetPvP(bool state); uint32 GetCreatureType() const; uint32 GetCreatureTypeMask() const; @@ -1870,14 +1871,18 @@ class Unit : public WorldObject virtual bool UpdateStats(Stats stat) = 0; virtual bool UpdateAllStats() = 0; virtual void UpdateResistances(uint32 school) = 0; + virtual void UpdateAllResistances(); virtual void UpdateArmor() = 0; virtual void UpdateMaxHealth() = 0; virtual void UpdateMaxPower(Powers power) = 0; virtual void UpdateAttackPowerAndDamage(bool ranged = false) = 0; - virtual void UpdateDamagePhysical(WeaponAttackType attType) = 0; + virtual void UpdateDamagePhysical(WeaponAttackType attType); float GetTotalAttackPowerValue(WeaponAttackType attType) const; float GetWeaponDamageRange(WeaponAttackType attType, WeaponDamageRange type) const; void SetBaseWeaponDamage(WeaponAttackType attType, WeaponDamageRange damageRange, float value) { m_weaponDamage[attType][damageRange] = value; } + virtual void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) = 0; + uint32 CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct); + float GetAPMultiplier(WeaponAttackType attType, bool normalized); bool isInFrontInMap(Unit const* target, float distance, float arc = M_PI) const; bool isInBackInMap(Unit const* target, float distance, float arc = M_PI) const; @@ -1935,8 +1940,6 @@ class Unit : public WorldObject void RemoveGameObject(uint32 spellid, bool del); void RemoveAllGameObjects(); - uint32 CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct); - float GetAPMultiplier(WeaponAttackType attType, bool normalized); void ModifyAuraState(AuraStateType flag, bool apply); uint32 BuildAuraStateUpdateForTarget(Unit* target) const; bool HasAuraState(AuraStateType flag, SpellInfo const* spellProto = NULL, Unit const* Caster = NULL) const; @@ -1956,7 +1959,6 @@ class Unit : public WorldObject uint32 MeleeDamageBonusDone(Unit* pVictim, uint32 damage, WeaponAttackType attType, SpellInfo const* spellProto = NULL); uint32 MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackType attType, SpellInfo const* spellProto = NULL); - bool isSpellBlocked(Unit* victim, SpellInfo const* spellProto, WeaponAttackType attackType = BASE_ATTACK); bool isBlockCritical(); bool isSpellCrit(Unit* victim, SpellInfo const* spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType = BASE_ATTACK) const; @@ -2245,7 +2247,8 @@ class Unit : public WorldObject bool m_cleanupDone; // lock made to not add stuff after cleanup before delete bool m_duringRemoveFromWorld; // lock made to not add stuff after begining removing from world - bool _isWalkingBeforeCharm; // Are we walking before we were charmed? + uint32 _oldFactionId; ///< faction before charm + bool _isWalkingBeforeCharm; ///< Are we walking before we were charmed? time_t _lastDamagedTime; // Part of Evade mechanics }; @@ -2256,31 +2259,31 @@ namespace Trinity class PowerPctOrderPred { public: - PowerPctOrderPred(Powers power, bool ascending = true) : m_power(power), m_ascending(ascending) { } - bool operator() (const Unit* a, const Unit* b) const + PowerPctOrderPred(Powers power, bool ascending = true) : _power(power), _ascending(ascending) { } + bool operator() (Unit const* a, Unit const* b) const { - float rA = a->GetMaxPower(m_power) ? float(a->GetPower(m_power)) / float(a->GetMaxPower(m_power)) : 0.0f; - float rB = b->GetMaxPower(m_power) ? float(b->GetPower(m_power)) / float(b->GetMaxPower(m_power)) : 0.0f; - return m_ascending ? rA < rB : rA > rB; + float rA = a->GetMaxPower(_power) ? float(a->GetPower(_power)) / float(a->GetMaxPower(_power)) : 0.0f; + float rB = b->GetMaxPower(_power) ? float(b->GetPower(_power)) / float(b->GetMaxPower(_power)) : 0.0f; + return _ascending ? rA < rB : rA > rB; } private: - const Powers m_power; - const bool m_ascending; + Powers const _power; + bool const _ascending; }; // Binary predicate for sorting Units based on percent value of health class HealthPctOrderPred { public: - HealthPctOrderPred(bool ascending = true) : m_ascending(ascending) { } - bool operator() (const Unit* a, const Unit* b) const + HealthPctOrderPred(bool ascending = true) : _ascending(ascending) { } + bool operator() (Unit const* a, Unit const* b) const { float rA = a->GetMaxHealth() ? float(a->GetHealth()) / float(a->GetMaxHealth()) : 0.0f; float rB = b->GetMaxHealth() ? float(b->GetHealth()) / float(b->GetMaxHealth()) : 0.0f; - return m_ascending ? rA < rB : rA > rB; + return _ascending ? rA < rB : rA > rB; } private: - const bool m_ascending; + bool const _ascending; }; } #endif diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index a48f46191ba..fae4f0c6b6a 100755 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -521,8 +521,13 @@ Vehicle* Vehicle::RemovePassenger(Unit* unit) if (_me->IsInWorld()) { - unit->RemoveUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT); - unit->m_movementInfo.transport.Reset(); + if (!_me->GetTransport()) + { + unit->RemoveUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT); + unit->m_movementInfo.transport.Reset(); + } + else + unit->m_movementInfo.transport = _me->m_movementInfo.transport; } // only for flyable vehicles diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index a84e2910e52..04f3395653d 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -638,6 +638,24 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo) if (!ok2) continue; + if (cInfo->expansion > difficultyInfo->expansion) + { + TC_LOG_ERROR("sql.sql", "Creature (Entry: %u, expansion %u) has different `expansion` in difficulty %u mode (Entry: %u, expansion %u).", + cInfo->Entry, cInfo->expansion, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->expansion); + } + + if (cInfo->faction_A != difficultyInfo->faction_A) + { + TC_LOG_ERROR("sql.sql", "Creature (Entry: %u, faction_A %u) has different `faction_A` in difficulty %u mode (Entry: %u, faction_A %u).", + cInfo->Entry, cInfo->faction_A, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->faction_A); + } + + if (cInfo->faction_H != difficultyInfo->faction_H) + { + TC_LOG_ERROR("sql.sql", "Creature (Entry: %u, faction_H %u) has different `faction_H` in difficulty %u mode (Entry: %u, faction_H %u).", + cInfo->Entry, cInfo->faction_H, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->faction_H); + } + if (cInfo->unit_class != difficultyInfo->unit_class) { TC_LOG_ERROR("sql.sql", "Creature (Entry: %u, class %u) has different `unit_class` in difficulty %u mode (Entry: %u, class %u).", @@ -651,6 +669,12 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo) continue; } + if (cInfo->family != difficultyInfo->family) + { + TC_LOG_ERROR("sql.sql", "Creature (Entry: %u, family %u) has different `family` in difficulty %u mode (Entry: %u, family %u).", + cInfo->Entry, cInfo->family, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->family); + } + if (cInfo->trainer_class != difficultyInfo->trainer_class) { TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has different `trainer_class` in difficulty %u mode (Entry: %u).", cInfo->Entry, diff + 1, cInfo->DifficultyEntry[diff]); @@ -675,6 +699,24 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo) continue; } + if (cInfo->type != difficultyInfo->type) + { + TC_LOG_ERROR("sql.sql", "Creature (Entry: %u, type %u) has different `type` in difficulty %u mode (Entry: %u, type %u).", + cInfo->Entry, cInfo->type, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->type); + } + + if (cInfo->type_flags != difficultyInfo->type_flags) + { + TC_LOG_ERROR("sql.sql", "Creature (Entry: %u, type_flags %u) has different `type_flags` in difficulty %u mode (Entry: %u, type_flags %u).", + cInfo->Entry, cInfo->type_flags, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->type_flags); + } + + if (!cInfo->VehicleId && difficultyInfo->VehicleId) + { + TC_LOG_ERROR("sql.sql", "Creature (Entry: %u, VehicleId %u) has different `VehicleId` in difficulty %u mode (Entry: %u, VehicleId %u).", + cInfo->Entry, cInfo->VehicleId, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->VehicleId); + } + if (!difficultyInfo->AIName.empty()) { TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) lists difficulty %u mode entry %u with `AIName` filled in. `AIName` of difficulty 0 mode creature is always used instead.", @@ -883,7 +925,7 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo) const_cast<CreatureTemplate*>(cInfo)->scale = 1.0f; } - if (cInfo->expansion > (MAX_CREATURE_BASE_HP - 1)) + if (cInfo->expansion > (MAX_EXPANSIONS - 1)) { TC_LOG_ERROR("sql.sql", "Table `creature_template` lists creature (Entry: %u) with expansion %u. Ignored and set to 0.", cInfo->Entry, cInfo->expansion); const_cast<CreatureTemplate*>(cInfo)->expansion = 0; @@ -1772,7 +1814,7 @@ bool ObjectMgr::MoveCreData(uint32 guid, uint32 mapId, const Position& pos) // We use spawn coords to spawn if (!map->Instanceable() && map->IsGridLoaded(data.posX, data.posY)) { - Creature* creature = new Creature; + Creature* creature = new Creature(); if (!creature->LoadCreatureFromDB(guid, map)) { TC_LOG_ERROR("misc", "MoveCreData: Cannot add creature guid %u to map", guid); @@ -1824,7 +1866,7 @@ uint32 ObjectMgr::AddCreData(uint32 entry, uint32 /*team*/, uint32 mapId, float // We use spawn coords to spawn if (!map->Instanceable() && !map->IsRemovalGrid(x, y)) { - Creature* creature = new Creature; + Creature* creature = new Creature(); if (!creature->LoadCreatureFromDB(guid, map)) { TC_LOG_ERROR("misc", "AddCreature: Cannot add creature entry %u to map", entry); @@ -3044,8 +3086,8 @@ void ObjectMgr::LoadPetLevelInfo() { if (pInfo[level].health == 0) { - TC_LOG_ERROR("sql.sql", "Creature %u has no data for Level %i pet stats data, using data of Level %i.", itr->first, level+1, level); - pInfo[level] = pInfo[level-1]; + TC_LOG_ERROR("sql.sql", "Creature %u has no data for Level %i pet stats data, using data of Level %i.", itr->first, level + 1, level); + pInfo[level] = pInfo[level - 1]; } } } @@ -3266,7 +3308,7 @@ void ObjectMgr::LoadPlayerInfo() if (!result) { - TC_LOG_ERROR("server.loading", ">> Loaded 0 player create spells. DB table `%s` is empty.", sWorld->getBoolConfig(CONFIG_START_ALL_SPELLS) ? "playercreateinfo_spell_custom" : "playercreateinfo_spell"); + TC_LOG_ERROR("server.loading", ">> Loaded 0 player create spells. DB table `%s` is empty.", tableName.c_str()); } else { @@ -3281,13 +3323,13 @@ void ObjectMgr::LoadPlayerInfo() if (raceMask != 0 && !(raceMask & RACEMASK_ALL_PLAYABLE)) { - TC_LOG_ERROR("sql.sql", "Wrong race mask %u in `playercreateinfo_spell` table, ignoring.", raceMask); + TC_LOG_ERROR("sql.sql", "Wrong race mask %u in `%s` table, ignoring.", raceMask, tableName.c_str()); continue; } if (classMask != 0 && !(classMask & CLASSMASK_ALL_PLAYABLE)) { - TC_LOG_ERROR("sql.sql", "Wrong class mask %u in `playercreateinfo_spell` table, ignoring.", classMask); + TC_LOG_ERROR("sql.sql", "Wrong class mask %u in `%s` table, ignoring.", classMask, tableName.c_str()); continue; } @@ -3307,7 +3349,7 @@ void ObjectMgr::LoadPlayerInfo() // We need something better here, the check is not accounting for spells used by multiple races/classes but not all of them. // Either split the masks per class, or per race, which kind of kills the point yet. // else if (raceMask != 0 && classMask != 0) - // TC_LOG_ERROR("sql.sql", "Racemask/classmask (%u/%u) combination was found containing an invalid race/class combination (%u/%u) in `playercreateinfo_spell` (Spell %u), ignoring.", raceMask, classMask, raceIndex, classIndex, spellId); + // TC_LOG_ERROR("sql.sql", "Racemask/classmask (%u/%u) combination was found containing an invalid race/class combination (%u/%u) in `%s` (Spell %u), ignoring.", raceMask, classMask, raceIndex, classIndex, tableName.c_str(), spellId); } } } @@ -3374,7 +3416,7 @@ void ObjectMgr::LoadPlayerInfo() if (!result) { - TC_LOG_ERROR("server.loading", ">> Loaded 0 level health/mana definitions. DB table `game_event_condition` is empty."); + TC_LOG_ERROR("server.loading", ">> Loaded 0 level health/mana definitions. DB table `player_classlevelstats` is empty."); exit(1); } @@ -3437,8 +3479,8 @@ void ObjectMgr::LoadPlayerInfo() { if (pClassInfo->levelInfo[level].basehealth == 0) { - TC_LOG_ERROR("sql.sql", "Class %i Level %i does not have health/mana data. Using stats data of level %i.", class_, level+1, level); - pClassInfo->levelInfo[level] = pClassInfo->levelInfo[level-1]; + TC_LOG_ERROR("sql.sql", "Class %i Level %i does not have health/mana data. Using stats data of level %i.", class_, level + 1, level); + pClassInfo->levelInfo[level] = pClassInfo->levelInfo[level - 1]; } } } @@ -3498,9 +3540,9 @@ void ObjectMgr::LoadPlayerInfo() if (!info->levelInfo) info->levelInfo = new PlayerLevelInfo[sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)]; - PlayerLevelInfo& levelInfo = info->levelInfo[current_level-1]; + PlayerLevelInfo& levelInfo = info->levelInfo[current_level - 1]; for (int i = 0; i < MAX_STATS; i++) - levelInfo.stats[i] = fields[i+3].GetUInt8(); + levelInfo.stats[i] = fields[i + 3].GetUInt8(); } ++count; @@ -3525,11 +3567,11 @@ void ObjectMgr::LoadPlayerInfo() continue; // skip expansion races if not playing with expansion - if (sWorld->getIntConfig(CONFIG_EXPANSION) < 1 && (race == RACE_BLOODELF || race == RACE_DRAENEI)) + if (sWorld->getIntConfig(CONFIG_EXPANSION) < EXPANSION_THE_BURNING_CRUSADE && (race == RACE_BLOODELF || race == RACE_DRAENEI)) continue; // skip expansion classes if not playing with expansion - if (sWorld->getIntConfig(CONFIG_EXPANSION) < 2 && class_ == CLASS_DEATH_KNIGHT) + if (sWorld->getIntConfig(CONFIG_EXPANSION) < EXPANSION_WRATH_OF_THE_LICH_KING && class_ == CLASS_DEATH_KNIGHT) continue; // fatal error if no level 1 data @@ -3544,8 +3586,8 @@ void ObjectMgr::LoadPlayerInfo() { if (info->levelInfo[level].stats[0] == 0) { - TC_LOG_ERROR("sql.sql", "Race %i Class %i Level %i does not have stats data. Using stats data of level %i.", race, class_, level+1, level); - info->levelInfo[level] = info->levelInfo[level-1]; + TC_LOG_ERROR("sql.sql", "Race %i Class %i Level %i does not have stats data. Using stats data of level %i.", race, class_, level + 1, level); + info->levelInfo[level] = info->levelInfo[level - 1]; } } } @@ -3603,8 +3645,8 @@ void ObjectMgr::LoadPlayerInfo() { if (_playerXPperLevel[level] == 0) { - TC_LOG_ERROR("sql.sql", "Level %i does not have XP for level data. Using data of level [%i] + 100.", level+1, level); - _playerXPperLevel[level] = _playerXPperLevel[level-1]+100; + TC_LOG_ERROR("sql.sql", "Level %i does not have XP for level data. Using data of level [%i] + 100.", level + 1, level); + _playerXPperLevel[level] = _playerXPperLevel[level - 1] + 100; } } @@ -7468,9 +7510,9 @@ void ObjectMgr::LoadGameObjectForQuests() { switch (itr->second.type) { - // scan GO chest with loot including quest items case GAMEOBJECT_TYPE_CHEST: { + // scan GO chest with loot including quest items uint32 loot_id = (itr->second.GetLootId()); // find quest loot for GO @@ -7486,7 +7528,7 @@ void ObjectMgr::LoadGameObjectForQuests() if (itr->second._generic.questID > 0) //quests objects { _gameObjectForQuestStore.insert(itr->second.entry); - count++; + ++count; } break; } @@ -7495,7 +7537,7 @@ void ObjectMgr::LoadGameObjectForQuests() if (itr->second.goober.questId > 0) //quests objects { _gameObjectForQuestStore.insert(itr->second.entry); - count++; + ++count; } break; } @@ -8519,13 +8561,18 @@ CreatureBaseStats const* ObjectMgr::GetCreatureBaseStats(uint8 level, uint8 unit DefaultCreatureBaseStats() { BaseArmor = 1; - for (uint8 j = 0; j < MAX_CREATURE_BASE_HP; ++j) + for (uint8 j = 0; j < MAX_EXPANSIONS; ++j) + { BaseHealth[j] = 1; + BaseDamage[j] = 0.0f; + } BaseMana = 0; + AttackPower = 0; + RangedAttackPower = 0; } }; - static const DefaultCreatureBaseStats def_stats; - return &def_stats; + static const DefaultCreatureBaseStats defStats; + return &defStats; } void ObjectMgr::LoadCreatureClassLevelStats() @@ -8545,35 +8592,38 @@ void ObjectMgr::LoadCreatureClassLevelStats() { Field* fields = result->Fetch(); - uint8 Level = fields[0].GetInt8(); - uint8 Class = fields[1].GetInt8(); - - CreatureBaseStats stats; - - for (uint8 i = 0; i < MAX_CREATURE_BASE_HP; ++i) - stats.BaseHealth[i] = fields[i + 2].GetInt16(); - - stats.BaseMana = fields[5].GetInt16(); - stats.BaseArmor = fields[6].GetInt16(); - - stats.AttackPower = fields[7].GetInt16(); - stats.RangedAttackPower = fields[8].GetInt16(); - - for (uint8 i = 0; i < MAX_CREATURE_BASE_DAMAGE; ++i) - stats.BaseDamage[i] = fields[i + 9].GetFloat(); + uint8 Level = fields[0].GetUInt8(); + uint8 Class = fields[1].GetUInt8(); if (!Class || ((1 << (Class - 1)) & CLASSMASK_ALL_CREATURES) == 0) TC_LOG_ERROR("sql.sql", "Creature base stats for level %u has invalid class %u", Level, Class); - for (uint8 i = 0; i < MAX_CREATURE_BASE_HP; ++i) + CreatureBaseStats stats; + + for (uint8 i = 0; i < MAX_EXPANSIONS; ++i) { - if (stats.BaseHealth[i] < 1) + stats.BaseHealth[i] = fields[2 + i].GetUInt16(); + + if (stats.BaseHealth[i] == 0) { TC_LOG_ERROR("sql.sql", "Creature base stats for class %u, level %u has invalid zero base HP[%u] - set to 1", Class, Level, i); stats.BaseHealth[i] = 1; } + + stats.BaseDamage[i] = fields[9 + i].GetFloat(); + if (stats.BaseDamage[i] < 0.0f) + { + TC_LOG_ERROR("sql.sql", "Creature base stats for class %u, level %u has invalid negative base damage[%u] - set to 0.0", Class, Level, i); + stats.BaseDamage[i] = 0.0f; + } } + stats.BaseMana = fields[5].GetUInt16(); + stats.BaseArmor = fields[6].GetUInt16(); + + stats.AttackPower = fields[7].GetUInt16(); + stats.RangedAttackPower = fields[8].GetUInt16(); + _creatureBaseStatsStore[MAKE_PAIR16(Level, Class)] = stats; ++count; diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index c6907d125c0..354f00a9e91 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -1960,7 +1960,7 @@ void Group::ResetInstances(uint8 method, bool isRaid, Player* SendMsgTo) if (isEmpty || method == INSTANCE_RESET_GROUP_DISBAND || method == INSTANCE_RESET_CHANGE_DIFFICULTY) { // do not reset the instance, just unbind if others are permanently bound to it - if (instanceSave->CanReset()) + if (isEmpty && instanceSave->CanReset()) instanceSave->DeleteFromDB(); else { diff --git a/src/server/game/Handlers/BattlefieldHandler.cpp b/src/server/game/Handlers/BattlefieldHandler.cpp index 078c2eb1084..b0580681f91 100644 --- a/src/server/game/Handlers/BattlefieldHandler.cpp +++ b/src/server/game/Handlers/BattlefieldHandler.cpp @@ -15,136 +15,173 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "Common.h" #include "ObjectAccessor.h" #include "ObjectMgr.h" +#include "Opcodes.h" +#include "Player.h" #include "WorldPacket.h" #include "WorldSession.h" #include "Battlefield.h" #include "BattlefieldMgr.h" -#include "Opcodes.h" -#include "Player.h" -//This send to player windows for invite player to join the war -//Param1:(BattleId) the BattleId of Bf -//Param2:(ZoneId) the zone where the battle is (4197 for wg) -//Param3:(time) Time in second that the player have for accept -void WorldSession::SendBfInvitePlayerToWar(uint32 BattleId, uint32 ZoneId, uint32 p_time) +/** + * @fn void WorldSession::SendBfInvitePlayerToWar(uint32 battleId, uint32 zoneId, uint32 acceptTime) + * + * @brief This send to player windows for invite player to join the war. + * + * @param battleId The BattleId of Bf + * @param zoneId The zone where the battle is (4197 for wg) + * @param acceptTime Time in second that the player have for accept + */ +void WorldSession::SendBfInvitePlayerToWar(uint32 battleId, uint32 zoneId, uint32 acceptTime) { - //Send packet WorldPacket data(SMSG_BATTLEFIELD_MGR_ENTRY_INVITE, 12); - data << uint32(BattleId); - data << uint32(ZoneId); - data << uint32((time(NULL) + p_time)); - - //Sending the packet to player + data << uint32(battleId); + data << uint32(zoneId); + data << uint32(time(NULL) + acceptTime); SendPacket(&data); } -//This send invitation to player to join the queue -//Param1:(BattleId) the BattleId of Bf -void WorldSession::SendBfInvitePlayerToQueue(uint32 BattleId) +/** + * @fn void WorldSession::SendBfInvitePlayerToQueue(uint32 battleId) + * + * @brief This send invitation to player to join the queue. + * + * @param battleId The BattleId of Bf + */ +void WorldSession::SendBfInvitePlayerToQueue(uint32 battleId) { WorldPacket data(SMSG_BATTLEFIELD_MGR_QUEUE_INVITE, 5); - - data << uint32(BattleId); - data << uint8(1); //warmup ? used ? - - //Sending packet to player + data << uint32(battleId); + data << uint8(1); // warmup ? used ? SendPacket(&data); } -//This send packet for inform player that he join queue -//Param1:(BattleId) the BattleId of Bf -//Param2:(ZoneId) the zone where the battle is (4197 for wg) -//Param3:(CanQueue) if able to queue -//Param4:(Full) on log in is full -void WorldSession::SendBfQueueInviteResponse(uint32 BattleId, uint32 ZoneId, bool CanQueue, bool Full) +/** + * @fn void WorldSession::SendBfQueueInviteResponse(uint32 battleId, uint32 zoneId, bool canQueue, bool full) + * + * @brief This send packet for inform player that he join queue. + * + * @param battleId The BattleId of Bf + * @param zoneId The zone where the battle is (4197 for wg) + * @param canQueue if able to queue + * @param full on log in is full + */ +void WorldSession::SendBfQueueInviteResponse(uint32 battleId, uint32 zoneId, bool canQueue, bool full) { WorldPacket data(SMSG_BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE, 11); - data << uint32(BattleId); - data << uint32(ZoneId); - data << uint8((CanQueue ? 1 : 0)); //Accepted //0 you cannot queue wg //1 you are queued - data << uint8((Full ? 0 : 1)); //Logging In //0 wg full //1 queue for upcoming - data << uint8(1); //Warmup + data << uint32(battleId); + data << uint32(zoneId); + data << uint8(canQueue ? 1 : 0); // Accepted // 0 you cannot queue wg // 1 you are queued + data << uint8(full ? 0 : 1); // Logging In // 0 wg full // 1 queue for upcoming + data << uint8(1); // Warmup SendPacket(&data); } -//This is call when player accept to join war -//Param1:(BattleId) the BattleId of Bf -void WorldSession::SendBfEntered(uint32 BattleId) +/** + * @fn void WorldSession::SendBfEntered(uint32 battleId) + * + * @brief This is call when player accept to join war. + * + * @param battleId The BattleId of Bf + */ +void WorldSession::SendBfEntered(uint32 battleId) { -// m_PlayerInWar[player->GetTeamId()].insert(player->GetGUID()); WorldPacket data(SMSG_BATTLEFIELD_MGR_ENTERED, 7); - data << uint32(BattleId); - data << uint8(1); //unk - data << uint8(1); //unk - data << uint8(_player->isAFK() ? 1 : 0); //Clear AFK + data << uint32(battleId); + data << uint8(1); // unk + data << uint8(1); // unk + data << uint8(_player->isAFK() ? 1 : 0); // Clear AFK SendPacket(&data); } -void WorldSession::SendBfLeaveMessage(uint32 BattleId, BFLeaveReason reason) +/** + * @fn void WorldSession::SendBfLeaveMessage(uint32 battleId, BFLeaveReason reason) + * + * @brief This is call when player leave battlefield zone. + * + * @param battleId The BattleId of Bf + * @param reason Reason why player left battlefield + */ +void WorldSession::SendBfLeaveMessage(uint32 battleId, BFLeaveReason reason /*= BF_LEAVE_REASON_EXITED*/) { WorldPacket data(SMSG_BATTLEFIELD_MGR_EJECTED, 7); - data << uint32(BattleId); - data << uint8(reason);//byte Reason - data << uint8(2);//byte BattleStatus - data << uint8(0);//bool Relocated + data << uint32(battleId); + data << uint8(reason); // byte Reason + data << uint8(2); // byte BattleStatus + data << uint8(0); // bool Relocated SendPacket(&data); } -//Send by client when he click on accept for queue -void WorldSession::HandleBfQueueInviteResponse(WorldPacket & recvData) +/** + * @fn void WorldSession::HandleBfQueueInviteResponse(WorldPacket& recvData) + * + * @brief Send by client when he click on accept for queue. + */ +void WorldSession::HandleBfQueueInviteResponse(WorldPacket& recvData) { - uint32 BattleId; - uint8 Accepted; + uint32 battleId; + uint8 accepted; + + recvData >> battleId >> accepted; - recvData >> BattleId >> Accepted; - TC_LOG_DEBUG("misc", "HandleQueueInviteResponse: BattleID:%u Accepted:%u", BattleId, Accepted); - Battlefield* Bf = sBattlefieldMgr->GetBattlefieldByBattleId(BattleId); - if (!Bf) + TC_LOG_DEBUG("misc", "HandleBfQueueInviteResponse: BattleID:%u Accepted:%u", battleId, accepted); + + Battlefield* bf = sBattlefieldMgr->GetBattlefieldByBattleId(battleId); + if (!bf) return; - if (Accepted) - { - Bf->PlayerAcceptInviteToQueue(_player); - } + if (accepted) + bf->PlayerAcceptInviteToQueue(_player); } -//Send by client on clicking in accept or refuse of invitation windows for join game -void WorldSession::HandleBfEntryInviteResponse(WorldPacket & recvData) +/** + * @fn void WorldSession::HandleBfEntryInviteResponse(WorldPacket& recvData) + * + * @brief Send by client on clicking in accept or refuse of invitation windows for join game. + */ +void WorldSession::HandleBfEntryInviteResponse(WorldPacket& recvData) { - uint32 BattleId; - uint8 Accepted; + uint32 battleId; + uint8 accepted; + + recvData >> battleId >> accepted; + + TC_LOG_DEBUG("misc", "HandleBfEntryInviteResponse: battleId: %u, accepted: %u", battleId, accepted); - recvData >> BattleId >> Accepted; - TC_LOG_DEBUG("misc", "HandleBattlefieldInviteResponse: BattleID:%u Accepted:%u", BattleId, Accepted); - Battlefield* Bf = sBattlefieldMgr->GetBattlefieldByBattleId(BattleId); - if (!Bf) + Battlefield* bf = sBattlefieldMgr->GetBattlefieldByBattleId(battleId); + if (!bf) return; - //If player accept invitation - if (Accepted) + // If player accept invitation + if (accepted) { - Bf->PlayerAcceptInviteToWar(_player); + bf->PlayerAcceptInviteToWar(_player); } else { - if (_player->GetZoneId() == Bf->GetZoneId()) - Bf->KickPlayerFromBattlefield(_player->GetGUID()); + if (_player->GetZoneId() == bf->GetZoneId()) + bf->KickPlayerFromBattlefield(_player->GetGUID()); } } -void WorldSession::HandleBfExitRequest(WorldPacket & recvData) +/** + * @fn void WorldSession::HandleBfExitRequest(WorldPacket& recvData) + * + * @brief Send by client when exited battlefield + */ +void WorldSession::HandleBfExitRequest(WorldPacket& recvData) { - uint32 BattleId; + uint32 battleId; + + recvData >> battleId; + + TC_LOG_DEBUG("misc", "HandleBfExitRequest: battleId: %u ", battleId); - recvData >> BattleId; - TC_LOG_DEBUG("misc", "HandleBfExitRequest: BattleID:%u ", BattleId); - Battlefield* Bf = sBattlefieldMgr->GetBattlefieldByBattleId(BattleId); - if (!Bf) + Battlefield* bf = sBattlefieldMgr->GetBattlefieldByBattleId(battleId); + if (!bf) return; - Bf->AskToLeaveQueue(_player); + bf->AskToLeaveQueue(_player); } diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 6d790919633..94e9306b29f 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -1919,6 +1919,8 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData) if (result) if (Guild* guild = sGuildMgr->GetGuildById((result->Fetch()[0]).GetUInt32())) guild->DeleteMember(MAKE_NEW_GUID(lowGuid, 0, HIGHGUID_PLAYER), false, false, true); + + Player::LeaveAllArenaTeams(guid); } if (!HasPermission(rbac::RBAC_PERM_TWO_SIDE_ADD_FRIEND)) @@ -1931,12 +1933,8 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData) stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_SOCIAL_BY_FRIEND); stmt->setUInt32(0, lowGuid); trans->Append(stmt); - } - // Leave Arena Teams - Player::LeaveAllArenaTeams(guid); - // Reset homebind and position stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_HOMEBIND); stmt->setUInt32(0, lowGuid); diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp index b6b4ca84263..6404d3c8e41 100644 --- a/src/server/game/Handlers/GroupHandler.cpp +++ b/src/server/game/Handlers/GroupHandler.cpp @@ -741,7 +741,7 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacke playerStatus |= MEMBER_STATUS_DEAD; } - if (player->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) + if (player->IsFFAPvP()) playerStatus |= MEMBER_STATUS_PVP_FFA; if (player->isAFK()) @@ -943,7 +943,7 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket &recvData) playerStatus |= MEMBER_STATUS_DEAD; } - if (player->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) + if (player->IsFFAPvP()) playerStatus |= MEMBER_STATUS_PVP_FFA; if (player->isAFK()) diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp index 477b6ddfc77..3571410fd5c 100644 --- a/src/server/game/Handlers/ItemHandler.cpp +++ b/src/server/game/Handlers/ItemHandler.cpp @@ -991,9 +991,9 @@ void WorldSession::HandleAutoStoreBankItemOpcode(WorldPacket& recvPacket) void WorldSession::HandleSetAmmoOpcode(WorldPacket& recvData) { - if (!GetPlayer()->IsAlive()) + if (!_player->IsAlive()) { - GetPlayer()->SendEquipError(EQUIP_ERR_YOU_ARE_DEAD, NULL, NULL); + _player->SendEquipError(EQUIP_ERR_YOU_ARE_DEAD, NULL, NULL); return; } @@ -1002,10 +1002,18 @@ void WorldSession::HandleSetAmmoOpcode(WorldPacket& recvData) recvData >> item; - if (!item) - GetPlayer()->RemoveAmmo(); + if (item) + { + if (!_player->GetItemCount(item)) + { + _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); + return; + } + + _player->SetAmmo(item); + } else - GetPlayer()->SetAmmo(item); + _player->RemoveAmmo(); } void WorldSession::SendEnchantmentLog(uint64 target, uint64 caster, uint32 itemId, uint32 enchantId) diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 7405cbe538b..8b92706bd06 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -1721,7 +1721,7 @@ void WorldSession::HandleHearthAndResurrect(WorldPacket& /*recvData*/) return; _player->BuildPlayerRepop(); - _player->ResurrectPlayer(100); + _player->ResurrectPlayer(1.0f); _player->TeleportTo(_player->m_homebindMapId, _player->m_homebindX, _player->m_homebindY, _player->m_homebindZ, _player->GetOrientation()); } diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 08dc8602351..0c2eae849b8 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -381,6 +381,9 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData) if (plrMover) // nothing is charmed, or player charmed { + if (plrMover->IsSitState() && (movementInfo.flags & (MOVEMENTFLAG_MASK_MOVING | MOVEMENTFLAG_MASK_TURNING))) + plrMover->SetStandState(UNIT_STAND_STATE_STAND); + plrMover->UpdateFallInformationIfNeed(movementInfo, opcode); if (movementInfo.pos.GetPositionZ() < -500.0f) diff --git a/src/server/game/Instances/InstanceSaveMgr.cpp b/src/server/game/Instances/InstanceSaveMgr.cpp index a6690a7e0b3..c46d9002604 100644 --- a/src/server/game/Instances/InstanceSaveMgr.cpp +++ b/src/server/game/Instances/InstanceSaveMgr.cpp @@ -161,6 +161,16 @@ void InstanceSaveManager::RemoveInstanceSave(uint32 InstanceId) } } +void InstanceSaveManager::UnloadInstanceSave(uint32 InstanceId) +{ + if (InstanceSave* save = GetInstanceSave(InstanceId)) + { + save->UnloadIfEmpty(); + if (save->m_toDelete) + delete save; + } +} + InstanceSave::InstanceSave(uint16 MapId, uint32 InstanceId, Difficulty difficulty, time_t resetTime, bool canReset) : m_resetTime(resetTime), m_instanceid(InstanceId), m_mapid(MapId), m_difficulty(difficulty), m_canReset(canReset), m_toDelete(false) { } @@ -232,6 +242,11 @@ bool InstanceSave::UnloadIfEmpty() { if (m_playerList.empty() && m_groupList.empty()) { + // don't remove the save if there are still players inside the map + if (Map* map = sMapMgr->FindMap(GetMapId(), GetInstanceId())) + if (map->HavePlayers()) + return true; + if (!sInstanceSaveMgr->lock_instLists) sInstanceSaveMgr->RemoveInstanceSave(GetInstanceId()); diff --git a/src/server/game/Instances/InstanceSaveMgr.h b/src/server/game/Instances/InstanceSaveMgr.h index 85c9e081db5..1d753ebaa48 100644 --- a/src/server/game/Instances/InstanceSaveMgr.h +++ b/src/server/game/Instances/InstanceSaveMgr.h @@ -115,16 +115,16 @@ class InstanceSave but that would depend on a lot of things that can easily change in future */ Difficulty GetDifficulty() const { return m_difficulty; } + typedef std::list<Player*> PlayerListType; + typedef std::list<Group*> GroupListType; + private: + bool UnloadIfEmpty(); /* used to flag the InstanceSave as to be deleted, so the caller can delete it */ void SetToDelete(bool toDelete) { m_toDelete = toDelete; } - typedef std::list<Player*> PlayerListType; - typedef std::list<Group*> GroupListType; - private: - bool UnloadIfEmpty(); /* the only reason the instSave-object links are kept is because the object-instSave links need to be broken at reset time */ /// @todo: Check if maybe it's enough to just store the number of players/groups @@ -195,6 +195,7 @@ class InstanceSaveManager InstanceSave* AddInstanceSave(uint32 mapId, uint32 instanceId, Difficulty difficulty, time_t resetTime, bool canReset, bool load = false); void RemoveInstanceSave(uint32 InstanceId); + void UnloadInstanceSave(uint32 InstanceId); static void DeleteInstanceFromDB(uint32 instanceid); InstanceSave* GetInstanceSave(uint32 InstanceId); diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 39d989ef9bc..21e282cfcf4 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -2863,6 +2863,7 @@ void InstanceMap::RemovePlayerFromMap(Player* player, bool remove) Map::RemovePlayerFromMap(player, remove); // for normal instances schedule the reset after all players have left SetResetSchedule(true); + sInstanceSaveMgr->UnloadInstanceSave(GetInstanceId()); } void InstanceMap::CreateInstanceData(bool load) diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index 6f380d42fda..3102e2c6854 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -1215,6 +1215,18 @@ enum TrinityStrings LANG_AUTO_BROADCAST = 11000, LANG_INVALID_REALMID = 11001, + // Show Kick in world + LANG_COMMAND_KICKMESSAGE_WORLD = 11002, + + // Show Mute in world + LANG_COMMAND_MUTEMESSAGE_WORLD = 11003, + + // Show Ban in world + LANG_BAN_CHARACTER_YOUBANNEDMESSAGE_WORLD = 11004, + LANG_BAN_CHARACTER_YOUPERMBANNEDMESSAGE_WORLD = 11005, + LANG_BAN_ACCOUNT_YOUBANNEDMESSAGE_WORLD = 11006, + LANG_BAN_ACCOUNT_YOUPERMBANNEDMESSAGE_WORLD = 11007, + // NOT RESERVED IDS 12000-1999999999 // `db_script_string` table index 2000000000-2000009999 (MIN_DB_SCRIPT_STRING_ID-MAX_DB_SCRIPT_STRING_ID) // For other tables maybe 2000010000-2147483647 (max index) diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 9d63e97a159..e5d3a5312de 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -44,6 +44,14 @@ enum LootModes LOOT_MODE_HARD_MODE_4 = 0x10 }; +enum Expansions +{ + EXPANSION_CLASSIC = 0, + EXPANSION_THE_BURNING_CRUSADE = 1, + EXPANSION_WRATH_OF_THE_LICH_KING = 2, + MAX_EXPANSIONS = 3 +}; + enum Gender { GENDER_MALE = 0, diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index c05d7804948..aabb117ef50 100644 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -96,11 +96,11 @@ class MotionMaster //: private std::stack<MovementGenerator *> } void push(_Ty _Val) { ++_top; Impl[_top] = _Val; } - bool needInitTop() const - { + bool needInitTop() const + { if (empty()) return false; - return _needInit[_top]; + return _needInit[_top]; } void InitTop(); public: @@ -120,15 +120,15 @@ class MotionMaster //: private std::stack<MovementGenerator *> bool empty() const { return (_top < 0); } int size() const { return _top + 1; } - _Ty top() const - { + _Ty top() const + { ASSERT(!empty()); - return Impl[_top]; + return Impl[_top]; } - _Ty GetMotionSlot(int slot) const - { + _Ty GetMotionSlot(int slot) const + { ASSERT(slot >= 0); - return Impl[slot]; + return Impl[slot]; } void DirectDelete(_Ty curr); diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp index bc2460fa709..572d65b07c7 100644 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp @@ -25,6 +25,7 @@ #include "MoveSplineInit.h" #include "MoveSpline.h" #include "Player.h" +#include "VMapFactory.h" #define MIN_QUIET_DISTANCE 28.0f #define MAX_QUIET_DISTANCE 43.0f @@ -43,6 +44,20 @@ void FleeingMovementGenerator<T>::_setTargetLocation(T* owner) float x, y, z; _getPoint(owner, x, y, z); + // Add LOS check for target point + Position mypos; + owner->GetPosition(&mypos); + bool isInLOS = VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(owner->GetMapId(), + mypos.m_positionX, + mypos.m_positionY, + mypos.m_positionZ + 2.0f, + x, y, z + 2.0f); + if (!isInLOS) + { + i_nextCheckTime.Reset(200); + return; + } + PathGenerator path(owner); path.SetPathLengthLimit(30.0f); bool result = path.CalculatePath(x, y, z); diff --git a/src/server/game/Movement/Spline/MoveSplineInit.cpp b/src/server/game/Movement/Spline/MoveSplineInit.cpp index f6ef219522c..87d8e4a0c34 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.cpp +++ b/src/server/game/Movement/Spline/MoveSplineInit.cpp @@ -60,23 +60,27 @@ namespace Movement { MoveSpline& move_spline = *unit->movespline; - bool transport = false; - Location real_position(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZMinusOffset(), unit->GetOrientation()); - // Elevators also use MOVEMENTFLAG_ONTRANSPORT but we do not keep track of their position changes - if (unit->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && unit->GetTransGUID()) - { - transport = true; - real_position.x = unit->GetTransOffsetX(); - real_position.y = unit->GetTransOffsetY(); - real_position.z = unit->GetTransOffsetZ(); - real_position.orientation = unit->GetTransOffsetO(); - } - + // Elevators also use MOVEMENTFLAG_ONTRANSPORT but we do not keep track of their position changes (movementInfo.transport.guid is 0 in that case) + bool transport = unit->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && unit->GetTransGUID(); + Location real_position; // there is a big chance that current position is unknown if current state is not finalized, need compute it // this also allows CalculatePath spline position and update map position in much greater intervals // Don't compute for transport movement if the unit is in a motion between two transports if (!move_spline.Finalized() && move_spline.onTransport == transport) real_position = move_spline.ComputePosition(); + else + { + Position const* pos; + if (!transport) + pos = unit; + else + pos = &unit->m_movementInfo.transport.pos; + + real_position.x = pos->GetPositionX(); + real_position.y = pos->GetPositionY(); + real_position.z = pos->GetPositionZ(); + real_position.orientation = unit->GetOrientation(); + } // should i do the things that user should do? - no. if (args.path.empty()) @@ -135,14 +139,32 @@ namespace Movement if (move_spline.Finalized()) return; - Location loc = move_spline.ComputePosition(); + bool transport = unit->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && unit->GetTransGUID(); + Location loc; + if (move_spline.onTransport == transport) + loc = move_spline.ComputePosition(); + else + { + Position const* pos; + if (!transport) + pos = unit; + else + pos = &unit->m_movementInfo.transport.pos; + + loc.x = pos->GetPositionX(); + loc.y = pos->GetPositionY(); + loc.z = pos->GetPositionZ(); + loc.orientation = unit->GetOrientation(); + } + args.flags = MoveSplineFlag::Done; unit->m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_SPLINE_ENABLED); + move_spline.onTransport = transport; move_spline.Initialize(args); WorldPacket data(SMSG_MONSTER_MOVE, 64); data.append(unit->GetPackGUID()); - if (unit->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && unit->GetTransGUID()) + if (transport) { data.SetOpcode(SMSG_MONSTER_MOVE_TRANSPORT); data.appendPackGUID(unit->GetTransGUID()); diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index b84a9a6f093..97e81de7ecf 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -526,7 +526,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = /*0x1F1*/ { "MSG_SAVE_GUILD_EMBLEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSaveGuildEmblemOpcode }, /*0x1F2*/ { "MSG_TABARDVENDOR_ACTIVATE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTabardVendorActivateOpcode}, /*0x1F3*/ { "SMSG_PLAY_SPELL_VISUAL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, - /*0x1F4*/ { "CMSG_ZONEUPDATE", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleZoneUpdateOpcode }, + /*0x1F4*/ { "CMSG_ZONEUPDATE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleZoneUpdateOpcode }, /*0x1F5*/ { "SMSG_PARTYKILLLOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, /*0x1F6*/ { "SMSG_COMPRESSED_UPDATE_OBJECT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, /*0x1F7*/ { "SMSG_PLAY_SPELL_IMPACT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index d3586bf6e8f..8b00cb9432e 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -757,6 +757,16 @@ class WorldSession void HandleBattlemasterJoinArena(WorldPacket& recvData); void HandleReportPvPAFK(WorldPacket& recvData); + // Battlefield + void SendBfInvitePlayerToWar(uint32 battleId, uint32 zoneId, uint32 time); + void SendBfInvitePlayerToQueue(uint32 battleId); + void SendBfQueueInviteResponse(uint32 battleId, uint32 zoneId, bool canQueue = true, bool full = false); + void SendBfEntered(uint32 battleId); + void SendBfLeaveMessage(uint32 battleId, BFLeaveReason reason = BF_LEAVE_REASON_EXITED); + void HandleBfQueueInviteResponse(WorldPacket& recvData); + void HandleBfEntryInviteResponse(WorldPacket& recvData); + void HandleBfExitRequest(WorldPacket& recvData); + void HandleWardenDataOpcode(WorldPacket& recvData); void HandleWorldTeleportOpcode(WorldPacket& recvData); void HandleMinimapPingOpcode(WorldPacket& recvData); @@ -773,16 +783,6 @@ class WorldSession void HandleHearthAndResurrect(WorldPacket& recvData); void HandleInstanceLockResponse(WorldPacket& recvPacket); - // Battlefield - void SendBfInvitePlayerToWar(uint32 battleId, uint32 zoneId, uint32 time); - void SendBfInvitePlayerToQueue(uint32 battleId); - void SendBfQueueInviteResponse(uint32 battleId, uint32 zoneId, bool canQueue = true, bool full = false); - void SendBfEntered(uint32 battleId); - void SendBfLeaveMessage(uint32 battleId, BFLeaveReason reason = BF_LEAVE_REASON_EXITED); - void HandleBfQueueInviteResponse(WorldPacket& recvData); - void HandleBfEntryInviteResponse(WorldPacket& recvData); - void HandleBfExitRequest(WorldPacket& recvData); - // Looking for Dungeon/Raid void HandleLfgSetCommentOpcode(WorldPacket& recvData); void HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& recvData); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 6a3e804eb57..5cb86244aa1 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -2214,26 +2214,26 @@ void AuraEffect::HandleAuraModDisarm(AuraApplication const* aurApp, uint8 mode, WeaponAttackType attType; switch (type) { - case SPELL_AURA_MOD_DISARM: - field=UNIT_FIELD_FLAGS; - flag=UNIT_FLAG_DISARMED; - slot=EQUIPMENT_SLOT_MAINHAND; - attType=BASE_ATTACK; - break; - case SPELL_AURA_MOD_DISARM_OFFHAND: - field=UNIT_FIELD_FLAGS_2; - flag=UNIT_FLAG2_DISARM_OFFHAND; - slot=EQUIPMENT_SLOT_OFFHAND; - attType=OFF_ATTACK; - break; - case SPELL_AURA_MOD_DISARM_RANGED: - field=UNIT_FIELD_FLAGS_2; - flag=UNIT_FLAG2_DISARM_RANGED; - slot=EQUIPMENT_SLOT_RANGED; - attType=RANGED_ATTACK; - break; - default: - return; + case SPELL_AURA_MOD_DISARM: + field = UNIT_FIELD_FLAGS; + flag = UNIT_FLAG_DISARMED; + slot = EQUIPMENT_SLOT_MAINHAND; + attType = BASE_ATTACK; + break; + case SPELL_AURA_MOD_DISARM_OFFHAND: + field = UNIT_FIELD_FLAGS_2; + flag = UNIT_FLAG2_DISARM_OFFHAND; + slot = EQUIPMENT_SLOT_OFFHAND; + attType = OFF_ATTACK; + break; + case SPELL_AURA_MOD_DISARM_RANGED: + field = UNIT_FIELD_FLAGS_2; + flag = UNIT_FLAG2_DISARM_RANGED; + slot = EQUIPMENT_SLOT_RANGED; + attType = RANGED_ATTACK; + break; + default: + return; } // if disarm aura is to be removed, remove the flag first to reapply damage/aura mods @@ -4112,7 +4112,7 @@ void AuraEffect::HandleModAttackSpeed(AuraApplication const* aurApp, uint8 mode, Unit* target = aurApp->GetTarget(); - target->ApplyAttackTimePercentMod(BASE_ATTACK, (float)GetAmount(), apply); + target->ApplyAttackTimePercentMod(BASE_ATTACK, float(GetAmount()), apply); target->UpdateDamagePhysical(BASE_ATTACK); } @@ -4123,8 +4123,8 @@ void AuraEffect::HandleModMeleeSpeedPct(AuraApplication const* aurApp, uint8 mod Unit* target = aurApp->GetTarget(); - target->ApplyAttackTimePercentMod(BASE_ATTACK, (float)GetAmount(), apply); - target->ApplyAttackTimePercentMod(OFF_ATTACK, (float)GetAmount(), apply); + target->ApplyAttackTimePercentMod(BASE_ATTACK, float(GetAmount()), apply); + target->ApplyAttackTimePercentMod(OFF_ATTACK, float(GetAmount()), apply); } void AuraEffect::HandleAuraModRangedHaste(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -4371,9 +4371,9 @@ void AuraEffect::HandleModDamagePercentDone(AuraApplication const* aurApp, uint8 if ((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) && (GetSpellInfo()->EquippedItemClass == -1 || target->GetTypeId() != TYPEID_PLAYER)) { - target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float (GetAmount()), apply); - target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float (GetAmount()), apply); - target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float (GetAmount()), apply); + target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(GetAmount()), apply); + target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetAmount()), apply); + target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(GetAmount()), apply); if (target->GetTypeId() == TYPEID_PLAYER) target->ToPlayer()->ApplyPercentModFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT, float (GetAmount()), apply); @@ -5684,9 +5684,6 @@ void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster) case 46284: target->CastCustomSpell(triggerSpellId, SPELLVALUE_MAX_TARGETS, m_tickNumber / 10 + 1, NULL, true, NULL, this); return; - // Poison (Grobbulus) - case 28158: - case 54362: // Slime Pool (Dreadscale & Acidmaw) case 66882: target->CastCustomSpell(triggerSpellId, SPELLVALUE_RADIUS_MOD, (int32)((((float)m_tickNumber / 60) * 0.9f + 0.1f) * 10000 * 2 / 3), NULL, true, NULL, this); diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 4aedc1a95eb..49eed70f57d 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -4760,6 +4760,10 @@ SpellCastResult Spell::CheckCast(bool strict) else return SPELL_FAILED_NOT_READY; } + + // check if we are using a potion in combat for the 2nd+ time. Cooldown is added only after caster gets out of combat + if (m_caster->ToPlayer()->GetLastPotionId() && m_CastItem && (m_CastItem->IsPotion() || m_spellInfo->IsCooldownStartedOnEvent())) + return SPELL_FAILED_NOT_READY; } if (m_spellInfo->AttributesEx7 & SPELL_ATTR7_IS_CHEAT_SPELL && !m_caster->HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_ALLOW_CHEAT_SPELLS)) diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 9a2b3815285..b8e5b3ff742 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -2326,7 +2326,7 @@ void Spell::EffectSummonType(SpellEffIndex effIndex) if (!summon || !summon->HasUnitTypeMask(UNIT_MASK_MINION)) return; - summon->SelectLevel(summon->GetCreatureTemplate()); // some summoned creaters have different from 1 DB data for level/hp + summon->SelectLevel(); // some summoned creaters have different from 1 DB data for level/hp summon->SetUInt32Value(UNIT_NPC_FLAGS, summon->GetCreatureTemplate()->npcflag); summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); @@ -2538,8 +2538,6 @@ void Spell::EffectDualWield(SpellEffIndex /*effIndex*/) return; unitTarget->SetCanDualWield(true); - if (unitTarget->GetTypeId() == TYPEID_UNIT) - unitTarget->ToCreature()->UpdateDamagePhysical(OFF_ATTACK); } void Spell::EffectPull(SpellEffIndex effIndex) @@ -5819,11 +5817,11 @@ void Spell::SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const* { if (uint32 weapon = m_caster->GetUInt32Value(PLAYER_VISIBLE_ITEM_16_ENTRYID)) { - summon->SetDisplayId(11686); + summon->SetDisplayId(11686); // modelid2 summon->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, weapon); } else - summon->SetDisplayId(1126); + summon->SetDisplayId(1126); // modelid1 } summon->AI()->EnterEvadeMode(); diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 2861ddf049f..d51be9b04b5 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -455,6 +455,8 @@ uint32 SpellMgr::GetSpellDifficultyId(uint32 spellId) const void SpellMgr::SetSpellDifficultyId(uint32 spellId, uint32 id) { + if (uint32 i = GetSpellDifficultyId(spellId)) + TC_LOG_ERROR("spells", "SpellMgr::SetSpellDifficultyId: Spell %u has already spellDifficultyId %u. Will override with spellDifficultyId %u.", spellId, i, id); mSpellDifficultySearcherMap[spellId] = id; } @@ -480,7 +482,7 @@ uint32 SpellMgr::GetSpellIdForDifficulty(uint32 spellId, Unit const* caster) con SpellDifficultyEntry const* difficultyEntry = sSpellDifficultyStore.LookupEntry(difficultyId); if (!difficultyEntry) { - TC_LOG_DEBUG("spells", "SpellMgr::GetSpellIdForDifficulty: SpellDifficultyEntry not found for spell %u. This should never happen.", spellId); + TC_LOG_ERROR("spells", "SpellMgr::GetSpellIdForDifficulty: SpellDifficultyEntry not found for spell %u. This should never happen.", spellId); return spellId; //return source spell } @@ -3042,6 +3044,9 @@ void SpellMgr::LoadSpellInfoCorrections() case 42730: spellInfo->Effects[EFFECT_1].TriggerSpell = 42739; break; + case 42436: // Drink! (Brewfest) + spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ANY); + break; case 59735: spellInfo->Effects[EFFECT_1].TriggerSpell = 59736; break; @@ -3690,6 +3695,9 @@ void SpellMgr::LoadSpellInfoCorrections() // // RUBY SANCTUM SPELLS // + case 74799: // Soul Consumption + spellInfo->Effects[EFFECT_1].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_12_YARDS); + break; case 74769: // Twilight Cutter case 77844: // Twilight Cutter case 77845: // Twilight Cutter diff --git a/src/server/game/Warden/Warden.cpp b/src/server/game/Warden/Warden.cpp index 2462fc203d2..4611a4da884 100644 --- a/src/server/game/Warden/Warden.cpp +++ b/src/server/game/Warden/Warden.cpp @@ -32,7 +32,7 @@ Warden::Warden() : _session(NULL), _inputCrypto(16), _outputCrypto(16), _checkTimer(10000/*10 sec*/), _clientResponseTimer(0), _dataSent(false), _previousTimestamp(0), _module(NULL), _initialized(false) -{ +{ memset(_inputKey, 0, sizeof(_inputKey)); memset(_outputKey, 0, sizeof(_outputKey)); memset(_seed, 0, sizeof(_seed)); diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index c071505e97c..d5bd0974922 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -431,27 +431,27 @@ void World::LoadConfigSettings(bool reload) m_int_configs[CONFIG_ENABLE_SINFO_LOGIN] = sConfigMgr->GetIntDefault("Server.LoginInfo", 0); ///- Read all rates from the config file - rate_values[RATE_HEALTH] = sConfigMgr->GetFloatDefault("Rate.Health", 1); + rate_values[RATE_HEALTH] = sConfigMgr->GetFloatDefault("Rate.Health", 1.0f); if (rate_values[RATE_HEALTH] < 0) { TC_LOG_ERROR("server.loading", "Rate.Health (%f) must be > 0. Using 1 instead.", rate_values[RATE_HEALTH]); rate_values[RATE_HEALTH] = 1; } - rate_values[RATE_POWER_MANA] = sConfigMgr->GetFloatDefault("Rate.Mana", 1); + rate_values[RATE_POWER_MANA] = sConfigMgr->GetFloatDefault("Rate.Mana", 1.0f); if (rate_values[RATE_POWER_MANA] < 0) { TC_LOG_ERROR("server.loading", "Rate.Mana (%f) must be > 0. Using 1 instead.", rate_values[RATE_POWER_MANA]); rate_values[RATE_POWER_MANA] = 1; } - rate_values[RATE_POWER_RAGE_INCOME] = sConfigMgr->GetFloatDefault("Rate.Rage.Income", 1); - rate_values[RATE_POWER_RAGE_LOSS] = sConfigMgr->GetFloatDefault("Rate.Rage.Loss", 1); + rate_values[RATE_POWER_RAGE_INCOME] = sConfigMgr->GetFloatDefault("Rate.Rage.Income", 1.0f); + rate_values[RATE_POWER_RAGE_LOSS] = sConfigMgr->GetFloatDefault("Rate.Rage.Loss", 1.0f); if (rate_values[RATE_POWER_RAGE_LOSS] < 0) { TC_LOG_ERROR("server.loading", "Rate.Rage.Loss (%f) must be > 0. Using 1 instead.", rate_values[RATE_POWER_RAGE_LOSS]); rate_values[RATE_POWER_RAGE_LOSS] = 1; } - rate_values[RATE_POWER_RUNICPOWER_INCOME] = sConfigMgr->GetFloatDefault("Rate.RunicPower.Income", 1); - rate_values[RATE_POWER_RUNICPOWER_LOSS] = sConfigMgr->GetFloatDefault("Rate.RunicPower.Loss", 1); + rate_values[RATE_POWER_RUNICPOWER_INCOME] = sConfigMgr->GetFloatDefault("Rate.RunicPower.Income", 1.0f); + rate_values[RATE_POWER_RUNICPOWER_LOSS] = sConfigMgr->GetFloatDefault("Rate.RunicPower.Loss", 1.0f); if (rate_values[RATE_POWER_RUNICPOWER_LOSS] < 0) { TC_LOG_ERROR("server.loading", "Rate.RunicPower.Loss (%f) must be > 0. Using 1 instead.", rate_values[RATE_POWER_RUNICPOWER_LOSS]); @@ -645,8 +645,8 @@ void World::LoadConfigSettings(bool reload) m_float_configs[CONFIG_MAX_RECRUIT_A_FRIEND_DISTANCE] = sConfigMgr->GetFloatDefault("MaxRecruitAFriendBonusDistance", 100.0f); /// @todo Add MonsterSight and GuarderSight (with meaning) in worldserver.conf or put them as define - m_float_configs[CONFIG_SIGHT_MONSTER] = sConfigMgr->GetFloatDefault("MonsterSight", 50); - m_float_configs[CONFIG_SIGHT_GUARDER] = sConfigMgr->GetFloatDefault("GuarderSight", 50); + m_float_configs[CONFIG_SIGHT_MONSTER] = sConfigMgr->GetFloatDefault("MonsterSight", 50.0f); + m_float_configs[CONFIG_SIGHT_GUARDER] = sConfigMgr->GetFloatDefault("GuarderSight", 50.0f); if (reload) { @@ -947,12 +947,12 @@ void World::LoadConfigSettings(bool reload) if (reload) { - uint32 val = sConfigMgr->GetIntDefault("Expansion", 1); + uint32 val = sConfigMgr->GetIntDefault("Expansion", 2); if (val != m_int_configs[CONFIG_EXPANSION]) TC_LOG_ERROR("server.loading", "Expansion option can't be changed at worldserver.conf reload, using current value (%u).", m_int_configs[CONFIG_EXPANSION]); } else - m_int_configs[CONFIG_EXPANSION] = sConfigMgr->GetIntDefault("Expansion", 1); + m_int_configs[CONFIG_EXPANSION] = sConfigMgr->GetIntDefault("Expansion", 2); m_int_configs[CONFIG_CHATFLOOD_MESSAGE_COUNT] = sConfigMgr->GetIntDefault("ChatFlood.MessageCount", 10); m_int_configs[CONFIG_CHATFLOOD_MESSAGE_DELAY] = sConfigMgr->GetIntDefault("ChatFlood.MessageDelay", 1); @@ -1173,6 +1173,8 @@ void World::LoadConfigSettings(bool reload) m_bool_configs[CONFIG_NO_RESET_TALENT_COST] = sConfigMgr->GetBoolDefault("NoResetTalentsCost", false); m_bool_configs[CONFIG_SHOW_KICK_IN_WORLD] = sConfigMgr->GetBoolDefault("ShowKickInWorld", false); + m_bool_configs[CONFIG_SHOW_MUTE_IN_WORLD] = sConfigMgr->GetBoolDefault("ShowMuteInWorld", false); + m_bool_configs[CONFIG_SHOW_BAN_IN_WORLD] = sConfigMgr->GetBoolDefault("ShowBanInWorld", false); m_int_configs[CONFIG_INTERVAL_LOG_UPDATE] = sConfigMgr->GetIntDefault("RecordUpdateTimeDiffInterval", 60000); m_int_configs[CONFIG_MIN_LOG_UPDATE] = sConfigMgr->GetIntDefault("MinRecordUpdateTimeDiff", 100); m_int_configs[CONFIG_NUMTHREADS] = sConfigMgr->GetIntDefault("MapUpdate.Threads", 1); @@ -3167,6 +3169,10 @@ void World::UpdateCharacterNameData(uint32 guid, std::string const& name, uint8 if (race != RACE_NONE) itr->second.m_race = race; + + WorldPacket data(SMSG_INVALIDATE_PLAYER, 8); + data << MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER); + SendGlobalMessage(&data); } void World::UpdateCharacterNameDataLevel(uint32 guid, uint8 level) diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 080c9d9006b..8c8aebf97d9 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -137,6 +137,8 @@ enum WorldBoolConfigs CONFIG_PVP_TOKEN_ENABLE, CONFIG_NO_RESET_TALENT_COST, CONFIG_SHOW_KICK_IN_WORLD, + CONFIG_SHOW_MUTE_IN_WORLD, + CONFIG_SHOW_BAN_IN_WORLD, CONFIG_CHATLOG_CHANNEL, CONFIG_CHATLOG_WHISPER, CONFIG_CHATLOG_SYSCHAN, diff --git a/src/server/scripts/Commands/cs_ban.cpp b/src/server/scripts/Commands/cs_ban.cpp index c32a03f9bd8..b1a3dd4bca5 100644 --- a/src/server/scripts/Commands/cs_ban.cpp +++ b/src/server/scripts/Commands/cs_ban.cpp @@ -114,9 +114,19 @@ public: case BAN_SUCCESS: { if (atoi(durationStr) > 0) - handler->PSendSysMessage(LANG_BAN_YOUBANNED, name.c_str(), secsToTimeString(TimeStringToSecs(durationStr), true).c_str(), reasonStr); + { + if (sWorld->getBoolConfig(CONFIG_SHOW_BAN_IN_WORLD)) + sWorld->SendWorldText(LANG_BAN_CHARACTER_YOUBANNEDMESSAGE_WORLD, (handler->GetSession() ? handler->GetSession()->GetPlayerName().c_str() : "Server"), name.c_str(), secsToTimeString(TimeStringToSecs(durationStr), true).c_str(), reasonStr); + else + handler->PSendSysMessage(LANG_BAN_YOUBANNED, name.c_str(), secsToTimeString(TimeStringToSecs(durationStr), true).c_str(), reasonStr); + } else - handler->PSendSysMessage(LANG_BAN_YOUPERMBANNED, name.c_str(), reasonStr); + { + if (sWorld->getBoolConfig(CONFIG_SHOW_BAN_IN_WORLD)) + sWorld->SendWorldText(LANG_BAN_CHARACTER_YOUPERMBANNEDMESSAGE_WORLD, (handler->GetSession() ? handler->GetSession()->GetPlayerName().c_str() : "Server"), name.c_str(), reasonStr); + else + handler->PSendSysMessage(LANG_BAN_YOUPERMBANNED, name.c_str(), reasonStr); + } break; } case BAN_NOTFOUND: @@ -189,9 +199,19 @@ public: { case BAN_SUCCESS: if (atoi(durationStr) > 0) - handler->PSendSysMessage(LANG_BAN_YOUBANNED, nameOrIP.c_str(), secsToTimeString(TimeStringToSecs(durationStr), true).c_str(), reasonStr); - else - handler->PSendSysMessage(LANG_BAN_YOUPERMBANNED, nameOrIP.c_str(), reasonStr); + { + if (sWorld->getBoolConfig(CONFIG_SHOW_BAN_IN_WORLD)) + sWorld->SendWorldText(LANG_BAN_ACCOUNT_YOUBANNEDMESSAGE_WORLD, (handler->GetSession() ? handler->GetSession()->GetPlayerName().c_str() : "Server"), nameOrIP.c_str(), secsToTimeString(TimeStringToSecs(durationStr), true).c_str(), reasonStr); + else + handler->PSendSysMessage(LANG_BAN_YOUBANNED, nameOrIP.c_str(), secsToTimeString(TimeStringToSecs(durationStr), true).c_str(), reasonStr); + } + else + { + if (sWorld->getBoolConfig(CONFIG_SHOW_BAN_IN_WORLD)) + sWorld->SendWorldText(LANG_BAN_ACCOUNT_YOUPERMBANNEDMESSAGE_WORLD, (handler->GetSession() ? handler->GetSession()->GetPlayerName().c_str() : "Server"), nameOrIP.c_str(), reasonStr); + else + handler->PSendSysMessage(LANG_BAN_YOUPERMBANNED, nameOrIP.c_str(), reasonStr); + } break; case BAN_SYNTAX_ERROR: return false; diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 796416b4031..1b8f50b5eab 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -808,12 +808,16 @@ public: if (handler->HasLowerSecurity(target, 0)) return false; - if (sWorld->getBoolConfig(CONFIG_SHOW_KICK_IN_WORLD)) - sWorld->SendWorldText(LANG_COMMAND_KICKMESSAGE, playerName.c_str()); - else - handler->PSendSysMessage(LANG_COMMAND_KICKMESSAGE, playerName.c_str()); + char const* kickReason = strtok(NULL, "\r"); + std::string kickReasonStr = "No reason"; + if (kickReason != NULL) + kickReasonStr = kickReason; - target->GetSession()->KickPlayer(); + if (sWorld->getBoolConfig(CONFIG_SHOW_KICK_IN_WORLD)) + sWorld->SendWorldText(LANG_COMMAND_KICKMESSAGE_WORLD, (handler->GetSession() ? handler->GetSession()->GetPlayerName().c_str() : "Server"), playerName.c_str(), kickReasonStr.c_str()); + else + handler->PSendSysMessage(LANG_COMMAND_KICKMESSAGE, playerName.c_str()); + target->GetSession()->KickPlayer(); return true; } @@ -1835,7 +1839,17 @@ public: int64 muteTime = time(NULL) + notSpeakTime * MINUTE; target->GetSession()->m_muteTime = muteTime; stmt->setInt64(0, muteTime); - ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOUR_CHAT_DISABLED, notSpeakTime, muteBy.c_str(), muteReasonStr.c_str()); + std::string nameLink = handler->playerLink(targetName); + + if (sWorld->getBoolConfig(CONFIG_SHOW_MUTE_IN_WORLD)) + { + sWorld->SendWorldText(LANG_COMMAND_MUTEMESSAGE_WORLD, (handler->GetSession() ? handler->GetSession()->GetPlayerName().c_str() : "Server"), nameLink.c_str(), notSpeakTime, muteReasonStr.c_str()); + ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOUR_CHAT_DISABLED, notSpeakTime, muteBy.c_str(), muteReasonStr.c_str()); + } + else + { + ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOUR_CHAT_DISABLED, notSpeakTime, muteBy.c_str(), muteReasonStr.c_str()); + } } else { @@ -1850,8 +1864,10 @@ public: LoginDatabase.Execute(stmt); std::string nameLink = handler->playerLink(targetName); - handler->PSendSysMessage(target ? LANG_YOU_DISABLE_CHAT : LANG_COMMAND_DISABLE_CHAT_DELAYED, nameLink.c_str(), notSpeakTime, muteReasonStr.c_str()); - + if (sWorld->getBoolConfig(CONFIG_SHOW_MUTE_IN_WORLD) && !target) + sWorld->SendWorldText(LANG_COMMAND_MUTEMESSAGE_WORLD, handler->GetSession()->GetPlayerName().c_str(), nameLink.c_str(), notSpeakTime, muteReasonStr.c_str()); + else + handler->PSendSysMessage(target ? LANG_YOU_DISABLE_CHAT : LANG_COMMAND_DISABLE_CHAT_DELAYED, nameLink.c_str(), notSpeakTime, muteReasonStr.c_str()); return true; } diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index c25002fe4f4..a5b13301403 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -744,7 +744,7 @@ public: for (uint8 i = 0; i < NPCFLAG_COUNT; i++) if (npcflags & npcFlagTexts[i].Value) - handler->PSendSysMessage(npcFlagTexts[i].Name); + handler->PSendSysMessage(npcFlagTexts[i].Name, npcFlagTexts[i].Value); handler->PSendSysMessage(LANG_NPCINFO_MECHANIC_IMMUNE, mechanicImmuneMask); for (uint8 i = 0; i < MAX_MECHANIC; ++i) diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp index b82c0099ce4..bde326a5c37 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp @@ -297,12 +297,7 @@ public: void ClearWeapons() { SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); - - //damage - const CreatureTemplate* cinfo = me->GetCreatureTemplate(); - me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, cinfo->mindmg); - me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, cinfo->maxdmg); - me->UpdateDamagePhysical(BASE_ATTACK); + me->SetCanDualWield(false); } void EnfeebleHealthEffect() @@ -419,19 +414,8 @@ public: //models SetEquipmentSlots(false, EQUIP_ID_AXE, EQUIP_ID_AXE, EQUIP_NO_CHANGE); - //damage - const CreatureTemplate* cinfo = me->GetCreatureTemplate(); - me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, 2*cinfo->mindmg); - me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, 2*cinfo->maxdmg); - me->UpdateDamagePhysical(BASE_ATTACK); - - me->SetBaseWeaponDamage(OFF_ATTACK, MINDAMAGE, cinfo->mindmg); - me->SetBaseWeaponDamage(OFF_ATTACK, MAXDAMAGE, cinfo->maxdmg); - //Sigh, updating only works on main attack, do it manually .... - me->SetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE, cinfo->mindmg); - me->SetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE, cinfo->maxdmg); - me->SetAttackTime(OFF_ATTACK, (me->GetAttackTime(BASE_ATTACK)*150)/100); + me->SetCanDualWield(true); } } else if (phase == 2) diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp index 646c9ddfe81..eca840dbeb2 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp @@ -228,7 +228,7 @@ class boss_akilzon : public CreatureScript case EVENT_STATIC_DISRUPTION: { Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1); - if (!target) + if (!target) target = me->GetVictim(); if (target) { @@ -244,7 +244,7 @@ class boss_akilzon : public CreatureScript case EVENT_GUST_OF_WIND: { Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1); - if (!target) + if (!target) target = me->GetVictim(); if (target) DoCast(target, SPELL_GUST_OF_WIND); diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp index 4bf50581108..5b943fd57f2 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp @@ -96,24 +96,21 @@ class boss_arlokk : public CreatureScript void Reset() OVERRIDE { + if (events.IsInPhase(PHASE_TWO)) + me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false); // hack + _Reset(); _summonCountA = 0; _summonCountB = 0; - me->RemoveAllAuras(); me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_DAGGER)); me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(WEAPON_DAGGER)); - if (GameObject* gate = me->GetMap()->GetGameObject(instance->GetData64(GO_FORCEFIELD))) - gate->SetGoState(GO_STATE_READY); me->SetWalk(false); me->GetMotionMaster()->MovePoint(0, PosMoveOnSpawn[0]); } void JustDied(Unit* /*killer*/) OVERRIDE { + _JustDied(); Talk(SAY_DEATH); - me->RemoveAllAuras(); - if (GameObject* gate = me->GetMap()->GetGameObject(instance->GetData64(GO_FORCEFIELD))) - gate->SetGoState(GO_STATE_ACTIVE); - instance->SetBossState(DATA_ARLOKK, DONE); } void EnterCombat(Unit* /*who*/) OVERRIDE @@ -154,11 +151,9 @@ class boss_arlokk : public CreatureScript void EnterEvadeMode() OVERRIDE { - if (GameObject* object = me->GetMap()->GetGameObject(instance->GetData64(GO_FORCEFIELD))) - object->SetGoState(GO_STATE_ACTIVE); - if (GameObject* object = me->GetMap()->GetGameObject(instance->GetData64(GO_GONG_OF_BETHEKK))) + BossAI::EnterEvadeMode(); + if (GameObject* object = ObjectAccessor::GetGameObject(*me, instance->GetData64(GO_GONG_OF_BETHEKK))) object->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - instance->SetBossState(DATA_ARLOKK, NOT_STARTED); me->DespawnOrUnsummon(4000); } @@ -194,7 +189,7 @@ class boss_arlokk : public CreatureScript case EVENT_SUMMON_PROWLERS: if (_summonCountA < MAX_PROWLERS_PER_SIDE) { - if (Unit* trigger = me->GetUnit(*me, _triggersSideAGUID[urand(0, 4)])) + if (Unit* trigger = ObjectAccessor::GetUnit(*me, _triggersSideAGUID[urand(0, 4)])) { trigger->CastSpell(trigger, SPELL_SUMMON_PROWLER); ++_summonCountA; @@ -202,7 +197,7 @@ class boss_arlokk : public CreatureScript } if (_summonCountB < MAX_PROWLERS_PER_SIDE) { - if (Unit* trigger = me->GetUnit(*me, _triggersSideBGUID[urand(0, 4)])) + if (Unit* trigger = ObjectAccessor::GetUnit(*me, _triggersSideBGUID[urand(0, 4)])) { trigger->CastSpell(trigger, SPELL_SUMMON_PROWLER); ++_summonCountB; @@ -225,13 +220,15 @@ class boss_arlokk : public CreatureScript } case EVENT_TRANSFORM: { - DoCast(me, SPELL_PANTHER_TRANSFORM); + DoCast(me, SPELL_PANTHER_TRANSFORM); // SPELL_AURA_TRANSFORM me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(EQUIP_UNEQUIP)); me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(EQUIP_UNEQUIP)); + /* const CreatureTemplate* cinfo = me->GetCreatureTemplate(); me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35))); me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35))); me->UpdateDamagePhysical(BASE_ATTACK); + */ me->AttackStop(); DoResetThreat(); me->SetReactState(REACT_PASSIVE); @@ -262,6 +259,7 @@ class boss_arlokk : public CreatureScript events.ScheduleEvent(EVENT_RAVAGE, urand(10000, 14000), 0, PHASE_TWO); events.ScheduleEvent(EVENT_TRANSFORM_BACK, urand(15000, 18000), 0, PHASE_TWO); events.SetPhase(PHASE_TWO); + me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, true); // hack break; case EVENT_RAVAGE: DoCastVictim(SPELL_RAVAGE, true); @@ -269,14 +267,17 @@ class boss_arlokk : public CreatureScript break; case EVENT_TRANSFORM_BACK: { - me->RemoveAura(SPELL_PANTHER_TRANSFORM); + me->RemoveAura(SPELL_PANTHER_TRANSFORM); // SPELL_AURA_TRANSFORM DoCast(me, SPELL_VANISH_VISUAL); me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_DAGGER)); me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(WEAPON_DAGGER)); + /* const CreatureTemplate* cinfo = me->GetCreatureTemplate(); me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg)); me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg)); me->UpdateDamagePhysical(BASE_ATTACK); + */ + me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false); // hack events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(4000, 7000), 0, PHASE_ONE); events.ScheduleEvent(EVENT_GOUGE, urand(12000, 15000), 0, PHASE_ONE); events.ScheduleEvent(EVENT_TRANSFORM, urand(16000, 20000), 0, PHASE_ONE); diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp index 3ff18d81032..efd79d89a2b 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp @@ -64,11 +64,6 @@ enum Phases PHASE_THREE = 3 }; -enum ModelId -{ - MODEL_MARLI = 15220 -}; - class boss_marli : public CreatureScript { public: boss_marli() : CreatureScript("boss_marli") { } @@ -79,6 +74,8 @@ class boss_marli : public CreatureScript void Reset() OVERRIDE { + if (events.IsInPhase(PHASE_THREE)) + me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false); // hack _Reset(); } @@ -155,11 +152,14 @@ class boss_marli : public CreatureScript case EVENT_TRANSFORM: { Talk(SAY_TRANSFORM); - DoCast(me, SPELL_SPIDER_FORM); + DoCast(me, SPELL_SPIDER_FORM); // SPELL_AURA_TRANSFORM + /* CreatureTemplate const* cinfo = me->GetCreatureTemplate(); me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35))); me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35))); me->UpdateDamagePhysical(BASE_ATTACK); + */ + me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, true); // hack DoCastVictim(SPELL_ENVOLWINGWEB); if (DoGetThreat(me->GetVictim())) DoModifyThreatPercent(me->GetVictim(), -100); @@ -188,11 +188,14 @@ class boss_marli : public CreatureScript } case EVENT_TRANSFORM_BACK: { - me->SetDisplayId(MODEL_MARLI); + me->RemoveAura(SPELL_SPIDER_FORM); + /* CreatureTemplate const* cinfo = me->GetCreatureTemplate(); me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 1))); me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 1))); me->UpdateDamagePhysical(BASE_ATTACK); + */ + me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false); // hack events.ScheduleEvent(EVENT_ASPECT_OF_MARLI, 12000, 0, PHASE_TWO); events.ScheduleEvent(EVENT_TRANSFORM, 45000, 0, PHASE_TWO); events.ScheduleEvent(EVENT_POISON_VOLLEY, 15000); diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp index d857bff69e0..a70dd5e0a30 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp @@ -89,6 +89,8 @@ class boss_thekal : public CreatureScript void Reset() OVERRIDE { + if (events.IsInPhase(PHASE_TWO)) + me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false); // hack _Reset(); Enraged = false; WasDead = false; @@ -141,15 +143,17 @@ class boss_thekal : public CreatureScript //Thekal will transform to Tiger if he died and was not resurrected after 10 seconds. if (WasDead) { - DoCast(me, SPELL_TIGER_FORM); + DoCast(me, SPELL_TIGER_FORM); // SPELL_AURA_TRANSFORM me->SetObjectScale(2.00f); me->SetStandState(UNIT_STAND_STATE_STAND); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFullHealth(); + /* const CreatureTemplate* cinfo = me->GetCreatureTemplate(); me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 40))); me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 40))); me->UpdateDamagePhysical(BASE_ATTACK); + */ + me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 40.0f, true); // hack DoResetThreat(); events.ScheduleEvent(EVENT_FRENZY, 30000, 0, PHASE_TWO); // Phase 2 events.ScheduleEvent(EVENT_FORCEPUNCH, 4000, 0, PHASE_TWO); // Phase 2 diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp index 673450f83d0..67d40abaea3 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp @@ -27,6 +27,12 @@ EndScriptData */ #include "InstanceScript.h" #include "zulgurub.h" +DoorData const doorData[] = +{ + { GO_FORCEFIELD, DATA_ARLOKK, DOOR_TYPE_ROOM, BOUNDARY_NONE }, + { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END +}; + class instance_zulgurub : public InstanceMapScript { public: instance_zulgurub(): InstanceMapScript(ZGScriptName, 309) { } @@ -36,6 +42,7 @@ class instance_zulgurub : public InstanceMapScript instance_zulgurub_InstanceMapScript(Map* map) : InstanceScript(map) { SetBossNumber(EncounterCount); + LoadDoorData(doorData); } void Initialize() OVERRIDE @@ -46,7 +53,6 @@ class instance_zulgurub : public InstanceMapScript _jindoTheHexxerGUID = 0; _vilebranchSpeakerGUID = 0; _arlokkGUID = 0; - _goForcefieldGUID = 0; _goGongOfBethekkGUID = 0; } @@ -86,7 +92,7 @@ class instance_zulgurub : public InstanceMapScript switch (go->GetEntry()) { case GO_FORCEFIELD: - _goForcefieldGUID = go->GetGUID(); + AddDoor(go, true); break; case GO_GONG_OF_BETHEKK: _goGongOfBethekkGUID = go->GetGUID(); @@ -100,6 +106,18 @@ class instance_zulgurub : public InstanceMapScript } } + void OnGameObjectRemove(GameObject* go) OVERRIDE + { + switch (go->GetEntry()) + { + case GO_FORCEFIELD: + AddDoor(go, false); + break; + default: + break; + } + } + uint64 GetData64(uint32 uiData) const OVERRIDE { switch (uiData) @@ -119,9 +137,6 @@ class instance_zulgurub : public InstanceMapScript case NPC_ARLOKK: return _arlokkGUID; break; - case GO_FORCEFIELD: - return _goForcefieldGUID; - break; case GO_GONG_OF_BETHEKK: return _goGongOfBethekkGUID; break; @@ -181,7 +196,6 @@ class instance_zulgurub : public InstanceMapScript uint64 _jindoTheHexxerGUID; uint64 _vilebranchSpeakerGUID; uint64 _arlokkGUID; - uint64 _goForcefieldGUID; uint64 _goGongOfBethekkGUID; }; diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp index 0b281c58839..84c9181e495 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp @@ -232,7 +232,6 @@ public: npc_nadox_eggsAI(Creature* creature) : ScriptedAI(creature) { creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - creature->UpdateAllStats(); } void Reset() OVERRIDE { } diff --git a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp index 0b50375b809..045564ce570 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp @@ -467,7 +467,7 @@ public: CallDragon(DATA_TENEBRON); break; case EVENT_CALL_SHADRON: - CallDragon(DATA_SHADRON); + CallDragon(DATA_SHADRON); break; case EVENT_CALL_VESPERON: CallDragon(DATA_VESPERON); diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp index d0120e4c2de..0d7dc9062ad 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp @@ -281,7 +281,6 @@ struct boss_twin_baseAI : public BossAI { SetEquipmentSlots(false, Weapon, mode ? Weapon : int32(EQUIP_UNEQUIP), EQUIP_UNEQUIP); me->SetCanDualWield(mode); - me->UpdateDamagePhysical(mode ? OFF_ATTACK : BASE_ATTACK); } void UpdateAI(uint32 diff) OVERRIDE diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp index 0859d43ee85..fe2b818b325 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp @@ -111,12 +111,13 @@ class boss_garfrost : public CreatureScript { _JustDied(); Talk(SAY_DEATH); + me->RemoveAllGameObjects(); if (Creature* tyrannus = me->GetCreature(*me, instance->GetData64(DATA_TYRANNUS))) tyrannus->AI()->Talk(SAY_TYRANNUS_DEATH); } - void DamageTaken(Unit* /*attacker*/, uint32& /*uiDamage*/) OVERRIDE + void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) OVERRIDE { if (events.IsInPhase(PHASE_ONE) && !HealthAbovePct(66)) { diff --git a/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp b/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp index 3de5b6a7b2b..6769e3429fa 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp @@ -17,18 +17,19 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" #include "naxxramas.h" -#include "SpellInfo.h" enum Spells { SPELL_BOMBARD_SLIME = 28280, - SPELL_POISON_CLOUD = 28240, - SPELL_MUTATING_INJECTION = 28169, SPELL_SLIME_SPRAY = 28157, - H_SPELL_SLIME_SPRAY = 54364, - SPELL_BERSERK = 26662, - SPELL_POISON_CLOUD_ADD = 59116 + SPELL_MUTATING_INJECTION = 28169, + SPELL_MUTATING_EXPLOSION = 28206, + SPELL_POISON_CLOUD = 28240, + SPELL_POISON_CLOUD_PASSIVE = 28158, + SPELL_BERSERK = 26662 }; enum Events @@ -46,115 +47,183 @@ enum CreatureId class boss_grobbulus : public CreatureScript { -public: - boss_grobbulus() : CreatureScript("boss_grobbulus") { } + public: + boss_grobbulus() : CreatureScript("boss_grobbulus") { } - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new boss_grobbulusAI(creature); - } - - struct boss_grobbulusAI : public BossAI - { - boss_grobbulusAI(Creature* creature) : BossAI(creature, BOSS_GROBBULUS) + struct boss_grobbulusAI : public BossAI { - me->ApplySpellImmune(0, IMMUNITY_ID, SPELL_POISON_CLOUD_ADD, true); - } + boss_grobbulusAI(Creature* creature) : BossAI(creature, BOSS_GROBBULUS) { } - void EnterCombat(Unit* /*who*/) OVERRIDE - { - _EnterCombat(); - events.ScheduleEvent(EVENT_CLOUD, 15000); - events.ScheduleEvent(EVENT_INJECT, 20000); - events.ScheduleEvent(EVENT_SPRAY, 15000+rand()%15000); //not sure - events.ScheduleEvent(EVENT_BERSERK, 12*60000); - } + void EnterCombat(Unit* /*who*/) OVERRIDE + { + _EnterCombat(); + events.ScheduleEvent(EVENT_CLOUD, 15000); + events.ScheduleEvent(EVENT_INJECT, 20000); + events.ScheduleEvent(EVENT_SPRAY, urand(15000, 30000)); // not sure + events.ScheduleEvent(EVENT_BERSERK, 12 * 60000); + } - void SpellHitTarget(Unit* target, const SpellInfo* spell) OVERRIDE - { - if (spell->Id == uint32(SPELL_SLIME_SPRAY)) + void SpellHitTarget(Unit* target, SpellInfo const* spell) OVERRIDE { - if (TempSummon* slime = me->SummonCreature(NPC_FALLOUT_SLIME, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0)) - DoZoneInCombat(slime); + if (spell->Id == SPELL_SLIME_SPRAY) + me->SummonCreature(NPC_FALLOUT_SLIME, *target, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT); } - } - void UpdateAI(uint32 diff) OVERRIDE - { - if (!UpdateVictim()) - return; + void UpdateAI(uint32 diff) OVERRIDE + { + if (!UpdateVictim()) + return; - events.Update(diff); + events.Update(diff); - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) + while (uint32 eventId = events.ExecuteEvent()) { - case EVENT_CLOUD: - DoCastAOE(SPELL_POISON_CLOUD); - events.ScheduleEvent(EVENT_CLOUD, 15000); - return; - case EVENT_BERSERK: - DoCastAOE(SPELL_BERSERK); - return; - case EVENT_SPRAY: - DoCastAOE(SPELL_SLIME_SPRAY); - events.ScheduleEvent(EVENT_SPRAY, 15000+rand()%15000); - return; - case EVENT_INJECT: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1)) - if (!target->HasAura(SPELL_MUTATING_INJECTION)) + switch (eventId) + { + case EVENT_CLOUD: + DoCastAOE(SPELL_POISON_CLOUD); + events.ScheduleEvent(EVENT_CLOUD, 15000); + return; + case EVENT_BERSERK: + DoCastAOE(SPELL_BERSERK, true); + return; + case EVENT_SPRAY: + DoCastAOE(SPELL_SLIME_SPRAY); + events.ScheduleEvent(EVENT_SPRAY, urand(15000, 30000)); + return; + case EVENT_INJECT: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, -SPELL_MUTATING_INJECTION)) DoCast(target, SPELL_MUTATING_INJECTION); - events.ScheduleEvent(EVENT_INJECT, 8000 + uint32(120 * me->GetHealthPct())); - return; + events.ScheduleEvent(EVENT_INJECT, 8000 + uint32(120 * me->GetHealthPct())); + return; + default: + break; + } } + + DoMeleeAttackIfReady(); } + }; - DoMeleeAttackIfReady(); + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return new boss_grobbulusAI(creature); } - }; - }; class npc_grobbulus_poison_cloud : public CreatureScript { -public: - npc_grobbulus_poison_cloud() : CreatureScript("npc_grobbulus_poison_cloud") { } + public: + npc_grobbulus_poison_cloud() : CreatureScript("npc_grobbulus_poison_cloud") { } + + struct npc_grobbulus_poison_cloudAI : public ScriptedAI + { + npc_grobbulus_poison_cloudAI(Creature* creature) : ScriptedAI(creature) + { + SetCombatMovement(false); + creature->SetReactState(REACT_PASSIVE); + } + + void IsSummonedBy(Unit* /*summoner*/) OVERRIDE + { + // no visual when casting in ctor or Reset() + DoCast(me, SPELL_POISON_CLOUD_PASSIVE, true); + } - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new npc_grobbulus_poison_cloudAI(creature); - } + void UpdateAI(uint32 /*diff*/) OVERRIDE { } + }; - struct npc_grobbulus_poison_cloudAI : public ScriptedAI - { - npc_grobbulus_poison_cloudAI(Creature* creature) : ScriptedAI(creature) + CreatureAI* GetAI(Creature* creature) const OVERRIDE { - SetCombatMovement(false); + return new npc_grobbulus_poison_cloudAI(creature); } +}; + +// 28169 - Mutating Injection +class spell_grobbulus_mutating_injection : public SpellScriptLoader +{ + public: + spell_grobbulus_mutating_injection() : SpellScriptLoader("spell_grobbulus_mutating_injection") { } - uint32 Cloud_Timer; + class spell_grobbulus_mutating_injection_AuraScript : public AuraScript + { + PrepareAuraScript(spell_grobbulus_mutating_injection_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE + { + if (!sSpellMgr->GetSpellInfo(SPELL_MUTATING_EXPLOSION) + || !sSpellMgr->GetSpellInfo(SPELL_POISON_CLOUD)) + return false; + return true; + } + + void HandleRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + AuraRemoveMode removeMode = GetTargetApplication()->GetRemoveMode(); + if (removeMode != AURA_REMOVE_BY_ENEMY_SPELL && removeMode != AURA_REMOVE_BY_EXPIRE) + return; + + if (Unit* caster = GetCaster()) + { + caster->CastSpell(GetTarget(), SPELL_MUTATING_EXPLOSION, true); + GetTarget()->CastSpell(GetTarget(), SPELL_POISON_CLOUD, true, NULL, aurEff, GetCasterGUID()); + } + } - void Reset() OVERRIDE + void Register() OVERRIDE + { + AfterEffectRemove += AuraEffectRemoveFn(spell_grobbulus_mutating_injection_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const OVERRIDE { - Cloud_Timer = 1000; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + return new spell_grobbulus_mutating_injection_AuraScript(); } +}; - void UpdateAI(uint32 diff) OVERRIDE +// 28158, 54362 - Poison (Grobbulus) +class spell_grobbulus_poison_cloud : public SpellScriptLoader +{ + public: + spell_grobbulus_poison_cloud() : SpellScriptLoader("spell_grobbulus_poison_cloud") { } + + class spell_grobbulus_poison_cloud_AuraScript : public AuraScript { - if (Cloud_Timer <= diff) + PrepareAuraScript(spell_grobbulus_poison_cloud_AuraScript); + + bool Validate(SpellInfo const* spellInfo) OVERRIDE { - DoCast(me, SPELL_POISON_CLOUD_ADD); - Cloud_Timer = 10000; - } else Cloud_Timer -= diff; - } - }; + if (!sSpellMgr->GetSpellInfo(spellInfo->Effects[EFFECT_0].TriggerSpell)) + return false; + return true; + } + + void PeriodicTick(AuraEffect const* aurEff) + { + PreventDefaultAction(); + uint32 triggerSpell = GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell; + int32 mod = int32(((float(aurEff->GetTickNumber()) / aurEff->GetTotalTicks()) * 0.9f + 0.1f) * 10000 * 2 / 3); + GetTarget()->CastCustomSpell(triggerSpell, SPELLVALUE_RADIUS_MOD, mod, (Unit*)NULL, TRIGGERED_FULL_MASK, NULL, aurEff); + } + + void Register() OVERRIDE + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_grobbulus_poison_cloud_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const OVERRIDE + { + return new spell_grobbulus_poison_cloud_AuraScript(); + } }; void AddSC_boss_grobbulus() { new boss_grobbulus(); new npc_grobbulus_poison_cloud(); + new spell_grobbulus_mutating_injection(); + new spell_grobbulus_poison_cloud(); } diff --git a/src/server/scripts/Northrend/Nexus/Nexus/boss_ormorok.cpp b/src/server/scripts/Northrend/Nexus/Nexus/boss_ormorok.cpp index aa6bb11447b..93e52c4da73 100644 --- a/src/server/scripts/Northrend/Nexus/Nexus/boss_ormorok.cpp +++ b/src/server/scripts/Northrend/Nexus/Nexus/boss_ormorok.cpp @@ -195,8 +195,8 @@ public: struct npc_crystal_spike_triggerAI : public ScriptedAI { - npc_crystal_spike_triggerAI(Creature* creature) : ScriptedAI(creature) - { + npc_crystal_spike_triggerAI(Creature* creature) : ScriptedAI(creature) + { _count = 0; _despawntimer = 0; } diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp index 08d12d715f9..927f4490770 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp @@ -15,146 +15,130 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* Script Data Start -SDName: Boss maiden_of_grief -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "halls_of_stone.h" +enum Yells +{ + SAY_AGGRO = 0, + SAY_SLAY = 1, + SAY_DEATH = 2, + SAY_STUN = 3 +}; + enum Spells { - SPELL_PARTING_SORROW = 59723, - SPELL_STORM_OF_GRIEF_N = 50752, - SPELL_STORM_OF_GRIEF_H = 59772, - SPELL_SHOCK_OF_SORROW_N = 50760, - SPELL_SHOCK_OF_SORROW_H = 59726, - SPELL_PILLAR_OF_WOE_N = 50761, - SPELL_PILLAR_OF_WOE_H = 59727 + SPELL_PARTING_SORROW = 59723, + SPELL_STORM_OF_GRIEF = 50752, + SPELL_SHOCK_OF_SORROW = 50760, + SPELL_PILLAR_OF_WOE = 50761 }; -enum Yells +enum Events { - SAY_AGGRO = 0, - SAY_SLAY = 1, - SAY_DEATH = 2, - SAY_STUN = 3 + EVENT_PARTING_SORROW = 1, + EVENT_STORM_OF_GRIEF, + EVENT_SHOCK_OF_SORROW, + EVENT_PILLAR_OF_WOE }; enum Achievements { - ACHIEV_GOOD_GRIEF_START_EVENT = 20383, + ACHIEV_GOOD_GRIEF_START_EVENT = 20383, }; class boss_maiden_of_grief : public CreatureScript { -public: - boss_maiden_of_grief() : CreatureScript("boss_maiden_of_grief") { } + public: + boss_maiden_of_grief() : CreatureScript("boss_maiden_of_grief") { } - struct boss_maiden_of_griefAI : public ScriptedAI - { - boss_maiden_of_griefAI(Creature* creature) : ScriptedAI(creature) + struct boss_maiden_of_griefAI : public BossAI { - instance = me->GetInstanceScript(); - } - - InstanceScript* instance; + boss_maiden_of_griefAI(Creature* creature) : BossAI(creature, DATA_MAIDEN_OF_GRIEF) { } - uint32 PartingSorrowTimer; - uint32 StormOfGriefTimer; - uint32 ShockOfSorrowTimer; - uint32 PillarOfWoeTimer; - - void Reset() OVERRIDE - { - PartingSorrowTimer = urand(25000, 30000); - StormOfGriefTimer = 10000; - ShockOfSorrowTimer = 20000+rand()%5000; - PillarOfWoeTimer = urand(5000, 15000); - - instance->SetBossState(DATA_MAIDEN_OF_GRIEF, NOT_STARTED); - instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_GOOD_GRIEF_START_EVENT); - } - - void EnterCombat(Unit* /*who*/) OVERRIDE - { - Talk(SAY_AGGRO); + void Reset() OVERRIDE + { + _Reset(); - instance->SetBossState(DATA_MAIDEN_OF_GRIEF, IN_PROGRESS); - instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_GOOD_GRIEF_START_EVENT); - } + if (IsHeroic()) + events.ScheduleEvent(EVENT_PARTING_SORROW, urand(25000, 30000)); + events.ScheduleEvent(EVENT_STORM_OF_GRIEF, 10000); + events.ScheduleEvent(EVENT_SHOCK_OF_SORROW, urand(20000, 25000)); + events.ScheduleEvent(EVENT_PILLAR_OF_WOE, urand(5000, 15000)); - void UpdateAI(uint32 diff) OVERRIDE - { - //Return since we have no target - if (!UpdateVictim()) - return; + instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_GOOD_GRIEF_START_EVENT); + } - if (IsHeroic()) + void EnterCombat(Unit* /*who*/) OVERRIDE { - if (PartingSorrowTimer <= diff) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(target, SPELL_PARTING_SORROW); + _EnterCombat(); + Talk(SAY_AGGRO); - PartingSorrowTimer = urand(30000, 40000); - } else PartingSorrowTimer -= diff; + instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_GOOD_GRIEF_START_EVENT); } - if (StormOfGriefTimer <= diff) + void KilledUnit(Unit* who) OVERRIDE { - DoCastVictim(SPELL_STORM_OF_GRIEF_N, true); - StormOfGriefTimer = urand(15000, 20000); - } else StormOfGriefTimer -= diff; + if (who->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } - if (ShockOfSorrowTimer <= diff) + void JustDied(Unit* /*killer*/) OVERRIDE { - DoResetThreat(); - Talk(SAY_STUN); - DoCast(me, SPELL_SHOCK_OF_SORROW_N); - ShockOfSorrowTimer = urand(20000, 30000); - } else ShockOfSorrowTimer -= diff; + _JustDied(); + Talk(SAY_DEATH); + } - if (PillarOfWoeTimer <= diff) + void UpdateAI(uint32 diff) OVERRIDE { - Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1); + if (!UpdateVictim()) + return; - if (target) - DoCast(target, SPELL_PILLAR_OF_WOE_N); - else - DoCastVictim(SPELL_PILLAR_OF_WOE_N); + events.Update(diff); - PillarOfWoeTimer = urand(5000, 25000); - } else PillarOfWoeTimer -= diff; - - DoMeleeAttackIfReady(); - } + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - void JustDied(Unit* /*killer*/) OVERRIDE - { - Talk(SAY_DEATH); - - instance->SetBossState(DATA_MAIDEN_OF_GRIEF, DONE); - } + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_PARTING_SORROW: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) + DoCast(target, SPELL_PARTING_SORROW); + events.ScheduleEvent(EVENT_PARTING_SORROW, urand(30000, 40000)); + break; + case EVENT_STORM_OF_GRIEF: + DoCastVictim(SPELL_STORM_OF_GRIEF, true); + events.ScheduleEvent(EVENT_STORM_OF_GRIEF, urand(15000, 20000)); + break; + case EVENT_SHOCK_OF_SORROW: + DoResetThreat(); + Talk(SAY_STUN); + DoCastAOE(SPELL_SHOCK_OF_SORROW); + events.ScheduleEvent(EVENT_SHOCK_OF_SORROW, urand(20000, 30000)); + break; + case EVENT_PILLAR_OF_WOE: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true)) + DoCast(target, SPELL_PILLAR_OF_WOE); + else + DoCastVictim(SPELL_PILLAR_OF_WOE); + events.ScheduleEvent(EVENT_PILLAR_OF_WOE, urand(5000, 25000)); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); + } + }; - void KilledUnit(Unit* victim) OVERRIDE + CreatureAI* GetAI(Creature* creature) const OVERRIDE { - if (victim->GetTypeId() != TYPEID_PLAYER) - return; - - Talk(SAY_SLAY); + return GetHallsOfStoneAI<boss_maiden_of_griefAI>(creature); } - }; - - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return GetHallsOfStoneAI<boss_maiden_of_griefAI>(creature); - } }; void AddSC_boss_maiden_of_grief() diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp index c46158b0f7a..2a24b1145c0 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp @@ -258,7 +258,7 @@ class boss_svala : public CreatureScript case EVENT_INTRO_TRANSFORM_0: { if (Creature* arthas = ObjectAccessor::GetCreature(*me, _arthasGUID)) - arthas->CastSpell(me, SPELL_TRANSFORMING_CHANNEL, false); + arthas->CastSpell(me, SPELL_TRANSFORMING_CHANNEL, true); Position pos; pos.Relocate(me); pos.m_positionZ += 8.0f; diff --git a/src/server/scripts/Northrend/zone_borean_tundra.cpp b/src/server/scripts/Northrend/zone_borean_tundra.cpp index cbad220aed6..0173454ef28 100644 --- a/src/server/scripts/Northrend/zone_borean_tundra.cpp +++ b/src/server/scripts/Northrend/zone_borean_tundra.cpp @@ -428,8 +428,8 @@ public: struct npc_jennyAI : public ScriptedAI { - npc_jennyAI(Creature* creature) : ScriptedAI(creature) - { + npc_jennyAI(Creature* creature) : ScriptedAI(creature) + { setCrateNumber = false; } diff --git a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/blood_furnace.h b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/blood_furnace.h index 193b0be51b0..b2097c34b33 100644 --- a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/blood_furnace.h +++ b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/blood_furnace.h @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -16,32 +15,59 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef DEF_BLOOD_FURNACE_H -#define DEF_BLOOD_FURNACE_H +#ifndef BLOOD_FURNACE_H_ +#define BLOOD_FURNACE_H_ + +#define BFScriptName "instance_blood_furnace" +uint32 const EncounterCount = 3; enum DataTypes { - DATA_THE_MAKER = 1, - DATA_BROGGOK = 2, - DATA_KELIDAN_THE_MAKER = 3, - TYPE_THE_MAKER_EVENT = 4, - TYPE_BROGGOK_EVENT = 5, - TYPE_KELIDAN_THE_BREAKER_EVENT = 6, - DATA_DOOR1 = 7, - DATA_DOOR2 = 8, - DATA_DOOR3 = 9, - DATA_DOOR4 = 10, - DATA_DOOR5 = 11, - DATA_DOOR6 = 12, - DATA_PRISON_CELL1 = 13, - DATA_PRISON_CELL2 = 14, - DATA_PRISON_CELL3 = 15, - DATA_PRISON_CELL4 = 16, - DATA_PRISON_CELL5 = 17, - DATA_PRISON_CELL6 = 18, - DATA_PRISON_CELL7 = 19, - DATA_PRISON_CELL8 = 20, - DATA_BROGGOK_LEVER = 21 + // Encounter States/Boss GUIDs + DATA_THE_MAKER = 0, + DATA_BROGGOK = 1, + DATA_KELIDAN_THE_BREAKER = 2, + + // Additional Data + DATA_DOOR_4 = 3, + DATA_PRISON_CELL1 = 4, + DATA_PRISON_CELL2 = 5, + DATA_PRISON_CELL3 = 6, + DATA_PRISON_CELL4 = 7, + DATA_PRISON_CELL5 = 8, + DATA_PRISON_CELL6 = 9, + DATA_PRISON_CELL7 = 10, + DATA_PRISON_CELL8 = 11, + DATA_BROGGOK_LEVER = 12 +}; + +enum CreatureIds +{ + NPC_THE_MAKER = 17381, + NPC_BROGGOK = 17380, + NPC_KELIDAN_THE_BREAKER = 17377, + NPC_PRISONER = 17398 +}; + +enum GameObjectIds +{ + GO_PRISON_DOOR_01 = 181766, // Final Exit Door + GO_PRISON_DOOR_02 = 181811, // The Maker Front Door + GO_PRISON_DOOR_03 = 181812, // The Maker Rear Door + GO_PRISON_DOOR_04 = 181819, // Broggok Rear Door + GO_PRISON_DOOR_05 = 181822, // Broggok Front Door + GO_SUMMON_DOOR = 181823, // Kelidan Exit Door + + GO_PRISON_CELL_DOOR_1 = 181813, // The Maker Prison Cell front right + GO_PRISON_CELL_DOOR_2 = 181814, // The Maker Prison Cell back right + GO_PRISON_CELL_DOOR_3 = 181816, // The Maker Prison Cell front left + GO_PRISON_CELL_DOOR_4 = 181815, // The Maker Prison Cell back left + GO_PRISON_CELL_DOOR_5 = 181821, // Broggok Prison Cell front right + GO_PRISON_CELL_DOOR_6 = 181818, // Broggok Prison Cell back right + GO_PRISON_CELL_DOOR_7 = 181820, // Broggok Prison Cell front left + GO_PRISON_CELL_DOOR_8 = 181817, // Broggok Prison Cell back left + + GO_BROGGOK_LEVER = 181982 }; enum ActionIds @@ -51,5 +77,11 @@ enum ActionIds ACTION_PREPARE_BROGGOK = 3 }; -#endif +template<class AI> +AI* GetBloodFurnaceAI(Creature* creature) +{ + return GetInstanceAI<AI>(creature, BFScriptName); +} + +#endif // BLOOD_FURNACE_H_ diff --git a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp index 1dda4161b8c..f610d6dd7e0 100644 --- a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp @@ -25,39 +25,32 @@ EndScriptData */ #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" #include "blood_furnace.h" enum Yells { - SAY_AGGRO = 0 + SAY_AGGRO = 0 }; enum Spells { - SPELL_SLIME_SPRAY = 30913, - SPELL_POISON_CLOUD = 30916, - SPELL_POISON_BOLT = 30917, + SPELL_SLIME_SPRAY = 30913, + SPELL_POISON_CLOUD = 30916, + SPELL_POISON_BOLT = 30917, - SPELL_POISON = 30914 + SPELL_POISON_CLOUD_PASSIVE = 30914 }; class boss_broggok : public CreatureScript { public: - - boss_broggok() - : CreatureScript("boss_broggok") - { - } + boss_broggok() : CreatureScript("boss_broggok") { } struct boss_broggokAI : public BossAI { - boss_broggokAI(Creature* creature) : BossAI(creature, DATA_BROGGOK) - { - instance = creature->GetInstanceScript(); - } - - InstanceScript* instance; + boss_broggokAI(Creature* creature) : BossAI(creature, DATA_BROGGOK) { } uint32 AcidSpray_Timer; uint32 PoisonSpawn_Timer; @@ -71,28 +64,22 @@ class boss_broggok : public CreatureScript PoisonSpawn_Timer = 5000; PoisonBolt_Timer = 7000; DoAction(ACTION_RESET_BROGGOK); - instance->SetData(TYPE_BROGGOK_EVENT, NOT_STARTED); } void EnterCombat(Unit* /*who*/) OVERRIDE { + _EnterCombat(); Talk(SAY_AGGRO); } - void JustSummoned(Creature* summoned) OVERRIDE - { - summoned->setFaction(16); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - summoned->CastSpell(summoned, SPELL_POISON, false, 0, 0, me->GetGUID()); - } - void UpdateAI(uint32 diff) OVERRIDE { if (!UpdateVictim()) return; + if (!canAttack) return; + if (AcidSpray_Timer <= diff) { DoCastVictim(SPELL_SLIME_SPRAY); @@ -122,9 +109,7 @@ class boss_broggok : public CreatureScript void JustDied(Unit* /*killer*/) OVERRIDE { - instance->HandleGameObject(instance->GetData64(DATA_DOOR4), true); - instance->HandleGameObject(instance->GetData64(DATA_DOOR5), true); - instance->SetData(TYPE_BROGGOK_EVENT, DONE); + _JustDied(); } void DoAction(int32 action) OVERRIDE @@ -151,7 +136,34 @@ class boss_broggok : public CreatureScript CreatureAI* GetAI(Creature* creature) const OVERRIDE { - return GetInstanceAI<boss_broggokAI>(creature); + return GetBloodFurnaceAI<boss_broggokAI>(creature); + } +}; + +class npc_broggok_poison_cloud : public CreatureScript +{ + public: + npc_broggok_poison_cloud() : CreatureScript("npc_broggok_poison_cloud") { } + + struct npc_broggok_poison_cloudAI : public ScriptedAI + { + npc_broggok_poison_cloudAI(Creature* creature) : ScriptedAI(creature) + { + SetCombatMovement(false); + creature->SetReactState(REACT_PASSIVE); + } + + void IsSummonedBy(Unit* /*summoner*/) OVERRIDE + { + DoCast(me, SPELL_POISON_CLOUD_PASSIVE, true); + } + + void UpdateAI(uint32 /*diff*/) OVERRIDE { } + }; + + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return new npc_broggok_poison_cloudAI(creature); } }; @@ -163,19 +175,60 @@ class go_broggok_lever : public GameObjectScript bool OnGossipHello(Player* /*player*/, GameObject* go) OVERRIDE { if (InstanceScript* instance = go->GetInstanceScript()) - if (instance->GetData(TYPE_BROGGOK_EVENT) != DONE && instance->GetData(TYPE_BROGGOK_EVENT) != IN_PROGRESS) + if (instance->GetBossState(DATA_BROGGOK) != DONE && instance->GetBossState(DATA_BROGGOK) != IN_PROGRESS) { - instance->SetData(TYPE_BROGGOK_EVENT, IN_PROGRESS); - if (Creature* broggok = Creature::GetCreature(*go, instance->GetData64(DATA_BROGGOK))) + instance->SetBossState(DATA_BROGGOK, IN_PROGRESS); + if (Creature* broggok = ObjectAccessor::GetCreature(*go, instance->GetData64(DATA_BROGGOK))) broggok->AI()->DoAction(ACTION_PREPARE_BROGGOK); } + go->UseDoorOrButton(); return false; } }; +// 30914, 38462 - Poison (Broggok) +class spell_broggok_poison_cloud : public SpellScriptLoader +{ + public: + spell_broggok_poison_cloud() : SpellScriptLoader("spell_broggok_poison_cloud") { } + + class spell_broggok_poison_cloud_AuraScript : public AuraScript + { + PrepareAuraScript(spell_broggok_poison_cloud_AuraScript); + + bool Validate(SpellInfo const* spellInfo) OVERRIDE + { + if (!sSpellMgr->GetSpellInfo(spellInfo->Effects[EFFECT_0].TriggerSpell)) + return false; + return true; + } + + void PeriodicTick(AuraEffect const* aurEff) + { + PreventDefaultAction(); + + uint32 triggerSpell = GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell; + int32 mod = int32(((float(aurEff->GetTickNumber()) / aurEff->GetTotalTicks()) * 0.9f + 0.1f) * 10000 * 2 / 3); + GetTarget()->CastCustomSpell(triggerSpell, SPELLVALUE_RADIUS_MOD, mod, (Unit*)NULL, TRIGGERED_FULL_MASK, NULL, aurEff); + } + + void Register() OVERRIDE + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_broggok_poison_cloud_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const OVERRIDE + { + return new spell_broggok_poison_cloud_AuraScript(); + } +}; + void AddSC_boss_broggok() { new boss_broggok(); + new npc_broggok_poison_cloud(); new go_broggok_lever(); + new spell_broggok_poison_cloud(); } diff --git a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_kelidan_the_breaker.cpp b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_kelidan_the_breaker.cpp index 78be2347656..4c04c06b091 100644 --- a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_kelidan_the_breaker.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_kelidan_the_breaker.cpp @@ -16,18 +16,6 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Boss_Kelidan_The_Breaker -SD%Complete: 100 -SDComment: -SDCategory: Hellfire Citadel, Blood Furnace -EndScriptData */ - -/* ContentData -boss_kelidan_the_breaker -npc_shadowmoon_channeler -EndContentData */ - #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "SpellAuras.h" @@ -71,23 +59,16 @@ const float ShadowmoonChannelers[5][4]= class boss_kelidan_the_breaker : public CreatureScript { public: + boss_kelidan_the_breaker() : CreatureScript("boss_kelidan_the_breaker") { } - boss_kelidan_the_breaker() - : CreatureScript("boss_kelidan_the_breaker") - { - } - - struct boss_kelidan_the_breakerAI : public ScriptedAI + struct boss_kelidan_the_breakerAI : public BossAI { - boss_kelidan_the_breakerAI(Creature* creature) : ScriptedAI(creature) + boss_kelidan_the_breakerAI(Creature* creature) : BossAI(creature, DATA_KELIDAN_THE_BREAKER) { - instance = creature->GetInstanceScript(); - for (uint8 i=0; i<5; ++i) + for (uint8 i = 0; i < 5; ++i) Channelers[i] = 0; } - InstanceScript* instance; - uint32 ShadowVolley_Timer; uint32 BurningNova_Timer; uint32 Firenova_Timer; @@ -99,6 +80,7 @@ class boss_kelidan_the_breaker : public CreatureScript void Reset() OVERRIDE { + _Reset(); ShadowVolley_Timer = 1000; BurningNova_Timer = 15000; Corruption_Timer = 5000; @@ -108,16 +90,15 @@ class boss_kelidan_the_breaker : public CreatureScript SummonChannelers(); me->SetReactState(REACT_PASSIVE); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_NON_ATTACKABLE); - instance->SetData(TYPE_KELIDAN_THE_BREAKER_EVENT, NOT_STARTED); } void EnterCombat(Unit* who) OVERRIDE { + _EnterCombat(); Talk(SAY_WAKE); if (me->IsNonMeleeSpellCast(false)) me->InterruptNonMeleeSpells(true); DoStartMovement(who); - instance->SetData(TYPE_KELIDAN_THE_BREAKER_EVENT, IN_PROGRESS); } void KilledUnit(Unit* /*victim*/) OVERRIDE @@ -189,11 +170,8 @@ class boss_kelidan_the_breaker : public CreatureScript void JustDied(Unit* /*killer*/) OVERRIDE { + _JustDied(); Talk(SAY_DIE); - - instance->SetData(TYPE_KELIDAN_THE_BREAKER_EVENT, DONE); - instance->HandleGameObject(instance->GetData64(DATA_DOOR1), true); - instance->HandleGameObject(instance->GetData64(DATA_DOOR6), true); } void UpdateAI(uint32 diff) OVERRIDE @@ -270,7 +248,7 @@ class boss_kelidan_the_breaker : public CreatureScript CreatureAI* GetAI(Creature* creature) const OVERRIDE { - return GetInstanceAI<boss_kelidan_the_breakerAI>(creature); + return GetBloodFurnaceAI<boss_kelidan_the_breakerAI>(creature); } }; @@ -368,7 +346,7 @@ class npc_shadowmoon_channeler : public CreatureScript CreatureAI* GetAI(Creature* creature) const OVERRIDE { - return GetInstanceAI<npc_shadowmoon_channelerAI>(creature); + return GetBloodFurnaceAI<npc_shadowmoon_channelerAI>(creature); } }; diff --git a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_the_maker.cpp b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_the_maker.cpp index 214edf4f5c2..6ab356bfa4a 100644 --- a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_the_maker.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_the_maker.cpp @@ -45,20 +45,11 @@ enum Spells class boss_the_maker : public CreatureScript { public: + boss_the_maker() : CreatureScript("boss_the_maker") { } - boss_the_maker() - : CreatureScript("boss_the_maker") + struct boss_the_makerAI : public BossAI { - } - - struct boss_the_makerAI : public ScriptedAI - { - boss_the_makerAI(Creature* creature) : ScriptedAI(creature) - { - instance = creature->GetInstanceScript(); - } - - InstanceScript* instance; + boss_the_makerAI(Creature* creature) : BossAI(creature, DATA_THE_MAKER) { } uint32 AcidSpray_Timer; uint32 ExplodingBreaker_Timer; @@ -67,37 +58,30 @@ class boss_the_maker : public CreatureScript void Reset() OVERRIDE { + _Reset(); AcidSpray_Timer = 15000; ExplodingBreaker_Timer = 6000; Domination_Timer = 120000; Knockdown_Timer = 10000; - - instance->SetData(TYPE_THE_MAKER_EVENT, NOT_STARTED); - instance->HandleGameObject(instance->GetData64(DATA_DOOR2), true); } void EnterCombat(Unit* /*who*/) OVERRIDE { + _EnterCombat(); Talk(SAY_AGGRO); - - instance->SetData(TYPE_THE_MAKER_EVENT, IN_PROGRESS); - instance->HandleGameObject(instance->GetData64(DATA_DOOR2), false); } - void KilledUnit(Unit* /*victim*/) OVERRIDE + void KilledUnit(Unit* who) OVERRIDE { - Talk(SAY_KILL); + if (who->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_KILL); } void JustDied(Unit* /*killer*/) OVERRIDE { + _JustDied(); Talk(SAY_DIE); - - instance->SetData(TYPE_THE_MAKER_EVENT, DONE); - instance->HandleGameObject(instance->GetData64(DATA_DOOR2), true); - instance->HandleGameObject(instance->GetData64(DATA_DOOR3), true); - - } + } void UpdateAI(uint32 diff) OVERRIDE { @@ -147,7 +131,7 @@ class boss_the_maker : public CreatureScript CreatureAI* GetAI(Creature* creature) const OVERRIDE { - return GetInstanceAI<boss_the_makerAI>(creature); + return GetBloodFurnaceAI<boss_the_makerAI>(creature); } }; diff --git a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/instance_blood_furnace.cpp b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/instance_blood_furnace.cpp index 7a9db8f4a63..bc399e4b43f 100644 --- a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/instance_blood_furnace.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/instance_blood_furnace.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -16,292 +15,207 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Instance_Blood_Furnace -SD%Complete: 85 -SDComment: -SDCategory: Hellfire Citadel, Blood Furnace -EndScriptData */ - #include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "InstanceScript.h" #include "blood_furnace.h" -#include "CreatureAI.h" -#define ENTRY_SEWER1 181823 -#define ENTRY_SEWER2 181766 -#define MAX_ENCOUNTER 3 +DoorData const doorData[] = +{ + { GO_PRISON_DOOR_01, DATA_KELIDAN_THE_BREAKER, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_PRISON_DOOR_02, DATA_THE_MAKER, DOOR_TYPE_ROOM, BOUNDARY_NONE }, + { GO_PRISON_DOOR_03, DATA_THE_MAKER, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_PRISON_DOOR_04, DATA_BROGGOK, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_PRISON_DOOR_05, DATA_BROGGOK, DOOR_TYPE_ROOM, BOUNDARY_NONE }, + { GO_SUMMON_DOOR, DATA_KELIDAN_THE_BREAKER, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END +}; class instance_blood_furnace : public InstanceMapScript { public: - instance_blood_furnace() - : InstanceMapScript("instance_blood_furnace", 542) { } + instance_blood_furnace() : InstanceMapScript(BFScriptName, 542) { } struct instance_blood_furnace_InstanceMapScript : public InstanceScript { - instance_blood_furnace_InstanceMapScript(Map* map) : InstanceScript(map) { } - - uint64 The_MakerGUID; - uint64 BroggokGUID; - uint64 Kelidan_The_BreakerGUID; - - uint64 Door1GUID; - uint64 Door2GUID; - uint64 Door3GUID; - uint64 Door4GUID; - uint64 Door5GUID; - uint64 Door6GUID; - - uint64 PrisonCell1GUID; - uint64 PrisonCell2GUID; - uint64 PrisonCell3GUID; - uint64 PrisonCell4GUID; - uint64 PrisonCell5GUID; - uint64 PrisonCell6GUID; - uint64 PrisonCell7GUID; - uint64 PrisonCell8GUID; - - std::set<uint64> PrisonersCell5; - std::set<uint64> PrisonersCell6; - std::set<uint64> PrisonersCell7; - std::set<uint64> PrisonersCell8; - - uint8 PrisonerCounter5; - uint8 PrisonerCounter6; - uint8 PrisonerCounter7; - uint8 PrisonerCounter8; + instance_blood_furnace_InstanceMapScript(Map* map) : InstanceScript(map) + { + SetBossNumber(EncounterCount); + LoadDoorData(doorData); - uint64 BroggokLeverGUID; + TheMakerGUID = 0; + BroggokGUID = 0; + KelidanTheBreakerGUID = 0; - uint32 m_auiEncounter[MAX_ENCOUNTER]; - std::string str_data; + BroggokLeverGUID = 0; + PrisonDoor4GUID = 0; - void Initialize() OVERRIDE - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - The_MakerGUID = 0; - BroggokGUID = 0; - Kelidan_The_BreakerGUID = 0; - - Door1GUID = 0; - Door2GUID = 0; - Door3GUID = 0; - Door4GUID = 0; - Door5GUID = 0; - Door6GUID = 0; - - PrisonCell1GUID = 0; - PrisonCell2GUID = 0; - PrisonCell3GUID = 0; - PrisonCell4GUID = 0; - PrisonCell5GUID = 0; - PrisonCell6GUID = 0; - PrisonCell7GUID = 0; - PrisonCell8GUID = 0; + memset(PrisonCellGUIDs, 0, 8 * sizeof(uint64)); PrisonersCell5.clear(); PrisonersCell6.clear(); PrisonersCell7.clear(); PrisonersCell8.clear(); - PrisonerCounter5 = 0; - PrisonerCounter6 = 0; - PrisonerCounter7 = 0; - PrisonerCounter8 = 0; - - BroggokLeverGUID = 0; + PrisonerCounter5 = 0; + PrisonerCounter6 = 0; + PrisonerCounter7 = 0; + PrisonerCounter8 = 0; } void OnCreatureCreate(Creature* creature) OVERRIDE { switch (creature->GetEntry()) { - case 17381: - The_MakerGUID = creature->GetGUID(); + case NPC_THE_MAKER: + TheMakerGUID = creature->GetGUID(); break; - case 17380: + case NPC_BROGGOK: BroggokGUID = creature->GetGUID(); break; - case 17377: - Kelidan_The_BreakerGUID = creature->GetGUID(); + case NPC_KELIDAN_THE_BREAKER: + KelidanTheBreakerGUID = creature->GetGUID(); break; - case 17398: + case NPC_PRISONER: StorePrisoner(creature); break; + default: + break; } } void OnUnitDeath(Unit* unit) OVERRIDE { - if (unit && unit->GetTypeId() == TYPEID_UNIT && unit->GetEntry() == 17398) + if (unit->GetTypeId() == TYPEID_UNIT && unit->GetEntry() == NPC_PRISONER) PrisonerDied(unit->GetGUID()); } void OnGameObjectCreate(GameObject* go) OVERRIDE { - if (go->GetEntry() == 181766) //Final exit door - Door1GUID = go->GetGUID(); - if (go->GetEntry() == 181811) //The Maker Front door - Door2GUID = go->GetGUID(); - if (go->GetEntry() == 181812) //The Maker Rear door - Door3GUID = go->GetGUID(); - if (go->GetEntry() == 181822) //Broggok Front door - Door4GUID = go->GetGUID(); - if (go->GetEntry() == 181819) //Broggok Rear door - Door5GUID = go->GetGUID(); - if (go->GetEntry() == 181823) //Kelidan exit door - Door6GUID = go->GetGUID(); - - if (go->GetEntry() == 181813) //The Maker prison cell front right - PrisonCell1GUID = go->GetGUID(); - if (go->GetEntry() == 181814) //The Maker prison cell back right - PrisonCell2GUID = go->GetGUID(); - if (go->GetEntry() == 181816) //The Maker prison cell front left - PrisonCell3GUID = go->GetGUID(); - if (go->GetEntry() == 181815) //The Maker prison cell back left - PrisonCell4GUID = go->GetGUID(); - if (go->GetEntry() == 181821) //Broggok prison cell front right - PrisonCell5GUID = go->GetGUID(); - if (go->GetEntry() == 181818) //Broggok prison cell back right - PrisonCell6GUID = go->GetGUID(); - if (go->GetEntry() == 181820) //Broggok prison cell front left - PrisonCell7GUID = go->GetGUID(); - if (go->GetEntry() == 181817) //Broggok prison cell back left - PrisonCell8GUID = go->GetGUID(); - - if (go->GetEntry() == 181982) - BroggokLeverGUID = go->GetGUID(); //Broggok lever - } - - uint64 GetData64(uint32 data) const OVERRIDE - { - switch (data) + switch (go->GetEntry()) { - case DATA_THE_MAKER: return The_MakerGUID; - case DATA_BROGGOK: return BroggokGUID; - case DATA_KELIDAN_THE_MAKER: return Kelidan_The_BreakerGUID; - case DATA_DOOR1: return Door1GUID; - case DATA_DOOR2: return Door2GUID; - case DATA_DOOR3: return Door3GUID; - case DATA_DOOR4: return Door4GUID; - case DATA_DOOR5: return Door5GUID; - case DATA_DOOR6: return Door6GUID; - case DATA_PRISON_CELL1: return PrisonCell1GUID; - case DATA_PRISON_CELL2: return PrisonCell2GUID; - case DATA_PRISON_CELL3: return PrisonCell3GUID; - case DATA_PRISON_CELL4: return PrisonCell4GUID; - case DATA_PRISON_CELL5: return PrisonCell5GUID; - case DATA_PRISON_CELL6: return PrisonCell6GUID; - case DATA_PRISON_CELL7: return PrisonCell7GUID; - case DATA_PRISON_CELL8: return PrisonCell8GUID; - case DATA_BROGGOK_LEVER: return BroggokLeverGUID; + case GO_PRISON_DOOR_04: + PrisonDoor4GUID = go->GetGUID(); + // no break + case GO_PRISON_DOOR_01: + case GO_PRISON_DOOR_02: + case GO_PRISON_DOOR_03: + case GO_PRISON_DOOR_05: + case GO_SUMMON_DOOR: + AddDoor(go, true); + break; + case GO_BROGGOK_LEVER: + BroggokLeverGUID = go->GetGUID(); + break; + case GO_PRISON_CELL_DOOR_1: + PrisonCellGUIDs[DATA_PRISON_CELL1 - DATA_PRISON_CELL1] = go->GetGUID(); + break; + case GO_PRISON_CELL_DOOR_2: + PrisonCellGUIDs[DATA_PRISON_CELL2 - DATA_PRISON_CELL1] = go->GetGUID(); + break; + case GO_PRISON_CELL_DOOR_3: + PrisonCellGUIDs[DATA_PRISON_CELL3 - DATA_PRISON_CELL1] = go->GetGUID(); + break; + case GO_PRISON_CELL_DOOR_4: + PrisonCellGUIDs[DATA_PRISON_CELL4 - DATA_PRISON_CELL1] = go->GetGUID(); + break; + case GO_PRISON_CELL_DOOR_5: + PrisonCellGUIDs[DATA_PRISON_CELL5 - DATA_PRISON_CELL1] = go->GetGUID(); + break; + case GO_PRISON_CELL_DOOR_6: + PrisonCellGUIDs[DATA_PRISON_CELL6 - DATA_PRISON_CELL1] = go->GetGUID(); + break; + case GO_PRISON_CELL_DOOR_7: + PrisonCellGUIDs[DATA_PRISON_CELL7 - DATA_PRISON_CELL1] = go->GetGUID(); + break; + case GO_PRISON_CELL_DOOR_8: + PrisonCellGUIDs[DATA_PRISON_CELL8 - DATA_PRISON_CELL1] = go->GetGUID(); + break; + default: + break; } - return 0; } - void SetData(uint32 type, uint32 data) OVERRIDE + void OnGameObjectRemove(GameObject* go) OVERRIDE { - switch (type) - { - case TYPE_THE_MAKER_EVENT: - m_auiEncounter[0] = data; - break; - case TYPE_BROGGOK_EVENT: - m_auiEncounter[1] = data; - UpdateBroggokEvent(data); - break; - case TYPE_KELIDAN_THE_BREAKER_EVENT: - m_auiEncounter[2] = data; - break; - } - - if (data == DONE) + switch (go->GetEntry()) { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << ' ' << m_auiEncounter[1] << ' ' << m_auiEncounter[2]; - - str_data = saveStream.str(); - - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; + case GO_PRISON_DOOR_01: + case GO_PRISON_DOOR_02: + case GO_PRISON_DOOR_03: + case GO_PRISON_DOOR_04: + case GO_PRISON_DOOR_05: + case GO_SUMMON_DOOR: + AddDoor(go, false); + break; + default: + break; } } - uint32 GetData(uint32 type) const OVERRIDE + uint64 GetData64(uint32 type) const OVERRIDE { switch (type) { - case TYPE_THE_MAKER_EVENT: return m_auiEncounter[0]; - case TYPE_BROGGOK_EVENT: return m_auiEncounter[1]; - case TYPE_KELIDAN_THE_BREAKER_EVENT: return m_auiEncounter[2]; + case DATA_THE_MAKER: + return TheMakerGUID; + case DATA_BROGGOK: + return BroggokGUID; + case DATA_KELIDAN_THE_BREAKER: + return KelidanTheBreakerGUID; + case DATA_BROGGOK_LEVER: + return BroggokLeverGUID; } - return 0; - } - const char* Save() - { - return str_data.c_str(); + return 0; } - void Load(const char* in) OVERRIDE + bool SetBossState(uint32 type, EncounterState state) OVERRIDE { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); + if (!InstanceScript::SetBossState(type, state)) + return false; - std::istringstream loadStream(in); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2]; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS || m_auiEncounter[i] == FAIL) - m_auiEncounter[i] = NOT_STARTED; - - OUT_LOAD_INST_DATA_COMPLETE; - } - - void UpdateBroggokEvent(uint32 data) - { - switch (data) + switch (type) { - case IN_PROGRESS: - ActivateCell(DATA_PRISON_CELL5); - HandleGameObject(Door4GUID, false); + case DATA_BROGGOK: + switch (state) + { + case IN_PROGRESS: + ActivateCell(DATA_PRISON_CELL5); + break; + case NOT_STARTED: + ResetPrisons(); + if (GameObject* lever = instance->GetGameObject(BroggokLeverGUID)) + lever->Respawn(); + break; + default: + break; + } break; - case NOT_STARTED: - ResetPrisons(); - HandleGameObject(Door5GUID, false); - HandleGameObject(Door4GUID, true); - if (GameObject* lever = instance->GetGameObject(BroggokLeverGUID)) - lever->Respawn(); + default: break; } + + return true; } void ResetPrisons() { PrisonerCounter5 = PrisonersCell5.size(); ResetPrisoners(PrisonersCell5); - HandleGameObject(PrisonCell5GUID, false); + HandleGameObject(PrisonCellGUIDs[DATA_PRISON_CELL5 - DATA_PRISON_CELL1], false); PrisonerCounter6 = PrisonersCell6.size(); ResetPrisoners(PrisonersCell6); - HandleGameObject(PrisonCell6GUID, false); + HandleGameObject(PrisonCellGUIDs[DATA_PRISON_CELL6 - DATA_PRISON_CELL1], false); PrisonerCounter7 = PrisonersCell7.size(); ResetPrisoners(PrisonersCell7); - HandleGameObject(PrisonCell7GUID, false); + HandleGameObject(PrisonCellGUIDs[DATA_PRISON_CELL7 - DATA_PRISON_CELL1], false); PrisonerCounter8 = PrisonersCell8.size(); ResetPrisoners(PrisonersCell8); - HandleGameObject(PrisonCell8GUID, false); + HandleGameObject(PrisonCellGUIDs[DATA_PRISON_CELL8 - DATA_PRISON_CELL1], false); } void ResetPrisoners(const std::set<uint64>& prisoners) @@ -367,7 +281,7 @@ class instance_blood_furnace : public InstanceMapScript else if (PrisonersCell7.find(guid) != PrisonersCell7.end() && --PrisonerCounter7 <= 0) ActivateCell(DATA_PRISON_CELL8); else if (PrisonersCell8.find(guid) != PrisonersCell8.end() && --PrisonerCounter8 <= 0) - ActivateCell(DATA_DOOR5); + ActivateCell(DATA_DOOR_4); } void ActivateCell(uint8 id) @@ -375,30 +289,30 @@ class instance_blood_furnace : public InstanceMapScript switch (id) { case DATA_PRISON_CELL5: - HandleGameObject(PrisonCell5GUID, true); + HandleGameObject(PrisonCellGUIDs[id - DATA_PRISON_CELL1], true); ActivatePrisoners(PrisonersCell5); break; case DATA_PRISON_CELL6: - HandleGameObject(PrisonCell6GUID, true); + HandleGameObject(PrisonCellGUIDs[id - DATA_PRISON_CELL1], true); ActivatePrisoners(PrisonersCell6); break; case DATA_PRISON_CELL7: - HandleGameObject(PrisonCell7GUID, true); + HandleGameObject(PrisonCellGUIDs[id - DATA_PRISON_CELL1], true); ActivatePrisoners(PrisonersCell7); break; case DATA_PRISON_CELL8: - HandleGameObject(PrisonCell8GUID, true); + HandleGameObject(PrisonCellGUIDs[id - DATA_PRISON_CELL1], true); ActivatePrisoners(PrisonersCell8); break; - case DATA_DOOR5: - HandleGameObject(Door5GUID, true); + case DATA_DOOR_4: + HandleGameObject(PrisonDoor4GUID, true); if (Creature* broggok = instance->GetCreature(BroggokGUID)) broggok->AI()->DoAction(ACTION_ACTIVATE_BROGGOK); break; } } - void ActivatePrisoners(const std::set<uint64>& prisoners) + void ActivatePrisoners(std::set<uint64> const& prisoners) { for (std::set<uint64>::const_iterator i = prisoners.begin(); i != prisoners.end(); ++i) if (Creature* prisoner = instance->GetCreature(*i)) @@ -407,6 +321,69 @@ class instance_blood_furnace : public InstanceMapScript prisoner->SetInCombatWithZone(); } } + + std::string GetSaveData() OVERRIDE + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "B F " << GetBossSaveData(); + + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); + } + + void Load(char const* str) OVERRIDE + { + if (!str) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(str); + + char dataHead1, dataHead2; + + std::istringstream loadStream(str); + loadStream >> dataHead1 >> dataHead2; + + if (dataHead1 == 'B' && dataHead2 == 'F') + { + for (uint32 i = 0; i < EncounterCount; ++i) + { + uint32 tmpState; + loadStream >> tmpState; + if (tmpState == IN_PROGRESS || tmpState > SPECIAL) + tmpState = NOT_STARTED; + SetBossState(i, EncounterState(tmpState)); + } + } + else + OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } + + protected: + uint64 TheMakerGUID; + uint64 BroggokGUID; + uint64 KelidanTheBreakerGUID; + + uint64 BroggokLeverGUID; + uint64 PrisonDoor4GUID; + + uint64 PrisonCellGUIDs[8]; + + std::set<uint64>PrisonersCell5; + std::set<uint64>PrisonersCell6; + std::set<uint64>PrisonersCell7; + std::set<uint64>PrisonersCell8; + + uint8 PrisonerCounter5; + uint8 PrisonerCounter6; + uint8 PrisonerCounter7; + uint8 PrisonerCounter8; }; InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE diff --git a/src/server/scripts/Outland/zone_blades_edge_mountains.cpp b/src/server/scripts/Outland/zone_blades_edge_mountains.cpp index 83b4f0440e0..cc58be26664 100644 --- a/src/server/scripts/Outland/zone_blades_edge_mountains.cpp +++ b/src/server/scripts/Outland/zone_blades_edge_mountains.cpp @@ -1125,7 +1125,7 @@ public: struct npc_oscillating_frequency_scanner_master_bunnyAI : public ScriptedAI { - npc_oscillating_frequency_scanner_master_bunnyAI(Creature* creature) : ScriptedAI(creature) + npc_oscillating_frequency_scanner_master_bunnyAI(Creature* creature) : ScriptedAI(creature) { playerGuid = 0; } diff --git a/src/server/scripts/Pet/pet_dk.cpp b/src/server/scripts/Pet/pet_dk.cpp index daeb0d71720..61c3de0e6b1 100644 --- a/src/server/scripts/Pet/pet_dk.cpp +++ b/src/server/scripts/Pet/pet_dk.cpp @@ -54,7 +54,7 @@ class npc_pet_dk_ebon_gargoyle : public CreatureScript uint64 ownerGuid = me->GetOwnerGUID(); if (!ownerGuid) return; - + // Find victim of Summon Gargoyle spell std::list<Unit*> targets; Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(me, me, 30.0f); diff --git a/src/server/scripts/Pet/pet_hunter.cpp b/src/server/scripts/Pet/pet_hunter.cpp index 0db35bf2fe6..8a0b78b5478 100644 --- a/src/server/scripts/Pet/pet_hunter.cpp +++ b/src/server/scripts/Pet/pet_hunter.cpp @@ -25,9 +25,9 @@ enum HunterSpells { - SPELL_HUNTER_CRIPPLING_POISON = 30981, // Viper - SPELL_HUNTER_DEADLY_POISON = 34655, // Venomous Snake - SPELL_HUNTER_MIND_NUMBING_POISON = 25810 // Viper + SPELL_HUNTER_CRIPPLING_POISON = 30981, // Viper + SPELL_HUNTER_DEADLY_POISON_PASSIVE = 34657, // Venomous Snake + SPELL_HUNTER_MIND_NUMBING_POISON = 25810 // Viper }; enum HunterCreatures @@ -57,14 +57,17 @@ class npc_pet_hunter_snake_trap : public CreatureScript me->SetMaxHealth(uint32(107 * (me->getLevel() - 40) * 0.025f)); // Add delta to make them not all hit the same time uint32 delta = (rand() % 7) * 100; - me->SetStatFloatValue(UNIT_FIELD_BASEATTACKTIME, float(Info->baseattacktime + delta)); - me->SetStatFloatValue(UNIT_FIELD_RANGED_ATTACK_POWER, float(Info->attackpower)); + me->SetAttackTime(BASE_ATTACK, Info->baseattacktime + delta); + //me->SetStatFloatValue(UNIT_FIELD_RANGED_ATTACK_POWER, float(Info->attackpower)); // Start attacking attacker of owner on first ai update after spawn - move in line of sight may choose better target if (!me->GetVictim() && me->IsSummon()) if (Unit* Owner = me->ToTempSummon()->GetSummoner()) if (Owner->getAttackerForHelper()) AttackStart(Owner->getAttackerForHelper()); + + if (!_isViper) + DoCast(me, SPELL_HUNTER_DEADLY_POISON_PASSIVE, true); } // Redefined for random target selection: @@ -99,32 +102,19 @@ class npc_pet_hunter_snake_trap : public CreatureScript return; } - if (_spellTimer <= diff) + // Viper + if (_isViper) { - if (_isViper) // Viper + if (_spellTimer <= diff) { - if (urand(0, 2) == 0) //33% chance to cast - { - uint32 spell; - if (urand(0, 1) == 0) - spell = SPELL_HUNTER_MIND_NUMBING_POISON; - else - spell = SPELL_HUNTER_CRIPPLING_POISON; - - DoCastVictim(spell); - } + if (urand(0, 2) == 0) // 33% chance to cast + DoCastVictim(RAND(SPELL_HUNTER_MIND_NUMBING_POISON, SPELL_HUNTER_CRIPPLING_POISON)); _spellTimer = 3000; } - else // Venomous Snake - { - if (urand(0, 2) == 0) // 33% chance to cast - DoCastVictim(SPELL_HUNTER_DEADLY_POISON); - _spellTimer = 1500 + (rand() % 5) * 100; - } + else + _spellTimer -= diff; } - else - _spellTimer -= diff; DoMeleeAttackIfReady(); } diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index 3f5bb34015e..e1ef9ea6862 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -879,7 +879,7 @@ class spell_dk_presence : public SpellScriptLoader { Unit* target = GetTarget(); - if (GetSpellInfo()->Id == SPELL_DK_BLOOD_PRESENCE) + if (GetId() == SPELL_DK_BLOOD_PRESENCE) target->CastSpell(target, SPELL_DK_IMPROVED_BLOOD_PRESENCE_TRIGGERED, true); else if (AuraEffect const* impAurEff = target->GetAuraEffectOfRankedSpell(SPELL_DK_IMPROVED_BLOOD_PRESENCE_R1, EFFECT_0)) if (!target->HasAura(SPELL_DK_IMPROVED_BLOOD_PRESENCE_TRIGGERED)) @@ -890,7 +890,7 @@ class spell_dk_presence : public SpellScriptLoader { Unit* target = GetTarget(); - if (GetSpellInfo()->Id == SPELL_DK_FROST_PRESENCE) + if (GetId() == SPELL_DK_FROST_PRESENCE) target->CastSpell(target, SPELL_DK_FROST_PRESENCE_TRIGGERED, true); else if (AuraEffect const* impAurEff = target->GetAuraEffectOfRankedSpell(SPELL_DK_IMPROVED_FROST_PRESENCE_R1, EFFECT_0)) if (!target->HasAura(SPELL_DK_FROST_PRESENCE_TRIGGERED)) @@ -901,12 +901,12 @@ class spell_dk_presence : public SpellScriptLoader { Unit* target = GetTarget(); - if (GetSpellInfo()->Id == SPELL_DK_UNHOLY_PRESENCE) + if (GetId() == SPELL_DK_UNHOLY_PRESENCE) target->CastSpell(target, SPELL_DK_UNHOLY_PRESENCE_TRIGGERED, true); if (AuraEffect const* impAurEff = target->GetAuraEffectOfRankedSpell(SPELL_DK_IMPROVED_UNHOLY_PRESENCE_R1, EFFECT_0)) { - if (GetSpellInfo()->Id == SPELL_DK_UNHOLY_PRESENCE) + if (GetId() == SPELL_DK_UNHOLY_PRESENCE) { // Not listed as any effect, only base points set int32 bp = impAurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue(); diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp index e9a010868d8..ac30f6f1e80 100644 --- a/src/server/scripts/World/npcs_special.cpp +++ b/src/server/scripts/World/npcs_special.cpp @@ -34,7 +34,6 @@ npc_garments_of_quests 80% NPC's related to all Garments of-quests 5621, 56 npc_injured_patient 100% patients for triage-quests (6622 and 6624) npc_doctor 100% Gustaf Vanhowzen and Gregory Victor, quest 6622 and 6624 (Triage) npc_mount_vendor 100% Regular mount vendors all over the world. Display gossip if player doesn't meet the requirements to buy -npc_rogue_trainer 80% Scripted trainers, so they are able to offer item 17126 for class quest 6681 npc_sayge 100% Darkmoon event fortune teller, buff player based on answers given npc_snake_trap_serpents 80% AI for snakes that summoned by Snake Trap npc_shadowfiend 100% restore 5% of owner's mana when shadowfiend die from damage @@ -1239,86 +1238,6 @@ public: } }; -/*###### -## npc_rogue_trainer -######*/ - -#define GOSSIP_HELLO_ROGUE1 "I wish to unlearn my talents" -#define GOSSIP_HELLO_ROGUE2 "<Take the letter>" -#define GOSSIP_HELLO_ROGUE3 "Purchase a Dual Talent Specialization." - -class npc_rogue_trainer : public CreatureScript -{ -public: - npc_rogue_trainer() : CreatureScript("npc_rogue_trainer") { } - - bool OnGossipHello(Player* player, Creature* creature) OVERRIDE - { - if (creature->IsQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - if (creature->IsTrainer()) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_TEXT_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN); - - if (player->getClass() == CLASS_ROGUE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_HELLO_ROGUE1, GOSSIP_SENDER_MAIN, GOSSIP_OPTION_UNLEARNTALENTS); - - if (player->GetSpecsCount() == 1 && player->getLevel() >= sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL)) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_HELLO_ROGUE3, GOSSIP_SENDER_MAIN, GOSSIP_OPTION_LEARNDUALSPEC); - - if (player->getClass() == CLASS_ROGUE && player->getLevel() >= 24 && !player->HasItemCount(17126) && !player->GetQuestRewardStatus(6681)) - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_ROGUE2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - player->SEND_GOSSIP_MENU(5996, creature->GetGUID()); - } else - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - - return true; - } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) OVERRIDE - { - player->PlayerTalkClass->ClearMenus(); - switch (action) - { - case GOSSIP_ACTION_INFO_DEF + 1: - player->CLOSE_GOSSIP_MENU(); - player->CastSpell(player, 21100, false); - break; - case GOSSIP_ACTION_TRAIN: - player->GetSession()->SendTrainerList(creature->GetGUID()); - break; - case GOSSIP_OPTION_UNLEARNTALENTS: - player->CLOSE_GOSSIP_MENU(); - player->SendTalentWipeConfirm(creature->GetGUID()); - break; - case GOSSIP_OPTION_LEARNDUALSPEC: - if (player->GetSpecsCount() == 1 && !(player->getLevel() < sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL))) - { - if (!player->HasEnoughMoney(10000000)) - { - player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0); - player->PlayerTalkClass->SendCloseGossip(); - break; - } - else - { - player->ModifyMoney(-10000000); - - // Cast spells that teach dual spec - // Both are also ImplicitTarget self and must be cast by player - player->CastSpell(player, 63680, true, NULL, NULL, player->GetGUID()); - player->CastSpell(player, 63624, true, NULL, NULL, player->GetGUID()); - - // Should show another Gossip text with "Congratulations..." - player->PlayerTalkClass->SendCloseGossip(); - } - } - break; - } - return true; - } -}; /*###### ## npc_sayge @@ -2445,7 +2364,6 @@ void AddSC_npcs_special() new npc_garments_of_quests(); new npc_guardian(); new npc_mount_vendor(); - new npc_rogue_trainer(); new npc_sayge(); new npc_steam_tonk(); new npc_tonk_mine(); diff --git a/src/server/shared/Utilities/EventProcessor.h b/src/server/shared/Utilities/EventProcessor.h index fd8b2909165..10ae6aa954c 100644 --- a/src/server/shared/Utilities/EventProcessor.h +++ b/src/server/shared/Utilities/EventProcessor.h @@ -28,9 +28,9 @@ class BasicEvent { public: - BasicEvent() - { - to_Abort = false; + BasicEvent() + { + to_Abort = false; m_addTime = 0; m_execTime = 0; } diff --git a/src/server/worldserver/Master.cpp b/src/server/worldserver/Master.cpp index 67af12660de..f4b2b542de6 100644 --- a/src/server/worldserver/Master.cpp +++ b/src/server/worldserver/Master.cpp @@ -86,8 +86,8 @@ private: uint32 _lastChange; uint32 _delaytime; public: - FreezeDetectorRunnable() - { + FreezeDetectorRunnable() + { _loops = 0; _lastChange = 0; _delaytime = 0; diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 4e594fc88c0..2a47c8f989e 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -138,7 +138,7 @@ WorldServerPort = 8085 # # BindIP -# Description: Bind world server to IP/hostname +# Description: Bind world server to IP/hostname. # Default: "0.0.0.0" - (Bind to all IPs on the system) BindIP = "0.0.0.0" @@ -152,7 +152,7 @@ BindIP = "0.0.0.0" # UseProcessors # Description: Processors mask for Windows and Linux based multi-processor systems. # Example: A computer with 2 CPUs: -# 1 - 1st CPU only, 2 - 2nd CPU only, 3 - 1st and 2nd CPU, because 1 | 2 is 3 +# 1 - 1st CPU only, 2 - 2nd CPU only, 3 - 1st and 2nd CPU, because 1 | 2 is 3 # Default: 0 - (Selected by OS) # 1+ - (Bit mask value of selected processors) @@ -169,7 +169,7 @@ ProcessPriority = 0 # # Compression -# Description: Compression level for client update packages +# Description: Compression level for client update packages. # Range: 1-9 # Default: 1 - (Speed) # 9 - (Best compression) @@ -275,7 +275,7 @@ PlayerSave.Stats.SaveOnlyOnLogout = 1 # # mmap.enablePathFinding -# Description: Enable/Disable pathfinding using mmaps - experimental +# Description: Enable/Disable pathfinding using mmaps - experimental. # Default: 0 - (Disabled) # 1 - (Enabled) @@ -395,7 +395,7 @@ PersistentCharacterCleanFlags = 0 # SERVER LOGGING # # PidFile -# Description: World daemon PID file +# Description: World daemon PID file. # Example: "./world.pid" - (Enabled) # Default: "" - (Disabled) @@ -440,7 +440,6 @@ ChatLogs.SysChan = 0 # Default: 0 - (Disabled) # 1 - (Enabled) - ChatLogs.Party = 0 # @@ -449,7 +448,6 @@ ChatLogs.Party = 0 # Default: 0 - (Disabled) # 1 - (Enabled) - ChatLogs.Raid = 0 # @@ -698,6 +696,7 @@ CharacterCreating.Disabled.ClassMask = 0 # Default: 50 CharactersPerAccount = 50 + # # CharactersPerRealm # Description: Limit number of characters per account on this realm. @@ -717,7 +716,7 @@ HeroicCharactersPerRealm = 1 # # CharacterCreating.MinLevelForHeroicCharacter # Description: Limit creating heroic characters only for account with another -# character of specific level (ignored for GM accounts) +# character of specific level (ignored for GM accounts). # Default: 55 - (Enabled, Requires at least another level 55 character) # 0 - (Disabled) # 1 - (Enabled, Requires at least another level 1 character) @@ -745,7 +744,7 @@ MaxPlayerLevel = 80 # # MinDualSpecLevel -# Description: Level requirement for Dual Talent Specialization +# Description: Level requirement for Dual Talent Specialization. # Default: 40 MinDualSpecLevel = 40 @@ -913,6 +912,7 @@ Instance.UnloadDelay = 1800000 # true - (Enabled, show) InstancesResetAnnounce = false + # # Quests.LowLevelHideDiff # Description: Level difference between player and quest level at which quests are @@ -1125,7 +1125,7 @@ DBC.EnforceItemAttributes = 1 # # AccountInstancesPerHour -# Description: Controls the max amount of different instances player can enter within hour +# Description: Controls the max amount of different instances player can enter within hour. # Default: 5 AccountInstancesPerHour = 5 @@ -1813,7 +1813,7 @@ Rate.Damage.Fall = 1 # Rate.Auction.Deposit # Rate.Auction.Cut # Description: Auction rates (auction time, deposit get at auction start, -# auction cut from price at auction end) +# auction cut from price at auction end). # Default: 1 - (Rate.Auction.Time) # 1 - (Rate.Auction.Deposit) # 1 - (Rate.Auction.Cut) @@ -2018,14 +2018,14 @@ Die.Command.Mode = 1 # STATS LIMITS # # Stats.Limits.Enable -# Description: Enable or disable stats system +# Description: Enable or disable stats system. # Default: 0 - Disabled Stats.Limits.Enable = 0 # # Stats.Limit.[STAT] -# Description: Set percentage limit for dodge, parry, block and crit rating +# Description: Set percentage limit for dodge, parry, block and crit rating. # Default: 95.0 (95%) Stats.Limits.Dodge = 95.0 @@ -2142,7 +2142,7 @@ Battleground.Random.ResetHour = 6 # Battleground.RewardWinnerArenaLast # Battleground.RewardLoserHonorFirst # Battleground.RewardLoserHonorLast -# Description: Random Battlegrounds / call to the arms rewards +# Description: Random Battlegrounds / call to the arms rewards. # Default: 30 - Battleground.RewardWinnerHonorFirst # 25 - Battleground.RewardWinnerArenaFirst # 15 - Battleground.RewardWinnerHonorLast @@ -2238,7 +2238,7 @@ Arena.RatingDiscardTimer = 600000 # # Arena.RatedUpdateTimer -# Description: Time (in milliseconds) between checks for matchups in rated arena +# Description: Time (in milliseconds) between checks for matchups in rated arena. # Default: 5000 - (5 seconds) Arena.RatedUpdateTimer = 5000 @@ -2392,7 +2392,7 @@ Ra.MinLevel = 3 # # SOAP.Enable -# Description: Enable soap service +# Description: Enable soap service. # Default: 0 - (Disabled) # 1 - (Enabled) @@ -2400,7 +2400,7 @@ SOAP.Enabled = 0 # # SOAP.IP -# Description: Bind SOAP service to IP/hostname +# Description: Bind SOAP service to IP/hostname. # Default: "127.0.0.1" - (Bind to localhost) SOAP.IP = "127.0.0.1" @@ -2554,12 +2554,29 @@ Guild.AllowMultipleGuildMaster = 0 # # ShowKickInWorld # Description: Determines whether a message is broadcasted to the entire server when a -# player gets kicked +# player gets kicked. # Default: 0 - (Disabled) # 1 - (Enabled) ShowKickInWorld = 0 +# ShowMuteInWorld +# Description: Determines whether a message is broadcasted to the entire server when a +# player gets muted. +# Default: 0 - (Disabled) +# 1 - (Enabled) + +ShowMuteInWorld = 0 + +# +# ShowBanInWorld +# Description: Determines whether a message is broadcasted to the entire server when a +# player gets banned. +# Default: 0 - (Disabled) +# 1 - (Enabled) + +ShowBanInWorld = 0 + # # RecordUpdateTimeDiffInterval # Description: Time (in milliseconds) update time diff is written to the log file. @@ -2569,6 +2586,7 @@ ShowKickInWorld = 0 # 0 - (Disabled) RecordUpdateTimeDiffInterval = 60000 + # # MinRecordUpdateTimeDiff # Description: Only record update time diff which is greater than this value. @@ -2628,8 +2646,8 @@ PlayerDump.DisallowOverwrite = 1 # # UI.ShowQuestLevelsInDialogs # Description: Show quest levels next to quest titles in UI dialogs -# Example: [13] Westfall Stew -# Default: 0 (do not show) +# Example: [13] Westfall Stew +# Default: 0 - (Do not show) UI.ShowQuestLevelsInDialogs = 0 @@ -2641,7 +2659,7 @@ UI.ShowQuestLevelsInDialogs = 0 # # Appender config values: Given a appender "name" # Appender.name -# Description: Defines 'where to log' +# Description: Defines 'where to log'. # Format: Type,LogLevel,Flags,optional1,optional2,optional3 # # Type @@ -2789,18 +2807,18 @@ Log.Async.Enable = 0 # # PacketSpoof.Policy # Description: Determines the course of action when packet spoofing is detected. -# Default: 1 - Log + kick -# 0 - Log only ("network") -# 2 - Log + kick + ban +# Default: 1 - (Log + kick) +# 0 - (Log only 'network') +# 2 - (Log + kick + ban) PacketSpoof.Policy = 1 # # PacketSpoof.BanMode # Description: If PacketSpoof.Policy equals 2, this will determine the ban mode. -# Note: Banning by character not supported for logical reasons. -# Default: 0 - Ban Account -# 2 - Ban IP +# Note: Banning by character not supported for logical reasons. +# Default: 0 - Ban Account +# 2 - Ban IP # PacketSpoof.BanMode = 0 diff --git a/src/tools/map_extractor/adt.h b/src/tools/map_extractor/adt.h index 227d6f2c763..5cb45d488d5 100644 --- a/src/tools/map_extractor/adt.h +++ b/src/tools/map_extractor/adt.h @@ -255,7 +255,7 @@ public: if (h->offsData2a) return *((uint64 *)((uint8*)this + 8 + h->offsData2a)); else - return 0xFFFFFFFFFFFFFFFFLL; + return 0xFFFFFFFFFFFFFFFFuLL; } }; |