From fa26c1f8d78e3b7160231abbafb3f05e42d200c1 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Wed, 25 Feb 2009 06:40:10 +0300 Subject: [PATCH 01/32] [7332] Allow provided target for .distance command using player name or shift-link with guid. --- sql/mangos.sql | 4 ++-- sql/updates/7332_01_mangos_command.sql | 6 +++++ sql/updates/Makefile.am | 2 ++ src/game/Level3.cpp | 32 ++++++++++++++++++++------ src/shared/revision_nr.h | 2 +- 5 files changed, 36 insertions(+), 10 deletions(-) create mode 100644 sql/updates/7332_01_mangos_command.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index 7302faea9..0b46f3f9e 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -22,7 +22,7 @@ DROP TABLE IF EXISTS `db_version`; CREATE TABLE `db_version` ( `version` varchar(120) default NULL, - `required_7331_01_mangos_command` bit(1) default NULL + `required_7332_01_mangos_command` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -275,7 +275,7 @@ INSERT INTO `command` VALUES ('demorph',2,'Syntax: .demorph\r\n\r\nDemorph the selected player.'), ('die',3,'Syntax: .die\r\n\r\nKill the selected player. If no player is selected, it will kill you.'), ('dismount',0,'Syntax: .dismount\r\n\r\nDismount you, if you are mounted.'), -('distance',3,'Syntax: .distance\r\n\r\nDisplay the distance from your character to the selected creature.'), +('distance',3,'Syntax: .distance [$name/$link]\r\n\r\nDisplay the distance from your character to the selected creature/player, or player with name $name, or player/creature/gameobject pointed to shift-link with guid.'), ('event',2,'Syntax: .event #event_id\r\nShow details about event with #event_id.'), ('event activelist',2,'Syntax: .event activelist\r\nShow list of currently active events.'), ('event start',2,'Syntax: .event start #event_id\r\nStart event #event_id. Set start time for event to current moment (change not saved in DB).'), diff --git a/sql/updates/7332_01_mangos_command.sql b/sql/updates/7332_01_mangos_command.sql new file mode 100644 index 000000000..65248d19c --- /dev/null +++ b/sql/updates/7332_01_mangos_command.sql @@ -0,0 +1,6 @@ +ALTER TABLE db_version CHANGE COLUMN required_7331_01_mangos_command required_7332_01_mangos_command bit; + +DELETE FROM `command` WHERE `name` = 'distance'; + +INSERT INTO `command` VALUES +('distance',3,'Syntax: .distance [$name/$link]\r\n\r\nDisplay the distance from your character to the selected creature/player, or player with name $name, or player/creature/gameobject pointed to shift-link with guid.'); diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index edaf35255..899b7b430 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -186,6 +186,7 @@ pkgdata_DATA = \ 7324_01_characters_character_spell.sql \ 7324_02_characters_character_aura.sql \ 7331_01_mangos_command.sql \ + 7332_01_mangos_command.sql \ README ## Additional files to include when running 'make dist' @@ -352,4 +353,5 @@ EXTRA_DIST = \ 7324_01_characters_character_spell.sql \ 7324_02_characters_character_aura.sql \ 7331_01_mangos_command.sql \ + 7332_01_mangos_command.sql \ README diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index c993949d1..4a89e25d8 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -3218,18 +3218,36 @@ bool ChatHandler::HandleGuildDeleteCommand(const char* args) return true; } -bool ChatHandler::HandleGetDistanceCommand(const char* /*args*/) +bool ChatHandler::HandleGetDistanceCommand(const char* args) { - Unit* pUnit = getSelectedUnit(); + WorldObject* obj; - if(!pUnit) + if (*args) { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; + uint64 guid = extractGuidFromLink((char*)args); + if(guid) + obj = (WorldObject*)ObjectAccessor::GetObjectByTypeMask(*m_session->GetPlayer(),guid,TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); + + if(!obj) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + } + else + { + obj = getSelectedUnit(); + + if(!obj) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } } - PSendSysMessage(LANG_DISTANCE, m_session->GetPlayer()->GetDistance(pUnit),m_session->GetPlayer()->GetDistance2d(pUnit)); + PSendSysMessage(LANG_DISTANCE, m_session->GetPlayer()->GetDistance(obj),m_session->GetPlayer()->GetDistance2d(obj)); return true; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 019806b23..78f402f3c 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7331" + #define REVISION_NR "7332" #endif // __REVISION_NR_H__ From e510fd247b65f0e2d8fd3b2c98c730cb2577c3fc Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Wed, 25 Feb 2009 06:44:18 +0300 Subject: [PATCH 02/32] Fixed bug with not send not finished move for recently visible creature with waypoint movement generator. --- src/game/WaypointMovementGenerator.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/game/WaypointMovementGenerator.h b/src/game/WaypointMovementGenerator.h index cc552d974..2ee893fb4 100644 --- a/src/game/WaypointMovementGenerator.h +++ b/src/game/WaypointMovementGenerator.h @@ -105,6 +105,10 @@ public PathMovementBase // statics static void Initialize(void); + + // allow use for overwrite empty implementation + bool GetDestination(float& x, float& y, float& z) const { return PathMovementBase::GetDestination(x,y,z); } + private: void ClearWaypoints(); @@ -138,5 +142,8 @@ public PathMovementBase bool HasArrived() const { return (i_currentNode >= i_path.Size()); } void SetCurrentNodeAfterTeleport(); void SkipCurrentNode() { ++i_currentNode; } + + // allow use for overwrite empty implementation + bool GetDestination(float& x, float& y, float& z) const { return PathMovementBase::GetDestination(x,y,z); } }; #endif From 3c87af93e612186f450a99bb63cca2419387892d Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Wed, 25 Feb 2009 06:53:54 +0300 Subject: [PATCH 03/32] Send not finished moves for creatures at mass visibility update. --- src/game/GridNotifiers.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/game/GridNotifiers.cpp b/src/game/GridNotifiers.cpp index 56de6adaa..8f49150d3 100644 --- a/src/game/GridNotifiers.cpp +++ b/src/game/GridNotifiers.cpp @@ -130,11 +130,17 @@ VisibleNotifier::Notify() // Now do operations that required done at object visibility change to visible - // target aura duration for caster show only if target exist at caster client // send data at target visibility change (adding to client) for(std::set::const_iterator vItr = i_visibleNow.begin(); vItr != i_visibleNow.end(); ++vItr) + { + // target aura duration for caster show only if target exist at caster client if((*vItr)!=&i_player && (*vItr)->isType(TYPEMASK_UNIT)) i_player.SendAurasForTarget((Unit*)(*vItr)); + + // non finished movements show to player + if((*vItr)->GetTypeId()==TYPEID_UNIT && ((Creature*)(*vItr))->isAlive()) + ((Creature*)(*vItr))->SendMonsterMoveWithSpeedToCurrentDestination(&i_player); + } } void From 1349d36270be76db06945316abe90a21670c50ce Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Wed, 25 Feb 2009 06:58:43 +0300 Subject: [PATCH 04/32] [7333] Refactoring DestinationHolder/Traveler/Unit::SendMonsterMoveWithSpeed code. * Move common code in appropriate functions. * Correct select speed and 2D/3D distance for creature/player walk/fly --- src/game/DestinationHolderImp.h | 20 +---------------- src/game/Traveller.h | 40 +++++++++++++++++++++++++++++++++ src/game/Unit.cpp | 30 +++++++++++-------------- src/game/Unit.h | 2 +- src/game/World.cpp | 2 +- src/shared/revision_nr.h | 2 +- 6 files changed, 57 insertions(+), 39 deletions(-) diff --git a/src/game/DestinationHolderImp.h b/src/game/DestinationHolderImp.h index 911f9d2be..ca881fe4f 100644 --- a/src/game/DestinationHolderImp.h +++ b/src/game/DestinationHolderImp.h @@ -79,25 +79,7 @@ DestinationHolder::StartTravel(TRAVELLER &traveller, bool sendMove) { if(!i_destSet) return 0; - i_fromX = traveller.GetPositionX(); - i_fromY = traveller.GetPositionY(); - i_fromZ = traveller.GetPositionZ(); - - float dx = i_destX - i_fromX; - float dy = i_destY - i_fromY; - float dz = i_destZ - i_fromZ; - - float dist; - //Should be for Creature Flying and Swimming. - if(traveller.GetTraveller().hasUnitState(UNIT_STAT_IN_FLIGHT)) - dist = sqrt((dx*dx) + (dy*dy) + (dz*dz)); - else //Walking on the ground - dist = sqrt((dx*dx) + (dy*dy)); - float speed = traveller.Speed(); - - speed *= 0.001f; // speed is in seconds so convert from second to millisecond - i_totalTravelTime = static_cast(dist/speed); - i_timeElapsed = 0; + i_totalTravelTime = traveller.GetTotalTrevelTimeTo(i_destX,i_destY,i_destZ); if(sendMove) traveller.MoveTo(i_destX, i_destY, i_destZ, i_totalTravelTime); return i_totalTravelTime; diff --git a/src/game/Traveller.h b/src/game/Traveller.h index 3daa558da..bfb3715d5 100644 --- a/src/game/Traveller.h +++ b/src/game/Traveller.h @@ -50,11 +50,24 @@ struct MANGOS_DLL_DECL Traveller T& GetTraveller(void) { return i_traveller; } float Speed(void) { assert(false); return 0.0f; } + float GetMoveDestinationTo(float x, float y, float z); + uint32 GetTotalTrevelTimeTo(float x, float y, float z); + void Relocation(float x, float y, float z, float orientation) {} void Relocation(float x, float y, float z) { Relocation(x, y, z, i_traveller.GetOrientation()); } void MoveTo(float x, float y, float z, uint32 t) {} }; +template +inline uint32 Traveller::GetTotalTrevelTimeTo(float x, float y, float z) +{ + float dist = GetMoveDestinationTo(x,y,z); + float speed = Speed(); + + speed *= 0.001f; // speed is in seconds so convert from second to millisecond + return static_cast(dist/speed); +} + // specialization for creatures template<> inline float Traveller::Speed() @@ -73,6 +86,20 @@ inline void Traveller::Relocation(float x, float y, float z, float ori i_traveller.GetMap()->CreatureRelocation(&i_traveller, x, y, z, orientation); } +template<> +inline float Traveller::GetMoveDestinationTo(float x, float y, float z) +{ + float dx = x - GetPositionX(); + float dy = y - GetPositionY(); + float dz = z - GetPositionZ(); + + if(i_traveller.hasUnitState(UNIT_STAT_IN_FLIGHT)) + return sqrt((dx*dx) + (dy*dy) + (dz*dz)); + else //Walking on the ground + return sqrt((dx*dx) + (dy*dy)); +} + + template<> inline void Traveller::MoveTo(float x, float y, float z, uint32 t) { @@ -89,6 +116,19 @@ inline float Traveller::Speed() return i_traveller.GetSpeed(i_traveller.HasUnitMovementFlag(MOVEMENTFLAG_WALK_MODE) ? MOVE_WALK : MOVE_RUN); } +template<> +inline float Traveller::GetMoveDestinationTo(float x, float y, float z) +{ + float dx = x - GetPositionX(); + float dy = y - GetPositionY(); + float dz = z - GetPositionZ(); + + if (i_traveller.isInFlight()) + return sqrt((dx*dx) + (dy*dy) + (dz*dz)); + else //Walking on the ground + return sqrt((dx*dx) + (dy*dy)); +} + template<> inline void Traveller::Relocation(float x, float y, float z, float orientation) { diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 97a26d978..d01837c09 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -43,6 +43,7 @@ #include "GridNotifiersImpl.h" #include "CellImpl.h" #include "Path.h" +#include "Traveller.h" #include @@ -232,31 +233,26 @@ void Unit::SendMonsterMoveWithSpeedToCurrentDestination(Player* player) { float x, y, z; if(GetMotionMaster()->GetDestination(x, y, z)) - SendMonsterMoveWithSpeed(x, y, z, GetUnitMovementFlags(), 0, player); + SendMonsterMoveWithSpeed(x, y, z, 0, player); } -void Unit::SendMonsterMoveWithSpeed(float x, float y, float z, uint32 MovementFlags, uint32 transitTime, Player* player) +void Unit::SendMonsterMoveWithSpeed(float x, float y, float z, uint32 transitTime, Player* player) { if (!transitTime) { - float dx = x - GetPositionX(); - float dy = y - GetPositionY(); - float dz = z - GetPositionZ(); - - float dist = ((dx*dx) + (dy*dy) + (dz*dz)); - if(dist<0) - dist = 0; + if(GetTypeId()==TYPEID_PLAYER) + { + Traveller traveller(*(Player*)this); + transitTime = traveller.GetTotalTrevelTimeTo(x,y,z); + } else - dist = sqrt(dist); - - double speed = GetSpeed((MovementFlags & MOVEMENTFLAG_WALK_MODE) ? MOVE_WALK : MOVE_RUN); - if(speed<=0) - speed = 2.5f; - speed *= 0.001f; - transitTime = static_cast(dist / speed + 0.5); + { + Traveller traveller(*(Creature*)this); + transitTime = traveller.GetTotalTrevelTimeTo(x,y,z); + } } //float orientation = (float)atan2((double)dy, (double)dx); - SendMonsterMove(x, y, z, 0, MovementFlags, transitTime, player); + SendMonsterMove(x, y, z, 0, GetUnitMovementFlags(), transitTime, player); } void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, uint32 MovementFlags, uint32 Time, Player* player) diff --git a/src/game/Unit.h b/src/game/Unit.h index 7ad9da6b6..362ead84b 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1068,7 +1068,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, uint32 MovementFlags, uint32 Time, Player* player = NULL); void SendMonsterMoveByPath(Path const& path, uint32 start, uint32 end, uint32 MovementFlags); - void SendMonsterMoveWithSpeed(float x, float y, float z, uint32 MovementFlags, uint32 transitTime = 0, Player* player = NULL); + void SendMonsterMoveWithSpeed(float x, float y, float z, uint32 transitTime = 0, Player* player = NULL); void SendMonsterMoveWithSpeedToCurrentDestination(Player* player = NULL); virtual void MoveOutOfRange(Player &) { }; diff --git a/src/game/World.cpp b/src/game/World.cpp index 3576a60a8..7093a93dc 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -1799,7 +1799,7 @@ void World::ScriptsProcess() sLog.outError("SCRIPT_COMMAND_MOVE_TO call for non-creature (TypeId: %u), skipping.",source->GetTypeId()); break; } - ((Unit *)source)->SendMonsterMoveWithSpeed(step.script->x, step.script->y, step.script->z, ((Unit *)source)->GetUnitMovementFlags(), step.script->datalong2 ); + ((Unit *)source)->SendMonsterMoveWithSpeed(step.script->x, step.script->y, step.script->z, step.script->datalong2 ); ((Unit *)source)->GetMap()->CreatureRelocation(((Creature *)source), step.script->x, step.script->y, step.script->z, 0); break; case SCRIPT_COMMAND_FLAG_SET: diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 78f402f3c..6bc1a8f1a 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7332" + #define REVISION_NR "7333" #endif // __REVISION_NR_H__ From dd06340d6cbfa2a6cca65bf0a754f9b3c2db21b5 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Wed, 25 Feb 2009 13:23:18 +0300 Subject: [PATCH 05/32] [7334] Restore movement generators work after recent commits. --- src/game/DestinationHolderImp.h | 5 +++++ src/shared/revision_nr.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/game/DestinationHolderImp.h b/src/game/DestinationHolderImp.h index ca881fe4f..d91eb8bcd 100644 --- a/src/game/DestinationHolderImp.h +++ b/src/game/DestinationHolderImp.h @@ -79,7 +79,12 @@ DestinationHolder::StartTravel(TRAVELLER &traveller, bool sendMove) { if(!i_destSet) return 0; + i_fromX = traveller.GetPositionX(); + i_fromY = traveller.GetPositionY(); + i_fromZ = traveller.GetPositionZ(); + i_totalTravelTime = traveller.GetTotalTrevelTimeTo(i_destX,i_destY,i_destZ); + i_timeElapsed = 0; if(sendMove) traveller.MoveTo(i_destX, i_destY, i_destZ, i_totalTravelTime); return i_totalTravelTime; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 6bc1a8f1a..90e21aa91 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7333" + #define REVISION_NR "7334" #endif // __REVISION_NR_H__ From 872d791ca67ed9b51184cf7c280bcbc064b4f9eb Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Wed, 25 Feb 2009 13:27:13 +0300 Subject: [PATCH 06/32] [7335] Implement active objects support. Active objects triggrering grid loading and updating around self like players. It can be used for event long run movements or escoring quest travels. Also can be used for proper implementation far vision spells. Currently only creatures can be activated by function call (from script) cr->SetActiveObjectState(true); Please avoid lot amount active objects in same time use. Existance active objects support isn't meaning that each rabbit must be active creature. Also added independent grid unloading locks for explicit unloading lock, lock for used by instance copied grids, lock counter for actiove object spawn grids locks. Last case required for prevent double spawn active creature walk far away from spawn point. --- src/framework/GameSystem/Grid.h | 18 ++- src/framework/GameSystem/NGrid.h | 21 +++- src/game/Corpse.h | 2 + src/game/Creature.cpp | 22 +++- src/game/Creature.h | 6 +- src/game/DynamicObject.h | 2 + src/game/GameObject.h | 2 + src/game/GridStates.cpp | 6 +- src/game/Map.cpp | 181 ++++++++++++++++++++++++++----- src/game/Map.h | 53 ++++++++- src/game/MapInstanced.h | 11 +- src/game/ObjectGridLoader.cpp | 4 + src/game/Player.h | 1 + src/game/Traveller.h | 2 +- src/shared/revision_nr.h | 2 +- 15 files changed, 282 insertions(+), 51 deletions(-) diff --git a/src/framework/GameSystem/Grid.h b/src/framework/GameSystem/Grid.h index f1c826da0..ce1d5463e 100644 --- a/src/framework/GameSystem/Grid.h +++ b/src/framework/GameSystem/Grid.h @@ -103,7 +103,7 @@ class MANGOS_DLL_DECL Grid /** Returns the number of object within the grid. */ - unsigned int ActiveObjectsInGrid(void) const { return i_objects.template Count(); } + unsigned int ActiveObjectsInGrid(void) const { return m_activeGridObjects.size()+i_objects.template Count(); } /** Accessors: Returns a specific type of object in the GRID_OBJECT_TYPES */ @@ -112,11 +112,21 @@ class MANGOS_DLL_DECL Grid /** Inserts a container type object into the grid. */ - template bool AddGridObject(SPECIFIC_OBJECT *obj, OBJECT_HANDLE hdl) { return i_container.template insert(hdl, obj); } + template bool AddGridObject(SPECIFIC_OBJECT *obj, OBJECT_HANDLE hdl) + { + if(obj->isActiveObject()) + m_activeGridObjects.insert(obj); + return i_container.template insert(hdl, obj); + } /** Removes a containter type object from the grid */ - template bool RemoveGridObject(SPECIFIC_OBJECT *obj, OBJECT_HANDLE hdl) { return i_container.template remove(obj, hdl); } + template bool RemoveGridObject(SPECIFIC_OBJECT *obj, OBJECT_HANDLE hdl) + { + if(obj->isActiveObject()) + m_activeGridObjects.erase(obj); + return i_container.template remove(obj, hdl); + } private: @@ -125,5 +135,7 @@ class MANGOS_DLL_DECL Grid TypeMapContainer i_container; TypeMapContainer i_objects; + typedef std::set ActiveGridObjects; + ActiveGridObjects m_activeGridObjects; }; #endif diff --git a/src/framework/GameSystem/NGrid.h b/src/framework/GameSystem/NGrid.h index 663cf2059..0d6211243 100644 --- a/src/framework/GameSystem/NGrid.h +++ b/src/framework/GameSystem/NGrid.h @@ -30,17 +30,23 @@ class GridInfo { public: GridInfo() : i_timer(0) {} - GridInfo(time_t expiry, bool unload = true ) : i_timer(expiry), i_unloadflag(unload) {} + GridInfo(time_t expiry, bool unload = true ) : i_timer(expiry), i_unloadExplicitLock(!unload) {} const TimeTracker& getTimeTracker() const { return i_timer; } - bool getUnloadFlag() const { return i_unloadflag; } - void setUnloadFlag( bool pFlag) { i_unloadflag = pFlag; } + bool getUnloadLock() const { return i_unloadActiveLockCount || i_unloadExplicitLock || i_unloadReferenceLock; } + void setUnloadExplicitLock( bool on ) { i_unloadExplicitLock = on; } + void setUnloadReferenceLock( bool on ) { i_unloadReferenceLock = on; } + void incUnloadActiveLock() { ++i_unloadActiveLockCount; } + void decUnloadActiveLock() { if(i_unloadActiveLockCount) --i_unloadActiveLockCount; } + void setTimer(const TimeTracker& pTimer) { i_timer = pTimer; } void ResetTimeTracker(time_t interval) { i_timer.Reset(interval); } void UpdateTimeTracker(time_t diff) { i_timer.Update(diff); } private: TimeTracker i_timer; - bool i_unloadflag; + uint16 i_unloadActiveLockCount : 16; // lock from active object spawn points (prevent clone loading) + bool i_unloadExplicitLock : 1; // explicit manual lock or config setting + bool i_unloadReferenceLock : 1; // lock from instance map copy }; typedef enum @@ -90,8 +96,11 @@ class MANGOS_DLL_DECL NGrid GridInfo* getGridInfoRef() { return &i_GridInfo; } const TimeTracker& getTimeTracker() const { return i_GridInfo.getTimeTracker(); } - bool getUnloadFlag() const { return i_GridInfo.getUnloadFlag(); } - void setUnloadFlag( bool pFlag) { i_GridInfo.setUnloadFlag(pFlag); } + bool getUnloadLock() const { return i_GridInfo.getUnloadLock(); } + void setUnloadExplicitLock( bool on ) { i_GridInfo.setUnloadExplicitLock(on); } + void setUnloadReferenceLock( bool on ) { i_GridInfo.setUnloadReferenceLock(on); } + void incUnloadActiveLock() { i_GridInfo.incUnloadActiveLock(); } + void decUnloadActiveLock() { i_GridInfo.decUnloadActiveLock(); } void ResetTimeTracker(time_t interval) { i_GridInfo.ResetTimeTracker(interval); } void UpdateTimeTracker(time_t diff) { i_GridInfo.UpdateTimeTracker(diff); } diff --git a/src/game/Corpse.h b/src/game/Corpse.h index a072402e5..819382847 100644 --- a/src/game/Corpse.h +++ b/src/game/Corpse.h @@ -86,6 +86,8 @@ class Corpse : public WorldObject void Whisper(int32 textId,uint64 receiver) { MonsterWhisper(textId,receiver); } GridReference &GetGridRef() { return m_gridRef; } + + bool isActiveObject() const { return false; } private: GridReference m_gridRef; diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index df96a2b88..e0d9846e0 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -114,7 +114,7 @@ m_deathTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_resp m_gossipOptionLoaded(false), m_emoteState(0), m_isPet(false), m_isVehicle(false), m_isTotem(false), m_defaultMovementType(IDLE_MOTION_TYPE), m_DBTableGuid(0), m_equipmentId(0), m_AlreadyCallAssistance(false), m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), -m_creatureInfo(NULL) +m_creatureInfo(NULL), m_isActiveObject(false) { m_regenTimer = 200; m_valuesCount = UNIT_END; @@ -2098,3 +2098,23 @@ const char* Creature::GetNameForLocaleIdx(int32 loc_idx) const return GetName(); } + +void Creature::SetActiveObjectState( bool on ) +{ + if(m_isActiveObject==on) + return; + + bool world = IsInWorld(); + + Map* map; + if(world) + { + map = GetMap(); + map->Remove(this,false); + } + + m_isActiveObject = on; + + if(world) + map->Add(this); +} \ No newline at end of file diff --git a/src/game/Creature.h b/src/game/Creature.h index e6076dbbb..59c655477 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -609,7 +609,10 @@ class MANGOS_DLL_SPEC Creature : public Unit uint32 GetGlobalCooldown() const { return m_GlobalCooldown; } - void SetDeadByDefault (bool death_state) {m_isDeadByDefault = death_state;} + void SetDeadByDefault (bool death_state) { m_isDeadByDefault = death_state; } + + bool isActiveObject() const { return m_isActiveObject; } + void SetActiveObjectState(bool on); protected: bool CreateFromProto(uint32 guidlow,uint32 Entry,uint32 team, const CreatureData *data = NULL); @@ -661,6 +664,7 @@ class MANGOS_DLL_SPEC Creature : public Unit private: GridReference m_gridRef; CreatureInfo const* m_creatureInfo; // in heroic mode can different from ObjMgr::GetCreatureTemplate(GetEntry()) + bool m_isActiveObject; }; class AssistDelayEvent : public BasicEvent diff --git a/src/game/DynamicObject.h b/src/game/DynamicObject.h index 7c1d821e1..830662f0c 100644 --- a/src/game/DynamicObject.h +++ b/src/game/DynamicObject.h @@ -54,6 +54,8 @@ class DynamicObject : public WorldObject void Whisper(int32 textId,uint64 receiver) { MonsterWhisper(textId,receiver); } GridReference &GetGridRef() { return m_gridRef; } + + bool isActiveObject() const { return false; } protected: uint64 m_casterGuid; uint32 m_spellId; diff --git a/src/game/GameObject.h b/src/game/GameObject.h index 404d20fac..f34364bc5 100644 --- a/src/game/GameObject.h +++ b/src/game/GameObject.h @@ -575,6 +575,8 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject GameObject* LookupFishingHoleAround(float range); GridReference &GetGridRef() { return m_gridRef; } + + bool isActiveObject() const { return false; } protected: uint32 m_charges; // Spell charges for GAMEOBJECT_TYPE_SPELLCASTER (22) uint32 m_spellId; diff --git a/src/game/GridStates.cpp b/src/game/GridStates.cpp index 1bace7c27..4743860f5 100644 --- a/src/game/GridStates.cpp +++ b/src/game/GridStates.cpp @@ -34,7 +34,7 @@ ActiveState::Update(Map &m, NGridType &grid, GridInfo & info, const uint32 &x, c info.UpdateTimeTracker(t_diff); if( info.getTimeTracker().Passed() ) { - if( grid.ActiveObjectsInGrid() == 0 && !m.PlayersNearGrid(x, y) ) + if( grid.ActiveObjectsInGrid() == 0 && !m.ActiveObjectsNearGrid(x, y) ) { ObjectGridStoper stoper(grid); stoper.StopN(); @@ -58,14 +58,14 @@ IdleState::Update(Map &m, NGridType &grid, GridInfo &, const uint32 &x, const ui void RemovalState::Update(Map &m, NGridType &grid, GridInfo &info, const uint32 &x, const uint32 &y, const uint32 &t_diff) const { - if(info.getUnloadFlag()) + if(!info.getUnloadLock()) { info.UpdateTimeTracker(t_diff); if( info.getTimeTracker().Passed() ) { if( !m.UnloadGrid(x, y, false) ) { - sLog.outDebug("Grid[%u,%u] for map %u differed unloading due to players nearby", x, y, m.GetId()); + sLog.outDebug("Grid[%u,%u] for map %u differed unloading due to players or active objects nearby", x, y, m.GetId()); m.ResetGridExpiry(grid); } } diff --git a/src/game/Map.cpp b/src/game/Map.cpp index 47df9ebc9..18cc41174 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -138,7 +138,6 @@ void Map::LoadMap(uint32 mapid, uint32 instanceid, int x,int y) // return; ((MapInstanced*)(baseMap))->AddGridMapReference(GridPair(x,y)); - baseMap->SetUnloadFlag(GridPair(63-x,63-y), false); GridMaps[x][y] = baseMap->GridMaps[x][y]; return; } @@ -209,7 +208,8 @@ void Map::DeleteStateMachine() Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode) : i_mapEntry (sMapStore.LookupEntry(id)), i_spawnMode(SpawnMode), - i_id(id), i_InstanceId(InstanceId), m_unloadTimer(0), i_gridExpiry(expiry) + i_id(id), i_InstanceId(InstanceId), m_unloadTimer(0), i_gridExpiry(expiry), + m_activeNonPlayersIter(m_activeNonPlayers.end()) { for(unsigned int idx=0; idx < MAX_NUMBER_OF_GRIDS; ++idx) { @@ -360,22 +360,22 @@ Map::EnsureGridCreated(const GridPair &p) } void -Map::EnsureGridLoadedForPlayer(const Cell &cell, Player *player, bool add_player) +Map::EnsureGridLoaded(const Cell &cell, Player *player) { EnsureGridCreated(GridPair(cell.GridX(), cell.GridY())); NGridType *grid = getNGrid(cell.GridX(), cell.GridY()); assert(grid != NULL); - if( !isGridObjectDataLoaded(cell.GridX(), cell.GridY()) ) + if (!isGridObjectDataLoaded(cell.GridX(), cell.GridY())) { - if( player != NULL ) + if (player) { player->SendDelayResponse(MAX_GRID_LOAD_TIME); DEBUG_LOG("Player %s enter cell[%u,%u] triggers of loading grid[%u,%u] on map %u", player->GetName(), cell.CellX(), cell.CellY(), cell.GridX(), cell.GridY(), i_id); } else { - DEBUG_LOG("Player nearby triggers of loading grid [%u,%u] on map %u", cell.GridX(), cell.GridY(), i_id); + DEBUG_LOG("Active object nearby triggers of loading grid [%u,%u] on map %u", cell.GridX(), cell.GridY(), i_id); } ObjectGridLoader loader(*grid, this, cell); @@ -387,11 +387,9 @@ Map::EnsureGridLoadedForPlayer(const Cell &cell, Player *player, bool add_player ResetGridExpiry(*getNGrid(cell.GridX(), cell.GridY()), 0.1f); grid->SetGridState(GRID_STATE_ACTIVE); - - if( add_player && player != NULL ) - (*grid)(cell.CellX(), cell.CellY()).AddWorldObject(player, player->GetGUID()); } - else if( player && add_player ) + + if (player) AddToGrid(player,grid,cell); } @@ -412,7 +410,7 @@ Map::LoadGrid(const Cell& cell, bool no_unload) setGridObjectDataLoaded(true,cell.GridX(), cell.GridY()); if(no_unload) - getNGrid(cell.GridX(), cell.GridY())->setUnloadFlag(false); + getNGrid(cell.GridX(), cell.GridY())->setUnloadExplicitLock(true); } LoadVMap(63-cell.GridX(),63-cell.GridY()); } @@ -426,7 +424,7 @@ bool Map::Add(Player *player) // update player state for other player and visa-versa CellPair p = MaNGOS::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); Cell cell(p); - EnsureGridLoadedForPlayer(cell, player, true); + EnsureGridLoaded(cell, player); player->AddToWorld(); SendInitSelf(player); @@ -454,13 +452,19 @@ Map::Add(T *obj) } Cell cell(p); - EnsureGridCreated(GridPair(cell.GridX(), cell.GridY())); + if(obj->isActiveObject()) + EnsureGridLoaded(cell); + else + EnsureGridCreated(GridPair(cell.GridX(), cell.GridY())); + NGridType *grid = getNGrid(cell.GridX(), cell.GridY()); assert( grid != NULL ); AddToGrid(obj,grid,cell); obj->AddToWorld(); + AddToActive(obj); + DEBUG_LOG("Object %u enters grid[%u,%u]", GUID_LOPART(obj->GetGUID()), cell.GridX(), cell.GridY()); UpdateObjectVisibility(obj,cell,p); @@ -616,6 +620,56 @@ void Map::Update(const uint32 &t_diff) } } + // non-player active objects + if(!m_activeNonPlayers.empty()) + { + for(m_activeNonPlayersIter = m_activeNonPlayers.begin(); m_activeNonPlayersIter != m_activeNonPlayers.end(); ) + { + // skip not in world + WorldObject* obj = *m_activeNonPlayersIter; + + // step before processing, in this case if Map::Remove remove next object we correctly + // step to next-next, and if we step to end() then newly added objects can wait next update. + ++m_activeNonPlayersIter; + + if(!obj->IsInWorld()) + continue; + + CellPair standing_cell(MaNGOS::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY())); + + // Check for correctness of standing_cell, it also avoids problems with update_cell + if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) + continue; + + // the overloaded operators handle range checking + // so ther's no need for range checking inside the loop + CellPair begin_cell(standing_cell), end_cell(standing_cell); + begin_cell << 1; begin_cell -= 1; // upper left + end_cell >> 1; end_cell += 1; // lower right + + for(uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; ++x) + { + for(uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; ++y) + { + // marked cells are those that have been visited + // don't visit the same cell twice + uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x; + if(!isCellMarked(cell_id)) + { + markCell(cell_id); + CellPair pair(x,y); + Cell cell(pair); + cell.data.Part.reserved = CENTER_DISTRICT; + cell.SetNoCreate(); + CellLock cell_lock(cell, pair); + cell_lock->Visit(cell_lock, grid_object_update, *this); + cell_lock->Visit(cell_lock, world_object_update, *this); + } + } + } + } + } + // Don't unload grids if it's battleground, since we may have manually added GOs,creatures, those doesn't load from DB at grid re-load ! // This isn't really bother us, since as soon as we have instanced BG-s, the whole map unloads as the BG gets ended if (IsBattleGroundOrArena()) @@ -708,6 +762,8 @@ Map::Remove(T *obj, bool remove) NGridType *grid = getNGrid(cell.GridX(), cell.GridY()); assert( grid != NULL ); + RemoveFromActive(obj); + obj->RemoveFromWorld(); RemoveFromGrid(obj,grid,cell); @@ -749,9 +805,8 @@ Map::PlayerRelocation(Player *player, float x, float y, float z, float orientati RemoveFromGrid(player, oldGrid,old_cell); if( !old_cell.DiffGrid(new_cell) ) AddToGrid(player, oldGrid,new_cell); - - if( old_cell.DiffGrid(new_cell) ) - EnsureGridLoadedForPlayer(new_cell, player, true); + else + EnsureGridLoaded(new_cell, player); } // if move then update what player see and who seen @@ -868,8 +923,27 @@ bool Map::CreatureCellRelocation(Creature *c, Cell new_cell) sLog.outDebug("Creature (GUID: %u Entry: %u) move in same grid[%u,%u]cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY()); #endif } + + return true; } - else // in diff. grids + + // in diff. grids but active creature + if(c->isActiveObject()) + { + EnsureGridLoaded(new_cell); + + #ifdef MANGOS_DEBUG + if((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES)==0) + sLog.outDebug("Active creature (GUID: %u Entry: %u) moved from grid[%u,%u]cell[%u,%u] to grid[%u,%u]cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY()); + #endif + + RemoveFromGrid(c,getNGrid(old_cell.GridX(), old_cell.GridY()),old_cell); + AddToGrid(c,getNGrid(new_cell.GridX(), new_cell.GridY()),new_cell); + + return true; + } + + // in diff. loaded grid normal creature if(loaded(GridPair(new_cell.GridX(), new_cell.GridY()))) { #ifdef MANGOS_DEBUG @@ -882,17 +956,16 @@ bool Map::CreatureCellRelocation(Creature *c, Cell new_cell) EnsureGridCreated(GridPair(new_cell.GridX(), new_cell.GridY())); AddToGrid(c,getNGrid(new_cell.GridX(), new_cell.GridY()),new_cell); } - } - else - { - #ifdef MANGOS_DEBUG - if((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES)==0) - sLog.outDebug("Creature (GUID: %u Entry: %u) attempt move from grid[%u,%u]cell[%u,%u] to unloaded grid[%u,%u]cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY()); - #endif - return false; + + return true; } - return true; + // fail to move: normal creature attempt move to unloaded grid + #ifdef MANGOS_DEBUG + if((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES)==0) + sLog.outDebug("Creature (GUID: %u Entry: %u) attempt move from grid[%u,%u]cell[%u,%u] to unloaded grid[%u,%u]cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY()); + #endif + return false; } bool Map::CreatureRespawnRelocation(Creature *c) @@ -929,7 +1002,7 @@ bool Map::UnloadGrid(const uint32 &x, const uint32 &y, bool pForce) assert( grid != NULL); { - if(!pForce && PlayersNearGrid(x, y) ) + if(!pForce && ActiveObjectsNearGrid(x, y) ) return false; DEBUG_LOG("Unloading grid[%u,%u] for map %u", x,y, i_id); @@ -1513,7 +1586,7 @@ void Map::SendToPlayers(WorldPacket const* data) const itr->getSource()->GetSession()->SendPacket(data); } -bool Map::PlayersNearGrid(uint32 x, uint32 y) const +bool Map::ActiveObjectsNearGrid(uint32 x, uint32 y) const { CellPair cell_min(x*MAX_NUMBER_OF_CELLS, y*MAX_NUMBER_OF_CELLS); CellPair cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord+MAX_NUMBER_OF_CELLS); @@ -1532,9 +1605,61 @@ bool Map::PlayersNearGrid(uint32 x, uint32 y) const return true; } + for(ActiveNonPlayers::const_iterator iter = m_activeNonPlayers.begin(); iter != m_activeNonPlayers.end(); ++iter) + { + WorldObject* obj = *iter; + + CellPair p = MaNGOS::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); + if( (cell_min.x_coord <= p.x_coord && p.x_coord <= cell_max.x_coord) && + (cell_min.y_coord <= p.y_coord && p.y_coord <= cell_max.y_coord) ) + return true; + } + return false; } +void Map::AddToActive( Creature* c ) +{ + AddToActiveHelper(c); + + // also not allow unloading spawn grid to prevent creating creature clone at load + if(c->GetDBTableGUIDLow()) + { + float x,y,z; + c->GetRespawnCoord(x,y,z); + GridPair p = MaNGOS::ComputeGridPair(x, y); + if(getNGrid(p.x_coord, p.y_coord)) + getNGrid(p.x_coord, p.y_coord)->incUnloadActiveLock(); + else + { + GridPair p2 = MaNGOS::ComputeGridPair(c->GetPositionX(), c->GetPositionY()); + sLog.outError("Active creature (GUID: %u Entry: %u) added to grid[%u,%u] but spawn grid[%u,%u] not loaded.", + c->GetGUIDLow(), c->GetEntry(), p.x_coord, p.y_coord, p2.x_coord, p2.y_coord); + } + } +} + +void Map::RemoveFromActive( Creature* c ) +{ + RemoveFromActiveHelper(c); + + // also allow unloading spawn grid + if(c->GetDBTableGUIDLow()) + { + float x,y,z; + c->GetRespawnCoord(x,y,z); + GridPair p = MaNGOS::ComputeGridPair(x, y); + if(getNGrid(p.x_coord, p.y_coord)) + getNGrid(p.x_coord, p.y_coord)->decUnloadActiveLock(); + else + { + GridPair p2 = MaNGOS::ComputeGridPair(c->GetPositionX(), c->GetPositionY()); + sLog.outError("Active creature (GUID: %u Entry: %u) removed from grid[%u,%u] but spawn grid[%u,%u] not loaded.", + c->GetGUIDLow(), c->GetEntry(), p.x_coord, p.y_coord, p2.x_coord, p2.y_coord); + } + } +} + template void Map::Add(Corpse *); template void Map::Add(Creature *); template void Map::Add(GameObject *); diff --git a/src/game/Map.h b/src/game/Map.h index 65baba71d..a5900f7d7 100644 --- a/src/game/Map.h +++ b/src/game/Map.h @@ -164,8 +164,8 @@ class MANGOS_DLL_SPEC Map : public GridRefManager, public MaNGOS::Obj return( !getNGrid(p.x_coord, p.y_coord) || getNGrid(p.x_coord, p.y_coord)->GetGridState() == GRID_STATE_REMOVAL ); } - bool GetUnloadFlag(const GridPair &p) const { return getNGrid(p.x_coord, p.y_coord)->getUnloadFlag(); } - void SetUnloadFlag(const GridPair &p, bool unload) { getNGrid(p.x_coord, p.y_coord)->setUnloadFlag(unload); } + bool GetUnloadLock(const GridPair &p) const { return getNGrid(p.x_coord, p.y_coord)->getUnloadLock(); } + void SetUnloadLock(const GridPair &p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadExplicitLock(on); } void LoadGrid(const Cell& cell, bool no_unload = false); bool UnloadGrid(const uint32 &x, const uint32 &y, bool pForce); virtual void UnloadAll(bool pForce); @@ -256,12 +256,24 @@ class MANGOS_DLL_SPEC Map : public GridRefManager, public MaNGOS::Obj bool HavePlayers() const { return !m_mapRefManager.isEmpty(); } uint32 GetPlayersCountExceptGMs() const; - bool PlayersNearGrid(uint32 x,uint32 y) const; + bool ActiveObjectsNearGrid(uint32 x,uint32 y) const; void SendToPlayers(WorldPacket const* data) const; typedef MapRefManager PlayerList; PlayerList const& GetPlayers() const { return m_mapRefManager; } + + // must called with AddToWorld + template + void AddToActive(T* obj) { AddToActiveHelper(obj); } + + void AddToActive(Creature* obj); + + // must called with RemoveFromWorld + template + void RemoveFromActive(T* obj) { RemoveFromActiveHelper(obj); } + + void RemoveFromActive(Creature* obj); private: void LoadVMap(int pX, int pY); void LoadMap(uint32 mapid, uint32 instanceid, int x,int y); @@ -283,7 +295,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager, public MaNGOS::Obj CreatureMoveList i_creaturesToMove; bool loaded(const GridPair &) const; - void EnsureGridLoadedForPlayer(const Cell&, Player*, bool add_player); + void EnsureGridLoaded(const Cell&, Player* player = NULL); void EnsureGridCreated(const GridPair &); void buildNGridLinkage(NGridType* pNGridType) { pNGridType->link(this); } @@ -302,6 +314,8 @@ class MANGOS_DLL_SPEC Map : public GridRefManager, public MaNGOS::Obj void setNGrid(NGridType* grid, uint32 x, uint32 y); protected: + void SetUnloadReferenceLock(const GridPair &p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadReferenceLock(on); } + typedef MaNGOS::ObjectLevelLockable::Lock Guard; MapEntry const* i_mapEntry; @@ -312,6 +326,10 @@ class MANGOS_DLL_SPEC Map : public GridRefManager, public MaNGOS::Obj MapRefManager m_mapRefManager; MapRefManager::iterator m_mapRefIter; + + typedef std::set ActiveNonPlayers; + ActiveNonPlayers m_activeNonPlayers; + ActiveNonPlayers::iterator m_activeNonPlayersIter; private: typedef GridReadGuard ReadGuard; typedef GridWriteGuard WriteGuard; @@ -336,6 +354,31 @@ class MANGOS_DLL_SPEC Map : public GridRefManager, public MaNGOS::Obj template void DeleteFromWorld(T*); + + template + void AddToActiveHelper(T* obj) + { + if(obj->isActiveObject()) + m_activeNonPlayers.insert(obj); + } + + template + void RemoveFromActiveHelper(T* obj) + { + if(obj->isActiveObject()) + { + // Map::Update for active object in proccess + if(m_activeNonPlayersIter != m_activeNonPlayers.end()) + { + ActiveNonPlayers::iterator itr = m_activeNonPlayers.find(obj); + if(itr==m_activeNonPlayersIter) + ++m_activeNonPlayersIter; + m_activeNonPlayers.erase(itr); + } + else + m_activeNonPlayers.erase(obj); + } + } }; enum InstanceResetMethod @@ -408,7 +451,7 @@ Map::Visit(const CellLock &cell, TypeContainerVisitor & if( !cell->NoCreate() || loaded(GridPair(x,y)) ) { - EnsureGridLoadedForPlayer(cell, NULL, false); + EnsureGridLoaded(cell); //LOCK_TYPE guard(i_info[x][y]->i_lock); getNGrid(x, y)->Visit(cell_x, cell_y, visitor); } diff --git a/src/game/MapInstanced.h b/src/game/MapInstanced.h index 0a998e50d..e195cdcb7 100644 --- a/src/game/MapInstanced.h +++ b/src/game/MapInstanced.h @@ -42,11 +42,18 @@ class MANGOS_DLL_DECL MapInstanced : public Map Map* FindMap(uint32 InstanceId) { return _FindMap(InstanceId); } void DestroyInstance(uint32 InstanceId); void DestroyInstance(InstancedMaps::iterator &itr); - void AddGridMapReference(const GridPair &p) { ++GridMapReference[p.x_coord][p.y_coord]; } + + void AddGridMapReference(const GridPair &p) + { + ++GridMapReference[p.x_coord][p.y_coord]; + SetUnloadReferenceLock(GridPair(63-p.x_coord, 63-p.y_coord), true); + } + void RemoveGridMapReference(const GridPair &p) { --GridMapReference[p.x_coord][p.y_coord]; - if (!GridMapReference[p.x_coord][p.y_coord]) { SetUnloadFlag(GridPair(63-p.x_coord,63-p.y_coord), true); } + if (!GridMapReference[p.x_coord][p.y_coord]) + SetUnloadReferenceLock(GridPair(63-p.x_coord, 63-p.y_coord), false); } InstancedMaps &GetInstancedMaps() { return m_InstancedMaps; } diff --git a/src/game/ObjectGridLoader.cpp b/src/game/ObjectGridLoader.cpp index b2735df3b..9b944893e 100644 --- a/src/game/ObjectGridLoader.cpp +++ b/src/game/ObjectGridLoader.cpp @@ -125,6 +125,8 @@ void LoadHelper(CellGuidSet const& guid_set, CellPair &cell, GridRefManager & addUnitState(obj,cell); obj->AddToWorld(); + map->AddToActive(obj); + ++count; } @@ -150,6 +152,8 @@ void LoadHelper(CellCorpseSet const& cell_corpses, CellPair &cell, CorpseMapType addUnitState(obj,cell); obj->AddToWorld(); + map->AddToActive(obj); + ++count; } } diff --git a/src/game/Player.h b/src/game/Player.h index 9e102436a..76d6cc272 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -2142,6 +2142,7 @@ class MANGOS_DLL_SPEC Player : public Unit bool HasTitle(CharTitlesEntry const* title) { return HasTitle(title->bit_index); } void SetTitle(CharTitlesEntry const* title); + bool isActiveObject() const { return true; } protected: /*********************************************************/ diff --git a/src/game/Traveller.h b/src/game/Traveller.h index bfb3715d5..6aa55eb14 100644 --- a/src/game/Traveller.h +++ b/src/game/Traveller.h @@ -62,7 +62,7 @@ template inline uint32 Traveller::GetTotalTrevelTimeTo(float x, float y, float z) { float dist = GetMoveDestinationTo(x,y,z); - float speed = Speed(); + double speed = Speed(); speed *= 0.001f; // speed is in seconds so convert from second to millisecond return static_cast(dist/speed); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 90e21aa91..c4c742e0a 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7334" + #define REVISION_NR "7335" #endif // __REVISION_NR_H__ From 8f995ce90408370fa366f473c9fedf1e3b349830 Mon Sep 17 00:00:00 2001 From: Triply Date: Wed, 25 Feb 2009 19:21:31 +0100 Subject: [PATCH 07/32] [7336] Implemented new BattleGroundQueue invitation system. Now it supports premade group versus premade group matches. Added 2 new config options - InvitationType and PremadeGroupWaitForMatch - you can find more info in default config file. This patch can cause crashes. Signed-off-by: Triply --- src/game/AchievementMgr.cpp | 6 +- src/game/BattleGround.cpp | 71 +- src/game/BattleGround.h | 65 +- src/game/BattleGroundHandler.cpp | 23 +- src/game/BattleGroundMgr.cpp | 1303 +++++++++++++++--------------- src/game/BattleGroundMgr.h | 76 +- src/game/Group.cpp | 2 +- src/game/Player.cpp | 34 +- src/game/Player.h | 11 +- src/game/World.cpp | 55 +- src/game/World.h | 12 +- src/mangosd/mangosd.conf.dist.in | 137 ++-- src/shared/Common.h | 3 +- src/shared/revision_nr.h | 2 +- 14 files changed, 860 insertions(+), 940 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 989c1be35..83a6302bc 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -573,11 +573,11 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui uint32 spellCount = 0; for (PlayerSpellMap::const_iterator spellIter = GetPlayer()->GetSpellMap().begin(); spellIter != GetPlayer()->GetSpellMap().end(); - spellIter++) + ++spellIter) { for(SkillLineAbilityMap::const_iterator skillIter = spellmgr.GetBeginSkillLineAbilityMap(spellIter->first); skillIter != spellmgr.GetEndSkillLineAbilityMap(spellIter->first); - skillIter++) + ++skillIter) { if(skillIter->second->skillId == achievementCriteria->learn_skilline_spell.skillLine) spellCount++; @@ -605,7 +605,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui { uint32 counter = 0; const FactionStateList factionStateList = GetPlayer()->GetFactionStateList(); - for (FactionStateList::const_iterator iter = factionStateList.begin(); iter!= factionStateList.end(); iter++) + for (FactionStateList::const_iterator iter = factionStateList.begin(); iter!= factionStateList.end(); ++iter) { if(GetPlayer()->ReputationToRank(iter->second.Standing) >= REP_EXALTED) ++counter; diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 1790df0e5..9c165803a 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -39,7 +39,7 @@ BattleGround::BattleGround() m_Status = 0; m_EndTime = 0; m_LastResurrectTime = 0; - m_QueueId = MAX_BATTLEGROUND_QUEUES; + m_QueueId = QUEUE_ID_MAX_LEVEL_19; m_InvitedAlliance = 0; m_InvitedHorde = 0; m_ArenaType = 0; @@ -130,8 +130,6 @@ void BattleGround::Update(uint32 diff) //BG is empty return; - WorldPacket data; - if(GetRemovedPlayersSize()) { for(std::map::iterator itr = m_RemovedPlayers.begin(); itr != m_RemovedPlayers.end(); ++itr) @@ -139,16 +137,6 @@ void BattleGround::Update(uint32 diff) Player *plr = objmgr.GetPlayer(itr->first); switch(itr->second) { - //following code is handled by event: - /*case 0: - sBattleGroundMgr.m_BattleGroundQueues[GetTypeID()].RemovePlayer(itr->first); - //RemovePlayerFromQueue(itr->first); - if(plr) - { - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(m_TypeID), STATUS_NONE, 0, 0); - plr->GetSession()->SendPacket(&data); - } - break;*/ case 1: // currently in bg and was removed from bg if(plr) RemovePlayerAtLeave(itr->first, true, true); @@ -874,7 +862,7 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac // this method is called when no players remains in battleground void BattleGround::Reset() { - SetQueueId(MAX_BATTLEGROUND_QUEUES); + SetQueueId(QUEUE_ID_MAX_LEVEL_19); SetWinner(WINNER_NONE); SetStatus(STATUS_WAIT_QUEUE); SetStartTime(0); @@ -1009,7 +997,7 @@ void BattleGround::AddOrSetPlayerToCorrectBgGroup(Player *plr, uint64 plr_guid, void BattleGround::AddToBGFreeSlotQueue() { // make sure to add only once - if(!m_InBGFreeSlotQueue) + if(!m_InBGFreeSlotQueue && isBattleGround()) { sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].push_front(this); m_InBGFreeSlotQueue = true; @@ -1033,61 +1021,12 @@ void BattleGround::RemoveFromBGFreeSlotQueue() } // get the number of free slots for team -// works in similar way that HasFreeSlotsForTeam did, but this is needed for join as group +// returns the number how many players can join battleground to MaxPlayersPerTeam uint32 BattleGround::GetFreeSlotsForTeam(uint32 Team) const { //if BG is starting ... invite anyone - if (GetStatus() == STATUS_WAIT_JOIN) + if (GetStatus() == STATUS_WAIT_JOIN || GetStatus() == STATUS_IN_PROGRESS) return (GetInvitedCount(Team) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team) : 0; - //if BG is already started .. do not allow to join too much players of one faction - uint32 otherTeam; - uint32 otherIn; - if (Team == ALLIANCE) - { - otherTeam = GetInvitedCount(HORDE); - otherIn = GetPlayersCountByTeam(HORDE); - } - else - { - otherTeam = GetInvitedCount(ALLIANCE); - otherIn = GetPlayersCountByTeam(ALLIANCE); - } - if (GetStatus() == STATUS_IN_PROGRESS) - { - // difference based on ppl invited (not necessarily entered battle) - // default: allow 0 - uint32 diff = 0; - // allow join one person if the sides are equal (to fill up bg to minplayersperteam) - if (otherTeam == GetInvitedCount(Team)) - diff = 1; - // allow join more ppl if the other side has more players - else if(otherTeam > GetInvitedCount(Team)) - diff = otherTeam - GetInvitedCount(Team); - - // difference based on max players per team (don't allow inviting more) - uint32 diff2 = (GetInvitedCount(Team) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team) : 0; - - // difference based on players who already entered - // default: allow 0 - uint32 diff3 = 0; - // allow join one person if the sides are equal (to fill up bg minplayersperteam) - if (otherIn == GetPlayersCountByTeam(Team)) - diff3 = 1; - // allow join more ppl if the other side has more players - else if (otherIn > GetPlayersCountByTeam(Team)) - diff3 = otherIn - GetPlayersCountByTeam(Team); - // or other side has less than minPlayersPerTeam - else if (GetInvitedCount(Team) <= GetMinPlayersPerTeam()) - diff3 = GetMinPlayersPerTeam() - GetInvitedCount(Team) + 1; - - // return the minimum of the 3 differences - - // min of diff and diff 2 - diff = diff < diff2 ? diff : diff2; - - // min of diff, diff2 and diff3 - return diff < diff3 ? diff : diff3 ; - } return 0; } diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index 4590ed839..1d5e5ef4b 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -86,6 +86,7 @@ enum BattleGroundTimeIntervals { RESURRECTION_INTERVAL = 30000, // ms REMIND_INTERVAL = 30000, // ms + INVITATION_REMIND_TIME = 60000, // ms INVITE_ACCEPT_WAIT_TIME = 80000, // ms TIME_TO_AUTOREMOVE = 120000, // ms MAX_OFFLINE_TIME = 300000, // ms @@ -135,16 +136,30 @@ struct BattleGroundObjectInfo // handle the queue types and bg types separately to enable joining queue for different sized arenas at the same time enum BattleGroundQueueTypeId { - BATTLEGROUND_QUEUE_NONE = 0, - BATTLEGROUND_QUEUE_AV = 1, - BATTLEGROUND_QUEUE_WS = 2, - BATTLEGROUND_QUEUE_AB = 3, - BATTLEGROUND_QUEUE_EY = 4, - BATTLEGROUND_QUEUE_SA = 5, - BATTLEGROUND_QUEUE_2v2 = 6, - BATTLEGROUND_QUEUE_3v3 = 7, - BATTLEGROUND_QUEUE_5v5 = 8, + BATTLEGROUND_QUEUE_NONE = 0, + BATTLEGROUND_QUEUE_AV = 1, + BATTLEGROUND_QUEUE_WS = 2, + BATTLEGROUND_QUEUE_AB = 3, + BATTLEGROUND_QUEUE_EY = 4, + BATTLEGROUND_QUEUE_SA = 5, + BATTLEGROUND_QUEUE_2v2 = 6, + BATTLEGROUND_QUEUE_3v3 = 7, + BATTLEGROUND_QUEUE_5v5 = 8 }; +#define MAX_BATTLEGROUND_QUEUE_TYPES 9 + +enum BGQueueIdBasedOnLevel // queue_id for level ranges +{ + QUEUE_ID_MAX_LEVEL_19 = 0, + QUEUE_ID_MAX_LEVEL_29 = 1, + QUEUE_ID_MAX_LEVEL_39 = 2, + QUEUE_ID_MAX_LEVEL_49 = 3, + QUEUE_ID_MAX_LEVEL_59 = 4, + QUEUE_ID_MAX_LEVEL_69 = 5, + QUEUE_ID_MAX_LEVEL_79 = 6, + QUEUE_ID_MAX_LEVEL_80 = 7 +}; +#define MAX_BATTLEGROUND_QUEUES 8 enum ScoreType { @@ -195,7 +210,8 @@ enum BattleGroundWinner enum BattleGroundTeamId { BG_TEAM_ALLIANCE = 0, - BG_TEAM_HORDE = 1 + BG_TEAM_HORDE = 1, + BG_TEAMS_COUNT = 2 }; enum BattleGroundJoinError @@ -255,7 +271,7 @@ class BattleGround // Get methods: char const* GetName() const { return m_Name; } BattleGroundTypeId GetTypeID() const { return m_TypeID; } - uint32 GetQueueId() const { return m_QueueId; } + BGQueueIdBasedOnLevel GetQueueId() const { return m_QueueId; } uint32 GetInstanceID() const { return m_InstanceID; } uint32 GetStatus() const { return m_Status; } uint32 GetStartTime() const { return m_StartTime; } @@ -278,7 +294,13 @@ class BattleGround // Set methods: void SetName(char const* Name) { m_Name = Name; } void SetTypeID(BattleGroundTypeId TypeID) { m_TypeID = TypeID; } - void SetQueueId(uint32 ID) { m_QueueId = ID; } + //here we can count minlevel and maxlevel for players + void SetQueueId(BGQueueIdBasedOnLevel ID) + { + m_QueueId = ID; + uint8 diff = (m_TypeID == BATTLEGROUND_AV) ? 1 : 0; + this->SetLevelRange((ID + 1) * 10 + diff, (ID + 2) * 10 - ((diff + 1) % 2)); + } void SetInstanceID(uint32 InstanceID) { m_InstanceID = InstanceID; } void SetStatus(uint32 Status) { m_Status = Status; } void SetStartTime(uint32 Time) { m_StartTime = Time; } @@ -310,7 +332,6 @@ class BattleGround else return m_InvitedHorde; } - bool HasFreeSlotsForTeam(uint32 Team) const; bool HasFreeSlots() const; uint32 GetFreeSlotsForTeam(uint32 Team) const; @@ -472,7 +493,7 @@ class BattleGround uint32 m_StartTime; uint32 m_EndTime; uint32 m_LastResurrectTime; - uint32 m_QueueId; + BGQueueIdBasedOnLevel m_QueueId; uint8 m_ArenaType; // 2=2v2, 3=3v3, 5=5v5 bool m_InBGFreeSlotQueue; // used to make sure that BG is only once inserted into the BattleGroundMgr.BGFreeSlotQueue[bgTypeId] deque bool m_SetDeleteThis; // used for safe deletion of the bg after end / all players leave @@ -498,15 +519,15 @@ class BattleGround uint32 m_InvitedHorde; /* Raid Group */ - Group *m_BgRaids[2]; // 0 - alliance, 1 - horde + Group *m_BgRaids[BG_TEAMS_COUNT]; // 0 - alliance, 1 - horde /* Players count by team */ - uint32 m_PlayersCount[2]; + uint32 m_PlayersCount[BG_TEAMS_COUNT]; /* Arena team ids by team */ - uint32 m_ArenaTeamIds[2]; + uint32 m_ArenaTeamIds[BG_TEAMS_COUNT]; - int32 m_ArenaTeamRatingChanges[2]; + int32 m_ArenaTeamRatingChanges[BG_TEAMS_COUNT]; /* Limits */ uint32 m_LevelMin; @@ -518,9 +539,9 @@ class BattleGround /* Location */ uint32 m_MapId; - float m_TeamStartLocX[2]; - float m_TeamStartLocY[2]; - float m_TeamStartLocZ[2]; - float m_TeamStartLocO[2]; + float m_TeamStartLocX[BG_TEAMS_COUNT]; + float m_TeamStartLocY[BG_TEAMS_COUNT]; + float m_TeamStartLocZ[BG_TEAMS_COUNT]; + float m_TeamStartLocO[BG_TEAMS_COUNT]; }; #endif diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp index dca996662..df4eee36e 100644 --- a/src/game/BattleGroundHandler.cpp +++ b/src/game/BattleGroundHandler.cpp @@ -78,6 +78,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) uint32 bgTypeId_; uint32 instanceId; uint8 joinAsGroup; + bool isPremade = false; Group * grp; recv_data >> guid; // battlemaster guid @@ -146,6 +147,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) if(!grp) return; uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0); + isPremade = (grp->GetMembersCount() >= bg->GetMinPlayersPerTeam()); if (err != BG_JOIN_ERR_OK) { SendBattleGroundOrArenaJoinError(err); @@ -158,7 +160,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) if(joinAsGroup /* && _player->GetGroup()*/) { sLog.outDebug("Battleground: the following players are joining as group:"); - GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, 0); + GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, isPremade, 0); for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *member = itr->getSource(); @@ -195,7 +197,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); SendPacket(&data); - GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, 0); + GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, false, 0); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId)); if(!ginfo->IsInvitedToBGInstanceGUID) @@ -316,8 +318,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data ) if(!bgQueueTypeId) continue; BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId); - uint32 queue_id = _player->GetBattleGroundQueueIdFromLevel(bgTypeId); - BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[queue_id]; + BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers; BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID()); // if the player is not in queue, continue if(itrPlayerStatus == qpMap.end()) @@ -370,7 +371,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data ) BattleGroundQueueTypeId bgQueueTypeId = BATTLEGROUND_QUEUE_NONE; // get the bg what we were invited to bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId,type); - BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel(bgTypeId)]; + BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers; BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID()); if(itrPlayerStatus == qpMap.end()) { @@ -410,7 +411,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data ) uint32 opponentsRating = 0; // get the team info from the queue - BattleGroundQueue::QueuedPlayersMap& qpMap2 = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel(bgTypeId)]; + BattleGroundQueue::QueuedPlayersMap& qpMap2 = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers; BattleGroundQueue::QueuedPlayersMap::iterator pitr = qpMap2.find(_player->GetGUID()); if (pitr !=qpMap2.end() && pitr->second.GroupInfo) { @@ -546,8 +547,7 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId); uint8 arenatype = BattleGroundMgr::BGArenaType(bgQueueTypeId); uint8 isRated = 0; - uint32 queue_id = _player->GetBattleGroundQueueIdFromLevel(bgTypeId); - BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[queue_id]; + BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers; BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID()); if(itrPlayerStatus == qpMap.end()) continue; @@ -578,9 +578,8 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId); uint8 arenatype = BattleGroundMgr::BGArenaType(bgQueueTypeId); uint8 isRated = 0; - uint32 queue_id = _player->GetBattleGroundQueueIdFromLevel(bgTypeId); BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); - BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[queue_id]; + BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers; BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID()); if(itrPlayerStatus == qpMap.end()) continue; @@ -768,7 +767,7 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data ) if(asGroup) { - GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, arenaRating, ateamId); + GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, false, arenaRating, ateamId); sLog.outDebug("Battleground: arena join as group start"); if(isRated) sLog.outDebug("Battleground: arena team id %u, leader %s queued with rating %u for type %u",_player->GetArenaTeamId(arenaslot),_player->GetName(),arenaRating,arenatype); @@ -807,7 +806,7 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data ) // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated); SendPacket(&data); - GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, arenaRating); + GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, false, arenaRating); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId), arenatype, isRated, arenaRating); sLog.outDebug("Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index 73345aafb..8931c407b 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -52,159 +52,90 @@ INSTANTIATE_SINGLETON_1( BattleGroundMgr ); BattleGroundQueue::BattleGroundQueue() { - //queues are empty, we don't have to call clear() } BattleGroundQueue::~BattleGroundQueue() { + m_QueuedPlayers.clear(); for (int i = 0; i < MAX_BATTLEGROUND_QUEUES; i++) { - m_QueuedPlayers[i].clear(); - for(QueuedGroupsList::iterator itr = m_QueuedGroups[i].begin(); itr!= m_QueuedGroups[i].end(); ++itr) + for(uint32 j = 0; j < BG_QUEUE_GROUP_TYPES_COUNT; j++) { - delete (*itr); - } - m_QueuedGroups[i].clear(); - } -} - -// initialize eligible groups from the given source matching the given specifications -void BattleGroundQueue::EligibleGroups::Init(BattleGroundQueue::QueuedGroupsList *source, BattleGroundTypeId BgTypeId, uint32 side, uint32 MaxPlayers, uint8 ArenaType, bool IsRated, uint32 MinRating, uint32 MaxRating, uint32 DisregardTime, uint32 excludeTeam) -{ - // clear from prev initialization - clear(); - BattleGroundQueue::QueuedGroupsList::iterator itr, next; - // iterate through the source - for(itr = source->begin(); itr!= source->end(); itr = next) - { - next = itr; - ++next; - if( (*itr)->BgTypeId == BgTypeId && // bg type must match - (*itr)->ArenaType == ArenaType && // arena type must match - (*itr)->IsRated == IsRated && // israted must match - (*itr)->IsInvitedToBGInstanceGUID == 0 && // leave out already invited groups - (*itr)->Team == side && // match side - (*itr)->Players.size() <= MaxPlayers && // the group must fit in the bg - ( !excludeTeam || (*itr)->ArenaTeamId != excludeTeam ) && // if excludeTeam is specified, leave out those arena team ids - ( !IsRated || (*itr)->Players.size() == MaxPlayers ) && // if rated, then pass only if the player count is exact NEEDS TESTING! (but now this should never happen) - ( (*itr)->JoinTime <= DisregardTime // pass if disregard time is greater than join time - || (*itr)->ArenaTeamRating == 0 // pass if no rating info - || ( (*itr)->ArenaTeamRating >= MinRating // pass if matches the rating range - && (*itr)->ArenaTeamRating <= MaxRating ) ) ) - { - // the group matches the conditions - // insert it in order of groupsize, and join time - uint32 size = (*itr)->Players.size(); - uint32 jointime = (*itr)->JoinTime; - bool inserted = false; - - for(std::list::iterator elig_itr = begin(); elig_itr != end(); ++elig_itr) - { - // if the next one's size is smaller, then insert - // also insert if the next one's size is equal, but it joined the queue later - if( ((*elig_itr)->Players.size()Players.size() == size && (*elig_itr)->JoinTime > jointime) ) - { - insert(elig_itr,(*itr)); - inserted = true; - break; - } - } - // if not inserted -> this is the smallest group -> push_back - if(!inserted) - { - push_back((*itr)); - } + for(GroupsQueueType::iterator itr = m_QueuedGroups[i][j].begin(); itr!= m_QueuedGroups[i][j].end(); ++itr) + delete (*itr); + m_QueuedGroups[i][j].clear(); } } } -// remove group from eligible groups -// used when building selection pools -void BattleGroundQueue::EligibleGroups::RemoveGroup(GroupQueueInfo * ginfo) -{ - for(std::list::iterator itr = begin(); itr != end(); ++itr) - { - if((*itr)==ginfo) - { - erase(itr); - return; - } - } -} +/*********************************************************/ +/*** BATTLEGROUND QUEUE SELECTION POOLS ***/ +/*********************************************************/ // selection pool initialization, used to clean up from prev selection void BattleGroundQueue::SelectionPool::Init() { SelectedGroups.clear(); - MaxGroup = 0; PlayerCount = 0; } -// get the maximal group from the selection pool -// used when building the pool, and have to remove the largest -GroupQueueInfo * BattleGroundQueue::SelectionPool::GetMaximalGroup() -{ - if(SelectedGroups.empty()) - { - sLog.outError("Getting max group when selection pool is empty, this should never happen."); - MaxGroup = NULL; - return 0; - } - // actually select the max group if it's not set - if(MaxGroup==0 && !SelectedGroups.empty()) - { - uint32 max_size = 0; - for(std::list::iterator itr = SelectedGroups.begin(); itr != SelectedGroups.end(); ++itr) - { - if(max_size<(*itr)->Players.size()) - { - MaxGroup =(*itr); - max_size = MaxGroup->Players.size(); - } - } - } - return MaxGroup; -} - // remove group info from selection pool -// used when building selection pools and have to remove maximal group -void BattleGroundQueue::SelectionPool::RemoveGroup(GroupQueueInfo *ginfo) +// returns true when we need to try to add new group to selection pool +// or false when pool is ok +// sometimes it can be called on empty selection pool +bool BattleGroundQueue::SelectionPool::KickGroup(uint32 size) { - // uninitiate max group info if needed - if(MaxGroup == ginfo) - MaxGroup = 0; - // find what to remove - for(std::list::iterator itr = SelectedGroups.begin(); itr != SelectedGroups.end(); ++itr) + //find maxgroup or LAST group with size == size and kick it + bool found = false; + GroupsQueueType::iterator groupToKick = SelectedGroups.begin(); + for (GroupsQueueType::iterator itr = groupToKick; itr != SelectedGroups.end(); ++itr) { - if((*itr)==ginfo) + if( abs((int32)((*itr)->Players.size() - size)) <= 1 ) { - SelectedGroups.erase(itr); - // decrease selected players count - PlayerCount -= ginfo->Players.size(); - return; + groupToKick = itr; + found = true; } + else if (!found && (*itr)->Players.size() >= (*groupToKick)->Players.size()) + groupToKick = itr; } + //if pool is empty, do nothing + if( GetPlayerCount() ) + { + //update player count + GroupQueueInfo* ginfo = (*groupToKick); + SelectedGroups.erase(groupToKick); + PlayerCount -= ginfo->Players.size(); + if (abs((int32)(ginfo->Players.size() - size)) <= 1) + return false; + } + return true; } -// add group to selection +// add group to selection pool // used when building selection pools -void BattleGroundQueue::SelectionPool::AddGroup(GroupQueueInfo * ginfo) +// returns true if we can invite more players, otherwise return false - (selection pool is set that time) +bool BattleGroundQueue::SelectionPool::AddGroup(GroupQueueInfo *ginfo, uint32 desiredCount) { - SelectedGroups.push_back(ginfo); - // increase selected players count - PlayerCount+=ginfo->Players.size(); - if(!MaxGroup || ginfo->Players.size() > MaxGroup->Players.size()) + //if group is larger than desired count - don't allow to add it to pool + if (!ginfo->IsInvitedToBGInstanceGUID && desiredCount >= PlayerCount + ginfo->Players.size()) { - // update max group info if needed - MaxGroup = ginfo; + SelectedGroups.push_back(ginfo); + // increase selected players count + PlayerCount += ginfo->Players.size(); } + if (PlayerCount == desiredCount) + return true; + return false; } +/*********************************************************/ +/*** BATTLEGROUND QUEUES ***/ +/*********************************************************/ + // add group to bg queue with the given leader and bg specifications -GroupQueueInfo * BattleGroundQueue::AddGroup(Player *leader, BattleGroundTypeId BgTypeId, uint8 ArenaType, bool isRated, uint32 arenaRating, uint32 arenateamid) +GroupQueueInfo * BattleGroundQueue::AddGroup(Player *leader, BattleGroundTypeId BgTypeId, uint8 ArenaType, bool isRated, bool isPremade, uint32 arenaRating, uint32 arenateamid) { - uint32 queue_id = leader->GetBattleGroundQueueIdFromLevel(BgTypeId); + BGQueueIdBasedOnLevel queue_id = leader->GetBattleGroundQueueIdFromLevel(BgTypeId); // create new ginfo // cannot use the method like in addplayer, because that could modify an in-queue group's stats @@ -214,26 +145,33 @@ GroupQueueInfo * BattleGroundQueue::AddGroup(Player *leader, BattleGroundTypeId ginfo->ArenaType = ArenaType; ginfo->ArenaTeamId = arenateamid; ginfo->IsRated = isRated; - ginfo->IsInvitedToBGInstanceGUID = 0; // maybe this should be modifiable by function arguments to enable selection of running instances? + ginfo->IsInvitedToBGInstanceGUID = 0; ginfo->JoinTime = getMSTime(); ginfo->Team = leader->GetTeam(); ginfo->ArenaTeamRating = arenaRating; - ginfo->OpponentsTeamRating = 0; //initialize it to 0 + ginfo->OpponentsTeamRating = 0; ginfo->Players.clear(); - m_QueuedGroups[queue_id].push_back(ginfo); + //compute index (if group is premade or joined a rated match) to queues + uint32 index = 0; + if(!isRated && !isPremade) + index += BG_TEAMS_COUNT; + if(ginfo->Team == HORDE) + index++; + sLog.outDebug("Adding Group to BattleGroundQueue bgTypeId : %u, queue_id : %u, index : %u", BgTypeId, queue_id, index); + + m_QueuedGroups[queue_id][index].push_back(ginfo); // return ginfo, because it is needed to add players to this group info return ginfo; } +//add player to playermap void BattleGroundQueue::AddPlayer(Player *plr, GroupQueueInfo *ginfo) { - uint32 queue_id = plr->GetBattleGroundQueueIdFromLevel(ginfo->BgTypeId); - //if player isn't in queue, he is added, if already is, then values are overwritten, no memory leak - PlayerQueueInfo& info = m_QueuedPlayers[queue_id][plr->GetGUID()]; + PlayerQueueInfo& info = m_QueuedPlayers[plr->GetGUID()]; info.InviteTime = 0; info.LastInviteTime = 0; info.LastOnlineTime = getMSTime(); @@ -243,112 +181,112 @@ void BattleGroundQueue::AddPlayer(Player *plr, GroupQueueInfo *ginfo) ginfo->Players[plr->GetGUID()] = &info; } +//remove player from queue and from group info, if group info is empty then remove it too void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCount) { - Player *plr = objmgr.GetPlayer(guid); + //Player *plr = objmgr.GetPlayer(guid); - int32 queue_id = 0; // signed for proper for-loop finish + int32 queue_id = -1; // signed for proper for-loop finish QueuedPlayersMap::iterator itr; - // mostly people with the highest levels are in battlegrounds, thats why - // we count from MAX_BATTLEGROUND_QUEUES to 0 - for (queue_id = MAX_BATTLEGROUND_QUEUES-1; queue_id >= 0; queue_id--) + //remove player from map, if he's there + itr = m_QueuedPlayers.find(guid); + if( itr == m_QueuedPlayers.end() ) { - itr = m_QueuedPlayers[queue_id].find(guid); - if(itr != m_QueuedPlayers[queue_id].end()) - break; - } - - // couldn't find the player in bg queue, return - if(queue_id == -1) - { - sLog.outError("Battleground: couldn't find player to remove."); + sLog.outError("BattleGroundQueue: couldn't find player to remove GUID: %u", GUID_LOPART(guid)); return; } GroupQueueInfo* group = itr->second.GroupInfo; - - QueuedGroupsList::iterator group_itr = m_QueuedGroups[queue_id].begin(); - for(; group_itr != m_QueuedGroups[queue_id].end(); ++group_itr) + GroupsQueueType::iterator group_itr, group_itr_tmp; + // mostly people with the highest levels are in battlegrounds, thats why + // we count from MAX_BATTLEGROUND_QUEUES - 1 to 0 + // variable index removes useless searching in other team's queue + uint32 index = (group->Team == HORDE) ? BG_TEAM_HORDE : BG_TEAM_ALLIANCE; + for (int32 queue_id_tmp = MAX_BATTLEGROUND_QUEUES - 1; queue_id_tmp >= 0 && queue_id == -1; queue_id_tmp--) { - if(group == *group_itr) - break; + //we must check premade and normal team's queue - because when players from premade are joining bg, they leave groupinfo so we can't use its players size to find out index + for (uint32 j = 0; j < 3; j += BG_QUEUE_NORMAL_ALLIANCE) + { + for(group_itr_tmp = m_QueuedGroups[queue_id_tmp][index + j].begin(); group_itr_tmp != m_QueuedGroups[queue_id_tmp][index + j].end(); ++group_itr_tmp) + { + if( (*group_itr_tmp) == group ) + { + queue_id = queue_id_tmp; + group_itr = group_itr_tmp; + //we must store index to be able to erase iterator + index += j; + break; + } + } + } } + //player can't be in queue without group, but just in case + if( queue_id == -1 ) + { + sLog.outError("BattleGroundQueue: ERROR Cannot find groupinfo for player GUID: %u", GUID_LOPART(guid)); + return; + } + sLog.outDebug("BattleGroundQueue: Removing player GUID %u, from queue_id %u", GUID_LOPART(guid), (uint32)queue_id); - // variables are set (what about leveling up when in queue???? - // iterate through all queue_ids this isn't bad for us) + // ALL variables are corrcetly set + // We can ignore leveling up in queue - it should not cause crash // remove player from group - // if only player there, remove group + // if only one player there, remove group // remove player queue info from group queue info std::map::iterator pitr = group->Players.find(guid); - - if(pitr != group->Players.end()) + if( pitr != group->Players.end() ) group->Players.erase(pitr); - // check for iterator correctness - if (group_itr != m_QueuedGroups[queue_id].end() && itr != m_QueuedPlayers[queue_id].end()) + // if invited to bg, and should decrease invited count, then do it + if( decreaseInvitedCount && group->IsInvitedToBGInstanceGUID ) { - // used when player left the queue, NOT used when porting to bg - if (decreaseInvitedCount) - { - // if invited to bg, and should decrease invited count, then do it - if(group->IsInvitedToBGInstanceGUID) - { - BattleGround* bg = sBattleGroundMgr.GetBattleGround(group->IsInvitedToBGInstanceGUID); - if (bg) - bg->DecreaseInvitedCount(group->Team); - if (bg && !bg->GetPlayersSize() && !bg->GetInvitedCount(ALLIANCE) && !bg->GetInvitedCount(HORDE)) - { - // no more players on battleground, set delete it - bg->SetDeleteThis(); - } - } - // update the join queue, maybe now the player's group fits in a queue! - // not yet implemented (should store bgTypeId in group queue info?) - } - // remove player queue info - m_QueuedPlayers[queue_id].erase(itr); - // remove group queue info if needed + BattleGround* bg = sBattleGroundMgr.GetBattleGround(group->IsInvitedToBGInstanceGUID); + if( bg ) + bg->DecreaseInvitedCount(group->Team); + } - //if we left BG queue(not porting) OR if arena team left queue for rated match - if((decreaseInvitedCount && !group->ArenaType) || (group->ArenaType && group->IsRated && group->Players.empty())) - AnnounceWorld(group, guid, false); + // remove player queue info + m_QueuedPlayers.erase(itr); - if(group->Players.empty()) + //if we left BG queue(not porting) OR if arena team left queue for rated match + if( (decreaseInvitedCount && !group->ArenaType) || (group->ArenaType && group->IsRated && group->Players.empty()) ) + AnnounceWorld(group, guid, false); + + // remove group queue info if needed + if( group->Players.empty() ) + { + m_QueuedGroups[queue_id][index].erase(group_itr); + delete group; + } + // if group wasn't empty, so it wasn't deleted, and player have left a rated queue -> everyone from the group should leave too + // don't remove recursively if already invited to bg! + else if( !group->IsInvitedToBGInstanceGUID && group->IsRated ) + { + // remove next player, this is recursive + // first send removal information + if(Player *plr2 = objmgr.GetPlayer(group->Players.begin()->first)) { - m_QueuedGroups[queue_id].erase(group_itr); - delete group; - } - // NEEDS TESTING! - // group wasn't empty, so it wasn't deleted, and player have left a rated queue -> everyone from the group should leave too - // don't remove recursively if already invited to bg! - else if(!group->IsInvitedToBGInstanceGUID && decreaseInvitedCount && group->IsRated) - { - // remove next player, this is recursive - // first send removal information - if(Player *plr2 = objmgr.GetPlayer(group->Players.begin()->first)) - { - BattleGround * bg = sBattleGroundMgr.GetBattleGroundTemplate(group->BgTypeId); - BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(group->BgTypeId,group->ArenaType); - uint32 queueSlot = plr2->GetBattleGroundQueueIndex(bgQueueTypeId); - plr2->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs - WorldPacket data; - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr2->GetTeam(), queueSlot, STATUS_NONE, 0, 0); - plr2->GetSession()->SendPacket(&data); - } - // then actually delete, this may delete the group as well! - RemovePlayer(group->Players.begin()->first,decreaseInvitedCount); + BattleGround * bg = sBattleGroundMgr.GetBattleGroundTemplate(group->BgTypeId); + BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(group->BgTypeId, group->ArenaType); + uint32 queueSlot = plr2->GetBattleGroundQueueIndex(bgQueueTypeId); + plr2->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs + WorldPacket data; + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr2->GetTeam(), queueSlot, STATUS_NONE, 0, 0); + plr2->GetSession()->SendPacket(&data); } + // then actually delete, this may delete the group as well! + RemovePlayer(group->Players.begin()->first, decreaseInvitedCount); } } +//Announce world message void BattleGroundQueue::AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playerGUID, bool isAddedToQueue) { - if(ginfo->ArenaType) //if Arena { - if( sWorld.getConfig(CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE) && ginfo->IsRated) + if( sWorld.getConfig(CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE) && ginfo->IsRated ) { BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(ginfo->BgTypeId); if(!bg) @@ -366,57 +304,35 @@ void BattleGroundQueue::AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playe if( sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE) ) { Player *plr = objmgr.GetPlayer(playerGUID); - if(!plr) - return; - BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(ginfo->BgTypeId); - if(!bg) + if(!bg || !plr) return; - uint32 queue_id = plr->GetBattleGroundQueueIdFromLevel(bg->GetTypeID()); + BGQueueIdBasedOnLevel queue_id = plr->GetBattleGroundQueueIdFromLevel(bg->GetTypeID()); char const* bgName = bg->GetName(); - - uint32 q_min_level = Player::GetMinLevelForBattleGroundQueueId(queue_id, ginfo->BgTypeId); - uint32 q_max_level = Player::GetMaxLevelForBattleGroundQueueId(queue_id, ginfo->BgTypeId); - - // replace hardcoded max level by player max level for nice output - if(q_max_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) - q_max_level = sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); - - int8 MinPlayers = bg->GetMinPlayersPerTeam(); - - uint8 qHorde = 0; - uint8 qAlliance = 0; - - BattleGroundTypeId bgTypeId = ginfo->BgTypeId; - QueuedPlayersMap::iterator itr; - for(itr = m_QueuedPlayers[queue_id].begin(); itr!= m_QueuedPlayers[queue_id].end(); ++itr) - { - if(itr->second.GroupInfo->BgTypeId == bgTypeId) - { - switch(itr->second.GroupInfo->Team) - { - case HORDE: - qHorde++; break; - case ALLIANCE: - qAlliance++; break; - default: - break; - } - } - } + uint32 MinPlayers = bg->GetMinPlayersPerTeam(); + uint32 qHorde = 0; + uint32 qAlliance = 0; + uint32 q_min_level = (queue_id + 1) * 10; + GroupsQueueType::const_iterator itr; + for(itr = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE].begin(); itr != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE].end(); ++itr) + if( !(*itr)->IsInvitedToBGInstanceGUID ) + qAlliance += (*itr)->Players.size(); + for(itr = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_HORDE].begin(); itr != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_HORDE].end(); ++itr) + if( !(*itr)->IsInvitedToBGInstanceGUID ) + qHorde += (*itr)->Players.size(); // Show queue status to player only (when joining queue) - if(sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY)) + if( sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY) ) { ChatHandler(plr).PSendSysMessage(LANG_BG_QUEUE_ANNOUNCE_SELF, - bgName, q_min_level, q_max_level, qAlliance, MinPlayers, qHorde, MinPlayers); + bgName, q_min_level, q_min_level + 10, qAlliance, MinPlayers, qHorde, MinPlayers); } // System message else { sWorld.SendWorldText(LANG_BG_QUEUE_ANNOUNCE_WORLD, - bgName, q_min_level, q_max_level, qAlliance, MinPlayers, qHorde, MinPlayers); + bgName, q_min_level, q_min_level + 10, qAlliance, MinPlayers, qHorde, MinPlayers); } } } @@ -425,10 +341,10 @@ void BattleGroundQueue::AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playe bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * bg, uint32 side) { // set side if needed - if(side) + if( side ) ginfo->Team = side; - if(!ginfo->IsInvitedToBGInstanceGUID) + if( !ginfo->IsInvitedToBGInstanceGUID ) { // not yet invited // set invitation @@ -443,12 +359,12 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b // get the player Player* plr = objmgr.GetPlayer(itr->first); - // if offline, skip him - if(!plr) + // if offline, skip him, this should not happen - player is removed from queue when he logs out + if( !plr ) continue; // invite the player - sBattleGroundMgr.InvitePlayer(plr, bg->GetInstanceID(),ginfo->Team); + sBattleGroundMgr.InvitePlayer(plr, bg->GetInstanceID(), ginfo->Team); WorldPacket data; @@ -466,113 +382,56 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b return false; } -// this function is responsible for the selection of queued groups when trying to create new battlegrounds -bool BattleGroundQueue::BuildSelectionPool(BattleGroundTypeId bgTypeId, uint32 queue_id, uint32 MinPlayers, uint32 MaxPlayers, SelectionPoolBuildMode mode, uint8 ArenaType, bool isRated, uint32 MinRating, uint32 MaxRating, uint32 DisregardTime, uint32 excludeTeam) -{ - uint32 side; - switch(mode) - { - case NORMAL_ALLIANCE: - case ONESIDE_ALLIANCE_TEAM1: - case ONESIDE_ALLIANCE_TEAM2: - side = ALLIANCE; - break; - case NORMAL_HORDE: - case ONESIDE_HORDE_TEAM1: - case ONESIDE_HORDE_TEAM2: - side = HORDE; - break; - default: - //unknown mode, return false - sLog.outDebug("Battleground: unknown selection pool build mode, returning..."); - return false; - } - - // inititate the groups eligible to create the bg - m_EligibleGroups.Init(&(m_QueuedGroups[queue_id]), bgTypeId, side, MaxPlayers, ArenaType, isRated, MinRating, MaxRating, DisregardTime, excludeTeam); - // init the selected groups (clear) - m_SelectionPools[mode].Init(); - while(!(m_EligibleGroups.empty())) - { - sLog.outDebug("m_EligibleGroups is not empty, continue building selection pool"); - // in decreasing group size, add groups to join if they fit in the MaxPlayersPerTeam players - for(EligibleGroups::iterator itr= m_EligibleGroups.begin(); itr!=m_EligibleGroups.end(); ++itr) - { - // get the maximal not yet checked group - GroupQueueInfo * MaxGroup = (*itr); - // if it fits in the maxplayer size, add it - if( (m_SelectionPools[mode].GetPlayerCount() + MaxGroup->Players.size()) <= MaxPlayers ) - { - m_SelectionPools[mode].AddGroup(MaxGroup); - } - } - if(m_SelectionPools[mode].GetPlayerCount()>=MinPlayers) - { - // the selection pool is set, return - sLog.outDebug("pool build succeeded, return true"); - return true; - } - // if the selection pool's not set, then remove the group with the highest player count, and try again with the rest. - GroupQueueInfo * MaxGroup = m_SelectionPools[mode].GetMaximalGroup(); - m_EligibleGroups.RemoveGroup(MaxGroup); - m_SelectionPools[mode].RemoveGroup(MaxGroup); - } - // failed to build a selection pool matching the given values - return false; -} - -// used to remove the Enter Battle window if the battle has already, but someone still has it +// used to remove the Enter Battle window if the battle has already ended, but someone still has it // (this can happen in arenas mainly, since the preparation is shorter than the timer for the bgqueueremove event void BattleGroundQueue::BGEndedRemoveInvites(BattleGround *bg) { - uint32 queue_id = bg->GetQueueId(); + BGQueueIdBasedOnLevel queue_id = bg->GetQueueId(); uint32 bgInstanceId = bg->GetInstanceID(); BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); - QueuedGroupsList::iterator itr, next; - for(itr = m_QueuedGroups[queue_id].begin(); itr != m_QueuedGroups[queue_id].end(); itr = next) + GroupsQueueType::iterator itr, next; + for(uint32 i = 0; i < BG_QUEUE_GROUP_TYPES_COUNT; i++) { - // must do this way, because the groupinfo will be deleted when all playerinfos are removed - GroupQueueInfo * ginfo = (*itr); - next = itr; - ++next; - // if group was invited to this bg instance, then remove all references - if(ginfo->IsInvitedToBGInstanceGUID == bgInstanceId) + for(itr = m_QueuedGroups[queue_id][i].begin(); itr != m_QueuedGroups[queue_id][i].end(); itr = next) { - // after removing this much playerinfos, the ginfo will be deleted, so we'll use a for loop - uint32 to_remove = ginfo->Players.size(); - uint32 team = ginfo->Team; - for(int i = 0; i < to_remove; ++i) + // must do this way, because the groupinfo will be deleted when all playerinfos are removed + GroupQueueInfo * ginfo = (*itr); + next = itr; + ++next; + // if group was invited to this bg instance, then remove all references + if( ginfo->IsInvitedToBGInstanceGUID == bgInstanceId ) { - // always remove the first one in the group - std::map::iterator itr2 = ginfo->Players.begin(); - if(itr2 == ginfo->Players.end()) + // after removing this much playerinfos, the ginfo will be deleted, so we'll use a for loop + uint32 to_remove = ginfo->Players.size(); + uint32 team = ginfo->Team; + for(uint32 j = 0; j < to_remove; j++) { - sLog.outError("Empty Players in ginfo, this should never happen!"); - return; - } + // always remove the first one in the group + std::map::iterator itr2 = ginfo->Players.begin(); + if( itr2 == ginfo->Players.end() ) + { + sLog.outError("Empty Players in ginfo, this should never happen!"); + return; + } + // get the player + Player * plr = objmgr.GetPlayer(itr2->first); + if( !plr ) + { + sLog.outError("Player offline when trying to remove from GroupQueueInfo, this should never happen."); + continue; + } - // get the player - Player * plr = objmgr.GetPlayer(itr2->first); - if(!plr) - { - sLog.outError("Player offline when trying to remove from GroupQueueInfo, this should never happen."); - continue; - } - - // get the queueslot - uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId); - if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue - { - plr->RemoveBattleGroundQueueId(bgQueueTypeId); - // remove player from queue, this might delete the ginfo as well! don't use that pointer after this! - RemovePlayer(itr2->first, true); - // this is probably unneeded, since this player was already invited -> does not fit when initing eligible groups - // but updateing the queue can't hurt - Update(bg->GetTypeID(), bg->GetQueueId()); - // send info to client - WorldPacket data; - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, team, queueSlot, STATUS_NONE, 0, 0); - plr->GetSession()->SendPacket(&data); + // get the queueslot + uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId); + if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue + { + plr->RemoveBattleGroundQueueId(bgQueueTypeId); + // remove player from queue, this might delete the ginfo as well! don't use that pointer after this! + RemovePlayer(itr2->first, true); + WorldPacket data; + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, team, queueSlot, STATUS_NONE, 0, 0); + plr->GetSession()->SendPacket(&data); + } } } } @@ -580,55 +439,230 @@ void BattleGroundQueue::BGEndedRemoveInvites(BattleGround *bg) } /* -this method is called when group is inserted, or player / group is removed from BG Queue - there is only one player's status changed, so we don't use while(true) cycles to invite whole queue -it must be called after fully adding the members of a group to ensure group joining -should be called after removeplayer functions in some cases +This function is inviting players to already running battlegrounds +Invitation type is based on config file +large groups are disadvantageous, because they will be kicked first if invitation type = 1 */ -void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, uint32 queue_id, uint8 arenatype, bool isRated, uint32 arenaRating) +void BattleGroundQueue::FillPlayersToBG(BattleGround* bg, BGQueueIdBasedOnLevel queue_id) { - if (queue_id >= MAX_BATTLEGROUND_QUEUES) - { - //this is error, that caused crashes (not in , but now it shouldn't) - sLog.outError("BattleGroundQueue::Update() called for non existing queue type - this can cause crash, pls report problem, if this is the last line of error log before crash"); + uint32 hordeFree = bg->GetFreeSlotsForTeam(HORDE); + uint32 aliFree = bg->GetFreeSlotsForTeam(ALLIANCE); + + //iterator for iterating through bg queue + GroupsQueueType::const_iterator Ali_itr = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE].begin(); + //count of groups in queue - used to stop cycles + uint32 aliCount = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE].size(); + //index to queue which group is current + uint32 aliIndex = 0; + for (; aliIndex < aliCount && m_SelectionPools[BG_TEAM_ALLIANCE].AddGroup((*Ali_itr), aliFree); aliIndex++) + ++Ali_itr; + //the same thing for horde + GroupsQueueType::const_iterator Horde_itr = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_HORDE].begin(); + uint32 hordeCount = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_HORDE].size(); + uint32 hordeIndex = 0; + for (; hordeIndex < hordeCount && m_SelectionPools[BG_TEAM_HORDE].AddGroup((*Horde_itr), hordeFree); hordeIndex++) + ++Horde_itr; + + //if ofc like BG queue invitation is set in config, then we are happy + if (sWorld.getConfig(CONFIG_BATTLEGROUND_INVITATION_TYPE) == 0) return; + + /* + if we reached this code, then we have to solve NP - complete problem called Subset sum problem + So one solution is to check all possible invitation subgroups, or we can use these conditions: + 1. Last time when BattleGroundQueue::Update was executed we invited all possible players - so there is only small possibility + that we will invite now whole queue, because only 1 change has been made to queues from the last BattleGroundQueue::Update call + 2. Other thing we should consider is group order in queue + */ + + // At first we need to compare free space in bg and our selection pool + int32 diffAli = aliFree - m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount(); + int32 diffHorde = hordeFree - m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount(); + while( abs(diffAli - diffHorde) > 1 && (m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() > 0 || m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() > 0) ) + { + //each cycle execution we need to kick at least 1 group + if( diffAli < diffHorde ) + { + //kick alliance group, add to pool new group if needed + if( m_SelectionPools[BG_TEAM_ALLIANCE].KickGroup(diffHorde - diffAli) ) + { + for (; aliIndex < aliCount && m_SelectionPools[BG_TEAM_ALLIANCE].AddGroup((*Ali_itr), (aliFree >= diffHorde) ? aliFree - diffHorde : 0); aliIndex++) + ++Ali_itr; + } + //if ali selection is already empty, then kick horde group, but if there are less horde than ali in bg - break; + if( !m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() ) + if( aliFree <= diffHorde - 1 ) + break; + m_SelectionPools[BG_TEAM_HORDE].KickGroup(diffHorde - diffAli); + } + else + { + //kick horde group, add to pool new group if needed + if( m_SelectionPools[BG_TEAM_HORDE].KickGroup(diffAli - diffHorde) ) + { + for (; hordeIndex < hordeCount && m_SelectionPools[BG_TEAM_HORDE].AddGroup((*Horde_itr), (hordeFree >= diffAli) ? hordeFree - diffAli : 0); hordeIndex++) + ++Horde_itr; + } + if( !m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() ) + if( hordeFree <= diffAli - 1 ) + break; + m_SelectionPools[BG_TEAM_ALLIANCE].KickGroup(diffAli - diffHorde); + } + //count diffs after small update + diffAli = aliFree - m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount(); + diffHorde = hordeFree - m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount(); + } +} + +// this method checks if premade versus premade battleground is possible +// then after 30 mins (default) in queue it moves premade group to normal queue +// it tries to invite as much players as it can - to MaxPlayersPerTeam, because premade groups have more than MinPlayersPerTeam players +bool BattleGroundQueue::CheckPremadeMatch(BGQueueIdBasedOnLevel queue_id, uint32 MaxPlayersPerTeam, uint32 MinPlayersPerTeam) +{ + //check match + if(!m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].empty() && !m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].empty()) + { + //start premade match + //if groups aren't invited + GroupsQueueType::const_iterator ali_group, horde_group; + for( ali_group = m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].begin(); ali_group != m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].end(); ++ali_group) + if( !(*ali_group)->IsInvitedToBGInstanceGUID ) + break; + for( horde_group = m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].begin(); horde_group != m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].end(); ++horde_group) + if( !(*horde_group)->IsInvitedToBGInstanceGUID ) + break; + + if( ali_group != m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].end() && horde_group != m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].end()) + { + m_SelectionPools[BG_TEAM_ALLIANCE].AddGroup((*ali_group), MaxPlayersPerTeam); + m_SelectionPools[BG_TEAM_HORDE].AddGroup((*horde_group), MaxPlayersPerTeam); + //add groups/players from normal queue to size of bigger group + uint32 maxPlayers = std::max(m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount(), m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount()); + GroupsQueueType::const_iterator itr; + for(uint32 i = 0; i < BG_TEAMS_COUNT; i++) + { + for(itr = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + i].begin(); itr != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + i].end(); ++itr) + { + if( !(*itr)->IsInvitedToBGInstanceGUID && m_SelectionPools[i].AddGroup((*itr), maxPlayers) ) + break; + } + } + //premade selection pools are set + return true; + } + } + // now check if we can move group from Premade queue to normal queue (timer has expired) or group size lowered!! + // this could be 2 cycles but i'm checking only first team in queue - it can cause problem - + // if first is invited to BG and seconds timer expired, but we can ignore it, because players have only 80 seconds to click to enter bg + // and when they click or after 80 seconds the queue info is removed from queue + uint32 time_before = getMSTime() - sWorld.getConfig(CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH); + for(uint32 i = 0; i < BG_TEAMS_COUNT; i++) + { + if(!m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE + i].empty()) + { + GroupsQueueType::iterator itr = m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE + i].begin(); + if(!(*itr)->IsInvitedToBGInstanceGUID && ((*itr)->JoinTime < time_before || (*itr)->Players.size() < MinPlayersPerTeam)) + { + //we must insert group to normal queue and erase pointer from premade queue + m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + i].push_front((*itr)); + m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE + i].erase(itr); //pop_front(); + } + } + } + //selection pools are not set + return false; +} + +//this function tries to create battleground or arena with MinPlayersPerTeam against MinPlayersPerTeam +bool BattleGroundQueue::CheckNormalMatch(BattleGround* bg_template, BGQueueIdBasedOnLevel queue_id, uint32 MinPlayersPerTeam) +{ + uint32 minPlayers = bg_template->GetMinPlayersPerTeam(); + uint32 maxPlayers = bg_template->GetMaxPlayersPerTeam(); + + GroupsQueueType::const_iterator itr_team[BG_TEAMS_COUNT]; + for(uint32 i = 0; i < BG_TEAMS_COUNT; i++) + { + itr_team[i] = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + i].begin(); + for(; itr_team[i] != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + i].end(); ++(itr_team[i])) + { + if( !(*(itr_team[i]))->IsInvitedToBGInstanceGUID ) + { + m_SelectionPools[i].AddGroup(*(itr_team[i]), maxPlayers); + if( m_SelectionPools[i].GetPlayerCount() >= minPlayers ) + break; + } + } + } + //try to invite same number of players - this cycle may cause longer wait time even if there are enough players in queue, but we want ballanced bg + uint32 j = BG_TEAM_ALLIANCE; + if( m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() < m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() ) + j = BG_TEAM_HORDE; + if( sWorld.getConfig(CONFIG_BATTLEGROUND_INVITATION_TYPE) != 0 + && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() >= minPlayers && m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() >= minPlayers ) + { + //we will try to invite more groups to team with less players indexed by j + ++(itr_team[j]); //this will not cause a crash, because for cycle above reached break; + for(; itr_team[j] != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + j].end(); ++(itr_team[j])) + { + if( !(*(itr_team[j]))->IsInvitedToBGInstanceGUID ) + if( m_SelectionPools[j].AddGroup(*(itr_team[j]), m_SelectionPools[(j + 1) % BG_TEAMS_COUNT].GetPlayerCount()) ) + break; + } + // do not allow to start bg with more than 2 players more on 1 faction + if( abs((int32)(m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() - m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount())) > 2 ) + return false; } - //if no players in queue ... do nothing - if (m_QueuedGroups[queue_id].empty()) + //return true if there are enough players in selection pools - enable to work .debug bg command correctly + return m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() >= MinPlayersPerTeam && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() >= MinPlayersPerTeam; +} + +/* +this method is called when group is inserted, or player / group is removed from BG Queue - there is only one player's status changed, so we don't use while(true) cycles to invite whole queue +it must be called after fully adding the members of a group to ensure group joining +should be called from BattleGround::RemovePlayer function in some cases +*/ +void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id, uint8 arenaType, bool isRated, uint32 arenaRating) +{ + // this can happen when removing last player from battleground + if( queue_id == MAX_BATTLEGROUND_QUEUES ) return; - BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, arenatype); + //if no players in queue ... do nothing + if( m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].empty() && m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].empty() && m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE].empty() && m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_HORDE].empty() ) + return; - //battleground with free slot for player should be always the last in this queue + BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, arenaType); + + //battleground with free slot for player should be always in the beggining of the queue + // maybe it would be better to create bgfreeslotqueue for each queue_id_based_on_level BGFreeSlotQueueType::iterator itr, next; for (itr = sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].end(); itr = next) { next = itr; ++next; - // battleground is running, so if: - // DO NOT allow queue manager to invite new player to running arena - if ((*itr)->isBattleGround() && (*itr)->GetTypeID() == bgTypeId && (*itr)->GetQueueId() == queue_id && (*itr)->GetStatus() > STATUS_WAIT_QUEUE && (*itr)->GetStatus() < STATUS_WAIT_LEAVE) + // DO NOT allow queue manager to invite new player to arena + if( (*itr)->isBattleGround() && (*itr)->GetTypeID() == bgTypeId && (*itr)->GetQueueId() == queue_id && (*itr)->GetStatus() > STATUS_WAIT_QUEUE && (*itr)->GetStatus() < STATUS_WAIT_LEAVE ) { - //we must check both teams BattleGround* bg = *itr; //we have to store battleground pointer here, because when battleground is full, it is removed from free queue (not yet implemented!!) // and iterator is invalid - for(QueuedGroupsList::iterator itr = m_QueuedGroups[queue_id].begin(); itr != m_QueuedGroups[queue_id].end(); ++itr) - { - // did the group join for this bg type? - if((*itr)->BgTypeId != bgTypeId) - continue; - // if so, check if fits in - if(bg->GetFreeSlotsForTeam((*itr)->Team) >= (*itr)->Players.size()) - { - // if group fits in, invite it - InviteGroupToBG((*itr),bg,(*itr)->Team); - } - } + // clear selection pools + m_SelectionPools[BG_TEAM_ALLIANCE].Init(); + m_SelectionPools[BG_TEAM_HORDE].Init(); - if (!bg->HasFreeSlots()) + // call a function that does the job for us + FillPlayersToBG(bg, queue_id); + + // now everything is set, invite players + for(GroupsQueueType::const_iterator itr = m_SelectionPools[BG_TEAM_ALLIANCE].SelectedGroups.begin(); itr != m_SelectionPools[BG_TEAM_ALLIANCE].SelectedGroups.end(); ++itr) + InviteGroupToBG((*itr), bg, (*itr)->Team); + for(GroupsQueueType::const_iterator itr = m_SelectionPools[BG_TEAM_HORDE].SelectedGroups.begin(); itr != m_SelectionPools[BG_TEAM_HORDE].SelectedGroups.end(); ++itr) + InviteGroupToBG((*itr), bg, (*itr)->Team); + + if( !bg->HasFreeSlots() ) { - //remove BG from BGFreeSlotQueue + // remove BG from BGFreeSlotQueue bg->RemoveFromBGFreeSlotQueue(); } } @@ -637,25 +671,29 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, uint32 queue_id, uin // finished iterating through the bgs with free slots, maybe we need to create a new bg BattleGround * bg_template = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); - if(!bg_template) + if( !bg_template ) { sLog.outError("Battleground: Update: bg template not found for %u", bgTypeId); return; } - // get the min. players per team, properly for larger arenas as well. (must have full teams for arena matches!) uint32 MinPlayersPerTeam = bg_template->GetMinPlayersPerTeam(); uint32 MaxPlayersPerTeam = bg_template->GetMaxPlayersPerTeam(); - if(bg_template->isArena()) + if( sBattleGroundMgr.isTesting() ) + MinPlayersPerTeam = 1; + if( bg_template->isArena() ) { - if(sBattleGroundMgr.isArenaTesting()) + if( sBattleGroundMgr.isArenaTesting() ) { MaxPlayersPerTeam = 1; MinPlayersPerTeam = 1; } else { - switch(arenatype) + //this switch can be much shorter + MaxPlayersPerTeam = arenaType; + MinPlayersPerTeam = arenaType; + /*switch(arenaType) { case ARENA_TYPE_2v2: MaxPlayersPerTeam = 2; @@ -669,292 +707,189 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, uint32 queue_id, uin MaxPlayersPerTeam = 5; MinPlayersPerTeam = 5; break; - } - } - } - // BG case - else - { - if(sBattleGroundMgr.isTesting()) - { - MinPlayersPerTeam = 1; + }*/ } } - // found out the minimum and maximum ratings the newly added team should battle against - // arenaRating is the rating of the latest joined team - uint32 arenaMinRating = (arenaRating <= sBattleGroundMgr.GetMaxRatingDifference()) ? 0 : arenaRating - sBattleGroundMgr.GetMaxRatingDifference(); - // if no rating is specified, set maxrating to 0 - uint32 arenaMaxRating = (arenaRating == 0)? 0 : arenaRating + sBattleGroundMgr.GetMaxRatingDifference(); - uint32 discardTime = 0; - // if max rating difference is set and the time past since server startup is greater than the rating discard time - // (after what time the ratings aren't taken into account when making teams) then - // the discard time is current_time - time_to_discard, teams that joined after that, will have their ratings taken into account - // else leave the discard time on 0, this way all ratings will be discarded - if(sBattleGroundMgr.GetMaxRatingDifference() && getMSTime() >= sBattleGroundMgr.GetRatingDiscardTimer()) - discardTime = getMSTime() - sBattleGroundMgr.GetRatingDiscardTimer(); + m_SelectionPools[BG_TEAM_ALLIANCE].Init(); + m_SelectionPools[BG_TEAM_HORDE].Init(); - // try to build the selection pools - bool bAllyOK = BuildSelectionPool(bgTypeId, queue_id, MinPlayersPerTeam, MaxPlayersPerTeam, NORMAL_ALLIANCE, arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime); - if(bAllyOK) - sLog.outDebug("Battleground: ally pool succesfully build"); - else - sLog.outDebug("Battleground: ally pool wasn't created"); - bool bHordeOK = BuildSelectionPool(bgTypeId, queue_id, MinPlayersPerTeam, MaxPlayersPerTeam, NORMAL_HORDE, arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime); - if(bHordeOK) - sLog.outDebug("Battleground: horde pool succesfully built"); - else - sLog.outDebug("Battleground: horde pool wasn't created"); - - // if selection pools are ready, create the new bg - if ((bAllyOK && bHordeOK) || ( sBattleGroundMgr.isTesting() && (bAllyOK || bHordeOK))) + if( bg_template->isBattleGround() ) { - BattleGround * bg2 = 0; - // special handling for arenas - if(bg_template->isArena()) + //check if there is premade against premade match + if( CheckPremadeMatch(queue_id, bg_template->GetMaxPlayersPerTeam(), bg_template->GetMinPlayersPerTeam()) ) { - // Find a random arena, that can be created - BattleGroundTypeId arenas[] = {BATTLEGROUND_NA, BATTLEGROUND_BE, BATTLEGROUND_RL}; - uint32 arena_num = urand(0,2); - if( !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[arena_num%3])) && - !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+1)%3])) && - !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+2)%3])) ) + //create new battleground + BattleGround * bg2 = NULL; + if( !(bg2 = sBattleGroundMgr.CreateNewBattleGround(bgTypeId, queue_id, 0, false)) ) { - sLog.outError("Battleground: couldn't create any arena instance!"); + sLog.outError("BattleGroundQueue::Update - Cannot create battleground: %u", bgTypeId); return; } - - // set the MaxPlayersPerTeam values based on arenatype - // setting the min player values isn't needed, since we won't be using that value later on. - if(sBattleGroundMgr.isArenaTesting()) - { - bg2->SetMaxPlayersPerTeam(1); - bg2->SetMaxPlayers(2); - } - else - { - switch(arenatype) - { - case ARENA_TYPE_2v2: - bg2->SetMaxPlayersPerTeam(2); - bg2->SetMaxPlayers(4); - break; - case ARENA_TYPE_3v3: - bg2->SetMaxPlayersPerTeam(3); - bg2->SetMaxPlayers(6); - break; - case ARENA_TYPE_5v5: - bg2->SetMaxPlayersPerTeam(5); - bg2->SetMaxPlayers(10); - break; - default: - break; - } - } - } - else - { - // create new battleground - bg2 = sBattleGroundMgr.CreateNewBattleGround(bgTypeId); - if( sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE) ) - { - char const* bgName = bg2->GetName(); - uint32 q_min_level = Player::GetMinLevelForBattleGroundQueueId(queue_id, bgTypeId); - uint32 q_max_level = Player::GetMaxLevelForBattleGroundQueueId(queue_id, bgTypeId); - if(q_max_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) - q_max_level = sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); - sWorld.SendWorldText(LANG_BG_STARTED_ANNOUNCE_WORLD, bgName, q_min_level, q_max_level); - } - } - - if(!bg2) - { - sLog.outError("Battleground: couldn't create bg %u",bgTypeId); - return; - } - - // start the joining of the bg - bg2->SetStatus(STATUS_WAIT_JOIN); - bg2->SetQueueId(queue_id); - // initialize arena / rating info - bg2->SetArenaType(arenatype); - // set rating - bg2->SetRated(isRated); - - std::list::iterator itr; - - // invite groups from horde selection pool - for(itr = m_SelectionPools[NORMAL_HORDE].SelectedGroups.begin(); itr != m_SelectionPools[NORMAL_HORDE].SelectedGroups.end(); ++itr) - { - InviteGroupToBG((*itr),bg2,HORDE); - } - - // invite groups from ally selection pools - for(itr = m_SelectionPools[NORMAL_ALLIANCE].SelectedGroups.begin(); itr != m_SelectionPools[NORMAL_ALLIANCE].SelectedGroups.end(); ++itr) - { - InviteGroupToBG((*itr),bg2,ALLIANCE); - } - - if (isRated) - { - std::list::iterator itr_alliance = m_SelectionPools[NORMAL_ALLIANCE].SelectedGroups.begin(); - std::list::iterator itr_horde = m_SelectionPools[NORMAL_HORDE].SelectedGroups.begin(); - (*itr_alliance)->OpponentsTeamRating = (*itr_horde)->ArenaTeamRating; - sLog.outDebug("setting oposite teamrating for team %u to %u", (*itr_alliance)->ArenaTeamId, (*itr_alliance)->OpponentsTeamRating); - (*itr_horde)->OpponentsTeamRating = (*itr_alliance)->ArenaTeamRating; - sLog.outDebug("setting oposite teamrating for team %u to %u", (*itr_horde)->ArenaTeamId, (*itr_horde)->OpponentsTeamRating); - } - - // start the battleground - bg2->StartBattleGround(); - } - - // there weren't enough players for a "normal" match - // if arena, enable horde versus horde or alliance versus alliance teams here - - else if(bg_template->isArena()) - { - bool bOneSideHordeTeam1 = false, bOneSideHordeTeam2 = false; - bool bOneSideAllyTeam1 = false, bOneSideAllyTeam2 = false; - bOneSideHordeTeam1 = BuildSelectionPool(bgTypeId, queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_HORDE_TEAM1,arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime); - if(bOneSideHordeTeam1) - { - // one team has been selected, find out if other can be selected too - std::list::iterator itr; - // temporarily change the team side to enable building the next pool excluding the already selected groups - for(itr = m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.end(); ++itr) - (*itr)->Team=ALLIANCE; - - bOneSideHordeTeam2 = BuildSelectionPool(bgTypeId, queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_HORDE_TEAM2,arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime, (*(m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.begin()))->ArenaTeamId); - - // change back the team to horde - for(itr = m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.end(); ++itr) - (*itr)->Team=HORDE; - - if(!bOneSideHordeTeam2) - bOneSideHordeTeam1 = false; - } - if(!bOneSideHordeTeam1) - { - // check for one sided ally - bOneSideAllyTeam1 = BuildSelectionPool(bgTypeId, queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_ALLIANCE_TEAM1,arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime); - if(bOneSideAllyTeam1) - { - // one team has been selected, find out if other can be selected too - std::list::iterator itr; - // temporarily change the team side to enable building the next pool excluding the already selected groups - for(itr = m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.end(); ++itr) - (*itr)->Team=HORDE; - - bOneSideAllyTeam2 = BuildSelectionPool(bgTypeId, queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_ALLIANCE_TEAM2,arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime,(*(m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.begin()))->ArenaTeamId); - - // change back the team to ally - for(itr = m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.end(); ++itr) - (*itr)->Team=ALLIANCE; - } - - if(!bOneSideAllyTeam2) - bOneSideAllyTeam1 = false; - } - // 1-sided BuildSelectionPool() will work, because the MinPlayersPerTeam == MaxPlayersPerTeam in every arena!!!! - if( (bOneSideHordeTeam1 && bOneSideHordeTeam2) || - (bOneSideAllyTeam1 && bOneSideAllyTeam2) ) - { - // which side has enough players? - uint32 side = 0; - SelectionPoolBuildMode mode1, mode2; - // find out what pools are we using - if(bOneSideAllyTeam1 && bOneSideAllyTeam2) - { - side = ALLIANCE; - mode1 = ONESIDE_ALLIANCE_TEAM1; - mode2 = ONESIDE_ALLIANCE_TEAM2; - } - else - { - side = HORDE; - mode1 = ONESIDE_HORDE_TEAM1; - mode2 = ONESIDE_HORDE_TEAM2; - } - - // create random arena - BattleGroundTypeId arenas[] = {BATTLEGROUND_NA, BATTLEGROUND_BE, BATTLEGROUND_RL}; - uint32 arena_num = urand(0,2); - BattleGround* bg2 = NULL; - if( !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[arena_num%3])) && - !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+1)%3])) && - !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+2)%3])) ) - { - sLog.outError("Could not create arena."); - return; - } - - sLog.outDebug("Battleground: One-faction arena created."); - // init stats - if(sBattleGroundMgr.isArenaTesting()) - { - bg2->SetMaxPlayersPerTeam(1); - bg2->SetMaxPlayers(2); - } - else - { - switch(arenatype) - { - case ARENA_TYPE_2v2: - bg2->SetMaxPlayersPerTeam(2); - bg2->SetMaxPlayers(4); - break; - case ARENA_TYPE_3v3: - bg2->SetMaxPlayersPerTeam(3); - bg2->SetMaxPlayers(6); - break; - case ARENA_TYPE_5v5: - bg2->SetMaxPlayersPerTeam(5); - bg2->SetMaxPlayers(10); - break; - default: - break; - } - } - - bg2->SetRated(isRated); - - // assigned team of the other group - uint32 other_side; - if(side == ALLIANCE) - other_side = HORDE; - else - other_side = ALLIANCE; - - // start the joining of the bg - bg2->SetStatus(STATUS_WAIT_JOIN); - bg2->SetQueueId(queue_id); - // initialize arena / rating info - bg2->SetArenaType(arenatype); - - std::list::iterator itr; - - // invite players from the first group as horde players (actually green team) - for(itr = m_SelectionPools[mode1].SelectedGroups.begin(); itr != m_SelectionPools[mode1].SelectedGroups.end(); ++itr) - { - InviteGroupToBG((*itr),bg2,HORDE); - } - - // invite players from the second group as ally players (actually gold team) - for(itr = m_SelectionPools[mode2].SelectedGroups.begin(); itr != m_SelectionPools[mode2].SelectedGroups.end(); ++itr) - { - InviteGroupToBG((*itr),bg2,ALLIANCE); - } - - if (isRated) - { - std::list::iterator itr_alliance = m_SelectionPools[mode1].SelectedGroups.begin(); - std::list::iterator itr_horde = m_SelectionPools[mode2].SelectedGroups.begin(); - (*itr_alliance)->OpponentsTeamRating = (*itr_horde)->ArenaTeamRating; - (*itr_horde)->OpponentsTeamRating = (*itr_alliance)->ArenaTeamRating; - } - + //invite those selection pools + for(uint32 i = 0; i < BG_TEAMS_COUNT; i++) + for(GroupsQueueType::const_iterator itr = m_SelectionPools[BG_TEAM_ALLIANCE + i].SelectedGroups.begin(); itr != m_SelectionPools[BG_TEAM_ALLIANCE + i].SelectedGroups.end(); ++itr) + InviteGroupToBG((*itr), bg2, (*itr)->Team); + //start bg bg2->StartBattleGround(); + //clear structures + m_SelectionPools[BG_TEAM_ALLIANCE].Init(); + m_SelectionPools[BG_TEAM_HORDE].Init(); + } + } + + // now check if there are in queues enough players to start new game of (normal battleground, or non-rated arena) + if( !isRated ) + { + // if there are enough players in pools, start new battleground or non rated arena + if( CheckNormalMatch(bg_template, queue_id, MinPlayersPerTeam) ) + { + // we successfully created a pool + BattleGround * bg2 = NULL; + if( !(bg2 = sBattleGroundMgr.CreateNewBattleGround(bgTypeId, queue_id, arenaType, false)) ) + { + sLog.outError("BattleGroundQueue::Update - Cannot create battleground: %u", bgTypeId); + return; + } + + // invite those selection pools + for(uint32 i = 0; i < BG_TEAMS_COUNT; i++) + for(GroupsQueueType::const_iterator itr = m_SelectionPools[BG_TEAM_ALLIANCE + i].SelectedGroups.begin(); itr != m_SelectionPools[BG_TEAM_ALLIANCE + i].SelectedGroups.end(); ++itr) + InviteGroupToBG((*itr), bg2, (*itr)->Team); + // start bg + bg2->StartBattleGround(); + } + } + else if( bg_template->isArena() ) + { + // found out the minimum and maximum ratings the newly added team should battle against + // arenaRating is the rating of the latest joined team, or 0 + // 0 is on (automatic update call) and we must set it to team's with longest wait time + if ( !arenaRating ) + { + GroupQueueInfo* front1 = NULL; + GroupQueueInfo* front2 = NULL; + if( !m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].empty() ) + { + front1 = m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].front(); + arenaRating = front1->ArenaTeamRating; + } + if( !m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].empty() ) + { + front2 = m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].front(); + arenaRating = front2->ArenaTeamRating; + } + if( front1 && front2 ) + { + if( front1->JoinTime < front2->JoinTime ) + arenaRating = front1->ArenaTeamRating; + } + else if( !front1 && !front2 ) + return; //queues are empty + } + + //set rating range + uint32 arenaMinRating = (arenaRating <= sBattleGroundMgr.GetMaxRatingDifference()) ? 0 : arenaRating - sBattleGroundMgr.GetMaxRatingDifference(); + uint32 arenaMaxRating = arenaRating + sBattleGroundMgr.GetMaxRatingDifference(); + // if max rating difference is set and the time past since server startup is greater than the rating discard time + // (after what time the ratings aren't taken into account when making teams) then + // the discard time is current_time - time_to_discard, teams that joined after that, will have their ratings taken into account + // else leave the discard time on 0, this way all ratings will be discarded + uint32 discardTime = getMSTime() - sBattleGroundMgr.GetRatingDiscardTimer(); + + // we need to find 2 teams which will play next game + + GroupsQueueType::iterator itr_team[BG_TEAMS_COUNT]; + + //optimalization : --- we dont need to use selection_pools - each update we select max 2 groups + + for(uint32 i = BG_QUEUE_PREMADE_ALLIANCE; i < BG_QUEUE_NORMAL_ALLIANCE; i++) + { + // take the group that joined first + itr_team[i] = m_QueuedGroups[queue_id][i].begin(); + for(; itr_team[i] != m_QueuedGroups[queue_id][i].end(); ++(itr_team[i])) + { + // if group match conditions, then add it to pool + if( !(*itr_team[i])->IsInvitedToBGInstanceGUID + && (((*itr_team[i])->ArenaTeamRating >= arenaMinRating && (*itr_team[i])->ArenaTeamRating <= arenaMaxRating) + || (*itr_team[i])->JoinTime < discardTime) ) + { + m_SelectionPools[i].AddGroup((*itr_team[i]), MaxPlayersPerTeam); + // break for cycle to be able to start selecting another group from same faction queue + break; + } + } + } + // now we are done if we have 2 groups - ali vs horde! + // if we don't have, we must try to continue search in same queue + // tmp variables are correctly set + // this code isn't much userfriendly - but it is supposed to continue search for mathing group in HORDE queue + if( m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() == 0 && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() ) + { + itr_team[BG_TEAM_ALLIANCE] = itr_team[BG_TEAM_HORDE]; + ++itr_team[BG_TEAM_ALLIANCE]; + for(; itr_team[BG_TEAM_ALLIANCE] != m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].end(); ++(itr_team[BG_TEAM_ALLIANCE])) + { + if( !(*itr_team[BG_TEAM_ALLIANCE])->IsInvitedToBGInstanceGUID + && (((*itr_team[BG_TEAM_ALLIANCE])->ArenaTeamRating >= arenaMinRating && (*itr_team[BG_TEAM_ALLIANCE])->ArenaTeamRating <= arenaMaxRating) + || (*itr_team[BG_TEAM_ALLIANCE])->JoinTime < discardTime) ) + { + m_SelectionPools[BG_TEAM_ALLIANCE].AddGroup((*itr_team[BG_TEAM_ALLIANCE]), MaxPlayersPerTeam); + break; + } + } + } + // this code isn't much userfriendly - but it is supposed to continue search for mathing group in ALLIANCE queue + if( m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() == 0 && m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() ) + { + itr_team[BG_TEAM_HORDE] = itr_team[BG_TEAM_ALLIANCE]; + ++itr_team[BG_TEAM_HORDE]; + for(; itr_team[BG_TEAM_HORDE] != m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].end(); ++(itr_team[BG_TEAM_HORDE])) + { + if( !(*itr_team[BG_TEAM_HORDE])->IsInvitedToBGInstanceGUID + && (((*itr_team[BG_TEAM_HORDE])->ArenaTeamRating >= arenaMinRating && (*itr_team[BG_TEAM_HORDE])->ArenaTeamRating <= arenaMaxRating) + || (*itr_team[BG_TEAM_HORDE])->JoinTime < discardTime) ) + { + m_SelectionPools[BG_TEAM_HORDE].AddGroup((*itr_team[BG_TEAM_HORDE]), MaxPlayersPerTeam); + break; + } + } + } + + //if we have 2 teams, then start new arena and invite players! + if( m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() ) + { + BattleGround* arena = NULL; + if( !(arena = sBattleGroundMgr.CreateNewBattleGround(bgTypeId, queue_id, arenaType, true)) ) + { + sLog.outError("BattlegroundQueue::Update couldn't create arena instance for rated arena match!"); + return; + } + + (*(itr_team[BG_TEAM_ALLIANCE]))->OpponentsTeamRating = (*(itr_team[BG_TEAM_HORDE]))->ArenaTeamRating; + sLog.outDebug("setting oposite teamrating for team %u to %u", (*(itr_team[BG_TEAM_ALLIANCE]))->ArenaTeamId, (*(itr_team[BG_TEAM_ALLIANCE]))->OpponentsTeamRating); + (*(itr_team[BG_TEAM_HORDE]))->OpponentsTeamRating = (*(itr_team[BG_TEAM_ALLIANCE]))->ArenaTeamRating; + sLog.outDebug("setting oposite teamrating for team %u to %u", (*(itr_team[BG_TEAM_HORDE]))->ArenaTeamId, (*(itr_team[BG_TEAM_HORDE]))->OpponentsTeamRating); + // now we must move team if we changed its faction to another faction queue, because then we will spam log by errors in Queue::RemovePlayer + if( (*(itr_team[BG_TEAM_ALLIANCE]))->Team != ALLIANCE ) + { + // add to alliance queue + m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].push_front(*(itr_team[BG_TEAM_ALLIANCE])); + // erase from horde queue + m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].erase(itr_team[BG_TEAM_ALLIANCE]); + } + if( (*(itr_team[BG_TEAM_HORDE]))->Team != HORDE ) + { + m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].push_front(*(itr_team[BG_TEAM_HORDE])); + m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].erase(itr_team[BG_TEAM_HORDE]); + } + + InviteGroupToBG(*(itr_team[BG_TEAM_ALLIANCE]), arena, ALLIANCE); + InviteGroupToBG(*(itr_team[BG_TEAM_HORDE]), arena, HORDE); + + sLog.outDebug("Starting rated arena match!"); + + arena->StartBattleGround(); } } } @@ -972,26 +907,22 @@ bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) return true; // Player can be in another BG queue and must be removed in normal way in any case - // // player is already in battleground ... do nothing (battleground queue status is deleted when player is teleported to BG) - // if (plr->GetBattleGroundId() > 0) - // return true; BattleGround* bg = sBattleGroundMgr.GetBattleGround(m_BgInstanceGUID); if (!bg) return true; BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); - BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId); uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId); if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue { // check if player is invited to this bg ... this check must be here, because when player leaves queue and joins another, it would cause a problems - BattleGroundQueue::QueuedPlayersMap const& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel(bgTypeId)]; + BattleGroundQueue::QueuedPlayersMap const& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers; BattleGroundQueue::QueuedPlayersMap::const_iterator qItr = qpMap.find(m_PlayerGuid); if (qItr != qpMap.end() && qItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID) { WorldPacket data; - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, qItr->second.GroupInfo->Team, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME/2, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, qItr->second.GroupInfo->Team, queueSlot, STATUS_WAIT_JOIN, INVITATION_REMIND_TIME, 0); plr->GetSession()->SendPacket(&data); } } @@ -1022,8 +953,7 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue { // check if player is invited to this bg ... this check must be here, because when player leaves queue and joins another, it would cause a problems - uint32 queue_id=plr->GetBattleGroundQueueIdFromLevel(bg->GetTypeID()); - BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[queue_id]; + BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers; BattleGroundQueue::QueuedPlayersMap::iterator qMapItr = qpMap.find(m_PlayerGuid); if (qMapItr != qpMap.end() && qMapItr->second.GroupInfo && qMapItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID) { @@ -1039,7 +969,7 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) } plr->RemoveBattleGroundQueueId(bgQueueTypeId); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(m_PlayerGuid, true); - sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bg->GetTypeID(),bg->GetQueueId()); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bg->GetTypeID(), bg->GetQueueId()); WorldPacket data; sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, m_PlayersTeam, queueSlot, STATUS_NONE, 0, 0); plr->GetSession()->SendPacket(&data); @@ -1111,15 +1041,19 @@ void BattleGroundMgr::Update(uint32 diff) } } // if rating difference counts, maybe force-update queues - if(sWorld.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE)) + if(sWorld.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE) && sWorld.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER)) { // it's time to force update if(m_NextRatingDiscardUpdate < diff) { // forced update for level 70 rated arenas - m_BattleGroundQueues[BATTLEGROUND_QUEUE_2v2].Update(BATTLEGROUND_AA,6,ARENA_TYPE_2v2,true,0); - m_BattleGroundQueues[BATTLEGROUND_QUEUE_3v3].Update(BATTLEGROUND_AA,6,ARENA_TYPE_3v3,true,0); - m_BattleGroundQueues[BATTLEGROUND_QUEUE_5v5].Update(BATTLEGROUND_AA,6,ARENA_TYPE_5v5,true,0); + sLog.outDebug("BattleGroundMgr: UPDATING ARENA QUEUES"); + m_BattleGroundQueues[BATTLEGROUND_QUEUE_2v2].Update(BATTLEGROUND_AA, QUEUE_ID_MAX_LEVEL_79, ARENA_TYPE_2v2, true, 0); + m_BattleGroundQueues[BATTLEGROUND_QUEUE_2v2].Update(BATTLEGROUND_AA, QUEUE_ID_MAX_LEVEL_80, ARENA_TYPE_2v2, true, 0); + m_BattleGroundQueues[BATTLEGROUND_QUEUE_3v3].Update(BATTLEGROUND_AA, QUEUE_ID_MAX_LEVEL_79, ARENA_TYPE_3v3, true, 0); + m_BattleGroundQueues[BATTLEGROUND_QUEUE_3v3].Update(BATTLEGROUND_AA, QUEUE_ID_MAX_LEVEL_80, ARENA_TYPE_3v3, true, 0); + m_BattleGroundQueues[BATTLEGROUND_QUEUE_5v5].Update(BATTLEGROUND_AA, QUEUE_ID_MAX_LEVEL_79, ARENA_TYPE_5v5, true, 0); + m_BattleGroundQueues[BATTLEGROUND_QUEUE_5v5].Update(BATTLEGROUND_AA, QUEUE_ID_MAX_LEVEL_80, ARENA_TYPE_5v5, true, 0); m_NextRatingDiscardUpdate = sWorld.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER); } else @@ -1412,7 +1346,7 @@ void BattleGroundMgr::InvitePlayer(Player* plr, uint32 bgInstanceGUID, uint32 te // create invite events: //add events to player's counters ---- this is not good way - there should be something like global event processor, where we should add those events BGQueueInviteEvent* inviteEvent = new BGQueueInviteEvent(plr->GetGUID(), bgInstanceGUID); - plr->m_Events.AddEvent(inviteEvent, plr->m_Events.CalculateTime(INVITE_ACCEPT_WAIT_TIME/2)); + plr->m_Events.AddEvent(inviteEvent, plr->m_Events.CalculateTime(INVITATION_REMIND_TIME)); BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(plr->GetGUID(), bgInstanceGUID, team); plr->m_Events.AddEvent(removeEvent, plr->m_Events.CalculateTime(INVITE_ACCEPT_WAIT_TIME)); } @@ -1423,7 +1357,7 @@ BattleGround * BattleGroundMgr::GetBattleGroundTemplate(BattleGroundTypeId bgTyp } // create a new battleground that will really be used to play -BattleGround * BattleGroundMgr::CreateNewBattleGround(BattleGroundTypeId bgTypeId) +BattleGround * BattleGroundMgr::CreateNewBattleGround(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id, uint8 arenaType, bool isRated) { // get the template BG BattleGround *bg_template = GetBattleGroundTemplate(bgTypeId); @@ -1433,8 +1367,21 @@ BattleGround * BattleGroundMgr::CreateNewBattleGround(BattleGroundTypeId bgTypeI return NULL; } - BattleGround *bg = NULL; + //for arenas there is random map used + if(bg_template->isArena()) + { + BattleGroundTypeId arenas[] = {BATTLEGROUND_NA, BATTLEGROUND_BE, BATTLEGROUND_RL}; + uint32 arena_num = urand(0,2); + bgTypeId = arenas[arena_num]; + bg_template = GetBattleGroundTemplate(bgTypeId); + if(!bg_template) + { + sLog.outError("BattleGround: CreateNewBattleGround - bg template not found for %u", bgTypeId); + return NULL; + } + } + BattleGround *bg = NULL; // create a copy of the BG template switch(bgTypeId) { @@ -1482,13 +1429,21 @@ BattleGround * BattleGroundMgr::CreateNewBattleGround(BattleGroundTypeId bgTypeI // reset the new bg (set status to status_wait_queue from status_none) bg->Reset(); + if( bg->isBattleGround() && sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE) ) + { + sWorld.SendWorldText(LANG_BG_STARTED_ANNOUNCE_WORLD, bg->GetName(), bg->GetMinLevel(), bg->GetMaxLevel()); + } + + // start the joining of the bg + bg->SetStatus(STATUS_WAIT_JOIN); + bg->SetQueueId(queue_id); + // initialize arena / rating info + bg->SetArenaType(arenaType); + // set rating + bg->SetRated(isRated); + /* will be setup in BG::Update() when the first player is ported in if(!(bg->SetupBattleGround())) - { - sLog.outError("BattleGround: CreateNewBattleGround: SetupBattleGround failed for bg %u", bgTypeId); - delete bg; - return 0; - } */ // add BG to free slot queue @@ -1905,7 +1860,11 @@ void BattleGroundMgr::ToggleArenaTesting() uint32 BattleGroundMgr::GetMaxRatingDifference() const { - return sWorld.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE); + // this is for stupid people who can't use brain and set max rating difference to 0 + uint32 diff = sWorld.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE); + if (diff == 0) + diff = 5000; + return diff; } uint32 BattleGroundMgr::GetRatingDiscardTimer() const diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h index df5e9668c..7910462f3 100644 --- a/src/game/BattleGroundMgr.h +++ b/src/game/BattleGroundMgr.h @@ -25,15 +25,11 @@ //TODO it is not possible to have this structure, because we should have BattlegroundSet for each queue //so i propose to change this type to array 1..MAX_BATTLEGROUND_TYPES of sets or maps.. typedef std::map BattleGroundSet; -//typedef std::map BattleGroundQueueSet; + typedef std::deque BGFreeSlotQueueType; typedef UNORDERED_MAP BattleMastersMap; -#define MAX_BATTLEGROUND_QUEUES 8 // for level ranges 10-19, 20-29, 30-39, 40-49, 50-59, 60-69, 70-79, 80+ - -#define MAX_BATTLEGROUND_QUEUE_TYPES 9 - #define BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY 86400 // seconds in a day struct GroupQueueInfo; // type predefinition @@ -59,6 +55,15 @@ struct GroupQueueInfo // stores informatio uint32 OpponentsTeamRating; // for rated arena matches }; +enum BattleGroundQueueGroupTypes +{ + BG_QUEUE_PREMADE_ALLIANCE = 0, + BG_QUEUE_PREMADE_HORDE = 1, + BG_QUEUE_NORMAL_ALLIANCE = 2, + BG_QUEUE_NORMAL_HORDE = 3, + BG_QUEUE_GROUP_TYPES_COUNT = 4 +}; + class BattleGround; class BattleGroundQueue { @@ -66,9 +71,12 @@ class BattleGroundQueue BattleGroundQueue(); ~BattleGroundQueue(); - void Update(BattleGroundTypeId bgTypeId, uint32 queue_id, uint8 arenatype = 0, bool isRated = false, uint32 minRating = 0); + void Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id, uint8 arenaType = 0, bool isRated = false, uint32 minRating = 0); - GroupQueueInfo * AddGroup(Player * leader, BattleGroundTypeId bgTypeId, uint8 ArenaType, bool isRated, uint32 ArenaRating, uint32 ArenaTeamId = 0); + void FillPlayersToBG(BattleGround* bg, BGQueueIdBasedOnLevel queue_id); + bool CheckPremadeMatch(BGQueueIdBasedOnLevel queue_id, uint32 MaxPlayersPerTeam, uint32 MinPlayersPerTeam); + bool CheckNormalMatch(BattleGround* bg_template, BGQueueIdBasedOnLevel queue_id, uint32 MinPlayersPerTeam); + GroupQueueInfo * AddGroup(Player * leader, BattleGroundTypeId bgTypeId, uint8 ArenaType, bool isRated, bool isPremade, uint32 ArenaRating, uint32 ArenaTeamId = 0); void AddPlayer(Player *plr, GroupQueueInfo *ginfo); void RemovePlayer(const uint64& guid, bool decreaseInvitedCount); void DecreaseGroupLength(uint32 queueId, uint32 AsGroup); @@ -76,52 +84,38 @@ class BattleGroundQueue void AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playerGUID, bool isAddedToQueue); typedef std::map QueuedPlayersMap; - QueuedPlayersMap m_QueuedPlayers[MAX_BATTLEGROUND_QUEUES]; + QueuedPlayersMap m_QueuedPlayers; - typedef std::list QueuedGroupsList; - QueuedGroupsList m_QueuedGroups[MAX_BATTLEGROUND_QUEUES]; + //we need constant add to begin and constant remove / add from the end, therefore deque suits our problem well + typedef std::deque GroupsQueueType; - // class to hold pointers to the groups eligible for a specific selection pool building mode - class EligibleGroups : public std::list - { - public: - void Init(QueuedGroupsList * source, BattleGroundTypeId BgTypeId, uint32 side, uint32 MaxPlayers, uint8 ArenaType = 0, bool IsRated = false, uint32 MinRating = 0, uint32 MaxRating = 0, uint32 DisregardTime = 0, uint32 excludeTeam = 0); - void RemoveGroup(GroupQueueInfo * ginfo); - }; - - EligibleGroups m_EligibleGroups; + /* + This two dimensional array is used to store All queued groups + First dimension specifies the bgTypeId + Second dimension specifies the player's group types - + BG_QUEUE_PREMADE_ALLIANCE is used for premade alliance groups and alliance rated arena teams + BG_QUEUE_PREMADE_HORDE is used for premade horde groups and horde rated arena teams + BG_QUEUE_NORMAL_ALLIANCE is used for normal (or small) alliance groups or non-rated arena matches + BG_QUEUE_NORMAL_HORDE is used for normal (or small) horde groups or non-rated arena matches + */ + GroupsQueueType m_QueuedGroups[MAX_BATTLEGROUND_QUEUES][BG_QUEUE_GROUP_TYPES_COUNT]; // class to select and invite groups to bg class SelectionPool { public: void Init(); - void AddGroup(GroupQueueInfo * group); - GroupQueueInfo * GetMaximalGroup(); - void RemoveGroup(GroupQueueInfo * group); + bool AddGroup(GroupQueueInfo *ginfo, uint32 desiredCount); + bool KickGroup(uint32 size); uint32 GetPlayerCount() const {return PlayerCount;} public: - std::list SelectedGroups; + GroupsQueueType SelectedGroups; private: uint32 PlayerCount; - GroupQueueInfo * MaxGroup; }; - enum SelectionPoolBuildMode - { - NORMAL_ALLIANCE, - NORMAL_HORDE, - ONESIDE_ALLIANCE_TEAM1, - ONESIDE_ALLIANCE_TEAM2, - ONESIDE_HORDE_TEAM1, - ONESIDE_HORDE_TEAM2, - - NUM_SELECTION_POOL_TYPES - }; - - SelectionPool m_SelectionPools[NUM_SELECTION_POOL_TYPES]; - - bool BuildSelectionPool(BattleGroundTypeId bgTypeId, uint32 queue_id, uint32 MinPlayers, uint32 MaxPlayers, SelectionPoolBuildMode mode, uint8 ArenaType = 0, bool isRated = false, uint32 MinRating = 0, uint32 MaxRating = 0, uint32 DisregardTime = 0, uint32 excludeTeam = 0); + //one selection pool for horde, other one for alliance + SelectionPool m_SelectionPools[BG_TEAMS_COUNT]; private: @@ -182,8 +176,8 @@ class BattleGroundMgr void BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg); void BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype = 0, uint8 israted = 0); void BuildPlaySoundPacket(WorldPacket *data, uint32 soundid); - void SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, const uint64& guid); + /* Player invitation */ // called from Queue update, or from Addplayer to queue void InvitePlayer(Player* plr, uint32 bgInstanceGUID, uint32 team); @@ -199,7 +193,7 @@ class BattleGroundMgr }; BattleGround * GetBattleGroundTemplate(BattleGroundTypeId bgTypeId); - BattleGround * CreateNewBattleGround(BattleGroundTypeId bgTypeId); + BattleGround * CreateNewBattleGround(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id, uint8 arenaType, bool isRated); uint32 CreateBattleGround(BattleGroundTypeId bgTypeId, bool IsArena, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam, uint32 LevelMin, uint32 LevelMax, char* BattleGroundName, uint32 MapID, float Team1StartLocX, float Team1StartLocY, float Team1StartLocZ, float Team1StartLocO, float Team2StartLocX, float Team2StartLocY, float Team2StartLocZ, float Team2StartLocO); diff --git a/src/game/Group.cpp b/src/game/Group.cpp index d2fabecea..21695b754 100644 --- a/src/game/Group.cpp +++ b/src/game/Group.cpp @@ -1344,7 +1344,7 @@ uint32 Group::CanJoinBattleGroundQueue(BattleGroundTypeId bgTypeId, BattleGround if(!reference) return BG_JOIN_ERR_OFFLINE_MEMBER; - uint32 queue_id = reference->GetBattleGroundQueueIdFromLevel(bgTypeId); + BGQueueIdBasedOnLevel queue_id = reference->GetBattleGroundQueueIdFromLevel(bgTypeId); uint32 arenaTeamId = reference->GetArenaTeamId(arenaSlot); uint32 team = reference->GetTeam(); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 0ce76b0ff..3ba8be20c 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -18475,34 +18475,20 @@ bool Player::GetBGAccessByLevel(BattleGroundTypeId bgTypeId) const return true; } -uint32 Player::GetMinLevelForBattleGroundQueueId(uint32 queue_id, BattleGroundTypeId bgTypeId) +BGQueueIdBasedOnLevel Player::GetBattleGroundQueueIdFromLevel(BattleGroundTypeId bgTypeId) const { - BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); - assert(bg); - return (queue_id*10)+bg->GetMinLevel(); -} + //returned to hardcoded version of this function, because there is no way to code it dynamic + uint32 level = getLevel(); + if( bgTypeId == BATTLEGROUND_QUEUE_AV ) + level--; -uint32 Player::GetMaxLevelForBattleGroundQueueId(uint32 queue_id, BattleGroundTypeId bgTypeId) -{ - return GetMinLevelForBattleGroundQueueId(queue_id, bgTypeId)+10; -} - -uint32 Player::GetBattleGroundQueueIdFromLevel(BattleGroundTypeId bgTypeId) const -{ - BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); - assert(bg); - if(getLevel()GetMinLevel()) + uint32 queue_id = (level / 10) - 1; // for ranges 0 - 19, 20 - 29, 30 - 39, 40 - 49, 50 - 59, 60 - 69, 70 -79, 80 + if( queue_id >= MAX_BATTLEGROUND_QUEUES ) { - sLog.outError("getting queue_id for player who doesn't meet the requirements - this shouldn't happen"); - return 0; + sLog.outError("BattleGround: too high queue_id %u this shouldn't happen", queue_id); + return QUEUE_ID_MAX_LEVEL_80; } - uint32 queue_id = (getLevel() - bg->GetMinLevel()) / 10; - if(queue_id>MAX_BATTLEGROUND_QUEUES) - { - sLog.outError("to high queue_id %u this shouldn't happen",queue_id); - return 0; - } - return queue_id; + return BGQueueIdBasedOnLevel(queue_id); } float Player::GetReputationPriceDiscount( Creature const* pCreature ) const diff --git a/src/game/Player.h b/src/game/Player.h index 76d6cc272..64a053fd5 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1865,14 +1865,13 @@ class MANGOS_DLL_SPEC Player : public Unit /*** BATTLEGROUND SYSTEM ***/ /*********************************************************/ - bool InBattleGround() const { return m_bgBattleGroundID != 0; } - uint32 GetBattleGroundId() const { return m_bgBattleGroundID; } - BattleGround* GetBattleGround() const; + bool InBattleGround() const { return m_bgBattleGroundID != 0; } bool InArena() const; + uint32 GetBattleGroundId() const { return m_bgBattleGroundID; } + BattleGround* GetBattleGround() const; - static uint32 GetMinLevelForBattleGroundQueueId(uint32 queue_id, BattleGroundTypeId bgTypeId); - static uint32 GetMaxLevelForBattleGroundQueueId(uint32 queue_id, BattleGroundTypeId bgTypeId); - uint32 GetBattleGroundQueueIdFromLevel(BattleGroundTypeId bgTypeId) const; + + BGQueueIdBasedOnLevel GetBattleGroundQueueIdFromLevel(BattleGroundTypeId bgTypeId) const; bool InBattleGroundQueue() const { diff --git a/src/game/World.cpp b/src/game/World.cpp index 7093a93dc..38d0e9f87 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -615,20 +615,20 @@ void World::LoadConfigSettings(bool reload) else m_configs[CONFIG_REALM_ZONE] = sConfig.GetIntDefault("RealmZone", REALM_ZONE_DEVELOPMENT); - m_configs[CONFIG_ALLOW_TWO_SIDE_ACCOUNTS] = sConfig.GetBoolDefault("AllowTwoSide.Accounts", false); + m_configs[CONFIG_ALLOW_TWO_SIDE_ACCOUNTS] = sConfig.GetBoolDefault("AllowTwoSide.Accounts", false); m_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT] = sConfig.GetBoolDefault("AllowTwoSide.Interaction.Chat",false); m_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL] = sConfig.GetBoolDefault("AllowTwoSide.Interaction.Channel",false); m_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP] = sConfig.GetBoolDefault("AllowTwoSide.Interaction.Group",false); m_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD] = sConfig.GetBoolDefault("AllowTwoSide.Interaction.Guild",false); m_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION] = sConfig.GetBoolDefault("AllowTwoSide.Interaction.Auction",false); m_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL] = sConfig.GetBoolDefault("AllowTwoSide.Interaction.Mail",false); - m_configs[CONFIG_ALLOW_TWO_SIDE_WHO_LIST] = sConfig.GetBoolDefault("AllowTwoSide.WhoList", false); - m_configs[CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND] = sConfig.GetBoolDefault("AllowTwoSide.AddFriend", false); - m_configs[CONFIG_STRICT_PLAYER_NAMES] = sConfig.GetIntDefault("StrictPlayerNames", 0); - m_configs[CONFIG_STRICT_CHARTER_NAMES] = sConfig.GetIntDefault("StrictCharterNames", 0); - m_configs[CONFIG_STRICT_PET_NAMES] = sConfig.GetIntDefault("StrictPetNames", 0); + m_configs[CONFIG_ALLOW_TWO_SIDE_WHO_LIST] = sConfig.GetBoolDefault("AllowTwoSide.WhoList", false); + m_configs[CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND] = sConfig.GetBoolDefault("AllowTwoSide.AddFriend", false); + m_configs[CONFIG_STRICT_PLAYER_NAMES] = sConfig.GetIntDefault ("StrictPlayerNames", 0); + m_configs[CONFIG_STRICT_CHARTER_NAMES] = sConfig.GetIntDefault ("StrictCharterNames", 0); + m_configs[CONFIG_STRICT_PET_NAMES] = sConfig.GetIntDefault ("StrictPetNames", 0); - m_configs[CONFIG_CHARACTERS_CREATING_DISABLED] = sConfig.GetIntDefault("CharactersCreatingDisabled", 0); + m_configs[CONFIG_CHARACTERS_CREATING_DISABLED] = sConfig.GetIntDefault ("CharactersCreatingDisabled", 0); m_configs[CONFIG_CHARACTERS_PER_REALM] = sConfig.GetIntDefault("CharactersPerRealm", 10); if(m_configs[CONFIG_CHARACTERS_PER_REALM] < 1 || m_configs[CONFIG_CHARACTERS_PER_REALM] > 10) @@ -762,13 +762,6 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_INSTANCE_IGNORE_LEVEL] = sConfig.GetBoolDefault("Instance.IgnoreLevel", false); m_configs[CONFIG_INSTANCE_IGNORE_RAID] = sConfig.GetBoolDefault("Instance.IgnoreRaid", false); - m_configs[CONFIG_BATTLEGROUND_CAST_DESERTER] = sConfig.GetBoolDefault("Battleground.CastDeserter", true); - m_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE] = sConfig.GetBoolDefault("Battleground.QueueAnnouncer.Enable", false); - m_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY] = sConfig.GetBoolDefault("Battleground.QueueAnnouncer.PlayerOnly", false); - m_configs[CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE] = sConfig.GetBoolDefault("Arena.QueueAnnouncer.Enable", false); - m_configs[CONFIG_ARENA_SEASON_ID] = sConfig.GetIntDefault ("Arena.ArenaSeason.ID", 1); - m_configs[CONFIG_ARENA_SEASON_IN_PROGRESS] = sConfig.GetBoolDefault("Arena.ArenaSeason.InProgress", true); - m_configs[CONFIG_CAST_UNSTUCK] = sConfig.GetBoolDefault("CastUnstuck", true); m_configs[CONFIG_INSTANCE_RESET_TIME_HOUR] = sConfig.GetIntDefault("Instance.ResetTimeHour", 4); m_configs[CONFIG_INSTANCE_UNLOAD_DELAY] = sConfig.GetIntDefault("Instance.UnloadDelay", 1800000); @@ -905,23 +898,23 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_DETECT_POS_COLLISION] = sConfig.GetBoolDefault("DetectPosCollision", true); - m_configs[CONFIG_RESTRICTED_LFG_CHANNEL] = sConfig.GetBoolDefault("Channel.RestrictedLfg", true); + m_configs[CONFIG_RESTRICTED_LFG_CHANNEL] = sConfig.GetBoolDefault("Channel.RestrictedLfg", true); m_configs[CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL] = sConfig.GetBoolDefault("Channel.SilentlyGMJoin", false); - m_configs[CONFIG_TALENTS_INSPECTING] = sConfig.GetBoolDefault("TalentsInspecting", true); + m_configs[CONFIG_TALENTS_INSPECTING] = sConfig.GetBoolDefault("TalentsInspecting", true); m_configs[CONFIG_CHAT_FAKE_MESSAGE_PREVENTING] = sConfig.GetBoolDefault("ChatFakeMessagePreventing", false); - m_configs[CONFIG_CORPSE_DECAY_NORMAL] = sConfig.GetIntDefault("Corpse.Decay.NORMAL", 60); - m_configs[CONFIG_CORPSE_DECAY_RARE] = sConfig.GetIntDefault("Corpse.Decay.RARE", 300); - m_configs[CONFIG_CORPSE_DECAY_ELITE] = sConfig.GetIntDefault("Corpse.Decay.ELITE", 300); + m_configs[CONFIG_CORPSE_DECAY_NORMAL] = sConfig.GetIntDefault("Corpse.Decay.NORMAL", 60); + m_configs[CONFIG_CORPSE_DECAY_RARE] = sConfig.GetIntDefault("Corpse.Decay.RARE", 300); + m_configs[CONFIG_CORPSE_DECAY_ELITE] = sConfig.GetIntDefault("Corpse.Decay.ELITE", 300); m_configs[CONFIG_CORPSE_DECAY_RAREELITE] = sConfig.GetIntDefault("Corpse.Decay.RAREELITE", 300); m_configs[CONFIG_CORPSE_DECAY_WORLDBOSS] = sConfig.GetIntDefault("Corpse.Decay.WORLDBOSS", 3600); - m_configs[CONFIG_DEATH_SICKNESS_LEVEL] = sConfig.GetIntDefault("Death.SicknessLevel", 11); + m_configs[CONFIG_DEATH_SICKNESS_LEVEL] = sConfig.GetIntDefault ("Death.SicknessLevel", 11); m_configs[CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVP] = sConfig.GetBoolDefault("Death.CorpseReclaimDelay.PvP", true); m_configs[CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVE] = sConfig.GetBoolDefault("Death.CorpseReclaimDelay.PvE", true); - m_configs[CONFIG_DEATH_BONES_WORLD] = sConfig.GetBoolDefault("Death.Bones.World", true); - m_configs[CONFIG_DEATH_BONES_BG_OR_ARENA] = sConfig.GetBoolDefault("Death.Bones.BattlegroundOrArena", true); + m_configs[CONFIG_DEATH_BONES_WORLD] = sConfig.GetBoolDefault("Death.Bones.World", true); + m_configs[CONFIG_DEATH_BONES_BG_OR_ARENA] = sConfig.GetBoolDefault("Death.Bones.BattlegroundOrArena", true); m_configs[CONFIG_THREAT_RADIUS] = sConfig.GetIntDefault("ThreatRadius", 100); @@ -933,12 +926,20 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_LISTEN_RANGE_TEXTEMOTE] = sConfig.GetIntDefault("ListenRange.TextEmote", 25); m_configs[CONFIG_LISTEN_RANGE_YELL] = sConfig.GetIntDefault("ListenRange.Yell", 300); - m_configs[CONFIG_ARENA_MAX_RATING_DIFFERENCE] = sConfig.GetIntDefault("Arena.MaxRatingDifference", 0); - m_configs[CONFIG_ARENA_RATING_DISCARD_TIMER] = sConfig.GetIntDefault("Arena.RatingDiscardTimer",300000); - m_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS] = sConfig.GetBoolDefault("Arena.AutoDistributePoints", false); - m_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS] = sConfig.GetIntDefault("Arena.AutoDistributeInterval", 7); + m_configs[CONFIG_BATTLEGROUND_CAST_DESERTER] = sConfig.GetBoolDefault("Battleground.CastDeserter", true); + m_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE] = sConfig.GetBoolDefault("Battleground.QueueAnnouncer.Enable", false); + m_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY] = sConfig.GetBoolDefault("Battleground.QueueAnnouncer.PlayerOnly", false); + m_configs[CONFIG_BATTLEGROUND_INVITATION_TYPE] = sConfig.GetIntDefault ("Battleground.InvitationType", 0); + m_configs[CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER] = sConfig.GetIntDefault ("BattleGround.PrematureFinishTimer", 5 * MINUTE * IN_MILISECONDS); + m_configs[CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH] = sConfig.GetIntDefault ("BattleGround.PremadeGroupWaitForMatch", 30 * MINUTE * IN_MILISECONDS); + m_configs[CONFIG_ARENA_MAX_RATING_DIFFERENCE] = sConfig.GetIntDefault ("Arena.MaxRatingDifference", 100); + m_configs[CONFIG_ARENA_RATING_DISCARD_TIMER] = sConfig.GetIntDefault ("Arena.RatingDiscardTimer", 10 * MINUTE * IN_MILISECONDS); + m_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS] = sConfig.GetBoolDefault("Arena.AutoDistributePoints", false); + m_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS] = sConfig.GetIntDefault ("Arena.AutoDistributeInterval", 7); + m_configs[CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE] = sConfig.GetBoolDefault("Arena.QueueAnnouncer.Enable", false); + m_configs[CONFIG_ARENA_SEASON_ID] = sConfig.GetIntDefault ("Arena.ArenaSeason.ID", 1); + m_configs[CONFIG_ARENA_SEASON_IN_PROGRESS] = sConfig.GetBoolDefault("Arena.ArenaSeason.InProgress", true); - m_configs[CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER] = sConfig.GetIntDefault("BattleGround.PrematureFinishTimer", 0); m_configs[CONFIG_INSTANT_LOGOUT] = sConfig.GetIntDefault("InstantLogout", SEC_MODERATOR); m_VisibleUnitGreyDistance = sConfig.GetFloatDefault("Visibility.Distance.Grey.Unit", 1); diff --git a/src/game/World.h b/src/game/World.h index 4bbf4ebf1..9c908c127 100644 --- a/src/game/World.h +++ b/src/game/World.h @@ -113,9 +113,6 @@ enum WorldConfigs CONFIG_START_ARENA_POINTS, CONFIG_INSTANCE_IGNORE_LEVEL, CONFIG_INSTANCE_IGNORE_RAID, - CONFIG_BATTLEGROUND_CAST_DESERTER, - CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE, - CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY, CONFIG_INSTANCE_RESET_TIME_HOUR, CONFIG_INSTANCE_UNLOAD_DELAY, CONFIG_CAST_UNSTUCK, @@ -184,6 +181,13 @@ enum WorldConfigs CONFIG_LISTEN_RANGE_SAY, CONFIG_LISTEN_RANGE_TEXTEMOTE, CONFIG_LISTEN_RANGE_YELL, + CONFIG_SKILL_MILLING, + CONFIG_BATTLEGROUND_CAST_DESERTER, + CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE, + CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY, + CONFIG_BATTLEGROUND_INVITATION_TYPE, + CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER, + CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH, CONFIG_ARENA_MAX_RATING_DIFFERENCE, CONFIG_ARENA_RATING_DISCARD_TIMER, CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS, @@ -191,8 +195,6 @@ enum WorldConfigs CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE, CONFIG_ARENA_SEASON_ID, CONFIG_ARENA_SEASON_IN_PROGRESS, - CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER, - CONFIG_SKILL_MILLING, CONFIG_VALUE_COUNT }; diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in index e8b916ce8..8a333823f 100644 --- a/src/mangosd/mangosd.conf.dist.in +++ b/src/mangosd/mangosd.conf.dist.in @@ -483,25 +483,6 @@ LogColors = "" # Default: 1 (true) # 0 (false) # -# Battleground.CastDeserter -# Cast or not Deserter spell at player who leave battleground in progress -# Default: 1 (true) -# 0 (false) -# -# Battleground.QueueAnnouncer.Enable -# Enable queue announcer posting to chat -# Default: 0 (false) -# 1 (true) -# -# Battleground.QueueAnnouncer.PlayerOnly -# Enable queue announcer posting to chat -# Default: 0 (false) -# 1 (true) -# -# Arena.QueueAnnouncer.Enable: Enable queue announcer posting to chat -# Default: 0 (false) -# 1 (true) -# # CastUnstuck # Allow cast or not Unstuck spell at .start or client Help option use # Default: 1 (true) @@ -606,10 +587,6 @@ DisableWaterBreath = 4 AllFlightPaths = 0 AlwaysMaxSkillForLevel = 0 ActivateWeather = 1 -Battleground.CastDeserter = 1 -Battleground.QueueAnnouncer.Enable = 0 -Battleground.QueueAnnouncer.PlayerOnly = 0 -Arena.QueueAnnouncer.Enable = 0 CastUnstuck = 1 Instance.IgnoreLevel = 0 Instance.IgnoreRaid = 0 @@ -1128,59 +1105,101 @@ Death.CorpseReclaimDelay.PvE = 1 Death.Bones.World = 1 Death.Bones.BattlegroundOrArena = 1 + ################################################################################################################### +# BATTLEGROUND CONFIG # -# Rated arena matches config +# Battleground.CastDeserter +# Cast or not Deserter spell at player who leave battleground in progress +# Default: 1 (true) +# 0 (false) # -# MaxRatingDifference: the maximum rating difference between two groups in rated matches -# Default: 0 (disable, rating difference is discarded) +# Battleground.QueueAnnouncer.Enable +# Enable queue announcer posting to chat +# Default: 0 (false) +# 1 (true) # -# RatingDiscardTimer: after the specified milliseconds has passed, -# rating information will be discarded when selecting teams for matches -# also initiates an update by this timer -# Default: 60000 +# Battleground.QueueAnnouncer.PlayerOnly +# Enable queue announcer posting to chat +# Default: 0 (false) +# 1 (true) # -# AutoDistributePoints: set if arena points should be distributed automatically, or by GM command -# Default: 0 (disable) (recommended): use gm command or sql query to distribute the points -# 1 (enable): arena points are distributed automatically +# Battleground.InvitationType +# Set Battleground invitation type +# Default: 0 (normal - invite as much players to bg as possible, don't bother with ballance) +# 1 (Experimental - don't allow to invite much more players of one faction) # -# AutoDistributeInterval: how often should the distribution take place -# if automatic distribution is enabled -# in days -# Default: 7 (weekly) +# Battleground.PrematureFinishTimer +# The time to end the bg if there are less than MinPlayersPerTeam on one side in milliseconds +# Default: 300000 (5 minutes) +# 0 - disable (not recommended) # -# ArenaSeason.ID: current area season id show in client -# Default: 1 -# -# ArenaSeason.InProgress: current area season state -# Default: 1 (active) -# 0 (finished) +# BattleGround.PremadeGroupWaitForMatch +# The time in which premade group of 1 faction waits in BG Queue for premade group of other faction +# Default: 1800000 (30 minutes) +# 0 - disable (not recommended) # ################################################################################################################### -Arena.MaxRatingDifference = 0 -Arena.RatingDiscardTimer = 60000 +Battleground.CastDeserter = 1 +Battleground.QueueAnnouncer.Enable = 0 +Battleground.QueueAnnouncer.PlayerOnly = 0 +Battleground.InvitationType = 0 +BattleGround.PrematureFinishTimer = 300000 +BattleGround.PremadeGroupWaitForMatch = 1800000 + + +################################################################################################################### +# ARENA CONFIG +# +# Arena.MaxRatingDifference +# The maximum rating difference between two groups in rated matches +# Default: 100 (enable, recommended) +# 0 (disable, rating difference is discarded) +# +# Arena.RatingDiscardTimer +# After the specified milliseconds has passed, +# rating information will be discarded when selecting teams for matches +# also initiates an update by this timer +# Default: 600000 (10 minutes, recommended) +# 0 (disable, DO NOT USE - it will cause lags) +# +# Arena.AutoDistributePoints +# Set if arena points should be distributed automatically, or by GM command +# Default: 0 (disable) (recommended): use gm command or sql query to distribute the points +# 1 (enable) arena points are distributed automatically +# +# Arena.AutoDistributeInterval +# How often should the distribution take place +# If automatic distribution is enabled in days +# Default: 7 (weekly) +# +# Arena.QueueAnnouncer.Enable +# Enable bg queue announcer posting to chat +# Default: 0 (false) +# 1 (true) +# +# Arena.ArenaSeason.ID +# Current area season id show in client +# Default: 1 +# +# Arena.ArenaSeason.InProgress +# Current area season state +# Default: 1 (active) +# 0 (finished) +# +################################################################################################################### + +Arena.MaxRatingDifference = 100 +Arena.RatingDiscardTimer = 600000 Arena.AutoDistributePoints = 0 Arena.AutoDistributeInterval = 7 +Arena.QueueAnnouncer.Enable = 0 Arena.ArenaSeason.ID = 1 Arena.ArenaSeason.InProgress = 1 -################################################################################################################### -# -# Battleground config -# -# PrematureFinishTimer: the time to end the bg if there are less than minplayersperteam on one side -# in milliseconds -# Default: 300000 -# 0 - disable -# -################################################################################################################### - -BattleGround.PrematureFinishTimer = 300000 - ################################################################################################################### -# # NETWORK CONFIG # # Network.Threads diff --git a/src/shared/Common.h b/src/shared/Common.h index ab65d0743..2dce4ac37 100644 --- a/src/shared/Common.h +++ b/src/shared/Common.h @@ -157,7 +157,8 @@ enum TimeConstants MINUTE = 60, HOUR = MINUTE*60, DAY = HOUR*24, - MONTH = DAY*30 + MONTH = DAY*30, + IN_MILISECONDS = 1000 }; enum AccountTypes diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index c4c742e0a..324103418 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7335" + #define REVISION_NR "7336" #endif // __REVISION_NR_H__ From 1fcaf35e29c13fd5eba7a1aacf2add01df380f55 Mon Sep 17 00:00:00 2001 From: ApoC Date: Wed, 25 Feb 2009 22:32:39 +0100 Subject: [PATCH 08/32] [7337] Make some methods const. Signed-off-by: ApoC --- src/game/Map.h | 4 ++-- src/shared/revision_nr.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/game/Map.h b/src/game/Map.h index a5900f7d7..3a9356f88 100644 --- a/src/game/Map.h +++ b/src/game/Map.h @@ -216,8 +216,8 @@ class MANGOS_DLL_SPEC Map : public GridRefManager, public MaNGOS::Obj // assert print helper bool CheckGridIntegrity(Creature* c, bool moved) const; - uint32 GetInstanceId() { return i_InstanceId; } - uint8 GetSpawnMode() { return (i_spawnMode); } + uint32 GetInstanceId() const { return i_InstanceId; } + uint8 GetSpawnMode() const { return (i_spawnMode); } virtual bool CanEnter(Player* /*player*/) { return true; } const char* GetMapName() const; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 324103418..eb685b899 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7336" + #define REVISION_NR "7337" #endif // __REVISION_NR_H__ From f35ffca03efc1a5800ccbbd47161083ecb38390b Mon Sep 17 00:00:00 2001 From: ApoC Date: Wed, 25 Feb 2009 23:28:21 +0100 Subject: [PATCH 09/32] [7338] Little cleanup in battleground queues code. * Moved counts and maxs out of enums. * Added some linebreaks to better code reading. * Little bit tuned up BattleGroundQueue::RemovePlayer. Signed-off-by: ApoC --- src/game/BattleGround.h | 4 ++-- src/game/BattleGroundMgr.cpp | 26 +++++++++++++++++--------- src/game/BattleGroundMgr.h | 4 ++-- src/shared/revision_nr.h | 2 +- 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index 1d5e5ef4b..696ef84b5 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -210,9 +210,9 @@ enum BattleGroundWinner enum BattleGroundTeamId { BG_TEAM_ALLIANCE = 0, - BG_TEAM_HORDE = 1, - BG_TEAMS_COUNT = 2 + BG_TEAM_HORDE = 1 }; +#define BG_TEAMS_COUNT 2 enum BattleGroundJoinError { diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index 8931c407b..af56787db 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -203,19 +203,21 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou // we count from MAX_BATTLEGROUND_QUEUES - 1 to 0 // variable index removes useless searching in other team's queue uint32 index = (group->Team == HORDE) ? BG_TEAM_HORDE : BG_TEAM_ALLIANCE; - for (int32 queue_id_tmp = MAX_BATTLEGROUND_QUEUES - 1; queue_id_tmp >= 0 && queue_id == -1; queue_id_tmp--) + + for (int32 queue_id_tmp = MAX_BATTLEGROUND_QUEUES - 1; queue_id_tmp >= 0 && queue_id == -1; --queue_id_tmp) { - //we must check premade and normal team's queue - because when players from premade are joining bg, they leave groupinfo so we can't use its players size to find out index - for (uint32 j = 0; j < 3; j += BG_QUEUE_NORMAL_ALLIANCE) + //we must check premade and normal team's queue - because when players from premade are joining bg, + //they leave groupinfo so we can't use its players size to find out index + for (uint32 j = index; j < BG_QUEUE_GROUP_TYPES_COUNT - 1; j += BG_QUEUE_NORMAL_ALLIANCE) { - for(group_itr_tmp = m_QueuedGroups[queue_id_tmp][index + j].begin(); group_itr_tmp != m_QueuedGroups[queue_id_tmp][index + j].end(); ++group_itr_tmp) + for(group_itr_tmp = m_QueuedGroups[queue_id_tmp][j].begin(); group_itr_tmp != m_QueuedGroups[queue_id_tmp][j].end(); ++group_itr_tmp) { if( (*group_itr_tmp) == group ) { queue_id = queue_id_tmp; group_itr = group_itr_tmp; //we must store index to be able to erase iterator - index += j; + index = j; break; } } @@ -260,7 +262,8 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou m_QueuedGroups[queue_id][index].erase(group_itr); delete group; } - // if group wasn't empty, so it wasn't deleted, and player have left a rated queue -> everyone from the group should leave too + // if group wasn't empty, so it wasn't deleted, and player have left a rated + // queue -> everyone from the group should leave too // don't remove recursively if already invited to bg! else if( !group->IsInvitedToBGInstanceGUID && group->IsRated ) { @@ -271,7 +274,8 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou BattleGround * bg = sBattleGroundMgr.GetBattleGroundTemplate(group->BgTypeId); BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(group->BgTypeId, group->ArenaType); uint32 queueSlot = plr2->GetBattleGroundQueueIndex(bgQueueTypeId); - plr2->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs + plr2->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to + // queue->removeplayer, it causes bugs WorldPacket data; sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr2->GetTeam(), queueSlot, STATUS_NONE, 0, 0); plr2->GetSession()->SendPacket(&data); @@ -629,7 +633,10 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve return; //if no players in queue ... do nothing - if( m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].empty() && m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].empty() && m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE].empty() && m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_HORDE].empty() ) + if( m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].empty() && + m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].empty() && + m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE].empty() && + m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_HORDE].empty() ) return; BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, arenaType); @@ -642,7 +649,8 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve next = itr; ++next; // DO NOT allow queue manager to invite new player to arena - if( (*itr)->isBattleGround() && (*itr)->GetTypeID() == bgTypeId && (*itr)->GetQueueId() == queue_id && (*itr)->GetStatus() > STATUS_WAIT_QUEUE && (*itr)->GetStatus() < STATUS_WAIT_LEAVE ) + if( (*itr)->isBattleGround() && (*itr)->GetTypeID() == bgTypeId && (*itr)->GetQueueId() == queue_id && + (*itr)->GetStatus() > STATUS_WAIT_QUEUE && (*itr)->GetStatus() < STATUS_WAIT_LEAVE ) { BattleGround* bg = *itr; //we have to store battleground pointer here, because when battleground is full, it is removed from free queue (not yet implemented!!) // and iterator is invalid diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h index 7910462f3..30ab006e1 100644 --- a/src/game/BattleGroundMgr.h +++ b/src/game/BattleGroundMgr.h @@ -60,9 +60,9 @@ enum BattleGroundQueueGroupTypes BG_QUEUE_PREMADE_ALLIANCE = 0, BG_QUEUE_PREMADE_HORDE = 1, BG_QUEUE_NORMAL_ALLIANCE = 2, - BG_QUEUE_NORMAL_HORDE = 3, - BG_QUEUE_GROUP_TYPES_COUNT = 4 + BG_QUEUE_NORMAL_HORDE = 3 }; +#define BG_QUEUE_GROUP_TYPES_COUNT 4 class BattleGround; class BattleGroundQueue diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index eb685b899..d791b16d7 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7337" + #define REVISION_NR "7338" #endif // __REVISION_NR_H__ From b4dbeb3bc891a5dde8b77dfe70248db40affc8df Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Thu, 26 Feb 2009 01:39:45 +0300 Subject: [PATCH 10/32] [7339] Attempt lock spawn grid only for active non-pet creatures. --- src/game/Map.cpp | 10 ++++++---- src/game/Map.h | 22 +++++++++------------- src/game/ObjectGridLoader.cpp | 6 ++++-- src/shared/revision_nr.h | 2 +- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/game/Map.cpp b/src/game/Map.cpp index 18cc41174..cafb3464c 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -463,7 +463,8 @@ Map::Add(T *obj) AddToGrid(obj,grid,cell); obj->AddToWorld(); - AddToActive(obj); + if(obj->isActiveObject()) + AddToActive(obj); DEBUG_LOG("Object %u enters grid[%u,%u]", GUID_LOPART(obj->GetGUID()), cell.GridX(), cell.GridY()); @@ -762,7 +763,8 @@ Map::Remove(T *obj, bool remove) NGridType *grid = getNGrid(cell.GridX(), cell.GridY()); assert( grid != NULL ); - RemoveFromActive(obj); + if(obj->isActiveObject()) + RemoveFromActive(obj); obj->RemoveFromWorld(); RemoveFromGrid(obj,grid,cell); @@ -1623,7 +1625,7 @@ void Map::AddToActive( Creature* c ) AddToActiveHelper(c); // also not allow unloading spawn grid to prevent creating creature clone at load - if(c->GetDBTableGUIDLow()) + if(!c->isPet() && c->GetDBTableGUIDLow()) { float x,y,z; c->GetRespawnCoord(x,y,z); @@ -1644,7 +1646,7 @@ void Map::RemoveFromActive( Creature* c ) RemoveFromActiveHelper(c); // also allow unloading spawn grid - if(c->GetDBTableGUIDLow()) + if(!c->isPet() && c->GetDBTableGUIDLow()) { float x,y,z; c->GetRespawnCoord(x,y,z); diff --git a/src/game/Map.h b/src/game/Map.h index 3a9356f88..80f042674 100644 --- a/src/game/Map.h +++ b/src/game/Map.h @@ -358,26 +358,22 @@ class MANGOS_DLL_SPEC Map : public GridRefManager, public MaNGOS::Obj template void AddToActiveHelper(T* obj) { - if(obj->isActiveObject()) - m_activeNonPlayers.insert(obj); + m_activeNonPlayers.insert(obj); } template void RemoveFromActiveHelper(T* obj) { - if(obj->isActiveObject()) + // Map::Update for active object in proccess + if(m_activeNonPlayersIter != m_activeNonPlayers.end()) { - // Map::Update for active object in proccess - if(m_activeNonPlayersIter != m_activeNonPlayers.end()) - { - ActiveNonPlayers::iterator itr = m_activeNonPlayers.find(obj); - if(itr==m_activeNonPlayersIter) - ++m_activeNonPlayersIter; - m_activeNonPlayers.erase(itr); - } - else - m_activeNonPlayers.erase(obj); + ActiveNonPlayers::iterator itr = m_activeNonPlayers.find(obj); + if(itr==m_activeNonPlayersIter) + ++m_activeNonPlayersIter; + m_activeNonPlayers.erase(itr); } + else + m_activeNonPlayers.erase(obj); } }; diff --git a/src/game/ObjectGridLoader.cpp b/src/game/ObjectGridLoader.cpp index 9b944893e..04a343d36 100644 --- a/src/game/ObjectGridLoader.cpp +++ b/src/game/ObjectGridLoader.cpp @@ -125,7 +125,8 @@ void LoadHelper(CellGuidSet const& guid_set, CellPair &cell, GridRefManager & addUnitState(obj,cell); obj->AddToWorld(); - map->AddToActive(obj); + if(obj->isActiveObject()) + map->AddToActive(obj); ++count; @@ -152,7 +153,8 @@ void LoadHelper(CellCorpseSet const& cell_corpses, CellPair &cell, CorpseMapType addUnitState(obj,cell); obj->AddToWorld(); - map->AddToActive(obj); + if(obj->isActiveObject()) + map->AddToActive(obj); ++count; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index d791b16d7..cd01be326 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7338" + #define REVISION_NR "7339" #endif // __REVISION_NR_H__ From ae1a404a04f1d34177713123150d0dc76c97568e Mon Sep 17 00:00:00 2001 From: aerione_alt Date: Thu, 26 Feb 2009 04:43:09 +0300 Subject: [PATCH 11/32] [7340] Prevent standup at save in result unexpected packet send to client. Signed-off-by: VladimirMangos --- src/game/Player.cpp | 3 +-- src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 3ba8be20c..d4b052bc0 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -15591,8 +15591,7 @@ void Player::SaveToDB() uint32 tmp_displayid = GetDisplayId(); // Set player sit state to standing on save, also stealth and shifted form - SetStandState(UNIT_STAND_STATE_STAND); // stand state - RemoveStandFlags(UNIT_STAND_FLAGS_ALL); // stand flags? + SetByteValue(UNIT_FIELD_BYTES_1, 0, UNIT_STAND_STATE_STAND); SetByteValue(UNIT_FIELD_BYTES_2, 3, 0); // shapeshift RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); SetDisplayId(GetNativeDisplayId()); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index cd01be326..84addee51 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7339" + #define REVISION_NR "7340" #endif // __REVISION_NR_H__ From dbe15f5e59cdb6d74bea87cab6328fa07594447c Mon Sep 17 00:00:00 2001 From: NoFantasy Date: Thu, 26 Feb 2009 05:05:05 +0300 Subject: [PATCH 12/32] [7341] Report about wrongly use CREATURE_FLAG_EXTRA_INSTANCE_BIND for creatures spawned at not dungeon maps. Signed-off-by: VladimirMangos --- src/game/ObjectMgr.cpp | 7 +++++++ src/shared/revision_nr.h | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index ca116e917..c782fcf81 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -932,6 +932,13 @@ void ObjectMgr::LoadCreatures() data.curhealth = cInfo->minhealth; } + if(cInfo->flags_extra & CREATURE_FLAG_EXTRA_INSTANCE_BIND) + { + MapEntry const* map = sMapStore.LookupEntry(data.mapid); + if(!map || !map->IsDungeon()) + sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `creature_template`.`flags_extra` including CREATURE_FLAG_EXTRA_INSTANCE_BIND but creature are not in instance.",guid,data.id); + } + if(data.curmana < cInfo->minmana) { sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with low current mana (%u), `creature_template`.`minmana`=%u.",guid,data.id,data.curmana, cInfo->minmana ); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 84addee51..ac205e216 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7340" + #define REVISION_NR "7341" #endif // __REVISION_NR_H__ From 4a46cb843de9ba72b78ec000ba55982847e31f1a Mon Sep 17 00:00:00 2001 From: "False.Genesis" Date: Thu, 26 Feb 2009 05:13:22 +0300 Subject: [PATCH 13/32] [7342] Use neutral auctionhouse id in case CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION as more expected. Signed-off-by: VladimirMangos --- src/game/AuctionHouseMgr.cpp | 2 +- src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/AuctionHouseMgr.cpp b/src/game/AuctionHouseMgr.cpp index 7db668ab0..24fac0a3a 100644 --- a/src/game/AuctionHouseMgr.cpp +++ b/src/game/AuctionHouseMgr.cpp @@ -456,7 +456,7 @@ void AuctionHouseMgr::Update() AuctionHouseEntry const* AuctionHouseMgr::GetAuctionHouseEntry(uint32 factionTemplateId) { - uint32 houseid = 1; // human auction house + uint32 houseid = 7; // goblin auction house if(!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) { diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index ac205e216..69bc7ff5a 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7341" + #define REVISION_NR "7342" #endif // __REVISION_NR_H__ From 3dd6b69adba61b3c57be0050d1f220ffb4b255e5 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Thu, 26 Feb 2009 08:51:42 +0300 Subject: [PATCH 14/32] [7343] Fixed uninitilized lock fields for grid info. This must fix problem with unexpected lock grids data in memory with enabled grid unloading config setting. --- src/framework/GameSystem/NGrid.h | 6 ++++-- src/shared/revision_nr.h | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/framework/GameSystem/NGrid.h b/src/framework/GameSystem/NGrid.h index 0d6211243..469e47fb0 100644 --- a/src/framework/GameSystem/NGrid.h +++ b/src/framework/GameSystem/NGrid.h @@ -29,8 +29,10 @@ class GridInfo { public: - GridInfo() : i_timer(0) {} - GridInfo(time_t expiry, bool unload = true ) : i_timer(expiry), i_unloadExplicitLock(!unload) {} + GridInfo() + : i_timer(0), i_unloadActiveLockCount(0), i_unloadExplicitLock(false), i_unloadReferenceLock(false) {} + GridInfo(time_t expiry, bool unload = true ) + : i_timer(expiry), i_unloadActiveLockCount(0), i_unloadExplicitLock(!unload), i_unloadReferenceLock(false) {} const TimeTracker& getTimeTracker() const { return i_timer; } bool getUnloadLock() const { return i_unloadActiveLockCount || i_unloadExplicitLock || i_unloadReferenceLock; } void setUnloadExplicitLock( bool on ) { i_unloadExplicitLock = on; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 69bc7ff5a..23d3554d9 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7342" + #define REVISION_NR "7343" #endif // __REVISION_NR_H__ From aba675c4ca510c5b560c68434a6cc3c55b02b5c5 Mon Sep 17 00:00:00 2001 From: Velorien Date: Thu, 26 Feb 2009 09:17:52 +0300 Subject: [PATCH 15/32] [7344] Ignore drop rate multipliers in loot groups. For grouped loot use rates create problems with impossibility loot some items including quest items. Signed-off-by: VladimirMangos --- src/game/LootMgr.cpp | 18 ++++++++---------- src/shared/revision_nr.h | 2 +- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/game/LootMgr.cpp b/src/game/LootMgr.cpp index 05b08eb8a..591a123f8 100644 --- a/src/game/LootMgr.cpp +++ b/src/game/LootMgr.cpp @@ -55,7 +55,7 @@ class LootTemplate::LootGroup // A set of loot def bool HasQuestDrop() const; // True if group includes at least 1 quest drop entry bool HasQuestDropForPlayer(Player const * player) const; // The same for active quests of the player - void Process(Loot& loot, bool rate) const; // Rolls an item from the group (if any) and adds the item to the loot + void Process(Loot& loot) const; // Rolls an item from the group (if any) and adds the item to the loot float RawTotalChance() const; // Overall chance for the group (without equal chanced items) float TotalChance() const; // Overall chance for the group @@ -66,7 +66,7 @@ class LootTemplate::LootGroup // A set of loot def LootStoreItemList ExplicitlyChanced; // Entries with chances defined in DB LootStoreItemList EqualChanced; // Zero chances - every entry takes the same chance - LootStoreItem const * Roll(bool rate) const; // Rolls an item from the group, returns NULL if all miss their chances + LootStoreItem const * Roll() const; // Rolls an item from the group, returns NULL if all miss their chances }; //Remove all data and free all memory @@ -789,7 +789,7 @@ void LootTemplate::LootGroup::AddEntry(LootStoreItem& item) } // Rolls an item from the group, returns NULL if all miss their chances -LootStoreItem const * LootTemplate::LootGroup::Roll(bool rate) const +LootStoreItem const * LootTemplate::LootGroup::Roll() const { if (!ExplicitlyChanced.empty()) // First explicitly chanced entries are checked { @@ -800,9 +800,7 @@ LootStoreItem const * LootTemplate::LootGroup::Roll(bool rate) const if(ExplicitlyChanced[i].chance>=100.f) return &ExplicitlyChanced[i]; - ItemPrototype const *pProto = objmgr.GetItemPrototype(ExplicitlyChanced[i].itemid); - float qualityMultiplier = pProto && rate ? sWorld.getRate(qualityToRate[pProto->Quality]) : 1.0f; - Roll -= ExplicitlyChanced[i].chance * qualityMultiplier; + Roll -= ExplicitlyChanced[i].chance; if (Roll < 0) return &ExplicitlyChanced[i]; } @@ -838,9 +836,9 @@ bool LootTemplate::LootGroup::HasQuestDropForPlayer(Player const * player) const } // Rolls an item from the group (if any takes its chance) and adds the item to the loot -void LootTemplate::LootGroup::Process(Loot& loot, bool rate) const +void LootTemplate::LootGroup::Process(Loot& loot) const { - LootStoreItem const * item = Roll(rate); + LootStoreItem const * item = Roll(); if (item != NULL) loot.AddItem(*item); } @@ -932,7 +930,7 @@ void LootTemplate::Process(Loot& loot, LootStore const& store, bool rate, uint8 if (groupId > Groups.size()) return; // Error message already printed at loading stage - Groups[groupId-1].Process(loot,rate); + Groups[groupId-1].Process(loot); return; } @@ -958,7 +956,7 @@ void LootTemplate::Process(Loot& loot, LootStore const& store, bool rate, uint8 // Now processing groups for (LootGroups::const_iterator i = Groups.begin( ) ; i != Groups.end( ) ; ++i ) - i->Process(loot,rate); + i->Process(loot); } // True if template includes at least 1 quest drop entry diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 23d3554d9..85c3c3d3b 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7343" + #define REVISION_NR "7344" #endif // __REVISION_NR_H__ From 64158d61b3a4520b2cf438eecec9fa198ef84077 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 27 Feb 2009 01:22:51 +0300 Subject: [PATCH 16/32] [7345] Use in most cases dynamic quest level as expected (player level for quests witl level 0) Original patch provided by NoFantasy. Signed-off-by: VladimirMangos --- src/game/GossipDef.cpp | 6 +++--- src/game/Player.cpp | 2 +- src/game/Player.h | 2 ++ src/game/QuestHandler.cpp | 2 +- src/shared/revision_nr.h | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/game/GossipDef.cpp b/src/game/GossipDef.cpp index 8310d9e27..2eefba679 100644 --- a/src/game/GossipDef.cpp +++ b/src/game/GossipDef.cpp @@ -151,7 +151,7 @@ void PlayerMenu::SendGossipMenu( uint32 TitleTextId, uint64 npcGUID ) data << uint32(questID); data << uint32( qItem.m_qIcon ); - data << uint32(pQuest && pQuest->GetQuestLevel() ? pQuest->GetQuestLevel() : pSession->GetPlayer()->getLevel()); + data << uint32(pSession->GetPlayer()->GetQuestLevel(pQuest)); std::string Title = pQuest->GetTitle(); int loc_idx = pSession->GetSessionDbLocaleIndex(); @@ -400,7 +400,7 @@ void PlayerMenu::SendQuestGiverQuestList( QEmote eEmote, const std::string& Titl data << uint32(questID); data << uint32(qmi.m_qIcon); - data << uint32(pQuest && pQuest->GetQuestLevel() ? pQuest->GetQuestLevel() : pSession->GetPlayer()->getLevel()); + data << uint32(pSession->GetPlayer()->GetQuestLevel(pQuest)); data << title; } pSession->SendPacket( &data ); @@ -546,7 +546,7 @@ void PlayerMenu::SendQuestQueryResponse( Quest const *pQuest ) data << uint32(pQuest->GetQuestId()); data << uint32(pQuest->GetQuestMethod()); // Accepted values: 0, 1 or 2. 0==IsAutoComplete() (skip objectives/details) - data << uint32(pQuest->GetQuestLevel()); // may be 0 + data << uint32(pQuest->GetQuestLevel()); // may be 0, static data, in other cases must be used dynamic level: Player::GetQuestLevel data << uint32(pQuest->GetZoneOrSort()); // zone or sort to display in quest log data << uint32(pQuest->GetType()); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index d4b052bc0..2f52476aa 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -6017,7 +6017,7 @@ void Player::RewardReputation(Quest const *pQuest) { if(pQuest->RewRepFaction[i] && pQuest->RewRepValue[i] ) { - int32 rep = CalculateReputationGain(pQuest->GetQuestLevel(),pQuest->RewRepValue[i],true); + int32 rep = CalculateReputationGain(GetQuestLevel(pQuest),pQuest->RewRepValue[i],true); FactionEntry const* factionEntry = sFactionStore.LookupEntry(pQuest->RewRepFaction[i]); if(factionEntry) ModifyFactionReputation(factionEntry, rep); diff --git a/src/game/Player.h b/src/game/Player.h index 64a053fd5..c6802dae1 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1199,6 +1199,8 @@ class MANGOS_DLL_SPEC Player : public Unit /*** QUEST SYSTEM ***/ /*********************************************************/ + uint32 GetQuestLevel( Quest const* pQuest ) const { return pQuest && pQuest->GetQuestLevel() ? pQuest->GetQuestLevel() : getLevel(); } + void PrepareQuestMenu( uint64 guid ); void SendPreparedQuest( uint64 guid ); bool IsActiveQuest( uint32 quest_id ) const; diff --git a/src/game/QuestHandler.cpp b/src/game/QuestHandler.cpp index 72b966e6b..28787184a 100644 --- a/src/game/QuestHandler.cpp +++ b/src/game/QuestHandler.cpp @@ -570,7 +570,7 @@ uint32 WorldSession::getDialogStatus(Player *pPlayer, Object* questgiver, uint32 { if ( pQuest->IsAutoComplete() || (pQuest->IsRepeatable() && pPlayer->getQuestStatusMap()[quest_id].m_rewarded)) result2 = DIALOG_STATUS_REWARD_REP; - else if (pPlayer->getLevel() <= pQuest->GetQuestLevel() + sWorld.getConfig(CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF) ) + else if (pPlayer->getLevel() <= pPlayer->GetQuestLevel(pQuest) + sWorld.getConfig(CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF) ) { if (pQuest->HasFlag(QUEST_FLAGS_DAILY)) result2 = DIALOG_STATUS_AVAILABLE_REP; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 85c3c3d3b..62fdbce7b 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7344" + #define REVISION_NR "7345" #endif // __REVISION_NR_H__ From 01d7801ca0d12662bbcb19f7c7f5ebecf780197c Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 27 Feb 2009 06:44:11 +0300 Subject: [PATCH 17/32] [7346] Revert [7342] and really restore work CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION setting. --- src/game/AuctionHouseMgr.cpp | 5 ++++- src/shared/revision_nr.h | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/game/AuctionHouseMgr.cpp b/src/game/AuctionHouseMgr.cpp index 24fac0a3a..b5370c19b 100644 --- a/src/game/AuctionHouseMgr.cpp +++ b/src/game/AuctionHouseMgr.cpp @@ -49,6 +49,9 @@ AuctionHouseMgr::~AuctionHouseMgr() AuctionHouseObject * AuctionHouseMgr::GetAuctionsMap( uint32 factionTemplateId ) { + if(sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) + return &mNeutralAuctions; + // team have linked auction houses FactionTemplateEntry const* u_entry = sFactionTemplateStore.LookupEntry(factionTemplateId); if(!u_entry) @@ -456,7 +459,7 @@ void AuctionHouseMgr::Update() AuctionHouseEntry const* AuctionHouseMgr::GetAuctionHouseEntry(uint32 factionTemplateId) { - uint32 houseid = 7; // goblin auction house + uint32 houseid = 1; // dwarf auction house (used for normal cut/etc percents) if(!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) { diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 62fdbce7b..5399b44cb 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7345" + #define REVISION_NR "7346" #endif // __REVISION_NR_H__ From 19c513fc61186cb9e3f37189ebd30f79d5ce2b5b Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 27 Feb 2009 06:47:33 +0300 Subject: [PATCH 18/32] [7347] Prevent sql errors at GM-mode corpse save. Apply same chnages and for other pahsemask save part for consistense and safe. --- src/game/Corpse.cpp | 17 +++++++++++++---- src/game/Creature.cpp | 4 ++-- src/game/GameObject.cpp | 4 ++-- src/shared/revision_nr.h | 2 +- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/game/Corpse.cpp b/src/game/Corpse.cpp index f2587b555..3fe362a8e 100644 --- a/src/game/Corpse.cpp +++ b/src/game/Corpse.cpp @@ -104,12 +104,21 @@ void Corpse::SaveToDB() std::ostringstream ss; ss << "INSERT INTO corpse (guid,player,position_x,position_y,position_z,orientation,zone,map,data,time,corpse_type,instance,phaseMask) VALUES (" - << GetGUIDLow() << ", " << GUID_LOPART(GetOwnerGUID()) << ", " << GetPositionX() << ", " << GetPositionY() << ", " << GetPositionZ() << ", " - << GetOrientation() << ", " << GetZoneId() << ", " << GetMapId() << ", '"; + << GetGUIDLow() << ", " + << GUID_LOPART(GetOwnerGUID()) << ", " + << GetPositionX() << ", " + << GetPositionY() << ", " + << GetPositionZ() << ", " + << GetOrientation() << ", " + << GetZoneId() << ", " + << GetMapId() << ", '"; for(uint16 i = 0; i < m_valuesCount; i++ ) ss << GetUInt32Value(i) << " "; - ss << "'," << uint64(m_time) <<", " << uint32(GetType()) - << ", " << int(GetInstanceId()) << ", " << int(GetPhaseMask()) << ")"; + ss << "'," + << uint64(m_time) <<", " + << uint32(GetType()) << ", " + << int(GetInstanceId()) << ", " + << uint16(GetPhaseMask()) << ")"; // prevent out of range error CharacterDatabase.Execute( ss.str().c_str() ); CharacterDatabase.CommitTransaction(); } diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index e0d9846e0..32ab79c6a 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -1124,8 +1124,8 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask) << m_DBTableGuid << "," << GetEntry() << "," << mapid <<"," - << (uint32)spawnMask << "," - << (uint32)GetPhaseMask() << "," + << uint32(spawnMask) << "," // cast to prevent save as symbol + << uint16(GetPhaseMask()) << "," // prevent out of range error << displayId <<"," << GetEquipmentId() <<"," << GetPositionX() << "," diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index 826c1fda0..6a5fb5687 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -552,8 +552,8 @@ void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask) << m_DBTableGuid << ", " << GetEntry() << ", " << mapid << ", " - << (uint32)spawnMask << ", " - << (uint32)GetPhaseMask() << "," + << uint32(spawnMask) << "," // cast to prevent save as symbol + << uint16(GetPhaseMask()) << "," // prevent out of range error << GetFloatValue(GAMEOBJECT_POS_X) << ", " << GetFloatValue(GAMEOBJECT_POS_Y) << ", " << GetFloatValue(GAMEOBJECT_POS_Z) << ", " diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 5399b44cb..9ab590e64 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7346" + #define REVISION_NR "7347" #endif // __REVISION_NR_H__ From 9e7e3740776c2ec070d2a9065d42fa30cafee8a3 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 27 Feb 2009 07:34:05 +0300 Subject: [PATCH 19/32] [7348] Remove hack code from IsDeathPersistentSpell. Re-apply zone dependent auras at resurrection by triggering zone update for player. --- src/game/Player.cpp | 6 +++--- src/game/SpellMgr.h | 10 +--------- src/shared/revision_nr.h | 2 +- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 2f52476aa..d3f63d42a 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -3868,12 +3868,12 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness) SetPower(POWER_ENERGY, uint32(GetMaxPower(POWER_ENERGY)*restore_percent)); } + // trigger update zone for alive state zone updates + UpdateZone(GetZoneId()); + // update visibility ObjectAccessor::UpdateVisibilityForPlayer(this); - // some items limited to specific map - DestroyZoneLimitedItem( true, GetZoneId()); - if(!applySickness) return; diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 9b318e954..5522337fa 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -338,14 +338,6 @@ inline bool IsPassiveSpellStackableWithRanks(SpellEntry const* spellProto) inline bool IsDeathPersistentSpell(SpellEntry const *spellInfo) { - switch(spellInfo->Id) - { - case 40214: // Dragonmaw Illusion - case 35480: case 35481: case 35482: // Human Illusion - case 35483: case 39824: // Human Illusion - return true; - } - return spellInfo->AttributesEx3 & SPELL_ATTR_EX3_DEATH_PERSISTENT; } @@ -1005,7 +997,7 @@ class SpellMgr SpellBonusMap mSpellBonusMap; SkillLineAbilityMap mSkillLineAbilityMap; SpellPetAuraMap mSpellPetAuraMap; - PetLevelupSpellMap mPetLevelupSpellMap; + PetLevelupSpellMap mPetLevelupSpellMap; }; #define spellmgr SpellMgr::Instance() diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 9ab590e64..ede9681cf 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7347" + #define REVISION_NR "7348" #endif // __REVISION_NR_H__ From 1fca6de6f36501ea37e8956f838a89a36950ed00 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 27 Feb 2009 11:03:09 +0300 Subject: [PATCH 20/32] [7349] Implement spell cast depenences from area/quest.aura state store in new table `spell_area`. * It allow store requirenments: area, active or rewarded quest (until possible another quest not rewarded), aura present at character, character race/gender. * Listed spell can marked as auto-casted when fit requirents. In this case spell requirements checked at zone/subzone update (and then resurraction also), quest start/reward, dummy aura apply. * Old hardcoded lines for similar check removed from sources and required DB support for work now. --- sql/mangos.sql | 29 +- sql/updates/7349_01_mangos_spell_area.sql | 15 ++ sql/updates/Makefile.am | 2 + src/game/Chat.cpp | 1 + src/game/Chat.h | 1 + src/game/Level3.cpp | 9 + src/game/Player.cpp | 103 +++---- src/game/Spell.cpp | 4 +- src/game/SpellAuras.cpp | 31 +++ src/game/SpellMgr.cpp | 315 +++++++++++++++++----- src/game/SpellMgr.h | 65 ++++- src/game/World.cpp | 3 + src/shared/revision_nr.h | 2 +- 13 files changed, 458 insertions(+), 122 deletions(-) create mode 100644 sql/updates/7349_01_mangos_spell_area.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index 0b46f3f9e..829a7586d 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -22,7 +22,7 @@ DROP TABLE IF EXISTS `db_version`; CREATE TABLE `db_version` ( `version` varchar(120) default NULL, - `required_7332_01_mangos_command` bit(1) default NULL + `required_7349_01_mangos_spell_area` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -13288,6 +13288,33 @@ LOCK TABLES `spell_affect` WRITE; /*!40000 ALTER TABLE `spell_affect` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `spell_area` +-- + +DROP TABLE IF EXISTS `spell_area`; +CREATE TABLE `spell_area` ( + `spell` mediumint(8) unsigned NOT NULL default '0', + `area` mediumint(8) unsigned NOT NULL default '0', + `quest_start` mediumint(8) unsigned NOT NULL default '0', + `quest_start_active` tinyint(1) unsigned NOT NULL default '0', + `quest_end` mediumint(8) unsigned NOT NULL default '0', + `aura_spell` mediumint(8) unsigned NOT NULL default '0', + `racemask` mediumint(8) unsigned NOT NULL default '0', + `gender` tinyint(1) unsigned NOT NULL default '2', + `autocast` tinyint(1) unsigned NOT NULL default '0', + PRIMARY KEY (`spell`,`area`,`quest_start`,`quest_start_active`,`aura_spell`,`racemask`,`gender`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `spell_area` +-- + +LOCK TABLES `spell_area` WRITE; +/*!40000 ALTER TABLE `spell_area` DISABLE KEYS */; +/*!40000 ALTER TABLE `spell_area` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `spell_chain` -- diff --git a/sql/updates/7349_01_mangos_spell_area.sql b/sql/updates/7349_01_mangos_spell_area.sql new file mode 100644 index 000000000..969fff950 --- /dev/null +++ b/sql/updates/7349_01_mangos_spell_area.sql @@ -0,0 +1,15 @@ +ALTER TABLE db_version CHANGE COLUMN required_7332_01_mangos_command required_7349_01_mangos_spell_area bit; + +DROP TABLE IF EXISTS `spell_area`; +CREATE TABLE `spell_area` ( + `spell` mediumint(8) unsigned NOT NULL default '0', + `area` mediumint(8) unsigned NOT NULL default '0', + `quest_start` mediumint(8) unsigned NOT NULL default '0', + `quest_start_active` tinyint(1) unsigned NOT NULL default '0', + `quest_end` mediumint(8) unsigned NOT NULL default '0', + `aura_spell` mediumint(8) unsigned NOT NULL default '0', + `racemask` mediumint(8) unsigned NOT NULL default '0', + `gender` tinyint(1) unsigned NOT NULL default '2', + `autocast` tinyint(1) unsigned NOT NULL default '0', + PRIMARY KEY (`spell`,`area`,`quest_start`,`quest_start_active`,`aura_spell`,`racemask`,`gender`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 899b7b430..6f9ec4dd4 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -187,6 +187,7 @@ pkgdata_DATA = \ 7324_02_characters_character_aura.sql \ 7331_01_mangos_command.sql \ 7332_01_mangos_command.sql \ + 7349_01_mangos_spell_area.sql \ README ## Additional files to include when running 'make dist' @@ -354,4 +355,5 @@ EXTRA_DIST = \ 7324_02_characters_character_aura.sql \ 7331_01_mangos_command.sql \ 7332_01_mangos_command.sql \ + 7349_01_mangos_spell_area.sql \ README diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index 4cf9cdbc5..6ed450502 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -309,6 +309,7 @@ ChatCommand * ChatHandler::getCommandTable() { "skill_fishing_base_level", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSkillFishingBaseLevelCommand, "", NULL }, { "skinning_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesSkinningCommand, "", NULL }, { "spell_affect", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellAffectCommand, "", NULL }, + { "spell_area", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellLearnSpellCommand, "", NULL }, { "spell_chain", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellChainCommand, "", NULL }, { "spell_elixir", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellElixirCommand, "", NULL }, { "spell_learn_spell", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellLearnSpellCommand, "", NULL }, diff --git a/src/game/Chat.h b/src/game/Chat.h index 87dd31610..0ab3bd902 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -259,6 +259,7 @@ class ChatHandler bool HandleReloadSkillExtraItemTemplateCommand(const char* args); bool HandleReloadSkillFishingBaseLevelCommand(const char* args); bool HandleReloadSpellAffectCommand(const char* args); + bool HandleReloadSpellAreaCommand(const char* args); bool HandleReloadSpellChainCommand(const char* args); bool HandleReloadSpellElixirCommand(const char* args); bool HandleReloadSpellLearnSpellCommand(const char* args); diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 4a89e25d8..51e840dbe 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -134,6 +134,7 @@ bool ChatHandler::HandleReloadAllSpellCommand(const char*) HandleReloadSkillDiscoveryTemplateCommand("a"); HandleReloadSkillExtraItemTemplateCommand("a"); HandleReloadSpellAffectCommand("a"); + HandleReloadSpellAreaCommand("a"); HandleReloadSpellChainCommand("a"); HandleReloadSpellElixirCommand("a"); HandleReloadSpellLearnSpellCommand("a"); @@ -444,6 +445,14 @@ bool ChatHandler::HandleReloadSpellAffectCommand(const char*) return true; } +bool ChatHandler::HandleReloadSpellAreaCommand(const char*) +{ + sLog.outString( "Re-Loading SpellArea Data..." ); + spellmgr.LoadSpellAreas(); + SendGlobalSysMessage("DB table `spell_area` (spell dependences from area/quest/auras state) reloaded."); + return true; +} + bool ChatHandler::HandleReloadSpellChainCommand(const char*) { sLog.outString( "Re-Loading Spell Chain Data... " ); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index d3f63d42a..aa97aaef2 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -12652,6 +12652,19 @@ void Player::AddQuest( Quest const *pQuest, Object *questGiver ) if(questGiver && pQuest->GetQuestStartScript()!=0) sWorld.ScriptsStart(sQuestStartScripts, pQuest->GetQuestStartScript(), questGiver, this); + // Some spells applied at quest activation + SpellAreaForQuestMapBounds saBounds = spellmgr.GetSpellAreaForQuestMapBounds(quest_id,true); + if(saBounds.first != saBounds.second) + { + uint32 zone = GetZoneId(); + uint32 area = GetAreaId(); + + for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) + if(itr->second->autocast && itr->second->IsFitToRequirements(this,zone,area)) + if( !HasAura(itr->second->spellId,0) ) + CastSpell(this,itr->second->spellId,true); + } + UpdateForQuestsGO(); } @@ -12842,6 +12855,34 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver if (q_status.uState != QUEST_NEW) q_status.uState = QUEST_CHANGED; GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST); + + uint32 zone = 0; + uint32 area = 0; + + // remove auras from spells with quest reward state limitations + SpellAreaForQuestMapBounds saEndBounds = spellmgr.GetSpellAreaForQuestEndMapBounds(quest_id); + if(saEndBounds.first != saEndBounds.second) + { + uint32 zone = GetZoneId(); + uint32 area = GetAreaId(); + + for(SpellAreaForAreaMap::const_iterator itr = saEndBounds.first; itr != saEndBounds.second; ++itr) + if(!itr->second->IsFitToRequirements(this,zone,area)) + RemoveAurasDueToSpell(itr->second->spellId); + } + + // Some spells applied at quest reward + SpellAreaForQuestMapBounds saBounds = spellmgr.GetSpellAreaForQuestMapBounds(quest_id,false); + if(saBounds.first != saBounds.second) + { + if(!zone) zone = GetZoneId(); + if(!area) area = GetAreaId(); + + for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) + if(itr->second->autocast && itr->second->IsFitToRequirements(this,zone,area)) + if( !HasAura(itr->second->spellId,0) ) + CastSpell(this,itr->second->spellId,true); + } } void Player::FailQuest( uint32 quest_id ) @@ -18982,26 +19023,12 @@ void Player::UpdateZoneDependentAuras( uint32 newZone ) RemoveSpellsCausingAura(SPELL_AURA_FLY); } - // Some spells applied at enter into zone (with subzones) - switch(newZone) - { - case 2367: // Old Hillsbrad Foothills - { - // Human Illusion - // NOTE: these are removed by RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CHANGE_MAP); - uint32 spellid = 0; - // all horde races - if( GetTeam() == HORDE ) - spellid = getGender() == GENDER_FEMALE ? 35481 : 35480; - // and some alliance races - else if( getRace() == RACE_NIGHTELF || getRace() == RACE_DRAENEI ) - spellid = getGender() == GENDER_FEMALE ? 35483 : 35482; - - if(spellid && !HasAura(spellid,0) ) - CastSpell(this,spellid,true); - break; - } - } + // Some spells applied at enter into zone (with subzones), aura removed in UpdateAreaDependentAuras that called always at zone->area update + SpellAreaForAreaMapBounds saBounds = spellmgr.GetSpellAreaForAreaMapBounds(newZone); + for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) + if(itr->second->autocast && itr->second->IsFitToRequirements(this,newZone,0)) + if( !HasAura(itr->second->spellId,0) ) + CastSpell(this,itr->second->spellId,true); } void Player::UpdateAreaDependentAuras( uint32 newArea ) @@ -19010,42 +19037,18 @@ void Player::UpdateAreaDependentAuras( uint32 newArea ) for(AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();) { // use m_zoneUpdateId for speed: UpdateArea called from UpdateZone or instead UpdateZone in both cases m_zoneUpdateId up-to-date - if(GetSpellAllowedInLocationError(iter->second->GetSpellProto(),GetMapId(),m_zoneUpdateId,newArea,GetBattleGroundId())!=0) + if(spellmgr.GetSpellAllowedInLocationError(iter->second->GetSpellProto(),GetMapId(),m_zoneUpdateId,newArea,this)!=0) RemoveAura(iter); else ++iter; } // some auras applied at subzone enter - switch(newArea) - { - // Dragonmaw Illusion - case 3759: // Netherwing Ledge - case 3939: // Dragonmaw Fortress - case 3966: // Dragonmaw Base Camp - if( GetDummyAura(40214) ) - { - if( !HasAura(40216,0) ) - CastSpell(this,40216,true); - if( !HasAura(42016,0) ) - CastSpell(this,42016,true); - } - break; - // Dominion Over Acherus - case 4281: // Acherus: The Ebon Hold - case 4342: // Acherus: The Ebon Hold - if( HasSpell(51721) ) - if( !HasAura(51721,0) ) - CastSpell(this,51721,true); - break; - // Mist of the Kvaldir - case 4028: //Riplash Strand - case 4029: //Riplash Ruins - case 4106: //Garrosh's Landing - case 4031: //Pal'ea - CastSpell(this,54119,true); - break; - } + SpellAreaForAreaMapBounds saBounds = spellmgr.GetSpellAreaForAreaMapBounds(newArea); + for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) + if(itr->second->autocast && itr->second->IsFitToRequirements(this,m_zoneUpdateId,newArea)) + if( !HasAura(itr->second->spellId,0) ) + CastSpell(this,itr->second->spellId,true); } uint32 Player::GetCorpseReclaimDelay(bool pvp) const diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 99b3df7b4..9ac30695c 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -3825,8 +3825,8 @@ uint8 Spell::CanCast(bool strict) return SPELL_FAILED_NOT_IN_ARENA; // zone check - if (uint8 res= GetSpellAllowedInLocationError(m_spellInfo,m_caster->GetMapId(),m_caster->GetZoneId(),m_caster->GetAreaId(), - m_caster->GetTypeId()==TYPEID_PLAYER ? ((Player*)m_caster)->GetBattleGroundId() : 0)) + if (uint8 res= spellmgr.GetSpellAllowedInLocationError(m_spellInfo,m_caster->GetMapId(),m_caster->GetZoneId(),m_caster->GetAreaId(), + m_caster->GetTypeId()==TYPEID_PLAYER ? ((Player*)m_caster) : NULL)) return res; // not let players cast spells at mount (and let do it to creatures) diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 01ff8aa57..8f713f38b 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -2062,6 +2062,22 @@ void Aura::HandleAuraDummy(bool apply, bool Real) m_modifier.m_amount = caster->SpellHealingBonus(m_target, GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE); return; } + + // some auras applied at aura apply + if(GetEffIndex()==0 && m_target->GetTypeId()==TYPEID_PLAYER) + { + SpellAreaForAreaMapBounds saBounds = spellmgr.GetSpellAreaForAuraMapBounds(GetId()); + if(saBounds.first != saBounds.second) + { + uint32 zone = m_target->GetZoneId(); + uint32 area = m_target->GetAreaId(); + + for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) + if(itr->second->autocast && itr->second->IsFitToRequirements((Player*)m_target,zone,area)) + if( !m_target->HasAura(itr->second->spellId,0) ) + m_target->CastSpell(m_target,itr->second->spellId,true); + } + } } // AT REMOVE else @@ -2151,6 +2167,21 @@ void Aura::HandleAuraDummy(bool apply, bool Real) } } + + // some auras remove at aura remove + if(GetEffIndex()==0 && m_target->GetTypeId()==TYPEID_PLAYER) + { + SpellAreaForAreaMapBounds saBounds = spellmgr.GetSpellAreaForAuraMapBounds(GetId()); + if(saBounds.first != saBounds.second) + { + uint32 zone = m_target->GetZoneId(); + uint32 area = m_target->GetAreaId(); + + for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) + if(!itr->second->IsFitToRequirements((Player*)m_target,zone,area)) + m_target->RemoveAurasDueToSpell(itr->second->spellId); + } + } } // AT APPLY & REMOVE diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index fcaf501fa..e164f8d05 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -2348,7 +2348,192 @@ bool SpellMgr::IsSpellValid(SpellEntry const* spellInfo, Player* pl, bool msg) return true; } -uint8 GetSpellAllowedInLocationError(SpellEntry const *spellInfo,uint32 map_id,uint32 zone_id,uint32 area_id, uint32 bgInstanceId) +void SpellMgr::LoadSpellAreas() +{ + mSpellAreaMap.clear(); // need for reload case + mSpellAreaForQuestMap.clear(); + mSpellAreaForActiveQuestMap.clear(); + mSpellAreaForQuestEndMap.clear(); + mSpellAreaForAuraMap.clear(); + + uint32 count = 0; + + // 0 1 2 3 4 5 6 7 8 + QueryResult *result = WorldDatabase.Query("SELECT spell, area, quest_start, quest_start_active, quest_end, aura_spell, racemask, gender, autocast FROM spell_area"); + + if( !result ) + { + barGoLink bar( 1 ); + + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded %u spell area requirements", count ); + return; + } + + barGoLink bar( result->GetRowCount() ); + + do + { + Field *fields = result->Fetch(); + + bar.step(); + + uint32 spell = fields[0].GetUInt32(); + SpellArea spellArea; + spellArea.spellId = spell; + spellArea.areaId = fields[1].GetUInt32(); + spellArea.questStart = fields[2].GetUInt32(); + spellArea.questStartCanActive = fields[3].GetBool(); + spellArea.questEnd = fields[4].GetUInt32(); + spellArea.auraSpell = fields[5].GetUInt32(); + spellArea.raceMask = fields[6].GetUInt32(); + spellArea.gender = Gender(fields[7].GetUInt8()); + + if(!sSpellStore.LookupEntry(spell)) + { + sLog.outErrorDb("Spell %u listed in `spell_area` does not exist", spell); + continue; + } + + if(mSpellAreaForAuraMap.find(spellArea.spellId)!=mSpellAreaForAuraMap.end()) + { + sLog.outErrorDb("Spell %u listed in `spell_area` have aura spell (%u) requirement that already listed in table itself", spell,spellArea.auraSpell); + continue; + } + + if(spellArea.areaId && !GetAreaEntryByAreaID(spellArea.areaId)) + { + sLog.outErrorDb("Spell %u listed in `spell_area` have wrong area (%u) requirement", spell,spellArea.areaId); + continue; + } + + if(spellArea.questStart && !objmgr.GetQuestTemplate(spellArea.questStart)) + { + sLog.outErrorDb("Spell %u listed in `spell_area` have wrong start quest (%u) requirement", spell,spellArea.questStart); + continue; + } + + if(spellArea.questEnd) + { + if(!objmgr.GetQuestTemplate(spellArea.questEnd)) + { + sLog.outErrorDb("Spell %u listed in `spell_area` have wrong end quest (%u) requirement", spell,spellArea.questEnd); + continue; + } + + if(spellArea.questEnd==spellArea.questStart && !spellArea.questStartCanActive) + { + sLog.outErrorDb("Spell %u listed in `spell_area` have quest (%u) requirement for start and end in same time", spell,spellArea.questEnd); + continue; + } + } + + if(spellArea.auraSpell) + { + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellArea.auraSpell); + if(!spellInfo) + { + sLog.outErrorDb("Spell %u listed in `spell_area` have wrong aura spell (%u) requirement", spell,spellArea.auraSpell); + continue; + } + + if(spellInfo->EffectApplyAuraName[0]!=SPELL_AURA_DUMMY) + { + sLog.outErrorDb("Spell %u listed in `spell_area` have aura spell requirement (%u) without dummy aura in effect 0", spell,spellArea.auraSpell); + continue; + } + + if(spellArea.auraSpell==spellArea.spellId) + { + sLog.outErrorDb("Spell %u listed in `spell_area` have aura spell (%u) requirement for itself", spell,spellArea.auraSpell); + continue; + } + + // not allow autocast chains by auraSpell field + if(spellArea.autocast) + { + bool chain = false; + SpellAreaForAuraMapBounds saBound = GetSpellAreaForAuraMapBounds(spellArea.spellId); + for(SpellAreaForAuraMap::const_iterator itr = saBound.first; itr != saBound.second; ++itr) + { + if(itr->second->autocast) + { + chain = true; + break; + } + } + + if(chain) + { + sLog.outErrorDb("Spell %u listed in `spell_area` have aura spell (%u) requirement that itself autocast from aura", spell,spellArea.auraSpell); + continue; + } + + SpellAreaMapBounds saBound2 = GetSpellAreaMapBounds(spellArea.auraSpell); + for(SpellAreaMap::const_iterator itr2 = saBound2.first; itr2 != saBound2.second; ++itr2) + { + if(itr2->second.autocast && itr2->second.auraSpell) + { + chain = true; + break; + } + } + + if(chain) + { + sLog.outErrorDb("Spell %u listed in `spell_area` have aura spell (%u) requirement that itself autocast from aura", spell,spellArea.auraSpell); + continue; + } + } + } + + if(spellArea.raceMask && (spellArea.raceMask & RACEMASK_ALL_PLAYABLE)==0) + { + sLog.outErrorDb("Spell %u listed in `spell_area` have wrong race mask (%u) requirement", spell,spellArea.raceMask); + continue; + } + + if(spellArea.gender!=GENDER_NONE && spellArea.gender!=GENDER_FEMALE && spellArea.gender!=GENDER_MALE) + { + sLog.outErrorDb("Spell %u listed in `spell_area` have wrong gender (%u) requirement", spell,spellArea.gender); + continue; + } + + SpellArea const* sa = &mSpellAreaMap.insert(SpellAreaMap::value_type(spell,spellArea))->second; + + // for search by current zone/subzone at zone/subzone change + if(spellArea.areaId) + mSpellAreaForAreaMap.insert(SpellAreaForAreaMap::value_type(spellArea.areaId,sa)); + + // for search at quest start/reward + if(spellArea.questStart) + { + if(spellArea.questStartCanActive) + mSpellAreaForActiveQuestMap.insert(SpellAreaForQuestMap::value_type(spellArea.questStart,sa)); + else + mSpellAreaForQuestMap.insert(SpellAreaForQuestMap::value_type(spellArea.questStart,sa)); + } + + // for search at quest start/reward + if(spellArea.questEnd) + mSpellAreaForQuestEndMap.insert(SpellAreaForQuestMap::value_type(spellArea.questEnd,sa)); + + // for search at aura apply + if(spellArea.auraSpell) + mSpellAreaForAuraMap.insert(SpellAreaForAuraMap::value_type(spellArea.auraSpell,sa)); + + ++count; + } while( result->NextRow() ); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u spell area requirements", count ); +} + +uint8 SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spellInfo, uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player) { // normal case if( spellInfo->AreaGroupId > 0) @@ -2367,75 +2552,26 @@ uint8 GetSpellAllowedInLocationError(SpellEntry const *spellInfo,uint32 map_id,u return SPELL_FAILED_INCORRECT_AREA; } - // elixirs (all area dependent elixirs have family SPELLFAMILY_POTION, use this for speedup) - if(spellInfo->SpellFamilyName==SPELLFAMILY_POTION) + // DB base check (if non empty then must fit at least single for allow) + SpellAreaMapBounds saBounds = spellmgr.GetSpellAreaMapBounds(spellInfo->Id); + if(saBounds.first != saBounds.second) { - if(uint32 mask = spellmgr.GetSpellElixirMask(spellInfo->Id)) + for(SpellAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) { - if(mask & ELIXIR_BATTLE_MASK) - { - if(spellInfo->Id==45373) // Bloodberry Elixir - return zone_id==4075 ? 0 : SPELL_FAILED_REQUIRES_AREA; - } - if(mask & ELIXIR_UNSTABLE_MASK) - { - // in the Blade's Edge Mountains Plateaus and Gruul's Lair. - return zone_id ==3522 || map_id==565 ? 0 : SPELL_FAILED_INCORRECT_AREA; - } - if(mask & ELIXIR_SHATTRATH_MASK) - { - // in Tempest Keep, Serpentshrine Cavern, Caverns of Time: Mount Hyjal, Black Temple, Sunwell Plateau - if(zone_id ==3607 || map_id==534 || map_id==564 || zone_id==4075) - return 0; - - MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); - if(!mapEntry) - return SPELL_FAILED_INCORRECT_AREA; - - return mapEntry->multimap_id==206 ? 0 : SPELL_FAILED_INCORRECT_AREA; - } - - // elixirs not have another limitations - return 0; + if(itr->second.IsFitToRequirements(player,zone_id,area_id)) + return 0; } + return SPELL_FAILED_INCORRECT_AREA; } - // special cases zone check (maps checked by multimap common id) + // bg spell checks switch(spellInfo->Id) { - case 41618: // Bottled Nethergon Energy - case 41620: // Bottled Nethergon Vapor - { - MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); - if(!mapEntry) - return SPELL_FAILED_INCORRECT_AREA; - - return mapEntry->multimap_id==206 ? 0 : SPELL_FAILED_REQUIRES_AREA; - } - case 41617: // Cenarion Mana Salve - case 41619: // Cenarion Healing Salve - { - MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); - if(!mapEntry) - return SPELL_FAILED_INCORRECT_AREA; - - return mapEntry->multimap_id==207 ? 0 : SPELL_FAILED_REQUIRES_AREA; - } - case 40216: // Dragonmaw Illusion - case 42016: // Dragonmaw Illusion - return area_id == 3759 || area_id == 3966 || area_id == 3939 ? 0 : SPELL_FAILED_INCORRECT_AREA; - case 51721: // Dominion Over Acherus - case 54055: // Dominion Over Acherus - return area_id == 4281 || area_id == 4342 ? 0 : SPELL_FAILED_INCORRECT_AREA; - case 51852: // The Eye of Acherus - return map_id == 609 ? 0 : SPELL_FAILED_REQUIRES_AREA; - case 54119: // Mist of the Kvaldir - return area_id == 4028 || area_id == 4029 || area_id == 4106 || area_id == 4031 ? 0 : SPELL_FAILED_INCORRECT_AREA; case 23333: // Warsong Flag case 23335: // Silverwing Flag - return map_id == 489 && bgInstanceId ? 0 : SPELL_FAILED_REQUIRES_AREA; + return map_id == 489 && player && player->InBattleGround() ? 0 : SPELL_FAILED_REQUIRES_AREA; case 34976: // Netherstorm Flag - return map_id == 566 && bgInstanceId ? 0 : SPELL_FAILED_REQUIRES_AREA; + return map_id == 566 && player && player->InBattleGround() ? 0 : SPELL_FAILED_REQUIRES_AREA; case 2584: // Waiting to Resurrect case 22011: // Spirit Heal Channel case 22012: // Spirit Heal @@ -2448,11 +2584,11 @@ uint8 GetSpellAllowedInLocationError(SpellEntry const *spellInfo,uint32 map_id,u if(!mapEntry) return SPELL_FAILED_INCORRECT_AREA; - return mapEntry->IsBattleGround() && bgInstanceId ? 0 : SPELL_FAILED_REQUIRES_AREA; + return mapEntry->IsBattleGround() && player && player->InBattleGround() ? 0 : SPELL_FAILED_REQUIRES_AREA; } case 44521: // Preparation { - if(!bgInstanceId) + if(!player) return SPELL_FAILED_REQUIRES_AREA; MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); @@ -2462,7 +2598,7 @@ uint8 GetSpellAllowedInLocationError(SpellEntry const *spellInfo,uint32 map_id,u if(!mapEntry->IsBattleGround()) return SPELL_FAILED_REQUIRES_AREA; - BattleGround* bg = sBattleGroundMgr.GetBattleGround(bgInstanceId); + BattleGround* bg = player->GetBattleGround(); return bg && bg->GetStatus()==STATUS_WAIT_JOIN ? 0 : SPELL_FAILED_REQUIRES_AREA; } case 32724: // Gold Team (Alliance) @@ -2474,11 +2610,11 @@ uint8 GetSpellAllowedInLocationError(SpellEntry const *spellInfo,uint32 map_id,u if(!mapEntry) return SPELL_FAILED_INCORRECT_AREA; - return mapEntry->IsBattleArena() && bgInstanceId ? 0 : SPELL_FAILED_REQUIRES_AREA; + return mapEntry->IsBattleArena() && player && player->InBattleGround() ? 0 : SPELL_FAILED_REQUIRES_AREA; } case 32727: // Arena Preparation { - if(!bgInstanceId) + if(!player) return SPELL_FAILED_REQUIRES_AREA; MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); @@ -2488,7 +2624,7 @@ uint8 GetSpellAllowedInLocationError(SpellEntry const *spellInfo,uint32 map_id,u if(!mapEntry->IsBattleArena()) return SPELL_FAILED_REQUIRES_AREA; - BattleGround* bg = sBattleGroundMgr.GetBattleGround(bgInstanceId); + BattleGround* bg = player->GetBattleGround(); return bg && bg->GetStatus()==STATUS_WAIT_JOIN ? 0 : SPELL_FAILED_REQUIRES_AREA; } } @@ -2632,3 +2768,50 @@ DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group) return DRTYPE_NONE; } + +bool SpellArea::IsFitToRequirements(Player const* player, uint32 newZone, uint32 newArea) const +{ + if(gender!=GENDER_NONE) + { + // not in expected gender + if(!player || gender != player->getGender()) + return false; + } + + if(raceMask) + { + // not in expected race + if(!player || !(raceMask & player->getRaceMask())) + return false; + } + + if(areaId) + { + // not in expected zone + if(newZone!=areaId && newArea!=areaId) + return false; + } + + if(questStart) + { + // not in expected required quest state + if(!player || (!questStartCanActive || !player->IsActiveQuest(questStart)) && !player->GetQuestRewardStatus(questStart)) + return false; + } + + if(questEnd) + { + // not in expected forbidden quest state + if(!player || player->GetQuestRewardStatus(questEnd)) + return false; + } + + if(auraSpell) + { + // not have expected aura + if(!player || !player->HasAura(auraSpell,0)) + return false; + } + + return true; +} diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 5522337fa..157981d5c 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -355,8 +355,6 @@ bool IsSingleTargetSpells(SpellEntry const *spellInfo1, SpellEntry const *spellI bool IsAuraAddedBySpell(uint32 auraType, uint32 spellId); -uint8 GetSpellAllowedInLocationError(SpellEntry const *spellInfo,uint32 map_id,uint32 zone_id,uint32 area_id,uint32 bgInstanceId); - inline bool IsAreaEffectTarget( Targets target ) { switch (target ) @@ -679,6 +677,32 @@ class PetAura }; typedef std::map SpellPetAuraMap; +struct SpellArea +{ + uint32 spellId; + uint32 areaId; // zone/subzone/or 0 is not limited to zone + uint32 questStart; // quest start (quest must be active or rewarded for spell apply) + uint32 questEnd; // quest end (quest don't must be rewarded for spell apply) + uint32 auraSpell; // spell aura must be applied for spell apply + uint32 raceMask; // can be applied only to races + Gender gender; // can be applied only to gender + bool questStartCanActive; // if true then quest start can be active (not only rewarded) + bool autocast; // if true then auto applied at area enter, in other case just allowed to cast + + // helpers + bool IsFitToRequirements(Player const* player, uint32 newZone, uint32 newArea) const; +}; + +typedef std::multimap SpellAreaMap; +typedef std::multimap SpellAreaForQuestMap; +typedef std::multimap SpellAreaForAuraMap; +typedef std::multimap SpellAreaForAreaMap; +typedef std::pair SpellAreaMapBounds; +typedef std::pair SpellAreaForQuestMapBounds; +typedef std::pair SpellAreaForAuraMapBounds; +typedef std::pair SpellAreaForAreaMapBounds; + + // Spell rank chain (accessed using SpellMgr functions) struct SpellChainNode { @@ -965,6 +989,36 @@ class SpellMgr return NULL; } + uint8 GetSpellAllowedInLocationError(SpellEntry const *spellInfo, uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player = NULL); + + SpellAreaMapBounds GetSpellAreaMapBounds(uint32 spell_id) const + { + return SpellAreaMapBounds(mSpellAreaMap.lower_bound(spell_id),mSpellAreaMap.upper_bound(spell_id)); + } + + SpellAreaForQuestMapBounds GetSpellAreaForQuestMapBounds(uint32 quest_id, bool active) const + { + if(active) + return SpellAreaForQuestMapBounds(mSpellAreaForActiveQuestMap.lower_bound(quest_id),mSpellAreaForActiveQuestMap.upper_bound(quest_id)); + else + return SpellAreaForQuestMapBounds(mSpellAreaForQuestMap.lower_bound(quest_id),mSpellAreaForQuestMap.upper_bound(quest_id)); + } + + SpellAreaForQuestMapBounds GetSpellAreaForQuestEndMapBounds(uint32 quest_id) const + { + return SpellAreaForQuestMapBounds(mSpellAreaForQuestEndMap.lower_bound(quest_id),mSpellAreaForQuestEndMap.upper_bound(quest_id)); + } + + SpellAreaForAuraMapBounds GetSpellAreaForAuraMapBounds(uint32 spell_id) const + { + return SpellAreaForAuraMapBounds(mSpellAreaForAuraMap.lower_bound(spell_id),mSpellAreaForAuraMap.upper_bound(spell_id)); + } + + SpellAreaForAreaMapBounds GetSpellAreaForAreaMapBounds(uint32 area_id) const + { + return SpellAreaForAreaMapBounds(mSpellAreaForAreaMap.lower_bound(area_id),mSpellAreaForAreaMap.upper_bound(area_id)); + } + // Modifiers public: static SpellMgr& Instance(); @@ -983,6 +1037,7 @@ class SpellMgr void LoadSkillLineAbilityMap(); void LoadSpellPetAuras(); void LoadPetLevelupSpellMap(); + void LoadSpellAreas(); private: SpellScriptTarget mSpellScriptTarget; @@ -998,6 +1053,12 @@ class SpellMgr SkillLineAbilityMap mSkillLineAbilityMap; SpellPetAuraMap mSpellPetAuraMap; PetLevelupSpellMap mPetLevelupSpellMap; + SpellAreaMap mSpellAreaMap; + SpellAreaForQuestMap mSpellAreaForQuestMap; + SpellAreaForQuestMap mSpellAreaForActiveQuestMap; + SpellAreaForQuestMap mSpellAreaForQuestEndMap; + SpellAreaForAuraMap mSpellAreaForAuraMap; + SpellAreaForAreaMap mSpellAreaForAreaMap; }; #define spellmgr SpellMgr::Instance() diff --git a/src/game/World.cpp b/src/game/World.cpp index 38d0e9f87..8b04917a7 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -1202,6 +1202,9 @@ void World::SetInitialWorldSettings() sLog.outString( ">>> Quests Relations loaded" ); sLog.outString(); + sLog.outString( "Loading SpellArea Data..." ); // must be after quest load + spellmgr.LoadSpellAreas(); + sLog.outString( "Loading AreaTrigger definitions..." ); objmgr.LoadAreaTriggerTeleports(); // must be after item template load diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index ede9681cf..201f685b2 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7348" + #define REVISION_NR "7349" #endif // __REVISION_NR_H__ From 95439564aa88b752a91969065c350fe0c004a241 Mon Sep 17 00:00:00 2001 From: zhenya Date: Fri, 27 Feb 2009 12:53:07 +0300 Subject: [PATCH 21/32] [7350] Use more compact and fast way for check class/race achievement. Signed-off-by: VladimirMangos --- src/game/AchievementMgr.cpp | 33 +++++++++------------------------ src/shared/revision_nr.h | 2 +- 2 files changed, 10 insertions(+), 25 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 83a6302bc..52adc738a 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -86,7 +86,6 @@ const CriteriaCastSpellRequirement AchievementGlobalMgr::m_criteriaCastSpellRequ {6662, 31261, 0, 0} }; - namespace MaNGOS { class AchievementChatBuilder @@ -727,6 +726,9 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui } } +static const uint32 achievIdByClass[MAX_CLASSES] = { 0, 459, 465 , 462, 458, 464, 461, 467, 460, 463, 0, 466 }; +static const uint32 achievIdByRace[MAX_RACES] = { 0, 1408, 1410, 1407, 1409, 1413, 1411, 1404, 1412, 0, 1405, 1406 }; + bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achievementCriteria) { AchievementEntry const* achievement = sAchievementStore.LookupEntry(achievementCriteria->referredAchievement); @@ -753,29 +755,12 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve switch(achievementCriteria->requiredType) { case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL: - if ((achievement->ID == 467 && GetPlayer()->getClass() != CLASS_SHAMAN ) || - (achievement->ID == 466 && GetPlayer()->getClass() != CLASS_DRUID ) || - (achievement->ID == 465 && GetPlayer()->getClass() != CLASS_PALADIN ) || - (achievement->ID == 464 && GetPlayer()->getClass() != CLASS_PRIEST ) || - (achievement->ID == 463 && GetPlayer()->getClass() != CLASS_WARLOCK ) || - (achievement->ID == 462 && GetPlayer()->getClass() != CLASS_HUNTER ) || - (achievement->ID == 461 && GetPlayer()->getClass() != CLASS_DEATH_KNIGHT)|| - (achievement->ID == 460 && GetPlayer()->getClass() != CLASS_MAGE ) || - (achievement->ID == 459 && GetPlayer()->getClass() != CLASS_WARRIOR ) || - (achievement->ID == 458 && GetPlayer()->getClass() != CLASS_ROGUE ) || - - (achievement->ID == 1404 && GetPlayer()->getRace() != RACE_GNOME ) || - (achievement->ID == 1405 && GetPlayer()->getRace() != RACE_BLOODELF ) || - (achievement->ID == 1406 && GetPlayer()->getRace() != RACE_DRAENEI ) || - (achievement->ID == 1407 && GetPlayer()->getRace() != RACE_DWARF ) || - (achievement->ID == 1408 && GetPlayer()->getRace() != RACE_HUMAN ) || - (achievement->ID == 1409 && GetPlayer()->getRace() != RACE_NIGHTELF ) || - (achievement->ID == 1410 && GetPlayer()->getRace() != RACE_ORC ) || - (achievement->ID == 1411 && GetPlayer()->getRace() != RACE_TAUREN ) || - (achievement->ID == 1412 && GetPlayer()->getRace() != RACE_TROLL ) || - (achievement->ID == 1413 && GetPlayer()->getRace() != RACE_UNDEAD_PLAYER) ) - return false; - return progress->counter >= achievementCriteria->reach_level.level; + { + if (achievIdByClass[GetPlayer()->getClass()] == achievement->ID || + achievIdByRace[GetPlayer()->getRace()] == achievement->ID) + return progress->counter >= achievementCriteria->reach_level.level; + return false; + } case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT: return progress->counter >= achievementCriteria->buy_bank_slot.numberOfSlots; case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE: diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 201f685b2..2476662f6 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7349" + #define REVISION_NR "7350" #endif // __REVISION_NR_H__ From 3560d9de544d37330c833029ec57f24b5df61038 Mon Sep 17 00:00:00 2001 From: Triply Date: Fri, 27 Feb 2009 11:08:57 +0100 Subject: [PATCH 22/32] [7351] Fixed removing normal horde groups from queue. Fixed Reflective shield - patch provided by Rastik. Thx Signed-off-by: Triply --- src/game/BattleGround.cpp | 2 +- src/game/BattleGroundMgr.cpp | 8 ++------ src/game/MovementHandler.cpp | 1 - src/game/Unit.cpp | 1 - src/shared/revision_nr.h | 2 +- 5 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 9c165803a..76475bacb 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -815,7 +815,7 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac DecreaseInvitedCount(team); //we should update battleground queue, but only if bg isn't ending - if (GetQueueId() < MAX_BATTLEGROUND_QUEUES) + if (GetStatus() < STATUS_WAIT_LEAVE) sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, GetQueueId()); Group * group = plr->GetGroup(); diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index af56787db..9439dff57 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -208,7 +208,7 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou { //we must check premade and normal team's queue - because when players from premade are joining bg, //they leave groupinfo so we can't use its players size to find out index - for (uint32 j = index; j < BG_QUEUE_GROUP_TYPES_COUNT - 1; j += BG_QUEUE_NORMAL_ALLIANCE) + for (uint32 j = index; j < BG_QUEUE_GROUP_TYPES_COUNT; j += BG_QUEUE_NORMAL_ALLIANCE) { for(group_itr_tmp = m_QueuedGroups[queue_id_tmp][j].begin(); group_itr_tmp != m_QueuedGroups[queue_id_tmp][j].end(); ++group_itr_tmp) { @@ -628,11 +628,7 @@ should be called from BattleGround::RemovePlayer function in some cases */ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id, uint8 arenaType, bool isRated, uint32 arenaRating) { - // this can happen when removing last player from battleground - if( queue_id == MAX_BATTLEGROUND_QUEUES ) - return; - - //if no players in queue ... do nothing + //if no players in queue - do nothing if( m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].empty() && m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].empty() && m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE].empty() && diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index 9dc84d62f..0cbeff0fe 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -87,7 +87,6 @@ void WorldSession::HandleMoveWorldportAckOpcode() return; } - //this will set player's team ... so IT MUST BE CALLED BEFORE SendInitialPacketsAfterAddToMap() // battleground state prepare (in case join to BG), at relogin/tele player not invited // only add to bg group and object, if the player was invited (else he entered through command) if(_player->InBattleGround()) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index d01837c09..6d5c8ce9d 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -1730,7 +1730,6 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe Unit* caster = (*i)->GetCaster(); if (!caster) break; - int32 reflectDamage = 0; AuraList const& vOverRideCS = caster->GetAurasByType(SPELL_AURA_DUMMY); for(AuraList::const_iterator k = vOverRideCS.begin(); k != vOverRideCS.end(); ++k) { diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 2476662f6..31229f629 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7350" + #define REVISION_NR "7351" #endif // __REVISION_NR_H__ From 0be003ac903ae328e96a69495be54667780cbdb7 Mon Sep 17 00:00:00 2001 From: Triply Date: Fri, 27 Feb 2009 11:56:38 +0100 Subject: [PATCH 23/32] [7352] Fixed conditions in FillPlayersToBG to correctly kick group only when other team's selection pool is empty. Problem reported by balrok. Thx Signed-off-by: Triply --- src/game/BattleGroundMgr.cpp | 4 ++++ src/game/Player.cpp | 2 +- src/shared/revision_nr.h | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index 9439dff57..4db76c358 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -495,9 +495,11 @@ void BattleGroundQueue::FillPlayersToBG(BattleGround* bg, BGQueueIdBasedOnLevel } //if ali selection is already empty, then kick horde group, but if there are less horde than ali in bg - break; if( !m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() ) + { if( aliFree <= diffHorde - 1 ) break; m_SelectionPools[BG_TEAM_HORDE].KickGroup(diffHorde - diffAli); + } } else { @@ -508,9 +510,11 @@ void BattleGroundQueue::FillPlayersToBG(BattleGround* bg, BGQueueIdBasedOnLevel ++Horde_itr; } if( !m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() ) + { if( hordeFree <= diffAli - 1 ) break; m_SelectionPools[BG_TEAM_ALLIANCE].KickGroup(diffAli - diffHorde); + } } //count diffs after small update diffAli = aliFree - m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount(); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index aa97aaef2..160fe02c9 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -18519,7 +18519,7 @@ BGQueueIdBasedOnLevel Player::GetBattleGroundQueueIdFromLevel(BattleGroundTypeId { //returned to hardcoded version of this function, because there is no way to code it dynamic uint32 level = getLevel(); - if( bgTypeId == BATTLEGROUND_QUEUE_AV ) + if( bgTypeId == BATTLEGROUND_AV ) level--; uint32 queue_id = (level / 10) - 1; // for ranges 0 - 19, 20 - 29, 30 - 39, 40 - 49, 50 - 59, 60 - 69, 70 -79, 80 diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 31229f629..8e9b6a0b2 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7351" + #define REVISION_NR "7352" #endif // __REVISION_NR_H__ From a81d174288a7b152f5c37b40471d605d9a69012f Mon Sep 17 00:00:00 2001 From: Triply Date: Fri, 27 Feb 2009 14:20:31 +0100 Subject: [PATCH 24/32] [7353] Fixed problem with joining rated arena matches. Thanks to balrok for help. Signed-off-by: Triply --- src/game/BattleGround.cpp | 6 +-- src/game/BattleGroundHandler.cpp | 10 ++-- src/game/BattleGroundMgr.cpp | 91 ++++++++++++++++++++------------ src/game/BattleGroundMgr.h | 32 +++++------ src/game/Level1.cpp | 4 +- src/game/MovementHandler.cpp | 2 +- src/game/Player.cpp | 9 ++-- src/game/Player.h | 14 +++-- src/game/SharedDefines.h | 1 + src/shared/revision_nr.h | 2 +- 10 files changed, 99 insertions(+), 72 deletions(-) diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 76475bacb..530ec6b3e 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -115,7 +115,7 @@ BattleGround::~BattleGround() // remove from battlegrounds } - sBattleGroundMgr.RemoveBattleGround(GetInstanceID()); + sBattleGroundMgr.RemoveBattleGround(GetInstanceID(), GetTypeID()); // unload map if(Map * map = MapManager::Instance().FindMap(GetMapId(), GetInstanceID())) if(map->IsBattleGroundOrArena()) @@ -835,7 +835,7 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac } // Do next only if found in battleground - plr->SetBattleGroundId(0); // We're not in BG. + plr->SetBattleGroundId(0, BATTLEGROUND_TYPE_NONE); // We're not in BG. // reset destination bg team plr->SetBGTeam(0); @@ -1010,7 +1010,7 @@ void BattleGround::RemoveFromBGFreeSlotQueue() // set to be able to re-add if needed m_InBGFreeSlotQueue = false; // uncomment this code when battlegrounds will work like instances - for (std::deque::iterator itr = sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].end(); ++itr) + for (BGFreeSlotQueueType::iterator itr = sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].end(); ++itr) { if ((*itr)->GetInstanceID() == m_InstanceID) { diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp index df4eee36e..0098490e1 100644 --- a/src/game/BattleGroundHandler.cpp +++ b/src/game/BattleGroundHandler.cpp @@ -113,7 +113,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) // get bg instance or bg template if instance not found BattleGround * bg = 0; if(instanceId) - BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId); + BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId, bgTypeId); if(!bg && !(bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId))) { @@ -345,7 +345,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data ) else { // get the bg we're invited to - BattleGround * bg = sBattleGroundMgr.GetBattleGround(itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID); + BattleGround * bg = sBattleGroundMgr.GetBattleGround(itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID, bgTypeId); status = STATUS_WAIT_JOIN; } @@ -387,7 +387,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data ) return; } - BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId); + BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId, bgTypeId); // bg template might and must be used in case of leaving queue, when instance is not created yet if(!bg && action == 0) @@ -456,11 +456,11 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data ) currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true); // set the destination instance id - _player->SetBattleGroundId(bg->GetInstanceID()); + _player->SetBattleGroundId(bg->GetInstanceID(), bgTypeId); // set the destination team _player->SetBGTeam(team); // bg->HandleBeforeTeleportToBattleGround(_player); - sBattleGroundMgr.SendToBattleGround(_player, instanceId); + sBattleGroundMgr.SendToBattleGround(_player, instanceId, bgTypeId); // add only in HandleMoveWorldPortAck() // bg->AddPlayer(_player,team); sLog.outDebug("Battleground: player %s (%u) joined battle for bg %u, bgtype %u, queue type %u.",_player->GetName(),_player->GetGUIDLow(),bg->GetInstanceID(),bg->GetTypeID(),bgQueueTypeId); diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index 4db76c358..9ad37f7b1 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -244,7 +244,7 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou // if invited to bg, and should decrease invited count, then do it if( decreaseInvitedCount && group->IsInvitedToBGInstanceGUID ) { - BattleGround* bg = sBattleGroundMgr.GetBattleGround(group->IsInvitedToBGInstanceGUID); + BattleGround* bg = sBattleGroundMgr.GetBattleGround(group->IsInvitedToBGInstanceGUID, group->BgTypeId); if( bg ) bg->DecreaseInvitedCount(group->Team); } @@ -368,7 +368,7 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b continue; // invite the player - sBattleGroundMgr.InvitePlayer(plr, bg->GetInstanceID(), ginfo->Team); + sBattleGroundMgr.InvitePlayer(plr, bg->GetInstanceID(), bg->GetTypeID(), ginfo->Team); WorldPacket data; @@ -916,7 +916,7 @@ bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) // Player can be in another BG queue and must be removed in normal way in any case - BattleGround* bg = sBattleGroundMgr.GetBattleGround(m_BgInstanceGUID); + BattleGround* bg = sBattleGroundMgr.GetBattleGround(m_BgInstanceGUID, m_BgTypeId); if (!bg) return true; @@ -950,7 +950,7 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) // player logged off (we should do nothing, he is correctly removed from queue in another procedure) return true; - BattleGround* bg = sBattleGroundMgr.GetBattleGround(m_BgInstanceGUID); + BattleGround* bg = sBattleGroundMgr.GetBattleGround(m_BgInstanceGUID, m_BgTypeId); if (!bg) return true; @@ -1002,7 +1002,8 @@ void BGQueueRemoveEvent::Abort(uint64 /*e_time*/) BattleGroundMgr::BattleGroundMgr() : m_AutoDistributionTimeChecker(0), m_ArenaTesting(false) { - m_BattleGrounds.clear(); + for(uint32 i = BATTLEGROUND_TYPE_NONE; i < MAX_BATTLEGROUND_TYPE_ID; i++) + m_BattleGrounds[i].clear(); m_NextRatingDiscardUpdate = sWorld.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER); m_Testing=false; } @@ -1014,11 +1015,14 @@ BattleGroundMgr::~BattleGroundMgr() void BattleGroundMgr::DeleteAlllBattleGrounds() { - for(BattleGroundSet::iterator itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end();) + for(uint32 i = BATTLEGROUND_TYPE_NONE; i < MAX_BATTLEGROUND_TYPE_ID; i++) { - BattleGround * bg = itr->second; - m_BattleGrounds.erase(itr++); - delete bg; + for(BattleGroundSet::iterator itr = m_BattleGrounds[i].begin(); itr != m_BattleGrounds[i].end();) + { + BattleGround * bg = itr->second; + m_BattleGrounds[i].erase(itr++); + delete bg; + } } // destroy template battlegrounds that listed only in queues (other already terminated) @@ -1034,18 +1038,21 @@ void BattleGroundMgr::DeleteAlllBattleGrounds() void BattleGroundMgr::Update(uint32 diff) { BattleGroundSet::iterator itr, next; - for(itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); itr = next) + for(uint32 i = BATTLEGROUND_TYPE_NONE; i < MAX_BATTLEGROUND_TYPE_ID; i++) { - next = itr; - ++next; - itr->second->Update(diff); - // use the SetDeleteThis variable - // direct deletion caused crashes - if(itr->second->m_SetDeleteThis) + for(itr = m_BattleGrounds[i].begin(); itr != m_BattleGrounds[i].end(); itr = next) { - BattleGround * bg = itr->second; - m_BattleGrounds.erase(itr); - delete bg; + next = itr; + ++next; + itr->second->Update(diff); + // use the SetDeleteThis variable + // direct deletion caused crashes + if(itr->second->m_SetDeleteThis) + { + BattleGround * bg = itr->second; + m_BattleGrounds[i].erase(itr); + delete bg; + } } } // if rating difference counts, maybe force-update queues @@ -1322,10 +1329,10 @@ void BattleGroundMgr::BuildPlayerJoinedBattleGroundPacket(WorldPacket *data, Pla *data << uint64(plr->GetGUID()); } -void BattleGroundMgr::InvitePlayer(Player* plr, uint32 bgInstanceGUID, uint32 team) +void BattleGroundMgr::InvitePlayer(Player* plr, uint32 bgInstanceGUID, BattleGroundTypeId bgTypeId, uint32 team) { // set invited player counters: - BattleGround* bg = GetBattleGround(bgInstanceGUID); + BattleGround* bg = GetBattleGround(bgInstanceGUID, bgTypeId); if(!bg) return; bg->IncreaseInvitedCount(team); @@ -1353,15 +1360,34 @@ void BattleGroundMgr::InvitePlayer(Player* plr, uint32 bgInstanceGUID, uint32 te // create invite events: //add events to player's counters ---- this is not good way - there should be something like global event processor, where we should add those events - BGQueueInviteEvent* inviteEvent = new BGQueueInviteEvent(plr->GetGUID(), bgInstanceGUID); + BGQueueInviteEvent* inviteEvent = new BGQueueInviteEvent(plr->GetGUID(), bgInstanceGUID, bgTypeId); plr->m_Events.AddEvent(inviteEvent, plr->m_Events.CalculateTime(INVITATION_REMIND_TIME)); - BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(plr->GetGUID(), bgInstanceGUID, team); + BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(plr->GetGUID(), bgInstanceGUID, bgTypeId, team); plr->m_Events.AddEvent(removeEvent, plr->m_Events.CalculateTime(INVITE_ACCEPT_WAIT_TIME)); } +BattleGround * BattleGroundMgr::GetBattleGround(uint32 InstanceID, BattleGroundTypeId bgTypeId) +{ + //search if needed + BattleGroundSet::iterator itr; + if( bgTypeId == BATTLEGROUND_TYPE_NONE) + { + for(uint32 i = BATTLEGROUND_AV; i < MAX_BATTLEGROUND_TYPE_ID; i++) + { + itr = m_BattleGrounds[i].find(InstanceID); + if( itr != m_BattleGrounds[i].end() ) + return itr->second; + } + return NULL; + } + itr = m_BattleGrounds[bgTypeId].find(InstanceID); + return ( (itr != m_BattleGrounds[bgTypeId].end()) ? itr->second : NULL ); +} + BattleGround * BattleGroundMgr::GetBattleGroundTemplate(BattleGroundTypeId bgTypeId) { - return BGFreeSlotQueue[bgTypeId].empty() ? NULL : BGFreeSlotQueue[bgTypeId].back(); + //map is sorted and we can be sure that lowest instance id has only BG template + return m_BattleGrounds[bgTypeId].empty() ? NULL : m_BattleGrounds[bgTypeId].begin()->second; } // create a new battleground that will really be used to play @@ -1458,7 +1484,7 @@ BattleGround * BattleGroundMgr::CreateNewBattleGround(BattleGroundTypeId bgTypeI bg->AddToBGFreeSlotQueue(); // add bg to update list - AddBattleGround(bg->GetInstanceID(), bg); + AddBattleGround(bg->GetInstanceID(), bg->GetTypeID(), bg); return bg; } @@ -1485,9 +1511,6 @@ uint32 BattleGroundMgr::CreateBattleGround(BattleGroundTypeId bgTypeId, bool IsA } bg->SetMapId(MapID); - - bg->Reset(); - bg->SetTypeID(bgTypeId); bg->SetInstanceID(0); bg->SetArenaorBGType(IsArena); @@ -1500,8 +1523,8 @@ uint32 BattleGroundMgr::CreateBattleGround(BattleGroundTypeId bgTypeId, bool IsA bg->SetTeamStartLoc(HORDE, Team2StartLocX, Team2StartLocY, Team2StartLocZ, Team2StartLocO); bg->SetLevelRange(LevelMin, LevelMax); - //add BattleGround instance to FreeSlotQueue (.back() will return the template!) - bg->AddToBGFreeSlotQueue(); + //reset() and add to free slot queue are called only when needed! + //bg->AddToBGFreeSlotQueue(); // do NOT add to update list, since this is a template battleground! @@ -1723,9 +1746,9 @@ void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket *data, const uint6 uint32 count = 0; *data << uint32(0x00); // number of bg instances - for(std::map::iterator itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); ++itr) + for(BattleGroundSet::iterator itr = m_BattleGrounds[bgTypeId].begin(); itr != m_BattleGrounds[bgTypeId].end(); ++itr) { - if(itr->second->GetTypeID() == bgTypeId && (PlayerLevel >= itr->second->GetMinLevel()) && (PlayerLevel <= itr->second->GetMaxLevel())) + if( PlayerLevel >= itr->second->GetMinLevel() && PlayerLevel <= itr->second->GetMaxLevel() ) { *data << uint32(itr->second->GetInstanceID()); ++count; @@ -1735,9 +1758,9 @@ void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket *data, const uint6 } } -void BattleGroundMgr::SendToBattleGround(Player *pl, uint32 instanceId) +void BattleGroundMgr::SendToBattleGround(Player *pl, uint32 instanceId, BattleGroundTypeId bgTypeId) { - BattleGround *bg = GetBattleGround(instanceId); + BattleGround *bg = GetBattleGround(instanceId, bgTypeId); if(bg) { uint32 mapid = bg->GetMapId(); diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h index 30ab006e1..fb0ea7b37 100644 --- a/src/game/BattleGroundMgr.h +++ b/src/game/BattleGroundMgr.h @@ -22,8 +22,6 @@ #include "Common.h" #include "BattleGround.h" -//TODO it is not possible to have this structure, because we should have BattlegroundSet for each queue -//so i propose to change this type to array 1..MAX_BATTLEGROUND_TYPES of sets or maps.. typedef std::map BattleGroundSet; typedef std::deque BGFreeSlotQueueType; @@ -129,7 +127,10 @@ class BattleGroundQueue class BGQueueInviteEvent : public BasicEvent { public: - BGQueueInviteEvent(const uint64& pl_guid, uint32 BgInstanceGUID) : m_PlayerGuid(pl_guid), m_BgInstanceGUID(BgInstanceGUID) {}; + BGQueueInviteEvent(const uint64& pl_guid, uint32 BgInstanceGUID, BattleGroundTypeId BgTypeId) : + m_PlayerGuid(pl_guid), m_BgInstanceGUID(BgInstanceGUID), m_BgTypeId(BgTypeId) + { + }; virtual ~BGQueueInviteEvent() {}; virtual bool Execute(uint64 e_time, uint32 p_time); @@ -137,6 +138,7 @@ class BGQueueInviteEvent : public BasicEvent private: uint64 m_PlayerGuid; uint32 m_BgInstanceGUID; + BattleGroundTypeId m_BgTypeId; }; /* @@ -145,8 +147,8 @@ class BGQueueInviteEvent : public BasicEvent class BGQueueRemoveEvent : public BasicEvent { public: - BGQueueRemoveEvent(const uint64& pl_guid, uint32 bgInstanceGUID, uint32 playersTeam) : - m_PlayerGuid(pl_guid), m_BgInstanceGUID(bgInstanceGUID), m_PlayersTeam(playersTeam) + BGQueueRemoveEvent(const uint64& pl_guid, uint32 bgInstanceGUID, BattleGroundTypeId BgTypeId, uint32 playersTeam) : + m_PlayerGuid(pl_guid), m_BgInstanceGUID(bgInstanceGUID), m_BgTypeId(BgTypeId), m_PlayersTeam(playersTeam) { }; virtual ~BGQueueRemoveEvent() {}; @@ -157,6 +159,7 @@ class BGQueueRemoveEvent : public BasicEvent uint64 m_PlayerGuid; uint32 m_BgInstanceGUID; uint32 m_PlayersTeam; + BattleGroundTypeId m_BgTypeId; }; class BattleGroundMgr @@ -180,30 +183,23 @@ class BattleGroundMgr /* Player invitation */ // called from Queue update, or from Addplayer to queue - void InvitePlayer(Player* plr, uint32 bgInstanceGUID, uint32 team); + void InvitePlayer(Player* plr, uint32 bgInstanceGUID, BattleGroundTypeId bgTypeId, uint32 team); /* Battlegrounds */ - BattleGroundSet::iterator GetBattleGroundsBegin() { return m_BattleGrounds.begin(); }; - BattleGroundSet::iterator GetBattleGroundsEnd() { return m_BattleGrounds.end(); }; - - BattleGround* GetBattleGround(uint32 InstanceID) - { - BattleGroundSet::iterator i = m_BattleGrounds.find(InstanceID); - return ( (i != m_BattleGrounds.end()) ? i->second : NULL ); - }; + BattleGround* GetBattleGround(uint32 InstanceID, BattleGroundTypeId bgTypeId); //there must be uint32 because MAX_BATTLEGROUND_TYPE_ID means unknown BattleGround * GetBattleGroundTemplate(BattleGroundTypeId bgTypeId); BattleGround * CreateNewBattleGround(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id, uint8 arenaType, bool isRated); uint32 CreateBattleGround(BattleGroundTypeId bgTypeId, bool IsArena, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam, uint32 LevelMin, uint32 LevelMax, char* BattleGroundName, uint32 MapID, float Team1StartLocX, float Team1StartLocY, float Team1StartLocZ, float Team1StartLocO, float Team2StartLocX, float Team2StartLocY, float Team2StartLocZ, float Team2StartLocO); - void AddBattleGround(uint32 InstanceID, BattleGround* BG) { m_BattleGrounds[InstanceID] = BG; }; - void RemoveBattleGround(uint32 instanceID) { m_BattleGrounds.erase(instanceID); } + void AddBattleGround(uint32 InstanceID, BattleGroundTypeId bgTypeId, BattleGround* BG) { m_BattleGrounds[bgTypeId][InstanceID] = BG; }; + void RemoveBattleGround(uint32 instanceID, BattleGroundTypeId bgTypeId) { m_BattleGrounds[bgTypeId].erase(instanceID); } void CreateInitialBattleGrounds(); void DeleteAlllBattleGrounds(); - void SendToBattleGround(Player *pl, uint32 InstanceID); + void SendToBattleGround(Player *pl, uint32 InstanceID, BattleGroundTypeId bgTypeId); /* Battleground queues */ //these queues are instantiated when creating BattlegroundMrg @@ -241,7 +237,7 @@ class BattleGroundMgr BattleMastersMap mBattleMastersMap; /* Battlegrounds */ - BattleGroundSet m_BattleGrounds; + BattleGroundSet m_BattleGrounds[MAX_BATTLEGROUND_TYPE_ID]; uint32 m_NextRatingDiscardUpdate; uint64 m_NextAutoDistributionTime; uint32 m_AutoDistributionTimeChecker; diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp index 60781c47d..4fd4e4a86 100644 --- a/src/game/Level1.cpp +++ b/src/game/Level1.cpp @@ -381,7 +381,7 @@ bool ChatHandler::HandleNamegoCommand(const char* args) } // all's well, set bg id // when porting out from the bg, it will be reset to 0 - chr->SetBattleGroundId(m_session->GetPlayer()->GetBattleGroundId()); + chr->SetBattleGroundId(m_session->GetPlayer()->GetBattleGroundId(), m_session->GetPlayer()->GetBattleGroundTypeId()); // remember current position as entry point for return at bg end teleportation chr->SetBattleGroundEntryPoint(chr->GetMapId(),chr->GetPositionX(),chr->GetPositionY(),chr->GetPositionZ(),chr->GetOrientation()); } @@ -499,7 +499,7 @@ bool ChatHandler::HandleGonameCommand(const char* args) } // all's well, set bg id // when porting out from the bg, it will be reset to 0 - _player->SetBattleGroundId(chr->GetBattleGroundId()); + _player->SetBattleGroundId(chr->GetBattleGroundId(), chr->GetBattleGroundTypeId()); // remember current position as entry point for return at bg end teleportation _player->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); } diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index 0cbeff0fe..84a28e463 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -94,7 +94,7 @@ void WorldSession::HandleMoveWorldportAckOpcode() // cleanup seting if outdated if(!mEntry->IsBattleGroundOrArena()) { - _player->SetBattleGroundId(0); // We're not in BG. + _player->SetBattleGroundId(0, BATTLEGROUND_TYPE_NONE); // We're not in BG. // reset destination bg team _player->SetBGTeam(0); } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 160fe02c9..fd688666f 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -366,6 +366,7 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this) m_DetectInvTimer = 1000; m_bgBattleGroundID = 0; + m_bgTypeID = BATTLEGROUND_TYPE_NONE; for (int j=0; j < PLAYER_MAX_BATTLEGROUND_QUEUES; j++) { m_bgBattleGroundQueueID[j].bgQueueTypeId = BATTLEGROUND_QUEUE_NONE; @@ -4242,7 +4243,7 @@ void Player::RepopAtGraveyard() WorldSafeLocsEntry const *ClosestGrave = NULL; // Special handle for battleground maps - BattleGround *bg = sBattleGroundMgr.GetBattleGround(GetBattleGroundId()); + BattleGround *bg = sBattleGroundMgr.GetBattleGround(GetBattleGroundId(), m_bgTypeID); if(bg && (bg->GetTypeID() == BATTLEGROUND_AB || bg->GetTypeID() == BATTLEGROUND_EY)) ClosestGrave = bg->GetClosestGraveYard(GetPositionX(), GetPositionY(), GetPositionZ(), GetTeam()); @@ -14251,14 +14252,14 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) if(!mapEntry || mapEntry->Instanceable() || !MapManager::IsValidMapCoord(m_bgEntryPoint)) SetBattleGroundEntryPoint(m_homebindMapId,m_homebindX,m_homebindY,m_homebindZ,0.0f); - BattleGround *currentBg = sBattleGroundMgr.GetBattleGround(bgid); + BattleGround *currentBg = sBattleGroundMgr.GetBattleGround(bgid, BATTLEGROUND_TYPE_NONE); if(currentBg && currentBg->IsPlayerInBattleGround(GetGUID())) { BattleGroundQueueTypeId bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(currentBg->GetTypeID(), currentBg->GetArenaType()); uint32 queueSlot = AddBattleGroundQueueId(bgQueueTypeId); - SetBattleGroundId(currentBg->GetInstanceID()); + SetBattleGroundId(currentBg->GetInstanceID(), currentBg->GetTypeID()); SetBGTeam(bgteam); //join player to battleground group @@ -18490,7 +18491,7 @@ BattleGround* Player::GetBattleGround() const if(GetBattleGroundId()==0) return NULL; - return sBattleGroundMgr.GetBattleGround(GetBattleGroundId()); + return sBattleGroundMgr.GetBattleGround(GetBattleGroundId(), m_bgTypeID); } bool Player::InArena() const diff --git a/src/game/Player.h b/src/game/Player.h index c6802dae1..2176150f6 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1867,9 +1867,10 @@ class MANGOS_DLL_SPEC Player : public Unit /*** BATTLEGROUND SYSTEM ***/ /*********************************************************/ - bool InBattleGround() const { return m_bgBattleGroundID != 0; } - bool InArena() const; - uint32 GetBattleGroundId() const { return m_bgBattleGroundID; } + bool InBattleGround() const { return m_bgBattleGroundID != 0; } + bool InArena() const; + uint32 GetBattleGroundId() const { return m_bgBattleGroundID; } + BattleGroundTypeId GetBattleGroundTypeId() const { return m_bgTypeID; } BattleGround* GetBattleGround() const; @@ -1903,7 +1904,11 @@ class MANGOS_DLL_SPEC Player : public Unit return GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES; } - void SetBattleGroundId(uint32 val) { m_bgBattleGroundID = val; } + void SetBattleGroundId(uint32 val, BattleGroundTypeId bgTypeId) + { + m_bgBattleGroundID = val; + m_bgTypeID = bgTypeId; + } uint32 AddBattleGroundQueueId(BattleGroundQueueTypeId val) { for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) @@ -2152,6 +2157,7 @@ class MANGOS_DLL_SPEC Player : public Unit /* this variable is set to bg->m_InstanceID, when player is teleported to BG - (it is battleground's GUID)*/ uint32 m_bgBattleGroundID; + BattleGroundTypeId m_bgTypeID; /* this is an array of BG queues (BgTypeIDs) in which is player */ diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index d5159b626..496eefa4d 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -2215,6 +2215,7 @@ enum BanReturn // indexes of BattlemasterList.dbc enum BattleGroundTypeId { + BATTLEGROUND_TYPE_NONE = 0, BATTLEGROUND_AV = 1, BATTLEGROUND_WS = 2, BATTLEGROUND_AB = 3, diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 8e9b6a0b2..353577efd 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7352" + #define REVISION_NR "7353" #endif // __REVISION_NR_H__ From f49ee9e157d86221c41c4271b1877580f61e818e Mon Sep 17 00:00:00 2001 From: Triply Date: Fri, 27 Feb 2009 16:21:28 +0100 Subject: [PATCH 25/32] Finally fixed problem with joining rated arena matches. Thx to balrok for help and testing. Signed-off-by: Triply --- src/game/BattleGroundMgr.cpp | 29 +++++++++++++++-------------- src/game/BattleGroundMgr.h | 2 +- src/shared/revision_nr.h | 2 +- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index 9ad37f7b1..c6ede3665 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -582,7 +582,7 @@ bool BattleGroundQueue::CheckPremadeMatch(BGQueueIdBasedOnLevel queue_id, uint32 } //this function tries to create battleground or arena with MinPlayersPerTeam against MinPlayersPerTeam -bool BattleGroundQueue::CheckNormalMatch(BattleGround* bg_template, BGQueueIdBasedOnLevel queue_id, uint32 MinPlayersPerTeam) +bool BattleGroundQueue::CheckNormalMatch(BattleGround* bg_template, BGQueueIdBasedOnLevel queue_id) { uint32 minPlayers = bg_template->GetMinPlayersPerTeam(); uint32 maxPlayers = bg_template->GetMaxPlayersPerTeam(); @@ -620,9 +620,11 @@ bool BattleGroundQueue::CheckNormalMatch(BattleGround* bg_template, BGQueueIdBas if( abs((int32)(m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() - m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount())) > 2 ) return false; } - + //allow 1v0 if debug bg + if( sBattleGroundMgr.isTesting() && (m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() || m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount()) ) + return true; //return true if there are enough players in selection pools - enable to work .debug bg command correctly - return m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() >= MinPlayersPerTeam && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() >= MinPlayersPerTeam; + return m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() >= minPlayers && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() >= minPlayers; } /* @@ -750,7 +752,7 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve if( !isRated ) { // if there are enough players in pools, start new battleground or non rated arena - if( CheckNormalMatch(bg_template, queue_id, MinPlayersPerTeam) ) + if( CheckNormalMatch(bg_template, queue_id) ) { // we successfully created a pool BattleGround * bg2 = NULL; @@ -1040,6 +1042,10 @@ void BattleGroundMgr::Update(uint32 diff) BattleGroundSet::iterator itr, next; for(uint32 i = BATTLEGROUND_TYPE_NONE; i < MAX_BATTLEGROUND_TYPE_ID; i++) { + itr = m_BattleGrounds[i].begin(); + // skip updating battleground template + if( itr != m_BattleGrounds[i].end() ) + ++itr; for(itr = m_BattleGrounds[i].begin(); itr != m_BattleGrounds[i].end(); itr = next) { next = itr; @@ -1471,15 +1477,9 @@ BattleGround * BattleGroundMgr::CreateNewBattleGround(BattleGroundTypeId bgTypeI // start the joining of the bg bg->SetStatus(STATUS_WAIT_JOIN); bg->SetQueueId(queue_id); - // initialize arena / rating info bg->SetArenaType(arenaType); - // set rating bg->SetRated(isRated); - /* will be setup in BG::Update() when the first player is ported in - if(!(bg->SetupBattleGround())) - */ - // add BG to free slot queue bg->AddToBGFreeSlotQueue(); @@ -1523,10 +1523,8 @@ uint32 BattleGroundMgr::CreateBattleGround(BattleGroundTypeId bgTypeId, bool IsA bg->SetTeamStartLoc(HORDE, Team2StartLocX, Team2StartLocY, Team2StartLocZ, Team2StartLocO); bg->SetLevelRange(LevelMin, LevelMax); - //reset() and add to free slot queue are called only when needed! - //bg->AddToBGFreeSlotQueue(); - - // do NOT add to update list, since this is a template battleground! + // add bg to update list + AddBattleGround(bg->GetInstanceID(), bg->GetTypeID(), bg); // return some not-null value, bgTypeId is good enough for me return bgTypeId; @@ -1748,6 +1746,9 @@ void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket *data, const uint6 for(BattleGroundSet::iterator itr = m_BattleGrounds[bgTypeId].begin(); itr != m_BattleGrounds[bgTypeId].end(); ++itr) { + // skip sending battleground template + if( itr == m_BattleGrounds[bgTypeId].begin() ) + continue; if( PlayerLevel >= itr->second->GetMinLevel() && PlayerLevel <= itr->second->GetMaxLevel() ) { *data << uint32(itr->second->GetInstanceID()); diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h index fb0ea7b37..804d23ffe 100644 --- a/src/game/BattleGroundMgr.h +++ b/src/game/BattleGroundMgr.h @@ -73,7 +73,7 @@ class BattleGroundQueue void FillPlayersToBG(BattleGround* bg, BGQueueIdBasedOnLevel queue_id); bool CheckPremadeMatch(BGQueueIdBasedOnLevel queue_id, uint32 MaxPlayersPerTeam, uint32 MinPlayersPerTeam); - bool CheckNormalMatch(BattleGround* bg_template, BGQueueIdBasedOnLevel queue_id, uint32 MinPlayersPerTeam); + bool CheckNormalMatch(BattleGround* bg_template, BGQueueIdBasedOnLevel queue_id); GroupQueueInfo * AddGroup(Player * leader, BattleGroundTypeId bgTypeId, uint8 ArenaType, bool isRated, bool isPremade, uint32 ArenaRating, uint32 ArenaTeamId = 0); void AddPlayer(Player *plr, GroupQueueInfo *ginfo); void RemovePlayer(const uint64& guid, bool decreaseInvitedCount); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 353577efd..57867a1c1 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7353" + #define REVISION_NR "7354" #endif // __REVISION_NR_H__ From bb1d8d7bc7775ac945d864a1db5812d0d25635f6 Mon Sep 17 00:00:00 2001 From: Triply Date: Fri, 27 Feb 2009 21:00:48 +0100 Subject: [PATCH 26/32] Fixed crashes when inviting same faction arena groups. Fixed crash in BGEndedRemoveInvites (by setting queue type from deque to list). Signed-off-by: Triply --- src/game/BattleGroundMgr.cpp | 21 +++++++++++---------- src/game/BattleGroundMgr.h | 6 +++--- src/shared/revision_nr.h | 2 +- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index c6ede3665..e5379bb64 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -396,12 +396,14 @@ void BattleGroundQueue::BGEndedRemoveInvites(BattleGround *bg) GroupsQueueType::iterator itr, next; for(uint32 i = 0; i < BG_QUEUE_GROUP_TYPES_COUNT; i++) { - for(itr = m_QueuedGroups[queue_id][i].begin(); itr != m_QueuedGroups[queue_id][i].end(); itr = next) + itr = m_QueuedGroups[queue_id][i].begin(); + next = itr; + while (next != m_QueuedGroups[queue_id][i].end()) { // must do this way, because the groupinfo will be deleted when all playerinfos are removed - GroupQueueInfo * ginfo = (*itr); - next = itr; + itr = next; ++next; + GroupQueueInfo * ginfo = (*itr); // if group was invited to this bg instance, then remove all references if( ginfo->IsInvitedToBGInstanceGUID == bgInstanceId ) { @@ -525,7 +527,7 @@ void BattleGroundQueue::FillPlayersToBG(BattleGround* bg, BGQueueIdBasedOnLevel // this method checks if premade versus premade battleground is possible // then after 30 mins (default) in queue it moves premade group to normal queue // it tries to invite as much players as it can - to MaxPlayersPerTeam, because premade groups have more than MinPlayersPerTeam players -bool BattleGroundQueue::CheckPremadeMatch(BGQueueIdBasedOnLevel queue_id, uint32 MaxPlayersPerTeam, uint32 MinPlayersPerTeam) +bool BattleGroundQueue::CheckPremadeMatch(BGQueueIdBasedOnLevel queue_id, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam) { //check match if(!m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].empty() && !m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].empty()) @@ -582,11 +584,8 @@ bool BattleGroundQueue::CheckPremadeMatch(BGQueueIdBasedOnLevel queue_id, uint32 } //this function tries to create battleground or arena with MinPlayersPerTeam against MinPlayersPerTeam -bool BattleGroundQueue::CheckNormalMatch(BattleGround* bg_template, BGQueueIdBasedOnLevel queue_id) +bool BattleGroundQueue::CheckNormalMatch(BattleGround* bg_template, BGQueueIdBasedOnLevel queue_id, uint32 minPlayers, uint32 maxPlayers) { - uint32 minPlayers = bg_template->GetMinPlayersPerTeam(); - uint32 maxPlayers = bg_template->GetMaxPlayersPerTeam(); - GroupsQueueType::const_iterator itr_team[BG_TEAMS_COUNT]; for(uint32 i = 0; i < BG_TEAMS_COUNT; i++) { @@ -727,7 +726,7 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve if( bg_template->isBattleGround() ) { //check if there is premade against premade match - if( CheckPremadeMatch(queue_id, bg_template->GetMaxPlayersPerTeam(), bg_template->GetMinPlayersPerTeam()) ) + if( CheckPremadeMatch(queue_id, MinPlayersPerTeam, MaxPlayersPerTeam) ) { //create new battleground BattleGround * bg2 = NULL; @@ -752,7 +751,7 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve if( !isRated ) { // if there are enough players in pools, start new battleground or non rated arena - if( CheckNormalMatch(bg_template, queue_id) ) + if( CheckNormalMatch(bg_template, queue_id, MinPlayersPerTeam, MaxPlayersPerTeam) ) { // we successfully created a pool BattleGround * bg2 = NULL; @@ -887,11 +886,13 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].push_front(*(itr_team[BG_TEAM_ALLIANCE])); // erase from horde queue m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].erase(itr_team[BG_TEAM_ALLIANCE]); + itr_team[BG_TEAM_ALLIANCE] = m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].begin(); } if( (*(itr_team[BG_TEAM_HORDE]))->Team != HORDE ) { m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].push_front(*(itr_team[BG_TEAM_HORDE])); m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].erase(itr_team[BG_TEAM_HORDE]); + itr_team[BG_TEAM_HORDE] = m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].begin(); } InviteGroupToBG(*(itr_team[BG_TEAM_ALLIANCE]), arena, ALLIANCE); diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h index 804d23ffe..cf500629d 100644 --- a/src/game/BattleGroundMgr.h +++ b/src/game/BattleGroundMgr.h @@ -72,8 +72,8 @@ class BattleGroundQueue void Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id, uint8 arenaType = 0, bool isRated = false, uint32 minRating = 0); void FillPlayersToBG(BattleGround* bg, BGQueueIdBasedOnLevel queue_id); - bool CheckPremadeMatch(BGQueueIdBasedOnLevel queue_id, uint32 MaxPlayersPerTeam, uint32 MinPlayersPerTeam); - bool CheckNormalMatch(BattleGround* bg_template, BGQueueIdBasedOnLevel queue_id); + bool CheckPremadeMatch(BGQueueIdBasedOnLevel queue_id, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam); + bool CheckNormalMatch(BattleGround* bg_template, BGQueueIdBasedOnLevel queue_id, uint32 minPlayers, uint32 maxPlayers); GroupQueueInfo * AddGroup(Player * leader, BattleGroundTypeId bgTypeId, uint8 ArenaType, bool isRated, bool isPremade, uint32 ArenaRating, uint32 ArenaTeamId = 0); void AddPlayer(Player *plr, GroupQueueInfo *ginfo); void RemovePlayer(const uint64& guid, bool decreaseInvitedCount); @@ -85,7 +85,7 @@ class BattleGroundQueue QueuedPlayersMap m_QueuedPlayers; //we need constant add to begin and constant remove / add from the end, therefore deque suits our problem well - typedef std::deque GroupsQueueType; + typedef std::list GroupsQueueType; /* This two dimensional array is used to store All queued groups diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 57867a1c1..ee3af12e8 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7354" + #define REVISION_NR "7355" #endif // __REVISION_NR_H__ From 74b9874fd85af3100e59ae6efbc537e9c7f6460a Mon Sep 17 00:00:00 2001 From: freghar Date: Fri, 27 Feb 2009 17:44:20 +0100 Subject: [PATCH 27/32] [7356] Use tabs for indent in Makefiles Signed-off-by: freghar --- src/bindings/universal/Makefile.am | 20 +- src/framework/Makefile.am | 64 ++-- src/game/Makefile.am | 510 ++++++++++++++--------------- src/mangosd/Makefile.am | 41 +-- src/realmd/Makefile.am | 35 +- src/shared/Auth/Makefile.am | 20 +- src/shared/Database/Makefile.am | 70 ++-- src/shared/Makefile.am | 50 +-- src/shared/revision_nr.h | 2 +- src/shared/vmap/Makefile.am | 54 +-- 10 files changed, 434 insertions(+), 432 deletions(-) diff --git a/src/bindings/universal/Makefile.am b/src/bindings/universal/Makefile.am index 9c605004c..2655e3aa0 100644 --- a/src/bindings/universal/Makefile.am +++ b/src/bindings/universal/Makefile.am @@ -25,13 +25,13 @@ AM_CPPFLAGS = $(MANGOS_INCLUDES) -I$(srcdir) -I$(srcdir)/../../../dep/include -I # libmangosscript shared library will later be reused by world server daemon. lib_LTLIBRARIES = libmangosscript.la libmangosscript_la_SOURCES = \ - ScriptMgr.cpp \ - ScriptMgr.h \ - config.h \ - system.cpp \ - Scripts/sc_default.cpp \ - Scripts/sc_defines.cpp \ - Scripts/sc_defines.h + ScriptMgr.cpp \ + ScriptMgr.h \ + config.h \ + system.cpp \ + Scripts/sc_default.cpp \ + Scripts/sc_defines.cpp \ + Scripts/sc_defines.h ## libtool settings # API versioning @@ -51,6 +51,6 @@ libmangosscript_la_LIBFLAGS = -version-info $(LTMANGOS_CURRENT):$(LTMANGOS_REVIS ## Additional files to include when running 'make dist' # Scripts defaults. EXTRA_DIST = \ - Scripts/sc_default.cpp \ - Scripts/sc_defines.cpp \ - Scripts/sc_defines.h + Scripts/sc_default.cpp \ + Scripts/sc_defines.cpp \ + Scripts/sc_defines.h diff --git a/src/framework/Makefile.am b/src/framework/Makefile.am index a519dad42..748d5325e 100644 --- a/src/framework/Makefile.am +++ b/src/framework/Makefile.am @@ -25,39 +25,39 @@ AM_CPPFLAGS = $(MANGOS_INCLUDES) -I$(srcdir) # libMaNGOSScript shared library will later be reused by world server daemon. noinst_LIBRARIES = libmangosframework.a libmangosframework_a_SOURCES = \ - Policies/ObjectLifeTime.cpp \ - Utilities/EventProcessor.cpp + Policies/ObjectLifeTime.cpp \ + Utilities/EventProcessor.cpp ## Additional files to include when running 'make dist' # Source and header files for the Framework. EXTRA_DIST = \ - Dynamic/FactoryHolder.h \ - Dynamic/ObjectRegistry.h \ - GameSystem/Grid.h \ - GameSystem/GridLoader.h \ - GameSystem/GridRefManager.h \ - GameSystem/GridReference.h \ - GameSystem/NGrid.h \ - GameSystem/TypeContainer.h \ - GameSystem/TypeContainerFunctions.h \ - GameSystem/TypeContainerFunctionsPtr.h \ - GameSystem/TypeContainerVisitor.h \ - Network/SocketDefines.h \ - Platform/CompilerDefs.h \ - Platform/Define.h \ - Policies/CreationPolicy.h \ - Policies/ObjectLifeTime.h \ - Policies/Singleton.h \ - Policies/SingletonImp.h \ - Policies/ThreadingModel.h \ - Utilities/CountedReference/Reference.h \ - Utilities/CountedReference/ReferenceHolder.h \ - Utilities/CountedReference/ReferenceImpl.h \ - Utilities/LinkedReference/RefManager.h \ - Utilities/LinkedReference/Reference.h \ - Utilities/ByteConverter.h \ - Utilities/Callback.h \ - Utilities/EventProcessor.h \ - Utilities/UnorderedMap.h \ - Utilities/LinkedList.h \ - Utilities/TypeList.h + Dynamic/FactoryHolder.h \ + Dynamic/ObjectRegistry.h \ + GameSystem/Grid.h \ + GameSystem/GridLoader.h \ + GameSystem/GridRefManager.h \ + GameSystem/GridReference.h \ + GameSystem/NGrid.h \ + GameSystem/TypeContainer.h \ + GameSystem/TypeContainerFunctions.h \ + GameSystem/TypeContainerFunctionsPtr.h \ + GameSystem/TypeContainerVisitor.h \ + Network/SocketDefines.h \ + Platform/CompilerDefs.h \ + Platform/Define.h \ + Policies/CreationPolicy.h \ + Policies/ObjectLifeTime.h \ + Policies/Singleton.h \ + Policies/SingletonImp.h \ + Policies/ThreadingModel.h \ + Utilities/CountedReference/Reference.h \ + Utilities/CountedReference/ReferenceHolder.h \ + Utilities/CountedReference/ReferenceImpl.h \ + Utilities/LinkedReference/RefManager.h \ + Utilities/LinkedReference/Reference.h \ + Utilities/ByteConverter.h \ + Utilities/Callback.h \ + Utilities/EventProcessor.h \ + Utilities/UnorderedMap.h \ + Utilities/LinkedList.h \ + Utilities/TypeList.h diff --git a/src/game/Makefile.am b/src/game/Makefile.am index a162214ca..2b10e7b6e 100644 --- a/src/game/Makefile.am +++ b/src/game/Makefile.am @@ -28,261 +28,261 @@ noinst_LIBRARIES = libmangosgame.a # libmangossgame library will later be reused by ... libmangosgame_a_SOURCES = \ - AccountMgr.cpp \ - AccountMgr.h \ - AchievementMgr.h \ - AchievementMgr.cpp \ - AddonHandler.cpp \ - AddonHandler.h \ - AggressorAI.cpp \ - AggressorAI.h \ - AnimalRandomMovementGenerator.h \ - ArenaTeam.cpp \ - ArenaTeam.h \ - ArenaTeamHandler.cpp \ - AuctionHouseHandler.cpp \ - AuctionHouseMgr.cpp \ - AuctionHouseMgr.h \ - Bag.cpp \ - Bag.h \ - BattleGround.cpp \ - BattleGroundAA.cpp \ - BattleGroundAB.cpp \ - BattleGroundAV.cpp \ - BattleGroundBE.cpp \ - BattleGroundDS.cpp \ - BattleGroundEY.cpp \ - BattleGroundNA.cpp \ - BattleGroundRL.cpp \ - BattleGroundRV.cpp \ - BattleGroundSA.cpp \ - BattleGroundWS.cpp \ - BattleGround.h \ - BattleGroundAA.h \ - BattleGroundAB.h \ - BattleGroundAV.h \ - BattleGroundBE.h \ - BattleGroundDS.h \ - BattleGroundEY.h \ - BattleGroundNA.h \ - BattleGroundRL.h \ - BattleGroundRV.h \ - BattleGroundSA.h \ - BattleGroundWS.h \ - BattleGroundHandler.cpp \ - BattleGroundMgr.cpp \ - BattleGroundMgr.h \ - Calendar.cpp \ - Calendar.h \ - CalendarHandler.cpp \ - Cell.h \ - CellImpl.h \ - Channel.cpp \ - Channel.h \ - ChannelHandler.cpp \ - ChannelMgr.h \ - CharacterHandler.cpp \ - Chat.cpp \ - Chat.h \ - ChatHandler.cpp \ - CombatHandler.cpp \ - ConfusedMovementGenerator.cpp \ - ConfusedMovementGenerator.h \ - Corpse.cpp \ - Corpse.h \ - CreatureAI.cpp \ - CreatureAI.h \ - CreatureAIImpl.h \ - CreatureAIRegistry.cpp \ - CreatureAIRegistry.h \ - CreatureAISelector.cpp \ - CreatureAISelector.h \ - Creature.cpp \ - Creature.h \ - debugcmds.cpp \ - DestinationHolder.cpp \ - DestinationHolder.h \ - DestinationHolderImp.h \ - DuelHandler.cpp \ - DynamicObject.cpp \ - DynamicObject.h \ - FleeingMovementGenerator.cpp \ - FleeingMovementGenerator.h \ - Formulas.h \ - GameEvent.cpp \ - GameEvent.h \ - GameObject.cpp \ - GameObject.h \ - GlobalEvents.cpp \ - GlobalEvents.h \ - GMTicketHandler.cpp \ - GMTicketMgr.cpp \ - GMTicketMgr.h \ - GossipDef.cpp \ - GossipDef.h \ - GridDefines.h \ - GridNotifiers.cpp \ - GridNotifiers.h \ - GridNotifiersImpl.h \ - GridStates.cpp \ - GridStates.h \ - Group.cpp \ - Group.h \ - GroupHandler.cpp \ - GuardAI.cpp \ - GuardAI.h \ - Guild.cpp \ - Guild.h \ - GuildHandler.cpp \ - HomeMovementGenerator.cpp \ - HomeMovementGenerator.h \ - HostilRefManager.cpp \ - HostilRefManager.h \ - IdleMovementGenerator.cpp \ - IdleMovementGenerator.h \ - InstanceData.cpp \ - InstanceData.h \ - InstanceSaveMgr.cpp \ - InstanceSaveMgr.h \ - Item.cpp \ - Item.h \ - ItemEnchantmentMgr.cpp \ - ItemEnchantmentMgr.h \ - ItemHandler.cpp \ - ItemPrototype.h \ - Language.h \ - Level0.cpp \ - Level1.cpp \ - Level2.cpp \ - Level3.cpp \ - LFGHandler.cpp \ - LootHandler.cpp \ - LootMgr.cpp \ - LootMgr.h \ - Mail.cpp \ - Mail.h \ - Map.cpp \ - Map.h \ - MapInstanced.cpp \ - MapInstanced.h \ - MapManager.cpp \ - MapManager.h \ - MapReference.h \ - MapRefManager.h \ - MiscHandler.cpp \ - MotionMaster.cpp \ - MotionMaster.h \ - MovementGenerator.cpp \ - MovementGenerator.h \ - MovementGeneratorImpl.h \ - MovementHandler.cpp \ - NPCHandler.cpp \ - NPCHandler.h \ - NullCreatureAI.cpp \ - NullCreatureAI.h \ - ObjectAccessor.cpp \ - ObjectAccessor.h \ - Object.cpp \ - ObjectDefines.h \ - ObjectGridLoader.cpp \ - ObjectGridLoader.h \ - Object.h \ - ObjectMgr.cpp \ - ObjectMgr.h \ - ObjectPosSelector.cpp \ - ObjectPosSelector.h \ - Opcodes.cpp \ - Opcodes.h \ - Path.h \ - PetAI.cpp \ - PetAI.h \ - Pet.cpp \ - Pet.h \ - PetHandler.cpp \ - PetitionsHandler.cpp \ - Player.cpp \ - Player.h \ - PlayerDump.cpp \ - PlayerDump.h \ - PointMovementGenerator.cpp \ - PointMovementGenerator.h \ - PoolHandler.cpp \ - PoolHandler.h \ - QueryHandler.cpp \ - QuestDef.cpp \ - QuestDef.h \ - QuestHandler.cpp \ - RandomMovementGenerator.cpp \ - RandomMovementGenerator.h \ - ReactorAI.cpp \ - ReactorAI.h \ - ScriptCalls.cpp \ - ScriptCalls.h \ - SharedDefines.h \ - SkillHandler.cpp \ - SpellAuraDefines.h \ - SpellAuras.cpp \ - SpellAuras.h \ - Spell.cpp \ - SpellEffects.cpp \ - Spell.h \ - SkillDiscovery.cpp \ - SkillDiscovery.h \ - SkillExtraItems.cpp \ - SkillExtraItems.h \ - SpellHandler.cpp \ - SocialMgr.cpp \ - SocialMgr.h \ - SpellMgr.cpp \ - SpellMgr.h \ - StatSystem.cpp \ - TargetedMovementGenerator.cpp \ - TargetedMovementGenerator.h \ - TaxiHandler.cpp \ - TemporarySummon.cpp \ - TemporarySummon.h \ - TotemAI.cpp \ - TotemAI.h \ - Totem.cpp \ - Totem.h \ - TradeHandler.cpp \ - Transports.cpp \ - Transports.h \ - ThreatManager.cpp \ - ThreatManager.h \ - Traveller.h \ - Unit.cpp \ - Unit.h \ - UnitEvents.h \ - UpdateData.cpp \ - UpdateData.h \ - UpdateFields.h \ - UpdateMask.h \ - Vehicle.cpp \ - Vehicle.h \ - VoiceChatHandler.cpp \ - WaypointManager.cpp \ - WaypointManager.h \ - WaypointMovementGenerator.cpp \ - WaypointMovementGenerator.h \ - Weather.cpp \ - Weather.h \ - World.cpp \ - World.h \ - WorldLog.cpp \ - WorldLog.h \ - WorldSession.cpp \ - WorldSession.h \ - WorldSocket.cpp \ - WorldSocket.h \ - WorldSocketMgr.cpp \ - WorldSocketMgr.h \ - FollowerReference.cpp \ - FollowerReference.h \ - FollowerRefManager.h \ - GroupReference.cpp \ - GroupReference.h \ - GroupRefManager.h + AccountMgr.cpp \ + AccountMgr.h \ + AchievementMgr.h \ + AchievementMgr.cpp \ + AddonHandler.cpp \ + AddonHandler.h \ + AggressorAI.cpp \ + AggressorAI.h \ + AnimalRandomMovementGenerator.h \ + ArenaTeam.cpp \ + ArenaTeam.h \ + ArenaTeamHandler.cpp \ + AuctionHouseHandler.cpp \ + AuctionHouseMgr.cpp \ + AuctionHouseMgr.h \ + Bag.cpp \ + Bag.h \ + BattleGround.cpp \ + BattleGroundAA.cpp \ + BattleGroundAB.cpp \ + BattleGroundAV.cpp \ + BattleGroundBE.cpp \ + BattleGroundDS.cpp \ + BattleGroundEY.cpp \ + BattleGroundNA.cpp \ + BattleGroundRL.cpp \ + BattleGroundRV.cpp \ + BattleGroundSA.cpp \ + BattleGroundWS.cpp \ + BattleGround.h \ + BattleGroundAA.h \ + BattleGroundAB.h \ + BattleGroundAV.h \ + BattleGroundBE.h \ + BattleGroundDS.h \ + BattleGroundEY.h \ + BattleGroundNA.h \ + BattleGroundRL.h \ + BattleGroundRV.h \ + BattleGroundSA.h \ + BattleGroundWS.h \ + BattleGroundHandler.cpp \ + BattleGroundMgr.cpp \ + BattleGroundMgr.h \ + Calendar.cpp \ + Calendar.h \ + CalendarHandler.cpp \ + Cell.h \ + CellImpl.h \ + Channel.cpp \ + Channel.h \ + ChannelHandler.cpp \ + ChannelMgr.h \ + CharacterHandler.cpp \ + Chat.cpp \ + Chat.h \ + ChatHandler.cpp \ + CombatHandler.cpp \ + ConfusedMovementGenerator.cpp \ + ConfusedMovementGenerator.h \ + Corpse.cpp \ + Corpse.h \ + CreatureAI.cpp \ + CreatureAI.h \ + CreatureAIImpl.h \ + CreatureAIRegistry.cpp \ + CreatureAIRegistry.h \ + CreatureAISelector.cpp \ + CreatureAISelector.h \ + Creature.cpp \ + Creature.h \ + debugcmds.cpp \ + DestinationHolder.cpp \ + DestinationHolder.h \ + DestinationHolderImp.h \ + DuelHandler.cpp \ + DynamicObject.cpp \ + DynamicObject.h \ + FleeingMovementGenerator.cpp \ + FleeingMovementGenerator.h \ + Formulas.h \ + GameEvent.cpp \ + GameEvent.h \ + GameObject.cpp \ + GameObject.h \ + GlobalEvents.cpp \ + GlobalEvents.h \ + GMTicketHandler.cpp \ + GMTicketMgr.cpp \ + GMTicketMgr.h \ + GossipDef.cpp \ + GossipDef.h \ + GridDefines.h \ + GridNotifiers.cpp \ + GridNotifiers.h \ + GridNotifiersImpl.h \ + GridStates.cpp \ + GridStates.h \ + Group.cpp \ + Group.h \ + GroupHandler.cpp \ + GuardAI.cpp \ + GuardAI.h \ + Guild.cpp \ + Guild.h \ + GuildHandler.cpp \ + HomeMovementGenerator.cpp \ + HomeMovementGenerator.h \ + HostilRefManager.cpp \ + HostilRefManager.h \ + IdleMovementGenerator.cpp \ + IdleMovementGenerator.h \ + InstanceData.cpp \ + InstanceData.h \ + InstanceSaveMgr.cpp \ + InstanceSaveMgr.h \ + Item.cpp \ + Item.h \ + ItemEnchantmentMgr.cpp \ + ItemEnchantmentMgr.h \ + ItemHandler.cpp \ + ItemPrototype.h \ + Language.h \ + Level0.cpp \ + Level1.cpp \ + Level2.cpp \ + Level3.cpp \ + LFGHandler.cpp \ + LootHandler.cpp \ + LootMgr.cpp \ + LootMgr.h \ + Mail.cpp \ + Mail.h \ + Map.cpp \ + Map.h \ + MapInstanced.cpp \ + MapInstanced.h \ + MapManager.cpp \ + MapManager.h \ + MapReference.h \ + MapRefManager.h \ + MiscHandler.cpp \ + MotionMaster.cpp \ + MotionMaster.h \ + MovementGenerator.cpp \ + MovementGenerator.h \ + MovementGeneratorImpl.h \ + MovementHandler.cpp \ + NPCHandler.cpp \ + NPCHandler.h \ + NullCreatureAI.cpp \ + NullCreatureAI.h \ + ObjectAccessor.cpp \ + ObjectAccessor.h \ + Object.cpp \ + ObjectDefines.h \ + ObjectGridLoader.cpp \ + ObjectGridLoader.h \ + Object.h \ + ObjectMgr.cpp \ + ObjectMgr.h \ + ObjectPosSelector.cpp \ + ObjectPosSelector.h \ + Opcodes.cpp \ + Opcodes.h \ + Path.h \ + PetAI.cpp \ + PetAI.h \ + Pet.cpp \ + Pet.h \ + PetHandler.cpp \ + PetitionsHandler.cpp \ + Player.cpp \ + Player.h \ + PlayerDump.cpp \ + PlayerDump.h \ + PointMovementGenerator.cpp \ + PointMovementGenerator.h \ + PoolHandler.cpp \ + PoolHandler.h \ + QueryHandler.cpp \ + QuestDef.cpp \ + QuestDef.h \ + QuestHandler.cpp \ + RandomMovementGenerator.cpp \ + RandomMovementGenerator.h \ + ReactorAI.cpp \ + ReactorAI.h \ + ScriptCalls.cpp \ + ScriptCalls.h \ + SharedDefines.h \ + SkillHandler.cpp \ + SpellAuraDefines.h \ + SpellAuras.cpp \ + SpellAuras.h \ + Spell.cpp \ + SpellEffects.cpp \ + Spell.h \ + SkillDiscovery.cpp \ + SkillDiscovery.h \ + SkillExtraItems.cpp \ + SkillExtraItems.h \ + SpellHandler.cpp \ + SocialMgr.cpp \ + SocialMgr.h \ + SpellMgr.cpp \ + SpellMgr.h \ + StatSystem.cpp \ + TargetedMovementGenerator.cpp \ + TargetedMovementGenerator.h \ + TaxiHandler.cpp \ + TemporarySummon.cpp \ + TemporarySummon.h \ + TotemAI.cpp \ + TotemAI.h \ + Totem.cpp \ + Totem.h \ + TradeHandler.cpp \ + Transports.cpp \ + Transports.h \ + ThreatManager.cpp \ + ThreatManager.h \ + Traveller.h \ + Unit.cpp \ + Unit.h \ + UnitEvents.h \ + UpdateData.cpp \ + UpdateData.h \ + UpdateFields.h \ + UpdateMask.h \ + Vehicle.cpp \ + Vehicle.h \ + VoiceChatHandler.cpp \ + WaypointManager.cpp \ + WaypointManager.h \ + WaypointMovementGenerator.cpp \ + WaypointMovementGenerator.h \ + Weather.cpp \ + Weather.h \ + World.cpp \ + World.h \ + WorldLog.cpp \ + WorldLog.h \ + WorldSession.cpp \ + WorldSession.h \ + WorldSocket.cpp \ + WorldSocket.h \ + WorldSocketMgr.cpp \ + WorldSocketMgr.h \ + FollowerReference.cpp \ + FollowerReference.h \ + FollowerRefManager.h \ + GroupReference.cpp \ + GroupReference.h \ + GroupRefManager.h ## Link against shared library libmangosgame_a_LIBADD = ../shared/libmangosshared.a ../shared/Auth/libmangosauth.a ../shared/Config/libmangosconfig.a ../shared/Database/libmangosdatabase.a ../shared/vmap/libmangosvmaps.a diff --git a/src/mangosd/Makefile.am b/src/mangosd/Makefile.am index 73a385d4e..b7106cc4f 100644 --- a/src/mangosd/Makefile.am +++ b/src/mangosd/Makefile.am @@ -22,15 +22,15 @@ AM_CPPFLAGS = $(MANGOS_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir)/../../ ## Build world list daemon as standalone program bin_PROGRAMS = mangos-worldd mangos_worldd_SOURCES = \ - CliRunnable.cpp \ - CliRunnable.h \ - Main.cpp \ - Master.cpp \ - Master.h \ - RASocket.cpp \ - RASocket.h \ - WorldRunnable.cpp \ - WorldRunnable.h + CliRunnable.cpp \ + CliRunnable.h \ + Main.cpp \ + Master.cpp \ + Master.h \ + RASocket.cpp \ + RASocket.h \ + WorldRunnable.cpp \ + WorldRunnable.h ## Link world daemon against the shared library mangos_worldd_LDADD = ../bindings/universal/libmangosscript.la ../game/libmangosgame.a ../shared/Database/libmangosdatabase.a ../shared/Config/libmangosconfig.a ../shared/Auth/libmangosauth.a ../shared/libmangosshared.a ../shared/vmap/libmangosvmaps.a ../framework/libmangosframework.a ../../dep/src/sockets/libmangossockets.a ../../dep/src/zthread/libZThread.la ../../dep/src/g3dlite/libg3dlite.a @@ -39,22 +39,23 @@ mangos_worldd_LDFLAGS = -L../../dep/src/sockets -L../../dep/src/zthread -L../../ ## Additional files to include when running 'make dist' # Include world daemon configuration EXTRA_DIST = \ - mangosd.conf.dist + mangosd.conf.dist ## Additional files to install sysconf_DATA = \ - mangosd.conf.dist + mangosd.conf.dist install-data-hook: - @list='$(sysconf_DATA)'; for p in $$list; do \ - dest=`echo $$p | sed -e s/.dist//`; \ - if test -f $(DESTDIR)$(sysconfdir)/$$dest; then \ - echo "$@ will not overwrite existing $(DESTDIR)$(sysconfdir)/$$dest"; \ - else \ - echo " $(INSTALL_DATA) $$p $(DESTDIR)$(sysconfdir)/$$dest"; \ - $(INSTALL_DATA) $$p $(DESTDIR)$(sysconfdir)/$$dest; \ - fi; \ - done + @list='$(sysconf_DATA)' + for p in $$list; do \ + dest=`echo $$p | sed -e s/.dist//`; \ + if test -f $(DESTDIR)$(sysconfdir)/$$dest; then \ + echo "$@ will not overwrite existing $(DESTDIR)$(sysconfdir)/$$dest"; \ + else \ + echo " $(INSTALL_DATA) $$p $(DESTDIR)$(sysconfdir)/$$dest"; \ + $(INSTALL_DATA) $$p $(DESTDIR)$(sysconfdir)/$$dest; \ + fi; \ + done clean-local: rm -f $(sysconf_DATA) diff --git a/src/realmd/Makefile.am b/src/realmd/Makefile.am index 6de5189c3..38e1bdd61 100644 --- a/src/realmd/Makefile.am +++ b/src/realmd/Makefile.am @@ -22,12 +22,12 @@ AM_CPPFLAGS = $(MANGOS_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir)/../../ ## Build realm list daemon as standalone program bin_PROGRAMS = mangos-realmd mangos_realmd_SOURCES = \ - AuthCodes.h \ - AuthSocket.cpp \ - AuthSocket.h \ - Main.cpp \ - RealmList.cpp \ - RealmList.h + AuthCodes.h \ + AuthSocket.cpp \ + AuthSocket.h \ + Main.cpp \ + RealmList.cpp \ + RealmList.h ## Link realm list daemon against the shared library mangos_realmd_LDADD = ../shared/Database/libmangosdatabase.a ../shared/Config/libmangosconfig.a ../shared/Auth/libmangosauth.a ../shared/libmangosshared.a ../framework/libmangosframework.a ../../dep/src/sockets/libmangossockets.a ../../dep/src/zthread/libZThread.la @@ -36,22 +36,23 @@ mangos_realmd_LDFLAGS = -L../../dep/src/sockets -L../../dep/src/zthread -L$(libd ## Additional files to include when running 'make dist' # Include realm list daemon configuration EXTRA_DIST = \ - realmd.conf.dist + realmd.conf.dist ## Additional files to install sysconf_DATA = \ - realmd.conf.dist + realmd.conf.dist install-data-hook: - @list='$(sysconf_DATA)'; for p in $$list; do \ - dest=`echo $$p | sed -e s/.dist//`; \ - if test -f $(DESTDIR)$(sysconfdir)/$$dest; then \ - echo "$@ will not overwrite existing $(DESTDIR)$(sysconfdir)/$$dest"; \ - else \ - echo " $(INSTALL_DATA) $$p $(DESTDIR)$(sysconfdir)/$$dest"; \ - $(INSTALL_DATA) $$p $(DESTDIR)$(sysconfdir)/$$dest; \ - fi; \ - done + @list='$(sysconf_DATA)' + for p in $$list; do \ + dest=`echo $$p | sed -e s/.dist//`; \ + if test -f $(DESTDIR)$(sysconfdir)/$$dest; then \ + echo "$@ will not overwrite existing $(DESTDIR)$(sysconfdir)/$$dest"; \ + else \ + echo " $(INSTALL_DATA) $$p $(DESTDIR)$(sysconfdir)/$$dest"; \ + $(INSTALL_DATA) $$p $(DESTDIR)$(sysconfdir)/$$dest; \ + fi; \ + done clean-local: rm -f $(sysconf_DATA) diff --git a/src/shared/Auth/Makefile.am b/src/shared/Auth/Makefile.am index b7a2de5fc..9e4956711 100644 --- a/src/shared/Auth/Makefile.am +++ b/src/shared/Auth/Makefile.am @@ -27,13 +27,13 @@ AM_CPPFLAGS = $(MANGOS_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir) -I$(sr noinst_LIBRARIES = libmangosauth.a libmangosauth_a_SOURCES = \ - AuthCrypt.cpp \ - AuthCrypt.h \ - BigNumber.cpp \ - BigNumber.h \ - Hmac.cpp \ - Hmac.h \ - Sha1.cpp \ - Sha1.h \ - md5.c \ - md5.h + AuthCrypt.cpp \ + AuthCrypt.h \ + BigNumber.cpp \ + BigNumber.h \ + Hmac.cpp \ + Hmac.h \ + Sha1.cpp \ + Sha1.h \ + md5.c \ + md5.h diff --git a/src/shared/Database/Makefile.am b/src/shared/Database/Makefile.am index 31c24917b..f9de9576f 100644 --- a/src/shared/Database/Makefile.am +++ b/src/shared/Database/Makefile.am @@ -27,38 +27,38 @@ AM_CPPFLAGS = $(MANGOS_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir) -I$(sr noinst_LIBRARIES = libmangosdatabase.a libmangosdatabase_a_SOURCES = \ - DBCStores.cpp \ - DBCStores.h \ - DBCStructure.h \ - DBCfmt.cpp \ - Database.cpp \ - Database.h \ - DatabaseEnv.h \ - DatabaseImpl.h \ - DatabaseMysql.cpp \ - DatabasePostgre.cpp \ - DatabaseMysql.h \ - DatabasePostgre.h \ - DatabaseSqlite.cpp \ - DatabaseSqlite.h \ - DBCEnums.h \ - Field.cpp \ - Field.h \ - MySQLDelayThread.h \ - PGSQLDelayThread.h \ - QueryResult.h \ - QueryResultMysql.cpp \ - QueryResultMysql.h \ - QueryResultPostgre.cpp \ - QueryResultPostgre.h \ - QueryResultSqlite.cpp \ - QueryResultSqlite.h \ - SQLStorage.cpp \ - SQLStorage.h \ - SQLStorageImpl.h \ - SqlDelayThread.cpp \ - SqlDelayThread.h \ - SqlOperations.cpp \ - SqlOperations.h \ - dbcfile.cpp \ - dbcfile.h + DBCStores.cpp \ + DBCStores.h \ + DBCStructure.h \ + DBCfmt.cpp \ + Database.cpp \ + Database.h \ + DatabaseEnv.h \ + DatabaseImpl.h \ + DatabaseMysql.cpp \ + DatabasePostgre.cpp \ + DatabaseMysql.h \ + DatabasePostgre.h \ + DatabaseSqlite.cpp \ + DatabaseSqlite.h \ + DBCEnums.h \ + Field.cpp \ + Field.h \ + MySQLDelayThread.h \ + PGSQLDelayThread.h \ + QueryResult.h \ + QueryResultMysql.cpp \ + QueryResultMysql.h \ + QueryResultPostgre.cpp \ + QueryResultPostgre.h \ + QueryResultSqlite.cpp \ + QueryResultSqlite.h \ + SQLStorage.cpp \ + SQLStorage.h \ + SQLStorageImpl.h \ + SqlDelayThread.cpp \ + SqlDelayThread.h \ + SqlOperations.cpp \ + SqlOperations.h \ + dbcfile.cpp \ + dbcfile.h diff --git a/src/shared/Makefile.am b/src/shared/Makefile.am index 087f0ec20..f4533e4c2 100644 --- a/src/shared/Makefile.am +++ b/src/shared/Makefile.am @@ -30,24 +30,24 @@ noinst_LIBRARIES = libmangosshared.a # libmangosshared library will later be reused by ... libmangosshared_a_SOURCES = \ - Base.cpp \ - Base.h \ - ByteBuffer.h \ - Common.cpp \ - Common.h \ - Errors.h \ - Log.cpp \ - Log.h \ - MemoryLeaks.cpp \ - MemoryLeaks.h \ - ProgressBar.cpp \ - ProgressBar.h \ - Timer.h \ - Util.cpp \ - Util.h \ - WorldPacket.h \ - revision_nr.h \ - revision.h + Base.cpp \ + Base.h \ + ByteBuffer.h \ + Common.cpp \ + Common.h \ + Errors.h \ + Log.cpp \ + Log.h \ + MemoryLeaks.cpp \ + MemoryLeaks.h \ + ProgressBar.cpp \ + ProgressBar.h \ + Timer.h \ + Util.cpp \ + Util.h \ + WorldPacket.h \ + revision_nr.h \ + revision.h # Get revision (git or svn) REVISION_FILE = revision.h @@ -63,16 +63,16 @@ $(REVISION_FILE) : $(top_builddir)/src/tools/genrevision/genrevision FORCE ## Additional files to include when running 'make dist' # Disabled packet logger EXTRA_DIST = \ - PacketLog.cpp \ - PacketLog.h + PacketLog.cpp \ + PacketLog.h # System configuration EXTRA_DIST += \ - SystemConfig.h + SystemConfig.h # System Win32 files EXTRA_DIST += \ - ServiceWin32.cpp \ - ServiceWin32.h \ - WheatyExceptionReport.cpp \ - WheatyExceptionReport.h + ServiceWin32.cpp \ + ServiceWin32.h \ + WheatyExceptionReport.cpp \ + WheatyExceptionReport.h diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index ee3af12e8..87d3beae2 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7355" + #define REVISION_NR "7356" #endif // __REVISION_NR_H__ diff --git a/src/shared/vmap/Makefile.am b/src/shared/vmap/Makefile.am index 14ace12f0..8ebbb1e04 100644 --- a/src/shared/vmap/Makefile.am +++ b/src/shared/vmap/Makefile.am @@ -27,30 +27,30 @@ AM_CPPFLAGS = $(MANGOS_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir) -I$(sr noinst_LIBRARIES = libmangosvmaps.a libmangosvmaps_a_SOURCES = \ - AABSPTree.h \ - BaseModel.cpp \ - BaseModel.h \ - CoordModelMapping.cpp \ - CoordModelMapping.h \ - DebugCmdLogger.cpp \ - DebugCmdLogger.h \ - IVMapManager.h \ - ManagedModelContainer.cpp \ - ManagedModelContainer.h \ - ModelContainer.cpp \ - ModelContainer.h \ - NodeValueAccess.h \ - ShortBox.h \ - ShortVector.h \ - SubModel.cpp \ - SubModel.h \ - TileAssembler.cpp \ - TileAssembler.h \ - TreeNode.cpp \ - TreeNode.h \ - VMapDefinitions.h \ - VMapFactory.cpp \ - VMapFactory.h \ - VMapManager.cpp \ - VMapManager.h \ - VMapTools.h + AABSPTree.h \ + BaseModel.cpp \ + BaseModel.h \ + CoordModelMapping.cpp \ + CoordModelMapping.h \ + DebugCmdLogger.cpp \ + DebugCmdLogger.h \ + IVMapManager.h \ + ManagedModelContainer.cpp \ + ManagedModelContainer.h \ + ModelContainer.cpp \ + ModelContainer.h \ + NodeValueAccess.h \ + ShortBox.h \ + ShortVector.h \ + SubModel.cpp \ + SubModel.h \ + TileAssembler.cpp \ + TileAssembler.h \ + TreeNode.cpp \ + TreeNode.h \ + VMapDefinitions.h \ + VMapFactory.cpp \ + VMapFactory.h \ + VMapManager.cpp \ + VMapManager.h \ + VMapTools.h From 07bce28d5c62ffb3cc0afdac2db92dccd86bb4c6 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sat, 28 Feb 2009 01:56:47 +0300 Subject: [PATCH 28/32] Call proper function for .reload spell_area --- src/game/Chat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index 6ed450502..b943865c0 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -309,7 +309,7 @@ ChatCommand * ChatHandler::getCommandTable() { "skill_fishing_base_level", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSkillFishingBaseLevelCommand, "", NULL }, { "skinning_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesSkinningCommand, "", NULL }, { "spell_affect", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellAffectCommand, "", NULL }, - { "spell_area", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellLearnSpellCommand, "", NULL }, + { "spell_area", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellAreaCommand, "", NULL }, { "spell_chain", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellChainCommand, "", NULL }, { "spell_elixir", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellElixirCommand, "", NULL }, { "spell_learn_spell", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellLearnSpellCommand, "", NULL }, From 91ad4c21de769ad41a71c1a5ef92339cca7b7292 Mon Sep 17 00:00:00 2001 From: balrok Date: Sat, 28 Feb 2009 01:57:47 +0300 Subject: [PATCH 29/32] [7357] Fixed double applied playerlink in .levelup command. Signed-off-by: VladimirMangos --- src/game/Level3.cpp | 2 +- src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 51e840dbe..ec2bd95d5 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -3852,7 +3852,7 @@ bool ChatHandler::HandleLevelUpCommand(const char* args) return false; } - name = GetNameLink(chr); + name = chr->GetName(); } assert(chr || chr_guid); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 87d3beae2..e4665bd5a 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7356" + #define REVISION_NR "7357" #endif // __REVISION_NR_H__ From 2791d5a6d31e7b7646138328af1773b966d99fd3 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sat, 28 Feb 2009 03:24:01 +0300 Subject: [PATCH 30/32] [7358] Fixed spell_area autocast field loading. --- src/game/SpellMgr.cpp | 1 + src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index e164f8d05..89e88600e 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -2390,6 +2390,7 @@ void SpellMgr::LoadSpellAreas() spellArea.auraSpell = fields[5].GetUInt32(); spellArea.raceMask = fields[6].GetUInt32(); spellArea.gender = Gender(fields[7].GetUInt8()); + spellArea.autocast = fields[8].GetBool(); if(!sSpellStore.LookupEntry(spell)) { diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index e4665bd5a..6149e27cb 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7357" + #define REVISION_NR "7358" #endif // __REVISION_NR_H__ From 4994611582aeaef5ea231f176f516c66b8141acb Mon Sep 17 00:00:00 2001 From: Triply Date: Sat, 28 Feb 2009 09:55:17 +0100 Subject: [PATCH 31/32] [7359] Fixed crash when removing battleground from BGFreeSlotQueue. Fixed player will now drop a flag before he logs out, if he is in BG. Signed-off-by: Triply --- src/game/BattleGroundMgr.cpp | 5 ++++- src/game/WorldSession.cpp | 3 +++ src/shared/revision_nr.h | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index e5379bb64..457b36c70 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -644,8 +644,9 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve //battleground with free slot for player should be always in the beggining of the queue // maybe it would be better to create bgfreeslotqueue for each queue_id_based_on_level + bool continueAdding = true; BGFreeSlotQueueType::iterator itr, next; - for (itr = sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].end(); itr = next) + for (itr = sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].begin(); continueAdding && itr != sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].end(); itr = next) { next = itr; ++next; @@ -671,6 +672,8 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve if( !bg->HasFreeSlots() ) { + if( next == sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].end() ) + continueAdding = false; // remove BG from BGFreeSlotQueue bg->RemoveFromBGFreeSlotQueue(); } diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp index 9101711a9..73f622d6d 100644 --- a/src/game/WorldSession.cpp +++ b/src/game/WorldSession.cpp @@ -302,6 +302,9 @@ void WorldSession::LogoutPlayer(bool Save) _player->BuildPlayerRepop(); _player->RepopAtGraveyard(); } + //drop a flag if player is carrying it + if(BattleGround *bg = _player->GetBattleGround()) + bg->EventPlayerDroppedFlag(_player); ///- Teleport to home if the player is in an invalid instance if(!_player->m_InstanceValid && !_player->isGameMaster()) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 6149e27cb..3f3a2957e 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7358" + #define REVISION_NR "7359" #endif // __REVISION_NR_H__ From b9326100eaa21b2627b78b1f1e3316a073f56682 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 1 Mar 2009 00:23:51 +0300 Subject: [PATCH 32/32] [7360] Use defines instead harcoded item prototype array sizes. --- src/game/Item.cpp | 2 +- src/game/Item.h | 2 +- src/game/ItemHandler.cpp | 6 +++--- src/game/ItemPrototype.h | 15 ++++++++++----- src/game/ObjectMgr.cpp | 18 ++++++++++++------ src/game/Player.cpp | 10 +++++----- src/game/Spell.cpp | 6 +++--- src/game/SpellHandler.cpp | 2 +- src/shared/revision_nr.h | 2 +- 9 files changed, 37 insertions(+), 26 deletions(-) diff --git a/src/game/Item.cpp b/src/game/Item.cpp index 531bec46b..d7632e233 100644 --- a/src/game/Item.cpp +++ b/src/game/Item.cpp @@ -263,7 +263,7 @@ bool Item::Create( uint32 guidlow, uint32 itemid, Player const* owner) SetUInt32Value(ITEM_FIELD_MAXDURABILITY, itemProto->MaxDurability); SetUInt32Value(ITEM_FIELD_DURABILITY, itemProto->MaxDurability); - for(int i = 0; i < 5; ++i) + for(int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) SetSpellCharges(i,itemProto->Spells[i].SpellCharges); SetUInt32Value(ITEM_FIELD_FLAGS, itemProto->Flags); diff --git a/src/game/Item.h b/src/game/Item.h index 4dfea4b90..b3afa1124 100644 --- a/src/game/Item.h +++ b/src/game/Item.h @@ -165,7 +165,7 @@ enum EnchantmentSlot #define MAX_VISIBLE_ITEM_OFFSET 18 // 18 fields per visible item (creator(2) + enchantments(13) + properties(1) + seed(1) + pad(1)) -#define MAX_GEM_SOCKETS 3 // (BONUS_ENCHANTMENT_SLOT-SOCK_ENCHANTMENT_SLOT) +#define MAX_GEM_SOCKETS MAX_ITEM_PROTO_SOCKETS// (BONUS_ENCHANTMENT_SLOT-SOCK_ENCHANTMENT_SLOT) and item proto size, equal value expected enum EnchantmentOffset { diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp index 6a95acda2..dc92c6539 100644 --- a/src/game/ItemHandler.cpp +++ b/src/game/ItemHandler.cpp @@ -355,7 +355,7 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data ) } data << pProto->ScalingStatDistribution; // scaling stats distribution data << pProto->ScalingStatValue; // some kind of flags used to determine stat values column - for(int i = 0; i < 5; ++i) + for(int i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i) { data << pProto->Damage[i].DamageMin; data << pProto->Damage[i].DamageMax; @@ -375,7 +375,7 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data ) data << pProto->AmmoType; data << pProto->RangedModRange; - for(int s = 0; s < 5; s++) + for(int s = 0; s < MAX_ITEM_PROTO_SPELLS; ++s) { // send DBC data for cooldowns in same way as it used in Spell::SendSpellCooldown // use `item_template` or if not set then only use spell cooldowns @@ -429,7 +429,7 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data ) data << pProto->Map; // Added in 1.12.x & 2.0.1 client branch data << pProto->BagFamily; data << pProto->TotemCategory; - for(int s = 0; s < 3; s++) + for(int s = 0; s < MAX_ITEM_PROTO_SOCKETS; ++s) { data << pProto->Socket[s].Color; data << pProto->Socket[s].Content; diff --git a/src/game/ItemPrototype.h b/src/game/ItemPrototype.h index d46a80492..3335f3247 100644 --- a/src/game/ItemPrototype.h +++ b/src/game/ItemPrototype.h @@ -491,6 +491,11 @@ struct _Socket uint32 Content; }; +#define MAX_ITEM_PROTO_DAMAGES 5 +#define MAX_ITEM_PROTO_SOCKETS 3 +#define MAX_ITEM_PROTO_SPELLS 5 +#define MAX_ITEM_PROTO_STATS 10 + struct ItemPrototype { uint32 ItemId; @@ -520,10 +525,10 @@ struct ItemPrototype int32 Stackable; // 0: not allowed, -1: put in player coin info tab and don't limit stacking (so 1 slot) uint32 ContainerSlots; uint32 StatsCount; - _ItemStat ItemStat[10]; + _ItemStat ItemStat[MAX_ITEM_PROTO_STATS]; uint32 ScalingStatDistribution; // id from ScalingStatDistribution.dbc uint32 ScalingStatValue; // mask for selecting column in ScalingStatValues.dbc - _Damage Damage[5]; + _Damage Damage[MAX_ITEM_PROTO_DAMAGES]; uint32 Armor; uint32 HolyRes; uint32 FireRes; @@ -534,7 +539,7 @@ struct ItemPrototype uint32 Delay; uint32 AmmoType; float RangedModRange; - _Spell Spells[5]; + _Spell Spells[MAX_ITEM_PROTO_SPELLS]; uint32 Bonding; char* Description; uint32 PageText; @@ -553,7 +558,7 @@ struct ItemPrototype uint32 Map; // id from Map.dbc uint32 BagFamily; // id from ItemBagFamily.dbc uint32 TotemCategory; // id from TotemCategory.dbc - _Socket Socket[3]; + _Socket Socket[MAX_ITEM_PROTO_SOCKETS]; uint32 socketBonus; // id from SpellItemEnchantment.dbc uint32 GemProperties; // id from GemProperties.dbc uint32 RequiredDisenchantSkill; @@ -634,7 +639,7 @@ struct ItemPrototype if (Delay == 0) return 0; float temp = 0; - for (int i=0;i<5;++i) + for (int i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i) temp+=Damage[i].DamageMin + Damage[i].DamageMax; return temp*500/Delay; } diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index c782fcf81..36c209a00 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -1477,7 +1477,7 @@ void ObjectMgr::LoadItemPrototypes() bool req = proto->InventoryType!=INVTYPE_NON_EQUIP || proto->PageText; if(!req) { - for (int j = 0; j < 5; ++j) + for (int j = 0; j < MAX_ITEM_PROTO_SPELLS; ++j) { if(proto->Spells[j].SpellId) { @@ -1542,7 +1542,13 @@ void ObjectMgr::LoadItemPrototypes() const_cast(proto)->Stackable = 255; } - for (int j = 0; j < 10; j++) + if(proto->StatsCount > MAX_ITEM_PROTO_STATS) + { + sLog.outErrorDb("Item (Entry: %u) has too large value in statscount (%u), replace by hardcoded limit (%u).",i,proto->StatsCount,MAX_ITEM_PROTO_STATS); + const_cast(proto)->StatsCount = MAX_ITEM_PROTO_STATS; + } + + for (int j = 0; j < MAX_ITEM_PROTO_STATS; ++j) { // for ItemStatValue != 0 if(proto->ItemStat[j].ItemStatValue && proto->ItemStat[j].ItemStatType >= MAX_ITEM_MOD) @@ -1552,7 +1558,7 @@ void ObjectMgr::LoadItemPrototypes() } } - for (int j = 0; j < 5; j++) + for (int j = 0; j < MAX_ITEM_PROTO_DAMAGES; ++j) { if(proto->Damage[j].DamageType >= MAX_SPELL_SCHOOL) { @@ -1609,7 +1615,7 @@ void ObjectMgr::LoadItemPrototypes() } // spell_3*,spell_4*,spell_5* is empty - for (int j = 2; j < 5; j++) + for (int j = 2; j < MAX_ITEM_PROTO_SPELLS; ++j) { if(proto->Spells[j].SpellTrigger != ITEM_SPELLTRIGGER_ON_USE) { @@ -1627,7 +1633,7 @@ void ObjectMgr::LoadItemPrototypes() // normal spell list else { - for (int j = 0; j < 5; j++) + for (int j = 0; j < MAX_ITEM_PROTO_SPELLS; ++j) { if(proto->Spells[j].SpellTrigger >= MAX_ITEM_SPELLTRIGGER || proto->Spells[j].SpellTrigger == ITEM_SPELLTRIGGER_LEARN_SPELL_ID) { @@ -1696,7 +1702,7 @@ void ObjectMgr::LoadItemPrototypes() if(proto->TotemCategory && !sTotemCategoryStore.LookupEntry(proto->TotemCategory)) sLog.outErrorDb("Item (Entry: %u) has wrong TotemCategory (%u)",i,proto->TotemCategory); - for (int j = 0; j < 3; j++) + for (int j = 0; j < MAX_ITEM_PROTO_SOCKETS; j++) { if(proto->Socket[j].Color && (proto->Socket[j].Color & SOCKET_COLOR_ALL) != proto->Socket[j].Color) { diff --git a/src/game/Player.cpp b/src/game/Player.cpp index fd688666f..b97e044b4 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -6580,7 +6580,7 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl if(slot >= INVENTORY_SLOT_BAG_END || !proto) return; - for (int i = 0; i < 10; i++) + for (int i = 0; i < MAX_ITEM_PROTO_STATS; ++i) { uint32 statType = 0; int32 val = 0; @@ -6913,7 +6913,7 @@ void Player::ApplyItemEquipSpell(Item *item, bool apply, bool form_change) if(!proto) return; - for (int i = 0; i < 5; i++) + for (int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) { _Spell const& spellData = proto->Spells[i]; @@ -7026,7 +7026,7 @@ void Player::CastItemCombatSpell(Item *item,Unit* Target, WeaponAttackType attTy if (!Target || Target == this ) return; - for (int i = 0; i < 5; i++) + for (int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) { _Spell const& spellData = proto->Spells[i]; @@ -7124,7 +7124,7 @@ void Player::CastItemUseSpell(Item *item,SpellCastTargets const& targets,uint8 c int count = 0; // item spells casted at use - for(int i = 0; i < 5; ++i) + for(int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) { _Spell const& spellData = proto->Spells[i]; @@ -18241,7 +18241,7 @@ void Player::SendInstanceResetWarning(uint32 mapid, uint32 time) void Player::ApplyEquipCooldown( Item * pItem ) { - for(int i = 0; i <5; ++i) + for(int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) { _Spell const& spellData = pItem->GetProto()->Spells[i]; diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 9ac30695c..23d6a2815 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -321,7 +321,7 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi if((m_caster->getClassMask() & CLASSMASK_WAND_USERS) != 0 && m_caster->GetTypeId()==TYPEID_PLAYER) { if(Item* pItem = ((Player*)m_caster)->GetWeaponForAttack(RANGED_ATTACK)) - m_spellSchoolMask = SpellSchoolMask(1 << pItem->GetProto()->Damage->DamageType); + m_spellSchoolMask = SpellSchoolMask(1 << pItem->GetProto()->Damage[0].DamageType); } } // Set health leech amount to zero @@ -2542,7 +2542,7 @@ void Spell::SendSpellCooldown() ItemPrototype const* proto = m_CastItem->GetProto(); if(proto) { - for(int idx = 0; idx < 5; ++idx) + for(int idx = 0; idx < MAX_ITEM_PROTO_SPELLS; ++idx) { if(proto->Spells[idx].SpellId == m_spellInfo->Id) { @@ -3325,7 +3325,7 @@ void Spell::TakeCastItem() bool expendable = false; bool withoutCharges = false; - for (int i = 0; i<5; i++) + for (int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) { if (proto->Spells[i].SpellId) { diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp index 70227980e..986c39908 100644 --- a/src/game/SpellHandler.cpp +++ b/src/game/SpellHandler.cpp @@ -94,7 +94,7 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) if (pUser->isInCombat()) { - for(int i = 0; i < 5; ++i) + for(int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) { if (SpellEntry const *spellInfo = sSpellStore.LookupEntry(proto->Spells[i].SpellId)) { diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 3f3a2957e..057f92297 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7359" + #define REVISION_NR "7360" #endif // __REVISION_NR_H__