aboutsummaryrefslogtreecommitdiff
path: root/src/server/game
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game')
-rw-r--r--src/server/game/AI/CoreAI/CombatAI.cpp12
-rw-r--r--src/server/game/AI/CoreAI/CombatAI.h2
-rw-r--r--src/server/game/AI/CoreAI/PetAI.cpp10
-rw-r--r--src/server/game/AI/CoreAI/UnitAI.cpp8
-rw-r--r--src/server/game/AI/CoreAI/UnitAI.h5
-rw-r--r--src/server/game/AI/CreatureAI.cpp24
-rw-r--r--src/server/game/AI/CreatureAI.h5
-rw-r--r--src/server/game/AI/CreatureAIFactory.h5
-rw-r--r--src/server/game/AI/CreatureAIImpl.h290
-rw-r--r--src/server/game/AI/CreatureAISelector.cpp34
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedCreature.cpp21
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedCreature.h7
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp8
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedEscortAI.h12
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp8
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.cpp45
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.h6
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp176
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.h76
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.cpp8
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.h8
-rw-r--r--src/server/game/Accounts/AccountMgr.cpp2
-rw-r--r--src/server/game/Accounts/RBAC.cpp545
-rw-r--r--src/server/game/Accounts/RBAC.h8
-rw-r--r--src/server/game/Achievements/AchievementMgr.cpp16
-rw-r--r--src/server/game/AuctionHouse/AuctionHouseMgr.cpp120
-rw-r--r--src/server/game/AuctionHouse/AuctionHouseMgr.h30
-rw-r--r--src/server/game/AuctionHouseBot/AuctionHouseBot.cpp7
-rw-r--r--src/server/game/AuctionHouseBot/AuctionHouseBot.h10
-rw-r--r--src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.cpp44
-rw-r--r--src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp14
-rw-r--r--src/server/game/Battlefield/Battlefield.cpp8
-rw-r--r--src/server/game/Battlefield/Battlefield.h26
-rw-r--r--src/server/game/Battlefield/BattlefieldMgr.cpp4
-rw-r--r--src/server/game/Battlefield/Zones/BattlefieldWG.h2
-rw-r--r--src/server/game/Battlegrounds/Arena.cpp4
-rw-r--r--src/server/game/Battlegrounds/ArenaTeam.cpp14
-rw-r--r--src/server/game/Battlegrounds/ArenaTeamMgr.cpp4
-rw-r--r--src/server/game/Battlegrounds/Battleground.cpp109
-rw-r--r--src/server/game/Battlegrounds/Battleground.h10
-rw-r--r--src/server/game/Battlegrounds/BattlegroundMgr.cpp7
-rw-r--r--src/server/game/Battlegrounds/BattlegroundQueue.cpp52
-rw-r--r--src/server/game/Battlegrounds/BattlegroundQueue.h7
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp4
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp23
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp1
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp13
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp120
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundIC.h8
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp6
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp11
-rw-r--r--src/server/game/CMakeLists.txt70
-rw-r--r--src/server/game/Calendar/CalendarMgr.cpp12
-rw-r--r--src/server/game/Calendar/CalendarMgr.h10
-rw-r--r--src/server/game/Chat/Chat.cpp140
-rw-r--r--src/server/game/Chat/Chat.h45
-rw-r--r--src/server/game/Conditions/ConditionMgr.cpp312
-rw-r--r--src/server/game/Conditions/ConditionMgr.h89
-rw-r--r--src/server/game/Conditions/DisableMgr.cpp2
-rw-r--r--src/server/game/DataStores/DBCStores.cpp66
-rw-r--r--src/server/game/DataStores/DBCStores.h4
-rw-r--r--src/server/game/DataStores/DBCStructure.h47
-rw-r--r--src/server/game/DataStores/DBCfmt.h6
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.cpp13
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.h2
-rw-r--r--src/server/game/DungeonFinding/LFGQueue.cpp83
-rw-r--r--src/server/game/DungeonFinding/LFGQueue.h1
-rw-r--r--src/server/game/DungeonFinding/LFGScripts.cpp4
-rw-r--r--src/server/game/Entities/Corpse/Corpse.cpp76
-rw-r--r--src/server/game/Entities/Corpse/Corpse.h14
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp234
-rw-r--r--src/server/game/Entities/Creature/Creature.h60
-rw-r--r--src/server/game/Entities/Creature/CreatureGroups.cpp43
-rw-r--r--src/server/game/Entities/Creature/CreatureGroups.h4
-rw-r--r--src/server/game/Entities/Creature/GossipDef.cpp34
-rw-r--r--src/server/game/Entities/Creature/TemporarySummon.cpp2
-rw-r--r--src/server/game/Entities/Creature/TemporarySummon.h2
-rw-r--r--src/server/game/Entities/DynamicObject/DynamicObject.cpp9
-rw-r--r--src/server/game/Entities/DynamicObject/DynamicObject.h2
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp123
-rw-r--r--src/server/game/Entities/GameObject/GameObject.h36
-rw-r--r--src/server/game/Entities/Item/Container/Bag.cpp6
-rw-r--r--src/server/game/Entities/Item/Container/Bag.h4
-rw-r--r--src/server/game/Entities/Item/Item.cpp77
-rw-r--r--src/server/game/Entities/Item/Item.h17
-rw-r--r--src/server/game/Entities/Item/ItemEnchantmentMgr.cpp8
-rw-r--r--src/server/game/Entities/Object/Object.cpp165
-rw-r--r--src/server/game/Entities/Object/Object.h21
-rw-r--r--src/server/game/Entities/Object/ObjectGuid.cpp56
-rw-r--r--src/server/game/Entities/Object/ObjectGuid.h187
-rw-r--r--src/server/game/Entities/Object/Position.cpp31
-rw-r--r--src/server/game/Entities/Object/Position.h1
-rw-r--r--src/server/game/Entities/Object/Updates/UpdateData.cpp1
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp61
-rw-r--r--src/server/game/Entities/Pet/Pet.h14
-rw-r--r--src/server/game/Entities/Player/KillRewarder.cpp274
-rw-r--r--src/server/game/Entities/Player/KillRewarder.h59
-rw-r--r--src/server/game/Entities/Player/Player.cpp1383
-rw-r--r--src/server/game/Entities/Player/Player.h233
-rw-r--r--src/server/game/Entities/Player/SocialMgr.cpp26
-rw-r--r--src/server/game/Entities/Player/SocialMgr.h31
-rw-r--r--src/server/game/Entities/Player/TradeData.cpp139
-rw-r--r--src/server/game/Entities/Player/TradeData.h81
-rw-r--r--src/server/game/Entities/Transport/Transport.cpp18
-rw-r--r--src/server/game/Entities/Transport/Transport.h8
-rw-r--r--src/server/game/Entities/Unit/StatSystem.cpp1
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp382
-rw-r--r--src/server/game/Entities/Unit/Unit.h13
-rwxr-xr-xsrc/server/game/Entities/Vehicle/Vehicle.cpp32
-rw-r--r--src/server/game/Entities/Vehicle/VehicleDefines.h3
-rw-r--r--src/server/game/Events/GameEventMgr.cpp180
-rw-r--r--src/server/game/Events/GameEventMgr.h11
-rw-r--r--src/server/game/Globals/ObjectAccessor.cpp375
-rw-r--r--src/server/game/Globals/ObjectAccessor.h202
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp914
-rw-r--r--src/server/game/Globals/ObjectMgr.h127
-rw-r--r--src/server/game/Grids/GridDefines.h3
-rw-r--r--src/server/game/Grids/Notifiers/GridNotifiers.cpp5
-rw-r--r--src/server/game/Grids/Notifiers/GridNotifiers.h26
-rw-r--r--src/server/game/Grids/ObjectGridLoader.cpp65
-rw-r--r--src/server/game/Grids/ObjectGridLoader.h1
-rw-r--r--src/server/game/Groups/Group.cpp72
-rw-r--r--src/server/game/Groups/Group.h4
-rw-r--r--src/server/game/Groups/GroupMgr.cpp6
-rw-r--r--src/server/game/Groups/GroupMgr.h8
-rw-r--r--src/server/game/Guilds/Guild.cpp54
-rw-r--r--src/server/game/Guilds/Guild.h48
-rw-r--r--src/server/game/Guilds/GuildMgr.cpp8
-rw-r--r--src/server/game/Guilds/GuildMgr.h14
-rw-r--r--src/server/game/Handlers/ArenaTeamHandler.cpp9
-rw-r--r--src/server/game/Handlers/AuctionHouseHandler.cpp63
-rw-r--r--src/server/game/Handlers/BattleGroundHandler.cpp30
-rw-r--r--src/server/game/Handlers/CalendarHandler.cpp2
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp93
-rw-r--r--src/server/game/Handlers/ChatHandler.cpp4
-rw-r--r--src/server/game/Handlers/CombatHandler.cpp3
-rw-r--r--src/server/game/Handlers/DuelHandler.cpp4
-rw-r--r--src/server/game/Handlers/GroupHandler.cpp11
-rw-r--r--src/server/game/Handlers/ItemHandler.cpp5
-rw-r--r--src/server/game/Handlers/LootHandler.cpp14
-rw-r--r--src/server/game/Handlers/MailHandler.cpp22
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp91
-rw-r--r--src/server/game/Handlers/MovementHandler.cpp10
-rw-r--r--src/server/game/Handlers/NPCHandler.cpp18
-rw-r--r--src/server/game/Handlers/PetHandler.cpp26
-rw-r--r--src/server/game/Handlers/PetitionsHandler.cpp46
-rw-r--r--src/server/game/Handlers/QueryHandler.cpp81
-rw-r--r--src/server/game/Handlers/QuestHandler.cpp18
-rw-r--r--src/server/game/Handlers/ReferAFriendHandler.cpp6
-rw-r--r--src/server/game/Handlers/SkillHandler.cpp1
-rw-r--r--src/server/game/Handlers/SpellHandler.cpp12
-rw-r--r--src/server/game/Handlers/TaxiHandler.cpp64
-rw-r--r--src/server/game/Handlers/TicketHandler.cpp5
-rw-r--r--src/server/game/Handlers/TradeHandler.cpp28
-rw-r--r--src/server/game/Handlers/VehicleHandler.cpp7
-rw-r--r--src/server/game/Handlers/VoiceChatHandler.cpp1
-rw-r--r--src/server/game/Instances/InstanceSaveMgr.cpp15
-rw-r--r--src/server/game/Instances/InstanceSaveMgr.h6
-rw-r--r--src/server/game/Instances/InstanceScript.cpp27
-rw-r--r--src/server/game/Instances/InstanceScript.h7
-rw-r--r--src/server/game/Loot/LootMgr.cpp50
-rw-r--r--src/server/game/Loot/LootMgr.h8
-rw-r--r--src/server/game/Mails/Mail.cpp25
-rw-r--r--src/server/game/Mails/Mail.h31
-rw-r--r--src/server/game/Maps/Map.cpp407
-rw-r--r--src/server/game/Maps/Map.h115
-rw-r--r--src/server/game/Maps/MapInstanced.cpp7
-rw-r--r--src/server/game/Maps/MapManager.cpp10
-rw-r--r--src/server/game/Maps/MapManager.h47
-rw-r--r--src/server/game/Maps/MapUpdater.cpp5
-rw-r--r--src/server/game/Maps/TransportMgr.cpp17
-rw-r--r--src/server/game/Maps/TransportMgr.h5
-rw-r--r--src/server/game/Miscellaneous/Formulas.h6
-rw-r--r--src/server/game/Miscellaneous/Language.h11
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h29
-rw-r--r--src/server/game/Movement/MotionMaster.cpp85
-rw-r--r--src/server/game/Movement/MotionMaster.h1
-rwxr-xr-xsrc/server/game/Movement/MovementGenerator.h2
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h2
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h4
-rw-r--r--src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp2
-rw-r--r--src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h2
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp11
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/IdleMovementGenerator.h8
-rw-r--r--src/server/game/Movement/MovementGenerators/PointMovementGenerator.h8
-rw-r--r--src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h2
-rw-r--r--src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp4
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h4
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp111
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h42
-rw-r--r--src/server/game/Movement/PathGenerator.cpp23
-rw-r--r--src/server/game/Movement/PathGenerator.h2
-rw-r--r--src/server/game/Movement/Spline/MoveSpline.cpp5
-rw-r--r--src/server/game/Movement/Spline/Spline.cpp10
-rw-r--r--src/server/game/Movement/Spline/Spline.h10
-rw-r--r--src/server/game/Movement/Waypoints/Path.h100
-rw-r--r--src/server/game/OutdoorPvP/OutdoorPvP.cpp140
-rw-r--r--src/server/game/OutdoorPvP/OutdoorPvP.h44
-rw-r--r--src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp14
-rw-r--r--src/server/game/OutdoorPvP/OutdoorPvPMgr.h4
-rw-r--r--src/server/game/Pools/PoolMgr.cpp48
-rw-r--r--src/server/game/Pools/PoolMgr.h10
-rw-r--r--src/server/game/Quests/QuestDef.cpp219
-rw-r--r--src/server/game/Quests/QuestDef.h102
-rw-r--r--src/server/game/Reputation/ReputationMgr.cpp6
-rw-r--r--src/server/game/Scripting/MapScripts.cpp141
-rw-r--r--src/server/game/Scripting/ScriptLoader.cpp10
-rw-r--r--src/server/game/Scripting/ScriptMgr.cpp183
-rw-r--r--src/server/game/Scripting/ScriptMgr.h48
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp2
-rw-r--r--src/server/game/Server/WorldSession.cpp162
-rw-r--r--src/server/game/Server/WorldSession.h20
-rw-r--r--src/server/game/Server/WorldSocket.cpp347
-rw-r--r--src/server/game/Server/WorldSocket.h24
-rw-r--r--src/server/game/Server/WorldSocketMgr.cpp1
-rw-r--r--src/server/game/Skills/SkillExtraItems.cpp111
-rw-r--r--src/server/game/Skills/SkillExtraItems.h4
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp94
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp30
-rw-r--r--src/server/game/Spells/Spell.cpp189
-rw-r--r--src/server/game/Spells/Spell.h20
-rw-r--r--src/server/game/Spells/SpellEffects.cpp111
-rw-r--r--src/server/game/Spells/SpellHistory.cpp347
-rw-r--r--src/server/game/Spells/SpellHistory.h37
-rw-r--r--src/server/game/Spells/SpellInfo.cpp9
-rw-r--r--src/server/game/Spells/SpellInfo.h8
-rw-r--r--src/server/game/Spells/SpellMgr.cpp80
-rw-r--r--src/server/game/Spells/SpellScript.cpp29
-rw-r--r--src/server/game/Texts/CreatureTextMgr.cpp32
-rw-r--r--src/server/game/Texts/CreatureTextMgr.h6
-rw-r--r--src/server/game/Tickets/TicketMgr.cpp36
-rw-r--r--src/server/game/Tickets/TicketMgr.h17
-rw-r--r--src/server/game/Tools/CharacterDatabaseCleaner.cpp2
-rw-r--r--src/server/game/Tools/PlayerDump.cpp288
-rw-r--r--src/server/game/Tools/PlayerDump.h26
-rw-r--r--src/server/game/Warden/Warden.cpp3
-rw-r--r--src/server/game/Warden/WardenMac.cpp3
-rw-r--r--src/server/game/Warden/WardenWin.cpp2
-rw-r--r--src/server/game/Weather/WeatherMgr.cpp3
-rw-r--r--src/server/game/World/World.cpp166
-rw-r--r--src/server/game/World/World.h37
241 files changed, 7688 insertions, 6466 deletions
diff --git a/src/server/game/AI/CoreAI/CombatAI.cpp b/src/server/game/AI/CoreAI/CombatAI.cpp
index 7efed2976c4..9d76ee5573d 100644
--- a/src/server/game/AI/CoreAI/CombatAI.cpp
+++ b/src/server/game/AI/CoreAI/CombatAI.cpp
@@ -259,7 +259,7 @@ void TurretAI::UpdateAI(uint32 /*diff*/)
// VehicleAI
//////////////
-VehicleAI::VehicleAI(Creature* creature) : CreatureAI(creature), m_ConditionsTimer(VEHICLE_CONDITION_CHECK_TIME)
+VehicleAI::VehicleAI(Creature* creature) : CreatureAI(creature), m_HasConditions(false), m_ConditionsTimer(VEHICLE_CONDITION_CHECK_TIME)
{
LoadConditions();
m_DoDismiss = false;
@@ -285,7 +285,7 @@ void VehicleAI::UpdateAI(uint32 diff)
void VehicleAI::OnCharmed(bool apply)
{
- if (!me->GetVehicleKit()->IsVehicleInUse() && !apply && !conditions.empty()) // was used and has conditions
+ if (!me->GetVehicleKit()->IsVehicleInUse() && !apply && m_HasConditions) // was used and has conditions
{
m_DoDismiss = true; // needs reset
}
@@ -297,16 +297,14 @@ void VehicleAI::OnCharmed(bool apply)
void VehicleAI::LoadConditions()
{
- conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE, me->GetEntry());
- if (!conditions.empty())
- TC_LOG_DEBUG("condition", "VehicleAI::LoadConditions: loaded %u conditions", uint32(conditions.size()));
+ m_HasConditions = sConditionMgr->HasConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE, me->GetEntry());
}
void VehicleAI::CheckConditions(uint32 diff)
{
if (m_ConditionsTimer < diff)
{
- if (!conditions.empty())
+ if (m_HasConditions)
{
if (Vehicle* vehicleKit = me->GetVehicleKit())
for (SeatMap::iterator itr = vehicleKit->Seats.begin(); itr != vehicleKit->Seats.end(); ++itr)
@@ -314,7 +312,7 @@ void VehicleAI::CheckConditions(uint32 diff)
{
if (Player* player = passenger->ToPlayer())
{
- if (!sConditionMgr->IsObjectMeetToConditions(player, me, conditions))
+ if (!sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE, me->GetEntry(), player, me))
{
player->ExitVehicle();
return; // check other pessanger in next tick
diff --git a/src/server/game/AI/CoreAI/CombatAI.h b/src/server/game/AI/CoreAI/CombatAI.h
index 97308f22e5d..26b5db3e7c8 100644
--- a/src/server/game/AI/CoreAI/CombatAI.h
+++ b/src/server/game/AI/CoreAI/CombatAI.h
@@ -112,7 +112,7 @@ struct VehicleAI : public CreatureAI
private:
void LoadConditions();
void CheckConditions(uint32 diff);
- ConditionList conditions;
+ bool m_HasConditions;
uint32 m_ConditionsTimer;
bool m_DoDismiss;
uint32 m_DismissTimer;
diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp
index 2522c97de25..c870f786af3 100644
--- a/src/server/game/AI/CoreAI/PetAI.cpp
+++ b/src/server/game/AI/CoreAI/PetAI.cpp
@@ -55,7 +55,7 @@ void PetAI::_stopAttack()
{
if (!me->IsAlive())
{
- TC_LOG_DEBUG("misc", "Creature stoped attacking cuz his dead [guid=%u]", me->GetGUIDLow());
+ TC_LOG_DEBUG("misc", "Creature stoped attacking cuz his dead [guid=%u]", me->GetGUID().GetCounter());
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveIdle();
me->CombatStop();
@@ -97,7 +97,7 @@ void PetAI::UpdateAI(uint32 diff)
if (_needToStop())
{
- TC_LOG_DEBUG("misc", "Pet AI stopped attacking [guid=%u]", me->GetGUIDLow());
+ TC_LOG_DEBUG("misc", "Pet AI stopped attacking [guid=%u]", me->GetGUID().GetCounter());
_stopAttack();
return;
}
@@ -439,7 +439,7 @@ void PetAI::HandleReturnMovement()
ClearCharmInfoFlags();
me->GetCharmInfo()->SetIsReturning(true);
me->GetMotionMaster()->Clear();
- me->GetMotionMaster()->MovePoint(me->GetGUIDLow(), x, y, z);
+ me->GetMotionMaster()->MovePoint(me->GetGUID().GetCounter(), x, y, z);
}
}
else // COMMAND_FOLLOW
@@ -492,7 +492,7 @@ void PetAI::MovementInform(uint32 moveType, uint32 data)
{
// Pet is returning to where stay was clicked. data should be
// pet's GUIDLow since we set that as the waypoint ID
- if (data == me->GetGUIDLow() && me->GetCharmInfo()->IsReturning())
+ if (data == me->GetGUID().GetCounter() && me->GetCharmInfo()->IsReturning())
{
ClearCharmInfoFlags();
me->GetCharmInfo()->SetIsAtStay(true);
@@ -505,7 +505,7 @@ void PetAI::MovementInform(uint32 moveType, uint32 data)
{
// If data is owner's GUIDLow then we've reached follow point,
// otherwise we're probably chasing a creature
- if (me->GetCharmerOrOwner() && me->GetCharmInfo() && data == me->GetCharmerOrOwner()->GetGUIDLow() && me->GetCharmInfo()->IsReturning())
+ if (me->GetCharmerOrOwner() && me->GetCharmInfo() && data == me->GetCharmerOrOwner()->GetGUID().GetCounter() && me->GetCharmInfo()->IsReturning())
{
ClearCharmInfoFlags();
me->GetCharmInfo()->SetIsFollowing(true);
diff --git a/src/server/game/AI/CoreAI/UnitAI.cpp b/src/server/game/AI/CoreAI/UnitAI.cpp
index 5aa6ea8ea7a..f0d9d34db69 100644
--- a/src/server/game/AI/CoreAI/UnitAI.cpp
+++ b/src/server/game/AI/CoreAI/UnitAI.cpp
@@ -29,7 +29,15 @@
void UnitAI::AttackStart(Unit* victim)
{
if (victim && me->Attack(victim, true))
+ {
+ // Clear distracted state on attacking
+ if (me->HasUnitState(UNIT_STATE_DISTRACTED))
+ {
+ me->ClearUnitState(UNIT_STATE_DISTRACTED);
+ me->GetMotionMaster()->Clear();
+ }
me->GetMotionMaster()->MoveChase(victim);
+ }
}
void UnitAI::AttackStartCaster(Unit* victim, float dist)
diff --git a/src/server/game/AI/CoreAI/UnitAI.h b/src/server/game/AI/CoreAI/UnitAI.h
index efe55830b1b..c93ed0db008 100644
--- a/src/server/game/AI/CoreAI/UnitAI.h
+++ b/src/server/game/AI/CoreAI/UnitAI.h
@@ -22,6 +22,7 @@
#include "Define.h"
#include "Unit.h"
#include "Containers.h"
+#include "EventMap.h"
#include <list>
class Player;
@@ -254,8 +255,8 @@ class UnitAI
static void FillAISpellInfo();
virtual void sGossipHello(Player* /*player*/) { }
- virtual void sGossipSelect(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/) { }
- virtual void sGossipSelectCode(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/, char const* /*code*/) { }
+ virtual void sGossipSelect(Player* /*player*/, uint32 /*menuId*/, uint32 /*gossipListId*/) { }
+ virtual void sGossipSelectCode(Player* /*player*/, uint32 /*menuId*/, uint32 /*gossipListId*/, char const* /*code*/) { }
virtual void sQuestAccept(Player* /*player*/, Quest const* /*quest*/) { }
virtual void sQuestSelect(Player* /*player*/, Quest const* /*quest*/) { }
virtual void sQuestReward(Player* /*player*/, Quest const* /*quest*/, uint32 /*opt*/) { }
diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp
index 96a25588120..d76d106e81a 100644
--- a/src/server/game/AI/CreatureAI.cpp
+++ b/src/server/game/AI/CreatureAI.cpp
@@ -140,6 +140,30 @@ void CreatureAI::MoveInLineOfSight(Unit* who)
// me->GetMotionMaster()->MoveChase(who->GetVictim());
}
+// Distract creature, if player gets too close while stealthed/prowling
+void CreatureAI::TriggerAlert(Unit const* who) const
+{
+ // If there's no target, or target isn't a player do nothing
+ if (!who || who->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ // If this unit isn't an NPC, is already distracted, is in combat, is confused, stunned or fleeing, do nothing
+ if (me->GetTypeId() != TYPEID_UNIT || me->IsInCombat() || me->HasUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_STUNNED | UNIT_STATE_FLEEING | UNIT_STATE_DISTRACTED))
+ return;
+
+ // Only alert for hostiles!
+ if (me->IsCivilian() || me->HasReactState(REACT_PASSIVE) || !me->IsHostileTo(who) || !me->_IsTargetAcceptable(who))
+ return;
+
+ // Send alert sound (if any) for this creature
+ me->SendAIReaction(AI_REACTION_ALERT);
+
+ // Face the unit (stealthed player) and set distracted state for 5 seconds
+ me->SetFacingTo(me->GetAngle(who->GetPositionX(), who->GetPositionY()));
+ me->StopMoving();
+ me->GetMotionMaster()->MoveDistract(5 * IN_MILLISECONDS);
+}
+
void CreatureAI::EnterEvadeMode()
{
if (!_EnterEvadeMode())
diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h
index 2e862c37c0e..a205ef16833 100644
--- a/src/server/game/AI/CreatureAI.h
+++ b/src/server/game/AI/CreatureAI.h
@@ -89,6 +89,9 @@ class CreatureAI : public UnitAI
// Called if IsVisible(Unit* who) is true at each who move, reaction at visibility zone enter
void MoveInLineOfSight_Safe(Unit* who);
+ // Trigger Creature "Alert" state (creature can see stealthed unit)
+ void TriggerAlert(Unit const* who) const;
+
// Called in Creature::Update when deathstate = DEAD. Inherited classes may maniuplate the ability to respawn based on scripted events.
virtual bool CanRespawn() { return true; }
@@ -119,7 +122,7 @@ class CreatureAI : public UnitAI
// Called when the creature is target of hostile action: swing, hostile spell landed, fear/etc)
virtual void AttackedBy(Unit* /*attacker*/) { }
- virtual bool IsEscorted() { return false; }
+ virtual bool IsEscorted() const { return false; }
// Called when creature is spawned or respawned (for reseting variables)
virtual void JustRespawned() { Reset(); }
diff --git a/src/server/game/AI/CreatureAIFactory.h b/src/server/game/AI/CreatureAIFactory.h
index 4473d3e9cd5..4e11630259b 100644
--- a/src/server/game/AI/CreatureAIFactory.h
+++ b/src/server/game/AI/CreatureAIFactory.h
@@ -50,6 +50,8 @@ CreatureAIFactory<REAL_AI>::Create(void* data) const
typedef FactoryHolder<CreatureAI> CreatureAICreator;
typedef FactoryHolder<CreatureAI>::FactoryHolderRegistry CreatureAIRegistry;
+#define sCreatureAIRegistry CreatureAIRegistry::instance()
+
//GO
struct SelectableGameObjectAI : public FactoryHolder<GameObjectAI>, public Permissible<GameObject>
{
@@ -76,4 +78,7 @@ GameObjectAIFactory<REAL_GO_AI>::Create(void* data) const
typedef FactoryHolder<GameObjectAI> GameObjectAICreator;
typedef FactoryHolder<GameObjectAI>::FactoryHolderRegistry GameObjectAIRegistry;
+
+#define sGameObjectAIRegistry GameObjectAIRegistry::instance()
+
#endif
diff --git a/src/server/game/AI/CreatureAIImpl.h b/src/server/game/AI/CreatureAIImpl.h
index a2c5c5db057..529f7420021 100644
--- a/src/server/game/AI/CreatureAIImpl.h
+++ b/src/server/game/AI/CreatureAIImpl.h
@@ -23,292 +23,14 @@
#include "CreatureAI.h"
#include "SpellMgr.h"
-template<class T>
-inline
-const T& RAND(const T& v1, const T& v2)
-{
- return (urand(0, 1)) ? v1 : v2;
-}
-
-template<class T>
-inline
-const T& RAND(const T& v1, const T& v2, const T& v3)
-{
- switch (urand(0, 2))
- {
- default:
- case 0: return v1;
- case 1: return v2;
- case 2: return v3;
- }
-}
-
-template<class T>
-inline
-const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4)
-{
- switch (urand(0, 3))
- {
- default:
- case 0: return v1;
- case 1: return v2;
- case 2: return v3;
- case 3: return v4;
- }
-}
-
-template<class T>
-inline
-const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
-{
- switch (urand(0, 4))
- {
- default:
- case 0: return v1;
- case 1: return v2;
- case 2: return v3;
- case 3: return v4;
- case 4: return v5;
- }
-}
-
-template<class T>
-inline
-const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6)
-{
- switch (urand(0, 5))
- {
- default:
- case 0: return v1;
- case 1: return v2;
- case 2: return v3;
- case 3: return v4;
- case 4: return v5;
- case 5: return v6;
- }
-}
-
-template<class T>
-inline
-const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7)
-{
- switch (urand(0, 6))
- {
- default:
- case 0: return v1;
- case 1: return v2;
- case 2: return v3;
- case 3: return v4;
- case 4: return v5;
- case 5: return v6;
- case 6: return v7;
- }
-}
-
-template<class T>
-inline
-const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7, const T& v8)
-{
- switch (urand(0, 7))
- {
- default:
- case 0: return v1;
- case 1: return v2;
- case 2: return v3;
- case 3: return v4;
- case 4: return v5;
- case 5: return v6;
- case 6: return v7;
- case 7: return v8;
- }
-}
-
-template<class T>
-inline
-const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7, const T& v8,
- const T& v9)
-{
- switch (urand(0, 8))
- {
- default:
- case 0: return v1;
- case 1: return v2;
- case 2: return v3;
- case 3: return v4;
- case 4: return v5;
- case 5: return v6;
- case 6: return v7;
- case 7: return v8;
- case 8: return v9;
- }
-}
-
-template<class T>
-inline
-const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7, const T& v8,
- const T& v9, const T& v10)
-{
- switch (urand(0, 9))
- {
- default:
- case 0: return v1;
- case 1: return v2;
- case 2: return v3;
- case 3: return v4;
- case 4: return v5;
- case 5: return v6;
- case 6: return v7;
- case 7: return v8;
- case 8: return v9;
- case 9: return v10;
- }
-}
-
-template<class T>
-inline
-const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7, const T& v8,
- const T& v9, const T& v10, const T& v11)
-{
- switch (urand(0, 10))
- {
- default:
- case 0: return v1;
- case 1: return v2;
- case 2: return v3;
- case 3: return v4;
- case 4: return v5;
- case 5: return v6;
- case 6: return v7;
- case 7: return v8;
- case 8: return v9;
- case 9: return v10;
- case 10: return v11;
- }
-}
-
-template<class T>
-inline
-const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7, const T& v8,
- const T& v9, const T& v10, const T& v11, const T& v12)
-{
- switch (urand(0, 11))
- {
- default:
- case 0: return v1;
- case 1: return v2;
- case 2: return v3;
- case 3: return v4;
- case 4: return v5;
- case 5: return v6;
- case 6: return v7;
- case 7: return v8;
- case 8: return v9;
- case 9: return v10;
- case 10: return v11;
- case 11: return v12;
- }
-}
-
-template<class T>
-inline
-const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7, const T& v8,
- const T& v9, const T& v10, const T& v11, const T& v12, const T& v13)
-{
- switch (urand(0, 12))
- {
- default:
- case 0: return v1;
- case 1: return v2;
- case 2: return v3;
- case 3: return v4;
- case 4: return v5;
- case 5: return v6;
- case 6: return v7;
- case 7: return v8;
- case 8: return v9;
- case 9: return v10;
- case 10: return v11;
- case 11: return v12;
- case 12: return v13;
- }
-}
-
-template<class T>
-inline
-const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7, const T& v8,
- const T& v9, const T& v10, const T& v11, const T& v12, const T& v13, const T& v14)
-{
- switch (urand(0, 13))
- {
- default:
- case 0: return v1;
- case 1: return v2;
- case 2: return v3;
- case 3: return v4;
- case 4: return v5;
- case 5: return v6;
- case 6: return v7;
- case 7: return v8;
- case 8: return v9;
- case 9: return v10;
- case 10: return v11;
- case 11: return v12;
- case 12: return v13;
- case 13: return v14;
- }
-}
-
-template<class T>
-inline
-const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7, const T& v8,
- const T& v9, const T& v10, const T& v11, const T& v12, const T& v13, const T& v14, const T& v15)
-{
- switch (urand(0, 14))
- {
- default:
- case 0: return v1;
- case 1: return v2;
- case 2: return v3;
- case 3: return v4;
- case 4: return v5;
- case 5: return v6;
- case 6: return v7;
- case 7: return v8;
- case 8: return v9;
- case 9: return v10;
- case 10: return v11;
- case 11: return v12;
- case 12: return v13;
- case 13: return v14;
- case 14: return v15;
- }
-}
+#include <functional>
+#include <type_traits>
-template<class T>
-inline
-const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7, const T& v8,
- const T& v9, const T& v10, const T& v11, const T& v12, const T& v13, const T& v14, const T& v15, const T& v16)
+template<typename First, typename Second, typename... Rest>
+static inline First const& RAND(First const& first, Second const& second, Rest const&... rest)
{
- switch (urand(0, 15))
- {
- default:
- case 0: return v1;
- case 1: return v2;
- case 2: return v3;
- case 3: return v4;
- case 4: return v5;
- case 5: return v6;
- case 6: return v7;
- case 7: return v8;
- case 8: return v9;
- case 9: return v10;
- case 10: return v11;
- case 11: return v12;
- case 12: return v13;
- case 13: return v14;
- case 14: return v15;
- case 15: return v16;
- }
+ std::reference_wrapper<typename std::add_const<First>::type> const pack[] = { first, second, rest... };
+ return pack[urand(0, sizeof...(rest) + 1)].get();
}
enum AITarget
diff --git a/src/server/game/AI/CreatureAISelector.cpp b/src/server/game/AI/CreatureAISelector.cpp
index 07bd49bdcc6..4cab7d5c099 100644
--- a/src/server/game/AI/CreatureAISelector.cpp
+++ b/src/server/game/AI/CreatureAISelector.cpp
@@ -30,10 +30,9 @@ namespace FactorySelector
CreatureAI* selectAI(Creature* creature)
{
const CreatureAICreator* ai_factory = NULL;
- CreatureAIRegistry& ai_registry(*CreatureAIRegistry::instance());
if (creature->IsPet())
- ai_factory = ai_registry.GetRegistryItem("PetAI");
+ ai_factory = sCreatureAIRegistry->GetRegistryItem("PetAI");
//scriptname in db
if (!ai_factory)
@@ -43,32 +42,32 @@ namespace FactorySelector
// AIname in db
std::string ainame=creature->GetAIName();
if (!ai_factory && !ainame.empty())
- ai_factory = ai_registry.GetRegistryItem(ainame);
+ ai_factory = sCreatureAIRegistry->GetRegistryItem(ainame);
// select by NPC flags
if (!ai_factory)
{
if (creature->IsVehicle())
- ai_factory = ai_registry.GetRegistryItem("VehicleAI");
+ ai_factory = sCreatureAIRegistry->GetRegistryItem("VehicleAI");
else if (creature->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN) && ((Guardian*)creature)->GetOwner()->GetTypeId() == TYPEID_PLAYER)
- ai_factory = ai_registry.GetRegistryItem("PetAI");
+ ai_factory = sCreatureAIRegistry->GetRegistryItem("PetAI");
else if (creature->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK))
- ai_factory = ai_registry.GetRegistryItem("NullCreatureAI");
+ ai_factory = sCreatureAIRegistry->GetRegistryItem("NullCreatureAI");
else if (creature->IsGuard())
- ai_factory = ai_registry.GetRegistryItem("GuardAI");
+ ai_factory = sCreatureAIRegistry->GetRegistryItem("GuardAI");
else if (creature->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN))
- ai_factory = ai_registry.GetRegistryItem("PetAI");
+ ai_factory = sCreatureAIRegistry->GetRegistryItem("PetAI");
else if (creature->IsTotem())
- ai_factory = ai_registry.GetRegistryItem("TotemAI");
+ ai_factory = sCreatureAIRegistry->GetRegistryItem("TotemAI");
else if (creature->IsTrigger())
{
if (creature->m_spells[0])
- ai_factory = ai_registry.GetRegistryItem("TriggerAI");
+ ai_factory = sCreatureAIRegistry->GetRegistryItem("TriggerAI");
else
- ai_factory = ai_registry.GetRegistryItem("NullCreatureAI");
+ ai_factory = sCreatureAIRegistry->GetRegistryItem("NullCreatureAI");
}
else if (creature->IsCritter() && !creature->HasUnitTypeMask(UNIT_MASK_GUARDIAN))
- ai_factory = ai_registry.GetRegistryItem("CritterAI");
+ ai_factory = sCreatureAIRegistry->GetRegistryItem("CritterAI");
}
// select by permit check
@@ -76,7 +75,7 @@ namespace FactorySelector
{
int best_val = -1;
typedef CreatureAIRegistry::RegistryMapType RMT;
- RMT const& l = ai_registry.GetRegisteredItems();
+ RMT const& l = sCreatureAIRegistry->GetRegisteredItems();
for (RMT::const_iterator iter = l.begin(); iter != l.end(); ++iter)
{
const CreatureAICreator* factory = iter->second;
@@ -94,7 +93,7 @@ namespace FactorySelector
// select NullCreatureAI if not another cases
ainame = (ai_factory == NULL) ? "NullCreatureAI" : ai_factory->key();
- TC_LOG_DEBUG("scripts", "Creature %s (Entry: %u GUID: %u DB GUID: %u) is using AI type: %s.", creature->GetName().c_str(), creature->GetEntry(), creature->GetGUIDLow(), creature->GetDBTableGUIDLow(), ainame.c_str());
+ TC_LOG_DEBUG("scripts", "Creature %s (Entry: %u GUID: %u DB GUID: %u) is using AI type: %s.", creature->GetName().c_str(), creature->GetEntry(), creature->GetGUID().GetCounter(), creature->GetSpawnId(), ainame.c_str());
return (ai_factory == NULL ? new NullCreatureAI(creature) : ai_factory->Create(creature));
}
@@ -128,20 +127,19 @@ namespace FactorySelector
GameObjectAI* SelectGameObjectAI(GameObject* go)
{
- const GameObjectAICreator* ai_factory = NULL;
- GameObjectAIRegistry& ai_registry(*GameObjectAIRegistry::instance());
+ GameObjectAICreator const* ai_factory = NULL;
// scriptname in db
if (GameObjectAI* scriptedAI = sScriptMgr->GetGameObjectAI(go))
return scriptedAI;
- ai_factory = ai_registry.GetRegistryItem(go->GetAIName());
+ ai_factory = sGameObjectAIRegistry->GetRegistryItem(go->GetAIName());
//future goAI types go here
std::string ainame = (ai_factory == NULL || go->GetScriptId()) ? "NullGameObjectAI" : ai_factory->key();
- TC_LOG_DEBUG("scripts", "GameObject %u used AI is %s.", go->GetGUIDLow(), ainame.c_str());
+ TC_LOG_DEBUG("scripts", "GameObject %u used AI is %s.", go->GetGUID().GetCounter(), ainame.c_str());
return (ai_factory == NULL ? new NullGameObjectAI(go) : ai_factory->Create(go));
}
diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
index aa7ec3b847f..9a6742b5ebc 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
@@ -97,7 +97,6 @@ bool SummonList::HasEntry(uint32 entry) const
}
ScriptedAI::ScriptedAI(Creature* creature) : CreatureAI(creature),
- me(creature),
IsFleeing(false),
_evadeCheckCooldown(2500),
_isCombatMovementAllowed(true)
@@ -168,7 +167,7 @@ void ScriptedAI::DoPlaySoundToSet(WorldObject* source, uint32 soundId)
if (!sSoundEntriesStore.LookupEntry(soundId))
{
- TC_LOG_ERROR("scripts", "Invalid soundId %u used in DoPlaySoundToSet (Source: TypeId %u, GUID %u)", soundId, source->GetTypeId(), source->GetGUIDLow());
+ TC_LOG_ERROR("scripts", "Invalid soundId %u used in DoPlaySoundToSet (Source: TypeId %u, GUID %u)", soundId, source->GetTypeId(), source->GetGUID().GetCounter());
return;
}
@@ -457,16 +456,24 @@ BossAI::BossAI(Creature* creature, uint32 bossId) : ScriptedAI(creature),
instance(creature->GetInstanceScript()),
summons(creature),
_boundary(instance ? instance->GetBossBoundary(bossId) : NULL),
- _bossId(bossId) { }
+ _bossId(bossId)
+{
+ scheduler.SetValidator([this]
+ {
+ return !me->HasUnitState(UNIT_STATE_CASTING);
+ });
+}
void BossAI::_Reset()
{
if (!me->IsAlive())
return;
+ me->SetCombatPulseDelay(0);
me->ResetLootMode();
events.Reset();
summons.DespawnAll();
+ scheduler.CancelAll();
if (instance)
instance->SetBossState(_bossId, NOT_STARTED);
}
@@ -475,14 +482,13 @@ void BossAI::_JustDied()
{
events.Reset();
summons.DespawnAll();
+ scheduler.CancelAll();
if (instance)
instance->SetBossState(_bossId, DONE);
}
void BossAI::_EnterCombat()
{
- me->setActive(true);
- DoZoneInCombat();
if (instance)
{
// bosses do not respawn, check only on enter combat
@@ -493,6 +499,11 @@ void BossAI::_EnterCombat()
}
instance->SetBossState(_bossId, IN_PROGRESS);
}
+
+ me->SetCombatPulseDelay(5);
+ me->setActive(true);
+ DoZoneInCombat();
+ ScheduleTasks();
}
void BossAI::TeleportCheaters()
diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.h b/src/server/game/AI/ScriptedAI/ScriptedCreature.h
index 1a4c3064a59..242acbcd44d 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedCreature.h
+++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.h
@@ -23,6 +23,7 @@
#include "CreatureAI.h"
#include "CreatureAIImpl.h"
#include "InstanceScript.h"
+#include "TaskScheduler.h"
#define CAST_AI(a, b) (dynamic_cast<a*>(b))
#define ENSURE_AI(a,b) (EnsureAI<a>(b))
@@ -183,9 +184,6 @@ struct ScriptedAI : public CreatureAI
// Variables
// *************
- //Pointer to creature we are manipulating
- Creature* me;
-
//For fleeing
bool IsFleeing;
@@ -359,6 +357,8 @@ class BossAI : public ScriptedAI
// is supposed to run more than once
virtual void ExecuteEvent(uint32 /*eventId*/) { }
+ virtual void ScheduleTasks() { }
+
void Reset() override { _Reset(); }
void EnterCombat(Unit* /*who*/) override { _EnterCombat(); }
void JustDied(Unit* /*killer*/) override { _JustDied(); }
@@ -384,6 +384,7 @@ class BossAI : public ScriptedAI
EventMap events;
SummonList summons;
+ TaskScheduler scheduler;
private:
BossBoundaryMap const* const _boundary;
diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
index ed87804474a..f1c53e2f9eb 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
@@ -120,7 +120,13 @@ void npc_escortAI::MoveInLineOfSight(Unit* who)
{
if (!me->GetVictim())
{
- who->RemoveAurasByType(SPELL_AURA_MOD_STEALTH);
+ // Clear distracted state on combat
+ if (me->HasUnitState(UNIT_STATE_DISTRACTED))
+ {
+ me->ClearUnitState(UNIT_STATE_DISTRACTED);
+ me->GetMotionMaster()->Clear();
+ }
+
AttackStart(who);
}
else if (me->GetMap()->IsDungeon())
diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h
index 75ff1b8dfc9..deabd1dc484 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h
+++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h
@@ -68,8 +68,8 @@ struct npc_escortAI : public ScriptedAI
void EnterEvadeMode() override;
- void UpdateAI(uint32 diff) override; //the "internal" update, calls UpdateEscortAI()
- virtual void UpdateEscortAI(uint32 const diff); //used when it's needed to add code in update (abilities, scripted events, etc)
+ void UpdateAI(uint32 diff) override; // the "internal" update, calls UpdateEscortAI()
+ virtual void UpdateEscortAI(uint32 diff); // used when it's needed to add code in update (abilities, scripted events, etc)
void MovementInform(uint32, uint32) override;
@@ -94,16 +94,16 @@ struct npc_escortAI : public ScriptedAI
void SetEscortPaused(bool on);
bool HasEscortState(uint32 escortState) { return (m_uiEscortState & escortState) != 0; }
- virtual bool IsEscorted() override { return (m_uiEscortState & STATE_ESCORT_ESCORTING); }
+ virtual bool IsEscorted() const override { return (m_uiEscortState & STATE_ESCORT_ESCORTING); }
void SetMaxPlayerDistance(float newMax) { MaxPlayerDistance = newMax; }
- float GetMaxPlayerDistance() { return MaxPlayerDistance; }
+ float GetMaxPlayerDistance() const { return MaxPlayerDistance; }
void SetDespawnAtEnd(bool despawn) { DespawnAtEnd = despawn; }
void SetDespawnAtFar(bool despawn) { DespawnAtFar = despawn; }
- bool GetAttack() { return m_bIsActiveAttacker; }//used in EnterEvadeMode override
+ bool GetAttack() const { return m_bIsActiveAttacker; }//used in EnterEvadeMode override
void SetCanAttack(bool attack) { m_bIsActiveAttacker = attack; }
- ObjectGuid GetEventStarterGUID() { return m_uiPlayerGUID; }
+ ObjectGuid GetEventStarterGUID() const { return m_uiPlayerGUID; }
protected:
Player* GetPlayerForEscort() { return ObjectAccessor::GetPlayer(*me, m_uiPlayerGUID); }
diff --git a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp
index 7fd21a8f791..8985f722cf2 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp
@@ -117,7 +117,13 @@ void FollowerAI::MoveInLineOfSight(Unit* who)
{
if (!me->GetVictim())
{
- who->RemoveAurasByType(SPELL_AURA_MOD_STEALTH);
+ // Clear distracted state on combat
+ if (me->HasUnitState(UNIT_STATE_DISTRACTED))
+ {
+ me->ClearUnitState(UNIT_STATE_DISTRACTED);
+ me->GetMotionMaster()->Clear();
+ }
+
AttackStart(who);
}
else if (me->GetMap()->IsDungeon())
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp
index 21a15fa4f99..46cf934356d 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.cpp
+++ b/src/server/game/AI/SmartScripts/SmartAI.cpp
@@ -208,7 +208,7 @@ void SmartAI::EndPath(bool fail)
if (targets->size() == 1 && GetScript()->IsPlayer((*targets->begin())))
{
Player* player = (*targets->begin())->ToPlayer();
- if (!fail && player->IsAtGroupRewardDistance(me) && !player->GetCorpse())
+ if (!fail && player->IsAtGroupRewardDistance(me) && !player->HasCorpse())
player->GroupEventHappens(mEscortQuestID, me);
if (fail && player->GetQuestStatus(mEscortQuestID) == QUEST_STATUS_INCOMPLETE)
@@ -220,7 +220,7 @@ void SmartAI::EndPath(bool fail)
{
Player* groupGuy = groupRef->GetSource();
- if (!fail && groupGuy->IsAtGroupRewardDistance(me) && !groupGuy->GetCorpse())
+ if (!fail && groupGuy->IsAtGroupRewardDistance(me) && !groupGuy->HasCorpse())
groupGuy->AreaExploredOrEventHappens(mEscortQuestID);
if (fail && groupGuy->GetQuestStatus(mEscortQuestID) == QUEST_STATUS_INCOMPLETE)
groupGuy->FailQuest(mEscortQuestID);
@@ -233,7 +233,7 @@ void SmartAI::EndPath(bool fail)
if (GetScript()->IsPlayer((*iter)))
{
Player* player = (*iter)->ToPlayer();
- if (!fail && player->IsAtGroupRewardDistance(me) && !player->GetCorpse())
+ if (!fail && player->IsAtGroupRewardDistance(me) && !player->HasCorpse())
player->AreaExploredOrEventHappens(mEscortQuestID);
if (fail && player->GetQuestStatus(mEscortQuestID) == QUEST_STATUS_INCOMPLETE)
player->FailQuest(mEscortQuestID);
@@ -453,39 +453,15 @@ void SmartAI::MoveInLineOfSight(Unit* who)
GetScript()->OnMoveInLineOfSight(who);
- if (me->HasReactState(REACT_PASSIVE) || AssistPlayerInCombat(who))
+ if (AssistPlayerInCombat(who))
return;
- if (!CanAIAttack(who))
- return;
-
- if (!me->CanStartAttack(who, false))
- return;
-
- if (me->IsHostileTo(who))
- {
- float fAttackRadius = me->GetAttackDistance(who);
- if (me->IsWithinDistInMap(who, fAttackRadius) && me->IsWithinLOSInMap(who))
- {
- if (!me->GetVictim())
- {
- who->RemoveAurasByType(SPELL_AURA_MOD_STEALTH);
- AttackStart(who);
- }
- else/* if (me->GetMap()->IsDungeon())*/
- {
- who->SetInCombatWith(me);
- me->AddThreat(who, 0.0f);
- }
- }
- }
+ CreatureAI::MoveInLineOfSight(who);
}
bool SmartAI::CanAIAttack(const Unit* /*who*/) const
{
- if (me->GetReactState() == REACT_PASSIVE)
- return false;
- return true;
+ return !(me->HasReactState(REACT_PASSIVE));
}
bool SmartAI::AssistPlayerInCombat(Unit* who)
@@ -722,12 +698,12 @@ void SmartAI::sGossipHello(Player* player)
GetScript()->ProcessEventsFor(SMART_EVENT_GOSSIP_HELLO, player);
}
-void SmartAI::sGossipSelect(Player* player, uint32 sender, uint32 action)
+void SmartAI::sGossipSelect(Player* player, uint32 menuId, uint32 gossipListId)
{
- GetScript()->ProcessEventsFor(SMART_EVENT_GOSSIP_SELECT, player, sender, action);
+ GetScript()->ProcessEventsFor(SMART_EVENT_GOSSIP_SELECT, player, menuId, gossipListId);
}
-void SmartAI::sGossipSelectCode(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/, const char* /*code*/) { }
+void SmartAI::sGossipSelectCode(Player* /*player*/, uint32 /*menuId*/, uint32 /*gossipListId*/, const char* /*code*/) { }
void SmartAI::sQuestAccept(Player* player, Quest const* quest)
{
@@ -763,6 +739,9 @@ void SmartAI::SetCombatMove(bool on)
}
else
{
+ if (me->HasUnitState(UNIT_STATE_CONFUSED_MOVE | UNIT_STATE_FLEEING_MOVE))
+ return;
+
me->GetMotionMaster()->MovementExpired();
me->GetMotionMaster()->Clear(true);
me->StopMoving();
diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h
index 8efde6b180a..ea03a821846 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.h
+++ b/src/server/game/AI/SmartScripts/SmartAI.h
@@ -175,8 +175,8 @@ class SmartAI : public CreatureAI
void SetInvincibilityHpLevel(uint32 level) { mInvincibilityHpLevel = level; }
void sGossipHello(Player* player) override;
- void sGossipSelect(Player* player, uint32 sender, uint32 action) override;
- void sGossipSelectCode(Player* player, uint32 sender, uint32 action, const char* code) override;
+ void sGossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override;
+ void sGossipSelectCode(Player* player, uint32 menuId, uint32 gossipListId, const char* code) override;
void sQuestAccept(Player* player, Quest const* quest) override;
//void sQuestSelect(Player* player, Quest const* quest) override;
void sQuestReward(Player* player, Quest const* quest, uint32 opt) override;
@@ -214,7 +214,7 @@ class SmartAI : public CreatureAI
uint32 mWPPauseTimer;
WayPoint* mLastWP;
Position mLastOOCPos;//set on enter combat
- uint32 GetWPCount() { return mWayPoints ? mWayPoints->size() : 0; }
+ uint32 GetWPCount() const { return mWayPoints ? uint32(mWayPoints->size()) : 0; }
bool mCanRepeatPath;
bool mRun;
bool mCanAutoAttack;
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index 267c038faaf..7ca4274bc40 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -89,13 +89,8 @@ void SmartScript::ProcessEventsFor(SMART_EVENT e, Unit* unit, uint32 var0, uint3
continue;
if (eventType == e /*&& (!i->event.event_phase_mask || IsInPhase(i->event.event_phase_mask)) && !(i->event.event_flags & SMART_EVENT_FLAG_NOT_REPEATABLE && i->runOnce)*/)
- {
- ConditionList conds = sConditionMgr->GetConditionsForSmartEvent(i->entryOrGuid, i->event_id, i->source_type);
- ConditionSourceInfo info = ConditionSourceInfo(unit, GetBaseObject());
-
- if (sConditionMgr->IsObjectMeetToConditions(info, conds))
+ if (sConditionMgr->IsObjectMeetingSmartEventConditions(i->entryOrGuid, i->event_id, i->source_type, unit, GetBaseObject()))
ProcessEvent(*i, unit, var0, var1, bvar, spell, gob);
- }
}
}
@@ -114,7 +109,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
mLastInvoker = unit->GetGUID();
if (Unit* tempInvoker = GetLastInvoker())
- TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: Invoker: %s (guidlow: %u)", tempInvoker->GetName().c_str(), tempInvoker->GetGUIDLow());
+ TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: Invoker: %s (guidlow: %u)", tempInvoker->GetName().c_str(), tempInvoker->GetGUID().GetCounter());
switch (e.GetActionType())
{
@@ -123,13 +118,18 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
ObjectList* targets = GetTargets(e, unit);
Creature* talker = me;
Player* targetPlayer = NULL;
+ Unit* talkTarget = NULL;
+
if (targets)
{
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
{
if (IsCreature(*itr) && !(*itr)->ToCreature()->IsPet()) // Prevented sending text to pets.
{
- talker = (*itr)->ToCreature();
+ if (e.action.talk.useTalkTarget)
+ talkTarget = (*itr)->ToCreature();
+ else
+ talker = (*itr)->ToCreature();
break;
}
else if (IsPlayer(*itr))
@@ -148,7 +148,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
mTalkerEntry = talker->GetEntry();
mLastTextID = e.action.talk.textGroupID;
mTextTimer = e.action.talk.duration;
- Unit* talkTarget = NULL;
+
if (IsPlayer(GetLastInvoker())) // used for $vars in texts and whisper target
talkTarget = GetLastInvoker();
else if (targetPlayer)
@@ -157,7 +157,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
mUseTextTimer = true;
sCreatureTextMgr->SendChat(talker, uint8(e.action.talk.textGroupID), talkTarget);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_TALK: talker: %s (GuidLow: %u), textGuid: %u",
- talker->GetName().c_str(), talker->GetGUIDLow(), talkTarget ? talkTarget->GetGUIDLow() : 0);
+ talker->GetName().c_str(), talker->GetGUID().GetCounter(), talkTarget ? talkTarget->GetGUID().GetCounter() : 0);
break;
}
case SMART_ACTION_SIMPLE_TALK:
@@ -175,7 +175,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
sCreatureTextMgr->SendChat(me, uint8(e.action.talk.textGroupID), IsPlayer(templastInvoker) ? templastInvoker : 0, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_NORMAL, 0, TEAM_OTHER, false, (*itr)->ToPlayer());
}
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_SIMPLE_TALK: talker: %s (GuidLow: %u), textGroupId: %u",
- (*itr)->GetName().c_str(), (*itr)->GetGUIDLow(), uint8(e.action.talk.textGroupID));
+ (*itr)->GetName().c_str(), (*itr)->GetGUID().GetCounter(), uint8(e.action.talk.textGroupID));
}
delete targets;
@@ -193,7 +193,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
(*itr)->ToUnit()->HandleEmoteCommand(e.action.emote.emote);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_PLAY_EMOTE: target: %s (GuidLow: %u), emote: %u",
- (*itr)->GetName().c_str(), (*itr)->GetGUIDLow(), e.action.emote.emote);
+ (*itr)->GetName().c_str(), (*itr)->GetGUID().GetCounter(), e.action.emote.emote);
}
}
@@ -212,7 +212,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
(*itr)->PlayDirectSound(e.action.sound.sound, e.action.sound.onlySelf ? (*itr)->ToPlayer() : nullptr);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_SOUND: target: %s (GuidLow: %u), sound: %u, onlyself: %u",
- (*itr)->GetName().c_str(), (*itr)->GetGUIDLow(), e.action.sound.sound, e.action.sound.onlySelf);
+ (*itr)->GetName().c_str(), (*itr)->GetGUID().GetCounter(), e.action.sound.sound, e.action.sound.onlySelf);
}
}
@@ -233,7 +233,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
(*itr)->ToCreature()->setFaction(e.action.faction.factionID);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_SET_FACTION: Creature entry %u, GuidLow %u set faction to %u",
- (*itr)->GetEntry(), (*itr)->GetGUIDLow(), e.action.faction.factionID);
+ (*itr)->GetEntry(), (*itr)->GetGUID().GetCounter(), e.action.faction.factionID);
}
else
{
@@ -243,7 +243,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
(*itr)->ToCreature()->setFaction(ci->faction);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_SET_FACTION: Creature entry %u, GuidLow %u set faction to %u",
- (*itr)->GetEntry(), (*itr)->GetGUIDLow(), ci->faction);
+ (*itr)->GetEntry(), (*itr)->GetGUID().GetCounter(), ci->faction);
}
}
}
@@ -275,7 +275,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
uint32 displayId = ObjectMgr::ChooseDisplayId(ci);
(*itr)->ToCreature()->SetDisplayId(displayId);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: Creature entry %u, GuidLow %u set displayid to %u",
- (*itr)->GetEntry(), (*itr)->GetGUIDLow(), displayId);
+ (*itr)->GetEntry(), (*itr)->GetGUID().GetCounter(), displayId);
}
}
//if no param1, then use value from param2 (modelId)
@@ -283,14 +283,14 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
(*itr)->ToCreature()->SetDisplayId(e.action.morphOrMount.model);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: Creature entry %u, GuidLow %u set displayid to %u",
- (*itr)->GetEntry(), (*itr)->GetGUIDLow(), e.action.morphOrMount.model);
+ (*itr)->GetEntry(), (*itr)->GetGUID().GetCounter(), e.action.morphOrMount.model);
}
}
else
{
(*itr)->ToCreature()->DeMorph();
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: Creature entry %u, GuidLow %u demorphs.",
- (*itr)->GetEntry(), (*itr)->GetGUIDLow());
+ (*itr)->GetEntry(), (*itr)->GetGUID().GetCounter());
}
}
@@ -309,7 +309,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
(*itr)->ToPlayer()->FailQuest(e.action.quest.quest);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_FAIL_QUEST: Player guidLow %u fails quest %u",
- (*itr)->GetGUIDLow(), e.action.quest.quest);
+ (*itr)->GetGUID().GetCounter(), e.action.quest.quest);
}
}
@@ -330,7 +330,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
(*itr)->ToPlayer()->AddQuestAndCheckCompletion(q, NULL);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_ADD_QUEST: Player guidLow %u add quest %u",
- (*itr)->GetGUIDLow(), e.action.quest.quest);
+ (*itr)->GetGUID().GetCounter(), e.action.quest.quest);
}
}
}
@@ -392,7 +392,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
uint32 emote = temp[urand(0, count - 1)];
(*itr)->ToUnit()->HandleEmoteCommand(emote);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_RANDOM_EMOTE: Creature guidLow %u handle random emote %u",
- (*itr)->GetGUIDLow(), emote);
+ (*itr)->GetGUID().GetCounter(), emote);
}
}
@@ -411,7 +411,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
me->getThreatManager().modifyThreatPercent(target, e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_THREAT_ALL_PCT: Creature guidLow %u modify threat for unit %u, value %i",
- me->GetGUIDLow(), target->GetGUIDLow(), e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC);
+ me->GetGUID().GetCounter(), target->GetGUID().GetCounter(), e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC);
}
}
break;
@@ -431,7 +431,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
me->getThreatManager().modifyThreatPercent((*itr)->ToUnit(), e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_THREAT_SINGLE_PCT: Creature guidLow %u modify threat for unit %u, value %i",
- me->GetGUIDLow(), (*itr)->GetGUIDLow(), e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC);
+ me->GetGUID().GetCounter(), (*itr)->GetGUID().GetCounter(), e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC);
}
}
@@ -458,7 +458,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
(*itr)->ToPlayer()->GroupEventHappens(e.action.quest.quest, me);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS: Player guidLow %u credited quest %u",
- (*itr)->GetGUIDLow(), e.action.quest.quest);
+ (*itr)->GetGUID().GetCounter(), e.action.quest.quest);
}
}
@@ -507,7 +507,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
go->CastSpell((*itr)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED) != 0);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_CAST:: %s: %u casts spell %u on target %u with castflags %u",
- (me ? me->GetGUID() : go->GetGUID()).GetTypeName(), me ? me->GetGUIDLow() : go->GetGUIDLow(), e.action.cast.spell, (*itr)->GetGUIDLow(), e.action.cast.flags);
+ (me ? me->GetGUID() : go->GetGUID()).GetTypeName(), me ? me->GetGUID().GetCounter() : go->GetGUID().GetCounter(), e.action.cast.spell, (*itr)->GetGUID().GetCounter(), e.action.cast.flags);
}
else
TC_LOG_DEBUG("scripts.ai", "Spell %u not cast because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (%s) already has the aura", e.action.cast.spell, (*itr)->GetGUID().ToString().c_str());
@@ -538,7 +538,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
tempLastInvoker->CastSpell((*itr)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED) != 0);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_INVOKER_CAST: Invoker %u casts spell %u on target %u with castflags %u",
- tempLastInvoker->GetGUIDLow(), e.action.cast.spell, (*itr)->GetGUIDLow(), e.action.cast.flags);
+ tempLastInvoker->GetGUID().GetCounter(), e.action.cast.spell, (*itr)->GetGUID().GetCounter(), e.action.cast.flags);
}
else
TC_LOG_DEBUG("scripts.ai", "Spell %u not cast because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (%s) already has the aura", e.action.cast.spell, (*itr)->GetGUID().ToString().c_str());
@@ -559,7 +559,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
(*itr)->ToUnit()->AddAura(e.action.cast.spell, (*itr)->ToUnit());
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_ADD_AURA: Adding aura %u to unit %u",
- e.action.cast.spell, (*itr)->GetGUIDLow());
+ e.action.cast.spell, (*itr)->GetGUID().GetCounter());
}
}
@@ -580,7 +580,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
(*itr)->ToGameObject()->SetLootState(GO_READY);
(*itr)->ToGameObject()->UseDoorOrButton(0, false, unit);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_ACTIVATE_GOBJECT. Gameobject %u (entry: %u) activated",
- (*itr)->GetGUIDLow(), (*itr)->GetEntry());
+ (*itr)->GetGUID().GetCounter(), (*itr)->GetEntry());
}
}
@@ -599,7 +599,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
(*itr)->ToGameObject()->ResetDoorOrButton();
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_RESET_GOBJECT. Gameobject %u (entry: %u) reset",
- (*itr)->GetGUIDLow(), (*itr)->GetEntry());
+ (*itr)->GetGUID().GetCounter(), (*itr)->GetEntry());
}
}
@@ -618,7 +618,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
(*itr)->ToUnit()->SetUInt32Value(UNIT_NPC_EMOTESTATE, e.action.emote.emote);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_SET_EMOTE_STATE. Unit %u set emotestate to %u",
- (*itr)->GetGUIDLow(), e.action.emote.emote);
+ (*itr)->GetGUID().GetCounter(), e.action.emote.emote);
}
}
@@ -639,13 +639,13 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
(*itr)->ToUnit()->SetFlag(UNIT_FIELD_FLAGS, e.action.unitFlag.flag);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_SET_UNIT_FLAG. Unit %u added flag %u to UNIT_FIELD_FLAGS",
- (*itr)->GetGUIDLow(), e.action.unitFlag.flag);
+ (*itr)->GetGUID().GetCounter(), e.action.unitFlag.flag);
}
else
{
(*itr)->ToUnit()->SetFlag(UNIT_FIELD_FLAGS_2, e.action.unitFlag.flag);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_SET_UNIT_FLAG. Unit %u added flag %u to UNIT_FIELD_FLAGS_2",
- (*itr)->GetGUIDLow(), e.action.unitFlag.flag);
+ (*itr)->GetGUID().GetCounter(), e.action.unitFlag.flag);
}
}
}
@@ -667,13 +667,13 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
(*itr)->ToUnit()->RemoveFlag(UNIT_FIELD_FLAGS, e.action.unitFlag.flag);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_REMOVE_UNIT_FLAG. Unit %u removed flag %u to UNIT_FIELD_FLAGS",
- (*itr)->GetGUIDLow(), e.action.unitFlag.flag);
+ (*itr)->GetGUID().GetCounter(), e.action.unitFlag.flag);
}
else
{
(*itr)->ToUnit()->RemoveFlag(UNIT_FIELD_FLAGS_2, e.action.unitFlag.flag);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_REMOVE_UNIT_FLAG. Unit %u removed flag %u to UNIT_FIELD_FLAGS_2",
- (*itr)->GetGUIDLow(), e.action.unitFlag.flag);
+ (*itr)->GetGUID().GetCounter(), e.action.unitFlag.flag);
}
}
}
@@ -688,7 +688,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
ENSURE_AI(SmartAI, me->AI())->SetAutoAttack(e.action.autoAttack.attack != 0);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_AUTO_ATTACK: Creature: %u bool on = %u",
- me->GetGUIDLow(), e.action.autoAttack.attack);
+ me->GetGUID().GetCounter(), e.action.autoAttack.attack);
break;
}
case SMART_ACTION_ALLOW_COMBAT_MOVEMENT:
@@ -699,7 +699,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
bool move = e.action.combatMove.move != 0;
ENSURE_AI(SmartAI, me->AI())->SetCombatMove(move);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_ALLOW_COMBAT_MOVEMENT: Creature %u bool on = %u",
- me->GetGUIDLow(), e.action.combatMove.move);
+ me->GetGUID().GetCounter(), e.action.combatMove.move);
break;
}
case SMART_ACTION_SET_EVENT_PHASE:
@@ -709,7 +709,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
SetPhase(e.action.setEventPhase.phase);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_SET_EVENT_PHASE: Creature %u set event phase %u",
- GetBaseObject()->GetGUIDLow(), e.action.setEventPhase.phase);
+ GetBaseObject()->GetGUID().GetCounter(), e.action.setEventPhase.phase);
break;
}
case SMART_ACTION_INC_EVENT_PHASE:
@@ -720,7 +720,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
IncPhase(e.action.incEventPhase.inc);
DecPhase(e.action.incEventPhase.dec);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_INC_EVENT_PHASE: Creature %u inc event phase by %u, "
- "decrease by %u", GetBaseObject()->GetGUIDLow(), e.action.incEventPhase.inc, e.action.incEventPhase.dec);
+ "decrease by %u", GetBaseObject()->GetGUID().GetCounter(), e.action.incEventPhase.inc, e.action.incEventPhase.dec);
break;
}
case SMART_ACTION_EVADE:
@@ -729,7 +729,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
break;
me->AI()->EnterEvadeMode();
- TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_EVADE: Creature %u EnterEvadeMode", me->GetGUIDLow());
+ TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_EVADE: Creature %u EnterEvadeMode", me->GetGUID().GetCounter());
break;
}
case SMART_ACTION_FLEE_FOR_ASSIST:
@@ -743,7 +743,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
Trinity::BroadcastTextBuilder builder(me, CHAT_MSG_MONSTER_EMOTE, BROADCAST_TEXT_FLEE_FOR_ASSIST);
sCreatureTextMgr->SendChatPacket(me, builder, CHAT_MSG_MONSTER_EMOTE);
}
- TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_FLEE_FOR_ASSIST: Creature %u DoFleeToGetAssistance", me->GetGUIDLow());
+ TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_FLEE_FOR_ASSIST: Creature %u DoFleeToGetAssistance", me->GetGUID().GetCounter());
break;
}
case SMART_ACTION_CALL_GROUPEVENTHAPPENS:
@@ -755,7 +755,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
unit->ToPlayer()->GroupEventHappens(e.action.quest.quest, GetBaseObject());
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_CALL_GROUPEVENTHAPPENS: Player %u, group credit for quest %u",
- unit->GetGUIDLow(), e.action.quest.quest);
+ unit->GetGUID().GetCounter(), e.action.quest.quest);
}
// Special handling for vehicles
@@ -765,6 +765,15 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
player->GroupEventHappens(e.action.quest.quest, GetBaseObject());
break;
}
+ case SMART_ACTION_COMBAT_STOP:
+ {
+ if (!me)
+ break;
+
+ me->CombatStop(true);
+ TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_COMBAT_STOP: %s CombatStop", me->GetGUID().ToString().c_str());
+ break;
+ }
case SMART_ACTION_REMOVEAURASFROMSPELL:
{
ObjectList* targets = GetTargets(e, unit);
@@ -790,7 +799,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
(*itr)->ToUnit()->RemoveAllAuras();
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_REMOVEAURASFROMSPELL: Unit %u, spell %u",
- (*itr)->GetGUIDLow(), e.action.removeAura.spell);
+ (*itr)->GetGUID().GetCounter(), e.action.removeAura.spell);
}
delete targets;
@@ -814,7 +823,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
ENSURE_AI(SmartAI, me->AI())->SetFollow((*itr)->ToUnit(), (float)e.action.follow.dist, (float)e.action.follow.angle, e.action.follow.credit, e.action.follow.entry, e.action.follow.creditType);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_FOLLOW: Creature %u following target %u",
- me->GetGUIDLow(), (*itr)->GetGUIDLow());
+ me->GetGUID().GetCounter(), (*itr)->GetGUID().GetCounter());
break;
}
}
@@ -851,7 +860,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
uint32 phase = temp[urand(0, count - 1)];
SetPhase(phase);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_RANDOM_PHASE: Creature %u sets event phase to %u",
- GetBaseObject()->GetGUIDLow(), phase);
+ GetBaseObject()->GetGUID().GetCounter(), phase);
break;
}
case SMART_ACTION_RANDOM_PHASE_RANGE:
@@ -862,7 +871,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
uint32 phase = urand(e.action.randomPhaseRange.phaseMin, e.action.randomPhaseRange.phaseMax);
SetPhase(phase);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_RANDOM_PHASE_RANGE: Creature %u sets event phase to %u",
- GetBaseObject()->GetGUIDLow(), phase);
+ GetBaseObject()->GetGUID().GetCounter(), phase);
break;
}
case SMART_ACTION_CALL_KILLEDMONSTER:
@@ -876,7 +885,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
player->RewardPlayerAndGroupAtEvent(e.action.killedMonster.creature, player);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_CALL_KILLEDMONSTER: Player %u, Killcredit: %u",
- player->GetGUIDLow(), e.action.killedMonster.creature);
+ player->GetGUID().GetCounter(), e.action.killedMonster.creature);
}
}
else // Specific target type
@@ -891,12 +900,12 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
(*itr)->ToPlayer()->KilledMonsterCredit(e.action.killedMonster.creature);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_CALL_KILLEDMONSTER: Player %u, Killcredit: %u",
- (*itr)->GetGUIDLow(), e.action.killedMonster.creature);
+ (*itr)->GetGUID().GetCounter(), e.action.killedMonster.creature);
}
else if (IsUnit(*itr)) // Special handling for vehicles
if (Vehicle* vehicle = (*itr)->ToUnit()->GetVehicleKit())
- for (SeatMap::iterator itr = vehicle->Seats.begin(); itr != vehicle->Seats.end(); ++itr)
- if (Player* player = ObjectAccessor::FindPlayer(itr->second.Passenger.Guid))
+ for (SeatMap::iterator seatItr = vehicle->Seats.begin(); seatItr != vehicle->Seats.end(); ++seatItr)
+ if (Player* player = ObjectAccessor::FindPlayer(seatItr->second.Passenger.Guid))
player->KilledMonsterCredit(e.action.killedMonster.creature);
}
@@ -970,8 +979,8 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
if (me && !me->isDead())
{
- me->Kill(me);
- TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_DIE: Creature %u", me->GetGUIDLow());
+ me->KillSelf();
+ TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_DIE: Creature %u", me->GetGUID().GetCounter());
}
break;
}
@@ -980,7 +989,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (me)
{
me->SetInCombatWithZone();
- TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_SET_IN_COMBAT_WITH_ZONE: Creature %u", me->GetGUIDLow());
+ TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_SET_IN_COMBAT_WITH_ZONE: Creature %u", me->GetGUID().GetCounter());
}
break;
}
@@ -994,7 +1003,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
Trinity::BroadcastTextBuilder builder(me, CHAT_MSG_MONSTER_EMOTE, BROADCAST_TEXT_CALL_FOR_HELP);
sCreatureTextMgr->SendChatPacket(me, builder, CHAT_MSG_MONSTER_EMOTE);
}
- TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_CALL_FOR_HELP: Creature %u", me->GetGUIDLow());
+ TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_CALL_FOR_HELP: Creature %u", me->GetGUID().GetCounter());
}
break;
}
@@ -1004,7 +1013,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
me->SetSheath(SheathState(e.action.setSheath.sheath));
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_SET_SHEATH: Creature %u, State: %u",
- me->GetGUIDLow(), e.action.setSheath.sheath);
+ me->GetGUID().GetCounter(), e.action.setSheath.sheath);
}
break;
}
@@ -1017,16 +1026,21 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
{
- if (!IsCreature(*itr))
- continue;
-
- if ((*itr)->ToUnit()->IsAlive() && IsSmart((*itr)->ToCreature()))
+ if (Creature* target = (*itr)->ToCreature())
{
- ENSURE_AI(SmartAI, (*itr)->ToCreature()->AI())->SetDespawnTime(e.action.forceDespawn.delay + 1); // Next tick
- ENSURE_AI(SmartAI, (*itr)->ToCreature()->AI())->StartDespawn();
+ if (target->IsAlive() && IsSmart(target))
+ {
+ ENSURE_AI(SmartAI, target->AI())->SetDespawnTime(e.action.forceDespawn.delay + 1); // Next tick
+ ENSURE_AI(SmartAI, target->AI())->StartDespawn();
+ }
+ else
+ target->DespawnOrUnsummon(e.action.forceDespawn.delay);
+ }
+ else if (GameObject* goTarget = (*itr)->ToGameObject())
+ {
+ if (IsSmartGO(goTarget))
+ goTarget->SetRespawnTime(e.action.forceDespawn.delay + 1);
}
- else
- (*itr)->ToCreature()->DespawnOrUnsummon(e.action.forceDespawn.delay);
}
delete targets;
@@ -1122,6 +1136,14 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
me->GetMotionMaster()->MovePoint(SMART_RANDOM_POINT, x, y, z);
break;
}
+ case SMART_ACTION_RISE_UP:
+ {
+ if (!me)
+ break;
+
+ me->GetMotionMaster()->MovePoint(SMART_RANDOM_POINT, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + (float)e.action.moveRandom.distance);
+ break;
+ }
case SMART_ACTION_SET_VISIBILITY:
{
if (me)
@@ -1227,7 +1249,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (!IsUnit(*itr))
continue;
- (*itr)->ToUnit()->Kill((*itr)->ToUnit());
+ (*itr)->ToUnit()->KillSelf();
}
delete targets;
@@ -1721,7 +1743,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (!IsUnit(*itr))
continue;
- Unit* unit = (*itr)->ToUnit();
+ Unit* targetUnit = (*itr)->ToUnit();
bool interruptedSpell = false;
@@ -1734,11 +1756,11 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
if (!interruptedSpell && e.action.cast.flags & SMARTCAST_INTERRUPT_PREVIOUS)
{
- unit->InterruptNonMeleeSpells(false);
+ targetUnit->InterruptNonMeleeSpells(false);
interruptedSpell = true;
}
- unit->CastSpell((*it)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED) != 0);
+ targetUnit->CastSpell((*it)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED) != 0);
}
else
TC_LOG_DEBUG("scripts.ai", "Spell %u not cast because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (%s) already has the aura", e.action.cast.spell, (*it)->GetGUID().ToString().c_str());
@@ -2300,10 +2322,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
void SmartScript::ProcessTimedAction(SmartScriptHolder& e, uint32 const& min, uint32 const& max, Unit* unit, uint32 var0, uint32 var1, bool bvar, const SpellInfo* spell, GameObject* gob)
{
- ConditionList const conds = sConditionMgr->GetConditionsForSmartEvent(e.entryOrGuid, e.event_id, e.source_type);
- ConditionSourceInfo info = ConditionSourceInfo(unit, GetBaseObject());
-
- if (sConditionMgr->IsObjectMeetToConditions(info, conds))
+ if (sConditionMgr->IsObjectMeetingSmartEventConditions(e.entryOrGuid, e.event_id, e.source_type, unit, GetBaseObject()))
ProcessAction(e, unit, var0, var1, bvar, spell, gob);
RecalcTimer(e, min, max);
@@ -3257,10 +3276,6 @@ void SmartScript::InitTimer(SmartScriptHolder& e)
case SMART_EVENT_UPDATE_OOC:
RecalcTimer(e, e.event.minMaxRepeat.min, e.event.minMaxRepeat.max);
break;
- case SMART_EVENT_IC_LOS:
- case SMART_EVENT_OOC_LOS:
- RecalcTimer(e, e.event.los.cooldownMin, e.event.los.cooldownMax);
- break;
case SMART_EVENT_DISTANCE_CREATURE:
case SMART_EVENT_DISTANCE_GAMEOBJECT:
RecalcTimer(e, e.event.distance.repeat, e.event.distance.repeat);
@@ -3461,14 +3476,14 @@ void SmartScript::GetScript()
SmartAIEventList e;
if (me)
{
- e = sSmartScriptMgr->GetScript(-((int32)me->GetDBTableGUIDLow()), mScriptType);
+ e = sSmartScriptMgr->GetScript(-((int32)me->GetSpawnId()), mScriptType);
if (e.empty())
e = sSmartScriptMgr->GetScript((int32)me->GetEntry(), mScriptType);
FillScript(e, me, NULL);
}
else if (go)
{
- e = sSmartScriptMgr->GetScript(-((int32)go->GetDBTableGUIDLow()), mScriptType);
+ e = sSmartScriptMgr->GetScript(-((int32)go->GetSpawnId()), mScriptType);
if (e.empty())
e = sSmartScriptMgr->GetScript((int32)go->GetEntry(), mScriptType);
FillScript(e, go, NULL);
@@ -3658,5 +3673,12 @@ void SmartScript::SetScript9(SmartScriptHolder& e, uint32 entry)
Unit* SmartScript::GetLastInvoker()
{
- return ObjectAccessor::FindUnit(mLastInvoker);
+ WorldObject* lookupRoot = me;
+ if (!lookupRoot)
+ lookupRoot = go;
+
+ if (lookupRoot)
+ return ObjectAccessor::GetUnit(*lookupRoot, mLastInvoker);
+
+ return ObjectAccessor::FindPlayer(mLastInvoker);
}
diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h
index a3d75f1889b..1c4b9a51ece 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.h
+++ b/src/server/game/AI/SmartScripts/SmartScript.h
@@ -118,7 +118,7 @@ class SmartScript
smart = false;
if (!smart)
- TC_LOG_ERROR("sql.sql", "SmartScript: Action target Creature (GUID: %u Entry: %u) is not using SmartAI, action called by Creature (GUID: %u Entry: %u) skipped to prevent crash.", c ? c->GetDBTableGUIDLow() : 0, c ? c->GetEntry() : 0, me ? me->GetDBTableGUIDLow() : 0, me ? me->GetEntry() : 0);
+ TC_LOG_ERROR("sql.sql", "SmartScript: Action target Creature (GUID: %u Entry: %u) is not using SmartAI, action called by Creature (GUID: %u Entry: %u) skipped to prevent crash.", c ? c->GetSpawnId() : 0, c ? c->GetEntry() : 0, me ? me->GetSpawnId() : 0, me ? me->GetEntry() : 0);
return smart;
}
@@ -132,7 +132,7 @@ class SmartScript
if (!go || go->GetAIName() != "SmartGameObjectAI")
smart = false;
if (!smart)
- TC_LOG_ERROR("sql.sql", "SmartScript: Action target GameObject (GUID: %u Entry: %u) is not using SmartGameObjectAI, action called by GameObject (GUID: %u Entry: %u) skipped to prevent crash.", g ? g->GetDBTableGUIDLow() : 0, g ? g->GetEntry() : 0, go ? go->GetDBTableGUIDLow() : 0, go ? go->GetEntry() : 0);
+ TC_LOG_ERROR("sql.sql", "SmartScript: Action target GameObject (GUID: %u Entry: %u) is not using SmartGameObjectAI, action called by GameObject (GUID: %u Entry: %u) skipped to prevent crash.", g ? g->GetSpawnId() : 0, g ? g->GetEntry() : 0, go ? go->GetSpawnId() : 0, go ? go->GetEntry() : 0);
return smart;
}
@@ -175,35 +175,27 @@ class SmartScript
return 0;
}
- GameObject* FindGameObjectNear(WorldObject* searchObject, uint32 guid) const
+ GameObject* FindGameObjectNear(WorldObject* searchObject, ObjectGuid::LowType guid) const
{
- GameObject* gameObject = NULL;
+ auto bounds = searchObject->GetMap()->GetGameObjectBySpawnIdStore().equal_range(guid);
+ if (bounds.first == bounds.second)
+ return nullptr;
- CellCoord p(Trinity::ComputeCellCoord(searchObject->GetPositionX(), searchObject->GetPositionY()));
- Cell cell(p);
-
- Trinity::GameObjectWithDbGUIDCheck goCheck(*searchObject, guid);
- Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck> checker(searchObject, gameObject, goCheck);
-
- TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > objectChecker(checker);
- cell.Visit(p, objectChecker, *searchObject->GetMap(), *searchObject, searchObject->GetGridActivationRange());
-
- return gameObject;
+ return bounds.first->second;
}
- Creature* FindCreatureNear(WorldObject* searchObject, uint32 guid) const
+ Creature* FindCreatureNear(WorldObject* searchObject, ObjectGuid::LowType guid) const
{
- Creature* creature = NULL;
- CellCoord p(Trinity::ComputeCellCoord(searchObject->GetPositionX(), searchObject->GetPositionY()));
- Cell cell(p);
-
- Trinity::CreatureWithDbGUIDCheck target_check(searchObject, guid);
- Trinity::CreatureSearcher<Trinity::CreatureWithDbGUIDCheck> checker(searchObject, creature, target_check);
+ auto bounds = searchObject->GetMap()->GetCreatureBySpawnIdStore().equal_range(guid);
+ if (bounds.first == bounds.second)
+ return nullptr;
- TypeContainerVisitor<Trinity::CreatureSearcher <Trinity::CreatureWithDbGUIDCheck>, GridTypeMapContainer > unit_checker(checker);
- cell.Visit(p, unit_checker, *searchObject->GetMap(), *searchObject, searchObject->GetGridActivationRange());
+ auto creatureItr = std::find_if(bounds.first, bounds.second, [](Map::CreatureBySpawnIdContainer::value_type const& pair)
+ {
+ return pair.second->IsAlive();
+ });
- return creature;
+ return creatureItr != bounds.second ? creatureItr->second : bounds.first->second;
}
ObjectListMap* mTargetStorage;
@@ -211,20 +203,27 @@ class SmartScript
void OnReset();
void ResetBaseObject()
{
- if (meOrigGUID)
+ WorldObject* lookupRoot = me;
+ if (!lookupRoot)
+ lookupRoot = go;
+
+ if (lookupRoot)
{
- if (Creature* m = HashMapHolder<Creature>::Find(meOrigGUID))
+ if (!meOrigGUID)
{
- me = m;
- go = NULL;
+ if (Creature* m = ObjectAccessor::GetCreature(*lookupRoot, meOrigGUID))
+ {
+ me = m;
+ go = NULL;
+ }
}
- }
- if (goOrigGUID)
- {
- if (GameObject* o = HashMapHolder<GameObject>::Find(goOrigGUID))
+ if (!goOrigGUID)
{
- me = NULL;
- go = o;
+ if (GameObject* o = ObjectAccessor::GetGameObject(*lookupRoot, goOrigGUID))
+ {
+ me = NULL;
+ go = o;
+ }
}
}
goOrigGUID.Clear();
@@ -247,7 +246,14 @@ class SmartScript
DecPhase(abs(p));
}
- void DecPhase(int32 p = 1) { mEventPhase -= (mEventPhase < (uint32)p ? (uint32)p - mEventPhase : (uint32)p); }
+ void DecPhase(int32 p = 1)
+ {
+ if (mEventPhase > (uint32)p)
+ mEventPhase -= (uint32)p;
+ else
+ mEventPhase = 0;
+ }
+
bool IsInPhase(uint32 p) const { return ((1 << (mEventPhase - 1)) & p) != 0; }
void SetPhase(uint32 p = 0) { mEventPhase = p; }
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
index 37187d9b04c..f0e3c3caff6 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
@@ -1135,6 +1135,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_ACTION_STORE_TARGET_LIST:
case SMART_ACTION_EVADE:
case SMART_ACTION_FLEE_FOR_ASSIST:
+ case SMART_ACTION_COMBAT_STOP:
case SMART_ACTION_DIE:
case SMART_ACTION_SET_IN_COMBAT_WITH_ZONE:
case SMART_ACTION_SET_ACTIVE:
@@ -1197,6 +1198,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_ACTION_ADD_GO_FLAG:
case SMART_ACTION_REMOVE_GO_FLAG:
case SMART_ACTION_SUMMON_CREATURE_GROUP:
+ case SMART_ACTION_RISE_UP:
break;
default:
TC_LOG_ERROR("sql.sql", "SmartAIMgr: Not handled action_type(%u), event_type(%u), Entry %d SourceType %u Event %u, skipped.", e.GetActionType(), e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id);
@@ -1228,11 +1230,11 @@ bool SmartAIMgr::IsTextValid(SmartScriptHolder const& e, uint32 id)
default:
if (e.entryOrGuid < 0)
{
- entry = uint32(std::abs(e.entryOrGuid));
- CreatureData const* data = sObjectMgr->GetCreatureData(entry);
+ ObjectGuid::LowType guid = ObjectGuid::LowType(-e.entryOrGuid);
+ CreatureData const* data = sObjectMgr->GetCreatureData(guid);
if (!data)
{
- TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u using non-existent Creature guid %d, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry);
+ TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u using non-existent Creature guid %d, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), guid);
return false;
}
else
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
index 1f4891d6c24..2f9b032c14c 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
@@ -426,7 +426,7 @@ enum SMART_SCRIPT_RESPAWN_CONDITION
enum SMART_ACTION
{
SMART_ACTION_NONE = 0, // No action
- SMART_ACTION_TALK = 1, // groupID from creature_text, duration to wait before TEXT_OVER event is triggered
+ SMART_ACTION_TALK = 1, // groupID from creature_text, duration to wait before TEXT_OVER event is triggered, useTalkTarget (0/1) - use target as talk target
SMART_ACTION_SET_FACTION = 2, // FactionId (or 0 for default)
SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL = 3, // Creature_template entry(param1) OR ModelId (param2) (or 0 for both to demorph)
SMART_ACTION_SOUND = 4, // SoundId, onlySelf
@@ -452,7 +452,7 @@ enum SMART_ACTION
SMART_ACTION_EVADE = 24, // No Params
SMART_ACTION_FLEE_FOR_ASSIST = 25, // With Emote
SMART_ACTION_CALL_GROUPEVENTHAPPENS = 26, // QuestID
- // none = 27,
+ SMART_ACTION_COMBAT_STOP = 27, //
SMART_ACTION_REMOVEAURASFROMSPELL = 28, // Spellid (0 removes all auras), charges (0 removes aura)
SMART_ACTION_FOLLOW = 29, // Distance (0 = default), Angle (0 = default), EndCreatureEntry, credit, creditType (0monsterkill, 1event)
SMART_ACTION_RANDOM_PHASE = 30, // PhaseId1, PhaseId2, PhaseId3...
@@ -539,8 +539,9 @@ enum SMART_ACTION
SMART_ACTION_GAME_EVENT_STOP = 111, // GameEventId
SMART_ACTION_GAME_EVENT_START = 112, // GameEventId
SMART_ACTION_START_CLOSEST_WAYPOINT = 113, // wp1, wp2, wp3, wp4, wp5, wp6, wp7
+ SMART_ACTION_RISE_UP = 114, // distance
- SMART_ACTION_END = 114
+ SMART_ACTION_END = 115
};
struct SmartAction
@@ -553,6 +554,7 @@ struct SmartAction
{
uint32 textGroupID;
uint32 duration;
+ uint32 useTalkTarget;
} talk;
struct
diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp
index 0b85addfbf8..7ec1665bffc 100644
--- a/src/server/game/Accounts/AccountMgr.cpp
+++ b/src/server/game/Accounts/AccountMgr.cpp
@@ -81,7 +81,7 @@ AccountOpResult AccountMgr::DeleteAccount(uint32 accountId)
{
do
{
- ObjectGuid guid(HIGHGUID_PLAYER, (*result)[0].GetUInt32());
+ ObjectGuid guid(HighGuid::Player, (*result)[0].GetUInt32());
// Kick if player is online
if (Player* p = ObjectAccessor::FindConnectedPlayer(guid))
diff --git a/src/server/game/Accounts/RBAC.cpp b/src/server/game/Accounts/RBAC.cpp
index 54ef1a34766..c520564f0fa 100644
--- a/src/server/game/Accounts/RBAC.cpp
+++ b/src/server/game/Accounts/RBAC.cpp
@@ -1,265 +1,280 @@
-/*
- * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "RBAC.h"
-#include "AccountMgr.h"
-#include "DatabaseEnv.h"
-#include "Log.h"
-
-namespace rbac
-{
-
-std::string GetDebugPermissionString(RBACPermissionContainer const& perms)
-{
- std::string str = "";
- if (!perms.empty())
- {
- std::ostringstream o;
- RBACPermissionContainer::const_iterator itr = perms.begin();
- o << (*itr);
- for (++itr; itr != perms.end(); ++itr)
- o << ", " << uint32(*itr);
- str = o.str();
- }
-
- return str;
-}
-
-RBACCommandResult RBACData::GrantPermission(uint32 permissionId, int32 realmId /* = 0*/)
-{
- // Check if permission Id exists
- RBACPermission const* perm = sAccountMgr->GetRBACPermission(permissionId);
- if (!perm)
- {
- TC_LOG_TRACE("rbac", "RBACData::GrantPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Permission does not exists",
- GetId(), GetName().c_str(), permissionId, realmId);
- return RBAC_ID_DOES_NOT_EXISTS;
- }
-
- // Check if already added in denied list
- if (HasDeniedPermission(permissionId))
- {
- TC_LOG_TRACE("rbac", "RBACData::GrantPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Permission in deny list",
- GetId(), GetName().c_str(), permissionId, realmId);
- return RBAC_IN_DENIED_LIST;
- }
-
- // Already added?
- if (HasGrantedPermission(permissionId))
- {
- TC_LOG_TRACE("rbac", "RBACData::GrantPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Permission already granted",
- GetId(), GetName().c_str(), permissionId, realmId);
- return RBAC_CANT_ADD_ALREADY_ADDED;
- }
-
- AddGrantedPermission(permissionId);
-
- // Do not save to db when loading data from DB (realmId = 0)
- if (realmId)
- {
- TC_LOG_TRACE("rbac", "RBACData::GrantPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Ok and DB updated",
- GetId(), GetName().c_str(), permissionId, realmId);
- SavePermission(permissionId, true, realmId);
- CalculateNewPermissions();
- }
- else
- TC_LOG_TRACE("rbac", "RBACData::GrantPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Ok",
- GetId(), GetName().c_str(), permissionId, realmId);
-
- return RBAC_OK;
-}
-
-RBACCommandResult RBACData::DenyPermission(uint32 permissionId, int32 realmId /* = 0*/)
-{
- // Check if permission Id exists
- RBACPermission const* perm = sAccountMgr->GetRBACPermission(permissionId);
- if (!perm)
- {
- TC_LOG_TRACE("rbac", "RBACData::DenyPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Permission does not exists",
- GetId(), GetName().c_str(), permissionId, realmId);
- return RBAC_ID_DOES_NOT_EXISTS;
- }
-
- // Check if already added in granted list
- if (HasGrantedPermission(permissionId))
- {
- TC_LOG_TRACE("rbac", "RBACData::DenyPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Permission in grant list",
- GetId(), GetName().c_str(), permissionId, realmId);
- return RBAC_IN_GRANTED_LIST;
- }
-
- // Already added?
- if (HasDeniedPermission(permissionId))
- {
- TC_LOG_TRACE("rbac", "RBACData::DenyPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Permission already denied",
- GetId(), GetName().c_str(), permissionId, realmId);
- return RBAC_CANT_ADD_ALREADY_ADDED;
- }
-
- AddDeniedPermission(permissionId);
-
- // Do not save to db when loading data from DB (realmId = 0)
- if (realmId)
- {
- TC_LOG_TRACE("rbac", "RBACData::DenyPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Ok and DB updated",
- GetId(), GetName().c_str(), permissionId, realmId);
- SavePermission(permissionId, false, realmId);
- CalculateNewPermissions();
- }
- else
- TC_LOG_TRACE("rbac", "RBACData::DenyPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Ok",
- GetId(), GetName().c_str(), permissionId, realmId);
-
- return RBAC_OK;
-}
-
-void RBACData::SavePermission(uint32 permission, bool granted, int32 realmId)
-{
- PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_RBAC_ACCOUNT_PERMISSION);
- stmt->setUInt32(0, GetId());
- stmt->setUInt32(1, permission);
- stmt->setBool(2, granted);
- stmt->setInt32(3, realmId);
- LoginDatabase.Execute(stmt);
-}
-
-RBACCommandResult RBACData::RevokePermission(uint32 permissionId, int32 realmId /* = 0*/)
-{
- // Check if it's present in any list
- if (!HasGrantedPermission(permissionId) && !HasDeniedPermission(permissionId))
- {
- TC_LOG_TRACE("rbac", "RBACData::RevokePermission [Id: %u Name: %s] (Permission %u, RealmId %d). Not granted or revoked",
- GetId(), GetName().c_str(), permissionId, realmId);
- return RBAC_CANT_REVOKE_NOT_IN_LIST;
- }
-
- RemoveGrantedPermission(permissionId);
- RemoveDeniedPermission(permissionId);
-
- // Do not save to db when loading data from DB (realmId = 0)
- if (realmId)
- {
- TC_LOG_TRACE("rbac", "RBACData::RevokePermission [Id: %u Name: %s] (Permission %u, RealmId %d). Ok and DB updated",
- GetId(), GetName().c_str(), permissionId, realmId);
- PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_RBAC_ACCOUNT_PERMISSION);
- stmt->setUInt32(0, GetId());
- stmt->setUInt32(1, permissionId);
- stmt->setInt32(2, realmId);
- LoginDatabase.Execute(stmt);
-
- CalculateNewPermissions();
- }
- else
- TC_LOG_TRACE("rbac", "RBACData::RevokePermission [Id: %u Name: %s] (Permission %u, RealmId %d). Ok",
- GetId(), GetName().c_str(), permissionId, realmId);
-
- return RBAC_OK;
-}
-
-void RBACData::LoadFromDB()
-{
- ClearData();
-
- TC_LOG_DEBUG("rbac", "RBACData::LoadFromDB [Id: %u Name: %s]: Loading permissions", GetId(), GetName().c_str());
- // Load account permissions (granted and denied) that affect current realm
- PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_RBAC_ACCOUNT_PERMISSIONS);
- stmt->setUInt32(0, GetId());
- stmt->setInt32(1, GetRealmId());
-
- PreparedQueryResult result = LoginDatabase.Query(stmt);
- if (result)
- {
- do
- {
- Field* fields = result->Fetch();
- if (fields[1].GetBool())
- GrantPermission(fields[0].GetUInt32());
- else
- DenyPermission(fields[0].GetUInt32());
- }
- while (result->NextRow());
- }
-
- // Add default permissions
- RBACPermissionContainer const& permissions = sAccountMgr->GetRBACDefaultPermissions(_secLevel);
- for (RBACPermissionContainer::const_iterator itr = permissions.begin(); itr != permissions.end(); ++itr)
- GrantPermission(*itr);
-
- // Force calculation of permissions
- CalculateNewPermissions();
-}
-
-void RBACData::CalculateNewPermissions()
-{
- TC_LOG_TRACE("rbac", "RBACData::CalculateNewPermissions [Id: %u Name: %s]", GetId(), GetName().c_str());
-
- // Get the list of granted permissions
- _globalPerms = GetGrantedPermissions();
- ExpandPermissions(_globalPerms);
- RBACPermissionContainer revoked = GetDeniedPermissions();
- ExpandPermissions(revoked);
- RemovePermissions(_globalPerms, revoked);
-}
-
-void RBACData::AddPermissions(RBACPermissionContainer const& permsFrom, RBACPermissionContainer& permsTo)
-{
- for (RBACPermissionContainer::const_iterator itr = permsFrom.begin(); itr != permsFrom.end(); ++itr)
- permsTo.insert(*itr);
-}
-
-void RBACData::RemovePermissions(RBACPermissionContainer const& permsFrom, RBACPermissionContainer& permsTo)
-{
- for (RBACPermissionContainer::const_iterator itr = permsFrom.begin(); itr != permsFrom.end(); ++itr)
- permsTo.erase(*itr);
-}
-
-void RBACData::ExpandPermissions(RBACPermissionContainer& permissions)
-{
- RBACPermissionContainer toCheck = permissions;
- permissions.clear();
-
- while (!toCheck.empty())
- {
- // remove the permission from original list
- uint32 permissionId = *toCheck.begin();
- toCheck.erase(toCheck.begin());
-
- RBACPermission const* permission = sAccountMgr->GetRBACPermission(permissionId);
- if (!permission)
- continue;
-
- // insert into the final list (expanded list)
- permissions.insert(permissionId);
-
- // add all linked permissions (that are not already expanded) to the list of permissions to be checked
- RBACPermissionContainer const& linkedPerms = permission->GetLinkedPermissions();
- for (RBACPermissionContainer::const_iterator itr = linkedPerms.begin(); itr != linkedPerms.end(); ++itr)
- if (permissions.find(*itr) == permissions.end())
- toCheck.insert(*itr);
- }
-
- TC_LOG_DEBUG("rbac", "RBACData::ExpandPermissions: Expanded: %s", GetDebugPermissionString(permissions).c_str());
-}
-
-void RBACData::ClearData()
-{
- _grantedPerms.clear();
- _deniedPerms.clear();
- _globalPerms.clear();
-}
-
-}
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "RBAC.h"
+#include "AccountMgr.h"
+#include "Log.h"
+
+namespace rbac
+{
+
+std::string GetDebugPermissionString(RBACPermissionContainer const& perms)
+{
+ std::string str = "";
+ if (!perms.empty())
+ {
+ std::ostringstream o;
+ RBACPermissionContainer::const_iterator itr = perms.begin();
+ o << (*itr);
+ for (++itr; itr != perms.end(); ++itr)
+ o << ", " << uint32(*itr);
+ str = o.str();
+ }
+
+ return str;
+}
+
+RBACCommandResult RBACData::GrantPermission(uint32 permissionId, int32 realmId /* = 0*/)
+{
+ // Check if permission Id exists
+ RBACPermission const* perm = sAccountMgr->GetRBACPermission(permissionId);
+ if (!perm)
+ {
+ TC_LOG_TRACE("rbac", "RBACData::GrantPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Permission does not exists",
+ GetId(), GetName().c_str(), permissionId, realmId);
+ return RBAC_ID_DOES_NOT_EXISTS;
+ }
+
+ // Check if already added in denied list
+ if (HasDeniedPermission(permissionId))
+ {
+ TC_LOG_TRACE("rbac", "RBACData::GrantPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Permission in deny list",
+ GetId(), GetName().c_str(), permissionId, realmId);
+ return RBAC_IN_DENIED_LIST;
+ }
+
+ // Already added?
+ if (HasGrantedPermission(permissionId))
+ {
+ TC_LOG_TRACE("rbac", "RBACData::GrantPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Permission already granted",
+ GetId(), GetName().c_str(), permissionId, realmId);
+ return RBAC_CANT_ADD_ALREADY_ADDED;
+ }
+
+ AddGrantedPermission(permissionId);
+
+ // Do not save to db when loading data from DB (realmId = 0)
+ if (realmId)
+ {
+ TC_LOG_TRACE("rbac", "RBACData::GrantPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Ok and DB updated",
+ GetId(), GetName().c_str(), permissionId, realmId);
+ SavePermission(permissionId, true, realmId);
+ CalculateNewPermissions();
+ }
+ else
+ TC_LOG_TRACE("rbac", "RBACData::GrantPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Ok",
+ GetId(), GetName().c_str(), permissionId, realmId);
+
+ return RBAC_OK;
+}
+
+RBACCommandResult RBACData::DenyPermission(uint32 permissionId, int32 realmId /* = 0*/)
+{
+ // Check if permission Id exists
+ RBACPermission const* perm = sAccountMgr->GetRBACPermission(permissionId);
+ if (!perm)
+ {
+ TC_LOG_TRACE("rbac", "RBACData::DenyPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Permission does not exists",
+ GetId(), GetName().c_str(), permissionId, realmId);
+ return RBAC_ID_DOES_NOT_EXISTS;
+ }
+
+ // Check if already added in granted list
+ if (HasGrantedPermission(permissionId))
+ {
+ TC_LOG_TRACE("rbac", "RBACData::DenyPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Permission in grant list",
+ GetId(), GetName().c_str(), permissionId, realmId);
+ return RBAC_IN_GRANTED_LIST;
+ }
+
+ // Already added?
+ if (HasDeniedPermission(permissionId))
+ {
+ TC_LOG_TRACE("rbac", "RBACData::DenyPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Permission already denied",
+ GetId(), GetName().c_str(), permissionId, realmId);
+ return RBAC_CANT_ADD_ALREADY_ADDED;
+ }
+
+ AddDeniedPermission(permissionId);
+
+ // Do not save to db when loading data from DB (realmId = 0)
+ if (realmId)
+ {
+ TC_LOG_TRACE("rbac", "RBACData::DenyPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Ok and DB updated",
+ GetId(), GetName().c_str(), permissionId, realmId);
+ SavePermission(permissionId, false, realmId);
+ CalculateNewPermissions();
+ }
+ else
+ TC_LOG_TRACE("rbac", "RBACData::DenyPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Ok",
+ GetId(), GetName().c_str(), permissionId, realmId);
+
+ return RBAC_OK;
+}
+
+void RBACData::SavePermission(uint32 permission, bool granted, int32 realmId)
+{
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_RBAC_ACCOUNT_PERMISSION);
+ stmt->setUInt32(0, GetId());
+ stmt->setUInt32(1, permission);
+ stmt->setBool(2, granted);
+ stmt->setInt32(3, realmId);
+ LoginDatabase.Execute(stmt);
+}
+
+RBACCommandResult RBACData::RevokePermission(uint32 permissionId, int32 realmId /* = 0*/)
+{
+ // Check if it's present in any list
+ if (!HasGrantedPermission(permissionId) && !HasDeniedPermission(permissionId))
+ {
+ TC_LOG_TRACE("rbac", "RBACData::RevokePermission [Id: %u Name: %s] (Permission %u, RealmId %d). Not granted or revoked",
+ GetId(), GetName().c_str(), permissionId, realmId);
+ return RBAC_CANT_REVOKE_NOT_IN_LIST;
+ }
+
+ RemoveGrantedPermission(permissionId);
+ RemoveDeniedPermission(permissionId);
+
+ // Do not save to db when loading data from DB (realmId = 0)
+ if (realmId)
+ {
+ TC_LOG_TRACE("rbac", "RBACData::RevokePermission [Id: %u Name: %s] (Permission %u, RealmId %d). Ok and DB updated",
+ GetId(), GetName().c_str(), permissionId, realmId);
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_RBAC_ACCOUNT_PERMISSION);
+ stmt->setUInt32(0, GetId());
+ stmt->setUInt32(1, permissionId);
+ stmt->setInt32(2, realmId);
+ LoginDatabase.Execute(stmt);
+
+ CalculateNewPermissions();
+ }
+ else
+ TC_LOG_TRACE("rbac", "RBACData::RevokePermission [Id: %u Name: %s] (Permission %u, RealmId %d). Ok",
+ GetId(), GetName().c_str(), permissionId, realmId);
+
+ return RBAC_OK;
+}
+
+void RBACData::LoadFromDB()
+{
+ ClearData();
+
+ TC_LOG_DEBUG("rbac", "RBACData::LoadFromDB [Id: %u Name: %s]: Loading permissions", GetId(), GetName().c_str());
+ // Load account permissions (granted and denied) that affect current realm
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_RBAC_ACCOUNT_PERMISSIONS);
+ stmt->setUInt32(0, GetId());
+ stmt->setInt32(1, GetRealmId());
+
+ LoadFromDBCallback(LoginDatabase.Query(stmt));
+}
+
+PreparedQueryResultFuture RBACData::LoadFromDBAsync()
+{
+ ClearData();
+
+ TC_LOG_DEBUG("rbac", "RBACData::LoadFromDB [Id: %u Name: %s]: Loading permissions", GetId(), GetName().c_str());
+ // Load account permissions (granted and denied) that affect current realm
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_RBAC_ACCOUNT_PERMISSIONS);
+ stmt->setUInt32(0, GetId());
+ stmt->setInt32(1, GetRealmId());
+
+ return LoginDatabase.AsyncQuery(stmt);
+}
+
+void RBACData::LoadFromDBCallback(PreparedQueryResult result)
+{
+ if (result)
+ {
+ do
+ {
+ Field* fields = result->Fetch();
+ if (fields[1].GetBool())
+ GrantPermission(fields[0].GetUInt32());
+ else
+ DenyPermission(fields[0].GetUInt32());
+ } while (result->NextRow());
+ }
+
+ // Add default permissions
+ RBACPermissionContainer const& permissions = sAccountMgr->GetRBACDefaultPermissions(_secLevel);
+ for (RBACPermissionContainer::const_iterator itr = permissions.begin(); itr != permissions.end(); ++itr)
+ GrantPermission(*itr);
+
+ // Force calculation of permissions
+ CalculateNewPermissions();
+}
+
+void RBACData::CalculateNewPermissions()
+{
+ TC_LOG_TRACE("rbac", "RBACData::CalculateNewPermissions [Id: %u Name: %s]", GetId(), GetName().c_str());
+
+ // Get the list of granted permissions
+ _globalPerms = GetGrantedPermissions();
+ ExpandPermissions(_globalPerms);
+ RBACPermissionContainer revoked = GetDeniedPermissions();
+ ExpandPermissions(revoked);
+ RemovePermissions(_globalPerms, revoked);
+}
+
+void RBACData::AddPermissions(RBACPermissionContainer const& permsFrom, RBACPermissionContainer& permsTo)
+{
+ for (RBACPermissionContainer::const_iterator itr = permsFrom.begin(); itr != permsFrom.end(); ++itr)
+ permsTo.insert(*itr);
+}
+
+void RBACData::RemovePermissions(RBACPermissionContainer const& permsFrom, RBACPermissionContainer& permsTo)
+{
+ for (RBACPermissionContainer::const_iterator itr = permsFrom.begin(); itr != permsFrom.end(); ++itr)
+ permsTo.erase(*itr);
+}
+
+void RBACData::ExpandPermissions(RBACPermissionContainer& permissions)
+{
+ RBACPermissionContainer toCheck = permissions;
+ permissions.clear();
+
+ while (!toCheck.empty())
+ {
+ // remove the permission from original list
+ uint32 permissionId = *toCheck.begin();
+ toCheck.erase(toCheck.begin());
+
+ RBACPermission const* permission = sAccountMgr->GetRBACPermission(permissionId);
+ if (!permission)
+ continue;
+
+ // insert into the final list (expanded list)
+ permissions.insert(permissionId);
+
+ // add all linked permissions (that are not already expanded) to the list of permissions to be checked
+ RBACPermissionContainer const& linkedPerms = permission->GetLinkedPermissions();
+ for (RBACPermissionContainer::const_iterator itr = linkedPerms.begin(); itr != linkedPerms.end(); ++itr)
+ if (permissions.find(*itr) == permissions.end())
+ toCheck.insert(*itr);
+ }
+
+ TC_LOG_DEBUG("rbac", "RBACData::ExpandPermissions: Expanded: %s", GetDebugPermissionString(permissions).c_str());
+}
+
+void RBACData::ClearData()
+{
+ _grantedPerms.clear();
+ _deniedPerms.clear();
+ _globalPerms.clear();
+}
+
+}
diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h
index 339788dee01..4acadd7f2b4 100644
--- a/src/server/game/Accounts/RBAC.h
+++ b/src/server/game/Accounts/RBAC.h
@@ -40,7 +40,7 @@
#ifndef _RBAC_H
#define _RBAC_H
-#include "Define.h"
+#include "DatabaseEnv.h"
#include <string>
#include <set>
#include <map>
@@ -694,6 +694,8 @@ enum RBACPermissions
RBAC_PERM_COMMAND_INSTANCE_GET_BOSS_STATE = 796,
RBAC_PERM_COMMAND_PVPSTATS = 797,
RBAC_PERM_COMMAND_MODIFY_XP = 798,
+ // 799 - 834 6.x only
+ RBAC_PERM_COMMAND_DEBUG_LOADCELLS = 835,
// custom permissions 1000+
RBAC_PERM_MAX
@@ -862,6 +864,8 @@ class RBACData
/// Loads all permissions assigned to current account
void LoadFromDB();
+ PreparedQueryResultFuture LoadFromDBAsync();
+ void LoadFromDBCallback(PreparedQueryResult result);
/// Sets security level
void SetSecurityLevel(uint8 id)
@@ -889,7 +893,7 @@ class RBACData
*/
void CalculateNewPermissions();
- int32 GetRealmId() { return _realmId; }
+ int32 GetRealmId() const { return _realmId; }
// Auxiliar private functions - defined to allow to maintain same code even
// if internal structure changes.
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp
index 51106d7cfe1..a6359a353eb 100644
--- a/src/server/game/Achievements/AchievementMgr.cpp
+++ b/src/server/game/Achievements/AchievementMgr.cpp
@@ -522,11 +522,11 @@ void AchievementMgr::SaveToDB(SQLTransaction& trans)
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACHIEVEMENT_BY_ACHIEVEMENT);
stmt->setUInt16(0, iter->first);
- stmt->setUInt32(1, GetPlayer()->GetGUIDLow());
+ stmt->setUInt32(1, GetPlayer()->GetGUID().GetCounter());
trans->Append(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_ACHIEVEMENT);
- stmt->setUInt32(0, GetPlayer()->GetGUIDLow());
+ stmt->setUInt32(0, GetPlayer()->GetGUID().GetCounter());
stmt->setUInt16(1, iter->first);
stmt->setUInt32(2, uint32(iter->second.date));
trans->Append(stmt);
@@ -543,14 +543,14 @@ void AchievementMgr::SaveToDB(SQLTransaction& trans)
continue;
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACHIEVEMENT_PROGRESS_BY_CRITERIA);
- stmt->setUInt32(0, GetPlayer()->GetGUIDLow());
+ stmt->setUInt32(0, GetPlayer()->GetGUID().GetCounter());
stmt->setUInt16(1, iter->first);
trans->Append(stmt);
if (iter->second.counter)
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_ACHIEVEMENT_PROGRESS);
- stmt->setUInt32(0, GetPlayer()->GetGUIDLow());
+ stmt->setUInt32(0, GetPlayer()->GetGUID().GetCounter());
stmt->setUInt16(1, iter->first);
stmt->setUInt32(2, iter->second.counter);
stmt->setUInt32(3, uint32(iter->second.date));
@@ -1356,7 +1356,7 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry,
if (entry->timeLimit && timedIter == m_timedAchievements.end())
return;
- TC_LOG_DEBUG("achievement", "AchievementMgr::SetCriteriaProgress(%u, %u) for (GUID:%u)", entry->ID, changeValue, m_player->GetGUIDLow());
+ TC_LOG_DEBUG("achievement", "AchievementMgr::SetCriteriaProgress(%u, %u) for (GUID:%u)", entry->ID, changeValue, m_player->GetGUID().GetCounter());
CriteriaProgress* progress = GetCriteriaProgress(entry);
if (!progress)
@@ -1509,7 +1509,7 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
return;
TC_LOG_DEBUG("achievement", "AchievementMgr::CompletedAchievement(%u). Player: %s (%u)",
- achievement->ID, m_player->GetName().c_str(), m_player->GetGUIDLow());
+ achievement->ID, m_player->GetName().c_str(), m_player->GetGUID().GetCounter());
SendAchievementEarned(achievement);
CompletedAchievementData& ca = m_completedAchievements[achievement->ID];
@@ -1533,7 +1533,7 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
//! Since no common attributes were found, (not even in titleRewardFlags field)
//! we explicitly check by ID. Maybe in the future we could move the achievement_reward
//! condition fields to the condition system.
- if (uint32 titleId = reward->titleId[achievement->ID == 1793 ? GetPlayer()->getGender() : (GetPlayer()->GetTeam() == ALLIANCE ? 0 : 1)])
+ if (uint32 titleId = reward->titleId[achievement->ID == 1793 ? GetPlayer()->GetByteValue(PLAYER_BYTES_3, 0) : (GetPlayer()->GetTeam() == ALLIANCE ? 0 : 1)])
if (CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(titleId))
GetPlayer()->SetTitle(titleEntry);
@@ -2344,7 +2344,7 @@ void AchievementGlobalMgr::LoadAchievementCriteriaData()
if (dataType != ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT)
TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` has ScriptName set for non-scripted data type (Entry: %u, type %u), useless data.", criteria_id, dataType);
else
- scriptId = sObjectMgr->GetScriptId(scriptName.c_str());
+ scriptId = sObjectMgr->GetScriptId(scriptName);
}
AchievementCriteriaData data(dataType, fields[2].GetUInt32(), fields[3].GetUInt32(), scriptId);
diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
index 16d5f4b6959..768def2ff4d 100644
--- a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
+++ b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
@@ -61,12 +61,25 @@ AuctionHouseObject* AuctionHouseMgr::GetAuctionsMap(uint32 factionTemplateId)
return &mNeutralAuctions;
}
+AuctionHouseObject* AuctionHouseMgr::GetAuctionsMapByHouseId(uint8 auctionHouseId)
+{
+ if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION))
+ return &mNeutralAuctions;
+
+ switch(auctionHouseId)
+ {
+ case AUCTIONHOUSE_ALLIANCE : return &mAllianceAuctions;
+ case AUCTIONHOUSE_HORDE : return &mHordeAuctions;
+ default : return &mNeutralAuctions;
+ }
+}
+
uint32 AuctionHouseMgr::GetAuctionDeposit(AuctionHouseEntry const* entry, uint32 time, Item* pItem, uint32 count)
{
uint32 MSV = pItem->GetTemplate()->SellPrice;
if (MSV <= 0)
- return AH_MINIMUM_DEPOSIT;
+ return AH_MINIMUM_DEPOSIT * sWorld->getRate(RATE_AUCTION_DEPOSIT);
float multiplier = CalculatePct(float(entry->depositPercent), 3);
uint32 timeHr = (((time / 60) / 60) / 12);
@@ -77,8 +90,8 @@ uint32 AuctionHouseMgr::GetAuctionDeposit(AuctionHouseEntry const* entry, uint32
TC_LOG_DEBUG("auctionHouse", "Multiplier: %f", multiplier);
TC_LOG_DEBUG("auctionHouse", "Deposit: %u", deposit);
- if (deposit < AH_MINIMUM_DEPOSIT)
- return AH_MINIMUM_DEPOSIT;
+ if (deposit < AH_MINIMUM_DEPOSIT * sWorld->getRate(RATE_AUCTION_DEPOSIT))
+ return AH_MINIMUM_DEPOSIT * sWorld->getRate(RATE_AUCTION_DEPOSIT);
else
return deposit;
}
@@ -91,7 +104,7 @@ void AuctionHouseMgr::SendAuctionWonMail(AuctionEntry* auction, SQLTransaction&
return;
uint32 bidderAccId = 0;
- ObjectGuid bidderGuid(HIGHGUID_PLAYER, auction->bidder);
+ ObjectGuid bidderGuid(HighGuid::Player, auction->bidder);
Player* bidder = ObjectAccessor::FindConnectedPlayer(bidderGuid);
// data for gm.log
std::string bidderName;
@@ -114,7 +127,7 @@ void AuctionHouseMgr::SendAuctionWonMail(AuctionEntry* auction, SQLTransaction&
if (logGmTrade)
{
- ObjectGuid ownerGuid = ObjectGuid(HIGHGUID_PLAYER, auction->owner);
+ ObjectGuid ownerGuid = ObjectGuid(HighGuid::Player, auction->owner);
std::string ownerName;
if (!sObjectMgr->GetPlayerNameByGUID(ownerGuid, ownerName))
ownerName = sObjectMgr->GetTrinityStringForDBCLocale(LANG_UNKNOWN);
@@ -132,7 +145,7 @@ void AuctionHouseMgr::SendAuctionWonMail(AuctionEntry* auction, SQLTransaction&
// owner in `data` will set at mail receive and item extracting
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ITEM_OWNER);
stmt->setUInt32(0, auction->bidder);
- stmt->setUInt32(1, pItem->GetGUIDLow());
+ stmt->setUInt32(1, pItem->GetGUID().GetCounter());
trans->Append(stmt);
if (bidder)
@@ -155,7 +168,7 @@ void AuctionHouseMgr::SendAuctionWonMail(AuctionEntry* auction, SQLTransaction&
void AuctionHouseMgr::SendAuctionSalePendingMail(AuctionEntry* auction, SQLTransaction& trans)
{
- ObjectGuid owner_guid(HIGHGUID_PLAYER, auction->owner);
+ ObjectGuid owner_guid(HighGuid::Player, auction->owner);
Player* owner = ObjectAccessor::FindConnectedPlayer(owner_guid);
uint32 owner_accId = sObjectMgr->GetPlayerAccountIdByGUID(owner_guid);
// owner exist (online or offline)
@@ -167,7 +180,7 @@ void AuctionHouseMgr::SendAuctionSalePendingMail(AuctionEntry* auction, SQLTrans
//call this method to send mail to auction owner, when auction is successful, it does not clear ram
void AuctionHouseMgr::SendAuctionSuccessfulMail(AuctionEntry* auction, SQLTransaction& trans)
{
- ObjectGuid owner_guid(HIGHGUID_PLAYER, auction->owner);
+ ObjectGuid owner_guid(HighGuid::Player, auction->owner);
Player* owner = ObjectAccessor::FindConnectedPlayer(owner_guid);
uint32 owner_accId = sObjectMgr->GetPlayerAccountIdByGUID(owner_guid);
// owner exist
@@ -198,7 +211,7 @@ void AuctionHouseMgr::SendAuctionExpiredMail(AuctionEntry* auction, SQLTransacti
if (!pItem)
return;
- ObjectGuid owner_guid(HIGHGUID_PLAYER, auction->owner);
+ ObjectGuid owner_guid(HighGuid::Player, auction->owner);
Player* owner = ObjectAccessor::FindConnectedPlayer(owner_guid);
uint32 owner_accId = sObjectMgr->GetPlayerAccountIdByGUID(owner_guid);
// owner exist
@@ -221,7 +234,7 @@ void AuctionHouseMgr::SendAuctionExpiredMail(AuctionEntry* auction, SQLTransacti
//this function sends mail to old bidder
void AuctionHouseMgr::SendAuctionOutbiddedMail(AuctionEntry* auction, uint32 newPrice, Player* newBidder, SQLTransaction& trans)
{
- ObjectGuid oldBidder_guid(HIGHGUID_PLAYER, auction->bidder);
+ ObjectGuid oldBidder_guid(HighGuid::Player, auction->bidder);
Player* oldBidder = ObjectAccessor::FindConnectedPlayer(oldBidder_guid);
uint32 oldBidder_accId = 0;
@@ -243,7 +256,7 @@ void AuctionHouseMgr::SendAuctionOutbiddedMail(AuctionEntry* auction, uint32 new
//this function sends mail, when auction is cancelled to old bidder
void AuctionHouseMgr::SendAuctionCancelledToBidderMail(AuctionEntry* auction, SQLTransaction& trans)
{
- ObjectGuid bidder_guid = ObjectGuid(HIGHGUID_PLAYER, auction->bidder);
+ ObjectGuid bidder_guid = ObjectGuid(HighGuid::Player, auction->bidder);
Player* bidder = ObjectAccessor::FindConnectedPlayer(bidder_guid);
uint32 bidder_accId = 0;
@@ -287,13 +300,13 @@ void AuctionHouseMgr::LoadAuctionItems()
{
Field* fields = result->Fetch();
- uint32 item_guid = fields[11].GetUInt32();
+ ObjectGuid::LowType item_guid = fields[11].GetUInt32();
uint32 itemEntry = fields[12].GetUInt32();
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemEntry);
if (!proto)
{
- TC_LOG_ERROR("misc", "AuctionHouseMgr::LoadAuctionItems: Unknown item (GUID: %u id: #%u) in auction, skipped.", item_guid, itemEntry);
+ TC_LOG_ERROR("misc", "AuctionHouseMgr::LoadAuctionItems: Unknown item (GUID: %u item entry: #%u) in auction, skipped.", item_guid, itemEntry);
continue;
}
@@ -342,7 +355,7 @@ void AuctionHouseMgr::LoadAuctions()
continue;
}
- GetAuctionsMap(aItem->factionTemplateId)->AddAuction(aItem);
+ GetAuctionsMapByHouseId(aItem->houseId)->AddAuction(aItem);
++count;
} while (result->NextRow());
@@ -355,11 +368,11 @@ void AuctionHouseMgr::LoadAuctions()
void AuctionHouseMgr::AddAItem(Item* it)
{
ASSERT(it);
- ASSERT(mAitems.find(it->GetGUIDLow()) == mAitems.end());
- mAitems[it->GetGUIDLow()] = it;
+ ASSERT(mAitems.find(it->GetGUID().GetCounter()) == mAitems.end());
+ mAitems[it->GetGUID().GetCounter()] = it;
}
-bool AuctionHouseMgr::RemoveAItem(uint32 id, bool deleteItem)
+bool AuctionHouseMgr::RemoveAItem(ObjectGuid::LowType id, bool deleteItem)
{
ItemMap::iterator i = mAitems.find(id);
if (i == mAitems.end())
@@ -385,44 +398,32 @@ void AuctionHouseMgr::Update()
AuctionHouseEntry const* AuctionHouseMgr::GetAuctionHouseEntry(uint32 factionTemplateId)
{
- uint32 houseid = 7; // goblin auction house
+ uint32 houseid = AUCTIONHOUSE_NEUTRAL; // goblin auction house
if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION))
{
// FIXME: found way for proper auctionhouse selection by another way
// AuctionHouse.dbc have faction field with _player_ factions associated with auction house races.
// but no easy way convert creature faction to player race faction for specific city
- switch (factionTemplateId)
- {
- case 12: houseid = 1; break; // human
- case 29: houseid = 6; break; // orc, and generic for horde
- case 55: houseid = 2; break; // dwarf, and generic for alliance
- case 68: houseid = 4; break; // undead
- case 80: houseid = 3; break; // n-elf
- case 104: houseid = 5; break; // trolls
- case 120: houseid = 7; break; // booty bay, neutral
- case 474: houseid = 7; break; // gadgetzan, neutral
- case 855: houseid = 7; break; // everlook, neutral
- case 1604: houseid = 6; break; // b-elfs,
- default: // for unknown case
- {
- FactionTemplateEntry const* u_entry = sFactionTemplateStore.LookupEntry(factionTemplateId);
- if (!u_entry)
- houseid = 7; // goblin auction house
- else if (u_entry->ourMask & FACTION_MASK_ALLIANCE)
- houseid = 1; // human auction house
- else if (u_entry->ourMask & FACTION_MASK_HORDE)
- houseid = 6; // orc auction house
- else
- houseid = 7; // goblin auction house
- break;
- }
- }
+ FactionTemplateEntry const* u_entry = sFactionTemplateStore.LookupEntry(factionTemplateId);
+ if (!u_entry)
+ houseid = AUCTIONHOUSE_NEUTRAL; // goblin auction house
+ else if (u_entry->ourMask & FACTION_MASK_ALLIANCE)
+ houseid = AUCTIONHOUSE_ALLIANCE; // human auction house
+ else if (u_entry->ourMask & FACTION_MASK_HORDE)
+ houseid = AUCTIONHOUSE_HORDE; // orc auction house
+ else
+ houseid = AUCTIONHOUSE_NEUTRAL; // goblin auction house
}
return sAuctionHouseStore.LookupEntry(houseid);
}
+AuctionHouseEntry const* AuctionHouseMgr::GetAuctionHouseEntryFromHouse(uint8 houseId)
+{
+ return (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) ? sAuctionHouseStore.LookupEntry(AUCTIONHOUSE_NEUTRAL) : sAuctionHouseStore.LookupEntry(houseId);
+}
+
void AuctionHouseObject::AddAuction(AuctionEntry* auction)
{
ASSERT(auction);
@@ -498,7 +499,7 @@ void AuctionHouseObject::BuildListBidderItems(WorldPacket& data, Player* player,
for (AuctionEntryMap::const_iterator itr = AuctionsMap.begin(); itr != AuctionsMap.end(); ++itr)
{
AuctionEntry* Aentry = itr->second;
- if (Aentry && Aentry->bidder == player->GetGUIDLow())
+ if (Aentry && Aentry->bidder == player->GetGUID().GetCounter())
{
if (itr->second->BuildAuctionInfo(data))
++count;
@@ -513,7 +514,7 @@ void AuctionHouseObject::BuildListOwnerItems(WorldPacket& data, Player* player,
for (AuctionEntryMap::const_iterator itr = AuctionsMap.begin(); itr != AuctionsMap.end(); ++itr)
{
AuctionEntry* Aentry = itr->second;
- if (Aentry && Aentry->owner == player->GetGUIDLow())
+ if (Aentry && Aentry->owner == player->GetGUID().GetCounter())
{
if (Aentry->BuildAuctionInfo(data))
++count;
@@ -687,7 +688,7 @@ void AuctionEntry::SaveToDB(SQLTransaction& trans) const
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_AUCTION);
stmt->setUInt32(0, Id);
- stmt->setUInt32(1, auctioneer);
+ stmt->setUInt8(1, houseId);
stmt->setUInt32(2, itemGUIDLow);
stmt->setUInt32(3, owner);
stmt->setUInt32(4, buyout);
@@ -702,7 +703,7 @@ void AuctionEntry::SaveToDB(SQLTransaction& trans) const
bool AuctionEntry::LoadFromDB(Field* fields)
{
Id = fields[0].GetUInt32();
- auctioneer = fields[1].GetUInt32();
+ houseId = fields[1].GetUInt8();
itemGUIDLow = fields[2].GetUInt32();
itemEntry = fields[3].GetUInt32();
itemCount = fields[4].GetUInt32();
@@ -714,25 +715,10 @@ bool AuctionEntry::LoadFromDB(Field* fields)
startbid = fields[10].GetUInt32();
deposit = fields[11].GetUInt32();
- CreatureData const* auctioneerData = sObjectMgr->GetCreatureData(auctioneer);
- if (!auctioneerData)
- {
- TC_LOG_ERROR("misc", "Auction %u has not a existing auctioneer (GUID : %u)", Id, auctioneer);
- return false;
- }
-
- CreatureTemplate const* auctioneerInfo = sObjectMgr->GetCreatureTemplate(auctioneerData->id);
- if (!auctioneerInfo)
- {
- TC_LOG_ERROR("misc", "Auction %u has not a existing auctioneer (GUID : %u Entry: %u)", Id, auctioneer, auctioneerData->id);
- return false;
- }
-
- factionTemplateId = auctioneerInfo->faction;
- auctionHouseEntry = AuctionHouseMgr::GetAuctionHouseEntry(factionTemplateId);
+ auctionHouseEntry = AuctionHouseMgr::GetAuctionHouseEntryFromHouse(houseId);
if (!auctionHouseEntry)
{
- TC_LOG_ERROR("misc", "Auction %u has auctioneer (GUID : %u Entry: %u) with wrong faction %u", Id, auctioneer, auctioneerData->id, factionTemplateId);
+ TC_LOG_ERROR("misc", "Auction %u has invalid house id %u", Id, houseId);
return false;
}
@@ -752,11 +738,11 @@ std::string AuctionEntry::BuildAuctionMailSubject(MailAuctionAnswers response) c
return strm.str();
}
-std::string AuctionEntry::BuildAuctionMailBody(uint32 lowGuid, uint32 bid, uint32 buyout, uint32 deposit, uint32 cut)
+std::string AuctionEntry::BuildAuctionMailBody(ObjectGuid::LowType lowGuid, uint32 bid, uint32 buyout, uint32 deposit, uint32 cut)
{
std::ostringstream strm;
strm.width(16);
- strm << std::right << std::hex << ObjectGuid(HIGHGUID_PLAYER, lowGuid).GetRawValue(); // HIGHGUID_PLAYER always present, even for empty guids
+ strm << std::right << std::hex << ObjectGuid(HighGuid::Player, lowGuid).GetRawValue(); // HighGuid::Player always present, even for empty guids
strm << std::dec << ':' << bid << ':' << buyout;
strm << ':' << deposit << ':' << cut;
return strm.str();
diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.h b/src/server/game/AuctionHouse/AuctionHouseMgr.h
index d67c8143996..45cdba361f3 100644
--- a/src/server/game/AuctionHouse/AuctionHouseMgr.h
+++ b/src/server/game/AuctionHouse/AuctionHouseMgr.h
@@ -61,26 +61,31 @@ enum MailAuctionAnswers
AUCTION_SALE_PENDING = 6
};
+enum AuctionHouses
+{
+ AUCTIONHOUSE_ALLIANCE = 2,
+ AUCTIONHOUSE_HORDE = 6,
+ AUCTIONHOUSE_NEUTRAL = 7
+};
+
struct AuctionEntry
{
uint32 Id;
- uint32 auctioneer; // creature low guid
- uint32 itemGUIDLow;
+ uint8 houseId;
+ ObjectGuid::LowType itemGUIDLow;
uint32 itemEntry;
uint32 itemCount;
- uint32 owner;
+ ObjectGuid::LowType owner;
uint32 startbid; //maybe useless
uint32 bid;
uint32 buyout;
time_t expire_time;
- uint32 bidder;
+ ObjectGuid::LowType bidder;
uint32 deposit; //deposit can be calculated only when creating auction
AuctionHouseEntry const* auctionHouseEntry; // in AuctionHouse.dbc
- uint32 factionTemplateId;
// helpers
- uint32 GetHouseId() const { return auctionHouseEntry->houseId; }
- uint32 GetHouseFaction() const { return auctionHouseEntry->faction; }
+ uint8 GetHouseId() const { return houseId; }
uint32 GetAuctionCut() const;
uint32 GetAuctionOutBid() const;
bool BuildAuctionInfo(WorldPacket & data) const;
@@ -88,7 +93,7 @@ struct AuctionEntry
void SaveToDB(SQLTransaction& trans) const;
bool LoadFromDB(Field* fields);
std::string BuildAuctionMailSubject(MailAuctionAnswers response) const;
- static std::string BuildAuctionMailBody(uint32 lowGuid, uint32 bid, uint32 buyout, uint32 deposit, uint32 cut);
+ static std::string BuildAuctionMailBody(ObjectGuid::LowType lowGuid, uint32 bid, uint32 buyout, uint32 deposit, uint32 cut);
};
@@ -145,12 +150,13 @@ class AuctionHouseMgr
return &instance;
}
- typedef std::unordered_map<uint32, Item*> ItemMap;
+ typedef std::unordered_map<ObjectGuid::LowType, Item*> ItemMap;
AuctionHouseObject* GetAuctionsMap(uint32 factionTemplateId);
+ AuctionHouseObject* GetAuctionsMapByHouseId(uint8 auctionHouseId);
AuctionHouseObject* GetBidsMap(uint32 factionTemplateId);
- Item* GetAItem(uint32 id)
+ Item* GetAItem(ObjectGuid::LowType id)
{
ItemMap::const_iterator itr = mAitems.find(id);
if (itr != mAitems.end())
@@ -169,7 +175,7 @@ class AuctionHouseMgr
static uint32 GetAuctionDeposit(AuctionHouseEntry const* entry, uint32 time, Item* pItem, uint32 count);
static AuctionHouseEntry const* GetAuctionHouseEntry(uint32 factionTemplateId);
-
+ static AuctionHouseEntry const* GetAuctionHouseEntryFromHouse(uint8 houseId);
public:
//load first auction items, because of check if item exists, when loading
@@ -177,7 +183,7 @@ class AuctionHouseMgr
void LoadAuctions();
void AddAItem(Item* it);
- bool RemoveAItem(uint32 id, bool deleteItem = false);
+ bool RemoveAItem(ObjectGuid::LowType id, bool deleteItem = false);
void Update();
diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBot.cpp b/src/server/game/AuctionHouseBot/AuctionHouseBot.cpp
index c0c753100bc..c905ccedf2d 100644
--- a/src/server/game/AuctionHouseBot/AuctionHouseBot.cpp
+++ b/src/server/game/AuctionHouseBot/AuctionHouseBot.cpp
@@ -97,6 +97,11 @@ void AuctionBotConfig::SetConfig(AuctionBotConfigBoolValues index, char const* f
SetConfig(index, sConfigMgr->GetBoolDefault(fieldname, defvalue));
}
+void AuctionBotConfig::SetConfig(AuctionBotConfigFloatValues index, char const* fieldname, float defvalue)
+{
+ SetConfig(index, sConfigMgr->GetFloatDefault(fieldname, defvalue));
+}
+
//Get AuctionHousebot configuration file
void AuctionBotConfig::GetConfigFromFile()
{
@@ -111,6 +116,8 @@ void AuctionBotConfig::GetConfigFromFile()
SetConfig(CONFIG_AHBOT_BUYER_HORDE_ENABLED, "AuctionHouseBot.Buyer.Horde.Enabled", false);
SetConfig(CONFIG_AHBOT_BUYER_NEUTRAL_ENABLED, "AuctionHouseBot.Buyer.Neutral.Enabled", false);
+ SetConfig(CONFIG_AHBOT_BUYER_CHANCE_FACTOR, "AuctionHouseBot.Buyer.ChanceFactor", 2.0f);
+
SetConfig(CONFIG_AHBOT_ITEMS_VENDOR, "AuctionHouseBot.Items.Vendor", false);
SetConfig(CONFIG_AHBOT_ITEMS_LOOT, "AuctionHouseBot.Items.Loot", true);
SetConfig(CONFIG_AHBOT_ITEMS_MISC, "AuctionHouseBot.Items.Misc", false);
diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBot.h b/src/server/game/AuctionHouseBot/AuctionHouseBot.h
index d7570c37d44..225d3b7ee25 100644
--- a/src/server/game/AuctionHouseBot/AuctionHouseBot.h
+++ b/src/server/game/AuctionHouseBot/AuctionHouseBot.h
@@ -174,6 +174,12 @@ enum AuctionBotConfigBoolValues
CONFIG_UINT32_AHBOT_BOOL_COUNT
};
+enum AuctionBotConfigFloatValues
+{
+ CONFIG_AHBOT_BUYER_CHANCE_FACTOR,
+ CONFIG_AHBOT_FLOAT_COUNT
+};
+
// All basic config data used by other AHBot classes for self-configure.
class AuctionBotConfig
{
@@ -196,8 +202,10 @@ public:
uint32 GetConfig(AuctionBotConfigUInt32Values index) const { return _configUint32Values[index]; }
bool GetConfig(AuctionBotConfigBoolValues index) const { return _configBoolValues[index]; }
+ float GetConfig(AuctionBotConfigFloatValues index) const { return _configFloatValues[index]; }
void SetConfig(AuctionBotConfigBoolValues index, bool value) { _configBoolValues[index] = value; }
void SetConfig(AuctionBotConfigUInt32Values index, uint32 value) { _configUint32Values[index] = value; }
+ void SetConfig(AuctionBotConfigFloatValues index, float value) { _configFloatValues[index] = value; }
uint32 GetConfigItemAmountRatio(AuctionHouseType houseType) const;
bool GetConfigBuyerEnabled(AuctionHouseType houseType) const;
@@ -217,6 +225,7 @@ private:
uint32 _configUint32Values[CONFIG_UINT32_AHBOT_UINT32_COUNT];
bool _configBoolValues[CONFIG_UINT32_AHBOT_BOOL_COUNT];
+ float _configFloatValues[CONFIG_AHBOT_FLOAT_COUNT];
void SetAHBotIncludes(const std::string& AHBotIncludes) { _AHBotIncludes = AHBotIncludes; }
void SetAHBotExcludes(const std::string& AHBotExcludes) { _AHBotExcludes = AHBotExcludes; }
@@ -225,6 +234,7 @@ private:
void SetConfigMax(AuctionBotConfigUInt32Values index, char const* fieldname, uint32 defvalue, uint32 maxvalue);
void SetConfigMinMax(AuctionBotConfigUInt32Values index, char const* fieldname, uint32 defvalue, uint32 minvalue, uint32 maxvalue);
void SetConfig(AuctionBotConfigBoolValues index, char const* fieldname, bool defvalue);
+ void SetConfig(AuctionBotConfigFloatValues index, char const* fieldname, float defvalue);
void GetConfigFromFile();
};
diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.cpp b/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.cpp
index 64463948574..80c32cf66e7 100644
--- a/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.cpp
+++ b/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.cpp
@@ -102,6 +102,10 @@ uint32 AuctionBotBuyer::GetItemInformation(BuyerConfiguration& config)
for (AuctionHouseObject::AuctionEntryMap::const_iterator itr = house->GetAuctionsBegin(); itr != house->GetAuctionsEnd(); ++itr)
{
AuctionEntry* entry = itr->second;
+
+ if (!entry->owner)
+ continue; // Skip auctions owned by AHBot
+
Item* item = sAuctionMgr->GetAItem(entry->itemGUIDLow);
if (!item)
continue;
@@ -135,10 +139,10 @@ uint32 AuctionBotBuyer::GetItemInformation(BuyerConfiguration& config)
itemInfo.MinBuyPrice = std::min(itemInfo.MinBuyPrice, itemBuyPrice);
}
- // Add/update to EligibleItems if:
- // has a bid by player or
- // has no bids and not owned by bot
- if ((entry->bid && entry->bidder) || (entry->owner && !entry->bid))
+ // Add/update EligibleItems if:
+ // * no bid
+ // * bid from player
+ if (!entry->bid || entry->bidder)
{
config.EligibleItems[entry->Id].LastExist = now;
config.EligibleItems[entry->Id].AuctionId = entry->Id;
@@ -157,18 +161,18 @@ bool AuctionBotBuyer::RollBuyChance(const BuyerItemInfo* ahInfo, const Item* ite
if (!auction->buyout)
return false;
- uint32 itemBuyPrice = auction->buyout / item->GetCount();
- uint32 itemPrice = item->GetTemplate()->SellPrice ? item->GetTemplate()->SellPrice : GetVendorPrice(item->GetTemplate()->Quality);
+ float itemBuyPrice = float(auction->buyout / item->GetCount());
+ float itemPrice = float(item->GetTemplate()->SellPrice ? item->GetTemplate()->SellPrice : GetVendorPrice(item->GetTemplate()->Quality));
// The AH cut needs to be added to the price, but we dont want a 100% chance to buy if the price is exactly AH default
itemPrice *= 1.4f;
// This value is between 0 and 100 and is used directly as the chance to buy or bid
// Value equal or above 100 means 100% chance and value below 0 means 0% chance
- float chance = 100 / sqrt(itemBuyPrice / float(itemPrice));
+ float chance = std::min(100.f, std::pow(100.f, 1.f + (1.f - itemBuyPrice / itemPrice) / sAuctionBotConfig->GetConfig(CONFIG_AHBOT_BUYER_CHANCE_FACTOR)));
// If a player has bidded on item, have fifth of normal chance
if (auction->bidder)
- chance = chance / 5;
+ chance = chance / 5.f;
if (ahInfo)
{
@@ -178,31 +182,29 @@ bool AuctionBotBuyer::RollBuyChance(const BuyerItemInfo* ahInfo, const Item* ite
// If there are more than 5 items on AH of this entry, try weigh in the average buyout price
if (ahInfo->BuyItemCount > 5)
- {
- chance *= 1 / sqrt(itemBuyPrice / avgBuyPrice);
- }
+ chance *= 1.f / std::sqrt(itemBuyPrice / avgBuyPrice);
}
// Add config weigh in for quality
chance *= GetChanceMultiplier(item->GetTemplate()->Quality) / 100.0f;
- float rand = frand(0, 100);
+ float rand = frand(0.f, 100.f);
bool win = rand <= chance;
- TC_LOG_DEBUG("ahbot", "AHBot: %s BUY! chance = %.2f, price = %u, buyprice = %u.", win ? "WIN" : "LOSE", chance, itemPrice, itemBuyPrice);
+ TC_LOG_DEBUG("ahbot", "AHBot: %s BUY! chance = %.2f, price = %u, buyprice = %u.", win ? "WIN" : "LOSE", chance, uint32(itemPrice), uint32(itemBuyPrice));
return win;
}
// ahInfo can be NULL
bool AuctionBotBuyer::RollBidChance(const BuyerItemInfo* ahInfo, const Item* item, const AuctionEntry* auction, uint32 bidPrice)
{
- uint32 itemBidPrice = bidPrice / item->GetCount();
- uint32 itemPrice = item->GetTemplate()->SellPrice ? item->GetTemplate()->SellPrice : GetVendorPrice(item->GetTemplate()->Quality);
+ float itemBidPrice = float(bidPrice / item->GetCount());
+ float itemPrice = float(item->GetTemplate()->SellPrice ? item->GetTemplate()->SellPrice : GetVendorPrice(item->GetTemplate()->Quality));
// The AH cut needs to be added to the price, but we dont want a 100% chance to buy if the price is exactly AH default
itemPrice *= 1.4f;
// This value is between 0 and 100 and is used directly as the chance to buy or bid
// Value equal or above 100 means 100% chance and value below 0 means 0% chance
- float chance = 100 / sqrt(itemBidPrice / float(itemPrice));
+ float chance = std::min(100.f, std::pow(100.f, 1.f + (1.f - itemBidPrice / itemPrice) / sAuctionBotConfig->GetConfig(CONFIG_AHBOT_BUYER_CHANCE_FACTOR)));
if (ahInfo)
{
@@ -212,21 +214,19 @@ bool AuctionBotBuyer::RollBidChance(const BuyerItemInfo* ahInfo, const Item* ite
// If there are more than 5 items on AH of this entry, try weigh in the average bid price
if (ahInfo->BidItemCount >= 5)
- {
- chance *= 1 / sqrt(itemBidPrice / avgBidPrice);
- }
+ chance *= 1.f / std::sqrt(itemBidPrice / avgBidPrice);
}
// If a player has bidded on item, have fifth of normal chance
if (auction->bidder)
- chance = chance / 5;
+ chance = chance / 5.f;
// Add config weigh in for quality
chance *= GetChanceMultiplier(item->GetTemplate()->Quality) / 100.0f;
- float rand = frand(0, 100);
+ float rand = frand(0.f, 100.f);
bool win = rand <= chance;
- TC_LOG_DEBUG("ahbot", "AHBot: %s BID! chance = %.2f, price = %u, bidprice = %u.", win ? "WIN" : "LOSE", chance, itemPrice, itemBidPrice);
+ TC_LOG_DEBUG("ahbot", "AHBot: %s BID! chance = %.2f, price = %u, bidprice = %u.", win ? "WIN" : "LOSE", chance, uint32(itemPrice), uint32(itemBidPrice));
return win;
}
diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp
index 733bd5e9ec8..22dc5bb0bd0 100644
--- a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp
+++ b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp
@@ -906,15 +906,17 @@ void AuctionBotSeller::AddNewAuctions(SellerConfiguration& config)
items = sAuctionBotConfig->GetItemPerCycleNormal();
uint32 houseid = 0;
- uint32 auctioneer = 0;
switch (config.GetHouseType())
{
case AUCTION_HOUSE_ALLIANCE:
- houseid = 1; auctioneer = 79707; break;
+ houseid = AUCTIONHOUSE_ALLIANCE;
+ break;
case AUCTION_HOUSE_HORDE:
- houseid = 6; auctioneer = 4656; break;
+ houseid = AUCTIONHOUSE_HORDE;
+ break;
default:
- houseid = 7; auctioneer = 23442; break;
+ houseid = AUCTIONHOUSE_NEUTRAL;
+ break;
}
AuctionHouseEntry const* ahEntry = sAuctionHouseStore.LookupEntry(houseid);
@@ -991,11 +993,11 @@ void AuctionBotSeller::AddNewAuctions(SellerConfiguration& config)
AuctionEntry* auctionEntry = new AuctionEntry();
auctionEntry->Id = sObjectMgr->GenerateAuctionID();
auctionEntry->owner = 0;
- auctionEntry->itemGUIDLow = item->GetGUIDLow();
+ auctionEntry->itemGUIDLow = item->GetGUID().GetCounter();
auctionEntry->itemEntry = item->GetEntry();
auctionEntry->startbid = bidPrice;
auctionEntry->buyout = buyoutPrice;
- auctionEntry->auctioneer = auctioneer;
+ auctionEntry->houseId = houseid;
auctionEntry->bidder = 0;
auctionEntry->bid = 0;
auctionEntry->deposit = sAuctionMgr->GetAuctionDeposit(ahEntry, etime, item, stackCount);
diff --git a/src/server/game/Battlefield/Battlefield.cpp b/src/server/game/Battlefield/Battlefield.cpp
index a22db18fa7e..d22ac0ea5d5 100644
--- a/src/server/game/Battlefield/Battlefield.cpp
+++ b/src/server/game/Battlefield/Battlefield.cpp
@@ -695,7 +695,7 @@ void BfGraveyard::Resurrect()
player->CastSpell(player, 6962, true);
player->CastSpell(player, SPELL_SPIRIT_HEAL_MANA, true);
- sObjectAccessor->ConvertCorpseForPlayer(player->GetGUID());
+ player->SpawnCorpseBones(false);
}
m_ResurrectQueue.clear();
@@ -770,7 +770,7 @@ Creature* Battlefield::SpawnCreature(uint32 entry, float x, float y, float z, fl
}
Creature* creature = new Creature();
- if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, PHASEMASK_NORMAL, entry, x, y, z, o))
+ if (!creature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, PHASEMASK_NORMAL, entry, x, y, z, o))
{
TC_LOG_ERROR("bg.battlefield", "Battlefield::SpawnCreature: Can't create creature entry: %u", entry);
delete creature;
@@ -803,7 +803,7 @@ GameObject* Battlefield::SpawnGameObject(uint32 entry, float x, float y, float z
// Create gameobject
GameObject* go = new GameObject;
- if (!go->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), entry, map, PHASEMASK_NORMAL, x, y, z, o, 0, 0, 0, 0, 100, GO_STATE_READY))
+ if (!go->Create(map->GenerateLowGuid<HighGuid::GameObject>(), entry, map, PHASEMASK_NORMAL, x, y, z, o, 0, 0, 0, 0, 100, GO_STATE_READY))
{
TC_LOG_ERROR("bg.battlefield", "Battlefield::SpawnGameObject: Gameobject template %u not found in database! Battlefield not created!", entry);
TC_LOG_ERROR("bg.battlefield", "Battlefield::SpawnGameObject: Cannot create gameobject template %u! Battlefield not created!", entry);
@@ -901,7 +901,7 @@ bool BfCapturePoint::SetCapturePointData(GameObject* capturePoint)
TC_LOG_DEBUG("bg.battlefield", "Creating capture point %u", capturePoint->GetEntry());
- m_capturePointGUID = ObjectGuid(HIGHGUID_GAMEOBJECT, capturePoint->GetEntry(), capturePoint->GetGUIDLow());
+ m_capturePointGUID = ObjectGuid(HighGuid::GameObject, capturePoint->GetEntry(), capturePoint->GetGUID().GetCounter());
// check info existence
GameObjectTemplate const* goinfo = capturePoint->GetGOInfo();
diff --git a/src/server/game/Battlefield/Battlefield.h b/src/server/game/Battlefield/Battlefield.h
index 3dbe974f0af..bb3ecb60838 100644
--- a/src/server/game/Battlefield/Battlefield.h
+++ b/src/server/game/Battlefield/Battlefield.h
@@ -99,7 +99,7 @@ class BfCapturePoint
GameObject* GetCapturePointGo();
uint32 GetCapturePointEntry() const { return m_capturePointEntry; }
- TeamId GetTeamId() { return m_team; }
+ TeamId GetTeamId() const { return m_team; }
protected:
bool DelCapturePoint();
@@ -193,7 +193,7 @@ class Battlefield : public ZoneScript
virtual ~Battlefield();
/// typedef of map witch store capturepoint and the associate gameobject entry
- typedef std::map<uint32 /*lowguid */, BfCapturePoint*> BfCapturePointMap;
+ typedef std::map<ObjectGuid::LowType /*lowguid */, BfCapturePoint*> BfCapturePointMap;
/// Call this to init the Battlefield
virtual bool SetupBattlefield() { return true; }
@@ -220,18 +220,18 @@ class Battlefield : public ZoneScript
/// Called when a Unit is kill in battlefield zone
virtual void HandleKill(Player* /*killer*/, Unit* /*killed*/) { };
- uint32 GetTypeId() { return m_TypeId; }
- uint32 GetZoneId() { return m_ZoneId; }
+ uint32 GetTypeId() const { return m_TypeId; }
+ uint32 GetZoneId() const { return m_ZoneId; }
void TeamApplyBuff(TeamId team, uint32 spellId, uint32 spellId2 = 0);
/// Return true if battle is start, false if battle is not started
- bool IsWarTime() { return m_isActive; }
+ bool IsWarTime() const { return m_isActive; }
/// Enable or Disable battlefield
void ToggleBattlefield(bool enable) { m_IsEnabled = enable; }
/// Return if battlefield is enable
- bool IsEnabled() { return m_IsEnabled; }
+ bool IsEnabled() const { return m_IsEnabled; }
/**
* \brief Kick player from battlefield and teleport him to kick-point location
@@ -254,9 +254,9 @@ class Battlefield : public ZoneScript
virtual void UpdateData(uint32 index, int32 pad) { m_Data32[index] += pad; }
// Battlefield - generic methods
- TeamId GetDefenderTeam() { return m_DefenderTeam; }
- TeamId GetAttackerTeam() { return TeamId(1 - m_DefenderTeam); }
- TeamId GetOtherTeam(TeamId team) { return (team == TEAM_HORDE ? TEAM_ALLIANCE : TEAM_HORDE); }
+ TeamId GetDefenderTeam() const { return m_DefenderTeam; }
+ TeamId GetAttackerTeam() const { return TeamId(1 - m_DefenderTeam); }
+ TeamId GetOtherTeam(TeamId team) const { return (team == TEAM_HORDE ? TEAM_ALLIANCE : TEAM_HORDE); }
void SetDefenderTeam(TeamId team) { m_DefenderTeam = team; }
// Group methods
@@ -308,7 +308,7 @@ class Battlefield : public ZoneScript
void PlayerAcceptInviteToQueue(Player* player);
void PlayerAcceptInviteToWar(Player* player);
- uint32 GetBattleId() { return m_BattleId; }
+ uint32 GetBattleId() const { return m_BattleId; }
void AskToLeaveQueue(Player* player);
virtual void DoCompleteOrIncrementAchievement(uint32 /*achievement*/, Player* /*player*/, uint8 /*incrementNumber = 1*/) { }
@@ -328,9 +328,9 @@ class Battlefield : public ZoneScript
void HideNpc(Creature* creature);
void ShowNpc(Creature* creature, bool aggressive);
- GraveyardVect GetGraveyardVector() { return m_GraveyardList; }
+ GraveyardVect GetGraveyardVector() const { return m_GraveyardList; }
- uint32 GetTimer() { return m_Timer; }
+ uint32 GetTimer() const { return m_Timer; }
void SetTimer(uint32 timer) { m_Timer = timer; }
void DoPlaySoundToAll(uint32 SoundID);
@@ -400,7 +400,7 @@ class Battlefield : public ZoneScript
// CapturePoint system
void AddCapturePoint(BfCapturePoint* cp) { m_capturePoints[cp->GetCapturePointEntry()] = cp; }
- BfCapturePoint* GetCapturePoint(uint32 lowguid) const
+ BfCapturePoint* GetCapturePoint(ObjectGuid::LowType lowguid) const
{
Battlefield::BfCapturePointMap::const_iterator itr = m_capturePoints.find(lowguid);
if (itr != m_capturePoints.end())
diff --git a/src/server/game/Battlefield/BattlefieldMgr.cpp b/src/server/game/Battlefield/BattlefieldMgr.cpp
index 0060cf4f304..00da81fb992 100644
--- a/src/server/game/Battlefield/BattlefieldMgr.cpp
+++ b/src/server/game/Battlefield/BattlefieldMgr.cpp
@@ -80,7 +80,7 @@ void BattlefieldMgr::HandlePlayerEnterZone(Player* player, uint32 zoneId)
return;
bf->HandlePlayerEnterZone(player, zoneId);
- TC_LOG_DEBUG("bg.battlefield", "Player %u entered battlefield id %u", player->GetGUIDLow(), bf->GetTypeId());
+ TC_LOG_DEBUG("bg.battlefield", "Player %u entered battlefield id %u", player->GetGUID().GetCounter(), bf->GetTypeId());
}
void BattlefieldMgr::HandlePlayerLeaveZone(Player* player, uint32 zoneId)
@@ -94,7 +94,7 @@ void BattlefieldMgr::HandlePlayerLeaveZone(Player* player, uint32 zoneId)
return;
itr->second->HandlePlayerLeaveZone(player, zoneId);
- TC_LOG_DEBUG("bg.battlefield", "Player %u left battlefield id %u", player->GetGUIDLow(), itr->second->GetTypeId());
+ TC_LOG_DEBUG("bg.battlefield", "Player %u left battlefield id %u", player->GetGUID().GetCounter(), itr->second->GetTypeId());
}
Battlefield* BattlefieldMgr::GetBattlefieldToZoneId(uint32 zoneId)
diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.h b/src/server/game/Battlefield/Zones/BattlefieldWG.h
index 47196876126..dcad65afa85 100644
--- a/src/server/game/Battlefield/Zones/BattlefieldWG.h
+++ b/src/server/game/Battlefield/Zones/BattlefieldWG.h
@@ -149,7 +149,7 @@ class BfGraveyardWG : public BfGraveyard
BfGraveyardWG(BattlefieldWG* Bf);
void SetTextId(uint32 textId) { m_GossipTextId = textId; }
- uint32 GetTextId() { return m_GossipTextId; }
+ uint32 GetTextId() const { return m_GossipTextId; }
protected:
uint32 m_GossipTextId;
diff --git a/src/server/game/Battlegrounds/Arena.cpp b/src/server/game/Battlegrounds/Arena.cpp
index dc0388348fc..60cc609a06a 100644
--- a/src/server/game/Battlegrounds/Arena.cpp
+++ b/src/server/game/Battlegrounds/Arena.cpp
@@ -40,7 +40,7 @@ Arena::Arena()
void Arena::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
- PlayerScores[player->GetGUIDLow()] = new ArenaScore(player->GetGUID(), player->GetBGTeam());
+ PlayerScores[player->GetGUID().GetCounter()] = new ArenaScore(player->GetGUID(), player->GetBGTeam());
if (player->GetBGTeam() == ALLIANCE) // gold
{
@@ -177,7 +177,7 @@ void Arena::EndBattleground(uint32 winner)
if (sWorld->getBoolConfig(CONFIG_ARENA_LOG_EXTENDED_INFO))
for (auto const& score : PlayerScores)
- if (Player* player = ObjectAccessor::FindConnectedPlayer(ObjectGuid(HIGHGUID_PLAYER, score.first)))
+ if (Player* player = ObjectAccessor::FindConnectedPlayer(ObjectGuid(HighGuid::Player, score.first)))
{
TC_LOG_DEBUG("bg.arena", "Statistics match Type: %u for %s (GUID: %u, Team: %d, IP: %s): %s",
GetArenaType(), player->GetName().c_str(), score.first, player->GetArenaTeamId(GetArenaType() == 5 ? 2 : GetArenaType() == 3),
diff --git a/src/server/game/Battlegrounds/ArenaTeam.cpp b/src/server/game/Battlegrounds/ArenaTeam.cpp
index 3b7e9ac3f33..7806e0b343b 100644
--- a/src/server/game/Battlegrounds/ArenaTeam.cpp
+++ b/src/server/game/Battlegrounds/ArenaTeam.cpp
@@ -63,7 +63,7 @@ bool ArenaTeam::Create(ObjectGuid captainGuid, uint8 type, std::string const& te
EmblemColor = emblemColor;
BorderStyle = borderStyle;
BorderColor = borderColor;
- uint32 captainLowGuid = captainGuid.GetCounter();
+ ObjectGuid::LowType captainLowGuid = captainGuid.GetCounter();
// Save arena team to db
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ARENA_TEAM);
@@ -193,7 +193,7 @@ bool ArenaTeam::LoadArenaTeamFromDB(QueryResult result)
TeamId = fields[0].GetUInt32();
TeamName = fields[1].GetString();
- CaptainGuid = ObjectGuid(HIGHGUID_PLAYER, fields[2].GetUInt32());
+ CaptainGuid = ObjectGuid(HighGuid::Player, fields[2].GetUInt32());
Type = fields[3].GetUInt8();
BackgroundColor = fields[4].GetUInt32();
EmblemStyle = fields[5].GetUInt8();
@@ -232,7 +232,7 @@ bool ArenaTeam::LoadMembersFromDB(QueryResult result)
break;
ArenaTeamMember newMember;
- newMember.Guid = ObjectGuid(HIGHGUID_PLAYER, fields[1].GetUInt32());
+ newMember.Guid = ObjectGuid(HighGuid::Player, fields[1].GetUInt32());
newMember.WeekGames = fields[2].GetUInt16();
newMember.WeekWins = fields[3].GetUInt16();
newMember.SeasonGames = fields[4].GetUInt16();
@@ -305,8 +305,8 @@ void ArenaTeam::SetCaptain(ObjectGuid guid)
if (oldCaptain)
{
TC_LOG_DEBUG("bg.arena", "Player: %s [GUID: %u] promoted player: %s [GUID: %u] to leader of arena team [Id: %u, Name: %s] [Type: %u].",
- oldCaptain->GetName().c_str(), oldCaptain->GetGUIDLow(), newCaptain->GetName().c_str(),
- newCaptain->GetGUIDLow(), GetId(), GetName().c_str(), GetType());
+ oldCaptain->GetName().c_str(), oldCaptain->GetGUID().GetCounter(), newCaptain->GetName().c_str(),
+ newCaptain->GetGUID().GetCounter(), GetId(), GetName().c_str(), GetType());
}
}
}
@@ -328,7 +328,7 @@ void ArenaTeam::DelMember(ObjectGuid guid, bool cleanDb)
// delete all info regarding this team
for (uint32 i = 0; i < ARENA_TEAM_END; ++i)
player->SetArenaTeamInfoField(GetSlot(), ArenaTeamInfoType(i), 0);
- TC_LOG_DEBUG("bg.arena", "Player: %s [GUID: %u] left arena team type: %u [Id: %u, Name: %s].", player->GetName().c_str(), player->GetGUIDLow(), GetType(), GetId(), GetName().c_str());
+ TC_LOG_DEBUG("bg.arena", "Player: %s [GUID: %u] left arena team type: %u [Id: %u, Name: %s].", player->GetName().c_str(), player->GetGUID().GetCounter(), GetType(), GetId(), GetName().c_str());
}
// Only used for single member deletion, for arena team disband we use a single query for more efficiency
@@ -353,7 +353,7 @@ void ArenaTeam::Disband(WorldSession* session)
BroadcastEvent(ERR_ARENA_TEAM_DISBANDED_S, ObjectGuid::Empty, 2, session->GetPlayerName(), GetName(), "");
if (Player* player = session->GetPlayer())
- TC_LOG_DEBUG("bg.arena", "Player: %s [GUID: %u] disbanded arena team type: %u [Id: %u, Name: %s].", player->GetName().c_str(), player->GetGUIDLow(), GetType(), GetId(), GetName().c_str());
+ TC_LOG_DEBUG("bg.arena", "Player: %s [GUID: %u] disbanded arena team type: %u [Id: %u, Name: %s].", player->GetName().c_str(), player->GetGUID().GetCounter(), GetType(), GetId(), GetName().c_str());
}
// Update database
diff --git a/src/server/game/Battlegrounds/ArenaTeamMgr.cpp b/src/server/game/Battlegrounds/ArenaTeamMgr.cpp
index b8f90ce7f1e..4fdb34e8d2f 100644
--- a/src/server/game/Battlegrounds/ArenaTeamMgr.cpp
+++ b/src/server/game/Battlegrounds/ArenaTeamMgr.cpp
@@ -21,8 +21,8 @@
#include "Log.h"
#include "DatabaseEnv.h"
#include "Language.h"
-#include "ObjectAccessor.h"
#include "Player.h"
+#include "ObjectAccessor.h"
ArenaTeamMgr::ArenaTeamMgr()
{
@@ -158,7 +158,7 @@ void ArenaTeamMgr::DistributeArenaPoints()
for (std::map<uint32, uint32>::iterator playerItr = PlayerPoints.begin(); playerItr != PlayerPoints.end(); ++playerItr)
{
// Add points to player if online
- if (Player* player = ObjectAccessor::FindConnectedPlayer(ObjectGuid(HIGHGUID_PLAYER, playerItr->first)))
+ if (Player* player = ObjectAccessor::FindConnectedPlayer(ObjectGuid(HighGuid::Player, playerItr->first)))
player->ModifyArenaPoints(playerItr->second, trans);
else // Update database
{
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index 3e9b68d4611..d368b347a0f 100644
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -306,6 +306,15 @@ inline void Battleground::_ProcessOfflineQueue()
{
if (itr->second.OfflineRemoveTime <= sWorld->GetGameTime())
{
+ if (isBattleground() && sWorld->getBoolConfig(CONFIG_BATTLEGROUND_TRACK_DESERTERS) &&
+ (GetStatus() == STATUS_IN_PROGRESS || GetStatus() == STATUS_WAIT_JOIN))
+ {
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_DESERTER_TRACK);
+ stmt->setUInt32(0, itr->first.GetCounter());
+ stmt->setUInt8(1, BG_DESERTION_TYPE_OFFLINE);
+ CharacterDatabase.Execute(stmt);
+ }
+
RemovePlayerAtLeave(itr->first, true, true);// remove player from BG
m_OfflineQueue.pop_front(); // remove from offline queue
//do not use itr for anything, because it is erased in RemovePlayerAtLeave()
@@ -367,7 +376,7 @@ inline void Battleground::_ProcessResurrect(uint32 diff)
player->ResurrectPlayer(1.0f);
player->CastSpell(player, 6962, true);
player->CastSpell(player, SPELL_SPIRIT_HEAL_MANA, true);
- sObjectAccessor->ConvertCorpseForPlayer(*itr);
+ player->SpawnCorpseBones(false);
}
m_ResurrectQueue.clear();
}
@@ -782,21 +791,22 @@ void Battleground::EndBattleground(uint32 winner)
if (isBattleground() && sWorld->getBoolConfig(CONFIG_BATTLEGROUND_STORE_STATISTICS_ENABLE))
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PVPSTATS_PLAYER);
- BattlegroundScoreMap::const_iterator score = PlayerScores.find(player->GetGUIDLow());
-
- stmt->setUInt32(0, battlegroundId);
- stmt->setUInt32(1, player->GetGUIDLow());
- stmt->setUInt32(2, score->second->GetKillingBlows());
- stmt->setUInt32(3, score->second->GetDeaths());
- stmt->setUInt32(4, score->second->GetHonorableKills());
- stmt->setUInt32(5, score->second->GetBonusHonor());
- stmt->setUInt32(6, score->second->GetDamageDone());
- stmt->setUInt32(7, score->second->GetHealingDone());
- stmt->setUInt32(8, score->second->GetAttr1());
- stmt->setUInt32(9, score->second->GetAttr2());
- stmt->setUInt32(10, score->second->GetAttr3());
- stmt->setUInt32(11, score->second->GetAttr4());
- stmt->setUInt32(12, score->second->GetAttr5());
+ BattlegroundScoreMap::const_iterator score = PlayerScores.find(player->GetGUID().GetCounter());
+
+ stmt->setUInt32(0, battlegroundId);
+ stmt->setUInt32(1, player->GetGUID().GetCounter());
+ stmt->setBool (2, team == winner);
+ stmt->setUInt32(3, score->second->GetKillingBlows());
+ stmt->setUInt32(4, score->second->GetDeaths());
+ stmt->setUInt32(5, score->second->GetHonorableKills());
+ stmt->setUInt32(6, score->second->GetBonusHonor());
+ stmt->setUInt32(7, score->second->GetDamageDone());
+ stmt->setUInt32(8, score->second->GetHealingDone());
+ stmt->setUInt32(9, score->second->GetAttr1());
+ stmt->setUInt32(10, score->second->GetAttr2());
+ stmt->setUInt32(11, score->second->GetAttr3());
+ stmt->setUInt32(12, score->second->GetAttr4());
+ stmt->setUInt32(13, score->second->GetAttr5());
CharacterDatabase.Execute(stmt);
}
@@ -889,8 +899,11 @@ void Battleground::RemovePlayerAtLeave(ObjectGuid guid, bool Transport, bool Sen
player->SpawnCorpseBones();
}
}
- else // try to resurrect the offline player. If he is alive nothing will happen
- sObjectAccessor->ConvertCorpseForPlayer(guid);
+ else
+ {
+ SQLTransaction trans(nullptr);
+ Player::OfflineResurrect(guid, trans);
+ }
RemovePlayer(player, guid, team); // BG subclass specific code
@@ -1162,48 +1175,58 @@ void Battleground::RemoveFromBGFreeSlotQueue()
// 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 BG is starting and CONFIG_BATTLEGROUND_INVITATION_TYPE == BG_QUEUE_INVITATION_TYPE_NO_BALANCE, invite anyone
+ if (GetStatus() == STATUS_WAIT_JOIN && sWorld->getIntConfig(CONFIG_BATTLEGROUND_INVITATION_TYPE) == BG_QUEUE_INVITATION_TYPE_NO_BALANCE)
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 BG is already started or CONFIG_BATTLEGROUND_INVITATION_TYPE != BG_QUEUE_INVITATION_TYPE_NO_BALANCE, do not allow to join too much players of one faction
+ uint32 otherTeamInvitedCount;
+ uint32 thisTeamInvitedCount;
+ uint32 otherTeamPlayersCount;
+ uint32 thisTeamPlayersCount;
+
if (Team == ALLIANCE)
{
- otherTeam = GetInvitedCount(HORDE);
- otherIn = GetPlayersCountByTeam(HORDE);
+ thisTeamInvitedCount = GetInvitedCount(ALLIANCE);
+ otherTeamInvitedCount = GetInvitedCount(HORDE);
+ thisTeamPlayersCount = GetPlayersCountByTeam(ALLIANCE);
+ otherTeamPlayersCount = GetPlayersCountByTeam(HORDE);
}
else
{
- otherTeam = GetInvitedCount(ALLIANCE);
- otherIn = GetPlayersCountByTeam(ALLIANCE);
+ thisTeamInvitedCount = GetInvitedCount(HORDE);
+ otherTeamInvitedCount = GetInvitedCount(ALLIANCE);
+ thisTeamPlayersCount = GetPlayersCountByTeam(HORDE);
+ otherTeamPlayersCount = GetPlayersCountByTeam(ALLIANCE);
}
- if (GetStatus() == STATUS_IN_PROGRESS)
+ if (GetStatus() == STATUS_IN_PROGRESS || GetStatus() == STATUS_WAIT_JOIN)
{
// 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))
+
+ // allow join one person if the sides are equal (to fill up bg to minPlayerPerTeam)
+ if (otherTeamInvitedCount == thisTeamInvitedCount)
diff = 1;
// allow join more ppl if the other side has more players
- else if (otherTeam > GetInvitedCount(Team))
- diff = otherTeam - GetInvitedCount(Team);
+ else if (otherTeamInvitedCount > thisTeamInvitedCount)
+ diff = otherTeamInvitedCount - thisTeamInvitedCount;
// difference based on max players per team (don't allow inviting more)
- uint32 diff2 = (GetInvitedCount(Team) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team) : 0;
+ uint32 diff2 = (thisTeamInvitedCount < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - thisTeamInvitedCount : 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))
+ // allow join one person if the sides are equal (to fill up bg minPlayerPerTeam)
+ if (otherTeamPlayersCount == thisTeamPlayersCount)
diff3 = 1;
// allow join more ppl if the other side has more players
- else if (otherIn > GetPlayersCountByTeam(Team))
- diff3 = otherIn - GetPlayersCountByTeam(Team);
+ else if (otherTeamPlayersCount > thisTeamPlayersCount)
+ diff3 = otherTeamPlayersCount - thisTeamPlayersCount;
// or other side has less than minPlayersPerTeam
- else if (GetInvitedCount(Team) <= GetMinPlayersPerTeam())
- diff3 = GetMinPlayersPerTeam() - GetInvitedCount(Team) + 1;
+ else if (thisTeamInvitedCount <= GetMinPlayersPerTeam())
+ diff3 = GetMinPlayersPerTeam() - thisTeamInvitedCount + 1;
// return the minimum of the 3 differences
@@ -1251,7 +1274,7 @@ void Battleground::BuildPvPLogDataPacket(WorldPacket& data)
bool Battleground::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
{
- BattlegroundScoreMap::const_iterator itr = PlayerScores.find(player->GetGUIDLow());
+ BattlegroundScoreMap::const_iterator itr = PlayerScores.find(player->GetGUID().GetCounter());
if (itr == PlayerScores.end()) // player not found...
return false;
@@ -1326,7 +1349,7 @@ bool Battleground::AddObject(uint32 type, uint32 entry, float x, float y, float
// and when loading it (in go::LoadFromDB()), a new guid would be assigned to the object, and a new object would be created
// So we must create it specific for this instance
GameObject* go = new GameObject;
- if (!go->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), entry, GetBgMap(),
+ if (!go->Create(GetBgMap()->GenerateLowGuid<HighGuid::GameObject>(), entry, GetBgMap(),
PHASEMASK_NORMAL, x, y, z, o, rotation0, rotation1, rotation2, rotation3, 100, goState))
{
TC_LOG_ERROR("bg.battleground", "Battleground::AddObject: cannot create gameobject (entry: %u) for BG (map: %u, instance id: %u)!",
@@ -1335,7 +1358,7 @@ bool Battleground::AddObject(uint32 type, uint32 entry, float x, float y, float
return false;
}
/*
- uint32 guid = go->GetGUIDLow();
+ uint32 guid = go->GetGUID().GetCounter();
// without this, UseButtonOrDoor caused the crash, since it tried to get go info from godata
// iirc that was changed, so adding to go data map is no longer required if that was the only function using godata from GameObject without checking if it existed
@@ -1469,7 +1492,7 @@ Creature* Battleground::AddCreature(uint32 entry, uint32 type, float x, float y,
Creature* creature = new Creature();
- if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, PHASEMASK_NORMAL, entry, x, y, z, o))
+ if (!creature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, PHASEMASK_NORMAL, entry, x, y, z, o))
{
TC_LOG_ERROR("bg.battleground", "Battleground::AddCreature: cannot create creature (entry: %u) for BG (map: %u, instance id: %u)!",
entry, m_MapId, m_InstanceID);
diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h
index 562a20b340f..471da9846b2 100644
--- a/src/server/game/Battlegrounds/Battleground.h
+++ b/src/server/game/Battlegrounds/Battleground.h
@@ -26,6 +26,7 @@
#include "WorldPacket.h"
#include "Object.h"
#include "GameObject.h"
+#include "EventMap.h"
class Creature;
class GameObject;
@@ -39,6 +40,15 @@ class BattlegroundMap;
struct PvPDifficultyEntry;
struct WorldSafeLocsEntry;
+enum BattlegroundDesertionType
+{
+ BG_DESERTION_TYPE_LEAVE_BG = 0, // player leaves the BG
+ BG_DESERTION_TYPE_OFFLINE = 1, // player is kicked from BG because offline
+ BG_DESERTION_TYPE_LEAVE_QUEUE = 2, // player is invited to join and refuses to do it
+ BG_DESERTION_TYPE_NO_ENTER_BUTTON = 3, // player is invited to join and do nothing (time expires)
+ BG_DESERTION_TYPE_INVITE_LOGOUT = 4, // player is invited to join and logs out
+};
+
enum BattlegroundCriteriaId
{
BG_CRITERIA_CHECK_RESILIENT_VICTORY,
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
index 95a51f6d915..3aac3f080f2 100644
--- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
@@ -514,7 +514,7 @@ void BattlegroundMgr::LoadBattlegroundTemplates()
_battlegroundTemplates.clear();
// 0 1 2 3 4 5 6 7 8 9 10 11
- QueryResult result = WorldDatabase.Query("SELECT id, MinPlayersPerTeam, MaxPlayersPerTeam, MinLvl, MaxLvl, AllianceStartLoc, AllianceStartO, HordeStartLoc, HordeStartO, StartMaxDist, Weight, ScriptName FROM battleground_template");
+ QueryResult result = WorldDatabase.Query("SELECT ID, MinPlayersPerTeam, MaxPlayersPerTeam, MinLvl, MaxLvl, AllianceStartLoc, AllianceStartO, HordeStartLoc, HordeStartO, StartMaxDist, Weight, ScriptName FROM battleground_template");
if (!result)
{
TC_LOG_ERROR("server.loading", ">> Loaded 0 battlegrounds. DB table `battleground_template` is empty.");
@@ -549,7 +549,7 @@ void BattlegroundMgr::LoadBattlegroundTemplates()
float dist = fields[9].GetFloat();
bgTemplate.MaxStartDistSq = dist * dist;
bgTemplate.Weight = fields[10].GetUInt8();
- bgTemplate.ScriptId = sObjectMgr->GetScriptId(fields[11].GetCString());
+ bgTemplate.ScriptId = sObjectMgr->GetScriptId(fields[11].GetString());
bgTemplate.BattlemasterEntry = bl;
if (bgTemplate.MaxPlayersPerTeam == 0 || bgTemplate.MinPlayersPerTeam > bgTemplate.MaxPlayersPerTeam)
@@ -821,7 +821,8 @@ void BattlegroundMgr::ToggleArenaTesting()
void BattlegroundMgr::SetHolidayWeekends(uint32 mask)
{
- for (uint32 bgtype = 1; bgtype < MAX_BATTLEGROUND_TYPE_ID; ++bgtype)
+ // The current code supports battlegrounds up to BattlegroundTypeId(31)
+ for (uint32 bgtype = 1; bgtype < MAX_BATTLEGROUND_TYPE_ID && bgtype < 32; ++bgtype)
if (Battleground* bg = GetBattlegroundTemplate(BattlegroundTypeId(bgtype)))
bg->SetHoliday((mask & (1 << bgtype)) != 0);
}
diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.cpp b/src/server/game/Battlegrounds/BattlegroundQueue.cpp
index 43b7acde925..223b71eb8c5 100644
--- a/src/server/game/Battlegrounds/BattlegroundQueue.cpp
+++ b/src/server/game/Battlegrounds/BattlegroundQueue.cpp
@@ -290,10 +290,11 @@ void BattlegroundQueue::RemovePlayer(ObjectGuid guid, bool decreaseInvitedCount)
itr = m_QueuedPlayers.find(guid);
if (itr == m_QueuedPlayers.end())
{
+ //This happens if a player logs out while in a bg because WorldSession::LogoutPlayer() notifies the bg twice
std::string playerName = "Unknown";
if (Player* player = ObjectAccessor::FindPlayer(guid))
playerName = player->GetName();
- TC_LOG_ERROR("bg.battleground", "BattlegroundQueue: couldn't find player %s (%s)", playerName.c_str(), guid.ToString().c_str());
+ TC_LOG_DEBUG("bg.battleground", "BattlegroundQueue: couldn't find player %s (%s)", playerName.c_str(), guid.ToString().c_str());
return;
}
@@ -475,7 +476,7 @@ bool BattlegroundQueue::InviteGroupToBG(GroupQueueInfo* ginfo, Battleground* bg,
uint32 queueSlot = player->GetBattlegroundQueueIndex(bgQueueTypeId);
TC_LOG_DEBUG("bg.battleground", "Battleground: invited player %s (%u) to BG instance %u queueindex %u bgtype %u",
- player->GetName().c_str(), player->GetGUIDLow(), bg->GetInstanceID(), queueSlot, bg->GetTypeID());
+ player->GetName().c_str(), player->GetGUID().GetCounter(), bg->GetInstanceID(), queueSlot, bg->GetTypeID());
// send status packet
sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0, ginfo->ArenaType, 0);
@@ -496,24 +497,51 @@ void BattlegroundQueue::FillPlayersToBG(Battleground* bg, BattlegroundBracketId
{
int32 hordeFree = bg->GetFreeSlotsForTeam(HORDE);
int32 aliFree = bg->GetFreeSlotsForTeam(ALLIANCE);
+ uint32 aliCount = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE].size();
+ uint32 hordeCount = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_HORDE].size();
+
+ // try to get even teams
+ if (sWorld->getIntConfig(CONFIG_BATTLEGROUND_INVITATION_TYPE) == BG_QUEUE_INVITATION_TYPE_EVEN)
+ {
+ // check if the teams are even
+ if (hordeFree == 1 && aliFree == 1)
+ {
+ // if we are here, the teams have the same amount of players
+ // then we have to allow to join the same amount of players
+ int32 hordeExtra = hordeCount - aliCount;
+ int32 aliExtra = aliCount - hordeCount;
+
+ hordeExtra = std::max(hordeExtra, 0);
+ aliExtra = std::max(aliExtra, 0);
+
+ if (aliCount != hordeCount)
+ {
+ aliFree -= aliExtra;
+ hordeFree -= hordeExtra;
+
+ aliFree = std::max(aliFree, 0);
+ hordeFree = std::max(hordeFree, 0);
+ }
+ }
+ }
//iterator for iterating through bg queue
GroupsQueueType::const_iterator Ali_itr = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE].begin();
//count of groups in queue - used to stop cycles
- uint32 aliCount = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE].size();
+
//index to queue which group is current
uint32 aliIndex = 0;
for (; aliIndex < aliCount && m_SelectionPools[TEAM_ALLIANCE].AddGroup((*Ali_itr), aliFree); aliIndex++)
++Ali_itr;
//the same thing for horde
GroupsQueueType::const_iterator Horde_itr = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_HORDE].begin();
- uint32 hordeCount = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_HORDE].size();
+
uint32 hordeIndex = 0;
for (; hordeIndex < hordeCount && m_SelectionPools[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->getIntConfig(CONFIG_BATTLEGROUND_INVITATION_TYPE) == 0)
+ if (sWorld->getIntConfig(CONFIG_BATTLEGROUND_INVITATION_TYPE) == BG_QUEUE_INVITATION_TYPE_NO_BALANCE)
return;
/*
@@ -648,7 +676,7 @@ bool BattlegroundQueue::CheckNormalMatch(Battleground* bg_template, Battleground
uint32 j = TEAM_ALLIANCE;
if (m_SelectionPools[TEAM_HORDE].GetPlayerCount() < m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount())
j = TEAM_HORDE;
- if (sWorld->getIntConfig(CONFIG_BATTLEGROUND_INVITATION_TYPE) != 0
+ if (sWorld->getIntConfig(CONFIG_BATTLEGROUND_INVITATION_TYPE) != BG_QUEUE_INVITATION_TYPE_NO_BALANCE
&& m_SelectionPools[TEAM_HORDE].GetPlayerCount() >= minPlayers && m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount() >= minPlayers)
{
//we will try to invite more groups to team with less players indexed by j
@@ -1040,7 +1068,17 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
BattlegroundQueue &bgQueue = sBattlegroundMgr->GetBattlegroundQueue(m_BgQueueTypeId);
if (bgQueue.IsPlayerInvited(m_PlayerGuid, m_BgInstanceGUID, m_RemoveTime))
{
- TC_LOG_DEBUG("bg.battleground", "Battleground: removing player %u from bg queue for instance %u because of not pressing enter battle in time.", player->GetGUIDLow(), m_BgInstanceGUID);
+ // track if player leaves the BG by not clicking enter button
+ if (bg && bg->isBattleground() && sWorld->getBoolConfig(CONFIG_BATTLEGROUND_TRACK_DESERTERS) &&
+ (bg->GetStatus() == STATUS_IN_PROGRESS || bg->GetStatus() == STATUS_WAIT_JOIN))
+ {
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_DESERTER_TRACK);
+ stmt->setUInt32(0, player->GetGUID().GetCounter());
+ stmt->setUInt8(1, BG_DESERTION_TYPE_NO_ENTER_BUTTON);
+ CharacterDatabase.Execute(stmt);
+ }
+
+ TC_LOG_DEBUG("bg.battleground", "Battleground: removing player %u from bg queue for instance %u because of not pressing enter battle in time.", player->GetGUID().GetCounter(), m_BgInstanceGUID);
player->RemoveBattlegroundQueueId(m_BgQueueTypeId);
bgQueue.RemovePlayer(m_PlayerGuid, true);
diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.h b/src/server/game/Battlegrounds/BattlegroundQueue.h
index 7e8debfd24d..1509a60e15d 100644
--- a/src/server/game/Battlegrounds/BattlegroundQueue.h
+++ b/src/server/game/Battlegrounds/BattlegroundQueue.h
@@ -64,6 +64,13 @@ enum BattlegroundQueueGroupTypes
};
#define BG_QUEUE_GROUP_TYPES_COUNT 4
+enum BattlegroundQueueInvitationType
+{
+ BG_QUEUE_INVITATION_TYPE_NO_BALANCE = 0, // no balance: N+M vs N players
+ BG_QUEUE_INVITATION_TYPE_BALANCED = 1, // teams balanced: N+1 vs N players
+ BG_QUEUE_INVITATION_TYPE_EVEN = 2 // teams even: N vs N players
+};
+
class Battleground;
class BattlegroundQueue
{
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
index 00b6862369d..f9d32e68e0e 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
@@ -222,7 +222,7 @@ void BattlegroundAB::StartingEventOpenDoors()
void BattlegroundAB::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
- PlayerScores[player->GetGUIDLow()] = new BattlegroundABScore(player->GetGUID());
+ PlayerScores[player->GetGUID().GetCounter()] = new BattlegroundABScore(player->GetGUID());
}
void BattlegroundAB::RemovePlayer(Player* /*player*/, ObjectGuid /*guid*/, uint32 /*team*/)
@@ -309,7 +309,7 @@ int32 BattlegroundAB::_GetNodeNameId(uint8 node)
case BG_AB_NODE_LUMBER_MILL:return LANG_BG_AB_NODE_LUMBER_MILL;
case BG_AB_NODE_GOLD_MINE: return LANG_BG_AB_NODE_GOLD_MINE;
default:
- ASSERT(false);
+ ABORT();
}
return 0;
}
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
index a92cda0817b..4ac02bab9ec 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
@@ -21,7 +21,6 @@
#include "ObjectMgr.h"
#include "WorldPacket.h"
-#include "Formulas.h"
#include "GameObject.h"
#include "Language.h"
#include "Player.h"
@@ -303,7 +302,7 @@ Creature* BattlegroundAV::AddAVCreature(uint16 cinfoid, uint16 type)
if (!isStatic && ((cinfoid >= AV_NPC_A_GRAVEDEFENSE0 && cinfoid <= AV_NPC_A_GRAVEDEFENSE3)
|| (cinfoid >= AV_NPC_H_GRAVEDEFENSE0 && cinfoid <= AV_NPC_H_GRAVEDEFENSE3)))
{
- CreatureData &data = sObjectMgr->NewOrExistCreatureData(creature->GetDBTableGUIDLow());
+ CreatureData &data = sObjectMgr->NewOrExistCreatureData(creature->GetSpawnId());
data.spawndist = 5;
}
//else spawndist will be 15, so creatures move maximum=10
@@ -436,7 +435,7 @@ void BattlegroundAV::StartingEventOpenDoors()
void BattlegroundAV::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
- PlayerScores[player->GetGUIDLow()] = new BattlegroundAVScore(player->GetGUID());
+ PlayerScores[player->GetGUID().GetCounter()] = new BattlegroundAVScore(player->GetGUID());
}
void BattlegroundAV::EndBattleground(uint32 winner)
@@ -790,7 +789,7 @@ BG_AV_Nodes BattlegroundAV::GetNodeThroughObject(uint32 object)
if (object == BG_AV_OBJECT_FLAG_N_SNOWFALL_GRAVE)
return BG_AV_NODES_SNOWFALL_GRAVE;
TC_LOG_ERROR("bg.battleground", "BattlegroundAV: ERROR! GetPlace got a wrong object :(");
- ASSERT(false);
+ ABORT();
return BG_AV_Nodes(0);
}
@@ -828,7 +827,7 @@ uint32 BattlegroundAV::GetObjectThroughNode(BG_AV_Nodes node)
else if (m_Nodes[node].Owner == AV_NEUTRAL_TEAM)
return BG_AV_OBJECT_FLAG_N_SNOWFALL_GRAVE;
TC_LOG_ERROR("bg.battleground", "BattlegroundAV: Error! GetPlaceNode couldn't resolve node %i", node);
- ASSERT(false);
+ ABORT();
return 0;
}
@@ -1377,10 +1376,10 @@ bool BattlegroundAV::SetupBattleground()
//creatures
TC_LOG_DEBUG("bg.battleground", "BG_AV start poputlating nodes");
- for (BG_AV_Nodes i = BG_AV_NODES_FIRSTAID_STATION; i < BG_AV_NODES_MAX; ++i)
+ for (BG_AV_Nodes n = BG_AV_NODES_FIRSTAID_STATION; n < BG_AV_NODES_MAX; ++n)
{
- if (m_Nodes[i].Owner)
- PopulateNode(i);
+ if (m_Nodes[n].Owner)
+ PopulateNode(n);
}
//all creatures which don't get despawned through the script are static
TC_LOG_DEBUG("bg.battleground", "BG_AV: start spawning static creatures");
@@ -1403,22 +1402,22 @@ void BattlegroundAV::AssaultNode(BG_AV_Nodes node, uint16 team)
if (m_Nodes[node].TotalOwner == team)
{
TC_LOG_FATAL("bg.battleground", "Assaulting team is TotalOwner of node");
- ASSERT(false);
+ ABORT();
}
if (m_Nodes[node].Owner == team)
{
TC_LOG_FATAL("bg.battleground", "Assaulting team is owner of node");
- ASSERT(false);
+ ABORT();
}
if (m_Nodes[node].State == POINT_DESTROYED)
{
TC_LOG_FATAL("bg.battleground", "Destroyed node is being assaulted");
- ASSERT(false);
+ ABORT();
}
if (m_Nodes[node].State == POINT_ASSAULTED && m_Nodes[node].TotalOwner) //only assault an assaulted node if no totalowner exists
{
TC_LOG_FATAL("bg.battleground", "Assault on an not assaulted node with total owner");
- ASSERT(false);
+ ABORT();
}
//the timer gets another time, if the previous owner was 0 == Neutral
m_Nodes[node].Timer = (m_Nodes[node].PrevOwner)? BG_AV_CAPTIME : BG_AV_SNOWFALL_FIRSTCAP;
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp
index 9e62a8c4616..02f9d6a32a6 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp
@@ -18,7 +18,6 @@
#include "BattlegroundDS.h"
#include "Creature.h"
-#include "GameObject.h"
#include "Player.h"
#include "WorldPacket.h"
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
index ef2e2b15411..7ab513c9201 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
@@ -17,13 +17,13 @@
*/
#include "BattlegroundEY.h"
-#include "ObjectMgr.h"
#include "WorldPacket.h"
#include "BattlegroundMgr.h"
#include "Creature.h"
#include "Language.h"
#include "Player.h"
#include "Util.h"
+#include "ObjectAccessor.h"
// these variables aren't used outside of this file, so declare them only here
uint32 BG_EY_HonorScoreTicks[BG_HONOR_MODE_NUM] =
@@ -161,7 +161,8 @@ void BattlegroundEY::CheckSomeoneJoinedPoint()
GameObject* obj = NULL;
for (uint8 i = 0; i < EY_POINTS_MAX; ++i)
{
- obj = HashMapHolder<GameObject>::Find(BgObjects[BG_EY_OBJECT_TOWER_CAP_FEL_REAVER + i]);
+ obj = GetBgMap()->GetGameObject(BgObjects[BG_EY_OBJECT_TOWER_CAP_FEL_REAVER + i]);
+
if (obj)
{
uint8 j = 0;
@@ -201,7 +202,8 @@ void BattlegroundEY::CheckSomeoneLeftPoint()
GameObject* obj = NULL;
for (uint8 i = 0; i < EY_POINTS_MAX; ++i)
{
- obj = HashMapHolder<GameObject>::Find(BgObjects[BG_EY_OBJECT_TOWER_CAP_FEL_REAVER + i]);
+ obj = GetBgMap()->GetGameObject(BgObjects[BG_EY_OBJECT_TOWER_CAP_FEL_REAVER + i]);
+
if (obj)
{
uint8 j = 0;
@@ -362,7 +364,7 @@ void BattlegroundEY::UpdatePointsIcons(uint32 Team, uint32 Point)
void BattlegroundEY::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
- PlayerScores[player->GetGUIDLow()] = new BattlegroundEYScore(player->GetGUID());
+ PlayerScores[player->GetGUID().GetCounter()] = new BattlegroundEYScore(player->GetGUID());
m_PlayersNearPoint[EY_POINTS_MAX].push_back(player->GetGUID());
}
@@ -588,7 +590,8 @@ void BattlegroundEY::RespawnFlagAfterDrop()
{
RespawnFlag(true);
- GameObject* obj = HashMapHolder<GameObject>::Find(GetDroppedFlagGUID());
+ GameObject* obj = GetBgMap()->GetGameObject(GetDroppedFlagGUID());
+
if (obj)
obj->Delete();
else
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp
index 3432c740c1f..bc2fc387e89 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp
@@ -245,7 +245,7 @@ void BattlegroundIC::StartingEventOpenDoors()
void BattlegroundIC::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
- PlayerScores[player->GetGUIDLow()] = new BattlegroundICScore(player->GetGUID());
+ PlayerScores[player->GetGUID().GetCounter()] = new BattlegroundICScore(player->GetGUID());
if (nodePoint[NODE_TYPE_QUARRY].nodeState == (player->GetTeamId() == TEAM_ALLIANCE ? NODE_STATE_CONTROLLED_A : NODE_STATE_CONTROLLED_H))
player->CastSpell(player, SPELL_QUARRY, true);
@@ -495,62 +495,62 @@ void BattlegroundIC::EventPlayerClickedOnFlag(Player* player, GameObject* target
}
}
-void BattlegroundIC::UpdateNodeWorldState(ICNodePoint* nodePoint)
+void BattlegroundIC::UpdateNodeWorldState(ICNodePoint* node)
{
//updating worldstate
- if (nodePoint->gameobject_entry == nodePoint->banners[BANNER_A_CONTROLLED])
- nodePoint->nodeState = NODE_STATE_CONTROLLED_A;
- else if (nodePoint->gameobject_entry == nodePoint->banners[BANNER_A_CONTESTED])
- nodePoint->nodeState = NODE_STATE_CONFLICT_A;
- else if (nodePoint->gameobject_entry == nodePoint->banners[BANNER_H_CONTROLLED])
- nodePoint->nodeState = NODE_STATE_CONTROLLED_H;
- else if (nodePoint->gameobject_entry == nodePoint->banners[BANNER_H_CONTESTED])
- nodePoint->nodeState = NODE_STATE_CONFLICT_H;
+ if (node->gameobject_entry == node->banners[BANNER_A_CONTROLLED])
+ node->nodeState = NODE_STATE_CONTROLLED_A;
+ else if (node->gameobject_entry == node->banners[BANNER_A_CONTESTED])
+ node->nodeState = NODE_STATE_CONFLICT_A;
+ else if (node->gameobject_entry == node->banners[BANNER_H_CONTROLLED])
+ node->nodeState = NODE_STATE_CONTROLLED_H;
+ else if (node->gameobject_entry == node->banners[BANNER_H_CONTESTED])
+ node->nodeState = NODE_STATE_CONFLICT_H;
- uint32 worldstate = nodePoint->worldStates[nodePoint->nodeState];
+ uint32 worldstate = node->worldStates[node->nodeState];
// with this we are sure we dont bug the client
for (uint8 i = 0; i < 5; ++i)
{
- if (nodePoint->worldStates[i] == worldstate)
+ if (node->worldStates[i] == worldstate)
continue;
- UpdateWorldState(nodePoint->worldStates[i], 0);
+ UpdateWorldState(node->worldStates[i], 0);
}
UpdateWorldState(worldstate, 1);
}
-uint32 BattlegroundIC::GetNextBanner(ICNodePoint* nodePoint, uint32 team, bool returnDefinitve)
+uint32 BattlegroundIC::GetNextBanner(ICNodePoint* node, uint32 team, bool returnDefinitve)
{
// this is only used in the update map function
if (returnDefinitve)
// here is a special case, here we must return the definitve faction banner after the grey banner was spawned 1 minute
- return nodePoint->banners[(team == TEAM_ALLIANCE ? BANNER_A_CONTROLLED : BANNER_H_CONTROLLED)];
+ return node->banners[(team == TEAM_ALLIANCE ? BANNER_A_CONTROLLED : BANNER_H_CONTROLLED)];
// there were no changes, this point has never been captured by any faction or at least clicked
- if (nodePoint->last_entry == 0)
+ if (node->last_entry == 0)
// 1 returns the CONTESTED ALLIANCE BANNER, 3 returns the HORDE one
- return nodePoint->banners[(team == TEAM_ALLIANCE ? BANNER_A_CONTESTED : BANNER_H_CONTESTED)];
+ return node->banners[(team == TEAM_ALLIANCE ? BANNER_A_CONTESTED : BANNER_H_CONTESTED)];
// If the actual banner is the definitive faction banner, we must return the grey banner of the player's faction
- if (nodePoint->gameobject_entry == nodePoint->banners[BANNER_A_CONTROLLED] || nodePoint->gameobject_entry == nodePoint->banners[BANNER_H_CONTROLLED])
- return nodePoint->banners[(team == TEAM_ALLIANCE ? BANNER_A_CONTESTED : BANNER_H_CONTESTED)];
+ if (node->gameobject_entry == node->banners[BANNER_A_CONTROLLED] || node->gameobject_entry == node->banners[BANNER_H_CONTROLLED])
+ return node->banners[(team == TEAM_ALLIANCE ? BANNER_A_CONTESTED : BANNER_H_CONTESTED)];
// If the actual banner is the grey faction banner, we must return the previous banner
- if (nodePoint->gameobject_entry == nodePoint->banners[BANNER_A_CONTESTED] || nodePoint->banners[BANNER_H_CONTESTED])
- return nodePoint->last_entry;
+ if (node->gameobject_entry == node->banners[BANNER_A_CONTESTED] || node->banners[BANNER_H_CONTESTED])
+ return node->last_entry;
// we should never be here...
TC_LOG_ERROR("bg.battleground", "Isle Of Conquest: Unexpected return in GetNextBanner function");
return 0;
}
-void BattlegroundIC::HandleContestedNodes(ICNodePoint* nodePoint)
+void BattlegroundIC::HandleContestedNodes(ICNodePoint* node)
{
- if (nodePoint->nodeType == NODE_TYPE_HANGAR)
+ if (node->nodeType == NODE_TYPE_HANGAR)
{
if (gunshipAlliance && gunshipHorde)
- (nodePoint->faction == TEAM_ALLIANCE ? gunshipHorde : gunshipAlliance)->EnableMovement(false);
+ (node->faction == TEAM_ALLIANCE ? gunshipHorde : gunshipAlliance)->EnableMovement(false);
for (uint8 u = BG_IC_GO_HANGAR_TELEPORTER_1; u <= BG_IC_GO_HANGAR_TELEPORTER_3; ++u)
DelObject(u);
@@ -567,7 +567,7 @@ void BattlegroundIC::HandleContestedNodes(ICNodePoint* nodePoint)
}
std::list<Creature*> cannons;
- if (nodePoint->faction == TEAM_HORDE)
+ if (node->faction == TEAM_HORDE)
gunshipAlliance->GetCreatureListWithEntryInGrid(cannons, NPC_ALLIANCE_GUNSHIP_CANNON, 150.0f);
else
gunshipHorde->GetCreatureListWithEntryInGrid(cannons, NPC_HORDE_GUNSHIP_CANNON, 150.0f);
@@ -578,22 +578,22 @@ void BattlegroundIC::HandleContestedNodes(ICNodePoint* nodePoint)
cannon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
}
}
- else if (nodePoint->nodeType == NODE_TYPE_WORKSHOP)
+ else if (node->nodeType == NODE_TYPE_WORKSHOP)
{
DelObject(BG_IC_GO_SEAFORIUM_BOMBS_1);
DelObject(BG_IC_GO_SEAFORIUM_BOMBS_2);
}
}
-void BattlegroundIC::HandleCapturedNodes(ICNodePoint* nodePoint, bool recapture)
+void BattlegroundIC::HandleCapturedNodes(ICNodePoint* node, bool recapture)
{
- if (nodePoint->nodeType != NODE_TYPE_REFINERY && nodePoint->nodeType != NODE_TYPE_QUARRY)
+ if (node->nodeType != NODE_TYPE_REFINERY && node->nodeType != NODE_TYPE_QUARRY)
{
- if (!AddSpiritGuide(BG_IC_NPC_SPIRIT_GUIDE_1+nodePoint->nodeType-2, BG_IC_SpiritGuidePos[nodePoint->nodeType], nodePoint->faction))
- TC_LOG_ERROR("bg.battleground", "Isle of Conquest: Failed to spawn spirit guide! point: %u, team: %u, ", nodePoint->nodeType, nodePoint->faction);
+ if (!AddSpiritGuide(BG_IC_NPC_SPIRIT_GUIDE_1+node->nodeType-2, BG_IC_SpiritGuidePos[node->nodeType], node->faction))
+ TC_LOG_ERROR("bg.battleground", "Isle of Conquest: Failed to spawn spirit guide! point: %u, team: %u, ", node->nodeType, node->faction);
}
- switch (nodePoint->gameobject_type)
+ switch (node->gameobject_type)
{
case BG_IC_GO_HANGAR_BANNER:
{
@@ -601,7 +601,7 @@ void BattlegroundIC::HandleCapturedNodes(ICNodePoint* nodePoint, bool recapture)
break;
std::list<Creature*> cannons;
- if (nodePoint->faction == TEAM_ALLIANCE)
+ if (node->faction == TEAM_ALLIANCE)
gunshipAlliance->GetCreatureListWithEntryInGrid(cannons, NPC_ALLIANCE_GUNSHIP_CANNON, 150.0f);
else
gunshipHorde->GetCreatureListWithEntryInGrid(cannons, NPC_HORDE_GUNSHIP_CANNON, 150.0f);
@@ -612,20 +612,20 @@ void BattlegroundIC::HandleCapturedNodes(ICNodePoint* nodePoint, bool recapture)
for (uint8 u = 0; u < MAX_HANGAR_TELEPORTERS_SPAWNS; ++u)
{
uint8 type = BG_IC_GO_HANGAR_TELEPORTER_1 + u;
- if (!AddObject(type, (nodePoint->faction == TEAM_ALLIANCE ? GO_ALLIANCE_GUNSHIP_PORTAL : GO_HORDE_GUNSHIP_PORTAL), BG_IC_HangarTeleporters[u], 0, 0, 0, 0, RESPAWN_ONE_DAY))
+ if (!AddObject(type, (node->faction == TEAM_ALLIANCE ? GO_ALLIANCE_GUNSHIP_PORTAL : GO_HORDE_GUNSHIP_PORTAL), BG_IC_HangarTeleporters[u], 0, 0, 0, 0, RESPAWN_ONE_DAY))
TC_LOG_ERROR("bg.battleground", "Isle of Conquest: There was an error spawning a gunship portal. Type: %u", BG_IC_GO_HANGAR_TELEPORTER_1 + u);
}
for (uint8 u = 0; u < MAX_HANGAR_TELEPORTER_EFFECTS_SPAWNS; ++u)
{
uint8 type = BG_IC_GO_HANGAR_TELEPORTER_EFFECT_1 + u;
- if (!AddObject(type, (nodePoint->faction == TEAM_ALLIANCE ? GO_ALLIANCE_GUNSHIP_PORTAL_EFFECTS : GO_HORDE_GUNSHIP_PORTAL_EFFECTS), BG_IC_HangarTeleporterEffects[u], 0, 0, 0, 0, RESPAWN_ONE_DAY, GO_STATE_ACTIVE))
+ if (!AddObject(type, (node->faction == TEAM_ALLIANCE ? GO_ALLIANCE_GUNSHIP_PORTAL_EFFECTS : GO_HORDE_GUNSHIP_PORTAL_EFFECTS), BG_IC_HangarTeleporterEffects[u], 0, 0, 0, 0, RESPAWN_ONE_DAY, GO_STATE_ACTIVE))
TC_LOG_ERROR("bg.battleground", "Isle of Conquest: There was an error spawning a gunship portal effects. Type: %u", BG_IC_GO_HANGAR_TELEPORTER_1 + u);
}
for (uint8 u = 0; u < MAX_TRIGGER_SPAWNS_PER_FACTION; ++u)
{
- if (!AddCreature(NPC_WORLD_TRIGGER_NOT_FLOATING, BG_IC_NPC_WORLD_TRIGGER_NOT_FLOATING, BG_IC_HangarTrigger[nodePoint->faction], nodePoint->faction, RESPAWN_ONE_DAY, nodePoint->faction == TEAM_ALLIANCE ? gunshipAlliance : gunshipHorde))
+ if (!AddCreature(NPC_WORLD_TRIGGER_NOT_FLOATING, BG_IC_NPC_WORLD_TRIGGER_NOT_FLOATING, BG_IC_HangarTrigger[node->faction], node->faction, RESPAWN_ONE_DAY, node->faction == TEAM_ALLIANCE ? gunshipAlliance : gunshipHorde))
TC_LOG_ERROR("bg.battleground", "Isle of Conquest: There was an error spawning a world trigger. Type: %u", BG_IC_NPC_WORLD_TRIGGER_NOT_FLOATING);
}
@@ -634,24 +634,24 @@ void BattlegroundIC::HandleCapturedNodes(ICNodePoint* nodePoint, bool recapture)
uint8 type = BG_IC_NPC_GUNSHIP_CAPTAIN_1 + u;
if (type == BG_IC_NPC_GUNSHIP_CAPTAIN_1)
- if (AddCreature(nodePoint->faction == TEAM_ALLIANCE ? NPC_ALLIANCE_GUNSHIP_CAPTAIN : NPC_HORDE_GUNSHIP_CAPTAIN, type, BG_IC_HangarCaptains[nodePoint->faction == TEAM_ALLIANCE ? 2 : 0], nodePoint->faction, RESPAWN_ONE_DAY))
+ if (AddCreature(node->faction == TEAM_ALLIANCE ? NPC_ALLIANCE_GUNSHIP_CAPTAIN : NPC_HORDE_GUNSHIP_CAPTAIN, type, BG_IC_HangarCaptains[node->faction == TEAM_ALLIANCE ? 2 : 0], node->faction, RESPAWN_ONE_DAY))
GetBGCreature(BG_IC_NPC_GUNSHIP_CAPTAIN_1)->GetAI()->DoAction(ACTION_GUNSHIP_READY);
if (type == BG_IC_NPC_GUNSHIP_CAPTAIN_2)
- if (!AddCreature(nodePoint->faction == TEAM_ALLIANCE ? NPC_ALLIANCE_GUNSHIP_CAPTAIN : NPC_HORDE_GUNSHIP_CAPTAIN, type, BG_IC_HangarCaptains[nodePoint->faction == TEAM_ALLIANCE ? 3 : 1], nodePoint->faction, RESPAWN_ONE_DAY, nodePoint->faction == TEAM_ALLIANCE ? gunshipAlliance : gunshipHorde))
+ if (!AddCreature(node->faction == TEAM_ALLIANCE ? NPC_ALLIANCE_GUNSHIP_CAPTAIN : NPC_HORDE_GUNSHIP_CAPTAIN, type, BG_IC_HangarCaptains[node->faction == TEAM_ALLIANCE ? 3 : 1], node->faction, RESPAWN_ONE_DAY, node->faction == TEAM_ALLIANCE ? gunshipAlliance : gunshipHorde))
TC_LOG_ERROR("bg.battleground", "Isle of Conquest: There was an error spawning a world trigger. Type: %u", BG_IC_NPC_GUNSHIP_CAPTAIN_2);
}
- (nodePoint->faction == TEAM_ALLIANCE ? gunshipAlliance : gunshipHorde)->EnableMovement(true);
+ (node->faction == TEAM_ALLIANCE ? gunshipAlliance : gunshipHorde)->EnableMovement(true);
break;
}
case BG_IC_GO_QUARRY_BANNER:
- RemoveAuraOnTeam(SPELL_QUARRY, (nodePoint->faction == TEAM_ALLIANCE ? HORDE : ALLIANCE));
- CastSpellOnTeam(SPELL_QUARRY, (nodePoint->faction == TEAM_ALLIANCE ? ALLIANCE : HORDE));
+ RemoveAuraOnTeam(SPELL_QUARRY, (node->faction == TEAM_ALLIANCE ? HORDE : ALLIANCE));
+ CastSpellOnTeam(SPELL_QUARRY, (node->faction == TEAM_ALLIANCE ? ALLIANCE : HORDE));
break;
case BG_IC_GO_REFINERY_BANNER:
- RemoveAuraOnTeam(SPELL_OIL_REFINERY, (nodePoint->faction == TEAM_ALLIANCE ? HORDE : ALLIANCE));
- CastSpellOnTeam(SPELL_OIL_REFINERY, (nodePoint->faction == TEAM_ALLIANCE ? ALLIANCE : HORDE));
+ RemoveAuraOnTeam(SPELL_OIL_REFINERY, (node->faction == TEAM_ALLIANCE ? HORDE : ALLIANCE));
+ CastSpellOnTeam(SPELL_OIL_REFINERY, (node->faction == TEAM_ALLIANCE ? ALLIANCE : HORDE));
break;
case BG_IC_GO_DOCKS_BANNER:
if (recapture)
@@ -661,7 +661,7 @@ void BattlegroundIC::HandleCapturedNodes(ICNodePoint* nodePoint, bool recapture)
docksTimer = DOCKS_UPDATE_TIME;
// we must del opposing faction vehicles when the node is captured (unused ones)
- for (uint8 i = (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_GLAIVE_THROWER_1_H : BG_IC_NPC_GLAIVE_THROWER_1_A); i < (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_GLAIVE_THROWER_2_H : BG_IC_NPC_GLAIVE_THROWER_2_A); ++i)
+ for (uint8 i = (node->faction == TEAM_ALLIANCE ? BG_IC_NPC_GLAIVE_THROWER_1_H : BG_IC_NPC_GLAIVE_THROWER_1_A); i < (node->faction == TEAM_ALLIANCE ? BG_IC_NPC_GLAIVE_THROWER_2_H : BG_IC_NPC_GLAIVE_THROWER_2_A); ++i)
{
if (Creature* glaiveThrower = GetBGCreature(i, false))
{
@@ -673,7 +673,7 @@ void BattlegroundIC::HandleCapturedNodes(ICNodePoint* nodePoint, bool recapture)
}
}
- for (uint8 i = (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_CATAPULT_1_H : BG_IC_NPC_CATAPULT_1_A); i < (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_CATAPULT_4_H : BG_IC_NPC_CATAPULT_4_A); ++i)
+ for (uint8 i = (node->faction == TEAM_ALLIANCE ? BG_IC_NPC_CATAPULT_1_H : BG_IC_NPC_CATAPULT_1_A); i < (node->faction == TEAM_ALLIANCE ? BG_IC_NPC_CATAPULT_4_H : BG_IC_NPC_CATAPULT_4_A); ++i)
{
if (Creature* catapult = GetBGCreature(i, false))
{
@@ -688,25 +688,25 @@ void BattlegroundIC::HandleCapturedNodes(ICNodePoint* nodePoint, bool recapture)
// spawning glaive throwers
for (uint8 i = 0; i < MAX_GLAIVE_THROWERS_SPAWNS_PER_FACTION; ++i)
{
- uint8 type = (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_GLAIVE_THROWER_1_A : BG_IC_NPC_GLAIVE_THROWER_1_H)+i;
+ uint8 type = (node->faction == TEAM_ALLIANCE ? BG_IC_NPC_GLAIVE_THROWER_1_A : BG_IC_NPC_GLAIVE_THROWER_1_H)+i;
if (GetBGCreature(type, false) && GetBGCreature(type)->IsAlive())
continue;
- if (AddCreature(nodePoint->faction == TEAM_ALLIANCE ? NPC_GLAIVE_THROWER_A : NPC_GLAIVE_THROWER_H, type, BG_IC_DocksVehiclesGlaives[i], nodePoint->faction, RESPAWN_ONE_DAY))
- GetBGCreature(type)->setFaction(BG_IC_Factions[(nodePoint->faction == TEAM_ALLIANCE ? 0 : 1)]);
+ if (AddCreature(node->faction == TEAM_ALLIANCE ? NPC_GLAIVE_THROWER_A : NPC_GLAIVE_THROWER_H, type, BG_IC_DocksVehiclesGlaives[i], node->faction, RESPAWN_ONE_DAY))
+ GetBGCreature(type)->setFaction(BG_IC_Factions[(node->faction == TEAM_ALLIANCE ? 0 : 1)]);
}
// spawning catapults
for (uint8 i = 0; i < MAX_CATAPULTS_SPAWNS_PER_FACTION; ++i)
{
- uint8 type = (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_CATAPULT_1_A : BG_IC_NPC_CATAPULT_1_H)+i;
+ uint8 type = (node->faction == TEAM_ALLIANCE ? BG_IC_NPC_CATAPULT_1_A : BG_IC_NPC_CATAPULT_1_H)+i;
if (GetBGCreature(type, false) && GetBGCreature(type)->IsAlive())
continue;
- if (AddCreature(NPC_CATAPULT, type, BG_IC_DocksVehiclesCatapults[i], nodePoint->faction, RESPAWN_ONE_DAY))
- GetBGCreature(type)->setFaction(BG_IC_Factions[(nodePoint->faction == TEAM_ALLIANCE ? 0 : 1)]);
+ if (AddCreature(NPC_CATAPULT, type, BG_IC_DocksVehiclesCatapults[i], node->faction, RESPAWN_ONE_DAY))
+ GetBGCreature(type)->setFaction(BG_IC_Factions[(node->faction == TEAM_ALLIANCE ? 0 : 1)]);
}
break;
case BG_IC_GO_WORKSHOP_BANNER:
@@ -717,7 +717,7 @@ void BattlegroundIC::HandleCapturedNodes(ICNodePoint* nodePoint, bool recapture)
if (!recapture)
{
// we must del opposing faction vehicles when the node is captured (unused ones)
- for (uint8 i = (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_DEMOLISHER_1_H : BG_IC_NPC_DEMOLISHER_1_A); i < (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_DEMOLISHER_4_H : BG_IC_NPC_DEMOLISHER_4_A); ++i)
+ for (uint8 i = (node->faction == TEAM_ALLIANCE ? BG_IC_NPC_DEMOLISHER_1_H : BG_IC_NPC_DEMOLISHER_1_A); i < (node->faction == TEAM_ALLIANCE ? BG_IC_NPC_DEMOLISHER_4_H : BG_IC_NPC_DEMOLISHER_4_A); ++i)
{
if (Creature* demolisher = GetBGCreature(i, false))
{
@@ -732,17 +732,17 @@ void BattlegroundIC::HandleCapturedNodes(ICNodePoint* nodePoint, bool recapture)
for (uint8 i = 0; i < MAX_DEMOLISHERS_SPAWNS_PER_FACTION; ++i)
{
- uint8 type = (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_DEMOLISHER_1_A : BG_IC_NPC_DEMOLISHER_1_H)+i;
+ uint8 type = (node->faction == TEAM_ALLIANCE ? BG_IC_NPC_DEMOLISHER_1_A : BG_IC_NPC_DEMOLISHER_1_H)+i;
if (GetBGCreature(type, false) && GetBGCreature(type)->IsAlive())
continue;
- if (AddCreature(NPC_DEMOLISHER, type, BG_IC_WorkshopVehicles[i], nodePoint->faction, RESPAWN_ONE_DAY))
- GetBGCreature(type)->setFaction(BG_IC_Factions[(nodePoint->faction == TEAM_ALLIANCE ? 0 : 1)]);
+ if (AddCreature(NPC_DEMOLISHER, type, BG_IC_WorkshopVehicles[i], node->faction, RESPAWN_ONE_DAY))
+ GetBGCreature(type)->setFaction(BG_IC_Factions[(node->faction == TEAM_ALLIANCE ? 0 : 1)]);
}
// we check if the opossing siege engine is in use
- int8 enemySiege = (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_SIEGE_ENGINE_H : BG_IC_NPC_SIEGE_ENGINE_A);
+ int8 enemySiege = (node->faction == TEAM_ALLIANCE ? BG_IC_NPC_SIEGE_ENGINE_H : BG_IC_NPC_SIEGE_ENGINE_A);
if (Creature* siegeEngine = GetBGCreature(enemySiege, false))
{
@@ -754,16 +754,16 @@ void BattlegroundIC::HandleCapturedNodes(ICNodePoint* nodePoint, bool recapture)
}
}
- uint8 siegeType = (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_SIEGE_ENGINE_A : BG_IC_NPC_SIEGE_ENGINE_H);
+ uint8 siegeType = (node->faction == TEAM_ALLIANCE ? BG_IC_NPC_SIEGE_ENGINE_A : BG_IC_NPC_SIEGE_ENGINE_H);
if (!GetBGCreature(siegeType, false) || !GetBGCreature(siegeType)->IsAlive())
{
- AddCreature((nodePoint->faction == TEAM_ALLIANCE ? NPC_SIEGE_ENGINE_A : NPC_SIEGE_ENGINE_H), siegeType,
- BG_IC_WorkshopVehicles[4], nodePoint->faction, RESPAWN_ONE_DAY);
+ AddCreature((node->faction == TEAM_ALLIANCE ? NPC_SIEGE_ENGINE_A : NPC_SIEGE_ENGINE_H), siegeType,
+ BG_IC_WorkshopVehicles[4], node->faction, RESPAWN_ONE_DAY);
if (Creature* siegeEngine = GetBGCreature(siegeType))
{
siegeEngine->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_UNK_14|UNIT_FLAG_IMMUNE_TO_PC);
- siegeEngine->setFaction(BG_IC_Factions[(nodePoint->faction == TEAM_ALLIANCE ? 0 : 1)]);
+ siegeEngine->setFaction(BG_IC_Factions[(node->faction == TEAM_ALLIANCE ? 0 : 1)]);
}
}
}
@@ -778,7 +778,7 @@ void BattlegroundIC::HandleCapturedNodes(ICNodePoint* nodePoint, bool recapture)
if (GameObject* seaforiumBombs = GetBGObject(BG_IC_GO_SEAFORIUM_BOMBS_1+i))
{
seaforiumBombs->SetRespawnTime(10);
- seaforiumBombs->SetFaction(BG_IC_Factions[(nodePoint->faction == TEAM_ALLIANCE ? 0 : 1)]);
+ seaforiumBombs->SetFaction(BG_IC_Factions[(node->faction == TEAM_ALLIANCE ? 0 : 1)]);
}
}
break;
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.h b/src/server/game/Battlegrounds/Zones/BattlegroundIC.h
index a313cd3901c..e2d511e0f1f 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.h
@@ -968,7 +968,7 @@ class BattlegroundIC : public Battleground
Transport* gunshipAlliance;
Transport* gunshipHorde;
- uint32 GetNextBanner(ICNodePoint* nodePoint, uint32 team, bool returnDefinitve);
+ uint32 GetNextBanner(ICNodePoint* node, uint32 team, bool returnDefinitve);
uint32 GetGateIDFromEntry(uint32 id)
{
@@ -1013,9 +1013,9 @@ class BattlegroundIC : public Battleground
return uws;
}
- void UpdateNodeWorldState(ICNodePoint* nodePoint);
- void HandleCapturedNodes(ICNodePoint* nodePoint, bool recapture);
- void HandleContestedNodes(ICNodePoint* nodePoint);
+ void UpdateNodeWorldState(ICNodePoint* node);
+ void HandleCapturedNodes(ICNodePoint* node, bool recapture);
+ void HandleContestedNodes(ICNodePoint* node);
};
#endif
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
index f267bf7c6c6..bfae37c64e6 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
@@ -476,7 +476,7 @@ void BattlegroundSA::FillInitialWorldStates(WorldPacket& data)
void BattlegroundSA::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
- PlayerScores[player->GetGUIDLow()] = new BattlegroundSAScore(player->GetGUID());
+ PlayerScores[player->GetGUID().GetCounter()] = new BattlegroundSAScore(player->GetGUID());
SendTransportInit(player);
@@ -744,7 +744,7 @@ bool BattlegroundSA::CanInteractWithObject(uint32 objectId)
return false;
break;
default:
- ASSERT(false);
+ ABORT();
break;
}
@@ -877,7 +877,7 @@ void BattlegroundSA::CaptureGraveyard(BG_SA_Graveyards i, Player* Source)
break;
default:
- ASSERT(false);
+ ABORT();
break;
};
}
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
index 378ce22ba3e..69f6b012c8b 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
@@ -20,10 +20,10 @@
#include "GameObject.h"
#include "Language.h"
#include "Object.h"
-#include "ObjectMgr.h"
#include "BattlegroundMgr.h"
#include "Player.h"
#include "WorldPacket.h"
+#include "ObjectAccessor.h"
// these variables aren't used outside of this file, so declare them only here
enum BG_WSG_Rewards
@@ -157,7 +157,7 @@ void BattlegroundWS::PostUpdateImpl(uint32 diff)
player->CastSpell(player, WS_SPELL_FOCUSED_ASSAULT, true);
_flagDebuffState = 1;
}
- else if (_flagDebuffState == 1 && _flagSpellForceTimer >= 900000) //15 minutes
+ else if (_flagDebuffState == 1 && _flagSpellForceTimer >= 15*MINUTE*IN_MILLISECONDS) //15 minutes
{
if (Player* player = ObjectAccessor::FindPlayer(m_FlagKeepers[0]))
{
@@ -227,7 +227,7 @@ void BattlegroundWS::StartingEventOpenDoors()
void BattlegroundWS::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
- PlayerScores[player->GetGUIDLow()] = new BattlegroundWGScore(player->GetGUID());
+ PlayerScores[player->GetGUID().GetCounter()] = new BattlegroundWGScore(player->GetGUID());
}
void BattlegroundWS::RespawnFlag(uint32 Team, bool captured)
@@ -882,7 +882,10 @@ bool BattlegroundWS::CheckAchievementCriteriaMeet(uint32 criteriaId, Player cons
switch (criteriaId)
{
case BG_CRITERIA_CHECK_SAVE_THE_DAY:
- return GetFlagState(player->GetTeam()) == BG_WS_FLAG_STATE_ON_BASE;
+ if (target)
+ if (Player const* playerTarget = target->ToPlayer())
+ return GetFlagState(playerTarget->GetTeam()) == BG_WS_FLAG_STATE_ON_BASE;
+ return false;
}
return Battleground::CheckAchievementCriteriaMeet(criteriaId, player, target, miscValue);
diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt
index 91380b085ea..6455e3a7e29 100644
--- a/src/server/game/CMakeLists.txt
+++ b/src/server/game/CMakeLists.txt
@@ -103,35 +103,6 @@ set(game_STAT_SRCS
)
include_directories(
- ${CMAKE_BINARY_DIR}
- ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour
- ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include
- ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast
- ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast/Include
- ${CMAKE_SOURCE_DIR}/dep/g3dlite/include
- ${CMAKE_SOURCE_DIR}/dep/SFMT
- ${CMAKE_SOURCE_DIR}/dep/cppformat
- ${CMAKE_SOURCE_DIR}/dep/zlib
- ${CMAKE_SOURCE_DIR}/src/server/collision
- ${CMAKE_SOURCE_DIR}/src/server/collision/Management
- ${CMAKE_SOURCE_DIR}/src/server/collision/Models
- ${CMAKE_SOURCE_DIR}/src/server/collision/Maps
- ${CMAKE_SOURCE_DIR}/src/server/shared
- ${CMAKE_SOURCE_DIR}/src/server/shared/Configuration
- ${CMAKE_SOURCE_DIR}/src/server/shared/Cryptography
- ${CMAKE_SOURCE_DIR}/src/server/shared/Cryptography/Authentication
- ${CMAKE_SOURCE_DIR}/src/server/shared/Database
- ${CMAKE_SOURCE_DIR}/src/server/shared/DataStores
- ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging
- ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference
- ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic
- ${CMAKE_SOURCE_DIR}/src/server/shared/Logging
- ${CMAKE_SOURCE_DIR}/src/server/shared/Networking
- ${CMAKE_SOURCE_DIR}/src/server/shared/Packets
- ${CMAKE_SOURCE_DIR}/src/server/shared/Threading
- ${CMAKE_SOURCE_DIR}/src/server/shared/Updater
- ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities
- ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/Accounts
${CMAKE_CURRENT_SOURCE_DIR}/Achievements
${CMAKE_CURRENT_SOURCE_DIR}/Addons
@@ -152,9 +123,8 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/Conditions
${CMAKE_CURRENT_SOURCE_DIR}/DataStores
${CMAKE_CURRENT_SOURCE_DIR}/DungeonFinding
- ${CMAKE_CURRENT_SOURCE_DIR}/Entities
- ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Creature
${CMAKE_CURRENT_SOURCE_DIR}/Entities/Corpse
+ ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Creature
${CMAKE_CURRENT_SOURCE_DIR}/Entities/DynamicObject
${CMAKE_CURRENT_SOURCE_DIR}/Entities/GameObject
${CMAKE_CURRENT_SOURCE_DIR}/Entities/Item
@@ -164,14 +134,14 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/Entities/Pet
${CMAKE_CURRENT_SOURCE_DIR}/Entities/Player
${CMAKE_CURRENT_SOURCE_DIR}/Entities/Totem
+ ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Transport
${CMAKE_CURRENT_SOURCE_DIR}/Entities/Unit
${CMAKE_CURRENT_SOURCE_DIR}/Entities/Vehicle
- ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Transport
${CMAKE_CURRENT_SOURCE_DIR}/Events
${CMAKE_CURRENT_SOURCE_DIR}/Globals
+ ${CMAKE_CURRENT_SOURCE_DIR}/Grids
${CMAKE_CURRENT_SOURCE_DIR}/Grids/Cells
${CMAKE_CURRENT_SOURCE_DIR}/Grids/Notifiers
- ${CMAKE_CURRENT_SOURCE_DIR}/Grids
${CMAKE_CURRENT_SOURCE_DIR}/Groups
${CMAKE_CURRENT_SOURCE_DIR}/Guilds
${CMAKE_CURRENT_SOURCE_DIR}/Handlers
@@ -181,28 +151,50 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/Maps
${CMAKE_CURRENT_SOURCE_DIR}/Miscellaneous
${CMAKE_CURRENT_SOURCE_DIR}/Movement
- ${CMAKE_CURRENT_SOURCE_DIR}/Movement/Spline
${CMAKE_CURRENT_SOURCE_DIR}/Movement/MovementGenerators
+ ${CMAKE_CURRENT_SOURCE_DIR}/Movement/Spline
${CMAKE_CURRENT_SOURCE_DIR}/Movement/Waypoints
${CMAKE_CURRENT_SOURCE_DIR}/OutdoorPvP
${CMAKE_CURRENT_SOURCE_DIR}/Pools
- ${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders
${CMAKE_CURRENT_SOURCE_DIR}/Quests
${CMAKE_CURRENT_SOURCE_DIR}/Reputation
${CMAKE_CURRENT_SOURCE_DIR}/Scripting
- ${CMAKE_CURRENT_SOURCE_DIR}/Server/Protocol
${CMAKE_CURRENT_SOURCE_DIR}/Server
+ ${CMAKE_CURRENT_SOURCE_DIR}/Server/Protocol
${CMAKE_CURRENT_SOURCE_DIR}/Skills
${CMAKE_CURRENT_SOURCE_DIR}/Spells
${CMAKE_CURRENT_SOURCE_DIR}/Spells/Auras
${CMAKE_CURRENT_SOURCE_DIR}/Texts
- ${CMAKE_CURRENT_SOURCE_DIR}/Tools
${CMAKE_CURRENT_SOURCE_DIR}/Tickets
+ ${CMAKE_CURRENT_SOURCE_DIR}/Tools
${CMAKE_CURRENT_SOURCE_DIR}/Warden
${CMAKE_CURRENT_SOURCE_DIR}/Warden/Modules
${CMAKE_CURRENT_SOURCE_DIR}/Weather
${CMAKE_CURRENT_SOURCE_DIR}/World
- ${CMAKE_SOURCE_DIR}/src/server/scripts/PrecompiledHeaders
+ ${CMAKE_SOURCE_DIR}/dep/cppformat
+ ${CMAKE_SOURCE_DIR}/dep/g3dlite/include
+ ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include
+ ${CMAKE_SOURCE_DIR}/dep/zlib
+ ${CMAKE_SOURCE_DIR}/src/common
+ ${CMAKE_SOURCE_DIR}/src/common/Collision
+ ${CMAKE_SOURCE_DIR}/src/common/Collision/Management
+ ${CMAKE_SOURCE_DIR}/src/common/Collision/Maps
+ ${CMAKE_SOURCE_DIR}/src/common/Collision/Models
+ ${CMAKE_SOURCE_DIR}/src/common/Configuration
+ ${CMAKE_SOURCE_DIR}/src/common/Cryptography
+ ${CMAKE_SOURCE_DIR}/src/common/Cryptography/Authentication
+ ${CMAKE_SOURCE_DIR}/src/common/Debugging
+ ${CMAKE_SOURCE_DIR}/src/common/Logging
+ ${CMAKE_SOURCE_DIR}/src/common/Threading
+ ${CMAKE_SOURCE_DIR}/src/common/Utilities
+ ${CMAKE_SOURCE_DIR}/src/server/database
+ ${CMAKE_SOURCE_DIR}/src/server/database/Database
+ ${CMAKE_SOURCE_DIR}/src/server/shared
+ ${CMAKE_SOURCE_DIR}/src/server/shared/DataStores
+ ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic
+ ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference
+ ${CMAKE_SOURCE_DIR}/src/server/shared/Networking
+ ${CMAKE_SOURCE_DIR}/src/server/shared/Packets
${MYSQL_INCLUDE_DIR}
${OPENSSL_INCLUDE_DIR}
${VALGRIND_INCLUDE_DIR}
@@ -215,8 +207,6 @@ add_library(game STATIC
${game_STAT_PCH_SRC}
)
-add_dependencies(game revision.h)
-
# Generate precompiled header
if (USE_COREPCH)
add_cxx_pch(game ${game_STAT_PCH_HDR} ${game_STAT_PCH_SRC})
diff --git a/src/server/game/Calendar/CalendarMgr.cpp b/src/server/game/Calendar/CalendarMgr.cpp
index bc1faa783fb..368ebecba84 100644
--- a/src/server/game/Calendar/CalendarMgr.cpp
+++ b/src/server/game/Calendar/CalendarMgr.cpp
@@ -58,7 +58,7 @@ void CalendarMgr::LoadFromDB()
Field* fields = result->Fetch();
uint64 eventId = fields[0].GetUInt64();
- ObjectGuid creatorGUID = ObjectGuid(HIGHGUID_PLAYER, fields[1].GetUInt32());
+ ObjectGuid creatorGUID = ObjectGuid(HighGuid::Player, fields[1].GetUInt32());
std::string title = fields[2].GetString();
std::string description = fields[3].GetString();
CalendarEventType type = CalendarEventType(fields[4].GetUInt8());
@@ -66,7 +66,7 @@ void CalendarMgr::LoadFromDB()
uint32 eventTime = fields[6].GetUInt32();
uint32 flags = fields[7].GetUInt32();
uint32 timezoneTime = fields[8].GetUInt32();
- uint32 guildId = 0;
+ ObjectGuid::LowType guildId = 0;
if (flags & CALENDAR_FLAG_GUILD_EVENT || flags & CALENDAR_FLAG_WITHOUT_INVITES)
guildId = Player::GetGuildIdFromDB(creatorGUID);
@@ -91,8 +91,8 @@ void CalendarMgr::LoadFromDB()
uint64 inviteId = fields[0].GetUInt64();
uint64 eventId = fields[1].GetUInt64();
- ObjectGuid invitee = ObjectGuid(HIGHGUID_PLAYER, fields[2].GetUInt32());
- ObjectGuid senderGUID = ObjectGuid(HIGHGUID_PLAYER, fields[3].GetUInt32());
+ ObjectGuid invitee = ObjectGuid(HighGuid::Player, fields[2].GetUInt32());
+ ObjectGuid senderGUID = ObjectGuid(HighGuid::Player, fields[3].GetUInt32());
CalendarInviteStatus status = CalendarInviteStatus(fields[4].GetUInt8());
uint32 statusTime = fields[5].GetUInt32();
CalendarModerationRank rank = CalendarModerationRank(fields[6].GetUInt8());
@@ -270,7 +270,7 @@ void CalendarMgr::RemoveAllPlayerEventsAndInvites(ObjectGuid guid)
RemoveInvite((*itr)->GetInviteId(), (*itr)->GetEventId(), guid);
}
-void CalendarMgr::RemovePlayerGuildEventsAndSignups(ObjectGuid guid, uint32 guildId)
+void CalendarMgr::RemovePlayerGuildEventsAndSignups(ObjectGuid guid, ObjectGuid::LowType guildId)
{
for (CalendarEventStore::const_iterator itr = _events.begin(); itr != _events.end(); ++itr)
if ((*itr)->GetCreatorGUID() == guid && ((*itr)->IsGuildEvent() || (*itr)->IsGuildAnnouncement()))
@@ -573,7 +573,7 @@ void CalendarMgr::SendCalendarEvent(ObjectGuid guid, CalendarEvent const& calend
Player* invitee = ObjectAccessor::FindPlayer(inviteeGuid);
uint8 inviteeLevel = invitee ? invitee->getLevel() : Player::GetLevelFromDB(inviteeGuid);
- uint32 inviteeGuildId = invitee ? invitee->GetGuildId() : Player::GetGuildIdFromDB(inviteeGuid);
+ ObjectGuid::LowType inviteeGuildId = invitee ? invitee->GetGuildId() : Player::GetGuildIdFromDB(inviteeGuid);
data << inviteeGuid.WriteAsPacked();
data << uint8(inviteeLevel);
diff --git a/src/server/game/Calendar/CalendarMgr.h b/src/server/game/Calendar/CalendarMgr.h
index 1027bd817f0..9969c00e3af 100644
--- a/src/server/game/Calendar/CalendarMgr.h
+++ b/src/server/game/Calendar/CalendarMgr.h
@@ -203,7 +203,7 @@ struct CalendarEvent
_description = calendarEvent.GetDescription();
}
- CalendarEvent(uint64 eventId, ObjectGuid creatorGUID, uint32 guildId, CalendarEventType type, int32 dungeonId,
+ CalendarEvent(uint64 eventId, ObjectGuid creatorGUID, ObjectGuid::LowType guildId, CalendarEventType type, int32 dungeonId,
time_t eventTime, uint32 flags, time_t timezoneTime, std::string title, std::string description) :
_eventId(eventId), _creatorGUID(creatorGUID), _guildId(guildId), _type(type), _dungeonId(dungeonId),
_eventTime(eventTime), _flags(flags), _timezoneTime(timezoneTime), _title(title),
@@ -220,8 +220,8 @@ struct CalendarEvent
void SetCreatorGUID(ObjectGuid guid) { _creatorGUID = guid; }
ObjectGuid GetCreatorGUID() const { return _creatorGUID; }
- void SetGuildId(uint32 guildId) { _guildId = guildId; }
- uint32 GetGuildId() const { return _guildId; }
+ void SetGuildId(ObjectGuid::LowType guildId) { _guildId = guildId; }
+ ObjectGuid::LowType GetGuildId() const { return _guildId; }
void SetTitle(const std::string& title) { _title = title; }
std::string GetTitle() const { return _title; }
@@ -253,7 +253,7 @@ struct CalendarEvent
private:
uint64 _eventId;
ObjectGuid _creatorGUID;
- uint32 _guildId;
+ ObjectGuid::LowType _guildId;
CalendarEventType _type;
int32 _dungeonId;
time_t _eventTime;
@@ -316,7 +316,7 @@ class CalendarMgr
void UpdateInvite(CalendarInvite* invite, SQLTransaction& trans);
void RemoveAllPlayerEventsAndInvites(ObjectGuid guid);
- void RemovePlayerGuildEventsAndSignups(ObjectGuid guid, uint32 guildId);
+ void RemovePlayerGuildEventsAndSignups(ObjectGuid guid, ObjectGuid::LowType guildId);
void SendCalendarEvent(ObjectGuid guid, CalendarEvent const& calendarEvent, CalendarSendEventType sendType);
void SendCalendarEventInvite(CalendarInvite const& invite);
diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp
index 1716aa73525..c99fe62f11e 100644
--- a/src/server/game/Chat/Chat.cpp
+++ b/src/server/game/Chat/Chat.cpp
@@ -19,7 +19,6 @@
#include "Common.h"
#include "ObjectMgr.h"
#include "World.h"
-#include "WorldPacket.h"
#include "WorldSession.h"
#include "DatabaseEnv.h"
@@ -29,61 +28,22 @@
#include "GridNotifiersImpl.h"
#include "Language.h"
#include "Log.h"
-#include "Opcodes.h"
#include "Player.h"
-#include "UpdateMask.h"
#include "ScriptMgr.h"
#include "ChatLink.h"
bool ChatHandler::load_command_table = true;
-// get number of commands in table
-static size_t getCommandTableSize(const ChatCommand* commands)
+std::vector<ChatCommand> const& ChatHandler::getCommandTable()
{
- if (!commands)
- return 0;
- size_t count = 0;
- while (commands[count].Name != NULL)
- count++;
- return count;
-}
-
-// append source command table to target, return number of appended commands
-static size_t appendCommandTable(ChatCommand* target, const ChatCommand* source)
-{
- const size_t count = getCommandTableSize(source);
- if (count)
- memcpy(target, source, count * sizeof(ChatCommand));
- return count;
-}
-
-ChatCommand* ChatHandler::getCommandTable()
-{
- // cache for commands, needed because some commands are loaded dynamically through ScriptMgr
- // cache is never freed and will show as a memory leak in diagnostic tools
- // can't use vector as vector storage is implementation-dependent, eg, there can be alignment gaps between elements
- static ChatCommand* commandTableCache = NULL;
+ static std::vector<ChatCommand> commandTableCache;
if (LoadCommandTable())
{
SetLoadCommandTable(false);
- {
- // count total number of top-level commands
- size_t total = 0;
- std::vector<ChatCommand*> const& dynamic = sScriptMgr->GetChatCommands();
- for (std::vector<ChatCommand*>::const_iterator it = dynamic.begin(); it != dynamic.end(); ++it)
- total += getCommandTableSize(*it);
- total += 1; // ending zero
-
- // cache top-level commands
- size_t added = 0;
- commandTableCache = (ChatCommand*)malloc(sizeof(ChatCommand) * total);
- ASSERT(commandTableCache);
- memset(commandTableCache, 0, sizeof(ChatCommand) * total);
- for (std::vector<ChatCommand*>::const_iterator it = dynamic.begin(); it != dynamic.end(); ++it)
- added += appendCommandTable(commandTableCache + added, *it);
- }
+ std::vector<ChatCommand> cmds = sScriptMgr->GetChatCommands();
+ commandTableCache.swap(cmds);
PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_COMMANDS);
PreparedQueryResult result = WorldDatabase.Query(stmt);
@@ -188,13 +148,33 @@ bool ChatHandler::hasStringAbbr(const char* name, const char* part)
return true;
}
-void ChatHandler::SendSysMessage(const char *str)
+void ChatHandler::SendSysMessage(const char *str, bool escapeCharacters)
{
WorldPacket data;
// need copy to prevent corruption by strtok call in LineFromMessage original string
- char* buf = strdup(str);
- char* pos = buf;
+ char* buf;
+ char* pos;
+
+ if (escapeCharacters && strchr(str, '|'))
+ {
+ size_t startPos = 0;
+ std::ostringstream o;
+ while (const char* charPos = strchr(str + startPos, '|'))
+ {
+ o.write(str + startPos, charPos - str - startPos);
+ o << "||";
+ startPos = charPos - str + 1;
+ }
+ o.write(str + startPos, strlen(str) - startPos);
+ buf = strdup(o.str().c_str());
+ }
+ else
+ {
+ buf = strdup(str);
+ }
+
+ pos = buf;
while (char* line = LineFromMessage(pos))
{
@@ -246,7 +226,7 @@ void ChatHandler::SendSysMessage(uint32 entry)
SendSysMessage(GetTrinityString(entry));
}
-bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, std::string const& fullcmd)
+bool ChatHandler::ExecuteCommandInTable(std::vector<ChatCommand> const& table, const char* text, std::string const& fullcmd)
{
char const* oldtext = text;
std::string cmd = "";
@@ -259,7 +239,7 @@ bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, st
while (*text == ' ') ++text;
- for (uint32 i = 0; table[i].Name != NULL; ++i)
+ for (uint32 i = 0; i < table.size(); ++i)
{
if (!hasStringAbbr(table[i].Name, cmd.c_str()))
continue;
@@ -267,7 +247,7 @@ bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, st
bool match = false;
if (strlen(table[i].Name) > cmd.length())
{
- for (uint32 j = 0; table[j].Name != NULL; ++j)
+ for (uint32 j = 0; j < table.size(); ++j)
{
if (!hasStringAbbr(table[j].Name, cmd.c_str()))
continue;
@@ -283,7 +263,7 @@ bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, st
continue;
// select subcommand from child commands list
- if (table[i].ChildCommands != NULL)
+ if (!table[i].ChildCommands.empty())
{
if (!ExecuteCommandInTable(table[i].ChildCommands, text, fullcmd))
{
@@ -328,7 +308,7 @@ bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, st
fullcmd.c_str(), player->GetName().c_str(), player->GetGUID().ToString().c_str(),
m_session->GetAccountId(), player->GetPositionX(), player->GetPositionY(),
player->GetPositionZ(), player->GetMapId(),
- player->GetMap() ? player->GetMap()->GetMapName() : "Unknown",
+ player->FindMap() ? player->FindMap()->GetMapName() : "Unknown",
areaId, areaName.c_str(), zoneName.c_str(),
(player->GetSelectedUnit()) ? player->GetSelectedUnit()->GetName().c_str() : "",
guid.ToString().c_str());
@@ -349,7 +329,7 @@ bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, st
return false;
}
-bool ChatHandler::SetDataForCommandInTable(ChatCommand* table, char const* text, uint32 permission, std::string const& help, std::string const& fullcommand)
+bool ChatHandler::SetDataForCommandInTable(std::vector<ChatCommand>& table, char const* text, uint32 permission, std::string const& help, std::string const& fullcommand)
{
std::string cmd = "";
@@ -361,14 +341,14 @@ bool ChatHandler::SetDataForCommandInTable(ChatCommand* table, char const* text,
while (*text == ' ') ++text;
- for (uint32 i = 0; table[i].Name != NULL; i++)
+ for (uint32 i = 0; i < table.size(); i++)
{
// for data fill use full explicit command names
if (table[i].Name != cmd)
continue;
// select subcommand from child commands list (including "")
- if (table[i].ChildCommands != NULL)
+ if (!table[i].ChildCommands.empty())
{
if (SetDataForCommandInTable(table[i].ChildCommands, text, permission, help, fullcommand))
return true;
@@ -395,7 +375,7 @@ bool ChatHandler::SetDataForCommandInTable(ChatCommand* table, char const* text,
// in case "" command let process by caller
if (!cmd.empty())
{
- if (table == getCommandTable())
+ if (&table == &getCommandTable())
TC_LOG_ERROR("sql.sql", "Table `command` have not existed command '%s', skip.", cmd.c_str());
else
TC_LOG_ERROR("sql.sql", "Table `command` have not existed subcommand '%s' in command '%s', skip.", cmd.c_str(), fullcommand.c_str());
@@ -501,10 +481,10 @@ Valid examples:
return LinkExtractor(message).IsValidMessage();
}
-bool ChatHandler::ShowHelpForSubCommands(ChatCommand* table, char const* cmd, char const* subcmd)
+bool ChatHandler::ShowHelpForSubCommands(std::vector<ChatCommand> const& table, char const* cmd, char const* subcmd)
{
std::string list;
- for (uint32 i = 0; table[i].Name != NULL; ++i)
+ for (uint32 i = 0; i < table.size(); ++i)
{
// must be available (ignore handler existence for show command with possible available subcommands)
if (!isAvailable(table[i]))
@@ -521,14 +501,14 @@ bool ChatHandler::ShowHelpForSubCommands(ChatCommand* table, char const* cmd, ch
list += table[i].Name;
- if (table[i].ChildCommands)
+ if (!table[i].ChildCommands.empty())
list += " ...";
}
if (list.empty())
return false;
- if (table == getCommandTable())
+ if (&table == &getCommandTable())
{
SendSysMessage(LANG_AVIABLE_CMD);
PSendSysMessage("%s", list.c_str());
@@ -539,11 +519,11 @@ bool ChatHandler::ShowHelpForSubCommands(ChatCommand* table, char const* cmd, ch
return true;
}
-bool ChatHandler::ShowHelpForCommand(ChatCommand* table, const char* cmd)
+bool ChatHandler::ShowHelpForCommand(std::vector<ChatCommand> const& table, const char* cmd)
{
if (*cmd)
{
- for (uint32 i = 0; table[i].Name != NULL; ++i)
+ for (uint32 i = 0; i < table.size(); ++i)
{
// must be available (ignore handler existence for show command with possible available subcommands)
if (!isAvailable(table[i]))
@@ -555,7 +535,7 @@ bool ChatHandler::ShowHelpForCommand(ChatCommand* table, const char* cmd)
// have subcommand
char const* subcmd = (*cmd) ? strtok(NULL, " ") : "";
- if (table[i].ChildCommands && subcmd && *subcmd)
+ if (!table[i].ChildCommands.empty() && subcmd && *subcmd)
{
if (ShowHelpForCommand(table[i].ChildCommands, subcmd))
return true;
@@ -564,7 +544,7 @@ bool ChatHandler::ShowHelpForCommand(ChatCommand* table, const char* cmd)
if (!table[i].Help.empty())
SendSysMessage(table[i].Help.c_str());
- if (table[i].ChildCommands)
+ if (!table[i].ChildCommands.empty())
if (ShowHelpForSubCommands(table[i].ChildCommands, table[i].Name, subcmd ? subcmd : ""))
return true;
@@ -573,7 +553,7 @@ bool ChatHandler::ShowHelpForCommand(ChatCommand* table, const char* cmd)
}
else
{
- for (uint32 i = 0; table[i].Name != NULL; ++i)
+ for (uint32 i = 0; i < table.size(); ++i)
{
// must be available (ignore handler existence for show command with possible available subcommands)
if (!isAvailable(table[i]))
@@ -585,7 +565,7 @@ bool ChatHandler::ShowHelpForCommand(ChatCommand* table, const char* cmd)
if (!table[i].Help.empty())
SendSysMessage(table[i].Help.c_str());
- if (table[i].ChildCommands)
+ if (!table[i].ChildCommands.empty())
if (ShowHelpForSubCommands(table[i].ChildCommands, "", ""))
return true;
@@ -892,26 +872,22 @@ GameObject* ChatHandler::GetNearbyGameObject()
return obj;
}
-GameObject* ChatHandler::GetObjectGlobalyWithGuidOrNearWithDbGuid(uint32 lowguid, uint32 entry)
+GameObject* ChatHandler::GetObjectGlobalyWithGuidOrNearWithDbGuid(ObjectGuid::LowType lowguid, uint32 entry)
{
if (!m_session)
return NULL;
Player* pl = m_session->GetPlayer();
- GameObject* obj = pl->GetMap()->GetGameObject(ObjectGuid(HIGHGUID_GAMEOBJECT, entry, lowguid));
+ GameObject* obj = pl->GetMap()->GetGameObject(ObjectGuid(HighGuid::GameObject, entry, lowguid));
if (!obj && sObjectMgr->GetGOData(lowguid)) // guid is DB guid of object
{
- // search near player then
- CellCoord p(Trinity::ComputeCellCoord(pl->GetPositionX(), pl->GetPositionY()));
- Cell cell(p);
-
- Trinity::GameObjectWithDbGUIDCheck go_check(*pl, lowguid);
- Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck> checker(pl, obj, go_check);
+ auto bounds = pl->GetMap()->GetGameObjectBySpawnIdStore().equal_range(lowguid);
+ if (bounds.first == bounds.second)
+ return nullptr;
- TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker);
- cell.Visit(p, object_checker, *pl->GetMap(), *pl, pl->GetGridActivationRange());
+ return bounds.first->second;
}
return obj;
@@ -1046,19 +1022,19 @@ ObjectGuid ChatHandler::extractGuidFromLink(char* text)
}
case SPELL_LINK_CREATURE:
{
- uint32 lowguid = atoul(idS);
+ ObjectGuid::LowType lowguid = atoul(idS);
if (CreatureData const* data = sObjectMgr->GetCreatureData(lowguid))
- return ObjectGuid(HIGHGUID_UNIT, data->id, lowguid);
+ return ObjectGuid(HighGuid::Unit, data->id, lowguid);
else
return ObjectGuid::Empty;
}
case SPELL_LINK_GAMEOBJECT:
{
- uint32 lowguid = atoul(idS);
+ ObjectGuid::LowType lowguid = atoul(idS);
if (GameObjectData const* data = sObjectMgr->GetGOData(lowguid))
- return ObjectGuid(HIGHGUID_GAMEOBJECT, data->id, lowguid);
+ return ObjectGuid(HighGuid::GameObject, data->id, lowguid);
else
return ObjectGuid::Empty;
}
@@ -1155,7 +1131,7 @@ void ChatHandler::extractOptFirstArg(char* args, char** arg1, char** arg2)
char* ChatHandler::extractQuotedArg(char* args)
{
- if (!*args)
+ if (!args || !*args)
return NULL;
if (*args == '"')
@@ -1225,7 +1201,7 @@ bool CliHandler::isAvailable(ChatCommand const& cmd) const
return cmd.AllowConsole;
}
-void CliHandler::SendSysMessage(const char *str)
+void CliHandler::SendSysMessage(const char *str, bool /*escapeCharacters*/)
{
m_print(m_callbackArg, str);
m_print(m_callbackArg, "\r\n");
diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h
index ba59245cdaa..2420331e363 100644
--- a/src/server/game/Chat/Chat.h
+++ b/src/server/game/Chat/Chat.h
@@ -38,13 +38,18 @@ struct GameTele;
class ChatCommand
{
+ typedef bool(*pHandler)(ChatHandler*, char const*);
+
public:
- const char * Name;
- uint32 Permission; // function pointer required correct align (use uint32)
- bool AllowConsole;
- bool (*Handler)(ChatHandler*, const char* args);
- std::string Help;
- ChatCommand* ChildCommands;
+ ChatCommand(char const* name, uint32 permission, bool allowConsole, pHandler handler, std::string help, std::vector<ChatCommand> childCommands = std::vector<ChatCommand>())
+ : Name(ASSERT_NOTNULL(name)), Permission(permission), AllowConsole(allowConsole), Handler(handler), Help(std::move(help)), ChildCommands(std::move(childCommands)) { }
+
+ char const* Name;
+ uint32 Permission; // function pointer required correct align (use uint32)
+ bool AllowConsole;
+ pHandler Handler;
+ std::string Help;
+ std::vector<ChatCommand> ChildCommands;
};
class ChatHandler
@@ -66,31 +71,31 @@ class ChatHandler
// function with different implementation for chat/console
virtual char const* GetTrinityString(uint32 entry) const;
- virtual void SendSysMessage(char const* str);
+ virtual void SendSysMessage(char const* str, bool escapeCharacters = false);
void SendSysMessage(uint32 entry);
template<typename... Args>
- void PSendSysMessage(const char* fmt, Args const&... args)
+ void PSendSysMessage(const char* fmt, Args&&... args)
{
- SendSysMessage(Trinity::StringFormat(fmt, args...).c_str());
+ SendSysMessage(Trinity::StringFormat(fmt, std::forward<Args>(args)...).c_str());
}
template<typename... Args>
- void PSendSysMessage(uint32 entry, Args const&... args)
+ void PSendSysMessage(uint32 entry, Args&&... args)
{
- SendSysMessage(PGetParseString(entry, args...).c_str());
+ SendSysMessage(PGetParseString(entry, std::forward<Args>(args)...).c_str());
}
template<typename... Args>
- std::string PGetParseString(uint32 entry, Args const&... args) const
+ std::string PGetParseString(uint32 entry, Args&&... args) const
{
- return Trinity::StringFormat(GetTrinityString(entry), args...);
+ return Trinity::StringFormat(GetTrinityString(entry), std::forward<Args>(args)...);
}
bool ParseCommands(const char* text);
- static ChatCommand* getCommandTable();
+ static std::vector<ChatCommand> const& getCommandTable();
bool isValidChatMessage(const char* msg);
void SendGlobalSysMessage(const char *str);
@@ -135,18 +140,18 @@ class ChatHandler
std::string GetNameLink(Player* chr) const;
GameObject* GetNearbyGameObject();
- GameObject* GetObjectGlobalyWithGuidOrNearWithDbGuid(uint32 lowguid, uint32 entry);
+ GameObject* GetObjectGlobalyWithGuidOrNearWithDbGuid(ObjectGuid::LowType lowguid, uint32 entry);
bool HasSentErrorMessage() const { return sentErrorMessage; }
void SetSentErrorMessage(bool val){ sentErrorMessage = val; }
static bool LoadCommandTable() { return load_command_table; }
static void SetLoadCommandTable(bool val) { load_command_table = val; }
- bool ShowHelpForCommand(ChatCommand* table, const char* cmd);
+ bool ShowHelpForCommand(std::vector<ChatCommand> const& table, const char* cmd);
protected:
explicit ChatHandler() : m_session(NULL), sentErrorMessage(false) { } // for CLI subclass
- static bool SetDataForCommandInTable(ChatCommand* table, const char* text, uint32 permission, std::string const& help, std::string const& fullcommand);
- bool ExecuteCommandInTable(ChatCommand* table, const char* text, std::string const& fullcmd);
- bool ShowHelpForSubCommands(ChatCommand* table, char const* cmd, char const* subcmd);
+ static bool SetDataForCommandInTable(std::vector<ChatCommand>& table, const char* text, uint32 permission, std::string const& help, std::string const& fullcommand);
+ bool ExecuteCommandInTable(std::vector<ChatCommand> const& table, const char* text, std::string const& fullcmd);
+ bool ShowHelpForSubCommands(std::vector<ChatCommand> const& table, char const* cmd, char const* subcmd);
private:
WorldSession* m_session; // != NULL for chat command call and NULL for CLI command
@@ -166,7 +171,7 @@ class CliHandler : public ChatHandler
char const* GetTrinityString(uint32 entry) const override;
bool isAvailable(ChatCommand const& cmd) const override;
bool HasPermission(uint32 /*permission*/) const override { return true; }
- void SendSysMessage(const char *str) override;
+ void SendSysMessage(const char *str, bool escapeCharacters) override;
std::string GetNameLink() const override;
bool needReportToTarget(Player* chr) const override;
LocaleConstant GetSessionDbcLocale() const override;
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index 25fbef2ca86..bae400adcc2 100644
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -27,9 +27,8 @@
#include "ScriptMgr.h"
#include "SpellAuras.h"
#include "SpellMgr.h"
-#include "Spell.h"
-char const* ConditionMgr::StaticSourceTypeData[CONDITION_SOURCE_TYPE_MAX] =
+char const* const ConditionMgr::StaticSourceTypeData[CONDITION_SOURCE_TYPE_MAX] =
{
"None",
"Creature Loot",
@@ -90,7 +89,7 @@ ConditionMgr::ConditionTypeInfo const ConditionMgr::StaticConditionTypeData[COND
{ "PhaseMask", true, false, false },
{ "Level", true, true, false },
{ "Quest Completed", true, false, false },
- { "Near Creature", true, true, false },
+ { "Near Creature", true, true, true },
{ "Near GameObject", true, true, false },
{ "Object Entry or Guid", true, true, true },
{ "Object TypeMask", true, false, false },
@@ -106,7 +105,7 @@ ConditionMgr::ConditionTypeInfo const ConditionMgr::StaticConditionTypeData[COND
// Checks if object meets the condition
// Can have CONDITION_SOURCE_TYPE_NONE && !mReferenceId if called from a special event (ie: eventAI)
-bool Condition::Meets(ConditionSourceInfo& sourceInfo)
+bool Condition::Meets(ConditionSourceInfo& sourceInfo) const
{
ASSERT(ConditionTarget < MAX_CONDITION_TARGETS);
WorldObject* object = sourceInfo.mConditionTargets[ConditionTarget];
@@ -232,7 +231,7 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo)
case CONDITION_INSTANCE_INFO:
{
Map* map = object->GetMap();
- if (map && map->IsDungeon())
+ if (map->IsDungeon())
{
if (InstanceScript const* instance = ((InstanceMap*)map)->GetInstanceScript())
{
@@ -281,7 +280,7 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo)
}
case CONDITION_NEAR_CREATURE:
{
- condMeets = GetClosestCreatureWithEntry(object, ConditionValue1, (float)ConditionValue2) ? true : false;
+ condMeets = GetClosestCreatureWithEntry(object, ConditionValue1, (float)ConditionValue2, bool(!ConditionValue3)) ? true : false;
break;
}
case CONDITION_NEAR_GAMEOBJECT:
@@ -300,10 +299,10 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo)
switch (object->GetTypeId())
{
case TYPEID_UNIT:
- condMeets &= object->ToCreature()->GetDBTableGUIDLow() == ConditionValue3;
+ condMeets &= object->ToCreature()->GetSpawnId() == ConditionValue3;
break;
case TYPEID_GAMEOBJECT:
- condMeets &= object->ToGameObject()->GetDBTableGUIDLow() == ConditionValue3;
+ condMeets &= object->ToGameObject()->GetSpawnId() == ConditionValue3;
break;
default:
break;
@@ -325,7 +324,7 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo)
Unit* unit = object->ToUnit();
if (toUnit && unit)
{
- switch (ConditionValue2)
+ switch (static_cast<RelationType>(ConditionValue2))
{
case RELATION_SELF:
condMeets = unit == toUnit;
@@ -345,6 +344,8 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo)
case RELATION_CREATED_BY:
condMeets = unit->GetCreatorGUID() == toUnit->GetGUID();
break;
+ default:
+ break;
}
}
}
@@ -446,7 +447,7 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo)
return condMeets && script;
}
-uint32 Condition::GetSearcherTypeMaskForCondition()
+uint32 Condition::GetSearcherTypeMaskForCondition() const
{
// build mask of types for which condition can return true
// this is used for speeding up gridsearches
@@ -608,7 +609,7 @@ uint32 Condition::GetSearcherTypeMaskForCondition()
return mask;
}
-uint32 Condition::GetMaxAvailableConditionTargets()
+uint32 Condition::GetMaxAvailableConditionTargets() const
{
// returns number of targets which are available for given source type
switch (SourceType)
@@ -664,114 +665,105 @@ ConditionMgr::~ConditionMgr()
Clean();
}
-ConditionList ConditionMgr::GetConditionReferences(uint32 refId)
-{
- ConditionList conditions;
- ConditionReferenceContainer::const_iterator ref = ConditionReferenceStore.find(refId);
- if (ref != ConditionReferenceStore.end())
- conditions = (*ref).second;
- return conditions;
-}
-
-uint32 ConditionMgr::GetSearcherTypeMaskForConditionList(ConditionList const& conditions)
+uint32 ConditionMgr::GetSearcherTypeMaskForConditionList(ConditionContainer const& conditions) const
{
if (conditions.empty())
return GRID_MAP_TYPE_MASK_ALL;
// groupId, typeMask
- std::map<uint32, uint32> ElseGroupStore;
- for (ConditionList::const_iterator i = conditions.begin(); i != conditions.end(); ++i)
+ std::map<uint32, uint32> elseGroupSearcherTypeMasks;
+ for (ConditionContainer::const_iterator i = conditions.begin(); i != conditions.end(); ++i)
{
// no point of having not loaded conditions in list
ASSERT((*i)->isLoaded() && "ConditionMgr::GetSearcherTypeMaskForConditionList - not yet loaded condition found in list");
- std::map<uint32, uint32>::const_iterator itr = ElseGroupStore.find((*i)->ElseGroup);
+ std::map<uint32, uint32>::const_iterator itr = elseGroupSearcherTypeMasks.find((*i)->ElseGroup);
// group not filled yet, fill with widest mask possible
- if (itr == ElseGroupStore.end())
- ElseGroupStore[(*i)->ElseGroup] = GRID_MAP_TYPE_MASK_ALL;
+ if (itr == elseGroupSearcherTypeMasks.end())
+ elseGroupSearcherTypeMasks[(*i)->ElseGroup] = GRID_MAP_TYPE_MASK_ALL;
// no point of checking anymore, empty mask
- else if (!(*itr).second)
+ else if (!itr->second)
continue;
if ((*i)->ReferenceId) // handle reference
{
ConditionReferenceContainer::const_iterator ref = ConditionReferenceStore.find((*i)->ReferenceId);
ASSERT(ref != ConditionReferenceStore.end() && "ConditionMgr::GetSearcherTypeMaskForConditionList - incorrect reference");
- ElseGroupStore[(*i)->ElseGroup] &= GetSearcherTypeMaskForConditionList((*ref).second);
+ elseGroupSearcherTypeMasks[(*i)->ElseGroup] &= GetSearcherTypeMaskForConditionList((*ref).second);
}
else // handle normal condition
{
// object will match conditions in one ElseGroupStore only when it matches all of them
// so, let's find a smallest possible mask which satisfies all conditions
- ElseGroupStore[(*i)->ElseGroup] &= (*i)->GetSearcherTypeMaskForCondition();
+ elseGroupSearcherTypeMasks[(*i)->ElseGroup] &= (*i)->GetSearcherTypeMaskForCondition();
}
}
// object will match condition when one of the checks in ElseGroupStore is matching
// so, let's include all possible masks
uint32 mask = 0;
- for (std::map<uint32, uint32>::const_iterator i = ElseGroupStore.begin(); i != ElseGroupStore.end(); ++i)
+ for (std::map<uint32, uint32>::const_iterator i = elseGroupSearcherTypeMasks.begin(); i != elseGroupSearcherTypeMasks.end(); ++i)
mask |= i->second;
return mask;
}
-bool ConditionMgr::IsObjectMeetToConditionList(ConditionSourceInfo& sourceInfo, ConditionList const& conditions)
+bool ConditionMgr::IsObjectMeetToConditionList(ConditionSourceInfo& sourceInfo, ConditionContainer const& conditions) const
{
// groupId, groupCheckPassed
- std::map<uint32, bool> ElseGroupStore;
- for (ConditionList::const_iterator i = conditions.begin(); i != conditions.end(); ++i)
+ std::map<uint32, bool> elseGroupStore;
+ for (Condition const* condition : conditions)
{
- TC_LOG_DEBUG("condition", "ConditionMgr::IsPlayerMeetToConditionList %s val1: %u", (*i)->ToString().c_str(), (*i)->ConditionValue1);
- if ((*i)->isLoaded())
+ TC_LOG_DEBUG("condition", "ConditionMgr::IsPlayerMeetToConditionList %s val1: %u", condition->ToString().c_str(), condition->ConditionValue1);
+ if (condition->isLoaded())
{
//! Find ElseGroup in ElseGroupStore
- std::map<uint32, bool>::const_iterator itr = ElseGroupStore.find((*i)->ElseGroup);
+ std::map<uint32, bool>::const_iterator itr = elseGroupStore.find(condition->ElseGroup);
//! If not found, add an entry in the store and set to true (placeholder)
- if (itr == ElseGroupStore.end())
- ElseGroupStore[(*i)->ElseGroup] = true;
+ if (itr == elseGroupStore.end())
+ elseGroupStore[condition->ElseGroup] = true;
else if (!(*itr).second)
continue;
- if ((*i)->ReferenceId)//handle reference
+ if (condition->ReferenceId)//handle reference
{
- ConditionReferenceContainer::const_iterator ref = ConditionReferenceStore.find((*i)->ReferenceId);
+ ConditionReferenceContainer::const_iterator ref = ConditionReferenceStore.find(condition->ReferenceId);
if (ref != ConditionReferenceStore.end())
{
- if (!IsObjectMeetToConditionList(sourceInfo, (*ref).second))
- ElseGroupStore[(*i)->ElseGroup] = false;
+ if (!IsObjectMeetToConditionList(sourceInfo, ref->second))
+ elseGroupStore[condition->ElseGroup] = false;
}
else
{
TC_LOG_DEBUG("condition", "ConditionMgr::IsPlayerMeetToConditionList %s Reference template -%u not found",
- (*i)->ToString().c_str(), (*i)->ReferenceId); // checked at loading, should never happen
+ condition->ToString().c_str(), condition->ReferenceId); // checked at loading, should never happen
}
}
else //handle normal condition
{
- if (!(*i)->Meets(sourceInfo))
- ElseGroupStore[(*i)->ElseGroup] = false;
+ if (!condition->Meets(sourceInfo))
+ elseGroupStore[condition->ElseGroup] = false;
}
}
}
- for (std::map<uint32, bool>::const_iterator i = ElseGroupStore.begin(); i != ElseGroupStore.end(); ++i)
+ for (std::map<uint32, bool>::const_iterator i = elseGroupStore.begin(); i != elseGroupStore.end(); ++i)
if (i->second)
return true;
return false;
}
-bool ConditionMgr::IsObjectMeetToConditions(WorldObject* object, ConditionList const& conditions)
+bool ConditionMgr::IsObjectMeetToConditions(WorldObject* object, ConditionContainer const& conditions) const
{
ConditionSourceInfo srcInfo = ConditionSourceInfo(object);
return IsObjectMeetToConditions(srcInfo, conditions);
}
-bool ConditionMgr::IsObjectMeetToConditions(WorldObject* object1, WorldObject* object2, ConditionList const& conditions)
+bool ConditionMgr::IsObjectMeetToConditions(WorldObject* object1, WorldObject* object2, ConditionContainer const& conditions) const
{
ConditionSourceInfo srcInfo = ConditionSourceInfo(object1, object2);
return IsObjectMeetToConditions(srcInfo, conditions);
}
-bool ConditionMgr::IsObjectMeetToConditions(ConditionSourceInfo& sourceInfo, ConditionList const& conditions)
+bool ConditionMgr::IsObjectMeetToConditions(ConditionSourceInfo& sourceInfo, ConditionContainer const& conditions) const
{
if (conditions.empty())
return true;
@@ -808,87 +800,113 @@ bool ConditionMgr::CanHaveSourceIdSet(ConditionSourceType sourceType)
return (sourceType == CONDITION_SOURCE_TYPE_SMART_EVENT);
}
-ConditionList ConditionMgr::GetConditionsForNotGroupedEntry(ConditionSourceType sourceType, uint32 entry)
+bool ConditionMgr::IsObjectMeetingNotGroupedConditions(ConditionSourceType sourceType, uint32 entry, ConditionSourceInfo& sourceInfo) const
{
- ConditionList spellCond;
if (sourceType > CONDITION_SOURCE_TYPE_NONE && sourceType < CONDITION_SOURCE_TYPE_MAX)
{
- ConditionContainer::const_iterator itr = ConditionStore.find(sourceType);
- if (itr != ConditionStore.end())
+ ConditionsByEntryMap::const_iterator i = ConditionStore[sourceType].find(entry);
+ if (i != ConditionStore[sourceType].end())
{
- ConditionTypeContainer::const_iterator i = (*itr).second.find(entry);
- if (i != (*itr).second.end())
- {
- spellCond = (*i).second;
- TC_LOG_DEBUG("condition", "GetConditionsForNotGroupedEntry: found conditions for type %u and entry %u", uint32(sourceType), entry);
- }
+ TC_LOG_DEBUG("condition", "GetConditionsForNotGroupedEntry: found conditions for type %u and entry %u", uint32(sourceType), entry);
+ return IsObjectMeetToConditions(sourceInfo, i->second);
+ }
+ }
+
+ return true;
+}
+
+bool ConditionMgr::IsObjectMeetingNotGroupedConditions(ConditionSourceType sourceType, uint32 entry, WorldObject* target0, WorldObject* target1 /*= nullptr*/, WorldObject* target2 /*= nullptr*/) const
+{
+ ConditionSourceInfo conditionSource(target0, target1, target2);
+ return IsObjectMeetingNotGroupedConditions(sourceType, entry, conditionSource);
+}
+
+bool ConditionMgr::HasConditionsForNotGroupedEntry(ConditionSourceType sourceType, uint32 entry) const
+{
+ if (sourceType > CONDITION_SOURCE_TYPE_NONE && sourceType < CONDITION_SOURCE_TYPE_MAX)
+ if (ConditionStore[sourceType].find(entry) != ConditionStore[sourceType].end())
+ return true;
+
+ return false;
+}
+
+bool ConditionMgr::IsObjectMeetingSpellClickConditions(uint32 creatureId, uint32 spellId, WorldObject* clicker, WorldObject* target) const
+{
+ ConditionEntriesByCreatureIdMap::const_iterator itr = SpellClickEventConditionStore.find(creatureId);
+ if (itr != SpellClickEventConditionStore.end())
+ {
+ ConditionsByEntryMap::const_iterator i = itr->second.find(spellId);
+ if (i != itr->second.end())
+ {
+ TC_LOG_DEBUG("condition", "GetConditionsForSpellClickEvent: found conditions for SpellClickEvent entry %u spell %u", creatureId, spellId);
+ ConditionSourceInfo sourceInfo(clicker, target);
+ return IsObjectMeetToConditions(sourceInfo, i->second);
}
}
- return spellCond;
+ return true;
}
-ConditionList ConditionMgr::GetConditionsForSpellClickEvent(uint32 creatureId, uint32 spellId)
+ConditionContainer const* ConditionMgr::GetConditionsForSpellClickEvent(uint32 creatureId, uint32 spellId) const
{
- ConditionList cond;
- CreatureSpellConditionContainer::const_iterator itr = SpellClickEventConditionStore.find(creatureId);
+ ConditionEntriesByCreatureIdMap::const_iterator itr = SpellClickEventConditionStore.find(creatureId);
if (itr != SpellClickEventConditionStore.end())
{
- ConditionTypeContainer::const_iterator i = (*itr).second.find(spellId);
- if (i != (*itr).second.end())
+ ConditionsByEntryMap::const_iterator i = itr->second.find(spellId);
+ if (i != itr->second.end())
{
- cond = (*i).second;
TC_LOG_DEBUG("condition", "GetConditionsForSpellClickEvent: found conditions for SpellClickEvent entry %u spell %u", creatureId, spellId);
+ return &i->second;
}
}
- return cond;
+ return nullptr;
}
-ConditionList ConditionMgr::GetConditionsForVehicleSpell(uint32 creatureId, uint32 spellId)
+bool ConditionMgr::IsObjectMeetingVehicleSpellConditions(uint32 creatureId, uint32 spellId, Player* player, Unit* vehicle) const
{
- ConditionList cond;
- CreatureSpellConditionContainer::const_iterator itr = VehicleSpellConditionStore.find(creatureId);
+ ConditionEntriesByCreatureIdMap::const_iterator itr = VehicleSpellConditionStore.find(creatureId);
if (itr != VehicleSpellConditionStore.end())
{
- ConditionTypeContainer::const_iterator i = (*itr).second.find(spellId);
- if (i != (*itr).second.end())
+ ConditionsByEntryMap::const_iterator i = itr->second.find(spellId);
+ if (i != itr->second.end())
{
- cond = (*i).second;
TC_LOG_DEBUG("condition", "GetConditionsForVehicleSpell: found conditions for Vehicle entry %u spell %u", creatureId, spellId);
+ ConditionSourceInfo sourceInfo(player, vehicle);
+ return IsObjectMeetToConditions(sourceInfo, i->second);
}
}
- return cond;
+ return true;
}
-ConditionList ConditionMgr::GetConditionsForSmartEvent(int32 entryOrGuid, uint32 eventId, uint32 sourceType)
+bool ConditionMgr::IsObjectMeetingSmartEventConditions(int32 entryOrGuid, uint32 eventId, uint32 sourceType, Unit* unit, WorldObject* baseObject) const
{
- ConditionList cond;
SmartEventConditionContainer::const_iterator itr = SmartEventConditionStore.find(std::make_pair(entryOrGuid, sourceType));
if (itr != SmartEventConditionStore.end())
{
- ConditionTypeContainer::const_iterator i = (*itr).second.find(eventId + 1);
- if (i != (*itr).second.end())
+ ConditionsByEntryMap::const_iterator i = itr->second.find(eventId + 1);
+ if (i != itr->second.end())
{
- cond = (*i).second;
TC_LOG_DEBUG("condition", "GetConditionsForSmartEvent: found conditions for Smart Event entry or guid %d eventId %u", entryOrGuid, eventId);
+ ConditionSourceInfo sourceInfo(unit, baseObject);
+ return IsObjectMeetToConditions(sourceInfo, i->second);
}
}
- return cond;
+ return true;
}
-ConditionList ConditionMgr::GetConditionsForNpcVendorEvent(uint32 creatureId, uint32 itemId)
+bool ConditionMgr::IsObjectMeetingVendorItemConditions(uint32 creatureId, uint32 itemId, Player* player, Creature* vendor) const
{
- ConditionList cond;
- NpcVendorConditionContainer::const_iterator itr = NpcVendorConditionContainerStore.find(creatureId);
+ ConditionEntriesByCreatureIdMap::const_iterator itr = NpcVendorConditionContainerStore.find(creatureId);
if (itr != NpcVendorConditionContainerStore.end())
{
- ConditionTypeContainer::const_iterator i = (*itr).second.find(itemId);
+ ConditionsByEntryMap::const_iterator i = (*itr).second.find(itemId);
if (i != (*itr).second.end())
{
- cond = (*i).second;
TC_LOG_DEBUG("condition", "GetConditionsForNpcVendorEvent: found conditions for creature entry %u item %u", creatureId, itemId);
+ ConditionSourceInfo sourceInfo(player, vendor);
+ return IsObjectMeetToConditions(sourceInfo, i->second);
}
}
- return cond;
+ return true;
}
void ConditionMgr::LoadConditions(bool isReload)
@@ -951,7 +969,7 @@ void ConditionMgr::LoadConditions(bool isReload)
cond->NegativeCondition = fields[10].GetBool();
cond->ErrorType = fields[11].GetUInt32();
cond->ErrorTextId = fields[12].GetUInt32();
- cond->ScriptId = sObjectMgr->GetScriptId(fields[13].GetCString());
+ cond->ScriptId = sObjectMgr->GetScriptId(fields[13].GetString());
if (iConditionTypeOrReference >= 0)
cond->ConditionType = ConditionTypes(iConditionTypeOrReference);
@@ -996,14 +1014,8 @@ void ConditionMgr::LoadConditions(bool isReload)
if (iSourceTypeOrReferenceId < 0)//it is a reference template
{
- uint32 uRefId = abs(iSourceTypeOrReferenceId);
- if (ConditionReferenceStore.find(uRefId) == ConditionReferenceStore.end())//make sure we have a list for our conditions, based on reference id
- {
- ConditionList mCondList;
- ConditionReferenceStore[uRefId] = mCondList;
- }
- ConditionReferenceStore[uRefId].push_back(cond);//add to reference storage
- count++;
+ ConditionReferenceStore[std::abs(iSourceTypeOrReferenceId)].push_back(cond);//add to reference storage
+ ++count;
continue;
}//end of reference templates
@@ -1139,20 +1151,6 @@ void ConditionMgr::LoadConditions(bool isReload)
}
//handle not grouped conditions
- //make sure we have a storage list for our SourceType
- if (ConditionStore.find(cond->SourceType) == ConditionStore.end())
- {
- ConditionTypeContainer mTypeMap;
- ConditionStore[cond->SourceType] = mTypeMap;//add new empty list for SourceType
- }
-
- //make sure we have a condition list for our SourceType's entry
- if (ConditionStore[cond->SourceType].find(cond->SourceEntry) == ConditionStore[cond->SourceType].end())
- {
- ConditionList mCondList;
- ConditionStore[cond->SourceType][cond->SourceEntry] = mCondList;
- }
-
//add new Condition to storage based on Type/Entry
ConditionStore[cond->SourceType][cond->SourceEntry].push_back(cond);
++count;
@@ -1162,7 +1160,7 @@ void ConditionMgr::LoadConditions(bool isReload)
TC_LOG_INFO("server.loading", ">> Loaded %u conditions in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
-bool ConditionMgr::addToLootTemplate(Condition* cond, LootTemplate* loot)
+bool ConditionMgr::addToLootTemplate(Condition* cond, LootTemplate* loot) const
{
if (!loot)
{
@@ -1177,7 +1175,7 @@ bool ConditionMgr::addToLootTemplate(Condition* cond, LootTemplate* loot)
return false;
}
-bool ConditionMgr::addToGossipMenus(Condition* cond)
+bool ConditionMgr::addToGossipMenus(Condition* cond) const
{
GossipMenusMapBoundsNonConst pMenuBounds = sObjectMgr->GetGossipMenusMapBoundsNonConst(cond->SourceGroup);
@@ -1197,7 +1195,7 @@ bool ConditionMgr::addToGossipMenus(Condition* cond)
return false;
}
-bool ConditionMgr::addToGossipMenuItems(Condition* cond)
+bool ConditionMgr::addToGossipMenuItems(Condition* cond) const
{
GossipMenuItemsMapBoundsNonConst pMenuItemBounds = sObjectMgr->GetGossipMenuItemsMapBoundsNonConst(cond->SourceGroup);
if (pMenuItemBounds.first != pMenuItemBounds.second)
@@ -1216,7 +1214,7 @@ bool ConditionMgr::addToGossipMenuItems(Condition* cond)
return false;
}
-bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond)
+bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond) const
{
uint32 conditionEffMask = cond->SourceGroup;
SpellInfo* spellInfo = const_cast<SpellInfo*>(sSpellMgr->EnsureSpellInfo(cond->SourceEntry));
@@ -1237,9 +1235,9 @@ bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond)
continue;
// build new shared mask with found effect
- uint32 sharedMask = (1 << i);
- ConditionList* cmp = spellInfo->Effects[i].ImplicitTargetConditions;
- for (uint8 effIndex = i+1; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
+ uint32 sharedMask = 1 << i;
+ ConditionContainer* cmp = spellInfo->Effects[i].ImplicitTargetConditions;
+ for (uint8 effIndex = i + 1; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
{
if (spellInfo->Effects[effIndex].ImplicitTargetConditions == cmp)
sharedMask |= 1 << effIndex;
@@ -1261,7 +1259,7 @@ bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond)
return false;
// get shared data
- ConditionList* sharedList = spellInfo->Effects[firstEffIndex].ImplicitTargetConditions;
+ ConditionContainer* sharedList = spellInfo->Effects[firstEffIndex].ImplicitTargetConditions;
// there's already data entry for that sharedMask
if (sharedList)
@@ -1278,7 +1276,7 @@ bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond)
else
{
// add new list, create new shared mask
- sharedList = new ConditionList();
+ sharedList = new ConditionContainer();
bool assigned = false;
for (uint8 i = firstEffIndex; i < MAX_SPELL_EFFECTS; ++i)
{
@@ -1299,7 +1297,7 @@ bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond)
return true;
}
-bool ConditionMgr::isSourceTypeValid(Condition* cond)
+bool ConditionMgr::isSourceTypeValid(Condition* cond) const
{
if (cond->SourceType == CONDITION_SOURCE_TYPE_NONE || cond->SourceType >= CONDITION_SOURCE_TYPE_MAX)
{
@@ -1535,6 +1533,9 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond)
if (!((1 << i) & cond->SourceGroup))
continue;
+ if (spellInfo->Effects[i].ChainTarget > 0)
+ continue;
+
switch (spellInfo->Effects[i].TargetA.GetSelectionCategory())
{
case TARGET_SELECT_CATEGORY_NEARBY:
@@ -1555,7 +1556,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond)
break;
}
- TC_LOG_ERROR("sql.sql", "SourceEntry %u SourceGroup %u in `condition` table - spell %u does not have implicit targets of types: _AREA_, _CONE_, _NEARBY_ for effect %u, SourceGroup needs correction, ignoring.", cond->SourceEntry, origGroup, cond->SourceEntry, uint32(i));
+ TC_LOG_ERROR("sql.sql", "SourceEntry %u SourceGroup %u in `condition` table - spell %u does not have implicit targets of types: _AREA_, _CONE_, _NEARBY_, __CHAIN__ for effect %u, SourceGroup needs correction, ignoring.", cond->SourceEntry, origGroup, cond->SourceEntry, uint32(i));
cond->SourceGroup &= ~(1 << i);
}
// all effects were removed, no need to add the condition at all
@@ -1648,7 +1649,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond)
return true;
}
-bool ConditionMgr::isConditionTypeValid(Condition* cond)
+bool ConditionMgr::isConditionTypeValid(Condition* cond) const
{
if (cond->ConditionType == CONDITION_NONE || cond->ConditionType >= CONDITION_MAX)
{
@@ -2111,81 +2112,50 @@ void ConditionMgr::LogUselessConditionValue(Condition* cond, uint8 index, uint32
void ConditionMgr::Clean()
{
for (ConditionReferenceContainer::iterator itr = ConditionReferenceStore.begin(); itr != ConditionReferenceStore.end(); ++itr)
- {
- for (ConditionList::const_iterator it = itr->second.begin(); it != itr->second.end(); ++it)
+ for (ConditionContainer::const_iterator it = itr->second.begin(); it != itr->second.end(); ++it)
delete *it;
- itr->second.clear();
- }
ConditionReferenceStore.clear();
- for (ConditionContainer::iterator itr = ConditionStore.begin(); itr != ConditionStore.end(); ++itr)
+ for (uint32 i = 0; i < CONDITION_SOURCE_TYPE_MAX; ++i)
{
- for (ConditionTypeContainer::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
- {
- for (ConditionList::const_iterator i = it->second.begin(); i != it->second.end(); ++i)
- delete *i;
- it->second.clear();
- }
- itr->second.clear();
- }
+ for (ConditionsByEntryMap::iterator it = ConditionStore[i].begin(); it != ConditionStore[i].end(); ++it)
+ for (ConditionContainer::const_iterator itr = it->second.begin(); itr != it->second.end(); ++itr)
+ delete *itr;
- ConditionStore.clear();
+ ConditionStore[i].clear();
+ }
- for (CreatureSpellConditionContainer::iterator itr = VehicleSpellConditionStore.begin(); itr != VehicleSpellConditionStore.end(); ++itr)
- {
- for (ConditionTypeContainer::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
- {
- for (ConditionList::const_iterator i = it->second.begin(); i != it->second.end(); ++i)
+ for (ConditionEntriesByCreatureIdMap::iterator itr = VehicleSpellConditionStore.begin(); itr != VehicleSpellConditionStore.end(); ++itr)
+ for (ConditionsByEntryMap::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
+ for (ConditionContainer::const_iterator i = it->second.begin(); i != it->second.end(); ++i)
delete *i;
- it->second.clear();
- }
- itr->second.clear();
- }
VehicleSpellConditionStore.clear();
for (SmartEventConditionContainer::iterator itr = SmartEventConditionStore.begin(); itr != SmartEventConditionStore.end(); ++itr)
- {
- for (ConditionTypeContainer::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
- {
- for (ConditionList::const_iterator i = it->second.begin(); i != it->second.end(); ++i)
+ for (ConditionsByEntryMap::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
+ for (ConditionContainer::const_iterator i = it->second.begin(); i != it->second.end(); ++i)
delete *i;
- it->second.clear();
- }
- itr->second.clear();
- }
SmartEventConditionStore.clear();
- for (CreatureSpellConditionContainer::iterator itr = SpellClickEventConditionStore.begin(); itr != SpellClickEventConditionStore.end(); ++itr)
- {
- for (ConditionTypeContainer::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
- {
- for (ConditionList::const_iterator i = it->second.begin(); i != it->second.end(); ++i)
+ for (ConditionEntriesByCreatureIdMap::iterator itr = SpellClickEventConditionStore.begin(); itr != SpellClickEventConditionStore.end(); ++itr)
+ for (ConditionsByEntryMap::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
+ for (ConditionContainer::const_iterator i = it->second.begin(); i != it->second.end(); ++i)
delete *i;
- it->second.clear();
- }
- itr->second.clear();
- }
SpellClickEventConditionStore.clear();
- for (NpcVendorConditionContainer::iterator itr = NpcVendorConditionContainerStore.begin(); itr != NpcVendorConditionContainerStore.end(); ++itr)
- {
- for (ConditionTypeContainer::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
- {
- for (ConditionList::const_iterator i = it->second.begin(); i != it->second.end(); ++i)
+ for (ConditionEntriesByCreatureIdMap::iterator itr = NpcVendorConditionContainerStore.begin(); itr != NpcVendorConditionContainerStore.end(); ++itr)
+ for (ConditionsByEntryMap::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
+ for (ConditionContainer::const_iterator i = it->second.begin(); i != it->second.end(); ++i)
delete *i;
- it->second.clear();
- }
- itr->second.clear();
- }
NpcVendorConditionContainerStore.clear();
// this is a BIG hack, feel free to fix it if you can figure out the ConditionMgr ;)
- for (std::list<Condition*>::const_iterator itr = AllocatedMemoryStore.begin(); itr != AllocatedMemoryStore.end(); ++itr)
+ for (std::vector<Condition*>::const_iterator itr = AllocatedMemoryStore.begin(); itr != AllocatedMemoryStore.end(); ++itr)
delete *itr;
AllocatedMemoryStore.clear();
diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h
index 27983782bdc..43454aba049 100644
--- a/src/server/game/Conditions/ConditionMgr.h
+++ b/src/server/game/Conditions/ConditionMgr.h
@@ -19,12 +19,9 @@
#ifndef TRINITY_CONDITIONMGR_H
#define TRINITY_CONDITIONMGR_H
-#include "Define.h"
-#include "Errors.h"
-#include <list>
-#include <map>
-#include <string>
+#include "Common.h"
+class Creature;
class Player;
class Unit;
class WorldObject;
@@ -62,7 +59,7 @@ enum ConditionTypes
CONDITION_PHASEMASK = 26, // phasemask 0 0 true if object is in phasemask
CONDITION_LEVEL = 27, // level ComparisonType 0 true if unit's level is equal to param1 (param2 can modify the statement)
CONDITION_QUEST_COMPLETE = 28, // quest_id 0 0 true if player has quest_id with all objectives complete, but not yet rewarded
- CONDITION_NEAR_CREATURE = 29, // creature entry distance 0 true if there is a creature of entry in range
+ CONDITION_NEAR_CREATURE = 29, // creature entry distance dead (0/1) true if there is a creature of entry in range
CONDITION_NEAR_GAMEOBJECT = 30, // gameobject entry distance 0 true if there is a gameobject of entry in range
CONDITION_OBJECT_ENTRY_GUID = 31, // TypeID entry guid true if object is type TypeID and the entry is 0 or matches entry of the object or matches guid of the object
CONDITION_TYPE_MASK = 32, // TypeMask 0 0 true if object is type object's TypeMask matches provided TypeMask
@@ -162,13 +159,13 @@ enum MaxConditionTargets
struct ConditionSourceInfo
{
WorldObject* mConditionTargets[MAX_CONDITION_TARGETS]; // an array of targets available for conditions
- Condition* mLastFailedCondition;
- ConditionSourceInfo(WorldObject* target0, WorldObject* target1 = NULL, WorldObject* target2 = NULL)
+ Condition const* mLastFailedCondition;
+ ConditionSourceInfo(WorldObject* target0, WorldObject* target1 = nullptr, WorldObject* target2 = nullptr)
{
mConditionTargets[0] = target0;
mConditionTargets[1] = target1;
mConditionTargets[2] = target2;
- mLastFailedCondition = NULL;
+ mLastFailedCondition = nullptr;
}
};
@@ -209,22 +206,20 @@ struct Condition
NegativeCondition = false;
}
- bool Meets(ConditionSourceInfo& sourceInfo);
- uint32 GetSearcherTypeMaskForCondition();
+ bool Meets(ConditionSourceInfo& sourceInfo) const;
+ uint32 GetSearcherTypeMaskForCondition() const;
bool isLoaded() const { return ConditionType > CONDITION_NONE || ReferenceId; }
- uint32 GetMaxAvailableConditionTargets();
+ uint32 GetMaxAvailableConditionTargets() const;
std::string ToString(bool ext = false) const; /// For logging purpose
};
-typedef std::list<Condition*> ConditionList;
-typedef std::map<uint32, ConditionList> ConditionTypeContainer;
-typedef std::map<ConditionSourceType, ConditionTypeContainer> ConditionContainer;
-typedef std::map<uint32, ConditionTypeContainer> CreatureSpellConditionContainer;
-typedef std::map<uint32, ConditionTypeContainer> NpcVendorConditionContainer;
-typedef std::map<std::pair<int32, uint32 /*SAI source_type*/>, ConditionTypeContainer> SmartEventConditionContainer;
-
-typedef std::map<uint32, ConditionList> ConditionReferenceContainer;//only used for references
+typedef std::vector<Condition*> ConditionContainer;
+typedef std::unordered_map<uint32 /*SourceEntry*/, ConditionContainer> ConditionsByEntryMap;
+typedef std::array<ConditionsByEntryMap, CONDITION_SOURCE_TYPE_MAX> ConditionEntriesByTypeArray;
+typedef std::unordered_map<uint32, ConditionsByEntryMap> ConditionEntriesByCreatureIdMap;
+typedef std::unordered_map<std::pair<int32, uint32 /*SAI source_type*/>, ConditionsByEntryMap> SmartEventConditionContainer;
+typedef std::unordered_map<uint32, ConditionContainer> ConditionReferenceContainer;//only used for references
class ConditionMgr
{
@@ -240,20 +235,22 @@ class ConditionMgr
}
void LoadConditions(bool isReload = false);
- bool isConditionTypeValid(Condition* cond);
- ConditionList GetConditionReferences(uint32 refId);
+ bool isConditionTypeValid(Condition* cond) const;
- uint32 GetSearcherTypeMaskForConditionList(ConditionList const& conditions);
- bool IsObjectMeetToConditions(WorldObject* object, ConditionList const& conditions);
- bool IsObjectMeetToConditions(WorldObject* object1, WorldObject* object2, ConditionList const& conditions);
- bool IsObjectMeetToConditions(ConditionSourceInfo& sourceInfo, ConditionList const& conditions);
+ uint32 GetSearcherTypeMaskForConditionList(ConditionContainer const& conditions) const;
+ bool IsObjectMeetToConditions(WorldObject* object, ConditionContainer const& conditions) const;
+ bool IsObjectMeetToConditions(WorldObject* object1, WorldObject* object2, ConditionContainer const& conditions) const;
+ bool IsObjectMeetToConditions(ConditionSourceInfo& sourceInfo, ConditionContainer const& conditions) const;
static bool CanHaveSourceGroupSet(ConditionSourceType sourceType);
static bool CanHaveSourceIdSet(ConditionSourceType sourceType);
- ConditionList GetConditionsForNotGroupedEntry(ConditionSourceType sourceType, uint32 entry);
- ConditionList GetConditionsForSpellClickEvent(uint32 creatureId, uint32 spellId);
- ConditionList GetConditionsForSmartEvent(int32 entryOrGuid, uint32 eventId, uint32 sourceType);
- ConditionList GetConditionsForVehicleSpell(uint32 creatureId, uint32 spellId);
- ConditionList GetConditionsForNpcVendorEvent(uint32 creatureId, uint32 itemId);
+ bool IsObjectMeetingNotGroupedConditions(ConditionSourceType sourceType, uint32 entry, ConditionSourceInfo& sourceInfo) const;
+ bool IsObjectMeetingNotGroupedConditions(ConditionSourceType sourceType, uint32 entry, WorldObject* target0, WorldObject* target1 = nullptr, WorldObject* target2 = nullptr) const;
+ bool HasConditionsForNotGroupedEntry(ConditionSourceType sourceType, uint32 entry) const;
+ bool IsObjectMeetingSpellClickConditions(uint32 creatureId, uint32 spellId, WorldObject* clicker, WorldObject* target) const;
+ ConditionContainer const* GetConditionsForSpellClickEvent(uint32 creatureId, uint32 spellId) const;
+ bool IsObjectMeetingVehicleSpellConditions(uint32 creatureId, uint32 spellId, Player* player, Unit* vehicle) const;
+ bool IsObjectMeetingSmartEventConditions(int32 entryOrGuid, uint32 eventId, uint32 sourceType, Unit* unit, WorldObject* baseObject) const;
+ bool IsObjectMeetingVendorItemConditions(uint32 creatureId, uint32 itemId, Player* player, Creature* vendor) const;
struct ConditionTypeInfo
{
@@ -262,28 +259,28 @@ class ConditionMgr
bool HasConditionValue2;
bool HasConditionValue3;
};
- static char const* StaticSourceTypeData[CONDITION_SOURCE_TYPE_MAX];
+ static char const* const StaticSourceTypeData[CONDITION_SOURCE_TYPE_MAX];
static ConditionTypeInfo const StaticConditionTypeData[CONDITION_MAX];
private:
- bool isSourceTypeValid(Condition* cond);
- bool addToLootTemplate(Condition* cond, LootTemplate* loot);
- bool addToGossipMenus(Condition* cond);
- bool addToGossipMenuItems(Condition* cond);
- bool addToSpellImplicitTargetConditions(Condition* cond);
- bool IsObjectMeetToConditionList(ConditionSourceInfo& sourceInfo, ConditionList const& conditions);
+ bool isSourceTypeValid(Condition* cond) const;
+ bool addToLootTemplate(Condition* cond, LootTemplate* loot) const;
+ bool addToGossipMenus(Condition* cond) const;
+ bool addToGossipMenuItems(Condition* cond) const;
+ bool addToSpellImplicitTargetConditions(Condition* cond) const;
+ bool IsObjectMeetToConditionList(ConditionSourceInfo& sourceInfo, ConditionContainer const& conditions) const;
static void LogUselessConditionValue(Condition* cond, uint8 index, uint32 value);
void Clean(); // free up resources
- std::list<Condition*> AllocatedMemoryStore; // some garbage collection :)
-
- ConditionContainer ConditionStore;
- ConditionReferenceContainer ConditionReferenceStore;
- CreatureSpellConditionContainer VehicleSpellConditionStore;
- CreatureSpellConditionContainer SpellClickEventConditionStore;
- NpcVendorConditionContainer NpcVendorConditionContainerStore;
- SmartEventConditionContainer SmartEventConditionStore;
+ std::vector<Condition*> AllocatedMemoryStore; // some garbage collection :)
+
+ ConditionEntriesByTypeArray ConditionStore;
+ ConditionReferenceContainer ConditionReferenceStore;
+ ConditionEntriesByCreatureIdMap VehicleSpellConditionStore;
+ ConditionEntriesByCreatureIdMap SpellClickEventConditionStore;
+ ConditionEntriesByCreatureIdMap NpcVendorConditionContainerStore;
+ SmartEventConditionContainer SmartEventConditionStore;
};
#define sConditionMgr ConditionMgr::instance()
diff --git a/src/server/game/Conditions/DisableMgr.cpp b/src/server/game/Conditions/DisableMgr.cpp
index fac8484e77f..6f77d2af66b 100644
--- a/src/server/game/Conditions/DisableMgr.cpp
+++ b/src/server/game/Conditions/DisableMgr.cpp
@@ -309,7 +309,7 @@ bool IsDisabledFor(DisableType type, uint32 entry, Unit const* unit, uint8 flags
if (unit)
{
if ((spellFlags & SPELL_DISABLE_PLAYER && unit->GetTypeId() == TYPEID_PLAYER) ||
- (unit->GetTypeId() == TYPEID_UNIT && ((unit->ToCreature()->IsPet() && spellFlags & SPELL_DISABLE_PET) || spellFlags & SPELL_DISABLE_CREATURE)))
+ (unit->GetTypeId() == TYPEID_UNIT && ((unit->IsPet() && spellFlags & SPELL_DISABLE_PET) || spellFlags & SPELL_DISABLE_CREATURE)))
{
if (spellFlags & SPELL_DISABLE_MAP)
{
diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp
index 5cd9b363ae0..806d9d46763 100644
--- a/src/server/game/DataStores/DBCStores.cpp
+++ b/src/server/game/DataStores/DBCStores.cpp
@@ -25,6 +25,7 @@
#include "Timer.h"
#include "ObjectDefines.h"
+#include <boost/regex.hpp>
#include <map>
typedef std::map<uint16, uint32> AreaFlagByAreaID;
@@ -140,6 +141,12 @@ MapDifficultyMap sMapDifficultyMap;
DBCStorage <MovieEntry> sMovieStore(MovieEntryfmt);
+DBCStorage<NamesProfanityEntry> sNamesProfanityStore(NamesProfanityEntryfmt);
+DBCStorage<NamesReservedEntry> sNamesReservedStore(NamesReservedEntryfmt);
+typedef std::array<std::vector<boost::regex>, TOTAL_LOCALES> NameValidationRegexContainer;
+NameValidationRegexContainer NamesProfaneValidators;
+NameValidationRegexContainer NamesReservedValidators;
+
DBCStorage <OverrideSpellDataEntry> sOverrideSpellDataStore(OverrideSpellDatafmt);
DBCStorage <PowerDisplayEntry> sPowerDisplayStore(PowerDisplayfmt);
@@ -163,7 +170,6 @@ DBCStorage <SoundEntriesEntry> sSoundEntriesStore(SoundEntriesfmt);
DBCStorage <SpellItemEnchantmentEntry> sSpellItemEnchantmentStore(SpellItemEnchantmentfmt);
DBCStorage <SpellItemEnchantmentConditionEntry> sSpellItemEnchantmentConditionStore(SpellItemEnchantmentConditionfmt);
DBCStorage <SpellEntry> sSpellStore(SpellEntryfmt);
-SpellCategoryStore sSpellsByCategoryStore;
PetFamilySpellsStore sPetFamilySpellsStore;
DBCStorage <SpellCastTimesEntry> sSpellCastTimesStore(SpellCastTimefmt);
@@ -402,6 +408,37 @@ void LoadDBCStores(const std::string& dataPath)
LoadDBC(availableDbcLocales, bad_dbc_files, sMovieStore, dbcPath, "Movie.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sNamesProfanityStore, dbcPath, "NamesProfanity.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sNamesReservedStore, dbcPath, "NamesReserved.dbc");
+ for (uint32 i = 0; i < sNamesProfanityStore.GetNumRows(); ++i)
+ {
+ NamesProfanityEntry const* namesProfanity = sNamesProfanityStore.LookupEntry(i);
+ if (!namesProfanity)
+ continue;
+
+ ASSERT(namesProfanity->Language < TOTAL_LOCALES || namesProfanity->Language == -1);
+ if (namesProfanity->Language != -1)
+ NamesProfaneValidators[namesProfanity->Language].emplace_back(namesProfanity->Name, boost::regex::perl | boost::regex::icase | boost::regex::optimize);
+ else
+ for (uint32 i = 0; i < TOTAL_LOCALES; ++i)
+ NamesProfaneValidators[i].emplace_back(namesProfanity->Name, boost::regex::perl | boost::regex::icase | boost::regex::optimize);
+ }
+
+ for (uint32 i = 0; i < sNamesReservedStore.GetNumRows(); ++i)
+ {
+ NamesReservedEntry const* namesReserved = sNamesReservedStore.LookupEntry(i);
+ if (!namesReserved)
+ continue;
+
+ ASSERT(namesReserved->Language < TOTAL_LOCALES || namesReserved->Language == -1);
+ if (namesReserved->Language != -1)
+ NamesReservedValidators[namesReserved->Language].emplace_back(namesReserved->Name, boost::regex::perl | boost::regex::icase | boost::regex::optimize);
+ else
+ for (uint32 i = 0; i < TOTAL_LOCALES; ++i)
+ NamesReservedValidators[i].emplace_back(namesReserved->Name, boost::regex::perl | boost::regex::icase | boost::regex::optimize);
+ }
+
+
LoadDBC(availableDbcLocales, bad_dbc_files, sOverrideSpellDataStore, dbcPath, "OverrideSpellData.dbc");
LoadDBC(availableDbcLocales, bad_dbc_files, sPowerDisplayStore, dbcPath, "PowerDisplay.dbc");
@@ -430,12 +467,6 @@ void LoadDBCStores(const std::string& dataPath)
LoadDBC(availableDbcLocales, bad_dbc_files, sSkillTiersStore, dbcPath, "SkillTiers.dbc");
LoadDBC(availableDbcLocales, bad_dbc_files, sSoundEntriesStore, dbcPath, "SoundEntries.dbc");
LoadDBC(availableDbcLocales, bad_dbc_files, sSpellStore, dbcPath, "Spell.dbc", &CustomSpellEntryfmt, &CustomSpellEntryIndex);
- for (uint32 i = 1; i < sSpellStore.GetNumRows(); ++i)
- {
- SpellEntry const* spell = sSpellStore.LookupEntry(i);
- if (spell && spell->Category)
- sSpellsByCategoryStore[spell->Category].insert(i);
- }
for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
{
@@ -570,7 +601,7 @@ void LoadDBCStores(const std::string& dataPath)
// fill data
for (uint32 i = 1; i < sTaxiPathNodeStore.GetNumRows(); ++i)
if (TaxiPathNodeEntry const* entry = sTaxiPathNodeStore.LookupEntry(i))
- sTaxiPathNodesByPath[entry->PathID].set(entry->NodeIndex, entry);
+ sTaxiPathNodesByPath[entry->PathID][entry->NodeIndex] = entry;
// Initialize global taxinodes mask
// include existed nodes that have at least single not spell base (scripted) path
@@ -600,7 +631,7 @@ void LoadDBCStores(const std::string& dataPath)
for (TaxiPathSetForSource::const_iterator dest_i = src_i->second.begin(); dest_i != src_i->second.end(); ++dest_i)
{
// not spell path
- if (spellPaths.find(dest_i->second.ID) == spellPaths.end())
+ if (dest_i->second.price || spellPaths.find(dest_i->second.ID) == spellPaths.end())
{
ok = true;
break;
@@ -1012,3 +1043,20 @@ SkillRaceClassInfoEntry const* GetSkillRaceClassInfo(uint32 skill, uint8 race, u
return NULL;
}
+
+ResponseCodes ValidateName(std::string const& name, LocaleConstant locale)
+{
+ if (locale >= TOTAL_LOCALES)
+ return RESPONSE_FAILURE;
+
+ for (boost::regex const& regex : NamesProfaneValidators[locale])
+ if (boost::regex_search(name, regex))
+ return CHAR_NAME_PROFANE;
+
+ // regexes at TOTAL_LOCALES are loaded from NamesReserved which is not locale specific
+ for (boost::regex const& regex : NamesReservedValidators[locale])
+ if (boost::regex_search(name, regex))
+ return CHAR_NAME_RESERVED;
+
+ return CHAR_NAME_SUCCESS;
+}
diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h
index d955e9581ab..2def7901244 100644
--- a/src/server/game/DataStores/DBCStores.h
+++ b/src/server/game/DataStores/DBCStores.h
@@ -22,6 +22,7 @@
#include "Common.h"
#include "DBCStore.h"
#include "DBCStructure.h"
+#include "SharedDefines.h"
#include <list>
@@ -79,6 +80,8 @@ typedef std::unordered_multimap<uint32, SkillRaceClassInfoEntry const*> SkillRac
typedef std::pair<SkillRaceClassInfoMap::iterator, SkillRaceClassInfoMap::iterator> SkillRaceClassInfoBounds;
SkillRaceClassInfoEntry const* GetSkillRaceClassInfo(uint32 skill, uint8 race, uint8 class_);
+ResponseCodes ValidateName(std::string const& name, LocaleConstant locale);
+
extern DBCStorage <AchievementEntry> sAchievementStore;
extern DBCStorage <AchievementCriteriaEntry> sAchievementCriteriaStore;
extern DBCStorage <AreaTableEntry> sAreaStore;// recommend access using functions
@@ -165,7 +168,6 @@ extern DBCStorage <SpellDurationEntry> sSpellDurationStore;
extern DBCStorage <SpellFocusObjectEntry> sSpellFocusObjectStore;
extern DBCStorage <SpellItemEnchantmentEntry> sSpellItemEnchantmentStore;
extern DBCStorage <SpellItemEnchantmentConditionEntry> sSpellItemEnchantmentConditionStore;
-extern SpellCategoryStore sSpellsByCategoryStore;
extern PetFamilySpellsStore sPetFamilySpellsStore;
extern DBCStorage <SpellRadiusEntry> sSpellRadiusStore;
extern DBCStorage <SpellRangeEntry> sSpellRangeStore;
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index 5ccd5d2b7e5..a419864a194 100644
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -21,14 +21,8 @@
#include "Common.h"
#include "DBCEnums.h"
-#include "Define.h"
-#include "Path.h"
#include "Util.h"
-#include <map>
-#include <set>
-#include <vector>
-
// Structures using to access raw DBC data and required packing to portability
#pragma pack(push, 1)
@@ -815,7 +809,7 @@ struct CreatureModelDataEntry
{
uint32 Id;
uint32 Flags;
- //char* ModelPath[16]
+ char* ModelPath;
//uint32 Unk1;
float Scale; // Used in calculation of unit collision data
//int32 Unk2
@@ -1410,6 +1404,20 @@ struct MovieEntry
//uint32 unk2; // 2 always 100
};
+struct NamesProfanityEntry
+{
+ //uint32 ID; // 0
+ char const* Name; // 1
+ int32 Language; // 2
+};
+
+struct NamesReservedEntry
+{
+ //uint32 ID; // 0
+ char const* Name; // 1
+ int32 Language; // 2
+};
+
#define MAX_OVERRIDE_SPELL 10
struct OverrideSpellDataEntry
@@ -1643,10 +1651,8 @@ struct SpellEntry
uint32 AttributesEx5; // 9 m_attributesExE
uint32 AttributesEx6; // 10 m_attributesExF
uint32 AttributesEx7; // 11 m_attributesExG
- uint32 Stances; // 12 m_shapeshiftMask
- // uint32 unk_320_2; // 13 3.2.0
- uint32 StancesNot; // 14 m_shapeshiftExclude
- // uint32 unk_320_3; // 15 3.2.0
+ uint32 Stances[2]; // 12 m_shapeshiftMask
+ uint32 StancesNot[2]; // 14 m_shapeshiftExclude
uint32 Targets; // 16 m_targets
uint32 TargetCreatureType; // 17 m_targetCreatureType
uint32 RequiresSpellFocus; // 18 m_requiresSpellFocus
@@ -1742,8 +1748,6 @@ struct SpellEntry
//uint32 SpellDifficultyId; // 233 3.3.0
};
-typedef std::set<uint32> SpellCategorySet;
-typedef std::map<uint32, SpellCategorySet > SpellCategoryStore;
typedef std::set<uint32> PetFamilySpellsSet;
typedef std::map<uint32, PetFamilySpellsSet > PetFamilySpellsStore;
@@ -2072,7 +2076,12 @@ struct VehicleSeatEntry
uint32 m_flagsB; // 45
// 46-57 added in 3.1, floats mostly
- bool CanEnterOrExit() const { return (m_flags & VEHICLE_SEAT_FLAG_CAN_ENTER_OR_EXIT) != 0; }
+ bool CanEnterOrExit() const
+ {
+ return ((m_flags & VEHICLE_SEAT_FLAG_CAN_ENTER_OR_EXIT) != 0 ||
+ //If it has anmation for enter/ride, means it can be entered/exited by logic
+ (m_flags & (VEHICLE_SEAT_FLAG_HAS_LOWER_ANIM_FOR_ENTER | VEHICLE_SEAT_FLAG_HAS_LOWER_ANIM_FOR_RIDE)) != 0);
+ }
bool CanSwitchFromSeat() const { return (m_flags & VEHICLE_SEAT_FLAG_CAN_SWITCH) != 0; }
bool IsUsableByOverride() const { return (m_flags & (VEHICLE_SEAT_FLAG_UNCONTROLLED | VEHICLE_SEAT_FLAG_UNK18)
|| (m_flagsB & (VEHICLE_SEAT_FLAG_B_USABLE_FORCED | VEHICLE_SEAT_FLAG_B_USABLE_FORCED_2 |
@@ -2206,15 +2215,7 @@ struct TaxiPathBySourceAndDestination
typedef std::map<uint32, TaxiPathBySourceAndDestination> TaxiPathSetForSource;
typedef std::map<uint32, TaxiPathSetForSource> TaxiPathSetBySource;
-struct TaxiPathNodePtr
-{
- TaxiPathNodePtr() : i_ptr(NULL) { }
- TaxiPathNodePtr(TaxiPathNodeEntry const* ptr) : i_ptr(ptr) { }
- TaxiPathNodeEntry const* i_ptr;
- operator TaxiPathNodeEntry const& () const { return *i_ptr; }
-};
-
-typedef Path<TaxiPathNodePtr, TaxiPathNodeEntry const> TaxiPathNodeList;
+typedef std::vector<TaxiPathNodeEntry const*> TaxiPathNodeList;
typedef std::vector<TaxiPathNodeList> TaxiPathNodesByPath;
#define TaxiMaskSize 14
diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h
index 5c24e6f938a..e81db5924f6 100644
--- a/src/server/game/DataStores/DBCfmt.h
+++ b/src/server/game/DataStores/DBCfmt.h
@@ -42,7 +42,7 @@ char const CinematicSequencesEntryfmt[] = "nxxxxxxxxx";
char const CreatureDisplayInfofmt[] = "nixifxxxxxxxxxxx";
char const CreatureDisplayInfoExtrafmt[] = "diixxxxxxxxxxxxxxxxxx";
char const CreatureFamilyfmt[] = "nfifiiiiixssssssssssssssssxx";
-char const CreatureModelDatafmt[] = "nixxfxxxxxxxxxxffxxxxxxxxxxx";
+char const CreatureModelDatafmt[] = "nisxfxxxxxxxxxxffxxxxxxxxxxx";
char const CreatureSpellDatafmt[] = "niiiixxxx";
char const CreatureTypefmt[] = "nxxxxxxxxxxxxxxxxxx";
char const CurrencyTypesfmt[] = "xnxi";
@@ -88,6 +88,8 @@ char const MailTemplateEntryfmt[] = "nxxxxxxxxxxxxxxxxxssssssssssssssssx";
char const MapEntryfmt[] = "nxiixssssssssssssssssxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixiffxiii";
char const MapDifficultyEntryfmt[] = "diisxxxxxxxxxxxxxxxxiix";
char const MovieEntryfmt[] = "nxx";
+char const NamesProfanityEntryfmt[] = "dsi";
+char const NamesReservedEntryfmt[] = "dsi";
char const OverrideSpellDatafmt[] = "niiiiiiiiiix";
char const QuestFactionRewardfmt[] = "niiiiiiiiii";
char const QuestSortEntryfmt[] = "nxxxxxxxxxxxxxxxxx";
@@ -108,7 +110,7 @@ char const SpellDifficultyfmt[] = "niiii";
const std::string CustomSpellDifficultyfmt = "ppppp";
const std::string CustomSpellDifficultyIndex = "id";
char const SpellDurationfmt[] = "niii";
-char const SpellEntryfmt[] = "niiiiiiiiiiiixixiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiiiiiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiixxfffxx";
+char const SpellEntryfmt[] = "niiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiiiiiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiixxfffxx";
const std::string CustomSpellEntryfmt = "papppppppppppapapaaaaaaaaaaapaaapapppppppaaaaapaapaaaaaaaaaaaaaaaaaappppppppppppppppppppppppppppppppppppaaappppppppppppaaapppppppppaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaappppppppapppaaaaappaaaaaaa";
const std::string CustomSpellEntryIndex = "Id";
char const SpellFocusObjectfmt[] = "nxxxxxxxxxxxxxxxxx";
diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp
index 5ad94948cd0..250f6e07718 100644
--- a/src/server/game/DungeonFinding/LFGMgr.cpp
+++ b/src/server/game/DungeonFinding/LFGMgr.cpp
@@ -58,7 +58,7 @@ void LFGMgr::_LoadFromDB(Field* fields, ObjectGuid guid)
if (!guid.IsGroup())
return;
- SetLeader(guid, ObjectGuid(HIGHGUID_PLAYER, fields[0].GetUInt32()));
+ SetLeader(guid, ObjectGuid(HighGuid::Player, fields[0].GetUInt32()));
uint32 dungeon = fields[17].GetUInt32();
uint8 state = fields[18].GetUInt8();
@@ -194,11 +194,12 @@ void LFGMgr::LoadLFGDungeons(bool reload /* = false */)
}
// Fill teleport locations from DB
- QueryResult result = WorldDatabase.Query("SELECT dungeonId, position_x, position_y, position_z, orientation FROM lfg_entrances");
+ // 0 1 2 3 4
+ QueryResult result = WorldDatabase.Query("SELECT dungeonId, position_x, position_y, position_z, orientation FROM lfg_dungeon_template");
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 lfg entrance positions. DB table `lfg_entrances` is empty!");
+ TC_LOG_ERROR("server.loading", ">> Loaded 0 lfg entrance positions. DB table `lfg_dungeon_template` is empty!");
return;
}
@@ -211,7 +212,7 @@ void LFGMgr::LoadLFGDungeons(bool reload /* = false */)
LFGDungeonContainer::iterator dungeonItr = LfgDungeonStore.find(dungeonId);
if (dungeonItr == LfgDungeonStore.end())
{
- TC_LOG_ERROR("sql.sql", "table `lfg_entrances` contains coordinates for wrong dungeon %u", dungeonId);
+ TC_LOG_ERROR("sql.sql", "table `lfg_dungeon_template` contains coordinates for wrong dungeon %u", dungeonId);
continue;
}
@@ -584,7 +585,7 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const
@param[in] guid Player or group guid
*/
-void LFGMgr::LeaveLfg(ObjectGuid guid)
+void LFGMgr::LeaveLfg(ObjectGuid guid, bool disconnected)
{
ObjectGuid gguid = guid.IsGroup() ? guid : GetGroup(guid);
@@ -645,7 +646,7 @@ void LFGMgr::LeaveLfg(ObjectGuid guid)
break;
case LFG_STATE_DUNGEON:
case LFG_STATE_FINISHED_DUNGEON:
- if (guid != gguid) // Player
+ if (guid != gguid && !disconnected) // Player
SetState(guid, LFG_STATE_NONE);
break;
}
diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h
index fda9a8b7ce9..90fbc36a114 100644
--- a/src/server/game/DungeonFinding/LFGMgr.h
+++ b/src/server/game/DungeonFinding/LFGMgr.h
@@ -399,7 +399,7 @@ class LFGMgr
/// Join Lfg with selected roles, dungeons and comment
void JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, std::string const& comment);
/// Leaves lfg
- void LeaveLfg(ObjectGuid guid);
+ void LeaveLfg(ObjectGuid guid, bool disconnected = false);
// LfgQueue
/// Get last lfg state (NONE, DUNGEON or FINISHED_DUNGEON)
diff --git a/src/server/game/DungeonFinding/LFGQueue.cpp b/src/server/game/DungeonFinding/LFGQueue.cpp
index 6ac20541574..86b010a9ace 100644
--- a/src/server/game/DungeonFinding/LFGQueue.cpp
+++ b/src/server/game/DungeonFinding/LFGQueue.cpp
@@ -72,7 +72,7 @@ char const* GetCompatibleString(LfgCompatibility compatibles)
case LFG_INCOMPATIBLES_NO_ROLES:
return "Incompatible roles";
case LFG_INCOMPATIBLES_TOO_MUCH_PLAYERS:
- return "Too much players";
+ return "Too many players";
case LFG_INCOMPATIBLES_WRONG_GROUP_SIZE:
return "Wrong group size";
default:
@@ -80,6 +80,43 @@ char const* GetCompatibleString(LfgCompatibility compatibles)
}
}
+std::string LFGQueue::GetDetailedMatchRoles(GuidList const& check) const
+{
+ if (check.empty())
+ return "";
+
+ // need the guids in order to avoid duplicates
+ GuidSet guids(check.begin(), check.end());
+
+ std::ostringstream o;
+
+ GuidSet::const_iterator it = guids.begin();
+ o << it->GetRawValue();
+ LfgQueueDataContainer::const_iterator itQueue = QueueDataStore.find(*it);
+ if (itQueue != QueueDataStore.end())
+ {
+ // skip leader flag, log only dps/tank/healer
+ auto role = itQueue->second.roles.find(*it);
+ if (role != itQueue->second.roles.end())
+ o << ' ' << GetRolesString(itQueue->second.roles.at(*it) & uint8(~PLAYER_ROLE_LEADER));
+ }
+
+ for (++it; it != guids.end(); ++it)
+ {
+ o << '|' << it->GetRawValue();
+ itQueue = QueueDataStore.find(*it);
+ if (itQueue != QueueDataStore.end())
+ {
+ // skip leader flag, log only dps/tank/healer
+ auto role = itQueue->second.roles.find(*it);
+ if (role != itQueue->second.roles.end())
+ o << ' ' << GetRolesString(itQueue->second.roles.at(*it) & uint8(~PLAYER_ROLE_LEADER));
+ }
+ }
+
+ return o.str();
+}
+
void LFGQueue::AddToQueue(ObjectGuid guid)
{
LfgQueueDataContainer::iterator itQueue = QueueDataStore.find(guid);
@@ -278,13 +315,13 @@ LfgCompatibility LFGQueue::FindNewGroups(GuidList& check, GuidList& all)
std::string strGuids = ConcatenateGuids(check);
LfgCompatibility compatibles = GetCompatibles(strGuids);
- TC_LOG_DEBUG("lfg.queue.match.check", "Guids: (%s): %s - all(%s)", strGuids.c_str(), GetCompatibleString(compatibles), ConcatenateGuids(all).c_str());
+ TC_LOG_DEBUG("lfg.queue.match.check", "Guids: (%s): %s - all(%s)", GetDetailedMatchRoles(check).c_str(), GetCompatibleString(compatibles), GetDetailedMatchRoles(all).c_str());
if (compatibles == LFG_COMPATIBILITY_PENDING) // Not previously cached, calculate
compatibles = CheckCompatibility(check);
if (compatibles == LFG_COMPATIBLES_BAD_STATES && sLFGMgr->AllQueued(check))
{
- TC_LOG_DEBUG("lfg.queue.match.check", "Guids: (%s) compatibles (cached) changed from bad states to match", strGuids.c_str());
+ TC_LOG_DEBUG("lfg.queue.match.check", "Guids: (%s) compatibles (cached) changed from bad states to match", GetDetailedMatchRoles(check).c_str());
SetCompatibles(strGuids, LFG_COMPATIBLES_MATCH);
return LFG_COMPATIBLES_MATCH;
}
@@ -322,7 +359,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check)
// Check for correct size
if (check.size() > MAXGROUPSIZE || check.empty())
{
- TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s): Size wrong - Not compatibles", strGuids.c_str());
+ TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s): Size wrong - Not compatibles", GetDetailedMatchRoles(check).c_str());
return LFG_INCOMPATIBLES_WRONG_GROUP_SIZE;
}
@@ -336,7 +373,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check)
LfgCompatibility child_compatibles = CheckCompatibility(check);
if (child_compatibles < LFG_COMPATIBLES_WITH_LESS_PLAYERS) // Group not compatible
{
- TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) child %s not compatibles", strGuids.c_str(), ConcatenateGuids(check).c_str());
+ TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) child %s not compatibles", strGuids.c_str(), GetDetailedMatchRoles(check).c_str());
SetCompatibles(strGuids, child_compatibles);
return child_compatibles;
}
@@ -374,7 +411,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check)
// Group with less that MAXGROUPSIZE members always compatible
if (check.size() == 1 && numPlayers != MAXGROUPSIZE)
{
- TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) single group. Compatibles", strGuids.c_str());
+ TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) single group. Compatibles", GetDetailedMatchRoles(check).c_str());
LfgQueueDataContainer::iterator itQueue = QueueDataStore.find(check.front());
LfgCompatibilityData data(LFG_COMPATIBLES_WITH_LESS_PLAYERS);
@@ -388,14 +425,14 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check)
if (numLfgGroups > 1)
{
- TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) More than one Lfggroup (%u)", strGuids.c_str(), numLfgGroups);
+ TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) More than one Lfggroup (%u)", GetDetailedMatchRoles(check).c_str(), numLfgGroups);
SetCompatibles(strGuids, LFG_INCOMPATIBLES_MULTIPLE_LFG_GROUPS);
return LFG_INCOMPATIBLES_MULTIPLE_LFG_GROUPS;
}
if (numPlayers > MAXGROUPSIZE)
{
- TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) Too much players (%u)", strGuids.c_str(), numPlayers);
+ TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) Too many players (%u)", GetDetailedMatchRoles(check).c_str(), numPlayers);
SetCompatibles(strGuids, LFG_INCOMPATIBLES_TOO_MUCH_PLAYERS);
return LFG_INCOMPATIBLES_TOO_MUCH_PLAYERS;
}
@@ -423,7 +460,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check)
if (uint8 playersize = numPlayers - proposalRoles.size())
{
- TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) not compatible, %u players are ignoring each other", strGuids.c_str(), playersize);
+ TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) not compatible, %u players are ignoring each other", GetDetailedMatchRoles(check).c_str(), playersize);
SetCompatibles(strGuids, LFG_INCOMPATIBLES_HAS_IGNORES);
return LFG_INCOMPATIBLES_HAS_IGNORES;
}
@@ -435,7 +472,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check)
for (LfgRolesMap::const_iterator it = debugRoles.begin(); it != debugRoles.end(); ++it)
o << ", " << it->first.GetRawValue() << ": " << GetRolesString(it->second);
- TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) Roles not compatible%s", strGuids.c_str(), o.str().c_str());
+ TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) Roles not compatible%s", GetDetailedMatchRoles(check).c_str(), o.str().c_str());
SetCompatibles(strGuids, LFG_INCOMPATIBLES_NO_ROLES);
return LFG_INCOMPATIBLES_NO_ROLES;
}
@@ -455,7 +492,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check)
if (proposalDungeons.empty())
{
- TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) No compatible dungeons%s", strGuids.c_str(), o.str().c_str());
+ TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) No compatible dungeons%s", GetDetailedMatchRoles(check).c_str(), o.str().c_str());
SetCompatibles(strGuids, LFG_INCOMPATIBLES_NO_DUNGEONS);
return LFG_INCOMPATIBLES_NO_DUNGEONS;
}
@@ -472,7 +509,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check)
// Enough players?
if (numPlayers != MAXGROUPSIZE)
{
- TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) Compatibles but not enough players(%u)", strGuids.c_str(), numPlayers);
+ TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) Compatibles but not enough players(%u)", GetDetailedMatchRoles(check).c_str(), numPlayers);
LfgCompatibilityData data(LFG_COMPATIBLES_WITH_LESS_PLAYERS);
data.roles = proposalRoles;
@@ -489,7 +526,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check)
if (!sLFGMgr->AllQueued(check))
{
- TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) Group MATCH but can't create proposal!", strGuids.c_str());
+ TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) Group MATCH but can't create proposal!", GetDetailedMatchRoles(check).c_str());
SetCompatibles(strGuids, LFG_COMPATIBLES_BAD_STATES);
return LFG_COMPATIBLES_BAD_STATES;
}
@@ -531,7 +568,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check)
sLFGMgr->AddProposal(proposal);
- TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) MATCH! Group formed", strGuids.c_str());
+ TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) MATCH! Group formed", GetDetailedMatchRoles(check).c_str());
SetCompatibles(strGuids, LFG_COMPATIBLES_MATCH);
return LFG_COMPATIBLES_MATCH;
}
@@ -623,7 +660,23 @@ std::string LFGQueue::DumpCompatibleInfo(bool full /* = false */) const
o << "Compatible Map size: " << CompatibleMapStore.size() << "\n";
if (full)
for (LfgCompatibleContainer::const_iterator itr = CompatibleMapStore.begin(); itr != CompatibleMapStore.end(); ++itr)
- o << "(" << itr->first << "): " << GetCompatibleString(itr->second.compatibility) << "\n";
+ {
+ o << "(" << itr->first << "): " << GetCompatibleString(itr->second.compatibility);
+ if (!itr->second.roles.empty())
+ {
+ o << " (";
+ bool first = true;
+ for (const auto& role : itr->second.roles)
+ {
+ if (!first)
+ o << "|";
+ o << role.first.GetRawValue() << " " << GetRolesString(role.second & uint8(~PLAYER_ROLE_LEADER));
+ first = false;
+ }
+ o << ")";
+ }
+ o << "\n";
+ }
return o.str();
}
diff --git a/src/server/game/DungeonFinding/LFGQueue.h b/src/server/game/DungeonFinding/LFGQueue.h
index 9bf8ee64b78..f72e9b4fd6d 100644
--- a/src/server/game/DungeonFinding/LFGQueue.h
+++ b/src/server/game/DungeonFinding/LFGQueue.h
@@ -88,6 +88,7 @@ class LFGQueue
public:
// Add/Remove from queue
+ std::string GetDetailedMatchRoles(GuidList const& check) const;
void AddToQueue(ObjectGuid guid);
void RemoveFromQueue(ObjectGuid guid);
void AddQueueData(ObjectGuid guid, time_t joinTime, LfgDungeonSet const& dungeons, LfgRolesMap const& rolesMap);
diff --git a/src/server/game/DungeonFinding/LFGScripts.cpp b/src/server/game/DungeonFinding/LFGScripts.cpp
index 852eb7d8c5f..2f0734ff4d0 100644
--- a/src/server/game/DungeonFinding/LFGScripts.cpp
+++ b/src/server/game/DungeonFinding/LFGScripts.cpp
@@ -44,6 +44,8 @@ void LFGPlayerScript::OnLogout(Player* player)
player->GetSession()->SendLfgLfrList(false);
sLFGMgr->LeaveLfg(player->GetGUID());
}
+ else if (player->GetSession()->PlayerDisconnected())
+ sLFGMgr->LeaveLfg(player->GetGUID(), true);
}
void LFGPlayerScript::OnLogin(Player* player, bool /*loginFirst*/)
@@ -87,7 +89,7 @@ void LFGPlayerScript::OnMapChanged(Player* player)
player->RemoveAurasDueToSpell(LFG_SPELL_LUCK_OF_THE_DRAW);
player->TeleportTo(player->m_homebindMapId, player->m_homebindX, player->m_homebindY, player->m_homebindZ, 0.0f);
TC_LOG_ERROR("lfg", "LFGPlayerScript::OnMapChanged, Player %s (%u) is in LFG dungeon map but does not have a valid group! "
- "Teleporting to homebind.", player->GetName().c_str(), player->GetGUIDLow());
+ "Teleporting to homebind.", player->GetName().c_str(), player->GetGUID().GetCounter());
return;
}
diff --git a/src/server/game/Entities/Corpse/Corpse.cpp b/src/server/game/Entities/Corpse/Corpse.cpp
index 192a897238a..ce4e94b8ea6 100644
--- a/src/server/game/Entities/Corpse/Corpse.cpp
+++ b/src/server/game/Entities/Corpse/Corpse.cpp
@@ -22,6 +22,7 @@
#include "UpdateMask.h"
#include "ObjectAccessor.h"
#include "DatabaseEnv.h"
+#include "World.h"
Corpse::Corpse(CorpseType type) : WorldObject(type != CORPSE_BONES), m_type(type)
{
@@ -44,7 +45,7 @@ void Corpse::AddToWorld()
{
///- Register the corpse for guid lookup
if (!IsInWorld())
- sObjectAccessor->AddObject(this);
+ GetMap()->GetObjectsStore().Insert<Corpse>(GetGUID(), this);
Object::AddToWorld();
}
@@ -53,19 +54,18 @@ void Corpse::RemoveFromWorld()
{
///- Remove the corpse from the accessor
if (IsInWorld())
- sObjectAccessor->RemoveObject(this);
+ GetMap()->GetObjectsStore().Remove<Corpse>(GetGUID());
- Object::RemoveFromWorld();
+ WorldObject::RemoveFromWorld();
}
-bool Corpse::Create(uint32 guidlow, Map* map)
+bool Corpse::Create(ObjectGuid::LowType guidlow)
{
- SetMap(map);
- Object::_Create(guidlow, 0, HIGHGUID_CORPSE);
+ Object::_Create(guidlow, 0, HighGuid::Corpse);
return true;
}
-bool Corpse::Create(uint32 guidlow, Player* owner)
+bool Corpse::Create(ObjectGuid::LowType guidlow, Player* owner)
{
ASSERT(owner);
@@ -78,16 +78,12 @@ bool Corpse::Create(uint32 guidlow, Player* owner)
return false;
}
- //we need to assign owner's map for corpse
- //in other way we will get a crash in Corpse::SaveToDB()
- SetMap(owner->GetMap());
+ WorldObject::_Create(guidlow, HighGuid::Corpse, owner->GetPhaseMask());
- WorldObject::_Create(guidlow, HIGHGUID_CORPSE, owner->GetPhaseMask());
-
- SetObjectScale(1);
+ SetObjectScale(1.0f);
SetGuidValue(CORPSE_FIELD_OWNER, owner->GetGUID());
- _gridCoord = Trinity::ComputeGridCoord(GetPositionX(), GetPositionY());
+ _cellCoord = Trinity::ComputeCellCoord(GetPositionX(), GetPositionY());
return true;
}
@@ -100,7 +96,6 @@ void Corpse::SaveToDB()
uint16 index = 0;
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CORPSE);
- stmt->setUInt32(index++, GetGUIDLow()); // corpseGuid
stmt->setUInt32(index++, GetOwnerGUID().GetCounter()); // guid
stmt->setFloat (index++, GetPositionX()); // posX
stmt->setFloat (index++, GetPositionY()); // posY
@@ -123,51 +118,32 @@ void Corpse::SaveToDB()
CharacterDatabase.CommitTransaction(trans);
}
-void Corpse::DeleteBonesFromWorld()
+void Corpse::DeleteFromDB(SQLTransaction& trans)
{
- ASSERT(GetType() == CORPSE_BONES);
- Corpse* corpse = ObjectAccessor::GetCorpse(*this, GetGUID());
-
- if (!corpse)
- {
- TC_LOG_ERROR("entities.player", "Bones %u not found in world.", GetGUIDLow());
- return;
- }
-
- AddObjectToRemoveList();
+ DeleteFromDB(GetOwnerGUID(), trans);
}
-void Corpse::DeleteFromDB(SQLTransaction& trans)
+void Corpse::DeleteFromDB(ObjectGuid const& ownerGuid, SQLTransaction& trans)
{
- PreparedStatement* stmt = NULL;
- if (GetType() == CORPSE_BONES)
- {
- // Only specific bones
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CORPSE);
- stmt->setUInt32(0, GetGUIDLow());
- }
- else
- {
- // all corpses (not bones)
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_CORPSES);
- stmt->setUInt32(0, GetOwnerGUID().GetCounter());
- }
- trans->Append(stmt);
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CORPSE);
+ stmt->setUInt32(0, ownerGuid.GetCounter());
+ CharacterDatabase.ExecuteOrAppend(trans, stmt);
}
-bool Corpse::LoadCorpseFromDB(uint32 guid, Field* fields)
+bool Corpse::LoadCorpseFromDB(ObjectGuid::LowType guid, Field* fields)
{
- // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
- // SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, guildId, flags, dynFlags, time, corpseType, instanceId, phaseMask, corpseGuid, guid FROM corpse WHERE corpseType <> 0
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+ // SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, guildId, flags, dynFlags, time, corpseType, instanceId, phaseMask, guid FROM corpse WHERE mapId = ? AND instanceId = ?
- uint32 ownerGuid = fields[17].GetUInt32();
+
+ ObjectGuid::LowType ownerGuid = fields[16].GetUInt32();
float posX = fields[0].GetFloat();
float posY = fields[1].GetFloat();
float posZ = fields[2].GetFloat();
float o = fields[3].GetFloat();
uint32 mapId = fields[4].GetUInt16();
- Object::_Create(guid, 0, HIGHGUID_CORPSE);
+ Object::_Create(guid, 0, HighGuid::Corpse);
SetObjectScale(1.0f);
SetUInt32Value(CORPSE_FIELD_DISPLAY_ID, fields[5].GetUInt32());
@@ -177,7 +153,7 @@ bool Corpse::LoadCorpseFromDB(uint32 guid, Field* fields)
SetUInt32Value(CORPSE_FIELD_GUILD, fields[9].GetUInt32());
SetUInt32Value(CORPSE_FIELD_FLAGS, fields[10].GetUInt8());
SetUInt32Value(CORPSE_FIELD_DYNAMIC_FLAGS, fields[11].GetUInt8());
- SetGuidValue(CORPSE_FIELD_OWNER, ObjectGuid(HIGHGUID_PLAYER, ownerGuid));
+ SetGuidValue(CORPSE_FIELD_OWNER, ObjectGuid(HighGuid::Player, ownerGuid));
m_time = time_t(fields[12].GetUInt32());
@@ -197,12 +173,16 @@ bool Corpse::LoadCorpseFromDB(uint32 guid, Field* fields)
return false;
}
- _gridCoord = Trinity::ComputeGridCoord(GetPositionX(), GetPositionY());
+ _cellCoord = Trinity::ComputeCellCoord(GetPositionX(), GetPositionY());
return true;
}
bool Corpse::IsExpired(time_t t) const
{
+ // Deleted character
+ if (!sWorld->GetCharacterInfo(GetOwnerGUID()))
+ return true;
+
if (m_type == CORPSE_BONES)
return m_time < t - 60 * MINUTE;
else
diff --git a/src/server/game/Entities/Corpse/Corpse.h b/src/server/game/Entities/Corpse/Corpse.h
index c3a693d30d3..7f2608e4bf3 100644
--- a/src/server/game/Entities/Corpse/Corpse.h
+++ b/src/server/game/Entities/Corpse/Corpse.h
@@ -55,14 +55,14 @@ class Corpse : public WorldObject, public GridObject<Corpse>
void AddToWorld() override;
void RemoveFromWorld() override;
- bool Create(uint32 guidlow, Map* map);
- bool Create(uint32 guidlow, Player* owner);
+ bool Create(ObjectGuid::LowType guidlow);
+ bool Create(ObjectGuid::LowType guidlow, Player* owner);
void SaveToDB();
- bool LoadCorpseFromDB(uint32 guid, Field* fields);
+ bool LoadCorpseFromDB(ObjectGuid::LowType guid, Field* fields);
- void DeleteBonesFromWorld();
void DeleteFromDB(SQLTransaction& trans);
+ static void DeleteFromDB(ObjectGuid const& ownerGuid, SQLTransaction& trans);
ObjectGuid GetOwnerGUID() const { return GetGuidValue(CORPSE_FIELD_OWNER); }
@@ -70,8 +70,8 @@ class Corpse : public WorldObject, public GridObject<Corpse>
void ResetGhostTime() { m_time = time(NULL); }
CorpseType GetType() const { return m_type; }
- GridCoord const& GetGridCoord() const { return _gridCoord; }
- void SetGridCoord(GridCoord const& gridCoord) { _gridCoord = gridCoord; }
+ CellCoord const& GetCellCoord() const { return _cellCoord; }
+ void SetCellCoord(CellCoord const& cellCoord) { _cellCoord = cellCoord; }
Loot loot; // remove insignia ONLY at BG
Player* lootRecipient;
@@ -82,6 +82,6 @@ class Corpse : public WorldObject, public GridObject<Corpse>
private:
CorpseType m_type;
time_t m_time;
- GridCoord _gridCoord; // gride for corpse position for fast search
+ CellCoord _cellCoord;
};
#endif
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 3d11965ac6e..6ba8fb44e09 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -36,7 +36,6 @@
#include "LootMgr.h"
#include "MoveSpline.h"
#include "ObjectMgr.h"
-#include "Opcodes.h"
#include "Player.h"
#include "PoolMgr.h"
#include "QuestDef.h"
@@ -104,6 +103,48 @@ uint32 CreatureTemplate::GetFirstValidModelId() const
return 0;
}
+uint32 CreatureTemplate::GetFirstInvisibleModel() const
+{
+ CreatureModelInfo const* modelInfo = sObjectMgr->GetCreatureModelInfo(Modelid1);
+ if (modelInfo && modelInfo->is_trigger)
+ return Modelid1;
+
+ modelInfo = sObjectMgr->GetCreatureModelInfo(Modelid2);
+ if (modelInfo && modelInfo->is_trigger)
+ return Modelid2;
+
+ modelInfo = sObjectMgr->GetCreatureModelInfo(Modelid3);
+ if (modelInfo && modelInfo->is_trigger)
+ return Modelid3;
+
+ modelInfo = sObjectMgr->GetCreatureModelInfo(Modelid4);
+ if (modelInfo && modelInfo->is_trigger)
+ return Modelid4;
+
+ return 11686;
+}
+
+uint32 CreatureTemplate::GetFirstVisibleModel() const
+{
+ CreatureModelInfo const* modelInfo = sObjectMgr->GetCreatureModelInfo(Modelid1);
+ if (modelInfo && !modelInfo->is_trigger)
+ return Modelid1;
+
+ modelInfo = sObjectMgr->GetCreatureModelInfo(Modelid2);
+ if (modelInfo && !modelInfo->is_trigger)
+ return Modelid2;
+
+ modelInfo = sObjectMgr->GetCreatureModelInfo(Modelid3);
+ if (modelInfo && !modelInfo->is_trigger)
+ return Modelid3;
+
+ modelInfo = sObjectMgr->GetCreatureModelInfo(Modelid4);
+ if (modelInfo && !modelInfo->is_trigger)
+ return Modelid4;
+
+ return 17519;
+}
+
bool AssistDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
{
if (Unit* victim = ObjectAccessor::GetUnit(m_owner, m_victim))
@@ -139,8 +180,8 @@ bool ForcedDespawnDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
Creature::Creature(bool isWorldObject): Unit(isWorldObject), MapObject(),
m_groupLootTimer(0), lootingGroupLowGUID(0), m_PlayerDamageReq(0),
m_lootRecipient(), m_lootRecipientGroup(0), _skinner(), _pickpocketLootRestore(0), m_corpseRemoveTime(0), m_respawnTime(0),
-m_respawnDelay(300), m_corpseDelay(60), m_respawnradius(0.0f), m_reactState(REACT_AGGRESSIVE),
-m_defaultMovementType(IDLE_MOTION_TYPE), m_DBTableGuid(0), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false),
+m_respawnDelay(300), m_corpseDelay(60), m_respawnradius(0.0f), m_combatPulseTime(0), m_combatPulseDelay(0), m_reactState(REACT_AGGRESSIVE),
+m_defaultMovementType(IDLE_MOTION_TYPE), m_spawnId(0), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false),
m_AlreadySearchedAssistance(false), m_regenHealth(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),
m_originalEntry(0), m_homePosition(), m_transportHomePosition(), m_creatureInfo(NULL), m_creatureData(NULL), m_waypointID(0), m_path_id(0), m_formation(NULL)
{
@@ -177,7 +218,13 @@ void Creature::AddToWorld()
{
if (GetZoneScript())
GetZoneScript()->OnCreatureCreate(this);
- sObjectAccessor->AddObject(this);
+
+ GetMap()->GetObjectsStore().Insert<Creature>(GetGUID(), this);
+ if (m_spawnId)
+ GetMap()->GetCreatureBySpawnIdStore().insert(std::make_pair(m_spawnId, this));
+
+ TC_LOG_DEBUG("entities.unit", "Adding creature %u with entry %u and DBGUID %u to world in map %u", GetGUID().GetCounter(), GetEntry(), m_spawnId, GetMap()->GetId());
+
Unit::AddToWorld();
SearchFormation();
AIM_Initialize();
@@ -192,10 +239,17 @@ void Creature::RemoveFromWorld()
{
if (GetZoneScript())
GetZoneScript()->OnCreatureRemove(this);
+
if (m_formation)
sFormationMgr->RemoveCreatureFromGroup(m_formation, this);
+
Unit::RemoveFromWorld();
- sObjectAccessor->RemoveObject(this);
+
+ if (m_spawnId)
+ Trinity::Containers::MultimapErasePair(GetMap()->GetCreatureBySpawnIdStore(), m_spawnId, this);
+
+ TC_LOG_DEBUG("entities.unit", "Removing creature %u with entry %u and DBGUID %u to world in map %u", GetGUID().GetCounter(), GetEntry(), m_spawnId, GetMap()->GetId());
+ GetMap()->GetObjectsStore().Remove<Creature>(GetGUID());
}
}
@@ -214,7 +268,7 @@ void Creature::SearchFormation()
if (IsSummon())
return;
- uint32 lowguid = GetDBTableGUIDLow();
+ ObjectGuid::LowType lowguid = GetSpawnId();
if (!lowguid)
return;
@@ -429,6 +483,7 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/)
}
UpdateMovementFlags();
+ LoadCreaturesAddon();
return true;
}
@@ -448,11 +503,11 @@ void Creature::Update(uint32 diff)
{
case JUST_RESPAWNED:
// Must not be called, see Creature::setDeathState JUST_RESPAWNED -> ALIVE promoting.
- TC_LOG_ERROR("entities.unit", "Creature (GUID: %u Entry: %u) in wrong state: JUST_RESPAWNED (4)", GetGUIDLow(), GetEntry());
+ TC_LOG_ERROR("entities.unit", "Creature (GUID: %u Entry: %u) in wrong state: JUST_RESPAWNED (4)", GetGUID().GetCounter(), GetEntry());
break;
case JUST_DIED:
// Must not be called, see Creature::setDeathState JUST_DIED -> CORPSE promoting.
- TC_LOG_ERROR("entities.unit", "Creature (GUID: %u Entry: %u) in wrong state: JUST_DEAD (1)", GetGUIDLow(), GetEntry());
+ TC_LOG_ERROR("entities.unit", "Creature (GUID: %u Entry: %u) in wrong state: JUST_DEAD (1)", GetGUID().GetCounter(), GetEntry());
break;
case DEAD:
{
@@ -463,7 +518,7 @@ void Creature::Update(uint32 diff)
if (!allowed) // Will be rechecked on next Update call
break;
- ObjectGuid dbtableHighGuid(HIGHGUID_UNIT, GetEntry(), m_DBTableGuid);
+ ObjectGuid dbtableHighGuid(HighGuid::Unit, GetEntry(), m_spawnId);
time_t linkedRespawntime = GetMap()->GetLinkedRespawnTime(dbtableHighGuid);
if (!linkedRespawntime) // Can respawn
Respawn();
@@ -527,10 +582,44 @@ void Creature::Update(uint32 diff)
LastCharmerGUID.Clear();
}
+ // if periodic combat pulse is enabled and we are both in combat and in a dungeon, do this now
+ if (m_combatPulseDelay > 0 && IsInCombat() && GetMap()->IsDungeon())
+ {
+ if (diff > m_combatPulseTime)
+ m_combatPulseTime = 0;
+ else
+ m_combatPulseTime -= diff;
+
+ if (m_combatPulseTime == 0)
+ {
+ Map::PlayerList const &players = GetMap()->GetPlayers();
+ if (!players.isEmpty())
+ for (Map::PlayerList::const_iterator it = players.begin(); it != players.end(); ++it)
+ {
+ if (Player* player = it->GetSource())
+ {
+ if (player->IsGameMaster())
+ continue;
+
+ if (player->IsAlive() && this->IsHostileTo(player))
+ {
+ if (CanHaveThreatList())
+ AddThreat(player, 0.0f);
+ this->SetInCombatWith(player);
+ player->SetInCombatWith(this);
+ }
+ }
+ }
+
+ m_combatPulseTime = m_combatPulseDelay * IN_MILLISECONDS;
+ }
+ }
+
if (!IsInEvadeMode() && IsAIEnabled)
{
// do not allow the AI to be changed during update
m_AI_locked = true;
+
i_AI->UpdateAI(diff);
m_AI_locked = false;
}
@@ -729,7 +818,7 @@ void Creature::Motion_Initialize()
GetMotionMaster()->Initialize();
}
-bool Creature::Create(uint32 guidlow, Map* map, uint32 phaseMask, uint32 entry, float x, float y, float z, float ang, CreatureData const* data /*= nullptr*/, uint32 vehId /*= 0*/)
+bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, uint32 entry, float x, float y, float z, float ang, CreatureData const* data /*= nullptr*/, uint32 vehId /*= 0*/)
{
ASSERT(map);
SetMap(map);
@@ -774,8 +863,6 @@ bool Creature::Create(uint32 guidlow, Map* map, uint32 phaseMask, uint32 entry,
break;
}
- LoadCreaturesAddon();
-
//! Need to be called after LoadCreaturesAddon - MOVEMENTFLAG_HOVER is set there
if (HasUnitMovementFlag(MOVEMENTFLAG_HOVER))
{
@@ -919,7 +1006,7 @@ void Creature::SaveToDB()
{
// this should only be used when the creature has already been loaded
// preferably after adding to map, because mapid may not be valid otherwise
- CreatureData const* data = sObjectMgr->GetCreatureData(m_DBTableGuid);
+ CreatureData const* data = sObjectMgr->GetCreatureData(m_spawnId);
if (!data)
{
TC_LOG_ERROR("entities.unit", "Creature::SaveToDB failed, cannot get creature data!");
@@ -933,9 +1020,10 @@ void Creature::SaveToDB()
void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
{
// update in loaded data
- if (!m_DBTableGuid)
- m_DBTableGuid = GetGUIDLow();
- CreatureData& data = sObjectMgr->NewOrExistCreatureData(m_DBTableGuid);
+ if (!m_spawnId)
+ m_spawnId = sObjectMgr->GenerateCreatureSpawnId();
+
+ CreatureData& data = sObjectMgr->NewOrExistCreatureData(m_spawnId);
uint32 displayId = GetNativeDisplayId();
uint32 npcflag = GetUInt32Value(UNIT_NPC_FLAGS);
@@ -999,13 +1087,14 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
SQLTransaction trans = WorldDatabase.BeginTransaction();
PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CREATURE);
- stmt->setUInt32(0, m_DBTableGuid);
+ stmt->setUInt32(0, m_spawnId);
+
trans->Append(stmt);
uint8 index = 0;
stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_CREATURE);
- stmt->setUInt32(index++, m_DBTableGuid);
+ stmt->setUInt32(index++, m_spawnId);
stmt->setUInt32(index++, GetEntry());
stmt->setUInt16(index++, uint16(mapid));
stmt->setUInt8(index++, spawnMask);
@@ -1150,7 +1239,7 @@ float Creature::GetSpellDamageMod(int32 Rank) const
}
}
-bool Creature::CreateFromProto(uint32 guidlow, uint32 entry, CreatureData const* data /*= nullptr*/, uint32 vehId /*= 0*/)
+bool Creature::CreateFromProto(ObjectGuid::LowType guidlow, uint32 entry, CreatureData const* data /*= nullptr*/, uint32 vehId /*= 0*/)
{
SetZoneScript();
if (GetZoneScript() && data)
@@ -1169,7 +1258,7 @@ bool Creature::CreateFromProto(uint32 guidlow, uint32 entry, CreatureData const*
SetOriginalEntry(entry);
- Object::_Create(guidlow, entry, (vehId || cinfo->VehicleId) ? HIGHGUID_VEHICLE : HIGHGUID_UNIT);
+ Object::_Create(guidlow, entry, (vehId || cinfo->VehicleId) ? HighGuid::Vehicle : HighGuid::Unit);
if (!UpdateEntry(entry, data))
return false;
@@ -1191,26 +1280,18 @@ bool Creature::CreateFromProto(uint32 guidlow, uint32 entry, CreatureData const*
return true;
}
-bool Creature::LoadCreatureFromDB(uint32 guid, Map* map, bool addToMap)
+bool Creature::LoadCreatureFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap)
{
- CreatureData const* data = sObjectMgr->GetCreatureData(guid);
+ CreatureData const* data = sObjectMgr->GetCreatureData(spawnId);
if (!data)
{
- TC_LOG_ERROR("sql.sql", "Creature (GUID: %u) not found in table `creature`, can't load. ", guid);
+ TC_LOG_ERROR("sql.sql", "Creature (GUID: %u) not found in table `creature`, can't load. ", spawnId);
return false;
}
- m_DBTableGuid = guid;
- if (map->GetInstanceId() == 0)
- {
- if (map->GetCreature(ObjectGuid(HIGHGUID_UNIT, data->id, guid)))
- return false;
- }
- else
- guid = sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT);
-
- if (!Create(guid, map, data->phaseMask, data->id, data->posX, data->posY, data->posZ, data->orientation, data))
+ m_spawnId = spawnId;
+ if (!Create(map->GenerateLowGuid<HighGuid::Unit>(), map, data->phaseMask, data->id, data->posX, data->posY, data->posZ, data->orientation, data))
return false;
//We should set first home position, because then AI calls home movement
@@ -1221,7 +1302,7 @@ bool Creature::LoadCreatureFromDB(uint32 guid, Map* map, bool addToMap)
m_respawnDelay = data->spawntimesecs;
m_deathState = ALIVE;
- m_respawnTime = GetMap()->GetCreatureRespawnTime(m_DBTableGuid);
+ m_respawnTime = GetMap()->GetCreatureRespawnTime(m_spawnId);
if (m_respawnTime) // respawn on Update
{
m_deathState = DEAD;
@@ -1316,31 +1397,31 @@ bool Creature::hasInvolvedQuest(uint32 quest_id) const
void Creature::DeleteFromDB()
{
- if (!m_DBTableGuid)
+ if (!m_spawnId)
{
- TC_LOG_ERROR("entities.unit", "Trying to delete not saved creature! LowGUID: %u, Entry: %u", GetGUIDLow(), GetEntry());
+ TC_LOG_ERROR("entities.unit", "Trying to delete not saved creature! LowGUID: %u, Entry: %u", GetGUID().GetCounter(), GetEntry());
return;
}
- GetMap()->RemoveCreatureRespawnTime(m_DBTableGuid);
- sObjectMgr->DeleteCreatureData(m_DBTableGuid);
+ GetMap()->RemoveCreatureRespawnTime(m_spawnId);
+ sObjectMgr->DeleteCreatureData(m_spawnId);
SQLTransaction trans = WorldDatabase.BeginTransaction();
PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CREATURE);
- stmt->setUInt32(0, m_DBTableGuid);
+ stmt->setUInt32(0, m_spawnId);
trans->Append(stmt);
stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CREATURE_ADDON);
- stmt->setUInt32(0, m_DBTableGuid);
+ stmt->setUInt32(0, m_spawnId);
trans->Append(stmt);
stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_GAME_EVENT_CREATURE);
- stmt->setUInt32(0, m_DBTableGuid);
+ stmt->setUInt32(0, m_spawnId);
trans->Append(stmt);
stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_GAME_EVENT_MODEL_EQUIP);
- stmt->setUInt32(0, m_DBTableGuid);
+ stmt->setUInt32(0, m_spawnId);
trans->Append(stmt);
WorldDatabase.CommitTransaction(trans);
@@ -1370,6 +1451,12 @@ bool Creature::CanStartAttack(Unit const* who, bool force) const
if (IsCivilian())
return false;
+ // This set of checks is should be done only for creatures
+ if ((HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC) && who->GetTypeId() != TYPEID_PLAYER) // flag is valid only for non player characters
+ || (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC) && who->GetTypeId() == TYPEID_PLAYER) // immune to PC and target is a player, return false
+ || (who->GetOwner() && who->GetOwner()->GetTypeId() == TYPEID_PLAYER && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC))) // player pets are immune to pc as well
+ return false;
+
// Do not attack non-combat pets
if (who->GetTypeId() == TYPEID_UNIT && who->GetCreatureType() == CREATURE_TYPE_NON_COMBAT_PET)
return false;
@@ -1507,11 +1594,11 @@ void Creature::setDeathState(DeathState s)
SetUInt32Value(UNIT_NPC_FLAGS, cinfo->npcflag);
ClearUnitState(uint32(UNIT_STATE_ALL_STATE & ~UNIT_STATE_IGNORE_PATHFINDING));
SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool));
- LoadCreaturesAddon(true);
Motion_Initialize();
if (GetCreatureData() && GetPhaseMask() != GetCreatureData()->phaseMask)
SetPhaseMask(GetCreatureData()->phaseMask, false);
Unit::setDeathState(ALIVE);
+ LoadCreaturesAddon();
}
}
@@ -1531,8 +1618,8 @@ void Creature::Respawn(bool force)
if (getDeathState() == DEAD)
{
- if (m_DBTableGuid)
- GetMap()->RemoveCreatureRespawnTime(m_DBTableGuid);
+ if (m_spawnId)
+ GetMap()->RemoveCreatureRespawnTime(m_spawnId);
TC_LOG_DEBUG("entities.unit", "Respawning creature %s (%s)",
GetName().c_str(), GetGUID().ToString().c_str());
@@ -1565,9 +1652,9 @@ void Creature::Respawn(bool force)
TriggerJustRespawned = true;//delay event to next tick so all creatures are created on the map before processing
}
- uint32 poolid = GetDBTableGUIDLow() ? sPoolMgr->IsPartOfAPool<Creature>(GetDBTableGUIDLow()) : 0;
+ uint32 poolid = GetSpawnId() ? sPoolMgr->IsPartOfAPool<Creature>(GetSpawnId()) : 0;
if (poolid)
- sPoolMgr->UpdatePool<Creature>(poolid, GetDBTableGUIDLow());
+ sPoolMgr->UpdatePool<Creature>(poolid, GetSpawnId());
//Re-initialize reactstate that could be altered by movementgenerators
InitializeReactState();
@@ -1788,7 +1875,7 @@ Unit* Creature::SelectNearestTargetInAttackDistance(float dist) const
if (dist > MAX_VISIBILITY_DISTANCE)
{
- TC_LOG_ERROR("entities.unit", "Creature (GUID: %u Entry: %u) SelectNearestTargetInAttackDistance called with dist > MAX_VISIBILITY_DISTANCE. Distance set to ATTACK_DISTANCE.", GetGUIDLow(), GetEntry());
+ TC_LOG_ERROR("entities.unit", "Creature (GUID: %u Entry: %u) SelectNearestTargetInAttackDistance called with dist > MAX_VISIBILITY_DISTANCE. Distance set to ATTACK_DISTANCE.", GetGUID().GetCounter(), GetEntry());
dist = ATTACK_DISTANCE;
}
@@ -1971,10 +2058,10 @@ bool Creature::_IsTargetAcceptable(const Unit* target) const
void Creature::SaveRespawnTime()
{
- if (IsSummon() || !m_DBTableGuid || (m_creatureData && !m_creatureData->dbData))
+ if (IsSummon() || !m_spawnId || (m_creatureData && !m_creatureData->dbData))
return;
- GetMap()->SaveCreatureRespawnTime(m_DBTableGuid, m_respawnTime);
+ GetMap()->SaveCreatureRespawnTime(m_spawnId, m_respawnTime);
}
// this should not be called by petAI or
@@ -2006,9 +2093,9 @@ bool Creature::CanCreatureAttack(Unit const* victim, bool /*force*/) const
CreatureAddon const* Creature::GetCreatureAddon() const
{
- if (m_DBTableGuid)
+ if (m_spawnId)
{
- if (CreatureAddon const* addon = sObjectMgr->GetCreatureAddon(m_DBTableGuid))
+ if (CreatureAddon const* addon = sObjectMgr->GetCreatureAddon(m_spawnId))
return addon;
}
@@ -2017,7 +2104,7 @@ CreatureAddon const* Creature::GetCreatureAddon() const
}
//creature_addon table
-bool Creature::LoadCreaturesAddon(bool reload)
+bool Creature::LoadCreaturesAddon()
{
CreatureAddon const* cainfo = GetCreatureAddon();
if (!cainfo)
@@ -2077,21 +2164,16 @@ bool Creature::LoadCreaturesAddon(bool reload)
SpellInfo const* AdditionalSpellInfo = sSpellMgr->GetSpellInfo(*itr);
if (!AdditionalSpellInfo)
{
- TC_LOG_ERROR("sql.sql", "Creature (GUID: %u Entry: %u) has wrong spell %u defined in `auras` field.", GetGUIDLow(), GetEntry(), *itr);
+ TC_LOG_ERROR("sql.sql", "Creature (GUID: %u Entry: %u) has wrong spell %u defined in `auras` field.", GetGUID().GetCounter(), GetEntry(), *itr);
continue;
}
// skip already applied aura
if (HasAura(*itr))
- {
- if (!reload)
- TC_LOG_ERROR("sql.sql", "Creature (GUID: %u Entry: %u) has duplicate aura (spell %u) in `auras` field.", GetDBTableGUIDLow(), GetEntry(), *itr);
-
continue;
- }
AddAura(*itr, this);
- TC_LOG_DEBUG("entities.unit", "Spell: %u added to creature (GUID: %u Entry: %u)", *itr, GetGUIDLow(), GetEntry());
+ TC_LOG_DEBUG("entities.unit", "Spell: %u added to creature (GUID: %u Entry: %u)", *itr, GetGUID().GetCounter(), GetEntry());
}
}
@@ -2171,9 +2253,9 @@ time_t Creature::GetRespawnTimeEx() const
void Creature::GetRespawnPosition(float &x, float &y, float &z, float* ori, float* dist) const
{
- if (m_DBTableGuid)
+ if (m_spawnId)
{
- if (CreatureData const* data = sObjectMgr->GetCreatureData(GetDBTableGUIDLow()))
+ if (CreatureData const* data = sObjectMgr->GetCreatureData(GetSpawnId()))
{
x = data->posX;
y = data->posY;
@@ -2548,7 +2630,7 @@ void Creature::UpdateMovementFlags()
return;
// Set the movement flags if the creature is in that mode. (Only fly if actually in air, only swim if in water, etc)
- float ground = GetMap()->GetHeight(GetPositionX(), GetPositionY(), GetPositionZMinusOffset());
+ float ground = GetMap()->GetHeight(GetPhaseMask(), GetPositionX(), GetPositionY(), GetPositionZMinusOffset());
bool isInAir = (G3D::fuzzyGt(GetPositionZMinusOffset(), ground + 0.05f) || G3D::fuzzyLt(GetPositionZMinusOffset(), ground - 0.05f)); // Can be underground too, prevent the falling
@@ -2635,3 +2717,29 @@ void Creature::StartPickPocketRefillTimer()
_pickpocketLootRestore = time(NULL) + sWorld->getIntConfig(CONFIG_CREATURE_PICKPOCKET_REFILL);
}
+void Creature::SetTextRepeatId(uint8 textGroup, uint8 id)
+{
+ CreatureTextRepeatIds& repeats = m_textRepeat[textGroup];
+ if (std::find(repeats.begin(), repeats.end(), id) == repeats.end())
+ repeats.push_back(id);
+ else
+ TC_LOG_ERROR("sql.sql", "CreatureTextMgr: TextGroup %u for Creature(%s) GuidLow %u Entry %u, id %u already added", uint32(textGroup), GetName().c_str(), GetGUID().GetCounter(), GetEntry(), uint32(id));
+}
+
+CreatureTextRepeatIds Creature::GetTextRepeatGroup(uint8 textGroup)
+{
+ CreatureTextRepeatIds ids;
+
+ CreatureTextRepeatGroup::const_iterator groupItr = m_textRepeat.find(textGroup);
+ if (groupItr != m_textRepeat.end())
+ ids = groupItr->second;
+
+ return ids;
+}
+
+void Creature::ClearTextRepeatGroup(uint8 textGroup)
+{
+ CreatureTextRepeatGroup::iterator groupItr = m_textRepeat.find(textGroup);
+ if (groupItr != m_textRepeat.end())
+ groupItr->second.clear();
+}
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index 764a57d4cef..966944e099f 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -83,7 +83,7 @@ struct CreatureTemplate
uint32 Modelid3;
uint32 Modelid4;
std::string Name;
- std::string SubName;
+ std::string Title;
std::string IconName;
uint32 GossipMenuId;
uint8 minlevel;
@@ -130,7 +130,6 @@ struct CreatureTemplate
float ModDamage;
float ModExperience;
bool RacialLeader;
- uint32 questItems[MAX_CREATURE_QUEST_ITEMS];
uint32 movementId;
bool RegenHealth;
uint32 MechanicImmuneMask;
@@ -138,6 +137,8 @@ struct CreatureTemplate
uint32 ScriptID;
uint32 GetRandomValidModelId() const;
uint32 GetFirstValidModelId() const;
+ uint32 GetFirstInvisibleModel() const;
+ uint32 GetFirstVisibleModel() const;
// helpers
SkillType GetRequiredLootSkill() const
@@ -167,6 +168,9 @@ struct CreatureTemplate
}
};
+typedef std::vector<uint32> CreatureQuestItemList;
+typedef std::unordered_map<uint32, CreatureQuestItemList> CreatureQuestItemMap;
+
// Benchmarked: Faster than std::map (insert/find)
typedef std::unordered_map<uint32, CreatureTemplate> CreatureTemplateContainer;
@@ -216,7 +220,7 @@ typedef std::unordered_map<uint16, CreatureBaseStats> CreatureBaseStatsContainer
struct CreatureLocale
{
StringVector Name;
- StringVector SubName;
+ StringVector Title;
};
struct GossipMenuItemsLocale
@@ -276,6 +280,7 @@ struct CreatureModelInfo
float combat_reach;
uint8 gender;
uint32 modelid_other_gender;
+ bool is_trigger;
};
// Benchmarked: Faster than std::map (insert/find)
@@ -315,7 +320,8 @@ struct CreatureAddon
std::vector<uint32> auras;
};
-typedef std::unordered_map<uint32, CreatureAddon> CreatureAddonContainer;
+typedef std::unordered_map<ObjectGuid::LowType, CreatureAddon> CreatureAddonContainer;
+typedef std::unordered_map<uint32, CreatureAddon> CreatureAddonTemplateContainer;
// Vendors
struct VendorItem
@@ -409,6 +415,10 @@ struct TrainerSpellData
#define MAX_VENDOR_ITEMS 150 // Limitation in 3.x.x item count in SMSG_LIST_INVENTORY
+//used for handling non-repeatable random texts
+typedef std::vector<uint8> CreatureTextRepeatIds;
+typedef std::unordered_map<uint8, CreatureTextRepeatIds> CreatureTextRepeatGroup;
+
class Creature : public Unit, public GridObject<Creature>, public MapObject
{
public:
@@ -424,12 +434,12 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
void DisappearAndDie();
- bool Create(uint32 guidlow, Map* map, uint32 phaseMask, uint32 entry, float x, float y, float z, float ang, CreatureData const* data = nullptr, uint32 vehId = 0);
- bool LoadCreaturesAddon(bool reload = false);
+ bool Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, uint32 entry, float x, float y, float z, float ang, CreatureData const* data = nullptr, uint32 vehId = 0);
+ bool LoadCreaturesAddon();
void SelectLevel();
void LoadEquipment(int8 id = 1, bool force = false);
- uint32 GetDBTableGUIDLow() const { return m_DBTableGuid; }
+ ObjectGuid::LowType GetSpawnId() const { return m_spawnId; }
void Update(uint32 time) override; // overwrited Unit::Update
void GetRespawnPosition(float &x, float &y, float &z, float* ori = nullptr, float* dist =nullptr) const;
@@ -445,7 +455,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
bool CanFly() const override { return (GetCreatureTemplate()->InhabitType & INHABIT_AIR) != 0; }
void SetReactState(ReactStates st) { m_reactState = st; }
- ReactStates GetReactState() { return m_reactState; }
+ ReactStates GetReactState() const { return m_reactState; }
bool HasReactState(ReactStates state) const { return (m_reactState == state); }
void InitializeReactState();
@@ -499,7 +509,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
void SetCanDualWield(bool value) override;
int8 GetOriginalEquipmentId() const { return m_originalEquipmentId; }
- uint8 GetCurrentEquipmentId() { return m_equipmentId; }
+ uint8 GetCurrentEquipmentId() const { return m_equipmentId; }
void SetCurrentEquipmentId(uint8 id) { m_equipmentId = id; }
float GetSpellDamageMod(int32 Rank) const;
@@ -523,8 +533,8 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
void setDeathState(DeathState s) override; // override virtual Unit::setDeathState
- bool LoadFromDB(uint32 guid, Map* map) { return LoadCreatureFromDB(guid, map, false); }
- bool LoadCreatureFromDB(uint32 guid, Map* map, bool addToMap = true);
+ bool LoadFromDB(ObjectGuid::LowType spawnId, Map* map) { return LoadCreatureFromDB(spawnId, map, false); }
+ bool LoadCreatureFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap = true);
void SaveToDB();
// overriden in Pet
virtual void SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask);
@@ -544,7 +554,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
void SetLootRecipient (Unit* unit);
void AllLootRemovedFromCorpse();
- uint16 GetLootMode() { return m_LootMode; }
+ uint16 GetLootMode() const { return m_LootMode; }
bool HasLootMode(uint16 lootMode) { return (m_LootMode & lootMode) != 0; }
void SetLootMode(uint16 lootMode) { m_LootMode = lootMode; }
void AddLootMode(uint16 lootMode) { m_LootMode |= lootMode; }
@@ -572,7 +582,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
void CallAssistance();
void SetNoCallAssistance(bool val) { m_AlreadyCallAssistance = val; }
void SetNoSearchAssistance(bool val) { m_AlreadySearchedAssistance = val; }
- bool HasSearchedAssistance() { return m_AlreadySearchedAssistance; }
+ bool HasSearchedAssistance() const { return m_AlreadySearchedAssistance; }
bool CanAssistTo(const Unit* u, const Unit* enemy, bool checkfaction = true) const;
bool _IsTargetAcceptable(const Unit* target) const;
@@ -595,8 +605,16 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
float GetRespawnRadius() const { return m_respawnradius; }
void SetRespawnRadius(float dist) { m_respawnradius = dist; }
+ uint32 GetCombatPulseDelay() const { return m_combatPulseDelay; }
+ void SetCombatPulseDelay(uint32 delay) // (secs) interval at which the creature pulses the entire zone into combat (only works in dungeons)
+ {
+ m_combatPulseDelay = delay;
+ if (m_combatPulseTime == 0 || m_combatPulseTime > delay)
+ m_combatPulseTime = delay;
+ }
+
uint32 m_groupLootTimer; // (msecs)timer used for group loot
- uint32 lootingGroupLowGUID; // used to find group which is looting corpse
+ ObjectGuid::LowType lootingGroupLowGUID; // used to find group which is looting corpse
void SendZoneUnderAttackMessage(Player* attacker);
@@ -636,7 +654,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
Unit* SelectVictim();
void SetDisableReputationGain(bool disable) { DisableReputationGain = disable; }
- bool IsReputationGainDisabled() { return DisableReputationGain; }
+ bool IsReputationGainDisabled() const { return DisableReputationGain; }
bool IsDamageEnoughForLootingAndReward() const { return m_PlayerDamageReq == 0; }
void LowerPlayerDamageReq(uint32 unDamage);
void ResetPlayerDamageReq() { m_PlayerDamageReq = GetHealth() / 2; }
@@ -656,8 +674,12 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
void FocusTarget(Spell const* focusSpell, WorldObject const* target);
void ReleaseFocus(Spell const* focusSpell);
+ CreatureTextRepeatIds GetTextRepeatGroup(uint8 textGroup);
+ void SetTextRepeatId(uint8 textGroup, uint8 id);
+ void ClearTextRepeatGroup(uint8 textGroup);
+
protected:
- bool CreateFromProto(uint32 guidlow, uint32 entry, CreatureData const* data = nullptr, uint32 vehId = 0);
+ bool CreateFromProto(ObjectGuid::LowType guidlow, uint32 entry, CreatureData const* data = nullptr, uint32 vehId = 0);
bool InitEntry(uint32 entry, CreatureData const* data = nullptr);
// vendor items
@@ -676,13 +698,15 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
uint32 m_respawnDelay; // (secs) delay between corpse disappearance and respawning
uint32 m_corpseDelay; // (secs) delay between death and corpse disappearance
float m_respawnradius;
+ uint32 m_combatPulseTime; // (msecs) remaining time for next zone-in-combat pulse
+ uint32 m_combatPulseDelay; // (secs) how often the creature puts the entire zone in combat (only works in dungeons)
ReactStates m_reactState; // for AI, not charmInfo
void RegenerateMana();
void RegenerateHealth();
void Regenerate(Powers power);
MovementGeneratorType m_defaultMovementType;
- uint32 m_DBTableGuid; ///< For new or temporary creatures is 0 for saved it is lowguid
+ ObjectGuid::LowType m_spawnId; ///< For new or temporary creatures is 0 for saved it is lowguid
uint8 m_equipmentId;
int8 m_originalEquipmentId; // can be -1
@@ -720,6 +744,8 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
bool TriggerJustRespawned;
Spell const* _focusSpell; ///> Locks the target during spell cast for proper facing
+
+ CreatureTextRepeatGroup m_textRepeat;
};
class AssistDelayEvent : public BasicEvent
diff --git a/src/server/game/Entities/Creature/CreatureGroups.cpp b/src/server/game/Entities/Creature/CreatureGroups.cpp
index 2ccf4471788..e8ce0acdc86 100644
--- a/src/server/game/Entities/Creature/CreatureGroups.cpp
+++ b/src/server/game/Entities/Creature/CreatureGroups.cpp
@@ -30,33 +30,33 @@ FormationMgr::~FormationMgr()
delete itr->second;
}
-void FormationMgr::AddCreatureToGroup(uint32 groupId, Creature* member)
+void FormationMgr::AddCreatureToGroup(uint32 leaderGuid, Creature* creature)
{
- Map* map = member->FindMap();
+ Map* map = creature->FindMap();
if (!map)
return;
- CreatureGroupHolderType::iterator itr = map->CreatureGroupHolder.find(groupId);
+ CreatureGroupHolderType::iterator itr = map->CreatureGroupHolder.find(leaderGuid);
//Add member to an existing group
if (itr != map->CreatureGroupHolder.end())
{
- TC_LOG_DEBUG("entities.unit", "Group found: %u, inserting creature GUID: %u, Group InstanceID %u", groupId, member->GetGUIDLow(), member->GetInstanceId());
- itr->second->AddMember(member);
+ TC_LOG_DEBUG("entities.unit", "Group found: %u, inserting creature GUID: %u, Group InstanceID %u", leaderGuid, creature->GetGUID().GetCounter(), creature->GetInstanceId());
+ itr->second->AddMember(creature);
}
//Create new group
else
{
- TC_LOG_DEBUG("entities.unit", "Group not found: %u. Creating new group.", groupId);
- CreatureGroup* group = new CreatureGroup(groupId);
- map->CreatureGroupHolder[groupId] = group;
- group->AddMember(member);
+ TC_LOG_DEBUG("entities.unit", "Group not found: %u. Creating new group.", leaderGuid);
+ CreatureGroup* group = new CreatureGroup(leaderGuid);
+ map->CreatureGroupHolder[leaderGuid] = group;
+ group->AddMember(creature);
}
}
void FormationMgr::RemoveCreatureFromGroup(CreatureGroup* group, Creature* member)
{
- TC_LOG_DEBUG("entities.unit", "Deleting member pointer to GUID: %u from group %u", group->GetId(), member->GetDBTableGUIDLow());
+ TC_LOG_DEBUG("entities.unit", "Deleting member pointer to GUID: %u from group %u", group->GetId(), member->GetSpawnId());
group->RemoveMember(member);
if (group->isEmpty())
@@ -142,16 +142,16 @@ void FormationMgr::LoadCreatureFormations()
void CreatureGroup::AddMember(Creature* member)
{
- TC_LOG_DEBUG("entities.unit", "CreatureGroup::AddMember: Adding unit GUID: %u.", member->GetGUIDLow());
+ TC_LOG_DEBUG("entities.unit", "CreatureGroup::AddMember: Adding unit GUID: %u.", member->GetGUID().GetCounter());
//Check if it is a leader
- if (member->GetDBTableGUIDLow() == m_groupID)
+ if (member->GetSpawnId() == m_groupID)
{
- TC_LOG_DEBUG("entities.unit", "Unit GUID: %u is formation leader. Adding group.", member->GetGUIDLow());
+ TC_LOG_DEBUG("entities.unit", "Unit GUID: %u is formation leader. Adding group.", member->GetGUID().GetCounter());
m_leader = member;
}
- m_members[member] = sFormationMgr->CreatureGroupMap.find(member->GetDBTableGUIDLow())->second;
+ m_members[member] = sFormationMgr->CreatureGroupMap.find(member->GetSpawnId())->second;
member->SetFormation(this);
}
@@ -166,7 +166,7 @@ void CreatureGroup::RemoveMember(Creature* member)
void CreatureGroup::MemberAttackStart(Creature* member, Unit* target)
{
- uint8 groupAI = sFormationMgr->CreatureGroupMap[member->GetDBTableGUIDLow()]->groupAI;
+ uint8 groupAI = sFormationMgr->CreatureGroupMap[member->GetSpawnId()]->groupAI;
if (!groupAI)
return;
@@ -205,7 +205,7 @@ void CreatureGroup::FormationReset(bool dismiss)
itr->first->GetMotionMaster()->Initialize();
else
itr->first->GetMotionMaster()->MoveIdle();
- TC_LOG_DEBUG("entities.unit", "Set %s movement for member GUID: %u", dismiss ? "default" : "idle", itr->first->GetGUIDLow());
+ TC_LOG_DEBUG("entities.unit", "Set %s movement for member GUID: %u", dismiss ? "default" : "idle", itr->first->GetGUID().GetCounter());
}
}
m_Formed = !dismiss;
@@ -227,12 +227,8 @@ void CreatureGroup::LeaderMoveTo(float x, float y, float z)
continue;
if (itr->second->point_1)
- {
- if (m_leader->GetCurrentWaypointID() == itr->second->point_1)
- itr->second->follow_angle = (2 * float(M_PI)) - itr->second->follow_angle;
- if (m_leader->GetCurrentWaypointID() == itr->second->point_2)
- itr->second->follow_angle = (2 * float(M_PI)) + itr->second->follow_angle;
- }
+ if (m_leader->GetCurrentWaypointID() == itr->second->point_1 - 1 || m_leader->GetCurrentWaypointID() == itr->second->point_2 - 1)
+ itr->second->follow_angle = float(M_PI) * 2 - itr->second->follow_angle;
float angle = itr->second->follow_angle;
float dist = itr->second->follow_dist;
@@ -244,7 +240,8 @@ void CreatureGroup::LeaderMoveTo(float x, float y, float z)
Trinity::NormalizeMapCoord(dx);
Trinity::NormalizeMapCoord(dy);
- member->UpdateGroundPositionZ(dx, dy, dz);
+ if (!member->IsFlying())
+ member->UpdateGroundPositionZ(dx, dy, dz);
if (member->IsWithinDist(m_leader, dist + MAX_DESYNC))
member->SetUnitMovementFlags(m_leader->GetUnitMovementFlags());
diff --git a/src/server/game/Entities/Creature/CreatureGroups.h b/src/server/game/Entities/Creature/CreatureGroups.h
index e4b2f63c1a3..3de1370379b 100644
--- a/src/server/game/Entities/Creature/CreatureGroups.h
+++ b/src/server/game/Entities/Creature/CreatureGroups.h
@@ -32,8 +32,8 @@ struct FormationInfo
float follow_dist;
float follow_angle;
uint8 groupAI;
- uint16 point_1;
- uint16 point_2;
+ uint32 point_1;
+ uint32 point_2;
};
typedef std::unordered_map<uint32/*memberDBGUID*/, FormationInfo*> CreatureGroupInfoType;
diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp
index c8a251394cc..db67f1f74f1 100644
--- a/src/server/game/Entities/Creature/GossipDef.cpp
+++ b/src/server/game/Entities/Creature/GossipDef.cpp
@@ -19,8 +19,6 @@
#include "QuestDef.h"
#include "GossipDef.h"
#include "ObjectMgr.h"
-#include "Opcodes.h"
-#include "WorldPacket.h"
#include "WorldSession.h"
#include "Formulas.h"
@@ -383,10 +381,10 @@ void PlayerMenu::SendQuestGiverStatus(uint8 questStatus, ObjectGuid npcGUID) con
void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGUID, bool activateAccept) const
{
- std::string questTitle = quest->GetTitle();
- std::string questDetails = quest->GetDetails();
- std::string questObjectives = quest->GetObjectives();
- std::string questEndText = quest->GetEndText();
+ std::string questTitle = quest->GetTitle();
+ std::string questDetails = quest->GetDetails();
+ std::string questObjectives = quest->GetObjectives();
+ std::string questAreaDescription = quest->GetAreaDescription();
int32 locale = _session->GetSessionDbLocaleIndex();
if (locale >= 0)
@@ -396,7 +394,7 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGU
ObjectMgr::GetLocaleString(localeData->Title, locale, questTitle);
ObjectMgr::GetLocaleString(localeData->Details, locale, questDetails);
ObjectMgr::GetLocaleString(localeData->Objectives, locale, questObjectives);
- ObjectMgr::GetLocaleString(localeData->EndText, locale, questEndText);
+ ObjectMgr::GetLocaleString(localeData->AreaDescription, locale, questAreaDescription);
}
}
@@ -491,11 +489,11 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGU
void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
{
- std::string questTitle = quest->GetTitle();
- std::string questDetails = quest->GetDetails();
- std::string questObjectives = quest->GetObjectives();
- std::string questEndText = quest->GetEndText();
- std::string questCompletedText = quest->GetCompletedText();
+ std::string questTitle = quest->GetTitle();
+ std::string questDetails = quest->GetDetails();
+ std::string questObjectives = quest->GetObjectives();
+ std::string questAreaDescription = quest->GetAreaDescription();
+ std::string questCompletedText = quest->GetCompletedText();
std::string questObjectiveText[QUEST_OBJECTIVES_COUNT];
for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
@@ -509,7 +507,7 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
ObjectMgr::GetLocaleString(localeData->Title, locale, questTitle);
ObjectMgr::GetLocaleString(localeData->Details, locale, questDetails);
ObjectMgr::GetLocaleString(localeData->Objectives, locale, questObjectives);
- ObjectMgr::GetLocaleString(localeData->EndText, locale, questEndText);
+ ObjectMgr::GetLocaleString(localeData->AreaDescription, locale, questAreaDescription);
ObjectMgr::GetLocaleString(localeData->CompletedText, locale, questCompletedText);
for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
@@ -587,9 +585,9 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
for (uint8 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // unk (0)
data << int32(quest->RewardFactionValueIdOverride[i]);
- data << uint32(quest->GetPointMapId());
- data << float(quest->GetPointX());
- data << float(quest->GetPointY());
+ data << uint32(quest->GetPOIContinent());
+ data << float(quest->GetPOIx());
+ data << float(quest->GetPOIy());
data << uint32(quest->GetPointOpt());
if (sWorld->getBoolConfig(CONFIG_UI_QUESTLEVELS_IN_DIALOGS))
@@ -598,7 +596,7 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
data << questTitle;
data << questObjectives;
data << questDetails;
- data << questEndText;
+ data << questAreaDescription;
data << questCompletedText; // display in quest objectives window once all objectives are completed
for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
@@ -609,7 +607,7 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
data << uint32(quest->RequiredNpcOrGo[i]);
data << uint32(quest->RequiredNpcOrGoCount[i]);
- data << uint32(quest->RequiredSourceItemId[i]);
+ data << uint32(quest->ItemDrop[i]);
data << uint32(0); // req source count?
}
diff --git a/src/server/game/Entities/Creature/TemporarySummon.cpp b/src/server/game/Entities/Creature/TemporarySummon.cpp
index 2a3e91b7574..46422444bbb 100644
--- a/src/server/game/Entities/Creature/TemporarySummon.cpp
+++ b/src/server/game/Entities/Creature/TemporarySummon.cpp
@@ -368,7 +368,7 @@ void Puppet::InitSummon()
{
Minion::InitSummon();
if (!SetCharmedBy(GetOwner(), CHARM_TYPE_POSSESS))
- ASSERT(false);
+ ABORT();
}
void Puppet::Update(uint32 time)
diff --git a/src/server/game/Entities/Creature/TemporarySummon.h b/src/server/game/Entities/Creature/TemporarySummon.h
index 16fd7c11683..68c6cbb70e5 100644
--- a/src/server/game/Entities/Creature/TemporarySummon.h
+++ b/src/server/game/Entities/Creature/TemporarySummon.h
@@ -53,7 +53,7 @@ class TempSummon : public Creature
Creature* GetSummonerCreatureBase() const;
ObjectGuid GetSummonerGUID() const { return m_summonerGUID; }
TempSummonType const& GetSummonType() { return m_type; }
- uint32 GetTimer() { return m_timer; }
+ uint32 GetTimer() const { return m_timer; }
const SummonPropertiesEntry* const m_Properties;
private:
diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.cpp b/src/server/game/Entities/DynamicObject/DynamicObject.cpp
index 71d0f13488c..3d92f9e18cf 100644
--- a/src/server/game/Entities/DynamicObject/DynamicObject.cpp
+++ b/src/server/game/Entities/DynamicObject/DynamicObject.cpp
@@ -51,7 +51,7 @@ void DynamicObject::AddToWorld()
///- Register the dynamicObject for guid lookup and for caster
if (!IsInWorld())
{
- sObjectAccessor->AddObject(this);
+ GetMap()->GetObjectsStore().Insert<DynamicObject>(GetGUID(), this);
WorldObject::AddToWorld();
BindToCaster();
}
@@ -74,11 +74,12 @@ void DynamicObject::RemoveFromWorld()
UnbindFromCaster();
WorldObject::RemoveFromWorld();
- sObjectAccessor->RemoveObject(this);
+ GetMap()->GetObjectsStore().Remove<DynamicObject>(GetGUID());
+
}
}
-bool DynamicObject::CreateDynamicObject(uint32 guidlow, Unit* caster, uint32 spellId, Position const& pos, float radius, DynamicObjectType type)
+bool DynamicObject::CreateDynamicObject(ObjectGuid::LowType guidlow, Unit* caster, uint32 spellId, Position const& pos, float radius, DynamicObjectType type)
{
SetMap(caster->GetMap());
Relocate(pos);
@@ -88,7 +89,7 @@ bool DynamicObject::CreateDynamicObject(uint32 guidlow, Unit* caster, uint32 spe
return false;
}
- WorldObject::_Create(guidlow, HIGHGUID_DYNAMICOBJECT, caster->GetPhaseMask());
+ WorldObject::_Create(guidlow, HighGuid::DynamicObject, caster->GetPhaseMask());
SetEntry(spellId);
SetObjectScale(1);
diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.h b/src/server/game/Entities/DynamicObject/DynamicObject.h
index f850573ec5a..44c771c77c4 100644
--- a/src/server/game/Entities/DynamicObject/DynamicObject.h
+++ b/src/server/game/Entities/DynamicObject/DynamicObject.h
@@ -41,7 +41,7 @@ class DynamicObject : public WorldObject, public GridObject<DynamicObject>, publ
void AddToWorld() override;
void RemoveFromWorld() override;
- bool CreateDynamicObject(uint32 guidlow, Unit* caster, uint32 spellId, Position const& pos, float radius, DynamicObjectType type);
+ bool CreateDynamicObject(ObjectGuid::LowType guidlow, Unit* caster, uint32 spellId, Position const& pos, float radius, DynamicObjectType type);
void Update(uint32 p_time) override;
void Remove();
void SetDuration(int32 newDuration);
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index a4b140b9878..c1ec2294c3d 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -52,7 +52,7 @@ GameObject::GameObject() : WorldObject(false), MapObject(),
m_goInfo = NULL;
m_goData = NULL;
- m_DBTableGuid = 0;
+ m_spawnId = 0;
m_rotation = 0;
m_lootRecipientGroup = 0;
@@ -113,8 +113,9 @@ void GameObject::RemoveFromOwner()
return;
}
- TC_LOG_FATAL("misc", "Removed GameObject (GUID: %u Entry: %u SpellId: %u LinkedGO: %u) that just lost any reference to the owner (%s) GO list",
- GetGUIDLow(), GetGOInfo()->entry, m_spellId, GetGOInfo()->GetLinkedGameObjectEntry(), ownerGUID.ToString().c_str());
+ // This happens when a mage portal is despawned after the caster changes map (for example using the portal)
+ TC_LOG_DEBUG("misc", "Removed GameObject (GUID: %u Entry: %u SpellId: %u LinkedGO: %u) that just lost any reference to the owner (%s) GO list",
+ GetGUID().GetCounter(), GetGOInfo()->entry, m_spellId, GetGOInfo()->GetLinkedGameObjectEntry(), ownerGUID.ToString().c_str());
SetOwnerGUID(ObjectGuid::Empty);
}
@@ -126,7 +127,9 @@ void GameObject::AddToWorld()
if (m_zoneScript)
m_zoneScript->OnGameObjectCreate(this);
- sObjectAccessor->AddObject(this);
+ GetMap()->GetObjectsStore().Insert<GameObject>(GetGUID(), this);
+ if (m_spawnId)
+ GetMap()->GetGameObjectBySpawnIdStore().insert(std::make_pair(m_spawnId, this));
// The state can be changed after GameObject::Create but before GameObject::AddToWorld
bool toggledState = GetGoType() == GAMEOBJECT_TYPE_CHEST ? getLootState() == GO_READY : (GetGoState() == GO_STATE_READY || IsTransport());
@@ -155,12 +158,16 @@ void GameObject::RemoveFromWorld()
if (m_model)
if (GetMap()->ContainsGameObjectModel(*m_model))
GetMap()->RemoveGameObjectModel(*m_model);
+
WorldObject::RemoveFromWorld();
- sObjectAccessor->RemoveObject(this);
+
+ if (m_spawnId)
+ Trinity::Containers::MultimapErasePair(GetMap()->GetGameObjectBySpawnIdStore(), m_spawnId, this);
+ GetMap()->GetObjectsStore().Remove<GameObject>(GetGUID());
}
}
-bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMask, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, GOState go_state, uint32 artKit)
+bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, uint32 phaseMask, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, GOState go_state, uint32 artKit)
{
ASSERT(map);
SetMap(map);
@@ -199,7 +206,7 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMa
if (goinfo->type == GAMEOBJECT_TYPE_TRANSPORT)
m_updateFlag = (m_updateFlag | UPDATEFLAG_TRANSPORT) & ~UPDATEFLAG_POSITION;
- Object::_Create(guidlow, goinfo->entry, HIGHGUID_GAMEOBJECT);
+ Object::_Create(guidlow, goinfo->entry, HighGuid::GameObject);
m_goInfo = goinfo;
@@ -226,7 +233,7 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMa
SetDisplayId(goinfo->displayId);
- m_model = GameObjectModel::Create(*this);
+ m_model = CreateModel();
// GAMEOBJECT_BYTES_1, index at 0, 1, 2 and 3
SetGoType(GameobjectTypes(goinfo->type));
SetGoState(go_state);
@@ -272,7 +279,7 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMa
break;
}
- if (GameObjectAddon const* addon = sObjectMgr->GetGameObjectAddon(guidlow))
+ if (GameObjectAddon const* addon = sObjectMgr->GetGameObjectAddon(GetSpawnId()))
{
if (addon->InvisibilityValue)
{
@@ -389,7 +396,7 @@ void GameObject::Update(uint32 diff)
time_t now = time(NULL);
if (m_respawnTime <= now) // timer expired
{
- ObjectGuid dbtableHighGuid(HIGHGUID_GAMEOBJECT, GetEntry(), m_DBTableGuid);
+ ObjectGuid dbtableHighGuid(HighGuid::GameObject, GetEntry(), m_spawnId);
time_t linkedRespawntime = GetMap()->GetLinkedRespawnTime(dbtableHighGuid);
if (linkedRespawntime) // Can't respawn, the master is dead
{
@@ -445,9 +452,9 @@ void GameObject::Update(uint32 diff)
}
// Respawn timer
- uint32 poolid = GetDBTableGUIDLow() ? sPoolMgr->IsPartOfAPool<GameObject>(GetDBTableGUIDLow()) : 0;
+ uint32 poolid = GetSpawnId() ? sPoolMgr->IsPartOfAPool<GameObject>(GetSpawnId()) : 0;
if (poolid)
- sPoolMgr->UpdatePool<GameObject>(poolid, GetDBTableGUIDLow());
+ sPoolMgr->UpdatePool<GameObject>(poolid, GetSpawnId());
else
GetMap()->AddToMap(this);
}
@@ -685,9 +692,9 @@ void GameObject::Delete()
SetGoState(GO_STATE_READY);
SetUInt32Value(GAMEOBJECT_FLAGS, GetGOInfo()->flags);
- uint32 poolid = GetDBTableGUIDLow() ? sPoolMgr->IsPartOfAPool<GameObject>(GetDBTableGUIDLow()) : 0;
+ uint32 poolid = GetSpawnId() ? sPoolMgr->IsPartOfAPool<GameObject>(GetSpawnId()) : 0;
if (poolid)
- sPoolMgr->UpdatePool<GameObject>(poolid, GetDBTableGUIDLow());
+ sPoolMgr->UpdatePool<GameObject>(poolid, GetSpawnId());
else
AddObjectToRemoveList();
}
@@ -736,7 +743,7 @@ void GameObject::SaveToDB()
{
// this should only be used when the gameobject has already been loaded
// preferably after adding to map, because mapid may not be valid otherwise
- GameObjectData const* data = sObjectMgr->GetGOData(m_DBTableGuid);
+ GameObjectData const* data = sObjectMgr->GetGOData(m_spawnId);
if (!data)
{
TC_LOG_ERROR("misc", "GameObject::SaveToDB failed, cannot get gameobject data!");
@@ -753,10 +760,11 @@ void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
if (!goI)
return;
- if (!m_DBTableGuid)
- m_DBTableGuid = GetGUIDLow();
+ if (!m_spawnId)
+ m_spawnId = sObjectMgr->GenerateGameObjectSpawnId();
+
// update in loaded data (changing data only in this place)
- GameObjectData& data = sObjectMgr->NewGOData(m_DBTableGuid);
+ GameObjectData& data = sObjectMgr->NewGOData(m_spawnId);
// data->guid = guid must not be updated at save
data.id = GetEntry();
@@ -782,11 +790,11 @@ void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
uint8 index = 0;
PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_GAMEOBJECT);
- stmt->setUInt32(0, m_DBTableGuid);
+ stmt->setUInt32(0, m_spawnId);
trans->Append(stmt);
stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_GAMEOBJECT);
- stmt->setUInt32(index++, m_DBTableGuid);
+ stmt->setUInt32(index++, m_spawnId);
stmt->setUInt32(index++, GetEntry());
stmt->setUInt16(index++, uint16(mapid));
stmt->setUInt8(index++, spawnMask);
@@ -807,13 +815,13 @@ void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
WorldDatabase.CommitTransaction(trans);
}
-bool GameObject::LoadGameObjectFromDB(uint32 guid, Map* map, bool addToMap)
+bool GameObject::LoadGameObjectFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap)
{
- GameObjectData const* data = sObjectMgr->GetGOData(guid);
+ GameObjectData const* data = sObjectMgr->GetGOData(spawnId);
if (!data)
{
- TC_LOG_ERROR("sql.sql", "Gameobject (GUID: %u) not found in table `gameobject`, can't load. ", guid);
+ TC_LOG_ERROR("sql.sql", "Gameobject (GUID: %u) not found in table `gameobject`, can't load. ", spawnId);
return false;
}
@@ -834,10 +842,8 @@ bool GameObject::LoadGameObjectFromDB(uint32 guid, Map* map, bool addToMap)
GOState go_state = data->go_state;
uint32 artKit = data->artKit;
- m_DBTableGuid = guid;
- if (map->GetInstanceId() != 0) guid = sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT);
-
- if (!Create(guid, entry, map, phaseMask, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, animprogress, go_state, artKit))
+ m_spawnId = spawnId;
+ if (!Create(map->GenerateLowGuid<HighGuid::GameObject>(), entry, map, phaseMask, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, animprogress, go_state, artKit))
return false;
if (data->spawntimesecs >= 0)
@@ -853,13 +859,13 @@ bool GameObject::LoadGameObjectFromDB(uint32 guid, Map* map, bool addToMap)
else
{
m_respawnDelayTime = data->spawntimesecs;
- m_respawnTime = GetMap()->GetGORespawnTime(m_DBTableGuid);
+ m_respawnTime = GetMap()->GetGORespawnTime(m_spawnId);
// ready to respawn
if (m_respawnTime && m_respawnTime <= time(NULL))
{
m_respawnTime = 0;
- GetMap()->RemoveGORespawnTime(m_DBTableGuid);
+ GetMap()->RemoveGORespawnTime(m_spawnId);
}
}
}
@@ -880,18 +886,18 @@ bool GameObject::LoadGameObjectFromDB(uint32 guid, Map* map, bool addToMap)
void GameObject::DeleteFromDB()
{
- GetMap()->RemoveGORespawnTime(m_DBTableGuid);
- sObjectMgr->DeleteGOData(m_DBTableGuid);
+ GetMap()->RemoveGORespawnTime(m_spawnId);
+ sObjectMgr->DeleteGOData(m_spawnId);
PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_GAMEOBJECT);
- stmt->setUInt32(0, m_DBTableGuid);
+ stmt->setUInt32(0, m_spawnId);
WorldDatabase.Execute(stmt);
stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_EVENT_GAMEOBJECT);
- stmt->setUInt32(0, m_DBTableGuid);
+ stmt->setUInt32(0, m_spawnId);
WorldDatabase.Execute(stmt);
}
@@ -959,7 +965,7 @@ Unit* GameObject::GetOwner() const
void GameObject::SaveRespawnTime()
{
if (m_goData && m_goData->dbData && m_respawnTime > time(NULL) && m_spawnedByDefault)
- GetMap()->SaveGORespawnTime(m_DBTableGuid, m_respawnTime);
+ GetMap()->SaveGORespawnTime(m_spawnId, m_respawnTime);
}
bool GameObject::IsNeverVisible() const
@@ -1016,7 +1022,7 @@ void GameObject::Respawn()
if (m_spawnedByDefault && m_respawnTime > 0)
{
m_respawnTime = time(NULL);
- GetMap()->RemoveGORespawnTime(m_DBTableGuid);
+ GetMap()->RemoveGORespawnTime(m_spawnId);
}
}
@@ -1141,12 +1147,12 @@ void GameObject::UseDoorOrButton(uint32 time_to_restore, bool alternative /* = f
void GameObject::SetGoArtKit(uint8 kit)
{
SetByteValue(GAMEOBJECT_BYTES_1, 2, kit);
- GameObjectData* data = const_cast<GameObjectData*>(sObjectMgr->GetGOData(m_DBTableGuid));
+ GameObjectData* data = const_cast<GameObjectData*>(sObjectMgr->GetGOData(m_spawnId));
if (data)
data->artKit = kit;
}
-void GameObject::SetGoArtKit(uint8 artkit, GameObject* go, uint32 lowguid)
+void GameObject::SetGoArtKit(uint8 artkit, GameObject* go, ObjectGuid::LowType lowguid)
{
const GameObjectData* data = NULL;
if (go)
@@ -1334,7 +1340,7 @@ void GameObject::Use(Unit* user)
if (info->goober.eventId)
{
- TC_LOG_DEBUG("maps.script", "Goober ScriptStart id %u for GO entry %u (GUID %u).", info->goober.eventId, GetEntry(), GetDBTableGUIDLow());
+ TC_LOG_DEBUG("maps.script", "Goober ScriptStart id %u for GO entry %u (GUID %u).", info->goober.eventId, GetEntry(), GetSpawnId());
GetMap()->ScriptsStart(sEventScripts, info->goober.eventId, player, this);
EventInform(info->goober.eventId, user);
}
@@ -1740,7 +1746,7 @@ void GameObject::Use(Unit* user)
default:
if (GetGoType() >= MAX_GAMEOBJECT_TYPE)
TC_LOG_ERROR("misc", "GameObject::Use(): unit (type: %u, guid: %u, name: %s) tries to use object (guid: %u, entry: %u, name: %s) of unknown type (%u)",
- user->GetTypeId(), user->GetGUIDLow(), user->GetName().c_str(), GetGUIDLow(), GetEntry(), GetGOInfo()->name.c_str(), GetGoType());
+ user->GetTypeId(), user->GetGUID().GetCounter(), user->GetName().c_str(), GetGUID().GetCounter(), GetEntry(), GetGOInfo()->name.c_str(), GetGoType());
break;
}
@@ -1757,6 +1763,9 @@ void GameObject::Use(Unit* user)
return;
}
+ if (Player* player = user->ToPlayer())
+ sOutdoorPvPMgr->HandleCustomSpell(player, spellId, this);
+
if (spellCaster)
spellCaster->CastSpell(user, spellInfo, triggered);
else
@@ -2125,7 +2134,7 @@ void GameObject::UpdateModel()
if (GetMap()->ContainsGameObjectModel(*m_model))
GetMap()->RemoveGameObjectModel(*m_model);
delete m_model;
- m_model = GameObjectModel::Create(*this);
+ m_model = CreateModel();
if (m_model)
GetMap()->InsertGameObjectModel(*m_model);
}
@@ -2250,12 +2259,12 @@ void GameObject::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* t
}
else if (index == GAMEOBJECT_FLAGS)
{
- uint32 flags = m_uint32Values[GAMEOBJECT_FLAGS];
+ uint32 goFlags = m_uint32Values[GAMEOBJECT_FLAGS];
if (GetGoType() == GAMEOBJECT_TYPE_CHEST)
if (GetGOInfo()->chest.groupLootRules && !IsLootAllowedFor(target))
- flags |= GO_FLAG_LOCKED | GO_FLAG_NOT_SELECTABLE;
+ goFlags |= GO_FLAG_LOCKED | GO_FLAG_NOT_SELECTABLE;
- fieldBuffer << flags;
+ fieldBuffer << goFlags;
}
else
fieldBuffer << m_uint32Values[index]; // other cases
@@ -2269,9 +2278,9 @@ void GameObject::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* t
void GameObject::GetRespawnPosition(float &x, float &y, float &z, float* ori /* = NULL*/) const
{
- if (m_DBTableGuid)
+ if (m_spawnId)
{
- if (GameObjectData const* data = sObjectMgr->GetGOData(GetDBTableGUIDLow()))
+ if (GameObjectData const* data = sObjectMgr->GetGOData(GetSpawnId()))
{
x = data->posX;
y = data->posY;
@@ -2314,7 +2323,29 @@ void GameObject::UpdateModelPosition()
if (GetMap()->ContainsGameObjectModel(*m_model))
{
GetMap()->RemoveGameObjectModel(*m_model);
- m_model->Relocate(*this);
+ m_model->UpdatePosition();
GetMap()->InsertGameObjectModel(*m_model);
}
}
+
+class GameObjectModelOwnerImpl : public GameObjectModelOwnerBase
+{
+public:
+ explicit GameObjectModelOwnerImpl(GameObject const* owner) : _owner(owner) { }
+
+ virtual bool IsSpawned() const override { return _owner->isSpawned(); }
+ virtual uint32 GetDisplayId() const override { return _owner->GetDisplayId(); }
+ virtual uint32 GetPhaseMask() const override { return _owner->GetPhaseMask(); }
+ virtual G3D::Vector3 GetPosition() const override { return G3D::Vector3(_owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ()); }
+ virtual float GetOrientation() const override { return _owner->GetOrientation(); }
+ virtual float GetScale() const override { return _owner->GetObjectScale(); }
+ virtual void DebugVisualizeCorner(G3D::Vector3 const& corner) const override { _owner->SummonCreature(1, corner.x, corner.y, corner.z, 0, TEMPSUMMON_MANUAL_DESPAWN); }
+
+private:
+ GameObject const* _owner;
+};
+
+GameObjectModel* GameObject::CreateModel()
+{
+ return GameObjectModel::Create(Trinity::make_unique<GameObjectModelOwnerImpl>(this), sWorld->GetDataPath());
+}
diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h
index 5f1d2c793e6..a744efbe1e3 100644
--- a/src/server/game/Entities/GameObject/GameObject.h
+++ b/src/server/game/Entities/GameObject/GameObject.h
@@ -45,7 +45,6 @@ struct GameObjectTemplate
uint32 faction;
uint32 flags;
float size;
- uint32 questItems[MAX_GAMEOBJECT_QUEST_ITEMS];
union // different GO types have different data field
{
//0 GAMEOBJECT_TYPE_DOOR
@@ -620,6 +619,9 @@ struct GameObjectData
bool dbData;
};
+typedef std::vector<uint32> GameObjectQuestItemList;
+typedef std::unordered_map<uint32, GameObjectQuestItemList> GameObjectQuestItemMap;
+
// For containers: [GO_NOT_READY]->GO_READY (close)->GO_ACTIVATED (open) ->GO_JUST_DEACTIVATED->GO_READY -> ...
// For bobber: GO_NOT_READY ->GO_READY (close)->GO_ACTIVATED (open) ->GO_JUST_DEACTIVATED-><deleted>
// For door(closed):[GO_NOT_READY]->GO_READY (close)->GO_ACTIVATED (open) ->GO_JUST_DEACTIVATED->GO_READY(close) -> ...
@@ -650,7 +652,7 @@ class GameObject : public WorldObject, public GridObject<GameObject>, public Map
void RemoveFromWorld() override;
void CleanupsBeforeDelete(bool finalCleanup = true) override;
- bool Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMask, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, GOState go_state, uint32 artKit = 0);
+ bool Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, uint32 phaseMask, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, GOState go_state, uint32 artKit = 0);
void Update(uint32 p_time) override;
GameObjectTemplate const* GetGOInfo() const { return m_goInfo; }
GameObjectData const* GetGOData() const { return m_goData; }
@@ -660,7 +662,7 @@ class GameObject : public WorldObject, public GridObject<GameObject>, public Map
bool IsDynTransport() const;
bool IsDestructibleBuilding() const;
- uint32 GetDBTableGUIDLow() const { return m_DBTableGuid; }
+ ObjectGuid::LowType GetSpawnId() const { return m_spawnId; }
void UpdateRotationFields(float rotation2 = 0.0f, float rotation3 = 0.0f);
@@ -669,8 +671,8 @@ class GameObject : public WorldObject, public GridObject<GameObject>, public Map
void SaveToDB();
void SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask);
- bool LoadFromDB(uint32 guid, Map* map) { return LoadGameObjectFromDB(guid, map, false); }
- bool LoadGameObjectFromDB(uint32 guid, Map* map, bool addToMap = true);
+ bool LoadFromDB(ObjectGuid::LowType spawnId, Map* map) { return LoadGameObjectFromDB(spawnId, map, false); }
+ bool LoadGameObjectFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap = true);
void DeleteFromDB();
void SetOwnerGUID(ObjectGuid owner)
@@ -678,7 +680,7 @@ class GameObject : public WorldObject, public GridObject<GameObject>, public Map
// Owner already found and different than expected owner - remove object from old owner
if (owner && GetOwnerGUID() && GetOwnerGUID() != owner)
{
- ASSERT(false);
+ ABORT();
}
m_spawnedByDefault = false; // all object with owner is despawned after delay
SetGuidValue(OBJECT_FIELD_CREATED_BY, owner);
@@ -731,9 +733,9 @@ class GameObject : public WorldObject, public GridObject<GameObject>, public Map
void SetGoArtKit(uint8 artkit);
uint8 GetGoAnimProgress() const { return GetByteValue(GAMEOBJECT_BYTES_1, 3); }
void SetGoAnimProgress(uint8 animprogress) { SetByteValue(GAMEOBJECT_BYTES_1, 3, animprogress); }
- static void SetGoArtKit(uint8 artkit, GameObject* go, uint32 lowguid = 0);
+ static void SetGoArtKit(uint8 artkit, GameObject* go, ObjectGuid::LowType lowguid = 0);
- void SetPhaseMask(uint32 newPhaseMask, bool update);
+ void SetPhaseMask(uint32 newPhaseMask, bool update) override;
void EnableCollision(bool enable);
void Use(Unit* user);
@@ -742,17 +744,17 @@ class GameObject : public WorldObject, public GridObject<GameObject>, public Map
// Note: unit is only used when s = GO_ACTIVATED
void SetLootState(LootState s, Unit* unit = NULL);
- uint16 GetLootMode() { return m_LootMode; }
- bool HasLootMode(uint16 lootMode) { return (m_LootMode & lootMode) != 0; }
+ uint16 GetLootMode() const { return m_LootMode; }
+ bool HasLootMode(uint16 lootMode) const { return (m_LootMode & lootMode) != 0; }
void SetLootMode(uint16 lootMode) { m_LootMode = lootMode; }
void AddLootMode(uint16 lootMode) { m_LootMode |= lootMode; }
void RemoveLootMode(uint16 lootMode) { m_LootMode &= ~lootMode; }
void ResetLootMode() { m_LootMode = LOOT_MODE_DEFAULT; }
- void AddToSkillupList(uint32 PlayerGuidLow) { m_SkillupList.push_back(PlayerGuidLow); }
- bool IsInSkillupList(uint32 PlayerGuidLow) const
+ void AddToSkillupList(ObjectGuid::LowType PlayerGuidLow) { m_SkillupList.push_back(PlayerGuidLow); }
+ bool IsInSkillupList(ObjectGuid::LowType PlayerGuidLow) const
{
- for (std::list<uint32>::const_iterator i = m_SkillupList.begin(); i != m_SkillupList.end(); ++i)
+ for (std::list<ObjectGuid::LowType>::const_iterator i = m_SkillupList.begin(); i != m_SkillupList.end(); ++i)
if (*i == PlayerGuidLow)
return true;
@@ -776,7 +778,7 @@ class GameObject : public WorldObject, public GridObject<GameObject>, public Map
bool IsLootAllowedFor(Player const* player) const;
bool HasLootRecipient() const { return !m_lootRecipient.IsEmpty() || m_lootRecipientGroup; }
uint32 m_groupLootTimer; // (msecs)timer used for group loot
- uint32 lootingGroupLowGUID; // used to find group which is looting
+ ObjectGuid::LowType lootingGroupLowGUID; // used to find group which is looting
bool hasQuest(uint32 quest_id) const override;
bool hasInvolvedQuest(uint32 quest_id) const override;
@@ -841,6 +843,7 @@ class GameObject : public WorldObject, public GridObject<GameObject>, public Map
float GetStationaryY() const override { if (GetGOInfo()->type != GAMEOBJECT_TYPE_MO_TRANSPORT) return m_stationaryPosition.GetPositionY(); return GetPositionY(); }
float GetStationaryZ() const override { if (GetGOInfo()->type != GAMEOBJECT_TYPE_MO_TRANSPORT) return m_stationaryPosition.GetPositionZ(); return GetPositionZ(); }
float GetStationaryO() const override { if (GetGOInfo()->type != GAMEOBJECT_TYPE_MO_TRANSPORT) return m_stationaryPosition.GetOrientation(); return GetOrientation(); }
+ void RelocateStationaryPosition(float x, float y, float z, float o) { m_stationaryPosition.Relocate(x, y, z, o); }
float GetInteractionDistance();
@@ -848,6 +851,7 @@ class GameObject : public WorldObject, public GridObject<GameObject>, public Map
protected:
bool AIM_Initialize();
+ GameObjectModel* CreateModel();
void UpdateModel(); // updates model in case displayId were changed
uint32 m_spellId;
time_t m_respawnTime; // (secs) time of next respawn (or despawn if GO have owner()),
@@ -857,7 +861,7 @@ class GameObject : public WorldObject, public GridObject<GameObject>, public Map
bool m_spawnedByDefault;
time_t m_cooldownTime; // used as internal reaction delay time store (not state change reaction).
// For traps this: spell casting cooldown, for doors/buttons: reset time.
- std::list<uint32> m_SkillupList;
+ std::list<ObjectGuid::LowType> m_SkillupList;
ObjectGuid m_ritualOwnerGUID; // used for GAMEOBJECT_TYPE_SUMMONING_RITUAL where GO is not summoned (no owner)
GuidSet m_unique_users;
@@ -866,7 +870,7 @@ class GameObject : public WorldObject, public GridObject<GameObject>, public Map
typedef std::map<uint32, ObjectGuid> ChairSlotAndUser;
ChairSlotAndUser ChairListSlots;
- uint32 m_DBTableGuid; ///< For new or temporary gameobjects is 0 for saved it is lowguid
+ ObjectGuid::LowType m_spawnId; ///< For new or temporary gameobjects is 0 for saved it is lowguid
GameObjectTemplate const* m_goInfo;
GameObjectData const* m_goData;
GameObjectValue m_goValue;
diff --git a/src/server/game/Entities/Item/Container/Bag.cpp b/src/server/game/Entities/Item/Container/Bag.cpp
index e3a325d9c2d..1d2fd9b2804 100644
--- a/src/server/game/Entities/Item/Container/Bag.cpp
+++ b/src/server/game/Entities/Item/Container/Bag.cpp
@@ -69,14 +69,14 @@ void Bag::RemoveFromWorld()
Item::RemoveFromWorld();
}
-bool Bag::Create(uint32 guidlow, uint32 itemid, Player const* owner)
+bool Bag::Create(ObjectGuid::LowType guidlow, uint32 itemid, Player const* owner)
{
ItemTemplate const* itemProto = sObjectMgr->GetItemTemplate(itemid);
if (!itemProto || itemProto->ContainerSlots > MAX_BAG_SIZE)
return false;
- Object::_Create(guidlow, 0, HIGHGUID_CONTAINER);
+ Object::_Create(guidlow, 0, HighGuid::Container);
SetEntry(itemid);
SetObjectScale(1.0f);
@@ -109,7 +109,7 @@ void Bag::SaveToDB(SQLTransaction& trans)
Item::SaveToDB(trans);
}
-bool Bag::LoadFromDB(uint32 guid, ObjectGuid owner_guid, Field* fields, uint32 entry)
+bool Bag::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid owner_guid, Field* fields, uint32 entry)
{
if (!Item::LoadFromDB(guid, owner_guid, fields, entry))
return false;
diff --git a/src/server/game/Entities/Item/Container/Bag.h b/src/server/game/Entities/Item/Container/Bag.h
index 11bff67855d..ead059030b6 100644
--- a/src/server/game/Entities/Item/Container/Bag.h
+++ b/src/server/game/Entities/Item/Container/Bag.h
@@ -35,7 +35,7 @@ class Bag : public Item
void AddToWorld() override;
void RemoveFromWorld() override;
- bool Create(uint32 guidlow, uint32 itemid, Player const* owner) override;
+ bool Create(ObjectGuid::LowType guidlow, ObjectGuid::LowType itemid, Player const* owner) override;
void Clear();
void StoreItem(uint8 slot, Item* pItem, bool update);
@@ -54,7 +54,7 @@ class Bag : public Item
// overwrite virtual Item::SaveToDB
void SaveToDB(SQLTransaction& trans) override;
// overwrite virtual Item::LoadFromDB
- bool LoadFromDB(uint32 guid, ObjectGuid owner_guid, Field* fields, uint32 entry) override;
+ bool LoadFromDB(ObjectGuid::LowType guid, ObjectGuid owner_guid, Field* fields, uint32 entry) override;
// overwrite virtual Item::DeleteFromDB
void DeleteFromDB(SQLTransaction& trans) override;
diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp
index 141bac5e50f..1b7914fd85f 100644
--- a/src/server/game/Entities/Item/Item.cpp
+++ b/src/server/game/Entities/Item/Item.cpp
@@ -28,6 +28,7 @@
#include "ConditionMgr.h"
#include "Player.h"
#include "WorldSession.h"
+#include "TradeData.h"
void AddItemsSetItem(Player* player, Item* item)
{
@@ -255,9 +256,9 @@ Item::Item()
m_paidExtendedCost = 0;
}
-bool Item::Create(uint32 guidlow, uint32 itemid, Player const* owner)
+bool Item::Create(ObjectGuid::LowType guidlow, uint32 itemid, Player const* owner)
{
- Object::_Create(guidlow, 0, HIGHGUID_ITEM);
+ Object::_Create(guidlow, 0, HighGuid::Item);
SetEntry(itemid);
SetObjectScale(1.0f);
@@ -317,7 +318,7 @@ void Item::SaveToDB(SQLTransaction& trans)
if (!isInTransaction)
trans = CharacterDatabase.BeginTransaction();
- uint32 guid = GetGUIDLow();
+ ObjectGuid::LowType guid = GetGUID().GetCounter();
switch (uState)
{
case ITEM_NEW:
@@ -398,14 +399,14 @@ void Item::SaveToDB(SQLTransaction& trans)
CharacterDatabase.CommitTransaction(trans);
}
-bool Item::LoadFromDB(uint32 guid, ObjectGuid owner_guid, Field* fields, uint32 entry)
+bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid owner_guid, Field* fields, uint32 entry)
{
// 0 1 2 3 4 5 6 7 8 9 10
//result = CharacterDatabase.PQuery("SELECT creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text FROM item_instance WHERE guid = '%u'", guid);
// create item before any checks for store correct guid
// and allow use "FSetState(ITEM_REMOVED); SaveToDB();" for deleting item from DB
- Object::_Create(guid, 0, HIGHGUID_ITEM);
+ Object::_Create(guid, 0, HighGuid::Item);
// Set entry, MUST be before proto check
SetEntry(entry);
@@ -420,8 +421,8 @@ bool Item::LoadFromDB(uint32 guid, ObjectGuid owner_guid, Field* fields, uint32
SetOwnerGUID(owner_guid);
bool need_save = false; // need explicit save data at load fixes
- SetGuidValue(ITEM_FIELD_CREATOR, ObjectGuid(HIGHGUID_PLAYER, fields[0].GetUInt32()));
- SetGuidValue(ITEM_FIELD_GIFTCREATOR, ObjectGuid(HIGHGUID_PLAYER, fields[1].GetUInt32()));
+ SetGuidValue(ITEM_FIELD_CREATOR, ObjectGuid(HighGuid::Player, fields[0].GetUInt32()));
+ SetGuidValue(ITEM_FIELD_GIFTCREATOR, ObjectGuid(HighGuid::Player, fields[1].GetUInt32()));
SetCount(fields[2].GetUInt32());
uint32 duration = fields[3].GetUInt32();
@@ -480,7 +481,7 @@ bool Item::LoadFromDB(uint32 guid, ObjectGuid owner_guid, Field* fields, uint32
}
/*static*/
-void Item::DeleteFromDB(SQLTransaction& trans, uint32 itemGuid)
+void Item::DeleteFromDB(SQLTransaction& trans, ObjectGuid::LowType itemGuid)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE);
stmt->setUInt32(0, itemGuid);
@@ -489,7 +490,7 @@ void Item::DeleteFromDB(SQLTransaction& trans, uint32 itemGuid)
void Item::DeleteFromDB(SQLTransaction& trans)
{
- DeleteFromDB(trans, GetGUIDLow());
+ DeleteFromDB(trans, GetGUID().GetCounter());
// Delete the items if this is a container
if (!loot.isLooted())
@@ -497,7 +498,7 @@ void Item::DeleteFromDB(SQLTransaction& trans)
}
/*static*/
-void Item::DeleteFromInventoryDB(SQLTransaction& trans, uint32 itemGuid)
+void Item::DeleteFromInventoryDB(SQLTransaction& trans, ObjectGuid::LowType itemGuid)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_INVENTORY_BY_ITEM);
stmt->setUInt32(0, itemGuid);
@@ -506,7 +507,7 @@ void Item::DeleteFromInventoryDB(SQLTransaction& trans, uint32 itemGuid)
void Item::DeleteFromInventoryDB(SQLTransaction& trans)
{
- DeleteFromInventoryDB(trans, GetGUIDLow());
+ DeleteFromInventoryDB(trans, GetGUID().GetCounter());
}
ItemTemplate const* Item::GetTemplate() const
@@ -1061,7 +1062,7 @@ Item* Item::CreateItem(uint32 itemEntry, uint32 count, Player const* player)
ASSERT(count != 0 && "pProto->Stackable == 0 but checked at loading already");
Item* item = NewItemOrBag(proto);
- if (item->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_ITEM), itemEntry, player))
+ if (item->Create(sObjectMgr->GetGenerator<HighGuid::Item>().Generate(), itemEntry, player))
{
item->SetCount(count);
return item;
@@ -1070,7 +1071,7 @@ Item* Item::CreateItem(uint32 itemEntry, uint32 count, Player const* player)
delete item;
}
else
- ASSERT(false);
+ ABORT();
return NULL;
}
@@ -1101,7 +1102,7 @@ bool Item::IsBindedNotWith(Player const* player) const
return false;
if (HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_BOP_TRADEABLE))
- if (allowedGUIDs.find(player->GetGUIDLow()) != allowedGUIDs.end())
+ if (allowedGUIDs.find(player->GetGUID().GetCounter()) != allowedGUIDs.end())
return false;
// BOA item case
@@ -1118,16 +1119,28 @@ void Item::BuildUpdate(UpdateDataMapType& data_map)
ClearUpdateMask(false);
}
+void Item::AddToObjectUpdate()
+{
+ if (Player* owner = GetOwner())
+ owner->GetMap()->AddUpdateObject(this);
+}
+
+void Item::RemoveFromObjectUpdate()
+{
+ if (Player* owner = GetOwner())
+ owner->GetMap()->RemoveUpdateObject(this);
+}
+
void Item::SaveRefundDataToDB()
{
SQLTransaction trans = CharacterDatabase.BeginTransaction();
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_REFUND_INSTANCE);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
trans->Append(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ITEM_REFUND_INSTANCE);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
stmt->setUInt32(1, GetRefundRecipient());
stmt->setUInt32(2, GetPaidMoney());
stmt->setUInt16(3, uint16(GetPaidExtendedCost()));
@@ -1141,7 +1154,7 @@ void Item::DeleteRefundDataFromDB(SQLTransaction* trans)
if (trans)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_REFUND_INSTANCE);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
(*trans)->Append(stmt);
}
@@ -1220,7 +1233,7 @@ void Item::ClearSoulboundTradeable(Player* currentOwner)
allowedGUIDs.clear();
SetState(ITEM_CHANGED, currentOwner);
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_BOP_TRADE);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
CharacterDatabase.Execute(stmt);
}
@@ -1242,7 +1255,7 @@ void Item::ItemContainerSaveLootToDB()
if (loot.isLooted()) // no money and no loot
return;
- uint32 container_id = GetGUIDLow();
+ ObjectGuid::LowType container_id = GetGUID().GetCounter();
SQLTransaction trans = CharacterDatabase.BeginTransaction();
loot.containerID = container_id; // Save this for when a LootItem is removed
@@ -1310,7 +1323,7 @@ bool Item::ItemContainerLoadLootFromDB()
// Default. If there are no records for this item then it will be rolled for in Player::SendLoot()
m_lootGenerated = false;
- uint32 container_id = GetGUIDLow();
+ ObjectGuid::LowType container_id = GetGUID().GetCounter();
// Save this for later use
loot.containerID = container_id;
@@ -1364,7 +1377,7 @@ bool Item::ItemContainerLoadLootFromDB()
// If container item is in a bag, add that player as an allowed looter
if (GetBagSlot())
- loot_item.allowedGUIDs.insert(GetOwner()->GetGUIDLow());
+ loot_item.allowedGUIDs.insert(GetOwner()->GetGUID().GetCounter());
// Finally add the LootItem to the container
loot.items.push_back(loot_item);
@@ -1386,7 +1399,7 @@ bool Item::ItemContainerLoadLootFromDB()
void Item::ItemContainerDeleteLootItemsFromDB()
{
// Deletes items associated with an openable item from the DB
- uint32 containerId = GetGUIDLow();
+ ObjectGuid::LowType containerId = GetGUID().GetCounter();
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEMCONTAINER_ITEMS);
stmt->setUInt32(0, containerId);
SQLTransaction trans = CharacterDatabase.BeginTransaction();
@@ -1397,7 +1410,7 @@ void Item::ItemContainerDeleteLootItemsFromDB()
void Item::ItemContainerDeleteLootItemFromDB(uint32 itemID)
{
// Deletes a single item associated with an openable item from the DB
- uint32 containerId = GetGUIDLow();
+ ObjectGuid::LowType containerId = GetGUID().GetCounter();
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEMCONTAINER_ITEM);
stmt->setUInt32(0, containerId);
stmt->setUInt32(1, itemID);
@@ -1409,7 +1422,7 @@ void Item::ItemContainerDeleteLootItemFromDB(uint32 itemID)
void Item::ItemContainerDeleteLootMoneyFromDB()
{
// Deletes the money loot associated with an openable item from the DB
- uint32 containerId = GetGUIDLow();
+ ObjectGuid::LowType containerId = GetGUID().GetCounter();
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEMCONTAINER_MONEY);
stmt->setUInt32(0, containerId);
SQLTransaction trans = CharacterDatabase.BeginTransaction();
@@ -1423,3 +1436,19 @@ void Item::ItemContainerDeleteLootMoneyAndLootItemsFromDB()
ItemContainerDeleteLootMoneyFromDB();
ItemContainerDeleteLootItemsFromDB();
}
+
+void Item::SetCount(uint32 value)
+{
+ SetUInt32Value(ITEM_FIELD_STACK_COUNT, value);
+
+ if (Player* player = GetOwner())
+ {
+ if (TradeData* tradeData = player->GetTradeData())
+ {
+ TradeSlots slot = tradeData->GetTradeSlotForItem(GetGUID());
+
+ if (slot != TRADE_SLOT_INVALID)
+ tradeData->SetItem(slot, this, true);
+ }
+ }
+}
diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h
index b832aeb5614..1eb6530a996 100644
--- a/src/server/game/Entities/Item/Item.h
+++ b/src/server/game/Entities/Item/Item.h
@@ -211,7 +211,7 @@ class Item : public Object
Item();
- virtual bool Create(uint32 guidlow, uint32 itemid, Player const* owner);
+ virtual bool Create(ObjectGuid::LowType guidlow, ObjectGuid::LowType itemid, Player const* owner);
ItemTemplate const* GetTemplate() const;
@@ -225,10 +225,10 @@ class Item : public Object
bool IsBindedNotWith(Player const* player) const;
bool IsBoundByEnchant() const;
virtual void SaveToDB(SQLTransaction& trans);
- virtual bool LoadFromDB(uint32 guid, ObjectGuid owner_guid, Field* fields, uint32 entry);
- static void DeleteFromDB(SQLTransaction& trans, uint32 itemGuid);
+ virtual bool LoadFromDB(ObjectGuid::LowType guid, ObjectGuid owner_guid, Field* fields, uint32 entry);
+ static void DeleteFromDB(SQLTransaction& trans, ObjectGuid::LowType itemGuid);
virtual void DeleteFromDB(SQLTransaction& trans);
- static void DeleteFromInventoryDB(SQLTransaction& trans, uint32 itemGuid);
+ static void DeleteFromInventoryDB(SQLTransaction& trans, ObjectGuid::LowType itemGuid);
// Lootable items and their contents
void ItemContainerSaveLootToDB();
@@ -262,7 +262,7 @@ class Item : public Object
bool GemsFitSockets() const;
uint32 GetCount() const { return GetUInt32Value(ITEM_FIELD_STACK_COUNT); }
- void SetCount(uint32 value) { SetUInt32Value(ITEM_FIELD_STACK_COUNT, value); }
+ void SetCount(uint32 value);
uint32 GetMaxStackCount() const { return GetTemplate()->GetMaxStackSize(); }
uint8 GetGemCountWithID(uint32 GemID) const;
uint8 GetGemCountWithLimitCategory(uint32 limitCategory) const;
@@ -331,7 +331,7 @@ class Item : public Object
// Item Refund system
void SetNotRefundable(Player* owner, bool changestate = true, SQLTransaction* trans = NULL);
- void SetRefundRecipient(uint32 pGuidLow) { m_refundRecipient = pGuidLow; }
+ void SetRefundRecipient(ObjectGuid::LowType pGuidLow) { m_refundRecipient = pGuidLow; }
void SetPaidMoney(uint32 money) { m_paidMoney = money; }
void SetPaidExtendedCost(uint32 iece) { m_paidExtendedCost = iece; }
@@ -350,6 +350,9 @@ class Item : public Object
void BuildUpdate(UpdateDataMapType&) override;
+ void AddToObjectUpdate() override;
+ void RemoveFromObjectUpdate() override;
+
uint32 GetScriptId() const { return GetTemplate()->ScriptId; }
private:
std::string m_text;
@@ -359,7 +362,7 @@ class Item : public Object
int16 uQueuePos;
bool mb_in_trade; // true if item is currently in trade-window
time_t m_lastPlayedTimeUpdate;
- uint32 m_refundRecipient;
+ ObjectGuid::LowType m_refundRecipient;
uint32 m_paidMoney;
uint32 m_paidExtendedCost;
AllowedLooterSet allowedGUIDs;
diff --git a/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp b/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp
index be27f5eca30..042d66d7f9e 100644
--- a/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp
+++ b/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp
@@ -16,17 +16,17 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <stdlib.h>
-#include <functional>
#include "ItemEnchantmentMgr.h"
#include "DatabaseEnv.h"
#include "Log.h"
#include "ObjectMgr.h"
-#include <list>
-#include <vector>
#include "Util.h"
#include "DBCStores.h"
+#include <list>
+#include <vector>
+#include <stdlib.h>
+
struct EnchStoreItem
{
uint32 ench;
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 6392c3ee51b..afb987f1980 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -67,7 +67,7 @@ WorldObject::~WorldObject()
{
TC_LOG_FATAL("misc", "WorldObject::~WorldObject Corpse Type: %d (%s) deleted but still in map!!",
ToCorpse()->GetType(), GetGUID().ToString().c_str());
- ASSERT(false);
+ ABORT();
}
ResetMap();
}
@@ -80,15 +80,13 @@ Object::~Object()
TC_LOG_FATAL("misc", "Object::~Object %s deleted but still in world!!", GetGUID().ToString().c_str());
if (isType(TYPEMASK_ITEM))
TC_LOG_FATAL("misc", "Item slot %u", ((Item*)this)->GetSlot());
- ASSERT(false);
- RemoveFromWorld();
+ ABORT();
}
if (m_objectUpdated)
{
TC_LOG_FATAL("misc", "Object::~Object %s deleted but still in update list!!", GetGUID().ToString().c_str());
- ASSERT(false);
- sObjectAccessor->RemoveUpdateObject(this);
+ ABORT();
}
delete [] m_uint32Values;
@@ -105,7 +103,7 @@ void Object::_InitValues()
m_objectUpdated = false;
}
-void Object::_Create(uint32 guidlow, uint32 entry, HighGuid guidhigh)
+void Object::_Create(ObjectGuid::LowType guidlow, uint32 entry, HighGuid guidhigh)
{
if (!m_uint32Values) _InitValues();
@@ -133,7 +131,8 @@ void Object::AddToWorld()
m_inWorld = true;
// synchronize values mirror with values array (changes will send in updatecreate opcode any way
- ClearUpdateMask(true);
+ ASSERT(!m_objectUpdated);
+ ClearUpdateMask(false);
}
void Object::RemoveFromWorld()
@@ -418,7 +417,7 @@ void Object::BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
case TYPEID_GAMEOBJECT:
case TYPEID_DYNAMICOBJECT:
case TYPEID_CORPSE:
- *data << uint32(GetGUIDLow()); // GetGUIDLow()
+ *data << uint32(GetGUID().GetCounter()); // GetGUID().GetCounter()
break;
//! Unit, Player and default here are sending wrong values.
/// @todo Research the proper formula
@@ -509,6 +508,15 @@ void Object::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* targe
data->append(fieldBuffer);
}
+void Object::AddToObjectUpdateIfNeeded()
+{
+ if (m_inWorld && !m_objectUpdated)
+ {
+ AddToObjectUpdate();
+ m_objectUpdated = true;
+ }
+}
+
void Object::ClearUpdateMask(bool remove)
{
_changesMask.Clear();
@@ -516,7 +524,8 @@ void Object::ClearUpdateMask(bool remove)
if (m_objectUpdated)
{
if (remove)
- sObjectAccessor->RemoveUpdateObject(this);
+ RemoveFromObjectUpdate();
+
m_objectUpdated = false;
}
}
@@ -614,11 +623,7 @@ void Object::SetInt32Value(uint16 index, int32 value)
m_int32Values[index] = value;
_changesMask.SetBit(index);
- if (m_inWorld && !m_objectUpdated)
- {
- sObjectAccessor->AddUpdateObject(this);
- m_objectUpdated = true;
- }
+ AddToObjectUpdateIfNeeded();
}
}
@@ -631,11 +636,7 @@ void Object::SetUInt32Value(uint16 index, uint32 value)
m_uint32Values[index] = value;
_changesMask.SetBit(index);
- if (m_inWorld && !m_objectUpdated)
- {
- sObjectAccessor->AddUpdateObject(this);
- m_objectUpdated = true;
- }
+ AddToObjectUpdateIfNeeded();
}
}
@@ -657,11 +658,7 @@ void Object::SetUInt64Value(uint16 index, uint64 value)
_changesMask.SetBit(index);
_changesMask.SetBit(index + 1);
- if (m_inWorld && !m_objectUpdated)
- {
- sObjectAccessor->AddUpdateObject(this);
- m_objectUpdated = true;
- }
+ AddToObjectUpdateIfNeeded();
}
}
@@ -674,11 +671,7 @@ bool Object::AddGuidValue(uint16 index, ObjectGuid value)
_changesMask.SetBit(index);
_changesMask.SetBit(index + 1);
- if (m_inWorld && !m_objectUpdated)
- {
- sObjectAccessor->AddUpdateObject(this);
- m_objectUpdated = true;
- }
+ AddToObjectUpdateIfNeeded();
return true;
}
@@ -696,11 +689,7 @@ bool Object::RemoveGuidValue(uint16 index, ObjectGuid value)
_changesMask.SetBit(index);
_changesMask.SetBit(index + 1);
- if (m_inWorld && !m_objectUpdated)
- {
- sObjectAccessor->AddUpdateObject(this);
- m_objectUpdated = true;
- }
+ AddToObjectUpdateIfNeeded();
return true;
}
@@ -717,11 +706,7 @@ void Object::SetFloatValue(uint16 index, float value)
m_floatValues[index] = value;
_changesMask.SetBit(index);
- if (m_inWorld && !m_objectUpdated)
- {
- sObjectAccessor->AddUpdateObject(this);
- m_objectUpdated = true;
- }
+ AddToObjectUpdateIfNeeded();
}
}
@@ -741,11 +726,8 @@ void Object::SetByteValue(uint16 index, uint8 offset, uint8 value)
m_uint32Values[index] |= uint32(uint32(value) << (offset * 8));
_changesMask.SetBit(index);
- if (m_inWorld && !m_objectUpdated)
- {
- sObjectAccessor->AddUpdateObject(this);
- m_objectUpdated = true;
- }
+ AddToObjectUpdateIfNeeded();
+
}
}
@@ -765,11 +747,7 @@ void Object::SetUInt16Value(uint16 index, uint8 offset, uint16 value)
m_uint32Values[index] |= uint32(uint32(value) << (offset * 16));
_changesMask.SetBit(index);
- if (m_inWorld && !m_objectUpdated)
- {
- sObjectAccessor->AddUpdateObject(this);
- m_objectUpdated = true;
- }
+ AddToObjectUpdateIfNeeded();
}
}
@@ -782,11 +760,7 @@ void Object::SetGuidValue(uint16 index, ObjectGuid value)
_changesMask.SetBit(index);
_changesMask.SetBit(index + 1);
- if (m_inWorld && !m_objectUpdated)
- {
- sObjectAccessor->AddUpdateObject(this);
- m_objectUpdated = true;
- }
+ AddToObjectUpdateIfNeeded();
}
}
@@ -856,11 +830,7 @@ void Object::SetFlag(uint16 index, uint32 newFlag)
m_uint32Values[index] = newval;
_changesMask.SetBit(index);
- if (m_inWorld && !m_objectUpdated)
- {
- sObjectAccessor->AddUpdateObject(this);
- m_objectUpdated = true;
- }
+ AddToObjectUpdateIfNeeded();
}
}
@@ -877,11 +847,7 @@ void Object::RemoveFlag(uint16 index, uint32 oldFlag)
m_uint32Values[index] = newval;
_changesMask.SetBit(index);
- if (m_inWorld && !m_objectUpdated)
- {
- sObjectAccessor->AddUpdateObject(this);
- m_objectUpdated = true;
- }
+ AddToObjectUpdateIfNeeded();
}
}
@@ -921,11 +887,7 @@ void Object::SetByteFlag(uint16 index, uint8 offset, uint8 newFlag)
m_uint32Values[index] |= uint32(uint32(newFlag) << (offset * 8));
_changesMask.SetBit(index);
- if (m_inWorld && !m_objectUpdated)
- {
- sObjectAccessor->AddUpdateObject(this);
- m_objectUpdated = true;
- }
+ AddToObjectUpdateIfNeeded();
}
}
@@ -944,11 +906,7 @@ void Object::RemoveByteFlag(uint16 index, uint8 offset, uint8 oldFlag)
m_uint32Values[index] &= ~uint32(uint32(oldFlag) << (offset * 8));
_changesMask.SetBit(index);
- if (m_inWorld && !m_objectUpdated)
- {
- sObjectAccessor->AddUpdateObject(this);
- m_objectUpdated = true;
- }
+ AddToObjectUpdateIfNeeded();
}
}
@@ -1108,7 +1066,7 @@ void WorldObject::CleanupsBeforeDelete(bool /*finalCleanup*/)
transport->RemovePassenger(this);
}
-void WorldObject::_Create(uint32 guidlow, HighGuid guidhigh, uint32 phaseMask)
+void WorldObject::_Create(ObjectGuid::LowType guidlow, HighGuid guidhigh, uint32 phaseMask)
{
Object::_Create(guidlow, 0, guidhigh);
m_phaseMask = phaseMask;
@@ -1158,7 +1116,7 @@ bool WorldObject::_IsWithinDist(WorldObject const* obj, float dist2compare, bool
float sizefactor = GetObjectSize() + obj->GetObjectSize();
float maxdist = dist2compare + sizefactor;
- if (GetTransport() && obj->GetTransport() && obj->GetTransport()->GetGUIDLow() == GetTransport()->GetGUIDLow())
+ if (GetTransport() && obj->GetTransport() && obj->GetTransport()->GetGUID().GetCounter() == GetTransport()->GetGUID().GetCounter())
{
float dtx = m_movementInfo.transport.pos.m_positionX - obj->m_movementInfo.transport.pos.m_positionX;
float dty = m_movementInfo.transport.pos.m_positionY - obj->m_movementInfo.transport.pos.m_positionY;
@@ -1539,7 +1497,7 @@ float WorldObject::GetSightRange(const WorldObject* target) const
return 0.0f;
}
-bool WorldObject::CanSeeOrDetect(WorldObject const* obj, bool ignoreStealth, bool distanceCheck) const
+bool WorldObject::CanSeeOrDetect(WorldObject const* obj, bool ignoreStealth, bool distanceCheck, bool checkAlert) const
{
if (this == obj)
return true;
@@ -1611,7 +1569,7 @@ bool WorldObject::CanSeeOrDetect(WorldObject const* obj, bool ignoreStealth, boo
if (obj->IsInvisibleDueToDespawn())
return false;
- if (!CanDetect(obj, ignoreStealth))
+ if (!CanDetect(obj, ignoreStealth, checkAlert))
return false;
return true;
@@ -1622,7 +1580,7 @@ bool WorldObject::CanNeverSee(WorldObject const* obj) const
return GetMap() != obj->GetMap() || !InSamePhase(obj);
}
-bool WorldObject::CanDetect(WorldObject const* obj, bool ignoreStealth) const
+bool WorldObject::CanDetect(WorldObject const* obj, bool ignoreStealth, bool checkAlert) const
{
const WorldObject* seer = this;
@@ -1637,7 +1595,7 @@ bool WorldObject::CanDetect(WorldObject const* obj, bool ignoreStealth) const
if (!ignoreStealth && !seer->CanDetectInvisibilityOf(obj))
return false;
- if (!ignoreStealth && !seer->CanDetectStealthOf(obj))
+ if (!ignoreStealth && !seer->CanDetectStealthOf(obj, checkAlert))
return false;
return true;
@@ -1674,7 +1632,7 @@ bool WorldObject::CanDetectInvisibilityOf(WorldObject const* obj) const
return true;
}
-bool WorldObject::CanDetectStealthOf(WorldObject const* obj) const
+bool WorldObject::CanDetectStealthOf(WorldObject const* obj, bool checkAlert) const
{
// Combat reach is the minimal distance (both in front and behind),
// and it is also used in the range calculation.
@@ -1724,9 +1682,19 @@ bool WorldObject::CanDetectStealthOf(WorldObject const* obj) const
// Calculate max distance
float visibilityRange = float(detectionValue) * 0.3f + combatReach;
- if (visibilityRange > MAX_PLAYER_STEALTH_DETECT_RANGE)
+ // If this unit is an NPC then player detect range doesn't apply
+ if (unit && unit->GetTypeId() == TYPEID_PLAYER && visibilityRange > MAX_PLAYER_STEALTH_DETECT_RANGE)
visibilityRange = MAX_PLAYER_STEALTH_DETECT_RANGE;
+ // When checking for alert state, look 8% further, and then 1.5 yards more than that.
+ if (checkAlert)
+ visibilityRange += (visibilityRange * 0.08f) + 1.5f;
+
+ // If checking for alert, and creature's visibility range is greater than aggro distance, No alert
+ Unit const* tunit = obj->ToUnit();
+ if (checkAlert && unit && unit->ToCreature() && visibilityRange >= unit->ToCreature()->GetAttackDistance(tunit) + unit->ToCreature()->m_CombatDistance)
+ return false;
+
if (distance > visibilityRange)
return false;
}
@@ -1737,11 +1705,7 @@ bool WorldObject::CanDetectStealthOf(WorldObject const* obj) const
void Object::ForceValuesUpdateAtIndex(uint32 i)
{
_changesMask.SetBit(i);
- if (m_inWorld && !m_objectUpdated)
- {
- sObjectAccessor->AddUpdateObject(this);
- m_objectUpdated = true;
- }
+ AddToObjectUpdateIfNeeded();
}
void Unit::BuildHeartBeatMsg(WorldPacket* data) const
@@ -1779,13 +1743,13 @@ void WorldObject::SendObjectDeSpawnAnim(ObjectGuid guid)
void WorldObject::SetMap(Map* map)
{
ASSERT(map);
- ASSERT(!IsInWorld() || GetTypeId() == TYPEID_CORPSE);
+ ASSERT(!IsInWorld());
if (m_currMap == map) // command add npc: first create, than loadfromdb
return;
if (m_currMap)
{
TC_LOG_FATAL("misc", "WorldObject::SetMap: obj %u new map %u %u, old map %u %u", (uint32)GetTypeId(), map->GetId(), map->GetInstanceId(), m_currMap->GetId(), m_currMap->GetInstanceId());
- ASSERT(false);
+ ABORT();
}
m_currMap = map;
m_mapId = map->GetId();
@@ -1819,7 +1783,7 @@ void WorldObject::AddObjectToRemoveList()
Map* map = FindMap();
if (!map)
{
- TC_LOG_ERROR("misc", "Object (TypeId: %u Entry: %u GUID: %u) at attempt add to move list not have valid map (Id: %u).", GetTypeId(), GetEntry(), GetGUIDLow(), GetMapId());
+ TC_LOG_ERROR("misc", "Object (TypeId: %u Entry: %u GUID: %u) at attempt add to move list not have valid map (Id: %u).", GetTypeId(), GetEntry(), GetGUID().GetCounter(), GetMapId());
return;
}
@@ -1900,7 +1864,7 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert
break;
}
- if (!summon->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), this, phase, entry, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), nullptr, vehId))
+ if (!summon->Create(GenerateLowGuid<HighGuid::Unit>(), this, phase, entry, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), nullptr, vehId))
{
delete summon;
return NULL;
@@ -1954,6 +1918,11 @@ void WorldObject::SetZoneScript()
}
}
+void WorldObject::ClearZoneScript()
+{
+ m_zoneScript = NULL;
+}
+
TempSummon* WorldObject::SummonCreature(uint32 entry, const Position &pos, TempSummonType spwtype, uint32 duration, uint32 /*vehId*/) const
{
if (Map* map = FindMap())
@@ -1994,7 +1963,7 @@ GameObject* WorldObject::SummonGameObject(uint32 entry, float x, float y, float
Map* map = GetMap();
GameObject* go = new GameObject();
- if (!go->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), entry, map, GetPhaseMask(), x, y, z, ang, rotation0, rotation1, rotation2, rotation3, 100, GO_STATE_READY))
+ if (!go->Create(map->GenerateLowGuid<HighGuid::GameObject>(), entry, map, GetPhaseMask(), x, y, z, ang, rotation0, rotation1, rotation2, rotation3, 100, GO_STATE_READY))
{
delete go;
return NULL;
@@ -2278,7 +2247,7 @@ void WorldObject::MovePosition(Position &pos, float dist, float angle)
if (!Trinity::IsValidMapCoord(destx, desty, pos.m_positionZ))
{
TC_LOG_FATAL("misc", "WorldObject::MovePosition: Object (TypeId: %u Entry: %u GUID: %u) has invalid coordinates X: %f and Y: %f were passed!",
- GetTypeId(), GetEntry(), GetGUIDLow(), destx, desty);
+ GetTypeId(), GetEntry(), GetGUID().GetCounter(), destx, desty);
return;
}
@@ -2553,6 +2522,16 @@ void WorldObject::BuildUpdate(UpdateDataMapType& data_map)
ClearUpdateMask(false);
}
+void WorldObject::AddToObjectUpdate()
+{
+ GetMap()->AddUpdateObject(this);
+}
+
+void WorldObject::RemoveFromObjectUpdate()
+{
+ GetMap()->RemoveUpdateObject(this);
+}
+
ObjectGuid WorldObject::GetTransGUID() const
{
if (GetTransport())
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index a560afa7f1b..c9e3d069218 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -101,9 +101,6 @@ class Object
virtual void RemoveFromWorld();
ObjectGuid GetGUID() const { return GetGuidValue(OBJECT_FIELD_GUID); }
- uint32 GetGUIDLow() const { return GetGuidValue(OBJECT_FIELD_GUID).GetCounter(); }
- uint32 GetGUIDMid() const { return GetGuidValue(OBJECT_FIELD_GUID).GetEntry(); }
- uint32 GetGUIDHigh() const { return GetGuidValue(OBJECT_FIELD_GUID).GetHigh(); }
PackedGuid const& GetPackGUID() const { return m_PackGUID; }
uint32 GetEntry() const { return GetUInt32Value(OBJECT_FIELD_ENTRY); }
void SetEntry(uint32 entry) { SetUInt32Value(OBJECT_FIELD_ENTRY, entry); }
@@ -207,7 +204,7 @@ class Object
Object();
void _InitValues();
- void _Create(uint32 guidlow, uint32 entry, HighGuid guidhigh);
+ void _Create(ObjectGuid::LowType guidlow, uint32 entry, HighGuid guidhigh);
std::string _ConcatFields(uint16 startIndex, uint16 size) const;
void _LoadIntoDataField(std::string const& data, uint32 startOffset, uint32 count);
@@ -234,6 +231,10 @@ class Object
uint16 _fieldNotifyFlags;
+ virtual void AddToObjectUpdate() = 0;
+ virtual void RemoveFromObjectUpdate() = 0;
+ void AddToObjectUpdateIfNeeded();
+
bool m_objectUpdated;
private:
@@ -430,7 +431,7 @@ class WorldObject : public Object, public WorldLocation
virtual void Update (uint32 /*time_diff*/) { }
- void _Create(uint32 guidlow, HighGuid guidhigh, uint32 phaseMask);
+ void _Create(ObjectGuid::LowType guidlow, HighGuid guidhigh, uint32 phaseMask);
virtual void RemoveFromWorld() override;
void GetNearPoint2D(float &x, float &y, float distance, float absAngle) const;
@@ -514,7 +515,7 @@ class WorldObject : public Object, public WorldLocation
float GetGridActivationRange() const;
float GetVisibilityRange() const;
float GetSightRange(WorldObject const* target = NULL) const;
- bool CanSeeOrDetect(WorldObject const* obj, bool ignoreStealth = false, bool distanceCheck = false) const;
+ bool CanSeeOrDetect(WorldObject const* obj, bool ignoreStealth = false, bool distanceCheck = false, bool checkAlert = false) const;
FlaggedValuesArray32<int32, uint32, StealthType, TOTAL_STEALTH_TYPES> m_stealth;
FlaggedValuesArray32<int32, uint32, StealthType, TOTAL_STEALTH_TYPES> m_stealthDetect;
@@ -535,6 +536,7 @@ class WorldObject : public Object, public WorldLocation
Map const* GetBaseMap() const;
void SetZoneScript();
+ void ClearZoneScript();
ZoneScript* GetZoneScript() const { return m_zoneScript; }
TempSummon* SummonCreature(uint32 id, Position const &pos, TempSummonType spwtype = TEMPSUMMON_MANUAL_DESPAWN, uint32 despwtime = 0, uint32 vehId = 0) const;
@@ -555,6 +557,9 @@ class WorldObject : public Object, public WorldLocation
virtual void UpdateObjectVisibility(bool forced = true);
void BuildUpdate(UpdateDataMapType&) override;
+ void AddToObjectUpdate() override;
+ void RemoveFromObjectUpdate() override;
+
//relocation and visibility system functions
void AddToNotify(uint16 f) { m_notifyflags |= f;}
bool isNeedNotify(uint16 f) const { return (m_notifyflags & f) != 0; }
@@ -634,9 +639,9 @@ class WorldObject : public Object, public WorldLocation
bool CanNeverSee(WorldObject const* obj) const;
virtual bool CanAlwaysSee(WorldObject const* /*obj*/) const { return false; }
- bool CanDetect(WorldObject const* obj, bool ignoreStealth) const;
+ bool CanDetect(WorldObject const* obj, bool ignoreStealth, bool checkAlert = false) const;
bool CanDetectInvisibilityOf(WorldObject const* obj) const;
- bool CanDetectStealthOf(WorldObject const* obj) const;
+ bool CanDetectStealthOf(WorldObject const* obj, bool checkAlert = false) const;
};
namespace Trinity
diff --git a/src/server/game/Entities/Object/ObjectGuid.cpp b/src/server/game/Entities/Object/ObjectGuid.cpp
index c15668c3887..552705d8df8 100644
--- a/src/server/game/Entities/Object/ObjectGuid.cpp
+++ b/src/server/game/Entities/Object/ObjectGuid.cpp
@@ -18,6 +18,7 @@
#include "ObjectGuid.h"
#include "World.h"
+#include "ObjectMgr.h"
#include <sstream>
#include <iomanip>
@@ -27,18 +28,18 @@ char const* ObjectGuid::GetTypeName(HighGuid high)
{
switch (high)
{
- case HIGHGUID_ITEM: return "Item";
- case HIGHGUID_PLAYER: return "Player";
- case HIGHGUID_GAMEOBJECT: return "Gameobject";
- case HIGHGUID_TRANSPORT: return "Transport";
- case HIGHGUID_UNIT: return "Creature";
- case HIGHGUID_PET: return "Pet";
- case HIGHGUID_VEHICLE: return "Vehicle";
- case HIGHGUID_DYNAMICOBJECT: return "DynObject";
- case HIGHGUID_CORPSE: return "Corpse";
- case HIGHGUID_MO_TRANSPORT: return "MoTransport";
- case HIGHGUID_INSTANCE: return "InstanceID";
- case HIGHGUID_GROUP: return "Group";
+ case HighGuid::Item: return "Item";
+ case HighGuid::Player: return "Player";
+ case HighGuid::GameObject: return "Gameobject";
+ case HighGuid::Transport: return "Transport";
+ case HighGuid::Unit: return "Creature";
+ case HighGuid::Pet: return "Pet";
+ case HighGuid::Vehicle: return "Vehicle";
+ case HighGuid::DynamicObject: return "DynObject";
+ case HighGuid::Corpse: return "Corpse";
+ case HighGuid::Mo_Transport: return "MoTransport";
+ case HighGuid::Instance: return "InstanceID";
+ case HighGuid::Group: return "Group";
default:
return "<unknown>";
}
@@ -56,15 +57,14 @@ std::string ObjectGuid::ToString() const
return str.str();
}
-template<HighGuid high>
-uint32 ObjectGuidGenerator<high>::Generate()
+ObjectGuid ObjectGuid::Global(HighGuid type, LowType counter)
{
- if (_nextGuid >= ObjectGuid::GetMaxCounter(high) - 1)
- {
- TC_LOG_ERROR("", "%s guid overflow!! Can't continue, shutting down server. ", ObjectGuid::GetTypeName(high));
- World::StopNow(ERROR_EXIT_CODE);
- }
- return _nextGuid++;
+ return ObjectGuid(type, counter);
+}
+
+ObjectGuid ObjectGuid::MapSpecific(HighGuid type, uint32 entry, LowType counter)
+{
+ return ObjectGuid(type, entry, counter);
}
ByteBuffer& operator<<(ByteBuffer& buf, ObjectGuid const& guid)
@@ -91,14 +91,8 @@ ByteBuffer& operator>>(ByteBuffer& buf, PackedGuidReader const& guid)
return buf;
}
-template uint32 ObjectGuidGenerator<HIGHGUID_ITEM>::Generate();
-template uint32 ObjectGuidGenerator<HIGHGUID_PLAYER>::Generate();
-template uint32 ObjectGuidGenerator<HIGHGUID_GAMEOBJECT>::Generate();
-template uint32 ObjectGuidGenerator<HIGHGUID_TRANSPORT>::Generate();
-template uint32 ObjectGuidGenerator<HIGHGUID_UNIT>::Generate();
-template uint32 ObjectGuidGenerator<HIGHGUID_PET>::Generate();
-template uint32 ObjectGuidGenerator<HIGHGUID_VEHICLE>::Generate();
-template uint32 ObjectGuidGenerator<HIGHGUID_DYNAMICOBJECT>::Generate();
-template uint32 ObjectGuidGenerator<HIGHGUID_CORPSE>::Generate();
-template uint32 ObjectGuidGenerator<HIGHGUID_INSTANCE>::Generate();
-template uint32 ObjectGuidGenerator<HIGHGUID_GROUP>::Generate();
+void ObjectGuidGeneratorBase::HandleCounterOverflow(HighGuid high)
+{
+ TC_LOG_ERROR("misc", "%s guid overflow!! Can't continue, shutting down server. ", ObjectGuid::GetTypeName(high));
+ World::StopNow(ERROR_EXIT_CODE);
+} \ No newline at end of file
diff --git a/src/server/game/Entities/Object/ObjectGuid.h b/src/server/game/Entities/Object/ObjectGuid.h
index 45881ddab6d..74fffe09796 100644
--- a/src/server/game/Entities/Object/ObjectGuid.h
+++ b/src/server/game/Entities/Object/ObjectGuid.h
@@ -21,9 +21,8 @@
#include "Common.h"
#include "ByteBuffer.h"
-
+#include <type_traits>
#include <functional>
-#include <unordered_set>
enum TypeID
{
@@ -52,23 +51,57 @@ enum TypeMask
TYPEMASK_SEER = TYPEMASK_PLAYER | TYPEMASK_UNIT | TYPEMASK_DYNAMICOBJECT
};
-enum HighGuid
+enum class HighGuid
+{
+ Item = 0x4000, // blizz 4000
+ Container = 0x4000, // blizz 4000
+ Player = 0x0000, // blizz 0000
+ GameObject = 0xF110, // blizz F110
+ Transport = 0xF120, // blizz F120 (for GAMEOBJECT_TYPE_TRANSPORT)
+ Unit = 0xF130, // blizz F130
+ Pet = 0xF140, // blizz F140
+ Vehicle = 0xF150, // blizz F550
+ DynamicObject = 0xF100, // blizz F100
+ Corpse = 0xF101, // blizz F100
+ Mo_Transport = 0x1FC0, // blizz 1FC0 (for GAMEOBJECT_TYPE_MO_TRANSPORT)
+ Instance = 0x1F40, // blizz 1F40
+ Group = 0x1F50,
+};
+
+template<HighGuid high>
+struct ObjectGuidTraits
{
- HIGHGUID_ITEM = 0x4000, // blizz 4000
- HIGHGUID_CONTAINER = 0x4000, // blizz 4000
- HIGHGUID_PLAYER = 0x0000, // blizz 0000
- HIGHGUID_GAMEOBJECT = 0xF110, // blizz F110
- HIGHGUID_TRANSPORT = 0xF120, // blizz F120 (for GAMEOBJECT_TYPE_TRANSPORT)
- HIGHGUID_UNIT = 0xF130, // blizz F130
- HIGHGUID_PET = 0xF140, // blizz F140
- HIGHGUID_VEHICLE = 0xF150, // blizz F550
- HIGHGUID_DYNAMICOBJECT = 0xF100, // blizz F100
- HIGHGUID_CORPSE = 0xF101, // blizz F100
- HIGHGUID_MO_TRANSPORT = 0x1FC0, // blizz 1FC0 (for GAMEOBJECT_TYPE_MO_TRANSPORT)
- HIGHGUID_INSTANCE = 0x1F40, // blizz 1F40
- HIGHGUID_GROUP = 0x1F50
+ static bool const Global = false;
+ static bool const MapSpecific = false;
};
+#define GUID_TRAIT_GLOBAL(highguid) \
+ template<> struct ObjectGuidTraits<highguid> \
+ { \
+ static bool const Global = true; \
+ static bool const MapSpecific = false; \
+ };
+
+#define GUID_TRAIT_MAP_SPECIFIC(highguid) \
+ template<> struct ObjectGuidTraits<highguid> \
+ { \
+ static bool const Global = false; \
+ static bool const MapSpecific = true; \
+ };
+
+GUID_TRAIT_GLOBAL(HighGuid::Player)
+GUID_TRAIT_GLOBAL(HighGuid::Item)
+GUID_TRAIT_GLOBAL(HighGuid::Mo_Transport)
+GUID_TRAIT_GLOBAL(HighGuid::Group)
+GUID_TRAIT_GLOBAL(HighGuid::Instance)
+GUID_TRAIT_MAP_SPECIFIC(HighGuid::Transport)
+GUID_TRAIT_MAP_SPECIFIC(HighGuid::Unit)
+GUID_TRAIT_MAP_SPECIFIC(HighGuid::Vehicle)
+GUID_TRAIT_MAP_SPECIFIC(HighGuid::Pet)
+GUID_TRAIT_MAP_SPECIFIC(HighGuid::GameObject)
+GUID_TRAIT_MAP_SPECIFIC(HighGuid::DynamicObject)
+GUID_TRAIT_MAP_SPECIFIC(HighGuid::Corpse)
+
class ObjectGuid;
class PackedGuid;
@@ -85,6 +118,12 @@ class ObjectGuid
typedef uint32 LowType;
+ template<HighGuid type>
+ static typename std::enable_if<ObjectGuidTraits<type>::Global, ObjectGuid>::type Create(LowType counter) { return Global(type, counter); }
+
+ template<HighGuid type>
+ static typename std::enable_if<ObjectGuidTraits<type>::MapSpecific, ObjectGuid>::type Create(uint32 entry, LowType counter) { return MapSpecific(type, entry, counter); }
+
ObjectGuid() : _guid(0) { }
explicit ObjectGuid(uint64 guid) : _guid(guid) { }
ObjectGuid(HighGuid hi, uint32 entry, LowType counter) : _guid(counter ? uint64(counter) | (uint64(entry) << 24) | (uint64(hi) << 48) : 0) { }
@@ -108,51 +147,51 @@ class ObjectGuid
: LowType(_guid & UI64LIT(0x00000000FFFFFFFF));
}
- static uint32 GetMaxCounter(HighGuid high)
+ static LowType GetMaxCounter(HighGuid high)
{
return HasEntry(high)
- ? uint32(0x00FFFFFF)
- : uint32(0xFFFFFFFF);
+ ? LowType(0x00FFFFFF)
+ : LowType(0xFFFFFFFF);
}
- uint32 GetMaxCounter() const { return GetMaxCounter(GetHigh()); }
+ ObjectGuid::LowType GetMaxCounter() const { return GetMaxCounter(GetHigh()); }
bool IsEmpty() const { return _guid == 0; }
- bool IsCreature() const { return GetHigh() == HIGHGUID_UNIT; }
- bool IsPet() const { return GetHigh() == HIGHGUID_PET; }
- bool IsVehicle() const { return GetHigh() == HIGHGUID_VEHICLE; }
+ bool IsCreature() const { return GetHigh() == HighGuid::Unit; }
+ bool IsPet() const { return GetHigh() == HighGuid::Pet; }
+ bool IsVehicle() const { return GetHigh() == HighGuid::Vehicle; }
bool IsCreatureOrPet() const { return IsCreature() || IsPet(); }
bool IsCreatureOrVehicle() const { return IsCreature() || IsVehicle(); }
bool IsAnyTypeCreature() const { return IsCreature() || IsPet() || IsVehicle(); }
- bool IsPlayer() const { return !IsEmpty() && GetHigh() == HIGHGUID_PLAYER; }
+ bool IsPlayer() const { return !IsEmpty() && GetHigh() == HighGuid::Player; }
bool IsUnit() const { return IsAnyTypeCreature() || IsPlayer(); }
- bool IsItem() const { return GetHigh() == HIGHGUID_ITEM; }
- bool IsGameObject() const { return GetHigh() == HIGHGUID_GAMEOBJECT; }
- bool IsDynamicObject() const { return GetHigh() == HIGHGUID_DYNAMICOBJECT; }
- bool IsCorpse() const { return GetHigh() == HIGHGUID_CORPSE; }
- bool IsTransport() const { return GetHigh() == HIGHGUID_TRANSPORT; }
- bool IsMOTransport() const { return GetHigh() == HIGHGUID_MO_TRANSPORT; }
+ bool IsItem() const { return GetHigh() == HighGuid::Item; }
+ bool IsGameObject() const { return GetHigh() == HighGuid::GameObject; }
+ bool IsDynamicObject() const { return GetHigh() == HighGuid::DynamicObject; }
+ bool IsCorpse() const { return GetHigh() == HighGuid::Corpse; }
+ bool IsTransport() const { return GetHigh() == HighGuid::Transport; }
+ bool IsMOTransport() const { return GetHigh() == HighGuid::Mo_Transport; }
bool IsAnyTypeGameObject() const { return IsGameObject() || IsTransport() || IsMOTransport(); }
- bool IsInstance() const { return GetHigh() == HIGHGUID_INSTANCE; }
- bool IsGroup() const { return GetHigh() == HIGHGUID_GROUP; }
+ bool IsInstance() const { return GetHigh() == HighGuid::Instance; }
+ bool IsGroup() const { return GetHigh() == HighGuid::Group; }
static TypeID GetTypeId(HighGuid high)
{
switch (high)
{
- case HIGHGUID_ITEM: return TYPEID_ITEM;
- //case HIGHGUID_CONTAINER: return TYPEID_CONTAINER; HIGHGUID_CONTAINER==HIGHGUID_ITEM currently
- case HIGHGUID_UNIT: return TYPEID_UNIT;
- case HIGHGUID_PET: return TYPEID_UNIT;
- case HIGHGUID_PLAYER: return TYPEID_PLAYER;
- case HIGHGUID_GAMEOBJECT: return TYPEID_GAMEOBJECT;
- case HIGHGUID_DYNAMICOBJECT: return TYPEID_DYNAMICOBJECT;
- case HIGHGUID_CORPSE: return TYPEID_CORPSE;
- case HIGHGUID_MO_TRANSPORT: return TYPEID_GAMEOBJECT;
- case HIGHGUID_VEHICLE: return TYPEID_UNIT;
+ case HighGuid::Item: return TYPEID_ITEM;
+ //case HighGuid::Container: return TYPEID_CONTAINER; HighGuid::Container==HighGuid::Item currently
+ case HighGuid::Unit: return TYPEID_UNIT;
+ case HighGuid::Pet: return TYPEID_UNIT;
+ case HighGuid::Player: return TYPEID_PLAYER;
+ case HighGuid::GameObject: return TYPEID_GAMEOBJECT;
+ case HighGuid::DynamicObject: return TYPEID_DYNAMICOBJECT;
+ case HighGuid::Corpse: return TYPEID_CORPSE;
+ case HighGuid::Mo_Transport: return TYPEID_GAMEOBJECT;
+ case HighGuid::Vehicle: return TYPEID_UNIT;
// unknown
- case HIGHGUID_INSTANCE:
- case HIGHGUID_GROUP:
+ case HighGuid::Instance:
+ case HighGuid::Group:
default: return TYPEID_OBJECT;
}
}
@@ -173,19 +212,19 @@ class ObjectGuid
{
switch (high)
{
- case HIGHGUID_ITEM:
- case HIGHGUID_PLAYER:
- case HIGHGUID_DYNAMICOBJECT:
- case HIGHGUID_CORPSE:
- case HIGHGUID_MO_TRANSPORT:
- case HIGHGUID_INSTANCE:
- case HIGHGUID_GROUP:
+ case HighGuid::Item:
+ case HighGuid::Player:
+ case HighGuid::DynamicObject:
+ case HighGuid::Corpse:
+ case HighGuid::Mo_Transport:
+ case HighGuid::Instance:
+ case HighGuid::Group:
return false;
- case HIGHGUID_GAMEOBJECT:
- case HIGHGUID_TRANSPORT:
- case HIGHGUID_UNIT:
- case HIGHGUID_PET:
- case HIGHGUID_VEHICLE:
+ case HighGuid::GameObject:
+ case HighGuid::Transport:
+ case HighGuid::Unit:
+ case HighGuid::Pet:
+ case HighGuid::Vehicle:
default:
return true;
}
@@ -193,6 +232,9 @@ class ObjectGuid
bool HasEntry() const { return HasEntry(GetHigh()); }
+ static ObjectGuid Global(HighGuid type, LowType counter);
+ static ObjectGuid MapSpecific(HighGuid type, uint32 entry, LowType counter);
+
explicit ObjectGuid(uint32 const&) = delete; // no implementation, used to catch wrong type assignment
ObjectGuid(HighGuid, uint32, uint64 counter) = delete; // no implementation, used to catch wrong type assignment
ObjectGuid(HighGuid, uint64 counter) = delete; // no implementation, used to catch wrong type assignment
@@ -228,18 +270,33 @@ class PackedGuid
ByteBuffer _packedGuid;
};
-template<HighGuid high>
-class ObjectGuidGenerator
+
+class ObjectGuidGeneratorBase
{
- public:
- explicit ObjectGuidGenerator(uint32 start = 1) : _nextGuid(start) { }
+public:
+ ObjectGuidGeneratorBase(ObjectGuid::LowType start = 1) : _nextGuid(start) { }
- void Set(uint32 val) { _nextGuid = val; }
- uint32 Generate();
- uint32 GetNextAfterMaxUsed() const { return _nextGuid; }
+ virtual void Set(ObjectGuid::LowType val) { _nextGuid = val; }
+ virtual ObjectGuid::LowType Generate() = 0;
+ ObjectGuid::LowType GetNextAfterMaxUsed() const { return _nextGuid; }
- private:
- uint32 _nextGuid;
+protected:
+ static void HandleCounterOverflow(HighGuid high);
+ ObjectGuid::LowType _nextGuid;
+};
+
+template<HighGuid high>
+class ObjectGuidGenerator : public ObjectGuidGeneratorBase
+{
+public:
+ explicit ObjectGuidGenerator(ObjectGuid::LowType start = 1) : ObjectGuidGeneratorBase(start) { }
+
+ ObjectGuid::LowType Generate() override
+ {
+ if (_nextGuid >= ObjectGuid::GetMaxCounter(high) - 1)
+ HandleCounterOverflow(high);
+ return _nextGuid++;
+ }
};
ByteBuffer& operator<<(ByteBuffer& buf, ObjectGuid const& guid);
diff --git a/src/server/game/Entities/Object/Position.cpp b/src/server/game/Entities/Object/Position.cpp
index 530e51cd8f5..ae559cbac3a 100644
--- a/src/server/game/Entities/Object/Position.cpp
+++ b/src/server/game/Entities/Object/Position.cpp
@@ -17,9 +17,10 @@
#include "Position.h"
#include "ByteBuffer.h"
-#include "G3D/g3dmath.h"
#include "GridDefines.h"
+#include <G3D/g3dmath.h>
+
bool Position::operator==(Position const &a)
{
return (G3D::fuzzyEq(a.m_positionX, m_positionX) &&
@@ -97,6 +98,34 @@ void Position::GetSinCos(const float x, const float y, float &vsin, float &vcos)
}
}
+bool Position::IsWithinBox(const Position& center, float xradius, float yradius, float zradius) const
+{
+ // rotate the WorldObject position instead of rotating the whole cube, that way we can make a simplified
+ // is-in-cube check and we have to calculate only one point instead of 4
+
+ // 2PI = 360*, keep in mind that ingame orientation is counter-clockwise
+ double rotation = 2 * M_PI - center.GetOrientation();
+ double sinVal = std::sin(rotation);
+ double cosVal = std::cos(rotation);
+
+ float BoxDistX = GetPositionX() - center.GetPositionX();
+ float BoxDistY = GetPositionY() - center.GetPositionY();
+
+ float rotX = float(center.GetPositionX() + BoxDistX * cosVal - BoxDistY*sinVal);
+ float rotY = float(center.GetPositionY() + BoxDistY * cosVal + BoxDistX*sinVal);
+
+ // box edges are parallel to coordiante axis, so we can treat every dimension independently :D
+ float dz = GetPositionZ() - center.GetPositionZ();
+ float dx = rotX - center.GetPositionX();
+ float dy = rotY - center.GetPositionY();
+ if ((std::fabs(dx) > xradius) ||
+ (std::fabs(dy) > yradius) ||
+ (std::fabs(dz) > zradius))
+ return false;
+
+ return true;
+}
+
bool Position::HasInArc(float arc, const Position* obj, float border) const
{
// always have self in arc
diff --git a/src/server/game/Entities/Object/Position.h b/src/server/game/Entities/Object/Position.h
index 5bd37567811..b3e474fa96b 100644
--- a/src/server/game/Entities/Object/Position.h
+++ b/src/server/game/Entities/Object/Position.h
@@ -195,6 +195,7 @@ public:
return GetExactDistSq(pos) < dist * dist;
}
+ bool IsWithinBox(const Position& center, float xradius, float yradius, float zradius) const;
bool HasInArc(float arcangle, Position const* pos, float border = 2.0f) const;
bool HasInLine(Position const* pos, float width) const;
std::string ToString() const;
diff --git a/src/server/game/Entities/Object/Updates/UpdateData.cpp b/src/server/game/Entities/Object/Updates/UpdateData.cpp
index 937bda3a79d..ce27319de74 100644
--- a/src/server/game/Entities/Object/Updates/UpdateData.cpp
+++ b/src/server/game/Entities/Object/Updates/UpdateData.cpp
@@ -20,7 +20,6 @@
#include "ByteBuffer.h"
#include "WorldPacket.h"
#include "UpdateData.h"
-#include "Log.h"
#include "Opcodes.h"
#include "World.h"
#include "zlib.h"
diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index 97cdb0cf1df..a399600d2f2 100644
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -52,7 +52,7 @@ Pet::Pet(Player* owner, PetType type) :
}
m_name = "Pet";
- m_regenTimer = PET_FOCUS_REGEN_INTERVAL;
+ m_focusRegenTimer = PET_FOCUS_REGEN_INTERVAL;
}
Pet::~Pet()
@@ -66,7 +66,7 @@ void Pet::AddToWorld()
if (!IsInWorld())
{
///- Register the pet for guid lookup
- sObjectAccessor->AddObject(this);
+ GetMap()->GetObjectsStore().Insert<Pet>(GetGUID(), this);
Unit::AddToWorld();
AIM_Initialize();
}
@@ -90,7 +90,7 @@ void Pet::RemoveFromWorld()
{
///- Don't call the function for Creature, normal mobs + totems go in a different storage
Unit::RemoveFromWorld();
- sObjectAccessor->RemoveObject(this);
+ GetMap()->GetObjectsStore().Remove<Pet>(GetGUID());
}
}
@@ -98,7 +98,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
{
m_loading = true;
- uint32 ownerid = owner->GetGUIDLow();
+ ObjectGuid::LowType ownerid = owner->GetGUID().GetCounter();
PreparedStatement* stmt;
PreparedQueryResult result;
@@ -174,7 +174,8 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
}
Map* map = owner->GetMap();
- uint32 guid = sObjectMgr->GenerateLowGuid(HIGHGUID_PET);
+ ObjectGuid::LowType guid = map->GenerateLowGuid<HighGuid::Pet>();
+
if (!Create(guid, map, owner->GetPhaseMask(), petEntry, petId))
return false;
@@ -191,7 +192,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
if (!IsPositionValid())
{
TC_LOG_ERROR("entities.pet", "Pet (guidlow %d, entry %d) not loaded. Suggested coordinates isn't valid (X: %f Y: %f)",
- GetGUIDLow(), GetEntry(), GetPositionX(), GetPositionY());
+ GetGUID().GetCounter(), GetEntry(), GetPositionX(), GetPositionY());
return false;
}
@@ -248,7 +249,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
if (!IsPositionValid())
{
TC_LOG_ERROR("entities.pet", "Pet (guidlow %d, entry %d) not loaded. Suggested coordinates isn't valid (X: %f Y: %f)",
- GetGUIDLow(), GetEntry(), GetPositionX(), GetPositionY());
+ GetGUID().GetCounter(), GetEntry(), GetPositionX(), GetPositionY());
return false;
}
@@ -332,7 +333,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
CleanupActionBar(); // remove unknown spells from action bar after load
- TC_LOG_DEBUG("entities.pet", "New Pet has guid %u", GetGUIDLow());
+ TC_LOG_DEBUG("entities.pet", "New Pet has guid %u", GetGUID().GetCounter());
owner->PetSpellInitialize();
@@ -343,10 +344,10 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
if (getPetType() == HUNTER_PET)
{
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_DECLINED_NAME);
- stmt->setUInt32(0, owner->GetGUIDLow());
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_DECLINED_NAME);
+ stmt->setUInt32(0, owner->GetGUID().GetCounter());
stmt->setUInt32(1, GetCharmInfo()->GetPetNumber());
- PreparedQueryResult result = CharacterDatabase.Query(stmt);
+ result = CharacterDatabase.Query(stmt);
if (result)
{
@@ -414,7 +415,7 @@ void Pet::SavePetToDB(PetSaveMode mode)
// current/stable/not_in_slot
if (mode >= PET_SAVE_AS_CURRENT)
{
- uint32 ownerLowGUID = GetOwnerGUID().GetCounter();
+ ObjectGuid::LowType ownerLowGUID = GetOwnerGUID().GetCounter();
std::string name = m_name;
CharacterDatabase.EscapeString(name);
trans = CharacterDatabase.BeginTransaction();
@@ -484,7 +485,7 @@ void Pet::SavePetToDB(PetSaveMode mode)
}
}
-void Pet::DeleteFromDB(uint32 guidlow)
+void Pet::DeleteFromDB(ObjectGuid::LowType guidlow)
{
SQLTransaction trans = CharacterDatabase.BeginTransaction();
@@ -588,22 +589,22 @@ void Pet::Update(uint32 diff)
}
//regenerate focus for hunter pets or energy for deathknight's ghoul
- if (m_regenTimer)
+ if (m_focusRegenTimer)
{
- if (m_regenTimer > diff)
- m_regenTimer -= diff;
+ if (m_focusRegenTimer > diff)
+ m_focusRegenTimer -= diff;
else
{
switch (getPowerType())
{
case POWER_FOCUS:
Regenerate(POWER_FOCUS);
- m_regenTimer += PET_FOCUS_REGEN_INTERVAL - diff;
- if (!m_regenTimer) ++m_regenTimer;
+ m_focusRegenTimer += PET_FOCUS_REGEN_INTERVAL - diff;
+ if (!m_focusRegenTimer) ++m_focusRegenTimer;
// Reset if large diff (lag) causes focus to get 'stuck'
- if (m_regenTimer > PET_FOCUS_REGEN_INTERVAL)
- m_regenTimer = PET_FOCUS_REGEN_INTERVAL;
+ if (m_focusRegenTimer > PET_FOCUS_REGEN_INTERVAL)
+ m_focusRegenTimer = PET_FOCUS_REGEN_INTERVAL;
break;
@@ -614,7 +615,7 @@ void Pet::Update(uint32 diff)
// if (!m_regenTimer) ++m_regenTimer;
// break;
default:
- m_regenTimer = 0;
+ m_focusRegenTimer = 0;
break;
}
}
@@ -769,7 +770,7 @@ bool Pet::CreateBaseAtCreature(Creature* creature)
if (!IsPositionValid())
{
TC_LOG_ERROR("entities.pet", "Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
- GetGUIDLow(), GetEntry(), GetPositionX(), GetPositionY());
+ GetGUID().GetCounter(), GetEntry(), GetPositionX(), GetPositionY());
return false;
}
@@ -806,7 +807,7 @@ bool Pet::CreateBaseAtCreatureInfo(CreatureTemplate const* cinfo, Unit* owner)
bool Pet::CreateBaseAtTamed(CreatureTemplate const* cinfo, Map* map, uint32 phaseMask)
{
TC_LOG_DEBUG("entities.pet", "Pet::CreateBaseForTamed");
- uint32 guid=sObjectMgr->GenerateLowGuid(HIGHGUID_PET);
+ ObjectGuid::LowType guid=map->GenerateLowGuid<HighGuid::Pet>();
uint32 petId = sObjectMgr->GeneratePetNumber();
if (!Create(guid, map, phaseMask, cinfo->Entry, petId))
return false;
@@ -1183,7 +1184,7 @@ void Pet::_SaveSpells(SQLTransaction& trans)
void Pet::_LoadAuras(uint32 timediff)
{
- TC_LOG_DEBUG("entities.pet", "Loading auras for pet %u", GetGUIDLow());
+ TC_LOG_DEBUG("entities.pet", "Loading auras for pet %u", GetGUID().GetCounter());
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_AURA);
stmt->setUInt32(0, m_charmInfo->GetPetNumber());
@@ -1679,7 +1680,7 @@ void Pet::resetTalentsForAllPetsOf(Player* owner, Pet* onlinePet /*= NULL*/)
uint32 exceptPetNumber = onlinePet ? onlinePet->GetCharmInfo()->GetPetNumber() : 0;
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_PET);
- stmt->setUInt32(0, owner->GetGUIDLow());
+ stmt->setUInt32(0, owner->GetGUID().GetCounter());
stmt->setUInt32(1, exceptPetNumber);
PreparedQueryResult resultPets = CharacterDatabase.Query(stmt);
@@ -1688,7 +1689,7 @@ void Pet::resetTalentsForAllPetsOf(Player* owner, Pet* onlinePet /*= NULL*/)
return;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_SPELL_LIST);
- stmt->setUInt32(0, owner->GetGUIDLow());
+ stmt->setUInt32(0, owner->GetGUID().GetCounter());
stmt->setUInt32(1, exceptPetNumber);
PreparedQueryResult result = CharacterDatabase.Query(stmt);
@@ -1756,7 +1757,7 @@ void Pet::InitTalentForLevel()
GetOwner()->SendTalentsInfoData(true);
}
-uint8 Pet::GetMaxTalentPointsForLevel(uint8 level)
+uint8 Pet::GetMaxTalentPointsForLevel(uint8 level) const
{
uint8 points = (level >= 20) ? ((level - 16) / 4) : 0;
// Mod points from owner SPELL_AURA_MOD_PET_TALENT_POINTS
@@ -1834,15 +1835,15 @@ bool Pet::IsPermanentPetFor(Player* owner) const
}
}
-bool Pet::Create(uint32 guidlow, Map* map, uint32 phaseMask, uint32 Entry, uint32 petId)
+bool Pet::Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, uint32 Entry, uint32 petId)
{
ASSERT(map);
SetMap(map);
SetPhaseMask(phaseMask, false);
- Object::_Create(guidlow, petId, HIGHGUID_PET);
+ Object::_Create(guidlow, petId, HighGuid::Pet);
- m_DBTableGuid = guidlow;
+ m_spawnId = guidlow;
m_originalEntry = Entry;
if (!InitEntry(Entry))
diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h
index 1cc86ea2a20..c8e95a06a2c 100644
--- a/src/server/game/Entities/Pet/Pet.h
+++ b/src/server/game/Entities/Pet/Pet.h
@@ -55,7 +55,7 @@ class Pet : public Guardian
bool IsPermanentPetFor(Player* owner) const; // pet have tab in character windows and set UNIT_FIELD_PETNUMBER
- bool Create(uint32 guidlow, Map* map, uint32 phaseMask, uint32 Entry, uint32 pet_number);
+ bool Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, uint32 Entry, uint32 pet_number);
bool CreateBaseAtCreature(Creature* creature);
bool CreateBaseAtCreatureInfo(CreatureTemplate const* cinfo, Unit* owner);
bool CreateBaseAtTamed(CreatureTemplate const* cinfo, Map* map, uint32 phaseMask);
@@ -63,7 +63,7 @@ class Pet : public Guardian
bool IsLoading() const override { return m_loading;}
void SavePetToDB(PetSaveMode mode);
void Remove(PetSaveMode mode, bool returnreagent = false);
- static void DeleteFromDB(uint32 guidlow);
+ static void DeleteFromDB(ObjectGuid::LowType guidlow);
void setDeathState(DeathState s) override; // overwrite virtual Creature::setDeathState and Unit::setDeathState
void Update(uint32 diff) override; // overwrite virtual Creature::Update and Unit::Update
@@ -130,8 +130,8 @@ class Pet : public Guardian
static void resetTalentsForAllPetsOf(Player* owner, Pet* online_pet = nullptr);
void InitTalentForLevel();
- uint8 GetMaxTalentPointsForLevel(uint8 level);
- uint8 GetFreeTalentPoints() { return GetByteValue(UNIT_FIELD_BYTES_1, 1); }
+ uint8 GetMaxTalentPointsForLevel(uint8 level) const;
+ uint8 GetFreeTalentPoints() const { return GetByteValue(UNIT_FIELD_BYTES_1, 1); }
void SetFreeTalentPoints(uint8 points) { SetByteValue(UNIT_FIELD_BYTES_1, 1, points); }
uint32 m_usedTalentCount;
@@ -152,18 +152,18 @@ class Pet : public Guardian
int32 m_duration; // time until unsummon (used mostly for summoned guardians and not used for controlled pets)
uint64 m_auraRaidUpdateMask;
bool m_loading;
- uint32 m_regenTimer;
+ uint32 m_focusRegenTimer;
DeclinedName *m_declinedname;
private:
void SaveToDB(uint32, uint8, uint32) override // override of Creature::SaveToDB - must not be called
{
- ASSERT(false);
+ ABORT();
}
void DeleteFromDB() override // override of Creature::DeleteFromDB - must not be called
{
- ASSERT(false);
+ ABORT();
}
};
#endif
diff --git a/src/server/game/Entities/Player/KillRewarder.cpp b/src/server/game/Entities/Player/KillRewarder.cpp
new file mode 100644
index 00000000000..ad2f8f641ea
--- /dev/null
+++ b/src/server/game/Entities/Player/KillRewarder.cpp
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "KillRewarder.h"
+#include "SpellAuraEffects.h"
+#include "Creature.h"
+#include "Formulas.h"
+#include "Group.h"
+#include "Guild.h"
+#include "GuildMgr.h"
+#include "InstanceScript.h"
+#include "Pet.h"
+#include "Player.h"
+
+ // == KillRewarder ====================================================
+ // KillRewarder encapsulates logic of rewarding player upon kill with:
+ // * XP;
+ // * honor;
+ // * reputation;
+ // * kill credit (for quest objectives).
+ // Rewarding is initiated in two cases: when player kills unit in Unit::Kill()
+ // and on battlegrounds in Battleground::RewardXPAtKill().
+ //
+ // Rewarding algorithm is:
+ // 1. Initialize internal variables to default values.
+ // 2. In case when player is in group, initialize variables necessary for group calculations:
+ // 2.1. _count - number of alive group members within reward distance;
+ // 2.2. _sumLevel - sum of levels of alive group members within reward distance;
+ // 2.3. _maxLevel - maximum level of alive group member within reward distance;
+ // 2.4. _maxNotGrayMember - maximum level of alive group member within reward distance,
+ // for whom victim is not gray;
+ // 2.5. _isFullXP - flag identifying that for all group members victim is not gray,
+ // so 100% XP will be rewarded (50% otherwise).
+ // 3. Reward killer (and group, if necessary).
+ // 3.1. If killer is in group, reward group.
+ // 3.1.1. Initialize initial XP amount based on maximum level of group member,
+ // for whom victim is not gray.
+ // 3.1.2. Alter group rate if group is in raid (not for battlegrounds).
+ // 3.1.3. Reward each group member (even dead) within reward distance (see 4. for more details).
+ // 3.2. Reward single killer (not group case).
+ // 3.2.1. Initialize initial XP amount based on killer's level.
+ // 3.2.2. Reward killer (see 4. for more details).
+ // 4. Reward player.
+ // 4.1. Give honor (player must be alive and not on BG).
+ // 4.2. Give XP.
+ // 4.2.1. If player is in group, adjust XP:
+ // * set to 0 if player's level is more than maximum level of not gray member;
+ // * cut XP in half if _isFullXP is false.
+ // 4.2.2. Apply auras modifying rewarded XP.
+ // 4.2.3. Give XP to player.
+ // 4.2.4. If player has pet, reward pet with XP (100% for single player, 50% for group case).
+ // 4.3. Give reputation (player must not be on BG).
+ // 4.4. Give kill credit (player must not be in group, or he must be alive or without corpse).
+ // 5. Credit instance encounter.
+
+KillRewarder::KillRewarder(Player* killer, Unit* victim, bool isBattleGround) :
+ // 1. Initialize internal variables to default values.
+ _killer(killer), _victim(victim), _group(killer->GetGroup()),
+ _groupRate(1.0f), _maxNotGrayMember(nullptr), _count(0), _sumLevel(0), _xp(0),
+ _isFullXP(false), _maxLevel(0), _isBattleGround(isBattleGround), _isPvP(false)
+{
+ // mark the credit as pvp if victim is player
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ _isPvP = true;
+ // or if its owned by player and its not a vehicle
+ else if (victim->GetCharmerOrOwnerGUID().IsPlayer())
+ _isPvP = !victim->IsVehicle();
+
+ _InitGroupData();
+}
+
+inline void KillRewarder::_InitGroupData()
+{
+ if (_group)
+ {
+ // 2. In case when player is in group, initialize variables necessary for group calculations:
+ for (GroupReference* itr = _group->GetFirstMember(); itr != nullptr; itr = itr->next())
+ if (Player* member = itr->GetSource())
+ if (member->IsAlive() && member->IsAtGroupRewardDistance(_victim))
+ {
+ const uint8 lvl = member->getLevel();
+ // 2.1. _count - number of alive group members within reward distance;
+ ++_count;
+ // 2.2. _sumLevel - sum of levels of alive group members within reward distance;
+ _sumLevel += lvl;
+ // 2.3. _maxLevel - maximum level of alive group member within reward distance;
+ if (_maxLevel < lvl)
+ _maxLevel = lvl;
+ // 2.4. _maxNotGrayMember - maximum level of alive group member within reward distance,
+ // for whom victim is not gray;
+ uint32 grayLevel = Trinity::XP::GetGrayLevel(lvl);
+ if (_victim->getLevel() > grayLevel && (!_maxNotGrayMember || _maxNotGrayMember->getLevel() < lvl))
+ _maxNotGrayMember = member;
+ }
+ // 2.5. _isFullXP - flag identifying that for all group members victim is not gray,
+ // so 100% XP will be rewarded (50% otherwise).
+ _isFullXP = _maxNotGrayMember && (_maxLevel == _maxNotGrayMember->getLevel());
+ }
+ else
+ _count = 1;
+}
+
+inline void KillRewarder::_InitXP(Player* player)
+{
+ // Get initial value of XP for kill.
+ // XP is given:
+ // * on battlegrounds;
+ // * otherwise, not in PvP;
+ // * not if killer is on vehicle.
+ if (_isBattleGround || (!_isPvP && !_killer->GetVehicle()))
+ _xp = Trinity::XP::Gain(player, _victim, _isBattleGround);
+}
+
+inline void KillRewarder::_RewardHonor(Player* player)
+{
+ // Rewarded player must be alive.
+ if (player->IsAlive())
+ player->RewardHonor(_victim, _count, -1, true);
+}
+
+inline void KillRewarder::_RewardXP(Player* player, float rate)
+{
+ uint32 xp(_xp);
+ if (_group)
+ {
+ // 4.2.1. If player is in group, adjust XP:
+ // * set to 0 if player's level is more than maximum level of not gray member;
+ // * cut XP in half if _isFullXP is false.
+ if (_maxNotGrayMember && player->IsAlive() &&
+ _maxNotGrayMember->getLevel() >= player->getLevel())
+ xp = _isFullXP ?
+ uint32(xp * rate) : // Reward FULL XP if all group members are not gray.
+ uint32(xp * rate / 2) + 1; // Reward only HALF of XP if some of group members are gray.
+ else
+ xp = 0;
+ }
+ if (xp)
+ {
+ // 4.2.2. Apply auras modifying rewarded XP (SPELL_AURA_MOD_XP_PCT).
+ for (auto const& aura : player->GetAuraEffectsByType(SPELL_AURA_MOD_XP_PCT))
+ AddPct(xp, aura->GetAmount());
+
+ // 4.2.3. Give XP to player.
+ player->GiveXP(xp, _victim, _groupRate);
+ if (Pet* pet = player->GetPet())
+ // 4.2.4. If player has pet, reward pet with XP (100% for single player, 50% for group case).
+ pet->GivePetXP(_group ? xp / 2 : xp);
+ }
+}
+
+inline void KillRewarder::_RewardReputation(Player* player, float rate)
+{
+ // 4.3. Give reputation (player must not be on BG).
+ // Even dead players and corpses are rewarded.
+ player->RewardReputation(_victim, rate);
+}
+
+inline void KillRewarder::_RewardKillCredit(Player* player)
+{
+ // 4.4. Give kill credit (player must not be in group, or he must be alive or without corpse).
+ if (!_group || player->IsAlive() || !player->GetCorpse())
+ if (Creature* target = _victim->ToCreature())
+ {
+ player->KilledMonster(target->GetCreatureTemplate(), target->GetGUID());
+ player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE, target->GetCreatureType(), 1, target);
+ }
+}
+
+void KillRewarder::_RewardPlayer(Player* player, bool isDungeon)
+{
+ // 4. Reward player.
+ if (!_isBattleGround)
+ {
+ // 4.1. Give honor (player must be alive and not on BG).
+ _RewardHonor(player);
+ // 4.1.1 Send player killcredit for quests with PlayerSlain
+ if (_victim->GetTypeId() == TYPEID_PLAYER)
+ player->KilledPlayerCredit();
+ }
+ // Give XP only in PvE or in battlegrounds.
+ // Give reputation and kill credit only in PvE.
+ if (!_isPvP || _isBattleGround)
+ {
+ float const rate = _group ?
+ _groupRate * float(player->getLevel()) / _sumLevel : // Group rate depends on summary level.
+ 1.0f; // Personal rate is 100%.
+ if (_xp)
+ // 4.2. Give XP.
+ _RewardXP(player, rate);
+ if (!_isBattleGround)
+ {
+ // If killer is in dungeon then all members receive full reputation at kill.
+ _RewardReputation(player, isDungeon ? 1.0f : rate);
+ _RewardKillCredit(player);
+ }
+ }
+}
+
+void KillRewarder::_RewardGroup()
+{
+ if (_maxLevel)
+ {
+ if (_maxNotGrayMember)
+ // 3.1.1. Initialize initial XP amount based on maximum level of group member,
+ // for whom victim is not gray.
+ _InitXP(_maxNotGrayMember);
+ // To avoid unnecessary calculations and calls,
+ // proceed only if XP is not ZERO or player is not on battleground
+ // (battleground rewards only XP, that's why).
+ if (!_isBattleGround || _xp)
+ {
+ bool const isDungeon = !_isPvP && sMapStore.LookupEntry(_killer->GetMapId())->IsDungeon();
+ if (!_isBattleGround)
+ {
+ // 3.1.2. Alter group rate if group is in raid (not for battlegrounds).
+ bool const isRaid = !_isPvP && sMapStore.LookupEntry(_killer->GetMapId())->IsRaid() && _group->isRaidGroup();
+ _groupRate = Trinity::XP::xp_in_group_rate(_count, isRaid);
+ }
+
+ // 3.1.3. Reward each group member (even dead or corpse) within reward distance.
+ for (GroupReference* itr = _group->GetFirstMember(); itr != nullptr; itr = itr->next())
+ {
+ if (Player* member = itr->GetSource())
+ {
+ if (member->IsAtGroupRewardDistance(_victim))
+ {
+ _RewardPlayer(member, isDungeon);
+ member->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL, 1, 0, _victim);
+ }
+ }
+ }
+ }
+ }
+}
+
+void KillRewarder::Reward()
+{
+ // 3. Reward killer (and group, if necessary).
+ if (_group)
+ // 3.1. If killer is in group, reward group.
+ _RewardGroup();
+ else
+ {
+ // 3.2. Reward single killer (not group case).
+ // 3.2.1. Initialize initial XP amount based on killer's level.
+ _InitXP(_killer);
+ // To avoid unnecessary calculations and calls,
+ // proceed only if XP is not ZERO or player is not on battleground
+ // (battleground rewards only XP, that's why).
+ if (!_isBattleGround || _xp)
+ // 3.2.2. Reward killer.
+ _RewardPlayer(_killer, false);
+ }
+
+ // 5. Credit instance encounter.
+ if (Creature* victim = _victim->ToCreature())
+ if (victim->IsDungeonBoss())
+ if (InstanceScript* instance = _victim->GetInstanceScript())
+ instance->UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, _victim->GetEntry(), _victim);
+}
diff --git a/src/server/game/Entities/Player/KillRewarder.h b/src/server/game/Entities/Player/KillRewarder.h
new file mode 100644
index 00000000000..577a8ffea20
--- /dev/null
+++ b/src/server/game/Entities/Player/KillRewarder.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KillRewarder_h__
+#define KillRewarder_h__
+
+#include "Define.h"
+
+class Player;
+class Unit;
+class Group;
+
+class KillRewarder
+{
+public:
+ KillRewarder(Player* killer, Unit* victim, bool isBattleGround);
+
+ void Reward();
+
+private:
+ void _InitXP(Player* player);
+ void _InitGroupData();
+
+ void _RewardHonor(Player* player);
+ void _RewardXP(Player* player, float rate);
+ void _RewardReputation(Player* player, float rate);
+ void _RewardKillCredit(Player* player);
+ void _RewardPlayer(Player* player, bool isDungeon);
+ void _RewardGroup();
+
+ Player* _killer;
+ Unit* _victim;
+ Group* _group;
+ float _groupRate;
+ Player* _maxNotGrayMember;
+ uint32 _count;
+ uint32 _sumLevel;
+ uint32 _xp;
+ bool _isFullXP;
+ uint8 _maxLevel;
+ bool _isBattleGround;
+ bool _isPvP;
+};
+
+#endif // KillRewarder_h__
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 275dbf92dca..a8f015a8749 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -48,6 +48,7 @@
#include "GuildMgr.h"
#include "InstanceSaveMgr.h"
#include "InstanceScript.h"
+#include "KillRewarder.h"
#include "LFGMgr.h"
#include "Language.h"
#include "Log.h"
@@ -60,7 +61,7 @@
#include "Pet.h"
#include "QuestDef.h"
#include "ReputationMgr.h"
-#include "revision.h"
+#include "GitRevision.h"
#include "SkillDiscovery.h"
#include "SocialMgr.h"
#include "Spell.h"
@@ -69,6 +70,7 @@
#include "SpellMgr.h"
#include "SpellHistory.h"
#include "Transport.h"
+#include "TicketMgr.h"
#include "UpdateData.h"
#include "UpdateFieldFlags.h"
#include "UpdateMask.h"
@@ -288,374 +290,6 @@ std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi)
return ss;
}
-//== TradeData =================================================
-
-TradeData* TradeData::GetTraderData() const
-{
- return m_trader->GetTradeData();
-}
-
-Item* TradeData::GetItem(TradeSlots slot) const
-{
- return m_items[slot] ? m_player->GetItemByGuid(m_items[slot]) : NULL;
-}
-
-bool TradeData::HasItem(ObjectGuid itemGuid) const
-{
- for (uint8 i = 0; i < TRADE_SLOT_COUNT; ++i)
- if (m_items[i] == itemGuid)
- return true;
-
- return false;
-}
-
-TradeSlots TradeData::GetTradeSlotForItem(ObjectGuid itemGuid) const
-{
- for (uint8 i = 0; i < TRADE_SLOT_COUNT; ++i)
- if (m_items[i] == itemGuid)
- return TradeSlots(i);
-
- return TRADE_SLOT_INVALID;
-}
-
-Item* TradeData::GetSpellCastItem() const
-{
- return m_spellCastItem ? m_player->GetItemByGuid(m_spellCastItem) : NULL;
-}
-
-void TradeData::SetItem(TradeSlots slot, Item* item)
-{
- ObjectGuid itemGuid;
- if (item)
- itemGuid = item->GetGUID();
-
- if (m_items[slot] == itemGuid)
- return;
-
- m_items[slot] = itemGuid;
-
- SetAccepted(false);
- GetTraderData()->SetAccepted(false);
-
- Update();
-
- // need remove possible trader spell applied to changed item
- if (slot == TRADE_SLOT_NONTRADED)
- GetTraderData()->SetSpell(0);
-
- // need remove possible player spell applied (possible move reagent)
- SetSpell(0);
-}
-
-void TradeData::SetSpell(uint32 spell_id, Item* castItem /*= NULL*/)
-{
- ObjectGuid itemGuid = castItem ? castItem->GetGUID() : ObjectGuid::Empty;
-
- if (m_spell == spell_id && m_spellCastItem == itemGuid)
- return;
-
- m_spell = spell_id;
- m_spellCastItem = itemGuid;
-
- SetAccepted(false);
- GetTraderData()->SetAccepted(false);
-
- Update(true); // send spell info to item owner
- Update(false); // send spell info to caster self
-}
-
-void TradeData::SetMoney(uint32 money)
-{
- if (m_money == money)
- return;
-
- if (!m_player->HasEnoughMoney(money))
- {
- TradeStatusInfo info;
- info.Status = TRADE_STATUS_CLOSE_WINDOW;
- info.Result = EQUIP_ERR_NOT_ENOUGH_MONEY;
- m_player->GetSession()->SendTradeStatus(info);
- return;
- }
-
- m_money = money;
-
- SetAccepted(false);
- GetTraderData()->SetAccepted(false);
-
- Update(true);
-}
-
-void TradeData::Update(bool forTarget /*= true*/)
-{
- if (forTarget)
- m_trader->GetSession()->SendUpdateTrade(true); // player state for trader
- else
- m_player->GetSession()->SendUpdateTrade(false); // player state for player
-}
-
-void TradeData::SetAccepted(bool state, bool crosssend /*= false*/)
-{
- m_accepted = state;
-
- if (!state)
- {
- TradeStatusInfo info;
- info.Status = TRADE_STATUS_BACK_TO_TRADE;
- if (crosssend)
- m_trader->GetSession()->SendTradeStatus(info);
- else
- m_player->GetSession()->SendTradeStatus(info);
- }
-}
-
-// == KillRewarder ====================================================
-// KillRewarder incapsulates logic of rewarding player upon kill with:
-// * XP;
-// * honor;
-// * reputation;
-// * kill credit (for quest objectives).
-// Rewarding is initiated in two cases: when player kills unit in Unit::Kill()
-// and on battlegrounds in Battleground::RewardXPAtKill().
-//
-// Rewarding algorithm is:
-// 1. Initialize internal variables to default values.
-// 2. In case when player is in group, initialize variables necessary for group calculations:
-// 2.1. _count - number of alive group members within reward distance;
-// 2.2. _sumLevel - sum of levels of alive group members within reward distance;
-// 2.3. _maxLevel - maximum level of alive group member within reward distance;
-// 2.4. _maxNotGrayMember - maximum level of alive group member within reward distance,
-// for whom victim is not gray;
-// 2.5. _isFullXP - flag identifying that for all group members victim is not gray,
-// so 100% XP will be rewarded (50% otherwise).
-// 3. Reward killer (and group, if necessary).
-// 3.1. If killer is in group, reward group.
-// 3.1.1. Initialize initial XP amount based on maximum level of group member,
-// for whom victim is not gray.
-// 3.1.2. Alter group rate if group is in raid (not for battlegrounds).
-// 3.1.3. Reward each group member (even dead) within reward distance (see 4. for more details).
-// 3.2. Reward single killer (not group case).
-// 3.2.1. Initialize initial XP amount based on killer's level.
-// 3.2.2. Reward killer (see 4. for more details).
-// 4. Reward player.
-// 4.1. Give honor (player must be alive and not on BG).
-// 4.2. Give XP.
-// 4.2.1. If player is in group, adjust XP:
-// * set to 0 if player's level is more than maximum level of not gray member;
-// * cut XP in half if _isFullXP is false.
-// 4.2.2. Apply auras modifying rewarded XP.
-// 4.2.3. Give XP to player.
-// 4.2.4. If player has pet, reward pet with XP (100% for single player, 50% for group case).
-// 4.3. Give reputation (player must not be on BG).
-// 4.4. Give kill credit (player must not be in group, or he must be alive or without corpse).
-// 5. Credit instance encounter.
-KillRewarder::KillRewarder(Player* killer, Unit* victim, bool isBattleGround) :
- // 1. Initialize internal variables to default values.
- _killer(killer), _victim(victim), _group(killer->GetGroup()),
- _groupRate(1.0f), _maxNotGrayMember(NULL), _count(0), _sumLevel(0), _xp(0),
- _isFullXP(false), _maxLevel(0), _isBattleGround(isBattleGround), _isPvP(false)
-{
- // mark the credit as pvp if victim is player
- if (victim->GetTypeId() == TYPEID_PLAYER)
- _isPvP = true;
- // or if its owned by player and its not a vehicle
- else if (victim->GetCharmerOrOwnerGUID().IsPlayer())
- _isPvP = !victim->IsVehicle();
-
- _InitGroupData();
-}
-
-inline void KillRewarder::_InitGroupData()
-{
- if (_group)
- {
- // 2. In case when player is in group, initialize variables necessary for group calculations:
- for (GroupReference* itr = _group->GetFirstMember(); itr != NULL; itr = itr->next())
- if (Player* member = itr->GetSource())
- if (member->IsAlive() && member->IsAtGroupRewardDistance(_victim))
- {
- const uint8 lvl = member->getLevel();
- // 2.1. _count - number of alive group members within reward distance;
- ++_count;
- // 2.2. _sumLevel - sum of levels of alive group members within reward distance;
- _sumLevel += lvl;
- // 2.3. _maxLevel - maximum level of alive group member within reward distance;
- if (_maxLevel < lvl)
- _maxLevel = lvl;
- // 2.4. _maxNotGrayMember - maximum level of alive group member within reward distance,
- // for whom victim is not gray;
- uint32 grayLevel = Trinity::XP::GetGrayLevel(lvl);
- if (_victim->getLevel() > grayLevel && (!_maxNotGrayMember || _maxNotGrayMember->getLevel() < lvl))
- _maxNotGrayMember = member;
- }
- // 2.5. _isFullXP - flag identifying that for all group members victim is not gray,
- // so 100% XP will be rewarded (50% otherwise).
- _isFullXP = _maxNotGrayMember && (_maxLevel == _maxNotGrayMember->getLevel());
- }
- else
- _count = 1;
-}
-
-inline void KillRewarder::_InitXP(Player* player)
-{
- // Get initial value of XP for kill.
- // XP is given:
- // * on battlegrounds;
- // * otherwise, not in PvP;
- // * not if killer is on vehicle.
- if (_isBattleGround || (!_isPvP && !_killer->GetVehicle()))
- _xp = Trinity::XP::Gain(player, _victim);
-}
-
-inline void KillRewarder::_RewardHonor(Player* player)
-{
- // Rewarded player must be alive.
- if (player->IsAlive())
- player->RewardHonor(_victim, _count, -1, true);
-}
-
-inline void KillRewarder::_RewardXP(Player* player, float rate)
-{
- uint32 xp(_xp);
- if (_group)
- {
- // 4.2.1. If player is in group, adjust XP:
- // * set to 0 if player's level is more than maximum level of not gray member;
- // * cut XP in half if _isFullXP is false.
- if (_maxNotGrayMember && player->IsAlive() &&
- _maxNotGrayMember->getLevel() >= player->getLevel())
- xp = _isFullXP ?
- uint32(xp * rate) : // Reward FULL XP if all group members are not gray.
- uint32(xp * rate / 2) + 1; // Reward only HALF of XP if some of group members are gray.
- else
- xp = 0;
- }
- if (xp)
- {
- // 4.2.2. Apply auras modifying rewarded XP (SPELL_AURA_MOD_XP_PCT).
- Unit::AuraEffectList const& auras = player->GetAuraEffectsByType(SPELL_AURA_MOD_XP_PCT);
- for (Unit::AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i)
- AddPct(xp, (*i)->GetAmount());
-
- // 4.2.3. Give XP to player.
- player->GiveXP(xp, _victim, _groupRate);
- if (Pet* pet = player->GetPet())
- // 4.2.4. If player has pet, reward pet with XP (100% for single player, 50% for group case).
- pet->GivePetXP(_group ? xp / 2 : xp);
- }
-}
-
-inline void KillRewarder::_RewardReputation(Player* player, float rate)
-{
- // 4.3. Give reputation (player must not be on BG).
- // Even dead players and corpses are rewarded.
- player->RewardReputation(_victim, rate);
-}
-
-inline void KillRewarder::_RewardKillCredit(Player* player)
-{
- // 4.4. Give kill credit (player must not be in group, or he must be alive or without corpse).
- if (!_group || player->IsAlive() || !player->GetCorpse())
- if (Creature* target = _victim->ToCreature())
- {
- player->KilledMonster(target->GetCreatureTemplate(), target->GetGUID());
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE, target->GetCreatureType(), 1, target);
- }
-}
-
-void KillRewarder::_RewardPlayer(Player* player, bool isDungeon)
-{
- // 4. Reward player.
- if (!_isBattleGround)
- {
- // 4.1. Give honor (player must be alive and not on BG).
- _RewardHonor(player);
- // 4.1.1 Send player killcredit for quests with PlayerSlain
- if (_victim->GetTypeId() == TYPEID_PLAYER)
- player->KilledPlayerCredit();
- }
- // Give XP only in PvE or in battlegrounds.
- // Give reputation and kill credit only in PvE.
- if (!_isPvP || _isBattleGround)
- {
- const float rate = _group ?
- _groupRate * float(player->getLevel()) / _sumLevel : // Group rate depends on summary level.
- 1.0f; // Personal rate is 100%.
- if (_xp)
- // 4.2. Give XP.
- _RewardXP(player, rate);
- if (!_isBattleGround)
- {
- // If killer is in dungeon then all members receive full reputation at kill.
- _RewardReputation(player, isDungeon ? 1.0f : rate);
- _RewardKillCredit(player);
- }
- }
-}
-
-void KillRewarder::_RewardGroup()
-{
- if (_maxLevel)
- {
- if (_maxNotGrayMember)
- // 3.1.1. Initialize initial XP amount based on maximum level of group member,
- // for whom victim is not gray.
- _InitXP(_maxNotGrayMember);
- // To avoid unnecessary calculations and calls,
- // proceed only if XP is not ZERO or player is not on battleground
- // (battleground rewards only XP, that's why).
- if (!_isBattleGround || _xp)
- {
- const bool isDungeon = !_isPvP && sMapStore.LookupEntry(_killer->GetMapId())->IsDungeon();
- if (!_isBattleGround)
- {
- // 3.1.2. Alter group rate if group is in raid (not for battlegrounds).
- const bool isRaid = !_isPvP && sMapStore.LookupEntry(_killer->GetMapId())->IsRaid() && _group->isRaidGroup();
- _groupRate = Trinity::XP::xp_in_group_rate(_count, isRaid);
- }
-
- // 3.1.3. Reward each group member (even dead or corpse) within reward distance.
- for (GroupReference* itr = _group->GetFirstMember(); itr != NULL; itr = itr->next())
- {
- if (Player* member = itr->GetSource())
- {
- if (member->IsAtGroupRewardDistance(_victim))
- {
- _RewardPlayer(member, isDungeon);
- member->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL, 1, 0, _victim);
- }
- }
- }
- }
- }
-}
-
-void KillRewarder::Reward()
-{
- // 3. Reward killer (and group, if necessary).
- if (_group)
- // 3.1. If killer is in group, reward group.
- _RewardGroup();
- else
- {
- // 3.2. Reward single killer (not group case).
- // 3.2.1. Initialize initial XP amount based on killer's level.
- _InitXP(_killer);
- // To avoid unnecessary calculations and calls,
- // proceed only if XP is not ZERO or player is not on battleground
- // (battleground rewards only XP, that's why).
- if (!_isBattleGround || _xp)
- // 3.2.2. Reward killer.
- _RewardPlayer(_killer, false);
- }
-
- // 5. Credit instance encounter.
- if (Creature* victim = _victim->ToCreature())
- if (victim->IsDungeonBoss())
- if (InstanceScript* instance = _victim->GetInstanceScript())
- instance->UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, _victim->GetEntry(), _victim);
-}
-
Player::Player(WorldSession* session): Unit(true)
{
m_speakTime = 0;
@@ -749,7 +383,6 @@ Player::Player(WorldSession* session): Unit(true)
m_MirrorTimerFlagsLast = UNDERWATER_NONE;
m_isInWater = false;
m_drunkTimer = 0;
- m_restTime = 0;
m_deathTimer = 0;
m_deathExpireTime = 0;
@@ -780,13 +413,10 @@ Player::Player(WorldSession* session): Unit(true)
m_lastpetnumber = 0;
////////////////////Rest System/////////////////////
- time_inn_enter = 0;
- inn_pos_mapid = 0;
- inn_pos_x = 0.0f;
- inn_pos_y = 0.0f;
- inn_pos_z = 0.0f;
+ _restTime = 0;
+ inn_triggerId = 0;
m_rest_bonus = 0;
- rest_type = REST_TYPE_NO;
+ _restFlagMask = 0;
////////////////////Rest System/////////////////////
m_mailsLoaded = false;
@@ -905,6 +535,8 @@ Player::Player(WorldSession* session): Unit(true)
SetPendingBind(0, 0);
_activeCheats = CHEAT_NONE;
+ healthBeforeDuel = 0;
+ manaBeforeDuel = 0;
m_achievementMgr = new AchievementMgr(this);
m_reputationMgr = new ReputationMgr(this);
}
@@ -961,12 +593,12 @@ void Player::CleanupsBeforeDelete(bool finalCleanup)
itr->second.save->RemovePlayer(this);
}
-bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
+bool Player::Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo)
{
//FIXME: outfitId not used in player creating
/// @todo need more checks against packet modifications
- Object::_Create(guidlow, 0, HIGHGUID_PLAYER);
+ Object::_Create(guidlow, 0, HighGuid::Player);
m_name = createInfo->Name;
@@ -1726,15 +1358,20 @@ void Player::Update(uint32 p_time)
if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING))
{
- if (roll_chance_i(3) && GetTimeInnEnter() > 0) // freeze update
+ if (roll_chance_i(3) && _restTime > 0) // freeze update
{
- time_t time_inn = time(NULL)-GetTimeInnEnter();
- if (time_inn >= 10) // freeze update
+ time_t currTime = time(nullptr);
+ time_t timeDiff = currTime - _restTime;
+ if (timeDiff >= 10) // freeze update
{
- float bubble = 0.125f*sWorld->getRate(RATE_REST_INGAME);
- // speed collect rest bonus (section/in hour)
- SetRestBonus(GetRestBonus()+ time_inn*((float)GetUInt32Value(PLAYER_NEXT_LEVEL_XP)/72000)*bubble);
- UpdateInnerTime(time(NULL));
+ _restTime = currTime;
+
+ float bubble = 0.125f * sWorld->getRate(RATE_REST_INGAME);
+ float extraPerSec = ((float)GetUInt32Value(PLAYER_NEXT_LEVEL_XP) / 72000.0f) * bubble;
+
+ // speed collect rest bonus (section/in hour)
+ float currRestBonus = GetRestBonus();
+ SetRestBonus(currRestBonus + timeDiff * extraPerSec);
}
}
}
@@ -1751,6 +1388,14 @@ void Player::Update(uint32 p_time)
{
if (p_time >= m_zoneUpdateTimer)
{
+ // On zone update tick check if we are still in an inn if we are supposed to be in one
+ if (HasRestFlag(REST_FLAG_IN_TAVERN))
+ {
+ AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(GetInnTriggerId());
+ if (!atEntry || !IsInAreaTriggerRadius(atEntry))
+ RemoveRestFlag(REST_FLAG_IN_TAVERN);
+ }
+
uint32 newzone, newarea;
GetZoneAndAreaId(newzone, newarea);
@@ -1793,7 +1438,7 @@ void Player::Update(uint32 p_time)
{
// m_nextSave reset in SaveToDB call
SaveToDB();
- TC_LOG_DEBUG("entities.player", "Player '%s' (GUID: %u) saved", GetName().c_str(), GetGUIDLow());
+ TC_LOG_DEBUG("entities.player", "Player '%s' (GUID: %u) saved", GetName().c_str(), GetGUID().GetCounter());
}
else
m_nextSave -= p_time;
@@ -1902,7 +1547,7 @@ void Player::setDeathState(DeathState s)
{
if (!cur)
{
- TC_LOG_ERROR("entities.player", "setDeathState: attempt to kill a dead player %s(%d)", GetName().c_str(), GetGUIDLow());
+ TC_LOG_ERROR("entities.player", "setDeathState: attempt to kill a dead player %s(%d)", GetName().c_str(), GetGUID().GetCounter());
return;
}
@@ -1941,15 +1586,6 @@ void Player::setDeathState(DeathState s)
SetUInt32Value(PLAYER_SELF_RES_SPELL, 0);
}
-void Player::InnEnter(time_t time, uint32 mapid, float x, float y, float z)
-{
- inn_pos_mapid = mapid;
- inn_pos_x = x;
- inn_pos_y = y;
- inn_pos_z = z;
- time_inn_enter = time;
-}
-
bool Player::BuildEnumData(PreparedQueryResult result, WorldPacket* data)
{
// 0 1 2 3 4 5 6 7
@@ -1961,7 +1597,7 @@ bool Player::BuildEnumData(PreparedQueryResult result, WorldPacket* data)
Field* fields = result->Fetch();
- uint32 guid = fields[0].GetUInt32();
+ ObjectGuid::LowType guid = fields[0].GetUInt32();
uint8 plrRace = fields[2].GetUInt8();
uint8 plrClass = fields[3].GetUInt8();
uint8 gender = fields[4].GetUInt8();
@@ -1978,7 +1614,7 @@ bool Player::BuildEnumData(PreparedQueryResult result, WorldPacket* data)
return false;
}
- *data << ObjectGuid(HIGHGUID_PLAYER, guid);
+ *data << ObjectGuid(HighGuid::Player, guid);
*data << fields[1].GetString(); // name
*data << uint8(plrRace); // race
*data << uint8(plrClass); // class
@@ -2022,6 +1658,8 @@ bool Player::BuildEnumData(PreparedQueryResult result, WorldPacket* data)
uint32 charFlags = 0;
uint32 playerFlags = fields[14].GetUInt32();
+ if (atLoginFlags & AT_LOGIN_RESURRECT)
+ playerFlags &= ~PLAYER_FLAGS_GHOST;
if (playerFlags & PLAYER_FLAGS_HIDE_HELM)
charFlags |= CHARACTER_FLAG_HIDE_HELM;
if (playerFlags & PLAYER_FLAGS_HIDE_CLOAK)
@@ -2158,13 +1796,13 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
if (!MapManager::IsValidMapCoord(mapid, x, y, z, orientation))
{
TC_LOG_ERROR("maps", "TeleportTo: invalid map (%d) or invalid coordinates (X: %f, Y: %f, Z: %f, O: %f) given when teleporting player (GUID: %u, name: %s, map: %d, X: %f, Y: %f, Z: %f, O: %f).",
- mapid, x, y, z, orientation, GetGUIDLow(), GetName().c_str(), GetMapId(), GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
+ mapid, x, y, z, orientation, GetGUID().GetCounter(), GetName().c_str(), GetMapId(), GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
return false;
}
if (!GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_DISABLE_MAP) && DisableMgr::IsDisabledFor(DISABLE_TYPE_MAP, mapid, this))
{
- TC_LOG_ERROR("maps", "Player (GUID: %u, name: %s) tried to enter a forbidden map %u", GetGUIDLow(), GetName().c_str(), mapid);
+ TC_LOG_ERROR("maps", "Player (GUID: %u, name: %s) tried to enter a forbidden map %u", GetGUID().GetCounter(), GetName().c_str(), mapid);
SendTransferAborted(mapid, TRANSFER_ABORT_MAP_NOT_ALLOWED);
return false;
}
@@ -2485,17 +2123,18 @@ void Player::RemoveFromWorld()
sBattlefieldMgr->HandlePlayerLeaveZone(this, m_zoneUpdateId);
}
- ///- Do not add/remove the player from the object storage
- ///- It will crash when updating the ObjectAccessor
- ///- The player should only be removed when logging out
- Unit::RemoveFromWorld();
-
+ // Remove items from world before self - player must be found in Item::RemoveFromObjectUpdate
for (uint8 i = PLAYER_SLOT_START; i < PLAYER_SLOT_END; ++i)
{
if (m_items[i])
m_items[i]->RemoveFromWorld();
}
+ ///- Do not add/remove the player from the object storage
+ ///- It will crash when updating the ObjectAccessor
+ ///- The player should only be removed when logging out
+ Unit::RemoveFromWorld();
+
for (ItemMap::iterator iter = mMitems.begin(); iter != mMitems.end(); ++iter)
iter->second->RemoveFromWorld();
@@ -2510,6 +2149,17 @@ void Player::RemoveFromWorld()
}
}
+bool Player::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const
+{
+ // players are immune to taunt (the aura and the spell effect)
+ if (spellInfo->Effects[index].IsAura(SPELL_AURA_MOD_TAUNT))
+ return true;
+ if (spellInfo->Effects[index].IsEffect(SPELL_EFFECT_ATTACK_ME))
+ return true;
+
+ return Unit::IsImmunedToSpellEffect(spellInfo, index);
+}
+
void Player::RegenerateAll()
{
//if (m_regenTimer <= 500)
@@ -2806,7 +2456,7 @@ GameObject* Player::GetGameObjectIfCanInteractWith(ObjectGuid guid, GameobjectTy
return go;
TC_LOG_DEBUG("maps", "GetGameObjectIfCanInteractWith: GameObject '%s' [GUID: %u] is too far away from player %s [GUID: %u] to be used by him (distance=%f, maximal 10 is allowed)", go->GetGOInfo()->name.c_str(),
- go->GetGUIDLow(), GetName().c_str(), GetGUIDLow(), go->GetDistance(this));
+ go->GetGUID().GetCounter(), GetName().c_str(), GetGUID().GetCounter(), go->GetDistance(this));
}
}
@@ -2837,6 +2487,28 @@ void Player::SetInWater(bool apply)
getHostileRefManager().updateThreatTables();
}
+bool Player::IsInAreaTriggerRadius(const AreaTriggerEntry* trigger) const
+{
+ if (!trigger || GetMapId() != trigger->mapid)
+ return false;
+
+ if (trigger->radius > 0.f)
+ {
+ // if we have radius check it
+ float dist = GetDistance(trigger->x, trigger->y, trigger->z);
+ if (dist > trigger->radius)
+ return false;
+ }
+ else
+ {
+ Position center(trigger->x, trigger->y, trigger->z, trigger->box_orientation);
+ if (!IsWithinBox(center, trigger->box_x / 2.f, trigger->box_y / 2.f, trigger->box_z / 2.f))
+ return false;
+ }
+
+ return true;
+}
+
void Player::SetGameMaster(bool on)
{
if (on)
@@ -2900,6 +2572,11 @@ void Player::SetGameMaster(bool on)
UpdateObjectVisibility();
}
+bool Player::CanBeGameMaster() const
+{
+ return GetSession()->HasPermission(rbac::RBAC_PERM_COMMAND_GM);
+}
+
void Player::SetGMVisible(bool on)
{
if (on)
@@ -3391,7 +3068,7 @@ void Player::RemoveMail(uint32 id)
}
}
-void Player::SendMailResult(uint32 mailId, MailResponseType mailAction, MailResponseResult mailError, uint32 equipError, uint32 item_guid, uint32 item_count)
+void Player::SendMailResult(uint32 mailId, MailResponseType mailAction, MailResponseResult mailError, uint32 equipError, ObjectGuid::LowType item_guid, uint32 item_count)
{
WorldPacket data(SMSG_SEND_MAIL_RESULT, (4+4+4+(mailError == MAIL_ERR_EQUIP_ERROR?4:(mailAction == MAIL_ITEM_TAKEN?4+4:0))));
data << (uint32) mailId;
@@ -3526,7 +3203,7 @@ bool Player::AddTalent(uint32 spellId, uint8 spec, bool learning)
return false;
}
-bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent, bool disabled, bool loading /*= false*/, bool fromSkill /*= false*/)
+bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent, bool disabled, bool loading /*= false*/, uint32 fromSkill /*= 0*/)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!spellInfo)
@@ -3784,10 +3461,10 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent
SkillLineAbilityMapBounds skill_bounds = sSpellMgr->GetSkillLineAbilityMapBounds(spellId);
- // add dependent skills if this spell is not learned from adding skill already
- if (!fromSkill)
+ if (SpellLearnSkillNode const* spellLearnSkill = sSpellMgr->GetSpellLearnSkill(spellId))
{
- if (SpellLearnSkillNode const* spellLearnSkill = sSpellMgr->GetSpellLearnSkill(spellId))
+ // add dependent skills if this spell is not learned from adding skill already
+ if (spellLearnSkill->skill != fromSkill)
{
uint32 skill_value = GetPureSkillValue(spellLearnSkill->skill);
uint32 skill_max_value = GetPureMaxSkillValue(spellLearnSkill->skill);
@@ -3802,25 +3479,29 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent
SetSkill(spellLearnSkill->skill, spellLearnSkill->step, skill_value, skill_max_value);
}
- else
+ }
+ else
+ {
+ // not ranked skills
+ for (SkillLineAbilityMap::const_iterator _spell_idx = skill_bounds.first; _spell_idx != skill_bounds.second; ++_spell_idx)
{
- // not ranked skills
- for (SkillLineAbilityMap::const_iterator _spell_idx = skill_bounds.first; _spell_idx != skill_bounds.second; ++_spell_idx)
- {
- SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(_spell_idx->second->skillId);
- if (!pSkill)
- continue;
+ SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(_spell_idx->second->skillId);
+ if (!pSkill)
+ continue;
- ///@todo: confirm if rogues start with lockpicking skill at level 1 but only receive the spell to use it at level 16
- if ((_spell_idx->second->AutolearnType == SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN && !HasSkill(pSkill->id)) || (pSkill->id == SKILL_LOCKPICKING && _spell_idx->second->max_value == 0))
- LearnDefaultSkill(pSkill->id, 0);
+ if (pSkill->id == fromSkill)
+ continue;
- if (pSkill->id == SKILL_MOUNTS && !Has310Flyer(false))
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- if (spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED &&
- spellInfo->Effects[i].CalcValue() == 310)
- SetHas310Flyer(true);
- }
+ ///@todo: confirm if rogues start with lockpicking skill at level 1 but only receive the spell to use it at level 16
+ // Also added for runeforging. It's already confirmed this happens upon learning for Death Knights, not from character creation.
+ if ((_spell_idx->second->AutolearnType == SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN && !HasSkill(pSkill->id)) || ((pSkill->id == SKILL_LOCKPICKING || pSkill->id == SKILL_RUNEFORGING) && _spell_idx->second->max_value == 0))
+ LearnDefaultSkill(pSkill->id, 0);
+
+ if (pSkill->id == SKILL_MOUNTS && !Has310Flyer(false))
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ if (spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED &&
+ spellInfo->Effects[i].CalcValue() == 310)
+ SetHas310Flyer(true);
}
}
@@ -3886,14 +3567,14 @@ bool Player::IsNeedCastPassiveSpellAtLearn(SpellInfo const* spellInfo) const
// note: form passives activated with shapeshift spells be implemented by HandleShapeshiftBoosts instead of spell_learn_spell
// talent dependent passives activated at form apply have proper stance data
ShapeshiftForm form = GetShapeshiftForm();
- bool need_cast = (!spellInfo->Stances || (form && (spellInfo->Stances & (1 << (form - 1)))) ||
+ bool need_cast = (!spellInfo->Stances || (form && (spellInfo->Stances & (UI64LIT(1) << (form - 1)))) ||
(!form && spellInfo->HasAttribute(SPELL_ATTR2_NOT_NEED_SHAPESHIFT)));
//Check CasterAuraStates
return need_cast && (!spellInfo->CasterAuraState || HasAuraState(AuraStateType(spellInfo->CasterAuraState)));
}
-void Player::LearnSpell(uint32 spell_id, bool dependent, bool fromSkill /*= false*/)
+void Player::LearnSpell(uint32 spell_id, bool dependent, uint32 fromSkill /*= 0*/)
{
PlayerSpellMap::iterator itr = m_spells.find(spell_id);
@@ -4497,30 +4178,31 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
updateRealmChars = false;
// Convert guid to low GUID for CharacterNameData, but also other methods on success
- uint32 guid = playerguid.GetCounter();
+ ObjectGuid::LowType guid = playerguid.GetCounter();
uint32 charDelete_method = sWorld->getIntConfig(CONFIG_CHARDELETE_METHOD);
if (deleteFinally)
charDelete_method = CHAR_DELETE_REMOVE;
- else if (CharacterNameData const* nameData = sWorld->GetCharacterNameData(playerguid)) // To avoid a query, we select loaded data. If it doesn't exist, return.
+ else if (CharacterInfo const* nameData = sWorld->GetCharacterInfo(playerguid)) // To avoid a query, we select loaded data. If it doesn't exist, return.
{
// Define the required variables
- uint32 charDelete_minLvl = sWorld->getIntConfig(nameData->m_class != CLASS_DEATH_KNIGHT ? CONFIG_CHARDELETE_MIN_LEVEL : CONFIG_CHARDELETE_HEROIC_MIN_LEVEL);
+ uint32 charDelete_minLvl = sWorld->getIntConfig(nameData->Class != CLASS_DEATH_KNIGHT ? CONFIG_CHARDELETE_MIN_LEVEL : CONFIG_CHARDELETE_HEROIC_MIN_LEVEL);
// if we want to finalize the character removal or the character does not meet the level requirement of either heroic or non-heroic settings,
// we set it to mode CHAR_DELETE_REMOVE
- if (nameData->m_level < charDelete_minLvl)
+ if (nameData->Level < charDelete_minLvl)
charDelete_method = CHAR_DELETE_REMOVE;
}
- // convert corpse to bones if exist (to prevent exiting Corpse in World without DB entry)
- // bones will be deleted by corpse/bones deleting thread shortly
- sObjectAccessor->ConvertCorpseForPlayer(playerguid);
-
- if (uint32 guildId = GetGuildIdFromDB(playerguid))
+ if (ObjectGuid::LowType guildId = GetGuildIdFromDB(playerguid))
if (Guild* guild = sGuildMgr->GetGuildById(guildId))
guild->DeleteMember(playerguid, false, false, true);
+ // close player ticket if any
+ GmTicket* ticket = sTicketMgr->GetTicketByPlayer(playerguid);
+ if (ticket)
+ ticket->SetClosedBy(playerguid);
+
// remove from arena teams
LeaveAllArenaTeams(playerguid);
@@ -4595,7 +4277,7 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
do
{
Field* itemFields = resultItems->Fetch();
- uint32 item_guidlow = itemFields[11].GetUInt32();
+ ObjectGuid::LowType item_guidlow = itemFields[11].GetUInt32();
uint32 item_template = itemFields[12].GetUInt32();
ItemTemplate const* itemProto = sObjectMgr->GetItemTemplate(item_template);
@@ -4642,7 +4324,7 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
{
do
{
- uint32 petguidlow = (*resultPets)[0].GetUInt32();
+ ObjectGuid::LowType petguidlow = (*resultPets)[0].GetUInt32();
Pet::DeleteFromDB(petguidlow);
} while (resultPets->NextRow());
}
@@ -4656,7 +4338,7 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
{
do
{
- if (Player* pFriend = ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER, 0, (*resultFriends)[0].GetUInt32())))
+ if (Player* pFriend = ObjectAccessor::FindPlayer(ObjectGuid(HighGuid::Player, 0, (*resultFriends)[0].GetUInt32())))
{
pFriend->GetSocial()->RemoveFromSocialList(guid, false);
sSocialMgr->SendFriendStatus(pFriend, FRIEND_REMOVED, guid, false);
@@ -4732,9 +4414,18 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
stmt->setUInt32(0, guid);
trans->Append(stmt);
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_GM_TICKETS);
- stmt->setUInt32(0, guid);
- trans->Append(stmt);
+ if (sWorld->getBoolConfig(CONFIG_DELETE_CHARACTER_TICKET_TRACE))
+ {
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_PLAYER_GM_TICKETS_ON_CHAR_DELETION);
+ stmt->setUInt32(0, guid);
+ trans->Append(stmt);
+ }
+ else
+ {
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_GM_TICKETS);
+ stmt->setUInt32(0, guid);
+ trans->Append(stmt);
+ }
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_BY_OWNER);
stmt->setUInt32(0, guid);
@@ -4817,6 +4508,8 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
stmt->setUInt32(0, guid);
trans->Append(stmt);
+ Corpse::DeleteFromDB(playerguid, trans);
+
CharacterDatabase.CommitTransaction(trans);
break;
}
@@ -4838,7 +4531,7 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
if (updateRealmChars)
sWorld->UpdateRealmCharCount(accountId);
- sWorld->DeleteCharacterNameData(playerguid);
+ sWorld->DeleteCharacterInfo(playerguid);
}
/**
@@ -4876,7 +4569,7 @@ void Player::DeleteOldCharacters(uint32 keepDays)
do
{
Field* fields = result->Fetch();
- Player::DeleteFromDB(ObjectGuid(HIGHGUID_PLAYER, fields[0].GetUInt32()), fields[1].GetUInt32(), true, true);
+ Player::DeleteFromDB(ObjectGuid(HighGuid::Player, fields[0].GetUInt32()), fields[1].GetUInt32(), true, true);
}
while (result->NextRow());
}
@@ -4916,21 +4609,20 @@ void Player::BuildPlayerRepop()
// there must be SMSG.FORCE_RUN_SPEED_CHANGE, SMSG.FORCE_SWIM_SPEED_CHANGE, SMSG.MOVE_WATER_WALK
// there must be SMSG.STOP_MIRROR_TIMER
- // there we must send 888 opcode
- // the player cannot have a corpse already, only bones which are not returned by GetCorpse
- if (GetCorpse())
+ // the player cannot have a corpse already on current map, only bones which are not returned by GetCorpse
+ WorldLocation corpseLocation = GetCorpseLocation();
+ if (corpseLocation.GetMapId() == GetMapId())
{
- TC_LOG_ERROR("entities.player", "BuildPlayerRepop: player %s(%d) already has a corpse", GetName().c_str(), GetGUIDLow());
+ TC_LOG_ERROR("entities.player", "BuildPlayerRepop: player %s(%d) already has a corpse", GetName().c_str(), GetGUID().GetCounter());
return;
}
// create a corpse and place it at the player's location
- CreateCorpse();
- Corpse* corpse = GetCorpse();
+ Corpse* corpse = CreateCorpse();
if (!corpse)
{
- TC_LOG_ERROR("entities.player", "Error creating corpse for Player %s [%u]", GetName().c_str(), GetGUIDLow());
+ TC_LOG_ERROR("entities.player", "Error creating corpse for Player %s [%u]", GetName().c_str(), GetGUID().GetCounter());
return;
}
GetMap()->AddToMap(corpse);
@@ -5069,34 +4761,43 @@ void Player::KillPlayer()
UpdateObjectVisibility();
}
-void Player::CreateCorpse()
+void Player::OfflineResurrect(ObjectGuid const& guid, SQLTransaction& trans)
+{
+ Corpse::DeleteFromDB(guid, trans);
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG);
+ stmt->setUInt16(0, uint16(AT_LOGIN_RESURRECT));
+ stmt->setUInt64(1, guid.GetCounter());
+ CharacterDatabase.ExecuteOrAppend(trans, stmt);
+}
+
+Corpse* Player::CreateCorpse()
{
// prevent existence 2 corpse for player
SpawnCorpseBones();
- uint32 _uf, _pb, _pb2, _cfb1, _cfb2;
+ uint32 _pb, _pb2, _cfb1, _cfb2;
Corpse* corpse = new Corpse((m_ExtraFlags & PLAYER_EXTRA_PVP_DEATH) ? CORPSE_RESURRECTABLE_PVP : CORPSE_RESURRECTABLE_PVE);
SetPvPDeath(false);
- if (!corpse->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_CORPSE), this))
+ if (!corpse->Create(GetMap()->GenerateLowGuid<HighGuid::Corpse>(), this))
{
delete corpse;
- return;
+ return nullptr;
}
- _uf = GetUInt32Value(UNIT_FIELD_BYTES_0);
+ _corpseLocation.WorldRelocate(*this);
+
_pb = GetUInt32Value(PLAYER_BYTES);
_pb2 = GetUInt32Value(PLAYER_BYTES_2);
- uint8 race = (uint8)(_uf);
uint8 skin = (uint8)(_pb);
uint8 face = (uint8)(_pb >> 8);
uint8 hairstyle = (uint8)(_pb >> 16);
uint8 haircolor = (uint8)(_pb >> 24);
uint8 facialhair = (uint8)(_pb2);
- _cfb1 = ((0x00) | (race << 8) | (getGender() << 16) | (skin << 24));
+ _cfb1 = ((0x00) | (getRace() << 8) | (GetByteValue(PLAYER_BYTES_3, 0) << 16) | (skin << 24));
_cfb2 = ((face) | (hairstyle << 8) | (haircolor << 16) | (facialhair << 24));
corpse->SetUInt32Value(CORPSE_FIELD_BYTES_1, _cfb1);
@@ -5130,24 +4831,27 @@ void Player::CreateCorpse()
}
}
+ // register for player, but not show
+ GetMap()->AddCorpse(corpse);
+
// we do not need to save corpses for BG/arenas
if (!GetMap()->IsBattlegroundOrArena())
corpse->SaveToDB();
- // register for player, but not show
- sObjectAccessor->AddCorpse(corpse);
+ return corpse;
}
-void Player::SpawnCorpseBones()
+void Player::SpawnCorpseBones(bool triggerSave /*= true*/)
{
- if (sObjectAccessor->ConvertCorpseForPlayer(GetGUID()))
- if (!GetSession()->PlayerLogoutWithSave()) // at logout we will already store the player
- SaveToDB(); // prevent loading as ghost without corpse
+ _corpseLocation.WorldRelocate();
+ if (GetMap()->ConvertCorpseToBones(GetGUID()))
+ if (triggerSave && !GetSession()->PlayerLogoutWithSave()) // at logout we will already store the player
+ SaveToDB(); // prevent loading as ghost without corpse
}
Corpse* Player::GetCorpse() const
{
- return sObjectAccessor->GetCorpseForPlayerGUID(GetGUID());
+ return GetMap()->GetCorpseByPlayer(GetGUID());
}
void Player::DurabilityLossAll(double percent, bool inventory)
@@ -6498,20 +6202,20 @@ void Player::SendActionButtons(uint32 state) const
}
GetSession()->SendPacket(&data);
- TC_LOG_DEBUG("network", "SMSG_ACTION_BUTTONS sent '%u' spec '%u' Sent", GetGUIDLow(), m_activeSpec);
+ TC_LOG_DEBUG("network", "SMSG_ACTION_BUTTONS sent '%u' spec '%u' Sent", GetGUID().GetCounter(), m_activeSpec);
}
bool Player::IsActionButtonDataValid(uint8 button, uint32 action, uint8 type)
{
if (button >= MAX_ACTION_BUTTONS)
{
- TC_LOG_DEBUG("entities.player", "Action %u not added into button %u for player %s (GUID: %u): button must be < %u", action, button, GetName().c_str(), GetGUIDLow(), MAX_ACTION_BUTTONS );
+ TC_LOG_DEBUG("entities.player", "Action %u not added into button %u for player %s (GUID: %u): button must be < %u", action, button, GetName().c_str(), GetGUID().GetCounter(), MAX_ACTION_BUTTONS );
return false;
}
if (action >= MAX_ACTION_BUTTON_ACTION_VALUE)
{
- TC_LOG_DEBUG("entities.player", "Action %u not added into button %u for player %s (GUID: %u): action must be < %u", action, button, GetName().c_str(), GetGUIDLow(), MAX_ACTION_BUTTON_ACTION_VALUE);
+ TC_LOG_DEBUG("entities.player", "Action %u not added into button %u for player %s (GUID: %u): action must be < %u", action, button, GetName().c_str(), GetGUID().GetCounter(), MAX_ACTION_BUTTON_ACTION_VALUE);
return false;
}
@@ -6520,20 +6224,20 @@ bool Player::IsActionButtonDataValid(uint8 button, uint32 action, uint8 type)
case ACTION_BUTTON_SPELL:
if (!sSpellMgr->GetSpellInfo(action))
{
- TC_LOG_DEBUG("entities.player", "Spell action %u not added into button %u for player %s (GUID: %u): spell not exist", action, button, GetName().c_str(), GetGUIDLow());
+ TC_LOG_DEBUG("entities.player", "Spell action %u not added into button %u for player %s (GUID: %u): spell not exist", action, button, GetName().c_str(), GetGUID().GetCounter());
return false;
}
if (!HasSpell(action))
{
- TC_LOG_DEBUG("entities.player", "Spell action %u not added into button %u for player %s (GUID: %u): player don't known this spell", action, button, GetName().c_str(), GetGUIDLow());
+ TC_LOG_DEBUG("entities.player", "Spell action %u not added into button %u for player %s (GUID: %u): player don't known this spell", action, button, GetName().c_str(), GetGUID().GetCounter());
return false;
}
break;
case ACTION_BUTTON_ITEM:
if (!sObjectMgr->GetItemTemplate(action))
{
- TC_LOG_DEBUG("entities.player", "Item action %u not added into button %u for player %s (GUID: %u): item not exist", action, button, GetName().c_str(), GetGUIDLow());
+ TC_LOG_DEBUG("entities.player", "Item action %u not added into button %u for player %s (GUID: %u): item not exist", action, button, GetName().c_str(), GetGUID().GetCounter());
return false;
}
break;
@@ -6561,7 +6265,7 @@ ActionButton* Player::addActionButton(uint8 button, uint32 action, uint8 type)
// set data and update to CHANGED if not NEW
ab.SetActionAndType(action, ActionButtonType(type));
- TC_LOG_DEBUG("entities.player", "Player '%u' Added Action '%u' (type %u) to Button '%u'", GetGUIDLow(), action, type, button);
+ TC_LOG_DEBUG("entities.player", "Player '%u' Added Action '%u' (type %u) to Button '%u'", GetGUID().GetCounter(), action, type, button);
return &ab;
}
@@ -6576,7 +6280,7 @@ void Player::removeActionButton(uint8 button)
else
buttonItr->second.uState = ACTIONBUTTON_DELETED; // saved, will deleted at next save
- TC_LOG_DEBUG("entities.player", "Action Button '%u' Removed from Player '%u'", button, GetGUIDLow());
+ TC_LOG_DEBUG("entities.player", "Action Button '%u' Removed from Player '%u'", button, GetGUID().GetCounter());
}
ActionButton const* Player::GetActionButton(uint8 button)
@@ -6710,7 +6414,7 @@ void Player::CheckAreaExploreAndOutdoor()
AreaTableEntry const* areaEntry = GetAreaEntryByAreaFlagAndMap(areaFlag, GetMapId());
if (!areaEntry)
{
- TC_LOG_ERROR("entities.player", "Player %u discovered unknown area (x: %f y: %f z: %f map: %u", GetGUIDLow(), GetPositionX(), GetPositionY(), GetPositionZ(), GetMapId());
+ TC_LOG_ERROR("entities.player", "Player %u discovered unknown area (x: %f y: %f z: %f map: %u", GetGUID().GetCounter(), GetPositionX(), GetPositionY(), GetPositionZ(), GetMapId());
return;
}
@@ -6745,7 +6449,7 @@ void Player::CheckAreaExploreAndOutdoor()
GiveXP(XP, NULL);
SendExplorationExperience(area, XP);
}
- TC_LOG_DEBUG("entities.player", "Player %u discovered a new area: %u", GetGUIDLow(), area);
+ TC_LOG_DEBUG("entities.player", "Player %u discovered a new area: %u", GetGUID().GetCounter(), area);
}
}
}
@@ -6880,7 +6584,7 @@ void Player::RewardReputation(Unit* victim, float rate)
{
// support for: Championing - http://www.wowwiki.com/Championing
Map const* map = GetMap();
- if (map && map->IsNonRaidDungeon())
+ if (map->IsNonRaidDungeon())
if (LFGDungeonEntry const* dungeon = GetLFGDungeon(map->GetId(), map->GetDifficulty()))
if (dungeon->reclevel == 80)
ChampioningFaction = GetChampioningFaction();
@@ -7175,7 +6879,7 @@ void Player::ModifyHonorPoints(int32 value, SQLTransaction trans)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_HONOR_POINTS);
stmt->setUInt32(0, newValue);
- stmt->setUInt32(1, GetGUIDLow());
+ stmt->setUInt32(1, GetGUID().GetCounter());
trans->Append(stmt);
}
}
@@ -7191,12 +6895,12 @@ void Player::ModifyArenaPoints(int32 value, SQLTransaction trans)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_ARENA_POINTS);
stmt->setUInt32(0, newValue);
- stmt->setUInt32(1, GetGUIDLow());
+ stmt->setUInt32(1, GetGUID().GetCounter());
trans->Append(stmt);
}
}
-uint32 Player::GetGuildIdFromDB(ObjectGuid guid)
+ObjectGuid::LowType Player::GetGuildIdFromDB(ObjectGuid guid)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_MEMBER);
stmt->setUInt32(0, guid.GetCounter());
@@ -7250,7 +6954,7 @@ uint32 Player::GetArenaTeamIdFromDB(ObjectGuid guid, uint8 type)
uint32 Player::GetZoneIdFromDB(ObjectGuid guid)
{
- uint32 guidLow = guid.GetCounter();
+ ObjectGuid::LowType guidLow = guid.GetCounter();
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_ZONE);
stmt->setUInt32(0, guidLow);
PreparedQueryResult result = CharacterDatabase.Query(stmt);
@@ -7265,7 +6969,7 @@ uint32 Player::GetZoneIdFromDB(ObjectGuid guid)
// stored zone is zero, use generic and slow zone detection
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_POSITION_XYZ);
stmt->setUInt32(0, guidLow);
- PreparedQueryResult result = CharacterDatabase.Query(stmt);
+ result = CharacterDatabase.Query(stmt);
if (!result)
return 0;
@@ -7313,7 +7017,7 @@ void Player::UpdateArea(uint32 newArea)
{
// FFA_PVP flags are area and not zone id dependent
// so apply them accordingly
- m_areaUpdateId = newArea;
+ m_areaUpdateId = newArea;
AreaTableEntry const* area = GetAreaEntryByAreaID(newArea);
pvpInfo.IsInFFAPvPArea = area && (area->flags & AREA_FLAG_ARENA);
@@ -7335,16 +7039,9 @@ void Player::UpdateArea(uint32 newArea)
uint32 const areaRestFlag = (GetTeam() == ALLIANCE) ? AREA_FLAG_REST_ZONE_ALLIANCE : AREA_FLAG_REST_ZONE_HORDE;
if (area && area->flags & areaRestFlag)
- {
- SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
- SetRestType(REST_TYPE_IN_FACTION_AREA);
- InnEnter(time(0), GetMapId(), 0, 0, 0);
- }
- else if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) && GetRestType() == REST_TYPE_IN_FACTION_AREA)
- {
- RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
- SetRestType(REST_TYPE_NO);
- }
+ SetRestFlag(REST_FLAG_IN_FACTION_AREA);
+ else
+ RemoveRestFlag(REST_FLAG_IN_FACTION_AREA);
}
void Player::UpdateZone(uint32 newZone, uint32 newArea)
@@ -7410,34 +7107,12 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
if (zone->flags & AREA_FLAG_CAPITAL) // Is in a capital city
{
if (!pvpInfo.IsHostile || zone->IsSanctuary())
- {
- SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
- SetRestType(REST_TYPE_IN_CITY);
- InnEnter(time(0), GetMapId(), 0, 0, 0);
- }
+ SetRestFlag(REST_FLAG_IN_CITY);
+
pvpInfo.IsInNoPvPArea = true;
}
else
- {
- if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING))
- {
- if (GetRestType() == REST_TYPE_IN_TAVERN) // Still inside a tavern or has recently left
- {
- // Remove rest state if we have recently left a tavern.
- if (GetMapId() != GetInnPosMapId() || GetExactDist(GetInnPosX(), GetInnPosY(), GetInnPosZ()) > 1.0f)
- {
- RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
- SetRestType(REST_TYPE_NO);
- }
- }
- else if (GetRestType() != REST_TYPE_IN_FACTION_AREA) // handled in UpdateArea
- {
- // Recently left a capital city
- RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
- SetRestType(REST_TYPE_NO);
- }
- }
- }
+ RemoveRestFlag(REST_FLAG_IN_CITY); // Recently left a capital city
UpdatePvPState();
@@ -7625,7 +7300,7 @@ void Player::_ApplyItemMods(Item* item, uint8 slot, bool apply)
if (item->IsBroken())
return;
- TC_LOG_DEBUG("entities.player.items", "applying mods for item %u ", item->GetGUIDLow());
+ TC_LOG_DEBUG("entities.player.items", "applying mods for item %u ", item->GetGUID().GetCounter());
uint8 attacktype = Player::GetAttackBySlot(slot);
@@ -8090,7 +7765,7 @@ void Player::ApplyItemEquipSpell(Item* item, bool apply, bool form_change)
_Spell const& spellData = proto->Spells[i];
// no spell
- if (!spellData.SpellId)
+ if (spellData.SpellId <= 0)
continue;
// wrong triggering type
@@ -8218,7 +7893,7 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
_Spell const& spellData = proto->Spells[i];
// no spell
- if (!spellData.SpellId)
+ if (spellData.SpellId <= 0)
continue;
// wrong triggering type
@@ -8284,7 +7959,7 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
if (!spellInfo)
{
TC_LOG_ERROR("entities.player.items", "Player::CastItemCombatSpell(GUID: %u, name: %s, enchant: %i): unknown spell %i is cast, ignoring...",
- GetGUIDLow(), GetName().c_str(), pEnchant->ID, pEnchant->spellid[s]);
+ GetGUID().GetCounter(), GetName().c_str(), pEnchant->ID, pEnchant->spellid[s]);
continue;
}
@@ -8341,16 +8016,13 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8
return;
}
- // use triggered flag only for items with many spell casts and for not first cast
- uint8 count = 0;
-
// item spells cast at use
for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
{
_Spell const& spellData = proto->Spells[i];
// no spell
- if (!spellData.SpellId)
+ if (spellData.SpellId <= 0)
continue;
// wrong triggering type
@@ -8364,13 +8036,12 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8
continue;
}
- Spell* spell = new Spell(this, spellInfo, (count > 0) ? TRIGGERED_FULL_MASK : TRIGGERED_NONE);
+ Spell* spell = new Spell(this, spellInfo, TRIGGERED_NONE);
spell->m_CastItem = item;
spell->m_cast_count = cast_count; // set count of casts
spell->m_glyphIndex = glyphIndex; // glyph index
spell->prepare(&targets);
-
- ++count;
+ return;
}
// Item enchantments spells cast at use
@@ -8392,13 +8063,12 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8
continue;
}
- Spell* spell = new Spell(this, spellInfo, (count > 0) ? TRIGGERED_FULL_MASK : TRIGGERED_NONE);
+ Spell* spell = new Spell(this, spellInfo, TRIGGERED_NONE);
spell->m_CastItem = item;
spell->m_cast_count = cast_count; // set count of casts
spell->m_glyphIndex = glyphIndex; // glyph index
spell->prepare(&targets);
-
- ++count;
+ return;
}
}
}
@@ -8590,9 +8260,11 @@ void Player::RemovedInsignia(Player* looterPlr)
RepopAtGraveyard();
}
+ _corpseLocation.WorldRelocate();
+
// We have to convert player corpse to bones, not to be able to resurrect there
// SpawnCorpseBones isn't handy, 'cos it saves player while he in BG
- Corpse* bones = sObjectAccessor->ConvertCorpseForPlayer(GetGUID(), true);
+ Corpse* bones = GetMap()->ConvertCorpseToBones(GetGUID(), true);
if (!bones)
return;
@@ -9560,6 +9232,17 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
data << uint32(4131) << uint32(0); // 10 WORLDSTATE_ALGALON_DESPAWN_TIMER
}
break;
+ // Violet Hold
+ case 4415:
+ if (instance && mapid == 608)
+ instance->FillInitialWorldStates(data);
+ else
+ {
+ data << uint32(3816) << uint32(0); // 9 WORLD_STATE_VH_SHOW
+ data << uint32(3815) << uint32(100); // 10 WORLD_STATE_VH_PRISON_STATE
+ data << uint32(3810) << uint32(0); // 11 WORLD_STATE_VH_WAVE_COUNT
+ }
+ break;
// Halls of Refection
case 4820:
if (instance && mapid == 668)
@@ -9616,13 +9299,9 @@ void Player::SendBattlefieldWorldStates()
{
if (BattlefieldWG* wg = (BattlefieldWG*)sBattlefieldMgr->GetBattlefieldByBattleId(BATTLEFIELD_BATTLEID_WG))
{
- if (wg->IsWarTime())
- SendUpdateWorldState(ClockWorldState[1], uint32(time(NULL)));
- else // Time to next battle
- {
- uint32 timer = wg->GetTimer() / 1000;
- SendUpdateWorldState(ClockWorldState[1], time(NULL) + timer);
- }
+ SendUpdateWorldState(BATTLEFIELD_WG_WORLD_STATE_ACTIVE, wg->IsWarTime() ? 0 : 1);
+ uint32 timer = wg->IsWarTime() ? 0 : (wg->GetTimer() / 1000); // 0 - Time to next battle
+ SendUpdateWorldState(ClockWorldState[1], uint32(time(NULL) + timer));
}
}
}
@@ -9636,7 +9315,7 @@ uint32 Player::GetXPRestBonus(uint32 xp)
SetRestBonus(GetRestBonus() - rested_bonus);
- TC_LOG_DEBUG("entities.player", "GetXPRestBonus: Player %s (%u) gain %u xp (+%u Rested Bonus). Rested points=%f", GetName().c_str(), GetGUIDLow(), xp+rested_bonus, rested_bonus, GetRestBonus());
+ TC_LOG_DEBUG("entities.player", "GetXPRestBonus: Player %s (%u) gain %u xp (+%u Rested Bonus). Rested points=%f", GetName().c_str(), GetGUID().GetCounter(), xp+rested_bonus, rested_bonus, GetRestBonus());
return rested_bonus;
}
@@ -9668,7 +9347,7 @@ void Player::ResetPetTalents()
CharmInfo* charmInfo = pet->GetCharmInfo();
if (!charmInfo)
{
- TC_LOG_ERROR("entities.player", "Object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId());
+ TC_LOG_ERROR("entities.player", "Object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUID().GetCounter(), pet->GetTypeId());
return;
}
pet->resetTalents();
@@ -11627,7 +11306,7 @@ InventoryResult Player::CanBankItem(uint8 bag, uint8 slot, ItemPosCountVec &dest
if (pItemslot >= CURRENCYTOKEN_SLOT_START && pItemslot < CURRENCYTOKEN_SLOT_END)
{
TC_LOG_ERROR("entities.player", "Possible hacking attempt: Player %s [guid: %u] tried to move token [guid: %u, entry: %u] out of the currency bag!",
- GetName().c_str(), GetGUIDLow(), pItem->GetGUIDLow(), pProto->ItemId);
+ GetName().c_str(), GetGUID().GetCounter(), pItem->GetGUID().GetCounter(), pProto->ItemId);
return EQUIP_ERR_ITEMS_CANT_BE_SWAPPED;
}
@@ -12064,7 +11743,7 @@ Item* Player::StoreNewItem(ItemPosCountVec const& dest, uint32 item, bool update
ss << ' ' << *itr;
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ITEM_BOP_TRADE);
- stmt->setUInt32(0, pItem->GetGUIDLow());
+ stmt->setUInt32(0, pItem->GetGUID().GetCounter());
stmt->setString(1, ss.str());
CharacterDatabase.Execute(stmt);
}
@@ -12105,7 +11784,7 @@ Item* Player::_StoreItem(uint16 pos, Item* pItem, uint32 count, bool clone, bool
uint8 bag = pos >> 8;
uint8 slot = pos & 255;
- TC_LOG_DEBUG("entities.player.items", "STORAGE: StoreItem bag = %u, slot = %u, item = %u, count = %u, guid = %u", bag, slot, pItem->GetEntry(), count, pItem->GetGUIDLow());
+ TC_LOG_DEBUG("entities.player.items", "STORAGE: StoreItem bag = %u, slot = %u, item = %u, count = %u, guid = %u", bag, slot, pItem->GetEntry(), count, pItem->GetGUID().GetCounter());
Item* pItem2 = GetItemByPos(bag, slot);
@@ -12531,7 +12210,7 @@ void Player::DestroyItem(uint8 bag, uint8 slot, bool update)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GIFT);
- stmt->setUInt32(0, pItem->GetGUIDLow());
+ stmt->setUInt32(0, pItem->GetGUID().GetCounter());
CharacterDatabase.Execute(stmt);
}
@@ -12897,7 +12576,7 @@ void Player::DestroyItemCount(Item* pItem, uint32 &count, bool update)
if (!pItem)
return;
- TC_LOG_DEBUG("entities.player.items", "STORAGE: DestroyItemCount item (GUID: %u, Entry: %u) count = %u", pItem->GetGUIDLow(), pItem->GetEntry(), count);
+ TC_LOG_DEBUG("entities.player.items", "STORAGE: DestroyItemCount item (GUID: %u, Entry: %u) count = %u", pItem->GetGUID().GetCounter(), pItem->GetEntry(), count);
if (pItem->GetCount() <= count)
{
@@ -13562,36 +13241,25 @@ void Player::TradeCancel(bool sendback)
void Player::UpdateSoulboundTradeItems()
{
- if (m_itemSoulboundTradeable.empty())
- return;
-
// also checks for garbage data
- for (ItemDurationList::iterator itr = m_itemSoulboundTradeable.begin(); itr != m_itemSoulboundTradeable.end();)
+ for (GuidUnorderedSet::iterator itr = m_itemSoulboundTradeable.begin(); itr != m_itemSoulboundTradeable.end();)
{
- ASSERT(*itr);
- if ((*itr)->GetOwnerGUID() != GetGUID())
- {
- m_itemSoulboundTradeable.erase(itr++);
- continue;
- }
- if ((*itr)->CheckSoulboundTradeExpire())
- {
- m_itemSoulboundTradeable.erase(itr++);
- continue;
- }
- ++itr;
+ Item* item = GetItemByGuid(*itr);
+ if (!item || item->GetOwnerGUID() != GetGUID() || item->CheckSoulboundTradeExpire())
+ itr = m_itemSoulboundTradeable.erase(itr);
+ else
+ ++itr;
}
}
void Player::AddTradeableItem(Item* item)
{
- m_itemSoulboundTradeable.push_back(item);
+ m_itemSoulboundTradeable.insert(item->GetGUID());
}
-/// @todo should never allow an item to be added to m_itemSoulboundTradeable twice
void Player::RemoveTradeableItem(Item* item)
{
- m_itemSoulboundTradeable.remove(item);
+ m_itemSoulboundTradeable.erase(item->GetGUID());
}
void Player::UpdateItemDuration(uint32 time, bool realtimeonly)
@@ -14252,7 +13920,7 @@ void Player::PrepareGossipMenu(WorldObject* source, uint32 menuId /*= 0*/, bool
VendorItemData const* vendorItems = creature->GetVendorItems();
if (!vendorItems || vendorItems->Empty())
{
- TC_LOG_ERROR("sql.sql", "Creature %s (Entry: %u GUID: %u DB GUID: %u) has UNIT_NPC_FLAG_VENDOR set but has an empty trading item list.", creature->GetName().c_str(), creature->GetEntry(), creature->GetGUIDLow(), creature->GetDBTableGUIDLow());
+ TC_LOG_ERROR("sql.sql", "Creature %s (Entry: %u GUID: %u DB GUID: %u) has UNIT_NPC_FLAG_VENDOR set but has an empty trading item list.", creature->GetName().c_str(), creature->GetEntry(), creature->GetGUID().GetCounter(), creature->GetSpawnId());
canTalk = false;
}
break;
@@ -14287,7 +13955,7 @@ void Player::PrepareGossipMenu(WorldObject* source, uint32 menuId /*= 0*/, bool
case GOSSIP_OPTION_TRAINER:
if (getClass() != creature->GetCreatureTemplate()->trainer_class && creature->GetCreatureTemplate()->trainer_type == TRAINER_TYPE_CLASS)
TC_LOG_ERROR("sql.sql", "GOSSIP_OPTION_TRAINER:: Player %s (GUID: %u) request wrong gossip menu: %u with wrong class: %u at Creature: %s (Entry: %u, Trainer Class: %u)",
- GetName().c_str(), GetGUIDLow(), menu->GetGossipMenu().GetMenuId(), getClass(), creature->GetName().c_str(), creature->GetEntry(), creature->GetCreatureTemplate()->trainer_class);
+ GetName().c_str(), GetGUID().GetCounter(), menu->GetGossipMenu().GetMenuId(), getClass(), creature->GetName().c_str(), creature->GetEntry(), creature->GetCreatureTemplate()->trainer_class);
// no break;
case GOSSIP_OPTION_GOSSIP:
case GOSSIP_OPTION_SPIRITGUIDE:
@@ -14415,7 +14083,7 @@ void Player::OnGossipSelect(WorldObject* source, uint32 gossipListId, uint32 men
{
if (gossipOptionId > GOSSIP_OPTION_QUESTGIVER)
{
- TC_LOG_ERROR("entities.player", "Player guid %u request invalid gossip option for GameObject entry %u", GetGUIDLow(), source->GetEntry());
+ TC_LOG_ERROR("entities.player", "Player guid %u request invalid gossip option for GameObject entry %u", GetGUID().GetCounter(), source->GetEntry());
return;
}
}
@@ -14448,7 +14116,7 @@ void Player::OnGossipSelect(WorldObject* source, uint32 gossipListId, uint32 men
break;
}
case GOSSIP_OPTION_OUTDOORPVP:
- sOutdoorPvPMgr->HandleGossipOption(this, source->GetGUID(), gossipListId);
+ sOutdoorPvPMgr->HandleGossipOption(this, source->ToCreature(), gossipListId);
break;
case GOSSIP_OPTION_SPIRITHEALER:
if (isDead())
@@ -14519,7 +14187,7 @@ void Player::OnGossipSelect(WorldObject* source, uint32 gossipListId, uint32 men
if (bgTypeId == BATTLEGROUND_TYPE_NONE)
{
- TC_LOG_ERROR("entities.player", "a user (guid %u) requested battlegroundlist from a npc who is no battlemaster", GetGUIDLow());
+ TC_LOG_ERROR("entities.player", "a user (guid %u) requested battlegroundlist from a npc who is no battlemaster", GetGUID().GetCounter());
return;
}
@@ -15064,15 +14732,15 @@ void Player::AddQuest(Quest const* quest, Object* questGiver)
uint32 qtime = 0;
if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED))
{
- uint32 limittime = quest->GetLimitTime();
+ uint32 timeAllowed = quest->GetTimeAllowed();
// shared timed quest
if (questGiver && questGiver->GetTypeId() == TYPEID_PLAYER)
- limittime = questGiver->ToPlayer()->getQuestStatusMap()[quest_id].Timer / IN_MILLISECONDS;
+ timeAllowed = questGiver->ToPlayer()->getQuestStatusMap()[quest_id].Timer / IN_MILLISECONDS;
AddTimedQuest(quest_id);
- questStatusData.Timer = limittime * IN_MILLISECONDS;
- qtime = static_cast<uint32>(time(NULL)) + limittime;
+ questStatusData.Timer = timeAllowed * IN_MILLISECONDS;
+ qtime = static_cast<uint32>(time(NULL)) + timeAllowed;
}
else
questStatusData.Timer = 0;
@@ -15096,9 +14764,9 @@ void Player::AddQuest(Quest const* quest, Object* questGiver)
// prepare Quest Tracker datas
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_QUEST_TRACK);
stmt->setUInt32(0, quest_id);
- stmt->setUInt32(1, GetGUIDLow());
- stmt->setString(2, _HASH);
- stmt->setString(3, _DATE);
+ stmt->setUInt32(1, GetGUID().GetCounter());
+ stmt->setString(2, GitRevision::GetHash());
+ stmt->setString(3, GitRevision::GetDate());
// add to Quest Tracker
CharacterDatabase.Execute(stmt);
@@ -15129,7 +14797,7 @@ void Player::CompleteQuest(uint32 quest_id)
// prepare Quest Tracker datas
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_QUEST_TRACK_COMPLETE_TIME);
stmt->setUInt32(0, quest_id);
- stmt->setUInt32(1, GetGUIDLow());
+ stmt->setUInt32(1, GetGUID().GetCounter());
// add to Quest Tracker
CharacterDatabase.Execute(stmt);
@@ -15162,10 +14830,10 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
for (uint8 i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
{
- if (quest->RequiredSourceItemId[i])
+ if (quest->ItemDrop[i])
{
- uint32 count = quest->RequiredSourceItemCount[i];
- DestroyItemCount(quest->RequiredSourceItemId[i], count ? count : 9999, true);
+ uint32 count = quest->ItemDropQuantity[i];
+ DestroyItemCount(quest->ItemDrop[i], count ? count : 9999, true);
}
}
@@ -15372,9 +15040,9 @@ void Player::FailQuest(uint32 questId)
// Destroy items received on starting the quest.
DestroyItemCount(quest->RequiredItemId[i], quest->RequiredItemCount[i], true, true);
for (uint8 i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
- if (quest->RequiredSourceItemId[i] > 0 && quest->RequiredSourceItemCount[i] > 0)
+ if (quest->ItemDrop[i] > 0 && quest->ItemDropQuantity[i] > 0)
// Destroy items received during the quest.
- DestroyItemCount(quest->RequiredSourceItemId[i], quest->RequiredSourceItemCount[i], true, true);
+ DestroyItemCount(quest->ItemDrop[i], quest->ItemDropQuantity[i], true, true);
}
}
@@ -15556,7 +15224,7 @@ bool Player::SatisfyQuestClass(Quest const* qInfo, bool msg) const
bool Player::SatisfyQuestRace(Quest const* qInfo, bool msg)
{
- uint32 reqraces = qInfo->GetRequiredRaces();
+ uint32 reqraces = qInfo->GetAllowableRaces();
if (reqraces == 0)
return true;
if ((reqraces & getRaceMask()) == 0)
@@ -15628,8 +15296,7 @@ bool Player::SatisfyQuestStatus(Quest const* qInfo, bool msg)
bool Player::SatisfyQuestConditions(Quest const* qInfo, bool msg)
{
- ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_QUEST_ACCEPT, qInfo->GetQuestId());
- if (!sConditionMgr->IsObjectMeetToConditions(this, conditions))
+ if (!sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_QUEST_ACCEPT, qInfo->GetQuestId(), this))
{
if (msg)
{
@@ -15895,6 +15562,17 @@ bool Player::GetQuestRewardStatus(uint32 quest_id) const
Quest const* qInfo = sObjectMgr->GetQuestTemplate(quest_id);
if (qInfo)
{
+ if (qInfo->IsSeasonal() && !qInfo->IsRepeatable())
+ {
+ uint16 eventId = sGameEventMgr->GetEventIdForQuest(qInfo);
+ auto seasonalQuestItr = m_seasonalquests.find(eventId);
+ if (seasonalQuestItr != m_seasonalquests.end())
+ return seasonalQuestItr->second.find(quest_id) != seasonalQuestItr->second.end();
+
+ return false;
+ }
+
+
// for repeatable quests: rewarded field is set after first reward only to prevent getting XP more than once
if (!qInfo->IsRepeatable())
return m_RewardedQuests.find(quest_id) != m_RewardedQuests.end();
@@ -15913,8 +15591,18 @@ QuestStatus Player::GetQuestStatus(uint32 quest_id) const
return itr->second.Status;
if (Quest const* qInfo = sObjectMgr->GetQuestTemplate(quest_id))
+ {
+ if (qInfo->IsSeasonal() && !qInfo->IsRepeatable())
+ {
+ uint16 eventId = sGameEventMgr->GetEventIdForQuest(qInfo);
+ auto seasonalQuestItr = m_seasonalquests.find(eventId);
+ if (seasonalQuestItr == m_seasonalquests.end() || seasonalQuestItr->second.find(quest_id) == seasonalQuestItr->second.end())
+ return QUEST_STATUS_NONE;
+ }
+
if (!qInfo->IsRepeatable() && m_RewardedQuests.find(quest_id) != m_RewardedQuests.end())
return QUEST_STATUS_REWARDED;
+ }
}
return QUEST_STATUS_NONE;
}
@@ -16041,8 +15729,7 @@ QuestGiverStatus Player::GetQuestDialogStatus(Object* questgiver)
if (!quest)
continue;
- ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK, quest->GetQuestId());
- if (!sConditionMgr->IsObjectMeetToConditions(this, conditions))
+ if (!sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK, quest->GetQuestId(), this))
continue;
QuestStatus status = GetQuestStatus(questId);
@@ -16069,8 +15756,7 @@ QuestGiverStatus Player::GetQuestDialogStatus(Object* questgiver)
if (!quest)
continue;
- ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK, quest->GetQuestId());
- if (!sConditionMgr->IsObjectMeetToConditions(this, conditions))
+ if (!sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK, quest->GetQuestId(), this))
continue;
QuestStatus status = GetQuestStatus(questId);
@@ -16677,7 +16363,7 @@ bool Player::HasQuestForItem(uint32 itemid) const
for (uint8 j = 0; j < QUEST_SOURCE_ITEM_IDS_COUNT; ++j)
{
// examined item is a source item
- if (qinfo->RequiredSourceItemId[j] == itemid)
+ if (qinfo->ItemDrop[j] == itemid)
{
ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(itemid);
@@ -16686,9 +16372,9 @@ bool Player::HasQuestForItem(uint32 itemid) const
return true;
// allows custom amount drop when not 0
- if (qinfo->RequiredSourceItemCount[j])
+ if (qinfo->ItemDropQuantity[j])
{
- if (GetItemCount(itemid, true) < qinfo->RequiredSourceItemCount[j])
+ if (GetItemCount(itemid, true) < qinfo->ItemDropQuantity[j])
return true;
} else if (GetItemCount(itemid, true) < pProto->GetMaxStackSize())
return true;
@@ -16870,9 +16556,9 @@ bool Player::HasPvPForcingQuest() const
/*** LOAD SYSTEM ***/
/*********************************************************/
-void Player::Initialize(uint32 guid)
+void Player::Initialize(ObjectGuid::LowType guid)
{
- Object::_Create(guid, 0, HIGHGUID_PLAYER);
+ Object::_Create(guid, 0, HighGuid::Player);
}
void Player::_LoadDeclinedNames(PreparedQueryResult result)
@@ -17016,7 +16702,7 @@ void Player::SetHomebind(WorldLocation const& loc, uint32 areaId)
stmt->setFloat (2, m_homebindX);
stmt->setFloat (3, m_homebindY);
stmt->setFloat (4, m_homebindZ);
- stmt->setUInt32(5, GetGUIDLow());
+ stmt->setUInt32(5, GetGUID().GetCounter());
CharacterDatabase.Execute(stmt);
}
@@ -17052,8 +16738,8 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
//"resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, instance_mode_mask, "
// 39 40 41 42 43 44 45 46 47 48 49
//"arenaPoints, totalHonorPoints, todayHonorPoints, yesterdayHonorPoints, totalKills, todayKills, yesterdayKills, chosenTitle, knownCurrencies, watchedFaction, drunk, "
- // 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
- //"health, power1, power2, power3, power4, power5, power6, power7, instance_id, speccount, activespec, exploredZones, equipmentCache, ammoId, knownTitles, actionBars, grantableLevels FROM characters WHERE guid = '%u'", guid);
+ // 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
+ //"health, power1, power2, power3, power4, power5, power6, power7, instance_id, talentGroupsCount, activeTalentGroup, exploredZones, equipmentCache, ammoId, knownTitles, actionBars, grantableLevels FROM characters WHERE guid = '%u'", guid);
PreparedQueryResult result = holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_FROM);
if (!result)
{
@@ -17081,12 +16767,12 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
return false;
}
- Object::_Create(guid.GetCounter(), 0, HIGHGUID_PLAYER);
+ Object::_Create(guid.GetCounter(), 0, HighGuid::Player);
m_name = fields[2].GetString();
// check name limitations
- if (ObjectMgr::CheckPlayerName(m_name) != CHAR_NAME_SUCCESS ||
+ if (ObjectMgr::CheckPlayerName(m_name, GetSession()->GetSessionDbcLocale()) != CHAR_NAME_SUCCESS ||
(!GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) &&
sObjectMgr->IsReservedName(m_name)))
{
@@ -17193,7 +16879,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
InitPrimaryProfessions(); // to max set before any spell loaded
// init saved position, and fix it later if problematic
- uint32 transLowGUID = fields[30].GetUInt32();
+ ObjectGuid::LowType transLowGUID = fields[30].GetUInt32();
Relocate(fields[12].GetFloat(), fields[13].GetFloat(), fields[14].GetFloat(), fields[16].GetFloat());
uint32 mapId = fields[15].GetUInt16();
uint32 instanceId = fields[58].GetUInt32();
@@ -17303,11 +16989,11 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
// currently we do not support transport in bg
else if (transLowGUID)
{
- ObjectGuid transGUID(HIGHGUID_MO_TRANSPORT, transLowGUID);
+ ObjectGuid transGUID(HighGuid::Mo_Transport, transLowGUID);
Transport* transport = NULL;
- if (GameObject* go = HashMapHolder<GameObject>::Find(transGUID))
- transport = go->ToTransport();
+ if (Transport* go = HashMapHolder<Transport>::Find(transGUID))
+ transport = go;
if (transport)
{
@@ -17364,12 +17050,12 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
if (!nodeEntry) // don't know taxi start node, to homebind
{
- TC_LOG_ERROR("entities.player", "Character %u have wrong data in taxi destination list, teleport to homebind.", GetGUIDLow());
+ TC_LOG_ERROR("entities.player", "Character %u have wrong data in taxi destination list, teleport to homebind.", GetGUID().GetCounter());
RelocateToHomebind();
}
else // have start node, to it
{
- TC_LOG_ERROR("entities.player", "Character %u have too short taxi destination list, teleport to original node.", GetGUIDLow());
+ TC_LOG_ERROR("entities.player", "Character %u have too short taxi destination list, teleport to original node.", GetGUID().GetCounter());
mapId = nodeEntry->map_id;
Relocate(nodeEntry->x, nodeEntry->y, nodeEntry->z, 0.0f);
}
@@ -17422,7 +17108,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
}
else if (map->IsDungeon()) // if map is dungeon...
{
- if (!((InstanceMap*)map)->CanEnter(this)) // ... and can't enter map, then look for entry point.
+ if (!((InstanceMap*)map)->CanEnter(this) || !CheckInstanceLoginValid(map)) // ... and can't enter map, then look for entry point.
{
areaTrigger = sObjectMgr->GetGoBackTrigger(mapId);
check = true;
@@ -17449,6 +17135,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
{
TC_LOG_ERROR("entities.player", "Player %s %s Map: %u, X: %f, Y: %f, Z: %f, O: %f. Areatrigger not found.",
m_name.c_str(), guid.ToString().c_str(), mapId, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
+ RelocateToHomebind();
map = NULL;
}
}
@@ -17511,7 +17198,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
if (HasAtLoginFlag(AT_LOGIN_RENAME))
{
- TC_LOG_ERROR("entities.player", "Player (GUID: %u) tried to login while forced to rename, can't load.'", GetGUIDLow());
+ TC_LOG_ERROR("entities.player", "Player (GUID: %u) tried to login while forced to rename, can't load.'", GetGUID().GetCounter());
return false;
}
@@ -17588,7 +17275,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
if (m_specsCount > MAX_TALENT_SPECS || m_activeSpec > MAX_TALENT_SPEC || m_specsCount < MIN_TALENT_SPECS)
{
m_activeSpec = 0;
- TC_LOG_ERROR("entities.player", "Player %s(GUID: %u) has SpecCount = %u and ActiveSpec = %u.", GetName().c_str(), GetGUIDLow(), m_specsCount, m_activeSpec);
+ TC_LOG_ERROR("entities.player", "Player %s(GUID: %u) has SpecCount = %u and ActiveSpec = %u.", GetName().c_str(), GetGUID().GetCounter(), m_specsCount, m_activeSpec);
}
_LoadTalents(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_TALENTS));
@@ -17628,7 +17315,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
// unread mails and next delivery time, actual mails not loaded
_LoadMailInit(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_MAIL_COUNT), holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_MAIL_DATE));
- m_social = sSocialMgr->LoadFromDB(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_SOCIAL_LIST), GetGUIDLow());
+ m_social = sSocialMgr->LoadFromDB(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_SOCIAL_LIST), GetGUID().GetCounter());
// check PLAYER_CHOSEN_TITLE compatibility with PLAYER__FIELD_KNOWN_TITLES
// note: PLAYER__FIELD_KNOWN_TITLES updated at quest status loaded
@@ -17809,12 +17496,12 @@ void Player::_LoadActions(PreparedQueryResult result)
void Player::_LoadAuras(PreparedQueryResult result, uint32 timediff)
{
- TC_LOG_DEBUG("entities.player.loading", "Loading auras for player %u", GetGUIDLow());
+ TC_LOG_DEBUG("entities.player.loading", "Loading auras for player %u", GetGUID().GetCounter());
/* 0 1 2 3 4 5 6 7 8 9 10
- QueryResult* result = CharacterDatabase.PQuery("SELECT caster_guid, spell, effect_mask, recalculate_mask, stackcount, amount0, amount1, amount2, base_amount0, base_amount1, base_amount2,
+ QueryResult* result = CharacterDatabase.PQuery("SELECT casterGuid, spell, effectMask, recalculateMask, stackCount, amount0, amount1, amount2, base_amount0, base_amount1, base_amount2,
11 12 13
- maxduration, remaintime, remaincharges FROM character_aura WHERE guid = '%u'", GetGUIDLow());
+ maxDuration, remainTime, remainCharges FROM character_aura WHERE guid = '%u'", GetGUID().GetCounter());
*/
if (result)
@@ -17913,23 +17600,29 @@ void Player::_LoadGlyphAuras()
}
}
-void Player::LoadCorpse()
+void Player::LoadCorpse(PreparedQueryResult result)
{
- if (IsAlive())
- sObjectAccessor->ConvertCorpseForPlayer(GetGUID());
- else
+ if (IsAlive() || HasAtLoginFlag(AT_LOGIN_RESURRECT))
+ SpawnCorpseBones(false);
+
+ if (!IsAlive())
{
- if (Corpse* corpse = GetCorpse())
- ApplyModFlag(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTE_RELEASE_TIMER, corpse && !sMapStore.LookupEntry(corpse->GetMapId())->Instanceable());
+ if (result && !HasAtLoginFlag(AT_LOGIN_RESURRECT))
+ {
+ Field* fields = result->Fetch();
+ _corpseLocation.WorldRelocate(fields[0].GetUInt16(), fields[1].GetFloat(), fields[2].GetFloat(), fields[3].GetFloat(), fields[4].GetFloat());
+ ApplyModFlag(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTE_RELEASE_TIMER, !sMapStore.LookupEntry(_corpseLocation.GetMapId())->Instanceable());
+ }
else
- //Prevent Dead Player login without corpse
ResurrectPlayer(0.5f);
}
+
+ RemoveAtLoginFlag(AT_LOGIN_RESURRECT);
}
void Player::_LoadInventory(PreparedQueryResult result, uint32 timeDiff)
{
- //QueryResult* result = CharacterDatabase.PQuery("SELECT data, text, bag, slot, item, item_template FROM character_inventory JOIN item_instance ON character_inventory.item = item_instance.guid WHERE character_inventory.guid = '%u' ORDER BY bag, slot", GetGUIDLow());
+ //QueryResult* result = CharacterDatabase.PQuery("SELECT data, text, bag, slot, item, item_template FROM character_inventory JOIN item_instance ON character_inventory.item = item_instance.guid WHERE character_inventory.guid = '%u' ORDER BY bag, slot", GetGUID().GetCounter());
//NOTE: the "order by `bag`" is important because it makes sure
//the bagMap is filled before items in the bags are loaded
//NOTE2: the "order by `slot`" is needed because mainhand weapons are (wrongly?)
@@ -17939,8 +17632,8 @@ void Player::_LoadInventory(PreparedQueryResult result, uint32 timeDiff)
{
uint32 zoneId = GetZoneId();
- std::map<uint32, Bag*> bagMap; // fast guid lookup for bags
- std::map<uint32, Item*> invalidBagMap; // fast guid lookup for bags
+ std::map<ObjectGuid::LowType, Bag*> bagMap; // fast guid lookup for bags
+ std::map<ObjectGuid::LowType, Item*> invalidBagMap; // fast guid lookup for bags
std::list<Item*> problematicItems;
SQLTransaction trans = CharacterDatabase.BeginTransaction();
@@ -17951,7 +17644,7 @@ void Player::_LoadInventory(PreparedQueryResult result, uint32 timeDiff)
Field* fields = result->Fetch();
if (Item* item = _LoadItem(trans, zoneId, timeDiff, fields))
{
- uint32 bagGuid = fields[11].GetUInt32();
+ ObjectGuid::LowType bagGuid = fields[11].GetUInt32();
uint8 slot = fields[12].GetUInt8();
uint8 err = EQUIP_ERR_OK;
@@ -17988,18 +17681,18 @@ void Player::_LoadInventory(PreparedQueryResult result, uint32 timeDiff)
{
if (IsBagPos(item->GetPos()))
if (Bag* pBag = item->ToBag())
- bagMap[item->GetGUIDLow()] = pBag;
+ bagMap[item->GetGUID().GetCounter()] = pBag;
}
else
if (IsBagPos(item->GetPos()))
if (item->IsBag())
- invalidBagMap[item->GetGUIDLow()] = item;
+ invalidBagMap[item->GetGUID().GetCounter()] = item;
}
else
{
item->SetSlot(NULL_SLOT);
// Item is in the bag, find the bag
- std::map<uint32, Bag*>::iterator itr = bagMap.find(bagGuid);
+ std::map<ObjectGuid::LowType, Bag*>::iterator itr = bagMap.find(bagGuid);
if (itr != bagMap.end())
{
ItemPosCountVec dest;
@@ -18009,14 +17702,14 @@ void Player::_LoadInventory(PreparedQueryResult result, uint32 timeDiff)
}
else if (invalidBagMap.find(bagGuid) != invalidBagMap.end())
{
- std::map<uint32, Item*>::iterator itr = invalidBagMap.find(bagGuid);
- if (std::find(problematicItems.begin(), problematicItems.end(), itr->second) != problematicItems.end())
+ std::map<ObjectGuid::LowType, Item*>::iterator invalidBagItr = invalidBagMap.find(bagGuid);
+ if (std::find(problematicItems.begin(), problematicItems.end(), invalidBagItr->second) != problematicItems.end())
err = EQUIP_ERR_INT_BAG_ERROR;
}
else
{
TC_LOG_ERROR("entities.player", "Player::_LoadInventory: player (GUID: %u, name: '%s') has item (GUID: %u, entry: %u) which doesnt have a valid bag (Bag GUID: %u, slot: %u). Possible cheat?",
- GetGUIDLow(), GetName().c_str(), item->GetGUIDLow(), item->GetEntry(), bagGuid, slot);
+ GetGUID().GetCounter(), GetName().c_str(), item->GetGUID().GetCounter(), item->GetEntry(), bagGuid, slot);
item->DeleteFromInventoryDB(trans);
delete item;
continue;
@@ -18030,7 +17723,7 @@ void Player::_LoadInventory(PreparedQueryResult result, uint32 timeDiff)
else
{
TC_LOG_ERROR("entities.player", "Player::_LoadInventory: player (GUID: %u, name: '%s') has item (GUID: %u, entry: %u) which can't be loaded into inventory (Bag GUID: %u, slot: %u) by reason %u. Item will be sent by mail.",
- GetGUIDLow(), GetName().c_str(), item->GetGUIDLow(), item->GetEntry(), bagGuid, slot, err);
+ GetGUID().GetCounter(), GetName().c_str(), item->GetGUID().GetCounter(), item->GetEntry(), bagGuid, slot, err);
item->DeleteFromInventoryDB(trans);
problematicItems.push_back(item);
}
@@ -18061,7 +17754,7 @@ void Player::_LoadInventory(PreparedQueryResult result, uint32 timeDiff)
Item* Player::_LoadItem(SQLTransaction& trans, uint32 zoneId, uint32 timeDiff, Field* fields)
{
Item* item = NULL;
- uint32 itemGuid = fields[13].GetUInt32();
+ ObjectGuid::LowType itemGuid = fields[13].GetUInt32();
uint32 itemEntry = fields[14].GetUInt32();
if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemEntry))
{
@@ -18075,14 +17768,14 @@ Item* Player::_LoadItem(SQLTransaction& trans, uint32 zoneId, uint32 timeDiff, F
if (IsAlive() && item->IsLimitedToAnotherMapOrZone(GetMapId(), zoneId))
{
TC_LOG_DEBUG("entities.player.loading", "Player::_LoadInventory: player (GUID: %u, name: '%s', map: %u) has item (GUID: %u, entry: %u) limited to another map (%u). Deleting item.",
- GetGUIDLow(), GetName().c_str(), GetMapId(), item->GetGUIDLow(), item->GetEntry(), zoneId);
+ GetGUID().GetCounter(), GetName().c_str(), GetMapId(), item->GetGUID().GetCounter(), item->GetEntry(), zoneId);
remove = true;
}
// "Conjured items disappear if you are logged out for more than 15 minutes"
else if (timeDiff > 15 * MINUTE && proto->Flags & ITEM_PROTO_FLAG_CONJURED)
{
TC_LOG_DEBUG("entities.player.loading", "Player::_LoadInventory: player (GUID: %u, name: '%s', diff: %u) has conjured item (GUID: %u, entry: %u) with expired lifetime (15 minutes). Deleting item.",
- GetGUIDLow(), GetName().c_str(), timeDiff, item->GetGUIDLow(), item->GetEntry());
+ GetGUID().GetCounter(), GetName().c_str(), timeDiff, item->GetGUID().GetCounter(), item->GetEntry());
remove = true;
}
else if (item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE))
@@ -18090,10 +17783,10 @@ Item* Player::_LoadItem(SQLTransaction& trans, uint32 zoneId, uint32 timeDiff, F
if (item->GetPlayedTime() > (2 * HOUR))
{
TC_LOG_DEBUG("entities.player.loading", "Player::_LoadInventory: player (GUID: %u, name: '%s') has item (GUID: %u, entry: %u) with expired refund time (%u). Deleting refund data and removing refundable flag.",
- GetGUIDLow(), GetName().c_str(), item->GetGUIDLow(), item->GetEntry(), item->GetPlayedTime());
+ GetGUID().GetCounter(), GetName().c_str(), item->GetGUID().GetCounter(), item->GetEntry(), item->GetPlayedTime());
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_REFUND_INSTANCE);
- stmt->setUInt32(0, item->GetGUIDLow());
+ stmt->setUInt32(0, item->GetGUID().GetCounter());
trans->Append(stmt);
item->RemoveFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE);
@@ -18101,8 +17794,8 @@ Item* Player::_LoadItem(SQLTransaction& trans, uint32 zoneId, uint32 timeDiff, F
else
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ITEM_REFUNDS);
- stmt->setUInt32(0, item->GetGUIDLow());
- stmt->setUInt32(1, GetGUIDLow());
+ stmt->setUInt32(0, item->GetGUID().GetCounter());
+ stmt->setUInt32(1, GetGUID().GetCounter());
if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
{
item->SetRefundRecipient((*result)[0].GetUInt32());
@@ -18113,7 +17806,7 @@ Item* Player::_LoadItem(SQLTransaction& trans, uint32 zoneId, uint32 timeDiff, F
else
{
TC_LOG_DEBUG("entities.player.loading", "Player::_LoadInventory: player (GUID: %u, name: '%s') has item (GUID: %u, entry: %u) with refundable flags, but without data in item_refund_instance. Removing flag.",
- GetGUIDLow(), GetName().c_str(), item->GetGUIDLow(), item->GetEntry());
+ GetGUID().GetCounter(), GetName().c_str(), item->GetGUID().GetCounter(), item->GetEntry());
item->RemoveFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE);
}
}
@@ -18121,7 +17814,7 @@ Item* Player::_LoadItem(SQLTransaction& trans, uint32 zoneId, uint32 timeDiff, F
else if (item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_BOP_TRADEABLE))
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ITEM_BOP_TRADE);
- stmt->setUInt32(0, item->GetGUIDLow());
+ stmt->setUInt32(0, item->GetGUID().GetCounter());
if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
{
std::string strGUID = (*result)[0].GetString();
@@ -18141,7 +17834,7 @@ Item* Player::_LoadItem(SQLTransaction& trans, uint32 zoneId, uint32 timeDiff, F
else
{
TC_LOG_DEBUG("entities.player.loading", "Player::_LoadInventory: player (GUID: %u, name: '%s') has item (GUID: %u, entry: %u) with ITEM_FLAG_BOP_TRADEABLE flag, but without data in item_soulbound_trade_data. Removing flag.",
- GetGUIDLow(), GetName().c_str(), item->GetGUIDLow(), item->GetEntry());
+ GetGUID().GetCounter(), GetName().c_str(), item->GetGUID().GetCounter(), item->GetEntry());
item->RemoveFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_BOP_TRADEABLE);
}
}
@@ -18163,7 +17856,7 @@ Item* Player::_LoadItem(SQLTransaction& trans, uint32 zoneId, uint32 timeDiff, F
else
{
TC_LOG_ERROR("entities.player", "Player::_LoadInventory: player (GUID: %u, name: '%s') has broken item (GUID: %u, entry: %u) in inventory. Deleting item.",
- GetGUIDLow(), GetName().c_str(), itemGuid, itemEntry);
+ GetGUID().GetCounter(), GetName().c_str(), itemGuid, itemEntry);
remove = true;
}
// Remove item from inventory if necessary
@@ -18178,7 +17871,7 @@ Item* Player::_LoadItem(SQLTransaction& trans, uint32 zoneId, uint32 timeDiff, F
else
{
TC_LOG_ERROR("entities.player", "Player::_LoadInventory: player (GUID: %u, name: '%s') has unknown item (entry: %u) in inventory. Deleting item.",
- GetGUIDLow(), GetName().c_str(), itemEntry);
+ GetGUID().GetCounter(), GetName().c_str(), itemEntry);
Item::DeleteFromInventoryDB(trans, itemGuid);
Item::DeleteFromDB(trans, itemGuid);
}
@@ -18199,7 +17892,7 @@ void Player::_LoadMailedItems(Mail* mail)
{
Field* fields = result->Fetch();
- uint32 itemGuid = fields[11].GetUInt32();
+ ObjectGuid::LowType itemGuid = fields[11].GetUInt32();
uint32 itemTemplate = fields[12].GetUInt32();
mail->AddItem(itemGuid, itemTemplate);
@@ -18208,7 +17901,7 @@ void Player::_LoadMailedItems(Mail* mail)
if (!proto)
{
- TC_LOG_ERROR("entities.player", "Player %u has unknown item_template (ProtoType) in mailed items(GUID: %u template: %u) in mail (%u), deleted.", GetGUIDLow(), itemGuid, itemTemplate, mail->messageID);
+ TC_LOG_ERROR("entities.player", "Player %u has unknown item_template (ProtoType) in mailed items(GUID: %u template: %u) in mail (%u), deleted.", GetGUID().GetCounter(), itemGuid, itemTemplate, mail->messageID);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INVALID_MAIL_ITEM);
stmt->setUInt32(0, itemGuid);
@@ -18222,7 +17915,7 @@ void Player::_LoadMailedItems(Mail* mail)
Item* item = NewItemOrBag(proto);
- if (!item->LoadFromDB(itemGuid, ObjectGuid(HIGHGUID_PLAYER, fields[13].GetUInt32()), fields, itemTemplate))
+ if (!item->LoadFromDB(itemGuid, ObjectGuid(HighGuid::Player, fields[13].GetUInt32()), fields, itemTemplate))
{
TC_LOG_ERROR("entities.player", "Player::_LoadMailedItems - Item in mail (%u) doesn't exist !!!! - item guid: %u, deleted from mail", mail->messageID, itemGuid);
@@ -18260,7 +17953,7 @@ void Player::_LoadMail()
m_mail.clear();
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAIL);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
PreparedQueryResult result = CharacterDatabase.Query(stmt);
if (result)
@@ -18322,7 +18015,7 @@ void Player::_LoadQuestStatus(PreparedQueryResult result)
//// 0 1 2 3 4 5 6 7 8 9 10
//QueryResult* result = CharacterDatabase.PQuery("SELECT quest, status, explored, timer, mobcount1, mobcount2, mobcount3, mobcount4, itemcount1, itemcount2, itemcount3,
// 11 12
- // itemcount4, playercount FROM character_queststatus WHERE guid = '%u'", GetGUIDLow());
+ // itemcount4, playercount FROM character_queststatus WHERE guid = '%u'", GetGUID().GetCounter());
if (result)
{
@@ -18345,7 +18038,7 @@ void Player::_LoadQuestStatus(PreparedQueryResult result)
{
questStatusData.Status = QUEST_STATUS_INCOMPLETE;
TC_LOG_ERROR("entities.player", "Player %s (GUID: %u) has invalid quest %d status (%u), replaced by QUEST_STATUS_INCOMPLETE(3).",
- GetName().c_str(), GetGUIDLow(), quest_id, qstatus);
+ GetName().c_str(), GetGUID().GetCounter(), quest_id, qstatus);
}
questStatusData.Explored = (fields[2].GetUInt8() > 0);
@@ -18394,7 +18087,7 @@ void Player::_LoadQuestStatus(PreparedQueryResult result)
++slot;
}
- TC_LOG_DEBUG("entities.player.loading", "Quest status is {%u} for quest {%u} for player (GUID: %u)", questStatusData.Status, quest_id, GetGUIDLow());
+ TC_LOG_DEBUG("entities.player.loading", "Quest status is {%u} for quest {%u} for player (GUID: %u)", questStatusData.Status, quest_id, GetGUID().GetCounter());
}
}
while (result->NextRow());
@@ -18447,7 +18140,7 @@ void Player::_LoadDailyQuestStatus(PreparedQueryResult result)
m_DFQuests.clear();
- //QueryResult* result = CharacterDatabase.PQuery("SELECT quest, time FROM character_queststatus_daily WHERE guid = '%u'", GetGUIDLow());
+ //QueryResult* result = CharacterDatabase.PQuery("SELECT quest, time FROM character_queststatus_daily WHERE guid = '%u'", GetGUID().GetCounter());
if (result)
{
@@ -18468,7 +18161,7 @@ void Player::_LoadDailyQuestStatus(PreparedQueryResult result)
if (quest_daily_idx >= PLAYER_MAX_DAILY_QUESTS) // max amount with exist data in query
{
- TC_LOG_ERROR("entities.player", "Player (GUID: %u) have more 25 daily quest records in `charcter_queststatus_daily`", GetGUIDLow());
+ TC_LOG_ERROR("entities.player", "Player (GUID: %u) have more 25 daily quest records in `charcter_queststatus_daily`", GetGUID().GetCounter());
break;
}
@@ -18484,7 +18177,7 @@ void Player::_LoadDailyQuestStatus(PreparedQueryResult result)
SetUInt32Value(PLAYER_FIELD_DAILY_QUESTS_1+quest_daily_idx, quest_id);
++quest_daily_idx;
- TC_LOG_DEBUG("entities.player.loading", "Daily quest (%u) cooldown for player (GUID: %u)", quest_id, GetGUIDLow());
+ TC_LOG_DEBUG("entities.player.loading", "Daily quest (%u) cooldown for player (GUID: %u)", quest_id, GetGUID().GetCounter());
}
while (result->NextRow());
}
@@ -18507,7 +18200,7 @@ void Player::_LoadWeeklyQuestStatus(PreparedQueryResult result)
continue;
m_weeklyquests.insert(quest_id);
- TC_LOG_DEBUG("entities.player.loading", "Weekly quest {%u} cooldown for player (GUID: %u)", quest_id, GetGUIDLow());
+ TC_LOG_DEBUG("entities.player.loading", "Weekly quest {%u} cooldown for player (GUID: %u)", quest_id, GetGUID().GetCounter());
}
while (result->NextRow());
}
@@ -18531,7 +18224,7 @@ void Player::_LoadSeasonalQuestStatus(PreparedQueryResult result)
continue;
m_seasonalquests[event_id].insert(quest_id);
- TC_LOG_DEBUG("entities.player.loading", "Seasonal quest {%u} cooldown for player (GUID: %u)", quest_id, GetGUIDLow());
+ TC_LOG_DEBUG("entities.player.loading", "Seasonal quest {%u} cooldown for player (GUID: %u)", quest_id, GetGUID().GetCounter());
}
while (result->NextRow());
}
@@ -18554,7 +18247,7 @@ void Player::_LoadMonthlyQuestStatus(PreparedQueryResult result)
continue;
m_monthlyquests.insert(quest_id);
- TC_LOG_DEBUG("entities.player.loading", "Monthly quest {%u} cooldown for player (GUID: %u)", quest_id, GetGUIDLow());
+ TC_LOG_DEBUG("entities.player.loading", "Monthly quest {%u} cooldown for player (GUID: %u)", quest_id, GetGUID().GetCounter());
}
while (result->NextRow());
}
@@ -18564,7 +18257,7 @@ void Player::_LoadMonthlyQuestStatus(PreparedQueryResult result)
void Player::_LoadSpells(PreparedQueryResult result)
{
- //QueryResult* result = CharacterDatabase.PQuery("SELECT spell, active, disabled FROM character_spell WHERE guid = '%u'", GetGUIDLow());
+ //QueryResult* result = CharacterDatabase.PQuery("SELECT spell, active, disabled FROM character_spell WHERE guid = '%u'", GetGUID().GetCounter());
if (result)
{
@@ -18576,7 +18269,7 @@ void Player::_LoadSpells(PreparedQueryResult result)
void Player::_LoadGroup(PreparedQueryResult result)
{
- //QueryResult* result = CharacterDatabase.PQuery("SELECT guid FROM group_member WHERE memberGuid=%u", GetGUIDLow());
+ //QueryResult* result = CharacterDatabase.PQuery("SELECT guid FROM group_member WHERE memberGuid=%u", GetGUID().GetCounter());
if (result)
{
if (Group* group = sGroupMgr->GetGroupByDbStoreId((*result)[0].GetUInt32()))
@@ -18630,12 +18323,12 @@ void Player::_LoadBoundInstances(PreparedQueryResult result)
if (!mapEntry || !mapEntry->IsDungeon())
{
- TC_LOG_ERROR("entities.player", "_LoadBoundInstances: player %s(%d) has bind to not existed or not dungeon map %d (%s)", GetName().c_str(), GetGUIDLow(), mapId, mapname.c_str());
+ TC_LOG_ERROR("entities.player", "_LoadBoundInstances: player %s(%d) has bind to not existed or not dungeon map %d (%s)", GetName().c_str(), GetGUID().GetCounter(), mapId, mapname.c_str());
deleteInstance = true;
}
else if (difficulty >= MAX_DIFFICULTY)
{
- TC_LOG_ERROR("entities.player", "_LoadBoundInstances: player %s(%d) has bind to not existed difficulty %d instance for map %u (%s)", GetName().c_str(), GetGUIDLow(), difficulty, mapId, mapname.c_str());
+ TC_LOG_ERROR("entities.player", "_LoadBoundInstances: player %s(%d) has bind to not existed difficulty %d instance for map %u (%s)", GetName().c_str(), GetGUID().GetCounter(), difficulty, mapId, mapname.c_str());
deleteInstance = true;
}
else
@@ -18643,12 +18336,12 @@ void Player::_LoadBoundInstances(PreparedQueryResult result)
MapDifficulty const* mapDiff = GetMapDifficultyData(mapId, Difficulty(difficulty));
if (!mapDiff)
{
- TC_LOG_ERROR("entities.player", "_LoadBoundInstances: player %s(%d) has bind to not existed difficulty %d instance for map %u (%s)", GetName().c_str(), GetGUIDLow(), difficulty, mapId, mapname.c_str());
+ TC_LOG_ERROR("entities.player", "_LoadBoundInstances: player %s(%d) has bind to not existed difficulty %d instance for map %u (%s)", GetName().c_str(), GetGUID().GetCounter(), difficulty, mapId, mapname.c_str());
deleteInstance = true;
}
else if (!perm && group)
{
- TC_LOG_ERROR("entities.player", "_LoadBoundInstances: player %s(%d) is in group %d but has a non-permanent character bind to map %d (%s), %d, %d", GetName().c_str(), GetGUIDLow(), group->GetLowGUID(), mapId, mapname.c_str(), instanceId, difficulty);
+ TC_LOG_ERROR("entities.player", "_LoadBoundInstances: player %s(%d) is in group %d but has a non-permanent character bind to map %d (%s), %d, %d", GetName().c_str(), GetGUID().GetCounter(), group->GetLowGUID(), mapId, mapname.c_str(), instanceId, difficulty);
deleteInstance = true;
}
}
@@ -18657,7 +18350,7 @@ void Player::_LoadBoundInstances(PreparedQueryResult result)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_INSTANCE_BY_INSTANCE_GUID);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
stmt->setUInt32(1, instanceId);
CharacterDatabase.Execute(stmt);
@@ -18713,7 +18406,7 @@ void Player::UnbindInstance(BoundInstancesMap::iterator &itr, Difficulty difficu
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_INSTANCE_BY_INSTANCE_GUID);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
stmt->setUInt32(1, itr->second.save->GetInstanceId());
CharacterDatabase.Execute(stmt);
@@ -18743,7 +18436,7 @@ InstancePlayerBind* Player::BindToInstance(InstanceSave* save, bool permanent, b
stmt->setUInt32(0, save->GetInstanceId());
stmt->setBool(1, permanent);
- stmt->setUInt32(2, GetGUIDLow());
+ stmt->setUInt32(2, GetGUID().GetCounter());
stmt->setUInt32(3, bind.save->GetInstanceId());
CharacterDatabase.Execute(stmt);
@@ -18753,7 +18446,7 @@ InstancePlayerBind* Player::BindToInstance(InstanceSave* save, bool permanent, b
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_INSTANCE);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
stmt->setUInt32(1, save->GetInstanceId());
stmt->setBool(2, permanent);
@@ -18774,7 +18467,7 @@ InstancePlayerBind* Player::BindToInstance(InstanceSave* save, bool permanent, b
bind.save = save;
bind.perm = permanent;
if (!load)
- TC_LOG_DEBUG("maps", "Player::BindToInstance: %s(%d) is now bound to map %d, instance %d, difficulty %d", GetName().c_str(), GetGUIDLow(), save->GetMapId(), save->GetInstanceId(), save->GetDifficulty());
+ TC_LOG_DEBUG("maps", "Player::BindToInstance: %s(%d) is now bound to map %d, instance %d, difficulty %d", GetName().c_str(), GetGUID().GetCounter(), save->GetMapId(), save->GetInstanceId(), save->GetDifficulty());
sScriptMgr->OnPlayerBindToInstance(this, save->GetDifficulty(), save->GetMapId(), permanent);
return &bind;
}
@@ -18791,9 +18484,11 @@ void Player::BindToInstance()
WorldPacket data(SMSG_INSTANCE_SAVE_CREATED, 4);
data << uint32(0);
GetSession()->SendPacket(&data);
- BindToInstance(mapSave, true);
-
- GetSession()->SendCalendarRaidLockout(mapSave, true);
+ if (!IsGameMaster())
+ {
+ BindToInstance(mapSave, true);
+ GetSession()->SendCalendarRaidLockout(mapSave, true);
+ }
}
void Player::SetPendingBind(uint32 instanceId, uint32 bindTimer)
@@ -18973,29 +18668,37 @@ bool Player::Satisfy(AccessRequirement const* ar, uint32 target_map, bool report
return true;
}
-bool Player::CheckInstanceLoginValid()
+bool Player::CheckInstanceLoginValid(Map* map)
{
- if (!FindMap())
- return false;
-
- if (!GetMap()->IsDungeon() || IsGameMaster())
+ if (!map->IsDungeon() || IsGameMaster())
return true;
- if (GetMap()->IsRaid())
+ if (map->IsRaid())
{
// cannot be in raid instance without a group
if (!GetGroup())
- return false;
+ return IsInstanceLoginGameMasterException();
}
else
{
// cannot be in normal instance without a group and more players than 1 in instance
- if (!GetGroup() && GetMap()->GetPlayersCountExceptGMs() > 1)
- return false;
+ if (!GetGroup() && map->GetPlayersCountExceptGMs() > 1)
+ return IsInstanceLoginGameMasterException();
}
// do checks for satisfy accessreqs, instance full, encounter in progress (raid), perm bind group != perm bind player
- return sMapMgr->CanPlayerEnter(GetMap()->GetId(), this, true);
+ return sMapMgr->CanPlayerEnter(map->GetId(), this, true) || IsInstanceLoginGameMasterException();
+}
+
+bool Player::IsInstanceLoginGameMasterException() const
+{
+ if (CanBeGameMaster())
+ {
+ ChatHandler(GetSession()).SendSysMessage(LANG_INSTANCE_LOGIN_GAMEMASTER_EXCEPTION);
+ return true;
+ }
+ else
+ return false;
}
bool Player::CheckInstanceCount(uint32 instanceId) const
@@ -19041,7 +18744,7 @@ bool Player::_LoadHomeBind(PreparedQueryResult result)
else
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_HOMEBIND);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
CharacterDatabase.Execute(stmt);
}
}
@@ -19055,7 +18758,7 @@ bool Player::_LoadHomeBind(PreparedQueryResult result)
m_homebindZ = info->positionZ;
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PLAYER_HOMEBIND);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
stmt->setUInt16(1, m_homebindMapId);
stmt->setUInt16(2, m_homebindAreaId);
stmt->setFloat (3, m_homebindX);
@@ -19103,12 +18806,12 @@ void Player::SaveToDB(bool create /*=false*/)
//! Insert query
/// @todo: Filter out more redundant fields that can take their default value at player create
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER);
- stmt->setUInt32(index++, GetGUIDLow());
+ stmt->setUInt32(index++, GetGUID().GetCounter());
stmt->setUInt32(index++, GetSession()->GetAccountId());
stmt->setString(index++, GetName());
stmt->setUInt8(index++, getRace());
stmt->setUInt8(index++, getClass());
- stmt->setUInt8(index++, getGender());
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_3, 0)); // save gender from PLAYER_BYTES_3, UNIT_BYTES_0 changes with every transform effect
stmt->setUInt8(index++, getLevel());
stmt->setUInt32(index++, GetUInt32Value(PLAYER_XP));
stmt->setUInt32(index++, GetMoney());
@@ -19126,9 +18829,9 @@ void Player::SaveToDB(bool create /*=false*/)
stmt->setFloat(index++, finiteAlways(GetTransOffsetY()));
stmt->setFloat(index++, finiteAlways(GetTransOffsetZ()));
stmt->setFloat(index++, finiteAlways(GetTransOffsetO()));
- uint32 transLowGUID = 0;
+ ObjectGuid::LowType transLowGUID = 0;
if (GetTransport())
- transLowGUID = GetTransport()->GetGUIDLow();
+ transLowGUID = GetTransport()->GetGUID().GetCounter();
stmt->setUInt32(index++, transLowGUID);
std::ostringstream ss;
@@ -19213,7 +18916,7 @@ void Player::SaveToDB(bool create /*=false*/)
stmt->setString(index++, GetName());
stmt->setUInt8(index++, getRace());
stmt->setUInt8(index++, getClass());
- stmt->setUInt8(index++, getGender());
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_3, 0)); // save gender from PLAYER_BYTES_3, UNIT_BYTES_0 changes with every transform effect
stmt->setUInt8(index++, getLevel());
stmt->setUInt32(index++, GetUInt32Value(PLAYER_XP));
stmt->setUInt32(index++, GetMoney());
@@ -19246,9 +18949,9 @@ void Player::SaveToDB(bool create /*=false*/)
stmt->setFloat(index++, finiteAlways(GetTransOffsetY()));
stmt->setFloat(index++, finiteAlways(GetTransOffsetZ()));
stmt->setFloat(index++, finiteAlways(GetTransOffsetO()));
- uint32 transLowGUID = 0;
+ ObjectGuid::LowType transLowGUID = 0;
if (GetTransport())
- transLowGUID = GetTransport()->GetGUIDLow();
+ transLowGUID = GetTransport()->GetGUID().GetCounter();
stmt->setUInt32(index++, transLowGUID);
std::ostringstream ss;
@@ -19328,7 +19031,7 @@ void Player::SaveToDB(bool create /*=false*/)
stmt->setUInt8(index++, IsInWorld() && !GetSession()->PlayerLogout() ? 1 : 0);
// Index
- stmt->setUInt32(index++, GetGUIDLow());
+ stmt->setUInt32(index++, GetGUID().GetCounter());
}
SQLTransaction trans = CharacterDatabase.BeginTransaction();
@@ -19381,7 +19084,7 @@ void Player::SaveGoldToDB(SQLTransaction& trans)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_MONEY);
stmt->setUInt32(0, GetMoney());
- stmt->setUInt32(1, GetGUIDLow());
+ stmt->setUInt32(1, GetGUID().GetCounter());
trans->Append(stmt);
}
@@ -19395,7 +19098,7 @@ void Player::_SaveActions(SQLTransaction& trans)
{
case ACTIONBUTTON_NEW:
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_ACTION);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
stmt->setUInt8(1, m_activeSpec);
stmt->setUInt8(2, itr->first);
stmt->setUInt32(3, itr->second.GetAction());
@@ -19409,7 +19112,7 @@ void Player::_SaveActions(SQLTransaction& trans)
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_ACTION);
stmt->setUInt32(0, itr->second.GetAction());
stmt->setUInt8(1, uint8(itr->second.GetType()));
- stmt->setUInt32(2, GetGUIDLow());
+ stmt->setUInt32(2, GetGUID().GetCounter());
stmt->setUInt8(3, itr->first);
stmt->setUInt8(4, m_activeSpec);
trans->Append(stmt);
@@ -19419,7 +19122,7 @@ void Player::_SaveActions(SQLTransaction& trans)
break;
case ACTIONBUTTON_DELETED:
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACTION_BY_BUTTON_SPEC);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
stmt->setUInt8(1, itr->first);
stmt->setUInt8(2, m_activeSpec);
trans->Append(stmt);
@@ -19436,7 +19139,7 @@ void Player::_SaveActions(SQLTransaction& trans)
void Player::_SaveAuras(SQLTransaction& trans)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_AURA);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
trans->Append(stmt);
for (AuraMap::const_iterator itr = m_ownedAuras.begin(); itr != m_ownedAuras.end(); ++itr)
@@ -19469,7 +19172,7 @@ void Player::_SaveAuras(SQLTransaction& trans)
uint8 index = 0;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_AURA);
- stmt->setUInt32(index++, GetGUIDLow());
+ stmt->setUInt32(index++, GetGUID().GetCounter());
stmt->setUInt64(index++, itr->second->GetCasterGUID().GetRawValue());
stmt->setUInt64(index++, itr->second->GetCastItemGUID().GetRawValue());
stmt->setUInt32(index++, itr->second->GetId());
@@ -19501,11 +19204,11 @@ void Player::_SaveInventory(SQLTransaction& trans)
continue;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_INVENTORY_BY_ITEM);
- stmt->setUInt32(0, item->GetGUIDLow());
+ stmt->setUInt32(0, item->GetGUID().GetCounter());
trans->Append(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE);
- stmt->setUInt32(0, item->GetGUIDLow());
+ stmt->setUInt32(0, item->GetGUID().GetCounter());
trans->Append(stmt);
m_items[i]->FSetState(ITEM_NEW);
}
@@ -19529,7 +19232,7 @@ void Player::_SaveInventory(SQLTransaction& trans)
}
else
{
- TC_LOG_ERROR("entities.player", "Can't find %s but is in refundable storage for player %u ! Removing.", itr->ToString().c_str(), GetGUIDLow());
+ TC_LOG_ERROR("entities.player", "Can't find %s but is in refundable storage for player %u ! Removing.", itr->ToString().c_str(), GetGUID().GetCounter());
m_refundableItems.erase(itr);
}
}
@@ -19542,7 +19245,7 @@ void Player::_SaveInventory(SQLTransaction& trans)
if (m_itemUpdateQueue.empty())
return;
- uint32 lowGuid = GetGUIDLow();
+ ObjectGuid::LowType lowGuid = GetGUID().GetCounter();
for (size_t i = 0; i < m_itemUpdateQueue.size(); ++i)
{
Item* item = m_itemUpdateQueue[i];
@@ -19550,17 +19253,17 @@ void Player::_SaveInventory(SQLTransaction& trans)
continue;
Bag* container = item->GetContainer();
- uint32 bag_guid = container ? container->GetGUIDLow() : 0;
+ ObjectGuid::LowType bag_guid = container ? container->GetGUID().GetCounter() : 0;
if (item->GetState() != ITEM_REMOVED)
{
Item* test = GetItemByPos(item->GetBagSlot(), item->GetSlot());
if (test == NULL)
{
- uint32 bagTestGUID = 0;
+ ObjectGuid::LowType bagTestGUID = 0;
if (Item* test2 = GetItemByPos(INVENTORY_SLOT_BAG_0, item->GetBagSlot()))
- bagTestGUID = test2->GetGUIDLow();
- TC_LOG_ERROR("entities.player", "Player(GUID: %u Name: %s)::_SaveInventory - the bag(%u) and slot(%u) values for the item with guid %u (state %d) are incorrect, the player doesn't have an item at that position!", lowGuid, GetName().c_str(), item->GetBagSlot(), item->GetSlot(), item->GetGUIDLow(), (int32)item->GetState());
+ bagTestGUID = test2->GetGUID().GetCounter();
+ TC_LOG_ERROR("entities.player", "Player(GUID: %u Name: %s)::_SaveInventory - the bag(%u) and slot(%u) values for the item with guid %u (state %d) are incorrect, the player doesn't have an item at that position!", lowGuid, GetName().c_str(), item->GetBagSlot(), item->GetSlot(), item->GetGUID().GetCounter(), (int32)item->GetState());
// according to the test that was just performed nothing should be in this slot, delete
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_INVENTORY_BY_BAG_SLOT);
stmt->setUInt32(0, bagTestGUID);
@@ -19576,7 +19279,7 @@ void Player::_SaveInventory(SQLTransaction& trans)
}
else if (test != item)
{
- TC_LOG_ERROR("entities.player", "Player(GUID: %u Name: %s)::_SaveInventory - the bag(%u) and slot(%u) values for the item with guid %u are incorrect, the item with guid %u is there instead!", lowGuid, GetName().c_str(), item->GetBagSlot(), item->GetSlot(), item->GetGUIDLow(), test->GetGUIDLow());
+ TC_LOG_ERROR("entities.player", "Player(GUID: %u Name: %s)::_SaveInventory - the bag(%u) and slot(%u) values for the item with guid %u are incorrect, the item with guid %u is there instead!", lowGuid, GetName().c_str(), item->GetBagSlot(), item->GetSlot(), item->GetGUID().GetCounter(), test->GetGUID().GetCounter());
// save all changes to the item...
if (item->GetState() != ITEM_NEW) // only for existing items, no dupes
item->SaveToDB(trans);
@@ -19593,12 +19296,12 @@ void Player::_SaveInventory(SQLTransaction& trans)
stmt->setUInt32(0, lowGuid);
stmt->setUInt32(1, bag_guid);
stmt->setUInt8 (2, item->GetSlot());
- stmt->setUInt32(3, item->GetGUIDLow());
+ stmt->setUInt32(3, item->GetGUID().GetCounter());
trans->Append(stmt);
break;
case ITEM_REMOVED:
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_INVENTORY_BY_ITEM);
- stmt->setUInt32(0, item->GetGUIDLow());
+ stmt->setUInt32(0, item->GetGUID().GetCounter());
trans->Append(stmt);
case ITEM_UNCHANGED:
break;
@@ -19705,7 +19408,7 @@ void Player::_SaveQuestStatus(SQLTransaction& trans)
uint8 index = 0;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_CHAR_QUESTSTATUS);
- stmt->setUInt32(index++, GetGUIDLow());
+ stmt->setUInt32(index++, GetGUID().GetCounter());
stmt->setUInt32(index++, statusItr->first);
stmt->setUInt8(index++, uint8(statusItr->second.Status));
stmt->setBool(index++, statusItr->second.Explored);
@@ -19724,7 +19427,7 @@ void Player::_SaveQuestStatus(SQLTransaction& trans)
else
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_QUESTSTATUS_BY_QUEST);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
stmt->setUInt32(1, saveItr->first);
trans->Append(stmt);
}
@@ -19737,7 +19440,7 @@ void Player::_SaveQuestStatus(SQLTransaction& trans)
if (saveItr->second == QUEST_DEFAULT_SAVE_TYPE)
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_QUESTSTATUS_REWARDED);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
stmt->setUInt32(1, saveItr->first);
trans->Append(stmt);
@@ -19745,7 +19448,7 @@ void Player::_SaveQuestStatus(SQLTransaction& trans)
else if (saveItr->second == QUEST_FORCE_DELETE_SAVE_TYPE || !keepAbandoned)
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_QUESTSTATUS_REWARDED_BY_QUEST);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
stmt->setUInt32(1, saveItr->first);
trans->Append(stmt);
}
@@ -19768,7 +19471,7 @@ void Player::_SaveDailyQuestStatus(SQLTransaction& trans)
// we don't need transactions here.
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_QUESTSTATUS_DAILY);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
trans->Append(stmt);
for (uint32 quest_daily_idx = 0; quest_daily_idx < PLAYER_MAX_DAILY_QUESTS; ++quest_daily_idx)
@@ -19776,7 +19479,7 @@ void Player::_SaveDailyQuestStatus(SQLTransaction& trans)
if (GetUInt32Value(PLAYER_FIELD_DAILY_QUESTS_1+quest_daily_idx))
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_QUESTSTATUS_DAILY);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
stmt->setUInt32(1, GetUInt32Value(PLAYER_FIELD_DAILY_QUESTS_1+quest_daily_idx));
stmt->setUInt64(2, uint64(m_lastDailyQuestTime));
trans->Append(stmt);
@@ -19788,7 +19491,7 @@ void Player::_SaveDailyQuestStatus(SQLTransaction& trans)
for (DFQuestsDoneList::iterator itr = m_DFQuests.begin(); itr != m_DFQuests.end(); ++itr)
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_QUESTSTATUS_DAILY);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
stmt->setUInt32(1, (*itr));
stmt->setUInt64(2, uint64(m_lastDailyQuestTime));
trans->Append(stmt);
@@ -19803,7 +19506,7 @@ void Player::_SaveWeeklyQuestStatus(SQLTransaction& trans)
// we don't need transactions here.
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_QUESTSTATUS_WEEKLY);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
trans->Append(stmt);
for (QuestSet::const_iterator iter = m_weeklyquests.begin(); iter != m_weeklyquests.end(); ++iter)
@@ -19811,7 +19514,7 @@ void Player::_SaveWeeklyQuestStatus(SQLTransaction& trans)
uint32 questId = *iter;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_QUESTSTATUS_WEEKLY);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
stmt->setUInt32(1, questId);
trans->Append(stmt);
}
@@ -19826,7 +19529,7 @@ void Player::_SaveSeasonalQuestStatus(SQLTransaction& trans)
// we don't need transactions here.
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_QUESTSTATUS_SEASONAL);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
trans->Append(stmt);
for (SeasonalEventQuestMap::const_iterator iter = m_seasonalquests.begin(); iter != m_seasonalquests.end(); ++iter)
@@ -19838,7 +19541,7 @@ void Player::_SaveSeasonalQuestStatus(SQLTransaction& trans)
uint32 questId = *itr;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_QUESTSTATUS_SEASONAL);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
stmt->setUInt32(1, questId);
stmt->setUInt32(2, eventId);
trans->Append(stmt);
@@ -19855,7 +19558,7 @@ void Player::_SaveMonthlyQuestStatus(SQLTransaction& trans)
// we don't need transactions here.
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_QUESTSTATUS_MONTHLY);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
trans->Append(stmt);
for (QuestSet::const_iterator iter = m_monthlyquests.begin(); iter != m_monthlyquests.end(); ++iter)
@@ -19863,7 +19566,7 @@ void Player::_SaveMonthlyQuestStatus(SQLTransaction& trans)
uint32 questId = *iter;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_QUESTSTATUS_MONTHLY);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
stmt->setUInt32(1, questId);
trans->Append(stmt);
}
@@ -19886,7 +19589,7 @@ void Player::_SaveSkills(SQLTransaction& trans)
if (itr->second.uState == SKILL_DELETED)
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_SKILL_BY_SKILL);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
stmt->setUInt32(1, itr->first);
trans->Append(stmt);
@@ -19902,7 +19605,7 @@ void Player::_SaveSkills(SQLTransaction& trans)
{
case SKILL_NEW:
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_SKILLS);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
stmt->setUInt16(1, uint16(itr->first));
stmt->setUInt16(2, value);
stmt->setUInt16(3, max);
@@ -19913,7 +19616,7 @@ void Player::_SaveSkills(SQLTransaction& trans)
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_SKILLS);
stmt->setUInt16(0, value);
stmt->setUInt16(1, max);
- stmt->setUInt32(2, GetGUIDLow());
+ stmt->setUInt32(2, GetGUID().GetCounter());
stmt->setUInt16(3, uint16(itr->first));
trans->Append(stmt);
@@ -19937,7 +19640,7 @@ void Player::_SaveSpells(SQLTransaction& trans)
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_SPELL_BY_SPELL);
stmt->setUInt32(0, itr->first);
- stmt->setUInt32(1, GetGUIDLow());
+ stmt->setUInt32(1, GetGUID().GetCounter());
trans->Append(stmt);
}
@@ -19945,7 +19648,7 @@ void Player::_SaveSpells(SQLTransaction& trans)
if (!itr->second->dependent && (itr->second->state == PLAYERSPELL_NEW || itr->second->state == PLAYERSPELL_CHANGED))
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_SPELL);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
stmt->setUInt32(1, itr->first);
stmt->setBool(2, itr->second->active);
stmt->setBool(3, itr->second->disabled);
@@ -19976,13 +19679,13 @@ void Player::_SaveStats(SQLTransaction& trans)
PreparedStatement* stmt = NULL;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_STATS);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
trans->Append(stmt);
uint8 index = 0;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_STATS);
- stmt->setUInt32(index++, GetGUIDLow());
+ stmt->setUInt32(index++, GetGUID().GetCounter());
stmt->setUInt32(index++, GetMaxHealth());
for (uint8 i = 0; i < MAX_POWERS; ++i)
@@ -20224,7 +19927,7 @@ void Player::ResetInstances(uint8 method, bool isRaid)
// if the map is loaded, reset it
Map* map = sMapMgr->FindMap(p->GetMapId(), p->GetInstanceId());
if (map && map->IsDungeon())
- if (!((InstanceMap*)map)->Reset(method))
+ if (!map->ToInstanceMap()->Reset(method))
{
++itr;
continue;
@@ -20444,7 +20147,7 @@ void Player::StopCastingCharm()
if (charm->GetCharmerGUID())
{
TC_LOG_FATAL("entities.player", "Charmed unit has charmer %s", charm->GetCharmerGUID().ToString().c_str());
- ASSERT(false);
+ ABORT();
}
else
SetCharm(charm, false);
@@ -20527,7 +20230,7 @@ void Player::AddMItem(Item* it)
{
ASSERT(it);
//ASSERT deleted, because items can be added before loading
- mMitems[it->GetGUIDLow()] = it;
+ mMitems[it->GetGUID().GetCounter()] = it;
}
bool Player::RemoveMItem(uint32 id)
@@ -20645,8 +20348,7 @@ void Player::VehicleSpellInitialize()
continue;
}
- ConditionList conditions = sConditionMgr->GetConditionsForVehicleSpell(vehicle->GetEntry(), spellId);
- if (!sConditionMgr->IsObjectMeetToConditions(this, vehicle, conditions))
+ if (!sConditionMgr->IsObjectMeetingVehicleSpellConditions(vehicle->GetEntry(), spellId, this, vehicle))
{
TC_LOG_DEBUG("condition", "VehicleSpellInitialize: conditions not met for Vehicle entry %u spell %u", vehicle->ToCreature()->GetEntry(), spellId);
data << uint16(0) << uint8(0) << uint8(i+8);
@@ -20946,8 +20648,8 @@ void Player::RemovePetitionsAndSigns(ObjectGuid guid, uint32 type)
do // this part effectively does nothing, since the deletion / modification only takes place _after_ the PetitionQuery. Though I don't know if the result remains intact if I execute the delete query beforehand.
{ // and SendPetitionQueryOpcode reads data from the DB
Field* fields = result->Fetch();
- ObjectGuid ownerguid = ObjectGuid(HIGHGUID_PLAYER, fields[0].GetUInt32());
- ObjectGuid petitionguid = ObjectGuid(HIGHGUID_ITEM, fields[1].GetUInt32());
+ ObjectGuid ownerguid = ObjectGuid(HighGuid::Player, fields[0].GetUInt32());
+ ObjectGuid petitionguid = ObjectGuid(HighGuid::Item, fields[1].GetUInt32());
// send update if charter owner in game
Player* owner = ObjectAccessor::FindConnectedPlayer(ownerguid);
@@ -21162,6 +20864,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
// fill destinations path tail
uint32 sourcepath = 0;
uint32 totalcost = 0;
+ uint32 firstcost = 0;
uint32 prevnode = sourcenode;
uint32 lastnode = 0;
@@ -21180,6 +20883,8 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
}
totalcost += cost;
+ if (i == 1)
+ firstcost = cost;
if (prevnode == sourcenode)
sourcepath = path;
@@ -21218,8 +20923,6 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
}
//Checks and preparations done, DO FLIGHT
- ModifyMoney(-(int32)totalcost);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING, totalcost);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN, 1);
// prevent stealth flight
@@ -21230,11 +20933,15 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
TaxiNodesEntry const* lastPathNode = sTaxiNodesStore.LookupEntry(nodes[nodes.size()-1]);
ASSERT(lastPathNode);
m_taxi.ClearTaxiDestinations();
+ ModifyMoney(-(int32)totalcost);
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING, totalcost);
TeleportTo(lastPathNode->map_id, lastPathNode->x, lastPathNode->y, lastPathNode->z, GetOrientation());
return false;
}
else
{
+ ModifyMoney(-(int32)firstcost);
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING, firstcost);
GetSession()->SendActivateTaxiReply(ERR_TAXIOK);
GetSession()->SendDoFlight(mount_display_id, sourcepath);
}
@@ -21270,7 +20977,7 @@ void Player::ContinueTaxiFlight()
if (!sourceNode)
return;
- TC_LOG_DEBUG("entities.unit", "WORLD: Restart character %u taxi flight", GetGUIDLow());
+ TC_LOG_DEBUG("entities.unit", "WORLD: Restart character %u taxi flight", GetGUID().GetCounter());
uint32 mountDisplayId = sObjectMgr->GetTaxiMountDisplayId(sourceNode, GetTeam(), true);
if (!mountDisplayId)
@@ -21285,30 +20992,30 @@ void Player::ContinueTaxiFlight()
float distPrev = MAP_SIZE*MAP_SIZE;
float distNext =
- (nodeList[0].LocX-GetPositionX())*(nodeList[0].LocX-GetPositionX())+
- (nodeList[0].LocY-GetPositionY())*(nodeList[0].LocY-GetPositionY())+
- (nodeList[0].LocZ-GetPositionZ())*(nodeList[0].LocZ-GetPositionZ());
+ (nodeList[0]->LocX - GetPositionX())*(nodeList[0]->LocX - GetPositionX()) +
+ (nodeList[0]->LocY - GetPositionY())*(nodeList[0]->LocY - GetPositionY()) +
+ (nodeList[0]->LocZ - GetPositionZ())*(nodeList[0]->LocZ - GetPositionZ());
for (uint32 i = 1; i < nodeList.size(); ++i)
{
- TaxiPathNodeEntry const& node = nodeList[i];
- TaxiPathNodeEntry const& prevNode = nodeList[i-1];
+ TaxiPathNodeEntry const* node = nodeList[i];
+ TaxiPathNodeEntry const* prevNode = nodeList[i-1];
// skip nodes at another map
- if (node.MapID != GetMapId())
+ if (node->MapID != GetMapId())
continue;
distPrev = distNext;
distNext =
- (node.LocX-GetPositionX())*(node.LocX-GetPositionX())+
- (node.LocY-GetPositionY())*(node.LocY-GetPositionY())+
- (node.LocZ-GetPositionZ())*(node.LocZ-GetPositionZ());
+ (node->LocX - GetPositionX())*(node->LocX - GetPositionX()) +
+ (node->LocY - GetPositionY())*(node->LocY - GetPositionY()) +
+ (node->LocZ - GetPositionZ())*(node->LocZ - GetPositionZ());
float distNodes =
- (node.LocX-prevNode.LocX)*(node.LocX-prevNode.LocX)+
- (node.LocY-prevNode.LocY)*(node.LocY-prevNode.LocY)+
- (node.LocZ-prevNode.LocZ)*(node.LocZ-prevNode.LocZ);
+ (node->LocX - prevNode->LocX)*(node->LocX - prevNode->LocX) +
+ (node->LocY - prevNode->LocY)*(node->LocY - prevNode->LocY) +
+ (node->LocZ - prevNode->LocZ)*(node->LocZ - prevNode->LocZ);
if (distNext + distPrev < distNodes)
{
@@ -21372,11 +21079,11 @@ void Player::InitDisplayIds()
PlayerInfo const* info = sObjectMgr->GetPlayerInfo(getRace(), getClass());
if (!info)
{
- TC_LOG_ERROR("entities.player", "Player %u has incorrect race/class pair. Can't init display ids.", GetGUIDLow());
+ TC_LOG_ERROR("entities.player", "Player %s (%s) has incorrect race/class pair. Can't init display ids.", GetName().c_str(), GetGUID().ToString().c_str());
return;
}
- uint8 gender = getGender();
+ uint8 gender = GetByteValue(PLAYER_BYTES_3, 0);
switch (gender)
{
case GENDER_FEMALE:
@@ -21388,8 +21095,7 @@ void Player::InitDisplayIds()
SetNativeDisplayId(info->displayId_m);
break;
default:
- TC_LOG_ERROR("entities.player", "Invalid gender %u for player", gender);
- return;
+ TC_LOG_ERROR("entities.player", "Player %s (%s) has invalid gender %u", GetName().c_str(), GetGUID().ToString().c_str(), gender);
}
}
@@ -21446,7 +21152,7 @@ inline bool Player::_StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 c
if (pProto->Flags & ITEM_PROTO_FLAG_REFUNDABLE && crItem->ExtendedCost && pProto->GetMaxStackSize() == 1)
{
it->SetFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE);
- it->SetRefundRecipient(GetGUIDLow());
+ it->SetRefundRecipient(GetGUID().GetCounter());
it->SetPaidMoney(price);
it->SetPaidExtendedCost(crItem->ExtendedCost);
it->SaveRefundDataToDB();
@@ -21493,8 +21199,7 @@ bool Player::BuyItemFromVendorSlot(ObjectGuid vendorguid, uint32 vendorslot, uin
return false;
}
- ConditionList conditions = sConditionMgr->GetConditionsForNpcVendorEvent(creature->GetEntry(), item);
- if (!sConditionMgr->IsObjectMeetToConditions(this, creature, conditions))
+ if (!sConditionMgr->IsObjectMeetingVendorItemConditions(creature->GetEntry(), item, this, creature))
{
TC_LOG_DEBUG("condition", "BuyItemFromVendor: conditions not met for creature entry %u item %u", creature->GetEntry(), item);
SendBuyError(BUY_ERR_CANT_FIND_ITEM, creature, item, 0);
@@ -21680,7 +21385,7 @@ void Player::UpdateHomebindTime(uint32 time)
data << uint32(m_HomebindTimer);
data << uint32(1);
GetSession()->SendPacket(&data);
- TC_LOG_DEBUG("maps", "PLAYER: Player '%s' (GUID: %u) will be teleported to homebind in 60 seconds", GetName().c_str(), GetGUIDLow());
+ TC_LOG_DEBUG("maps", "PLAYER: Player '%s' (GUID: %u) will be teleported to homebind in 60 seconds", GetName().c_str(), GetGUID().GetCounter());
}
}
@@ -22009,6 +21714,16 @@ void Player::LeaveBattleground(bool teleportToEntryPoint)
CastSpell(this, 26013, true); // Deserter
}
}
+
+ // track if player leaves the BG while inside it
+ if (bg->isBattleground() && sWorld->getBoolConfig(CONFIG_BATTLEGROUND_TRACK_DESERTERS) &&
+ (bg->GetStatus() == STATUS_IN_PROGRESS || bg->GetStatus() == STATUS_WAIT_JOIN))
+ {
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_DESERTER_TRACK);
+ stmt->setUInt32(0, GetGUID().GetCounter());
+ stmt->setUInt8(1, BG_DESERTION_TYPE_LEAVE_BG);
+ CharacterDatabase.Execute(stmt);
+ }
}
}
@@ -22048,9 +21763,9 @@ void Player::ReportedAfkBy(Player* reporter)
return;
// check if player has 'Idle' or 'Inactive' debuff
- if (m_bgData.bgAfkReporter.find(reporter->GetGUIDLow()) == m_bgData.bgAfkReporter.end() && !HasAura(43680) && !HasAura(43681) && reporter->CanReportAfkDueToLimit())
+ if (m_bgData.bgAfkReporter.find(reporter->GetGUID().GetCounter()) == m_bgData.bgAfkReporter.end() && !HasAura(43680) && !HasAura(43681) && reporter->CanReportAfkDueToLimit())
{
- m_bgData.bgAfkReporter.insert(reporter->GetGUIDLow());
+ m_bgData.bgAfkReporter.insert(reporter->GetGUID().GetCounter());
// 3 players have to complain to apply debuff
if (m_bgData.bgAfkReporter.size() >= 3)
{
@@ -22166,7 +21881,7 @@ inline void BeforeVisibilityDestroy(T* /*t*/, Player* /*p*/) { }
template<>
inline void BeforeVisibilityDestroy<Creature>(Creature* t, Player* p)
{
- if (p->GetPetGUID() == t->GetGUID() && t->ToCreature()->IsPet())
+ if (p->GetPetGUID() == t->GetGUID() && t->IsPet())
((Pet*)t)->Remove(PET_SAVE_NOT_IN_SLOT, true);
}
@@ -22183,7 +21898,7 @@ void Player::UpdateVisibilityOf(WorldObject* target)
m_clientGUIDs.erase(target->GetGUID());
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "Object %u (Type: %u) out of range for player %u. Distance = %f", target->GetGUIDLow(), target->GetTypeId(), GetGUIDLow(), GetDistance(target));
+ TC_LOG_DEBUG("maps", "Object %u (Type: %u) out of range for player %u. Distance = %f", target->GetGUID().GetCounter(), target->GetTypeId(), GetGUID().GetCounter(), GetDistance(target));
#endif
}
}
@@ -22195,7 +21910,7 @@ void Player::UpdateVisibilityOf(WorldObject* target)
m_clientGUIDs.insert(target->GetGUID());
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "Object %u (Type: %u) is visible now for player %u. Distance = %f", target->GetGUIDLow(), target->GetTypeId(), GetGUIDLow(), GetDistance(target));
+ TC_LOG_DEBUG("maps", "Object %u (Type: %u) is visible now for player %u. Distance = %f", target->GetGUID().GetCounter(), target->GetTypeId(), GetGUID().GetCounter(), GetDistance(target));
#endif
// target aura duration for caster show only if target exist at caster client
@@ -22271,7 +21986,7 @@ void Player::UpdateVisibilityOf(T* target, UpdateData& data, std::set<Unit*>& vi
m_clientGUIDs.erase(target->GetGUID());
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "Object %u (Type: %u, Entry: %u) is out of range for player %u. Distance = %f", target->GetGUIDLow(), target->GetTypeId(), target->GetEntry(), GetGUIDLow(), GetDistance(target));
+ TC_LOG_DEBUG("maps", "Object %u (Type: %u, Entry: %u) is out of range for player %u. Distance = %f", target->GetGUID().GetCounter(), target->GetTypeId(), target->GetEntry(), GetGUID().GetCounter(), GetDistance(target));
#endif
}
}
@@ -22283,7 +21998,7 @@ void Player::UpdateVisibilityOf(T* target, UpdateData& data, std::set<Unit*>& vi
UpdateVisibilityOf_helper(m_clientGUIDs, target, visibleNow);
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "Object %u (Type: %u, Entry: %u) is visible now for player %u. Distance = %f", target->GetGUIDLow(), target->GetTypeId(), target->GetEntry(), GetGUIDLow(), GetDistance(target));
+ TC_LOG_DEBUG("maps", "Object %u (Type: %u, Entry: %u) is visible now for player %u. Distance = %f", target->GetGUID().GetCounter(), target->GetTypeId(), target->GetEntry(), GetGUID().GetCounter(), GetDistance(target));
#endif
}
}
@@ -22625,15 +22340,17 @@ void Player::SendTransferAborted(uint32 mapid, TransferAbortReason reason, uint8
GetSession()->SendPacket(&data);
}
-void Player::SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint32 time)
+void Player::SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint32 time, bool welcome)
{
// type of warning, based on the time remaining until reset
uint32 type;
- if (time > 3600)
+ if (welcome)
type = RAID_INSTANCE_WELCOME;
- else if (time > 900 && time <= 3600)
+ else if (time > 21600)
+ type = RAID_INSTANCE_WELCOME;
+ else if (time > 3600)
type = RAID_INSTANCE_WARNING_HOURS;
- else if (time > 300 && time <= 900)
+ else if (time > 300)
type = RAID_INSTANCE_WARNING_MIN;
else
type = RAID_INSTANCE_WARNING_MIN_SOON;
@@ -22661,7 +22378,7 @@ void Player::ApplyEquipCooldown(Item* pItem)
_Spell const& spellData = pItem->GetTemplate()->Spells[i];
// no spell
- if (!spellData.SpellId)
+ if (spellData.SpellId <= 0)
continue;
// wrong triggering type (note: ITEM_SPELLTRIGGER_ON_NO_DELAY_USE not have cooldown)
@@ -22669,7 +22386,7 @@ void Player::ApplyEquipCooldown(Item* pItem)
continue;
// Don't replace longer cooldowns by equip cooldown if we have any.
- if (GetSpellHistory()->GetRemainingCooldown(spellData.SpellId) > 30 * IN_MILLISECONDS)
+ if (GetSpellHistory()->GetRemainingCooldown(sSpellMgr->EnsureSpellInfo(spellData.SpellId)) > 30 * IN_MILLISECONDS)
continue;
GetSpellHistory()->AddCooldown(spellData.SpellId, pItem->GetEntry(), std::chrono::seconds(30));
@@ -22943,9 +22660,9 @@ void Player::LearnSkillRewardedSpells(uint32 skillId, uint32 skillValue)
RemoveSpell(ability->spellId);
// need learn
else if (!IsInWorld())
- AddSpell(ability->spellId, true, true, true, false, false, true);
+ AddSpell(ability->spellId, true, true, true, false, false, ability->skillId);
else
- LearnSpell(ability->spellId, true, true);
+ LearnSpell(ability->spellId, true, ability->skillId);
}
}
@@ -23278,7 +22995,7 @@ void Player::UpdateForQuestWorldObjects()
{
if (itr->IsGameObject())
{
- if (GameObject* obj = HashMapHolder<GameObject>::Find(*itr))
+ if (GameObject* obj = ObjectAccessor::GetGameObject(*this, *itr))
obj->BuildValuesUpdateBlockForPlayer(&udata, this);
}
else if (itr->IsCreatureOrVehicle())
@@ -23296,16 +23013,18 @@ void Player::UpdateForQuestWorldObjects()
{
//! This code doesn't look right, but it was logically converted to condition system to do the exact
//! same thing it did before. It definitely needs to be overlooked for intended functionality.
- ConditionList conds = sConditionMgr->GetConditionsForSpellClickEvent(obj->GetEntry(), _itr->second.spellId);
- bool buildUpdateBlock = false;
- for (ConditionList::const_iterator jtr = conds.begin(); jtr != conds.end() && !buildUpdateBlock; ++jtr)
- if ((*jtr)->ConditionType == CONDITION_QUESTREWARDED || (*jtr)->ConditionType == CONDITION_QUESTTAKEN)
- buildUpdateBlock = true;
-
- if (buildUpdateBlock)
+ if (ConditionContainer const* conds = sConditionMgr->GetConditionsForSpellClickEvent(obj->GetEntry(), _itr->second.spellId))
{
- obj->BuildValuesUpdateBlockForPlayer(&udata, this);
- break;
+ bool buildUpdateBlock = false;
+ for (ConditionContainer::const_iterator jtr = conds->begin(); jtr != conds->end() && !buildUpdateBlock; ++jtr)
+ if ((*jtr)->ConditionType == CONDITION_QUESTREWARDED || (*jtr)->ConditionType == CONDITION_QUESTTAKEN)
+ buildUpdateBlock = true;
+
+ if (buildUpdateBlock)
+ {
+ obj->BuildValuesUpdateBlockForPlayer(&udata, this);
+ break;
+ }
}
}
}
@@ -23564,8 +23283,8 @@ bool Player::isHonorOrXPTarget(Unit* victim) const
if (victim->GetTypeId() == TYPEID_UNIT)
{
- if (victim->ToCreature()->IsTotem() ||
- victim->ToCreature()->IsPet() ||
+ if (victim->IsTotem() ||
+ victim->IsPet() ||
victim->ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_NO_XP_AT_KILL)
return false;
}
@@ -23657,6 +23376,9 @@ bool Player::IsAtGroupRewardDistance(WorldObject const* pRewardSource) const
if (player->GetMapId() != pRewardSource->GetMapId() || player->GetInstanceId() != pRewardSource->GetInstanceId())
return false;
+ if (player->GetMap()->IsDungeon())
+ return true;
+
return pRewardSource->GetDistance(player) <= sWorld->getFloatConfig(CONFIG_GROUP_XP_DISTANCE);
}
@@ -24111,7 +23833,7 @@ void Player::SetViewpoint(WorldObject* target, bool apply)
// farsight dynobj or puppet may be very far away
UpdateVisibilityOf(target);
- if (target->isType(TYPEMASK_UNIT) && !GetVehicle())
+ if (target->isType(TYPEMASK_UNIT) && target != GetVehicleBase())
((Unit*)target)->AddPlayerToVision(this);
}
else
@@ -24124,7 +23846,7 @@ void Player::SetViewpoint(WorldObject* target, bool apply)
return;
}
- if (target->isType(TYPEMASK_UNIT) && !GetVehicle())
+ if (target->isType(TYPEMASK_UNIT) && target != GetVehicleBase())
((Unit*)target)->RemovePlayerFromVision(this);
//must immediately set seer back otherwise may crash
@@ -24649,7 +24371,7 @@ void Player::_LoadSkills(PreparedQueryResult result)
if (!rcEntry)
{
TC_LOG_ERROR("entities.player", "Character: %s (GUID: %u Race: %u Class: %u) has skill %u not allowed for his race/class combination",
- GetName().c_str(), GetGUIDLow(), uint32(getRace()), uint32(getClass()), skill);
+ GetName().c_str(), GetGUID().GetCounter(), uint32(getRace()), uint32(getClass()), skill);
mSkillStatus.insert(SkillStatusMap::value_type(skill, SkillStatusData(0, SKILL_DELETED)));
continue;
@@ -24672,11 +24394,11 @@ void Player::_LoadSkills(PreparedQueryResult result)
if (value == 0)
{
- TC_LOG_ERROR("entities.player", "Character %u has skill %u with value 0. Will be deleted.", GetGUIDLow(), skill);
+ TC_LOG_ERROR("entities.player", "Character %u has skill %u with value 0. Will be deleted.", GetGUID().GetCounter(), skill);
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_SKILL);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
stmt->setUInt16(1, skill);
CharacterDatabase.Execute(stmt);
@@ -24709,7 +24431,7 @@ void Player::_LoadSkills(PreparedQueryResult result)
if (count >= PLAYER_MAX_SKILLS) // client limit
{
- TC_LOG_ERROR("entities.player", "Character %u has more than %u skills.", GetGUIDLow(), PLAYER_MAX_SKILLS);
+ TC_LOG_ERROR("entities.player", "Character %u has more than %u skills.", GetGUID().GetCounter(), PLAYER_MAX_SKILLS);
break;
}
}
@@ -25227,9 +24949,7 @@ bool Player::CanSeeSpellClickOn(Creature const* c) const
if (!itr->second.IsFitToRequirements(this, c))
return false;
- ConditionList conds = sConditionMgr->GetConditionsForSpellClickEvent(c->GetEntry(), itr->second.spellId);
- ConditionSourceInfo info = ConditionSourceInfo(const_cast<Player*>(this), const_cast<Creature*>(c));
- if (sConditionMgr->IsObjectMeetToConditions(info, conds))
+ if (sConditionMgr->IsObjectMeetingSpellClickConditions(c->GetEntry(), itr->second.spellId, const_cast<Player*>(this), const_cast<Creature*>(c)))
return true;
}
@@ -25445,11 +25165,11 @@ void Player::SendEquipmentSetList()
data << itr->second.IconName;
for (uint32 i = 0; i < EQUIPMENT_SLOT_END; ++i)
{
- // ignored slots stored in IgnoreMask, client wants "1" as raw GUID, so no HIGHGUID_ITEM
+ // ignored slots stored in IgnoreMask, client wants "1" as raw GUID, so no HighGuid::Item
if (itr->second.IgnoreMask & (1 << i))
data.appendPackGUID(uint64(1));
else
- data << ObjectGuid(HIGHGUID_ITEM, 0, itr->second.Items[i]).WriteAsPacked();
+ data << ObjectGuid(HighGuid::Item, 0, itr->second.Items[i]).WriteAsPacked();
}
++count; // client have limit but it checked at loading and set
@@ -25519,7 +25239,7 @@ void Player::_SaveEquipmentSets(SQLTransaction& trans)
stmt->setUInt32(j++, eqset.IgnoreMask);
for (uint8 i=0; i<EQUIPMENT_SLOT_END; ++i)
stmt->setUInt32(j++, eqset.Items[i]);
- stmt->setUInt32(j++, GetGUIDLow());
+ stmt->setUInt32(j++, GetGUID().GetCounter());
stmt->setUInt64(j++, eqset.Guid);
stmt->setUInt32(j, index);
trans->Append(stmt);
@@ -25528,7 +25248,7 @@ void Player::_SaveEquipmentSets(SQLTransaction& trans)
break;
case EQUIPMENT_SET_NEW:
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_EQUIP_SET);
- stmt->setUInt32(j++, GetGUIDLow());
+ stmt->setUInt32(j++, GetGUID().GetCounter());
stmt->setUInt64(j++, eqset.Guid);
stmt->setUInt32(j++, index);
stmt->setString(j++, eqset.Name.c_str());
@@ -25553,11 +25273,11 @@ void Player::_SaveEquipmentSets(SQLTransaction& trans)
void Player::_SaveBGData(SQLTransaction& trans)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_BGDATA);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
trans->Append(stmt);
/* guid, bgInstanceID, bgTeam, x, y, z, o, map, taxi[0], taxi[1], mountSpell */
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PLAYER_BGDATA);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
stmt->setUInt32(1, m_bgData.bgInstanceID);
stmt->setUInt16(2, m_bgData.bgTeam);
stmt->setFloat (3, m_bgData.joinPos.GetPositionX());
@@ -25595,7 +25315,7 @@ void Player::RemoveAtLoginFlag(AtLoginFlags flags, bool persist /*= false*/)
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_REM_AT_LOGIN_FLAG);
stmt->setUInt16(0, uint16(flags));
- stmt->setUInt32(1, GetGUIDLow());
+ stmt->setUInt32(1, GetGUID().GetCounter());
CharacterDatabase.Execute(stmt);
}
@@ -25621,7 +25341,7 @@ void Player::SetMap(Map* map)
void Player::_LoadGlyphs(PreparedQueryResult result)
{
- // SELECT spec, glyph1, glyph2, glyph3, glyph4, glyph5, glyph6 from character_glyphs WHERE guid = '%u'
+ // SELECT talentGroup, glyph1, glyph2, glyph3, glyph4, glyph5, glyph6 from character_glyphs WHERE guid = '%u'
if (!result)
return;
@@ -25646,7 +25366,7 @@ void Player::_LoadGlyphs(PreparedQueryResult result)
void Player::_SaveGlyphs(SQLTransaction& trans)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_GLYPHS);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
trans->Append(stmt);
@@ -25655,7 +25375,7 @@ void Player::_SaveGlyphs(SQLTransaction& trans)
uint8 index = 0;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_GLYPHS);
- stmt->setUInt32(index++, GetGUIDLow());
+ stmt->setUInt32(index++, GetGUID().GetCounter());
stmt->setUInt8(index++, spec);
@@ -25668,7 +25388,7 @@ void Player::_SaveGlyphs(SQLTransaction& trans)
void Player::_LoadTalents(PreparedQueryResult result)
{
- // SetPQuery(PLAYER_LOGIN_QUERY_LOADTALENTS, "SELECT spell, spec FROM character_talent WHERE guid = '%u'", GUID_LOPART(m_guid));
+ // SetPQuery(PLAYER_LOGIN_QUERY_LOADTALENTS, "SELECT spell, talentGroup FROM character_talent WHERE guid = '%u'", GUID_LOPART(m_guid));
if (result)
{
do
@@ -25688,7 +25408,7 @@ void Player::_SaveTalents(SQLTransaction& trans)
if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->state == PLAYERSPELL_CHANGED)
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_TALENT_BY_SPELL_SPEC);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
stmt->setUInt32(1, itr->first);
stmt->setUInt8(2, itr->second->spec);
trans->Append(stmt);
@@ -25697,7 +25417,7 @@ void Player::_SaveTalents(SQLTransaction& trans)
if (itr->second->state == PLAYERSPELL_NEW || itr->second->state == PLAYERSPELL_CHANGED)
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_TALENT);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
stmt->setUInt32(1, itr->first);
stmt->setUInt8(2, itr->second->spec);
trans->Append(stmt);
@@ -25736,7 +25456,7 @@ void Player::UpdateSpecCount(uint8 count)
for (ActionButtonList::iterator itr = m_actionButtons.begin(); itr != m_actionButtons.end(); ++itr)
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_ACTION);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
stmt->setUInt8(1, 1);
stmt->setUInt8(2, itr->first);
stmt->setUInt32(3, itr->second.GetAction());
@@ -25751,7 +25471,7 @@ void Player::UpdateSpecCount(uint8 count)
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACTION_EXCEPT_SPEC);
stmt->setUInt8(0, m_activeSpec);
- stmt->setUInt32(1, GetGUIDLow());
+ stmt->setUInt32(1, GetGUID().GetCounter());
trans->Append(stmt);
m_activeSpec = 0;
@@ -25892,7 +25612,7 @@ void Player::ActivateSpec(uint8 spec)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_ACTIONS_SPEC);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
stmt->setUInt8(1, m_activeSpec);
if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
_LoadActions(result);
@@ -25970,7 +25690,7 @@ void Player::SendRefundInfo(Item* item)
return;
}
- if (GetGUIDLow() != item->GetRefundRecipient()) // Formerly refundable item got traded
+ if (GetGUID().GetCounter() != item->GetRefundRecipient()) // Formerly refundable item got traded
{
TC_LOG_DEBUG("entities.player.items", "Item refund: item was traded!");
item->SetNotRefundable(this);
@@ -26040,7 +25760,7 @@ void Player::RefundItem(Item* item)
return;
}
- if (GetGUIDLow() != item->GetRefundRecipient()) // Formerly refundable item got traded
+ if (GetGUID().GetCounter() != item->GetRefundRecipient()) // Formerly refundable item got traded
{
TC_LOG_DEBUG("entities.player.items", "Item refund: item was traded!");
item->SetNotRefundable(this);
@@ -26149,7 +25869,7 @@ void Player::SendItemRetrievalMail(uint32 itemEntry, uint32 count)
draft.AddItem(item);
}
- draft.SendMailTo(trans, MailReceiver(this, GetGUIDLow()), sender);
+ draft.SendMailTo(trans, MailReceiver(this, GetGUID().GetCounter()), sender);
CharacterDatabase.CommitTransaction(trans);
}
@@ -26160,7 +25880,7 @@ void Player::SetRandomWinner(bool isWinner)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_BATTLEGROUND_RANDOM);
- stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(0, GetGUID().GetCounter());
CharacterDatabase.Execute(stmt);
}
@@ -26168,7 +25888,7 @@ void Player::SetRandomWinner(bool isWinner)
void Player::_LoadRandomBGStatus(PreparedQueryResult result)
{
- //QueryResult result = CharacterDatabase.PQuery("SELECT guid FROM character_battleground_random WHERE guid = '%u'", GetGUIDLow());
+ //QueryResult result = CharacterDatabase.PQuery("SELECT guid FROM character_battleground_random WHERE guid = '%u'", GetGUID().GetCounter());
if (result)
m_IsBGRandomWinner = true;
@@ -26418,14 +26138,14 @@ Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetTy
pet->Relocate(x, y, z, ang);
if (!pet->IsPositionValid())
{
- TC_LOG_ERROR("misc", "Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)", pet->GetGUIDLow(), pet->GetEntry(), pet->GetPositionX(), pet->GetPositionY());
+ TC_LOG_ERROR("misc", "Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)", pet->GetGUID().GetCounter(), pet->GetEntry(), pet->GetPositionX(), pet->GetPositionY());
delete pet;
return NULL;
}
Map* map = GetMap();
uint32 pet_number = sObjectMgr->GeneratePetNumber();
- if (!pet->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_PET), map, GetPhaseMask(), entry, pet_number))
+ if (!pet->Create(map->GenerateLowGuid<HighGuid::Pet>(), map, GetPhaseMask(), entry, pet_number))
{
TC_LOG_ERROR("misc", "no such creature entry %u", entry);
delete pet;
@@ -26557,3 +26277,30 @@ bool Player::ValidateAppearance(uint8 race, uint8 class_, uint8 gender, uint8 ha
return true;
}
+
+void Player::SetRestFlag(RestFlag restFlag, uint32 triggerId /*= 0*/)
+{
+ uint32 oldRestMask = _restFlagMask;
+ _restFlagMask |= restFlag;
+
+ if (!oldRestMask && _restFlagMask) // only set flag/time on the first rest state
+ {
+ _restTime = time(nullptr);
+ SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
+ }
+
+ if (triggerId)
+ inn_triggerId = triggerId;
+}
+
+void Player::RemoveRestFlag(RestFlag restFlag)
+{
+ uint32 oldRestMask = _restFlagMask;
+ _restFlagMask &= ~restFlag;
+
+ if (oldRestMask && !_restFlagMask) // only remove flag/time on the last rest state remove
+ {
+ _restTime = 0;
+ RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
+ }
+}
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 98b9d8a3d07..26944de9770 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -27,7 +27,9 @@
#include "PetDefines.h"
#include "QuestDef.h"
#include "SpellMgr.h"
+#include "SpellHistory.h"
#include "Unit.h"
+#include "TradeData.h"
#include <limits>
#include <string>
@@ -503,15 +505,16 @@ enum PlayerExtraFlags
// 2^n values
enum AtLoginFlags
{
- AT_LOGIN_NONE = 0x00,
- AT_LOGIN_RENAME = 0x01,
- AT_LOGIN_RESET_SPELLS = 0x02,
- AT_LOGIN_RESET_TALENTS = 0x04,
- AT_LOGIN_CUSTOMIZE = 0x08,
- AT_LOGIN_RESET_PET_TALENTS = 0x10,
- AT_LOGIN_FIRST = 0x20,
- AT_LOGIN_CHANGE_FACTION = 0x40,
- AT_LOGIN_CHANGE_RACE = 0x80
+ AT_LOGIN_NONE = 0x000,
+ AT_LOGIN_RENAME = 0x001,
+ AT_LOGIN_RESET_SPELLS = 0x002,
+ AT_LOGIN_RESET_TALENTS = 0x004,
+ AT_LOGIN_CUSTOMIZE = 0x008,
+ AT_LOGIN_RESET_PET_TALENTS = 0x010,
+ AT_LOGIN_FIRST = 0x020,
+ AT_LOGIN_CHANGE_FACTION = 0x040,
+ AT_LOGIN_CHANGE_RACE = 0x080,
+ AT_LOGIN_RESURRECT = 0x100,
};
typedef std::map<uint32, QuestStatusData> QuestStatusMap;
@@ -685,14 +688,6 @@ struct ItemPosCount
};
typedef std::vector<ItemPosCount> ItemPosCountVec;
-enum TradeSlots
-{
- TRADE_SLOT_COUNT = 7,
- TRADE_SLOT_TRADED_COUNT = 6,
- TRADE_SLOT_NONTRADED = 6,
- TRADE_SLOT_INVALID = -1
-};
-
enum TransferAbortReason
{
TRANSFER_ABORT_NONE = 0x00,
@@ -737,12 +732,11 @@ enum ArenaTeamInfoType
class InstanceSave;
-enum RestType
+enum RestFlag
{
- REST_TYPE_NO = 0,
- REST_TYPE_IN_TAVERN = 1,
- REST_TYPE_IN_CITY = 2,
- REST_TYPE_IN_FACTION_AREA = 3 // used with AREA_FLAG_REST_ZONE_*
+ REST_FLAG_IN_TAVERN = 0x1,
+ REST_FLAG_IN_CITY = 0x2,
+ REST_FLAG_IN_FACTION_AREA = 0x4, // used with AREA_FLAG_REST_ZONE_*
};
enum TeleportToOptions
@@ -820,6 +814,7 @@ enum PlayerLoginQueryIndex
PLAYER_LOGIN_QUERY_LOAD_INSTANCE_LOCK_TIMES = 30,
PLAYER_LOGIN_QUERY_LOAD_SEASONAL_QUEST_STATUS = 31,
PLAYER_LOGIN_QUERY_LOAD_MONTHLY_QUEST_STATUS = 32,
+ PLAYER_LOGIN_QUERY_LOAD_CORPSE_LOCATION = 33,
MAX_PLAYER_LOGIN_QUERY
};
@@ -953,6 +948,8 @@ class PlayerTaxi
m_TaxiDestinations.pop_front();
return GetTaxiDestination();
}
+
+ std::deque<uint32> const& GetPath() const { return m_TaxiDestinations; }
bool empty() const { return m_TaxiDestinations.empty(); }
friend std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi);
@@ -1003,88 +1000,6 @@ struct TradeStatusInfo
uint8 Slot;
};
-class TradeData
-{
- public: // constructors
- TradeData(Player* player, Player* trader) :
- m_player(player), m_trader(trader), m_accepted(false), m_acceptProccess(false),
- m_money(0), m_spell(0), m_spellCastItem() { }
-
- Player* GetTrader() const { return m_trader; }
- TradeData* GetTraderData() const;
-
- Item* GetItem(TradeSlots slot) const;
- bool HasItem(ObjectGuid itemGuid) const;
- TradeSlots GetTradeSlotForItem(ObjectGuid itemGuid) const;
- void SetItem(TradeSlots slot, Item* item);
-
- uint32 GetSpell() const { return m_spell; }
- void SetSpell(uint32 spell_id, Item* castItem = NULL);
-
- Item* GetSpellCastItem() const;
- bool HasSpellCastItem() const { return !m_spellCastItem.IsEmpty(); }
-
- uint32 GetMoney() const { return m_money; }
- void SetMoney(uint32 money);
-
- bool IsAccepted() const { return m_accepted; }
- void SetAccepted(bool state, bool crosssend = false);
-
- bool IsInAcceptProcess() const { return m_acceptProccess; }
- void SetInAcceptProcess(bool state) { m_acceptProccess = state; }
-
- private: // internal functions
-
- void Update(bool for_trader = true);
-
- private: // fields
-
- Player* m_player; // Player who own of this TradeData
- Player* m_trader; // Player who trade with m_player
-
- bool m_accepted; // m_player press accept for trade list
- bool m_acceptProccess; // one from player/trader press accept and this processed
-
- uint32 m_money; // m_player place money to trade
-
- uint32 m_spell; // m_player apply spell to non-traded slot item
- ObjectGuid m_spellCastItem; // applied spell cast by item use
-
- ObjectGuid m_items[TRADE_SLOT_COUNT]; // traded items from m_player side including non-traded slot
-};
-
-class KillRewarder
-{
-public:
- KillRewarder(Player* killer, Unit* victim, bool isBattleGround);
-
- void Reward();
-
-private:
- void _InitXP(Player* player);
- void _InitGroupData();
-
- void _RewardHonor(Player* player);
- void _RewardXP(Player* player, float rate);
- void _RewardReputation(Player* player, float rate);
- void _RewardKillCredit(Player* player);
- void _RewardPlayer(Player* player, bool isDungeon);
- void _RewardGroup();
-
- Player* _killer;
- Unit* _victim;
- Group* _group;
- float _groupRate;
- Player* _maxNotGrayMember;
- uint32 _count;
- uint32 _sumLevel;
- uint32 _xp;
- bool _isFullXP;
- uint8 _maxLevel;
- bool _isBattleGround;
- bool _isPvP;
-};
-
class Player : public Unit, public GridObject<Player>
{
friend class WorldSession;
@@ -1113,23 +1028,26 @@ class Player : public Unit, public GridObject<Player>
void SetSummonPoint(uint32 mapid, float x, float y, float z);
void SummonIfPossible(bool agree);
- bool Create(uint32 guidlow, CharacterCreateInfo* createInfo);
+ bool Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo);
void Update(uint32 time) override;
static bool BuildEnumData(PreparedQueryResult result, WorldPacket* data);
+ bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const override;
+
void SetInWater(bool apply);
bool IsInWater() const override { return m_isInWater; }
bool IsUnderWater() const override;
bool IsFalling() { return GetPositionZ() < m_lastFallZ; }
+ bool IsInAreaTriggerRadius(const AreaTriggerEntry* trigger) const;
void SendInitialPacketsBeforeAddToMap();
void SendInitialPacketsAfterAddToMap();
void SendSupercededSpell(uint32 oldSpell, uint32 newSpell);
void SendTransferAborted(uint32 mapid, TransferAbortReason reason, uint8 arg = 0);
- void SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint32 time);
+ void SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint32 time, bool welcome);
bool CanInteractWithQuestGiver(Object* questGiver);
Creature* GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask);
@@ -1156,6 +1074,7 @@ class Player : public Unit, public GridObject<Player>
bool isAcceptWhispers() const { return (m_ExtraFlags & PLAYER_EXTRA_ACCEPT_WHISPERS) != 0; }
void SetAcceptWhispers(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_ACCEPT_WHISPERS; else m_ExtraFlags &= ~PLAYER_EXTRA_ACCEPT_WHISPERS; }
bool IsGameMaster() const { return (m_ExtraFlags & PLAYER_EXTRA_GM_ON) != 0; }
+ bool CanBeGameMaster() const;
void SetGameMaster(bool on);
bool isGMChat() const { return (m_ExtraFlags & PLAYER_EXTRA_GM_CHAT) != 0; }
void SetGMChat(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_GM_CHAT; else m_ExtraFlags &= ~PLAYER_EXTRA_GM_CHAT; }
@@ -1181,26 +1100,20 @@ class Player : public Unit, public GridObject<Player>
time_t m_logintime;
time_t m_Last_tick;
uint32 m_Played_time[MAX_PLAYED_TIME_INDEX];
- uint32 GetTotalPlayedTime() { return m_Played_time[PLAYED_TIME_TOTAL]; }
- uint32 GetLevelPlayedTime() { return m_Played_time[PLAYED_TIME_LEVEL]; }
+ uint32 GetTotalPlayedTime() const { return m_Played_time[PLAYED_TIME_TOTAL]; }
+ uint32 GetLevelPlayedTime() const { return m_Played_time[PLAYED_TIME_LEVEL]; }
void setDeathState(DeathState s) override; // overwrite Unit::setDeathState
- void InnEnter(time_t time, uint32 mapid, float x, float y, float z);
-
float GetRestBonus() const { return m_rest_bonus; }
void SetRestBonus(float rest_bonus_new);
- RestType GetRestType() const { return rest_type; }
- void SetRestType(RestType n_r_type) { rest_type = n_r_type; }
-
- uint32 GetInnPosMapId() const { return inn_pos_mapid; }
- float GetInnPosX() const { return inn_pos_x; }
- float GetInnPosY() const { return inn_pos_y; }
- float GetInnPosZ() const { return inn_pos_z; }
+ bool HasRestFlag(RestFlag restFlag) const { return (_restFlagMask & restFlag) != 0; }
+ void SetRestFlag(RestFlag restFlag, uint32 triggerId = 0);
+ void RemoveRestFlag(RestFlag restFlag);
- time_t GetTimeInnEnter() const { return time_inn_enter; }
- void UpdateInnerTime (time_t time) { time_inn_enter = time; }
+ uint32 GetXPRestBonus(uint32 xp);
+ uint32 GetInnTriggerId() const { return inn_triggerId; }
Pet* GetPet() const;
Pet* SummonPet(uint32 entry, float x, float y, float z, float ang, PetType petType, uint32 despwtime);
@@ -1326,7 +1239,7 @@ class Player : public Unit, public GridObject<Player>
float GetReputationPriceDiscount(Creature const* creature) const;
- Player* GetTrader() const { return m_trade ? m_trade->GetTrader() : NULL; }
+ Player* GetTrader() const { return m_trade ? m_trade->GetTrader() : nullptr; }
TradeData* GetTradeData() const { return m_trade; }
void TradeCancel(bool sendback);
@@ -1347,7 +1260,7 @@ class Player : public Unit, public GridObject<Player>
void AddItemDurations(Item* item);
void RemoveItemDurations(Item* item);
void SendItemDurations();
- void LoadCorpse();
+ void LoadCorpse(PreparedQueryResult result);
void LoadPet();
bool AddItem(uint32 itemId, uint32 count);
@@ -1484,7 +1397,7 @@ class Player : public Unit, public GridObject<Player>
bool LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder);
bool IsLoading() const override;
- void Initialize(uint32 guid);
+ void Initialize(ObjectGuid::LowType guid);
static uint32 GetUInt32ValueFromArray(Tokenizer const& data, uint16 index);
static float GetFloatValueFromArray(Tokenizer const& data, uint16 index);
static uint32 GetZoneIdFromDB(ObjectGuid guid);
@@ -1550,7 +1463,7 @@ class Player : public Unit, public GridObject<Player>
void ClearComboPoints();
void SendComboPoints();
- void SendMailResult(uint32 mailId, MailResponseType mailAction, MailResponseResult mailError, uint32 equipError = 0, uint32 item_guid = 0, uint32 item_count = 0);
+ void SendMailResult(uint32 mailId, MailResponseType mailAction, MailResponseResult mailError, uint32 equipError = 0, ObjectGuid::LowType item_guid = 0, uint32 item_count = 0);
void SendNewMail();
void UpdateNextMailTimeAndUnreads();
void AddNewMailDeliverTime(time_t deliver_time);
@@ -1596,8 +1509,8 @@ class Player : public Unit, public GridObject<Player>
void SendProficiency(ItemClass itemClass, uint32 itemSubclassMask);
void SendInitialSpells();
- bool AddSpell(uint32 spellId, bool active, bool learning, bool dependent, bool disabled, bool loading = false, bool fromSkill = false);
- void LearnSpell(uint32 spell_id, bool dependent, bool fromSkill = false);
+ bool AddSpell(uint32 spellId, bool active, bool learning, bool dependent, bool disabled, bool loading = false, uint32 fromSkill = 0);
+ void LearnSpell(uint32 spell_id, bool dependent, uint32 fromSkill = 0);
void RemoveSpell(uint32 spell_id, bool disabled = false, bool learn_low_rank = true);
void ResetSpells(bool myClassOnly = false);
void LearnCustomSpells();
@@ -1629,9 +1542,9 @@ class Player : public Unit, public GridObject<Player>
// Dual Spec
void UpdateSpecCount(uint8 count);
- uint32 GetActiveSpec() { return m_activeSpec; }
+ uint32 GetActiveSpec() const { return m_activeSpec; }
void SetActiveSpec(uint8 spec){ m_activeSpec = spec; }
- uint8 GetSpecsCount() { return m_specsCount; }
+ uint8 GetSpecsCount() const { return m_specsCount; }
void SetSpecsCount(uint8 count) { m_specsCount = count; }
void ActivateSpec(uint8 spec);
@@ -1658,7 +1571,7 @@ class Player : public Unit, public GridObject<Player>
void SetSpellModTakingSpell(Spell* spell, bool apply);
void RemoveArenaSpellCooldowns(bool removeActivePetCooldowns = false);
- uint32 GetLastPotionId() { return m_lastPotionId; }
+ uint32 GetLastPotionId() const { return m_lastPotionId; }
void SetLastPotionId(uint32 item_id) { m_lastPotionId = item_id; }
void UpdatePotionCooldown(Spell* spell = NULL);
@@ -1716,9 +1629,9 @@ class Player : public Unit, public GridObject<Player>
void SetGuildIdInvited(uint32 GuildId) { m_GuildIdInvited = GuildId; }
uint32 GetGuildId() const { return GetUInt32Value(PLAYER_GUILDID); }
Guild* GetGuild();
- static uint32 GetGuildIdFromDB(ObjectGuid guid);
+ static ObjectGuid::LowType GetGuildIdFromDB(ObjectGuid guid);
static uint8 GetRankFromDB(ObjectGuid guid);
- int GetGuildIdInvited() { return m_GuildIdInvited; }
+ int GetGuildIdInvited() const { return m_GuildIdInvited; }
static void RemovePetitionsAndSigns(ObjectGuid guid, uint32 type);
// Arena Team
@@ -1729,7 +1642,7 @@ class Player : public Unit, public GridObject<Player>
uint32 GetArenaTeamId(uint8 slot) const { return GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + ARENA_TEAM_ID); }
uint32 GetArenaPersonalRating(uint8 slot) const { return GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + ARENA_TEAM_PERSONAL_RATING); }
void SetArenaTeamIdInvited(uint32 ArenaTeamId) { m_ArenaTeamIdInvited = ArenaTeamId; }
- uint32 GetArenaTeamIdInvited() { return m_ArenaTeamIdInvited; }
+ uint32 GetArenaTeamIdInvited() const { return m_ArenaTeamIdInvited; }
Difficulty GetDifficulty(bool isRaid) const { return isRaid ? m_raidDifficulty : m_dungeonDifficulty; }
Difficulty GetDungeonDifficulty() const { return m_dungeonDifficulty; }
@@ -1839,17 +1752,20 @@ class Player : public Unit, public GridObject<Player>
bool UpdatePosition(const Position &pos, bool teleport = false) { return UpdatePosition(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), teleport); }
void UpdateUnderwaterState(Map* m, float x, float y, float z) override;
- void SendMessageToSet(WorldPacket* data, bool self) override {SendMessageToSetInRange(data, GetVisibilityRange(), self); }// overwrite Object::SendMessageToSet
- void SendMessageToSetInRange(WorldPacket* data, float fist, bool self) override;// overwrite Object::SendMessageToSetInRange
+ void SendMessageToSet(WorldPacket* data, bool self) override { SendMessageToSetInRange(data, GetVisibilityRange(), self); }
+ void SendMessageToSetInRange(WorldPacket* data, float dist, bool self) override;
void SendMessageToSetInRange(WorldPacket* data, float dist, bool self, bool own_team_only);
void SendMessageToSet(WorldPacket* data, Player const* skipped_rcvr) override;
void SendTeleportAckPacket();
Corpse* GetCorpse() const;
- void SpawnCorpseBones();
- void CreateCorpse();
+ void SpawnCorpseBones(bool triggerSave = true);
+ Corpse* CreateCorpse();
void KillPlayer();
+ static void OfflineResurrect(ObjectGuid const& guid, SQLTransaction& trans);
+ bool HasCorpse() const { return _corpseLocation.GetMapId() != MAPID_INVALID; }
+ WorldLocation GetCorpseLocation() const { return _corpseLocation; }
uint32 GetResurrectionSpellId();
void ResurrectPlayer(float restore_percent, bool applySickness = false);
void BuildPlayerRepop();
@@ -1881,7 +1797,7 @@ class Player : public Unit, public GridObject<Player>
void UpdateWeaponSkill (WeaponAttackType attType);
void UpdateCombatSkills(Unit* victim, WeaponAttackType attType, bool defence);
- void SetSkill(uint16 id, uint16 step, uint16 currVal, uint16 maxVal);
+ void SetSkill(uint16 id, uint16 step, uint16 newVal, uint16 maxVal);
uint16 GetMaxSkillValue(uint32 skill) const; // max + perm. bonus + temp bonus
uint16 GetPureMaxSkillValue(uint32 skill) const; // max
uint16 GetSkillValue(uint32 skill) const; // skill value + perm. bonus + temp bonus
@@ -1917,7 +1833,7 @@ class Player : public Unit, public GridObject<Player>
bool isHonorOrXPTarget(Unit* victim) const;
bool GetsRecruitAFriendBonus(bool forXP);
- uint8 GetGrantableLevels() { return m_grantableLevels; }
+ uint8 GetGrantableLevels() const { return m_grantableLevels; }
void SetGrantableLevels(uint8 val) { m_grantableLevels = val; }
ReputationMgr& GetReputationMgr() { return *m_reputationMgr; }
@@ -1945,6 +1861,12 @@ class Player : public Unit, public GridObject<Player>
void SetHonorPoints(uint32 value);
void SetArenaPoints(uint32 value);
+ // duel health and mana reset methods
+ void SaveHealthBeforeDuel() { healthBeforeDuel = GetHealth(); }
+ void SaveManaBeforeDuel() { manaBeforeDuel = GetPower(POWER_MANA); }
+ void RestoreHealthAfterDuel() { SetHealth(healthBeforeDuel); }
+ void RestoreManaAfterDuel() { SetPower(POWER_MANA, manaBeforeDuel); }
+
//End of PvP System
void SetDrunkValue(uint8 newDrunkValue, uint32 itemId = 0);
@@ -2062,7 +1984,7 @@ class Player : public Unit, public GridObject<Player>
bool isTotalImmune();
bool CanCaptureTowerPoint();
- bool GetRandomWinner() { return m_IsBGRandomWinner; }
+ bool GetRandomWinner() const { return m_IsBGRandomWinner; }
void SetRandomWinner(bool isWinner);
/*********************************************************/
@@ -2074,15 +1996,6 @@ class Player : public Unit, public GridObject<Player>
bool IsOutdoorPvPActive();
/*********************************************************/
- /*** REST SYSTEM ***/
- /*********************************************************/
-
- bool isRested() const { return GetRestTime() >= 10*IN_MILLISECONDS; }
- uint32 GetXPRestBonus(uint32 xp);
- uint32 GetRestTime() const { return m_restTime;}
- void SetRestTime(uint32 v) { m_restTime = v;}
-
- /*********************************************************/
/*** ENVIROMENTAL SYSTEM ***/
/*********************************************************/
@@ -2205,7 +2118,7 @@ class Player : public Unit, public GridObject<Player>
void SendSavedInstances();
static void ConvertInstancesToGroup(Player* player, Group* group, bool switchLeader);
bool Satisfy(AccessRequirement const* ar, uint32 target_map, bool report = false);
- bool CheckInstanceLoginValid();
+ bool CheckInstanceLoginValid(Map* map);
bool CheckInstanceCount(uint32 instanceId) const;
void AddInstanceEnterTime(uint32 instanceId, time_t enterTime);
@@ -2257,7 +2170,7 @@ class Player : public Unit, public GridObject<Player>
uint32 GetRuneCooldown(uint8 index) const { return m_runes->runes[index].Cooldown; }
uint32 GetRuneBaseCooldown(uint8 index);
bool IsBaseRuneSlotsOnCooldown(RuneType runeType) const;
- RuneType GetLastUsedRune() { return m_runes->lastUsedRune; }
+ RuneType GetLastUsedRune() const { return m_runes->lastUsedRune; }
void SetLastUsedRune(RuneType type) { m_runes->lastUsedRune = type; }
void SetBaseRune(uint8 index, RuneType baseRune) { m_runes->runes[index].BaseRune = baseRune; }
void SetCurrentRune(uint8 index, RuneType currentRune) { m_runes->runes[index].CurrentRune = currentRune; }
@@ -2377,7 +2290,6 @@ class Player : public Unit, public GridObject<Player>
void _LoadGroup(PreparedQueryResult result);
void _LoadSkills(PreparedQueryResult result);
void _LoadSpells(PreparedQueryResult result);
- void _LoadFriendList(PreparedQueryResult result);
bool _LoadHomeBind(PreparedQueryResult result);
void _LoadDeclinedNames(PreparedQueryResult result);
void _LoadArenaTeamInfo(PreparedQueryResult result);
@@ -2482,7 +2394,7 @@ class Player : public Unit, public GridObject<Player>
EnchantDurationList m_enchantDuration;
ItemDurationList m_itemDuration;
- ItemDurationList m_itemSoulboundTradeable;
+ GuidUnorderedSet m_itemSoulboundTradeable;
void ResetTimeSync();
void SendTimeSync();
@@ -2517,8 +2429,6 @@ class Player : public Unit, public GridObject<Player>
uint32 m_deathTimer;
time_t m_deathExpireTime;
- uint32 m_restTime;
-
uint32 m_WeaponProficiency;
uint32 m_ArmorProficiency;
bool m_canParry;
@@ -2528,13 +2438,10 @@ class Player : public Unit, public GridObject<Player>
float m_ammoDPS;
////////////////////Rest System/////////////////////
- time_t time_inn_enter;
- uint32 inn_pos_mapid;
- float inn_pos_x;
- float inn_pos_y;
- float inn_pos_z;
+ time_t _restTime;
+ uint32 inn_triggerId;
float m_rest_bonus;
- RestType rest_type;
+ uint32 _restFlagMask;
////////////////////Rest System/////////////////////
uint32 m_resetTalentsCost;
time_t m_resetTalentsTime;
@@ -2596,6 +2503,8 @@ class Player : public Unit, public GridObject<Player>
bool IsHasDelayedTeleport() const { return m_bHasDelayedTeleport; }
void SetDelayedTeleportFlag(bool setting) { m_bHasDelayedTeleport = setting; }
void ScheduleDelayedOperation(uint32 operation) { if (operation < DELAYED_END) m_DelayedOperations |= operation; }
+
+ bool IsInstanceLoginGameMasterException() const;
MapReference m_mapRef;
@@ -2642,6 +2551,12 @@ class Player : public Unit, public GridObject<Player>
uint32 _pendingBindTimer;
uint32 _activeCheats;
+
+ // variables to save health and mana before duel and restore them after duel
+ uint32 healthBeforeDuel;
+ uint32 manaBeforeDuel;
+
+ WorldLocation _corpseLocation;
};
void AddItemsSetItem(Player* player, Item* item);
diff --git a/src/server/game/Entities/Player/SocialMgr.cpp b/src/server/game/Entities/Player/SocialMgr.cpp
index 77cd701ee35..b65584a4357 100644
--- a/src/server/game/Entities/Player/SocialMgr.cpp
+++ b/src/server/game/Entities/Player/SocialMgr.cpp
@@ -40,7 +40,7 @@ uint32 PlayerSocial::GetNumberOfSocialsWithFlag(SocialFlag flag)
return counter;
}
-bool PlayerSocial::AddToSocialList(uint32 friendGuid, bool ignore)
+bool PlayerSocial::AddToSocialList(ObjectGuid::LowType friendGuid, bool ignore)
{
// check client limits
if (ignore)
@@ -88,7 +88,7 @@ bool PlayerSocial::AddToSocialList(uint32 friendGuid, bool ignore)
return true;
}
-void PlayerSocial::RemoveFromSocialList(uint32 friendGuid, bool ignore)
+void PlayerSocial::RemoveFromSocialList(ObjectGuid::LowType friendGuid, bool ignore)
{
PlayerSocialMap::iterator itr = m_playerSocialMap.find(friendGuid);
if (itr == m_playerSocialMap.end()) // not exist
@@ -122,7 +122,7 @@ void PlayerSocial::RemoveFromSocialList(uint32 friendGuid, bool ignore)
}
}
-void PlayerSocial::SetFriendNote(uint32 friendGuid, std::string note)
+void PlayerSocial::SetFriendNote(ObjectGuid::LowType friendGuid, std::string note)
{
PlayerSocialMap::const_iterator itr = m_playerSocialMap.find(friendGuid);
if (itr == m_playerSocialMap.end()) // not exist
@@ -175,7 +175,7 @@ void PlayerSocial::SendSocialList(Player* player)
TC_LOG_DEBUG("network", "WORLD: Sent SMSG_CONTACT_LIST");
}
-bool PlayerSocial::HasFriend(uint32 friendGuid)
+bool PlayerSocial::HasFriend(ObjectGuid::LowType friendGuid)
{
PlayerSocialMap::const_iterator itr = m_playerSocialMap.find(friendGuid);
if (itr != m_playerSocialMap.end())
@@ -183,7 +183,7 @@ bool PlayerSocial::HasFriend(uint32 friendGuid)
return false;
}
-bool PlayerSocial::HasIgnore(uint32 ignore_guid)
+bool PlayerSocial::HasIgnore(ObjectGuid::LowType ignore_guid)
{
PlayerSocialMap::const_iterator itr = m_playerSocialMap.find(ignore_guid);
if (itr != m_playerSocialMap.end())
@@ -195,7 +195,7 @@ SocialMgr::SocialMgr() { }
SocialMgr::~SocialMgr() { }
-void SocialMgr::GetFriendInfo(Player* player, uint32 friendGUID, FriendInfo &friendInfo)
+void SocialMgr::GetFriendInfo(Player* player, ObjectGuid::LowType friendGUID, FriendInfo &friendInfo)
{
if (!player)
return;
@@ -205,7 +205,7 @@ void SocialMgr::GetFriendInfo(Player* player, uint32 friendGUID, FriendInfo &fri
friendInfo.Level = 0;
friendInfo.Class = 0;
- Player* target = ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER, friendGUID));
+ Player* target = ObjectAccessor::FindPlayer(ObjectGuid(HighGuid::Player, friendGUID));
if (!target)
return;
@@ -239,14 +239,14 @@ void SocialMgr::GetFriendInfo(Player* player, uint32 friendGUID, FriendInfo &fri
}
}
-void SocialMgr::MakeFriendStatusPacket(FriendsResult result, uint32 guid, WorldPacket* data)
+void SocialMgr::MakeFriendStatusPacket(FriendsResult result, ObjectGuid::LowType guid, WorldPacket* data)
{
data->Initialize(SMSG_FRIEND_STATUS, 9);
*data << uint8(result);
*data << uint64(guid);
}
-void SocialMgr::SendFriendStatus(Player* player, FriendsResult result, uint32 friendGuid, bool broadcast)
+void SocialMgr::SendFriendStatus(Player* player, FriendsResult result, ObjectGuid::LowType friendGuid, bool broadcast)
{
FriendInfo fi;
@@ -290,10 +290,10 @@ void SocialMgr::BroadcastToFriendListers(Player* player, WorldPacket* packet)
AccountTypes gmSecLevel = AccountTypes(sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_WHO_LIST));
for (SocialMap::const_iterator itr = m_socialMap.begin(); itr != m_socialMap.end(); ++itr)
{
- PlayerSocialMap::const_iterator itr2 = itr->second.m_playerSocialMap.find(player->GetGUIDLow());
+ PlayerSocialMap::const_iterator itr2 = itr->second.m_playerSocialMap.find(player->GetGUID().GetCounter());
if (itr2 != itr->second.m_playerSocialMap.end() && (itr2->second.Flags & SOCIAL_FLAG_FRIEND))
{
- Player* target = ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER, 0, itr->first));
+ Player* target = ObjectAccessor::FindPlayer(ObjectGuid(HighGuid::Player, 0, itr->first));
if (!target)
continue;
@@ -310,7 +310,7 @@ void SocialMgr::BroadcastToFriendListers(Player* player, WorldPacket* packet)
}
}
-PlayerSocial* SocialMgr::LoadFromDB(PreparedQueryResult result, uint32 guid)
+PlayerSocial* SocialMgr::LoadFromDB(PreparedQueryResult result, ObjectGuid::LowType guid)
{
PlayerSocial *social = &m_socialMap[guid];
social->SetPlayerGUID(guid);
@@ -318,7 +318,7 @@ PlayerSocial* SocialMgr::LoadFromDB(PreparedQueryResult result, uint32 guid)
if (!result)
return social;
- uint32 friendGuid = 0;
+ ObjectGuid::LowType friendGuid = 0;
uint8 flags = 0;
std::string note = "";
diff --git a/src/server/game/Entities/Player/SocialMgr.h b/src/server/game/Entities/Player/SocialMgr.h
index 5bf336a9abe..887b5de58df 100644
--- a/src/server/game/Entities/Player/SocialMgr.h
+++ b/src/server/game/Entities/Player/SocialMgr.h
@@ -21,6 +21,7 @@
#include "DatabaseEnv.h"
#include "Common.h"
+#include "ObjectGuid.h"
class SocialMgr;
class PlayerSocial;
@@ -60,8 +61,8 @@ struct FriendInfo
{ }
};
-typedef std::map<uint32, FriendInfo> PlayerSocialMap;
-typedef std::map<uint32, PlayerSocial> SocialMap;
+typedef std::map<ObjectGuid::LowType, FriendInfo> PlayerSocialMap;
+typedef std::map<ObjectGuid::LowType, PlayerSocial> SocialMap;
/// Results of friend related commands
enum FriendsResult
@@ -104,20 +105,20 @@ class PlayerSocial
public:
PlayerSocial();
// adding/removing
- bool AddToSocialList(uint32 friend_guid, bool ignore);
- void RemoveFromSocialList(uint32 friend_guid, bool ignore);
- void SetFriendNote(uint32 friendGuid, std::string note);
+ bool AddToSocialList(ObjectGuid::LowType friendGuid, bool ignore);
+ void RemoveFromSocialList(ObjectGuid::LowType friend_guid, bool ignore);
+ void SetFriendNote(ObjectGuid::LowType friendGuid, std::string note);
// Packet send's
void SendSocialList(Player* player);
// Misc
- bool HasFriend(uint32 friend_guid);
- bool HasIgnore(uint32 ignore_guid);
- uint32 GetPlayerGUID() const { return m_playerGUID; }
- void SetPlayerGUID(uint32 guid) { m_playerGUID = guid; }
+ bool HasFriend(ObjectGuid::LowType friend_guid);
+ bool HasIgnore(ObjectGuid::LowType ignore_guid);
+ ObjectGuid::LowType GetPlayerGUID() const { return m_playerGUID; }
+ void SetPlayerGUID(ObjectGuid::LowType guid) { m_playerGUID = guid; }
uint32 GetNumberOfSocialsWithFlag(SocialFlag flag);
private:
PlayerSocialMap m_playerSocialMap;
- uint32 m_playerGUID;
+ ObjectGuid::LowType m_playerGUID;
};
class SocialMgr
@@ -134,15 +135,15 @@ class SocialMgr
}
// Misc
- void RemovePlayerSocial(uint32 guid) { m_socialMap.erase(guid); }
+ void RemovePlayerSocial(ObjectGuid::LowType guid) { m_socialMap.erase(guid); }
- void GetFriendInfo(Player* player, uint32 friendGUID, FriendInfo &friendInfo);
+ void GetFriendInfo(Player* player, ObjectGuid::LowType friendGUID, FriendInfo &friendInfo);
// Packet management
- void MakeFriendStatusPacket(FriendsResult result, uint32 friend_guid, WorldPacket* data);
- void SendFriendStatus(Player* player, FriendsResult result, uint32 friend_guid, bool broadcast);
+ void MakeFriendStatusPacket(FriendsResult result, ObjectGuid::LowType friend_guid, WorldPacket* data);
+ void SendFriendStatus(Player* player, FriendsResult result, ObjectGuid::LowType friend_guid, bool broadcast);
void BroadcastToFriendListers(Player* player, WorldPacket* packet);
// Loading
- PlayerSocial *LoadFromDB(PreparedQueryResult result, uint32 guid);
+ PlayerSocial *LoadFromDB(PreparedQueryResult result, ObjectGuid::LowType guid);
private:
SocialMap m_socialMap;
};
diff --git a/src/server/game/Entities/Player/TradeData.cpp b/src/server/game/Entities/Player/TradeData.cpp
new file mode 100644
index 00000000000..bbbd1c81773
--- /dev/null
+++ b/src/server/game/Entities/Player/TradeData.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "TradeData.h"
+#include "Player.h"
+#include "WorldSession.h"
+
+TradeData* TradeData::GetTraderData() const
+{
+ return _trader->GetTradeData();
+}
+
+Item* TradeData::GetItem(TradeSlots slot) const
+{
+ return !_items[slot].IsEmpty() ? _player->GetItemByGuid(_items[slot]) : nullptr;
+}
+
+bool TradeData::HasItem(ObjectGuid itemGuid) const
+{
+ for (uint8 i = 0; i < TRADE_SLOT_COUNT; ++i)
+ if (_items[i] == itemGuid)
+ return true;
+
+ return false;
+}
+
+TradeSlots TradeData::GetTradeSlotForItem(ObjectGuid itemGuid) const
+{
+ for (uint8 i = 0; i < TRADE_SLOT_COUNT; ++i)
+ if (_items[i] == itemGuid)
+ return TradeSlots(i);
+
+ return TRADE_SLOT_INVALID;
+}
+
+Item* TradeData::GetSpellCastItem() const
+{
+ return !_spellCastItem.IsEmpty() ? _player->GetItemByGuid(_spellCastItem) : nullptr;
+}
+
+void TradeData::SetItem(TradeSlots slot, Item* item, bool update /*= false*/)
+{
+ ObjectGuid itemGuid;
+ if (item)
+ itemGuid = item->GetGUID();
+
+ if (_items[slot] == itemGuid && !update)
+ return;
+
+ _items[slot] = itemGuid;
+
+ SetAccepted(false);
+ GetTraderData()->SetAccepted(false);
+
+ Update();
+
+ // need remove possible trader spell applied to changed item
+ if (slot == TRADE_SLOT_NONTRADED)
+ GetTraderData()->SetSpell(0);
+
+ // need remove possible player spell applied (possible move reagent)
+ SetSpell(0);
+}
+
+void TradeData::SetSpell(uint32 spell_id, Item* castItem /*= nullptr*/)
+{
+ ObjectGuid itemGuid = castItem ? castItem->GetGUID() : ObjectGuid::Empty;
+
+ if (_spell == spell_id && _spellCastItem == itemGuid)
+ return;
+
+ _spell = spell_id;
+ _spellCastItem = itemGuid;
+
+ SetAccepted(false);
+ GetTraderData()->SetAccepted(false);
+
+ Update(true); // send spell info to item owner
+ Update(false); // send spell info to caster self
+}
+
+void TradeData::SetMoney(uint32 money)
+{
+ if (_money == money)
+ return;
+
+ if (!_player->HasEnoughMoney(money))
+ {
+ TradeStatusInfo info;
+ info.Status = TRADE_STATUS_CLOSE_WINDOW;
+ info.Result = EQUIP_ERR_NOT_ENOUGH_MONEY;
+ _player->GetSession()->SendTradeStatus(info);
+ return;
+ }
+
+ _money = money;
+
+ SetAccepted(false);
+ GetTraderData()->SetAccepted(false);
+
+ Update(true);
+}
+
+void TradeData::Update(bool forTrader /*= true*/) const
+{
+ if (forTrader)
+ _trader->GetSession()->SendUpdateTrade(true); // player state for trader
+ else
+ _player->GetSession()->SendUpdateTrade(false); // player state for player
+}
+
+void TradeData::SetAccepted(bool state, bool forTrader /*= false*/)
+{
+ _accepted = state;
+
+ if (!state)
+ {
+ TradeStatusInfo info;
+ info.Status = TRADE_STATUS_BACK_TO_TRADE;
+ if (forTrader)
+ _trader->GetSession()->SendTradeStatus(info);
+ else
+ _player->GetSession()->SendTradeStatus(info);
+ }
+}
diff --git a/src/server/game/Entities/Player/TradeData.h b/src/server/game/Entities/Player/TradeData.h
new file mode 100644
index 00000000000..cfaf066bde0
--- /dev/null
+++ b/src/server/game/Entities/Player/TradeData.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TradeData_h__
+#define TradeData_h__
+
+#include "ObjectGuid.h"
+
+enum TradeSlots
+{
+ TRADE_SLOT_COUNT = 7,
+ TRADE_SLOT_TRADED_COUNT = 6,
+ TRADE_SLOT_NONTRADED = 6,
+ TRADE_SLOT_INVALID = -1
+};
+
+class Item;
+class Player;
+
+class TradeData
+{
+public:
+ TradeData(Player* player, Player* trader) :
+ _player(player), _trader(trader), _accepted(false), _acceptProccess(false),
+ _money(0), _spell(0), _spellCastItem() { }
+
+ Player* GetTrader() const { return _trader; }
+ TradeData* GetTraderData() const;
+
+ Item* GetItem(TradeSlots slot) const;
+ bool HasItem(ObjectGuid itemGuid) const;
+ TradeSlots GetTradeSlotForItem(ObjectGuid itemGuid) const;
+ void SetItem(TradeSlots slot, Item* item, bool update = false);
+
+ uint32 GetSpell() const { return _spell; }
+ void SetSpell(uint32 spell_id, Item* castItem = nullptr);
+
+ Item* GetSpellCastItem() const;
+ bool HasSpellCastItem() const { return !_spellCastItem.IsEmpty(); }
+
+ uint32 GetMoney() const { return _money; }
+ void SetMoney(uint32 money);
+
+ bool IsAccepted() const { return _accepted; }
+ void SetAccepted(bool state, bool forTrader = false);
+
+ bool IsInAcceptProcess() const { return _acceptProccess; }
+ void SetInAcceptProcess(bool state) { _acceptProccess = state; }
+
+private:
+ void Update(bool for_trader = true) const;
+
+ Player* _player; // Player who own of this TradeData
+ Player* _trader; // Player who trade with _player
+
+ bool _accepted; // _player press accept for trade list
+ bool _acceptProccess; // one from player/trader press accept and this processed
+
+ uint32 _money; // _player place money to trade
+
+ uint32 _spell; // _player apply spell to non-traded slot item
+ ObjectGuid _spellCastItem; // applied spell cast by item use
+
+ ObjectGuid _items[TRADE_SLOT_COUNT]; // traded items from _player side including non-traded slot
+};
+
+#endif // TradeData_h__
diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp
index 6d98a4c78b2..99459dce81e 100644
--- a/src/server/game/Entities/Transport/Transport.cpp
+++ b/src/server/game/Entities/Transport/Transport.cpp
@@ -43,7 +43,7 @@ Transport::~Transport()
UnloadStaticPassengers();
}
-bool Transport::Create(uint32 guidlow, uint32 entry, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress)
+bool Transport::Create(ObjectGuid::LowType guidlow, uint32 entry, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress)
{
Relocate(x, y, z, ang);
@@ -54,7 +54,7 @@ bool Transport::Create(uint32 guidlow, uint32 entry, uint32 mapid, float x, floa
return false;
}
- Object::_Create(guidlow, 0, HIGHGUID_MO_TRANSPORT);
+ Object::_Create(guidlow, 0, HighGuid::Mo_Transport);
GameObjectTemplate const* goinfo = sObjectMgr->GetGameObjectTemplate(entry);
@@ -94,7 +94,7 @@ bool Transport::Create(uint32 guidlow, uint32 entry, uint32 mapid, float x, floa
SetName(goinfo->name);
UpdateRotationFields(0.0f, 1.0f);
- m_model = GameObjectModel::Create(*this);
+ m_model = CreateModel();
return true;
}
@@ -281,7 +281,7 @@ void Transport::RemovePassenger(WorldObject* passenger)
}
}
-Creature* Transport::CreateNPCPassenger(uint32 guid, CreatureData const* data)
+Creature* Transport::CreateNPCPassenger(ObjectGuid::LowType guid, CreatureData const* data)
{
Map* map = GetMap();
Creature* creature = new Creature();
@@ -312,7 +312,7 @@ Creature* Transport::CreateNPCPassenger(uint32 guid, CreatureData const* data)
if (!creature->IsPositionValid())
{
- TC_LOG_ERROR("entities.transport", "Creature (guidlow %d, entry %d) not created. Suggested coordinates aren't valid (X: %f Y: %f)",creature->GetGUIDLow(),creature->GetEntry(),creature->GetPositionX(),creature->GetPositionY());
+ TC_LOG_ERROR("entities.transport", "Creature (guidlow %d, entry %d) not created. Suggested coordinates aren't valid (X: %f Y: %f)",creature->GetGUID().GetCounter(),creature->GetEntry(),creature->GetPositionX(),creature->GetPositionY());
delete creature;
return NULL;
}
@@ -328,7 +328,7 @@ Creature* Transport::CreateNPCPassenger(uint32 guid, CreatureData const* data)
return creature;
}
-GameObject* Transport::CreateGOPassenger(uint32 guid, GameObjectData const* data)
+GameObject* Transport::CreateGOPassenger(ObjectGuid::LowType guid, GameObjectData const* data)
{
Map* map = GetMap();
GameObject* go = new GameObject();
@@ -351,10 +351,11 @@ GameObject* Transport::CreateGOPassenger(uint32 guid, GameObjectData const* data
go->m_movementInfo.transport.pos.Relocate(x, y, z, o);
CalculatePassengerPosition(x, y, z, &o);
go->Relocate(x, y, z, o);
+ go->RelocateStationaryPosition(x, y, z, o);
if (!go->IsPositionValid())
{
- TC_LOG_ERROR("entities.transport", "GameObject (guidlow %d, entry %d) not created. Suggested coordinates aren't valid (X: %f Y: %f)", go->GetGUIDLow(), go->GetEntry(), go->GetPositionX(), go->GetPositionY());
+ TC_LOG_ERROR("entities.transport", "GameObject (guidlow %d, entry %d) not created. Suggested coordinates aren't valid (X: %f Y: %f)", go->GetGUID().GetCounter(), go->GetEntry(), go->GetPositionX(), go->GetPositionY());
delete go;
return NULL;
}
@@ -451,7 +452,7 @@ TempSummon* Transport::SummonPassenger(uint32 entry, Position const& pos, TempSu
pos.GetPosition(x, y, z, o);
CalculatePassengerPosition(x, y, z, &o);
- if (!summon->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, phase, entry, x, y, z, o, nullptr, vehId))
+ if (!summon->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, phase, entry, x, y, z, o, nullptr, vehId))
{
delete summon;
return NULL;
@@ -703,6 +704,7 @@ void Transport::UpdatePassengerPositions(PassengerSet& passengers)
break;
case TYPEID_GAMEOBJECT:
GetMap()->GameObjectRelocation(passenger->ToGameObject(), x, y, z, o, false);
+ passenger->ToGameObject()->RelocateStationaryPosition(x, y, z, o);
break;
case TYPEID_DYNAMICOBJECT:
GetMap()->DynamicObjectRelocation(passenger->ToDynObject(), x, y, z, o);
diff --git a/src/server/game/Entities/Transport/Transport.h b/src/server/game/Entities/Transport/Transport.h
index c56ceb1696d..3a2d0e4a7bd 100644
--- a/src/server/game/Entities/Transport/Transport.h
+++ b/src/server/game/Entities/Transport/Transport.h
@@ -27,7 +27,7 @@ struct CreatureData;
class Transport : public GameObject, public TransportBase
{
- friend Transport* TransportMgr::CreateTransport(uint32, uint32, Map*);
+ friend Transport* TransportMgr::CreateTransport(uint32, ObjectGuid::LowType, Map*);
Transport();
public:
@@ -35,7 +35,7 @@ class Transport : public GameObject, public TransportBase
~Transport();
- bool Create(uint32 guidlow, uint32 entry, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress);
+ bool Create(ObjectGuid::LowType guidlow, uint32 entry, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress);
void CleanupsBeforeDelete(bool finalCleanup = true) override;
void Update(uint32 diff) override;
@@ -47,8 +47,8 @@ class Transport : public GameObject, public TransportBase
void RemovePassenger(WorldObject* passenger);
PassengerSet const& GetPassengers() const { return _passengers; }
- Creature* CreateNPCPassenger(uint32 guid, CreatureData const* data);
- GameObject* CreateGOPassenger(uint32 guid, GameObjectData const* data);
+ Creature* CreateNPCPassenger(ObjectGuid::LowType guid, CreatureData const* data);
+ GameObject* CreateGOPassenger(ObjectGuid::LowType guid, GameObjectData const* data);
/**
* @fn bool Transport::SummonPassenger(uint64, Position const&, TempSummonType, SummonPropertiesEntry const*, uint32, Unit*, uint32, uint32)
diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp
index 67101dc8961..fb27fea7060 100644
--- a/src/server/game/Entities/Unit/StatSystem.cpp
+++ b/src/server/game/Entities/Unit/StatSystem.cpp
@@ -23,7 +23,6 @@
#include "SharedDefines.h"
#include "SpellAuras.h"
#include "SpellAuraEffects.h"
-#include "SpellMgr.h"
#include "World.h"
inline bool _ModifyUInt32(bool apply, uint32& baseValue, int32& amount)
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index a58fde1e3a3..27f6d5f614d 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -54,8 +54,8 @@
#include "SpellHistory.h"
#include "SpellMgr.h"
#include "TemporarySummon.h"
-#include "Totem.h"
#include "Transport.h"
+#include "Totem.h"
#include "UpdateFieldFlags.h"
#include "Util.h"
#include "Vehicle.h"
@@ -288,6 +288,28 @@ Unit::~Unit()
ASSERT(m_dynObj.empty());
}
+// Check if unit in combat with specific unit
+bool Unit::IsInCombatWith(Unit const* who) const
+{
+ // Check target exists
+ if (!who)
+ return false;
+
+ // Search in threat list
+ ObjectGuid guid = who->GetGUID();
+ for (ThreatContainer::StorageType::const_iterator i = m_ThreatManager.getThreatList().begin(); i != m_ThreatManager.getThreatList().end(); ++i)
+ {
+ HostileReference* ref = (*i);
+
+ // Return true if the unit matches
+ if (ref && ref->getUnitGuid() == guid)
+ return true;
+ }
+
+ // Nothing found, false.
+ return false;
+}
+
void Unit::Update(uint32 p_time)
{
// WARNING! Order of execution here is important, do not change.
@@ -308,7 +330,7 @@ void Unit::Update(uint32 p_time)
SendThreatListUpdate();
// update combat timer only for players and pets (only pets with PetAI)
- if (IsInCombat() && (GetTypeId() == TYPEID_PLAYER || (ToCreature()->IsPet() && IsControlledByPlayer())))
+ if (IsInCombat() && (GetTypeId() == TYPEID_PLAYER || (IsPet() && IsControlledByPlayer())))
{
// Check UNIT_STATE_MELEE_ATTACKING or UNIT_STATE_CHASE (without UNIT_STATE_FOLLOW in this case) so pets can reach far away
// targets without stopping half way there and running off.
@@ -699,7 +721,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
if (!victim->ToCreature()->hasLootRecipient())
victim->ToCreature()->SetLootRecipient(this);
- if (IsControlledByPlayer())
+ if (IsControlledByPlayer() || (ToTempSummon() && ToTempSummon()->GetSummoner() && ToTempSummon()->GetSummoner()->GetTypeId() == TYPEID_PLAYER))
victim->ToCreature()->LowerPlayerDamageReq(health < damage ? health : damage);
}
@@ -819,7 +841,7 @@ void Unit::CastSpell(SpellCastTargets const& targets, SpellInfo const* spellInfo
{
if (!spellInfo)
{
- TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell by caster: %s %u)", (GetTypeId() == TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"), (GetTypeId() == TYPEID_PLAYER ? GetGUIDLow() : GetEntry()));
+ TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell by caster: %s %u)", (GetTypeId() == TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"), (GetTypeId() == TYPEID_PLAYER ? GetGUID().GetCounter() : GetEntry()));
return;
}
@@ -847,7 +869,7 @@ void Unit::CastSpell(Unit* victim, uint32 spellId, TriggerCastFlags triggerFlags
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!spellInfo)
{
- TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell id %u by caster: %s %u)", spellId, (GetTypeId() == TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"), (GetTypeId() == TYPEID_PLAYER ? GetGUIDLow() : GetEntry()));
+ TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell id %u by caster: %s %u)", spellId, (GetTypeId() == TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"), (GetTypeId() == TYPEID_PLAYER ? GetGUID().GetCounter() : GetEntry()));
return;
}
@@ -897,7 +919,7 @@ void Unit::CastCustomSpell(uint32 spellId, CustomSpellValues const& value, Unit*
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!spellInfo)
{
- TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell id %u by caster: %s %u)", spellId, (GetTypeId() == TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"), (GetTypeId() == TYPEID_PLAYER ? GetGUIDLow() : GetEntry()));
+ TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell id %u by caster: %s %u)", spellId, (GetTypeId() == TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"), (GetTypeId() == TYPEID_PLAYER ? GetGUID().GetCounter() : GetEntry()));
return;
}
SpellCastTargets targets;
@@ -911,7 +933,7 @@ void Unit::CastSpell(float x, float y, float z, uint32 spellId, bool triggered,
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!spellInfo)
{
- TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell id %u by caster: %s %u)", spellId, (GetTypeId() == TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"), (GetTypeId() == TYPEID_PLAYER ? GetGUIDLow() : GetEntry()));
+ TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell id %u by caster: %s %u)", spellId, (GetTypeId() == TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"), (GetTypeId() == TYPEID_PLAYER ? GetGUID().GetCounter() : GetEntry()));
return;
}
SpellCastTargets targets;
@@ -925,7 +947,7 @@ void Unit::CastSpell(GameObject* go, uint32 spellId, bool triggered, Item* castI
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!spellInfo)
{
- TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell id %u by caster: %s %u)", spellId, (GetTypeId() == TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"), (GetTypeId() == TYPEID_PLAYER ? GetGUIDLow() : GetEntry()));
+ TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell id %u by caster: %s %u)", spellId, (GetTypeId() == TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"), (GetTypeId() == TYPEID_PLAYER ? GetGUID().GetCounter() : GetEntry()));
return;
}
SpellCastTargets targets;
@@ -1787,6 +1809,13 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
dmgInfo.AbsorbDamage(splitDamage);
+ // check if caster is immune to damage
+ if (caster->IsImmunedToDamage(schoolMask))
+ {
+ victim->SendSpellMiss(caster, (*itr)->GetSpellInfo()->Id, SPELL_MISS_IMMUNE);
+ continue;
+ }
+
uint32 splitted = splitDamage;
uint32 splitted_absorb = 0;
DealDamageMods(caster, splitted, &splitted_absorb);
@@ -1824,6 +1853,14 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
splitDamage = RoundToInterval(splitDamage, uint32(0), uint32(dmgInfo.GetDamage()));
dmgInfo.AbsorbDamage(splitDamage);
+
+ // check if caster is immune to damage
+ if (caster->IsImmunedToDamage(schoolMask))
+ {
+ victim->SendSpellMiss(caster, (*itr)->GetSpellInfo()->Id, SPELL_MISS_IMMUNE);
+ continue;
+ }
+
uint32 split_absorb = 0;
DealDamageMods(caster, splitDamage, &split_absorb);
@@ -1940,10 +1977,10 @@ void Unit::AttackerStateUpdate (Unit* victim, WeaponAttackType attType, bool ext
if (GetTypeId() == TYPEID_PLAYER)
TC_LOG_DEBUG("entities.unit", "AttackerStateUpdate: (Player) %u attacked %u (TypeId: %u) for %u dmg, absorbed %u, blocked %u, resisted %u.",
- GetGUIDLow(), victim->GetGUIDLow(), victim->GetTypeId(), damageInfo.damage, damageInfo.absorb, damageInfo.blocked_amount, damageInfo.resist);
+ GetGUID().GetCounter(), victim->GetGUID().GetCounter(), victim->GetTypeId(), damageInfo.damage, damageInfo.absorb, damageInfo.blocked_amount, damageInfo.resist);
else
TC_LOG_DEBUG("entities.unit", "AttackerStateUpdate: (NPC) %u attacked %u (TypeId: %u) for %u dmg, absorbed %u, blocked %u, resisted %u.",
- GetGUIDLow(), victim->GetGUIDLow(), victim->GetTypeId(), damageInfo.damage, damageInfo.absorb, damageInfo.blocked_amount, damageInfo.resist);
+ GetGUID().GetCounter(), victim->GetGUID().GetCounter(), victim->GetTypeId(), damageInfo.damage, damageInfo.absorb, damageInfo.blocked_amount, damageInfo.resist);
}
}
@@ -2094,8 +2131,8 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit* victim, WeaponAttackT
// Max 40% chance to score a glancing blow against mobs that are higher level (can do only players and pets and not with ranged weapon)
if (attType != RANGED_ATTACK &&
- (GetTypeId() == TYPEID_PLAYER || ToCreature()->IsPet()) &&
- victim->GetTypeId() != TYPEID_PLAYER && !victim->ToCreature()->IsPet() &&
+ (GetTypeId() == TYPEID_PLAYER || IsPet()) &&
+ victim->GetTypeId() != TYPEID_PLAYER && !victim->IsPet() &&
getLevel() < victim->getLevelForTarget(this))
{
// cap possible value (with bonuses > max skill)
@@ -2169,6 +2206,9 @@ uint32 Unit::CalculateDamage(WeaponAttackType attType, bool normalized, bool add
}
}
+ minDamage = std::max(0.f, minDamage);
+ maxDamage = std::max(0.f, maxDamage);
+
if (minDamage > maxDamage)
std::swap(minDamage, maxDamage);
@@ -2217,9 +2257,9 @@ void Unit::SendMeleeAttackStop(Unit* victim)
TC_LOG_DEBUG("entities.unit", "WORLD: Sent SMSG_ATTACKSTOP");
if (victim)
- TC_LOG_DEBUG("entities.unit", "%s %u stopped attacking %s %u", (GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature"), GetGUIDLow(), (victim->GetTypeId() == TYPEID_PLAYER ? "player" : "creature"), victim->GetGUIDLow());
+ TC_LOG_DEBUG("entities.unit", "%s %u stopped attacking %s %u", (GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature"), GetGUID().GetCounter(), (victim->GetTypeId() == TYPEID_PLAYER ? "player" : "creature"), victim->GetGUID().GetCounter());
else
- TC_LOG_DEBUG("entities.unit", "%s %u stopped attacking", (GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature"), GetGUIDLow());
+ TC_LOG_DEBUG("entities.unit", "%s %u stopped attacking", (GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature"), GetGUID().GetCounter());
}
bool Unit::isSpellBlocked(Unit* victim, SpellInfo const* spellProto, WeaponAttackType attackType)
@@ -2665,7 +2705,7 @@ float Unit::GetUnitDodgeChance() const
return GetFloatValue(PLAYER_DODGE_PERCENTAGE);
else
{
- if (ToCreature()->IsTotem())
+ if (IsTotem())
return 0.0f;
else
{
@@ -2740,7 +2780,7 @@ float Unit::GetUnitBlockChance() const
}
else
{
- if (ToCreature()->IsTotem())
+ if (IsTotem())
return 0.0f;
else
{
@@ -3152,7 +3192,7 @@ bool Unit::IsUnderWater() const
void Unit::UpdateUnderwaterState(Map* m, float x, float y, float z)
{
- if (!IsPet() && !IsVehicle())
+ if (IsFlying() || (!IsPet() && !IsVehicle()))
return;
LiquidData liquid_status;
@@ -3445,7 +3485,7 @@ void Unit::_UnapplyAura(AuraApplicationMap::iterator &i, AuraRemoveMode removeMo
ASSERT(!aurApp->GetEffectMask());
// Remove totem at next update if totem loses its aura
- if (aurApp->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE && GetTypeId() == TYPEID_UNIT && ToCreature()->IsTotem())
+ if (aurApp->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE && GetTypeId() == TYPEID_UNIT && IsTotem())
{
if (ToTotem()->GetSpell() == aura->GetId() && ToTotem()->GetTotemType() == TOTEM_PASSIVE)
ToTotem()->setDeathState(JUST_DIED);
@@ -3480,7 +3520,7 @@ void Unit::_UnapplyAura(AuraApplication * aurApp, AuraRemoveMode removeMode)
else
++iter;
}
- ASSERT(false);
+ ABORT();
}
void Unit::_RemoveNoStackAurasDueToAura(Aura* aura)
@@ -3590,7 +3630,7 @@ void Unit::RemoveOwnedAura(Aura* aura, AuraRemoveMode removeMode)
}
}
- ASSERT(false);
+ ABORT();
}
Aura* Unit::GetOwnedAura(uint32 spellId, ObjectGuid casterGUID, ObjectGuid itemCasterGUID, uint8 reqEffMask, Aura* except) const
@@ -3868,20 +3908,27 @@ void Unit::RemoveAurasWithAttribute(uint32 flags)
void Unit::RemoveNotOwnSingleTargetAuras(uint32 newPhase)
{
// single target auras from other casters
- for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();)
+ // Iterate m_ownedAuras - aura is marked as single target in Unit::AddAura (and pushed to m_ownedAuras).
+ // m_appliedAuras will NOT contain the aura before first Unit::Update after adding it to m_ownedAuras.
+ // Quickly removing such an aura will lead to it not being unregistered from caster's single cast auras container
+ // leading to assertion failures if the aura was cast on a player that can
+ // (and is changing map at the point where this function is called).
+ // Such situation occurs when player is logging in inside an instance and fails the entry check for any reason.
+ // The aura that was loaded from db (indirectly, via linked casts) gets removed before it has a chance
+ // to register in m_appliedAuras
+ for (AuraMap::iterator iter = m_ownedAuras.begin(); iter != m_ownedAuras.end();)
{
- AuraApplication const* aurApp = iter->second;
- Aura const* aura = aurApp->GetBase();
+ Aura const* aura = iter->second;
- if (aura->GetCasterGUID() != GetGUID() && aura->GetSpellInfo()->IsSingleTarget())
+ if (aura->GetCasterGUID() != GetGUID() && aura->IsSingleTarget())
{
if (!newPhase)
- RemoveAura(iter);
+ RemoveOwnedAura(iter);
else
{
Unit* caster = aura->GetCaster();
if (!caster || !caster->InSamePhase(newPhase))
- RemoveAura(iter);
+ RemoveOwnedAura(iter);
else
++iter;
}
@@ -4141,7 +4188,7 @@ void Unit::DelayOwnedAuras(uint32 spellId, ObjectGuid caster, int32 delaytime)
// update for out of range group members (on 1 slot use)
aura->SetNeedClientUpdateForTargets();
- TC_LOG_DEBUG("spells", "Aura %u partially interrupted on unit %u, new duration: %u ms", aura->GetId(), GetGUIDLow(), aura->GetDuration());
+ TC_LOG_DEBUG("spells", "Aura %u partially interrupted on unit %u, new duration: %u ms", aura->GetId(), GetGUID().GetCounter(), aura->GetDuration());
}
}
}
@@ -5674,7 +5721,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
if (dummySpell->SpellIconID == 1697)
{
// only for spells and hit/crit (trigger start always) and not start from self cast spells (5530 Mace Stun Effect for example)
- if (procSpell == 0 || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == victim)
+ if (!procSpell || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == victim)
return false;
// Need stun or root mechanic
if (!(procSpell->GetAllEffectsMechanicMask() & ((1<<MECHANIC_ROOT)|(1<<MECHANIC_STUN))))
@@ -5871,7 +5918,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
// Vampiric Embrace
case 15286:
{
- if (!victim || !victim->IsAlive() || procSpell->SpellFamilyFlags[1] & 0x80000)
+ if (!victim || !victim->IsAlive() || !procSpell || procSpell->SpellFamilyFlags[1] & 0x80000)
return false;
// heal amount
@@ -5885,7 +5932,9 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
case 40438:
{
// Shadow Word: Pain
- if (procSpell->SpellFamilyFlags[0] & 0x8000)
+ if (!procSpell)
+ return false;
+ else if (procSpell->SpellFamilyFlags[0] & 0x8000)
triggered_spell_id = 40441;
// Renew
else if (procSpell->SpellFamilyFlags[0] & 0x40)
@@ -5949,7 +5998,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
// Priest T10 Healer 2P Bonus
case 70770:
// Flash Heal
- if (procSpell->SpellFamilyFlags[0] & 0x800)
+ if (procSpell && procSpell->SpellFamilyFlags[0] & 0x800)
{
triggered_spell_id = 70772;
SpellInfo const* blessHealing = sSpellMgr->GetSpellInfo(triggered_spell_id);
@@ -5968,7 +6017,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
// Glyph of Innervate
case 54832:
{
- if (procSpell->SpellIconID != 62)
+ if (!procSpell || procSpell->SpellIconID != 62)
return false;
int32 mana_perc = triggeredByAura->GetSpellInfo()->Effects[triggeredByAura->GetEffIndex()].CalcValue();
@@ -6018,7 +6067,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
// Glyph of Rake
case 54821:
{
- if (procSpell->SpellVisual[0] == 750 && procSpell->Effects[1].ApplyAuraName == 3)
+ if (procSpell && procSpell->SpellVisual[0] == 750 && procSpell->Effects[1].ApplyAuraName == 3)
{
if (target && target->GetTypeId() == TYPEID_UNIT)
{
@@ -6048,10 +6097,13 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
// Healing Touch (Dreamwalker Raiment set)
case 28719:
{
- // mana back
- basepoints0 = int32(CalculatePct(procSpell->ManaCost, 30));
- target = this;
- triggered_spell_id = 28742;
+ if (procSpell)
+ {
+ // mana back
+ basepoints0 = int32(CalculatePct(procSpell->ManaCost, 30));
+ target = this;
+ triggered_spell_id = 28742;
+ }
break;
}
// Glyph of Rejuvenation
@@ -6083,8 +6135,10 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
{
float chance;
+ if (!procSpell)
+ return false;
// Starfire
- if (procSpell->SpellFamilyFlags[0] & 0x4)
+ else if (procSpell->SpellFamilyFlags[0] & 0x4)
{
triggered_spell_id = 40445;
chance = 25.0f;
@@ -6121,7 +6175,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
case 70723:
{
// Wrath & Starfire
- if ((procSpell->SpellFamilyFlags[0] & 0x5) && (procEx & PROC_EX_CRITICAL_HIT))
+ if (procSpell && (procSpell->SpellFamilyFlags[0] & 0x5) && (procEx & PROC_EX_CRITICAL_HIT))
{
triggered_spell_id = 71023;
SpellInfo const* triggeredSpell = sSpellMgr->GetSpellInfo(triggered_spell_id);
@@ -6137,7 +6191,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
case 70664:
{
// Proc only from normal Rejuvenation
- if (procSpell->SpellVisual[0] != 32)
+ if (!procSpell || procSpell->SpellVisual[0] != 32)
return false;
Player* caster = ToPlayer();
@@ -6268,7 +6322,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
case 3560: // Rapid Recuperation
{
// This effect only from Rapid Killing (mana regen)
- if (!(procSpell->SpellFamilyFlags[1] & 0x01000000))
+ if (!procSpell || !(procSpell->SpellFamilyFlags[1] & 0x01000000))
return false;
target = this;
@@ -6310,7 +6364,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
// Light's Beacon - Beacon of Light
if (dummySpell->Id == 53651)
{
- if (!victim)
+ if (!victim || !procSpell)
return false;
triggered_spell_id = 0;
Unit* beaconTarget = NULL;
@@ -6471,9 +6525,9 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
return false;
// At melee attack or Hammer of the Righteous spell damage considered as melee attack
- bool stacker = !procSpell || procSpell->Id == 53595;
+ bool stacker = procSpell ? procSpell->Id == 53595 : true;
// spells with SPELL_DAMAGE_CLASS_MELEE excluding Judgements
- bool damager = procSpell && (procSpell->EquippedItemClass != -1 || (procSpell->SpellIconID == 243 && procSpell->SpellVisual[0] == 39));
+ bool damager = procSpell ? (procSpell->EquippedItemClass != -1 || (procSpell->SpellIconID == 243 && procSpell->SpellVisual[0] == 39)) : false;
if (!stacker && !damager)
return false;
@@ -6503,9 +6557,9 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
return false;
// At melee attack or Hammer of the Righteous spell damage considered as melee attack
- bool stacker = !procSpell || procSpell->Id == 53595;
+ bool stacker = procSpell ? procSpell->Id == 53595 : true;
// spells with SPELL_DAMAGE_CLASS_MELEE excluding Judgements
- bool damager = procSpell && (procSpell->EquippedItemClass != -1 || (procSpell->SpellIconID == 243 && procSpell->SpellVisual[0] == 39));
+ bool damager = procSpell ? (procSpell->EquippedItemClass != -1 || (procSpell->SpellIconID == 243 && procSpell->SpellVisual[0] == 39)) : false;
if (!stacker && !damager)
return false;
@@ -6852,7 +6906,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
case 67228:
{
// Lava Burst
- if (procSpell->SpellFamilyFlags[1] & 0x1000)
+ if (procSpell && procSpell->SpellFamilyFlags[1] & 0x1000)
{
triggered_spell_id = 71824;
SpellInfo const* triggeredSpell = sSpellMgr->GetSpellInfo(triggered_spell_id);
@@ -6866,7 +6920,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
case 70808:
{
// Chain Heal
- if ((procSpell->SpellFamilyFlags[0] & 0x100) && (procEx & PROC_EX_CRITICAL_HIT))
+ if (procSpell && (procSpell->SpellFamilyFlags[0] & 0x100) && (procEx & PROC_EX_CRITICAL_HIT))
{
triggered_spell_id = 70809;
SpellInfo const* triggeredSpell = sSpellMgr->GetSpellInfo(triggered_spell_id);
@@ -6902,7 +6956,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
}
case 63280: // Glyph of Totem of Wrath
{
- if (procSpell->SpellIconID != 2019)
+ if (!procSpell || procSpell->SpellIconID != 2019)
return false;
if (Creature* totem = GetMap()->GetCreature(m_SummonSlot[1])) // Fire totem summon slot
@@ -6994,7 +7048,9 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
// Default chance for Healing Wave and Riptide
float chance = (float)triggeredByAura->GetAmount();
- if (procSpell->SpellFamilyFlags[0] & 0x80)
+ if (!procSpell)
+ return false; //This is the same than putting chance *= 0.0f;
+ else if (procSpell->SpellFamilyFlags[0] & 0x80)
// Lesser Healing Wave - 0.6 of default
chance *= 0.6f;
else if (procSpell->SpellFamilyFlags[0] & 0x100)
@@ -7249,7 +7305,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
if (dummySpell->Id == 61257)
{
// only for spells and hit/crit (trigger start always) and not start from self cast spells
- if (procSpell == 0 || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == victim)
+ if (!procSpell || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == victim)
return false;
// Need snare or root mechanic
if (!(procSpell->GetAllEffectsMechanicMask() & ((1<<MECHANIC_ROOT)|(1<<MECHANIC_SNARE))))
@@ -7308,7 +7364,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
case SPELLFAMILY_POTION:
{
// alchemist's stone
- if (dummySpell->Id == 17619)
+ if (procSpell && dummySpell->Id == 17619)
{
if (procSpell->SpellFamilyName == SPELLFAMILY_POTION)
{
@@ -7340,7 +7396,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
// Guard Dog
case 201:
{
- if (!victim)
+ if (!victim || !procSpell)
return false;
triggered_spell_id = 54445;
@@ -7419,8 +7475,8 @@ bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, Sp
uint32 stack = triggeredByAura->GetStackAmount();
int32 const mod = (GetMap()->GetSpawnMode() & 1) ? 1500 : 1250;
int32 dmg = 0;
- for (uint8 i = 1; i < stack; ++i)
- dmg += mod * stack;
+ for (uint8 i = 1; i <= stack; ++i)
+ dmg += mod * i;
if (Unit* caster = triggeredByAura->GetCaster())
caster->CastCustomSpell(70701, SPELLVALUE_BASE_POINT0, dmg);
break;
@@ -8235,6 +8291,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
case 15337: // Improved Spirit Tap (Rank 1)
case 15338: // Improved Spirit Tap (Rank 2)
{
+ ASSERT(procSpell);
if (procSpell->SpellFamilyFlags[0] & 0x800000)
if ((procSpell->Id != 58381) || !roll_chance_i(50))
return false;
@@ -8411,7 +8468,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
// Item - Shaman T10 Enhancement 4P Bonus
if (AuraEffect const* aurEff = GetAuraEffect(70832, 0))
if (Aura const* maelstrom = GetAura(53817))
- if ((maelstrom->GetStackAmount() == maelstrom->GetSpellInfo()->StackAmount - 1) && roll_chance_i(aurEff->GetAmount()))
+ if ((maelstrom->GetStackAmount() == maelstrom->GetSpellInfo()->StackAmount) && roll_chance_i(aurEff->GetAmount()))
CastSpell(this, 70831, true, castItem, triggeredByAura);
break;
}
@@ -8496,7 +8553,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
// try detect target manually if not set
if (target == NULL)
- target = !(procFlags & (PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS | PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS)) && triggerEntry && triggerEntry->IsPositive() ? this : victim;
+ target = !(procFlags & (PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS | PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS)) && triggerEntry->IsPositive() ? this : victim;
if (basepoints0)
CastCustomSpell(target, trigger_spell_id, &basepoints0, NULL, NULL, true, castItem, triggeredByAura);
@@ -8944,7 +9001,7 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
//if (GetTypeId() == TYPEID_UNIT)
// ToCreature()->SetCombatStartPosition(GetPositionX(), GetPositionY(), GetPositionZ());
- if (GetTypeId() == TYPEID_UNIT && !ToCreature()->IsPet())
+ if (GetTypeId() == TYPEID_UNIT && !IsPet())
{
// should not let player enter combat by right clicking target - doesn't helps
SetInCombatWith(victim);
@@ -9401,7 +9458,7 @@ void Unit::SetMinion(Minion *minion, bool apply)
{
OutDebugInfo();
(*itr)->OutDebugInfo();
- ASSERT(false);
+ ABORT();
}
ASSERT((*itr)->GetTypeId() == TYPEID_UNIT);
@@ -9433,7 +9490,7 @@ void Unit::GetAllMinionsByEntry(std::list<Creature*>& Minions, uint32 entry)
Unit* unit = *itr;
++itr;
if (unit->GetEntry() == entry && unit->GetTypeId() == TYPEID_UNIT
- && unit->ToCreature()->IsSummon()) // minion, actually
+ && unit->IsSummon()) // minion, actually
Minions.push_back(unit->ToCreature());
}
}
@@ -9445,7 +9502,7 @@ void Unit::RemoveAllMinionsByEntry(uint32 entry)
Unit* unit = *itr;
++itr;
if (unit->GetEntry() == entry && unit->GetTypeId() == TYPEID_UNIT
- && unit->ToCreature()->IsSummon()) // minion, actually
+ && unit->IsSummon()) // minion, actually
unit->ToTempSummon()->UnSummon();
// i think this is safe because i have never heard that a despawned minion will trigger a same minion
}
@@ -9545,7 +9602,7 @@ int32 Unit::DealHeal(Unit* victim, uint32 addhealth)
Unit* unit = this;
- if (GetTypeId() == TYPEID_UNIT && ToCreature()->IsTotem())
+ if (GetTypeId() == TYPEID_UNIT && IsTotem())
unit = GetOwner();
if (Player* player = unit->ToPlayer())
@@ -9589,16 +9646,15 @@ Unit* Unit::GetMagicHitRedirectTarget(Unit* victim, SpellInfo const* spellInfo)
{
if (Unit* magnet = (*itr)->GetBase()->GetCaster())
if (spellInfo->CheckExplicitTarget(this, magnet) == SPELL_CAST_OK
- && spellInfo->CheckTarget(this, magnet, false) == SPELL_CAST_OK
&& _IsValidAttackTarget(magnet, spellInfo))
{
/// @todo handle this charge drop by proc in cast phase on explicit target
- if (victim && spellInfo->Speed > 0.0f)
+ if (spellInfo->Speed > 0.0f)
{
// Set up missile speed based delay
uint32 delay = uint32(std::floor(std::max<float>(victim->GetDistance(this), 5.0f) / spellInfo->Speed * 1000.0f));
// Schedule charge drop
- (*itr)->GetBase()->DropChargeDelayed(delay,AURA_REMOVE_BY_EXPIRE);
+ (*itr)->GetBase()->DropChargeDelayed(delay, AURA_REMOVE_BY_EXPIRE);
}
else
(*itr)->GetBase()->DropCharge(AURA_REMOVE_BY_EXPIRE);
@@ -9687,7 +9743,7 @@ Unit* Unit::GetNextRandomRaidMemberOrPet(float radius)
if (GetTypeId() == TYPEID_PLAYER)
player = ToPlayer();
// Should we enable this also for charmed units?
- else if (GetTypeId() == TYPEID_UNIT && ToCreature()->IsPet())
+ else if (GetTypeId() == TYPEID_UNIT && IsPet())
player = GetOwner()->ToPlayer();
if (!player)
@@ -9837,7 +9893,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
return pdamage;
// For totems get damage bonus from owner
- if (GetTypeId() == TYPEID_UNIT && ToCreature()->IsTotem())
+ if (GetTypeId() == TYPEID_UNIT && IsTotem())
if (Unit* owner = GetOwner())
return owner->SpellDamageBonusDone(victim, spellProto, pdamage, damagetype);
@@ -9949,15 +10005,11 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
DoneTotal += int32(DoneAdvertisedBenefit * coeff * factorMod);
}
- float tmpDamage = float(int32(pdamage) + DoneTotal);
- // SPELLMOD_DOT will be applied in AuraEffect::HandlePeriodicDamageAurasTick.
- if (damagetype != DOT)
- {
- tmpDamage *= SpellDamagePctDone(victim, spellProto, damagetype);
- // apply spellmod to Done damage (flat and pct)
- if (Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_DAMAGE, tmpDamage);
- }
+ // Done Percentage for DOT is already calculated, no need to do it again. The percentage mod is applied in Aura::HandleAuraSpecificMods.
+ float tmpDamage = (int32(pdamage) + DoneTotal) * (damagetype == DOT ? 1.0f : SpellDamagePctDone(victim, spellProto, damagetype));
+ // apply spellmod to Done damage (flat and pct)
+ if (Player* modOwner = GetSpellModOwner())
+ modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, tmpDamage);
return uint32(std::max(tmpDamage, 0.0f));
}
@@ -9972,14 +10024,14 @@ float Unit::SpellDamagePctDone(Unit* victim, SpellInfo const* spellProto, Damage
return 1.0f;
// For totems pct done mods are calculated when its calculation is run on the player in SpellDamageBonusDone.
- if (GetTypeId() == TYPEID_UNIT && ToCreature()->IsTotem())
+ if (GetTypeId() == TYPEID_UNIT && IsTotem())
return 1.0f;
// Done total percent damage auras
float DoneTotalMod = 1.0f;
// Pet damage?
- if (GetTypeId() == TYPEID_UNIT && !ToCreature()->IsPet())
+ if (GetTypeId() == TYPEID_UNIT && !IsPet())
DoneTotalMod *= ToCreature()->GetSpellDamageMod(ToCreature()->GetCreatureTemplate()->rank);
AuraEffectList const& mModDamagePercentDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
@@ -10797,15 +10849,11 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
DoneTotal = 0;
}
- float heal = float(int32(healamount) + DoneTotal);
- // SPELLMOD_DOT will be applied in AuraEffect::HandlePeriodicHealAurasTick.
- if (damagetype != DOT)
- {
- heal *= SpellHealingPctDone(victim, spellProto);
- // apply spellmod to Done amount
- if (Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_DAMAGE, heal);
- }
+ // Done Percentage for DOT is already calculated, no need to do it again. The percentage mod is applied in Aura::HandleAuraSpecificMods.
+ float heal = float(int32(healamount) + DoneTotal) * (damagetype == DOT ? 1.0f : SpellHealingPctDone(victim, spellProto));
+ // apply spellmod to Done amount
+ if (Player* modOwner = GetSpellModOwner())
+ modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, heal);
return uint32(std::max(heal, 0.0f));
}
@@ -11136,6 +11184,26 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo) const
return false;
}
+uint32 Unit::GetSchoolImmunityMask() const
+{
+ uint32 mask = 0;
+ SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_SCHOOL];
+ for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr)
+ mask |= itr->type;
+
+ return mask;
+}
+
+uint32 Unit::GetMechanicImmunityMask() const
+{
+ uint32 mask = 0;
+ SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
+ for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr)
+ mask |= (1 << itr->type);
+
+ return mask;
+}
+
bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const
{
if (!spellInfo || !spellInfo->Effects[index].IsEffect())
@@ -11850,8 +11918,8 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo
if (IsOnVehicle(target) || m_vehicle->GetBase()->IsOnVehicle(target))
return false;
- // can't attack invisible (ignore stealth for aoe spells) also if the area being looked at is from a spell use the dynamic object created instead of the casting unit.
- if ((!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && (obj ? !obj->CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea()) : !CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea())))
+ // can't attack invisible (ignore stealth for aoe spells) also if the area being looked at is from a spell use the dynamic object created instead of the casting unit. Ignore stealth if target is player and unit in combat with same player
+ if ((!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && (obj ? !obj->CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea()) : !CanSeeOrDetect(target, (bySpell && bySpell->IsAffectingArea()) || (target->GetTypeId() == TYPEID_PLAYER && target->HasStealthAura() && target->IsInCombat() && IsInCombatWith(target)))))
return false;
// can't attack dead
@@ -11887,9 +11955,9 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo
|| target->GetReactionTo(this) > REP_NEUTRAL)
return false;
- // Not all neutral creatures can be attacked
+ // Not all neutral creatures can be attacked (even some unfriendly faction does not react aggresive to you, like Sporaggar)
if (GetReactionTo(target) == REP_NEUTRAL &&
- target->GetReactionTo(this) == REP_NEUTRAL)
+ target->GetReactionTo(this) <= REP_NEUTRAL)
{
if (!(target->GetTypeId() == TYPEID_PLAYER && GetTypeId() == TYPEID_PLAYER) &&
!(target->GetTypeId() == TYPEID_UNIT && GetTypeId() == TYPEID_UNIT))
@@ -12294,6 +12362,13 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced)
/// @todo possible affect only on MOVE_RUN
if (int32 normalization = GetMaxPositiveAuraModifier(SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED))
{
+ if (Creature* creature = ToCreature())
+ {
+ uint32 immuneMask = creature->GetCreatureTemplate()->MechanicImmuneMask;
+ if (immuneMask & (1 << MECHANIC_SNARE) || immuneMask & (1 << MECHANIC_DAZE))
+ break;
+ }
+
// Use speed from aura
float max_speed = normalization / (IsControlledByPlayer() ? playerBaseMoveSpeed[mtype] : baseMoveSpeed[mtype]);
if (speed > max_speed)
@@ -12315,15 +12390,15 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced)
// Apply strongest slow aura mod to speed
int32 slow = GetMaxNegativeAuraModifier(SPELL_AURA_MOD_DECREASE_SPEED);
if (slow)
- {
AddPct(speed, slow);
- if (float minSpeedMod = (float)GetMaxPositiveAuraModifier(SPELL_AURA_MOD_MINIMUM_SPEED))
- {
- float min_speed = minSpeedMod / 100.0f;
- if (speed < min_speed)
- speed = min_speed;
- }
+
+ if (float minSpeedMod = (float)GetMaxPositiveAuraModifier(SPELL_AURA_MOD_MINIMUM_SPEED))
+ {
+ float min_speed = minSpeedMod / 100.0f;
+ if (speed < min_speed)
+ speed = min_speed;
}
+
SetSpeed(mtype, speed, forced);
}
@@ -12512,7 +12587,7 @@ bool Unit::CanHaveThreatList(bool skipAliveCheck) const
return false;
// totems can not have threat list
- if (ToCreature()->IsTotem())
+ if (IsTotem())
return false;
// vehicles can not have threat list
@@ -12913,9 +12988,6 @@ void Unit::ModSpellCastTime(SpellInfo const* spellInfo, int32 & castTime, Spell*
if (!spellInfo || castTime < 0)
return;
- if (spellInfo->IsChanneled() && !spellInfo->HasAttribute(SPELL_ATTR5_HASTE_AFFECT_DURATION))
- return;
-
// called from caster
if (Player* modOwner = GetSpellModOwner())
modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CASTING_TIME, castTime, spell);
@@ -12929,6 +13001,25 @@ void Unit::ModSpellCastTime(SpellInfo const* spellInfo, int32 & castTime, Spell*
castTime = 500;
}
+void Unit::ModSpellDurationTime(SpellInfo const* spellInfo, int32 & duration, Spell* spell)
+{
+ if (!spellInfo || duration < 0)
+ return;
+
+ if (spellInfo->IsChanneled() && !spellInfo->HasAttribute(SPELL_ATTR5_HASTE_AFFECT_DURATION))
+ return;
+
+ // called from caster
+ if (Player* modOwner = GetSpellModOwner())
+ modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CASTING_TIME, duration, spell);
+
+ if (!(spellInfo->HasAttribute(SPELL_ATTR0_ABILITY) || spellInfo->HasAttribute(SPELL_ATTR0_TRADESPELL) || spellInfo->HasAttribute(SPELL_ATTR3_NO_DONE_BONUS)) &&
+ ((GetTypeId() == TYPEID_PLAYER && spellInfo->SpellFamilyName) || GetTypeId() == TYPEID_UNIT))
+ duration = int32(float(duration) * GetFloatValue(UNIT_MOD_CAST_SPEED));
+ else if (spellInfo->HasAttribute(SPELL_ATTR0_REQ_AMMO) && !spellInfo->HasAttribute(SPELL_ATTR2_AUTOREPEAT_FLAG))
+ duration = int32(float(duration) * m_modAttackSpeedPct[RANGED_ATTACK]);
+}
+
DiminishingLevels Unit::GetDiminishing(DiminishingGroup group)
{
for (Diminishing::iterator i = m_Diminishing.begin(); i != m_Diminishing.end(); ++i)
@@ -13104,6 +13195,10 @@ bool Unit::IsInFeralForm() const
bool Unit::IsInDisallowedMountForm() const
{
+ if (SpellInfo const* transformSpellInfo = sSpellMgr->GetSpellInfo(getTransForm()))
+ if (transformSpellInfo->HasAttribute(SPELL_ATTR0_CASTABLE_WHILE_MOUNTED))
+ return false;
+
if (ShapeshiftForm form = GetShapeshiftForm())
{
SpellShapeshiftEntry const* shapeshift = sSpellShapeshiftStore.LookupEntry(form);
@@ -13351,7 +13446,7 @@ void Unit::SetLevel(uint8 lvl)
if (player->GetGroup())
player->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_LEVEL);
- sWorld->UpdateCharacterNameDataLevel(GetGUID(), lvl);
+ sWorld->UpdateCharacterInfoLevel(GetGUID(), lvl);
}
}
@@ -13533,7 +13628,7 @@ void Unit::RemoveFromWorld()
if (GetCharmerGUID())
{
TC_LOG_FATAL("entities.unit", "Unit %u has charmer guid when removed from world", GetEntry());
- ASSERT(false);
+ ABORT();
}
if (Unit* owner = GetOwner())
@@ -13541,7 +13636,7 @@ void Unit::RemoveFromWorld()
if (owner->m_Controlled.find(this) != owner->m_Controlled.end())
{
TC_LOG_FATAL("entities.unit", "Unit %u is in controlled list of %u when removed from world", GetEntry(), owner->GetEntry());
- ASSERT(false);
+ ABORT();
}
}
@@ -13694,16 +13789,16 @@ void CharmInfo::InitPossessCreateSpells()
break;
}
- for (uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i)
+ for (uint8 i = 0; i < CREATURE_MAX_SPELLS; ++i)
{
uint32 spellId = _unit->ToCreature()->m_spells[i];
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
- if (spellInfo && !spellInfo->HasAttribute(SPELL_ATTR0_CASTABLE_WHILE_DEAD))
+ if (spellInfo)
{
if (spellInfo->IsPassive())
_unit->CastSpell(_unit, spellInfo, true);
else
- AddSpellToActionBar(spellInfo, ACT_PASSIVE);
+ AddSpellToActionBar(spellInfo, ACT_PASSIVE, i % MAX_UNIT_ACTION_BAR_INDEX);
}
}
}
@@ -13726,7 +13821,7 @@ void CharmInfo::InitCharmCreateSpells()
uint32 spellId = _unit->ToCreature()->m_spells[x];
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
- if (!spellInfo || spellInfo->HasAttribute(SPELL_ATTR0_CASTABLE_WHILE_DEAD))
+ if (!spellInfo)
{
_charmspells[x].SetActionAndType(spellId, ACT_DISABLED);
continue;
@@ -13761,11 +13856,12 @@ void CharmInfo::InitCharmCreateSpells()
}
}
-bool CharmInfo::AddSpellToActionBar(SpellInfo const* spellInfo, ActiveStates newstate)
+bool CharmInfo::AddSpellToActionBar(SpellInfo const* spellInfo, ActiveStates newstate, uint8 preferredSlot)
{
uint32 spell_id = spellInfo->Id;
uint32 first_id = spellInfo->GetFirstRankSpell()->Id;
+ ASSERT(preferredSlot < MAX_UNIT_ACTION_BAR_INDEX);
// new spell rank can be already listed
for (uint8 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i)
{
@@ -13782,9 +13878,10 @@ bool CharmInfo::AddSpellToActionBar(SpellInfo const* spellInfo, ActiveStates new
// or use empty slot in other case
for (uint8 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i)
{
- if (!PetActionBar[i].GetAction() && PetActionBar[i].IsActionBarForSpell())
+ uint8 j = (preferredSlot + i) % MAX_UNIT_ACTION_BAR_INDEX;
+ if (!PetActionBar[j].GetAction() && PetActionBar[j].IsActionBarForSpell())
{
- SetActionBar(i, spell_id, newstate == ACT_DECIDE ? spellInfo->IsAutocastable() ? ACT_DISABLED : ACT_PASSIVE : newstate);
+ SetActionBar(j, spell_id, newstate == ACT_DECIDE ? spellInfo->IsAutocastable() ? ACT_DISABLED : ACT_PASSIVE : newstate);
return true;
}
}
@@ -14103,9 +14200,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
continue;
// do checks using conditions table
- ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_PROC, spellProto->Id);
- ConditionSourceInfo condInfo = ConditionSourceInfo(eventInfo.GetActor(), eventInfo.GetActionTarget());
- if (!sConditionMgr->IsObjectMeetToConditions(condInfo, conditions))
+ if (!sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_SPELL_PROC, spellProto->Id, eventInfo.GetActor(), eventInfo.GetActionTarget()))
continue;
// AuraScript Hook
@@ -14460,7 +14555,7 @@ Player* Unit::GetSpellModOwner() const
if (Player* player = const_cast<Unit*>(this)->ToPlayer())
return player;
- if (ToCreature()->IsPet() || ToCreature()->IsTotem())
+ if (IsPet() || IsTotem())
{
if (Unit* owner = GetOwner())
if (Player* player = owner->ToPlayer())
@@ -14574,6 +14669,9 @@ bool Unit::IsPolymorphed() const
void Unit::SetDisplayId(uint32 modelId)
{
SetUInt32Value(UNIT_FIELD_DISPLAYID, modelId);
+ // Set Gender by modelId
+ if (CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(modelId))
+ SetByteValue(UNIT_FIELD_BYTES_0, 2, minfo->gender);
}
void Unit::RestoreDisplayId()
@@ -14731,7 +14829,7 @@ void Unit::ApplyCastTimePercentMod(float val, bool apply)
uint32 Unit::GetCastingTimeForBonus(SpellInfo const* spellProto, DamageEffectType damagetype, uint32 CastingTime) const
{
// Not apply this to creature cast spells with casttime == 0
- if (CastingTime == 0 && GetTypeId() == TYPEID_UNIT && !ToCreature()->IsPet())
+ if (CastingTime == 0 && GetTypeId() == TYPEID_UNIT && !IsPet())
return 3500;
if (CastingTime > 7000) CastingTime = 7000;
@@ -14831,7 +14929,7 @@ void Unit::UpdateAuraForGroup(uint8 slot)
player->SetAuraUpdateMaskForRaid(slot);
}
}
- else if (GetTypeId() == TYPEID_UNIT && ToCreature()->IsPet())
+ else if (GetTypeId() == TYPEID_UNIT && IsPet())
{
Pet* pet = ((Pet*)this);
if (pet->isControlled())
@@ -15723,7 +15821,7 @@ void Unit::SetFeared(bool apply)
}
if (Player* player = ToPlayer())
- if(!player->HasUnitState(UNIT_STATE_POSSESSED))
+ if (!player->HasUnitState(UNIT_STATE_POSSESSED))
player->SetClientControl(this, !apply);
}
@@ -15765,11 +15863,11 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au
ASSERT(type != CHARM_TYPE_POSSESS || charmer->GetTypeId() == TYPEID_PLAYER);
ASSERT((type == CHARM_TYPE_VEHICLE) == IsVehicle());
- TC_LOG_DEBUG("entities.unit", "SetCharmedBy: charmer %u (GUID %u), charmed %u (GUID %u), type %u.", charmer->GetEntry(), charmer->GetGUIDLow(), GetEntry(), GetGUIDLow(), uint32(type));
+ TC_LOG_DEBUG("entities.unit", "SetCharmedBy: charmer %u (GUID %u), charmed %u (GUID %u), type %u.", charmer->GetEntry(), charmer->GetGUID().GetCounter(), GetEntry(), GetGUID().GetCounter(), uint32(type));
if (this == charmer)
{
- TC_LOG_FATAL("entities.unit", "Unit::SetCharmedBy: Unit %u (GUID %u) is trying to charm itself!", GetEntry(), GetGUIDLow());
+ TC_LOG_FATAL("entities.unit", "Unit::SetCharmedBy: Unit %u (GUID %u) is trying to charm itself!", GetEntry(), GetGUID().GetCounter());
return false;
}
@@ -15778,14 +15876,14 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au
if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->GetTransport())
{
- TC_LOG_FATAL("entities.unit", "Unit::SetCharmedBy: Player on transport is trying to charm %u (GUID %u)", GetEntry(), GetGUIDLow());
+ TC_LOG_FATAL("entities.unit", "Unit::SetCharmedBy: Player on transport is trying to charm %u (GUID %u)", GetEntry(), GetGUID().GetCounter());
return false;
}
// Already charmed
if (GetCharmerGUID())
{
- TC_LOG_FATAL("entities.unit", "Unit::SetCharmedBy: %u (GUID %u) has already been charmed but %u (GUID %u) is trying to charm it!", GetEntry(), GetGUIDLow(), charmer->GetEntry(), charmer->GetGUIDLow());
+ TC_LOG_FATAL("entities.unit", "Unit::SetCharmedBy: %u (GUID %u) has already been charmed but %u (GUID %u) is trying to charm it!", GetEntry(), GetGUID().GetCounter(), charmer->GetEntry(), charmer->GetGUID().GetCounter());
return false;
}
@@ -15812,7 +15910,7 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au
// StopCastingCharm may remove a possessed pet?
if (!IsInWorld())
{
- TC_LOG_FATAL("entities.unit", "Unit::SetCharmedBy: %u (GUID %u) is not in world but %u (GUID %u) is trying to charm it!", GetEntry(), GetGUIDLow(), charmer->GetEntry(), charmer->GetGUIDLow());
+ TC_LOG_FATAL("entities.unit", "Unit::SetCharmedBy: %u (GUID %u) is not in world but %u (GUID %u) is trying to charm it!", GetEntry(), GetGUID().GetCounter(), charmer->GetEntry(), charmer->GetGUID().GetCounter());
return false;
}
@@ -15909,7 +16007,7 @@ void Unit::RemoveCharmedBy(Unit* charmer)
{
// TC_LOG_FATAL("entities.unit", "Unit::RemoveCharmedBy: this: " UI64FMTD " true charmer: " UI64FMTD " false charmer: " UI64FMTD,
// GetGUID(), GetCharmerGUID(), charmer->GetGUID());
-// ASSERT(false);
+// ABORT();
return;
}
@@ -15944,7 +16042,7 @@ void Unit::RemoveCharmedBy(Unit* charmer)
// Vehicle should not attack its passenger after he exists the seat
if (type != CHARM_TYPE_VEHICLE)
- LastCharmerGUID = charmer->GetGUID();
+ LastCharmerGUID = ASSERT_NOTNULL(charmer)->GetGUID();
}
// If charmer still exists
@@ -15999,7 +16097,7 @@ void Unit::RemoveCharmedBy(Unit* charmer)
// a guardian should always have charminfo
if (playerCharmer && this != charmer->GetFirstControlled())
playerCharmer->SendRemoveControlBar();
- else if (GetTypeId() == TYPEID_PLAYER || (GetTypeId() == TYPEID_UNIT && !ToCreature()->IsGuardian()))
+ else if (GetTypeId() == TYPEID_PLAYER || (GetTypeId() == TYPEID_UNIT && !IsGuardian()))
DeleteCharmInfo();
}
@@ -16457,7 +16555,7 @@ void Unit::KnockbackFrom(float x, float y, float speedXY, float speedZ)
data << float(-speedZ); // Z Movement speed (vertical)
player->GetSession()->SendPacket(&data);
-
+
if (player->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) || player->HasAuraType(SPELL_AURA_FLY))
player->SetCanFly(true, true);
}
@@ -16806,9 +16904,7 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId)
continue;
//! Check database conditions
- ConditionList conds = sConditionMgr->GetConditionsForSpellClickEvent(spellClickEntry, itr->second.spellId);
- ConditionSourceInfo info = ConditionSourceInfo(clicker, this);
- if (!sConditionMgr->IsObjectMeetToConditions(info, conds))
+ if (!sConditionMgr->IsObjectMeetingSpellClickConditions(spellClickEntry, itr->second.spellId, clicker, this))
continue;
Unit* caster = (itr->second.castFlags & NPC_CLICK_CAST_CASTER_CLICKER) ? clicker : this;
@@ -16904,6 +17000,12 @@ void Unit::_EnterVehicle(Vehicle* vehicle, int8 seatId, AuraApplication const* a
}
}
+ // If vehicle flag for fixed position set (cannons), or if the following hardcoded units, then set state rooted
+ // 30236 | Argent Cannon
+ // 39759 | Tankbuster Cannon
+ if ((vehicle->GetVehicleInfo()->m_flags & VEHICLE_FLAG_FIXED_POSITION) || vehicle->GetBase()->GetEntry() == 30236 || vehicle->GetBase()->GetEntry() == 39759)
+ SetControlled(true, UNIT_STATE_ROOT);
+
ASSERT(!m_vehicle);
(void)vehicle->AddPassenger(this, seatId);
}
@@ -17206,7 +17308,7 @@ void Unit::SendChangeCurrentVictimOpcode(HostileReference* pHostileReference)
for (ThreatContainer::StorageType::const_iterator itr = tlist.begin(); itr != tlist.end(); ++itr)
{
data << (*itr)->getUnitGuid().WriteAsPacked();
- data << uint32((*itr)->getThreat());
+ data << uint32((*itr)->getThreat() * 100);
}
SendMessageToSet(&data, false);
}
@@ -17689,22 +17791,8 @@ void Unit::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target)
}
if (cinfo->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER)
- {
if (target->IsGameMaster())
- {
- if (cinfo->Modelid1)
- displayId = cinfo->Modelid1; // Modelid1 is a visible model for gms
- else
- displayId = 17519; // world visible trigger's model
- }
- else
- {
- if (cinfo->Modelid2)
- displayId = cinfo->Modelid2; // Modelid2 is an invisible model for players
- else
- displayId = 11686; // world invisible trigger's model
- }
- }
+ displayId = cinfo->GetFirstVisibleModel();
}
fieldBuffer << uint32(displayId);
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 2593ca2c728..2ddbe398f76 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -898,6 +898,12 @@ public:
uint32 GetHitMask() const { return _hitMask; }
SpellInfo const* GetSpellInfo() const { return NULL; }
+ SpellInfo const* EnsureSpellInfo() const
+ {
+ SpellInfo const* spellInfo = GetSpellInfo();
+ ASSERT(spellInfo);
+ return spellInfo;
+ }
SpellSchoolMask GetSchoolMask() const { return SPELL_SCHOOL_MASK_NONE; }
DamageInfo* GetDamageInfo() const { return _damageInfo; }
@@ -1119,7 +1125,7 @@ struct CharmInfo
void InitEmptyActionBar(bool withAttack = true);
//return true if successful
- bool AddSpellToActionBar(SpellInfo const* spellInfo, ActiveStates newstate = ACT_DECIDE);
+ bool AddSpellToActionBar(SpellInfo const* spellInfo, ActiveStates newstate = ACT_DECIDE, uint8 preferredSlot = 0);
bool RemoveSpellFromActionBar(uint32 spell_id);
void LoadPetActionBar(const std::string& data);
void BuildActionBar(WorldPacket* data);
@@ -1395,6 +1401,7 @@ class Unit : public WorldObject
void DealDamageMods(Unit* victim, uint32 &damage, uint32* absorb);
uint32 DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDamage = NULL, DamageEffectType damagetype = DIRECT_DAMAGE, SpellSchoolMask damageSchoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellInfo const* spellProto = NULL, bool durabilityLoss = true);
void Kill(Unit* victim, bool durabilityLoss = true);
+ void KillSelf(bool durabilityLoss = true) { Kill(this, durabilityLoss); }
int32 DealHeal(Unit* victim, uint32 addhealth);
void ProcDamageAndSpell(Unit* victim, uint32 procAttacker, uint32 procVictim, uint32 procEx, uint32 amount, WeaponAttackType attType = BASE_ATTACK, SpellInfo const* procSpell = NULL, SpellInfo const* procAura = NULL);
@@ -1480,6 +1487,7 @@ class Unit : public WorldObject
bool IsInFlight() const { return HasUnitState(UNIT_STATE_IN_FLIGHT); }
bool IsInCombat() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); }
+ bool IsInCombatWith(Unit const* who) const;
void CombatStart(Unit* target, bool initialAggro = true);
void SetInCombatState(bool PvP, Unit* enemy = NULL);
void SetInCombatWith(Unit* enemy);
@@ -1958,6 +1966,8 @@ class Unit : public WorldObject
void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply);
void ApplySpellDispelImmunity(const SpellInfo* spellProto, DispelType type, bool apply);
virtual bool IsImmunedToSpell(SpellInfo const* spellInfo) const; // redefined in Creature
+ uint32 GetSchoolImmunityMask() const;
+ uint32 GetMechanicImmunityMask() const;
bool IsImmunedToDamage(SpellSchoolMask meleeSchoolMask) const;
bool IsImmunedToDamage(SpellInfo const* spellInfo) const;
@@ -1979,6 +1989,7 @@ class Unit : public WorldObject
int32 CalcSpellDuration(SpellInfo const* spellProto);
int32 ModSpellDuration(SpellInfo const* spellProto, Unit const* target, int32 duration, bool positive, uint32 effectMask);
void ModSpellCastTime(SpellInfo const* spellProto, int32& castTime, Spell* spell = NULL);
+ void ModSpellDurationTime(SpellInfo const* spellProto, int32& castTime, Spell* spell = NULL);
float CalculateLevelPenalty(SpellInfo const* spellProto) const;
void addFollower(FollowerReference* pRef) { m_FollowingRefManager.insertFirst(pRef); }
diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp
index b6f9534ac51..982b931fd4f 100755
--- a/src/server/game/Entities/Vehicle/Vehicle.cpp
+++ b/src/server/game/Entities/Vehicle/Vehicle.cpp
@@ -115,12 +115,12 @@ void Vehicle::Uninstall()
if (_status == STATUS_UNINSTALLING && !GetBase()->HasUnitTypeMask(UNIT_MASK_MINION))
{
TC_LOG_ERROR("entities.vehicle", "Vehicle GuidLow: %u, Entry: %u attempts to uninstall, but already has STATUS_UNINSTALLING! "
- "Check Uninstall/PassengerBoarded script hooks for errors.", _me->GetGUIDLow(), _me->GetEntry());
+ "Check Uninstall/PassengerBoarded script hooks for errors.", _me->GetGUID().GetCounter(), _me->GetEntry());
return;
}
_status = STATUS_UNINSTALLING;
- TC_LOG_DEBUG("entities.vehicle", "Vehicle::Uninstall Entry: %u, GuidLow: %u", _creatureEntry, _me->GetGUIDLow());
+ TC_LOG_DEBUG("entities.vehicle", "Vehicle::Uninstall Entry: %u, GuidLow: %u", _creatureEntry, _me->GetGUID().GetCounter());
RemoveAllPassengers();
if (GetBase()->GetTypeId() == TYPEID_UNIT)
@@ -143,7 +143,7 @@ void Vehicle::Reset(bool evading /*= false*/)
if (GetBase()->GetTypeId() != TYPEID_UNIT)
return;
- TC_LOG_DEBUG("entities.vehicle", "Vehicle::Reset (Entry: %u, GuidLow: %u, DBGuid: %u)", GetCreatureEntry(), _me->GetGUIDLow(), _me->ToCreature()->GetDBTableGUIDLow());
+ TC_LOG_DEBUG("entities.vehicle", "Vehicle::Reset (Entry: %u, GuidLow: %u, DBGuid: %u)", GetCreatureEntry(), _me->GetGUID().GetCounter(), _me->ToCreature()->GetSpawnId());
ApplyAllImmunities();
InstallAllAccessories(evading);
@@ -192,6 +192,12 @@ void Vehicle::ApplyAllImmunities()
_me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, true);
}
+ // If vehicle flag for fixed position set (cannons), or if the following hardcoded units, then set state rooted
+ // 30236 | Argent Cannon
+ // 39759 | Tankbuster Cannon
+ if ((GetVehicleInfo()->m_flags & VEHICLE_FLAG_FIXED_POSITION) || GetBase()->GetEntry() == 30236 || GetBase()->GetEntry() == 39759)
+ _me->SetControlled(true, UNIT_STATE_ROOT);
+
// Different immunities for vehicles goes below
switch (GetVehicleInfo()->m_ID)
{
@@ -221,7 +227,7 @@ void Vehicle::ApplyAllImmunities()
void Vehicle::RemoveAllPassengers()
{
- TC_LOG_DEBUG("entities.vehicle", "Vehicle::RemoveAllPassengers. Entry: %u, GuidLow: %u", _creatureEntry, _me->GetGUIDLow());
+ TC_LOG_DEBUG("entities.vehicle", "Vehicle::RemoveAllPassengers. Entry: %u, GuidLow: %u", _creatureEntry, _me->GetGUID().GetCounter());
/// Setting to_Abort to true will cause @VehicleJoinEvent::Abort to be executed on next @Unit::UpdateEvents call
/// This will properly "reset" the pending join process for the passenger.
@@ -358,13 +364,13 @@ void Vehicle::InstallAccessory(uint32 entry, int8 seatId, bool minion, uint8 typ
if (_status == STATUS_UNINSTALLING)
{
TC_LOG_ERROR("entities.vehicle", "Vehicle (GuidLow: %u, DB GUID: %u, Entry: %u) attempts to install accessory (Entry: %u) on seat %d with STATUS_UNINSTALLING! "
- "Check Uninstall/PassengerBoarded script hooks for errors.", _me->GetGUIDLow(),
- (_me->GetTypeId() == TYPEID_UNIT ? _me->ToCreature()->GetDBTableGUIDLow() : _me->GetGUIDLow()), GetCreatureEntry(), entry, (int32)seatId);
+ "Check Uninstall/PassengerBoarded script hooks for errors.", _me->GetGUID().GetCounter(),
+ (_me->GetTypeId() == TYPEID_UNIT ? _me->ToCreature()->GetSpawnId() : _me->GetGUID().GetCounter()), GetCreatureEntry(), entry, (int32)seatId);
return;
}
TC_LOG_DEBUG("entities.vehicle", "Vehicle (GuidLow: %u, DB Guid: %u, Entry %u): installing accessory (Entry: %u) on seat: %d",
- _me->GetGUIDLow(), (_me->GetTypeId() == TYPEID_UNIT ? _me->ToCreature()->GetDBTableGUIDLow() : _me->GetGUIDLow()), GetCreatureEntry(),
+ _me->GetGUID().GetCounter(), (_me->GetTypeId() == TYPEID_UNIT ? _me->ToCreature()->GetSpawnId() : _me->GetGUID().GetCounter()), GetCreatureEntry(),
entry, (int32)seatId);
TempSummon* accessory = _me->SummonCreature(entry, *_me, TempSummonType(type), summonTime);
@@ -399,13 +405,13 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId)
if (_status == STATUS_UNINSTALLING)
{
TC_LOG_ERROR("entities.vehicle", "Passenger GuidLow: %u, Entry: %u, attempting to board vehicle GuidLow: %u, Entry: %u during uninstall! SeatId: %d",
- unit->GetGUIDLow(), unit->GetEntry(), _me->GetGUIDLow(), _me->GetEntry(), (int32)seatId);
+ unit->GetGUID().GetCounter(), unit->GetEntry(), _me->GetGUID().GetCounter(), _me->GetEntry(), (int32)seatId);
return false;
}
TC_LOG_DEBUG("entities.vehicle", "Unit %s scheduling enter vehicle (entry: %u, vehicleId: %u, guid: %u (dbguid: %u) on seat %d",
- unit->GetName().c_str(), _me->GetEntry(), _vehicleInfo->m_ID, _me->GetGUIDLow(),
- (_me->GetTypeId() == TYPEID_UNIT ? _me->ToCreature()->GetDBTableGUIDLow() : 0), (int32)seatId);
+ unit->GetName().c_str(), _me->GetEntry(), _vehicleInfo->m_ID, _me->GetGUID().GetCounter(),
+ (_me->GetTypeId() == TYPEID_UNIT ? _me->ToCreature()->GetSpawnId() : 0), (int32)seatId);
// The seat selection code may kick other passengers off the vehicle.
// While the validity of the following may be arguable, it is possible that when such a passenger
@@ -474,7 +480,7 @@ Vehicle* Vehicle::RemovePassenger(Unit* unit)
ASSERT(seat != Seats.end());
TC_LOG_DEBUG("entities.vehicle", "Unit %s exit vehicle entry %u id %u dbguid %u seat %d",
- unit->GetName().c_str(), _me->GetEntry(), _vehicleInfo->m_ID, _me->GetGUIDLow(), (int32)seat->first);
+ unit->GetName().c_str(), _me->GetEntry(), _vehicleInfo->m_ID, _me->GetGUID().GetCounter(), (int32)seat->first);
if (seat->second.SeatInfo->CanEnterOrExit() && ++UsableSeatNum)
_me->SetFlag(UNIT_NPC_FLAGS, (_me->GetTypeId() == TYPEID_PLAYER ? UNIT_NPC_FLAG_PLAYER_VEHICLE : UNIT_NPC_FLAG_SPELLCLICK));
@@ -849,7 +855,7 @@ void VehicleJoinEvent::Abort(uint64)
if (Target)
{
TC_LOG_DEBUG("entities.vehicle", "Passenger GuidLow: %u, Entry: %u, board on vehicle GuidLow: %u, Entry: %u SeatId: %d cancelled",
- Passenger->GetGUIDLow(), Passenger->GetEntry(), Target->GetBase()->GetGUIDLow(), Target->GetBase()->GetEntry(), (int32)Seat->first);
+ Passenger->GetGUID().GetCounter(), Passenger->GetEntry(), Target->GetBase()->GetGUID().GetCounter(), Target->GetBase()->GetEntry(), (int32)Seat->first);
/// @SPELL_AURA_CONTROL_VEHICLE auras can be applied even when the passenger is not (yet) on the vehicle.
/// When this code is triggered it means that something went wrong in @Vehicle::AddPassenger, and we should remove
@@ -858,7 +864,7 @@ void VehicleJoinEvent::Abort(uint64)
}
else
TC_LOG_DEBUG("entities.vehicle", "Passenger GuidLow: %u, Entry: %u, board on uninstalled vehicle SeatId: %d cancelled",
- Passenger->GetGUIDLow(), Passenger->GetEntry(), (int32)Seat->first);
+ Passenger->GetGUID().GetCounter(), Passenger->GetEntry(), (int32)Seat->first);
if (Passenger->IsInWorld() && Passenger->HasUnitTypeMask(UNIT_MASK_ACCESSORY))
Passenger->ToCreature()->DespawnOrUnsummon();
diff --git a/src/server/game/Entities/Vehicle/VehicleDefines.h b/src/server/game/Entities/Vehicle/VehicleDefines.h
index c00bc429f38..3726e9ddf8f 100644
--- a/src/server/game/Entities/Vehicle/VehicleDefines.h
+++ b/src/server/game/Entities/Vehicle/VehicleDefines.h
@@ -44,7 +44,8 @@ enum VehicleFlags
VEHICLE_FLAG_FULLSPEEDPITCHING = 0x00000020, // Sets MOVEFLAG2_FULLSPEEDPITCHING
VEHICLE_FLAG_CUSTOM_PITCH = 0x00000040, // If set use pitchMin and pitchMax from DBC, otherwise pitchMin = -pi/2, pitchMax = pi/2
VEHICLE_FLAG_ADJUST_AIM_ANGLE = 0x00000400, // Lua_IsVehicleAimAngleAdjustable
- VEHICLE_FLAG_ADJUST_AIM_POWER = 0x00000800 // Lua_IsVehicleAimPowerAdjustable
+ VEHICLE_FLAG_ADJUST_AIM_POWER = 0x00000800, // Lua_IsVehicleAimPowerAdjustable
+ VEHICLE_FLAG_FIXED_POSITION = 0x00200000 // Used for cannons, when they should be rooted
};
enum VehicleSpells
diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp
index 2264612f89b..9e5e7ff9990 100644
--- a/src/server/game/Events/GameEventMgr.cpp
+++ b/src/server/game/Events/GameEventMgr.cpp
@@ -371,7 +371,7 @@ void GameEventMgr::LoadFromDB()
{
Field* fields = result->Fetch();
- uint32 guid = fields[0].GetUInt32();
+ ObjectGuid::LowType guid = fields[0].GetUInt32();
int16 event_id = fields[1].GetInt8();
int32 internal_event_id = mGameEvent.size() + event_id - 1;
@@ -417,7 +417,7 @@ void GameEventMgr::LoadFromDB()
{
Field* fields = result->Fetch();
- uint32 guid = fields[0].GetUInt32();
+ ObjectGuid::LowType guid = fields[0].GetUInt32();
int16 event_id = fields[1].GetInt8();
int32 internal_event_id = mGameEvent.size() + event_id - 1;
@@ -463,7 +463,7 @@ void GameEventMgr::LoadFromDB()
{
Field* fields = result->Fetch();
- uint32 guid = fields[0].GetUInt32();
+ ObjectGuid::LowType guid = fields[0].GetUInt32();
uint32 entry = fields[1].GetUInt32();
uint16 event_id = fields[2].GetUInt8();
@@ -712,7 +712,7 @@ void GameEventMgr::LoadFromDB()
{
Field* fields = result->Fetch();
- uint32 guid = fields[0].GetUInt32();
+ ObjectGuid::LowType guid = fields[0].GetUInt32();
uint16 event_id = fields[1].GetUInt8();
uint32 npcflag = fields[2].GetUInt32();
@@ -798,7 +798,7 @@ void GameEventMgr::LoadFromDB()
NPCVendorList& vendors = mGameEventVendors[event_id];
NPCVendorEntry newEntry;
- uint32 guid = fields[1].GetUInt32();
+ ObjectGuid::LowType guid = fields[1].GetUInt32();
newEntry.item = fields[2].GetUInt32();
newEntry.maxcount = fields[3].GetUInt32();
newEntry.incrtime = fields[4].GetUInt32();
@@ -917,7 +917,7 @@ void GameEventMgr::LoadFromDB()
uint32 GameEventMgr::GetNPCFlag(Creature* cr)
{
uint32 mask = 0;
- uint32 guid = cr->GetDBTableGUIDLow();
+ ObjectGuid::LowType guid = cr->GetSpawnId();
for (ActiveEvents::iterator e_itr = m_ActiveEvents.begin(); e_itr != m_ActiveEvents.end(); ++e_itr)
{
@@ -1115,25 +1115,34 @@ void GameEventMgr::ApplyNewEvent(uint16 event_id)
void GameEventMgr::UpdateEventNPCFlags(uint16 event_id)
{
+ std::unordered_map<uint32, std::unordered_set<ObjectGuid::LowType>> creaturesByMap;
+
// go through the creatures whose npcflags are changed in the event
for (NPCFlagList::iterator itr = mGameEventNPCFlags[event_id].begin(); itr != mGameEventNPCFlags[event_id].end(); ++itr)
- {
// get the creature data from the low guid to get the entry, to be able to find out the whole guid
if (CreatureData const* data = sObjectMgr->GetCreatureData(itr->first))
+ creaturesByMap[data->mapid].insert(itr->first);
+
+ for (auto const& p : creaturesByMap)
+ {
+ sMapMgr->DoForAllMapsWithMapId(p.first, [this, &p](Map* map)
{
- Creature* cr = HashMapHolder<Creature>::Find(ObjectGuid(HIGHGUID_UNIT, data->id, itr->first));
- // if we found the creature, modify its npcflag
- if (cr)
+ for (auto& spawnId : p.second)
{
- uint32 npcflag = GetNPCFlag(cr);
- if (const CreatureTemplate* ci = cr->GetCreatureTemplate())
- npcflag |= ci->npcflag;
- cr->SetUInt32Value(UNIT_NPC_FLAGS, npcflag);
- // reset gossip options, since the flag change might have added / removed some
- //cr->ResetGossipOptions();
+ auto creatureBounds = map->GetCreatureBySpawnIdStore().equal_range(spawnId);
+ for (auto itr = creatureBounds.first; itr != creatureBounds.second; ++itr)
+ {
+ Creature* creature = itr->second;
+ uint32 npcflag = GetNPCFlag(creature);
+ if (CreatureTemplate const* creatureTemplate = creature->GetCreatureTemplate())
+ npcflag |= creatureTemplate->npcflag;
+
+ creature->SetUInt32Value(UNIT_NPC_FLAGS, npcflag);
+ // reset gossip options, since the flag change might have added / removed some
+ //cr->ResetGossipOptions();
+ }
}
- // if we didn't find it, then the npcflag will be updated when the creature is loaded
- }
+ });
}
}
@@ -1252,8 +1261,16 @@ void GameEventMgr::GameEventUnspawn(int16 event_id)
{
sObjectMgr->RemoveCreatureFromGrid(*itr, data);
- if (Creature* creature = ObjectAccessor::GetObjectInWorld(ObjectGuid(HIGHGUID_UNIT, data->id, *itr), (Creature*)NULL))
- creature->AddObjectToRemoveList();
+ sMapMgr->DoForAllMapsWithMapId(data->mapid, [&itr](Map* map)
+ {
+ auto creatureBounds = map->GetCreatureBySpawnIdStore().equal_range(*itr);
+ for (auto itr2 = creatureBounds.first; itr2 != creatureBounds.second;)
+ {
+ Creature* creature = itr2->second;
+ ++itr2;
+ creature->AddObjectToRemoveList();
+ }
+ });
}
}
@@ -1274,8 +1291,16 @@ void GameEventMgr::GameEventUnspawn(int16 event_id)
{
sObjectMgr->RemoveGameobjectFromGrid(*itr, data);
- if (GameObject* pGameobject = ObjectAccessor::GetObjectInWorld(ObjectGuid(HIGHGUID_GAMEOBJECT, data->id, *itr), (GameObject*)NULL))
- pGameobject->AddObjectToRemoveList();
+ sMapMgr->DoForAllMapsWithMapId(data->mapid, [&itr](Map* map)
+ {
+ auto gameobjectBounds = map->GetGameObjectBySpawnIdStore().equal_range(*itr);
+ for (auto itr2 = gameobjectBounds.first; itr2 != gameobjectBounds.second;)
+ {
+ GameObject* go = itr2->second;
+ ++itr2;
+ go->AddObjectToRemoveList();
+ }
+ });
}
}
if (internal_event_id < 0 || internal_event_id >= int32(mGameEventPoolIds.size()))
@@ -1300,53 +1325,43 @@ void GameEventMgr::ChangeEquipOrModel(int16 event_id, bool activate)
continue;
// Update if spawned
- Creature* creature = ObjectAccessor::GetObjectInWorld(ObjectGuid(HIGHGUID_UNIT, data->id, itr->first), (Creature*)NULL);
- if (creature)
+ sMapMgr->DoForAllMapsWithMapId(data->mapid, [&itr, activate](Map* map)
+
{
- if (activate)
+ auto creatureBounds = map->GetCreatureBySpawnIdStore().equal_range(itr->first);
+ for (auto itr2 = creatureBounds.first; itr2 != creatureBounds.second; ++itr2)
{
- itr->second.equipement_id_prev = creature->GetCurrentEquipmentId();
- itr->second.modelid_prev = creature->GetDisplayId();
- creature->LoadEquipment(itr->second.equipment_id, true);
- if (itr->second.modelid > 0 && itr->second.modelid_prev != itr->second.modelid &&
- sObjectMgr->GetCreatureModelInfo(itr->second.modelid))
+ Creature* creature = itr2->second;
+ if (activate)
{
- creature->SetDisplayId(itr->second.modelid);
- creature->SetNativeDisplayId(itr->second.modelid);
+ itr->second.equipement_id_prev = creature->GetCurrentEquipmentId();
+ itr->second.modelid_prev = creature->GetDisplayId();
+ creature->LoadEquipment(itr->second.equipment_id, true);
+ if (itr->second.modelid > 0 && itr->second.modelid_prev != itr->second.modelid &&
+ sObjectMgr->GetCreatureModelInfo(itr->second.modelid))
+ {
+ creature->SetDisplayId(itr->second.modelid);
+ creature->SetNativeDisplayId(itr->second.modelid);
+ }
}
- }
- else
- {
- creature->LoadEquipment(itr->second.equipement_id_prev, true);
- if (itr->second.modelid_prev > 0 && itr->second.modelid_prev != itr->second.modelid &&
- sObjectMgr->GetCreatureModelInfo(itr->second.modelid_prev))
+ else
{
- creature->SetDisplayId(itr->second.modelid_prev);
- creature->SetNativeDisplayId(itr->second.modelid_prev);
+ creature->LoadEquipment(itr->second.equipement_id_prev, true);
+ if (itr->second.modelid_prev > 0 && itr->second.modelid_prev != itr->second.modelid &&
+ sObjectMgr->GetCreatureModelInfo(itr->second.modelid_prev))
+ {
+ creature->SetDisplayId(itr->second.modelid_prev);
+ creature->SetNativeDisplayId(itr->second.modelid_prev);
+ }
}
}
- }
- else // If not spawned
- {
- CreatureData const* data2 = sObjectMgr->GetCreatureData(itr->first);
- if (data2 && activate)
- {
- CreatureTemplate const* cinfo = sObjectMgr->GetCreatureTemplate(data2->id);
- uint32 displayID = ObjectMgr::ChooseDisplayId(cinfo, data2);
- sObjectMgr->GetCreatureModelRandomGender(&displayID);
-
- if (data2->equipmentId == 0)
- itr->second.equipement_id_prev = 0; ///@todo: verify this line
- else if (data2->equipmentId != -1)
- itr->second.equipement_id_prev = data->equipmentId;
- itr->second.modelid_prev = displayID;
- }
- }
+ });
// now last step: put in data
- // just to have write access to it
CreatureData& data2 = sObjectMgr->NewOrExistCreatureData(itr->first);
if (activate)
{
+ itr->second.modelid_prev = data2.displayid;
+ itr->second.equipement_id_prev = data2.equipmentId;
data2.displayid = itr->second.modelid;
data2.equipmentId = itr->second.equipment_id;
}
@@ -1385,7 +1400,7 @@ bool GameEventMgr::hasGameObjectQuestActiveEventExcept(uint32 quest_id, uint16 e
}
return false;
}
-bool GameEventMgr::hasCreatureActiveEventExcept(uint32 creature_id, uint16 event_id)
+bool GameEventMgr::hasCreatureActiveEventExcept(ObjectGuid::LowType creature_id, uint16 event_id)
{
for (ActiveEvents::iterator e_itr = m_ActiveEvents.begin(); e_itr != m_ActiveEvents.end(); ++e_itr)
{
@@ -1401,7 +1416,7 @@ bool GameEventMgr::hasCreatureActiveEventExcept(uint32 creature_id, uint16 event
}
return false;
}
-bool GameEventMgr::hasGameObjectActiveEventExcept(uint32 go_id, uint16 event_id)
+bool GameEventMgr::hasGameObjectActiveEventExcept(ObjectGuid::LowType go_id, uint16 event_id)
{
for (ActiveEvents::iterator e_itr = m_ActiveEvents.begin(); e_itr != m_ActiveEvents.end(); ++e_itr)
{
@@ -1594,24 +1609,43 @@ void GameEventMgr::SendWorldStateUpdate(Player* player, uint16 event_id)
}
}
-void GameEventMgr::RunSmartAIScripts(uint16 event_id, bool activate)
+class GameEventAIHookWorker
{
- //! Iterate over every supported source type (creature and gameobject)
- //! Not entirely sure how this will affect units in non-loaded grids.
+public:
+ GameEventAIHookWorker(uint16 eventId, bool activate) : _eventId(eventId), _activate(activate) { }
+
+ void Visit(std::unordered_map<ObjectGuid, Creature*>& creatureMap)
{
- boost::shared_lock<boost::shared_mutex> lock(*HashMapHolder<Creature>::GetLock());
- HashMapHolder<Creature>::MapType const& m = ObjectAccessor::GetCreatures();
- for (HashMapHolder<Creature>::MapType::const_iterator iter = m.begin(); iter != m.end(); ++iter)
- if (iter->second->IsInWorld())
- iter->second->AI()->sOnGameEvent(activate, event_id);
+ for (auto const& p : creatureMap)
+ if (p.second->IsInWorld() && p.second->IsAIEnabled)
+ p.second->AI()->sOnGameEvent(_activate, _eventId);
}
+
+ void Visit(std::unordered_map<ObjectGuid, GameObject*>& gameObjectMap)
{
- boost::shared_lock<boost::shared_mutex> lock(*HashMapHolder<GameObject>::GetLock());
- HashMapHolder<GameObject>::MapType const& m = ObjectAccessor::GetGameObjects();
- for (HashMapHolder<GameObject>::MapType::const_iterator iter = m.begin(); iter != m.end(); ++iter)
- if (iter->second->IsInWorld())
- iter->second->AI()->OnGameEvent(activate, event_id);
+ for (auto const& p : gameObjectMap)
+ if (p.second->IsInWorld())
+ p.second->AI()->OnGameEvent(_activate, _eventId);
}
+
+ template<class T>
+ void Visit(std::unordered_map<ObjectGuid, T*>&) { }
+
+private:
+ uint16 _eventId;
+ bool _activate;
+};
+
+void GameEventMgr::RunSmartAIScripts(uint16 event_id, bool activate)
+{
+ //! Iterate over every supported source type (creature and gameobject)
+ //! Not entirely sure how this will affect units in non-loaded grids.
+ sMapMgr->DoForAllMaps([event_id, activate](Map* map)
+ {
+ GameEventAIHookWorker worker(event_id, activate);
+ TypeContainerVisitor<GameEventAIHookWorker, MapStoredObjectTypesContainer> visitor(worker);
+ visitor.Visit(map->GetObjectsStore());
+ });
}
uint16 GameEventMgr::GetEventIdForQuest(Quest const* quest) const
diff --git a/src/server/game/Events/GameEventMgr.h b/src/server/game/Events/GameEventMgr.h
index eb29e463a4d..57f30eb4015 100644
--- a/src/server/game/Events/GameEventMgr.h
+++ b/src/server/game/Events/GameEventMgr.h
@@ -20,6 +20,7 @@
#define TRINITY_GAMEEVENT_MGR_H
#include "Common.h"
+#include "ObjectGuid.h"
#include "SharedDefines.h"
#include "Define.h"
@@ -144,14 +145,14 @@ class GameEventMgr
void SaveWorldEventStateToDB(uint16 event_id);
bool hasCreatureQuestActiveEventExcept(uint32 quest_id, uint16 event_id);
bool hasGameObjectQuestActiveEventExcept(uint32 quest_id, uint16 event_id);
- bool hasCreatureActiveEventExcept(uint32 creature_guid, uint16 event_id);
- bool hasGameObjectActiveEventExcept(uint32 go_guid, uint16 event_id);
+ bool hasCreatureActiveEventExcept(ObjectGuid::LowType creature_guid, uint16 event_id);
+ bool hasGameObjectActiveEventExcept(ObjectGuid::LowType go_guid, uint16 event_id);
- typedef std::list<uint32> GuidList;
+ typedef std::list<ObjectGuid::LowType> GuidList;
typedef std::list<uint32> IdList;
typedef std::vector<GuidList> GameEventGuidMap;
typedef std::vector<IdList> GameEventIdMap;
- typedef std::pair<uint32, ModelEquip> ModelEquipPair;
+ typedef std::pair<ObjectGuid::LowType, ModelEquip> ModelEquipPair;
typedef std::list<ModelEquipPair> ModelEquipList;
typedef std::vector<ModelEquipList> GameEventModelEquipMap;
typedef std::pair<uint32, uint32> QuestRelation;
@@ -160,7 +161,7 @@ class GameEventMgr
typedef std::list<NPCVendorEntry> NPCVendorList;
typedef std::vector<NPCVendorList> GameEventNPCVendorMap;
typedef std::map<uint32 /*quest id*/, GameEventQuestToEventConditionNum> QuestIdToEventConditionMap;
- typedef std::pair<uint32 /*guid*/, uint32 /*npcflag*/> GuidNPCFlagPair;
+ typedef std::pair<ObjectGuid::LowType /*guid*/, uint32 /*npcflag*/> GuidNPCFlagPair;
typedef std::list<GuidNPCFlagPair> NPCFlagList;
typedef std::vector<NPCFlagList> GameEventNPCFlagMap;
typedef std::vector<uint32> GameEventBitmask;
diff --git a/src/server/game/Globals/ObjectAccessor.cpp b/src/server/game/Globals/ObjectAccessor.cpp
index 859633b16c4..ca974ba9a37 100644
--- a/src/server/game/Globals/ObjectAccessor.cpp
+++ b/src/server/game/Globals/ObjectAccessor.cpp
@@ -16,9 +16,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <boost/thread/shared_mutex.hpp>
-#include <boost/thread/locks.hpp>
-
#include "ObjectAccessor.h"
#include "Corpse.h"
#include "Creature.h"
@@ -31,97 +28,61 @@
#include "ObjectMgr.h"
#include "Pet.h"
#include "Player.h"
+#include "Transport.h"
#include "World.h"
-#include "WorldPacket.h"
-
-ObjectAccessor::ObjectAccessor() { }
-
-ObjectAccessor::~ObjectAccessor() { }
-
-template<class T> T* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, ObjectGuid guid, T* /*fake*/)
-{
- T* obj = HashMapHolder<T>::Find(guid);
- if (!obj || obj->GetMapId() != mapid)
- return NULL;
-
- CellCoord p = Trinity::ComputeCellCoord(x, y);
- if (!p.IsCoordValid())
- {
- TC_LOG_ERROR("misc", "ObjectAccessor::GetObjectInWorld: invalid coordinates supplied X:%f Y:%f grid cell [%u:%u]", x, y, p.x_coord, p.y_coord);
- return NULL;
- }
-
- CellCoord q = Trinity::ComputeCellCoord(obj->GetPositionX(), obj->GetPositionY());
- if (!q.IsCoordValid())
- {
- TC_LOG_ERROR("misc", "ObjectAccessor::GetObjecInWorld: object (GUID: %u TypeId: %u) has invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUIDLow(), obj->GetTypeId(), obj->GetPositionX(), obj->GetPositionY(), q.x_coord, q.y_coord);
- return NULL;
- }
-
- int32 dx = int32(p.x_coord) - int32(q.x_coord);
- int32 dy = int32(p.y_coord) - int32(q.y_coord);
- if (dx > -2 && dx < 2 && dy > -2 && dy < 2)
- return obj;
- else
- return NULL;
-}
-
-Player* ObjectAccessor::GetObjectInWorld(ObjectGuid guid, Player* /*typeSpecifier*/)
-{
- Player* player = HashMapHolder<Player>::Find(guid);
- return player && player->IsInWorld() ? player : NULL;
-}
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/thread/locks.hpp>
-WorldObject* ObjectAccessor::GetWorldObject(WorldObject const& p, ObjectGuid guid)
+WorldObject* ObjectAccessor::GetWorldObject(WorldObject const& p, ObjectGuid const& guid)
{
switch (guid.GetHigh())
{
- case HIGHGUID_PLAYER: return GetPlayer(p, guid);
- case HIGHGUID_TRANSPORT:
- case HIGHGUID_MO_TRANSPORT:
- case HIGHGUID_GAMEOBJECT: return GetGameObject(p, guid);
- case HIGHGUID_VEHICLE:
- case HIGHGUID_UNIT: return GetCreature(p, guid);
- case HIGHGUID_PET: return GetPet(p, guid);
- case HIGHGUID_DYNAMICOBJECT: return GetDynamicObject(p, guid);
- case HIGHGUID_CORPSE: return GetCorpse(p, guid);
+ case HighGuid::Player: return GetPlayer(p, guid);
+ case HighGuid::Transport:
+ case HighGuid::Mo_Transport:
+ case HighGuid::GameObject: return GetGameObject(p, guid);
+ case HighGuid::Vehicle:
+ case HighGuid::Unit: return GetCreature(p, guid);
+ case HighGuid::Pet: return GetPet(p, guid);
+ case HighGuid::DynamicObject: return GetDynamicObject(p, guid);
+ case HighGuid::Corpse: return GetCorpse(p, guid);
default: return NULL;
}
}
-Object* ObjectAccessor::GetObjectByTypeMask(WorldObject const& p, ObjectGuid guid, uint32 typemask)
+Object* ObjectAccessor::GetObjectByTypeMask(WorldObject const& p, ObjectGuid const& guid, uint32 typemask)
{
switch (guid.GetHigh())
{
- case HIGHGUID_ITEM:
+ case HighGuid::Item:
if (typemask & TYPEMASK_ITEM && p.GetTypeId() == TYPEID_PLAYER)
return ((Player const&)p).GetItemByGuid(guid);
break;
- case HIGHGUID_PLAYER:
+ case HighGuid::Player:
if (typemask & TYPEMASK_PLAYER)
return GetPlayer(p, guid);
break;
- case HIGHGUID_TRANSPORT:
- case HIGHGUID_MO_TRANSPORT:
- case HIGHGUID_GAMEOBJECT:
+ case HighGuid::Transport:
+ case HighGuid::Mo_Transport:
+ case HighGuid::GameObject:
if (typemask & TYPEMASK_GAMEOBJECT)
return GetGameObject(p, guid);
break;
- case HIGHGUID_UNIT:
- case HIGHGUID_VEHICLE:
+ case HighGuid::Unit:
+ case HighGuid::Vehicle:
if (typemask & TYPEMASK_UNIT)
return GetCreature(p, guid);
break;
- case HIGHGUID_PET:
+ case HighGuid::Pet:
if (typemask & TYPEMASK_UNIT)
return GetPet(p, guid);
break;
- case HIGHGUID_DYNAMICOBJECT:
+ case HighGuid::DynamicObject:
if (typemask & TYPEMASK_DYNAMICOBJECT)
return GetDynamicObject(p, guid);
break;
- case HIGHGUID_CORPSE:
+ case HighGuid::Corpse:
break;
default:
break;
@@ -130,51 +91,62 @@ Object* ObjectAccessor::GetObjectByTypeMask(WorldObject const& p, ObjectGuid gui
return NULL;
}
-Corpse* ObjectAccessor::GetCorpse(WorldObject const& u, ObjectGuid guid)
+Corpse* ObjectAccessor::GetCorpse(WorldObject const& u, ObjectGuid const& guid)
{
- return GetObjectInMap(guid, u.GetMap(), (Corpse*)NULL);
+ return u.GetMap()->GetCorpse(guid);
}
-GameObject* ObjectAccessor::GetGameObject(WorldObject const& u, ObjectGuid guid)
+GameObject* ObjectAccessor::GetGameObject(WorldObject const& u, ObjectGuid const& guid)
{
- return GetObjectInMap(guid, u.GetMap(), (GameObject*)NULL);
+ return u.GetMap()->GetGameObject(guid);
}
-Transport* ObjectAccessor::GetTransport(WorldObject const& u, ObjectGuid guid)
+Transport* ObjectAccessor::GetTransport(WorldObject const& u, ObjectGuid const& guid)
{
- if (!guid.IsMOTransport())
- return NULL;
+ return u.GetMap()->GetTransport(guid);
+}
- GameObject* go = GetGameObject(u, guid);
- return go ? go->ToTransport() : NULL;
+DynamicObject* ObjectAccessor::GetDynamicObject(WorldObject const& u, ObjectGuid const& guid)
+{
+ return u.GetMap()->GetDynamicObject(guid);
}
-DynamicObject* ObjectAccessor::GetDynamicObject(WorldObject const& u, ObjectGuid guid)
+Unit* ObjectAccessor::GetUnit(WorldObject const& u, ObjectGuid const& guid)
{
- return GetObjectInMap(guid, u.GetMap(), (DynamicObject*)NULL);
+ if (guid.IsPlayer())
+ return GetPlayer(u, guid);
+
+ if (guid.IsPet())
+ return GetPet(u, guid);
+
+ return GetCreature(u, guid);
}
-Unit* ObjectAccessor::GetUnit(WorldObject const& u, ObjectGuid guid)
+Creature* ObjectAccessor::GetCreature(WorldObject const& u, ObjectGuid const& guid)
{
- return GetObjectInMap(guid, u.GetMap(), (Unit*)NULL);
+ return u.GetMap()->GetCreature(guid);
}
-Creature* ObjectAccessor::GetCreature(WorldObject const& u, ObjectGuid guid)
+Pet* ObjectAccessor::GetPet(WorldObject const& u, ObjectGuid const& guid)
{
- return GetObjectInMap(guid, u.GetMap(), (Creature*)NULL);
+ return u.GetMap()->GetPet(guid);
}
-Pet* ObjectAccessor::GetPet(WorldObject const& u, ObjectGuid guid)
+Player* ObjectAccessor::GetPlayer(Map const* m, ObjectGuid const& guid)
{
- return GetObjectInMap(guid, u.GetMap(), (Pet*)NULL);
+ if (Player* player = HashMapHolder<Player>::Find(guid))
+ if (player->IsInWorld() && player->GetMap() == m)
+ return player;
+
+ return nullptr;
}
-Player* ObjectAccessor::GetPlayer(WorldObject const& u, ObjectGuid guid)
+Player* ObjectAccessor::GetPlayer(WorldObject const& u, ObjectGuid const& guid)
{
- return GetObjectInMap(guid, u.GetMap(), (Player*)NULL);
+ return GetPlayer(u.GetMap(), guid);
}
-Creature* ObjectAccessor::GetCreatureOrPetOrVehicle(WorldObject const& u, ObjectGuid guid)
+Creature* ObjectAccessor::GetCreatureOrPetOrVehicle(WorldObject const& u, ObjectGuid const& guid)
{
if (guid.IsPet())
return GetPet(u, guid);
@@ -185,26 +157,17 @@ Creature* ObjectAccessor::GetCreatureOrPetOrVehicle(WorldObject const& u, Object
return NULL;
}
-Pet* ObjectAccessor::FindPet(ObjectGuid guid)
+Player* ObjectAccessor::FindPlayer(ObjectGuid const& guid)
{
- return GetObjectInWorld(guid, (Pet*)NULL);
-}
-
-Player* ObjectAccessor::FindPlayer(ObjectGuid guid)
-{
- return GetObjectInWorld(guid, (Player*)NULL);
+ Player* player = HashMapHolder<Player>::Find(guid);
+ return player && player->IsInWorld() ? player : nullptr;
}
-Player* ObjectAccessor::FindConnectedPlayer(ObjectGuid guid)
+Player* ObjectAccessor::FindConnectedPlayer(ObjectGuid const& guid)
{
return HashMapHolder<Player>::Find(guid);
}
-Unit* ObjectAccessor::FindUnit(ObjectGuid guid)
-{
- return GetObjectInWorld(guid, (Unit*)NULL);
-}
-
Player* ObjectAccessor::FindPlayerByName(std::string const& name)
{
boost::shared_lock<boost::shared_mutex> lock(*HashMapHolder<Player>::GetLock());
@@ -243,6 +206,11 @@ Player* ObjectAccessor::FindConnectedPlayerByName(std::string const& name)
return NULL;
}
+HashMapHolder<Player>::MapType const& ObjectAccessor::GetPlayers()
+{
+ return HashMapHolder<Player>::GetContainer();
+}
+
void ObjectAccessor::SaveAllPlayers()
{
boost::shared_lock<boost::shared_mutex> lock(*HashMapHolder<Player>::GetLock());
@@ -252,207 +220,6 @@ void ObjectAccessor::SaveAllPlayers()
itr->second->SaveToDB();
}
-Corpse* ObjectAccessor::GetCorpseForPlayerGUID(ObjectGuid guid)
-{
- boost::shared_lock<boost::shared_mutex> lock(_corpseLock);
-
- Player2CorpsesMapType::iterator iter = i_player2corpse.find(guid);
- if (iter == i_player2corpse.end())
- return NULL;
-
- ASSERT(iter->second->GetType() != CORPSE_BONES);
-
- return iter->second;
-}
-
-void ObjectAccessor::RemoveCorpse(Corpse* corpse)
-{
- ASSERT(corpse && corpse->GetType() != CORPSE_BONES);
-
- boost::upgrade_lock<boost::shared_mutex> lock(_corpseLock);
-
- /// @todo more works need to be done for corpse and other world object
- if (Map* map = corpse->FindMap())
- {
- corpse->DestroyForNearbyPlayers();
- if (corpse->IsInGrid())
- map->RemoveFromMap(corpse, false);
- else
- {
- corpse->RemoveFromWorld();
- corpse->ResetMap();
- }
- }
- else
-
- corpse->RemoveFromWorld();
-
- // Critical section
- {
- boost::upgrade_to_unique_lock<boost::shared_mutex> uniqueLock(lock);
-
- Player2CorpsesMapType::iterator iter = i_player2corpse.find(corpse->GetOwnerGUID());
- if (iter == i_player2corpse.end()) /// @todo Fix this
- return;
-
- // build mapid*cellid -> guid_set map
- CellCoord cellCoord = Trinity::ComputeCellCoord(corpse->GetPositionX(), corpse->GetPositionY());
- sObjectMgr->DeleteCorpseCellData(corpse->GetMapId(), cellCoord.GetId(), corpse->GetOwnerGUID().GetCounter());
-
- i_player2corpse.erase(iter);
- }
-}
-
-void ObjectAccessor::AddCorpse(Corpse* corpse)
-{
- ASSERT(corpse && corpse->GetType() != CORPSE_BONES);
-
- // Critical section
- {
- boost::unique_lock<boost::shared_mutex> lock(_corpseLock);
-
- ASSERT(i_player2corpse.find(corpse->GetOwnerGUID()) == i_player2corpse.end());
- i_player2corpse[corpse->GetOwnerGUID()] = corpse;
-
- // build mapid*cellid -> guid_set map
- CellCoord cellCoord = Trinity::ComputeCellCoord(corpse->GetPositionX(), corpse->GetPositionY());
- sObjectMgr->AddCorpseCellData(corpse->GetMapId(), cellCoord.GetId(), corpse->GetOwnerGUID().GetCounter(), corpse->GetInstanceId());
- }
-}
-
-void ObjectAccessor::AddCorpsesToGrid(GridCoord const& gridpair, GridType& grid, Map* map)
-{
- boost::shared_lock<boost::shared_mutex> lock(_corpseLock);
-
- for (Player2CorpsesMapType::iterator iter = i_player2corpse.begin(); iter != i_player2corpse.end(); ++iter)
- {
- // We need this check otherwise a corpose may be added to a grid twice
- if (iter->second->IsInGrid())
- continue;
-
- if (iter->second->GetGridCoord() == gridpair)
- {
- // verify, if the corpse in our instance (add only corpses which are)
- if (map->Instanceable())
- {
- if (iter->second->GetInstanceId() == map->GetInstanceId())
- grid.AddWorldObject(iter->second);
- }
- else
- grid.AddWorldObject(iter->second);
- }
- }
-}
-
-Corpse* ObjectAccessor::ConvertCorpseForPlayer(ObjectGuid player_guid, bool insignia /*=false*/)
-{
- Corpse* corpse = GetCorpseForPlayerGUID(player_guid);
- if (!corpse)
- {
- //in fact this function is called from several places
- //even when player doesn't have a corpse, not an error
- return NULL;
- }
-
- TC_LOG_DEBUG("misc", "Deleting Corpse and spawned bones.");
-
- // Map can be NULL
- Map* map = corpse->FindMap();
-
- // remove corpse from player_guid -> corpse map and from current map
- RemoveCorpse(corpse);
-
- // remove corpse from DB
- SQLTransaction trans = CharacterDatabase.BeginTransaction();
- corpse->DeleteFromDB(trans);
- CharacterDatabase.CommitTransaction(trans);
-
- Corpse* bones = NULL;
- // create the bones only if the map and the grid is loaded at the corpse's location
- // ignore bones creating option in case insignia
-
- if (map && (insignia ||
- (map->IsBattlegroundOrArena() ? sWorld->getBoolConfig(CONFIG_DEATH_BONES_BG_OR_ARENA) : sWorld->getBoolConfig(CONFIG_DEATH_BONES_WORLD))) &&
- !map->IsRemovalGrid(corpse->GetPositionX(), corpse->GetPositionY()))
- {
- // Create bones, don't change Corpse
- bones = new Corpse;
- bones->Create(corpse->GetGUIDLow(), map);
-
- for (uint8 i = OBJECT_FIELD_TYPE + 1; i < CORPSE_END; ++i) // don't overwrite guid and object type
- bones->SetUInt32Value(i, corpse->GetUInt32Value(i));
-
- bones->SetGridCoord(corpse->GetGridCoord());
- // bones->m_time = m_time; // don't overwrite time
- // bones->m_type = m_type; // don't overwrite type
- bones->Relocate(corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetOrientation());
- bones->SetPhaseMask(corpse->GetPhaseMask(), false);
-
- bones->SetUInt32Value(CORPSE_FIELD_FLAGS, CORPSE_FLAG_UNK2 | CORPSE_FLAG_BONES);
- bones->SetGuidValue(CORPSE_FIELD_OWNER, ObjectGuid::Empty);
-
- for (uint8 i = 0; i < EQUIPMENT_SLOT_END; ++i)
- {
- if (corpse->GetUInt32Value(CORPSE_FIELD_ITEM + i))
- bones->SetUInt32Value(CORPSE_FIELD_ITEM + i, 0);
- }
-
- // add bones in grid store if grid loaded where corpse placed
- map->AddToMap(bones);
- }
-
- // all references to the corpse should be removed at this point
- delete corpse;
-
- return bones;
-}
-
-void ObjectAccessor::RemoveOldCorpses()
-{
- time_t now = time(NULL);
- Player2CorpsesMapType::iterator next;
- for (Player2CorpsesMapType::iterator itr = i_player2corpse.begin(); itr != i_player2corpse.end(); itr = next)
- {
- next = itr;
- ++next;
-
- if (!itr->second->IsExpired(now))
- continue;
-
- ConvertCorpseForPlayer(itr->first);
- }
-}
-
-void ObjectAccessor::Update(uint32 /*diff*/)
-{
- UpdateDataMapType update_players;
-
- while (!i_objects.empty())
- {
- Object* obj = *i_objects.begin();
- ASSERT(obj && obj->IsInWorld());
- i_objects.erase(i_objects.begin());
- obj->BuildUpdate(update_players);
- }
-
- WorldPacket packet; // here we allocate a std::vector with a size of 0x10000
- for (UpdateDataMapType::iterator iter = update_players.begin(); iter != update_players.end(); ++iter)
- {
- iter->second.BuildPacket(&packet);
- iter->first->GetSession()->SendPacket(&packet);
- packet.clear(); // clean the string
- }
-}
-
-void ObjectAccessor::UnloadAll()
-{
- for (Player2CorpsesMapType::const_iterator itr = i_player2corpse.begin(); itr != i_player2corpse.end(); ++itr)
- {
- itr->second->RemoveFromWorld();
- delete itr->second;
- }
-}
-
/// Define the static members of HashMapHolder
template <class T> typename HashMapHolder<T>::MapType HashMapHolder<T>::_objectMap;
@@ -461,15 +228,5 @@ template <class T> boost::shared_mutex HashMapHolder<T>::_lock;
/// Global definitions for the hashmap storage
template class HashMapHolder<Player>;
-template class HashMapHolder<Pet>;
-template class HashMapHolder<GameObject>;
-template class HashMapHolder<DynamicObject>;
-template class HashMapHolder<Creature>;
-template class HashMapHolder<Corpse>;
-
-template Player* ObjectAccessor::GetObjectInWorld<Player>(uint32 mapid, float x, float y, ObjectGuid guid, Player* /*fake*/);
-template Pet* ObjectAccessor::GetObjectInWorld<Pet>(uint32 mapid, float x, float y, ObjectGuid guid, Pet* /*fake*/);
-template Creature* ObjectAccessor::GetObjectInWorld<Creature>(uint32 mapid, float x, float y, ObjectGuid guid, Creature* /*fake*/);
-template Corpse* ObjectAccessor::GetObjectInWorld<Corpse>(uint32 mapid, float x, float y, ObjectGuid guid, Corpse* /*fake*/);
-template GameObject* ObjectAccessor::GetObjectInWorld<GameObject>(uint32 mapid, float x, float y, ObjectGuid guid, GameObject* /*fake*/);
-template DynamicObject* ObjectAccessor::GetObjectInWorld<DynamicObject>(uint32 mapid, float x, float y, ObjectGuid guid, DynamicObject* /*fake*/);
+
+template class HashMapHolder<Transport>;
diff --git a/src/server/game/Globals/ObjectAccessor.h b/src/server/game/Globals/ObjectAccessor.h
index 2d32e747eb1..d5fb8564b96 100644
--- a/src/server/game/Globals/ObjectAccessor.h
+++ b/src/server/game/Globals/ObjectAccessor.h
@@ -30,7 +30,6 @@
#include "UpdateData.h"
#include "Object.h"
-
class Creature;
class Corpse;
class Unit;
@@ -46,6 +45,9 @@ template <class T>
class HashMapHolder
{
public:
+ static_assert(std::is_same<Player, T>::value
+ || std::is_same<Transport, T>::value,
+ "Only Player and Transport can be registered in global HashMapHolder");
typedef std::unordered_map<ObjectGuid, T*> MapType;
@@ -83,165 +85,47 @@ class HashMapHolder
static MapType _objectMap;
};
-class ObjectAccessor
+namespace ObjectAccessor
{
- private:
- ObjectAccessor();
- ~ObjectAccessor();
- ObjectAccessor(const ObjectAccessor&);
- ObjectAccessor& operator=(const ObjectAccessor&);
-
- public:
- /// @todo: Override these template functions for each holder type and add assertions
-
- static ObjectAccessor* instance()
- {
- static ObjectAccessor instance;
- return &instance;
- }
-
- template<class T> static T* GetObjectInOrOutOfWorld(ObjectGuid guid, T* /*typeSpecifier*/)
- {
- return HashMapHolder<T>::Find(guid);
- }
-
- static Unit* GetObjectInOrOutOfWorld(ObjectGuid guid, Unit* /*typeSpecifier*/)
- {
- if (guid.IsPlayer())
- return (Unit*)GetObjectInOrOutOfWorld(guid, (Player*)NULL);
-
- if (guid.IsPet())
- return (Unit*)GetObjectInOrOutOfWorld(guid, (Pet*)NULL);
-
- return (Unit*)GetObjectInOrOutOfWorld(guid, (Creature*)NULL);
- }
-
- // returns object if is in world
- template<class T> static T* GetObjectInWorld(ObjectGuid guid, T* /*typeSpecifier*/)
- {
- return HashMapHolder<T>::Find(guid);
- }
-
- // Player may be not in world while in ObjectAccessor
- static Player* GetObjectInWorld(ObjectGuid guid, Player* /*typeSpecifier*/);
-
- static Unit* GetObjectInWorld(ObjectGuid guid, Unit* /*typeSpecifier*/)
- {
- if (guid.IsPlayer())
- return (Unit*)GetObjectInWorld(guid, (Player*)NULL);
-
- if (guid.IsPet())
- return (Unit*)GetObjectInWorld(guid, (Pet*)NULL);
-
- return (Unit*)GetObjectInWorld(guid, (Creature*)NULL);
- }
-
- // returns object if is in map
- template<class T> static T* GetObjectInMap(ObjectGuid guid, Map* map, T* /*typeSpecifier*/)
- {
- ASSERT(map);
- if (T * obj = GetObjectInWorld(guid, (T*)NULL))
- if (obj->GetMap() == map)
- return obj;
- return NULL;
- }
-
- template<class T> static T* GetObjectInWorld(uint32 mapid, float x, float y, ObjectGuid guid, T* /*fake*/);
-
- // these functions return objects only if in map of specified object
- static WorldObject* GetWorldObject(WorldObject const&, ObjectGuid);
- static Object* GetObjectByTypeMask(WorldObject const&, ObjectGuid, uint32 typemask);
- static Corpse* GetCorpse(WorldObject const& u, ObjectGuid guid);
- static GameObject* GetGameObject(WorldObject const& u, ObjectGuid guid);
- static Transport* GetTransport(WorldObject const& u, ObjectGuid guid);
- static DynamicObject* GetDynamicObject(WorldObject const& u, ObjectGuid guid);
- static Unit* GetUnit(WorldObject const&, ObjectGuid guid);
- static Creature* GetCreature(WorldObject const& u, ObjectGuid guid);
- static Pet* GetPet(WorldObject const&, ObjectGuid guid);
- static Player* GetPlayer(WorldObject const&, ObjectGuid guid);
- static Creature* GetCreatureOrPetOrVehicle(WorldObject const&, ObjectGuid);
-
- // these functions return objects if found in whole world
- // ACCESS LIKE THAT IS NOT THREAD SAFE
- static Pet* FindPet(ObjectGuid);
- static Player* FindPlayer(ObjectGuid);
- static Creature* FindCreature(ObjectGuid);
- static Unit* FindUnit(ObjectGuid);
- static Player* FindPlayerByName(std::string const& name);
-
- // this returns Player even if he is not in world, for example teleporting
- static Player* FindConnectedPlayer(ObjectGuid);
- static Player* FindConnectedPlayerByName(std::string const& name);
-
- // when using this, you must use the hashmapholder's lock
- static HashMapHolder<Player>::MapType const& GetPlayers()
- {
- return HashMapHolder<Player>::GetContainer();
- }
-
- // when using this, you must use the hashmapholder's lock
- static HashMapHolder<Creature>::MapType const& GetCreatures()
- {
- return HashMapHolder<Creature>::GetContainer();
- }
-
- // when using this, you must use the hashmapholder's lock
- static HashMapHolder<GameObject>::MapType const& GetGameObjects()
- {
- return HashMapHolder<GameObject>::GetContainer();
- }
-
- template<class T> static void AddObject(T* object)
- {
- HashMapHolder<T>::Insert(object);
- }
-
- template<class T> static void RemoveObject(T* object)
- {
- HashMapHolder<T>::Remove(object);
- }
-
- static void SaveAllPlayers();
-
- //non-static functions
- void AddUpdateObject(Object* obj)
- {
- std::lock_guard<std::mutex> lock(_objectLock);
- i_objects.insert(obj);
- }
-
- void RemoveUpdateObject(Object* obj)
- {
- std::lock_guard<std::mutex> lock(_objectLock);
- i_objects.erase(obj);
- }
-
- //Thread safe
- Corpse* GetCorpseForPlayerGUID(ObjectGuid guid);
- void RemoveCorpse(Corpse* corpse);
- void AddCorpse(Corpse* corpse);
- void AddCorpsesToGrid(GridCoord const& gridpair, GridType& grid, Map* map);
- Corpse* ConvertCorpseForPlayer(ObjectGuid player_guid, bool insignia = false);
-
- //Thread unsafe
- void Update(uint32 diff);
- void RemoveOldCorpses();
- void UnloadAll();
-
- private:
- static void _buildChangeObjectForPlayer(WorldObject*, UpdateDataMapType&);
- static void _buildPacket(Player*, Object*, UpdateDataMapType&);
- void _update();
-
- typedef std::unordered_map<ObjectGuid, Corpse*> Player2CorpsesMapType;
- typedef std::unordered_map<Player*, UpdateData>::value_type UpdateDataValueType;
-
- std::set<Object*> i_objects;
- Player2CorpsesMapType i_player2corpse;
-
- std::mutex _objectLock;
- boost::shared_mutex _corpseLock;
+ // these functions return objects only if in map of specified object
+ WorldObject* GetWorldObject(WorldObject const&, ObjectGuid const&);
+ Object* GetObjectByTypeMask(WorldObject const&, ObjectGuid const&, uint32 typemask);
+ Corpse* GetCorpse(WorldObject const& u, ObjectGuid const& guid);
+ GameObject* GetGameObject(WorldObject const& u, ObjectGuid const& guid);
+ Transport* GetTransport(WorldObject const& u, ObjectGuid const& guid);
+ DynamicObject* GetDynamicObject(WorldObject const& u, ObjectGuid const& guid);
+ Unit* GetUnit(WorldObject const&, ObjectGuid const& guid);
+ Creature* GetCreature(WorldObject const& u, ObjectGuid const& guid);
+ Pet* GetPet(WorldObject const&, ObjectGuid const& guid);
+ Player* GetPlayer(Map const*, ObjectGuid const& guid);
+ Player* GetPlayer(WorldObject const&, ObjectGuid const& guid);
+ Creature* GetCreatureOrPetOrVehicle(WorldObject const&, ObjectGuid const&);
+
+ // these functions return objects if found in whole world
+ // ACCESS LIKE THAT IS NOT THREAD SAFE
+ Player* FindPlayer(ObjectGuid const&);
+ Player* FindPlayerByName(std::string const& name);
+
+ // this returns Player even if he is not in world, for example teleporting
+ Player* FindConnectedPlayer(ObjectGuid const&);
+ Player* FindConnectedPlayerByName(std::string const& name);
+
+ // when using this, you must use the hashmapholder's lock
+ HashMapHolder<Player>::MapType const& GetPlayers();
+
+ template<class T>
+ void AddObject(T* object)
+ {
+ HashMapHolder<T>::Insert(object);
+ }
+
+ template<class T>
+ void RemoveObject(T* object)
+ {
+ HashMapHolder<T>::Remove(object);
+ }
+
+ void SaveAllPlayers();
};
-#define sObjectAccessor ObjectAccessor::instance()
#endif
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index e540824e71c..6f5368ed150 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -25,7 +25,6 @@
#include "Common.h"
#include "DatabaseEnv.h"
#include "DisableMgr.h"
-#include "GameEventMgr.h"
#include "GossipDef.h"
#include "GroupMgr.h"
#include "GuildMgr.h"
@@ -36,19 +35,15 @@
#include "MapManager.h"
#include "Object.h"
#include "ObjectMgr.h"
-#include "Pet.h"
#include "PoolMgr.h"
#include "ReputationMgr.h"
#include "ScriptMgr.h"
#include "SpellAuras.h"
-#include "Spell.h"
#include "SpellMgr.h"
#include "SpellScript.h"
-#include "Transport.h"
#include "UpdateMask.h"
#include "Util.h"
#include "Vehicle.h"
-#include "WaypointManager.h"
#include "World.h"
ScriptMapMap sSpellScripts;
@@ -228,15 +223,8 @@ ObjectMgr::ObjectMgr():
_itemTextId(1),
_mailId(1),
_hiPetNumber(1),
- _hiCharGuid(1),
- _hiCreatureGuid(1),
- _hiPetGuid(1),
- _hiVehicleGuid(1),
- _hiItemGuid(1),
- _hiGoGuid(1),
- _hiDoGuid(1),
- _hiCorpseGuid(1),
- _hiMoTransGuid(1),
+ _creatureSpawnId(1),
+ _gameObjectSpawnId(1),
DBCLocaleIndex(LOCALE_enUS)
{
for (uint8 i = 0; i < MAX_CLASSES; ++i)
@@ -303,8 +291,8 @@ void ObjectMgr::LoadCreatureLocales()
_creatureLocaleStore.clear(); // need for reload case
- QueryResult result = WorldDatabase.Query("SELECT entry, name_loc1, subname_loc1, name_loc2, subname_loc2, name_loc3, subname_loc3, name_loc4, subname_loc4, name_loc5, subname_loc5, name_loc6, subname_loc6, name_loc7, subname_loc7, name_loc8, subname_loc8 FROM locales_creature");
-
+ // 0 1 2 3
+ QueryResult result = WorldDatabase.Query("SELECT entry, locale, Name, Title FROM creature_template_locale");
if (!result)
return;
@@ -312,16 +300,20 @@ void ObjectMgr::LoadCreatureLocales()
{
Field* fields = result->Fetch();
- uint32 entry = fields[0].GetUInt32();
+ uint32 id = fields[0].GetUInt32();
+ std::string localeName = fields[1].GetString();
- CreatureLocale& data = _creatureLocaleStore[entry];
+ std::string name = fields[2].GetString();
+ std::string title = fields[3].GetString();
+
+ CreatureLocale& data = _creatureLocaleStore[id];
+ LocaleConstant locale = GetLocaleByName(localeName);
+ if (locale == LOCALE_enUS)
+ continue;
+
+ AddLocaleString(name, locale, data.Name);
+ AddLocaleString(title, locale, data.Title);
- for (uint8 i = TOTAL_LOCALES - 1; i > 0; --i)
- {
- LocaleConstant locale = (LocaleConstant) i;
- AddLocaleString(fields[1 + 2 * (i - 1)].GetString(), locale, data.Name);
- AddLocaleString(fields[1 + 2 * (i - 1) + 1].GetString(), locale, data.SubName);
- }
} while (result->NextRow());
TC_LOG_INFO("server.loading", ">> Loaded %u creature locale strings in %u ms", uint32(_creatureLocaleStore.size()), GetMSTimeDiffToNow(oldMSTime));
@@ -408,8 +400,8 @@ void ObjectMgr::LoadCreatureTemplates()
"spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, "
// 62 63 64 65 66 67 68 69
"InhabitType, HoverHeight, HealthModifier, ManaModifier, ArmorModifier, DamageModifier, ExperienceModifier, RacialLeader, "
- // 70 71 72 73 74 75 76 77 78 79 80
- "questItem1, questItem2, questItem3, questItem4, questItem5, questItem6, movementId, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName "
+ // 70 71 72 73 74
+ "movementId, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName "
"FROM creature_template;");
if (!result)
@@ -454,7 +446,7 @@ void ObjectMgr::LoadCreatureTemplate(Field* fields)
creatureTemplate.Modelid3 = fields[8].GetUInt32();
creatureTemplate.Modelid4 = fields[9].GetUInt32();
creatureTemplate.Name = fields[10].GetString();
- creatureTemplate.SubName = fields[11].GetString();
+ creatureTemplate.Title = fields[11].GetString();
creatureTemplate.IconName = fields[12].GetString();
creatureTemplate.GossipMenuId = fields[13].GetUInt32();
creatureTemplate.minlevel = fields[14].GetUInt8();
@@ -507,14 +499,11 @@ void ObjectMgr::LoadCreatureTemplate(Field* fields)
creatureTemplate.ModExperience = fields[68].GetFloat();
creatureTemplate.RacialLeader = fields[69].GetBool();
- for (uint8 i = 0; i < MAX_CREATURE_QUEST_ITEMS; ++i)
- creatureTemplate.questItems[i] = fields[70 + i].GetUInt32();
-
- creatureTemplate.movementId = fields[76].GetUInt32();
- creatureTemplate.RegenHealth = fields[77].GetBool();
- creatureTemplate.MechanicImmuneMask = fields[78].GetUInt32();
- creatureTemplate.flags_extra = fields[79].GetUInt32();
- creatureTemplate.ScriptID = GetScriptId(fields[80].GetCString());
+ creatureTemplate.movementId = fields[70].GetUInt32();
+ creatureTemplate.RegenHealth = fields[71].GetBool();
+ creatureTemplate.MechanicImmuneMask = fields[72].GetUInt32();
+ creatureTemplate.flags_extra = fields[73].GetUInt32();
+ creatureTemplate.ScriptID = GetScriptId(fields[74].GetString());
}
void ObjectMgr::LoadCreatureTemplateAddons()
@@ -566,6 +555,12 @@ void ObjectMgr::LoadCreatureTemplateAddons()
if (AdditionalSpellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE))
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has SPELL_AURA_CONTROL_VEHICLE aura %lu defined in `auras` field in `creature_template_addon`.", entry, atoul(*itr));
+ if (std::find(creatureAddon.auras.begin(), creatureAddon.auras.end(), atoul(*itr)) != creatureAddon.auras.end())
+ {
+ TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has duplicate aura (spell %lu) in `auras` field in `creature_template_addon`.", entry, atoul(*itr));
+ continue;
+ }
+
creatureAddon.auras[i++] = atoul(*itr);
}
@@ -976,7 +971,7 @@ void ObjectMgr::LoadCreatureAddons()
{
Field* fields = result->Fetch();
- uint32 guid = fields[0].GetUInt32();
+ ObjectGuid::LowType guid = fields[0].GetUInt32();
CreatureData const* creData = GetCreatureData(guid);
if (!creData)
@@ -1014,6 +1009,12 @@ void ObjectMgr::LoadCreatureAddons()
if (AdditionalSpellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE))
TC_LOG_ERROR("sql.sql", "Creature (GUID: %u) has SPELL_AURA_CONTROL_VEHICLE aura %lu defined in `auras` field in `creature_addon`.", guid, atoul(*itr));
+ if (std::find(creatureAddon.auras.begin(), creatureAddon.auras.end(), atoul(*itr)) != creatureAddon.auras.end())
+ {
+ TC_LOG_ERROR("sql.sql", "Creature (GUID: %u) has duplicate aura (spell %lu) in `auras` field in `creature_addon`.", guid, atoul(*itr));
+ continue;
+ }
+
creatureAddon.auras[i++] = atoul(*itr);
}
@@ -1099,7 +1100,7 @@ GameObjectAddon const* ObjectMgr::GetGameObjectAddon(ObjectGuid::LowType lowguid
return NULL;
}
-CreatureAddon const* ObjectMgr::GetCreatureAddon(uint32 lowguid)
+CreatureAddon const* ObjectMgr::GetCreatureAddon(ObjectGuid::LowType lowguid)
{
CreatureAddonContainer::const_iterator itr = _creatureAddonStore.find(lowguid);
if (itr != _creatureAddonStore.end())
@@ -1147,8 +1148,8 @@ void ObjectMgr::LoadEquipmentTemplates()
{
uint32 oldMSTime = getMSTime();
- // 0 1 2 3 4
- QueryResult result = WorldDatabase.Query("SELECT entry, id, itemEntry1, itemEntry2, itemEntry3 FROM creature_equip_template");
+ // 0 1 2 3 4
+ QueryResult result = WorldDatabase.Query("SELECT CreatureID, ID, ItemID1, ItemID2, ItemID3 FROM creature_equip_template");
if (!result)
{
@@ -1235,7 +1236,11 @@ uint32 ObjectMgr::ChooseDisplayId(CreatureTemplate const* cinfo, CreatureData co
if (data && data->displayid)
return data->displayid;
- return cinfo->GetRandomValidModelId();
+ if (!(cinfo->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER))
+ return cinfo->GetRandomValidModelId();
+
+ // Triggers by default receive the invisible model
+ return cinfo->GetFirstInvisibleModel();
}
void ObjectMgr::ChooseCreatureFlags(const CreatureTemplate* cinfo, uint32& npcflag, uint32& unit_flags, uint32& dynamicflags, const CreatureData* data /*= NULL*/)
@@ -1283,8 +1288,8 @@ CreatureModelInfo const* ObjectMgr::GetCreatureModelRandomGender(uint32* display
void ObjectMgr::LoadCreatureModelInfo()
{
uint32 oldMSTime = getMSTime();
-
- QueryResult result = WorldDatabase.Query("SELECT modelid, bounding_radius, combat_reach, gender, modelid_other_gender FROM creature_model_info");
+ // 0 1 2 3 4
+ QueryResult result = WorldDatabase.Query("SELECT DisplayID, BoundingRadius, CombatReach, Gender, DisplayID_Other_Gender FROM creature_model_info");
if (!result)
{
@@ -1300,6 +1305,12 @@ void ObjectMgr::LoadCreatureModelInfo()
Field* fields = result->Fetch();
uint32 modelId = fields[0].GetUInt32();
+ CreatureDisplayInfoEntry const* creatureDisplay = sCreatureDisplayInfoStore.LookupEntry(modelId);
+ if (!creatureDisplay)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `creature_model_info` has model for nonexistent display id (%u).", modelId);
+ continue;
+ }
CreatureModelInfo& modelInfo = _creatureModelStore[modelId];
@@ -1307,12 +1318,10 @@ void ObjectMgr::LoadCreatureModelInfo()
modelInfo.combat_reach = fields[2].GetFloat();
modelInfo.gender = fields[3].GetUInt8();
modelInfo.modelid_other_gender = fields[4].GetUInt32();
+ modelInfo.is_trigger = false;
// Checks
- if (!sCreatureDisplayInfoStore.LookupEntry(modelId))
- TC_LOG_ERROR("sql.sql", "Table `creature_model_info` has model for nonexistent display id (%u).", modelId);
-
if (modelInfo.gender > GENDER_NONE)
{
TC_LOG_ERROR("sql.sql", "Table `creature_model_info` has wrong gender (%u) for display id (%u).", uint32(modelInfo.gender), modelId);
@@ -1328,6 +1337,9 @@ void ObjectMgr::LoadCreatureModelInfo()
if (modelInfo.combat_reach < 0.1f)
modelInfo.combat_reach = DEFAULT_COMBAT_REACH;
+ if (CreatureModelDataEntry const* modelData = sCreatureModelDataStore.LookupEntry(creatureDisplay->ModelId))
+ modelInfo.is_trigger = strstr(modelData->ModelPath, "InvisibleStalker") != nullptr;
+
++count;
}
while (result->NextRow());
@@ -1353,8 +1365,8 @@ void ObjectMgr::LoadLinkedRespawn()
{
Field* fields = result->Fetch();
- uint32 guidLow = fields[0].GetUInt32();
- uint32 linkedGuidLow = fields[1].GetUInt32();
+ ObjectGuid::LowType guidLow = fields[0].GetUInt32();
+ ObjectGuid::LowType linkedGuidLow = fields[1].GetUInt32();
uint8 linkType = fields[2].GetUInt8();
ObjectGuid guid, linkedGuid;
@@ -1394,8 +1406,8 @@ void ObjectMgr::LoadLinkedRespawn()
break;
}
- guid = ObjectGuid(HIGHGUID_UNIT, slave->id, guidLow);
- linkedGuid = ObjectGuid(HIGHGUID_UNIT, master->id, linkedGuidLow);
+ guid = ObjectGuid(HighGuid::Unit, slave->id, guidLow);
+ linkedGuid = ObjectGuid(HighGuid::Unit, master->id, linkedGuidLow);
break;
}
case CREATURE_TO_GO:
@@ -1431,8 +1443,8 @@ void ObjectMgr::LoadLinkedRespawn()
break;
}
- guid = ObjectGuid(HIGHGUID_UNIT, slave->id, guidLow);
- linkedGuid = ObjectGuid(HIGHGUID_GAMEOBJECT, master->id, linkedGuidLow);
+ guid = ObjectGuid(HighGuid::Unit, slave->id, guidLow);
+ linkedGuid = ObjectGuid(HighGuid::GameObject, master->id, linkedGuidLow);
break;
}
case GO_TO_GO:
@@ -1468,8 +1480,8 @@ void ObjectMgr::LoadLinkedRespawn()
break;
}
- guid = ObjectGuid(HIGHGUID_GAMEOBJECT, slave->id, guidLow);
- linkedGuid = ObjectGuid(HIGHGUID_GAMEOBJECT, master->id, linkedGuidLow);
+ guid = ObjectGuid(HighGuid::GameObject, slave->id, guidLow);
+ linkedGuid = ObjectGuid(HighGuid::GameObject, master->id, linkedGuidLow);
break;
}
case GO_TO_CREATURE:
@@ -1505,8 +1517,8 @@ void ObjectMgr::LoadLinkedRespawn()
break;
}
- guid = ObjectGuid(HIGHGUID_GAMEOBJECT, slave->id, guidLow);
- linkedGuid = ObjectGuid(HIGHGUID_UNIT, master->id, linkedGuidLow);
+ guid = ObjectGuid(HighGuid::GameObject, slave->id, guidLow);
+ linkedGuid = ObjectGuid(HighGuid::Unit, master->id, linkedGuidLow);
break;
}
}
@@ -1519,14 +1531,14 @@ void ObjectMgr::LoadLinkedRespawn()
TC_LOG_INFO("server.loading", ">> Loaded " UI64FMTD " linked respawns in %u ms", uint64(_linkedRespawnStore.size()), GetMSTimeDiffToNow(oldMSTime));
}
-bool ObjectMgr::SetCreatureLinkedRespawn(uint32 guidLow, uint32 linkedGuidLow)
+bool ObjectMgr::SetCreatureLinkedRespawn(ObjectGuid::LowType guidLow, ObjectGuid::LowType linkedGuidLow)
{
if (!guidLow)
return false;
CreatureData const* master = GetCreatureData(guidLow);
ASSERT(master);
- ObjectGuid guid(HIGHGUID_UNIT, master->id, guidLow);
+ ObjectGuid guid(HighGuid::Unit, master->id, guidLow);
if (!linkedGuidLow) // we're removing the linking
{
@@ -1557,7 +1569,7 @@ bool ObjectMgr::SetCreatureLinkedRespawn(uint32 guidLow, uint32 linkedGuidLow)
return false;
}
- ObjectGuid linkedGuid(HIGHGUID_UNIT, slave->id, linkedGuidLow);
+ ObjectGuid linkedGuid(HighGuid::Unit, slave->id, linkedGuidLow);
_linkedRespawnStore[guid] = linkedGuid;
PreparedStatement *stmt = WorldDatabase.GetPreparedStatement(WORLD_REP_CREATURE_LINKED_RESPAWN);
@@ -1687,7 +1699,7 @@ void ObjectMgr::LoadCreatures()
{
Field* fields = result->Fetch();
- uint32 guid = fields[0].GetUInt32();
+ ObjectGuid::LowType guid = fields[0].GetUInt32();
uint32 entry = fields[1].GetUInt32();
CreatureTemplate const* cInfo = GetCreatureTemplate(entry);
@@ -1818,7 +1830,7 @@ void ObjectMgr::LoadCreatures()
TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " creatures in %u ms", _creatureDataStore.size(), GetMSTimeDiffToNow(oldMSTime));
}
-void ObjectMgr::AddCreatureToGrid(uint32 guid, CreatureData const* data)
+void ObjectMgr::AddCreatureToGrid(ObjectGuid::LowType guid, CreatureData const* data)
{
uint8 mask = data->spawnMask;
for (uint8 i = 0; mask != 0; i++, mask >>= 1)
@@ -1832,7 +1844,7 @@ void ObjectMgr::AddCreatureToGrid(uint32 guid, CreatureData const* data)
}
}
-void ObjectMgr::RemoveCreatureFromGrid(uint32 guid, CreatureData const* data)
+void ObjectMgr::RemoveCreatureFromGrid(ObjectGuid::LowType guid, CreatureData const* data)
{
uint8 mask = data->spawnMask;
for (uint8 i = 0; mask != 0; i++, mask >>= 1)
@@ -1846,7 +1858,7 @@ void ObjectMgr::RemoveCreatureFromGrid(uint32 guid, CreatureData const* data)
}
}
-uint32 ObjectMgr::AddGOData(uint32 entry, uint32 mapId, float x, float y, float z, float o, uint32 spawntimedelay, float rotation0, float rotation1, float rotation2, float rotation3)
+ObjectGuid::LowType ObjectMgr::AddGOData(uint32 entry, uint32 mapId, float x, float y, float z, float o, uint32 spawntimedelay, float rotation0, float rotation1, float rotation2, float rotation3)
{
GameObjectTemplate const* goinfo = GetGameObjectTemplate(entry);
if (!goinfo)
@@ -1856,7 +1868,8 @@ uint32 ObjectMgr::AddGOData(uint32 entry, uint32 mapId, float x, float y, float
if (!map)
return 0;
- uint32 guid = GenerateLowGuid(HIGHGUID_GAMEOBJECT);
+ ObjectGuid::LowType guid = GenerateGameObjectSpawnId();
+
GameObjectData& data = NewGOData(guid);
data.id = entry;
data.mapid = mapId;
@@ -1896,40 +1909,8 @@ uint32 ObjectMgr::AddGOData(uint32 entry, uint32 mapId, float x, float y, float
return guid;
}
-bool ObjectMgr::MoveCreData(uint32 guid, uint32 mapId, const Position& pos)
-{
- CreatureData& data = NewOrExistCreatureData(guid);
- if (!data.id)
- return false;
- RemoveCreatureFromGrid(guid, &data);
- if (data.posX == pos.GetPositionX() && data.posY == pos.GetPositionY() && data.posZ == pos.GetPositionZ())
- return true;
- data.posX = pos.GetPositionX();
- data.posY = pos.GetPositionY();
- data.posZ = pos.GetPositionZ();
- data.orientation = pos.GetOrientation();
- AddCreatureToGrid(guid, &data);
-
- // Spawn if necessary (loaded grids only)
- if (Map* map = sMapMgr->CreateBaseMap(mapId))
- {
- // We use spawn coords to spawn
- if (!map->Instanceable() && map->IsGridLoaded(data.posX, data.posY))
- {
- Creature* creature = new Creature();
- if (!creature->LoadCreatureFromDB(guid, map))
- {
- TC_LOG_ERROR("misc", "MoveCreData: Cannot add creature guid %u to map", guid);
- delete creature;
- return false;
- }
- }
- }
- return true;
-}
-
-uint32 ObjectMgr::AddCreData(uint32 entry, uint32 mapId, float x, float y, float z, float o, uint32 spawntimedelay /*= 0*/)
+ObjectGuid::LowType ObjectMgr::AddCreatureData(uint32 entry, uint32 mapId, float x, float y, float z, float o, uint32 spawntimedelay /*= 0*/)
{
CreatureTemplate const* cInfo = GetCreatureTemplate(entry);
if (!cInfo)
@@ -1937,8 +1918,11 @@ uint32 ObjectMgr::AddCreData(uint32 entry, uint32 mapId, float x, float y, float
uint32 level = cInfo->minlevel == cInfo->maxlevel ? cInfo->minlevel : urand(cInfo->minlevel, cInfo->maxlevel); // Only used for extracting creature base stats
CreatureBaseStats const* stats = GetCreatureBaseStats(level, cInfo->unit_class);
+ Map* map = sMapMgr->CreateBaseMap(mapId);
+ if (!map)
+ return 0;
- uint32 guid = GenerateLowGuid(HIGHGUID_UNIT);
+ ObjectGuid::LowType guid = GenerateCreatureSpawnId();
CreatureData& data = NewOrExistCreatureData(guid);
data.id = entry;
data.mapid = mapId;
@@ -1963,19 +1947,15 @@ uint32 ObjectMgr::AddCreData(uint32 entry, uint32 mapId, float x, float y, float
AddCreatureToGrid(guid, &data);
- // Spawn if necessary (loaded grids only)
- if (Map* map = sMapMgr->CreateBaseMap(mapId))
+ // We use spawn coords to spawn
+ if (!map->Instanceable() && !map->IsRemovalGrid(x, y))
{
- // We use spawn coords to spawn
- if (!map->Instanceable() && !map->IsRemovalGrid(x, y))
+ Creature* creature = new Creature();
+ if (!creature->LoadCreatureFromDB(guid, map))
{
- Creature* creature = new Creature();
- if (!creature->LoadCreatureFromDB(guid, map))
- {
- TC_LOG_ERROR("misc", "AddCreature: Cannot add creature entry %u to map", entry);
- delete creature;
- return 0;
- }
+ TC_LOG_ERROR("misc", "AddCreature: Cannot add creature entry %u to map", entry);
+ delete creature;
+ return 0;
}
}
@@ -2013,7 +1993,7 @@ void ObjectMgr::LoadGameobjects()
{
Field* fields = result->Fetch();
- uint32 guid = fields[0].GetUInt32();
+ ObjectGuid::LowType guid = fields[0].GetUInt32();
uint32 entry = fields[1].GetUInt32();
GameObjectTemplate const* gInfo = GetGameObjectTemplate(entry);
@@ -2141,7 +2121,7 @@ void ObjectMgr::LoadGameobjects()
TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " gameobjects in %u ms", _gameObjectDataStore.size(), GetMSTimeDiffToNow(oldMSTime));
}
-void ObjectMgr::AddGameobjectToGrid(uint32 guid, GameObjectData const* data)
+void ObjectMgr::AddGameobjectToGrid(ObjectGuid::LowType guid, GameObjectData const* data)
{
uint8 mask = data->spawnMask;
for (uint8 i = 0; mask != 0; i++, mask >>= 1)
@@ -2155,7 +2135,7 @@ void ObjectMgr::AddGameobjectToGrid(uint32 guid, GameObjectData const* data)
}
}
-void ObjectMgr::RemoveGameobjectFromGrid(uint32 guid, GameObjectData const* data)
+void ObjectMgr::RemoveGameobjectFromGrid(ObjectGuid::LowType guid, GameObjectData const* data)
{
uint8 mask = data->spawnMask;
for (uint8 i = 0; mask != 0; i++, mask >>= 1)
@@ -2169,9 +2149,9 @@ void ObjectMgr::RemoveGameobjectFromGrid(uint32 guid, GameObjectData const* data
}
}
-Player* ObjectMgr::GetPlayerByLowGUID(uint32 lowguid) const
+Player* ObjectMgr::GetPlayerByLowGUID(ObjectGuid::LowType lowguid) const
{
- ObjectGuid guid(HIGHGUID_PLAYER, lowguid);
+ ObjectGuid guid(HighGuid::Player, lowguid);
return ObjectAccessor::FindPlayer(guid);
}
@@ -2185,7 +2165,7 @@ ObjectGuid ObjectMgr::GetPlayerGUIDByName(std::string const& name) const
PreparedQueryResult result = CharacterDatabase.Query(stmt);
if (result)
- return ObjectGuid(HIGHGUID_PLAYER, (*result)[0].GetUInt32());
+ return ObjectGuid(HighGuid::Player, (*result)[0].GetUInt32());
return ObjectGuid::Empty;
}
@@ -2239,23 +2219,10 @@ uint32 ObjectMgr::GetPlayerTeamByGUID(ObjectGuid guid) const
uint32 ObjectMgr::GetPlayerAccountIdByGUID(ObjectGuid guid) const
{
- // prevent DB access for online player
- if (Player* player = ObjectAccessor::FindConnectedPlayer(guid))
- {
- return player->GetSession()->GetAccountId();
- }
-
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ACCOUNT_BY_GUID);
+ if (CharacterInfo const* characterInfo = sWorld->GetCharacterInfo(guid))
+ return characterInfo->AccountId;
- stmt->setUInt32(0, guid.GetCounter());
- PreparedQueryResult result = CharacterDatabase.Query(stmt);
-
- if (result)
- {
- uint32 acc = (*result)[0].GetUInt32();
- return acc;
- }
return 0;
}
@@ -2391,6 +2358,12 @@ void ObjectMgr::LoadItemTemplates()
itemTemplate.ContainerSlots = uint32(fields[26].GetUInt8());
itemTemplate.StatsCount = uint32(fields[27].GetUInt8());
+ if (itemTemplate.StatsCount > MAX_ITEM_PROTO_STATS)
+ {
+ TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has too large value in statscount (%u), replace by hardcoded limit (%u).", entry, itemTemplate.StatsCount, MAX_ITEM_PROTO_STATS);
+ itemTemplate.StatsCount = MAX_ITEM_PROTO_STATS;
+ }
+
for (uint8 i = 0; i < itemTemplate.StatsCount; ++i)
{
itemTemplate.ItemStat[i].ItemStatType = uint32(fields[28 + i*2].GetUInt8());
@@ -2461,7 +2434,7 @@ void ObjectMgr::LoadItemTemplates()
itemTemplate.Duration = fields[129].GetUInt32();
itemTemplate.ItemLimitCategory = uint32(fields[130].GetInt16());
itemTemplate.HolidayId = fields[131].GetUInt32();
- itemTemplate.ScriptId = sObjectMgr->GetScriptId(fields[132].GetCString());
+ itemTemplate.ScriptId = sObjectMgr->GetScriptId(fields[132].GetString());
itemTemplate.DisenchantID = fields[133].GetUInt32();
itemTemplate.FoodType = uint32(fields[134].GetUInt8());
itemTemplate.MinMoneyLoot = fields[135].GetUInt32();
@@ -2577,7 +2550,7 @@ void ObjectMgr::LoadItemTemplates()
if (!req)
for (uint8 j = 0; j < MAX_ITEM_PROTO_SPELLS; ++j)
{
- if (itemTemplate.Spells[j].SpellId)
+ if (itemTemplate.Spells[j].SpellId > 0)
{
req = true;
break;
@@ -2638,12 +2611,6 @@ void ObjectMgr::LoadItemTemplates()
itemTemplate.ContainerSlots = MAX_BAG_SIZE;
}
- if (itemTemplate.StatsCount > MAX_ITEM_PROTO_STATS)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has too large value in statscount (%u), replace by hardcoded limit (%u).", entry, itemTemplate.StatsCount, MAX_ITEM_PROTO_STATS);
- itemTemplate.StatsCount = MAX_ITEM_PROTO_STATS;
- }
-
for (uint8 j = 0; j < itemTemplate.StatsCount; ++j)
{
// for ItemStatValue != 0
@@ -3800,8 +3767,8 @@ void ObjectMgr::LoadPlayerInfo()
for (uint8 level = 0; level < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); ++level)
_playerXPperLevel[level] = 0;
- // 0 1
- QueryResult result = WorldDatabase.Query("SELECT lvl, xp_for_next_level FROM player_xp_for_level");
+ // 0 1
+ QueryResult result = WorldDatabase.Query("SELECT Level, Experience FROM player_xp_for_level");
if (!result)
{
@@ -3965,36 +3932,32 @@ void ObjectMgr::LoadQuests()
mExclusiveQuestGroups.clear();
QueryResult result = WorldDatabase.Query("SELECT "
- //0 1 2 3 4 5 6 7 8 9 10 11 12
- "Id, Method, Level, MinLevel, MaxLevel, ZoneOrSort, Type, SuggestedPlayers, LimitTime, RequiredClasses, RequiredRaces, RequiredSkillId, RequiredSkillPoints, "
- // 13 14 15 16 17 18 19 20
- "RequiredFactionId1, RequiredFactionId2, RequiredFactionValue1, RequiredFactionValue2, RequiredMinRepFaction, RequiredMaxRepFaction, RequiredMinRepValue, RequiredMaxRepValue, "
- // 21 22 23 24 25 26 27 28 29 30 31
- "PrevQuestId, NextQuestId, ExclusiveGroup, NextQuestIdChain, RewardXPId, RewardOrRequiredMoney, RewardMoneyMaxLevel, RewardSpell, RewardSpellCast, RewardHonor, RewardHonorMultiplier, "
- // 32 33 34 35 36 37 38 39 40 41 42
- "RewardMailTemplateId, RewardMailDelay, SourceItemId, SourceItemCount, SourceSpellId, Flags, SpecialFlags, RewardTitleId, RequiredPlayerKills, RewardTalents, RewardArenaPoints, "
- // 43 44 45 46 47 48 49 50
- "RewardItemId1, RewardItemId2, RewardItemId3, RewardItemId4, RewardItemCount1, RewardItemCount2, RewardItemCount3, RewardItemCount4, "
- // 51 52 53 54 55 56 57 58 59 60 61 62
- "RewardChoiceItemId1, RewardChoiceItemId2, RewardChoiceItemId3, RewardChoiceItemId4, RewardChoiceItemId5, RewardChoiceItemId6, RewardChoiceItemCount1, RewardChoiceItemCount2, RewardChoiceItemCount3, RewardChoiceItemCount4, RewardChoiceItemCount5, RewardChoiceItemCount6, "
- // 63 64 65 66 67 68 69 70 71 72
- "RewardFactionId1, RewardFactionId2, RewardFactionId3, RewardFactionId4, RewardFactionId5, RewardFactionValueId1, RewardFactionValueId2, RewardFactionValueId3, RewardFactionValueId4, RewardFactionValueId5, "
- // 73 74 75 76 77
- "RewardFactionValueIdOverride1, RewardFactionValueIdOverride2, RewardFactionValueIdOverride3, RewardFactionValueIdOverride4, RewardFactionValueIdOverride5, "
- // 78 79 80 81
- "PointMapId, PointX, PointY, PointOption, "
- // 82 83 84 85 86 87 88
- "Title, Objectives, Details, EndText, OfferRewardText, RequestItemsText, CompletedText, "
- // 89 90 91 92 93 94 95 96
+ //0 1 2 3 4 5 6 7 8
+ "ID, QuestType, QuestLevel, MinLevel, QuestSortID, QuestInfoID, SuggestedGroupNum, TimeAllowed, AllowableRaces,"
+ // 9 10 11 12
+ "RequiredFactionId1, RequiredFactionId2, RequiredFactionValue1, RequiredFactionValue2, "
+ // 13 14 15 16 17 18 19 20
+ "RewardNextQuest, RewardXPDifficulty, RewardMoney, RewardBonusMoney, RewardDisplaySpell, RewardSpell, RewardHonor, RewardKillHonor, "
+ // 21 22 23 24 25 26
+ "StartItem, Flags, RewardTitle, RequiredPlayerKills, RewardTalents, RewardArenaPoints, "
+ // 27 28 29 30 31 32 33 34
+ "RewardItem1, RewardAmount1, RewardItem2, RewardAmount2, RewardItem3, RewardAmount3, RewardItem4, RewardAmount4, "
+ // 35 36 37 38 39 40 41 42 43 44 45 46
+ "RewardChoiceItemID1, RewardChoiceItemQuantity1, RewardChoiceItemID2, RewardChoiceItemQuantity2, RewardChoiceItemID3, RewardChoiceItemQuantity3, RewardChoiceItemID4, RewardChoiceItemQuantity4, RewardChoiceItemID5, RewardChoiceItemQuantity5, RewardChoiceItemID6, RewardChoiceItemQuantity6, "
+ // 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
+ "RewardFactionID1, RewardFactionValue1, RewardFactionOverride1, RewardFactionID2, RewardFactionValue2, RewardFactionOverride2, RewardFactionID3, RewardFactionValue3, RewardFactionOverride3, RewardFactionID4, RewardFactionValue4, RewardFactionOverride4, RewardFactionID5, RewardFactionValue5, RewardFactionOverride5,"
+ // 62 63 64 65
+ "POIContinent, POIx, POIy, POIPriority, "
+ // 66 67 68 69 70
+ "LogTitle, LogDescription, QuestDescription, AreaDescription, QuestCompletionLog, "
+ // 71 72 73 74 75 76 77 78
"RequiredNpcOrGo1, RequiredNpcOrGo2, RequiredNpcOrGo3, RequiredNpcOrGo4, RequiredNpcOrGoCount1, RequiredNpcOrGoCount2, RequiredNpcOrGoCount3, RequiredNpcOrGoCount4, "
- // 97 98 99 100 101 102 103 104
- "RequiredSourceItemId1, RequiredSourceItemId2, RequiredSourceItemId3, RequiredSourceItemId4, RequiredSourceItemCount1, RequiredSourceItemCount2, RequiredSourceItemCount3, RequiredSourceItemCount4, "
- // 105 106 107 108 109 110 111 112 113 114 115 116
+ // 79 80 81 82 83 84 85 86
+ "ItemDrop1, ItemDrop2, ItemDrop3, ItemDrop4, ItemDropQuantity1, ItemDropQuantity2, ItemDropQuantity3, ItemDropQuantity4, "
+ // 87 88 89 90 91 92 93 94 95 96 97 98
"RequiredItemId1, RequiredItemId2, RequiredItemId3, RequiredItemId4, RequiredItemId5, RequiredItemId6, RequiredItemCount1, RequiredItemCount2, RequiredItemCount3, RequiredItemCount4, RequiredItemCount5, RequiredItemCount6, "
- // 117 118 119 120 121 122 123 124 125 126 127 128 129
- "Unknown0, ObjectiveText1, ObjectiveText2, ObjectiveText3, ObjectiveText4, DetailsEmote1, DetailsEmote2, DetailsEmote3, DetailsEmote4, DetailsEmoteDelay1, DetailsEmoteDelay2, DetailsEmoteDelay3, DetailsEmoteDelay4, "
- // 130 131 132 133 134 135 136 137 138 139
- "EmoteOnIncomplete, EmoteOnComplete, OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4, OfferRewardEmoteDelay1, OfferRewardEmoteDelay2, OfferRewardEmoteDelay3, OfferRewardEmoteDelay4"
+ // 99 100 101 102 103
+ "Unknown0, ObjectiveText1, ObjectiveText2, ObjectiveText3, ObjectiveText4"
" FROM quest_template");
if (!result)
{
@@ -4015,6 +3978,100 @@ void ObjectMgr::LoadQuests()
std::map<uint32, uint32> usedMailTemplates;
+ // Load `quest_details`
+ // 0 1 2 3 4 5 6 7 8
+ result = WorldDatabase.Query("SELECT ID, Emote1, Emote2, Emote3, Emote4, EmoteDelay1, EmoteDelay2, EmoteDelay3, EmoteDelay4 FROM quest_details");
+
+ if (!result)
+ {
+ TC_LOG_ERROR("server.loading", ">> Loaded 0 quest details. DB table `quest_details` is empty.");
+ }
+ else
+ {
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 questId = fields[0].GetUInt32();
+
+ auto itr = _questTemplates.find(questId);
+ if (itr != _questTemplates.end())
+ itr->second->LoadQuestDetails(fields);
+ else
+ TC_LOG_ERROR("server.loading", "Table `quest_details` has data for quest %u but such quest does not exist", questId);
+ } while (result->NextRow());
+ }
+
+ // Load `quest_request_items`
+ // 0 1 2 3
+ result = WorldDatabase.Query("SELECT ID, EmoteOnComplete, EmoteOnIncomplete, CompletionText FROM quest_request_items");
+
+ if (!result)
+ {
+ TC_LOG_ERROR("server.loading", ">> Loaded 0 quest request items. DB table `quest_request_items` is empty.");
+ }
+ else
+ {
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 questId = fields[0].GetUInt32();
+
+ auto itr = _questTemplates.find(questId);
+ if (itr != _questTemplates.end())
+ itr->second->LoadQuestRequestItems(fields);
+ else
+ TC_LOG_ERROR("server.loading", "Table `quest_request_items` has data for quest %u but such quest does not exist", questId);
+ } while (result->NextRow());
+ }
+
+ // Load `quest_offer_reward`
+ // 0 1 2 3 4 5 6 7 8 9
+ result = WorldDatabase.Query("SELECT ID, Emote1, Emote2, Emote3, Emote4, EmoteDelay1, EmoteDelay2, EmoteDelay3, EmoteDelay4, RewardText FROM quest_offer_reward");
+
+ if (!result)
+ {
+ TC_LOG_ERROR("server.loading", ">> Loaded 0 quest reward emotes. DB table `quest_offer_reward` is empty.");
+ }
+ else
+ {
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 questId = fields[0].GetUInt32();
+
+ auto itr = _questTemplates.find(questId);
+ if (itr != _questTemplates.end())
+ itr->second->LoadQuestOfferReward(fields);
+ else
+ TC_LOG_ERROR("server.loading", "Table `quest_offer_reward` has data for quest %u but such quest does not exist", questId);
+ } while (result->NextRow());
+ }
+
+ // Load `quest_template_addon`
+ // 0 1 2 3 4 5 6 7 8
+ result = WorldDatabase.Query("SELECT ID, MaxLevel, AllowableClasses, SourceSpellID, PrevQuestID, NextQuestID, ExclusiveGroup, RewardMailTemplateID, RewardMailDelay, "
+ //9 10 11 12 13 14 15 16
+ "RequiredSkillID, RequiredSkillPoints, RequiredMinRepFaction, RequiredMaxRepFaction, RequiredMinRepValue, RequiredMaxRepValue, ProvidedItemCount, SpecialFlags FROM quest_template_addon");
+
+ if (!result)
+ {
+ TC_LOG_ERROR("server.loading", ">> Loaded 0 quest template addons. DB table `quest_template_addon` is empty.");
+ }
+ else
+ {
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 questId = fields[0].GetUInt32();
+
+ auto itr = _questTemplates.find(questId);
+ if (itr != _questTemplates.end())
+ itr->second->LoadQuestTemplateAddon(fields);
+ else
+ TC_LOG_ERROR("server.loading", "Table `quest_template_addon` has data for quest %u but such quest does not exist", questId);
+ } while (result->NextRow());
+ }
+
// Post processing
for (QuestMap::iterator iter = _questTemplates.begin(); iter != _questTemplates.end(); ++iter)
{
@@ -4124,13 +4181,13 @@ void ObjectMgr::LoadQuests()
qinfo->RequiredClasses = 0;
}
}
- // RequiredRaces, can be 0/RACEMASK_ALL_PLAYABLE to allow any race
- if (qinfo->RequiredRaces)
+ // AllowableRaces, can be 0/RACEMASK_ALL_PLAYABLE to allow any race
+ if (qinfo->AllowableRaces)
{
- if (!(qinfo->RequiredRaces & RACEMASK_ALL_PLAYABLE))
+ if (!(qinfo->AllowableRaces & RACEMASK_ALL_PLAYABLE))
{
- TC_LOG_ERROR("sql.sql", "Quest %u does not contain any playable races in `RequiredRaces` (%u), value set to 0 (all races).", qinfo->GetQuestId(), qinfo->RequiredRaces);
- qinfo->RequiredRaces = 0;
+ TC_LOG_ERROR("sql.sql", "Quest %u does not contain any playable races in `AllowableRaces` (%u), value set to 0 (all races).", qinfo->GetQuestId(), qinfo->AllowableRaces);
+ qinfo->AllowableRaces = 0;
}
}
// RequiredSkillId, can be 0
@@ -4232,26 +4289,26 @@ void ObjectMgr::LoadQuests()
// quest can't reward this title
}
- if (qinfo->SourceItemId)
+ if (qinfo->StartItem)
{
- if (!sObjectMgr->GetItemTemplate(qinfo->SourceItemId))
+ if (!sObjectMgr->GetItemTemplate(qinfo->StartItem))
{
- TC_LOG_ERROR("sql.sql", "Quest %u has `SourceItemId` = %u but item with entry %u does not exist, quest can't be done.",
- qinfo->GetQuestId(), qinfo->SourceItemId, qinfo->SourceItemId);
- qinfo->SourceItemId = 0; // quest can't be done for this requirement
+ TC_LOG_ERROR("sql.sql", "Quest %u has `StartItem` = %u but item with entry %u does not exist, quest can't be done.",
+ qinfo->GetQuestId(), qinfo->StartItem, qinfo->StartItem);
+ qinfo->StartItem = 0; // quest can't be done for this requirement
}
- else if (qinfo->SourceItemIdCount == 0)
+ else if (qinfo->StartItemCount == 0)
{
- TC_LOG_ERROR("sql.sql", "Quest %u has `SourceItemId` = %u but `SourceItemIdCount` = 0, set to 1 but need fix in DB.",
- qinfo->GetQuestId(), qinfo->SourceItemId);
- qinfo->SourceItemIdCount = 1; // update to 1 for allow quest work for backward compatibility with DB
+ TC_LOG_ERROR("sql.sql", "Quest %u has `StartItem` = %u but `StartItemCount` = 0, set to 1 but need fix in DB.",
+ qinfo->GetQuestId(), qinfo->StartItem);
+ qinfo->StartItemCount = 1; // update to 1 for allow quest work for backward compatibility with DB
}
}
- else if (qinfo->SourceItemIdCount>0)
+ else if (qinfo->StartItemCount>0)
{
- TC_LOG_ERROR("sql.sql", "Quest %u has `SourceItemId` = 0 but `SourceItemIdCount` = %u, useless value.",
- qinfo->GetQuestId(), qinfo->SourceItemIdCount);
- qinfo->SourceItemIdCount=0; // no quest work changes in fact
+ TC_LOG_ERROR("sql.sql", "Quest %u has `StartItem` = 0 but `StartItemCount` = %u, useless value.",
+ qinfo->GetQuestId(), qinfo->StartItemCount);
+ qinfo->StartItemCount=0; // no quest work changes in fact
}
if (qinfo->SourceSpellid)
@@ -4302,22 +4359,22 @@ void ObjectMgr::LoadQuests()
for (uint8 j = 0; j < QUEST_SOURCE_ITEM_IDS_COUNT; ++j)
{
- uint32 id = qinfo->RequiredSourceItemId[j];
+ uint32 id = qinfo->ItemDrop[j];
if (id)
{
if (!sObjectMgr->GetItemTemplate(id))
{
- TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredSourceItemId%d` = %u but item with entry %u does not exist, quest can't be done.",
+ TC_LOG_ERROR("sql.sql", "Quest %u has `ItemDrop%d` = %u but item with entry %u does not exist, quest can't be done.",
qinfo->GetQuestId(), j+1, id, id);
// no changes, quest can't be done for this requirement
}
}
else
{
- if (qinfo->RequiredSourceItemCount[j]>0)
+ if (qinfo->ItemDropQuantity[j]>0)
{
- TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredSourceItemId%d` = 0 but `RequiredSourceItemCount%d` = %u.",
- qinfo->GetQuestId(), j+1, j+1, qinfo->RequiredSourceItemCount[j]);
+ TC_LOG_ERROR("sql.sql", "Quest %u has `ItemDrop%d` = 0 but `ItemDropQuantity%d` = %u.",
+ qinfo->GetQuestId(), j+1, j+1, qinfo->ItemDropQuantity[j]);
// no changes, quest ignore this data
}
}
@@ -4438,55 +4495,55 @@ void ObjectMgr::LoadQuests()
}
}
- if (qinfo->RewardSpell)
+ if (qinfo->RewardDisplaySpell)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(qinfo->RewardSpell);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(qinfo->RewardDisplaySpell);
if (!spellInfo)
{
- TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSpell` = %u but spell %u does not exist, spell removed as display reward.",
- qinfo->GetQuestId(), qinfo->RewardSpell, qinfo->RewardSpell);
- qinfo->RewardSpell = 0; // no spell reward will display for this quest
+ TC_LOG_ERROR("sql.sql", "Quest %u has `RewardDisplaySpell` = %u but spell %u does not exist, spell removed as display reward.",
+ qinfo->GetQuestId(), qinfo->RewardDisplaySpell, qinfo->RewardDisplaySpell);
+ qinfo->RewardDisplaySpell = 0; // no spell reward will display for this quest
}
else if (!SpellMgr::IsSpellValid(spellInfo))
{
- TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSpell` = %u but spell %u is broken, quest will not have a spell reward.",
- qinfo->GetQuestId(), qinfo->RewardSpell, qinfo->RewardSpell);
- qinfo->RewardSpell = 0; // no spell reward will display for this quest
+ TC_LOG_ERROR("sql.sql", "Quest %u has `RewardDisplaySpell` = %u but spell %u is broken, quest will not have a spell reward.",
+ qinfo->GetQuestId(), qinfo->RewardDisplaySpell, qinfo->RewardDisplaySpell);
+ qinfo->RewardDisplaySpell = 0; // no spell reward will display for this quest
}
- else if (GetTalentSpellCost(qinfo->RewardSpell))
+ else if (GetTalentSpellCost(qinfo->RewardDisplaySpell))
{
- TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSpell` = %u but spell %u is talent, quest will not have a spell reward.",
- qinfo->GetQuestId(), qinfo->RewardSpell, qinfo->RewardSpell);
- qinfo->RewardSpell = 0; // no spell reward will display for this quest
+ TC_LOG_ERROR("sql.sql", "Quest %u has `RewardDisplaySpell` = %u but spell %u is talent, quest will not have a spell reward.",
+ qinfo->GetQuestId(), qinfo->RewardDisplaySpell, qinfo->RewardDisplaySpell);
+ qinfo->RewardDisplaySpell = 0; // no spell reward will display for this quest
}
}
- if (qinfo->RewardSpellCast > 0)
+ if (qinfo->RewardSpell > 0)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(qinfo->RewardSpellCast);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(qinfo->RewardSpell);
if (!spellInfo)
{
- TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSpellCast` = %u but spell %u does not exist, quest will not have a spell reward.",
- qinfo->GetQuestId(), qinfo->RewardSpellCast, qinfo->RewardSpellCast);
- qinfo->RewardSpellCast = 0; // no spell will be cast on player
+ TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSpell` = %u but spell %u does not exist, quest will not have a spell reward.",
+ qinfo->GetQuestId(), qinfo->RewardSpell, qinfo->RewardSpell);
+ qinfo->RewardSpell = 0; // no spell will be cast on player
}
else if (!SpellMgr::IsSpellValid(spellInfo))
{
- TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSpellCast` = %u but spell %u is broken, quest will not have a spell reward.",
- qinfo->GetQuestId(), qinfo->RewardSpellCast, qinfo->RewardSpellCast);
- qinfo->RewardSpellCast = 0; // no spell will be cast on player
+ TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSpell` = %u but spell %u is broken, quest will not have a spell reward.",
+ qinfo->GetQuestId(), qinfo->RewardSpell, qinfo->RewardSpell);
+ qinfo->RewardSpell = 0; // no spell will be cast on player
}
- else if (GetTalentSpellCost(qinfo->RewardSpellCast))
+ else if (GetTalentSpellCost(qinfo->RewardSpell))
{
- TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSpell` = %u but spell %u is talent, quest will not have a spell reward.",
- qinfo->GetQuestId(), qinfo->RewardSpellCast, qinfo->RewardSpellCast);
- qinfo->RewardSpellCast = 0; // no spell will be cast on player
+ TC_LOG_ERROR("sql.sql", "Quest %u has `RewardDisplaySpell` = %u but spell %u is talent, quest will not have a spell reward.",
+ qinfo->GetQuestId(), qinfo->RewardSpell, qinfo->RewardSpell);
+ qinfo->RewardSpell = 0; // no spell will be cast on player
}
}
@@ -4511,14 +4568,14 @@ void ObjectMgr::LoadQuests()
usedMailTemplates[qinfo->RewardMailTemplateId] = qinfo->GetQuestId();
}
- if (qinfo->NextQuestIdChain)
+ if (qinfo->RewardNextQuest)
{
- QuestMap::iterator qNextItr = _questTemplates.find(qinfo->NextQuestIdChain);
+ QuestMap::iterator qNextItr = _questTemplates.find(qinfo->RewardNextQuest);
if (qNextItr == _questTemplates.end())
{
- TC_LOG_ERROR("sql.sql", "Quest %u has `NextQuestIdChain` = %u but quest %u does not exist, quest chain will not work.",
- qinfo->GetQuestId(), qinfo->NextQuestIdChain, qinfo->NextQuestIdChain);
- qinfo->NextQuestIdChain = 0;
+ TC_LOG_ERROR("sql.sql", "Quest %u has `RewardNextQuest` = %u but quest %u does not exist, quest chain will not work.",
+ qinfo->GetQuestId(), qinfo->RewardNextQuest, qinfo->RewardNextQuest);
+ qinfo->RewardNextQuest = 0;
}
else
qNextItr->second->prevChainQuests.push_back(qinfo->GetQuestId());
@@ -4553,7 +4610,7 @@ void ObjectMgr::LoadQuests()
if (qinfo->ExclusiveGroup)
mExclusiveQuestGroups.insert(std::pair<int32, uint32>(qinfo->ExclusiveGroup, qinfo->GetQuestId()));
- if (qinfo->LimitTime)
+ if (qinfo->TimeAllowed)
qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED);
if (qinfo->RequiredPlayerKills)
qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_PLAYER_KILL);
@@ -4629,7 +4686,7 @@ void ObjectMgr::LoadQuestLocales()
AddLocaleString(fields[1 + 11 * (i - 1) + 2].GetString(), locale, data.Objectives);
AddLocaleString(fields[1 + 11 * (i - 1) + 3].GetString(), locale, data.OfferRewardText);
AddLocaleString(fields[1 + 11 * (i - 1) + 4].GetString(), locale, data.RequestItemsText);
- AddLocaleString(fields[1 + 11 * (i - 1) + 5].GetString(), locale, data.EndText);
+ AddLocaleString(fields[1 + 11 * (i - 1) + 5].GetString(), locale, data.AreaDescription);
AddLocaleString(fields[1 + 11 * (i - 1) + 6].GetString(), locale, data.CompletedText);
for (uint8 k = 0; k < 4; ++k)
@@ -4999,13 +5056,13 @@ void ObjectMgr::LoadEventScripts()
{
for (size_t node_idx = 0; node_idx < sTaxiPathNodesByPath[path_idx].size(); ++node_idx)
{
- TaxiPathNodeEntry const& node = sTaxiPathNodesByPath[path_idx][node_idx];
+ TaxiPathNodeEntry const* node = sTaxiPathNodesByPath[path_idx][node_idx];
- if (node.ArrivalEventID)
- evt_scripts.insert(node.ArrivalEventID);
+ if (node->ArrivalEventID)
+ evt_scripts.insert(node->ArrivalEventID);
- if (node.DepartureEventID)
- evt_scripts.insert(node.DepartureEventID);
+ if (node->DepartureEventID)
+ evt_scripts.insert(node->DepartureEventID);
}
}
@@ -5069,8 +5126,8 @@ void ObjectMgr::LoadSpellScriptNames()
Field* fields = result->Fetch();
- int32 spellId = fields[0].GetInt32();
- char const* scriptName = fields[1].GetCString();
+ int32 spellId = fields[0].GetInt32();
+ std::string const scriptName = fields[1].GetString();
bool allRanks = false;
if (spellId < 0)
@@ -5082,18 +5139,18 @@ void ObjectMgr::LoadSpellScriptNames()
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!spellInfo)
{
- TC_LOG_ERROR("sql.sql", "Scriptname: `%s` spell (Id: %d) does not exist.", scriptName, spellId);
+ TC_LOG_ERROR("sql.sql", "Scriptname: `%s` spell (Id: %d) does not exist.", scriptName.c_str(), spellId);
continue;
}
if (allRanks)
{
if (!spellInfo->IsRanked())
- TC_LOG_ERROR("sql.sql", "Scriptname: `%s` spell (Id: %d) has no ranks of spell.", scriptName, fields[0].GetInt32());
+ TC_LOG_ERROR("sql.sql", "Scriptname: `%s` spell (Id: %d) has no ranks of spell.", scriptName.c_str(), fields[0].GetInt32());
if (spellInfo->GetFirstRankSpell()->Id != uint32(spellId))
{
- TC_LOG_ERROR("sql.sql", "Scriptname: `%s` spell (Id: %d) is not first rank of spell.", scriptName, fields[0].GetInt32());
+ TC_LOG_ERROR("sql.sql", "Scriptname: `%s` spell (Id: %d) is not first rank of spell.", scriptName.c_str(), fields[0].GetInt32());
continue;
}
@@ -5106,7 +5163,7 @@ void ObjectMgr::LoadSpellScriptNames()
else
{
if (spellInfo->IsRanked())
- TC_LOG_ERROR("sql.sql", "Scriptname: `%s` spell (Id: %d) is ranked spell. Perhaps not all ranks are assigned to this script.", scriptName, spellId);
+ TC_LOG_ERROR("sql.sql", "Scriptname: `%s` spell (Id: %d) is ranked spell. Perhaps not all ranks are assigned to this script.", scriptName.c_str(), spellId);
_spellScriptsStore.insert(SpellScriptsContainer::value_type(spellInfo->Id, GetScriptId(scriptName)));
}
@@ -5144,7 +5201,7 @@ void ObjectMgr::ValidateSpellScripts()
bool valid = true;
if (!spellScript && !auraScript)
{
- TC_LOG_ERROR("scripts", "Functions GetSpellScript() and GetAuraScript() of script `%s` do not return objects - script skipped", GetScriptName(sitr->second->second));
+ TC_LOG_ERROR("scripts", "Functions GetSpellScript() and GetAuraScript() of script `%s` do not return objects - script skipped", GetScriptName(sitr->second->second).c_str());
valid = false;
}
if (spellScript)
@@ -5178,8 +5235,8 @@ void ObjectMgr::LoadPageTexts()
{
uint32 oldMSTime = getMSTime();
- // 0 1 2
- QueryResult result = WorldDatabase.Query("SELECT entry, text, next_page FROM page_text");
+ // 0 1 2
+ QueryResult result = WorldDatabase.Query("SELECT ID, Text, NextPageID FROM page_text");
if (!result)
{
@@ -5280,7 +5337,7 @@ void ObjectMgr::LoadInstanceTemplate()
instanceTemplate.AllowMount = fields[3].GetBool();
instanceTemplate.Parent = uint32(fields[1].GetUInt16());
- instanceTemplate.ScriptId = sObjectMgr->GetScriptId(fields[2].GetCString());
+ instanceTemplate.ScriptId = sObjectMgr->GetScriptId(fields[2].GetString());
_instanceTemplateStore[mapID] = instanceTemplate;
@@ -5392,14 +5449,14 @@ void ObjectMgr::LoadGossipText()
uint32 oldMSTime = getMSTime();
QueryResult result = WorldDatabase.Query("SELECT ID, "
- "text0_0, text0_1, BroadcastTextID0, lang0, prob0, em0_0, em0_1, em0_2, em0_3, em0_4, em0_5, "
- "text1_0, text1_1, BroadcastTextID1, lang1, prob1, em1_0, em1_1, em1_2, em1_3, em1_4, em1_5, "
- "text2_0, text2_1, BroadcastTextID2, lang2, prob2, em2_0, em2_1, em2_2, em2_3, em2_4, em2_5, "
- "text3_0, text3_1, BroadcastTextID3, lang3, prob3, em3_0, em3_1, em3_2, em3_3, em3_4, em3_5, "
- "text4_0, text4_1, BroadcastTextID4, lang4, prob4, em4_0, em4_1, em4_2, em4_3, em4_4, em4_5, "
- "text5_0, text5_1, BroadcastTextID5, lang5, prob5, em5_0, em5_1, em5_2, em5_3, em5_4, em5_5, "
- "text6_0, text6_1, BroadcastTextID6, lang6, prob6, em6_0, em6_1, em6_2, em6_3, em6_4, em6_5, "
- "text7_0, text7_1, BroadcastTextID7, lang7, prob7, em7_0, em7_1, em7_2, em7_3, em7_4, em7_5 "
+ "text0_0, text0_1, BroadcastTextID0, lang0, Probability0, em0_0, em0_1, em0_2, em0_3, em0_4, em0_5, "
+ "text1_0, text1_1, BroadcastTextID1, lang1, Probability1, em1_0, em1_1, em1_2, em1_3, em1_4, em1_5, "
+ "text2_0, text2_1, BroadcastTextID2, lang2, Probability2, em2_0, em2_1, em2_2, em2_3, em2_4, em2_5, "
+ "text3_0, text3_1, BroadcastTextID3, lang3, Probability3, em3_0, em3_1, em3_2, em3_3, em3_4, em3_5, "
+ "text4_0, text4_1, BroadcastTextID4, lang4, Probability4, em4_0, em4_1, em4_2, em4_3, em4_4, em4_5, "
+ "text5_0, text5_1, BroadcastTextID5, lang5, Probability5, em5_0, em5_1, em5_2, em5_3, em5_4, em5_5, "
+ "text6_0, text6_1, BroadcastTextID6, lang6, Probability6, em6_0, em6_1, em6_2, em6_3, em6_4, em6_5, "
+ "text7_0, text7_1, BroadcastTextID7, lang7, Probability7, em7_0, em7_1, em7_2, em7_3, em7_4, em7_5 "
"FROM npc_text");
@@ -5567,7 +5624,7 @@ void ObjectMgr::ReturnOrDeleteOldMails(bool serverUp)
Player* player = NULL;
if (serverUp)
- player = ObjectAccessor::FindConnectedPlayer(ObjectGuid(HIGHGUID_PLAYER, m->receiver));
+ player = ObjectAccessor::FindConnectedPlayer(ObjectGuid(HighGuid::Player, m->receiver));
if (player && player->m_mailsLoaded)
{ // this code will run very improbably (the time is between 4 and 5 am, in game is online a player, who has old mail
@@ -5745,8 +5802,8 @@ void ObjectMgr::LoadAreaTriggerScripts()
{
Field* fields = result->Fetch();
- uint32 triggerId = fields[0].GetUInt32();
- char const* scriptName = fields[1].GetCString();
+ uint32 triggerId = fields[0].GetUInt32();
+ std::string const scriptName = fields[1].GetString();
AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(triggerId);
if (!atEntry)
@@ -5967,7 +6024,8 @@ WorldSafeLocsEntry const* ObjectMgr::GetClosestGraveYard(float x, float y, float
// not need to check validity of map object; MapId _MUST_ be valid here
if (range.first == range.second && !map->IsBattlegroundOrArena())
{
- TC_LOG_ERROR("sql.sql", "Table `game_graveyard_zone` incomplete: Zone %u Team %u does not have a linked graveyard.", zoneId, team);
+ if (zoneId != 0) // zone == 0 can't be fixed, used by bliz for bugged zones
+ TC_LOG_ERROR("sql.sql", "Table `game_graveyard_zone` incomplete: Zone %u Team %u does not have a linked graveyard.", zoneId, team);
return GetDefaultGraveYard(team);
}
@@ -6158,8 +6216,8 @@ void ObjectMgr::LoadAreaTriggerTeleports()
_areaTriggerStore.clear(); // need for reload case
- // 0 1 2 3 4 5
- QueryResult result = WorldDatabase.Query("SELECT id, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM areatrigger_teleport");
+ // 0 1 2 3 4 5
+ QueryResult result = WorldDatabase.Query("SELECT ID, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM areatrigger_teleport");
if (!result)
{
TC_LOG_INFO("server.loading", ">> Loaded 0 area trigger teleport definitions. DB table `areatrigger_teleport` is empty.");
@@ -6363,29 +6421,21 @@ void ObjectMgr::SetHighestGuids()
{
QueryResult result = CharacterDatabase.Query("SELECT MAX(guid) FROM characters");
if (result)
- _hiCharGuid = (*result)[0].GetUInt32()+1;
-
- result = WorldDatabase.Query("SELECT MAX(guid) FROM creature");
- if (result)
- _hiCreatureGuid = (*result)[0].GetUInt32()+1;
+ GetGuidSequenceGenerator<HighGuid::Player>().Set((*result)[0].GetUInt32()+1);
result = CharacterDatabase.Query("SELECT MAX(guid) FROM item_instance");
if (result)
- _hiItemGuid = (*result)[0].GetUInt32()+1;
+ GetGuidSequenceGenerator<HighGuid::Item>().Set((*result)[0].GetUInt32()+1);
// Cleanup other tables from nonexistent guids ( >= _hiItemGuid)
- CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item >= '%u'", _hiItemGuid); // One-time query
- CharacterDatabase.PExecute("DELETE FROM mail_items WHERE item_guid >= '%u'", _hiItemGuid); // One-time query
- CharacterDatabase.PExecute("DELETE FROM auctionhouse WHERE itemguid >= '%u'", _hiItemGuid); // One-time query
- CharacterDatabase.PExecute("DELETE FROM guild_bank_item WHERE item_guid >= '%u'", _hiItemGuid); // One-time query
-
- result = WorldDatabase.Query("SELECT MAX(guid) FROM gameobject");
- if (result)
- _hiGoGuid = (*result)[0].GetUInt32()+1;
+ CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item >= '%u'", GetGuidSequenceGenerator<HighGuid::Item>().GetNextAfterMaxUsed()); // One-time query
+ CharacterDatabase.PExecute("DELETE FROM mail_items WHERE item_guid >= '%u'", GetGuidSequenceGenerator<HighGuid::Item>().GetNextAfterMaxUsed()); // One-time query
+ CharacterDatabase.PExecute("DELETE FROM auctionhouse WHERE itemguid >= '%u'", GetGuidSequenceGenerator<HighGuid::Item>().GetNextAfterMaxUsed()); // One-time query
+ CharacterDatabase.PExecute("DELETE FROM guild_bank_item WHERE item_guid >= '%u'", GetGuidSequenceGenerator<HighGuid::Item>().GetNextAfterMaxUsed()); // One-time query
result = WorldDatabase.Query("SELECT MAX(guid) FROM transports");
if (result)
- _hiMoTransGuid = (*result)[0].GetUInt32()+1;
+ GetGuidSequenceGenerator<HighGuid::Mo_Transport>().Set((*result)[0].GetUInt32()+1);
result = CharacterDatabase.Query("SELECT MAX(id) FROM auctionhouse");
if (result)
@@ -6395,10 +6445,6 @@ void ObjectMgr::SetHighestGuids()
if (result)
_mailId = (*result)[0].GetUInt32()+1;
- result = CharacterDatabase.Query("SELECT MAX(corpseGuid) FROM corpse");
- if (result)
- _hiCorpseGuid = (*result)[0].GetUInt32()+1;
-
result = CharacterDatabase.Query("SELECT MAX(arenateamid) FROM arena_team");
if (result)
sArenaTeamMgr->SetNextArenaTeamId((*result)[0].GetUInt32()+1);
@@ -6414,6 +6460,14 @@ void ObjectMgr::SetHighestGuids()
result = CharacterDatabase.Query("SELECT MAX(guid) FROM groups");
if (result)
sGroupMgr->SetGroupDbStoreSize((*result)[0].GetUInt32()+1);
+
+ result = WorldDatabase.Query("SELECT MAX(guid) FROM creature");
+ if (result)
+ _creatureSpawnId = (*result)[0].GetUInt32() + 1;
+
+ result = WorldDatabase.Query("SELECT MAX(guid) FROM gameobject");
+ if (result)
+ _gameObjectSpawnId = (*result)[0].GetUInt32() + 1;
}
uint32 ObjectMgr::GenerateAuctionID()
@@ -6446,72 +6500,39 @@ uint32 ObjectMgr::GenerateMailID()
return _mailId++;
}
-uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh)
+uint32 ObjectMgr::GeneratePetNumber()
+{
+ return ++_hiPetNumber;
+}
+
+uint32 ObjectMgr::GenerateCreatureSpawnId()
{
- switch (guidhigh)
+ if (_creatureSpawnId >= uint32(0xFFFFFF))
{
- case HIGHGUID_ITEM:
- {
- ASSERT(_hiItemGuid < 0xFFFFFFFE && "Item guid overflow!");
- return _hiItemGuid++;
- }
- case HIGHGUID_UNIT:
- {
- ASSERT(_hiCreatureGuid < 0x00FFFFFE && "Creature guid overflow!");
- return _hiCreatureGuid++;
- }
- case HIGHGUID_PET:
- {
- ASSERT(_hiPetGuid < 0x00FFFFFE && "Pet guid overflow!");
- return _hiPetGuid++;
- }
- case HIGHGUID_VEHICLE:
- {
- ASSERT(_hiVehicleGuid < 0x00FFFFFF && "Vehicle guid overflow!");
- return _hiVehicleGuid++;
- }
- case HIGHGUID_PLAYER:
- {
- ASSERT(_hiCharGuid < 0xFFFFFFFE && "Player guid overflow!");
- return _hiCharGuid++;
- }
- case HIGHGUID_GAMEOBJECT:
- {
- ASSERT(_hiGoGuid < 0x00FFFFFE && "Gameobject guid overflow!");
- return _hiGoGuid++;
- }
- case HIGHGUID_CORPSE:
- {
- ASSERT(_hiCorpseGuid < 0xFFFFFFFE && "Corpse guid overflow!");
- return _hiCorpseGuid++;
- }
- case HIGHGUID_DYNAMICOBJECT:
- {
- ASSERT(_hiDoGuid < 0xFFFFFFFE && "DynamicObject guid overflow!");
- return _hiDoGuid++;
- }
- case HIGHGUID_MO_TRANSPORT:
- {
- ASSERT(_hiMoTransGuid < 0xFFFFFFFE && "MO Transport guid overflow!");
- return _hiMoTransGuid++;
- }
- default:
- ASSERT(false && "ObjectMgr::GenerateLowGuid - Unknown HIGHGUID type");
- return 0;
+ TC_LOG_ERROR("misc", "Creature spawn id overflow!! Can't continue, shutting down server. ");
+ World::StopNow(ERROR_EXIT_CODE);
+ }
+ return _creatureSpawnId++;
+}
+
+uint32 ObjectMgr::GenerateGameObjectSpawnId()
+{
+ if (_gameObjectSpawnId >= uint32(0xFFFFFF))
+ {
+ TC_LOG_ERROR("misc", "Creature spawn id overflow!! Can't continue, shutting down server. ");
+ World::StopNow(ERROR_EXIT_CODE);
}
+ return _gameObjectSpawnId++;
}
void ObjectMgr::LoadGameObjectLocales()
{
uint32 oldMSTime = getMSTime();
- _gameObjectLocaleStore.clear(); // need for reload case
-
- QueryResult result = WorldDatabase.Query("SELECT entry, "
- "name_loc1, name_loc2, name_loc3, name_loc4, name_loc5, name_loc6, name_loc7, name_loc8, "
- "castbarcaption_loc1, castbarcaption_loc2, castbarcaption_loc3, castbarcaption_loc4, "
- "castbarcaption_loc5, castbarcaption_loc6, castbarcaption_loc7, castbarcaption_loc8 FROM locales_gameobject");
+ _gameObjectLocaleStore.clear(); // need for reload case
+ // 0 1 2 3
+ QueryResult result = WorldDatabase.Query("SELECT entry, locale, name, castBarCaption FROM gameobject_template_locale");
if (!result)
return;
@@ -6519,18 +6540,23 @@ void ObjectMgr::LoadGameObjectLocales()
{
Field* fields = result->Fetch();
- uint32 entry = fields[0].GetUInt32();
+ uint32 id = fields[0].GetUInt32();
+ std::string localeName = fields[1].GetString();
- GameObjectLocale& data = _gameObjectLocaleStore[entry];
+ std::string name = fields[2].GetString();
+ std::string castBarCaption = fields[3].GetString();
+
+ GameObjectLocale& data = _gameObjectLocaleStore[id];
+ LocaleConstant locale = GetLocaleByName(localeName);
+ if (locale == LOCALE_enUS)
+ continue;
+
+ AddLocaleString(name, locale, data.Name);
+ AddLocaleString(castBarCaption, locale, data.CastBarCaption);
- for (uint8 i = TOTAL_LOCALES - 1; i > 0; --i)
- {
- AddLocaleString(fields[i].GetString(), LocaleConstant(i), data.Name);
- AddLocaleString(fields[i + (TOTAL_LOCALES - 1)].GetString(), LocaleConstant(i), data.CastBarCaption);
- }
} while (result->NextRow());
- TC_LOG_INFO("server.loading", ">> Loaded %u gameobject locale strings in %u ms", uint32(_gameObjectLocaleStore.size()), GetMSTimeDiffToNow(oldMSTime));
+ TC_LOG_INFO("server.loading", ">> Loaded %u gameobject_template_locale strings in %u ms", uint32(_gameObjectLocaleStore.size()), GetMSTimeDiffToNow(oldMSTime));
}
inline void CheckGOLockId(GameObjectTemplate const* goInfo, uint32 dataN, uint32 N)
@@ -6596,12 +6622,12 @@ void ObjectMgr::LoadGameObjectTemplate()
{
uint32 oldMSTime = getMSTime();
- // 0 1 2 3 4 5 6 7 8 9 10 11 12
- QueryResult result = WorldDatabase.Query("SELECT entry, type, displayId, name, IconName, castBarCaption, unk1, faction, flags, size, questItem1, questItem2, questItem3, "
- // 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
- "questItem4, questItem5, questItem6, data0, data1, data2, data3, data4, data5, data6, data7, data8, data9, data10, data11, data12, "
- // 29 30 31 32 33 34 35 36 37 38 39 40 41
- "data13, data14, data15, data16, data17, data18, data19, data20, data21, data22, data23, AIName, ScriptName "
+ // 0 1 2 3 4 5 6 7 8 9
+ QueryResult result = WorldDatabase.Query("SELECT entry, type, displayId, name, IconName, castBarCaption, unk1, faction, flags, size, "
+ // 10 11 12 13 14 15 16 17 18 19 20 21 22
+ "Data0, Data1, Data2, Data3, Data4, Data5, Data6, Data7, Data8, Data9, Data10, Data11, Data12, "
+ // 23 24 25 26 27 28 29 30 31 32 33 34 35
+ "Data13, Data14, Data15, Data16, Data17, Data18, Data19, Data20, Data21, Data22, Data23, AIName, ScriptName "
"FROM gameobject_template");
if (!result)
@@ -6631,14 +6657,11 @@ void ObjectMgr::LoadGameObjectTemplate()
got.flags = fields[8].GetUInt32();
got.size = fields[9].GetFloat();
- for (uint8 i = 0; i < MAX_GAMEOBJECT_QUEST_ITEMS; ++i)
- got.questItems[i] = fields[10 + i].GetUInt32();
-
for (uint8 i = 0; i < MAX_GAMEOBJECT_DATA; ++i)
- got.raw.data[i] = fields[16 + i].GetInt32(); // data1 and data6 can be -1
+ got.raw.data[i] = fields[10 + i].GetInt32(); // data1 and data6 can be -1
- got.AIName = fields[40].GetString();
- got.ScriptId = GetScriptId(fields[41].GetCString());
+ got.AIName = fields[34].GetString();
+ got.ScriptId = GetScriptId(fields[35].GetString());
// Checks
@@ -6885,49 +6908,6 @@ std::string ObjectMgr::GeneratePetName(uint32 entry)
return *(list0.begin()+urand(0, list0.size()-1)) + *(list1.begin()+urand(0, list1.size()-1));
}
-uint32 ObjectMgr::GeneratePetNumber()
-{
- return ++_hiPetNumber;
-}
-
-void ObjectMgr::LoadCorpses()
-{
- uint32 oldMSTime = getMSTime();
-
- PreparedQueryResult result = CharacterDatabase.Query(CharacterDatabase.GetPreparedStatement(CHAR_SEL_CORPSES));
- if (!result)
- {
- TC_LOG_INFO("server.loading", ">> Loaded 0 corpses. DB table `corpse` is empty.");
- return;
- }
-
- uint32 count = 0;
- do
- {
- Field* fields = result->Fetch();
- uint32 guid = fields[16].GetUInt32();
- CorpseType type = CorpseType(fields[13].GetUInt8());
- if (type >= MAX_CORPSE_TYPE)
- {
- TC_LOG_ERROR("misc", "Corpse (guid: %u) have wrong corpse type (%u), not loading.", guid, type);
- continue;
- }
-
- Corpse* corpse = new Corpse(type);
- if (!corpse->LoadCorpseFromDB(guid, fields))
- {
- delete corpse;
- continue;
- }
-
- sObjectAccessor->AddCorpse(corpse);
- ++count;
- }
- while (result->NextRow());
-
- TC_LOG_INFO("server.loading", ">> Loaded %u corpses in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
-}
-
void ObjectMgr::LoadReputationRewardRate()
{
uint32 oldMSTime = getMSTime();
@@ -7188,8 +7168,8 @@ void ObjectMgr::LoadPointsOfInterest()
uint32 count = 0;
- // 0 1 2 3 4 5 6
- QueryResult result = WorldDatabase.Query("SELECT entry, x, y, icon, flags, data, icon_name FROM points_of_interest");
+ // 0 1 2 3 4 5 6
+ QueryResult result = WorldDatabase.Query("SELECT ID, PositionX, PositionY, Icon, Flags, Data, Name FROM points_of_interest");
if (!result)
{
@@ -7234,8 +7214,8 @@ void ObjectMgr::LoadQuestPOI()
uint32 count = 0;
- // 0 1 2 3 4 5 6 7
- QueryResult result = WorldDatabase.Query("SELECT questId, id, objIndex, mapid, WorldMapAreaId, FloorId, unk3, unk4 FROM quest_poi order by questId");
+ // 0 1 2 3 4 5 6 7
+ QueryResult result = WorldDatabase.Query("SELECT QuestID, id, ObjectiveIndex, MapID, WorldMapAreaId, Floor, Priority, Flags FROM quest_poi order by QuestID");
if (!result)
{
@@ -7243,8 +7223,8 @@ void ObjectMgr::LoadQuestPOI()
return;
}
- // 0 1 2 3
- QueryResult points = WorldDatabase.Query("SELECT questId, id, x, y FROM quest_poi_points ORDER BY questId DESC, idx");
+ // 0 1 2 3
+ QueryResult points = WorldDatabase.Query("SELECT QuestID, Idx1, X, Y FROM quest_poi_points ORDER BY QuestID DESC, Idx2");
std::vector<std::vector<std::vector<QuestPOIPoint> > > POIs;
@@ -7366,7 +7346,7 @@ void ObjectMgr::LoadNPCSpellClickSpells()
TC_LOG_INFO("server.loading", ">> Loaded %u spellclick definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
-void ObjectMgr::DeleteCreatureData(uint32 guid)
+void ObjectMgr::DeleteCreatureData(ObjectGuid::LowType guid)
{
// remove mapid*cellid -> guid_set map
CreatureData const* data = GetCreatureData(guid);
@@ -7376,7 +7356,7 @@ void ObjectMgr::DeleteCreatureData(uint32 guid)
_creatureDataStore.erase(guid);
}
-void ObjectMgr::DeleteGOData(uint32 guid)
+void ObjectMgr::DeleteGOData(ObjectGuid::LowType guid)
{
// remove mapid*cellid -> guid_set map
GameObjectData const* data = GetGOData(guid);
@@ -7386,20 +7366,6 @@ void ObjectMgr::DeleteGOData(uint32 guid)
_gameObjectDataStore.erase(guid);
}
-void ObjectMgr::AddCorpseCellData(uint32 mapid, uint32 cellid, uint32 player_guid, uint32 instance)
-{
- // corpses are always added to spawn mode 0 and they are spawned by their instance id
- CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(mapid, 0)][cellid];
- cell_guids.corpses[player_guid] = instance;
-}
-
-void ObjectMgr::DeleteCorpseCellData(uint32 mapid, uint32 cellid, uint32 player_guid)
-{
- // corpses are always added to spawn mode 0 and they are spawned by their instance id
- CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(mapid, 0)][cellid];
- cell_guids.corpses.erase(player_guid);
-}
-
void ObjectMgr::LoadQuestRelationsHelper(QuestRelations& map, QuestRelationsReverse* reverseMap, std::string const& table, bool starter, bool go)
{
uint32 oldMSTime = getMSTime();
@@ -7626,7 +7592,7 @@ bool isValidString(const std::wstring& wstr, uint32 strictMask, bool numericOrSp
return false;
}
-ResponseCodes ObjectMgr::CheckPlayerName(const std::string& name, bool create)
+ResponseCodes ObjectMgr::CheckPlayerName(std::string const& name, LocaleConstant locale, bool create /*= false*/)
{
std::wstring wname;
if (!Utf8toWStr(name, wname))
@@ -7648,7 +7614,7 @@ ResponseCodes ObjectMgr::CheckPlayerName(const std::string& name, bool create)
if (wname[i] == wname[i-1] && wname[i] == wname[i-2])
return CHAR_NAME_THREE_CONSECUTIVE;
- return CHAR_NAME_SUCCESS;
+ return ValidateName(name, locale);
}
bool ObjectMgr::IsValidCharterName(const std::string& name)
@@ -7669,7 +7635,7 @@ bool ObjectMgr::IsValidCharterName(const std::string& name)
return isValidString(wname, strictMask, true);
}
-PetNameInvalidReason ObjectMgr::CheckPetName(const std::string& name)
+PetNameInvalidReason ObjectMgr::CheckPetName(const std::string& name, LocaleConstant locale)
{
std::wstring wname;
if (!Utf8toWStr(name, wname))
@@ -7686,6 +7652,17 @@ PetNameInvalidReason ObjectMgr::CheckPetName(const std::string& name)
if (!isValidString(wname, strictMask, false))
return PET_NAME_MIXED_LANGUAGES;
+ switch (ValidateName(name, locale))
+ {
+ case CHAR_NAME_PROFANE:
+ return PET_NAME_PROFANE;
+ case CHAR_NAME_RESERVED:
+ return PET_NAME_RESERVED;
+ case RESPONSE_FAILURE:
+ return PET_NAME_INVALID;
+ default:
+ break;
+ }
return PET_NAME_SUCCESS;
}
@@ -8217,9 +8194,9 @@ void ObjectMgr::LoadTrainerSpell()
// For reload case
_cacheTrainerSpellStore.clear();
- QueryResult result = WorldDatabase.Query("SELECT b.entry, a.spell, a.spellcost, a.reqskill, a.reqskillvalue, a.reqlevel FROM npc_trainer AS a "
- "INNER JOIN npc_trainer AS b ON a.entry = -(b.spell) "
- "UNION SELECT * FROM npc_trainer WHERE spell > 0");
+ QueryResult result = WorldDatabase.Query("SELECT b.ID, a.SpellID, a.MoneyCost, a.ReqSkillLine, a.ReqSkillRank, a.ReqLevel FROM npc_trainer AS a "
+ "INNER JOIN npc_trainer AS b ON a.ID = -(b.SpellID) "
+ "UNION SELECT * FROM npc_trainer WHERE SpellID > 0");
if (!result)
{
@@ -8618,7 +8595,7 @@ void ObjectMgr::LoadScriptNames()
do
{
- _scriptNamesStore.emplace_back((*result)[0].GetCString());
+ _scriptNamesStore.push_back((*result)[0].GetString());
}
while (result->NextRow());
@@ -8632,11 +8609,18 @@ void ObjectMgr::LoadScriptNames()
TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " ScriptNames in %u ms", _scriptNamesStore.size(), GetMSTimeDiffToNow(oldMSTime));
}
-uint32 ObjectMgr::GetScriptId(char const* name)
+std::string const& ObjectMgr::GetScriptName(uint32 id) const
+{
+ static std::string const empty = "";
+ return id < _scriptNamesStore.size() ? _scriptNamesStore[id] : empty;
+}
+
+
+uint32 ObjectMgr::GetScriptId(std::string const& name)
{
// use binary search to find the script name in the sorted vector
// assume "" is the first element
- if (!name)
+ if (name.empty())
return 0;
ScriptNameContainer::const_iterator itr = std::lower_bound(_scriptNamesStore.begin(), _scriptNamesStore.end(), name);
@@ -9099,7 +9083,7 @@ VehicleAccessoryList const* ObjectMgr::GetVehicleAccessoryList(Vehicle* veh) con
if (Creature* cre = veh->GetBase()->ToCreature())
{
// Give preference to GUID-based accessories
- VehicleAccessoryContainer::const_iterator itr = _vehicleAccessoryStore.find(cre->GetDBTableGUIDLow());
+ VehicleAccessoryContainer::const_iterator itr = _vehicleAccessoryStore.find(cre->GetSpawnId());
if (itr != _vehicleAccessoryStore.end())
return &itr->second;
}
@@ -9122,3 +9106,93 @@ PlayerInfo const* ObjectMgr::GetPlayerInfo(uint32 race, uint32 class_) const
return NULL;
return info;
}
+
+void ObjectMgr::LoadGameObjectQuestItems()
+{
+ uint32 oldMSTime = getMSTime();
+
+ // 0 1 2
+ QueryResult result = WorldDatabase.Query("SELECT GameObjectEntry, ItemId, Idx FROM gameobject_questitem ORDER BY Idx ASC");
+
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 gameobject quest items. DB table `gameobject_questitem` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+ do
+ {
+ Field* fields = result->Fetch();
+
+ uint32 entry = fields[0].GetUInt32();
+ uint32 item = fields[1].GetUInt32();
+ uint32 idx = fields[2].GetUInt32();
+
+ GameObjectTemplate const* goInfo = GetGameObjectTemplate(entry);
+ if (!goInfo)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `gameobject_questitem` has data for nonexistent gameobject (entry: %u, idx: %u), skipped", entry, idx);
+ continue;
+ };
+
+ ItemEntry const* db2Data = sItemStore.LookupEntry(item);
+ if (!db2Data)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `gameobject_questitem` has nonexistent item (ID: %u) in gameobject (entry: %u, idx: %u), skipped", item, entry, idx);
+ continue;
+ };
+
+ _gameObjectQuestItemStore[entry].push_back(item);
+
+ ++count;
+ }
+ while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u gameobject quest items in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
+void ObjectMgr::LoadCreatureQuestItems()
+{
+ uint32 oldMSTime = getMSTime();
+
+ // 0 1 2
+ QueryResult result = WorldDatabase.Query("SELECT CreatureEntry, ItemId, Idx FROM creature_questitem ORDER BY Idx ASC");
+
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 creature quest items. DB table `creature_questitem` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+ do
+ {
+ Field* fields = result->Fetch();
+
+ uint32 entry = fields[0].GetUInt32();
+ uint32 item = fields[1].GetUInt32();
+ uint32 idx = fields[2].GetUInt32();
+
+ CreatureTemplate const* creatureInfo = GetCreatureTemplate(entry);
+ if (!creatureInfo)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `creature_questitem` has data for nonexistent creature (entry: %u, idx: %u), skipped", entry, idx);
+ continue;
+ };
+
+ ItemEntry const* db2Data = sItemStore.LookupEntry(item);
+ if (!db2Data)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `creature_questitem` has nonexistent item (ID: %u) in creature (entry: %u, idx: %u), skipped", item, entry, idx);
+ continue;
+ };
+
+ _creatureQuestItemStore[entry].push_back(item);
+
+ ++count;
+ }
+ while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u creature quest items in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+}
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index f18e39077f3..396be440205 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -36,11 +36,14 @@
#include "ObjectAccessor.h"
#include "ObjectDefines.h"
#include "VehicleDefines.h"
+#include "ConditionMgr.h"
+#include "DBCStores.h"
#include <string>
+#include <tuple>
#include <map>
#include <limits>
-#include "ConditionMgr.h"
#include <functional>
+#include <memory>
class Item;
struct AccessRequirement;
@@ -67,8 +70,8 @@ struct TempSummonGroupKey
bool operator<(TempSummonGroupKey const& rhs) const
{
- // memcmp is only reliable if struct doesn't have any padding (packed)
- return memcmp(this, &rhs, sizeof(TempSummonGroupKey)) < 0;
+ return std::tie(_summonerEntry, _summonerType, _summonGroup) <
+ std::tie(rhs._summonerEntry, rhs._summonerType, rhs._summonGroup);
}
private:
@@ -255,7 +258,7 @@ struct ScriptInfo
struct // SCRIPT_COMMAND_RESPAWN_GAMEOBJECT (9)
{
- uint32 GOGuid; // datalong
+ ObjectGuid::LowType GOGuid; // datalong
uint32 DespawnDelay; // datalong2
} RespawnGameobject;
@@ -274,7 +277,7 @@ struct ScriptInfo
struct // SCRIPT_COMMAND_CLOSE_DOOR (12)
// SCRIPT_COMMAND_OPEN_DOOR (11)
{
- uint32 GOGuid; // datalong
+ ObjectGuid::LowType GOGuid; // datalong
uint32 ResetDelay; // datalong2
} ToggleDoor;
@@ -442,13 +445,11 @@ struct BroadcastText
typedef std::unordered_map<uint32, BroadcastText> BroadcastTextContainer;
-typedef std::set<uint32> CellGuidSet;
-typedef std::map<uint32/*player guid*/, uint32/*instance*/> CellCorpseSet;
+typedef std::set<ObjectGuid::LowType> CellGuidSet;
struct CellObjectGuids
{
CellGuidSet creatures;
CellGuidSet gameobjects;
- CellCorpseSet corpses;
};
typedef std::unordered_map<uint32/*cell_id*/, CellObjectGuids> CellObjectGuidsMap;
typedef std::unordered_map<uint32/*(mapid, spawnMode) pair*/, CellObjectGuidsMap> MapObjectGuids;
@@ -462,8 +463,8 @@ struct TrinityString
};
typedef std::map<ObjectGuid, ObjectGuid> LinkedRespawnContainer;
-typedef std::unordered_map<uint32, CreatureData> CreatureDataContainer;
-typedef std::unordered_map<uint32, GameObjectData> GameObjectDataContainer;
+typedef std::unordered_map<ObjectGuid::LowType, CreatureData> CreatureDataContainer;
+typedef std::unordered_map<ObjectGuid::LowType, GameObjectData> GameObjectDataContainer;
typedef std::map<TempSummonGroupKey, std::vector<TempSummonData> > TempSummonDataContainer;
typedef std::unordered_map<uint32, CreatureLocale> CreatureLocaleContainer;
typedef std::unordered_map<uint32, GameObjectLocale> GameObjectLocaleContainer;
@@ -563,14 +564,14 @@ struct GossipMenuItems
uint32 BoxMoney;
std::string BoxText;
uint32 BoxBroadcastTextId;
- ConditionList Conditions;
+ ConditionContainer Conditions;
};
struct GossipMenus
{
uint32 entry;
uint32 text_id;
- ConditionList conditions;
+ ConditionContainer conditions;
};
typedef std::multimap<uint32, GossipMenus> GossipMenusContainer;
@@ -705,7 +706,7 @@ class ObjectMgr
typedef std::map<uint32, uint32> CharacterConversionMap;
- Player* GetPlayerByLowGUID(uint32 lowguid) const;
+ Player* GetPlayerByLowGUID(ObjectGuid::LowType lowguid) const;
GameObjectTemplate const* GetGameObjectTemplate(uint32 entry);
GameObjectTemplateContainer const* GetGameObjectTemplates() const { return &_gameObjectTemplateStore; }
@@ -721,7 +722,7 @@ class ObjectMgr
static uint32 ChooseDisplayId(CreatureTemplate const* cinfo, CreatureData const* data = NULL);
static void ChooseCreatureFlags(CreatureTemplate const* cinfo, uint32& npcflag, uint32& unit_flags, uint32& dynamicflags, CreatureData const* data = NULL);
EquipmentInfo const* GetEquipmentInfo(uint32 entry, int8& id);
- CreatureAddon const* GetCreatureAddon(uint32 lowguid);
+ CreatureAddon const* GetCreatureAddon(ObjectGuid::LowType lowguid);
GameObjectAddon const* GetGameObjectAddon(ObjectGuid::LowType lowguid);
CreatureAddon const* GetCreatureTemplateAddon(uint32 entry);
ItemTemplate const* GetItemTemplate(uint32 entry);
@@ -753,13 +754,31 @@ class ObjectMgr
ObjectGuid GetPlayerGUIDByName(std::string const& name) const;
+ GameObjectQuestItemList const* GetGameObjectQuestItemList(uint32 id) const
+ {
+ GameObjectQuestItemMap::const_iterator itr = _gameObjectQuestItemStore.find(id);
+ if (itr != _gameObjectQuestItemStore.end())
+ return &itr->second;
+ return NULL;
+ }
+ GameObjectQuestItemMap const* GetGameObjectQuestItemMap() const { return &_gameObjectQuestItemStore; }
+
+ CreatureQuestItemList const* GetCreatureQuestItemList(uint32 id) const
+ {
+ CreatureQuestItemMap::const_iterator itr = _creatureQuestItemStore.find(id);
+ if (itr != _creatureQuestItemStore.end())
+ return &itr->second;
+ return NULL;
+ }
+ CreatureQuestItemMap const* GetCreatureQuestItemMap() const { return &_creatureQuestItemStore; }
+
/**
* Retrieves the player name by guid.
*
* If the player is online, the name is retrieved immediately otherwise
* a database query is done.
*
- * @remark Use sWorld->GetCharacterNameData because it doesn't require a database query when player is offline
+ * @remark Use sWorld->GetCharacterInfo because it doesn't require a database query when player is offline
*
* @param guid player full guid
* @param name returned name
@@ -960,10 +979,12 @@ class ObjectMgr
void LoadCreatureTemplateAddons();
void LoadCreatureTemplate(Field* fields);
void CheckCreatureTemplate(CreatureTemplate const* cInfo);
+ void LoadGameObjectQuestItems();
+ void LoadCreatureQuestItems();
void LoadTempSummons();
void LoadCreatures();
void LoadLinkedRespawn();
- bool SetCreatureLinkedRespawn(uint32 guid, uint32 linkedGuid);
+ bool SetCreatureLinkedRespawn(ObjectGuid::LowType guid, ObjectGuid::LowType linkedGuid);
void LoadCreatureAddons();
void LoadGameObjectAddons();
void LoadCreatureModelInfo();
@@ -1002,7 +1023,6 @@ class ObjectMgr
void LoadExplorationBaseXP();
void LoadPetNames();
void LoadPetNumber();
- void LoadCorpses();
void LoadFishingBaseSkillLevel();
void LoadReputationRewardRate();
@@ -1038,11 +1058,20 @@ class ObjectMgr
CreatureBaseStats const* GetCreatureBaseStats(uint8 level, uint8 unitClass);
void SetHighestGuids();
- uint32 GenerateLowGuid(HighGuid guidhigh);
+
+ template<HighGuid type>
+ inline ObjectGuidGeneratorBase& GetGenerator()
+ {
+ static_assert(ObjectGuidTraits<type>::Global, "Only global guid can be generated in ObjectMgr context");
+ return GetGuidSequenceGenerator<type>();
+ }
+
uint32 GenerateAuctionID();
uint64 GenerateEquipmentSetGuid();
uint32 GenerateMailID();
uint32 GeneratePetNumber();
+ uint32 GenerateCreatureSpawnId();
+ uint32 GenerateGameObjectSpawnId();
typedef std::multimap<int32, uint32> ExclusiveQuestGroups;
typedef std::pair<ExclusiveQuestGroups::const_iterator, ExclusiveQuestGroups::const_iterator> ExclusiveQuestGroupsBounds;
@@ -1098,14 +1127,14 @@ class ObjectMgr
return NULL;
}
- CreatureData const* GetCreatureData(uint32 guid) const
+ CreatureData const* GetCreatureData(ObjectGuid::LowType guid) const
{
CreatureDataContainer::const_iterator itr = _creatureDataStore.find(guid);
if (itr == _creatureDataStore.end()) return NULL;
return &itr->second;
}
- CreatureData& NewOrExistCreatureData(uint32 guid) { return _creatureDataStore[guid]; }
- void DeleteCreatureData(uint32 guid);
+ CreatureData& NewOrExistCreatureData(ObjectGuid::LowType guid) { return _creatureDataStore[guid]; }
+ void DeleteCreatureData(ObjectGuid::LowType guid);
ObjectGuid GetLinkedRespawnGuid(ObjectGuid guid) const
{
LinkedRespawnContainer::const_iterator itr = _linkedRespawnStore.find(guid);
@@ -1167,14 +1196,14 @@ class ObjectMgr
return &itr->second;
}
- GameObjectData const* GetGOData(uint32 guid) const
+ GameObjectData const* GetGOData(ObjectGuid::LowType guid) const
{
GameObjectDataContainer::const_iterator itr = _gameObjectDataStore.find(guid);
if (itr == _gameObjectDataStore.end()) return NULL;
return &itr->second;
}
- GameObjectData& NewGOData(uint32 guid) { return _gameObjectDataStore[guid]; }
- void DeleteGOData(uint32 guid);
+ GameObjectData& NewGOData(ObjectGuid::LowType guid) { return _gameObjectDataStore[guid]; }
+ void DeleteGOData(ObjectGuid::LowType guid);
TrinityString const* GetTrinityString(uint32 entry) const
{
@@ -1188,25 +1217,21 @@ class ObjectMgr
LocaleConstant GetDBCLocaleIndex() const { return DBCLocaleIndex; }
void SetDBCLocaleIndex(LocaleConstant locale) { DBCLocaleIndex = locale; }
- void AddCorpseCellData(uint32 mapid, uint32 cellid, uint32 player_guid, uint32 instance);
- void DeleteCorpseCellData(uint32 mapid, uint32 cellid, uint32 player_guid);
-
// grid objects
- void AddCreatureToGrid(uint32 guid, CreatureData const* data);
- void RemoveCreatureFromGrid(uint32 guid, CreatureData const* data);
- void AddGameobjectToGrid(uint32 guid, GameObjectData const* data);
- void RemoveGameobjectFromGrid(uint32 guid, GameObjectData const* data);
- uint32 AddGOData(uint32 entry, uint32 map, float x, float y, float z, float o, uint32 spawntimedelay = 0, float rotation0 = 0, float rotation1 = 0, float rotation2 = 0, float rotation3 = 0);
- uint32 AddCreData(uint32 entry, uint32 map, float x, float y, float z, float o, uint32 spawntimedelay = 0);
- bool MoveCreData(uint32 guid, uint32 map, const Position& pos);
+ void AddCreatureToGrid(ObjectGuid::LowType guid, CreatureData const* data);
+ void RemoveCreatureFromGrid(ObjectGuid::LowType guid, CreatureData const* data);
+ void AddGameobjectToGrid(ObjectGuid::LowType guid, GameObjectData const* data);
+ void RemoveGameobjectFromGrid(ObjectGuid::LowType guid, GameObjectData const* data);
+ ObjectGuid::LowType AddGOData(uint32 entry, uint32 map, float x, float y, float z, float o, uint32 spawntimedelay = 0, float rotation0 = 0, float rotation1 = 0, float rotation2 = 0, float rotation3 = 0);
+ ObjectGuid::LowType AddCreatureData(uint32 entry, uint32 map, float x, float y, float z, float o, uint32 spawntimedelay = 0);
// reserved names
void LoadReservedPlayersNames();
bool IsReservedName(std::string const& name) const;
// name with valid structure and symbols
- static ResponseCodes CheckPlayerName(std::string const& name, bool create = false);
- static PetNameInvalidReason CheckPetName(std::string const& name);
+ static ResponseCodes CheckPlayerName(std::string const& name, LocaleConstant locale, bool create = false);
+ static PetNameInvalidReason CheckPetName(std::string const& name, LocaleConstant locale);
static bool IsValidCharterName(std::string const& name);
static bool CheckDeclinedNames(const std::wstring& w_ownname, DeclinedName const& names);
@@ -1245,8 +1270,8 @@ class ObjectMgr
bool IsVendorItemValid(uint32 vendor_entry, uint32 item, int32 maxcount, uint32 ptime, uint32 ExtendedCost, Player* player = NULL, std::set<uint32>* skip_vendors = NULL, uint32 ORnpcflag = 0) const;
void LoadScriptNames();
- char const* GetScriptName(uint32 id) const { return id < _scriptNamesStore.size() ? _scriptNamesStore[id].c_str() : ""; }
- uint32 GetScriptId(char const* name);
+ std::string const& GetScriptName(uint32 id) const;
+ uint32 GetScriptId(std::string const& name);
SpellClickInfoMapBounds GetSpellClickInfoMapBounds(uint32 creature_id) const
{
@@ -1306,17 +1331,21 @@ class ObjectMgr
uint32 _mailId;
uint32 _hiPetNumber;
+ uint32 _creatureSpawnId;
+ uint32 _gameObjectSpawnId;
+
// first free low guid for selected guid type
- uint32 _hiCharGuid;
- uint32 _hiCreatureGuid;
- uint32 _hiPetGuid;
- uint32 _hiVehicleGuid;
- uint32 _hiItemGuid;
- uint32 _hiGoGuid;
- uint32 _hiDoGuid;
- uint32 _hiCorpseGuid;
- uint32 _hiMoTransGuid;
+ template<HighGuid high>
+ inline ObjectGuidGeneratorBase& GetGuidSequenceGenerator()
+ {
+ auto itr = _guidGenerators.find(high);
+ if (itr == _guidGenerators.end())
+ itr = _guidGenerators.insert(std::make_pair(high, std::unique_ptr<ObjectGuidGenerator<high>>(new ObjectGuidGenerator<high>()))).first;
+
+ return *itr->second;
+ }
+ std::map<HighGuid, std::unique_ptr<ObjectGuidGeneratorBase>> _guidGenerators;
QuestMap _questTemplates;
typedef std::unordered_map<uint32, GossipText> GossipTextContainer;
@@ -1410,8 +1439,10 @@ class ObjectMgr
CreatureTemplateContainer _creatureTemplateStore;
CreatureModelContainer _creatureModelStore;
CreatureAddonContainer _creatureAddonStore;
- CreatureAddonContainer _creatureTemplateAddonStore;
+ CreatureAddonTemplateContainer _creatureTemplateAddonStore;
GameObjectAddonContainer _gameObjectAddonStore;
+ GameObjectQuestItemMap _gameObjectQuestItemStore;
+ CreatureQuestItemMap _creatureQuestItemStore;
EquipmentInfoContainer _equipmentInfoStore;
LinkedRespawnContainer _linkedRespawnStore;
CreatureLocaleContainer _creatureLocaleStore;
diff --git a/src/server/game/Grids/GridDefines.h b/src/server/game/Grids/GridDefines.h
index 28670ad4968..8eae906ba87 100644
--- a/src/server/game/Grids/GridDefines.h
+++ b/src/server/game/Grids/GridDefines.h
@@ -20,6 +20,7 @@
#define TRINITY_GRIDDEFINES_H
#include "Common.h"
+#include "ObjectGuid.h"
#include "NGrid.h"
#include <cmath>
@@ -58,6 +59,7 @@ class Player;
// Creature used instead pet to simplify *::Visit templates (not required duplicate code for Creature->Pet case)
typedef TYPELIST_4(Player, Creature/*pets*/, Corpse/*resurrectable*/, DynamicObject/*farsight target*/) AllWorldObjectTypes;
typedef TYPELIST_4(GameObject, Creature/*except pets*/, DynamicObject, Corpse/*Bones*/) AllGridObjectTypes;
+typedef TYPELIST_5(Creature, GameObject, DynamicObject, Pet, Corpse) AllMapStoredObjectTypes;
typedef GridRefManager<Corpse> CorpseMapType;
typedef GridRefManager<Creature> CreatureMapType;
@@ -80,6 +82,7 @@ typedef NGrid<MAX_NUMBER_OF_CELLS, Player, AllWorldObjectTypes, AllGridObjectTyp
typedef TypeMapContainer<AllGridObjectTypes> GridTypeMapContainer;
typedef TypeMapContainer<AllWorldObjectTypes> WorldTypeMapContainer;
+typedef TypeUnorderedMapContainer<AllMapStoredObjectTypes, ObjectGuid> MapStoredObjectTypesContainer;
template<uint32 LIMIT>
struct CoordPair
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.cpp b/src/server/game/Grids/Notifiers/GridNotifiers.cpp
index d52e559c408..15f3c7811cd 100644
--- a/src/server/game/Grids/Notifiers/GridNotifiers.cpp
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.cpp
@@ -132,8 +132,13 @@ inline void CreatureUnitRelocationWorker(Creature* c, Unit* u)
return;
if (c->HasReactState(REACT_AGGRESSIVE) && !c->HasUnitState(UNIT_STATE_SIGHTLESS))
+ {
if (c->IsAIEnabled && c->CanSeeOrDetect(u, false, true))
c->AI()->MoveInLineOfSight_Safe(u);
+ else
+ if (u->GetTypeId() == TYPEID_PLAYER && u->HasStealthAura() && c->IsAIEnabled && c->CanSeeOrDetect(u, false, true, true))
+ c->AI()->TriggerAlert(u);
+ }
}
void PlayerRelocationNotifier::Visit(PlayerMapType &m)
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h
index ccf9748e67a..c2f5f75f98e 100644
--- a/src/server/game/Grids/Notifiers/GridNotifiers.h
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.h
@@ -722,18 +722,6 @@ namespace Trinity
NearestGameObjectTypeInObjectRangeCheck(NearestGameObjectTypeInObjectRangeCheck const&);
};
- class GameObjectWithDbGUIDCheck
- {
- public:
- GameObjectWithDbGUIDCheck(WorldObject const& /*obj*/, uint32 db_guid) : i_db_guid(db_guid) { }
- bool operator()(GameObject const* go) const
- {
- return go->GetDBTableGUIDLow() == i_db_guid;
- }
- private:
- uint32 i_db_guid;
- };
-
// Unit checks
class MostHPMissingInRange
@@ -835,18 +823,6 @@ namespace Trinity
float i_range;
};
- class CreatureWithDbGUIDCheck
- {
- public:
- CreatureWithDbGUIDCheck(WorldObject const* /*obj*/, uint32 lowguid) : i_lowguid(lowguid) { }
- bool operator()(Creature* u)
- {
- return u->GetDBTableGUIDLow() == i_lowguid;
- }
- private:
- uint32 i_lowguid;
- };
-
class AnyFriendlyUnitInObjectRangeCheck
{
public:
@@ -950,7 +926,7 @@ namespace Trinity
bool operator()(Unit* u)
{
// Check contains checks for: live, non-selectable, non-attackable flags, flight check and GM check, ignore totems
- if (u->GetTypeId() == TYPEID_UNIT && u->ToCreature()->IsTotem())
+ if (u->GetTypeId() == TYPEID_UNIT && u->IsTotem())
return false;
if (i_funit->_IsValidAttackTarget(u, _spellInfo, i_obj->GetTypeId() == TYPEID_DYNAMICOBJECT ? i_obj : NULL) && i_obj->IsWithinDistInMap(u, i_range))
diff --git a/src/server/game/Grids/ObjectGridLoader.cpp b/src/server/game/Grids/ObjectGridLoader.cpp
index c7e1056a3ef..2c292c43785 100644
--- a/src/server/game/Grids/ObjectGridLoader.cpp
+++ b/src/server/game/Grids/ObjectGridLoader.cpp
@@ -62,7 +62,7 @@ class ObjectWorldLoader
{
public:
explicit ObjectWorldLoader(ObjectGridLoader& gloader)
- : i_cell(gloader.i_cell), i_map(gloader.i_map), i_corpses (0)
+ : i_cell(gloader.i_cell), i_map(gloader.i_map), i_grid(gloader.i_grid), i_corpses(gloader.i_corpses)
{ }
void Visit(CorpseMapType &m);
@@ -72,8 +72,9 @@ class ObjectWorldLoader
private:
Cell i_cell;
Map* i_map;
+ NGridType& i_grid;
public:
- uint32 i_corpses;
+ uint32& i_corpses;
};
template<class T> void ObjectGridLoader::SetObjectCell(T* /*obj*/, CellCoord const& /*cellCoord*/) { }
@@ -117,7 +118,7 @@ void LoadHelper(CellGuidSet const& guid_set, CellCoord &cell, GridRefManager<T>
for (CellGuidSet::const_iterator i_guid = guid_set.begin(); i_guid != guid_set.end(); ++i_guid)
{
T* obj = new T;
- uint32 guid = *i_guid;
+ ObjectGuid::LowType guid = *i_guid;
//TC_LOG_INFO("misc", "DEBUG: LoadHelper from table: %s for (guid: %u) Loading", table, guid);
if (!obj->LoadFromDB(guid, map))
{
@@ -129,38 +130,6 @@ void LoadHelper(CellGuidSet const& guid_set, CellCoord &cell, GridRefManager<T>
}
}
-void LoadHelper(CellCorpseSet const& cell_corpses, CellCoord &cell, CorpseMapType &m, uint32 &count, Map* map)
-{
- if (cell_corpses.empty())
- return;
-
- for (CellCorpseSet::const_iterator itr = cell_corpses.begin(); itr != cell_corpses.end(); ++itr)
- {
- if (itr->second != map->GetInstanceId())
- continue;
-
- ObjectGuid player_guid(HIGHGUID_PLAYER, itr->first);
-
- Corpse* obj = sObjectAccessor->GetCorpseForPlayerGUID(player_guid);
- if (!obj)
- continue;
-
- /// @todo this is a hack
- // corpse's map should be reset when the map is unloaded
- // but it may still exist when the grid is unloaded but map is not
- // in that case map == currMap
- obj->SetMap(map);
-
- if (obj->IsInGrid())
- {
- obj->AddToWorld();
- continue;
- }
-
- AddObjectHelper(cell, m, count, map, obj);
- }
-}
-
void ObjectGridLoader::Visit(GameObjectMapType &m)
{
CellCoord cellCoord = i_cell.GetCellCoord();
@@ -175,22 +144,33 @@ void ObjectGridLoader::Visit(CreatureMapType &m)
LoadHelper(cell_guids.creatures, cellCoord, m, i_creatures, i_map);
}
-void ObjectWorldLoader::Visit(CorpseMapType &m)
+void ObjectWorldLoader::Visit(CorpseMapType& /*m*/)
{
CellCoord cellCoord = i_cell.GetCellCoord();
- // corpses are always added to spawn mode 0 and they are spawned by their instance id
- CellObjectGuids const& cell_guids = sObjectMgr->GetCellObjectGuids(i_map->GetId(), 0, cellCoord.GetId());
- LoadHelper(cell_guids.corpses, cellCoord, m, i_corpses, i_map);
+ if (std::unordered_set<Corpse*> const* corpses = i_map->GetCorpsesInCell(cellCoord.GetId()))
+ {
+ for (Corpse* corpse : *corpses)
+ {
+ corpse->AddToWorld();
+ GridType& cell = i_grid.GetGridType(i_cell.CellX(), i_cell.CellY());
+ if (corpse->IsWorldObject())
+ cell.AddWorldObject(corpse);
+ else
+ cell.AddGridObject(corpse);
+
+ ++i_corpses;
+ }
+ }
}
void ObjectGridLoader::LoadN(void)
{
i_gameObjects = 0; i_creatures = 0; i_corpses = 0;
i_cell.data.Part.cell_y = 0;
- for (unsigned int x=0; x < MAX_NUMBER_OF_CELLS; ++x)
+ for (uint32 x = 0; x < MAX_NUMBER_OF_CELLS; ++x)
{
i_cell.data.Part.cell_x = x;
- for (unsigned int y=0; y < MAX_NUMBER_OF_CELLS; ++y)
+ for (uint32 y = 0; y < MAX_NUMBER_OF_CELLS; ++y)
{
i_cell.data.Part.cell_y = y;
@@ -205,7 +185,6 @@ void ObjectGridLoader::LoadN(void)
ObjectWorldLoader worker(*this);
TypeContainerVisitor<ObjectWorldLoader, WorldTypeMapContainer> visitor(worker);
i_grid.VisitGrid(x, y, visitor);
- i_corpses += worker.i_corpses;
}
}
}
@@ -256,7 +235,7 @@ void ObjectGridCleaner::Visit(GridRefManager<T> &m)
template void ObjectGridUnloader::Visit(CreatureMapType &);
template void ObjectGridUnloader::Visit(GameObjectMapType &);
template void ObjectGridUnloader::Visit(DynamicObjectMapType &);
-template void ObjectGridUnloader::Visit(CorpseMapType &);
+
template void ObjectGridCleaner::Visit(CreatureMapType &);
template void ObjectGridCleaner::Visit<GameObject>(GameObjectMapType &);
template void ObjectGridCleaner::Visit<DynamicObject>(DynamicObjectMapType &);
diff --git a/src/server/game/Grids/ObjectGridLoader.h b/src/server/game/Grids/ObjectGridLoader.h
index 54dadaefdb3..126ebd0d0a3 100644
--- a/src/server/game/Grids/ObjectGridLoader.h
+++ b/src/server/game/Grids/ObjectGridLoader.h
@@ -82,6 +82,7 @@ class ObjectGridCleaner
class ObjectGridUnloader
{
public:
+ void Visit(CorpseMapType& /*m*/) { } // corpses are deleted with Map
template<class T> void Visit(GridRefManager<T> &m);
};
#endif
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index 2e81bdd1af8..4f8accee69c 100644
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -91,9 +91,9 @@ Group::~Group()
bool Group::Create(Player* leader)
{
ObjectGuid leaderGuid = leader->GetGUID();
- uint32 lowguid = sGroupMgr->GenerateGroupId();
+ ObjectGuid::LowType lowguid = sGroupMgr->GenerateGroupId();
- m_guid = ObjectGuid(HIGHGUID_GROUP, lowguid);
+ m_guid = ObjectGuid(HighGuid::Group, lowguid);
m_leaderGuid = leaderGuid;
m_leaderName = leader->GetName();
leader->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GROUP_LEADER);
@@ -162,15 +162,15 @@ bool Group::Create(Player* leader)
void Group::LoadGroupFromDB(Field* fields)
{
m_dbStoreId = fields[16].GetUInt32();
- m_guid = ObjectGuid(HIGHGUID_GROUP, sGroupMgr->GenerateGroupId());
- m_leaderGuid = ObjectGuid(HIGHGUID_PLAYER, fields[0].GetUInt32());
+ m_guid = ObjectGuid(HighGuid::Group, sGroupMgr->GenerateGroupId());
+ m_leaderGuid = ObjectGuid(HighGuid::Player, fields[0].GetUInt32());
// group leader not exist
if (!sObjectMgr->GetPlayerNameByGUID(m_leaderGuid, m_leaderName))
return;
m_lootMethod = LootMethod(fields[1].GetUInt8());
- m_looterGuid = ObjectGuid(HIGHGUID_PLAYER, fields[2].GetUInt32());
+ m_looterGuid = ObjectGuid(HighGuid::Player, fields[2].GetUInt32());
m_lootThreshold = ItemQualities(fields[3].GetUInt8());
for (uint8 i = 0; i < TARGETICONCOUNT; ++i)
@@ -192,16 +192,16 @@ void Group::LoadGroupFromDB(Field* fields)
else
m_raidDifficulty = Difficulty(r_diff);
- m_masterLooterGuid = ObjectGuid(HIGHGUID_PLAYER, fields[15].GetUInt32());
+ m_masterLooterGuid = ObjectGuid(HighGuid::Player, fields[15].GetUInt32());
if (m_groupType & GROUPTYPE_LFG)
sLFGMgr->_LoadFromDB(fields, GetGUID());
}
-void Group::LoadMemberFromDB(uint32 guidLow, uint8 memberFlags, uint8 subgroup, uint8 roles)
+void Group::LoadMemberFromDB(ObjectGuid::LowType guidLow, uint8 memberFlags, uint8 subgroup, uint8 roles)
{
MemberSlot member;
- member.guid = ObjectGuid(HIGHGUID_PLAYER, guidLow);
+ member.guid = ObjectGuid(HighGuid::Player, guidLow);
// skip non-existed member
if (!sObjectMgr->GetPlayerNameByGUID(member.guid, member.name))
@@ -443,24 +443,24 @@ bool Group::AddMember(Player* player)
if (itr->GetSource() == player)
continue;
- if (Player* member = itr->GetSource())
+ if (Player* existingMember = itr->GetSource())
{
- if (player->HaveAtClient(member))
+ if (player->HaveAtClient(existingMember))
{
- member->SetFieldNotifyFlag(UF_FLAG_PARTY_MEMBER);
- member->BuildValuesUpdateBlockForPlayer(&groupData, player);
- member->RemoveFieldNotifyFlag(UF_FLAG_PARTY_MEMBER);
+ existingMember->SetFieldNotifyFlag(UF_FLAG_PARTY_MEMBER);
+ existingMember->BuildValuesUpdateBlockForPlayer(&groupData, player);
+ existingMember->RemoveFieldNotifyFlag(UF_FLAG_PARTY_MEMBER);
}
- if (member->HaveAtClient(player))
+ if (existingMember->HaveAtClient(player))
{
UpdateData newData;
WorldPacket newDataPacket;
- player->BuildValuesUpdateBlockForPlayer(&newData, member);
+ player->BuildValuesUpdateBlockForPlayer(&newData, existingMember);
if (newData.HasData())
{
newData.BuildPacket(&newDataPacket);
- member->SendDirectMessage(&newDataPacket);
+ existingMember->SendDirectMessage(&newDataPacket);
}
}
}
@@ -539,7 +539,7 @@ bool Group::RemoveMember(ObjectGuid guid, const RemoveMethod& method /*= GROUP_R
}
// Reevaluate group enchanter if the leaving player had enchanting skill or the player is offline
- if ((player && player->GetSkillValue(SKILL_ENCHANTING)) || !player)
+ if (!player || player->GetSkillValue(SKILL_ENCHANTING))
ResetMaxEnchantingLevel();
// Remove player from loot rolls
@@ -659,7 +659,7 @@ void Group::ChangeLeader(ObjectGuid newLeaderGuid)
// Update the group leader
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GROUP_LEADER);
- stmt->setUInt32(0, newLeader->GetGUIDLow());
+ stmt->setUInt32(0, newLeader->GetGUID().GetCounter());
stmt->setUInt32(1, m_dbStoreId);
trans->Append(stmt);
@@ -925,7 +925,8 @@ void Group::GroupLoot(Loot* loot, WorldObject* pLootedObject)
//roll for over-threshold item if it's one-player loot
if (item->Quality >= uint32(m_lootThreshold))
{
- ObjectGuid newitemGUID = ObjectGuid(HIGHGUID_ITEM, sObjectMgr->GenerateLowGuid(HIGHGUID_ITEM));
+ ObjectGuid newitemGUID = ObjectGuid::Create<HighGuid::Item>(sObjectMgr->GetGenerator<HighGuid::Item>().Generate());
+
Roll* r = new Roll(newitemGUID, *i);
//a vector is filled with only near party members
@@ -936,7 +937,7 @@ void Group::GroupLoot(Loot* loot, WorldObject* pLootedObject)
continue;
if (i->AllowedForPlayer(member))
{
- if (member->IsWithinDistInMap(pLootedObject, sWorld->getFloatConfig(CONFIG_GROUP_XP_DISTANCE), false))
+ if (member->IsAtGroupRewardDistance(pLootedObject))
{
r->totalPlayersRolling++;
@@ -1009,7 +1010,8 @@ void Group::GroupLoot(Loot* loot, WorldObject* pLootedObject)
continue;
}
- ObjectGuid newitemGUID = ObjectGuid(HIGHGUID_ITEM, sObjectMgr->GenerateLowGuid(HIGHGUID_ITEM));
+ ObjectGuid newitemGUID = ObjectGuid::Create<HighGuid::Item>(sObjectMgr->GetGenerator<HighGuid::Item>().Generate());
+
Roll* r = new Roll(newitemGUID, *i);
//a vector is filled with only near party members
@@ -1021,7 +1023,7 @@ void Group::GroupLoot(Loot* loot, WorldObject* pLootedObject)
if (i->AllowedForPlayer(member))
{
- if (member->IsWithinDistInMap(pLootedObject, sWorld->getFloatConfig(CONFIG_GROUP_XP_DISTANCE), false))
+ if (member->IsAtGroupRewardDistance(pLootedObject))
{
r->totalPlayersRolling++;
r->playerVote[member->GetGUID()] = NOT_EMITED_YET;
@@ -1070,7 +1072,8 @@ void Group::NeedBeforeGreed(Loot* loot, WorldObject* lootedObject)
//roll for over-threshold item if it's one-player loot
if (item->Quality >= uint32(m_lootThreshold))
{
- ObjectGuid newitemGUID = ObjectGuid(HIGHGUID_ITEM, sObjectMgr->GenerateLowGuid(HIGHGUID_ITEM));
+ ObjectGuid newitemGUID = ObjectGuid::Create<HighGuid::Item>(sObjectMgr->GetGenerator<HighGuid::Item>().Generate());
+
Roll* r = new Roll(newitemGUID, *i);
for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
@@ -1080,7 +1083,7 @@ void Group::NeedBeforeGreed(Loot* loot, WorldObject* lootedObject)
continue;
bool allowedForPlayer = i->AllowedForPlayer(playerToRoll);
- if (allowedForPlayer && playerToRoll->IsWithinDistInMap(lootedObject, sWorld->getFloatConfig(CONFIG_GROUP_XP_DISTANCE), false))
+ if (allowedForPlayer && playerToRoll->IsAtGroupRewardDistance(lootedObject))
{
r->totalPlayersRolling++;
if (playerToRoll->GetPassOnGroupLoot())
@@ -1145,7 +1148,8 @@ void Group::NeedBeforeGreed(Loot* loot, WorldObject* lootedObject)
continue;
item = sObjectMgr->GetItemTemplate(i->itemid);
- ObjectGuid newitemGUID = ObjectGuid(HIGHGUID_ITEM, sObjectMgr->GenerateLowGuid(HIGHGUID_ITEM));
+ ObjectGuid newitemGUID = ObjectGuid::Create<HighGuid::Item>(sObjectMgr->GetGenerator<HighGuid::Item>().Generate());
+
Roll* r = new Roll(newitemGUID, *i);
for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
@@ -1155,7 +1159,7 @@ void Group::NeedBeforeGreed(Loot* loot, WorldObject* lootedObject)
continue;
bool allowedForPlayer = i->AllowedForPlayer(playerToRoll);
- if (allowedForPlayer && playerToRoll->IsWithinDistInMap(lootedObject, sWorld->getFloatConfig(CONFIG_GROUP_XP_DISTANCE), false))
+ if (allowedForPlayer && playerToRoll->IsAtGroupRewardDistance(lootedObject))
{
r->totalPlayersRolling++;
r->playerVote[playerToRoll->GetGUID()] = NOT_EMITED_YET;
@@ -1231,7 +1235,7 @@ void Group::MasterLoot(Loot* loot, WorldObject* pLootedObject)
if (!looter->IsInWorld())
continue;
- if (looter->IsWithinDistInMap(pLootedObject, sWorld->getFloatConfig(CONFIG_GROUP_XP_DISTANCE), false))
+ if (looter->IsAtGroupRewardDistance(pLootedObject))
{
data << uint64(looter->GetGUID());
++real_count;
@@ -1243,7 +1247,7 @@ void Group::MasterLoot(Loot* loot, WorldObject* pLootedObject)
for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
{
Player* looter = itr->GetSource();
- if (looter->IsWithinDistInMap(pLootedObject, sWorld->getFloatConfig(CONFIG_GROUP_XP_DISTANCE), false))
+ if (looter->IsAtGroupRewardDistance(pLootedObject))
looter->GetSession()->SendPacket(&data);
}
}
@@ -1743,7 +1747,7 @@ void Group::UpdateLooterGuid(WorldObject* pLootedObject, bool ifneed)
{
// not update if only update if need and ok
Player* looter = ObjectAccessor::FindPlayer(guid_itr->guid);
- if (looter && looter->IsWithinDistInMap(pLootedObject, sWorld->getFloatConfig(CONFIG_GROUP_XP_DISTANCE), false))
+ if (looter && looter->IsAtGroupRewardDistance(pLootedObject))
return;
}
++guid_itr;
@@ -1754,7 +1758,7 @@ void Group::UpdateLooterGuid(WorldObject* pLootedObject, bool ifneed)
for (member_citerator itr = guid_itr; itr != m_memberSlots.end(); ++itr)
{
if (Player* player = ObjectAccessor::FindPlayer(itr->guid))
- if (player->IsWithinDistInMap(pLootedObject, sWorld->getFloatConfig(CONFIG_GROUP_XP_DISTANCE), false))
+ if (player->IsAtGroupRewardDistance(pLootedObject))
{
pNewLooter = player;
break;
@@ -1767,7 +1771,7 @@ void Group::UpdateLooterGuid(WorldObject* pLootedObject, bool ifneed)
for (member_citerator itr = m_memberSlots.begin(); itr != guid_itr; ++itr)
{
if (Player* player = ObjectAccessor::FindPlayer(itr->guid))
- if (player->IsWithinDistInMap(pLootedObject, sWorld->getFloatConfig(CONFIG_GROUP_XP_DISTANCE), false))
+ if (player->IsAtGroupRewardDistance(pLootedObject))
{
pNewLooter = player;
break;
@@ -1989,8 +1993,8 @@ void Group::ResetInstances(uint8 method, bool isRaid, Player* SendMsgTo)
{
if (Group* group = SendMsgTo->GetGroup())
{
- for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
- if (Player* player = itr->GetSource())
+ for (GroupReference* groupRef = group->GetFirstMember(); groupRef != NULL; groupRef = groupRef->next())
+ if (Player* player = groupRef->GetSource())
player->SendResetInstanceSuccess(instanceSave->GetMapId());
}
@@ -2220,7 +2224,7 @@ ObjectGuid Group::GetGUID() const
return m_guid;
}
-uint32 Group::GetLowGUID() const
+ObjectGuid::LowType Group::GetLowGUID() const
{
return m_guid.GetCounter();
}
diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h
index 732afce9517..b814ab08026 100644
--- a/src/server/game/Groups/Group.h
+++ b/src/server/game/Groups/Group.h
@@ -186,7 +186,7 @@ class Group
// group manipulation methods
bool Create(Player* leader);
void LoadGroupFromDB(Field* field);
- void LoadMemberFromDB(uint32 guidLow, uint8 memberFlags, uint8 subgroup, uint8 roles);
+ void LoadMemberFromDB(ObjectGuid::LowType guidLow, uint8 memberFlags, uint8 subgroup, uint8 roles);
bool AddInvite(Player* player);
void RemoveInvite(Player* player);
void RemoveAllInvites();
@@ -211,7 +211,7 @@ class Group
bool IsCreated() const;
ObjectGuid GetLeaderGUID() const;
ObjectGuid GetGUID() const;
- uint32 GetLowGUID() const;
+ ObjectGuid::LowType GetLowGUID() const;
const char * GetLeaderName() const;
LootMethod GetLootMethod() const;
ObjectGuid GetLooterGuid() const;
diff --git a/src/server/game/Groups/GroupMgr.cpp b/src/server/game/Groups/GroupMgr.cpp
index 771fcb17b32..b8c8157b6d9 100644
--- a/src/server/game/Groups/GroupMgr.cpp
+++ b/src/server/game/Groups/GroupMgr.cpp
@@ -82,7 +82,7 @@ Group* GroupMgr::GetGroupByDbStoreId(uint32 storageId) const
return NULL;
}
-uint32 GroupMgr::GenerateGroupId()
+ObjectGuid::LowType GroupMgr::GenerateGroupId()
{
if (NextGroupId >= 0xFFFFFFFE)
{
@@ -92,7 +92,7 @@ uint32 GroupMgr::GenerateGroupId()
return NextGroupId++;
}
-Group* GroupMgr::GetGroupByGUID(uint32 groupId) const
+Group* GroupMgr::GetGroupByGUID(ObjectGuid::LowType groupId) const
{
GroupContainer::const_iterator itr = GroupStore.find(groupId);
if (itr != GroupStore.end())
@@ -124,7 +124,7 @@ void GroupMgr::LoadGroups()
// 0 1 2 3 4 5 6 7 8 9
QueryResult result = CharacterDatabase.Query("SELECT g.leaderGuid, g.lootMethod, g.looterGuid, g.lootThreshold, g.icon1, g.icon2, g.icon3, g.icon4, g.icon5, g.icon6"
// 10 11 12 13 14 15 16 17 18
- ", g.icon7, g.icon8, g.groupType, g.difficulty, g.raiddifficulty, g.masterLooterGuid, g.guid, lfg.dungeon, lfg.state FROM groups g LEFT JOIN lfg_data lfg ON lfg.guid = g.guid ORDER BY g.guid ASC");
+ ", g.icon7, g.icon8, g.groupType, g.difficulty, g.raidDifficulty, g.masterLooterGuid, g.guid, lfg.dungeon, lfg.state FROM groups g LEFT JOIN lfg_data lfg ON lfg.guid = g.guid ORDER BY g.guid ASC");
if (!result)
{
TC_LOG_INFO("server.loading", ">> Loaded 0 group definitions. DB table `groups` is empty!");
diff --git a/src/server/game/Groups/GroupMgr.h b/src/server/game/Groups/GroupMgr.h
index 737c1771c14..ec02de16bc2 100644
--- a/src/server/game/Groups/GroupMgr.h
+++ b/src/server/game/Groups/GroupMgr.h
@@ -33,10 +33,10 @@ public:
return &instance;
}
- typedef std::map<uint32, Group*> GroupContainer;
+ typedef std::map<ObjectGuid::LowType, Group*> GroupContainer;
typedef std::vector<Group*> GroupDbContainer;
- Group* GetGroupByGUID(uint32 guid) const;
+ Group* GetGroupByGUID(ObjectGuid::LowType guid) const;
uint32 GenerateNewGroupDbStoreId();
void RegisterGroupDbStoreId(uint32 storageId, Group* group);
@@ -46,13 +46,13 @@ public:
void SetGroupDbStoreSize(uint32 newSize) { GroupDbStore.resize(newSize); }
void LoadGroups();
- uint32 GenerateGroupId();
+ ObjectGuid::LowType GenerateGroupId();
void AddGroup(Group* group);
void RemoveGroup(Group* group);
protected:
- uint32 NextGroupId;
+ ObjectGuid::LowType NextGroupId;
uint32 NextGroupDbStoreId;
GroupContainer GroupStore;
GroupDbContainer GroupDbStore;
diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp
index 04eb99b3097..d2fcad512bb 100644
--- a/src/server/game/Guilds/Guild.cpp
+++ b/src/server/game/Guilds/Guild.cpp
@@ -194,10 +194,10 @@ void Guild::EventLogEntry::WritePacket(WorldPacket& data) const
// Event type
data << uint8(m_eventType);
// Player 1
- data << ObjectGuid(HIGHGUID_PLAYER, m_playerGuid1);
+ data << ObjectGuid(HighGuid::Player, m_playerGuid1);
// Player 2 not for left/join guild events
if (m_eventType != GUILD_EVENT_LOG_JOIN_GUILD && m_eventType != GUILD_EVENT_LOG_LEAVE_GUILD)
- data << ObjectGuid(HIGHGUID_PLAYER, m_playerGuid2);
+ data << ObjectGuid(HighGuid::Player, m_playerGuid2);
// New Rank - only for promote/demote guild events
if (m_eventType == GUILD_EVENT_LOG_PROMOTE_PLAYER || m_eventType == GUILD_EVENT_LOG_DEMOTE_PLAYER)
data << uint8(m_newRank);
@@ -233,7 +233,7 @@ void Guild::BankEventLogEntry::SaveToDB(SQLTransaction& trans) const
void Guild::BankEventLogEntry::WritePacket(WorldPacket& data) const
{
data << uint8(m_eventType);
- data << ObjectGuid(HIGHGUID_PLAYER, m_playerGuid);
+ data << ObjectGuid(HighGuid::Player, m_playerGuid);
switch (m_eventType)
{
@@ -395,7 +395,7 @@ void Guild::BankTab::LoadFromDB(Field* fields)
bool Guild::BankTab::LoadItemFromDB(Field* fields)
{
uint8 slotId = fields[13].GetUInt8();
- uint32 itemGuid = fields[14].GetUInt32();
+ ObjectGuid::LowType itemGuid = fields[14].GetUInt32();
uint32 itemEntry = fields[15].GetUInt32();
if (slotId >= GUILD_BANK_MAX_SLOTS)
{
@@ -554,7 +554,7 @@ bool Guild::BankTab::SetItem(SQLTransaction& trans, uint8 slotId, Item* item)
stmt->setUInt32(0, m_guildId);
stmt->setUInt8 (1, m_tabId);
stmt->setUInt8 (2, slotId);
- stmt->setUInt32(3, item->GetGUIDLow());
+ stmt->setUInt32(3, item->GetGUID().GetCounter());
CharacterDatabase.ExecuteOrAppend(trans, stmt);
item->SetGuidValue(ITEM_FIELD_CONTAINED, ObjectGuid::Empty);
@@ -784,7 +784,7 @@ void EmblemInfo::WritePacket(WorldPacket& data) const
data << uint32(m_backgroundColor);
}
-void EmblemInfo::SaveToDB(uint32 guildId) const
+void EmblemInfo::SaveToDB(ObjectGuid::LowType guildId) const
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GUILD_EMBLEM_INFO);
stmt->setUInt32(0, m_style);
@@ -893,7 +893,7 @@ void Guild::PlayerMoveItemData::LogBankEvent(SQLTransaction& trans, MoveItemData
{
ASSERT(pFrom);
// Bank -> Char
- m_pGuild->_LogBankEvent(trans, GUILD_BANK_LOG_WITHDRAW_ITEM, pFrom->GetContainer(), m_pPlayer->GetGUIDLow(),
+ m_pGuild->_LogBankEvent(trans, GUILD_BANK_LOG_WITHDRAW_ITEM, pFrom->GetContainer(), m_pPlayer->GetGUID().GetCounter(),
pFrom->GetItem()->GetEntry(), count);
}
@@ -978,11 +978,11 @@ void Guild::BankMoveItemData::LogBankEvent(SQLTransaction& trans, MoveItemData*
ASSERT(pFrom->GetItem());
if (pFrom->IsBank())
// Bank -> Bank
- m_pGuild->_LogBankEvent(trans, GUILD_BANK_LOG_MOVE_ITEM, pFrom->GetContainer(), m_pPlayer->GetGUIDLow(),
+ m_pGuild->_LogBankEvent(trans, GUILD_BANK_LOG_MOVE_ITEM, pFrom->GetContainer(), m_pPlayer->GetGUID().GetCounter(),
pFrom->GetItem()->GetEntry(), count, m_container);
else
// Char -> Bank
- m_pGuild->_LogBankEvent(trans, GUILD_BANK_LOG_DEPOSIT_ITEM, m_container, m_pPlayer->GetGUIDLow(),
+ m_pGuild->_LogBankEvent(trans, GUILD_BANK_LOG_DEPOSIT_ITEM, m_container, m_pPlayer->GetGUID().GetCounter(),
pFrom->GetItem()->GetEntry(), count);
}
@@ -993,7 +993,7 @@ void Guild::BankMoveItemData::LogAction(MoveItemData* pFrom) const
{
sLog->outCommand(m_pPlayer->GetSession()->GetAccountId(),
"GM %s (Guid: %u) (Account: %u) deposit item: %s (Entry: %d Count: %u) to guild bank named: %s (Guild ID: %u)",
- m_pPlayer->GetName().c_str(), m_pPlayer->GetGUIDLow(), m_pPlayer->GetSession()->GetAccountId(),
+ m_pPlayer->GetName().c_str(), m_pPlayer->GetGUID().GetCounter(), m_pPlayer->GetSession()->GetAccountId(),
pFrom->GetItem()->GetTemplate()->Name1.c_str(), pFrom->GetItem()->GetEntry(), pFrom->GetItem()->GetCount(),
m_pGuild->GetName().c_str(), m_pGuild->GetId());
}
@@ -1522,7 +1522,7 @@ void Guild::HandleInviteMember(WorldSession* session, std::string const& name)
Player* player = session->GetPlayer();
// Do not show invitations from ignored players
- if (pInvitee->GetSocial()->HasIgnore(player->GetGUIDLow()))
+ if (pInvitee->GetSocial()->HasIgnore(player->GetGUID().GetCounter()))
return;
if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && pInvitee->GetTeam() != player->GetTeam())
@@ -1554,7 +1554,7 @@ void Guild::HandleInviteMember(WorldSession* session, std::string const& name)
TC_LOG_DEBUG("guild", "Player %s invited %s to join his Guild", player->GetName().c_str(), name.c_str());
pInvitee->SetGuildIdInvited(m_id);
- _LogEvent(GUILD_EVENT_LOG_INVITE_PLAYER, player->GetGUIDLow(), pInvitee->GetGUIDLow());
+ _LogEvent(GUILD_EVENT_LOG_INVITE_PLAYER, player->GetGUID().GetCounter(), pInvitee->GetGUID().GetCounter());
WorldPacket data(SMSG_GUILD_INVITE, 8 + 10); // Guess size
data << player->GetName();
@@ -1595,7 +1595,7 @@ void Guild::HandleLeaveMember(WorldSession* session)
{
DeleteMember(player->GetGUID(), false, false);
- _LogEvent(GUILD_EVENT_LOG_LEAVE_GUILD, player->GetGUIDLow());
+ _LogEvent(GUILD_EVENT_LOG_LEAVE_GUILD, player->GetGUID().GetCounter());
_BroadcastEvent(GE_LEFT, player->GetGUID(), player->GetName().c_str());
SendCommandResult(session, GUILD_COMMAND_QUIT, ERR_GUILD_COMMAND_SUCCESS, m_name);
@@ -1629,7 +1629,7 @@ void Guild::HandleRemoveMember(WorldSession* session, std::string const& name)
ObjectGuid guid = member->GetGUID();
// After call to DeleteMember pointer to member becomes invalid
DeleteMember(guid, false, true);
- _LogEvent(GUILD_EVENT_LOG_UNINVITE_PLAYER, player->GetGUIDLow(), guid.GetCounter());
+ _LogEvent(GUILD_EVENT_LOG_UNINVITE_PLAYER, player->GetGUID().GetCounter(), guid.GetCounter());
_BroadcastEvent(GE_REMOVED, ObjectGuid::Empty, name.c_str(), player->GetName().c_str());
}
}
@@ -1683,7 +1683,7 @@ void Guild::HandleUpdateMemberRank(WorldSession* session, std::string const& nam
uint32 newRankId = member->GetRankId() + (demote ? 1 : -1);
member->ChangeRank(newRankId);
- _LogEvent(demote ? GUILD_EVENT_LOG_DEMOTE_PLAYER : GUILD_EVENT_LOG_PROMOTE_PLAYER, player->GetGUIDLow(), member->GetGUID().GetCounter(), newRankId);
+ _LogEvent(demote ? GUILD_EVENT_LOG_DEMOTE_PLAYER : GUILD_EVENT_LOG_PROMOTE_PLAYER, player->GetGUID().GetCounter(), member->GetGUID().GetCounter(), newRankId);
_BroadcastEvent(demote ? GE_DEMOTION : GE_PROMOTION, ObjectGuid::Empty, player->GetName().c_str(), name.c_str(), _GetRankName(newRankId).c_str());
}
}
@@ -1743,7 +1743,7 @@ void Guild::HandleMemberDepositMoney(WorldSession* session, uint32 amount)
player->ModifyMoney(-int32(amount));
player->SaveGoldToDB(trans);
- _LogBankEvent(trans, GUILD_BANK_LOG_DEPOSIT_MONEY, uint8(0), player->GetGUIDLow(), amount);
+ _LogBankEvent(trans, GUILD_BANK_LOG_DEPOSIT_MONEY, uint8(0), player->GetGUID().GetCounter(), amount);
CharacterDatabase.CommitTransaction(trans);
@@ -1794,7 +1794,7 @@ bool Guild::HandleMemberWithdrawMoney(WorldSession* session, uint32 amount, bool
_ModifyBankMoney(trans, amount, false);
// Log guild bank event
- _LogBankEvent(trans, repair ? GUILD_BANK_LOG_REPAIR_MONEY : GUILD_BANK_LOG_WITHDRAW_MONEY, uint8(0), player->GetGUIDLow(), amount);
+ _LogBankEvent(trans, repair ? GUILD_BANK_LOG_REPAIR_MONEY : GUILD_BANK_LOG_WITHDRAW_MONEY, uint8(0), player->GetGUID().GetCounter(), amount);
CharacterDatabase.CommitTransaction(trans);
std::string aux = ByteArrayToHexStr(reinterpret_cast<uint8*>(&m_bankMoney), 8, true);
@@ -1942,7 +1942,7 @@ bool Guild::LoadFromDB(Field* fields)
{
m_id = fields[0].GetUInt32();
m_name = fields[1].GetString();
- m_leaderGuid = ObjectGuid(HIGHGUID_PLAYER, fields[2].GetUInt32());
+ m_leaderGuid = ObjectGuid(HighGuid::Player, fields[2].GetUInt32());
m_emblemInfo.LoadFromDB(fields);
m_info = fields[8].GetString();
m_motd = fields[9].GetString();
@@ -1972,8 +1972,8 @@ void Guild::LoadRankFromDB(Field* fields)
bool Guild::LoadMemberFromDB(Field* fields)
{
- uint32 lowguid = fields[1].GetUInt32();
- Member *member = new Member(m_id, ObjectGuid(HIGHGUID_PLAYER, lowguid), fields[2].GetUInt8());
+ ObjectGuid::LowType lowguid = fields[1].GetUInt32();
+ Member *member = new Member(m_id, ObjectGuid(HighGuid::Player, lowguid), fields[2].GetUInt8());
if (!member->LoadFromDB(fields))
{
_DeleteMemberFromDB(lowguid);
@@ -2019,7 +2019,7 @@ bool Guild::LoadBankEventLogFromDB(Field* fields)
LogHolder* pLog = m_bankEventLog[tabId];
if (pLog->CanInsert())
{
- uint32 guid = fields[2].GetUInt32();
+ ObjectGuid::LowType guid = fields[2].GetUInt32();
GuildBankEventLogTypes eventType = GuildBankEventLogTypes(fields[3].GetUInt8());
if (BankEventLogEntry::IsMoneyEvent(eventType))
{
@@ -2152,7 +2152,7 @@ void Guild::BroadcastToGuild(WorldSession* session, bool officerOnly, std::strin
for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
if (Player* player = itr->second->FindConnectedPlayer())
if (player->GetSession() && _HasRankRight(player, officerOnly ? GR_RIGHT_OFFCHATLISTEN : GR_RIGHT_GCHATLISTEN) &&
- !player->GetSocial()->HasIgnore(session->GetPlayer()->GetGUIDLow()))
+ !player->GetSocial()->HasIgnore(session->GetPlayer()->GetGUID().GetCounter()))
player->GetSession()->SendPacket(&data);
}
}
@@ -2222,7 +2222,7 @@ bool Guild::AddMember(ObjectGuid guid, uint8 rankId)
// This will be prevent attempt to join many guilds and corrupt guild data integrity
Player::RemovePetitionsAndSigns(guid, GUILD_CHARTER_TYPE);
- uint32 lowguid = guid.GetCounter();
+ ObjectGuid::LowType lowguid = guid.GetCounter();
// If rank was not passed, assign lowest possible rank
if (rankId == GUILD_RANK_NONE)
@@ -2284,7 +2284,7 @@ bool Guild::AddMember(ObjectGuid guid, uint8 rankId)
void Guild::DeleteMember(ObjectGuid guid, bool isDisbanding, bool isKicked, bool canDeleteGuild)
{
- uint32 lowguid = guid.GetCounter();
+ ObjectGuid::LowType lowguid = guid.GetCounter();
Player* player = ObjectAccessor::FindConnectedPlayer(guid);
// Guild master can be deleted when loading guild and guid doesn't exist in characters table
@@ -2635,7 +2635,7 @@ inline bool Guild::_MemberHasTabRights(ObjectGuid guid, uint8 tabId, uint32 righ
}
// Add new event log record
-inline void Guild::_LogEvent(GuildEventLogTypes eventType, uint32 playerGuid1, uint32 playerGuid2, uint8 newRank)
+inline void Guild::_LogEvent(GuildEventLogTypes eventType, ObjectGuid::LowType playerGuid1, ObjectGuid::LowType playerGuid2, uint8 newRank)
{
SQLTransaction trans = CharacterDatabase.BeginTransaction();
m_eventLog->AddEvent(trans, new EventLogEntry(m_id, m_eventLog->GetNextGUID(), eventType, playerGuid1, playerGuid2, newRank));
@@ -2645,7 +2645,7 @@ inline void Guild::_LogEvent(GuildEventLogTypes eventType, uint32 playerGuid1, u
}
// Add new bank event log record
-void Guild::_LogBankEvent(SQLTransaction& trans, GuildBankEventLogTypes eventType, uint8 tabId, uint32 lowguid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId)
+void Guild::_LogBankEvent(SQLTransaction& trans, GuildBankEventLogTypes eventType, uint8 tabId, ObjectGuid::LowType lowguid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId)
{
if (tabId > GUILD_BANK_MAX_TABS)
return;
@@ -2692,7 +2692,7 @@ void Guild::_MoveItems(MoveItemData* pSrc, MoveItemData* pDest, uint32 splitedAm
if (pItemSrc->GetCount() == 0)
{
TC_LOG_FATAL("guild", "Guild::SwapItems: Player %s(GUIDLow: %u) tried to move item %u from tab %u slot %u to tab %u slot %u, but item %u has a stack of zero!",
- player->GetName(), player->GetGUIDLow(), pItemSrc->GetEntry(), tabId, slotId, destTabId, destSlotId, pItemSrc->GetEntry());
+ player->GetName(), player->GetGUID().GetCounter(), pItemSrc->GetEntry(), tabId, slotId, destTabId, destSlotId, pItemSrc->GetEntry());
//return; // Commented out for now, uncomment when it's verified that this causes a crash!!
}
// */
diff --git a/src/server/game/Guilds/Guild.h b/src/server/game/Guilds/Guild.h
index bfc6f2f9af3..ca5ea95ee2c 100644
--- a/src/server/game/Guilds/Guild.h
+++ b/src/server/game/Guilds/Guild.h
@@ -229,7 +229,7 @@ public:
EmblemInfo() : m_style(0), m_color(0), m_borderStyle(0), m_borderColor(0), m_backgroundColor(0) { }
void LoadFromDB(Field* fields);
- void SaveToDB(uint32 guildId) const;
+ void SaveToDB(ObjectGuid::LowType guildId) const;
void ReadPacket(WorldPacket& recv);
void WritePacket(WorldPacket& data) const;
@@ -286,7 +286,7 @@ private:
class Member
{
public:
- Member(uint32 guildId, ObjectGuid guid, uint8 rankId) :
+ Member(ObjectGuid::LowType guildId, ObjectGuid guid, uint8 rankId) :
m_guildId(guildId),
m_guid(guid),
m_zoneId(0),
@@ -328,7 +328,7 @@ private:
uint8 GetLevel() const { return m_level; }
uint8 GetFlags() const { return m_flags; }
uint32 GetZoneId() const { return m_zoneId; }
- bool IsOnline() { return (m_flags & GUILDMEMBER_STATUS_ONLINE); }
+ bool IsOnline() const { return (m_flags & GUILDMEMBER_STATUS_ONLINE); }
void ChangeRank(uint8 newRank);
@@ -345,7 +345,7 @@ private:
inline Player* FindConnectedPlayer() const { return ObjectAccessor::FindConnectedPlayer(m_guid); }
private:
- uint32 m_guildId;
+ ObjectGuid::LowType m_guildId;
// Fields from characters table
ObjectGuid m_guid;
std::string m_name;
@@ -367,8 +367,8 @@ private:
class LogEntry
{
public:
- LogEntry(uint32 guildId, uint32 guid) : m_guildId(guildId), m_guid(guid), m_timestamp(::time(NULL)) { }
- LogEntry(uint32 guildId, uint32 guid, time_t timestamp) : m_guildId(guildId), m_guid(guid), m_timestamp(timestamp) { }
+ LogEntry(ObjectGuid::LowType guildId, uint32 guid) : m_guildId(guildId), m_guid(guid), m_timestamp(::time(NULL)) { }
+ LogEntry(ObjectGuid::LowType guildId, uint32 guid, time_t timestamp) : m_guildId(guildId), m_guid(guid), m_timestamp(timestamp) { }
virtual ~LogEntry() { }
uint32 GetGUID() const { return m_guid; }
@@ -378,7 +378,7 @@ private:
virtual void WritePacket(WorldPacket& data) const = 0;
protected:
- uint32 m_guildId;
+ ObjectGuid::LowType m_guildId;
uint32 m_guid;
uint64 m_timestamp;
};
@@ -387,10 +387,10 @@ private:
class EventLogEntry : public LogEntry
{
public:
- EventLogEntry(uint32 guildId, uint32 guid, GuildEventLogTypes eventType, uint32 playerGuid1, uint32 playerGuid2, uint8 newRank) :
+ EventLogEntry(ObjectGuid::LowType guildId, uint32 guid, GuildEventLogTypes eventType, ObjectGuid::LowType playerGuid1, ObjectGuid::LowType playerGuid2, uint8 newRank) :
LogEntry(guildId, guid), m_eventType(eventType), m_playerGuid1(playerGuid1), m_playerGuid2(playerGuid2), m_newRank(newRank) { }
- EventLogEntry(uint32 guildId, uint32 guid, time_t timestamp, GuildEventLogTypes eventType, uint32 playerGuid1, uint32 playerGuid2, uint8 newRank) :
+ EventLogEntry(ObjectGuid::LowType guildId, uint32 guid, time_t timestamp, GuildEventLogTypes eventType, ObjectGuid::LowType playerGuid1, ObjectGuid::LowType playerGuid2, uint8 newRank) :
LogEntry(guildId, guid, timestamp), m_eventType(eventType), m_playerGuid1(playerGuid1), m_playerGuid2(playerGuid2), m_newRank(newRank) { }
~EventLogEntry() { }
@@ -400,8 +400,8 @@ private:
private:
GuildEventLogTypes m_eventType;
- uint32 m_playerGuid1;
- uint32 m_playerGuid2;
+ ObjectGuid::LowType m_playerGuid1;
+ ObjectGuid::LowType m_playerGuid2;
uint8 m_newRank;
};
@@ -417,11 +417,11 @@ private:
eventType == GUILD_BANK_LOG_REPAIR_MONEY;
}
- BankEventLogEntry(uint32 guildId, uint32 guid, GuildBankEventLogTypes eventType, uint8 tabId, uint32 playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId) :
+ BankEventLogEntry(ObjectGuid::LowType guildId, uint32 guid, GuildBankEventLogTypes eventType, uint8 tabId, ObjectGuid::LowType playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId) :
LogEntry(guildId, guid), m_eventType(eventType), m_bankTabId(tabId), m_playerGuid(playerGuid),
m_itemOrMoney(itemOrMoney), m_itemStackCount(itemStackCount), m_destTabId(destTabId) { }
- BankEventLogEntry(uint32 guildId, uint32 guid, time_t timestamp, uint8 tabId, GuildBankEventLogTypes eventType, uint32 playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId) :
+ BankEventLogEntry(ObjectGuid::LowType guildId, uint32 guid, time_t timestamp, uint8 tabId, GuildBankEventLogTypes eventType, ObjectGuid::LowType playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId) :
LogEntry(guildId, guid, timestamp), m_eventType(eventType), m_bankTabId(tabId), m_playerGuid(playerGuid),
m_itemOrMoney(itemOrMoney), m_itemStackCount(itemStackCount), m_destTabId(destTabId) { }
@@ -433,7 +433,7 @@ private:
private:
GuildBankEventLogTypes m_eventType;
uint8 m_bankTabId;
- uint32 m_playerGuid;
+ ObjectGuid::LowType m_playerGuid;
uint32 m_itemOrMoney;
uint16 m_itemStackCount;
uint8 m_destTabId;
@@ -470,8 +470,8 @@ private:
{
public:
RankInfo(): m_guildId(0), m_rankId(GUILD_RANK_NONE), m_rights(GR_RIGHT_EMPTY), m_bankMoneyPerDay(0) { }
- RankInfo(uint32 guildId) : m_guildId(guildId), m_rankId(GUILD_RANK_NONE), m_rights(GR_RIGHT_EMPTY), m_bankMoneyPerDay(0) { }
- RankInfo(uint32 guildId, uint8 rankId, std::string const& name, uint32 rights, uint32 money) :
+ RankInfo(ObjectGuid::LowType guildId) : m_guildId(guildId), m_rankId(GUILD_RANK_NONE), m_rights(GR_RIGHT_EMPTY), m_bankMoneyPerDay(0) { }
+ RankInfo(ObjectGuid::LowType guildId, uint8 rankId, std::string const& name, uint32 rights, uint32 money) :
m_guildId(guildId), m_rankId(rankId), m_name(name), m_rights(rights),
m_bankMoneyPerDay(rankId != GR_GUILDMASTER ? money : GUILD_WITHDRAW_MONEY_UNLIMITED) { }
@@ -505,7 +505,7 @@ private:
void CreateMissingTabsIfNeeded(uint8 ranks, SQLTransaction& trans, bool logOnCreate = false);
private:
- uint32 m_guildId;
+ ObjectGuid::LowType m_guildId;
uint8 m_rankId;
std::string m_name;
@@ -517,7 +517,7 @@ private:
class BankTab
{
public:
- BankTab(uint32 guildId, uint8 tabId) : m_guildId(guildId), m_tabId(tabId)
+ BankTab(ObjectGuid::LowType guildId, uint8 tabId) : m_guildId(guildId), m_tabId(tabId)
{
memset(m_items, 0, GUILD_BANK_MAX_SLOTS * sizeof(Item*));
}
@@ -542,7 +542,7 @@ private:
bool SetItem(SQLTransaction& trans, uint8 slotId, Item* pItem);
private:
- uint32 m_guildId;
+ ObjectGuid::LowType m_guildId;
uint8 m_tabId;
Item* m_items[GUILD_BANK_MAX_SLOTS];
@@ -653,7 +653,7 @@ public:
void Disband();
// Getters
- uint32 GetId() const { return m_id; }
+ ObjectGuid::LowType GetId() const { return m_id; }
ObjectGuid GetLeaderGUID() const { return m_leaderGuid; }
std::string const& GetName() const { return m_name; }
std::string const& GetMOTD() const { return m_motd; }
@@ -745,7 +745,7 @@ public:
void ResetTimes();
protected:
- uint32 m_id;
+ ObjectGuid::LowType m_id;
std::string m_name;
ObjectGuid m_leaderGuid;
std::string m_motd;
@@ -803,7 +803,7 @@ private:
return NULL;
}
- inline void _DeleteMemberFromDB(uint32 lowguid) const
+ inline void _DeleteMemberFromDB(ObjectGuid::LowType lowguid) const
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_MEMBER);
stmt->setUInt32(0, lowguid);
@@ -838,8 +838,8 @@ private:
void _UpdateMemberWithdrawSlots(SQLTransaction& trans, ObjectGuid guid, uint8 tabId);
bool _MemberHasTabRights(ObjectGuid guid, uint8 tabId, uint32 rights) const;
- void _LogEvent(GuildEventLogTypes eventType, uint32 playerGuid1, uint32 playerGuid2 = 0, uint8 newRank = 0);
- void _LogBankEvent(SQLTransaction& trans, GuildBankEventLogTypes eventType, uint8 tabId, uint32 playerGuid, uint32 itemOrMoney, uint16 itemStackCount = 0, uint8 destTabId = 0);
+ void _LogEvent(GuildEventLogTypes eventType, ObjectGuid::LowType playerGuid1, ObjectGuid::LowType playerGuid2 = 0, uint8 newRank = 0);
+ void _LogBankEvent(SQLTransaction& trans, GuildBankEventLogTypes eventType, uint8 tabId, ObjectGuid::LowType playerGuid, uint32 itemOrMoney, uint16 itemStackCount = 0, uint8 destTabId = 0);
Item* _GetItem(uint8 tabId, uint8 slotId) const;
void _RemoveItem(SQLTransaction& trans, uint8 tabId, uint8 slotId);
diff --git a/src/server/game/Guilds/GuildMgr.cpp b/src/server/game/Guilds/GuildMgr.cpp
index 2603a60ee0e..6a75761ded0 100644
--- a/src/server/game/Guilds/GuildMgr.cpp
+++ b/src/server/game/Guilds/GuildMgr.cpp
@@ -32,12 +32,12 @@ void GuildMgr::AddGuild(Guild* guild)
GuildStore[guild->GetId()] = guild;
}
-void GuildMgr::RemoveGuild(uint32 guildId)
+void GuildMgr::RemoveGuild(ObjectGuid::LowType guildId)
{
GuildStore.erase(guildId);
}
-uint32 GuildMgr::GenerateGuildId()
+ObjectGuid::LowType GuildMgr::GenerateGuildId()
{
if (NextGuildId >= 0xFFFFFFFE)
{
@@ -48,7 +48,7 @@ uint32 GuildMgr::GenerateGuildId()
}
// Guild collection
-Guild* GuildMgr::GetGuildById(uint32 guildId) const
+Guild* GuildMgr::GetGuildById(ObjectGuid::LowType guildId) const
{
GuildContainer::const_iterator itr = GuildStore.find(guildId);
if (itr != GuildStore.end())
@@ -71,7 +71,7 @@ Guild* GuildMgr::GetGuildByName(const std::string& guildName) const
return NULL;
}
-std::string GuildMgr::GetGuildNameById(uint32 guildId) const
+std::string GuildMgr::GetGuildNameById(ObjectGuid::LowType guildId) const
{
if (Guild* guild = GetGuildById(guildId))
return guild->GetName();
diff --git a/src/server/game/Guilds/GuildMgr.h b/src/server/game/Guilds/GuildMgr.h
index 2a73d53a740..1450769c578 100644
--- a/src/server/game/Guilds/GuildMgr.h
+++ b/src/server/game/Guilds/GuildMgr.h
@@ -34,21 +34,21 @@ public:
}
Guild* GetGuildByLeader(ObjectGuid guid) const;
- Guild* GetGuildById(uint32 guildId) const;
+ Guild* GetGuildById(ObjectGuid::LowType guildId) const;
Guild* GetGuildByName(std::string const& guildName) const;
- std::string GetGuildNameById(uint32 guildId) const;
+ std::string GetGuildNameById(ObjectGuid::LowType guildId) const;
void LoadGuilds();
void AddGuild(Guild* guild);
- void RemoveGuild(uint32 guildId);
+ void RemoveGuild(ObjectGuid::LowType guildId);
- uint32 GenerateGuildId();
- void SetNextGuildId(uint32 Id) { NextGuildId = Id; }
+ ObjectGuid::LowType GenerateGuildId();
+ void SetNextGuildId(ObjectGuid::LowType Id) { NextGuildId = Id; }
void ResetTimes();
protected:
- typedef std::unordered_map<uint32, Guild*> GuildContainer;
- uint32 NextGuildId;
+ typedef std::unordered_map<ObjectGuid::LowType, Guild*> GuildContainer;
+ ObjectGuid::LowType NextGuildId;
GuildContainer GuildStore;
};
diff --git a/src/server/game/Handlers/ArenaTeamHandler.cpp b/src/server/game/Handlers/ArenaTeamHandler.cpp
index 5ac5ae02b90..5616eb89b07 100644
--- a/src/server/game/Handlers/ArenaTeamHandler.cpp
+++ b/src/server/game/Handlers/ArenaTeamHandler.cpp
@@ -17,17 +17,14 @@
*/
#include "Player.h"
-#include "World.h"
#include "WorldPacket.h"
#include "WorldSession.h"
-#include "DatabaseEnv.h"
-
#include "ArenaTeam.h"
-#include "Log.h"
-#include "ObjectMgr.h"
#include "SocialMgr.h"
#include "ArenaTeamMgr.h"
#include "Opcodes.h"
+#include "ObjectAccessor.h"
+#include "ObjectMgr.h"
void WorldSession::HandleInspectArenaTeamsOpcode(WorldPacket& recvData)
{
@@ -128,7 +125,7 @@ void WorldSession::HandleArenaTeamInviteOpcode(WorldPacket& recvData)
}
// OK result but don't send invite
- if (player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow()))
+ if (player->GetSocial()->HasIgnore(GetPlayer()->GetGUID().GetCounter()))
return;
if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && player->GetTeam() != GetPlayer()->GetTeam())
diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp
index 4975d19743d..8ecf86680ca 100644
--- a/src/server/game/Handlers/AuctionHouseHandler.cpp
+++ b/src/server/game/Handlers/AuctionHouseHandler.cpp
@@ -25,7 +25,6 @@
#include "AuctionHouseMgr.h"
#include "Log.h"
#include "Language.h"
-#include "Opcodes.h"
#include "UpdateMask.h"
#include "Util.h"
#include "AccountMgr.h"
@@ -150,12 +149,11 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
if (bid > MAX_MONEY_AMOUNT || buyout > MAX_MONEY_AMOUNT)
{
- TC_LOG_DEBUG("network", "WORLD: HandleAuctionSellItem - Player %s (GUID %u) attempted to sell item with higher price than max gold amount.", _player->GetName().c_str(), _player->GetGUIDLow());
+ TC_LOG_DEBUG("network", "WORLD: HandleAuctionSellItem - Player %s (GUID %u) attempted to sell item with higher price than max gold amount.", _player->GetName().c_str(), _player->GetGUID().GetCounter());
SendAuctionCommandResult(0, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
return;
}
-
Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer, UNIT_NPC_FLAG_AUCTIONEER);
if (!creature)
{
@@ -203,7 +201,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
if (itemEntry == 0)
itemEntry = item->GetTemplate()->ItemId;
- if (sAuctionMgr->GetAItem(item->GetGUIDLow()) || !item->CanBeTraded() || item->IsNotEmptyBag() ||
+ if (sAuctionMgr->GetAItem(item->GetGUID().GetCounter()) || !item->CanBeTraded() || item->IsNotEmptyBag() ||
item->GetTemplate()->Flags & ITEM_PROTO_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION) ||
item->GetCount() < count[i] || itemEntry != item->GetTemplate()->ItemId)
{
@@ -260,9 +258,30 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
AuctionEntry* AH = new AuctionEntry();
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION))
- AH->auctioneer = 23442; ///@TODO - HARDCODED DB GUID, BAD BAD BAD
+ AH->houseId = AUCTIONHOUSE_NEUTRAL;
else
- AH->auctioneer = auctioneer.GetCounter();
+ {
+ CreatureData const* auctioneerData = sObjectMgr->GetCreatureData(creature->GetSpawnId());
+ if (!auctioneerData)
+ {
+ TC_LOG_ERROR("misc", "Data for auctioneer not found (%s)", auctioneer.ToString().c_str());
+ SendAuctionCommandResult(0, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
+ delete AH;
+ return;
+ }
+
+ CreatureTemplate const* auctioneerInfo = sObjectMgr->GetCreatureTemplate(auctioneerData->id);
+ if (!auctioneerInfo)
+ {
+ TC_LOG_ERROR("misc", "Non existing auctioneer (%s)", auctioneer.ToString().c_str());
+ SendAuctionCommandResult(0, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
+ delete AH;
+ return;
+ }
+
+ const AuctionHouseEntry* AHEntry = sAuctionMgr->GetAuctionHouseEntry(auctioneerInfo->faction);
+ AH->houseId = AHEntry->houseId;
+ }
// Required stack size of auction matches to current item stack size, just move item to auctionhouse
if (itemsCount == 1 && item->GetCount() == count[0])
@@ -274,10 +293,10 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
}
AH->Id = sObjectMgr->GenerateAuctionID();
- AH->itemGUIDLow = item->GetGUIDLow();
+ AH->itemGUIDLow = item->GetGUID().GetCounter();
AH->itemEntry = item->GetEntry();
AH->itemCount = item->GetCount();
- AH->owner = _player->GetGUIDLow();
+ AH->owner = _player->GetGUID().GetCounter();
AH->startbid = bid;
AH->bidder = 0;
AH->bid = 0;
@@ -286,8 +305,8 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
AH->deposit = deposit;
AH->auctionHouseEntry = auctionHouseEntry;
- TC_LOG_INFO("network", "CMSG_AUCTION_SELL_ITEM: Player %s (guid %d) is selling item %s entry %u (guid %d) to auctioneer %u with count %u with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u",
- _player->GetName().c_str(), _player->GetGUIDLow(), item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetGUIDLow(), AH->auctioneer, item->GetCount(), bid, buyout, auctionTime, AH->GetHouseId());
+ TC_LOG_INFO("network", "CMSG_AUCTION_SELL_ITEM: Player %s (guid %d) is selling item %s entry %u (guid %d) with count %u with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u",
+ _player->GetName().c_str(), _player->GetGUID().GetCounter(), item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetGUID().GetCounter(), item->GetCount(), bid, buyout, auctionTime, AH->GetHouseId());
sAuctionMgr->AddAItem(item);
auctionHouse->AddAuction(AH);
@@ -322,10 +341,10 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
}
AH->Id = sObjectMgr->GenerateAuctionID();
- AH->itemGUIDLow = newItem->GetGUIDLow();
+ AH->itemGUIDLow = newItem->GetGUID().GetCounter();
AH->itemEntry = newItem->GetEntry();
AH->itemCount = newItem->GetCount();
- AH->owner = _player->GetGUIDLow();
+ AH->owner = _player->GetGUID().GetCounter();
AH->startbid = bid;
AH->bidder = 0;
AH->bid = 0;
@@ -334,8 +353,8 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
AH->deposit = deposit;
AH->auctionHouseEntry = auctionHouseEntry;
- TC_LOG_INFO("network", "CMSG_AUCTION_SELL_ITEM: Player %s (guid %d) is selling item %s entry %u (guid %d) to auctioneer %u with count %u with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u",
- _player->GetName().c_str(), _player->GetGUIDLow(), newItem->GetTemplate()->Name1.c_str(), newItem->GetEntry(), newItem->GetGUIDLow(), AH->auctioneer, newItem->GetCount(), bid, buyout, auctionTime, AH->GetHouseId());
+ TC_LOG_INFO("network", "CMSG_AUCTION_SELL_ITEM: Player %s (guid %d) is selling item %s entry %u (guid %d) with count %u with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u",
+ _player->GetName().c_str(), _player->GetGUID().GetCounter(), newItem->GetTemplate()->Name1.c_str(), newItem->GetEntry(), newItem->GetGUID().GetCounter(), newItem->GetCount(), bid, buyout, auctionTime, AH->GetHouseId());
sAuctionMgr->AddAItem(newItem);
auctionHouse->AddAuction(AH);
@@ -411,7 +430,7 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData)
AuctionEntry* auction = auctionHouse->GetAuction(auctionId);
Player* player = GetPlayer();
- if (!auction || auction->owner == player->GetGUIDLow())
+ if (!auction || auction->owner == player->GetGUID().GetCounter())
{
//you cannot bid your own auction:
SendAuctionCommandResult(0, AUCTION_PLACE_BID, ERR_AUCTION_BID_OWN);
@@ -419,7 +438,7 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData)
}
// impossible have online own another character (use this for speedup check in case online owner)
- ObjectGuid ownerGuid(HIGHGUID_PLAYER, auction->owner);
+ ObjectGuid ownerGuid(HighGuid::Player, auction->owner);
Player* auction_owner = ObjectAccessor::FindPlayer(ownerGuid);
if (!auction_owner && sObjectMgr->GetPlayerAccountIdByGUID(ownerGuid) == player->GetSession()->GetAccountId())
{
@@ -453,7 +472,7 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData)
{
if (auction->bidder > 0)
{
- if (auction->bidder == player->GetGUIDLow())
+ if (auction->bidder == player->GetGUID().GetCounter())
player->ModifyMoney(-int32(price - auction->bid));
else
{
@@ -465,7 +484,7 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData)
else
player->ModifyMoney(-int32(price));
- auction->bidder = player->GetGUIDLow();
+ auction->bidder = player->GetGUID().GetCounter();
auction->bid = price;
GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, price);
@@ -480,7 +499,7 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData)
else
{
//buyout:
- if (player->GetGUIDLow() == auction->bidder)
+ if (player->GetGUID().GetCounter() == auction->bidder)
player->ModifyMoney(-int32(auction->buyout - auction->bid));
else
{
@@ -488,7 +507,7 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData)
if (auction->bidder) //buyout for bidded auction ..
sAuctionMgr->SendAuctionOutbiddedMail(auction, auction->buyout, GetPlayer(), trans);
}
- auction->bidder = player->GetGUIDLow();
+ auction->bidder = player->GetGUID().GetCounter();
auction->bid = auction->buyout;
GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, auction->buyout);
@@ -536,7 +555,7 @@ void WorldSession::HandleAuctionRemoveItem(WorldPacket& recvData)
Player* player = GetPlayer();
SQLTransaction trans = CharacterDatabase.BeginTransaction();
- if (auction && auction->owner == player->GetGUIDLow())
+ if (auction && auction->owner == player->GetGUID().GetCounter())
{
Item* pItem = sAuctionMgr->GetAItem(auction->itemGUIDLow);
if (pItem)
@@ -567,7 +586,7 @@ void WorldSession::HandleAuctionRemoveItem(WorldPacket& recvData)
{
SendAuctionCommandResult(0, AUCTION_CANCEL, ERR_AUCTION_DATABASE_ERROR);
//this code isn't possible ... maybe there should be assert
- TC_LOG_ERROR("network", "CHEATER : %u, he tried to cancel auction (id: %u) of another player, or auction is NULL", player->GetGUIDLow(), auctionId);
+ TC_LOG_ERROR("network", "CHEATER : %u, he tried to cancel auction (id: %u) of another player, or auction is NULL", player->GetGUID().GetCounter(), auctionId);
return;
}
diff --git a/src/server/game/Handlers/BattleGroundHandler.cpp b/src/server/game/Handlers/BattleGroundHandler.cpp
index 2ec89ac2a26..d4291e34df6 100644
--- a/src/server/game/Handlers/BattleGroundHandler.cpp
+++ b/src/server/game/Handlers/BattleGroundHandler.cpp
@@ -86,7 +86,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
if (!sBattlemasterListStore.LookupEntry(bgTypeId_))
{
- TC_LOG_ERROR("network", "Battleground: invalid bgtype (%u) received. possible cheater? player guid %u", bgTypeId_, _player->GetGUIDLow());
+ TC_LOG_ERROR("network", "Battleground: invalid bgtype (%u) received. possible cheater? player guid %u", bgTypeId_, _player->GetGUID().GetCounter());
return;
}
@@ -194,7 +194,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->ArenaType, 0);
SendPacket(&data);
TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",
- bgQueueTypeId, bgTypeId, _player->GetGUIDLow(), _player->GetName().c_str());
+ bgQueueTypeId, bgTypeId, _player->GetGUID().GetCounter(), _player->GetName().c_str());
}
else
{
@@ -242,7 +242,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err);
member->GetSession()->SendPacket(&data);
TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",
- bgQueueTypeId, bgTypeId, member->GetGUIDLow(), member->GetName().c_str());
+ bgQueueTypeId, bgTypeId, member->GetGUID().GetCounter(), member->GetName().c_str());
}
TC_LOG_DEBUG("bg.battleground", "Battleground: group end");
}
@@ -335,7 +335,7 @@ void WorldSession::HandleBattlefieldListOpcode(WorldPacket &recvData)
BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId);
if (!bl)
{
- TC_LOG_DEBUG("bg.battleground", "BattlegroundHandler: invalid bgtype (%u) with player (Name: %s, GUID: %u) received.", bgTypeId, _player->GetName().c_str(), _player->GetGUIDLow());
+ TC_LOG_DEBUG("bg.battleground", "BattlegroundHandler: invalid bgtype (%u) with player (Name: %s, GUID: %u) received.", bgTypeId, _player->GetName().c_str(), _player->GetGUID().GetCounter());
return;
}
@@ -424,13 +424,13 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData)
sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data2, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS);
_player->GetSession()->SendPacket(&data2);
action = 0;
- TC_LOG_DEBUG("bg.battleground", "Player %s (%u) has a deserter debuff, do not port him to battleground!", _player->GetName().c_str(), _player->GetGUIDLow());
+ TC_LOG_DEBUG("bg.battleground", "Player %s (%u) has a deserter debuff, do not port him to battleground!", _player->GetName().c_str(), _player->GetGUID().GetCounter());
}
//if player don't match battleground max level, then do not allow him to enter! (this might happen when player leveled up during his waiting in queue
if (_player->getLevel() > bg->GetMaxLevel())
{
TC_LOG_ERROR("network", "Player %s (%u) has level (%u) higher than maxlevel (%u) of battleground (%u)! Do not port him to battleground!",
- _player->GetName().c_str(), _player->GetGUIDLow(), _player->getLevel(), bg->GetMaxLevel(), bg->GetTypeID());
+ _player->GetName().c_str(), _player->GetGUID().GetCounter(), _player->getLevel(), bg->GetMaxLevel(), bg->GetTypeID());
action = 0;
}
}
@@ -480,7 +480,7 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData)
sBattlegroundMgr->SendToBattleground(_player, ginfo.IsInvitedToBGInstanceGUID, bgTypeId);
// add only in HandleMoveWorldPortAck()
// bg->AddPlayer(_player, team);
- TC_LOG_DEBUG("bg.battleground", "Battleground: player %s (%u) joined battle for bg %u, bgtype %u, queue type %u.", _player->GetName().c_str(), _player->GetGUIDLow(), bg->GetInstanceID(), bg->GetTypeID(), bgQueueTypeId);
+ TC_LOG_DEBUG("bg.battleground", "Battleground: player %s (%u) joined battle for bg %u, bgtype %u, queue type %u.", _player->GetName().c_str(), _player->GetGUID().GetCounter(), bg->GetInstanceID(), bg->GetTypeID(), bgQueueTypeId);
}
else // leave queue
{
@@ -505,7 +505,17 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData)
if (!ginfo.ArenaType)
sBattlegroundMgr->ScheduleQueueUpdate(ginfo.ArenaMatchmakerRating, ginfo.ArenaType, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId());
SendPacket(&data);
- TC_LOG_DEBUG("bg.battleground", "Battleground: player %s (%u) left queue for bgtype %u, queue type %u.", _player->GetName().c_str(), _player->GetGUIDLow(), bg->GetTypeID(), bgQueueTypeId);
+ TC_LOG_DEBUG("bg.battleground", "Battleground: player %s (%u) left queue for bgtype %u, queue type %u.", _player->GetName().c_str(), _player->GetGUID().GetCounter(), bg->GetTypeID(), bgQueueTypeId);
+
+ // track if player refuses to join the BG after being invited
+ if (bg->isBattleground() && sWorld->getBoolConfig(CONFIG_BATTLEGROUND_TRACK_DESERTERS) &&
+ (bg->GetStatus() == STATUS_IN_PROGRESS || bg->GetStatus() == STATUS_WAIT_JOIN))
+ {
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_DESERTER_TRACK);
+ stmt->setUInt32(0, _player->GetGUID().GetCounter());
+ stmt->setUInt8(1, BG_DESERTION_TYPE_LEAVE_QUEUE);
+ CharacterDatabase.Execute(stmt);
+ }
}
}
@@ -741,7 +751,7 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPacket& recvData)
member->GetSession()->SendPacket(&data);
sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err);
member->GetSession()->SendPacket(&data);
- TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, member->GetGUIDLow(), member->GetName().c_str());
+ TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, member->GetGUID().GetCounter(), member->GetName().c_str());
}
}
else
@@ -754,7 +764,7 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPacket& recvData)
// send status packet (in queue)
sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype, 0);
SendPacket(&data);
- TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, _player->GetGUIDLow(), _player->GetName().c_str());
+ TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, _player->GetGUID().GetCounter(), _player->GetName().c_str());
}
sBattlegroundMgr->ScheduleQueueUpdate(matchmakerRating, arenatype, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId());
}
diff --git a/src/server/game/Handlers/CalendarHandler.cpp b/src/server/game/Handlers/CalendarHandler.cpp
index 0cd170dfba7..e9b3bea5991 100644
--- a/src/server/game/Handlers/CalendarHandler.cpp
+++ b/src/server/game/Handlers/CalendarHandler.cpp
@@ -447,7 +447,7 @@ void WorldSession::HandleCalendarEventInvite(WorldPacket& recvData)
if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
{
Field* fields = result->Fetch();
- inviteeGuid = ObjectGuid(HIGHGUID_PLAYER, fields[0].GetUInt32());
+ inviteeGuid = ObjectGuid(HighGuid::Player, fields[0].GetUInt32());
inviteeTeam = Player::TeamForRace(fields[1].GetUInt8());
inviteeGuildId = Player::GetGuildIdFromDB(inviteeGuid);
}
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 9cb9077c5ff..60ec60443d6 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -36,10 +36,10 @@
#include "PlayerDump.h"
#include "Player.h"
#include "ReputationMgr.h"
+#include "GitRevision.h"
#include "ScriptMgr.h"
#include "SharedDefines.h"
#include "SocialMgr.h"
-#include "SystemConfig.h"
#include "UpdateMask.h"
#include "Util.h"
#include "World.h"
@@ -65,7 +65,7 @@ bool LoginQueryHolder::Initialize()
SetSize(MAX_PLAYER_LOGIN_QUERY);
bool res = true;
- uint32 lowGuid = m_guid.GetCounter();
+ ObjectGuid::LowType lowGuid = m_guid.GetCounter();
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER);
stmt->setUInt32(0, lowGuid);
@@ -203,6 +203,10 @@ bool LoginQueryHolder::Initialize()
stmt->setUInt32(0, m_accountId);
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_INSTANCE_LOCK_TIMES, stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CORPSE_LOCATION);
+ stmt->setUInt64(0, lowGuid);
+ res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_CORPSE_LOCATION, stmt);
+
return res;
}
@@ -219,7 +223,7 @@ void WorldSession::HandleCharEnum(PreparedQueryResult result)
{
do
{
- ObjectGuid guid(HIGHGUID_PLAYER, (*result)[0].GetUInt32());
+ ObjectGuid guid(HighGuid::Player, (*result)[0].GetUInt32());
TC_LOG_INFO("network", "Loading %s from account %u.", guid.ToString().c_str(), GetAccountId());
if (Player::BuildEnumData(result, &data))
{
@@ -227,8 +231,8 @@ void WorldSession::HandleCharEnum(PreparedQueryResult result)
if (!(*result)[20].GetUInt32())
_legitCharacters.insert(guid);
- if (!sWorld->HasCharacterNameData(guid)) // This can happen if characters are inserted into the database manually. Core hasn't loaded name data yet.
- sWorld->AddCharacterNameData(guid, (*result)[1].GetString(), (*result)[4].GetUInt8(), (*result)[2].GetUInt8(), (*result)[3].GetUInt8(), (*result)[7].GetUInt8());
+ if (!sWorld->HasCharacterInfo(guid)) // This can happen if characters are inserted into the database manually. Core hasn't loaded name data yet.
+ sWorld->AddCharacterInfo(guid, GetAccountId(), (*result)[1].GetString(), (*result)[4].GetUInt8(), (*result)[2].GetUInt8(), (*result)[3].GetUInt8(), (*result)[7].GetUInt8());
++num;
}
}
@@ -359,7 +363,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
}
// check name limitations
- ResponseCodes res = ObjectMgr::CheckPlayerName(createInfo.Name, true);
+ ResponseCodes res = ObjectMgr::CheckPlayerName(createInfo.Name, GetSessionDbcLocale(), true);
if (res != CHAR_NAME_SUCCESS)
{
SendCharCreate(res);
@@ -429,14 +433,11 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
}
case 1:
{
- uint16 acctCharCount = 0;
+ uint64 acctCharCount = 0;
if (result)
{
Field* fields = result->Fetch();
- // SELECT SUM(x) is MYSQL_TYPE_NEWDECIMAL - needs to be read as string
- const char* ch = fields[0].GetCString();
- if (ch)
- acctCharCount = atoi(ch);
+ acctCharCount = uint64(fields[0].GetDouble());
}
if (acctCharCount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_ACCOUNT))
@@ -601,7 +602,8 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
Player newChar(this);
newChar.GetMotionMaster()->Initialize();
- if (!newChar.Create(sObjectMgr->GenerateLowGuid(HIGHGUID_PLAYER), createInfo))
+ if (!newChar.Create(sObjectMgr->GetGenerator<HighGuid::Player>().Generate(), createInfo))
+
{
// Player not create (race/class/etc problem?)
newChar.CleanupsBeforeDelete();
@@ -638,9 +640,9 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
SendCharCreate(CHAR_CREATE_SUCCESS);
- TC_LOG_INFO("entities.player.character", "Account: %d (IP: %s) Create Character:[%s] (GUID: %u)", GetAccountId(), GetRemoteAddress().c_str(), createInfo->Name.c_str(), newChar.GetGUIDLow());
+ TC_LOG_INFO("entities.player.character", "Account: %d (IP: %s) Create Character:[%s] (GUID: %u)", GetAccountId(), GetRemoteAddress().c_str(), createInfo->Name.c_str(), newChar.GetGUID().GetCounter());
sScriptMgr->OnPlayerCreate(&newChar);
- sWorld->AddCharacterNameData(newChar.GetGUID(), newChar.GetName(), newChar.getGender(), newChar.getRace(), newChar.getClass(), newChar.getLevel());
+ sWorld->AddCharacterInfo(newChar.GetGUID(), GetAccountId(), newChar.GetName(), newChar.GetByteValue(PLAYER_BYTES_3, 0), newChar.getRace(), newChar.getClass(), newChar.getLevel());
newChar.CleanupsBeforeDelete();
delete createInfo;
@@ -827,12 +829,12 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
// send server info
if (sWorld->getIntConfig(CONFIG_ENABLE_SINFO_LOGIN) == 1)
- chH.PSendSysMessage(_FULLVERSION);
+ chH.PSendSysMessage(GitRevision::GetFullVersion());
TC_LOG_DEBUG("network", "WORLD: Sent server info");
}
- //QueryResult* result = CharacterDatabase.PQuery("SELECT guildid, rank FROM guild_member WHERE guid = '%u'", pCurrChar->GetGUIDLow());
+ //QueryResult* result = CharacterDatabase.PQuery("SELECT guildid, rank FROM guild_member WHERE guid = '%u'", pCurrChar->GetGUID().GetCounter());
if (PreparedQueryResult resultGuild = holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GUILD))
{
Field* fields = resultGuild->Fetch();
@@ -852,7 +854,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
else
{
// remove wrong guild data
- TC_LOG_ERROR("network", "Player %s (GUID: %u) marked as member of not existing guild (id: %u), removing guild membership for player.", pCurrChar->GetName().c_str(), pCurrChar->GetGUIDLow(), pCurrChar->GetGuildId());
+ TC_LOG_ERROR("network", "Player %s (GUID: %u) marked as member of not existing guild (id: %u), removing guild membership for player.", pCurrChar->GetName().c_str(), pCurrChar->GetGUID().GetCounter(), pCurrChar->GetGuildId());
pCurrChar->SetInGuild(0);
}
}
@@ -882,7 +884,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
}
}
- if (!pCurrChar->GetMap()->AddPlayerToMap(pCurrChar) || !pCurrChar->CheckInstanceLoginValid())
+ if (!pCurrChar->GetMap()->AddPlayerToMap(pCurrChar))
{
AreaTrigger const* at = sObjectMgr->GetGoBackTrigger(pCurrChar->GetMapId());
if (at)
@@ -891,14 +893,14 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
pCurrChar->TeleportTo(pCurrChar->m_homebindMapId, pCurrChar->m_homebindX, pCurrChar->m_homebindY, pCurrChar->m_homebindZ, pCurrChar->GetOrientation());
}
- sObjectAccessor->AddObject(pCurrChar);
+ ObjectAccessor::AddObject(pCurrChar);
//TC_LOG_DEBUG("Player %s added to Map.", pCurrChar->GetName().c_str());
pCurrChar->SendInitialPacketsAfterAddToMap();
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_ONLINE);
- stmt->setUInt32(0, pCurrChar->GetGUIDLow());
+ stmt->setUInt32(0, pCurrChar->GetGUID().GetCounter());
CharacterDatabase.Execute(stmt);
@@ -919,10 +921,10 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
}
// friend status
- sSocialMgr->SendFriendStatus(pCurrChar, FRIEND_ONLINE, pCurrChar->GetGUIDLow(), true);
+ sSocialMgr->SendFriendStatus(pCurrChar, FRIEND_ONLINE, pCurrChar->GetGUID().GetCounter(), true);
// Place character in world (and load zone) before some object loading
- pCurrChar->LoadCorpse();
+ pCurrChar->LoadCorpse(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_CORPSE_LOCATION));
// setting Ghost+speed if dead
if (pCurrChar->m_deathState != ALIVE)
@@ -981,7 +983,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
std::string IP_str = GetRemoteAddress();
TC_LOG_INFO("entities.player.character", "Account: %d (IP: %s) Login Character:[%s] (GUID: %u) Level: %d",
- GetAccountId(), IP_str.c_str(), pCurrChar->GetName().c_str(), pCurrChar->GetGUIDLow(), pCurrChar->getLevel());
+ GetAccountId(), IP_str.c_str(), pCurrChar->GetName().c_str(), pCurrChar->GetGUID().GetCounter(), pCurrChar->getLevel());
if (!pCurrChar->IsStandState() && !pCurrChar->HasUnitState(UNIT_STATE_STUNNED))
pCurrChar->SetStandState(UNIT_STAND_STATE_STAND);
@@ -1090,7 +1092,7 @@ void WorldSession::HandleCharRenameOpcode(WorldPacket& recvData)
return;
}
- ResponseCodes res = ObjectMgr::CheckPlayerName(renameInfo.Name, true);
+ ResponseCodes res = ObjectMgr::CheckPlayerName(renameInfo.Name, GetSessionDbcLocale(), true);
if (res != CHAR_NAME_SUCCESS)
{
SendCharRename(res, renameInfo);
@@ -1129,7 +1131,7 @@ void WorldSession::HandleChangePlayerNameOpcodeCallBack(PreparedQueryResult resu
Field* fields = result->Fetch();
- uint32 guidLow = fields[0].GetUInt32();
+ ObjectGuid::LowType guidLow = fields[0].GetUInt32();
std::string oldName = fields[1].GetString();
// Update name and at_login flag in the db
@@ -1152,7 +1154,7 @@ void WorldSession::HandleChangePlayerNameOpcodeCallBack(PreparedQueryResult resu
SendCharRename(RESPONSE_SUCCESS, *renameInfo);
- sWorld->UpdateCharacterNameData(renameInfo->Guid, renameInfo->Name);
+ sWorld->UpdateCharacterInfo(renameInfo->Guid, renameInfo->Name);
}
void WorldSession::HandleSetPlayerDeclinedNames(WorldPacket& recvData)
@@ -1240,20 +1242,20 @@ void WorldSession::HandleAlterAppearance(WorldPacket& recvData)
BarberShopStyleEntry const* bs_hair = sBarberShopStyleStore.LookupEntry(Hair);
- if (!bs_hair || bs_hair->type != 0 || bs_hair->race != _player->getRace() || bs_hair->gender != _player->getGender())
+ if (!bs_hair || bs_hair->type != 0 || bs_hair->race != _player->getRace() || bs_hair->gender != _player->GetByteValue(PLAYER_BYTES_3, 0))
return;
BarberShopStyleEntry const* bs_facialHair = sBarberShopStyleStore.LookupEntry(FacialHair);
- if (!bs_facialHair || bs_facialHair->type != 2 || bs_facialHair->race != _player->getRace() || bs_facialHair->gender != _player->getGender())
+ if (!bs_facialHair || bs_facialHair->type != 2 || bs_facialHair->race != _player->getRace() || bs_facialHair->gender != _player->GetByteValue(PLAYER_BYTES_3, 0))
return;
BarberShopStyleEntry const* bs_skinColor = sBarberShopStyleStore.LookupEntry(SkinColor);
- if (bs_skinColor && (bs_skinColor->type != 3 || bs_skinColor->race != _player->getRace() || bs_skinColor->gender != _player->getGender()))
+ if (bs_skinColor && (bs_skinColor->type != 3 || bs_skinColor->race != _player->getRace() || bs_skinColor->gender != _player->GetByteValue(PLAYER_BYTES_3, 0)))
return;
- if (!Player::ValidateAppearance(_player->getRace(), _player->getClass(), _player->getGender(), bs_hair->hair_id, Color, _player->GetByteValue(PLAYER_BYTES, 1), bs_facialHair->hair_id, bs_skinColor ? bs_skinColor->hair_id : _player->GetByteValue(PLAYER_BYTES, 0)))
+ if (!Player::ValidateAppearance(_player->getRace(), _player->getClass(), _player->GetByteValue(PLAYER_BYTES_3, 0), bs_hair->hair_id, Color, _player->GetByteValue(PLAYER_BYTES, 1), bs_facialHair->hair_id, bs_skinColor ? bs_skinColor->hair_id : _player->GetByteValue(PLAYER_BYTES, 0)))
return;
GameObject* go = _player->FindNearestGameObjectOfType(GAMEOBJECT_TYPE_BARBER_CHAIR, 5.0f);
@@ -1389,7 +1391,7 @@ void WorldSession::HandleCharCustomize(WorldPacket& recvData)
return;
}
- ResponseCodes res = ObjectMgr::CheckPlayerName(customizeInfo.Name, true);
+ ResponseCodes res = ObjectMgr::CheckPlayerName(customizeInfo.Name, GetSessionDbcLocale(), true);
if (res != CHAR_NAME_SUCCESS)
{
SendCharCustomize(res, customizeInfo);
@@ -1442,7 +1444,7 @@ void WorldSession::HandleCharCustomize(WorldPacket& recvData)
CharacterDatabase.CommitTransaction(trans);
- sWorld->UpdateCharacterNameData(customizeInfo.Guid, customizeInfo.Name, customizeInfo.Gender);
+ sWorld->UpdateCharacterInfo(customizeInfo.Guid, customizeInfo.Name, customizeInfo.Gender);
SendCharCustomize(RESPONSE_SUCCESS, customizeInfo);
}
@@ -1588,19 +1590,19 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
>> factionChangeInfo.Face
>> factionChangeInfo.Race;
- uint32 lowGuid = factionChangeInfo.Guid.GetCounter();
+ ObjectGuid::LowType lowGuid = factionChangeInfo.Guid.GetCounter();
// get the players old (at this moment current) race
- CharacterNameData const* nameData = sWorld->GetCharacterNameData(factionChangeInfo.Guid);
+ CharacterInfo const* nameData = sWorld->GetCharacterInfo(factionChangeInfo.Guid);
if (!nameData)
{
SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo);
return;
}
- uint8 oldRace = nameData->m_race;
- uint8 playerClass = nameData->m_class;
- uint8 level = nameData->m_level;
+ uint8 oldRace = nameData->Race;
+ uint8 playerClass = nameData->Class;
+ uint8 level = nameData->Level;
// TO Do: Make async
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_AT_LOGIN_TITLES);
@@ -1647,7 +1649,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
return;
}
- ResponseCodes res = ObjectMgr::CheckPlayerName(factionChangeInfo.Name, true);
+ ResponseCodes res = ObjectMgr::CheckPlayerName(factionChangeInfo.Name, GetSessionDbcLocale(), true);
if (res != CHAR_NAME_SUCCESS)
{
SendCharFactionChange(res, factionChangeInfo);
@@ -1671,11 +1673,11 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
}
}
- // resurrect the character in case he's dead
- sObjectAccessor->ConvertCorpseForPlayer(factionChangeInfo.Guid);
-
SQLTransaction trans = CharacterDatabase.BeginTransaction();
+ // resurrect the character in case he's dead
+ Player::OfflineResurrect(factionChangeInfo.Guid, trans);
+
CharacterDatabase.EscapeString(factionChangeInfo.Name);
Player::Customize(&factionChangeInfo, trans);
@@ -1690,7 +1692,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
stmt->setUInt32(0, lowGuid);
trans->Append(stmt);
- sWorld->UpdateCharacterNameData(factionChangeInfo.Guid, factionChangeInfo.Name, factionChangeInfo.Gender, factionChangeInfo.Race);
+ sWorld->UpdateCharacterInfo(factionChangeInfo.Guid, factionChangeInfo.Name, factionChangeInfo.Gender, factionChangeInfo.Race);
if (oldRace != factionChangeInfo.Race)
{
@@ -1819,6 +1821,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
trans->Append(stmt);
}
+ /// @todo: make this part async
if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD))
{
// Reset guild
@@ -1942,7 +1945,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
{
Quest const* quest = iter->second;
uint32 newRaceMask = (team == TEAM_ALLIANCE) ? RACEMASK_ALLIANCE : RACEMASK_HORDE;
- if (!(quest->GetRequiredRaces() & newRaceMask))
+ if (!(quest->GetAllowableRaces() & newRaceMask))
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_QUESTSTATUS_REWARDED_ACTIVE_BY_QUEST);
stmt->setUInt32(0, lowGuid);
@@ -1983,9 +1986,9 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
stmt->setUInt32(0, oldReputation);
stmt->setUInt32(1, lowGuid);
- if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
+ if (PreparedQueryResult reputationResult = CharacterDatabase.Query(stmt))
{
- Field* fields = result->Fetch();
+ fields = reputationResult->Fetch();
int32 oldDBRep = fields[0].GetInt32();
FactionEntry const* factionEntry = sFactionStore.LookupEntry(oldReputation);
diff --git a/src/server/game/Handlers/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp
index 2acbaba1f67..e13b417215b 100644
--- a/src/server/game/Handlers/ChatHandler.cpp
+++ b/src/server/game/Handlers/ChatHandler.cpp
@@ -115,7 +115,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
break;
default:
TC_LOG_ERROR("network", "Player %s (GUID: %u) sent a chatmessage with an invalid language/message type combination",
- GetPlayer()->GetName().c_str(), GetPlayer()->GetGUIDLow());
+ GetPlayer()->GetName().c_str(), GetPlayer()->GetGUID().GetCounter());
recvData.rfinish();
return;
@@ -226,7 +226,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
if (sWorld->getIntConfig(CONFIG_CHAT_STRICT_LINK_CHECKING_SEVERITY) && !ChatHandler(this).isValidChatMessage(msg.c_str()))
{
TC_LOG_ERROR("network", "Player %s (GUID: %u) sent a chatmessage with an invalid link: %s", GetPlayer()->GetName().c_str(),
- GetPlayer()->GetGUIDLow(), msg.c_str());
+ GetPlayer()->GetGUID().GetCounter(), msg.c_str());
if (sWorld->getIntConfig(CONFIG_CHAT_STRICT_LINK_CHECKING_KICK))
KickPlayer();
diff --git a/src/server/game/Handlers/CombatHandler.cpp b/src/server/game/Handlers/CombatHandler.cpp
index 39ba593c8d9..78aeaa1b41b 100644
--- a/src/server/game/Handlers/CombatHandler.cpp
+++ b/src/server/game/Handlers/CombatHandler.cpp
@@ -24,7 +24,6 @@
#include "CreatureAI.h"
#include "Vehicle.h"
#include "Player.h"
-#include "Opcodes.h"
void WorldSession::HandleAttackSwingOpcode(WorldPacket& recvData)
{
@@ -76,7 +75,7 @@ void WorldSession::HandleSetSheathedOpcode(WorldPacket& recvData)
uint32 sheathed;
recvData >> sheathed;
- //TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_SETSHEATHED Message guidlow:%u value1:%u", GetPlayer()->GetGUIDLow(), sheathed);
+ //TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_SETSHEATHED Message guidlow:%u value1:%u", GetPlayer()->GetGUID().GetCounter(), sheathed);
if (sheathed >= MAX_SHEATH_STATE)
{
diff --git a/src/server/game/Handlers/DuelHandler.cpp b/src/server/game/Handlers/DuelHandler.cpp
index 954fb66a9db..2f39a91afbe 100644
--- a/src/server/game/Handlers/DuelHandler.cpp
+++ b/src/server/game/Handlers/DuelHandler.cpp
@@ -40,8 +40,8 @@ void WorldSession::HandleDuelAcceptedOpcode(WorldPacket& recvPacket)
return;
//TC_LOG_DEBUG("network", "WORLD: Received CMSG_DUEL_ACCEPTED");
- TC_LOG_DEBUG("network", "Player 1 is: %u (%s)", player->GetGUIDLow(), player->GetName().c_str());
- TC_LOG_DEBUG("network", "Player 2 is: %u (%s)", plTarget->GetGUIDLow(), plTarget->GetName().c_str());
+ TC_LOG_DEBUG("network", "Player 1 is: %u (%s)", player->GetGUID().GetCounter(), player->GetName().c_str());
+ TC_LOG_DEBUG("network", "Player 2 is: %u (%s)", plTarget->GetGUID().GetCounter(), plTarget->GetName().c_str());
time_t now = time(NULL);
player->duel->startTimer = now;
diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp
index 9d6359c56e9..9f225df8427 100644
--- a/src/server/game/Handlers/GroupHandler.cpp
+++ b/src/server/game/Handlers/GroupHandler.cpp
@@ -22,7 +22,6 @@
#include "GroupMgr.h"
#include "Log.h"
#include "ObjectMgr.h"
-#include "Opcodes.h"
#include "Pet.h"
#include "Player.h"
#include "SocialMgr.h"
@@ -108,7 +107,7 @@ void WorldSession::HandleGroupInviteOpcode(WorldPacket& recvData)
return;
}
- if (player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow()))
+ if (player->GetSocial()->HasIgnore(GetPlayer()->GetGUID().GetCounter()))
{
SendPartyResult(PARTY_OP_INVITE, membername, ERR_IGNORING_YOU_S);
return;
@@ -211,7 +210,7 @@ void WorldSession::HandleGroupAcceptOpcode(WorldPacket& recvData)
if (group->GetLeaderGUID() == GetPlayer()->GetGUID())
{
- TC_LOG_ERROR("network", "HandleGroupAcceptOpcode: player %s(%d) tried to accept an invite to his own group", GetPlayer()->GetName().c_str(), GetPlayer()->GetGUIDLow());
+ TC_LOG_ERROR("network", "HandleGroupAcceptOpcode: player %s(%d) tried to accept an invite to his own group", GetPlayer()->GetName().c_str(), GetPlayer()->GetGUID().GetCounter());
return;
}
@@ -284,7 +283,7 @@ void WorldSession::HandleGroupUninviteGuidOpcode(WorldPacket& recvData)
if (guid == GetPlayer()->GetGUID())
{
TC_LOG_ERROR("network", "WorldSession::HandleGroupUninviteGuidOpcode: leader %s(%d) tried to uninvite himself from the group.",
- GetPlayer()->GetName().c_str(), GetPlayer()->GetGUIDLow());
+ GetPlayer()->GetName().c_str(), GetPlayer()->GetGUID().GetCounter());
return;
}
@@ -329,7 +328,7 @@ void WorldSession::HandleGroupUninviteOpcode(WorldPacket& recvData)
if (GetPlayer()->GetName() == membername)
{
TC_LOG_ERROR("network", "WorldSession::HandleGroupUninviteOpcode: leader %s(%d) tried to uninvite himself from the group.",
- GetPlayer()->GetName().c_str(), GetPlayer()->GetGUIDLow());
+ GetPlayer()->GetName().c_str(), GetPlayer()->GetGUID().GetCounter());
return;
}
@@ -992,7 +991,7 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket &recvData)
data.put<uint64>(maskPos, auraMask); // GROUP_UPDATE_FLAG_AURAS
if (updateFlags & GROUP_UPDATE_FLAG_PET_GUID)
- data << uint64(pet->GetGUID());
+ data << uint64(ASSERT_NOTNULL(pet)->GetGUID());
data << std::string(pet ? pet->GetName() : ""); // GROUP_UPDATE_FLAG_PET_NAME
data << uint16(pet ? pet->GetDisplayId() : 0); // GROUP_UPDATE_FLAG_PET_MODEL_ID
diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp
index 672e1c69920..b1f46c381bf 100644
--- a/src/server/game/Handlers/ItemHandler.cpp
+++ b/src/server/game/Handlers/ItemHandler.cpp
@@ -786,8 +786,7 @@ void WorldSession::SendListInventory(ObjectGuid vendorGuid)
if (!_player->IsGameMaster() && !leftInStock)
continue;
- ConditionList conditions = sConditionMgr->GetConditionsForNpcVendorEvent(vendor->GetEntry(), item->item);
- if (!sConditionMgr->IsObjectMeetToConditions(_player, vendor, conditions))
+ if (!sConditionMgr->IsObjectMeetingVendorItemConditions(vendor->GetEntry(), item->item, _player, vendor))
{
TC_LOG_DEBUG("condition", "SendListInventory: conditions not met for creature entry %u item %u", vendor->GetEntry(), item->item);
continue;
@@ -1157,7 +1156,7 @@ void WorldSession::HandleWrapItemOpcode(WorldPacket& recvData)
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_GIFT);
stmt->setUInt32(0, item->GetOwnerGUID().GetCounter());
- stmt->setUInt32(1, item->GetGUIDLow());
+ stmt->setUInt32(1, item->GetGUID().GetCounter());
stmt->setUInt32(2, item->GetEntry());
stmt->setUInt32(3, item->GetUInt32Value(ITEM_FIELD_FLAGS));
trans->Append(stmt);
diff --git a/src/server/game/Handlers/LootHandler.cpp b/src/server/game/Handlers/LootHandler.cpp
index b4f19234df9..9876e939395 100644
--- a/src/server/game/Handlers/LootHandler.cpp
+++ b/src/server/game/Handlers/LootHandler.cpp
@@ -25,9 +25,7 @@
#include "LootMgr.h"
#include "ObjectAccessor.h"
#include "Object.h"
-#include "Opcodes.h"
#include "Player.h"
-#include "World.h"
#include "WorldPacket.h"
#include "WorldSession.h"
@@ -112,7 +110,7 @@ void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recvData*/)
switch (guid.GetHigh())
{
- case HIGHGUID_GAMEOBJECT:
+ case HighGuid::GameObject:
{
GameObject* go = GetPlayer()->GetMap()->GetGameObject(guid);
@@ -122,7 +120,7 @@ void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recvData*/)
break;
}
- case HIGHGUID_CORPSE: // remove insignia ONLY in BG
+ case HighGuid::Corpse: // remove insignia ONLY in BG
{
Corpse* bones = ObjectAccessor::GetCorpse(*player, guid);
@@ -134,7 +132,7 @@ void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recvData*/)
break;
}
- case HIGHGUID_ITEM:
+ case HighGuid::Item:
{
if (Item* item = player->GetItemByGuid(guid))
{
@@ -143,8 +141,8 @@ void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recvData*/)
}
break;
}
- case HIGHGUID_UNIT:
- case HIGHGUID_VEHICLE:
+ case HighGuid::Unit:
+ case HighGuid::Vehicle:
{
Creature* creature = player->GetMap()->GetCreature(guid);
bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->loot.loot_type == LOOT_PICKPOCKETING);
@@ -176,7 +174,7 @@ void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recvData*/)
if (!member)
continue;
- if (player->IsWithinDistInMap(member, sWorld->getFloatConfig(CONFIG_GROUP_XP_DISTANCE), false))
+ if (player->IsAtGroupRewardDistance(member))
playersNear.push_back(member);
}
diff --git a/src/server/game/Handlers/MailHandler.cpp b/src/server/game/Handlers/MailHandler.cpp
index d55af4bac35..5f25f57addd 100644
--- a/src/server/game/Handlers/MailHandler.cpp
+++ b/src/server/game/Handlers/MailHandler.cpp
@@ -110,7 +110,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
{
TC_LOG_INFO("network", "Player %u is sending mail to %s (GUID: not existed!) with subject %s "
"and body %s includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u",
- player->GetGUIDLow(), receiverName.c_str(), subject.c_str(), body.c_str(),
+ player->GetGUID().GetCounter(), receiverName.c_str(), subject.c_str(), body.c_str(),
items_count, money, COD, stationery, package);
player->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_NOT_FOUND);
return;
@@ -118,7 +118,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
TC_LOG_INFO("network", "Player %u is sending mail to %s (%s) with subject %s and body %s "
"includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u",
- player->GetGUIDLow(), receiverName.c_str(), receiverGuid.ToString().c_str(), subject.c_str(),
+ player->GetGUID().GetCounter(), receiverName.c_str(), receiverGuid.ToString().c_str(), subject.c_str(),
body.c_str(), items_count, money, COD, stationery, package);
if (player->GetGUID() == receiverGuid)
@@ -293,7 +293,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
if (log)
{
sLog->outCommand(GetAccountId(), "GM %s (GUID: %u) (Account: %u) mail item: %s (Entry: %u Count: %u) "
- "to: %s (%s) (Account: %u)", GetPlayerName().c_str(), GetGuidLow(), GetAccountId(),
+ "to: %s (%s) (Account: %u)", GetPlayerName().c_str(), GetGUIDLow(), GetAccountId(),
item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetCount(),
receiverName.c_str(), receiverGuid.ToString().c_str(), receiverAccountId);
}
@@ -315,7 +315,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
if (log && money > 0)
{
sLog->outCommand(GetAccountId(), "GM %s (GUID: %u) (Account: %u) mail money: %u to: %s (%s) (Account: %u)",
- GetPlayerName().c_str(), GetGuidLow(), GetAccountId(), money, receiverName.c_str(), receiverGuid.ToString().c_str(), receiverAccountId);
+ GetPlayerName().c_str(), GetGUIDLow(), GetAccountId(), money, receiverName.c_str(), receiverGuid.ToString().c_str(), receiverAccountId);
}
}
@@ -499,7 +499,7 @@ void WorldSession::HandleMailTakeItem(WorldPacket& recvData)
if (m->COD > 0) //if there is COD, take COD money from player and send them to sender by mail
{
- ObjectGuid sender_guid(HIGHGUID_PLAYER, m->sender);
+ ObjectGuid sender_guid(HighGuid::Player, m->sender);
Player* receiver = ObjectAccessor::FindConnectedPlayer(sender_guid);
uint32 sender_accId = 0;
@@ -539,7 +539,7 @@ void WorldSession::HandleMailTakeItem(WorldPacket& recvData)
m->COD = 0;
m->state = MAIL_STATE_CHANGED;
player->m_mailsUpdated = true;
- player->RemoveMItem(it->GetGUIDLow());
+ player->RemoveMItem(it->GetGUID().GetCounter());
uint32 count = it->GetCount(); // save counts before store and possible merge with deleting
it->SetState(ITEM_UNCHANGED); // need to set this state, otherwise item cannot be removed later, if neccessary
@@ -649,7 +649,7 @@ void WorldSession::HandleGetMailList(WorldPacket& recvData)
switch ((*itr)->messageType)
{
case MAIL_NORMAL: // sender guid
- data << ObjectGuid(HIGHGUID_PLAYER, (*itr)->sender);
+ data << ObjectGuid(HighGuid::Player, (*itr)->sender);
break;
case MAIL_CREATURE:
case MAIL_GAMEOBJECT:
@@ -676,7 +676,7 @@ void WorldSession::HandleGetMailList(WorldPacket& recvData)
// item index (0-6?)
data << uint8(i);
// item guid low?
- data << uint32((item ? item->GetGUIDLow() : 0));
+ data << uint32((item ? item->GetGUID().GetCounter() : 0));
// entry
data << uint32((item ? item->GetEntry() : 0));
for (uint8 j = 0; j < MAX_INSPECTED_ENCHANTMENT_SLOT; ++j)
@@ -735,7 +735,7 @@ void WorldSession::HandleMailCreateTextItem(WorldPacket& recvData)
}
Item* bodyItem = new Item; // This is not bag and then can be used new Item.
- if (!bodyItem->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_ITEM), MAIL_BODY_ITEM_TEMPLATE, player))
+ if (!bodyItem->Create(sObjectMgr->GetGenerator<HighGuid::Item>().Generate(), MAIL_BODY_ITEM_TEMPLATE, player))
{
delete bodyItem;
return;
@@ -757,7 +757,7 @@ void WorldSession::HandleMailCreateTextItem(WorldPacket& recvData)
bodyItem->SetText(m->body);
if (m->messageType == MAIL_NORMAL)
- bodyItem->SetGuidValue(ITEM_FIELD_CREATOR, ObjectGuid(HIGHGUID_PLAYER, m->sender));
+ bodyItem->SetGuidValue(ITEM_FIELD_CREATOR, ObjectGuid(HighGuid::Player, m->sender));
bodyItem->SetFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_MAIL_TEXT_MASK);
@@ -812,7 +812,7 @@ void WorldSession::HandleQueryNextMailTime(WorldPacket & /*recvData*/)
if (sentSenders.count(m->sender))
continue;
- data << uint64(m->messageType == MAIL_NORMAL ? ObjectGuid(HIGHGUID_PLAYER, m->sender) : ObjectGuid::Empty); // player guid
+ data << uint64(m->messageType == MAIL_NORMAL ? ObjectGuid(HighGuid::Player, m->sender) : ObjectGuid::Empty); // player guid
data << uint32(m->messageType != MAIL_NORMAL ? m->sender : 0); // non-player entries
data << uint32(m->messageType);
data << uint32(m->stationery);
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index 7b8ce80ccd7..6dcd3242a6c 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -28,7 +28,6 @@
#include "ObjectMgr.h"
#include "GuildMgr.h"
#include "WorldSession.h"
-#include "LootMgr.h"
#include "Chat.h"
#include "zlib.h"
#include "ObjectAccessor.h"
@@ -37,7 +36,6 @@
#include "OutdoorPvP.h"
#include "SocialMgr.h"
#include "AccountMgr.h"
-#include "CreatureAI.h"
#include "DBCEnums.h"
#include "ScriptMgr.h"
#include "MapManager.h"
@@ -68,7 +66,7 @@ void WorldSession::HandleRepopRequestOpcode(WorldPacket& recvData)
if (GetPlayer()->getDeathState() == JUST_DIED)
{
TC_LOG_DEBUG("network", "HandleRepopRequestOpcode: got request after player %s(%d) was killed and before he was updated",
- GetPlayer()->GetName().c_str(), GetPlayer()->GetGUIDLow());
+ GetPlayer()->GetName().c_str(), GetPlayer()->GetGUID().GetCounter());
GetPlayer()->KillPlayer();
}
@@ -285,7 +283,7 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recvData)
continue;
uint32 pzoneid = target->GetZoneId();
- uint8 gender = target->getGender();
+ uint8 gender = target->GetByteValue(PLAYER_BYTES_3, 0);
bool z_show = true;
for (uint32 i = 0; i < zones_count; ++i)
@@ -566,7 +564,7 @@ void WorldSession::HandleAddFriendOpcodeCallBack(PreparedQueryResult result, std
{
Field* fields = result->Fetch();
- friendGuid = ObjectGuid(HIGHGUID_PLAYER, 0, fields[0].GetUInt32());
+ friendGuid = ObjectGuid(HighGuid::Player, 0, fields[0].GetUInt32());
team = Player::TeamForRace(fields[1].GetUInt8());
friendAccountId = fields[2].GetUInt32();
@@ -651,7 +649,7 @@ void WorldSession::HandleAddIgnoreOpcodeCallBack(PreparedQueryResult result)
if (result)
{
- IgnoreGuid = ObjectGuid(HIGHGUID_PLAYER, (*result)[0].GetUInt32());
+ IgnoreGuid = ObjectGuid(HighGuid::Player, (*result)[0].GetUInt32());
if (IgnoreGuid)
{
@@ -743,7 +741,6 @@ void WorldSession::HandleReclaimCorpseOpcode(WorldPacket& recvData)
return;
Corpse* corpse = _player->GetCorpse();
-
if (!corpse)
return;
@@ -813,7 +810,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket& recvData)
if (player->IsInFlight())
{
TC_LOG_DEBUG("network", "HandleAreaTriggerOpcode: Player '%s' (GUID: %u) in flight, ignore Area Trigger ID:%u",
- player->GetName().c_str(), player->GetGUIDLow(), triggerId);
+ player->GetName().c_str(), player->GetGUID().GetCounter(), triggerId);
return;
}
@@ -821,63 +818,17 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket& recvData)
if (!atEntry)
{
TC_LOG_DEBUG("network", "HandleAreaTriggerOpcode: Player '%s' (GUID: %u) send unknown (by DBC) Area Trigger ID:%u",
- player->GetName().c_str(), player->GetGUIDLow(), triggerId);
+ player->GetName().c_str(), player->GetGUID().GetCounter(), triggerId);
return;
}
- if (player->GetMapId() != atEntry->mapid)
+ if (!player->IsInAreaTriggerRadius(atEntry))
{
- TC_LOG_DEBUG("network", "HandleAreaTriggerOpcode: Player '%s' (GUID: %u) too far (trigger map: %u player map: %u), ignore Area Trigger ID: %u",
- player->GetName().c_str(), atEntry->mapid, player->GetMapId(), player->GetGUIDLow(), triggerId);
+ TC_LOG_DEBUG("network", "HandleAreaTriggerOpcode: Player '%s' (GUID: %u) too far, ignore Area Trigger ID: %u",
+ player->GetName().c_str(), player->GetGUID().GetCounter(), triggerId);
return;
}
- // delta is safe radius
- const float delta = 5.0f;
-
- if (atEntry->radius > 0)
- {
- // if we have radius check it
- float dist = player->GetDistance(atEntry->x, atEntry->y, atEntry->z);
- if (dist > atEntry->radius + delta)
- {
- TC_LOG_DEBUG("network", "HandleAreaTriggerOpcode: Player '%s' (GUID: %u) too far (radius: %f distance: %f), ignore Area Trigger ID: %u",
- player->GetName().c_str(), player->GetGUIDLow(), atEntry->radius, dist, triggerId);
- return;
- }
- }
- else
- {
- // we have only extent
-
- // rotate the players position instead of rotating the whole cube, that way we can make a simplified
- // is-in-cube check and we have to calculate only one point instead of 4
-
- // 2PI = 360°, keep in mind that ingame orientation is counter-clockwise
- double rotation = 2 * M_PI - atEntry->box_orientation;
- double sinVal = std::sin(rotation);
- double cosVal = std::cos(rotation);
-
- float playerBoxDistX = player->GetPositionX() - atEntry->x;
- float playerBoxDistY = player->GetPositionY() - atEntry->y;
-
- float rotPlayerX = float(atEntry->x + playerBoxDistX * cosVal - playerBoxDistY*sinVal);
- float rotPlayerY = float(atEntry->y + playerBoxDistY * cosVal + playerBoxDistX*sinVal);
-
- // box edges are parallel to coordiante axis, so we can treat every dimension independently :D
- float dz = player->GetPositionZ() - atEntry->z;
- float dx = rotPlayerX - atEntry->x;
- float dy = rotPlayerY - atEntry->y;
- if ((std::fabs(dx) > atEntry->box_x / 2 + delta) ||
- (std::fabs(dy) > atEntry->box_y / 2 + delta) ||
- (std::fabs(dz) > atEntry->box_z / 2 + delta))
- {
- TC_LOG_DEBUG("network", "HandleAreaTriggerOpcode: Player '%s' (GUID: %u) too far (1/2 box X: %f 1/2 box Y: %f 1/2 box Z: %f rotatedPlayerX: %f rotatedPlayerY: %f dZ:%f), ignore Area Trigger ID: %u",
- player->GetName().c_str(), player->GetGUIDLow(), atEntry->box_x/2, atEntry->box_y/2, atEntry->box_z/2, rotPlayerX, rotPlayerY, dz, triggerId);
- return;
- }
- }
-
if (player->isDebugAreaTriggers)
ChatHandler(player->GetSession()).PSendSysMessage(LANG_DEBUG_AREATRIGGER_REACHED, triggerId);
@@ -892,9 +843,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket& recvData)
if (sObjectMgr->IsTavernAreaTrigger(triggerId))
{
// set resting flag we are in the inn
- player->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
- player->InnEnter(time(NULL), atEntry->mapid, atEntry->x, atEntry->y, atEntry->z);
- player->SetRestType(REST_TYPE_IN_TAVERN);
+ player->SetRestFlag(REST_FLAG_IN_TAVERN, atEntry->id);
if (sWorld->IsFFAPvPRealm())
player->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
@@ -1241,7 +1190,7 @@ void WorldSession::HandleWorldTeleportOpcode(WorldPacket& recvData)
if (GetPlayer()->IsInFlight())
{
TC_LOG_DEBUG("network", "Player '%s' (GUID: %u) in flight, ignore worldport command.",
- GetPlayer()->GetName().c_str(), GetPlayer()->GetGUIDLow());
+ GetPlayer()->GetName().c_str(), GetPlayer()->GetGUID().GetCounter());
return;
}
@@ -1385,7 +1334,7 @@ void WorldSession::HandleFarSightOpcode(WorldPacket& recvData)
if (apply)
{
- TC_LOG_DEBUG("network", "Added FarSight %s to player %u", _player->GetGuidValue(PLAYER_FARSIGHT).ToString().c_str(), _player->GetGUIDLow());
+ TC_LOG_DEBUG("network", "Added FarSight %s to player %u", _player->GetGuidValue(PLAYER_FARSIGHT).ToString().c_str(), _player->GetGUID().GetCounter());
if (WorldObject* target = _player->GetViewpoint())
_player->SetSeer(target);
else
@@ -1393,7 +1342,7 @@ void WorldSession::HandleFarSightOpcode(WorldPacket& recvData)
}
else
{
- TC_LOG_DEBUG("network", "Player %u set vision to self", _player->GetGUIDLow());
+ TC_LOG_DEBUG("network", "Player %u set vision to self", _player->GetGUID().GetCounter());
_player->SetSeer(_player);
}
@@ -1461,7 +1410,7 @@ void WorldSession::HandleSetDungeonDifficultyOpcode(WorldPacket& recvData)
if (mode >= MAX_DUNGEON_DIFFICULTY)
{
- TC_LOG_DEBUG("network", "WorldSession::HandleSetDungeonDifficultyOpcode: player %d sent an invalid instance mode %d!", _player->GetGUIDLow(), mode);
+ TC_LOG_DEBUG("network", "WorldSession::HandleSetDungeonDifficultyOpcode: player %d sent an invalid instance mode %d!", _player->GetGUID().GetCounter(), mode);
return;
}
@@ -1473,7 +1422,7 @@ void WorldSession::HandleSetDungeonDifficultyOpcode(WorldPacket& recvData)
if (map && map->IsDungeon())
{
TC_LOG_DEBUG("network", "WorldSession::HandleSetDungeonDifficultyOpcode: player (Name: %s, GUID: %u) tried to reset the instance while player is inside!",
- _player->GetName().c_str(), _player->GetGUIDLow());
+ _player->GetName().c_str(), _player->GetGUID().GetCounter());
return;
}
@@ -1494,7 +1443,7 @@ void WorldSession::HandleSetDungeonDifficultyOpcode(WorldPacket& recvData)
if (groupGuy->GetMap()->IsNonRaidDungeon())
{
TC_LOG_DEBUG("network", "WorldSession::HandleSetDungeonDifficultyOpcode: player %d tried to reset the instance while group member (Name: %s, GUID: %u) is inside!",
- _player->GetGUIDLow(), groupGuy->GetName().c_str(), groupGuy->GetGUIDLow());
+ _player->GetGUID().GetCounter(), groupGuy->GetName().c_str(), groupGuy->GetGUID().GetCounter());
return;
}
}
@@ -1520,7 +1469,7 @@ void WorldSession::HandleSetRaidDifficultyOpcode(WorldPacket& recvData)
if (mode >= MAX_RAID_DIFFICULTY)
{
- TC_LOG_ERROR("network", "WorldSession::HandleSetRaidDifficultyOpcode: player %d sent an invalid instance mode %d!", _player->GetGUIDLow(), mode);
+ TC_LOG_ERROR("network", "WorldSession::HandleSetRaidDifficultyOpcode: player %d sent an invalid instance mode %d!", _player->GetGUID().GetCounter(), mode);
return;
}
@@ -1528,7 +1477,7 @@ void WorldSession::HandleSetRaidDifficultyOpcode(WorldPacket& recvData)
Map* map = _player->FindMap();
if (map && map->IsDungeon())
{
- TC_LOG_DEBUG("network", "WorldSession::HandleSetRaidDifficultyOpcode: player %d tried to reset the instance while inside!", _player->GetGUIDLow());
+ TC_LOG_DEBUG("network", "WorldSession::HandleSetRaidDifficultyOpcode: player %d tried to reset the instance while inside!", _player->GetGUID().GetCounter());
return;
}
@@ -1551,7 +1500,7 @@ void WorldSession::HandleSetRaidDifficultyOpcode(WorldPacket& recvData)
if (groupGuy->GetMap()->IsRaid())
{
- TC_LOG_DEBUG("network", "WorldSession::HandleSetRaidDifficultyOpcode: player %d tried to reset the instance while inside!", _player->GetGUIDLow());
+ TC_LOG_DEBUG("network", "WorldSession::HandleSetRaidDifficultyOpcode: player %d tried to reset the instance while inside!", _player->GetGUID().GetCounter());
return;
}
}
@@ -1745,7 +1694,7 @@ void WorldSession::HandleInstanceLockResponse(WorldPacket& recvPacket)
if (!_player->HasPendingBind())
{
TC_LOG_INFO("network", "InstanceLockResponse: Player %s (guid %u) tried to bind himself/teleport to graveyard without a pending bind!",
- _player->GetName().c_str(), _player->GetGUIDLow());
+ _player->GetName().c_str(), _player->GetGUID().GetCounter());
return;
}
diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp
index e86fa523f68..84816bf3f33 100644
--- a/src/server/game/Handlers/MovementHandler.cpp
+++ b/src/server/game/Handlers/MovementHandler.cpp
@@ -79,7 +79,7 @@ void WorldSession::HandleMoveWorldportAckOpcode()
// while the player is in transit, for example the map may get full
if (!newMap || !newMap->CanEnter(GetPlayer()))
{
- TC_LOG_ERROR("network", "Map %d (%s) could not be created for player %d (%s), porting player to homebind", loc.GetMapId(), newMap ? newMap->GetMapName() : "Unknown", GetPlayer()->GetGUIDLow(), GetPlayer()->GetName().c_str());
+ TC_LOG_ERROR("network", "Map %d (%s) could not be created for player %d (%s), porting player to homebind", loc.GetMapId(), newMap ? newMap->GetMapName() : "Unknown", GetPlayer()->GetGUID().GetCounter(), GetPlayer()->GetName().c_str());
GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation());
return;
}
@@ -96,7 +96,7 @@ void WorldSession::HandleMoveWorldportAckOpcode()
if (!GetPlayer()->GetMap()->AddPlayerToMap(GetPlayer()))
{
TC_LOG_ERROR("network", "WORLD: failed to teleport player %s (%d) to map %d (%s) because of unknown reason!",
- GetPlayer()->GetName().c_str(), GetPlayer()->GetGUIDLow(), loc.GetMapId(), newMap ? newMap->GetMapName() : "Unknown");
+ GetPlayer()->GetName().c_str(), GetPlayer()->GetGUID().GetCounter(), loc.GetMapId(), newMap ? newMap->GetMapName() : "Unknown");
GetPlayer()->ResetMap();
GetPlayer()->SetMap(oldMap);
GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation());
@@ -142,8 +142,8 @@ void WorldSession::HandleMoveWorldportAckOpcode()
}
// resurrect character at enter into instance where his corpse exist after add to map
- Corpse* corpse = GetPlayer()->GetCorpse();
- if (corpse && corpse->GetType() != CORPSE_BONES && corpse->GetMapId() == GetPlayer()->GetMapId())
+ Corpse* corpse = GetPlayer()->GetMap()->GetCorpseByPlayer(GetPlayer()->GetGUID());
+ if (corpse && corpse->GetType() != CORPSE_BONES)
{
if (mEntry->IsDungeon())
{
@@ -163,7 +163,7 @@ void WorldSession::HandleMoveWorldportAckOpcode()
if (time_t timeReset = sInstanceSaveMgr->GetResetTimeFor(mEntry->MapID, diff))
{
uint32 timeleft = uint32(timeReset - time(NULL));
- GetPlayer()->SendInstanceResetWarning(mEntry->MapID, diff, timeleft);
+ GetPlayer()->SendInstanceResetWarning(mEntry->MapID, diff, timeleft, true);
}
}
}
diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp
index 3c4bbd87b3f..f8d7f73e077 100644
--- a/src/server/game/Handlers/NPCHandler.cpp
+++ b/src/server/game/Handlers/NPCHandler.cpp
@@ -403,10 +403,12 @@ void WorldSession::SendSpiritResurrect()
// get corpse nearest graveyard
WorldSafeLocsEntry const* corpseGrave = NULL;
- Corpse* corpse = _player->GetCorpse();
- if (corpse)
- corpseGrave = sObjectMgr->GetClosestGraveYard(
- corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetMapId(), _player->GetTeam());
+ WorldLocation corpseLocation = _player->GetCorpseLocation();
+ if (_player->HasCorpse())
+ {
+ corpseGrave = sObjectMgr->GetClosestGraveYard(corpseLocation.GetPositionX(), corpseLocation.GetPositionY(),
+ corpseLocation.GetPositionZ(), corpseLocation.GetMapId(), _player->GetTeam());
+ }
// now can spawn bones
_player->SpawnCorpseBones();
@@ -494,7 +496,7 @@ void WorldSession::SendStablePet(ObjectGuid guid)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_SLOTS_DETAIL);
- stmt->setUInt32(0, _player->GetGUIDLow());
+ stmt->setUInt32(0, _player->GetGUID().GetCounter());
stmt->setUInt8(1, PET_SAVE_FIRST_STABLE_SLOT);
stmt->setUInt8(2, PET_SAVE_LAST_STABLE_SLOT);
@@ -596,7 +598,7 @@ void WorldSession::HandleStablePet(WorldPacket& recvData)
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_SLOTS);
- stmt->setUInt32(0, _player->GetGUIDLow());
+ stmt->setUInt32(0, _player->GetGUID().GetCounter());
stmt->setUInt8(1, PET_SAVE_FIRST_STABLE_SLOT);
stmt->setUInt8(2, PET_SAVE_LAST_STABLE_SLOT);
@@ -657,7 +659,7 @@ void WorldSession::HandleUnstablePet(WorldPacket& recvData)
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_ENTRY);
- stmt->setUInt32(0, _player->GetGUIDLow());
+ stmt->setUInt32(0, _player->GetGUID().GetCounter());
stmt->setUInt32(1, petnumber);
stmt->setUInt8(2, PET_SAVE_FIRST_STABLE_SLOT);
stmt->setUInt8(3, PET_SAVE_LAST_STABLE_SLOT);
@@ -786,7 +788,7 @@ void WorldSession::HandleStableSwapPet(WorldPacket& recvData)
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_SLOT_BY_ID);
- stmt->setUInt32(0, _player->GetGUIDLow());
+ stmt->setUInt32(0, _player->GetGUID().GetCounter());
stmt->setUInt32(1, petId);
_stableSwapCallback.SetParam(petId);
diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp
index 0bf33eee234..8c3c3e9082b 100644
--- a/src/server/game/Handlers/PetHandler.cpp
+++ b/src/server/game/Handlers/PetHandler.cpp
@@ -46,13 +46,13 @@ void WorldSession::HandleDismissCritter(WorldPacket& recvData)
if (!pet)
{
TC_LOG_DEBUG("network", "Vanitypet (%s) does not exist - player '%s' (guid: %u / account: %u) attempted to dismiss it (possibly lagged out)",
- guid.ToString().c_str(), GetPlayer()->GetName().c_str(), GetPlayer()->GetGUIDLow(), GetAccountId());
+ guid.ToString().c_str(), GetPlayer()->GetName().c_str(), GetPlayer()->GetGUID().GetCounter(), GetAccountId());
return;
}
if (_player->GetCritterGUID() == pet->GetGUID())
{
- if (pet->GetTypeId() == TYPEID_UNIT && pet->ToCreature()->IsSummon())
+ if (pet->GetTypeId() == TYPEID_UNIT && pet->IsSummon())
pet->ToTempSummon()->UnSummon();
}
}
@@ -146,7 +146,7 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe
if (!charmInfo)
{
TC_LOG_DEBUG("network", "WorldSession::HandlePetAction(petGuid: %s, tagGuid: %s, spellId: %u, flag: %u): object (GUID: %u Entry: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!",
- guid1.ToString().c_str(), guid2.ToString().c_str(), spellid, flag, pet->GetGUIDLow(), pet->GetEntry(), pet->GetTypeId());
+ guid1.ToString().c_str(), guid2.ToString().c_str(), spellid, flag, pet->GetGUID().GetCounter(), pet->GetEntry(), pet->GetTypeId());
return;
}
@@ -217,7 +217,7 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe
pet->ToCreature()->AI()->AttackStart(TargetUnit);
//10% chance to play special pet attack talk, else growl
- if (pet->ToCreature()->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10)
+ if (pet->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10)
pet->SendPetTalk((uint32)PET_TALK_ATTACK);
else
{
@@ -349,7 +349,7 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe
//10% chance to play special pet attack talk, else growl
//actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell
- if (pet->ToCreature()->IsPet() && (((Pet*)pet)->getPetType() == SUMMON_PET) && (pet != unit_target) && (urand(0, 100) < 10))
+ if (pet->IsPet() && (((Pet*)pet)->getPetType() == SUMMON_PET) && (pet != unit_target) && (urand(0, 100) < 10))
pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL);
else
{
@@ -482,7 +482,7 @@ void WorldSession::HandlePetSetAction(WorldPacket& recvData)
CharmInfo* charmInfo = pet->GetCharmInfo();
if (!charmInfo)
{
- TC_LOG_ERROR("network", "WorldSession::HandlePetSetAction: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId());
+ TC_LOG_ERROR("network", "WorldSession::HandlePetSetAction: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUID().GetCounter(), pet->GetTypeId());
return;
}
@@ -555,7 +555,7 @@ void WorldSession::HandlePetSetAction(WorldPacket& recvData)
//sign for autocast
if (act_state == ACT_ENABLED)
{
- if (pet->GetTypeId() == TYPEID_UNIT && pet->ToCreature()->IsPet())
+ if (pet->GetTypeId() == TYPEID_UNIT && pet->IsPet())
((Pet*)pet)->ToggleAutocast(spellInfo, true);
else
for (Unit::ControlList::iterator itr = GetPlayer()->m_Controlled.begin(); itr != GetPlayer()->m_Controlled.end(); ++itr)
@@ -565,7 +565,7 @@ void WorldSession::HandlePetSetAction(WorldPacket& recvData)
//sign for no/turn off autocast
else if (act_state == ACT_DISABLED)
{
- if (pet->GetTypeId() == TYPEID_UNIT && pet->ToCreature()->IsPet())
+ if (pet->GetTypeId() == TYPEID_UNIT && pet->IsPet())
((Pet*)pet)->ToggleAutocast(spellInfo, false);
else
for (Unit::ControlList::iterator itr = GetPlayer()->m_Controlled.begin(); itr != GetPlayer()->m_Controlled.end(); ++itr)
@@ -593,14 +593,14 @@ void WorldSession::HandlePetRename(WorldPacket& recvData)
recvData >> name;
recvData >> isdeclined;
- Pet* pet = ObjectAccessor::FindPet(petguid);
+ Pet* pet = ObjectAccessor::GetPet(*_player, petguid);
// check it!
if (!pet || !pet->IsPet() || ((Pet*)pet)->getPetType()!= HUNTER_PET ||
!pet->HasByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED) ||
pet->GetOwnerGUID() != _player->GetGUID() || !pet->GetCharmInfo())
return;
- PetNameInvalidReason res = ObjectMgr::CheckPetName(name);
+ PetNameInvalidReason res = ObjectMgr::CheckPetName(name, GetSessionDbcLocale());
if (res != PET_NAME_SUCCESS)
{
SendPetNameInvalid(res, name, NULL);
@@ -646,7 +646,7 @@ void WorldSession::HandlePetRename(WorldPacket& recvData)
trans->Append(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_PET_DECLINEDNAME);
- stmt->setUInt32(0, _player->GetGUIDLow());
+ stmt->setUInt32(0, _player->GetGUID().GetCounter());
for (uint8 i = 0; i < 5; i++)
stmt->setString(i + 1, declinedname.name[i]);
@@ -656,7 +656,7 @@ void WorldSession::HandlePetRename(WorldPacket& recvData)
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_PET_NAME);
stmt->setString(0, name);
- stmt->setUInt32(1, _player->GetGUIDLow());
+ stmt->setUInt32(1, _player->GetGUID().GetCounter());
stmt->setUInt32(2, pet->GetCharmInfo()->GetPetNumber());
trans->Append(stmt);
@@ -729,7 +729,7 @@ void WorldSession::HandlePetSpellAutocastOpcode(WorldPacket& recvPacket)
CharmInfo* charmInfo = pet->GetCharmInfo();
if (!charmInfo)
{
- TC_LOG_ERROR("network", "WorldSession::HandlePetSpellAutocastOpcod: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId());
+ TC_LOG_ERROR("network", "WorldSession::HandlePetSpellAutocastOpcod: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUID().GetCounter(), pet->GetTypeId());
return;
}
diff --git a/src/server/game/Handlers/PetitionsHandler.cpp b/src/server/game/Handlers/PetitionsHandler.cpp
index 05e793455da..952659dcea5 100644
--- a/src/server/game/Handlers/PetitionsHandler.cpp
+++ b/src/server/game/Handlers/PetitionsHandler.cpp
@@ -191,7 +191,7 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket& recvData)
if (!charter)
return;
- charter->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1, charter->GetGUIDLow());
+ charter->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1, charter->GetGUID().GetCounter());
// ITEM_FIELD_ENCHANTMENT_1_1 is guild/arenateam id
// ITEM_FIELD_ENCHANTMENT_1_1+1 is current signatures count (showed on item)
charter->SetState(ITEM_CHANGED, _player);
@@ -201,7 +201,7 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket& recvData)
// we checked above, if this player is in an arenateam, so this must be
// datacorruption
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_BY_OWNER);
- stmt->setUInt32(0, _player->GetGUIDLow());
+ stmt->setUInt32(0, _player->GetGUID().GetCounter());
stmt->setUInt8(1, type);
PreparedQueryResult result = CharacterDatabase.Query(stmt);
@@ -217,7 +217,7 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket& recvData)
}
// delete petitions with the same guid as this one
- ssInvalidPetitionGUIDs << '\'' << charter->GetGUIDLow() << '\'';
+ ssInvalidPetitionGUIDs << '\'' << charter->GetGUID().GetCounter() << '\'';
TC_LOG_DEBUG("network", "Invalid petition GUIDs: %s", ssInvalidPetitionGUIDs.str().c_str());
CharacterDatabase.EscapeString(name);
@@ -226,8 +226,8 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket& recvData)
trans->PAppend("DELETE FROM petition_sign WHERE petitionguid IN (%s)", ssInvalidPetitionGUIDs.str().c_str());
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PETITION);
- stmt->setUInt32(0, _player->GetGUIDLow());
- stmt->setUInt32(1, charter->GetGUIDLow());
+ stmt->setUInt32(0, _player->GetGUID().GetCounter());
+ stmt->setUInt32(1, charter->GetGUID().GetCounter());
stmt->setString(2, name);
stmt->setUInt8(3, uint8(type));
trans->Append(stmt);
@@ -243,7 +243,7 @@ void WorldSession::HandlePetitionShowSignOpcode(WorldPacket& recvData)
ObjectGuid petitionguid;
recvData >> petitionguid; // petition guid
- uint32 petitionGuidLow = petitionguid.GetCounter();
+ ObjectGuid::LowType petitionGuidLow = petitionguid.GetCounter();
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_TYPE);
@@ -253,7 +253,7 @@ void WorldSession::HandlePetitionShowSignOpcode(WorldPacket& recvData)
if (!result)
{
- TC_LOG_DEBUG("entities.player.items", "Petition %s is not found for player %u %s", petitionguid.ToString().c_str(), GetPlayer()->GetGUIDLow(), GetPlayer()->GetName().c_str());
+ TC_LOG_DEBUG("entities.player.items", "Petition %s is not found for player %u %s", petitionguid.ToString().c_str(), GetPlayer()->GetGUID().GetCounter(), GetPlayer()->GetName().c_str());
return;
}
Field* fields = result->Fetch();
@@ -284,9 +284,9 @@ void WorldSession::HandlePetitionShowSignOpcode(WorldPacket& recvData)
for (uint8 i = 1; i <= signs; ++i)
{
Field* fields2 = result->Fetch();
- uint32 lowGuid = fields2[0].GetUInt32();
+ ObjectGuid::LowType lowGuid = fields2[0].GetUInt32();
- data << ObjectGuid(HIGHGUID_PLAYER, 0, lowGuid); // Player GUID
+ data << ObjectGuid(HighGuid::Player, 0, lowGuid); // Player GUID
data << uint32(0); // there 0 ...
result->NextRow();
@@ -298,7 +298,7 @@ void WorldSession::HandlePetitionQueryOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG("network", "Received opcode CMSG_PETITION_QUERY"); // ok
- uint32 guildguid;
+ ObjectGuid::LowType guildguid;
ObjectGuid petitionguid;
recvData >> guildguid; // in Trinity always same as GUID_LOPART(petitionguid)
recvData >> petitionguid; // petition guid
@@ -322,7 +322,7 @@ void WorldSession::SendPetitionQueryOpcode(ObjectGuid petitionguid)
if (result)
{
Field* fields = result->Fetch();
- ownerguid = ObjectGuid(HIGHGUID_PLAYER, fields[0].GetUInt32());
+ ownerguid = ObjectGuid(HighGuid::Player, fields[0].GetUInt32());
name = fields[1].GetString();
type = fields[2].GetUInt8();
}
@@ -461,16 +461,16 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket& recvData)
if (!result)
{
- TC_LOG_ERROR("network", "Petition %s is not found for player %u %s", petitionGuid.ToString().c_str(), GetPlayer()->GetGUIDLow(), GetPlayer()->GetName().c_str());
+ TC_LOG_ERROR("network", "Petition %s is not found for player %u %s", petitionGuid.ToString().c_str(), GetPlayer()->GetGUID().GetCounter(), GetPlayer()->GetName().c_str());
return;
}
fields = result->Fetch();
- ObjectGuid ownerGuid(HIGHGUID_PLAYER, fields[0].GetUInt32());
+ ObjectGuid ownerGuid(HighGuid::Player, fields[0].GetUInt32());
uint64 signs = fields[1].GetUInt64();
uint8 type = fields[2].GetUInt8();
- uint32 playerGuid = _player->GetGUIDLow();
+ ObjectGuid::LowType playerGuid = _player->GetGUID().GetCounter();
if (ownerGuid == _player->GetGUID())
return;
@@ -585,7 +585,7 @@ void WorldSession::HandlePetitionDeclineOpcode(WorldPacket& recvData)
ObjectGuid petitionguid;
recvData >> petitionguid; // petition guid
- TC_LOG_DEBUG("network", "Petition %s declined by %u", petitionguid.ToString().c_str(), _player->GetGUIDLow());
+ TC_LOG_DEBUG("network", "Petition %s declined by %u", petitionguid.ToString().c_str(), _player->GetGUID().GetCounter());
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_OWNER_BY_GUID);
@@ -597,7 +597,7 @@ void WorldSession::HandlePetitionDeclineOpcode(WorldPacket& recvData)
return;
Field* fields = result->Fetch();
- ObjectGuid ownerguid(HIGHGUID_PLAYER, 0, fields[0].GetUInt32());
+ ObjectGuid ownerguid(HighGuid::Player, 0, fields[0].GetUInt32());
Player* owner = ObjectAccessor::FindConnectedPlayer(ownerguid);
if (owner) // petition owner online
@@ -708,7 +708,7 @@ void WorldSession::HandleOfferPetitionOpcode(WorldPacket& recvData)
for (uint8 i = 1; i <= signs; ++i)
{
Field* fields2 = result->Fetch();
- data << uint64(ObjectGuid(HIGHGUID_PLAYER, fields2[0].GetUInt32())); // Player GUID
+ data << uint64(ObjectGuid(HighGuid::Player, fields2[0].GetUInt32())); // Player GUID
data << uint32(0); // there 0 ...
result->NextRow();
@@ -732,10 +732,10 @@ void WorldSession::HandleTurnInPetitionOpcode(WorldPacket& recvData)
if (!item)
return;
- TC_LOG_DEBUG("network", "Petition %s turned in by %u", petitionGuid.ToString().c_str(), _player->GetGUIDLow());
+ TC_LOG_DEBUG("network", "Petition %s turned in by %u", petitionGuid.ToString().c_str(), _player->GetGUID().GetCounter());
// Get petition data from db
- uint32 ownerguidlo;
+ ObjectGuid::LowType ownerguidlo;
uint32 type;
std::string name;
@@ -752,12 +752,12 @@ void WorldSession::HandleTurnInPetitionOpcode(WorldPacket& recvData)
}
else
{
- TC_LOG_ERROR("network", "Player %s (guid: %u) tried to turn in petition (%s) that is not present in the database", _player->GetName().c_str(), _player->GetGUIDLow(), petitionGuid.ToString().c_str());
+ TC_LOG_ERROR("network", "Player %s (guid: %u) tried to turn in petition (%s) that is not present in the database", _player->GetName().c_str(), _player->GetGUID().GetCounter(), petitionGuid.ToString().c_str());
return;
}
// Only the petition owner can turn in the petition
- if (_player->GetGUIDLow() != ownerguidlo)
+ if (_player->GetGUID().GetCounter() != ownerguidlo)
return;
// Petition type (guild/arena) specific checks
@@ -853,7 +853,7 @@ void WorldSession::HandleTurnInPetitionOpcode(WorldPacket& recvData)
for (uint8 i = 0; i < signatures; ++i)
{
Field* fields = result->Fetch();
- guild->AddMember(ObjectGuid(HIGHGUID_PLAYER, fields[0].GetUInt32()));
+ guild->AddMember(ObjectGuid(HighGuid::Player, fields[0].GetUInt32()));
result->NextRow();
}
}
@@ -880,7 +880,7 @@ void WorldSession::HandleTurnInPetitionOpcode(WorldPacket& recvData)
for (uint8 i = 0; i < signatures; ++i)
{
Field* fields = result->Fetch();
- ObjectGuid memberGUID(HIGHGUID_PLAYER, fields[0].GetUInt32());
+ ObjectGuid memberGUID(HighGuid::Player, fields[0].GetUInt32());
TC_LOG_DEBUG("network", "PetitionsHandler: Adding arena team (guid: %u) member %s", arenaTeam->GetId(), memberGUID.ToString().c_str());
arenaTeam->AddMember(memberGUID);
result->NextRow();
diff --git a/src/server/game/Handlers/QueryHandler.cpp b/src/server/game/Handlers/QueryHandler.cpp
index d15f21f4ad3..153ce736946 100644
--- a/src/server/game/Handlers/QueryHandler.cpp
+++ b/src/server/game/Handlers/QueryHandler.cpp
@@ -20,7 +20,6 @@
#include "DatabaseEnv.h"
#include "WorldPacket.h"
#include "WorldSession.h"
-#include "Opcodes.h"
#include "Log.h"
#include "World.h"
#include "ObjectMgr.h"
@@ -32,7 +31,7 @@
void WorldSession::SendNameQueryOpcode(ObjectGuid guid)
{
Player* player = ObjectAccessor::FindConnectedPlayer(guid);
- CharacterNameData const* nameData = sWorld->GetCharacterNameData(guid);
+ CharacterInfo const* nameData = sWorld->GetCharacterInfo(guid);
WorldPacket data(SMSG_NAME_QUERY_RESPONSE, (8+1+1+1+1+1+10));
data << guid.WriteAsPacked();
@@ -44,11 +43,11 @@ void WorldSession::SendNameQueryOpcode(ObjectGuid guid)
}
data << uint8(0); // name known
- data << nameData->m_name; // played name
+ data << nameData->Name; // played name
data << uint8(0); // realm name - only set for cross realm interaction (such as Battlegrounds)
- data << uint8(nameData->m_race);
- data << uint8(nameData->m_gender);
- data << uint8(nameData->m_class);
+ data << uint8(nameData->Race);
+ data << uint8(nameData->Sex);
+ data << uint8(nameData->Class);
if (DeclinedName const* names = (player ? player->GetDeclinedNames() : NULL))
{
@@ -97,9 +96,9 @@ void WorldSession::HandleCreatureQueryOpcode(WorldPacket& recvData)
CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(entry);
if (ci)
{
- std::string Name, SubName;
+ std::string Name, Title;
Name = ci->Name;
- SubName = ci->SubName;
+ Title = ci->Title;
int loc_idx = GetSessionDbLocaleIndex();
if (loc_idx >= 0)
@@ -107,7 +106,7 @@ void WorldSession::HandleCreatureQueryOpcode(WorldPacket& recvData)
if (CreatureLocale const* cl = sObjectMgr->GetCreatureLocale(entry))
{
ObjectMgr::GetLocaleString(cl->Name, loc_idx, Name);
- ObjectMgr::GetLocaleString(cl->SubName, loc_idx, SubName);
+ ObjectMgr::GetLocaleString(cl->Title, loc_idx, Title);
}
}
TC_LOG_DEBUG("network", "WORLD: CMSG_CREATURE_QUERY '%s' - Entry: %u.", ci->Name.c_str(), entry);
@@ -116,7 +115,7 @@ void WorldSession::HandleCreatureQueryOpcode(WorldPacket& recvData)
data << uint32(entry); // creature entry
data << Name;
data << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4, always empty
- data << SubName;
+ data << Title;
data << ci->IconName; // "Directions" for guard, string for Icons 2.3.0
data << uint32(ci->type_flags); // flags
data << uint32(ci->type); // CreatureType.dbc
@@ -131,8 +130,15 @@ void WorldSession::HandleCreatureQueryOpcode(WorldPacket& recvData)
data << float(ci->ModHealth); // dmg/hp modifier
data << float(ci->ModMana); // dmg/mana modifier
data << uint8(ci->RacialLeader);
- for (uint32 i = 0; i < MAX_CREATURE_QUEST_ITEMS; ++i)
- data << uint32(ci->questItems[i]); // itemId[6], quest drop
+
+ CreatureQuestItemList const* items = sObjectMgr->GetCreatureQuestItemList(entry);
+ if (items)
+ for (size_t i = 0; i < MAX_CREATURE_QUEST_ITEMS; ++i)
+ data << (i < items->size() ? uint32((*items)[i]) : uint32(0));
+ else
+ for (size_t i = 0; i < MAX_CREATURE_QUEST_ITEMS; ++i)
+ data << uint32(0);
+
data << uint32(ci->movementId); // CreatureMovementInfo.dbc
SendPacket(&data);
TC_LOG_DEBUG("network", "WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE");
@@ -167,15 +173,14 @@ void WorldSession::HandleGameObjectQueryOpcode(WorldPacket& recvData)
IconName = info->IconName;
CastBarCaption = info->castBarCaption;
- int loc_idx = GetSessionDbLocaleIndex();
- if (loc_idx >= 0)
- {
- if (GameObjectLocale const* gl = sObjectMgr->GetGameObjectLocale(entry))
+ LocaleConstant localeConstant = GetSessionDbLocaleIndex();
+ if (localeConstant >= LOCALE_enUS)
+ if (GameObjectLocale const* gameObjectLocale = sObjectMgr->GetGameObjectLocale(entry))
{
- ObjectMgr::GetLocaleString(gl->Name, loc_idx, Name);
- ObjectMgr::GetLocaleString(gl->CastBarCaption, loc_idx, CastBarCaption);
+ ObjectMgr::GetLocaleString(gameObjectLocale->Name, localeConstant, Name);
+ ObjectMgr::GetLocaleString(gameObjectLocale->CastBarCaption, localeConstant, CastBarCaption);
}
- }
+
TC_LOG_DEBUG("network", "WORLD: CMSG_GAMEOBJECT_QUERY '%s' - Entry: %u. ", info->name.c_str(), entry);
WorldPacket data (SMSG_GAMEOBJECT_QUERY_RESPONSE, 150);
data << uint32(entry);
@@ -188,8 +193,15 @@ void WorldSession::HandleGameObjectQueryOpcode(WorldPacket& recvData)
data << info->unk1; // 2.0.3, string
data.append(info->raw.data, MAX_GAMEOBJECT_DATA);
data << float(info->size); // go size
- for (uint32 i = 0; i < MAX_GAMEOBJECT_QUEST_ITEMS; ++i)
- data << uint32(info->questItems[i]); // itemId[6], quest drop
+
+ GameObjectQuestItemList const* items = sObjectMgr->GetGameObjectQuestItemList(entry);
+ if (items)
+ for (size_t i = 0; i < MAX_GAMEOBJECT_QUEST_ITEMS; ++i)
+ data << (i < items->size() ? uint32((*items)[i]) : uint32(0));
+ else
+ for (size_t i = 0; i < MAX_GAMEOBJECT_QUEST_ITEMS; ++i)
+ data << uint32(0);
+
SendPacket(&data);
TC_LOG_DEBUG("network", "WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE");
}
@@ -206,11 +218,7 @@ void WorldSession::HandleGameObjectQueryOpcode(WorldPacket& recvData)
void WorldSession::HandleCorpseQueryOpcode(WorldPacket & /*recvData*/)
{
- TC_LOG_DEBUG("network", "WORLD: Received MSG_CORPSE_QUERY");
-
- Corpse* corpse = GetPlayer()->GetCorpse();
-
- if (!corpse)
+ if (!_player->HasCorpse())
{
WorldPacket data(MSG_CORPSE_QUERY, 1);
data << uint8(0); // corpse not found
@@ -218,24 +226,25 @@ void WorldSession::HandleCorpseQueryOpcode(WorldPacket & /*recvData*/)
return;
}
- uint32 mapid = corpse->GetMapId();
- float x = corpse->GetPositionX();
- float y = corpse->GetPositionY();
- float z = corpse->GetPositionZ();
- uint32 corpsemapid = mapid;
+ WorldLocation corpseLocation = _player->GetCorpseLocation();
+ uint32 corpseMapID = corpseLocation.GetMapId();
+ uint32 mapID = corpseLocation.GetMapId();
+ float x = corpseLocation.GetPositionX();
+ float y = corpseLocation.GetPositionY();
+ float z = corpseLocation.GetPositionZ();
// if corpse at different map
- if (mapid != _player->GetMapId())
+ if (mapID != _player->GetMapId())
{
// search entrance map for proper show entrance
- if (MapEntry const* corpseMapEntry = sMapStore.LookupEntry(mapid))
+ if (MapEntry const* corpseMapEntry = sMapStore.LookupEntry(mapID))
{
if (corpseMapEntry->IsDungeon() && corpseMapEntry->entrance_map >= 0)
{
// if corpse map have entrance
if (Map const* entranceMap = sMapMgr->CreateBaseMap(corpseMapEntry->entrance_map))
{
- mapid = corpseMapEntry->entrance_map;
+ mapID = corpseMapEntry->entrance_map;
x = corpseMapEntry->entrance_x;
y = corpseMapEntry->entrance_y;
z = entranceMap->GetHeight(GetPlayer()->GetPhaseMask(), x, y, MAX_HEIGHT);
@@ -246,11 +255,11 @@ void WorldSession::HandleCorpseQueryOpcode(WorldPacket & /*recvData*/)
WorldPacket data(MSG_CORPSE_QUERY, 1+(6*4));
data << uint8(1); // corpse found
- data << int32(mapid);
+ data << int32(mapID);
data << float(x);
data << float(y);
data << float(z);
- data << int32(corpsemapid);
+ data << int32(corpseMapID);
data << uint32(0); // unknown
SendPacket(&data);
}
diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp
index 3c6258b2d7c..fd7c4439c8f 100644
--- a/src/server/game/Handlers/QuestHandler.cpp
+++ b/src/server/game/Handlers/QuestHandler.cpp
@@ -20,7 +20,6 @@
#include "Log.h"
#include "WorldPacket.h"
#include "WorldSession.h"
-#include "Opcodes.h"
#include "World.h"
#include "ObjectMgr.h"
#include "Player.h"
@@ -49,14 +48,14 @@ void WorldSession::HandleQuestgiverStatusQueryOpcode(WorldPacket& recvData)
{
case TYPEID_UNIT:
{
- TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_STATUS_QUERY for npc, guid = %u", questGiver->GetGUIDLow());
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_STATUS_QUERY for npc, guid = %u", questGiver->GetGUID().GetCounter());
if (!questGiver->ToCreature()->IsHostileTo(_player)) // do not show quest status to enemies
questStatus = _player->GetQuestDialogStatus(questGiver);
break;
}
case TYPEID_GAMEOBJECT:
{
- TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_STATUS_QUERY for GameObject guid = %u", questGiver->GetGUIDLow());
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_STATUS_QUERY for GameObject guid = %u", questGiver->GetGUID().GetCounter());
questStatus = _player->GetQuestDialogStatus(questGiver);
break;
}
@@ -125,8 +124,7 @@ void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPacket& recvData)
if (Player* playerQuestObject = object->ToPlayer())
{
- if ((_player->GetDivider() && _player->GetDivider() != guid) ||
- ((object != _player && !playerQuestObject->CanShareQuest(questId))))
+ if ((_player->GetDivider() && _player->GetDivider() != guid) || !playerQuestObject->CanShareQuest(questId))
{
CLOSE_GOSSIP_CLEAR_DIVIDER();
return;
@@ -261,7 +259,7 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPacket& recvData)
if (reward >= QUEST_REWARD_CHOICES_COUNT)
{
- TC_LOG_ERROR("network", "Error in CMSG_QUESTGIVER_CHOOSE_REWARD: player %s (guid %d) tried to get invalid reward (%u) (possible packet-hacking detected)", _player->GetName().c_str(), _player->GetGUIDLow(), reward);
+ TC_LOG_ERROR("network", "Error in CMSG_QUESTGIVER_CHOOSE_REWARD: player %s (guid %d) tried to get invalid reward (%u) (possible packet-hacking detected)", _player->GetName().c_str(), _player->GetGUID().GetCounter(), reward);
return;
}
@@ -281,7 +279,7 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPacket& recvData)
(_player->GetQuestStatus(questId) != QUEST_STATUS_COMPLETE && !quest->IsAutoComplete()))
{
TC_LOG_ERROR("network", "Error in QUEST_STATUS_COMPLETE: player %s (guid %u) tried to complete quest %u, but is not allowed to do so (possible packet-hacking or high latency)",
- _player->GetName().c_str(), _player->GetGUIDLow(), questId);
+ _player->GetName().c_str(), _player->GetGUID().GetCounter(), questId);
return;
}
if (_player->CanRewardQuest(quest, reward, true))
@@ -419,14 +417,14 @@ void WorldSession::HandleQuestLogRemoveQuest(WorldPacket& recvData)
_player->RemoveActiveQuest(questId);
_player->RemoveTimedAchievement(ACHIEVEMENT_TIMED_TYPE_QUEST, questId);
- TC_LOG_INFO("network", "Player %u abandoned quest %u", _player->GetGUIDLow(), questId);
+ TC_LOG_INFO("network", "Player %u abandoned quest %u", _player->GetGUID().GetCounter(), questId);
if (sWorld->getBoolConfig(CONFIG_QUEST_ENABLE_QUEST_TRACKER)) // check if Quest Tracker is enabled
{
// prepare Quest Tracker datas
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_QUEST_TRACK_ABANDON_TIME);
stmt->setUInt32(0, questId);
- stmt->setUInt32(1, _player->GetGUIDLow());
+ stmt->setUInt32(1, _player->GetGUID().GetCounter());
// add to Quest Tracker
CharacterDatabase.Execute(stmt);
@@ -495,7 +493,7 @@ void WorldSession::HandleQuestgiverCompleteQuest(WorldPacket& recvData)
if (!_player->CanSeeStartQuest(quest) && _player->GetQuestStatus(questId) == QUEST_STATUS_NONE)
{
TC_LOG_ERROR("network", "Possible hacking attempt: Player %s [guid: %u] tried to complete quest [entry: %u] without being in possession of the quest!",
- _player->GetName().c_str(), _player->GetGUIDLow(), questId);
+ _player->GetName().c_str(), _player->GetGUID().GetCounter(), questId);
return;
}
diff --git a/src/server/game/Handlers/ReferAFriendHandler.cpp b/src/server/game/Handlers/ReferAFriendHandler.cpp
index cf864772b7c..db5d0997eeb 100644
--- a/src/server/game/Handlers/ReferAFriendHandler.cpp
+++ b/src/server/game/Handlers/ReferAFriendHandler.cpp
@@ -18,7 +18,6 @@
#include "WorldSession.h"
#include "Player.h"
#include "ObjectMgr.h"
-#include "Opcodes.h"
#include "Log.h"
void WorldSession::HandleGrantLevel(WorldPacket& recvData)
@@ -28,7 +27,7 @@ void WorldSession::HandleGrantLevel(WorldPacket& recvData)
ObjectGuid guid;
recvData >> guid.ReadAsPacked();
- Player* target = ObjectAccessor::GetObjectInWorld(guid, _player);
+ Player* target = ObjectAccessor::GetPlayer(*_player, guid);
// check cheating
uint8 levels = _player->GetGrantableLevels();
@@ -71,7 +70,8 @@ void WorldSession::HandleAcceptGrantLevel(WorldPacket& recvData)
ObjectGuid guid;
recvData >> guid.ReadAsPacked();
- Player* other = ObjectAccessor::GetObjectInWorld(guid, _player);
+ Player* other = ObjectAccessor::GetPlayer(*_player, guid);
+
if (!(other && other->GetSession()))
return;
diff --git a/src/server/game/Handlers/SkillHandler.cpp b/src/server/game/Handlers/SkillHandler.cpp
index 6da2efa38a6..5f50a7305ee 100644
--- a/src/server/game/Handlers/SkillHandler.cpp
+++ b/src/server/game/Handlers/SkillHandler.cpp
@@ -19,7 +19,6 @@
#include "Common.h"
#include "Log.h"
#include "ObjectAccessor.h"
-#include "Opcodes.h"
#include "Player.h"
#include "Pet.h"
#include "WorldPacket.h"
diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp
index a6108b36c13..0f0640e3a2e 100644
--- a/src/server/game/Handlers/SpellHandler.cpp
+++ b/src/server/game/Handlers/SpellHandler.cpp
@@ -200,7 +200,7 @@ void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket)
{
pUser->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW, item, NULL);
TC_LOG_ERROR("network", "Possible hacking attempt: Player %s [guid: %u] tried to open item [guid: %u, entry: %u] which is not openable!",
- pUser->GetName().c_str(), pUser->GetGUIDLow(), item->GetGUIDLow(), proto->ItemId);
+ pUser->GetName().c_str(), pUser->GetGUID().GetCounter(), item->GetGUID().GetCounter(), proto->ItemId);
return;
}
@@ -213,7 +213,7 @@ void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket)
if (!lockInfo)
{
pUser->SendEquipError(EQUIP_ERR_ITEM_LOCKED, item, NULL);
- TC_LOG_ERROR("network", "WORLD::OpenItem: item [guid = %u] has an unknown lockId: %u!", item->GetGUIDLow(), lockId);
+ TC_LOG_ERROR("network", "WORLD::OpenItem: item [guid = %u] has an unknown lockId: %u!", item->GetGUID().GetCounter(), lockId);
return;
}
@@ -229,7 +229,7 @@ void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_GIFT_BY_ITEM);
- stmt->setUInt32(0, item->GetGUIDLow());
+ stmt->setUInt32(0, item->GetGUID().GetCounter());
PreparedQueryResult result = CharacterDatabase.Query(stmt);
@@ -246,14 +246,14 @@ void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket)
}
else
{
- TC_LOG_ERROR("network", "Wrapped item %u don't have record in character_gifts table and will deleted", item->GetGUIDLow());
+ TC_LOG_ERROR("network", "Wrapped item %u don't have record in character_gifts table and will deleted", item->GetGUID().GetCounter());
pUser->DestroyItem(item->GetBagSlot(), item->GetSlot(), true);
return;
}
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GIFT);
- stmt->setUInt32(0, item->GetGUIDLow());
+ stmt->setUInt32(0, item->GetGUID().GetCounter());
CharacterDatabase.Execute(stmt);
}
@@ -579,7 +579,7 @@ void WorldSession::HandleMirrorImageDataRequest(WorldPacket& recvData)
recvData >> guid;
// Get unit for which data is needed by client
- Unit* unit = ObjectAccessor::GetObjectInWorld(guid, (Unit*)NULL);
+ Unit* unit = ObjectAccessor::GetUnit(*_player, guid);
if (!unit)
return;
diff --git a/src/server/game/Handlers/TaxiHandler.cpp b/src/server/game/Handlers/TaxiHandler.cpp
index af0f5b0fc75..a671250c17d 100644
--- a/src/server/game/Handlers/TaxiHandler.cpp
+++ b/src/server/game/Handlers/TaxiHandler.cpp
@@ -24,7 +24,6 @@
#include "Log.h"
#include "ObjectMgr.h"
#include "Player.h"
-#include "Path.h"
#include "WaypointMovementGenerator.h"
void WorldSession::HandleTaxiNodeStatusQueryOpcode(WorldPacket& recvData)
@@ -212,7 +211,7 @@ void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recvData)
MovementInfo movementInfo; // used only for proper packet read
ReadMovementInfo(recvData, &movementInfo);
- recvData.read_skip<uint32>(); // unk
+ recvData.read_skip<uint32>(); // spline id
// in taxi flight packet received in 2 case:
// 1) end taxi path in far (multi-node) flight
@@ -220,59 +219,32 @@ void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recvData)
// we need process only (1)
uint32 curDest = GetPlayer()->m_taxi.GetTaxiDestination();
- if (!curDest)
- return;
-
- TaxiNodesEntry const* curDestNode = sTaxiNodesStore.LookupEntry(curDest);
-
- // far teleport case
- if (curDestNode && curDestNode->map_id != GetPlayer()->GetMapId())
+ if (curDest)
{
- if (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE)
- {
- // short preparations to continue flight
- FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top());
-
- flight->SetCurrentNodeAfterTeleport();
- TaxiPathNodeEntry const& node = flight->GetPath()[flight->GetCurrentNode()];
- flight->SkipCurrentNode();
+ TaxiNodesEntry const* curDestNode = sTaxiNodesStore.LookupEntry(curDest);
- GetPlayer()->TeleportTo(curDestNode->map_id, node.LocX, node.LocY, node.LocZ, GetPlayer()->GetOrientation());
- }
- return;
- }
-
- uint32 destinationnode = GetPlayer()->m_taxi.NextTaxiDestination();
- if (destinationnode > 0) // if more destinations to go
- {
- // current source node for next destination
- uint32 sourcenode = GetPlayer()->m_taxi.GetTaxiSource();
-
- // Add to taximask middle hubs in taxicheat mode (to prevent having player with disabled taxicheat and not having back flight path)
- if (GetPlayer()->isTaxiCheater())
+ // far teleport case
+ if (curDestNode && curDestNode->map_id != GetPlayer()->GetMapId())
{
- if (GetPlayer()->m_taxi.SetTaximaskNode(sourcenode))
+ if (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE)
{
- WorldPacket data(SMSG_NEW_TAXI_PATH, 0);
- _player->GetSession()->SendPacket(&data);
- }
- }
+ // short preparations to continue flight
+ FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top());
- TC_LOG_DEBUG("network", "WORLD: Taxi has to go from %u to %u", sourcenode, destinationnode);
+ flight->SetCurrentNodeAfterTeleport();
+ TaxiPathNodeEntry const* node = flight->GetPath()[flight->GetCurrentNode()];
+ flight->SkipCurrentNode();
- uint32 mountDisplayId = sObjectMgr->GetTaxiMountDisplayId(sourcenode, GetPlayer()->GetTeam());
-
- uint32 path, cost;
- sObjectMgr->GetTaxiPath(sourcenode, destinationnode, path, cost);
+ GetPlayer()->TeleportTo(curDestNode->map_id, node->LocX, node->LocY, node->LocZ, GetPlayer()->GetOrientation());
+ }
+ }
- if (path && mountDisplayId)
- SendDoFlight(mountDisplayId, path, 1); // skip start fly node
- else
- GetPlayer()->m_taxi.ClearTaxiDestinations(); // clear problematic path and next
return;
}
- else
- GetPlayer()->m_taxi.ClearTaxiDestinations(); // not destinations, clear source node
+
+ // at this point only 1 node is expected (final destination)
+ if (GetPlayer()->m_taxi.GetPath().size() != 1)
+ return;
GetPlayer()->CleanupAfterTaxiFlight();
GetPlayer()->SetFallInformation(0, GetPlayer()->GetPositionZ());
diff --git a/src/server/game/Handlers/TicketHandler.cpp b/src/server/game/Handlers/TicketHandler.cpp
index 3ae9d6c8672..cf6181f02b4 100644
--- a/src/server/game/Handlers/TicketHandler.cpp
+++ b/src/server/game/Handlers/TicketHandler.cpp
@@ -24,7 +24,6 @@
#include "Player.h"
#include "TicketMgr.h"
#include "Util.h"
-#include "World.h"
#include "WorldPacket.h"
#include "WorldSession.h"
@@ -218,7 +217,7 @@ void WorldSession::HandleGMSurveySubmit(WorldPacket& recvData)
recvData >> comment;
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GM_SURVEY);
- stmt->setUInt32(0, GetPlayer()->GetGUIDLow());
+ stmt->setUInt32(0, GetPlayer()->GetGUID().GetCounter());
stmt->setUInt32(1, nextSurveyID);
stmt->setUInt32(2, mainSurvey);
stmt->setString(3, comment);
@@ -241,7 +240,7 @@ void WorldSession::HandleReportLag(WorldPacket& recvData)
recvData >> z;
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_LAG_REPORT);
- stmt->setUInt32(0, GetPlayer()->GetGUIDLow());
+ stmt->setUInt32(0, GetPlayer()->GetGUID().GetCounter());
stmt->setUInt8 (1, lagType);
stmt->setUInt16(2, mapId);
stmt->setFloat (3, x);
diff --git a/src/server/game/Handlers/TradeHandler.cpp b/src/server/game/Handlers/TradeHandler.cpp
index 4f7e9f05725..1bb21971935 100644
--- a/src/server/game/Handlers/TradeHandler.cpp
+++ b/src/server/game/Handlers/TradeHandler.cpp
@@ -22,13 +22,13 @@
#include "World.h"
#include "ObjectAccessor.h"
#include "Log.h"
-#include "Opcodes.h"
#include "Player.h"
#include "Item.h"
#include "Spell.h"
#include "SocialMgr.h"
#include "Language.h"
#include "AccountMgr.h"
+#include "TradeData.h"
void WorldSession::SendTradeStatus(TradeStatusInfo const& info)
{
@@ -61,13 +61,13 @@ void WorldSession::SendTradeStatus(TradeStatusInfo const& info)
void WorldSession::HandleIgnoreTradeOpcode(WorldPacket& /*recvPacket*/)
{
- TC_LOG_DEBUG("network", "WORLD: Ignore Trade %u", _player->GetGUIDLow());
+ TC_LOG_DEBUG("network", "WORLD: Ignore Trade %u", _player->GetGUID().GetCounter());
// recvPacket.print_storage();
}
void WorldSession::HandleBusyTradeOpcode(WorldPacket& /*recvPacket*/)
{
- TC_LOG_DEBUG("network", "WORLD: Busy Trade %u", _player->GetGUIDLow());
+ TC_LOG_DEBUG("network", "WORLD: Busy Trade %u", _player->GetGUID().GetCounter());
// recvPacket.print_storage();
}
@@ -142,7 +142,7 @@ void WorldSession::moveItems(Item* myItems[], Item* hisItems[])
if (myItems[i])
{
// logging
- TC_LOG_DEBUG("network", "partner storing: %u", myItems[i]->GetGUIDLow());
+ TC_LOG_DEBUG("network", "partner storing: %u", myItems[i]->GetGUID().GetCounter());
if (HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE))
{
sLog->outCommand(_player->GetSession()->GetAccountId(), "GM %s (Account: %u) trade: %s (Entry: %d Count: %u) to player: %s (Account: %u)",
@@ -160,7 +160,7 @@ void WorldSession::moveItems(Item* myItems[], Item* hisItems[])
if (hisItems[i])
{
// logging
- TC_LOG_DEBUG("network", "player storing: %u", hisItems[i]->GetGUIDLow());
+ TC_LOG_DEBUG("network", "player storing: %u", hisItems[i]->GetGUID().GetCounter());
if (HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE))
{
sLog->outCommand(trader->GetSession()->GetAccountId(), "GM %s (Account: %u) trade: %s (Entry: %d Count: %u) to player: %s (Account: %u)",
@@ -183,21 +183,21 @@ void WorldSession::moveItems(Item* myItems[], Item* hisItems[])
if (myItems[i])
{
if (!traderCanTrade)
- TC_LOG_ERROR("network", "trader can't store item: %u", myItems[i]->GetGUIDLow());
+ TC_LOG_ERROR("network", "trader can't store item: %u", myItems[i]->GetGUID().GetCounter());
if (_player->CanStoreItem(NULL_BAG, NULL_SLOT, playerDst, myItems[i], false) == EQUIP_ERR_OK)
_player->MoveItemToInventory(playerDst, myItems[i], true, true);
else
- TC_LOG_ERROR("network", "player can't take item back: %u", myItems[i]->GetGUIDLow());
+ TC_LOG_ERROR("network", "player can't take item back: %u", myItems[i]->GetGUID().GetCounter());
}
// return the already removed items to the original owner
if (hisItems[i])
{
if (!playerCanTrade)
- TC_LOG_ERROR("network", "player can't store item: %u", hisItems[i]->GetGUIDLow());
+ TC_LOG_ERROR("network", "player can't store item: %u", hisItems[i]->GetGUID().GetCounter());
if (trader->CanStoreItem(NULL_BAG, NULL_SLOT, traderDst, hisItems[i], false) == EQUIP_ERR_OK)
trader->MoveItemToInventory(traderDst, hisItems[i], true, true);
else
- TC_LOG_ERROR("network", "trader can't take item back: %u", hisItems[i]->GetGUIDLow());
+ TC_LOG_ERROR("network", "trader can't take item back: %u", hisItems[i]->GetGUID().GetCounter());
}
}
}
@@ -215,7 +215,7 @@ static void setAcceptTradeMode(TradeData* myTrade, TradeData* hisTrade, Item* *m
{
if (Item* item = myTrade->GetItem(TradeSlots(i)))
{
- TC_LOG_DEBUG("network", "player trade item %u bag: %u slot: %u", item->GetGUIDLow(), item->GetBagSlot(), item->GetSlot());
+ TC_LOG_DEBUG("network", "player trade item %u bag: %u slot: %u", item->GetGUID().GetCounter(), item->GetBagSlot(), item->GetSlot());
//Can return NULL
myItems[i] = item;
myItems[i]->SetInTrade();
@@ -223,7 +223,7 @@ static void setAcceptTradeMode(TradeData* myTrade, TradeData* hisTrade, Item* *m
if (Item* item = hisTrade->GetItem(TradeSlots(i)))
{
- TC_LOG_DEBUG("network", "partner trade item %u bag: %u slot: %u", item->GetGUIDLow(), item->GetBagSlot(), item->GetSlot());
+ TC_LOG_DEBUG("network", "partner trade item %u bag: %u slot: %u", item->GetGUID().GetCounter(), item->GetBagSlot(), item->GetSlot());
hisItems[i] = item;
hisItems[i]->SetInTrade();
}
@@ -455,6 +455,8 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
SendTradeStatus(myCanCompleteInfo);
my_trade->SetAccepted(false);
his_trade->SetAccepted(false);
+ delete my_spell;
+ delete his_spell;
return;
}
else if (hisCanCompleteInfo.Result != EQUIP_ERR_OK)
@@ -467,6 +469,8 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
trader->GetSession()->SendTradeStatus(hisCanCompleteInfo);
my_trade->SetAccepted(false);
his_trade->SetAccepted(false);
+ delete my_spell;
+ delete his_spell;
return;
}
@@ -669,7 +673,7 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket)
return;
}
- if (pOther->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow()))
+ if (pOther->GetSocial()->HasIgnore(GetPlayer()->GetGUID().GetCounter()))
{
info.Status = TRADE_STATUS_IGNORE_YOU;
SendTradeStatus(info);
diff --git a/src/server/game/Handlers/VehicleHandler.cpp b/src/server/game/Handlers/VehicleHandler.cpp
index 6b9d64be91a..3bb2ca78931 100644
--- a/src/server/game/Handlers/VehicleHandler.cpp
+++ b/src/server/game/Handlers/VehicleHandler.cpp
@@ -17,7 +17,6 @@
#include "WorldPacket.h"
#include "WorldSession.h"
-#include "Opcodes.h"
#include "Vehicle.h"
#include "Player.h"
#include "Log.h"
@@ -64,7 +63,7 @@ void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket &recvData)
{
recvData.rfinish(); // prevent warnings spam
TC_LOG_ERROR("network", "HandleChangeSeatsOnControlledVehicle, Opcode: %u, Player %u tried to switch seats but current seatflags %u don't permit that.",
- recvData.GetOpcode(), GetPlayer()->GetGUIDLow(), seat->m_flags);
+ recvData.GetOpcode(), GetPlayer()->GetGUID().GetCounter(), seat->m_flags);
return;
}
@@ -177,7 +176,7 @@ void WorldSession::HandleEjectPassenger(WorldPacket &data)
if (seat->IsEjectable())
unit->ExitVehicle();
else
- TC_LOG_ERROR("network", "Player %u attempted to eject %s from non-ejectable seat.", GetPlayer()->GetGUIDLow(), guid.ToString().c_str());
+ TC_LOG_ERROR("network", "Player %u attempted to eject %s from non-ejectable seat.", GetPlayer()->GetGUID().GetCounter(), guid.ToString().c_str());
}
else
TC_LOG_ERROR("network", "HandleEjectPassenger: %s tried to eject invalid %s ", GetPlayer()->GetGUID().ToString().c_str(), guid.ToString().c_str());
@@ -195,7 +194,7 @@ void WorldSession::HandleRequestVehicleExit(WorldPacket& /*recvData*/)
GetPlayer()->ExitVehicle();
else
TC_LOG_ERROR("network", "Player %u tried to exit vehicle, but seatflags %u (ID: %u) don't permit that.",
- GetPlayer()->GetGUIDLow(), seat->m_ID, seat->m_flags);
+ GetPlayer()->GetGUID().GetCounter(), seat->m_ID, seat->m_flags);
}
}
}
diff --git a/src/server/game/Handlers/VoiceChatHandler.cpp b/src/server/game/Handlers/VoiceChatHandler.cpp
index 277755c6eb1..e667eb4bfd9 100644
--- a/src/server/game/Handlers/VoiceChatHandler.cpp
+++ b/src/server/game/Handlers/VoiceChatHandler.cpp
@@ -19,7 +19,6 @@
#include "Common.h"
#include "WorldPacket.h"
#include "WorldSession.h"
-#include "Log.h"
void WorldSession::HandleVoiceSessionEnableOpcode(WorldPacket& recvData)
{
diff --git a/src/server/game/Instances/InstanceSaveMgr.cpp b/src/server/game/Instances/InstanceSaveMgr.cpp
index 260c2966a52..b3dd3e9f01f 100644
--- a/src/server/game/Instances/InstanceSaveMgr.cpp
+++ b/src/server/game/Instances/InstanceSaveMgr.cpp
@@ -555,7 +555,10 @@ void InstanceSaveManager::_ResetInstance(uint32 mapid, uint32 instanceId)
((InstanceMap*)iMap)->Reset(INSTANCE_RESET_RESPAWN_DELAY);
if (iMap)
+ {
iMap->DeleteRespawnTimes();
+ iMap->DeleteCorpseData();
+ }
else
Map::DeleteRespawnTimesInDB(mapid, instanceId);
@@ -646,10 +649,10 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, Difficulty difficulty, b
if (warn)
{
- if (now <= resetTime)
+ if (now >= resetTime)
timeLeft = 0;
else
- timeLeft = uint32(now - resetTime);
+ timeLeft = uint32(resetTime - now);
((InstanceMap*)map2)->SendResetWarnings(timeLeft);
}
@@ -660,19 +663,19 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, Difficulty difficulty, b
/// @todo delete creature/gameobject respawn times even if the maps are not loaded
}
-uint32 InstanceSaveManager::GetNumBoundPlayersTotal()
+uint32 InstanceSaveManager::GetNumBoundPlayersTotal() const
{
uint32 ret = 0;
- for (InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end(); ++itr)
+ for (InstanceSaveHashMap::const_iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end(); ++itr)
ret += itr->second->GetPlayerCount();
return ret;
}
-uint32 InstanceSaveManager::GetNumBoundGroupsTotal()
+uint32 InstanceSaveManager::GetNumBoundGroupsTotal() const
{
uint32 ret = 0;
- for (InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end(); ++itr)
+ for (InstanceSaveHashMap::const_iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end(); ++itr)
ret += itr->second->GetGroupCount();
return ret;
diff --git a/src/server/game/Instances/InstanceSaveMgr.h b/src/server/game/Instances/InstanceSaveMgr.h
index 7494d9f5746..5e8292057a8 100644
--- a/src/server/game/Instances/InstanceSaveMgr.h
+++ b/src/server/game/Instances/InstanceSaveMgr.h
@@ -222,9 +222,9 @@ class InstanceSaveManager
InstanceSave* GetInstanceSave(uint32 InstanceId);
/* statistics */
- uint32 GetNumInstanceSaves() { return m_instanceSaveById.size(); }
- uint32 GetNumBoundPlayersTotal();
- uint32 GetNumBoundGroupsTotal();
+ uint32 GetNumInstanceSaves() const { return uint32(m_instanceSaveById.size()); }
+ uint32 GetNumBoundPlayersTotal() const;
+ uint32 GetNumBoundGroupsTotal() const;
protected:
static uint16 ResetTimeDelay[];
diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp
index da806e5b038..a8cf42ea49e 100644
--- a/src/server/game/Instances/InstanceScript.cpp
+++ b/src/server/game/Instances/InstanceScript.cpp
@@ -319,6 +319,11 @@ bool InstanceScript::SetBossState(uint32 id, EncounterState state)
return false;
}
+bool InstanceScript::_SkipCheckRequiredBosses(Player const* player /*= nullptr*/) const
+{
+ return player && player->GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_INSTANCE_REQUIRED_BOSSES);
+}
+
void InstanceScript::Load(char const* data)
{
if (!data)
@@ -647,3 +652,25 @@ void InstanceScript::UpdateEncounterState(EncounterCreditType type, uint32 credi
}
}
}
+
+std::string InstanceScript::GetBossStateName(uint8 state)
+{
+ // See enum EncounterState in InstanceScript.h
+ switch (state)
+ {
+ case NOT_STARTED:
+ return "NOT_STARTED";
+ case IN_PROGRESS:
+ return "IN_PROGRESS";
+ case FAIL:
+ return "FAIL";
+ case DONE:
+ return "DONE";
+ case SPECIAL:
+ return "SPECIAL";
+ case TO_BE_DECIDED:
+ return "TO_BE_DECIDED";
+ default:
+ return "INVALID";
+ }
+}
diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h
index be05a9f4495..93dafea0413 100644
--- a/src/server/game/Instances/InstanceScript.h
+++ b/src/server/game/Instances/InstanceScript.h
@@ -174,11 +174,11 @@ class InstanceScript : public ZoneScript
inline Creature* GetCreature(uint32 type)
{
- return ObjectAccessor::GetObjectInMap<Creature>(GetObjectGuid(type), instance, nullptr);
+ return instance->GetCreature(GetObjectGuid(type));
}
inline GameObject* GetGameObject(uint32 type)
{
- return ObjectAccessor::GetObjectInMap<GameObject>(GetObjectGuid(type), instance, nullptr);
+ return instance->GetGameObject(GetObjectGuid(type));
}
// Called when a player successfully enters the instance.
@@ -220,6 +220,7 @@ class InstanceScript : public ZoneScript
virtual bool SetBossState(uint32 id, EncounterState state);
EncounterState GetBossState(uint32 id) const { return id < bosses.size() ? bosses[id].state : TO_BE_DECIDED; }
+ static std::string GetBossStateName(uint8 state);
BossBoundaryMap const* GetBossBoundary(uint32 id) const { return id < bosses.size() ? &bosses[id].boundary : NULL; }
// Achievement criteria additional requirements check
@@ -273,6 +274,8 @@ class InstanceScript : public ZoneScript
void WriteSaveDataBossStates(std::ostringstream& data);
virtual void WriteSaveDataMore(std::ostringstream& /*data*/) { }
+ bool _SkipCheckRequiredBosses(Player const* player = nullptr) const;
+
private:
static void LoadObjectData(ObjectData const* creatureData, ObjectInfoMap& objectInfo);
diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp
index ba4e4713458..b7a19a72bf5 100644
--- a/src/server/game/Loot/LootMgr.cpp
+++ b/src/server/game/Loot/LootMgr.cpp
@@ -95,7 +95,7 @@ class LootTemplate::LootGroup // A set of loot def
void CheckLootRefs(LootTemplateMap const& store, LootIdSet* ref_set) const;
LootStoreItemList* GetExplicitlyChancedItemList() { return &ExplicitlyChanced; }
LootStoreItemList* GetEqualChancedItemList() { return &EqualChanced; }
- void CopyConditions(ConditionList conditions);
+ void CopyConditions(ConditionContainer conditions);
private:
LootStoreItemList ExplicitlyChanced; // Entries with chances defined in DB
LootStoreItemList EqualChanced; // Zero chances - every entry takes the same chance
@@ -151,14 +151,8 @@ uint32 LootStore::LoadLootTable()
bool needsquest = fields[4].GetBool();
uint16 lootmode = fields[5].GetUInt16();
uint8 groupid = fields[6].GetUInt8();
- int32 mincount = fields[7].GetUInt8();
- int32 maxcount = fields[8].GetUInt8();
-
- if (maxcount > std::numeric_limits<uint8>::max())
- {
- TC_LOG_ERROR("sql.sql", "Table '%s' Entry %d Item %d: MaxCount value (%u) to large. must be less %u - skipped", GetName(), entry, item, maxcount, std::numeric_limits<uint8>::max());
- continue; // error already printed to log/console.
- }
+ uint8 mincount = fields[7].GetUInt8();
+ uint8 maxcount = fields[8].GetUInt8();
if (groupid >= 1 << 7) // it stored in 7 bit field
{
@@ -224,7 +218,7 @@ void LootStore::ResetConditions()
{
for (LootTemplateMap::iterator itr = m_LootTemplates.begin(); itr != m_LootTemplates.end(); ++itr)
{
- ConditionList empty;
+ ConditionContainer empty;
itr->second->CopyConditions(empty);
}
}
@@ -405,7 +399,7 @@ bool LootItem::AllowedForPlayer(Player const* player) const
void LootItem::AddAllowedLooter(const Player* player)
{
- allowedGUIDs.insert(player->GetGUIDLow());
+ allowedGUIDs.insert(player->GetGUID().GetCounter());
}
//
@@ -487,7 +481,7 @@ bool Loot::FillLoot(uint32 lootId, LootStore const& store, Player* lootOwner, bo
void Loot::FillNotNormalLootFor(Player* player, bool presentAtLooting)
{
- uint32 plguid = player->GetGUIDLow();
+ ObjectGuid::LowType plguid = player->GetGUID().GetCounter();
QuestItemMap::const_iterator qmapitr = PlayerQuestItems.find(plguid);
if (qmapitr == PlayerQuestItems.end())
@@ -542,7 +536,7 @@ QuestItemList* Loot::FillFFALoot(Player* player)
return NULL;
}
- PlayerFFAItems[player->GetGUIDLow()] = ql;
+ PlayerFFAItems[player->GetGUID().GetCounter()] = ql;
return ql;
}
@@ -580,7 +574,7 @@ QuestItemList* Loot::FillQuestLoot(Player* player)
return NULL;
}
- PlayerQuestItems[player->GetGUIDLow()] = ql;
+ PlayerQuestItems[player->GetGUID().GetCounter()] = ql;
return ql;
}
@@ -612,7 +606,7 @@ QuestItemList* Loot::FillNonQuestNonFFAConditionalLoot(Player* player, bool pres
return NULL;
}
- PlayerNonQuestNonFFAConditionalItems[player->GetGUIDLow()] = ql;
+ PlayerNonQuestNonFFAConditionalItems[player->GetGUID().GetCounter()] = ql;
return ql;
}
@@ -663,7 +657,7 @@ void Loot::NotifyQuestItemRemoved(uint8 questIndex)
++i_next;
if (Player* player = ObjectAccessor::FindPlayer(*i))
{
- QuestItemMap::const_iterator pq = PlayerQuestItems.find(player->GetGUIDLow());
+ QuestItemMap::const_iterator pq = PlayerQuestItems.find(player->GetGUID().GetCounter());
if (pq != PlayerQuestItems.end() && pq->second)
{
// find where/if the player has the given item in it's vector
@@ -730,7 +724,7 @@ LootItem* Loot::LootItemInSlot(uint32 lootSlot, Player* player, QuestItem* *qite
if (lootSlot >= items.size())
{
uint32 questSlot = lootSlot - items.size();
- QuestItemMap::const_iterator itr = PlayerQuestItems.find(player->GetGUIDLow());
+ QuestItemMap::const_iterator itr = PlayerQuestItems.find(player->GetGUID().GetCounter());
if (itr != PlayerQuestItems.end() && questSlot < itr->second->size())
{
QuestItem* qitem2 = &itr->second->at(questSlot);
@@ -746,7 +740,7 @@ LootItem* Loot::LootItemInSlot(uint32 lootSlot, Player* player, QuestItem* *qite
is_looted = item->is_looted;
if (item->freeforall)
{
- QuestItemMap::const_iterator itr = PlayerFFAItems.find(player->GetGUIDLow());
+ QuestItemMap::const_iterator itr = PlayerFFAItems.find(player->GetGUID().GetCounter());
if (itr != PlayerFFAItems.end())
{
for (QuestItemList::const_iterator iter=itr->second->begin(); iter!= itr->second->end(); ++iter)
@@ -762,7 +756,7 @@ LootItem* Loot::LootItemInSlot(uint32 lootSlot, Player* player, QuestItem* *qite
}
else if (!item->conditions.empty())
{
- QuestItemMap::const_iterator itr = PlayerNonQuestNonFFAConditionalItems.find(player->GetGUIDLow());
+ QuestItemMap::const_iterator itr = PlayerNonQuestNonFFAConditionalItems.find(player->GetGUID().GetCounter());
if (itr != PlayerNonQuestNonFFAConditionalItems.end())
{
for (QuestItemList::const_iterator iter=itr->second->begin(); iter!= itr->second->end(); ++iter)
@@ -788,7 +782,7 @@ LootItem* Loot::LootItemInSlot(uint32 lootSlot, Player* player, QuestItem* *qite
uint32 Loot::GetMaxSlotInLootFor(Player* player) const
{
- QuestItemMap::const_iterator itr = PlayerQuestItems.find(player->GetGUIDLow());
+ QuestItemMap::const_iterator itr = PlayerQuestItems.find(player->GetGUID().GetCounter());
return items.size() + (itr != PlayerQuestItems.end() ? itr->second->size() : 0);
}
@@ -796,7 +790,7 @@ uint32 Loot::GetMaxSlotInLootFor(Player* player) const
bool Loot::hasItemFor(Player* player) const
{
QuestItemMap const& lootPlayerQuestItems = GetPlayerQuestItems();
- QuestItemMap::const_iterator q_itr = lootPlayerQuestItems.find(player->GetGUIDLow());
+ QuestItemMap::const_iterator q_itr = lootPlayerQuestItems.find(player->GetGUID().GetCounter());
if (q_itr != lootPlayerQuestItems.end())
{
QuestItemList* q_list = q_itr->second;
@@ -809,7 +803,7 @@ bool Loot::hasItemFor(Player* player) const
}
QuestItemMap const& lootPlayerFFAItems = GetPlayerFFAItems();
- QuestItemMap::const_iterator ffa_itr = lootPlayerFFAItems.find(player->GetGUIDLow());
+ QuestItemMap::const_iterator ffa_itr = lootPlayerFFAItems.find(player->GetGUID().GetCounter());
if (ffa_itr != lootPlayerFFAItems.end())
{
QuestItemList* ffa_list = ffa_itr->second;
@@ -822,7 +816,7 @@ bool Loot::hasItemFor(Player* player) const
}
QuestItemMap const& lootPlayerNonQuestNonFFAConditionalItems = GetPlayerNonQuestNonFFAConditionalItems();
- QuestItemMap::const_iterator nn_itr = lootPlayerNonQuestNonFFAConditionalItems.find(player->GetGUIDLow());
+ QuestItemMap::const_iterator nn_itr = lootPlayerNonQuestNonFFAConditionalItems.find(player->GetGUID().GetCounter());
if (nn_itr != lootPlayerNonQuestNonFFAConditionalItems.end())
{
QuestItemList* conditional_list = nn_itr->second;
@@ -970,7 +964,7 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv)
LootSlotType slotType = lv.permission == OWNER_PERMISSION ? LOOT_SLOT_TYPE_OWNER : LOOT_SLOT_TYPE_ALLOW_LOOT;
QuestItemMap const& lootPlayerQuestItems = l.GetPlayerQuestItems();
- QuestItemMap::const_iterator q_itr = lootPlayerQuestItems.find(lv.viewer->GetGUIDLow());
+ QuestItemMap::const_iterator q_itr = lootPlayerQuestItems.find(lv.viewer->GetGUID().GetCounter());
if (q_itr != lootPlayerQuestItems.end())
{
QuestItemList* q_list = q_itr->second;
@@ -1011,7 +1005,7 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv)
}
QuestItemMap const& lootPlayerFFAItems = l.GetPlayerFFAItems();
- QuestItemMap::const_iterator ffa_itr = lootPlayerFFAItems.find(lv.viewer->GetGUIDLow());
+ QuestItemMap::const_iterator ffa_itr = lootPlayerFFAItems.find(lv.viewer->GetGUID().GetCounter());
if (ffa_itr != lootPlayerFFAItems.end())
{
QuestItemList* ffa_list = ffa_itr->second;
@@ -1029,7 +1023,7 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv)
}
QuestItemMap const& lootPlayerNonQuestNonFFAConditionalItems = l.GetPlayerNonQuestNonFFAConditionalItems();
- QuestItemMap::const_iterator nn_itr = lootPlayerNonQuestNonFFAConditionalItems.find(lv.viewer->GetGUIDLow());
+ QuestItemMap::const_iterator nn_itr = lootPlayerNonQuestNonFFAConditionalItems.find(lv.viewer->GetGUID().GetCounter());
if (nn_itr != lootPlayerNonQuestNonFFAConditionalItems.end())
{
QuestItemList* conditional_list = nn_itr->second;
@@ -1161,7 +1155,7 @@ bool LootTemplate::LootGroup::HasQuestDropForPlayer(Player const* player) const
return false;
}
-void LootTemplate::LootGroup::CopyConditions(ConditionList /*conditions*/)
+void LootTemplate::LootGroup::CopyConditions(ConditionContainer /*conditions*/)
{
for (LootStoreItemList::iterator i = ExplicitlyChanced.begin(); i != ExplicitlyChanced.end(); ++i)
(*i)->conditions.clear();
@@ -1266,7 +1260,7 @@ void LootTemplate::AddEntry(LootStoreItem* item)
Entries.push_back(item);
}
-void LootTemplate::CopyConditions(const ConditionList& conditions)
+void LootTemplate::CopyConditions(const ConditionContainer& conditions)
{
for (LootStoreItemList::iterator i = Entries.begin(); i != Entries.end(); ++i)
(*i)->conditions.clear();
diff --git a/src/server/game/Loot/LootMgr.h b/src/server/game/Loot/LootMgr.h
index 7d7580fd49f..08cd224cd0b 100644
--- a/src/server/game/Loot/LootMgr.h
+++ b/src/server/game/Loot/LootMgr.h
@@ -132,7 +132,7 @@ struct LootStoreItem
uint8 groupid : 7;
uint8 mincount; // mincount for drop items
uint8 maxcount; // max drop count for the item mincount or Ref multiplicator
- ConditionList conditions; // additional loot condition
+ ConditionContainer conditions; // additional loot condition
// Constructor
// displayid is filled in IsValid() which must be called after
@@ -146,14 +146,14 @@ struct LootStoreItem
// Checks correctness of values
};
-typedef std::set<uint32> AllowedLooterSet;
+typedef std::set<ObjectGuid::LowType> AllowedLooterSet;
struct LootItem
{
uint32 itemid;
uint32 randomSuffix;
int32 randomPropertyId;
- ConditionList conditions; // additional loot condition
+ ConditionContainer conditions; // additional loot condition
AllowedLooterSet allowedGUIDs;
uint8 count : 8;
bool is_looted : 1;
@@ -252,7 +252,7 @@ class LootTemplate
void AddEntry(LootStoreItem* item);
// Rolls for every item in the template and adds the rolled items the the loot
void Process(Loot& loot, bool rate, uint16 lootMode, uint8 groupId = 0) const;
- void CopyConditions(const ConditionList& conditions);
+ void CopyConditions(const ConditionContainer& conditions);
void CopyConditions(LootItem* li) const;
// True if template includes at least 1 quest drop entry
diff --git a/src/server/game/Mails/Mail.cpp b/src/server/game/Mails/Mail.cpp
index be0310017f7..78cd4d3692c 100644
--- a/src/server/game/Mails/Mail.cpp
+++ b/src/server/game/Mails/Mail.cpp
@@ -22,7 +22,6 @@
#include "World.h"
#include "ObjectMgr.h"
#include "Player.h"
-#include "Unit.h"
#include "BattlegroundMgr.h"
#include "Item.h"
#include "AuctionHouseMgr.h"
@@ -46,7 +45,7 @@ MailSender::MailSender(Object* sender, MailStationery stationery) : m_stationery
break;*/
case TYPEID_PLAYER:
m_messageType = MAIL_NORMAL;
- m_senderId = sender->GetGUIDLow();
+ m_senderId = sender->GetGUID().GetCounter();
break;
default:
m_messageType = MAIL_NORMAL;
@@ -68,19 +67,19 @@ MailSender::MailSender(Player* sender)
{
m_messageType = MAIL_NORMAL;
m_stationery = sender->IsGameMaster() ? MAIL_STATIONERY_GM : MAIL_STATIONERY_DEFAULT;
- m_senderId = sender->GetGUIDLow();
+ m_senderId = sender->GetGUID().GetCounter();
}
-MailReceiver::MailReceiver(Player* receiver) : m_receiver(receiver), m_receiver_lowguid(receiver->GetGUIDLow()) { }
+MailReceiver::MailReceiver(Player* receiver) : m_receiver(receiver), m_receiver_lowguid(receiver->GetGUID().GetCounter()) { }
-MailReceiver::MailReceiver(Player* receiver, uint32 receiver_lowguid) : m_receiver(receiver), m_receiver_lowguid(receiver_lowguid)
+MailReceiver::MailReceiver(Player* receiver, ObjectGuid::LowType receiver_lowguid) : m_receiver(receiver), m_receiver_lowguid(receiver_lowguid)
{
- ASSERT(!receiver || receiver->GetGUIDLow() == receiver_lowguid);
+ ASSERT(!receiver || receiver->GetGUID().GetCounter() == receiver_lowguid);
}
MailDraft& MailDraft::AddItem(Item* item)
{
- m_items[item->GetGUIDLow()] = item; return *this;
+ m_items[item->GetGUID().GetCounter()] = item; return *this;
}
void MailDraft::prepareItems(Player* receiver, SQLTransaction& trans)
@@ -118,7 +117,7 @@ void MailDraft::deleteIncludedItems(SQLTransaction& trans, bool inDB /*= false*/
if (inDB)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE);
- stmt->setUInt32(0, item->GetGUIDLow());
+ stmt->setUInt32(0, item->GetGUID().GetCounter());
trans->Append(stmt);
}
@@ -128,9 +127,9 @@ void MailDraft::deleteIncludedItems(SQLTransaction& trans, bool inDB /*= false*/
m_items.clear();
}
-void MailDraft::SendReturnToSender(uint32 sender_acc, uint32 sender_guid, uint32 receiver_guid, SQLTransaction& trans)
+void MailDraft::SendReturnToSender(uint32 sender_acc, ObjectGuid::LowType sender_guid, ObjectGuid::LowType receiver_guid, SQLTransaction& trans)
{
- ObjectGuid receiverGuid(HIGHGUID_PLAYER, receiver_guid);
+ ObjectGuid receiverGuid(HighGuid::Player, receiver_guid);
Player* receiver = ObjectAccessor::FindConnectedPlayer(receiverGuid);
uint32 rc_account = 0;
@@ -159,7 +158,7 @@ void MailDraft::SendReturnToSender(uint32 sender_acc, uint32 sender_guid, uint32
// owner in data will set at mail receive and item extracting
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ITEM_OWNER);
stmt->setUInt32(0, receiver_guid);
- stmt->setUInt32(1, item->GetGUIDLow());
+ stmt->setUInt32(1, item->GetGUID().GetCounter());
trans->Append(stmt);
}
}
@@ -227,7 +226,7 @@ void MailDraft::SendMailTo(SQLTransaction& trans, MailReceiver const& receiver,
Item* pItem = mailItemIter->second;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_MAIL_ITEM);
stmt->setUInt32(0, mailId);
- stmt->setUInt32(1, pItem->GetGUIDLow());
+ stmt->setUInt32(1, pItem->GetGUID().GetCounter());
stmt->setUInt32(2, receiver.GetPlayerGUIDLow());
trans->Append(stmt);
}
@@ -250,7 +249,7 @@ void MailDraft::SendMailTo(SQLTransaction& trans, MailReceiver const& receiver,
for (MailItemMap::const_iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter)
{
Item* item = mailItemIter->second;
- m->AddItem(item->GetGUIDLow(), item->GetEntry());
+ m->AddItem(item->GetGUID().GetCounter(), item->GetEntry());
}
m->messageType = sender.GetMailMessageType();
diff --git a/src/server/game/Mails/Mail.h b/src/server/game/Mails/Mail.h
index f4f155c5926..f044996bd0a 100644
--- a/src/server/game/Mails/Mail.h
+++ b/src/server/game/Mails/Mail.h
@@ -20,6 +20,7 @@
#define TRINITY_MAIL_H
#include "Common.h"
+#include "ObjectGuid.h"
#include <map>
struct AuctionEntry;
@@ -81,7 +82,7 @@ enum MailShowFlags
class MailSender
{
public: // Constructors
- MailSender(MailMessageType messageType, uint32 sender_guidlow_or_entry, MailStationery stationery = MAIL_STATIONERY_DEFAULT)
+ MailSender(MailMessageType messageType, ObjectGuid::LowType sender_guidlow_or_entry, MailStationery stationery = MAIL_STATIONERY_DEFAULT)
: m_messageType(messageType), m_senderId(sender_guidlow_or_entry), m_stationery(stationery)
{
}
@@ -91,31 +92,31 @@ class MailSender
MailSender(Player* sender);
public: // Accessors
MailMessageType GetMailMessageType() const { return m_messageType; }
- uint32 GetSenderId() const { return m_senderId; }
+ ObjectGuid::LowType GetSenderId() const { return m_senderId; }
MailStationery GetStationery() const { return m_stationery; }
private:
MailMessageType m_messageType;
- uint32 m_senderId; // player low guid or other object entry
+ ObjectGuid::LowType m_senderId; // player low guid or other object entry
MailStationery m_stationery;
};
class MailReceiver
{
public: // Constructors
- explicit MailReceiver(uint32 receiver_lowguid) : m_receiver(NULL), m_receiver_lowguid(receiver_lowguid) { }
+ explicit MailReceiver(ObjectGuid::LowType receiver_lowguid) : m_receiver(NULL), m_receiver_lowguid(receiver_lowguid) { }
MailReceiver(Player* receiver);
- MailReceiver(Player* receiver, uint32 receiver_lowguid);
+ MailReceiver(Player* receiver, ObjectGuid::LowType receiver_lowguid);
public: // Accessors
Player* GetPlayer() const { return m_receiver; }
- uint32 GetPlayerGUIDLow() const { return m_receiver_lowguid; }
+ ObjectGuid::LowType GetPlayerGUIDLow() const { return m_receiver_lowguid; }
private:
Player* m_receiver;
- uint32 m_receiver_lowguid;
+ ObjectGuid::LowType m_receiver_lowguid;
};
class MailDraft
{
- typedef std::map<uint32, Item*> MailItemMap;
+ typedef std::map<ObjectGuid::LowType, Item*> MailItemMap;
public: // Constructors
explicit MailDraft(uint16 mailTemplateId, bool need_items = true)
@@ -136,7 +137,7 @@ class MailDraft
MailDraft& AddCOD(uint32 COD) { m_COD = COD; return *this; }
public: // finishers
- void SendReturnToSender(uint32 sender_acc, uint32 sender_guid, uint32 receiver_guid, SQLTransaction& trans);
+ void SendReturnToSender(uint32 sender_acc, ObjectGuid::LowType sender_guid, ObjectGuid::LowType receiver_guid, SQLTransaction& trans);
void SendMailTo(SQLTransaction& trans, MailReceiver const& receiver, MailSender const& sender, MailCheckMask checked = MAIL_CHECK_MASK_NONE, uint32 deliver_delay = 0);
private:
@@ -156,7 +157,7 @@ class MailDraft
struct MailItemInfo
{
- uint32 item_guid;
+ ObjectGuid::LowType item_guid;
uint32 item_template;
};
typedef std::vector<MailItemInfo> MailItemInfoVec;
@@ -167,12 +168,12 @@ struct Mail
uint8 messageType;
uint8 stationery;
uint16 mailTemplateId;
- uint32 sender;
- uint32 receiver;
+ ObjectGuid::LowType sender;
+ ObjectGuid::LowType receiver;
std::string subject;
std::string body;
std::vector<MailItemInfo> items;
- std::vector<uint32> removedItems;
+ std::vector<ObjectGuid::LowType> removedItems;
time_t expire_time;
time_t deliver_time;
uint32 money;
@@ -180,7 +181,7 @@ struct Mail
uint32 checked;
MailState state;
- void AddItem(uint32 itemGuidLow, uint32 item_template)
+ void AddItem(ObjectGuid::LowType itemGuidLow, uint32 item_template)
{
MailItemInfo mii;
mii.item_guid = itemGuidLow;
@@ -188,7 +189,7 @@ struct Mail
items.push_back(mii);
}
- bool RemoveItem(uint32 item_guid)
+ bool RemoveItem(ObjectGuid::LowType item_guid)
{
for (MailItemInfoVec::iterator itr = items.begin(); itr != items.end(); ++itr)
{
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index c1a462497cd..6fbef752228 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -50,9 +50,9 @@ GridState* si_GridStates[MAX_GRID_STATE];
Map::~Map()
{
- sScriptMgr->OnDestroyMap(this);
+ // UnloadAll must be called before deleting the map
- UnloadAll();
+ sScriptMgr->OnDestroyMap(this);
while (!i_worldObjects.empty())
{
@@ -299,6 +299,25 @@ void Map::AddToGrid(DynamicObject* obj, Cell const& cell)
obj->SetCurrentCell(cell);
}
+template<>
+void Map::AddToGrid(Corpse* obj, Cell const& cell)
+{
+ NGridType* grid = getNGrid(cell.GridX(), cell.GridY());
+ // Corpses are a special object type - they can be added to grid via a call to AddToMap
+ // or loaded through ObjectGridLoader.
+ // Both corpses loaded from database and these freshly generated by Player::CreateCoprse are added to _corpsesByCell
+ // ObjectGridLoader loads all corpses from _corpsesByCell even if they were already added to grid before it was loaded
+ // so we need to explicitly check it here (Map::AddToGrid is only called from Player::BuildPlayerRepop, not from ObjectGridLoader)
+ // to avoid failing an assertion in GridObject::AddToGrid
+ if (grid->isGridObjectDataLoaded())
+ {
+ if (obj->IsWorldObject())
+ grid->GetGridType(cell.CellX(), cell.CellY()).AddWorldObject(obj);
+ else
+ grid->GetGridType(cell.CellX(), cell.CellY()).AddGridObject(obj);
+ }
+}
+
template<class T>
void Map::SwitchGridContainers(T* /*obj*/, bool /*on*/) { }
@@ -317,7 +336,15 @@ void Map::SwitchGridContainers(Creature* obj, bool on)
if (!IsGridLoaded(GridCoord(cell.data.Part.grid_x, cell.data.Part.grid_y)))
return;
- TC_LOG_DEBUG("maps", "Switch object %s from grid[%u, %u] %u", obj->GetGUID().ToString().c_str(), cell.data.Part.grid_x, cell.data.Part.grid_y, on);
+ if (sLog->ShouldLog("maps", LOG_LEVEL_DEBUG))
+ {
+ // Extract bitfield values
+ uint32 const grid_x = cell.data.Part.grid_x;
+ uint32 const grid_y = cell.data.Part.grid_y;
+
+ TC_LOG_DEBUG("maps", "Switch object %s from grid[%u, %u] %u", obj->GetGUID().ToString().c_str(), grid_x, grid_y, on);
+ }
+
NGridType *ngrid = getNGrid(cell.GridX(), cell.GridY());
ASSERT(ngrid != NULL);
@@ -354,7 +381,15 @@ void Map::SwitchGridContainers(GameObject* obj, bool on)
if (!IsGridLoaded(GridCoord(cell.data.Part.grid_x, cell.data.Part.grid_y)))
return;
- TC_LOG_DEBUG("maps", "Switch object %s from grid[%u, %u] %u", obj->GetGUID().ToString().c_str(), cell.data.Part.grid_x, cell.data.Part.grid_y, on);
+ if (sLog->ShouldLog("maps", LOG_LEVEL_DEBUG))
+ {
+ // Extract bitfield values
+ uint32 const grid_x = cell.data.Part.grid_x;
+ uint32 const grid_y = cell.data.Part.grid_y;
+
+ TC_LOG_DEBUG("maps", "Switch object %s from grid[%u, %u] %u", obj->GetGUID().ToString().c_str(), grid_x, grid_y, on);
+ }
+
NGridType *ngrid = getNGrid(cell.GridX(), cell.GridY());
ASSERT(ngrid != NULL);
@@ -384,11 +419,18 @@ void Map::DeleteFromWorld(T* obj)
template<>
void Map::DeleteFromWorld(Player* player)
{
- sObjectAccessor->RemoveObject(player);
- sObjectAccessor->RemoveUpdateObject(player); /// @todo I do not know why we need this, it should be removed in ~Object anyway
+ ObjectAccessor::RemoveObject(player);
+ RemoveUpdateObject(player); /// @todo I do not know why we need this, it should be removed in ~Object anyway
delete player;
}
+template<>
+void Map::DeleteFromWorld(Transport* transport)
+{
+ ObjectAccessor::RemoveObject(transport);
+ delete transport;
+}
+
void Map::EnsureGridCreated(const GridCoord &p)
{
std::lock_guard<std::mutex> lock(_gridLock);
@@ -452,8 +494,6 @@ bool Map::EnsureGridLoaded(const Cell &cell)
ObjectGridLoader loader(*grid, this, cell);
loader.LoadN();
- // Add resurrectable corpses to world object list in grid
- sObjectAccessor->AddCorpsesToGrid(GridCoord(cell.GridX(), cell.GridY()), grid->GetGridType(cell.CellX(), cell.CellY()), this);
Balance();
return true;
}
@@ -471,7 +511,7 @@ bool Map::AddPlayerToMap(Player* player)
CellCoord cellCoord = Trinity::ComputeCellCoord(player->GetPositionX(), player->GetPositionY());
if (!cellCoord.IsCoordValid())
{
- TC_LOG_ERROR("maps", "Map::Add: Player (GUID: %u) has invalid coordinates X:%f Y:%f grid cell [%u:%u]", player->GetGUIDLow(), player->GetPositionX(), player->GetPositionY(), cellCoord.x_coord, cellCoord.y_coord);
+ TC_LOG_ERROR("maps", "Map::Add: Player (GUID: %u) has invalid coordinates X:%f Y:%f grid cell [%u:%u]", player->GetGUID().GetCounter(), player->GetPositionX(), player->GetPositionY(), cellCoord.x_coord, cellCoord.y_coord);
return false;
}
@@ -491,6 +531,9 @@ bool Map::AddPlayerToMap(Player* player)
player->m_clientGUIDs.clear();
player->UpdateObjectVisibility(false);
+ if (player->IsAlive())
+ ConvertCorpseToBones(player->GetGUID());
+
sScriptMgr->OnPlayerEnterMap(this, player);
return true;
}
@@ -662,6 +705,26 @@ void Map::Update(const uint32 t_diff)
player->Update(t_diff);
VisitNearbyCellsOf(player, grid_object_update, world_object_update);
+
+ // Handle updates for creatures in combat with player and are more than 60 yards away
+ if (player->IsInCombat())
+ {
+ std::vector<Creature*> updateList;
+ HostileReference* ref = player->getHostileRefManager().getFirst();
+
+ while (ref)
+ {
+ if (Unit* unit = ref->GetSource()->GetOwner())
+ if (unit->ToCreature() && unit->GetMapId() == player->GetMapId() && !unit->IsWithinDistInMap(player, GetVisibilityRange(), false))
+ updateList.push_back(unit->ToCreature());
+
+ ref = ref->next();
+ }
+
+ // Process deferred update list for player
+ for (Creature* c : updateList)
+ VisitNearbyCellsOf(c, grid_object_update, world_object_update);
+ }
}
// non-player active objects, increasing iterator in the loop in case of object removal
@@ -687,6 +750,8 @@ void Map::Update(const uint32 t_diff)
obj->Update(t_diff);
}
+ SendObjectUpdates();
+
///- Process necessary scripts
if (!m_scriptSchedule.empty())
{
@@ -923,7 +988,7 @@ void Map::CreatureRelocation(Creature* creature, float x, float y, float z, floa
if (old_cell.DiffCell(new_cell) || old_cell.DiffGrid(new_cell))
{
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "Creature (GUID: %u Entry: %u) added to moving list from grid[%u, %u]cell[%u, %u] to grid[%u, %u]cell[%u, %u].", creature->GetGUIDLow(), creature->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());
+ TC_LOG_DEBUG("maps", "Creature (GUID: %u Entry: %u) added to moving list from grid[%u, %u]cell[%u, %u] to grid[%u, %u]cell[%u, %u].", creature->GetGUID().GetCounter(), creature->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
AddCreatureToMoveList(creature, x, y, z, ang);
// in diffcell/diffgrid case notifiers called at finishing move creature in Map::MoveAllCreaturesInMoveList
@@ -955,7 +1020,7 @@ void Map::GameObjectRelocation(GameObject* go, float x, float y, float z, float
if (old_cell.DiffCell(new_cell) || old_cell.DiffGrid(new_cell))
{
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "GameObject (GUID: %u Entry: %u) added to moving list from grid[%u, %u]cell[%u, %u] to grid[%u, %u]cell[%u, %u].", go->GetGUIDLow(), go->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());
+ TC_LOG_DEBUG("maps", "GameObject (GUID: %u Entry: %u) added to moving list from grid[%u, %u]cell[%u, %u] to grid[%u, %u]cell[%u, %u].", go->GetGUID().GetCounter(), go->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
AddGameObjectToMoveList(go, x, y, z, orientation);
// in diffcell/diffgrid case notifiers called at finishing move go in Map::MoveAllGameObjectsInMoveList
@@ -988,7 +1053,7 @@ void Map::DynamicObjectRelocation(DynamicObject* dynObj, float x, float y, float
if (old_cell.DiffCell(new_cell) || old_cell.DiffGrid(new_cell))
{
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "GameObject (GUID: %u) added to moving list from grid[%u, %u]cell[%u, %u] to grid[%u, %u]cell[%u, %u].", dynObj->GetGUIDLow(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY());
+ TC_LOG_DEBUG("maps", "GameObject (GUID: %u) added to moving list from grid[%u, %u]cell[%u, %u] to grid[%u, %u]cell[%u, %u].", dynObj->GetGUID().GetCounter(), 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
AddDynamicObjectToMoveList(dynObj, x, y, z, orientation);
// in diffcell/diffgrid case notifiers called at finishing move dynObj in Map::MoveAllGameObjectsInMoveList
@@ -1099,7 +1164,7 @@ void Map::MoveAllCreaturesInMoveList()
{
// ... or unload (if respawn grid also not loaded)
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "Creature (GUID: %u Entry: %u) cannot be move to unloaded respawn grid.", c->GetGUIDLow(), c->GetEntry());
+ TC_LOG_DEBUG("maps", "Creature (GUID: %u Entry: %u) cannot be move to unloaded respawn grid.", c->GetGUID().GetCounter(), c->GetEntry());
#endif
//AddObjectToRemoveList(Pet*) should only be called in Pet::Remove
//This may happen when a player just logs in and a pet moves to a nearby unloaded cell
@@ -1153,7 +1218,7 @@ void Map::MoveAllGameObjectsInMoveList()
{
// ... or unload (if respawn grid also not loaded)
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "GameObject (GUID: %u Entry: %u) cannot be move to unloaded respawn grid.", go->GetGUIDLow(), go->GetEntry());
+ TC_LOG_DEBUG("maps", "GameObject (GUID: %u Entry: %u) cannot be move to unloaded respawn grid.", go->GetGUID().GetCounter(), go->GetEntry());
#endif
AddObjectToRemoveList(go);
}
@@ -1192,7 +1257,7 @@ void Map::MoveAllDynamicObjectsInMoveList()
else
{
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "DynamicObject (GUID: %u) cannot be moved to unloaded grid.", dynObj->GetGUIDLow());
+ TC_LOG_DEBUG("maps", "DynamicObject (GUID: %u) cannot be moved to unloaded grid.", dynObj->GetGUID().GetCounter());
#endif
}
}
@@ -1210,7 +1275,7 @@ bool Map::CreatureCellRelocation(Creature* c, Cell new_cell)
if (old_cell.DiffCell(new_cell))
{
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "Creature (GUID: %u Entry: %u) moved in grid[%u, %u] from cell[%u, %u] to cell[%u, %u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.CellX(), new_cell.CellY());
+ TC_LOG_DEBUG("maps", "Creature (GUID: %u Entry: %u) moved in grid[%u, %u] from cell[%u, %u] to cell[%u, %u].", c->GetGUID().GetCounter(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.CellX(), new_cell.CellY());
#endif
c->RemoveFromGrid();
@@ -1219,7 +1284,7 @@ bool Map::CreatureCellRelocation(Creature* c, Cell new_cell)
else
{
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "Creature (GUID: %u Entry: %u) moved in same grid[%u, %u]cell[%u, %u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY());
+ TC_LOG_DEBUG("maps", "Creature (GUID: %u Entry: %u) moved in same grid[%u, %u]cell[%u, %u].", c->GetGUID().GetCounter(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY());
#endif
}
@@ -1232,7 +1297,7 @@ bool Map::CreatureCellRelocation(Creature* c, Cell new_cell)
EnsureGridLoadedForActiveObject(new_cell, c);
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "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());
+ TC_LOG_DEBUG("maps", "Active creature (GUID: %u Entry: %u) moved from grid[%u, %u]cell[%u, %u] to grid[%u, %u]cell[%u, %u].", c->GetGUID().GetCounter(), 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
c->RemoveFromGrid();
@@ -1245,7 +1310,7 @@ bool Map::CreatureCellRelocation(Creature* c, Cell new_cell)
if (IsGridLoaded(GridCoord(new_cell.GridX(), new_cell.GridY())))
{
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "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());
+ TC_LOG_DEBUG("maps", "Creature (GUID: %u Entry: %u) moved from grid[%u, %u]cell[%u, %u] to grid[%u, %u]cell[%u, %u].", c->GetGUID().GetCounter(), 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
c->RemoveFromGrid();
@@ -1257,7 +1322,7 @@ bool Map::CreatureCellRelocation(Creature* c, Cell new_cell)
// fail to move: normal creature attempt move to unloaded grid
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "Creature (GUID: %u Entry: %u) attempted to 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());
+ TC_LOG_DEBUG("maps", "Creature (GUID: %u Entry: %u) attempted to move from grid[%u, %u]cell[%u, %u] to unloaded grid[%u, %u]cell[%u, %u].", c->GetGUID().GetCounter(), 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;
}
@@ -1271,7 +1336,7 @@ bool Map::GameObjectCellRelocation(GameObject* go, Cell new_cell)
if (old_cell.DiffCell(new_cell))
{
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "GameObject (GUID: %u Entry: %u) moved in grid[%u, %u] from cell[%u, %u] to cell[%u, %u].", go->GetGUIDLow(), go->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.CellX(), new_cell.CellY());
+ TC_LOG_DEBUG("maps", "GameObject (GUID: %u Entry: %u) moved in grid[%u, %u] from cell[%u, %u] to cell[%u, %u].", go->GetGUID().GetCounter(), go->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.CellX(), new_cell.CellY());
#endif
go->RemoveFromGrid();
@@ -1280,7 +1345,7 @@ bool Map::GameObjectCellRelocation(GameObject* go, Cell new_cell)
else
{
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "GameObject (GUID: %u Entry: %u) moved in same grid[%u, %u]cell[%u, %u].", go->GetGUIDLow(), go->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY());
+ TC_LOG_DEBUG("maps", "GameObject (GUID: %u Entry: %u) moved in same grid[%u, %u]cell[%u, %u].", go->GetGUID().GetCounter(), go->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY());
#endif
}
@@ -1293,7 +1358,7 @@ bool Map::GameObjectCellRelocation(GameObject* go, Cell new_cell)
EnsureGridLoadedForActiveObject(new_cell, go);
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "Active GameObject (GUID: %u Entry: %u) moved from grid[%u, %u]cell[%u, %u] to grid[%u, %u]cell[%u, %u].", go->GetGUIDLow(), go->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());
+ TC_LOG_DEBUG("maps", "Active GameObject (GUID: %u Entry: %u) moved from grid[%u, %u]cell[%u, %u] to grid[%u, %u]cell[%u, %u].", go->GetGUID().GetCounter(), go->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
go->RemoveFromGrid();
@@ -1306,7 +1371,7 @@ bool Map::GameObjectCellRelocation(GameObject* go, Cell new_cell)
if (IsGridLoaded(GridCoord(new_cell.GridX(), new_cell.GridY())))
{
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "GameObject (GUID: %u Entry: %u) moved from grid[%u, %u]cell[%u, %u] to grid[%u, %u]cell[%u, %u].", go->GetGUIDLow(), go->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());
+ TC_LOG_DEBUG("maps", "GameObject (GUID: %u Entry: %u) moved from grid[%u, %u]cell[%u, %u] to grid[%u, %u]cell[%u, %u].", go->GetGUID().GetCounter(), go->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
go->RemoveFromGrid();
@@ -1318,7 +1383,7 @@ bool Map::GameObjectCellRelocation(GameObject* go, Cell new_cell)
// fail to move: normal GameObject attempt move to unloaded grid
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "GameObject (GUID: %u Entry: %u) attempted to move from grid[%u, %u]cell[%u, %u] to unloaded grid[%u, %u]cell[%u, %u].", go->GetGUIDLow(), go->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());
+ TC_LOG_DEBUG("maps", "GameObject (GUID: %u Entry: %u) attempted to move from grid[%u, %u]cell[%u, %u] to unloaded grid[%u, %u]cell[%u, %u].", go->GetGUID().GetCounter(), go->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;
}
@@ -1332,7 +1397,7 @@ bool Map::DynamicObjectCellRelocation(DynamicObject* go, Cell new_cell)
if (old_cell.DiffCell(new_cell))
{
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "DynamicObject (GUID: %u) moved in grid[%u, %u] from cell[%u, %u] to cell[%u, %u].", go->GetGUIDLow(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.CellX(), new_cell.CellY());
+ TC_LOG_DEBUG("maps", "DynamicObject (GUID: %u) moved in grid[%u, %u] from cell[%u, %u] to cell[%u, %u].", go->GetGUID().GetCounter(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.CellX(), new_cell.CellY());
#endif
go->RemoveFromGrid();
@@ -1341,7 +1406,7 @@ bool Map::DynamicObjectCellRelocation(DynamicObject* go, Cell new_cell)
else
{
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "DynamicObject (GUID: %u) moved in same grid[%u, %u]cell[%u, %u].", go->GetGUIDLow(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY());
+ TC_LOG_DEBUG("maps", "DynamicObject (GUID: %u) moved in same grid[%u, %u]cell[%u, %u].", go->GetGUID().GetCounter(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY());
#endif
}
@@ -1354,7 +1419,7 @@ bool Map::DynamicObjectCellRelocation(DynamicObject* go, Cell new_cell)
EnsureGridLoadedForActiveObject(new_cell, go);
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "Active DynamicObject (GUID: %u) moved from grid[%u, %u]cell[%u, %u] to grid[%u, %u]cell[%u, %u].", go->GetGUIDLow(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY());
+ TC_LOG_DEBUG("maps", "Active DynamicObject (GUID: %u) moved from grid[%u, %u]cell[%u, %u] to grid[%u, %u]cell[%u, %u].", go->GetGUID().GetCounter(), 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
go->RemoveFromGrid();
@@ -1367,7 +1432,7 @@ bool Map::DynamicObjectCellRelocation(DynamicObject* go, Cell new_cell)
if (IsGridLoaded(GridCoord(new_cell.GridX(), new_cell.GridY())))
{
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "DynamicObject (GUID: %u) moved from grid[%u, %u]cell[%u, %u] to grid[%u, %u]cell[%u, %u].", go->GetGUIDLow(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY());
+ TC_LOG_DEBUG("maps", "DynamicObject (GUID: %u) moved from grid[%u, %u]cell[%u, %u] to grid[%u, %u]cell[%u, %u].", go->GetGUID().GetCounter(), 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
go->RemoveFromGrid();
@@ -1379,7 +1444,7 @@ bool Map::DynamicObjectCellRelocation(DynamicObject* go, Cell new_cell)
// fail to move: normal GameObject attempt move to unloaded grid
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "DynamicObject (GUID: %u) attempted to move from grid[%u, %u]cell[%u, %u] to unloaded grid[%u, %u]cell[%u, %u].", go->GetGUIDLow(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY());
+ TC_LOG_DEBUG("maps", "DynamicObject (GUID: %u) attempted to move from grid[%u, %u]cell[%u, %u] to unloaded grid[%u, %u]cell[%u, %u].", go->GetGUID().GetCounter(), 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;
}
@@ -1398,7 +1463,7 @@ bool Map::CreatureRespawnRelocation(Creature* c, bool diffGridOnly)
c->GetMotionMaster()->Clear();
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "Creature (GUID: %u Entry: %u) moved from grid[%u, %u]cell[%u, %u] to respawn grid[%u, %u]cell[%u, %u].", c->GetGUIDLow(), c->GetEntry(), c->GetCurrentCell().GridX(), c->GetCurrentCell().GridY(), c->GetCurrentCell().CellX(), c->GetCurrentCell().CellY(), resp_cell.GridX(), resp_cell.GridY(), resp_cell.CellX(), resp_cell.CellY());
+ TC_LOG_DEBUG("maps", "Creature (GUID: %u Entry: %u) moved from grid[%u, %u]cell[%u, %u] to respawn grid[%u, %u]cell[%u, %u].", c->GetGUID().GetCounter(), c->GetEntry(), c->GetCurrentCell().GridX(), c->GetCurrentCell().GridY(), c->GetCurrentCell().CellX(), c->GetCurrentCell().CellY(), resp_cell.GridX(), resp_cell.GridY(), resp_cell.CellX(), resp_cell.CellY());
#endif
// teleport it to respawn point (like normal respawn if player see)
@@ -1425,7 +1490,7 @@ bool Map::GameObjectRespawnRelocation(GameObject* go, bool diffGridOnly)
return true;
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "GameObject (GUID: %u Entry: %u) moved from grid[%u, %u]cell[%u, %u] to respawn grid[%u, %u]cell[%u, %u].", go->GetGUIDLow(), go->GetEntry(), go->GetCurrentCell().GridX(), go->GetCurrentCell().GridY(), go->GetCurrentCell().CellX(), go->GetCurrentCell().CellY(), resp_cell.GridX(), resp_cell.GridY(), resp_cell.CellX(), resp_cell.CellY());
+ TC_LOG_DEBUG("maps", "GameObject (GUID: %u Entry: %u) moved from grid[%u, %u]cell[%u, %u] to respawn grid[%u, %u]cell[%u, %u].", go->GetGUID().GetCounter(), go->GetEntry(), go->GetCurrentCell().GridX(), go->GetCurrentCell().GridY(), go->GetCurrentCell().CellX(), go->GetCurrentCell().CellY(), resp_cell.GridX(), resp_cell.GridY(), resp_cell.CellX(), resp_cell.CellY());
#endif
// teleport it to respawn point (like normal respawn if player see)
@@ -1555,6 +1620,20 @@ void Map::UnloadAll()
RemoveFromMap<Transport>(transport, true);
}
+
+ for (auto& cellCorpsePair : _corpsesByCell)
+ {
+ for (Corpse* corpse : cellCorpsePair.second)
+ {
+ corpse->RemoveFromWorld();
+ corpse->ResetMap();
+ delete corpse;
+ }
+ }
+
+ _corpsesByCell.clear();
+ _corpsesByPlayer.clear();
+ _corpseBones.clear();
}
// *****************************
@@ -2461,7 +2540,7 @@ bool Map::CheckGridIntegrity(Creature* c, bool moved) const
if (xy_cell != cur_cell)
{
TC_LOG_DEBUG("maps", "Creature (GUID: %u) X: %f Y: %f (%s) is in grid[%u, %u]cell[%u, %u] instead of grid[%u, %u]cell[%u, %u]",
- c->GetGUIDLow(),
+ c->GetGUID().GetCounter(),
c->GetPositionX(), c->GetPositionY(), (moved ? "final" : "original"),
cur_cell.GridX(), cur_cell.GridY(), cur_cell.CellX(), cur_cell.CellY(),
xy_cell.GridX(), xy_cell.GridY(), xy_cell.CellX(), xy_cell.CellY());
@@ -2500,7 +2579,7 @@ void Map::UpdateObjectsVisibilityFor(Player* player, Cell cell, CellCoord cellpa
void Map::SendInitSelf(Player* player)
{
- TC_LOG_DEBUG("maps", "Creating player data for himself %u", player->GetGUIDLow());
+ TC_LOG_DEBUG("maps", "Creating player data for himself %u", player->GetGUID().GetCounter());
UpdateData data;
@@ -2555,11 +2634,33 @@ inline void Map::setNGrid(NGridType *grid, uint32 x, uint32 y)
if (x >= MAX_NUMBER_OF_GRIDS || y >= MAX_NUMBER_OF_GRIDS)
{
TC_LOG_ERROR("maps", "map::setNGrid() Invalid grid coordinates found: %d, %d!", x, y);
- ASSERT(false);
+ ABORT();
}
i_grids[x][y] = grid;
}
+void Map::SendObjectUpdates()
+{
+ UpdateDataMapType update_players;
+
+ while (!_updateObjects.empty())
+ {
+ Object* obj = *_updateObjects.begin();
+ ASSERT(obj->IsInWorld());
+
+ _updateObjects.erase(_updateObjects.begin());
+ obj->BuildUpdate(update_players);
+ }
+
+ WorldPacket packet; // here we allocate a std::vector with a size of 0x10000
+ for (UpdateDataMapType::iterator iter = update_players.begin(); iter != update_players.end(); ++iter)
+ {
+ iter->second.BuildPacket(&packet);
+ iter->first->GetSession()->SendPacket(&packet);
+ packet.clear(); // clean the string
+ }
+}
+
void Map::DelayedUpdate(const uint32 t_diff)
{
for (_transportsUpdateIter = _transports.begin(); _transportsUpdateIter != _transports.end();)
@@ -2597,7 +2698,7 @@ void Map::AddObjectToRemoveList(WorldObject* obj)
obj->CleanupsBeforeDelete(false); // remove or simplify at least cross referenced links
i_objectsToRemove.insert(obj);
- //TC_LOG_DEBUG("maps", "Object (GUID: %u TypeId: %u) added to removing list.", obj->GetGUIDLow(), obj->GetTypeId());
+ //TC_LOG_DEBUG("maps", "Object (GUID: %u TypeId: %u) added to removing list.", obj->GetGUID().GetCounter(), obj->GetTypeId());
}
void Map::AddObjectToSwitchList(WorldObject* obj, bool on)
@@ -2614,7 +2715,7 @@ void Map::AddObjectToSwitchList(WorldObject* obj, bool on)
else if (itr->second != on)
i_objectsToSwitch.erase(itr);
else
- ASSERT(false);
+ ABORT();
}
void Map::RemoveAllObjectsInRemoveList()
@@ -2654,7 +2755,7 @@ void Map::RemoveAllObjectsInRemoveList()
{
Corpse* corpse = ObjectAccessor::GetCorpse(*obj, obj->GetGUID());
if (!corpse)
- TC_LOG_ERROR("maps", "Tried to delete corpse/bones %u that is not in map.", obj->GetGUIDLow());
+ TC_LOG_ERROR("maps", "Tried to delete corpse/bones %u that is not in map.", obj->GetGUID().GetCounter());
else
RemoveFromMap(corpse, true);
break;
@@ -2752,7 +2853,7 @@ void Map::AddToActive(Creature* c)
AddToActiveHelper(c);
// also not allow unloading spawn grid to prevent creating creature clone at load
- if (!c->IsPet() && c->GetDBTableGUIDLow())
+ if (!c->IsPet() && c->GetSpawnId())
{
float x, y, z;
c->GetRespawnPosition(x, y, z);
@@ -2763,7 +2864,7 @@ void Map::AddToActive(Creature* c)
{
GridCoord p2 = Trinity::ComputeGridCoord(c->GetPositionX(), c->GetPositionY());
TC_LOG_ERROR("maps", "Active creature (GUID: %u Entry: %u) added to grid[%u, %u] but spawn grid[%u, %u] was not loaded.",
- c->GetGUIDLow(), c->GetEntry(), p.x_coord, p.y_coord, p2.x_coord, p2.y_coord);
+ c->GetGUID().GetCounter(), c->GetEntry(), p.x_coord, p.y_coord, p2.x_coord, p2.y_coord);
}
}
}
@@ -2783,7 +2884,7 @@ void Map::RemoveFromActive(Creature* c)
RemoveFromActiveHelper(c);
// also allow unloading spawn grid
- if (!c->IsPet() && c->GetDBTableGUIDLow())
+ if (!c->IsPet() && c->GetSpawnId())
{
float x, y, z;
c->GetRespawnPosition(x, y, z);
@@ -2794,7 +2895,7 @@ void Map::RemoveFromActive(Creature* c)
{
GridCoord p2 = Trinity::ComputeGridCoord(c->GetPositionX(), c->GetPositionY());
TC_LOG_ERROR("maps", "Active creature (GUID: %u Entry: %u) removed from grid[%u, %u] but spawn grid[%u, %u] was not loaded.",
- c->GetGUIDLow(), c->GetEntry(), p.x_coord, p.y_coord, p2.x_coord, p2.y_coord);
+ c->GetGUID().GetCounter(), c->GetEntry(), p.x_coord, p.y_coord, p2.x_coord, p2.y_coord);
}
}
}
@@ -2850,8 +2951,8 @@ bool InstanceMap::CanEnter(Player* player)
{
if (player->GetMapRef().getTarget() == this)
{
- TC_LOG_ERROR("maps", "InstanceMap::CanEnter - player %s(%u) already in map %d, %d, %d!", player->GetName().c_str(), player->GetGUIDLow(), GetId(), GetInstanceId(), GetSpawnMode());
- ASSERT(false);
+ TC_LOG_ERROR("maps", "InstanceMap::CanEnter - player %s(%u) already in map %d, %d, %d!", player->GetName().c_str(), player->GetGUID().GetCounter(), GetId(), GetInstanceId(), GetSpawnMode());
+ ABORT();
return false;
}
@@ -2945,7 +3046,7 @@ bool InstanceMap::AddPlayerToMap(Player* player)
// cannot enter other instances if bound permanently
if (playerBind->save != mapSave)
{
- TC_LOG_ERROR("maps", "InstanceMap::Add: player %s(%d) is permanently bound to instance %s %d, %d, %d, %d, %d, %d but he is being put into instance %s %d, %d, %d, %d, %d, %d", player->GetName().c_str(), player->GetGUIDLow(), GetMapName(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset(), GetMapName(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset());
+ TC_LOG_ERROR("maps", "InstanceMap::Add: player %s(%d) is permanently bound to instance %s %d, %d, %d, %d, %d, %d but he is being put into instance %s %d, %d, %d, %d, %d, %d", player->GetName().c_str(), player->GetGUID().GetCounter(), GetMapName(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset(), GetMapName(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset());
return false;
}
}
@@ -2957,10 +3058,10 @@ bool InstanceMap::AddPlayerToMap(Player* player)
InstanceGroupBind* groupBind = group->GetBoundInstance(this);
if (playerBind && playerBind->save != mapSave)
{
- TC_LOG_ERROR("maps", "InstanceMap::Add: player %s(%d) is being put into instance %s %d, %d, %d, %d, %d, %d but he is in group %s and is bound to instance %d, %d, %d, %d, %d, %d!", player->GetName().c_str(), player->GetGUIDLow(), GetMapName(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset(), group->GetLeaderGUID().ToString().c_str(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset());
+ TC_LOG_ERROR("maps", "InstanceMap::Add: player %s(%d) is being put into instance %s %d, %d, %d, %d, %d, %d but he is in group %s and is bound to instance %d, %d, %d, %d, %d, %d!", player->GetName().c_str(), player->GetGUID().GetCounter(), GetMapName(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset(), group->GetLeaderGUID().ToString().c_str(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset());
if (groupBind)
TC_LOG_ERROR("maps", "InstanceMap::Add: the group is bound to the instance %s %d, %d, %d, %d, %d, %d", GetMapName(), groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty(), groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount(), groupBind->save->CanReset());
- //ASSERT(false);
+ //ABORT();
return false;
}
// bind to the group or keep using the group save
@@ -2971,7 +3072,7 @@ bool InstanceMap::AddPlayerToMap(Player* player)
// cannot jump to a different instance without resetting it
if (groupBind->save != mapSave)
{
- TC_LOG_ERROR("maps", "InstanceMap::Add: player %s(%d) is being put into instance %d, %d, %d but he is in group %s which is bound to instance %d, %d, %d!", player->GetName().c_str(), player->GetGUIDLow(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), group->GetLeaderGUID().ToString().c_str(), groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty());
+ TC_LOG_ERROR("maps", "InstanceMap::Add: player %s(%d) is being put into instance %d, %d, %d but he is in group %s which is bound to instance %d, %d, %d!", player->GetName().c_str(), player->GetGUID().GetCounter(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), group->GetLeaderGUID().ToString().c_str(), groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty());
TC_LOG_ERROR("maps", "MapSave players: %d, group count: %d", mapSave->GetPlayerCount(), mapSave->GetGroupCount());
if (groupBind->save)
TC_LOG_ERROR("maps", "GroupBind save players: %d, group count: %d", groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount());
@@ -3076,7 +3177,7 @@ void InstanceMap::CreateInstanceData(bool load)
i_data->SetCompletedEncountersMask(fields[1].GetUInt32());
if (!data.empty())
{
- TC_LOG_DEBUG("maps", "Loading instance data for `%s` with id %u", sObjectMgr->GetScriptName(i_script_id), i_InstanceId);
+ TC_LOG_DEBUG("maps", "Loading instance data for `%s` with id %u", sObjectMgr->GetScriptName(i_script_id).c_str(), i_InstanceId);
i_data->Load(data.c_str());
}
}
@@ -3130,7 +3231,7 @@ void InstanceMap::PermBindAllPlayers(Player* source)
InstanceSave* save = sInstanceSaveMgr->GetInstanceSave(GetInstanceId());
if (!save)
{
- TC_LOG_ERROR("maps", "Cannot bind player (GUID: %u, Name: %s), because no instance save is available for instance map (Name: %s, Entry: %u, InstanceId: %u)!", source->GetGUIDLow(), source->GetName().c_str(), source->GetMap()->GetMapName(), source->GetMapId(), GetInstanceId());
+ TC_LOG_ERROR("maps", "Cannot bind player (GUID: %u, Name: %s), because no instance save is available for instance map (Name: %s, Entry: %u, InstanceId: %u)!", source->GetGUID().GetCounter(), source->GetName().c_str(), source->GetMap()->GetMapName(), source->GetMapId(), GetInstanceId());
return;
}
@@ -3148,8 +3249,8 @@ void InstanceMap::PermBindAllPlayers(Player* source)
WorldPacket data(SMSG_INSTANCE_SAVE_CREATED, 4);
data << uint32(0);
player->GetSession()->SendPacket(&data);
-
- player->GetSession()->SendCalendarRaidLockout(save, true);
+ if (!player->IsGameMaster())
+ player->GetSession()->SendCalendarRaidLockout(save, true);
}
// if the leader is not in the instance the group will not get a perm bind
@@ -3163,7 +3264,10 @@ void InstanceMap::UnloadAll()
ASSERT(!HavePlayers());
if (m_resetAfterUnload == true)
+ {
DeleteRespawnTimes();
+ DeleteCorpseData();
+ }
Map::UnloadAll();
}
@@ -3171,7 +3275,7 @@ void InstanceMap::UnloadAll()
void InstanceMap::SendResetWarnings(uint32 timeLeft) const
{
for (MapRefManager::const_iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
- itr->GetSource()->SendInstanceResetWarning(GetId(), itr->GetSource()->GetDifficulty(IsRaid()), timeLeft);
+ itr->GetSource()->SendInstanceResetWarning(GetId(), itr->GetSource()->GetDifficulty(IsRaid()), timeLeft, false);
}
void InstanceMap::SetResetSchedule(bool on)
@@ -3239,8 +3343,8 @@ bool BattlegroundMap::CanEnter(Player* player)
{
if (player->GetMapRef().getTarget() == this)
{
- TC_LOG_ERROR("maps", "BGMap::CanEnter - player %u is already in map!", player->GetGUIDLow());
- ASSERT(false);
+ TC_LOG_ERROR("maps", "BGMap::CanEnter - player %u is already in map!", player->GetGUID().GetCounter());
+ ABORT();
return false;
}
@@ -3285,17 +3389,27 @@ void BattlegroundMap::RemoveAllPlayers()
player->TeleportTo(player->GetBattlegroundEntryPoint());
}
-Creature* Map::GetCreature(ObjectGuid guid)
+Corpse* Map::GetCorpse(ObjectGuid const& guid)
+{
+ return _objectsStore.Find<Corpse>(guid);
+}
+
+Creature* Map::GetCreature(ObjectGuid const& guid)
{
- return ObjectAccessor::GetObjectInMap(guid, this, (Creature*)NULL);
+ return _objectsStore.Find<Creature>(guid);
}
-GameObject* Map::GetGameObject(ObjectGuid guid)
+GameObject* Map::GetGameObject(ObjectGuid const& guid)
{
- return ObjectAccessor::GetObjectInMap(guid, this, (GameObject*)NULL);
+ return _objectsStore.Find<GameObject>(guid);
}
-Transport* Map::GetTransport(ObjectGuid guid)
+Pet* Map::GetPet(ObjectGuid const& guid)
+{
+ return _objectsStore.Find<Pet>(guid);
+}
+
+Transport* Map::GetTransport(ObjectGuid const& guid)
{
if (!guid.IsMOTransport())
return NULL;
@@ -3304,9 +3418,9 @@ Transport* Map::GetTransport(ObjectGuid guid)
return go ? go->ToTransport() : NULL;
}
-DynamicObject* Map::GetDynamicObject(ObjectGuid guid)
+DynamicObject* Map::GetDynamicObject(ObjectGuid const& guid)
{
- return ObjectAccessor::GetObjectInMap(guid, this, (DynamicObject*)NULL);
+ return _objectsStore.Find<DynamicObject>(guid);
}
void Map::UpdateIteratorBack(Player* player)
@@ -3315,7 +3429,7 @@ void Map::UpdateIteratorBack(Player* player)
m_mapRefIter = m_mapRefIter->nocheck_prev();
}
-void Map::SaveCreatureRespawnTime(uint32 dbGuid, time_t respawnTime)
+void Map::SaveCreatureRespawnTime(ObjectGuid::LowType dbGuid, time_t respawnTime)
{
if (!respawnTime)
{
@@ -3334,7 +3448,7 @@ void Map::SaveCreatureRespawnTime(uint32 dbGuid, time_t respawnTime)
CharacterDatabase.Execute(stmt);
}
-void Map::RemoveCreatureRespawnTime(uint32 dbGuid)
+void Map::RemoveCreatureRespawnTime(ObjectGuid::LowType dbGuid)
{
_creatureRespawnTimes.erase(dbGuid);
@@ -3345,7 +3459,7 @@ void Map::RemoveCreatureRespawnTime(uint32 dbGuid)
CharacterDatabase.Execute(stmt);
}
-void Map::SaveGORespawnTime(uint32 dbGuid, time_t respawnTime)
+void Map::SaveGORespawnTime(ObjectGuid::LowType dbGuid, time_t respawnTime)
{
if (!respawnTime)
{
@@ -3364,7 +3478,7 @@ void Map::SaveGORespawnTime(uint32 dbGuid, time_t respawnTime)
CharacterDatabase.Execute(stmt);
}
-void Map::RemoveGORespawnTime(uint32 dbGuid)
+void Map::RemoveGORespawnTime(ObjectGuid::LowType dbGuid)
{
_goRespawnTimes.erase(dbGuid);
@@ -3385,7 +3499,7 @@ void Map::LoadRespawnTimes()
do
{
Field* fields = result->Fetch();
- uint32 loguid = fields[0].GetUInt32();
+ ObjectGuid::LowType loguid = fields[0].GetUInt32();
uint32 respawnTime = fields[1].GetUInt32();
_creatureRespawnTimes[loguid] = time_t(respawnTime);
@@ -3400,7 +3514,7 @@ void Map::LoadRespawnTimes()
do
{
Field* fields = result->Fetch();
- uint32 loguid = fields[0].GetUInt32();
+ ObjectGuid::LowType loguid = fields[0].GetUInt32();
uint32 respawnTime = fields[1].GetUInt32();
_goRespawnTimes[loguid] = time_t(respawnTime);
@@ -3434,9 +3548,9 @@ time_t Map::GetLinkedRespawnTime(ObjectGuid guid) const
ObjectGuid linkedGuid = sObjectMgr->GetLinkedRespawnGuid(guid);
switch (linkedGuid.GetHigh())
{
- case HIGHGUID_UNIT:
+ case HighGuid::Unit:
return GetCreatureRespawnTime(linkedGuid.GetCounter());
- case HIGHGUID_GAMEOBJECT:
+ case HighGuid::GameObject:
return GetGORespawnTime(linkedGuid.GetCounter());
default:
break;
@@ -3445,6 +3559,159 @@ time_t Map::GetLinkedRespawnTime(ObjectGuid guid) const
return time_t(0);
}
+void Map::LoadCorpseData()
+{
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CORPSES);
+ stmt->setUInt32(0, GetId());
+ stmt->setUInt32(1, GetInstanceId());
+
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+ // SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, guildId, flags, dynFlags, time, corpseType, instanceId, phaseMask, guid FROM corpse WHERE mapId = ? AND instanceId = ?
+ PreparedQueryResult result = CharacterDatabase.Query(stmt);
+ if (!result)
+ return;
+
+ do
+ {
+ Field* fields = result->Fetch();
+ CorpseType type = CorpseType(fields[13].GetUInt8());
+ ObjectGuid::LowType guid = fields[16].GetUInt32();
+ if (type >= MAX_CORPSE_TYPE || type == CORPSE_BONES)
+ {
+ TC_LOG_ERROR("misc", "Corpse (guid: %u) have wrong corpse type (%u), not loading.", guid, type);
+ continue;
+ }
+
+ Corpse* corpse = new Corpse(type);
+
+ if (!corpse->LoadCorpseFromDB(GenerateLowGuid<HighGuid::Corpse>(), fields))
+ {
+ delete corpse;
+ continue;
+ }
+
+ AddCorpse(corpse);
+
+ } while (result->NextRow());
+}
+
+void Map::DeleteCorpseData()
+{
+ // DELETE FROM corpse WHERE mapId = ? AND instanceId = ?
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CORPSES_FROM_MAP);
+ stmt->setUInt32(0, GetId());
+ stmt->setUInt32(1, GetInstanceId());
+ CharacterDatabase.Execute(stmt);
+}
+
+void Map::AddCorpse(Corpse* corpse)
+{
+ corpse->SetMap(this);
+
+ _corpsesByCell[corpse->GetCellCoord().GetId()].insert(corpse);
+ if (corpse->GetType() != CORPSE_BONES)
+ _corpsesByPlayer[corpse->GetOwnerGUID()] = corpse;
+ else
+ _corpseBones.insert(corpse);
+}
+
+void Map::RemoveCorpse(Corpse* corpse)
+{
+ ASSERT(corpse);
+
+ corpse->DestroyForNearbyPlayers();
+ if (corpse->IsInGrid())
+ RemoveFromMap(corpse, false);
+ else
+ {
+ corpse->RemoveFromWorld();
+ corpse->ResetMap();
+ }
+
+ _corpsesByCell[corpse->GetCellCoord().GetId()].erase(corpse);
+ if (corpse->GetType() != CORPSE_BONES)
+ _corpsesByPlayer.erase(corpse->GetOwnerGUID());
+ else
+ _corpseBones.erase(corpse);
+}
+
+Corpse* Map::ConvertCorpseToBones(ObjectGuid const& ownerGuid, bool insignia /*= false*/)
+{
+ Corpse* corpse = GetCorpseByPlayer(ownerGuid);
+ if (!corpse)
+ return nullptr;
+
+ RemoveCorpse(corpse);
+
+ // remove corpse from DB
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+ corpse->DeleteFromDB(trans);
+ CharacterDatabase.CommitTransaction(trans);
+
+ Corpse* bones = NULL;
+
+ // create the bones only if the map and the grid is loaded at the corpse's location
+ // ignore bones creating option in case insignia
+ if ((insignia ||
+ (IsBattlegroundOrArena() ? sWorld->getBoolConfig(CONFIG_DEATH_BONES_BG_OR_ARENA) : sWorld->getBoolConfig(CONFIG_DEATH_BONES_WORLD))) &&
+ !IsRemovalGrid(corpse->GetPositionX(), corpse->GetPositionY()))
+ {
+ // Create bones, don't change Corpse
+ bones = new Corpse();
+ bones->Create(corpse->GetGUID().GetCounter());
+
+ for (uint8 i = OBJECT_FIELD_TYPE + 1; i < CORPSE_END; ++i) // don't overwrite guid and object type
+ bones->SetUInt32Value(i, corpse->GetUInt32Value(i));
+
+ bones->SetCellCoord(corpse->GetCellCoord());
+ bones->Relocate(corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetOrientation());
+ bones->SetPhaseMask(corpse->GetPhaseMask(), false);
+
+ bones->SetUInt32Value(CORPSE_FIELD_FLAGS, CORPSE_FLAG_UNK2 | CORPSE_FLAG_BONES);
+ bones->SetGuidValue(CORPSE_FIELD_OWNER, ObjectGuid::Empty);
+
+ for (uint8 i = 0; i < EQUIPMENT_SLOT_END; ++i)
+ if (corpse->GetUInt32Value(CORPSE_FIELD_ITEM + i))
+ bones->SetUInt32Value(CORPSE_FIELD_ITEM + i, 0);
+
+ AddCorpse(bones);
+
+ // add bones in grid store if grid loaded where corpse placed
+ AddToMap(bones);
+ }
+
+ // all references to the corpse should be removed at this point
+ delete corpse;
+
+ return bones;
+}
+
+void Map::RemoveOldCorpses()
+{
+ time_t now = time(nullptr);
+
+ std::vector<ObjectGuid> corpses;
+ corpses.reserve(_corpsesByPlayer.size());
+
+ for (auto const& p : _corpsesByPlayer)
+ if (p.second->IsExpired(now))
+ corpses.push_back(p.first);
+
+ for (ObjectGuid const& ownerGuid : corpses)
+ ConvertCorpseToBones(ownerGuid);
+
+ std::vector<Corpse*> expiredBones;
+ for (Corpse* bones : _corpseBones)
+ if (bones->IsExpired(now))
+ expiredBones.push_back(bones);
+
+ for (Corpse* bones : expiredBones)
+ {
+ RemoveCorpse(bones);
+ delete bones;
+ }
+}
+
void Map::SendZoneDynamicInfo(Player* player)
{
uint32 zoneId = GetZoneId(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ());
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index 43fcbaba31c..0962bcc9d6c 100644
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -34,6 +34,7 @@
#include <bitset>
#include <list>
+#include <memory>
class Unit;
class WorldPacket;
@@ -443,10 +444,38 @@ class Map : public GridRefManager<NGridType>
TempSummon* SummonCreature(uint32 entry, Position const& pos, SummonPropertiesEntry const* properties = NULL, uint32 duration = 0, Unit* summoner = NULL, uint32 spellId = 0, uint32 vehId = 0);
void SummonCreatureGroup(uint8 group, std::list<TempSummon*>* list = NULL);
- Creature* GetCreature(ObjectGuid guid);
- GameObject* GetGameObject(ObjectGuid guid);
- Transport* GetTransport(ObjectGuid guid);
- DynamicObject* GetDynamicObject(ObjectGuid guid);
+ Corpse* GetCorpse(ObjectGuid const& guid);
+ Creature* GetCreature(ObjectGuid const& guid);
+ GameObject* GetGameObject(ObjectGuid const& guid);
+ Transport* GetTransport(ObjectGuid const& guid);
+ DynamicObject* GetDynamicObject(ObjectGuid const& guid);
+ Pet* GetPet(ObjectGuid const& guid);
+
+ MapStoredObjectTypesContainer& GetObjectsStore() { return _objectsStore; }
+
+ typedef std::unordered_multimap<ObjectGuid::LowType, Creature*> CreatureBySpawnIdContainer;
+ CreatureBySpawnIdContainer& GetCreatureBySpawnIdStore() { return _creatureBySpawnIdStore; }
+
+ typedef std::unordered_multimap<ObjectGuid::LowType, GameObject*> GameObjectBySpawnIdContainer;
+ GameObjectBySpawnIdContainer& GetGameObjectBySpawnIdStore() { return _gameobjectBySpawnIdStore; }
+
+ std::unordered_set<Corpse*> const* GetCorpsesInCell(uint32 cellId) const
+ {
+ auto itr = _corpsesByCell.find(cellId);
+ if (itr != _corpsesByCell.end())
+ return &itr->second;
+
+ return nullptr;
+ }
+
+ Corpse* GetCorpseByPlayer(ObjectGuid const& ownerGuid) const
+ {
+ auto itr = _corpsesByPlayer.find(ownerGuid);
+ if (itr != _corpsesByPlayer.end())
+ return itr->second;
+
+ return nullptr;
+ }
MapInstanced* ToMapInstanced() { if (Instanceable()) return reinterpret_cast<MapInstanced*>(this); return NULL; }
MapInstanced const* ToMapInstanced() const { if (Instanceable()) return reinterpret_cast<MapInstanced const*>(this); return NULL; }
@@ -470,31 +499,38 @@ class Map : public GridRefManager<NGridType>
RESPAWN TIMES
*/
time_t GetLinkedRespawnTime(ObjectGuid guid) const;
- time_t GetCreatureRespawnTime(uint32 dbGuid) const
+ time_t GetCreatureRespawnTime(ObjectGuid::LowType dbGuid) const
{
- std::unordered_map<uint32 /*dbGUID*/, time_t>::const_iterator itr = _creatureRespawnTimes.find(dbGuid);
+ std::unordered_map<ObjectGuid::LowType /*dbGUID*/, time_t>::const_iterator itr = _creatureRespawnTimes.find(dbGuid);
if (itr != _creatureRespawnTimes.end())
return itr->second;
return time_t(0);
}
- time_t GetGORespawnTime(uint32 dbGuid) const
+ time_t GetGORespawnTime(ObjectGuid::LowType dbGuid) const
{
- std::unordered_map<uint32 /*dbGUID*/, time_t>::const_iterator itr = _goRespawnTimes.find(dbGuid);
+ std::unordered_map<ObjectGuid::LowType /*dbGUID*/, time_t>::const_iterator itr = _goRespawnTimes.find(dbGuid);
if (itr != _goRespawnTimes.end())
return itr->second;
return time_t(0);
}
- void SaveCreatureRespawnTime(uint32 dbGuid, time_t respawnTime);
- void RemoveCreatureRespawnTime(uint32 dbGuid);
- void SaveGORespawnTime(uint32 dbGuid, time_t respawnTime);
- void RemoveGORespawnTime(uint32 dbGuid);
+ void SaveCreatureRespawnTime(ObjectGuid::LowType dbGuid, time_t respawnTime);
+ void RemoveCreatureRespawnTime(ObjectGuid::LowType dbGuid);
+ void SaveGORespawnTime(ObjectGuid::LowType dbGuid, time_t respawnTime);
+ void RemoveGORespawnTime(ObjectGuid::LowType dbGuid);
void LoadRespawnTimes();
void DeleteRespawnTimes();
+ void LoadCorpseData();
+ void DeleteCorpseData();
+ void AddCorpse(Corpse* corpse);
+ void RemoveCorpse(Corpse* corpse);
+ Corpse* ConvertCorpseToBones(ObjectGuid const& ownerGuid, bool insignia = false);
+ void RemoveOldCorpses();
+
static void DeleteRespawnTimesInDB(uint16 mapId, uint32 instanceId);
void SendInitTransports(Player* player);
@@ -507,7 +543,32 @@ class Map : public GridRefManager<NGridType>
void UpdateAreaDependentAuras();
+ template<HighGuid high>
+ inline ObjectGuid::LowType GenerateLowGuid()
+ {
+ static_assert(ObjectGuidTraits<high>::MapSpecific, "Only map specific guid can be generated in Map context");
+ return GetGuidSequenceGenerator<high>().Generate();
+ }
+
+ template<HighGuid high>
+ inline ObjectGuid::LowType GetMaxLowGuid()
+ {
+ static_assert(ObjectGuidTraits<high>::MapSpecific, "Only map specific guid can be retrieved in Map context");
+ return GetGuidSequenceGenerator<high>().GetNextAfterMaxUsed();
+ }
+
+ void AddUpdateObject(Object* obj)
+ {
+ _updateObjects.insert(obj);
+ }
+
+ void RemoveUpdateObject(Object* obj)
+ {
+ _updateObjects.erase(obj);
+ }
+
private:
+
void LoadMapAndVMap(int gx, int gy);
void LoadVMap(int gx, int gy);
void LoadMap(int gx, int gy, bool reload = false);
@@ -561,6 +622,8 @@ class Map : public GridRefManager<NGridType>
void UpdateActiveCells(const float &x, const float &y, const uint32 t_diff);
+ void SendObjectUpdates();
+
protected:
void SetUnloadReferenceLock(const GridCoord &p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadReferenceLock(on); }
@@ -596,7 +659,7 @@ class Map : public GridRefManager<NGridType>
Creature* _GetScriptCreature(Object* obj, bool isSource, const ScriptInfo* scriptInfo) const;
WorldObject* _GetScriptWorldObject(Object* obj, bool isSource, const ScriptInfo* scriptInfo) const;
void _ScriptProcessDoor(Object* source, Object* target, const ScriptInfo* scriptInfo) const;
- GameObject* _FindGameObject(WorldObject* pWorldObject, uint32 guid) const;
+ GameObject* _FindGameObject(WorldObject* pWorldObject, ObjectGuid::LowType guid) const;
time_t i_gridExpiry;
@@ -648,11 +711,31 @@ class Map : public GridRefManager<NGridType>
m_activeNonPlayers.erase(obj);
}
- std::unordered_map<uint32 /*dbGUID*/, time_t> _creatureRespawnTimes;
- std::unordered_map<uint32 /*dbGUID*/, time_t> _goRespawnTimes;
+ std::unordered_map<ObjectGuid::LowType /*dbGUID*/, time_t> _creatureRespawnTimes;
+ std::unordered_map<ObjectGuid::LowType /*dbGUID*/, time_t> _goRespawnTimes;
ZoneDynamicInfoMap _zoneDynamicInfo;
uint32 _defaultLight;
+
+ template<HighGuid high>
+ inline ObjectGuidGeneratorBase& GetGuidSequenceGenerator()
+ {
+ auto itr = _guidGenerators.find(high);
+ if (itr == _guidGenerators.end())
+ itr = _guidGenerators.insert(std::make_pair(high, std::unique_ptr<ObjectGuidGenerator<high>>(new ObjectGuidGenerator<high>()))).first;
+
+ return *itr->second;
+ }
+
+ std::map<HighGuid, std::unique_ptr<ObjectGuidGeneratorBase>> _guidGenerators;
+ MapStoredObjectTypesContainer _objectsStore;
+ CreatureBySpawnIdContainer _creatureBySpawnIdStore;
+ GameObjectBySpawnIdContainer _gameobjectBySpawnIdStore;
+ std::unordered_map<uint32/*cellId*/, std::unordered_set<Corpse*>> _corpsesByCell;
+ std::unordered_map<ObjectGuid, Corpse*> _corpsesByPlayer;
+ std::unordered_set<Corpse*> _corpseBones;
+
+ std::unordered_set<Object*> _updateObjects;
};
enum InstanceResetMethod
@@ -675,7 +758,7 @@ class InstanceMap : public Map
void Update(const uint32) override;
void CreateInstanceData(bool load);
bool Reset(uint8 method);
- uint32 GetScriptId() { return i_script_id; }
+ uint32 GetScriptId() const { return i_script_id; }
InstanceScript* GetInstanceScript() { return i_data; }
void PermBindAllPlayers(Player* source);
void UnloadAll() override;
diff --git a/src/server/game/Maps/MapInstanced.cpp b/src/server/game/Maps/MapInstanced.cpp
index e4632bb7515..d1b8bd66209 100644
--- a/src/server/game/Maps/MapInstanced.cpp
+++ b/src/server/game/Maps/MapInstanced.cpp
@@ -194,13 +194,13 @@ InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave* save,
if (!entry)
{
TC_LOG_ERROR("maps", "CreateInstance: no entry for map %d", GetId());
- ASSERT(false);
+ ABORT();
}
const InstanceTemplate* iTemplate = sObjectMgr->GetInstanceTemplate(GetId());
if (!iTemplate)
{
TC_LOG_ERROR("maps", "CreateInstance: no instance template for map %d", GetId());
- ASSERT(false);
+ ABORT();
}
// some instances only have one difficulty
@@ -212,6 +212,7 @@ InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave* save,
ASSERT(map->IsDungeon());
map->LoadRespawnTimes();
+ map->LoadCorpseData();
bool load_data = save != NULL;
map->CreateInstanceData(load_data);
@@ -279,6 +280,6 @@ bool MapInstanced::DestroyInstance(InstancedMaps::iterator &itr)
bool MapInstanced::CanEnter(Player* /*player*/)
{
- //ASSERT(false);
+ //ABORT();
return true;
}
diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp
index 29f4b4ab7c2..0e7f9dbb611 100644
--- a/src/server/game/Maps/MapManager.cpp
+++ b/src/server/game/Maps/MapManager.cpp
@@ -79,6 +79,7 @@ Map* MapManager::CreateBaseMap(uint32 id)
{
map = new Map(id, i_gridCleanUpDelay, 0, REGULAR_DIFFICULTY);
map->LoadRespawnTimes();
+ map->LoadCorpseData();
}
i_maps[id] = map;
@@ -163,10 +164,10 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck)
if (!player->IsAlive())
{
- if (Corpse* corpse = player->GetCorpse())
+ if (player->HasCorpse())
{
// let enter in ghost mode in instance that connected to inner instance with corpse
- uint32 corpseMap = corpse->GetMapId();
+ uint32 corpseMap = player->GetCorpseLocation().GetMapId();
do
{
if (corpseMap == mapid)
@@ -183,9 +184,8 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck)
TC_LOG_DEBUG("maps", "MAP: Player '%s' does not have a corpse in instance '%s' and cannot enter.", player->GetName().c_str(), mapName);
return false;
}
+
TC_LOG_DEBUG("maps", "MAP: Player '%s' has corpse in instance '%s' and can enter.", player->GetName().c_str(), mapName);
- player->ResurrectPlayer(0.5f, false);
- player->SpawnCorpseBones();
}
else
TC_LOG_DEBUG("maps", "Map::CanPlayerEnter - player '%s' is dead but does not have a corpse!", player->GetName().c_str());
@@ -250,8 +250,6 @@ void MapManager::Update(uint32 diff)
for (iter = i_maps.begin(); iter != i_maps.end(); ++iter)
iter->second->DelayedUpdate(uint32(i_timer.GetCurrent()));
- sObjectAccessor->Update(uint32(i_timer.GetCurrent()));
-
i_timer.SetCurrent(0);
}
diff --git a/src/server/game/Maps/MapManager.h b/src/server/game/Maps/MapManager.h
index dc6c0bb642f..5b957e00281 100644
--- a/src/server/game/Maps/MapManager.h
+++ b/src/server/game/Maps/MapManager.h
@@ -21,6 +21,7 @@
#include "Object.h"
#include "Map.h"
+#include "MapInstanced.h"
#include "GridStates.h"
#include "MapUpdater.h"
@@ -125,6 +126,12 @@ class MapManager
MapUpdater * GetMapUpdater() { return &m_updater; }
+ template<typename Worker>
+ void DoForAllMaps(Worker&& worker);
+
+ template<typename Worker>
+ void DoForAllMapsWithMapId(uint32 mapId, Worker&& worker);
+
private:
typedef std::unordered_map<uint32, Map*> MapMapType;
typedef std::vector<bool> InstanceIds;
@@ -150,5 +157,45 @@ class MapManager
uint32 _nextInstanceId;
MapUpdater m_updater;
};
+
+template<typename Worker>
+void MapManager::DoForAllMaps(Worker&& worker)
+{
+ std::lock_guard<std::mutex> lock(_mapsLock);
+
+ for (auto& mapPair : i_maps)
+ {
+ Map* map = mapPair.second;
+ if (MapInstanced* mapInstanced = map->ToMapInstanced())
+ {
+ MapInstanced::InstancedMaps& instances = mapInstanced->GetInstancedMaps();
+ for (auto& instancePair : instances)
+ worker(instancePair.second);
+ }
+ else
+ worker(map);
+ }
+}
+
+template<typename Worker>
+inline void MapManager::DoForAllMapsWithMapId(uint32 mapId, Worker&& worker)
+{
+ std::lock_guard<std::mutex> lock(_mapsLock);
+
+ auto itr = i_maps.find(mapId);
+ if (itr != i_maps.end())
+ {
+ Map* map = itr->second;
+ if (MapInstanced* mapInstanced = map->ToMapInstanced())
+ {
+ MapInstanced::InstancedMaps& instances = mapInstanced->GetInstancedMaps();
+ for (auto& p : instances)
+ worker(p.second);
+ }
+ else
+ worker(map);
+ }
+}
+
#define sMapMgr MapManager::instance()
#endif
diff --git a/src/server/game/Maps/MapUpdater.cpp b/src/server/game/Maps/MapUpdater.cpp
index 46b2fb86596..20b8da796a5 100644
--- a/src/server/game/Maps/MapUpdater.cpp
+++ b/src/server/game/Maps/MapUpdater.cpp
@@ -16,12 +16,11 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <mutex>
-#include <condition_variable>
-
#include "MapUpdater.h"
#include "Map.h"
+#include <mutex>
+
class MapUpdateRequest
{
diff --git a/src/server/game/Maps/TransportMgr.cpp b/src/server/game/Maps/TransportMgr.cpp
index dadc2eeeac3..84eba74c6dc 100644
--- a/src/server/game/Maps/TransportMgr.cpp
+++ b/src/server/game/Maps/TransportMgr.cpp
@@ -112,7 +112,7 @@ void TransportMgr::GeneratePath(GameObjectTemplate const* goInfo, TransportTempl
Movement::PointsArray splinePath, allPoints;
bool mapChange = false;
for (size_t i = 0; i < path.size(); ++i)
- allPoints.push_back(G3D::Vector3(path[i].LocX, path[i].LocY, path[i].LocZ));
+ allPoints.push_back(G3D::Vector3(path[i]->LocX, path[i]->LocY, path[i]->LocZ));
// Add extra points to allow derivative calculations for all path nodes
allPoints.insert(allPoints.begin(), allPoints.front().lerp(allPoints[1], -0.2f));
@@ -128,8 +128,8 @@ void TransportMgr::GeneratePath(GameObjectTemplate const* goInfo, TransportTempl
{
if (!mapChange)
{
- TaxiPathNodeEntry const& node_i = path[i];
- if (i != path.size() - 1 && (node_i.Flags & 1 || node_i.MapID != path[i + 1].MapID))
+ TaxiPathNodeEntry const* node_i = path[i];
+ if (i != path.size() - 1 && (node_i->Flags & 1 || node_i->MapID != path[i + 1]->MapID))
{
keyFrames.back().Teleport = true;
mapChange = true;
@@ -142,7 +142,7 @@ void TransportMgr::GeneratePath(GameObjectTemplate const* goInfo, TransportTempl
k.InitialOrientation = Position::NormalizeOrientation(std::atan2(h.y, h.x) + float(M_PI));
keyFrames.push_back(k);
- splinePath.push_back(G3D::Vector3(node_i.LocX, node_i.LocY, node_i.LocZ));
+ splinePath.push_back(G3D::Vector3(node_i->LocX, node_i->LocY, node_i->LocZ));
transport->mapsUsed.insert(k.Node->MapID);
}
}
@@ -348,7 +348,7 @@ void TransportMgr::AddPathNodeToTransport(uint32 transportEntry, uint32 timeSeg,
animNode.Path[timeSeg] = node;
}
-Transport* TransportMgr::CreateTransport(uint32 entry, uint32 guid /*= 0*/, Map* map /*= NULL*/)
+Transport* TransportMgr::CreateTransport(uint32 entry, ObjectGuid::LowType guid /*= 0*/, Map* map /*= NULL*/)
{
// instance case, execute GetGameObjectEntry hook
if (map)
@@ -381,7 +381,8 @@ Transport* TransportMgr::CreateTransport(uint32 entry, uint32 guid /*= 0*/, Map*
float o = tInfo->keyFrames.begin()->InitialOrientation;
// initialize the gameobject base
- uint32 guidLow = guid ? guid : sObjectMgr->GenerateLowGuid(HIGHGUID_MO_TRANSPORT);
+ ObjectGuid::LowType guidLow = guid ? guid : sObjectMgr->GetGenerator<HighGuid::Mo_Transport>().Generate();
+
if (!trans->Create(guidLow, entry, mapId, x, y, z, o, 255))
{
delete trans;
@@ -404,7 +405,7 @@ Transport* TransportMgr::CreateTransport(uint32 entry, uint32 guid /*= 0*/, Map*
trans->m_zoneScript = map->ToInstanceMap()->GetInstanceScript();
// Passengers will be loaded once a player is near
-
+ HashMapHolder<Transport>::Insert(trans);
trans->GetMap()->AddToMap<Transport>(trans);
return trans;
}
@@ -424,7 +425,7 @@ void TransportMgr::SpawnContinentTransports()
do
{
Field* fields = result->Fetch();
- uint32 guid = fields[0].GetUInt32();
+ ObjectGuid::LowType guid = fields[0].GetUInt32();
uint32 entry = fields[1].GetUInt32();
if (TransportTemplate const* tInfo = GetTransportTemplate(entry))
diff --git a/src/server/game/Maps/TransportMgr.h b/src/server/game/Maps/TransportMgr.h
index fff7b9d8afa..d100f60c604 100644
--- a/src/server/game/Maps/TransportMgr.h
+++ b/src/server/game/Maps/TransportMgr.h
@@ -21,6 +21,7 @@
#include <G3D/Quat.h>
#include "Spline.h"
#include "DBCStores.h"
+#include "ObjectGuid.h"
struct KeyFrame;
struct GameObjectTemplate;
@@ -37,7 +38,7 @@ typedef std::unordered_map<uint32, std::set<uint32> > TransportInstanceMap;
struct KeyFrame
{
- explicit KeyFrame(TaxiPathNodeEntry const& _node) : Index(0), Node(&_node), InitialOrientation(0.0f),
+ explicit KeyFrame(TaxiPathNodeEntry const* node) : Index(0), Node(node), InitialOrientation(0.0f),
DistSinceStop(-1.0f), DistUntilStop(-1.0f), DistFromPrev(-1.0f), TimeFrom(0.0f), TimeTo(0.0f),
Teleport(false), ArriveTime(0), DepartureTime(0), Spline(NULL), NextDistFromPrev(0.0f), NextArriveTime(0)
{
@@ -111,7 +112,7 @@ class TransportMgr
void LoadTransportTemplates();
// Creates a transport using given GameObject template entry
- Transport* CreateTransport(uint32 entry, uint32 guid = 0, Map* map = NULL);
+ Transport* CreateTransport(uint32 entry, ObjectGuid::LowType guid = 0, Map* map = NULL);
// Spawns all continent transports, used at core startup
void SpawnContinentTransports();
diff --git a/src/server/game/Miscellaneous/Formulas.h b/src/server/game/Miscellaneous/Formulas.h
index ba39723b19d..6edc3d74a5d 100644
--- a/src/server/game/Miscellaneous/Formulas.h
+++ b/src/server/game/Miscellaneous/Formulas.h
@@ -158,7 +158,7 @@ namespace Trinity
return baseGain;
}
- inline uint32 Gain(Player* player, Unit* u)
+ inline uint32 Gain(Player* player, Unit* u, bool isBattleGround = false)
{
Creature* creature = u->ToCreature();
uint32 gain = 0;
@@ -175,7 +175,7 @@ namespace Trinity
if (creature->isElite())
{
// Elites in instances have a 2.75x XP bonus instead of the regular 2x world bonus.
- if (u->GetMap() && u->GetMap()->IsDungeon())
+ if (u->GetMap()->IsDungeon())
xpMod *= 2.75f;
else
xpMod *= 2.0f;
@@ -184,7 +184,7 @@ namespace Trinity
xpMod *= creature->GetCreatureTemplate()->ModExperience;
}
- xpMod *= sWorld->getRate(RATE_XP_KILL);
+ xpMod *= isBattleGround ? sWorld->getRate(RATE_XP_BG_KILL) : sWorld->getRate(RATE_XP_KILL);
gain = uint32(gain * xpMod);
}
diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h
index 9bae8fbdfae..85971396619 100644
--- a/src/server/game/Miscellaneous/Language.h
+++ b/src/server/game/Miscellaneous/Language.h
@@ -379,7 +379,8 @@ enum TrinityStrings
LANG_COMMAND_CHEAT_POWER = 361,
LANG_COMMAND_CHEAT_WW = 362,
LANG_COMMAND_WHISPEROFFPLAYER = 363,
- // Room for more level 2 364-399 not used
+ LANG_COMMAND_CHEAT_TAXINODES = 364,
+ // Room for more level 2 365-399 not used
// level 3 chat
LANG_SCRIPTS_RELOADED = 400,
@@ -971,15 +972,15 @@ enum TrinityStrings
LANG_GUILD_INFO_BANK_GOLD = 1181,
LANG_GUILD_INFO_MOTD = 1182,
LANG_GUILD_INFO_EXTRA_INFO = 1183,
- // Room for more level 3 1184-1199 not used
+ // Room for more level 3 1184-1198 not used
// Debug commands
+ LANG_DO_NOT_USE_6X_DEBUG_AREATRIGGER_LEFT = 1999,
LANG_CINEMATIC_NOT_EXIST = 1200,
LANG_MOVIE_NOT_EXIST = 1201,
LANG_DEBUG_AREATRIGGER_ON = 1202,
LANG_DEBUG_AREATRIGGER_OFF = 1203,
LANG_DEBUG_AREATRIGGER_REACHED = 1204,
- // Room for more debug 1205-1299 not used
// Isle of Conquest
LANG_BG_IC_START_TWO_MINUTES = 1205,
@@ -1201,6 +1202,8 @@ enum TrinityStrings
LANG_BAN_ACCOUNT_YOUPERMBANNEDMESSAGE_WORLD = 11007,
LANG_NPCINFO_INHABIT_TYPE = 11008,
- LANG_NPCINFO_FLAGS_EXTRA = 11009
+ LANG_NPCINFO_FLAGS_EXTRA = 11009,
+ LANG_INSTANCE_LOGIN_GAMEMASTER_EXCEPTION = 11010
+
};
#endif
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index 06c58a408da..ac16a83e6a7 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -3560,35 +3560,6 @@ enum PartyResult
ERR_PARTY_LFG_TELEPORT_IN_COMBAT = 30
};
-const uint32 MMAP_MAGIC = 0x4d4d4150; // 'MMAP'
-#define MMAP_VERSION 5
-
-struct MmapTileHeader
-{
- uint32 mmapMagic;
- uint32 dtVersion;
- uint32 mmapVersion;
- uint32 size;
- bool usesLiquids : 1;
-
- MmapTileHeader() : mmapMagic(MMAP_MAGIC), dtVersion(DT_NAVMESH_VERSION),
- mmapVersion(MMAP_VERSION), size(0), usesLiquids(true) { }
-};
-
-enum NavTerrain
-{
- NAV_EMPTY = 0x00,
- NAV_GROUND = 0x01,
- NAV_MAGMA = 0x02,
- NAV_SLIME = 0x04,
- NAV_WATER = 0x08,
- NAV_UNUSED1 = 0x10,
- NAV_UNUSED2 = 0x20,
- NAV_UNUSED3 = 0x40,
- NAV_UNUSED4 = 0x80
- // we only have 8 bits
-};
-
enum DiminishingLevels
{
DIMINISHING_LEVEL_1 = 0,
diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp
index 2b323e196a7..cb8cab1849d 100644
--- a/src/server/game/Movement/MotionMaster.cpp
+++ b/src/server/game/Movement/MotionMaster.cpp
@@ -193,7 +193,7 @@ void MotionMaster::MoveRandom(float spawndist)
{
if (_owner->GetTypeId() == TYPEID_UNIT)
{
- TC_LOG_DEBUG("misc", "Creature (GUID: %u) start moving random", _owner->GetGUIDLow());
+ TC_LOG_DEBUG("misc", "Creature (GUID: %u) start moving random", _owner->GetGUID().GetCounter());
Mutate(new RandomMovementGenerator<Creature>(spawndist), MOTION_SLOT_IDLE);
}
}
@@ -204,22 +204,22 @@ void MotionMaster::MoveTargetedHome()
if (_owner->GetTypeId() == TYPEID_UNIT && !_owner->ToCreature()->GetCharmerOrOwnerGUID())
{
- TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) targeted home", _owner->GetEntry(), _owner->GetGUIDLow());
+ TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) targeted home", _owner->GetEntry(), _owner->GetGUID().GetCounter());
Mutate(new HomeMovementGenerator<Creature>(), MOTION_SLOT_ACTIVE);
}
else if (_owner->GetTypeId() == TYPEID_UNIT && _owner->ToCreature()->GetCharmerOrOwnerGUID())
{
- TC_LOG_DEBUG("misc", "Pet or controlled creature (Entry: %u GUID: %u) targeting home", _owner->GetEntry(), _owner->GetGUIDLow());
+ TC_LOG_DEBUG("misc", "Pet or controlled creature (Entry: %u GUID: %u) targeting home", _owner->GetEntry(), _owner->GetGUID().GetCounter());
Unit* target = _owner->ToCreature()->GetCharmerOrOwner();
if (target)
{
- TC_LOG_DEBUG("misc", "Following %s (GUID: %u)", target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", target->GetTypeId() == TYPEID_PLAYER ? target->GetGUIDLow() : ((Creature*)target)->GetDBTableGUIDLow());
+ TC_LOG_DEBUG("misc", "Following %s (GUID: %u)", target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", target->GetTypeId() == TYPEID_PLAYER ? target->GetGUID().GetCounter() : ((Creature*)target)->GetSpawnId());
Mutate(new FollowMovementGenerator<Creature>(target, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE), MOTION_SLOT_ACTIVE);
}
}
else
{
- TC_LOG_ERROR("misc", "Player (GUID: %u) attempt targeted home", _owner->GetGUIDLow());
+ TC_LOG_ERROR("misc", "Player (GUID: %u) attempt targeted home", _owner->GetGUID().GetCounter());
}
}
@@ -227,13 +227,13 @@ void MotionMaster::MoveConfused()
{
if (_owner->GetTypeId() == TYPEID_PLAYER)
{
- TC_LOG_DEBUG("misc", "Player (GUID: %u) move confused", _owner->GetGUIDLow());
+ TC_LOG_DEBUG("misc", "Player (GUID: %u) move confused", _owner->GetGUID().GetCounter());
Mutate(new ConfusedMovementGenerator<Player>(), MOTION_SLOT_CONTROLLED);
}
else
{
TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) move confused",
- _owner->GetEntry(), _owner->GetGUIDLow());
+ _owner->GetEntry(), _owner->GetGUID().GetCounter());
Mutate(new ConfusedMovementGenerator<Creature>(), MOTION_SLOT_CONTROLLED);
}
}
@@ -248,17 +248,17 @@ void MotionMaster::MoveChase(Unit* target, float dist, float angle)
if (_owner->GetTypeId() == TYPEID_PLAYER)
{
TC_LOG_DEBUG("misc", "Player (GUID: %u) chase to %s (GUID: %u)",
- _owner->GetGUIDLow(),
+ _owner->GetGUID().GetCounter(),
target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature",
- target->GetTypeId() == TYPEID_PLAYER ? target->GetGUIDLow() : target->ToCreature()->GetDBTableGUIDLow());
+ target->GetTypeId() == TYPEID_PLAYER ? target->GetGUID().GetCounter() : target->ToCreature()->GetSpawnId());
Mutate(new ChaseMovementGenerator<Player>(target, dist, angle), MOTION_SLOT_ACTIVE);
}
else
{
TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) chase to %s (GUID: %u)",
- _owner->GetEntry(), _owner->GetGUIDLow(),
+ _owner->GetEntry(), _owner->GetGUID().GetCounter(),
target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature",
- target->GetTypeId() == TYPEID_PLAYER ? target->GetGUIDLow() : target->ToCreature()->GetDBTableGUIDLow());
+ target->GetTypeId() == TYPEID_PLAYER ? target->GetGUID().GetCounter() : target->ToCreature()->GetSpawnId());
Mutate(new ChaseMovementGenerator<Creature>(target, dist, angle), MOTION_SLOT_ACTIVE);
}
}
@@ -272,17 +272,17 @@ void MotionMaster::MoveFollow(Unit* target, float dist, float angle, MovementSlo
//_owner->AddUnitState(UNIT_STATE_FOLLOW);
if (_owner->GetTypeId() == TYPEID_PLAYER)
{
- TC_LOG_DEBUG("misc", "Player (GUID: %u) follow to %s (GUID: %u)", _owner->GetGUIDLow(),
+ TC_LOG_DEBUG("misc", "Player (GUID: %u) follow to %s (GUID: %u)", _owner->GetGUID().GetCounter(),
target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature",
- target->GetTypeId() == TYPEID_PLAYER ? target->GetGUIDLow() : target->ToCreature()->GetDBTableGUIDLow());
+ target->GetTypeId() == TYPEID_PLAYER ? target->GetGUID().GetCounter() : target->ToCreature()->GetSpawnId());
Mutate(new FollowMovementGenerator<Player>(target, dist, angle), slot);
}
else
{
TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) follow to %s (GUID: %u)",
- _owner->GetEntry(), _owner->GetGUIDLow(),
+ _owner->GetEntry(), _owner->GetGUID().GetCounter(),
target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature",
- target->GetTypeId() == TYPEID_PLAYER ? target->GetGUIDLow() : target->ToCreature()->GetDBTableGUIDLow());
+ target->GetTypeId() == TYPEID_PLAYER ? target->GetGUID().GetCounter() : target->ToCreature()->GetSpawnId());
Mutate(new FollowMovementGenerator<Creature>(target, dist, angle), slot);
}
}
@@ -291,13 +291,13 @@ void MotionMaster::MovePoint(uint32 id, float x, float y, float z, bool generate
{
if (_owner->GetTypeId() == TYPEID_PLAYER)
{
- TC_LOG_DEBUG("misc", "Player (GUID: %u) targeted point (Id: %u X: %f Y: %f Z: %f)", _owner->GetGUIDLow(), id, x, y, z);
+ TC_LOG_DEBUG("misc", "Player (GUID: %u) targeted point (Id: %u X: %f Y: %f Z: %f)", _owner->GetGUID().GetCounter(), id, x, y, z);
Mutate(new PointMovementGenerator<Player>(id, x, y, z, generatePath), MOTION_SLOT_ACTIVE);
}
else
{
TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) targeted point (ID: %u X: %f Y: %f Z: %f)",
- _owner->GetEntry(), _owner->GetGUIDLow(), id, x, y, z);
+ _owner->GetEntry(), _owner->GetGUID().GetCounter(), id, x, y, z);
Mutate(new PointMovementGenerator<Creature>(id, x, y, z, generatePath), MOTION_SLOT_ACTIVE);
}
}
@@ -371,7 +371,7 @@ void MotionMaster::MoveJumpTo(float angle, float speedXY, float speedZ)
void MotionMaster::MoveJump(float x, float y, float z, float speedXY, float speedZ, uint32 id)
{
- TC_LOG_DEBUG("misc", "Unit (GUID: %u) jump to point (X: %f Y: %f Z: %f)", _owner->GetGUIDLow(), x, y, z);
+ TC_LOG_DEBUG("misc", "Unit (GUID: %u) jump to point (X: %f Y: %f Z: %f)", _owner->GetGUID().GetCounter(), x, y, z);
if (speedXY <= 0.1f)
return;
@@ -423,6 +423,24 @@ void MotionMaster::MoveCirclePath(float x, float y, float z, float radius, bool
init.Launch();
}
+void MotionMaster::MoveSmoothPath(uint32 pointId, G3D::Vector3 const* pathPoints, size_t pathSize, bool walk)
+{
+ Movement::PointsArray path(pathPoints, pathPoints + pathSize);
+
+ Movement::MoveSplineInit init(_owner);
+ init.MovebyPath(path);
+ init.SetSmooth();
+ init.SetWalk(walk);
+ init.Launch();
+
+ // This code is not correct
+ // EffectMovementGenerator does not affect UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE
+ // need to call PointMovementGenerator with various pointIds
+ Mutate(new EffectMovementGenerator(pointId), MOTION_SLOT_ACTIVE);
+ //Position pos(pathPoints[pathSize - 1].x, pathPoints[pathSize - 1].y, pathPoints[pathSize - 1].z);
+ //MovePoint(EVENT_CHARGE_PREPATH, pos, false);
+}
+
void MotionMaster::MoveFall(uint32 id /*=0*/)
{
// use larger distance for vmap height search than in most other cases
@@ -458,13 +476,13 @@ void MotionMaster::MoveCharge(float x, float y, float z, float speed /*= SPEED_C
if (_owner->GetTypeId() == TYPEID_PLAYER)
{
- TC_LOG_DEBUG("misc", "Player (GUID: %u) charge point (X: %f Y: %f Z: %f)", _owner->GetGUIDLow(), x, y, z);
+ TC_LOG_DEBUG("misc", "Player (GUID: %u) charge point (X: %f Y: %f Z: %f)", _owner->GetGUID().GetCounter(), x, y, z);
Mutate(new PointMovementGenerator<Player>(id, x, y, z, generatePath, speed), MOTION_SLOT_CONTROLLED);
}
else
{
TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) charge point (X: %f Y: %f Z: %f)",
- _owner->GetEntry(), _owner->GetGUIDLow(), x, y, z);
+ _owner->GetEntry(), _owner->GetGUID().GetCounter(), x, y, z);
Mutate(new PointMovementGenerator<Creature>(id, x, y, z, generatePath, speed), MOTION_SLOT_CONTROLLED);
}
}
@@ -486,12 +504,12 @@ void MotionMaster::MoveSeekAssistance(float x, float y, float z)
{
if (_owner->GetTypeId() == TYPEID_PLAYER)
{
- TC_LOG_ERROR("misc", "Player (GUID: %u) attempt to seek assistance", _owner->GetGUIDLow());
+ TC_LOG_ERROR("misc", "Player (GUID: %u) attempt to seek assistance", _owner->GetGUID().GetCounter());
}
else
{
TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) seek assistance (X: %f Y: %f Z: %f)",
- _owner->GetEntry(), _owner->GetGUIDLow(), x, y, z);
+ _owner->GetEntry(), _owner->GetGUID().GetCounter(), x, y, z);
_owner->AttackStop();
_owner->ToCreature()->SetReactState(REACT_PASSIVE);
Mutate(new AssistanceMovementGenerator(x, y, z), MOTION_SLOT_ACTIVE);
@@ -502,12 +520,12 @@ void MotionMaster::MoveSeekAssistanceDistract(uint32 time)
{
if (_owner->GetTypeId() == TYPEID_PLAYER)
{
- TC_LOG_ERROR("misc", "Player (GUID: %u) attempt to call distract after assistance", _owner->GetGUIDLow());
+ TC_LOG_ERROR("misc", "Player (GUID: %u) attempt to call distract after assistance", _owner->GetGUID().GetCounter());
}
else
{
TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) is distracted after assistance call (Time: %u)",
- _owner->GetEntry(), _owner->GetGUIDLow(), time);
+ _owner->GetEntry(), _owner->GetGUID().GetCounter(), time);
Mutate(new AssistanceDistractMovementGenerator(time), MOTION_SLOT_ACTIVE);
}
}
@@ -519,17 +537,17 @@ void MotionMaster::MoveFleeing(Unit* enemy, uint32 time)
if (_owner->GetTypeId() == TYPEID_PLAYER)
{
- TC_LOG_DEBUG("misc", "Player (GUID: %u) flee from %s (GUID: %u)", _owner->GetGUIDLow(),
+ TC_LOG_DEBUG("misc", "Player (GUID: %u) flee from %s (GUID: %u)", _owner->GetGUID().GetCounter(),
enemy->GetTypeId() == TYPEID_PLAYER ? "player" : "creature",
- enemy->GetTypeId() == TYPEID_PLAYER ? enemy->GetGUIDLow() : enemy->ToCreature()->GetDBTableGUIDLow());
+ enemy->GetTypeId() == TYPEID_PLAYER ? enemy->GetGUID().GetCounter() : enemy->ToCreature()->GetSpawnId());
Mutate(new FleeingMovementGenerator<Player>(enemy->GetGUID()), MOTION_SLOT_CONTROLLED);
}
else
{
TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) flee from %s (GUID: %u)%s",
- _owner->GetEntry(), _owner->GetGUIDLow(),
+ _owner->GetEntry(), _owner->GetGUID().GetCounter(),
enemy->GetTypeId() == TYPEID_PLAYER ? "player" : "creature",
- enemy->GetTypeId() == TYPEID_PLAYER ? enemy->GetGUIDLow() : enemy->ToCreature()->GetDBTableGUIDLow(),
+ enemy->GetTypeId() == TYPEID_PLAYER ? enemy->GetGUID().GetCounter() : enemy->ToCreature()->GetSpawnId(),
time ? " for a limited time" : "");
if (time)
Mutate(new TimedFleeingMovementGenerator(enemy->GetGUID(), time), MOTION_SLOT_CONTROLLED);
@@ -545,7 +563,8 @@ void MotionMaster::MoveTaxiFlight(uint32 path, uint32 pathnode)
if (path < sTaxiPathNodesByPath.size())
{
TC_LOG_DEBUG("misc", "%s taxi to (Path %u node %u)", _owner->GetName().c_str(), path, pathnode);
- FlightPathMovementGenerator* mgen = new FlightPathMovementGenerator(sTaxiPathNodesByPath[path], pathnode);
+ FlightPathMovementGenerator* mgen = new FlightPathMovementGenerator(pathnode);
+ mgen->LoadPath(_owner->ToPlayer());
Mutate(mgen, MOTION_SLOT_CONTROLLED);
}
else
@@ -557,7 +576,7 @@ void MotionMaster::MoveTaxiFlight(uint32 path, uint32 pathnode)
else
{
TC_LOG_ERROR("misc", "Creature (Entry: %u GUID: %u) attempt taxi to (Path %u node %u)",
- _owner->GetEntry(), _owner->GetGUIDLow(), path, pathnode);
+ _owner->GetEntry(), _owner->GetGUID().GetCounter(), path, pathnode);
}
}
@@ -568,12 +587,12 @@ void MotionMaster::MoveDistract(uint32 timer)
if (_owner->GetTypeId() == TYPEID_PLAYER)
{
- TC_LOG_DEBUG("misc", "Player (GUID: %u) distracted (timer: %u)", _owner->GetGUIDLow(), timer);
+ TC_LOG_DEBUG("misc", "Player (GUID: %u) distracted (timer: %u)", _owner->GetGUID().GetCounter(), timer);
}
else
{
TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) (timer: %u)",
- _owner->GetEntry(), _owner->GetGUIDLow(), timer);
+ _owner->GetEntry(), _owner->GetGUID().GetCounter(), timer);
}
DistractMovementGenerator* mgen = new DistractMovementGenerator(timer);
@@ -626,7 +645,7 @@ void MotionMaster::MovePath(uint32 path_id, bool repeatable)
TC_LOG_DEBUG("misc", "%s (GUID: %u) start moving over path(Id:%u, repeatable: %s)",
_owner->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature",
- _owner->GetGUIDLow(), path_id, repeatable ? "YES" : "NO");
+ _owner->GetGUID().GetCounter(), path_id, repeatable ? "YES" : "NO");
}
void MotionMaster::MoveRotate(uint32 time, RotateDirection direction)
diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h
index c8da50364ba..9a8950de9f7 100644
--- a/src/server/game/Movement/MotionMaster.h
+++ b/src/server/game/Movement/MotionMaster.h
@@ -185,6 +185,7 @@ class MotionMaster //: private std::stack<MovementGenerator *>
{ MoveJump(pos.m_positionX, pos.m_positionY, pos.m_positionZ, speedXY, speedZ, id); }
void MoveJump(float x, float y, float z, float speedXY, float speedZ, uint32 id = EVENT_JUMP);
void MoveCirclePath(float x, float y, float z, float radius, bool clockwise, uint8 stepCount);
+ void MoveSmoothPath(uint32 pointId, G3D::Vector3 const* pathPoints, size_t pathSize, bool walk);
void MoveFall(uint32 id = 0);
void MoveSeekAssistance(float x, float y, float z);
diff --git a/src/server/game/Movement/MovementGenerator.h b/src/server/game/Movement/MovementGenerator.h
index 879b8aea537..45fd252ddb9 100755
--- a/src/server/game/Movement/MovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerator.h
@@ -39,7 +39,7 @@ class MovementGenerator
virtual bool Update(Unit*, uint32 time_diff) = 0;
- virtual MovementGeneratorType GetMovementGeneratorType() = 0;
+ virtual MovementGeneratorType GetMovementGeneratorType() const = 0;
virtual void unitSpeedChanged() { }
diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h
index 4cc4baa081f..5b6d6c96482 100755
--- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h
@@ -33,7 +33,7 @@ class ConfusedMovementGenerator : public MovementGeneratorMedium< T, ConfusedMov
void DoReset(T*);
bool DoUpdate(T*, uint32);
- MovementGeneratorType GetMovementGeneratorType() { return CONFUSED_MOTION_TYPE; }
+ MovementGeneratorType GetMovementGeneratorType() const override { return CONFUSED_MOTION_TYPE; }
private:
TimeTracker i_nextMoveTime;
float i_x, i_y, i_z;
diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h
index d7cb956e541..dc42dc74991 100755
--- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h
@@ -32,7 +32,7 @@ class FleeingMovementGenerator : public MovementGeneratorMedium< T, FleeingMovem
void DoReset(T*);
bool DoUpdate(T*, uint32);
- MovementGeneratorType GetMovementGeneratorType() { return FLEEING_MOTION_TYPE; }
+ MovementGeneratorType GetMovementGeneratorType() const override { return FLEEING_MOTION_TYPE; }
private:
void _setTargetLocation(T*);
@@ -49,7 +49,7 @@ class TimedFleeingMovementGenerator : public FleeingMovementGenerator<Creature>
FleeingMovementGenerator<Creature>(fright),
i_totalFleeTime(time) { }
- MovementGeneratorType GetMovementGeneratorType() override { return TIMED_FLEEING_MOTION_TYPE; }
+ MovementGeneratorType GetMovementGeneratorType() const override { return TIMED_FLEEING_MOTION_TYPE; }
bool Update(Unit*, uint32) override;
void Finalize(Unit*) override;
diff --git a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
index 4245bffb864..7ab7534199a 100644
--- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
@@ -33,7 +33,7 @@ void HomeMovementGenerator<Creature>::DoFinalize(Creature* owner)
{
owner->ClearUnitState(UNIT_STATE_EVADE);
owner->SetWalk(true);
- owner->LoadCreaturesAddon(true);
+ owner->LoadCreaturesAddon();
owner->AI()->JustReachedHome();
}
}
diff --git a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h
index 099d81ff54e..cbb6f279c6d 100644
--- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h
@@ -38,7 +38,7 @@ class HomeMovementGenerator<Creature> : public MovementGeneratorMedium< Creature
void DoFinalize(Creature*);
void DoReset(Creature*);
bool DoUpdate(Creature*, const uint32);
- MovementGeneratorType GetMovementGeneratorType() override { return HOME_MOTION_TYPE; }
+ MovementGeneratorType GetMovementGeneratorType() const override { return HOME_MOTION_TYPE; }
private:
void _setTargetLocation(Creature*);
diff --git a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp
index 78d86fb7abb..2aaaa719e94 100755
--- a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp
@@ -81,12 +81,23 @@ void RotateMovementGenerator::Finalize(Unit* unit)
void DistractMovementGenerator::Initialize(Unit* owner)
{
+ // Distracted creatures stand up if not standing
+ if (!owner->IsStandState())
+ owner->SetStandState(UNIT_STAND_STATE_STAND);
+
owner->AddUnitState(UNIT_STATE_DISTRACTED);
}
void DistractMovementGenerator::Finalize(Unit* owner)
{
owner->ClearUnitState(UNIT_STATE_DISTRACTED);
+
+ // If this is a creature, then return orientation to original position (for idle movement creatures)
+ if (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature())
+ {
+ float angle = owner->ToCreature()->GetHomePosition().GetOrientation();
+ owner->SetFacingTo(angle);
+ }
}
bool DistractMovementGenerator::Update(Unit* /*owner*/, uint32 time_diff)
diff --git a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h
index e4ea99e00cb..30a8b9b868e 100755
--- a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h
@@ -29,7 +29,7 @@ class IdleMovementGenerator : public MovementGenerator
void Finalize(Unit*) override { }
void Reset(Unit*) override;
bool Update(Unit*, uint32) override { return true; }
- MovementGeneratorType GetMovementGeneratorType() override { return IDLE_MOTION_TYPE; }
+ MovementGeneratorType GetMovementGeneratorType() const override { return IDLE_MOTION_TYPE; }
};
extern IdleMovementGenerator si_idleMovement;
@@ -43,7 +43,7 @@ class RotateMovementGenerator : public MovementGenerator
void Finalize(Unit*) override;
void Reset(Unit* owner) override { Initialize(owner); }
bool Update(Unit*, uint32) override;
- MovementGeneratorType GetMovementGeneratorType() override { return ROTATE_MOTION_TYPE; }
+ MovementGeneratorType GetMovementGeneratorType() const override { return ROTATE_MOTION_TYPE; }
private:
uint32 m_duration, m_maxDuration;
@@ -59,7 +59,7 @@ class DistractMovementGenerator : public MovementGenerator
void Finalize(Unit*) override;
void Reset(Unit* owner) override { Initialize(owner); }
bool Update(Unit*, uint32) override;
- MovementGeneratorType GetMovementGeneratorType() override { return DISTRACT_MOTION_TYPE; }
+ MovementGeneratorType GetMovementGeneratorType() const override { return DISTRACT_MOTION_TYPE; }
private:
uint32 m_timer;
@@ -71,7 +71,7 @@ class AssistanceDistractMovementGenerator : public DistractMovementGenerator
AssistanceDistractMovementGenerator(uint32 timer) :
DistractMovementGenerator(timer) { }
- MovementGeneratorType GetMovementGeneratorType() override { return ASSISTANCE_DISTRACT_MOTION_TYPE; }
+ MovementGeneratorType GetMovementGeneratorType() const override { return ASSISTANCE_DISTRACT_MOTION_TYPE; }
void Finalize(Unit*) override;
};
diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h
index e967bd7f0ba..5b1155507aa 100644
--- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h
@@ -36,9 +36,9 @@ class PointMovementGenerator : public MovementGeneratorMedium< T, PointMovementG
void MovementInform(T*);
- void unitSpeedChanged() { i_recalculateSpeed = true; }
+ void unitSpeedChanged() override { i_recalculateSpeed = true; }
- MovementGeneratorType GetMovementGeneratorType() { return POINT_MOTION_TYPE; }
+ MovementGeneratorType GetMovementGeneratorType() const override { return POINT_MOTION_TYPE; }
void GetDestination(float& x, float& y, float& z) const { x = i_x; y = i_y; z = i_z; }
private:
@@ -55,7 +55,7 @@ class AssistanceMovementGenerator : public PointMovementGenerator<Creature>
AssistanceMovementGenerator(float _x, float _y, float _z) :
PointMovementGenerator<Creature>(0, _x, _y, _z, true) { }
- MovementGeneratorType GetMovementGeneratorType() override { return ASSISTANCE_MOTION_TYPE; }
+ MovementGeneratorType GetMovementGeneratorType() const override { return ASSISTANCE_MOTION_TYPE; }
void Finalize(Unit*) override;
};
@@ -68,7 +68,7 @@ class EffectMovementGenerator : public MovementGenerator
void Finalize(Unit*) override;
void Reset(Unit*) override { }
bool Update(Unit*, uint32) override;
- MovementGeneratorType GetMovementGeneratorType() override { return EFFECT_MOTION_TYPE; }
+ MovementGeneratorType GetMovementGeneratorType() const override { return EFFECT_MOTION_TYPE; }
private:
uint32 m_Id;
};
diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h
index 175e512c35d..763e3294613 100644
--- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h
@@ -33,7 +33,7 @@ class RandomMovementGenerator : public MovementGeneratorMedium< T, RandomMovemen
void DoReset(T*);
bool DoUpdate(T*, const uint32);
bool GetResetPos(T*, float& x, float& y, float& z);
- MovementGeneratorType GetMovementGeneratorType() { return RANDOM_MOTION_TYPE; }
+ MovementGeneratorType GetMovementGeneratorType() const override { return RANDOM_MOTION_TYPE; }
private:
TimeTrackerSmall i_nextMoveTime;
diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
index 31859899ce8..40bf3af5194 100644
--- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
@@ -232,7 +232,7 @@ void ChaseMovementGenerator<Creature>::MovementInform(Creature* unit)
{
// Pass back the GUIDLow of the target. If it is pet's owner then PetAI will handle
if (unit->AI())
- unit->AI()->MovementInform(CHASE_MOTION_TYPE, i_target.getTarget()->GetGUIDLow());
+ unit->AI()->MovementInform(CHASE_MOTION_TYPE, i_target.getTarget()->GetGUID().GetCounter());
}
//-----------------------------------------------//
@@ -304,7 +304,7 @@ void FollowMovementGenerator<Creature>::MovementInform(Creature* unit)
{
// Pass back the GUIDLow of the target. If it is pet's owner then PetAI will handle
if (unit->AI())
- unit->AI()->MovementInform(FOLLOW_MOTION_TYPE, i_target.getTarget()->GetGUIDLow());
+ unit->AI()->MovementInform(FOLLOW_MOTION_TYPE, i_target.getTarget()->GetGUID().GetCounter());
}
//-----------------------------------------------//
diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h
index 44d64909a3c..77a669e0738 100755
--- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h
@@ -73,7 +73,7 @@ class ChaseMovementGenerator : public TargetedMovementGeneratorMedium<T, ChaseMo
: TargetedMovementGeneratorMedium<T, ChaseMovementGenerator<T> >(target, offset, angle) { }
~ChaseMovementGenerator() { }
- MovementGeneratorType GetMovementGeneratorType() { return CHASE_MOTION_TYPE; }
+ MovementGeneratorType GetMovementGeneratorType() const override { return CHASE_MOTION_TYPE; }
void DoInitialize(T*);
void DoFinalize(T*);
@@ -97,7 +97,7 @@ class FollowMovementGenerator : public TargetedMovementGeneratorMedium<T, Follow
: TargetedMovementGeneratorMedium<T, FollowMovementGenerator<T> >(target, offset, angle) { }
~FollowMovementGenerator() { }
- MovementGeneratorType GetMovementGeneratorType() { return FOLLOW_MOTION_TYPE; }
+ MovementGeneratorType GetMovementGeneratorType() const override { return FOLLOW_MOTION_TYPE; }
void DoInitialize(T*);
void DoFinalize(T*);
diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
index f91fc1985d5..fe618e6ece7 100755
--- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
@@ -41,7 +41,7 @@ void WaypointMovementGenerator<Creature>::LoadPath(Creature* creature)
if (!i_path)
{
// No path id found for entry
- TC_LOG_ERROR("sql.sql", "WaypointMovementGenerator::LoadPath: creature %s (Entry: %u GUID: %u DB GUID: %u) doesn't have waypoint path id: %u", creature->GetName().c_str(), creature->GetEntry(), creature->GetGUIDLow(), creature->GetDBTableGUIDLow(), path_id);
+ TC_LOG_ERROR("sql.sql", "WaypointMovementGenerator::LoadPath: creature %s (Entry: %u GUID: %u DB GUID: %u) doesn't have waypoint path id: %u", creature->GetName().c_str(), creature->GetEntry(), creature->GetGUID().GetCounter(), creature->GetSpawnId(), path_id);
return;
}
@@ -245,17 +245,62 @@ bool WaypointMovementGenerator<Creature>::GetResetPos(Creature*, float& x, float
uint32 FlightPathMovementGenerator::GetPathAtMapEnd() const
{
- if (i_currentNode >= i_path->size())
- return i_path->size();
+ if (i_currentNode >= i_path.size())
+ return i_path.size();
- uint32 curMapId = (*i_path)[i_currentNode].MapID;
- for (uint32 i = i_currentNode; i < i_path->size(); ++i)
- {
- if ((*i_path)[i].MapID != curMapId)
+ uint32 curMapId = i_path[i_currentNode]->MapID;
+ for (uint32 i = i_currentNode; i < i_path.size(); ++i)
+ if (i_path[i]->MapID != curMapId)
return i;
- }
- return i_path->size();
+ return i_path.size();
+}
+
+#define SKIP_SPLINE_POINT_DISTANCE_SQ (40.0f * 40.0f)
+
+bool IsNodeIncludedInShortenedPath(TaxiPathNodeEntry const* p1, TaxiPathNodeEntry const* p2)
+{
+ return p1->MapID != p2->MapID || std::pow(p1->LocX - p2->LocX, 2) + std::pow(p1->LocY - p2->LocY, 2) > SKIP_SPLINE_POINT_DISTANCE_SQ;
+}
+
+void FlightPathMovementGenerator::LoadPath(Player* player)
+{
+ _pointsForPathSwitch.clear();
+ std::deque<uint32> const& taxi = player->m_taxi.GetPath();
+ for (uint32 src = 0, dst = 1; dst < taxi.size(); src = dst++)
+ {
+ uint32 path, cost;
+ sObjectMgr->GetTaxiPath(taxi[src], taxi[dst], path, cost);
+ if (path > sTaxiPathNodesByPath.size())
+ return;
+
+ TaxiPathNodeList const& nodes = sTaxiPathNodesByPath[path];
+ if (!nodes.empty())
+ {
+ TaxiPathNodeEntry const* start = nodes[0];
+ TaxiPathNodeEntry const* end = nodes[nodes.size() - 1];
+ bool passedPreviousSegmentProximityCheck = false;
+ for (uint32 i = 0; i < nodes.size(); ++i)
+ {
+ if (passedPreviousSegmentProximityCheck || !src || i_path.empty() || IsNodeIncludedInShortenedPath(i_path[i_path.size() - 1], nodes[i]))
+ {
+ if ((!src || (IsNodeIncludedInShortenedPath(start, nodes[i]) && i >= 2)) &&
+ (dst == taxi.size() - 1 || (IsNodeIncludedInShortenedPath(end, nodes[i]) && i < nodes.size() - 1)))
+ {
+ passedPreviousSegmentProximityCheck = true;
+ i_path.push_back(nodes[i]);
+ }
+ }
+ else
+ {
+ i_path.pop_back();
+ --_pointsForPathSwitch.back().PathIndex;
+ }
+ }
+ }
+
+ _pointsForPathSwitch.push_back({ uint32(i_path.size() - 1), int32(cost) });
+ }
}
void FlightPathMovementGenerator::DoInitialize(Player* player)
@@ -296,7 +341,7 @@ void FlightPathMovementGenerator::DoReset(Player* player)
uint32 end = GetPathAtMapEnd();
for (uint32 i = GetCurrentNode(); i != end; ++i)
{
- G3D::Vector3 vertice((*i_path)[i].LocX, (*i_path)[i].LocY, (*i_path)[i].LocZ);
+ G3D::Vector3 vertice(i_path[i]->LocX, i_path[i]->LocY, i_path[i]->LocZ);
init.Path().push_back(vertice);
}
init.SetFirstPointId(GetCurrentNode());
@@ -313,9 +358,21 @@ bool FlightPathMovementGenerator::DoUpdate(Player* player, uint32 /*diff*/)
bool departureEvent = true;
do
{
- DoEventIfAny(player, (*i_path)[i_currentNode], departureEvent);
+ DoEventIfAny(player, i_path[i_currentNode], departureEvent);
+ while (!_pointsForPathSwitch.empty() && _pointsForPathSwitch.front().PathIndex <= i_currentNode)
+ {
+ _pointsForPathSwitch.pop_front();
+ player->m_taxi.NextTaxiDestination();
+ if (!_pointsForPathSwitch.empty())
+ {
+ player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING, _pointsForPathSwitch.front().Cost);
+ player->ModifyMoney(-_pointsForPathSwitch.front().Cost);
+ }
+ }
+
if (pointId == i_currentNode)
break;
+
if (i_currentNode == _preloadTargetNode)
PreloadEndGrid();
i_currentNode += (uint32)departureEvent;
@@ -324,18 +381,18 @@ bool FlightPathMovementGenerator::DoUpdate(Player* player, uint32 /*diff*/)
while (true);
}
- return i_currentNode < (i_path->size()-1);
+ return i_currentNode < (i_path.size() - 1);
}
void FlightPathMovementGenerator::SetCurrentNodeAfterTeleport()
{
- if (i_path->empty())
+ if (i_path.empty() || i_currentNode >= i_path.size())
return;
- uint32 map0 = (*i_path)[0].MapID;
- for (size_t i = 1; i < i_path->size(); ++i)
+ uint32 map0 = i_path[i_currentNode]->MapID;
+ for (size_t i = i_currentNode + 1; i < i_path.size(); ++i)
{
- if ((*i_path)[i].MapID != map0)
+ if (i_path[i]->MapID != map0)
{
i_currentNode = i;
return;
@@ -343,19 +400,21 @@ void FlightPathMovementGenerator::SetCurrentNodeAfterTeleport()
}
}
-void FlightPathMovementGenerator::DoEventIfAny(Player* player, TaxiPathNodeEntry const& node, bool departure)
+void FlightPathMovementGenerator::DoEventIfAny(Player* player, TaxiPathNodeEntry const* node, bool departure)
{
- if (uint32 eventid = departure ? node.DepartureEventID : node.ArrivalEventID)
+ if (uint32 eventid = departure ? node->DepartureEventID : node->ArrivalEventID)
{
- TC_LOG_DEBUG("maps.script", "Taxi %s event %u of node %u of path %u for player %s", departure ? "departure" : "arrival", eventid, node.NodeIndex, node.PathID, player->GetName().c_str());
+ TC_LOG_DEBUG("maps.script", "Taxi %s event %u of node %u of path %u for player %s", departure ? "departure" : "arrival", eventid, node->NodeIndex, node->PathID, player->GetName().c_str());
player->GetMap()->ScriptsStart(sEventScripts, eventid, player, player);
}
}
bool FlightPathMovementGenerator::GetResetPos(Player*, float& x, float& y, float& z)
{
- const TaxiPathNodeEntry& node = (*i_path)[i_currentNode];
- x = node.LocX; y = node.LocY; z = node.LocZ;
+ TaxiPathNodeEntry const* node = i_path[i_currentNode];
+ x = node->LocX;
+ y = node->LocY;
+ z = node->LocZ;
return true;
}
@@ -363,11 +422,11 @@ void FlightPathMovementGenerator::InitEndGridInfo()
{
/*! Storage to preload flightmaster grid at end of flight. For multi-stop flights, this will
be reinitialized for each flightmaster at the end of each spline (or stop) in the flight. */
- uint32 nodeCount = (*i_path).size(); //! Number of nodes in path.
- _endMapId = (*i_path)[nodeCount - 1].MapID; //! MapId of last node
+ uint32 nodeCount = i_path.size(); //! Number of nodes in path.
+ _endMapId = i_path[nodeCount - 1]->MapID; //! MapId of last node
_preloadTargetNode = nodeCount - 3;
- _endGridX = (*i_path)[nodeCount - 1].LocX;
- _endGridY = (*i_path)[nodeCount - 1].LocY;
+ _endGridX = i_path[nodeCount - 1]->LocX;
+ _endGridY = i_path[nodeCount - 1]->LocY;
}
void FlightPathMovementGenerator::PreloadEndGrid()
@@ -378,7 +437,7 @@ void FlightPathMovementGenerator::PreloadEndGrid()
// Load the grid
if (endMap)
{
- TC_LOG_DEBUG("misc", "Preloading rid (%f, %f) for map %u at node index %u/%u", _endGridX, _endGridY, _endMapId, _preloadTargetNode, (uint32)(i_path->size()-1));
+ TC_LOG_DEBUG("misc", "Preloading rid (%f, %f) for map %u at node index %u/%u", _endGridX, _endGridY, _endMapId, _preloadTargetNode, (uint32)(i_path.size() - 1));
endMap->LoadGrid(_endGridX, _endGridY);
}
else
diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
index f65af3fb73d..caf76b5ea19 100755
--- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
@@ -27,13 +27,8 @@
#include "MovementGenerator.h"
#include "WaypointManager.h"
-#include "Path.h"
-
#include "Player.h"
-#include <vector>
-#include <set>
-
#define FLIGHT_TRAVEL_UPDATE 100
#define STOP_TIME_FOR_PLAYER 3 * MINUTE * IN_MILLISECONDS // 3 Minutes
#define TIMEDIFF_NEXT_WP 250
@@ -42,11 +37,9 @@ template<class T, class P>
class PathMovementBase
{
public:
- PathMovementBase() : i_path(NULL), i_currentNode(0) { }
+ PathMovementBase() : i_path(), i_currentNode(0) { }
virtual ~PathMovementBase() { };
- // template pattern, not defined .. override required
- void LoadPath(T &);
uint32 GetCurrentNode() const { return i_currentNode; }
protected:
@@ -72,7 +65,7 @@ class WaypointMovementGenerator<Creature> : public MovementGeneratorMedium< Crea
void MovementInform(Creature*);
- MovementGeneratorType GetMovementGeneratorType() override { return WAYPOINT_MOTION_TYPE; }
+ MovementGeneratorType GetMovementGeneratorType() const override { return WAYPOINT_MOTION_TYPE; }
// now path movement implmementation
void LoadPath(Creature*);
@@ -110,30 +103,30 @@ class WaypointMovementGenerator<Creature> : public MovementGeneratorMedium< Crea
* and hence generates ground and activities for the player.
*/
class FlightPathMovementGenerator : public MovementGeneratorMedium< Player, FlightPathMovementGenerator >,
- public PathMovementBase<Player, TaxiPathNodeList const*>
+ public PathMovementBase<Player, TaxiPathNodeList>
{
public:
- explicit FlightPathMovementGenerator(TaxiPathNodeList const& pathnodes, uint32 startNode = 0)
+ explicit FlightPathMovementGenerator(uint32 startNode = 0)
{
- i_path = &pathnodes;
i_currentNode = startNode;
_endGridX = 0.0f;
_endGridY = 0.0f;
_endMapId = 0;
_preloadTargetNode = 0;
}
+ void LoadPath(Player* player);
void DoInitialize(Player*);
void DoReset(Player*);
void DoFinalize(Player*);
bool DoUpdate(Player*, uint32);
- MovementGeneratorType GetMovementGeneratorType() override { return FLIGHT_MOTION_TYPE; }
+ MovementGeneratorType GetMovementGeneratorType() const override { return FLIGHT_MOTION_TYPE; }
- TaxiPathNodeList const& GetPath() { return *i_path; }
+ TaxiPathNodeList const& GetPath() { return i_path; }
uint32 GetPathAtMapEnd() const;
- bool HasArrived() const { return (i_currentNode >= i_path->size()); }
+ bool HasArrived() const { return (i_currentNode >= i_path.size()); }
void SetCurrentNodeAfterTeleport();
void SkipCurrentNode() { ++i_currentNode; }
- void DoEventIfAny(Player* player, TaxiPathNodeEntry const& node, bool departure);
+ void DoEventIfAny(Player* player, TaxiPathNodeEntry const* node, bool departure);
bool GetResetPos(Player*, float& x, float& y, float& z);
@@ -141,9 +134,18 @@ class FlightPathMovementGenerator : public MovementGeneratorMedium< Player, Flig
void PreloadEndGrid();
private:
- float _endGridX; //! X coord of last node location
- float _endGridY; //! Y coord of last node location
- uint32 _endMapId; //! map Id of last node location
- uint32 _preloadTargetNode; //! node index where preloading starts
+
+ float _endGridX; //! X coord of last node location
+ float _endGridY; //! Y coord of last node location
+ uint32 _endMapId; //! map Id of last node location
+ uint32 _preloadTargetNode; //! node index where preloading starts
+
+ struct TaxiNodeChangeInfo
+ {
+ uint32 PathIndex;
+ int32 Cost;
+ };
+
+ std::deque<TaxiNodeChangeInfo> _pointsForPathSwitch; //! node indexes and costs where TaxiPath changes
};
#endif
diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp
index afd1f73c785..3b4f19adb0b 100644
--- a/src/server/game/Movement/PathGenerator.cpp
+++ b/src/server/game/Movement/PathGenerator.cpp
@@ -35,7 +35,7 @@ PathGenerator::PathGenerator(const Unit* owner) :
{
memset(_pathPolyRefs, 0, sizeof(_pathPolyRefs));
- TC_LOG_DEBUG("maps", "++ PathGenerator::PathGenerator for %u \n", _sourceUnit->GetGUIDLow());
+ TC_LOG_DEBUG("maps", "++ PathGenerator::PathGenerator for %u \n", _sourceUnit->GetGUID().GetCounter());
uint32 mapId = _sourceUnit->GetMapId();
if (DisableMgr::IsPathfindingEnabled(mapId))
@@ -50,7 +50,7 @@ PathGenerator::PathGenerator(const Unit* owner) :
PathGenerator::~PathGenerator()
{
- TC_LOG_DEBUG("maps", "++ PathGenerator::~PathGenerator() for %u \n", _sourceUnit->GetGUIDLow());
+ TC_LOG_DEBUG("maps", "++ PathGenerator::~PathGenerator() for %u \n", _sourceUnit->GetGUID().GetCounter());
}
bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool forceDest, bool straightLine)
@@ -70,7 +70,7 @@ bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool fo
_forceDestination = forceDest;
_straightLine = straightLine;
- TC_LOG_DEBUG("maps", "++ PathGenerator::CalculatePath() for %u \n", _sourceUnit->GetGUIDLow());
+ TC_LOG_DEBUG("maps", "++ PathGenerator::CalculatePath() for %u \n", _sourceUnit->GetGUID().GetCounter());
// make sure navMesh works - we can run on map w/o mmap
// check if the start and end point have a .mmtile loaded (can we pass via not loaded tile on the way?)
@@ -116,7 +116,7 @@ dtPolyRef PathGenerator::GetPathPolyByPosition(dtPolyRef const* polyPath, uint32
}
if (distance)
- *distance = dtSqrt(minDist3d);
+ *distance = dtMathSqrtf(minDist3d);
return (minDist2d < 3.0f) ? nearestPoly : INVALID_POLYREF;
}
@@ -392,7 +392,7 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con
// this is probably an error state, but we'll leave it
// and hopefully recover on the next Update
// we still need to copy our preffix
- TC_LOG_ERROR("maps", "%u's Path Build failed: 0 length path", _sourceUnit->GetGUIDLow());
+ TC_LOG_ERROR("maps", "%u's Path Build failed: 0 length path", _sourceUnit->GetGUID().GetCounter());
}
TC_LOG_DEBUG("maps", "++ m_polyLength=%u prefixPolyLength=%u suffixPolyLength=%u \n", _polyLength, prefixPolyLength, suffixPolyLength);
@@ -453,7 +453,7 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con
if (!_polyLength || dtStatusFailed(dtResult))
{
// only happens if we passed bad data to findPath(), or navmesh is messed up
- TC_LOG_ERROR("maps", "%u's Path Build failed: 0 length path", _sourceUnit->GetGUIDLow());
+ TC_LOG_ERROR("maps", "%u's Path Build failed: 0 length path", _sourceUnit->GetGUID().GetCounter());
BuildShortcut();
_type = PATHFIND_NOPATH;
return;
@@ -799,7 +799,7 @@ dtStatus PathGenerator::FindSmoothPath(float const* startPos, float const* endPo
// Find movement delta.
float delta[VERTEX_SIZE];
dtVsub(delta, steerPos, iterPos);
- float len = dtSqrt(dtVdot(delta, delta));
+ float len = dtMathSqrtf(dtVdot(delta, delta));
// If the steer target is end of path or off-mesh link, do not move past the location.
if ((endOfPath || offMeshConnection) && len < SMOOTH_PATH_STEP_SIZE)
len = 1.0f;
@@ -853,16 +853,16 @@ dtStatus PathGenerator::FindSmoothPath(float const* startPos, float const* endPo
npolys -= npos;
// Handle the connection.
- float startPos[VERTEX_SIZE], endPos[VERTEX_SIZE];
- if (dtStatusSucceed(_navMesh->getOffMeshConnectionPolyEndPoints(prevRef, polyRef, startPos, endPos)))
+ float connectionStartPos[VERTEX_SIZE], connectionEndPos[VERTEX_SIZE];
+ if (dtStatusSucceed(_navMesh->getOffMeshConnectionPolyEndPoints(prevRef, polyRef, connectionStartPos, connectionEndPos)))
{
if (nsmoothPath < maxSmoothPathSize)
{
- dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], startPos);
+ dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], connectionStartPos);
nsmoothPath++;
}
// Move position at the other side of the off-mesh link.
- dtVcopy(iterPos, endPos);
+ dtVcopy(iterPos, connectionEndPos);
_navMeshQuery->getPolyHeight(polys[0], iterPos, &iterPos[1]);
iterPos[1] += 0.5f;
}
@@ -924,6 +924,7 @@ void PathGenerator::ReducePathLenghtByDist(float dist)
float step = dist / len;
// same as nextVec
_pathPoints[i + 1] -= diffVec * step;
+ _sourceUnit->UpdateAllowedPositionZ(_pathPoints[i + 1].x, _pathPoints[i + 1].y, _pathPoints[i + 1].z);
_pathPoints.resize(i + 2);
break;
}
diff --git a/src/server/game/Movement/PathGenerator.h b/src/server/game/Movement/PathGenerator.h
index a9a13c37251..71e0e88f0b2 100644
--- a/src/server/game/Movement/PathGenerator.h
+++ b/src/server/game/Movement/PathGenerator.h
@@ -19,7 +19,7 @@
#ifndef _PATH_GENERATOR_H
#define _PATH_GENERATOR_H
-#include "SharedDefines.h"
+#include "MapDefines.h"
#include "DetourNavMesh.h"
#include "DetourNavMeshQuery.h"
#include "MoveSplineInitArgs.h"
diff --git a/src/server/game/Movement/Spline/MoveSpline.cpp b/src/server/game/Movement/Spline/MoveSpline.cpp
index 1beeebbbad3..d8173aab331 100644
--- a/src/server/game/Movement/Spline/MoveSpline.cpp
+++ b/src/server/game/Movement/Spline/MoveSpline.cpp
@@ -17,10 +17,11 @@
*/
#include "MoveSpline.h"
-#include <sstream>
#include "Log.h"
#include "Creature.h"
+#include <sstream>
+
namespace Movement{
Location MoveSpline::ComputePosition() const
@@ -201,7 +202,7 @@ bool MoveSplineInitArgs::Validate(Unit* unit) const
#define CHECK(exp) \
if (!(exp))\
{\
- TC_LOG_ERROR("misc", "MoveSplineInitArgs::Validate: expression '%s' failed for GUID: %u Entry: %u", #exp, unit->GetTypeId() == TYPEID_PLAYER ? unit->GetGUIDLow() : unit->ToCreature()->GetDBTableGUIDLow(), unit->GetEntry());\
+ TC_LOG_ERROR("misc", "MoveSplineInitArgs::Validate: expression '%s' failed for GUID: %u Entry: %u", #exp, unit->GetTypeId() == TYPEID_PLAYER ? unit->GetGUID().GetCounter() : unit->ToCreature()->GetSpawnId(), unit->GetEntry());\
return false;\
}
CHECK(path.size() > 1);
diff --git a/src/server/game/Movement/Spline/Spline.cpp b/src/server/game/Movement/Spline/Spline.cpp
index b8a028b6fc0..fff83b788f9 100644
--- a/src/server/game/Movement/Spline/Spline.cpp
+++ b/src/server/game/Movement/Spline/Spline.cpp
@@ -204,7 +204,7 @@ void SplineBase::init_spline(const Vector3 * controls, index_type count, Evaluat
m_mode = m;
cyclic = false;
- (this->*initializers[m_mode])(controls, count, cyclic, 0);
+ (this->*initializers[m_mode])(controls, count, 0);
}
void SplineBase::init_cyclic_spline(const Vector3 * controls, index_type count, EvaluationMode m, index_type cyclic_point)
@@ -212,10 +212,10 @@ void SplineBase::init_cyclic_spline(const Vector3 * controls, index_type count,
m_mode = m;
cyclic = true;
- (this->*initializers[m_mode])(controls, count, cyclic, cyclic_point);
+ (this->*initializers[m_mode])(controls, count, cyclic_point);
}
-void SplineBase::InitLinear(const Vector3* controls, index_type count, bool cyclic, index_type cyclic_point)
+void SplineBase::InitLinear(const Vector3* controls, index_type count, index_type cyclic_point)
{
ASSERT(count >= 2);
const int real_size = count + 1;
@@ -235,7 +235,7 @@ void SplineBase::InitLinear(const Vector3* controls, index_type count, bool cycl
index_hi = cyclic ? count : (count - 1);
}
-void SplineBase::InitCatmullRom(const Vector3* controls, index_type count, bool cyclic, index_type cyclic_point)
+void SplineBase::InitCatmullRom(const Vector3* controls, index_type count, index_type cyclic_point)
{
const int real_size = count + (cyclic ? (1+2) : (1+1));
@@ -268,7 +268,7 @@ void SplineBase::InitCatmullRom(const Vector3* controls, index_type count, bool
index_hi = high_index + (cyclic ? 1 : 0);
}
-void SplineBase::InitBezier3(const Vector3* controls, index_type count, bool /*cyclic*/, index_type /*cyclic_point*/)
+void SplineBase::InitBezier3(const Vector3* controls, index_type count, index_type /*cyclic_point*/)
{
index_type c = count / 3u * 3u;
index_type t = c / 3u;
diff --git a/src/server/game/Movement/Spline/Spline.h b/src/server/game/Movement/Spline/Spline.h
index 6e8a5a0281d..59f514bed75 100644
--- a/src/server/game/Movement/Spline/Spline.h
+++ b/src/server/game/Movement/Spline/Spline.h
@@ -76,13 +76,13 @@ protected:
typedef float (SplineBase::*SegLenghtMethtod)(index_type) const;
static SegLenghtMethtod seglengths[ModesEnd];
- void InitLinear(const Vector3*, index_type, bool, index_type);
- void InitCatmullRom(const Vector3*, index_type, bool, index_type);
- void InitBezier3(const Vector3*, index_type, bool, index_type);
- typedef void (SplineBase::*InitMethtod)(const Vector3*, index_type, bool, index_type);
+ void InitLinear(const Vector3*, index_type, index_type);
+ void InitCatmullRom(const Vector3*, index_type, index_type);
+ void InitBezier3(const Vector3*, index_type, index_type);
+ typedef void (SplineBase::*InitMethtod)(const Vector3*, index_type, index_type);
static InitMethtod initializers[ModesEnd];
- void UninitializedSpline() const { ASSERT(false);}
+ void UninitializedSpline() const { ABORT();}
public:
diff --git a/src/server/game/Movement/Waypoints/Path.h b/src/server/game/Movement/Waypoints/Path.h
deleted file mode 100644
index bb8abc37eb3..00000000000
--- a/src/server/game/Movement/Waypoints/Path.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef TRINITYCORE_PATH_H
-#define TRINITYCORE_PATH_H
-
-#include "Common.h"
-#include <deque>
-
-struct PathNode
-{
- PathNode(): x(0.0f), y(0.0f), z(0.0f) { }
- PathNode(float _x, float _y, float _z): x(_x), y(_y), z(_z) { }
- float x, y, z;
-};
-template<typename PathElem, typename PathNode = PathElem>
-
-class Path
-{
- public:
- size_t size() const { return i_nodes.size(); }
- bool empty() const { return i_nodes.empty(); }
- void resize(unsigned int sz) { i_nodes.resize(sz); }
- void clear() { i_nodes.clear(); }
- void erase(uint32 idx) { i_nodes.erase(i_nodes.begin()+idx); }
- void crop(unsigned int start, unsigned int end)
- {
- while (start && !i_nodes.empty())
- {
- i_nodes.pop_front();
- --start;
- }
-
- while (end && !i_nodes.empty())
- {
- i_nodes.pop_back();
- --end;
- }
- }
-
- float GetTotalLength(uint32 start, uint32 end) const
- {
- float len = 0.0f;
- for (uint32 idx=start+1; idx < end; ++idx)
- {
- PathNode const& node = i_nodes[idx];
- PathNode const& prev = i_nodes[idx-1];
- float xd = node.x - prev.x;
- float yd = node.y - prev.y;
- float zd = node.z - prev.z;
- len += std::sqrt(xd*xd + yd*yd + zd*zd);
- }
- return len;
- }
-
- float GetTotalLength() const { return GetTotalLength(0, size()); }
-
- float GetPassedLength(uint32 curnode, float x, float y, float z) const
- {
- float len = GetTotalLength(0, curnode);
-
- if (curnode > 0)
- {
- PathNode const& node = i_nodes[curnode-1];
- float xd = x - node.x;
- float yd = y - node.y;
- float zd = z - node.z;
- len += std::sqrt(xd*xd + yd*yd + zd*zd);
- }
-
- return len;
- }
-
- PathNode& operator[](size_t idx) { return i_nodes[idx]; }
- PathNode const& operator[](size_t idx) const { return i_nodes[idx]; }
-
- void set(size_t idx, PathElem elem) { i_nodes[idx] = elem; }
-
- protected:
- std::deque<PathElem> i_nodes;
-};
-
-typedef Path<PathNode> SimplePath;
-
-#endif
diff --git a/src/server/game/OutdoorPvP/OutdoorPvP.cpp b/src/server/game/OutdoorPvP/OutdoorPvP.cpp
index c8bc68d0ddf..9046d9e6991 100644
--- a/src/server/game/OutdoorPvP/OutdoorPvP.cpp
+++ b/src/server/game/OutdoorPvP/OutdoorPvP.cpp
@@ -25,6 +25,7 @@
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
+#include "MapManager.h"
class DefenseMessageBuilder
{
@@ -48,7 +49,7 @@ class DefenseMessageBuilder
};
OPvPCapturePoint::OPvPCapturePoint(OutdoorPvP* pvp):
- m_capturePointGUID(), m_capturePoint(NULL), m_maxValue(0.0f), m_minValue(0.0f), m_maxSpeed(0),
+ m_capturePointSpawnId(), m_capturePoint(NULL), m_maxValue(0.0f), m_minValue(0.0f), m_maxSpeed(0),
m_value(0), m_team(TEAM_NEUTRAL), m_OldState(OBJECTIVESTATE_NEUTRAL),
m_State(OBJECTIVESTATE_NEUTRAL), m_neutralValuePct(0), m_PvP(pvp)
{ }
@@ -84,7 +85,7 @@ void OPvPCapturePoint::SendChangePhase()
SendUpdateWorldState(m_capturePoint->GetGOInfo()->capturePoint.worldstate3, m_neutralValuePct);
}
-void OPvPCapturePoint::AddGO(uint32 type, uint32 guid, uint32 entry)
+void OPvPCapturePoint::AddGO(uint32 type, ObjectGuid::LowType guid, uint32 entry)
{
if (!entry)
{
@@ -94,11 +95,11 @@ void OPvPCapturePoint::AddGO(uint32 type, uint32 guid, uint32 entry)
entry = data->id;
}
- m_Objects[type] = ObjectGuid(HIGHGUID_GAMEOBJECT, entry, guid);
+ m_Objects[type] = ObjectGuid(HighGuid::GameObject, entry, guid);
m_ObjectTypes[m_Objects[type]] = type;
}
-void OPvPCapturePoint::AddCre(uint32 type, uint32 guid, uint32 entry)
+void OPvPCapturePoint::AddCre(uint32 type, ObjectGuid::LowType guid, uint32 entry)
{
if (!entry)
{
@@ -108,13 +109,13 @@ void OPvPCapturePoint::AddCre(uint32 type, uint32 guid, uint32 entry)
entry = data->id;
}
- m_Creatures[type] = ObjectGuid(HIGHGUID_UNIT, entry, guid);
+ m_Creatures[type] = ObjectGuid(HighGuid::Unit, entry, guid);
m_CreatureTypes[m_Creatures[type]] = type;
}
bool OPvPCapturePoint::AddObject(uint32 type, uint32 entry, uint32 map, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3)
{
- if (uint32 guid = sObjectMgr->AddGOData(entry, map, x, y, z, o, 0, rotation0, rotation1, rotation2, rotation3))
+ if (ObjectGuid::LowType guid = sObjectMgr->AddGOData(entry, map, x, y, z, o, 0, rotation0, rotation1, rotation2, rotation3))
{
AddGO(type, guid, entry);
return true;
@@ -125,7 +126,7 @@ bool OPvPCapturePoint::AddObject(uint32 type, uint32 entry, uint32 map, float x,
bool OPvPCapturePoint::AddCreature(uint32 type, uint32 entry, uint32 map, float x, float y, float z, float o, TeamId /*teamId = TEAM_NEUTRAL*/, uint32 spawntimedelay /*= 0*/)
{
- if (uint32 guid = sObjectMgr->AddCreData(entry, map, x, y, z, o, spawntimedelay))
+ if (ObjectGuid::LowType guid = sObjectMgr->AddCreatureData(entry, map, x, y, z, o, spawntimedelay))
{
AddCre(type, guid, entry);
return true;
@@ -146,8 +147,9 @@ bool OPvPCapturePoint::SetCapturePointData(uint32 entry, uint32 map, float x, fl
return false;
}
- m_capturePointGUID = ObjectGuid(HIGHGUID_GAMEOBJECT, entry, sObjectMgr->AddGOData(entry, map, x, y, z, o, 0, rotation0, rotation1, rotation2, rotation3));
- if (!m_capturePointGUID)
+ m_capturePointSpawnId = sObjectMgr->AddGOData(entry, map, x, y, z, o, 0, rotation0, rotation1, rotation2, rotation3);
+
+ if (m_capturePointSpawnId == 0)
return false;
// get the needed values from goinfo
@@ -161,24 +163,25 @@ bool OPvPCapturePoint::SetCapturePointData(uint32 entry, uint32 map, float x, fl
bool OPvPCapturePoint::DelCreature(uint32 type)
{
- if (!m_Creatures[type])
+ uint32 spawnId = m_Creatures[type];
+ if (!spawnId)
{
TC_LOG_DEBUG("outdoorpvp", "opvp creature type %u was already deleted", type);
return false;
}
- Creature* cr = HashMapHolder<Creature>::Find(m_Creatures[type]);
- if (!cr)
+ auto bounds = m_PvP->GetMap()->GetCreatureBySpawnIdStore().equal_range(spawnId);
+ for (auto itr = bounds.first; itr != bounds.second;)
{
- // can happen when closing the core
- m_Creatures[type].Clear();
- return false;
+ Creature* c = itr->second;
+ ++itr;
+ // Don't save respawn time
+ c->SetRespawnTime(0);
+ c->RemoveCorpse();
+ c->AddObjectToRemoveList();
}
+
TC_LOG_DEBUG("outdoorpvp", "deleting opvp creature type %u", type);
- uint32 guid = cr->GetDBTableGUIDLow();
- // Don't save respawn time
- cr->SetRespawnTime(0);
- cr->RemoveCorpse();
// explicit removal from map
// beats me why this is needed, but with the recent removal "cleanup" some creatures stay in the map if "properly" deleted
// so this is a big fat workaround, if AddObjectToRemoveList and DoDelayedMovesAndRemoves worked correctly, this wouldn't be needed
@@ -186,15 +189,13 @@ bool OPvPCapturePoint::DelCreature(uint32 type)
// map->Remove(cr, false);
// delete respawn time for this creature
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CREATURE_RESPAWN);
- stmt->setUInt32(0, guid);
- stmt->setUInt16(1, cr->GetMapId());
- stmt->setUInt32(2, 0); // instance id, always 0 for world maps
+ stmt->setUInt32(0, spawnId);
+ stmt->setUInt16(1, m_PvP->GetMap()->GetId()); stmt->setUInt32(2, 0); // instance id, always 0 for world maps
CharacterDatabase.Execute(stmt);
- cr->AddObjectToRemoveList();
- sObjectMgr->DeleteCreatureData(guid);
+ sObjectMgr->DeleteCreatureData(spawnId);
m_CreatureTypes[m_Creatures[type]] = 0;
- m_Creatures[type].Clear();
+ m_Creatures[type] = 0;
return true;
}
@@ -203,25 +204,26 @@ bool OPvPCapturePoint::DelObject(uint32 type)
if (!m_Objects[type])
return false;
- GameObject* obj = HashMapHolder<GameObject>::Find(m_Objects[type]);
- if (!obj)
+ uint32 spawnId = m_Objects[type];
+ auto bounds = m_PvP->GetMap()->GetGameObjectBySpawnIdStore().equal_range(spawnId);
+ for (auto itr = bounds.first; itr != bounds.second;)
{
- m_Objects[type].Clear();
- return false;
+ GameObject* go = itr->second;
+ ++itr;
+ // Don't save respawn time
+ go->SetRespawnTime(0);
+ go->Delete();
}
- uint32 guid = obj->GetDBTableGUIDLow();
- obj->SetRespawnTime(0); // not save respawn time
- obj->Delete();
- sObjectMgr->DeleteGOData(guid);
+ sObjectMgr->DeleteGOData(spawnId);
m_ObjectTypes[m_Objects[type]] = 0;
- m_Objects[type].Clear();
+ m_Objects[type] = 0;
return true;
}
bool OPvPCapturePoint::DelCapturePoint()
{
- sObjectMgr->DeleteGOData(m_capturePointGUID.GetCounter());
- m_capturePointGUID.Clear();
+ sObjectMgr->DeleteGOData(m_capturePointSpawnId);
+ m_capturePointSpawnId = 0;
if (m_capturePoint)
{
@@ -234,15 +236,30 @@ bool OPvPCapturePoint::DelCapturePoint()
void OPvPCapturePoint::DeleteSpawns()
{
- for (std::map<uint32, ObjectGuid>::iterator i = m_Objects.begin(); i != m_Objects.end(); ++i)
+ for (std::map<uint32, uint32>::iterator i = m_Objects.begin(); i != m_Objects.end(); ++i)
DelObject(i->first);
- for (std::map<uint32, ObjectGuid>::iterator i = m_Creatures.begin(); i != m_Creatures.end(); ++i)
+ for (std::map<uint32, uint32>::iterator i = m_Creatures.begin(); i != m_Creatures.end(); ++i)
DelCreature(i->first);
DelCapturePoint();
}
void OutdoorPvP::DeleteSpawns()
{
+ // Remove script from any registered gameobjects/creatures
+ for (auto itr = m_GoScriptStore.begin(); itr != m_GoScriptStore.end(); ++itr)
+ {
+ if (GameObject* go = itr->second)
+ go->ClearZoneScript();
+ }
+ m_GoScriptStore.clear();
+
+ for (auto itr = m_CreatureScriptStore.begin(); itr != m_CreatureScriptStore.end(); ++itr)
+ {
+ if (Creature* creature = itr->second)
+ creature->ClearZoneScript();
+ }
+ m_CreatureScriptStore.clear();
+
for (OPvPCapturePointMap::iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr)
{
itr->second->DeleteSpawns();
@@ -251,7 +268,7 @@ void OutdoorPvP::DeleteSpawns()
m_capturePoints.clear();
}
-OutdoorPvP::OutdoorPvP() : m_TypeId(0), m_sendUpdate(true) { }
+OutdoorPvP::OutdoorPvP() : m_TypeId(0), m_sendUpdate(true), m_map(nullptr) { }
OutdoorPvP::~OutdoorPvP()
{
@@ -511,19 +528,19 @@ bool OPvPCapturePoint::HandleCustomSpell(Player* player, uint32 /*spellId*/, Gam
return true;
}
-bool OutdoorPvP::HandleOpenGo(Player* player, ObjectGuid guid)
+bool OutdoorPvP::HandleOpenGo(Player* player, GameObject* go)
{
for (OPvPCapturePointMap::iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr)
- if (itr->second->HandleOpenGo(player, guid) >= 0)
+ if (itr->second->HandleOpenGo(player, go) >= 0)
return true;
return false;
}
-bool OutdoorPvP::HandleGossipOption(Player* player, ObjectGuid guid, uint32 id)
+bool OutdoorPvP::HandleGossipOption(Player* player, Creature* creature, uint32 id)
{
for (OPvPCapturePointMap::iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr)
- if (itr->second->HandleGossipOption(player, guid, id))
+ if (itr->second->HandleGossipOption(player, creature, id))
return true;
return false;
@@ -547,7 +564,7 @@ bool OutdoorPvP::HandleDropFlag(Player* player, uint32 id)
return false;
}
-bool OPvPCapturePoint::HandleGossipOption(Player* /*player*/, ObjectGuid /*guid*/, uint32 /*id*/)
+bool OPvPCapturePoint::HandleGossipOption(Player* /*player*/, Creature* /*guid*/, uint32 /*id*/)
{
return false;
}
@@ -562,13 +579,12 @@ bool OPvPCapturePoint::HandleDropFlag(Player* /*player*/, uint32 /*id*/)
return false;
}
-int32 OPvPCapturePoint::HandleOpenGo(Player* /*player*/, ObjectGuid guid)
+int32 OPvPCapturePoint::HandleOpenGo(Player* /*player*/, GameObject* go)
{
- std::map<ObjectGuid, uint32>::iterator itr = m_ObjectTypes.find(guid);
+ std::map<uint32, uint32>::iterator itr = m_ObjectTypes.find(go->GetSpawnId());
if (itr != m_ObjectTypes.end())
- {
return itr->second;
- }
+
return -1;
}
@@ -621,22 +637,37 @@ void OutdoorPvP::TeamApplyBuff(TeamId team, uint32 spellId, uint32 spellId2)
void OutdoorPvP::OnGameObjectCreate(GameObject* go)
{
+ GoScriptPair sp(go->GetGUID().GetCounter(), go);
+ m_GoScriptStore.insert(sp);
if (go->GetGoType() != GAMEOBJECT_TYPE_CAPTURE_POINT)
return;
- if (OPvPCapturePoint *cp = GetCapturePoint(go->GetGUID()))
+ if (OPvPCapturePoint *cp = GetCapturePoint(go->GetSpawnId()))
cp->m_capturePoint = go;
}
void OutdoorPvP::OnGameObjectRemove(GameObject* go)
{
+ m_GoScriptStore.erase(go->GetGUID().GetCounter());
+
if (go->GetGoType() != GAMEOBJECT_TYPE_CAPTURE_POINT)
return;
- if (OPvPCapturePoint *cp = GetCapturePoint(go->GetGUID()))
+ if (OPvPCapturePoint *cp = GetCapturePoint(go->GetSpawnId()))
cp->m_capturePoint = NULL;
}
+void OutdoorPvP::OnCreatureCreate(Creature* creature)
+{
+ CreatureScriptPair sp(creature->GetGUID().GetCounter(), creature);
+ m_CreatureScriptStore.insert(sp);
+}
+
+void OutdoorPvP::OnCreatureRemove(Creature* creature)
+{
+ m_CreatureScriptStore.erase(creature->GetGUID().GetCounter());
+}
+
void OutdoorPvP::SendDefenseMessage(uint32 zoneId, uint32 id)
{
DefenseMessageBuilder builder(zoneId, id);
@@ -653,3 +684,12 @@ void OutdoorPvP::BroadcastWorker(Worker& _worker, uint32 zoneId)
if (player->GetZoneId() == zoneId)
_worker(player);
}
+
+void OutdoorPvP::SetMapFromZone(uint32 zone)
+{
+ AreaTableEntry const* areaTable = GetAreaEntryByAreaID(zone);
+ ASSERT(areaTable);
+ Map* map = sMapMgr->CreateBaseMap(areaTable->mapid);
+ ASSERT(!map->Instanceable());
+ m_map = map;
+}
diff --git a/src/server/game/OutdoorPvP/OutdoorPvP.h b/src/server/game/OutdoorPvP/OutdoorPvP.h
index ad99c64fbbd..4a423a8da5b 100644
--- a/src/server/game/OutdoorPvP/OutdoorPvP.h
+++ b/src/server/game/OutdoorPvP/OutdoorPvP.h
@@ -109,7 +109,7 @@ class OPvPCapturePoint
virtual bool HandleCustomSpell(Player* player, uint32 spellId, GameObject* go);
- virtual int32 HandleOpenGo(Player* player, ObjectGuid guid);
+ virtual int32 HandleOpenGo(Player* player, GameObject* go);
// returns true if the state of the objective has changed, in this case, the OutdoorPvP must send a world state ui update.
virtual bool Update(uint32 diff);
@@ -120,7 +120,7 @@ class OPvPCapturePoint
virtual void SendChangePhase();
- virtual bool HandleGossipOption(Player* player, ObjectGuid guid, uint32 gossipid);
+ virtual bool HandleGossipOption(Player* player, Creature* guid, uint32 gossipid);
virtual bool CanTalkTo(Player* player, Creature* c, GossipMenuItems const& gso);
@@ -128,12 +128,12 @@ class OPvPCapturePoint
virtual void DeleteSpawns();
- ObjectGuid m_capturePointGUID;
+ ObjectGuid::LowType m_capturePointSpawnId;
GameObject* m_capturePoint;
- void AddGO(uint32 type, uint32 guid, uint32 entry = 0);
- void AddCre(uint32 type, uint32 guid, uint32 entry = 0);
+ void AddGO(uint32 type, ObjectGuid::LowType guid, uint32 entry = 0);
+ void AddCre(uint32 type, ObjectGuid::LowType guid, uint32 entry = 0);
bool SetCapturePointData(uint32 entry, uint32 map, float x, float y, float z, float o = 0,
float rotation0 = 0, float rotation1 = 0, float rotation2 = 0, float rotation3 = 0);
@@ -178,10 +178,10 @@ class OPvPCapturePoint
// map to store the various gameobjects and creatures spawned by the objective
// type, guid
- std::map<uint32, ObjectGuid> m_Objects;
- std::map<uint32, ObjectGuid> m_Creatures;
- std::map<ObjectGuid, uint32> m_ObjectTypes;
- std::map<ObjectGuid, uint32> m_CreatureTypes;
+ std::map<uint32, ObjectGuid::LowType> m_Objects;
+ std::map<uint32, ObjectGuid::LowType> m_Creatures;
+ std::map<ObjectGuid::LowType, uint32> m_ObjectTypes;
+ std::map<ObjectGuid::LowType, uint32> m_CreatureTypes;
};
// base class for specific outdoor pvp handlers
@@ -200,7 +200,9 @@ class OutdoorPvP : public ZoneScript
// deletes all gos/creatures spawned by the pvp
void DeleteSpawns();
- typedef std::map<ObjectGuid/*guid*/, OPvPCapturePoint*> OPvPCapturePointMap;
+ typedef std::map<ObjectGuid::LowType/*spawnId*/, OPvPCapturePoint*> OPvPCapturePointMap;
+ typedef std::pair<ObjectGuid::LowType, GameObject*> GoScriptPair;
+ typedef std::pair<ObjectGuid::LowType, Creature*> CreatureScriptPair;
virtual void FillInitialWorldStates(WorldPacket & /*data*/) { }
@@ -211,14 +213,15 @@ class OutdoorPvP : public ZoneScript
virtual bool HandleCustomSpell(Player* player, uint32 spellId, GameObject* go);
// called on go use
- virtual bool HandleOpenGo(Player* player, ObjectGuid guid);
+ virtual bool HandleOpenGo(Player* player, GameObject* go);
// setup stuff
virtual bool SetupOutdoorPvP() {return true;}
void OnGameObjectCreate(GameObject* go) override;
void OnGameObjectRemove(GameObject* go) override;
- void OnCreatureCreate(Creature*) override { }
+ void OnCreatureCreate(Creature*) override;
+ void OnCreatureRemove(Creature*) override;
// send world state update to all players present
void SendUpdateWorldState(uint32 field, uint32 value);
@@ -236,11 +239,11 @@ class OutdoorPvP : public ZoneScript
// awards rewards for player kill
virtual void AwardKillBonus(Player* /*player*/) { }
- uint32 GetTypeId() {return m_TypeId;}
+ uint32 GetTypeId() const {return m_TypeId;}
virtual bool HandleDropFlag(Player* player, uint32 spellId);
- virtual bool HandleGossipOption(Player* player, ObjectGuid guid, uint32 gossipid);
+ virtual bool HandleGossipOption(Player* player, Creature* creature, uint32 gossipid);
virtual bool CanTalkTo(Player* player, Creature* c, GossipMenuItems const& gso);
@@ -261,6 +264,8 @@ class OutdoorPvP : public ZoneScript
void SendDefenseMessage(uint32 zoneId, uint32 id);
+ Map* GetMap() const { return m_map; }
+
protected:
// the map of the objectives belonging to this outdoorpvp
@@ -284,10 +289,10 @@ class OutdoorPvP : public ZoneScript
void AddCapturePoint(OPvPCapturePoint* cp)
{
- m_capturePoints[cp->m_capturePointGUID] = cp;
+ m_capturePoints[cp->m_capturePointSpawnId] = cp;
}
- OPvPCapturePoint * GetCapturePoint(ObjectGuid guid) const
+ OPvPCapturePoint * GetCapturePoint(ObjectGuid::LowType guid) const
{
OutdoorPvP::OPvPCapturePointMap::const_iterator itr = m_capturePoints.find(guid);
if (itr != m_capturePoints.end())
@@ -303,6 +308,13 @@ class OutdoorPvP : public ZoneScript
template<class Worker>
void BroadcastWorker(Worker& _worker, uint32 zoneId);
+
+ // Hack to store map because this code is just shit
+ void SetMapFromZone(uint32 zone);
+ std::map<ObjectGuid::LowType, GameObject*> m_GoScriptStore;
+ std::map<ObjectGuid::LowType, Creature*> m_CreatureScriptStore;
+
+ Map* m_map;
};
#endif /*OUTDOOR_PVP_H_*/
diff --git a/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp b/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp
index 4d7b80da157..37a380bf576 100644
--- a/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp
+++ b/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp
@@ -71,7 +71,7 @@ void OutdoorPvPMgr::InitOutdoorPvP()
OutdoorPvPData* data = new OutdoorPvPData();
OutdoorPvPTypes realTypeId = OutdoorPvPTypes(typeId);
data->TypeId = realTypeId;
- data->ScriptId = sObjectMgr->GetScriptId(fields[1].GetCString());
+ data->ScriptId = sObjectMgr->GetScriptId(fields[1].GetString());
m_OutdoorPvPDatas[realTypeId] = data;
++count;
@@ -123,7 +123,7 @@ void OutdoorPvPMgr::HandlePlayerEnterZone(Player* player, uint32 zoneid)
return;
itr->second->HandlePlayerEnterZone(player, zoneid);
- TC_LOG_DEBUG("outdoorpvp", "Player %u entered outdoorpvp id %u", player->GetGUIDLow(), itr->second->GetTypeId());
+ TC_LOG_DEBUG("outdoorpvp", "Player %u entered outdoorpvp id %u", player->GetGUID().GetCounter(), itr->second->GetTypeId());
}
void OutdoorPvPMgr::HandlePlayerLeaveZone(Player* player, uint32 zoneid)
@@ -137,7 +137,7 @@ void OutdoorPvPMgr::HandlePlayerLeaveZone(Player* player, uint32 zoneid)
return;
itr->second->HandlePlayerLeaveZone(player, zoneid);
- TC_LOG_DEBUG("outdoorpvp", "Player %u left outdoorpvp id %u", player->GetGUIDLow(), itr->second->GetTypeId());
+ TC_LOG_DEBUG("outdoorpvp", "Player %u left outdoorpvp id %u", player->GetGUID().GetCounter(), itr->second->GetTypeId());
}
OutdoorPvP* OutdoorPvPMgr::GetOutdoorPvPToZoneId(uint32 zoneid)
@@ -181,21 +181,21 @@ ZoneScript* OutdoorPvPMgr::GetZoneScript(uint32 zoneId)
return NULL;
}
-bool OutdoorPvPMgr::HandleOpenGo(Player* player, ObjectGuid guid)
+bool OutdoorPvPMgr::HandleOpenGo(Player* player, GameObject* go)
{
for (OutdoorPvPSet::iterator itr = m_OutdoorPvPSet.begin(); itr != m_OutdoorPvPSet.end(); ++itr)
{
- if ((*itr)->HandleOpenGo(player, guid))
+ if ((*itr)->HandleOpenGo(player, go))
return true;
}
return false;
}
-void OutdoorPvPMgr::HandleGossipOption(Player* player, ObjectGuid guid, uint32 gossipid)
+void OutdoorPvPMgr::HandleGossipOption(Player* player, Creature* creature, uint32 gossipid)
{
for (OutdoorPvPSet::iterator itr = m_OutdoorPvPSet.begin(); itr != m_OutdoorPvPSet.end(); ++itr)
{
- if ((*itr)->HandleGossipOption(player, guid, gossipid))
+ if ((*itr)->HandleGossipOption(player, creature, gossipid))
return;
}
}
diff --git a/src/server/game/OutdoorPvP/OutdoorPvPMgr.h b/src/server/game/OutdoorPvP/OutdoorPvPMgr.h
index 4f03dd37fac..542aad0ef0d 100644
--- a/src/server/game/OutdoorPvP/OutdoorPvPMgr.h
+++ b/src/server/game/OutdoorPvP/OutdoorPvPMgr.h
@@ -70,7 +70,7 @@ class OutdoorPvPMgr
bool HandleCustomSpell(Player* player, uint32 spellId, GameObject* go);
// handle custom go if registered
- bool HandleOpenGo(Player* player, ObjectGuid guid);
+ bool HandleOpenGo(Player* player, GameObject* go);
ZoneScript* GetZoneScript(uint32 zoneId);
@@ -78,7 +78,7 @@ class OutdoorPvPMgr
void Update(uint32 diff);
- void HandleGossipOption(Player* player, ObjectGuid guid, uint32 gossipid);
+ void HandleGossipOption(Player* player, Creature* creature, uint32 gossipid);
bool CanTalkTo(Player* player, Creature* creature, GossipMenuItems const& gso);
diff --git a/src/server/game/Pools/PoolMgr.cpp b/src/server/game/Pools/PoolMgr.cpp
index 3f561539917..1e7826f280b 100644
--- a/src/server/game/Pools/PoolMgr.cpp
+++ b/src/server/game/Pools/PoolMgr.cpp
@@ -184,7 +184,7 @@ PoolObject* PoolGroup<T>::RollOne(ActivePoolData& spawns, uint32 triggerFrom)
// If no guid is passed, the pool is just removed (event end case)
// If guid is filled, cache will be used and no removal will occur, it just fill the cache
template<class T>
-void PoolGroup<T>::DespawnObject(ActivePoolData& spawns, uint32 guid)
+void PoolGroup<T>::DespawnObject(ActivePoolData& spawns, ObjectGuid::LowType guid)
{
for (size_t i=0; i < EqualChanced.size(); ++i)
{
@@ -215,27 +215,45 @@ void PoolGroup<T>::DespawnObject(ActivePoolData& spawns, uint32 guid)
// Method that is actualy doing the removal job on one creature
template<>
-void PoolGroup<Creature>::Despawn1Object(uint32 guid)
+void PoolGroup<Creature>::Despawn1Object(ObjectGuid::LowType guid)
{
if (CreatureData const* data = sObjectMgr->GetCreatureData(guid))
{
sObjectMgr->RemoveCreatureFromGrid(guid, data);
- if (Creature* creature = ObjectAccessor::GetObjectInWorld(ObjectGuid(HIGHGUID_UNIT, data->id, guid), (Creature*)NULL))
- creature->AddObjectToRemoveList();
+ Map* map = sMapMgr->CreateBaseMap(data->mapid);
+ if (!map->Instanceable())
+ {
+ auto creatureBounds = map->GetCreatureBySpawnIdStore().equal_range(guid);
+ for (auto itr = creatureBounds.first; itr != creatureBounds.second;)
+ {
+ Creature* creature = itr->second;
+ ++itr;
+ creature->AddObjectToRemoveList();
+ }
+ }
}
}
// Same on one gameobject
template<>
-void PoolGroup<GameObject>::Despawn1Object(uint32 guid)
+void PoolGroup<GameObject>::Despawn1Object(ObjectGuid::LowType guid)
{
if (GameObjectData const* data = sObjectMgr->GetGOData(guid))
{
sObjectMgr->RemoveGameobjectFromGrid(guid, data);
- if (GameObject* pGameobject = ObjectAccessor::GetObjectInWorld(ObjectGuid(HIGHGUID_GAMEOBJECT, data->id, guid), (GameObject*)NULL))
- pGameobject->AddObjectToRemoveList();
+ Map* map = sMapMgr->CreateBaseMap(data->mapid);
+ if (!map->Instanceable())
+ {
+ auto gameobjectBounds = map->GetGameObjectBySpawnIdStore().equal_range(guid);
+ for (auto itr = gameobjectBounds.first; itr != gameobjectBounds.second;)
+ {
+ GameObject* go = itr->second;
+ ++itr;
+ go->AddObjectToRemoveList();
+ }
+ }
}
}
@@ -507,20 +525,16 @@ void PoolGroup<Quest>::SpawnObject(ActivePoolData& spawns, uint32 limit, uint32
// Method that does the respawn job on the specified creature
template <>
-void PoolGroup<Creature>::ReSpawn1Object(PoolObject* obj)
+void PoolGroup<Creature>::ReSpawn1Object(PoolObject* /*obj*/)
{
- if (CreatureData const* data = sObjectMgr->GetCreatureData(obj->guid))
- if (Creature* creature = ObjectAccessor::GetObjectInWorld(ObjectGuid(HIGHGUID_UNIT, data->id, obj->guid), (Creature*)NULL))
- creature->GetMap()->AddToMap(creature);
+ // Creature is still on map, nothing to do
}
// Method that does the respawn job on the specified gameobject
template <>
-void PoolGroup<GameObject>::ReSpawn1Object(PoolObject* obj)
+void PoolGroup<GameObject>::ReSpawn1Object(PoolObject* /*obj*/)
{
- if (GameObjectData const* data = sObjectMgr->GetGOData(obj->guid))
- if (GameObject* pGameobject = ObjectAccessor::GetObjectInWorld(ObjectGuid(HIGHGUID_GAMEOBJECT, data->id, obj->guid), (GameObject*)NULL))
- pGameobject->GetMap()->AddToMap(pGameobject);
+ // GameObject is still on map, nothing to do
}
// Nothing to do for a child Pool
@@ -607,7 +621,7 @@ void PoolMgr::LoadFromDB()
{
Field* fields = result->Fetch();
- uint32 guid = fields[0].GetUInt32();
+ ObjectGuid::LowType guid = fields[0].GetUInt32();
uint32 pool_id = fields[1].GetUInt32();
float chance = fields[2].GetFloat();
@@ -663,7 +677,7 @@ void PoolMgr::LoadFromDB()
{
Field* fields = result->Fetch();
- uint32 guid = fields[0].GetUInt32();
+ ObjectGuid::LowType guid = fields[0].GetUInt32();
uint32 pool_id = fields[1].GetUInt32();
float chance = fields[2].GetFloat();
diff --git a/src/server/game/Pools/PoolMgr.h b/src/server/game/Pools/PoolMgr.h
index 4ffcbe1faac..e165f9bd397 100644
--- a/src/server/game/Pools/PoolMgr.h
+++ b/src/server/game/Pools/PoolMgr.h
@@ -31,16 +31,16 @@ struct PoolTemplateData
struct PoolObject
{
- uint32 guid;
+ ObjectGuid::LowType guid;
float chance;
- PoolObject(uint32 _guid, float _chance) : guid(_guid), chance(std::fabs(_chance)) { }
+ PoolObject(ObjectGuid::LowType _guid, float _chance) : guid(_guid), chance(std::fabs(_chance)) { }
};
class Pool // for Pool of Pool case
{
};
-typedef std::set<uint32> ActivePoolObjects;
+typedef std::set<ObjectGuid::LowType> ActivePoolObjects;
typedef std::map<uint32, uint32> ActivePoolPools;
class ActivePoolData
@@ -77,8 +77,8 @@ class PoolGroup
void AddEntry(PoolObject& poolitem, uint32 maxentries);
bool CheckPool() const;
PoolObject* RollOne(ActivePoolData& spawns, uint32 triggerFrom);
- void DespawnObject(ActivePoolData& spawns, uint32 guid=0);
- void Despawn1Object(uint32 guid);
+ void DespawnObject(ActivePoolData& spawns, ObjectGuid::LowType guid=0);
+ void Despawn1Object(ObjectGuid::LowType guid);
void SpawnObject(ActivePoolData& spawns, uint32 limit, uint32 triggerFrom);
void Spawn1Object(PoolObject* obj);
diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp
index 6a6e0f45eb7..a3f662f2ade 100644
--- a/src/server/game/Quests/QuestDef.cpp
+++ b/src/server/game/Quests/QuestDef.cpp
@@ -26,121 +26,86 @@ Quest::Quest(Field* questRecord)
Method = questRecord[1].GetUInt8();
Level = questRecord[2].GetInt16();
MinLevel = questRecord[3].GetUInt8();
- MaxLevel = questRecord[4].GetUInt8();
- ZoneOrSort = questRecord[5].GetInt16();
- Type = questRecord[6].GetUInt16();
- SuggestedPlayers = questRecord[7].GetUInt8();
- LimitTime = questRecord[8].GetUInt32();
- RequiredClasses = questRecord[9].GetUInt16();
- RequiredRaces = questRecord[10].GetUInt16();
- RequiredSkillId = questRecord[11].GetUInt16();
- RequiredSkillPoints = questRecord[12].GetUInt16();
- RequiredFactionId1 = questRecord[13].GetUInt16();
- RequiredFactionId2 = questRecord[14].GetUInt16();
- RequiredFactionValue1 = questRecord[15].GetInt32();
- RequiredFactionValue2 = questRecord[16].GetInt32();
- RequiredMinRepFaction = questRecord[17].GetUInt16();
- RequiredMaxRepFaction = questRecord[18].GetUInt16();
- RequiredMinRepValue = questRecord[19].GetInt32();
- RequiredMaxRepValue = questRecord[20].GetInt32();
- PrevQuestId = questRecord[21].GetInt32();
- NextQuestId = questRecord[22].GetInt32();
- ExclusiveGroup = questRecord[23].GetInt32();
- NextQuestIdChain = questRecord[24].GetUInt32();
- RewardXPId = questRecord[25].GetUInt8();
- RewardOrRequiredMoney = questRecord[26].GetInt32();
- RewardMoneyMaxLevel = questRecord[27].GetUInt32();
- RewardSpell = questRecord[28].GetUInt32();
- RewardSpellCast = questRecord[29].GetInt32();
- RewardHonor = questRecord[30].GetUInt32();
- RewardHonorMultiplier = questRecord[31].GetFloat();
- RewardMailTemplateId = questRecord[32].GetUInt32();
- RewardMailDelay = questRecord[33].GetUInt32();
- SourceItemId = questRecord[34].GetUInt32();
- SourceItemIdCount = questRecord[35].GetUInt8();
- SourceSpellid = questRecord[36].GetUInt32();
- Flags = questRecord[37].GetUInt32();
- SpecialFlags = questRecord[38].GetUInt8();
- RewardTitleId = questRecord[39].GetUInt8();
- RequiredPlayerKills = questRecord[40].GetUInt8();
- RewardTalents = questRecord[41].GetUInt8();
- RewardArenaPoints = questRecord[42].GetUInt16();
+ ZoneOrSort = questRecord[4].GetInt16();
+ Type = questRecord[5].GetUInt16();
+ SuggestedPlayers = questRecord[6].GetUInt8();
+ TimeAllowed = questRecord[7].GetUInt32();
+ AllowableRaces = questRecord[8].GetUInt16();
+ RequiredFactionId1 = questRecord[9].GetUInt16();
+ RequiredFactionId2 = questRecord[10].GetUInt16();
+ RequiredFactionValue1 = questRecord[11].GetInt32();
+ RequiredFactionValue2 = questRecord[12].GetInt32();
+ RewardNextQuest = questRecord[13].GetUInt32();
+ RewardXPDifficulty = questRecord[14].GetUInt8();
+ RewardMoney = questRecord[15].GetInt32();
+ RewardBonusMoney = questRecord[16].GetUInt32();
+ RewardDisplaySpell = questRecord[17].GetUInt32();
+ RewardSpell = questRecord[18].GetInt32();
+ RewardHonor = questRecord[19].GetUInt32();
+ RewardKillHonor = questRecord[20].GetFloat();
+ StartItem = questRecord[21].GetUInt32();
+ Flags = questRecord[22].GetUInt32();
+ RewardTitleId = questRecord[23].GetUInt8();
+ RequiredPlayerKills = questRecord[24].GetUInt8();
+ RewardTalents = questRecord[25].GetUInt8();
+ RewardArenaPoints = questRecord[26].GetUInt16();
for (int i = 0; i < QUEST_REWARDS_COUNT; ++i)
- RewardItemId[i] = questRecord[43+i].GetUInt32();
-
- for (int i = 0; i < QUEST_REWARDS_COUNT; ++i)
- RewardItemIdCount[i] = questRecord[47+i].GetUInt16();
-
- for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
- RewardChoiceItemId[i] = questRecord[51+i].GetUInt32();
+ {
+ RewardItemId[i] = questRecord[27+i*2].GetUInt32();
+ RewardItemIdCount[i] = questRecord[28+i*2].GetUInt16();
+ }
for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
- RewardChoiceItemCount[i] = questRecord[57+i].GetUInt16();
-
- for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
- RewardFactionId[i] = questRecord[63+i].GetUInt16();
+ {
+ RewardChoiceItemId[i] = questRecord[35+i*2].GetUInt32();
+ RewardChoiceItemCount[i] = questRecord[36+i*2].GetUInt16();
+ }
for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
- RewardFactionValueId[i] = questRecord[68+i].GetInt32();
+ {
+ RewardFactionId[i] = questRecord[47+i*3].GetUInt16();
+ RewardFactionValueId[i] = questRecord[48+i*3].GetInt32();
+ RewardFactionValueIdOverride[i] = questRecord[49+i*3].GetInt32();
+ }
- for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
- RewardFactionValueIdOverride[i] = questRecord[73+i].GetInt32();
-
- PointMapId = questRecord[78].GetUInt16();
- PointX = questRecord[79].GetFloat();
- PointY = questRecord[80].GetFloat();
- PointOption = questRecord[81].GetUInt32();
- Title = questRecord[82].GetString();
- Objectives = questRecord[83].GetString();
- Details = questRecord[84].GetString();
- EndText = questRecord[85].GetString();
- OfferRewardText = questRecord[86].GetString();
- RequestItemsText = questRecord[87].GetString();
- CompletedText = questRecord[88].GetString();
+ POIContinent = questRecord[62].GetUInt16();
+ POIx = questRecord[63].GetFloat();
+ POIy = questRecord[64].GetFloat();
+ POIPriority = questRecord[65].GetUInt32();
+ Title = questRecord[66].GetString();
+ Objectives = questRecord[67].GetString();
+ Details = questRecord[68].GetString();
+ AreaDescription = questRecord[69].GetString();
+ CompletedText = questRecord[70].GetString();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
- RequiredNpcOrGo[i] = questRecord[89+i].GetInt32();
+ RequiredNpcOrGo[i] = questRecord[71+i].GetInt32();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
- RequiredNpcOrGoCount[i] = questRecord[93+i].GetUInt16();
+ RequiredNpcOrGoCount[i] = questRecord[75+i].GetUInt16();
for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
- RequiredSourceItemId[i] = questRecord[97+i].GetUInt32();
+ ItemDrop[i] = questRecord[79+i].GetUInt32();
for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
- RequiredSourceItemCount[i] = questRecord[101+i].GetUInt16();
+ ItemDropQuantity[i] = questRecord[83+i].GetUInt16();
for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
- RequiredItemId[i] = questRecord[105+i].GetUInt32();
+ RequiredItemId[i] = questRecord[87+i].GetUInt32();
for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
- RequiredItemCount[i] = questRecord[111+i].GetUInt16();
+ RequiredItemCount[i] = questRecord[93+i].GetUInt16();
- // int8 Unknown0 = questRecord[117].GetUInt8();
+ // int8 Unknown0 = questRecord[99].GetUInt8();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
- ObjectiveText[i] = questRecord[118+i].GetString();
+ ObjectiveText[i] = questRecord[100+i].GetString();
- for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
- DetailsEmote[i] = questRecord[122+i].GetUInt16();
+ EmoteOnIncomplete = 0;
+ EmoteOnComplete = 0;
- for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
- DetailsEmoteDelay[i] = questRecord[126+i].GetUInt32();
-
- EmoteOnIncomplete = questRecord[130].GetUInt16();
- EmoteOnComplete = questRecord[131].GetUInt16();
-
- for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
- OfferRewardEmote[i] = questRecord[132+i].GetInt16();
-
- for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
- OfferRewardEmoteDelay[i] = questRecord[136+i].GetInt32();
-
- //int32 VerifiedBuild = questRecord[140].GetInt32();
-
- if (SpecialFlags & QUEST_SPECIAL_FLAGS_AUTO_ACCEPT)
- Flags |= QUEST_FLAGS_AUTO_ACCEPT;
+ //int32 VerifiedBuild = questRecord[104].GetInt32();
_reqItemsCount = 0;
_reqCreatureOrGOcount = 0;
@@ -162,6 +127,68 @@ Quest::Quest(Field* questRecord)
for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
if (RewardChoiceItemId[i])
++_rewChoiceItemsCount;
+
+ for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
+ DetailsEmote[i] = 0;
+
+ for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
+ DetailsEmoteDelay[i] = 0;
+
+ for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
+ OfferRewardEmote[i] = 0;
+
+ for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
+ OfferRewardEmoteDelay[i] = 0;
+}
+
+void Quest::LoadQuestDetails(Field* fields)
+{
+ for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
+ DetailsEmote[i] = fields[1+i].GetUInt16();
+
+ for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
+ DetailsEmoteDelay[i] = fields[5+i].GetUInt32();
+}
+
+void Quest::LoadQuestRequestItems(Field* fields)
+{
+ EmoteOnComplete = fields[1].GetUInt16();
+ EmoteOnIncomplete = fields[2].GetUInt16();
+ RequestItemsText = fields[3].GetString();
+}
+
+void Quest::LoadQuestOfferReward(Field* fields)
+{
+ for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
+ OfferRewardEmote[i] = fields[1+i].GetUInt16();
+
+ for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
+ OfferRewardEmoteDelay[i] = fields[5+i].GetUInt32();
+
+ OfferRewardText = fields[9].GetString();
+}
+
+void Quest::LoadQuestTemplateAddon(Field* fields)
+{
+ MaxLevel = fields[1].GetUInt8();
+ RequiredClasses = fields[2].GetUInt32();
+ SourceSpellid = fields[3].GetUInt32();
+ PrevQuestId = fields[4].GetInt32();
+ NextQuestId = fields[5].GetInt32();
+ ExclusiveGroup = fields[6].GetInt32();
+ RewardMailTemplateId = fields[7].GetUInt32();
+ RewardMailDelay = fields[8].GetUInt32();
+ RequiredSkillId = fields[9].GetUInt16();
+ RequiredSkillPoints = fields[10].GetUInt16();
+ RequiredMinRepFaction = fields[11].GetUInt16();
+ RequiredMaxRepFaction = fields[12].GetUInt16();
+ RequiredMinRepValue = fields[13].GetInt32();
+ RequiredMaxRepValue = fields[14].GetInt32();
+ StartItemCount = fields[15].GetUInt8();
+ SpecialFlags = fields[16].GetUInt8();
+
+ if (SpecialFlags & QUEST_SPECIAL_FLAGS_AUTO_ACCEPT)
+ Flags |= QUEST_FLAGS_AUTO_ACCEPT;
}
uint32 Quest::XPValue(Player* player) const
@@ -179,7 +206,7 @@ uint32 Quest::XPValue(Player* player) const
else if (diffFactor > 10)
diffFactor = 10;
- uint32 xp = diffFactor * xpentry->Exp[RewardXPId] / 10;
+ uint32 xp = diffFactor * xpentry->Exp[RewardXPDifficulty] / 10;
if (xp <= 100)
xp = 5 * ((xp + 2) / 5);
else if (xp <= 500)
@@ -198,11 +225,11 @@ uint32 Quest::XPValue(Player* player) const
int32 Quest::GetRewOrReqMoney() const
{
// RequiredMoney: the amount is the negative copper sum.
- if (RewardOrRequiredMoney <= 0)
- return RewardOrRequiredMoney;
+ if (RewardMoney <= 0)
+ return RewardMoney;
// RewardMoney: the positive amount
- return int32(RewardOrRequiredMoney * sWorld->getRate(RATE_MONEY_QUEST));
+ return int32(RewardMoney * sWorld->getRate(RATE_MONEY_QUEST));
}
uint32 Quest::GetRewMoneyMaxLevel() const
@@ -212,7 +239,7 @@ uint32 Quest::GetRewMoneyMaxLevel() const
return 0;
// Else, return the rewarded copper sum modified by the rate
- return uint32(RewardMoneyMaxLevel * sWorld->getRate(RATE_MONEY_MAX_LEVEL_QUEST));
+ return uint32(RewardBonusMoney * sWorld->getRate(RATE_MONEY_MAX_LEVEL_QUEST));
}
bool Quest::IsAutoAccept() const
diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h
index 8485fab7f63..91b4a3181f5 100644
--- a/src/server/game/Quests/QuestDef.h
+++ b/src/server/game/Quests/QuestDef.h
@@ -182,7 +182,7 @@ struct QuestLocale
StringVector Objectives;
StringVector OfferRewardText;
StringVector RequestItemsText;
- StringVector EndText;
+ StringVector AreaDescription;
StringVector CompletedText;
std::vector< StringVector > ObjectiveText;
};
@@ -195,6 +195,11 @@ class Quest
friend class ObjectMgr;
public:
Quest(Field* questRecord);
+ void LoadQuestDetails(Field* fields);
+ void LoadQuestRequestItems(Field* fields);
+ void LoadQuestOfferReward(Field* fields);
+ void LoadQuestTemplateAddon(Field* fields);
+
uint32 XPValue(Player* player) const;
bool HasFlag(uint32 flag) const { return (Flags & flag) != 0; }
@@ -212,7 +217,7 @@ class Quest
int32 GetQuestLevel() const { return Level; }
uint32 GetType() const { return Type; }
uint32 GetRequiredClasses() const { return RequiredClasses; }
- uint32 GetRequiredRaces() const { return RequiredRaces; }
+ uint32 GetAllowableRaces() const { return AllowableRaces; }
uint32 GetRequiredSkill() const { return RequiredSkillId; }
uint32 GetRequiredSkillValue() const { return RequiredSkillPoints; }
uint32 GetRepObjectiveFaction() const { return RequiredFactionId1; }
@@ -224,38 +229,38 @@ class Quest
uint32 GetRequiredMaxRepFaction() const { return RequiredMaxRepFaction; }
int32 GetRequiredMaxRepValue() const { return RequiredMaxRepValue; }
uint32 GetSuggestedPlayers() const { return SuggestedPlayers; }
- uint32 GetLimitTime() const { return LimitTime; }
+ uint32 GetTimeAllowed() const { return TimeAllowed; }
int32 GetPrevQuestId() const { return PrevQuestId; }
int32 GetNextQuestId() const { return NextQuestId; }
int32 GetExclusiveGroup() const { return ExclusiveGroup; }
- uint32 GetNextQuestInChain() const { return NextQuestIdChain; }
+ uint32 GetNextQuestInChain() const { return RewardNextQuest; }
uint32 GetCharTitleId() const { return RewardTitleId; }
uint32 GetPlayersSlain() const { return RequiredPlayerKills; }
uint32 GetBonusTalents() const { return RewardTalents; }
int32 GetRewArenaPoints() const {return RewardArenaPoints; }
- uint32 GetXPId() const { return RewardXPId; }
- uint32 GetSrcItemId() const { return SourceItemId; }
- uint32 GetSrcItemCount() const { return SourceItemIdCount; }
+ uint32 GetXPId() const { return RewardXPDifficulty; }
+ uint32 GetSrcItemId() const { return StartItem; }
+ uint32 GetSrcItemCount() const { return StartItemCount; }
uint32 GetSrcSpell() const { return SourceSpellid; }
std::string const& GetTitle() const { return Title; }
std::string const& GetDetails() const { return Details; }
std::string const& GetObjectives() const { return Objectives; }
std::string const& GetOfferRewardText() const { return OfferRewardText; }
std::string const& GetRequestItemsText() const { return RequestItemsText; }
- std::string const& GetEndText() const { return EndText; }
+ std::string const& GetAreaDescription() const { return AreaDescription; }
std::string const& GetCompletedText() const { return CompletedText; }
int32 GetRewOrReqMoney() const;
uint32 GetRewHonorAddition() const { return RewardHonor; }
- float GetRewHonorMultiplier() const { return RewardHonorMultiplier; }
+ float GetRewHonorMultiplier() const { return RewardKillHonor; }
uint32 GetRewMoneyMaxLevel() const; // use in XP calculation at client
- uint32 GetRewSpell() const { return RewardSpell; }
- int32 GetRewSpellCast() const { return RewardSpellCast; }
+ uint32 GetRewSpell() const { return RewardDisplaySpell; }
+ int32 GetRewSpellCast() const { return RewardSpell; }
uint32 GetRewMailTemplateId() const { return RewardMailTemplateId; }
uint32 GetRewMailDelaySecs() const { return RewardMailDelay; }
- uint32 GetPointMapId() const { return PointMapId; }
- float GetPointX() const { return PointX; }
- float GetPointY() const { return PointY; }
- uint32 GetPointOpt() const { return PointOption; }
+ uint32 GetPOIContinent() const { return POIContinent; }
+ float GetPOIx() const { return POIx; }
+ float GetPOIy() const { return POIy; }
+ uint32 GetPointOpt() const { return POIPriority; }
uint32 GetIncompleteEmote() const { return EmoteOnIncomplete; }
uint32 GetCompleteEmote() const { return EmoteOnComplete; }
bool IsRepeatable() const { return SpecialFlags & QUEST_SPECIAL_FLAGS_REPEATABLE; }
@@ -276,8 +281,8 @@ class Quest
std::string ObjectiveText[QUEST_OBJECTIVES_COUNT];
uint32 RequiredItemId[QUEST_ITEM_OBJECTIVES_COUNT];
uint32 RequiredItemCount[QUEST_ITEM_OBJECTIVES_COUNT];
- uint32 RequiredSourceItemId[QUEST_SOURCE_ITEM_IDS_COUNT];
- uint32 RequiredSourceItemCount[QUEST_SOURCE_ITEM_IDS_COUNT];
+ uint32 ItemDrop[QUEST_SOURCE_ITEM_IDS_COUNT];
+ uint32 ItemDropQuantity[QUEST_SOURCE_ITEM_IDS_COUNT];
int32 RequiredNpcOrGo[QUEST_OBJECTIVES_COUNT]; // >0 Creature <0 Gameobject
uint32 RequiredNpcOrGoCount[QUEST_OBJECTIVES_COUNT];
uint32 RewardChoiceItemId[QUEST_REWARD_CHOICES_COUNT];
@@ -315,59 +320,60 @@ class Quest
uint32 Method;
int32 ZoneOrSort;
uint32 MinLevel;
- uint32 MaxLevel;
int32 Level;
uint32 Type;
- uint32 RequiredClasses;
- uint32 RequiredRaces;
- uint32 RequiredSkillId;
- uint32 RequiredSkillPoints;
+ uint32 AllowableRaces;
uint32 RequiredFactionId1;
int32 RequiredFactionValue1;
uint32 RequiredFactionId2;
int32 RequiredFactionValue2;
- uint32 RequiredMinRepFaction;
- int32 RequiredMinRepValue;
- uint32 RequiredMaxRepFaction;
- int32 RequiredMaxRepValue;
uint32 SuggestedPlayers;
- uint32 LimitTime;
+ uint32 TimeAllowed;
uint32 Flags;
uint32 RewardTitleId;
uint32 RequiredPlayerKills;
uint32 RewardTalents;
int32 RewardArenaPoints;
- int32 PrevQuestId;
- int32 NextQuestId;
- int32 ExclusiveGroup;
- uint32 NextQuestIdChain;
- uint32 RewardXPId;
- uint32 SourceItemId;
- uint32 SourceItemIdCount;
- uint32 SourceSpellid;
+ uint32 RewardNextQuest;
+ uint32 RewardXPDifficulty;
+ uint32 StartItem;
std::string Title;
std::string Details;
std::string Objectives;
std::string OfferRewardText;
std::string RequestItemsText;
- std::string EndText;
+ std::string AreaDescription;
std::string CompletedText;
uint32 RewardHonor;
- float RewardHonorMultiplier;
- int32 RewardOrRequiredMoney;
- uint32 RewardMoneyMaxLevel;
- uint32 RewardSpell;
- int32 RewardSpellCast;
- uint32 RewardMailTemplateId;
- uint32 RewardMailDelay;
- uint32 PointMapId;
- float PointX;
- float PointY;
- uint32 PointOption;
+ float RewardKillHonor;
+ int32 RewardMoney;
+ uint32 RewardBonusMoney;
+ uint32 RewardDisplaySpell;
+ int32 RewardSpell;
+ uint32 POIContinent;
+ float POIx;
+ float POIy;
+ uint32 POIPriority;
uint32 EmoteOnIncomplete;
uint32 EmoteOnComplete;
- uint32 SpecialFlags; // custom flags, not sniffed/WDB
+ // quest_template_addon table (custom data)
+ uint32 MaxLevel = 0;
+ uint32 RequiredClasses = 0;
+ uint32 SourceSpellid = 0;
+ int32 PrevQuestId = 0;
+ int32 NextQuestId = 0;
+ int32 ExclusiveGroup = 0;
+ uint32 RewardMailTemplateId = 0;
+ uint32 RewardMailDelay = 0;
+ uint32 RequiredSkillId = 0;
+ uint32 RequiredSkillPoints = 0;
+ uint32 RequiredMinRepFaction = 0;
+ int32 RequiredMinRepValue = 0;
+ uint32 RequiredMaxRepFaction = 0;
+ int32 RequiredMaxRepValue = 0;
+ uint32 StartItemCount = 0;
+ uint32 SpecialFlags = 0; // custom flags, not sniffed/WDB
};
struct QuestStatusData
diff --git a/src/server/game/Reputation/ReputationMgr.cpp b/src/server/game/Reputation/ReputationMgr.cpp
index a3e458503d6..a4065fa6f82 100644
--- a/src/server/game/Reputation/ReputationMgr.cpp
+++ b/src/server/game/Reputation/ReputationMgr.cpp
@@ -512,7 +512,7 @@ void ReputationMgr::LoadFromDB(PreparedQueryResult result)
// Set initial reputations (so everything is nifty before DB data load)
Initialize();
- //QueryResult* result = CharacterDatabase.PQuery("SELECT faction, standing, flags FROM character_reputation WHERE guid = '%u'", GetGUIDLow());
+ //QueryResult* result = CharacterDatabase.PQuery("SELECT faction, standing, flags FROM character_reputation WHERE guid = '%u'", GetGUID().GetCounter());
if (result)
{
@@ -574,12 +574,12 @@ void ReputationMgr::SaveToDB(SQLTransaction& trans)
if (itr->second.needSave)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_REPUTATION_BY_FACTION);
- stmt->setUInt32(0, _player->GetGUIDLow());
+ stmt->setUInt32(0, _player->GetGUID().GetCounter());
stmt->setUInt16(1, uint16(itr->second.ID));
trans->Append(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_REPUTATION_BY_FACTION);
- stmt->setUInt32(0, _player->GetGUIDLow());
+ stmt->setUInt32(0, _player->GetGUID().GetCounter());
stmt->setUInt16(1, uint16(itr->second.ID));
stmt->setInt32(2, itr->second.Standing);
stmt->setUInt16(3, uint16(itr->second.Flags));
diff --git a/src/server/game/Scripting/MapScripts.cpp b/src/server/game/Scripting/MapScripts.cpp
index 3beaa7daa9b..63006bc6ed6 100644
--- a/src/server/game/Scripting/MapScripts.cpp
+++ b/src/server/game/Scripting/MapScripts.cpp
@@ -23,6 +23,7 @@
#include "Map.h"
#include "ObjectMgr.h"
#include "Pet.h"
+#include "Item.h"
#include "ScriptedCreature.h"
#include "ScriptMgr.h"
#include "Transport.h"
@@ -113,8 +114,8 @@ inline Player* Map::_GetScriptPlayerSourceOrTarget(Object* source, Object* targe
if (!player)
TC_LOG_ERROR("scripts", "%s neither source nor target object is player (source: TypeId: %u, Entry: %u, GUID: %u; target: TypeId: %u, Entry: %u, GUID: %u), skipping.",
scriptInfo->GetDebugInfo().c_str(),
- source ? source->GetTypeId() : 0, source ? source->GetEntry() : 0, source ? source->GetGUIDLow() : 0,
- target ? target->GetTypeId() : 0, target ? target->GetEntry() : 0, target ? target->GetGUIDLow() : 0);
+ source ? source->GetTypeId() : 0, source ? source->GetEntry() : 0, source ? source->GetGUID().GetCounter() : 0,
+ target ? target->GetTypeId() : 0, target ? target->GetEntry() : 0, target ? target->GetGUID().GetCounter() : 0);
}
return player;
}
@@ -146,8 +147,8 @@ inline Creature* Map::_GetScriptCreatureSourceOrTarget(Object* source, Object* t
if (!creature)
TC_LOG_ERROR("scripts", "%s neither source nor target are creatures (source: TypeId: %u, Entry: %u, GUID: %u; target: TypeId: %u, Entry: %u, GUID: %u), skipping.",
scriptInfo->GetDebugInfo().c_str(),
- source ? source->GetTypeId() : 0, source ? source->GetEntry() : 0, source ? source->GetGUIDLow() : 0,
- target ? target->GetTypeId() : 0, target ? target->GetEntry() : 0, target ? target->GetGUIDLow() : 0);
+ source ? source->GetTypeId() : 0, source ? source->GetEntry() : 0, source ? source->GetGUID().GetCounter() : 0,
+ target ? target->GetTypeId() : 0, target ? target->GetEntry() : 0, target ? target->GetGUID().GetCounter() : 0);
}
return creature;
}
@@ -159,7 +160,7 @@ inline Unit* Map::_GetScriptUnit(Object* obj, bool isSource, const ScriptInfo* s
TC_LOG_ERROR("scripts", "%s %s object is NULL.", scriptInfo->GetDebugInfo().c_str(), isSource ? "source" : "target");
else if (!obj->isType(TYPEMASK_UNIT))
TC_LOG_ERROR("scripts", "%s %s object is not unit (TypeId: %u, Entry: %u, GUID: %u), skipping.",
- scriptInfo->GetDebugInfo().c_str(), isSource ? "source" : "target", obj->GetTypeId(), obj->GetEntry(), obj->GetGUIDLow());
+ scriptInfo->GetDebugInfo().c_str(), isSource ? "source" : "target", obj->GetTypeId(), obj->GetEntry(), obj->GetGUID().GetCounter());
else
{
unit = obj->ToUnit();
@@ -180,7 +181,7 @@ inline Player* Map::_GetScriptPlayer(Object* obj, bool isSource, const ScriptInf
player = obj->ToPlayer();
if (!player)
TC_LOG_ERROR("scripts", "%s %s object is not a player (TypeId: %u, Entry: %u, GUID: %u).",
- scriptInfo->GetDebugInfo().c_str(), isSource ? "source" : "target", obj->GetTypeId(), obj->GetEntry(), obj->GetGUIDLow());
+ scriptInfo->GetDebugInfo().c_str(), isSource ? "source" : "target", obj->GetTypeId(), obj->GetEntry(), obj->GetGUID().GetCounter());
}
return player;
}
@@ -195,7 +196,7 @@ inline Creature* Map::_GetScriptCreature(Object* obj, bool isSource, const Scrip
creature = obj->ToCreature();
if (!creature)
TC_LOG_ERROR("scripts", "%s %s object is not a creature (TypeId: %u, Entry: %u, GUID: %u).", scriptInfo->GetDebugInfo().c_str(),
- isSource ? "source" : "target", obj->GetTypeId(), obj->GetEntry(), obj->GetGUIDLow());
+ isSource ? "source" : "target", obj->GetTypeId(), obj->GetEntry(), obj->GetGUID().GetCounter());
}
return creature;
}
@@ -211,7 +212,7 @@ inline WorldObject* Map::_GetScriptWorldObject(Object* obj, bool isSource, const
pWorldObject = dynamic_cast<WorldObject*>(obj);
if (!pWorldObject)
TC_LOG_ERROR("scripts", "%s %s object is not a world object (TypeId: %u, Entry: %u, GUID: %u).",
- scriptInfo->GetDebugInfo().c_str(), isSource ? "source" : "target", obj->GetTypeId(), obj->GetEntry(), obj->GetGUIDLow());
+ scriptInfo->GetDebugInfo().c_str(), isSource ? "source" : "target", obj->GetTypeId(), obj->GetEntry(), obj->GetGUID().GetCounter());
}
return pWorldObject;
}
@@ -219,7 +220,7 @@ inline WorldObject* Map::_GetScriptWorldObject(Object* obj, bool isSource, const
inline void Map::_ScriptProcessDoor(Object* source, Object* target, const ScriptInfo* scriptInfo) const
{
bool bOpen = false;
- uint32 guid = scriptInfo->ToggleDoor.GOGuid;
+ ObjectGuid::LowType guid = scriptInfo->ToggleDoor.GOGuid;
int32 nTimeToToggle = std::max(15, int32(scriptInfo->ToggleDoor.ResetDelay));
switch (scriptInfo->command)
{
@@ -235,13 +236,13 @@ inline void Map::_ScriptProcessDoor(Object* source, Object* target, const Script
TC_LOG_ERROR("scripts", "%s source object is NULL.", scriptInfo->GetDebugInfo().c_str());
else if (!source->isType(TYPEMASK_UNIT))
TC_LOG_ERROR("scripts", "%s source object is not unit (TypeId: %u, Entry: %u, GUID: %u), skipping.", scriptInfo->GetDebugInfo().c_str(),
- source->GetTypeId(), source->GetEntry(), source->GetGUIDLow());
+ source->GetTypeId(), source->GetEntry(), source->GetGUID().GetCounter());
else
{
WorldObject* wSource = dynamic_cast <WorldObject*> (source);
if (!wSource)
TC_LOG_ERROR("scripts", "%s source object could not be cast to world object (TypeId: %u, Entry: %u, GUID: %u), skipping.",
- scriptInfo->GetDebugInfo().c_str(), source->GetTypeId(), source->GetEntry(), source->GetGUIDLow());
+ scriptInfo->GetDebugInfo().c_str(), source->GetTypeId(), source->GetEntry(), source->GetGUID().GetCounter());
else
{
GameObject* pDoor = _FindGameObject(wSource, guid);
@@ -249,7 +250,7 @@ inline void Map::_ScriptProcessDoor(Object* source, Object* target, const Script
TC_LOG_ERROR("scripts", "%s gameobject was not found (guid: %u).", scriptInfo->GetDebugInfo().c_str(), guid);
else if (pDoor->GetGoType() != GAMEOBJECT_TYPE_DOOR)
TC_LOG_ERROR("scripts", "%s gameobject is not a door (GoType: %u, Entry: %u, GUID: %u).",
- scriptInfo->GetDebugInfo().c_str(), pDoor->GetGoType(), pDoor->GetEntry(), pDoor->GetGUIDLow());
+ scriptInfo->GetDebugInfo().c_str(), pDoor->GetGoType(), pDoor->GetEntry(), pDoor->GetGUID().GetCounter());
else if (bOpen == (pDoor->GetGoState() == GO_STATE_READY))
{
pDoor->UseDoorOrButton(nTimeToToggle);
@@ -265,20 +266,13 @@ inline void Map::_ScriptProcessDoor(Object* source, Object* target, const Script
}
}
-inline GameObject* Map::_FindGameObject(WorldObject* searchObject, uint32 guid) const
+inline GameObject* Map::_FindGameObject(WorldObject* searchObject, ObjectGuid::LowType guid) const
{
- GameObject* gameobject = NULL;
+ auto bounds = searchObject->GetMap()->GetGameObjectBySpawnIdStore().equal_range(guid);
+ if (bounds.first == bounds.second)
+ return nullptr;
- CellCoord p(Trinity::ComputeCellCoord(searchObject->GetPositionX(), searchObject->GetPositionY()));
- Cell cell(p);
-
- Trinity::GameObjectWithDbGUIDCheck goCheck(*searchObject, guid);
- Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck> checker(searchObject, gameobject, goCheck);
-
- TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > objectChecker(checker);
- cell.Visit(p, objectChecker, *searchObject->GetMap(), *searchObject, searchObject->GetGridActivationRange());
-
- return gameobject;
+ return bounds.first->second;
}
/// Process queued scripts
@@ -299,33 +293,30 @@ void Map::ScriptsProcess()
{
switch (step.sourceGUID.GetHigh())
{
- case HIGHGUID_ITEM: // as well as HIGHGUID_CONTAINER
+ case HighGuid::Item: // as well as HighGuid::Container
if (Player* player = HashMapHolder<Player>::Find(step.ownerGUID))
source = player->GetItemByGuid(step.sourceGUID);
break;
- case HIGHGUID_UNIT:
- case HIGHGUID_VEHICLE:
- source = HashMapHolder<Creature>::Find(step.sourceGUID);
+ case HighGuid::Unit:
+ case HighGuid::Vehicle:
+ source = GetCreature(step.sourceGUID);
break;
- case HIGHGUID_PET:
- source = HashMapHolder<Pet>::Find(step.sourceGUID);
+ case HighGuid::Pet:
+ source = GetPet(step.sourceGUID);
break;
- case HIGHGUID_PLAYER:
+ case HighGuid::Player:
source = HashMapHolder<Player>::Find(step.sourceGUID);
break;
- case HIGHGUID_TRANSPORT:
- case HIGHGUID_GAMEOBJECT:
- source = HashMapHolder<GameObject>::Find(step.sourceGUID);
+ case HighGuid::Transport:
+ case HighGuid::GameObject:
+ source = GetGameObject(step.sourceGUID);
break;
- case HIGHGUID_CORPSE:
- source = HashMapHolder<Corpse>::Find(step.sourceGUID);
+ case HighGuid::Corpse:
+ source = GetCorpse(step.sourceGUID);
break;
- case HIGHGUID_MO_TRANSPORT:
- {
- GameObject* go = HashMapHolder<GameObject>::Find(step.sourceGUID);
- source = go ? go->ToTransport() : NULL;
+ case HighGuid::Mo_Transport:
+ source = GetTransport(step.sourceGUID);
break;
- }
default:
TC_LOG_ERROR("scripts", "%s source with unsupported high guid %s.",
step.script->GetDebugInfo().c_str(), step.sourceGUID.ToString().c_str());
@@ -338,29 +329,26 @@ void Map::ScriptsProcess()
{
switch (step.targetGUID.GetHigh())
{
- case HIGHGUID_UNIT:
- case HIGHGUID_VEHICLE:
- target = HashMapHolder<Creature>::Find(step.targetGUID);
+ case HighGuid::Unit:
+ case HighGuid::Vehicle:
+ target = GetCreature(step.targetGUID);
break;
- case HIGHGUID_PET:
- target = HashMapHolder<Pet>::Find(step.targetGUID);
+ case HighGuid::Pet:
+ target = GetPet(step.targetGUID);
break;
- case HIGHGUID_PLAYER: // empty GUID case also
+ case HighGuid::Player: // empty GUID case also
target = HashMapHolder<Player>::Find(step.targetGUID);
break;
- case HIGHGUID_TRANSPORT:
- case HIGHGUID_GAMEOBJECT:
- target = HashMapHolder<GameObject>::Find(step.targetGUID);
+ case HighGuid::Transport:
+ case HighGuid::GameObject:
+ target = GetGameObject(step.targetGUID);
break;
- case HIGHGUID_CORPSE:
- target = HashMapHolder<Corpse>::Find(step.targetGUID);
+ case HighGuid::Corpse:
+ target = GetCorpse(step.targetGUID);
break;
- case HIGHGUID_MO_TRANSPORT:
- {
- GameObject* go = HashMapHolder<GameObject>::Find(step.targetGUID);
- target = go ? go->ToTransport() : NULL;
+ case HighGuid::Mo_Transport:
+ target = GetTransport(step.targetGUID);
break;
- }
default:
TC_LOG_ERROR("scripts", "%s target with unsupported high guid %s.",
step.script->GetDebugInfo().c_str(), step.targetGUID.ToString().c_str());
@@ -469,7 +457,7 @@ void Map::ScriptsProcess()
if (step.script->FlagToggle.FieldID <= OBJECT_FIELD_ENTRY || step.script->FlagToggle.FieldID >= cSource->GetValuesCount())
TC_LOG_ERROR("scripts", "%s wrong field %u (max count: %u) in object (TypeId: %u, Entry: %u, GUID: %u) specified, skipping.",
step.script->GetDebugInfo().c_str(), step.script->FlagToggle.FieldID,
- cSource->GetValuesCount(), cSource->GetTypeId(), cSource->GetEntry(), cSource->GetGUIDLow());
+ cSource->GetValuesCount(), cSource->GetTypeId(), cSource->GetEntry(), cSource->GetGUID().GetCounter());
else
cSource->SetFlag(step.script->FlagToggle.FieldID, step.script->FlagToggle.FieldValue);
}
@@ -483,7 +471,7 @@ void Map::ScriptsProcess()
if (step.script->FlagToggle.FieldID <= OBJECT_FIELD_ENTRY || step.script->FlagToggle.FieldID >= cSource->GetValuesCount())
TC_LOG_ERROR("scripts", "%s wrong field %u (max count: %u) in object (TypeId: %u, Entry: %u, GUID: %u) specified, skipping.",
step.script->GetDebugInfo().c_str(), step.script->FlagToggle.FieldID,
- cSource->GetValuesCount(), cSource->GetTypeId(), cSource->GetEntry(), cSource->GetGUIDLow());
+ cSource->GetValuesCount(), cSource->GetTypeId(), cSource->GetEntry(), cSource->GetGUID().GetCounter());
else
cSource->RemoveFlag(step.script->FlagToggle.FieldID, step.script->FlagToggle.FieldValue);
}
@@ -525,7 +513,7 @@ void Map::ScriptsProcess()
if (source->GetTypeId() != TYPEID_UNIT && source->GetTypeId() != TYPEID_GAMEOBJECT && source->GetTypeId() != TYPEID_PLAYER)
{
TC_LOG_ERROR("scripts", "%s source is not unit, gameobject or player (TypeId: %u, Entry: %u, GUID: %u), skipping.",
- step.script->GetDebugInfo().c_str(), source->GetTypeId(), source->GetEntry(), source->GetGUIDLow());
+ step.script->GetDebugInfo().c_str(), source->GetTypeId(), source->GetEntry(), source->GetGUID().GetCounter());
break;
}
worldObject = dynamic_cast<WorldObject*>(source);
@@ -538,7 +526,7 @@ void Map::ScriptsProcess()
if (target->GetTypeId() != TYPEID_UNIT && target->GetTypeId() != TYPEID_GAMEOBJECT && target->GetTypeId() != TYPEID_PLAYER)
{
TC_LOG_ERROR("scripts", "%s target is not unit, gameobject or player (TypeId: %u, Entry: %u, GUID: %u), skipping.",
- step.script->GetDebugInfo().c_str(), target->GetTypeId(), target->GetEntry(), target->GetGUIDLow());
+ step.script->GetDebugInfo().c_str(), target->GetTypeId(), target->GetEntry(), target->GetGUID().GetCounter());
break;
}
worldObject = dynamic_cast<WorldObject*>(target);
@@ -546,8 +534,8 @@ void Map::ScriptsProcess()
else
{
TC_LOG_ERROR("scripts", "%s neither source nor target is player (source: TypeId: %u, Entry: %u, GUID: %u; target: TypeId: %u, Entry: %u, GUID: %u), skipping.",
- step.script->GetDebugInfo().c_str(), source->GetTypeId(), source->GetEntry(), source->GetGUIDLow(),
- target->GetTypeId(), target->GetEntry(), target->GetGUIDLow());
+ step.script->GetDebugInfo().c_str(), source->GetTypeId(), source->GetEntry(), source->GetGUID().GetCounter(),
+ target->GetTypeId(), target->GetEntry(), target->GetGUID().GetCounter());
break;
}
}
@@ -652,7 +640,7 @@ void Map::ScriptsProcess()
if (target->GetTypeId() != TYPEID_GAMEOBJECT)
{
TC_LOG_ERROR("scripts", "%s target object is not gameobject (TypeId: %u, Entry: %u, GUID: %u), skipping.",
- step.script->GetDebugInfo().c_str(), target->GetTypeId(), target->GetEntry(), target->GetGUIDLow());
+ step.script->GetDebugInfo().c_str(), target->GetTypeId(), target->GetEntry(), target->GetGUID().GetCounter());
break;
}
@@ -794,22 +782,15 @@ void Map::ScriptsProcess()
}
Creature* cTarget = NULL;
- WorldObject* wSource = dynamic_cast <WorldObject*> (source);
- if (wSource) //using grid searcher
- {
- CellCoord p(Trinity::ComputeCellCoord(wSource->GetPositionX(), wSource->GetPositionY()));
- Cell cell(p);
-
- Trinity::CreatureWithDbGUIDCheck target_check(wSource, step.script->CallScript.CreatureEntry);
- Trinity::CreatureSearcher<Trinity::CreatureWithDbGUIDCheck> checker(wSource, cTarget, target_check);
-
- TypeContainerVisitor<Trinity::CreatureSearcher <Trinity::CreatureWithDbGUIDCheck>, GridTypeMapContainer > unit_checker(checker);
- cell.Visit(p, unit_checker, *wSource->GetMap(), *wSource, wSource->GetGridActivationRange());
- }
- else //check hashmap holders
+ auto creatureBounds = _creatureBySpawnIdStore.equal_range(step.script->CallScript.CreatureEntry);
+ if (creatureBounds.first != creatureBounds.second)
{
- if (CreatureData const* data = sObjectMgr->GetCreatureData(step.script->CallScript.CreatureEntry))
- cTarget = ObjectAccessor::GetObjectInWorld<Creature>(data->mapid, data->posX, data->posY, ObjectGuid(HIGHGUID_UNIT, data->id, step.script->CallScript.CreatureEntry), cTarget);
+ // Prefer alive (last respawned) creature
+ auto creatureItr = std::find_if(creatureBounds.first, creatureBounds.second, [](Map::CreatureBySpawnIdContainer::value_type const& pair)
+ {
+ return pair.second->IsAlive();
+ });
+ cTarget = creatureItr != creatureBounds.second ? creatureItr->second : creatureBounds.first->second;
}
if (!cTarget)
@@ -838,7 +819,7 @@ void Map::ScriptsProcess()
{
if (cSource->isDead())
TC_LOG_ERROR("scripts", "%s creature is already dead (Entry: %u, GUID: %u)",
- step.script->GetDebugInfo().c_str(), cSource->GetEntry(), cSource->GetGUIDLow());
+ step.script->GetDebugInfo().c_str(), cSource->GetEntry(), cSource->GetGUID().GetCounter());
else
{
cSource->setDeathState(JUST_DIED);
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index f0ee013bcc2..47a23dedf0c 100644
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -92,6 +92,7 @@ void AddSC_npcs_special();
void AddSC_npc_taxi();
void AddSC_achievement_scripts();
void AddSC_action_ip_logger();
+void AddSC_duel_reset();
//eastern kingdoms
void AddSC_alterac_valley(); //Alterac Valley
@@ -101,11 +102,8 @@ void AddSC_boss_galvangar();
void AddSC_boss_vanndar();
void AddSC_blackrock_depths(); //Blackrock Depths
void AddSC_boss_ambassador_flamelash();
-void AddSC_boss_anubshiah();
void AddSC_boss_draganthaurissan();
void AddSC_boss_general_angerforge();
-void AddSC_boss_gorosh_the_dervish();
-void AddSC_boss_grizzle();
void AddSC_boss_high_interrogator_gerstahn();
void AddSC_boss_magmus();
void AddSC_boss_moira_bronzebeard();
@@ -360,7 +358,6 @@ void AddSC_orgrimmar();
void AddSC_silithus();
void AddSC_stonetalon_mountains();
void AddSC_tanaris();
-void AddSC_teldrassil();
void AddSC_the_barrens();
void AddSC_thousand_needles();
void AddSC_thunder_bluff();
@@ -790,6 +787,7 @@ void AddWorldScripts()
// To avoid duplicate code, we check once /*ONLY*/ if logging is permitted or not.
if (sWorld->getBoolConfig(CONFIG_IP_BASED_ACTION_LOGGING))
AddSC_action_ip_logger(); // location: scripts\World\action_ip_logger.cpp
+ AddSC_duel_reset();
#endif
}
@@ -803,11 +801,8 @@ void AddEasternKingdomsScripts()
AddSC_boss_vanndar();
AddSC_blackrock_depths(); //Blackrock Depths
AddSC_boss_ambassador_flamelash();
- AddSC_boss_anubshiah();
AddSC_boss_draganthaurissan();
AddSC_boss_general_angerforge();
- AddSC_boss_gorosh_the_dervish();
- AddSC_boss_grizzle();
AddSC_boss_high_interrogator_gerstahn();
AddSC_boss_magmus();
AddSC_boss_moira_bronzebeard();
@@ -1066,7 +1061,6 @@ void AddKalimdorScripts()
AddSC_silithus();
AddSC_stonetalon_mountains();
AddSC_tanaris();
- AddSC_teldrassil();
AddSC_the_barrens();
AddSC_thousand_needles();
AddSC_thunder_bluff();
diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp
index aed829a7b57..3cbdf93ca54 100644
--- a/src/server/game/Scripting/ScriptMgr.cpp
+++ b/src/server/game/Scripting/ScriptMgr.cpp
@@ -33,6 +33,7 @@
#include "Player.h"
#include "WorldPacket.h"
#include "WorldSession.h"
+#include "Chat.h"
// namespace
// {
@@ -40,6 +41,60 @@
UnusedScriptNamesContainer UnusedScriptNames;
// }
+// Trait which indicates whether this script type
+// must be assigned in the database.
+template<typename>
+struct is_script_database_bound
+ : std::false_type { };
+
+template<>
+struct is_script_database_bound<SpellScriptLoader>
+ : std::true_type { };
+
+template<>
+struct is_script_database_bound<InstanceMapScript>
+ : std::true_type { };
+
+template<>
+struct is_script_database_bound<ItemScript>
+ : std::true_type { };
+
+template<>
+struct is_script_database_bound<CreatureScript>
+ : std::true_type { };
+
+template<>
+struct is_script_database_bound<GameObjectScript>
+ : std::true_type { };
+
+template<>
+struct is_script_database_bound<AreaTriggerScript>
+ : std::true_type { };
+
+template<>
+struct is_script_database_bound<BattlegroundScript>
+ : std::true_type { };
+
+template<>
+struct is_script_database_bound<OutdoorPvPScript>
+ : std::true_type { };
+
+template<>
+struct is_script_database_bound<WeatherScript>
+ : std::true_type { };
+
+template<>
+struct is_script_database_bound<ConditionScript>
+ : std::true_type { };
+
+template<>
+struct is_script_database_bound<TransportScript>
+ : std::true_type { };
+
+template<>
+struct is_script_database_bound<AchievementCriteriaScript>
+ : std::true_type { };
+
// This is the global static registry of scripts.
template<class TScript>
class ScriptRegistry
@@ -70,78 +125,83 @@ class ScriptRegistry
}
}
- if (script->IsDatabaseBound())
+ AddScript(is_script_database_bound<TScript>{}, script);
+ }
+
+ // Gets a script by its ID (assigned by ObjectMgr).
+ static TScript* GetScriptById(uint32 id)
+ {
+ ScriptMapIterator it = ScriptPointerList.find(id);
+ if (it != ScriptPointerList.end())
+ return it->second;
+
+ return NULL;
+ }
+
+ private:
+
+ // Adds a database bound script
+ static void AddScript(std::true_type, TScript* const script)
+ {
+ // Get an ID for the script. An ID only exists if it's a script that is assigned in the database
+ // through a script name (or similar).
+ uint32 id = sObjectMgr->GetScriptId(script->GetName());
+ if (id)
{
- // Get an ID for the script. An ID only exists if it's a script that is assigned in the database
- // through a script name (or similar).
- uint32 id = sObjectMgr->GetScriptId(script->GetName().c_str());
- if (id)
+ // Try to find an existing script.
+ bool existing = false;
+ for (ScriptMapIterator it = ScriptPointerList.begin(); it != ScriptPointerList.end(); ++it)
{
- // Try to find an existing script.
- bool existing = false;
- for (ScriptMapIterator it = ScriptPointerList.begin(); it != ScriptPointerList.end(); ++it)
- {
- // If the script names match...
- if (it->second->GetName() == script->GetName())
- {
- // ... It exists.
- existing = true;
- break;
- }
- }
-
- // If the script isn't assigned -> assign it!
- if (!existing)
+ // If the script names match...
+ if (it->second->GetName() == script->GetName())
{
- ScriptPointerList[id] = script;
- sScriptMgr->IncrementScriptCount();
-
- #ifdef SCRIPTS
- UnusedScriptNamesContainer::iterator itr = std::lower_bound(UnusedScriptNames.begin(), UnusedScriptNames.end(), script->GetName());
- if (itr != UnusedScriptNames.end() && *itr == script->GetName())
- UnusedScriptNames.erase(itr);
- #endif
+ // ... It exists.
+ existing = true;
+ break;
}
- else
- {
- // If the script is already assigned -> delete it!
- TC_LOG_ERROR("scripts", "Script '%s' already assigned with the same script name, so the script can't work.",
- script->GetName().c_str());
+ }
- ASSERT(false); // Error that should be fixed ASAP.
- }
+ // If the script isn't assigned -> assign it!
+ if (!existing)
+ {
+ ScriptPointerList[id] = script;
+ sScriptMgr->IncrementScriptCount();
+
+ #ifdef SCRIPTS
+ UnusedScriptNamesContainer::iterator itr = std::lower_bound(UnusedScriptNames.begin(), UnusedScriptNames.end(), script->GetName());
+ if (itr != UnusedScriptNames.end() && *itr == script->GetName())
+ UnusedScriptNames.erase(itr);
+ #endif
}
else
{
- // The script uses a script name from database, but isn't assigned to anything.
- TC_LOG_ERROR("sql.sql", "Script named '%s' does not have a script name assigned in database.", script->GetName().c_str());
+ // If the script is already assigned -> delete it!
+ TC_LOG_ERROR("scripts", "Script '%s' already assigned with the same script name, so the script can't work.",
+ script->GetName().c_str());
- // Avoid calling "delete script;" because we are currently in the script constructor
- // In a valid scenario this will not happen because every script has a name assigned in the database
- UnusedScripts.push_back(script);
- return;
+ ABORT(); // Error that should be fixed ASAP.
}
}
else
{
- // We're dealing with a code-only script; just add it.
- ScriptPointerList[_scriptIdCounter++] = script;
- sScriptMgr->IncrementScriptCount();
+ // The script uses a script name from database, but isn't assigned to anything.
+ TC_LOG_ERROR("sql.sql", "Script named '%s' does not have a script name assigned in database.", script->GetName().c_str());
+
+ // Avoid calling "delete script;" because we are currently in the script constructor
+ // In a valid scenario this will not happen because every script has a name assigned in the database
+ UnusedScripts.push_back(script);
+ return;
}
}
- // Gets a script by its ID (assigned by ObjectMgr).
- static TScript* GetScriptById(uint32 id)
+ // Adds a non database bound script
+ static void AddScript(std::false_type, TScript* const script)
{
- ScriptMapIterator it = ScriptPointerList.find(id);
- if (it != ScriptPointerList.end())
- return it->second;
-
- return NULL;
+ // We're dealing with a code-only script; just add it.
+ ScriptPointerList[_scriptIdCounter++] = script;
+ sScriptMgr->IncrementScriptCount();
}
- private:
-
// Counter used for code-only scripts.
static uint32 _scriptIdCounter;
};
@@ -960,7 +1020,7 @@ bool ScriptMgr::OnAreaTrigger(Player* player, AreaTriggerEntry const* trigger)
Battleground* ScriptMgr::CreateBattleground(BattlegroundTypeId /*typeId*/)
{
/// @todo Implement script-side battlegrounds.
- ASSERT(false);
+ ABORT();
return NULL;
}
@@ -972,12 +1032,15 @@ OutdoorPvP* ScriptMgr::CreateOutdoorPvP(OutdoorPvPData const* data)
return tmpscript->GetOutdoorPvP();
}
-std::vector<ChatCommand*> ScriptMgr::GetChatCommands()
+std::vector<ChatCommand> ScriptMgr::GetChatCommands()
{
- std::vector<ChatCommand*> table;
+ std::vector<ChatCommand> table;
FOR_SCRIPTS_RET(CommandScript, itr, end, table)
- table.push_back(itr->second->GetCommands());
+ {
+ std::vector<ChatCommand> cmds = itr->second->GetCommands();
+ table.insert(table.end(), cmds.begin(), cmds.end());
+ }
return table;
}
@@ -1030,7 +1093,7 @@ void ScriptMgr::OnAuctionExpire(AuctionHouseObject* ah, AuctionEntry* entry)
FOREACH_SCRIPT(AuctionHouseScript)->OnAuctionExpire(ah, entry);
}
-bool ScriptMgr::OnConditionCheck(Condition* condition, ConditionSourceInfo& sourceInfo)
+bool ScriptMgr::OnConditionCheck(Condition const* condition, ConditionSourceInfo& sourceInfo)
{
ASSERT(condition);
@@ -1392,12 +1455,12 @@ void ScriptMgr::OnGuildItemMove(Guild* guild, Player* player, Item* pItem, bool
FOREACH_SCRIPT(GuildScript)->OnItemMove(guild, player, pItem, isSrcBank, srcContainer, srcSlotId, isDestBank, destContainer, destSlotId);
}
-void ScriptMgr::OnGuildEvent(Guild* guild, uint8 eventType, uint32 playerGuid1, uint32 playerGuid2, uint8 newRank)
+void ScriptMgr::OnGuildEvent(Guild* guild, uint8 eventType, ObjectGuid::LowType playerGuid1, ObjectGuid::LowType playerGuid2, uint8 newRank)
{
FOREACH_SCRIPT(GuildScript)->OnEvent(guild, eventType, playerGuid1, playerGuid2, newRank);
}
-void ScriptMgr::OnGuildBankEvent(Guild* guild, uint8 eventType, uint8 tabId, uint32 playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId)
+void ScriptMgr::OnGuildBankEvent(Guild* guild, uint8 eventType, uint8 tabId, ObjectGuid::LowType playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId)
{
FOREACH_SCRIPT(GuildScript)->OnBankEvent(guild, eventType, tabId, playerGuid, itemOrMoney, itemStackCount, destTabId);
}
diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h
index a226f1b7ed2..046c6c1a009 100644
--- a/src/server/game/Scripting/ScriptMgr.h
+++ b/src/server/game/Scripting/ScriptMgr.h
@@ -153,10 +153,6 @@ class ScriptObject
public:
- // Do not override this in scripts; it should be overridden by the various script type classes. It indicates
- // whether or not this script type must be assigned in the database.
- virtual bool IsDatabaseBound() const { return false; }
-
const std::string& GetName() const { return _name; }
protected:
@@ -198,8 +194,6 @@ class SpellScriptLoader : public ScriptObject
public:
- bool IsDatabaseBound() const final override { return true; }
-
// Should return a fully valid SpellScript pointer.
virtual SpellScript* GetSpellScript() const { return NULL; }
@@ -356,8 +350,6 @@ class InstanceMapScript : public ScriptObject, public MapScript<InstanceMap>
public:
- bool IsDatabaseBound() const final override { return true; }
-
// Gets an InstanceScript object for this instance.
virtual InstanceScript* GetInstanceScript(InstanceMap* /*map*/) const { return NULL; }
};
@@ -377,8 +369,6 @@ class ItemScript : public ScriptObject
public:
- bool IsDatabaseBound() const final override { return true; }
-
// Called when a dummy spell effect is triggered on the item.
virtual bool OnDummyEffect(Unit* /*caster*/, uint32 /*spellId*/, SpellEffIndex /*effIndex*/, Item* /*target*/) { return false; }
@@ -426,8 +416,6 @@ class CreatureScript : public UnitScript, public UpdatableScript<Creature>
public:
- bool IsDatabaseBound() const final override { return true; }
-
// Called when a dummy spell effect is triggered on the creature.
virtual bool OnDummyEffect(Unit* /*caster*/, uint32 /*spellId*/, SpellEffIndex /*effIndex*/, Creature* /*target*/) { return false; }
@@ -464,8 +452,6 @@ class GameObjectScript : public ScriptObject, public UpdatableScript<GameObject>
public:
- bool IsDatabaseBound() const final override { return true; }
-
// Called when a dummy spell effect is triggered on the gameobject.
virtual bool OnDummyEffect(Unit* /*caster*/, uint32 /*spellId*/, SpellEffIndex /*effIndex*/, GameObject* /*target*/) { return false; }
@@ -511,8 +497,6 @@ class AreaTriggerScript : public ScriptObject
public:
- bool IsDatabaseBound() const final override { return true; }
-
// Called when the area trigger is activated by a player.
virtual bool OnTrigger(Player* /*player*/, AreaTriggerEntry const* /*trigger*/) { return false; }
};
@@ -525,8 +509,6 @@ class BattlegroundScript : public ScriptObject
public:
- bool IsDatabaseBound() const final override { return true; }
-
// Should return a fully valid Battleground object for the type ID.
virtual Battleground* GetBattleground() const = 0;
};
@@ -539,8 +521,6 @@ class OutdoorPvPScript : public ScriptObject
public:
- bool IsDatabaseBound() const final override { return true; }
-
// Should return a fully valid OutdoorPvP object for the type ID.
virtual OutdoorPvP* GetOutdoorPvP() const = 0;
};
@@ -554,7 +534,7 @@ class CommandScript : public ScriptObject
public:
// Should return a pointer to a valid command table (ChatCommand array) to be used by ChatHandler.
- virtual ChatCommand* GetCommands() const = 0;
+ virtual std::vector<ChatCommand> GetCommands() const = 0;
};
class WeatherScript : public ScriptObject, public UpdatableScript<Weather>
@@ -565,8 +545,6 @@ class WeatherScript : public ScriptObject, public UpdatableScript<Weather>
public:
- bool IsDatabaseBound() const final override { return true; }
-
// Called when the weather changes in the zone this script is associated with.
virtual void OnChange(Weather* /*weather*/, WeatherState /*state*/, float /*grade*/) { }
};
@@ -600,10 +578,8 @@ class ConditionScript : public ScriptObject
public:
- bool IsDatabaseBound() const final override { return true; }
-
// Called when a single condition is checked for a player.
- virtual bool OnConditionCheck(Condition* /*condition*/, ConditionSourceInfo& /*sourceInfo*/) { return true; }
+ virtual bool OnConditionCheck(Condition const* /*condition*/, ConditionSourceInfo& /*sourceInfo*/) { return true; }
};
class VehicleScript : public ScriptObject
@@ -648,8 +624,6 @@ class TransportScript : public ScriptObject, public UpdatableScript<Transport>
public:
- bool IsDatabaseBound() const final override { return true; }
-
// Called when a player boards the transport.
virtual void OnAddPassenger(Transport* /*transport*/, Player* /*player*/) { }
@@ -671,8 +645,6 @@ class AchievementCriteriaScript : public ScriptObject
public:
- bool IsDatabaseBound() const final override { return true; }
-
// Called when an additional criteria is checked.
virtual bool OnCheck(Player* source, Unit* target) = 0;
};
@@ -809,8 +781,6 @@ class GuildScript : public ScriptObject
public:
- bool IsDatabaseBound() const final override { return false; }
-
// Called when a member is added to the guild.
virtual void OnAddMember(Guild* /*guild*/, Player* /*player*/, uint8& /*plRank*/) { }
@@ -839,9 +809,9 @@ class GuildScript : public ScriptObject
virtual void OnItemMove(Guild* /*guild*/, Player* /*player*/, Item* /*pItem*/, bool /*isSrcBank*/, uint8 /*srcContainer*/, uint8 /*srcSlotId*/,
bool /*isDestBank*/, uint8 /*destContainer*/, uint8 /*destSlotId*/) { }
- virtual void OnEvent(Guild* /*guild*/, uint8 /*eventType*/, uint32 /*playerGuid1*/, uint32 /*playerGuid2*/, uint8 /*newRank*/) { }
+ virtual void OnEvent(Guild* /*guild*/, uint8 /*eventType*/, ObjectGuid::LowType /*playerGuid1*/, ObjectGuid::LowType /*playerGuid2*/, uint8 /*newRank*/) { }
- virtual void OnBankEvent(Guild* /*guild*/, uint8 /*eventType*/, uint8 /*tabId*/, uint32 /*playerGuid*/, uint32 /*itemOrMoney*/, uint16 /*itemStackCount*/, uint8 /*destTabId*/) { }
+ virtual void OnBankEvent(Guild* /*guild*/, uint8 /*eventType*/, uint8 /*tabId*/, ObjectGuid::LowType /*playerGuid*/, uint32 /*itemOrMoney*/, uint16 /*itemStackCount*/, uint8 /*destTabId*/) { }
};
class GroupScript : public ScriptObject
@@ -852,8 +822,6 @@ class GroupScript : public ScriptObject
public:
- bool IsDatabaseBound() const final override { return false; }
-
// Called when a member is added to a group.
virtual void OnAddMember(Group* /*group*/, ObjectGuid /*guid*/) { }
@@ -1014,7 +982,7 @@ class ScriptMgr
public: /* CommandScript */
- std::vector<ChatCommand*> GetChatCommands();
+ std::vector<ChatCommand> GetChatCommands();
public: /* WeatherScript */
@@ -1030,7 +998,7 @@ class ScriptMgr
public: /* ConditionScript */
- bool OnConditionCheck(Condition* condition, ConditionSourceInfo& sourceInfo);
+ bool OnConditionCheck(Condition const* condition, ConditionSourceInfo& sourceInfo);
public: /* VehicleScript */
@@ -1111,8 +1079,8 @@ class ScriptMgr
void OnGuildMemberDepositMoney(Guild* guild, Player* player, uint32 &amount);
void OnGuildItemMove(Guild* guild, Player* player, Item* pItem, bool isSrcBank, uint8 srcContainer, uint8 srcSlotId,
bool isDestBank, uint8 destContainer, uint8 destSlotId);
- void OnGuildEvent(Guild* guild, uint8 eventType, uint32 playerGuid1, uint32 playerGuid2, uint8 newRank);
- void OnGuildBankEvent(Guild* guild, uint8 eventType, uint8 tabId, uint32 playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId);
+ void OnGuildEvent(Guild* guild, uint8 eventType, ObjectGuid::LowType playerGuid1, ObjectGuid::LowType playerGuid2, uint8 newRank);
+ void OnGuildBankEvent(Guild* guild, uint8 eventType, uint8 tabId, ObjectGuid::LowType playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId);
public: /* GroupScript */
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index 14ce4cfe3c1..4f7b8f510b0 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -1273,7 +1273,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
/*0x4DC*/ { "SMSG_PVP_QUEUE_STATS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x4DD*/ { "CMSG_SET_PAID_SERVICE_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
/*0x4DE*/ { "SMSG_BATTLEFIELD_MGR_ENTRY_INVITE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4DF*/ { "CMSG_BATTLEFIELD_MGR_ENTRY_INVITE_RESPONSE", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleBfEntryInviteResponse },
+ /*0x4DF*/ { "CMSG_BATTLEFIELD_MGR_ENTRY_INVITE_RESPONSE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBfEntryInviteResponse },
/*0x4E0*/ { "SMSG_BATTLEFIELD_MGR_ENTERED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x4E1*/ { "SMSG_BATTLEFIELD_MGR_QUEUE_INVITE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x4E2*/ { "CMSG_BATTLEFIELD_MGR_QUEUE_INVITE_RESPONSE", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleBfQueueInviteResponse },
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index d6055e9733b..6ae63f2efa3 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -39,10 +39,12 @@
#include "BattlegroundMgr.h"
#include "OutdoorPvPMgr.h"
#include "SocialMgr.h"
-#include "zlib.h"
#include "ScriptMgr.h"
#include "WardenWin.h"
#include "MoveSpline.h"
+#include "WardenMac.h"
+
+#include <zlib.h>
namespace {
@@ -93,7 +95,7 @@ bool WorldSessionFilter::Process(WorldPacket* packet)
}
/// WorldSession constructor
-WorldSession::WorldSession(uint32 id, std::shared_ptr<WorldSocket> sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale, uint32 recruiter, bool isARecruiter):
+WorldSession::WorldSession(uint32 id, std::string&& name, std::shared_ptr<WorldSocket> sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale, uint32 recruiter, bool isARecruiter):
m_muteTime(mute_time),
m_timeOutTime(0),
AntiDOS(this),
@@ -102,6 +104,7 @@ WorldSession::WorldSession(uint32 id, std::shared_ptr<WorldSocket> sock, Account
m_Socket(sock),
_security(sec),
_accountId(id),
+ _accountName(std::move(name)),
m_expansion(expansion),
_warden(NULL),
_logoutTime(0),
@@ -168,19 +171,19 @@ std::string WorldSession::GetPlayerInfo() const
{
std::ostringstream ss;
- ss << "[Player: " << GetPlayerName() << " (";
- if (_player != NULL)
- ss << _player->GetGUID().ToString() << ", ";
+ ss << "[Player: ";
+ if (!m_playerLoading && _player)
+ ss << _player->GetName() << ' ' << _player->GetGUID().ToString() << ", ";
- ss << "Account: " << GetAccountId() << ")]";
+ ss << "Account: " << GetAccountId() << "]";
return ss.str();
}
/// Get player guid if available. Use for logging purposes only
-uint32 WorldSession::GetGuidLow() const
+ObjectGuid::LowType WorldSession::GetGUIDLow() const
{
- return GetPlayer() ? GetPlayer()->GetGUIDLow() : 0;
+ return GetPlayer() ? GetPlayer()->GetGUID().GetCounter() : 0;
}
/// Send a packet to the client
@@ -338,7 +341,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
LogUnexpectedOpcode(packet, "STATUS_TRANSFER", "the player has not logged in yet");
else if (_player->IsInWorld())
LogUnexpectedOpcode(packet, "STATUS_TRANSFER", "the player is still in world");
- else if(AntiDOS.EvaluateOpcode(*packet, currentTime))
+ else if (AntiDOS.EvaluateOpcode(*packet, currentTime))
{
sScriptMgr->OnPacketReceive(this, *packet);
(this->*opHandle.handler)(*packet);
@@ -481,6 +484,15 @@ void WorldSession::LogoutPlayer(bool save)
{
if (BattlegroundQueueTypeId bgQueueTypeId = _player->GetBattlegroundQueueTypeId(i))
{
+ // track if player logs out after invited to join BG
+ if (_player->IsInvitedForBattlegroundQueueType(bgQueueTypeId) && sWorld->getBoolConfig(CONFIG_BATTLEGROUND_TRACK_DESERTERS))
+ {
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_DESERTER_TRACK);
+ stmt->setUInt32(0, _player->GetGUID().GetCounter());
+ stmt->setUInt8(1, BG_DESERTION_TYPE_INVITE_LOGOUT);
+ CharacterDatabase.Execute(stmt);
+ }
+
_player->RemoveBattlegroundQueueId(bgQueueTypeId);
BattlegroundQueue& queue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
queue.RemovePlayer(_player->GetGUID(), true);
@@ -536,8 +548,8 @@ void WorldSession::LogoutPlayer(bool save)
}
//! Broadcast a logout message to the player's friends
- sSocialMgr->SendFriendStatus(_player, FRIEND_OFFLINE, _player->GetGUIDLow(), true);
- sSocialMgr->RemovePlayerSocial(_player->GetGUIDLow());
+ sSocialMgr->SendFriendStatus(_player, FRIEND_OFFLINE, _player->GetGUID().GetCounter(), true);
+ sSocialMgr->RemovePlayerSocial(_player->GetGUID().GetCounter());
//! Call script hook before deletion
sScriptMgr->OnPlayerLogout(_player);
@@ -548,7 +560,7 @@ void WorldSession::LogoutPlayer(bool save)
// calls to GetMap in this case may cause crashes
_player->CleanupsBeforeDelete();
TC_LOG_INFO("entities.player.character", "Account: %d (IP: %s) Logout Character:[%s] (GUID: %u) Level: %d",
- GetAccountId(), GetRemoteAddress().c_str(), _player->GetName().c_str(), _player->GetGUIDLow(), _player->getLevel());
+ GetAccountId(), GetRemoteAddress().c_str(), _player->GetName().c_str(), _player->GetGUID().GetCounter(), _player->getLevel());
if (Map* _map = _player->FindMap())
_map->RemovePlayerFromMap(_player, true);
@@ -664,13 +676,6 @@ void WorldSession::SendAuthWaitQue(uint32 position)
}
}
-void WorldSession::LoadGlobalAccountData()
-{
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ACCOUNT_DATA);
- stmt->setUInt32(0, GetAccountId());
- LoadAccountData(CharacterDatabase.Query(stmt), GLOBAL_CACHE_MASK);
-}
-
void WorldSession::LoadAccountData(PreparedQueryResult result, uint32 mask)
{
for (uint32 i = 0; i < NUM_ACCOUNT_DATA_TYPES; ++i)
@@ -707,7 +712,7 @@ void WorldSession::LoadAccountData(PreparedQueryResult result, uint32 mask)
void WorldSession::SetAccountData(AccountDataType type, time_t tm, std::string const& data)
{
uint32 id = 0;
- uint32 index = 0;
+ CharacterDatabaseStatements index;
if ((1 << type) & GLOBAL_CACHE_MASK)
{
id = GetAccountId();
@@ -746,13 +751,11 @@ void WorldSession::SendAccountDataTimes(uint32 mask)
SendPacket(&data);
}
-void WorldSession::LoadTutorialsData()
+void WorldSession::LoadTutorialsData(PreparedQueryResult result)
{
memset(m_Tutorials, 0, sizeof(uint32) * MAX_ACCOUNT_TUTORIAL_VALUES);
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_TUTORIALS);
- stmt->setUInt32(0, GetAccountId());
- if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
+ if (result)
for (uint8 i = 0; i < MAX_ACCOUNT_TUTORIAL_VALUES; ++i)
m_Tutorials[i] = (*result)[i].GetUInt32();
@@ -828,7 +831,7 @@ void WorldSession::ReadMovementInfo(WorldPacket &data, MovementInfo* mi)
{ \
TC_LOG_DEBUG("entities.unit", "WorldSession::ReadMovementInfo: Violation of MovementFlags found (%s). " \
"MovementFlags: %u, MovementFlags2: %u for player GUID: %u. Mask %u will be removed.", \
- STRINGIZE(check), mi->GetMovementFlags(), mi->GetExtraMovementFlags(), GetPlayer()->GetGUIDLow(), maskToRemove); \
+ STRINGIZE(check), mi->GetMovementFlags(), mi->GetExtraMovementFlags(), GetPlayer()->GetGUID().GetCounter(), maskToRemove); \
mi->RemoveMovementFlag((maskToRemove)); \
} \
}
@@ -838,13 +841,32 @@ void WorldSession::ReadMovementInfo(WorldPacket &data, MovementInfo* mi)
mi->RemoveMovementFlag((maskToRemove));
#endif
-
/*! This must be a packet spoofing attempt. MOVEMENTFLAG_ROOT sent from the client is not valid
in conjunction with any of the moving movement flags such as MOVEMENTFLAG_FORWARD.
It will freeze clients that receive this player's movement info.
*/
- REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_ROOT),
- MOVEMENTFLAG_ROOT);
+ // Only adjust movement flag removal for vehicles with the VEHICLE_FLAG_FIXED_POSITION flag, or the hard coded exceptions below:
+ // 30236 | Argent Cannon
+ // 39759 | Tankbuster Cannon
+ if (GetPlayer()->GetVehicleBase() && ((GetPlayer()->GetVehicle()->GetVehicleInfo()->m_flags & VEHICLE_FLAG_FIXED_POSITION) || GetPlayer()->GetVehicleBase()->GetEntry() == 30236 || GetPlayer()->GetVehicleBase()->GetEntry() == 39759))
+ {
+ // Actually players in rooted vehicles still send commands, don't clear root for these!
+ // Check specifically for the following conditions:
+ // MOVEMENTFLAG_ROOT + no other flags (0x800)
+ // MOVEMENTFLAG_ROOT + MOVEMENTFLAG_LEFT (0x810)
+ // MOVEMENTFLAG_ROOT + MOVEMENTFLAG_RIGHT (0x820)
+ // MOVEMENTFLAG_ROOT + MOVEMENTFLAG_PITCH_UP (0x840)
+ // MOVEMENTFLAG_ROOT + MOVEMENTFLAG_PITCH_DOWN (0x880)
+ // If none of these are true, clear the root
+ REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_ROOT) && mi->HasMovementFlag(MOVEMENTFLAG_LEFT | MOVEMENTFLAG_RIGHT | MOVEMENTFLAG_PITCH_UP | MOVEMENTFLAG_PITCH_DOWN),
+ MOVEMENTFLAG_MASK_MOVING);
+ }
+ else
+ {
+ // Only remove here for non vehicles
+ REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_ROOT),
+ MOVEMENTFLAG_ROOT);
+ }
//! Cannot hover without SPELL_AURA_HOVER
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_HOVER) && !GetPlayer()->HasAuraType(SPELL_AURA_HOVER),
@@ -935,7 +957,7 @@ void WorldSession::WriteMovementInfo(WorldPacket* data, MovementInfo* mi)
*data << mi->splineElevation;
}
-void WorldSession::ReadAddonsInfo(WorldPacket &data)
+void WorldSession::ReadAddonsInfo(ByteBuffer &data)
{
if (data.rpos() + 4 > data.size())
return;
@@ -1080,7 +1102,7 @@ void WorldSession::SetPlayer(Player* player)
// set m_GUID that can be used while player loggined and later until m_playerRecentlyLogout not reset
if (_player)
- m_GUIDLow = _player->GetGUIDLow();
+ m_GUIDLow = _player->GetGUID().GetCounter();
}
void WorldSession::InitializeQueryCallbackParameters()
@@ -1094,6 +1116,9 @@ void WorldSession::ProcessQueryCallbacks()
{
PreparedQueryResult result;
+ if (_realmAccountLoginCallback.valid() && _realmAccountLoginCallback.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
+ InitializeSessionCallback(_realmAccountLoginCallback.get());
+
//! HandleCharEnumOpcode
if (_charEnumCallback.valid() && _charEnumCallback.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
{
@@ -1193,15 +1218,84 @@ void WorldSession::InitWarden(BigNumber* k, std::string const& os)
void WorldSession::LoadPermissions()
{
uint32 id = GetAccountId();
- std::string name;
- AccountMgr::GetName(id, name);
uint8 secLevel = GetSecurity();
- _RBACData = new rbac::RBACData(id, name, realmID, secLevel);
+ _RBACData = new rbac::RBACData(id, _accountName, realmID, secLevel);
_RBACData->LoadFromDB();
+}
+
+PreparedQueryResultFuture WorldSession::LoadPermissionsAsync()
+{
+ uint32 id = GetAccountId();
+ uint8 secLevel = GetSecurity();
TC_LOG_DEBUG("rbac", "WorldSession::LoadPermissions [AccountId: %u, Name: %s, realmId: %d, secLevel: %u]",
- id, name.c_str(), realmID, secLevel);
+ id, _accountName.c_str(), realmID, secLevel);
+
+ _RBACData = new rbac::RBACData(id, _accountName, realmID, secLevel);
+ return _RBACData->LoadFromDBAsync();
+}
+
+class AccountInfoQueryHolderPerRealm : public SQLQueryHolder
+{
+public:
+ enum
+ {
+ GLOBAL_ACCOUNT_DATA = 0,
+ TUTORIALS,
+
+ MAX_QUERIES
+ };
+
+ AccountInfoQueryHolderPerRealm() { SetSize(MAX_QUERIES); }
+
+ bool Initialize(uint32 accountId)
+ {
+ bool ok = true;
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ACCOUNT_DATA);
+ stmt->setUInt32(0, accountId);
+ ok = SetPreparedQuery(GLOBAL_ACCOUNT_DATA, stmt) && ok;
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_TUTORIALS);
+ stmt->setUInt32(0, accountId);
+ ok = SetPreparedQuery(TUTORIALS, stmt) && ok;
+
+ return ok;
+ }
+};
+
+void WorldSession::InitializeSession()
+{
+ AccountInfoQueryHolderPerRealm* realmHolder = new AccountInfoQueryHolderPerRealm();
+ if (!realmHolder->Initialize(GetAccountId()))
+ {
+ delete realmHolder;
+ SendAuthResponse(AUTH_SYSTEM_ERROR, false);
+ return;
+ }
+
+ _realmAccountLoginCallback = CharacterDatabase.DelayQueryHolder(realmHolder);
+}
+
+void WorldSession::InitializeSessionCallback(SQLQueryHolder* realmHolder)
+{
+ LoadAccountData(realmHolder->GetPreparedResult(AccountInfoQueryHolderPerRealm::GLOBAL_ACCOUNT_DATA), GLOBAL_CACHE_MASK);
+ LoadTutorialsData(realmHolder->GetPreparedResult(AccountInfoQueryHolderPerRealm::TUTORIALS));
+
+ if (!m_inQueue)
+ SendAuthResponse(AUTH_OK, true);
+ else
+ SendAuthWaitQue(0);
+
+ SetInQueue(false);
+ ResetTimeOutTime();
+
+ SendAddonsInfo();
+ SendClientCacheVersion(sWorld->getIntConfig(CONFIG_CLIENTCACHE_VERSION));
+ SendTutorialsData();
+
+ delete realmHolder;
}
rbac::RBACData* WorldSession::GetRBACData()
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index eda8f0bb6d9..af2d2d22c57 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -249,15 +249,16 @@ struct PacketCounter
class WorldSession
{
public:
- WorldSession(uint32 id, std::shared_ptr<WorldSocket> sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale, uint32 recruiter, bool isARecruiter);
+ WorldSession(uint32 id, std::string&& name, std::shared_ptr<WorldSocket> sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale, uint32 recruiter, bool isARecruiter);
~WorldSession();
bool PlayerLoading() const { return m_playerLoading; }
bool PlayerLogout() const { return m_playerLogout; }
bool PlayerLogoutWithSave() const { return m_playerLogout && m_playerSave; }
bool PlayerRecentlyLoggedOut() const { return m_playerRecentlyLogout; }
+ bool PlayerDisconnected() const { return !m_Socket; }
- void ReadAddonsInfo(WorldPacket& data);
+ void ReadAddonsInfo(ByteBuffer& data);
void SendAddonsInfo();
void ReadMovementInfo(WorldPacket& data, MovementInfo* mi);
@@ -275,9 +276,13 @@ class WorldSession
void SendAuthResponse(uint8 code, bool shortForm, uint32 queuePos = 0);
void SendClientCacheVersion(uint32 version);
+ void InitializeSession();
+ void InitializeSessionCallback(SQLQueryHolder* realmHolder);
+
rbac::RBACData* GetRBACData();
bool HasPermission(uint32 permissionId);
void LoadPermissions();
+ PreparedQueryResultFuture LoadPermissionsAsync();
void InvalidateRBACData(); // Used to force LoadPermissions at next HasPermission check
AccountTypes GetSecurity() const { return _security; }
@@ -286,9 +291,9 @@ class WorldSession
std::string const& GetPlayerName() const;
std::string GetPlayerInfo() const;
- uint32 GetGuidLow() const;
+ ObjectGuid::LowType GetGUIDLow() const;
void SetSecurity(AccountTypes security) { _security = security; }
- std::string const& GetRemoteAddress() { return m_Address; }
+ std::string const& GetRemoteAddress() const { return m_Address; }
void SetPlayer(Player* player);
uint8 Expansion() const { return m_expansion; }
@@ -357,10 +362,9 @@ class WorldSession
AccountData* GetAccountData(AccountDataType type) { return &m_accountData[type]; }
void SetAccountData(AccountDataType type, time_t tm, std::string const& data);
void SendAccountDataTimes(uint32 mask);
- void LoadGlobalAccountData();
void LoadAccountData(PreparedQueryResult result, uint32 mask);
- void LoadTutorialsData();
+ void LoadTutorialsData(PreparedQueryResult result);
void SendTutorialsData();
void SaveTutorialsData(SQLTransaction& trans);
uint32 GetTutorialInt(uint8 index) const { return m_Tutorials[index]; }
@@ -964,6 +968,7 @@ class WorldSession
void InitializeQueryCallbackParameters();
void ProcessQueryCallbacks();
+ QueryResultHolderFuture _realmAccountLoginCallback;
PreparedQueryResultFuture _charEnumCallback;
PreparedQueryResultFuture _addIgnoreCallback;
PreparedQueryResultFuture _stablePetCallback;
@@ -1025,7 +1030,7 @@ class WorldSession
// characters who failed on Player::BuildEnumData shouldn't login
GuidSet _legitCharacters;
- uint32 m_GUIDLow; // set logined or recently logout player (while m_playerRecentlyLogout set)
+ ObjectGuid::LowType m_GUIDLow; // set logined or recently logout player (while m_playerRecentlyLogout set)
Player* _player;
std::shared_ptr<WorldSocket> m_Socket;
std::string m_Address; // Current Remote Address
@@ -1033,6 +1038,7 @@ class WorldSession
AccountTypes _security;
uint32 _accountId;
+ std::string _accountName;
uint8 m_expansion;
typedef std::list<AddonInfo> AddonsList;
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp
index cff423c71c6..1dc470744a1 100644
--- a/src/server/game/Server/WorldSocket.cpp
+++ b/src/server/game/Server/WorldSocket.cpp
@@ -19,10 +19,10 @@
#include "WorldSocket.h"
#include "BigNumber.h"
#include "Opcodes.h"
-#include "Player.h"
#include "ScriptMgr.h"
#include "SHA1.h"
#include "PacketLog.h"
+
#include <memory>
using boost::asio::ip::tcp;
@@ -35,10 +35,65 @@ WorldSocket::WorldSocket(tcp::socket&& socket)
void WorldSocket::Start()
{
+ std::string ip_address = GetRemoteIpAddress().to_string();
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_IP_INFO);
+ stmt->setString(0, ip_address);
+ stmt->setUInt32(1, inet_addr(ip_address.c_str()));
+
+ {
+ std::lock_guard<std::mutex> guard(_queryLock);
+ _queryCallback = io_service().wrap(std::bind(&WorldSocket::CheckIpCallback, this, std::placeholders::_1));
+ _queryFuture = LoginDatabase.AsyncQuery(stmt);
+ }
+}
+
+void WorldSocket::CheckIpCallback(PreparedQueryResult result)
+{
+ if (result)
+ {
+ bool banned = false;
+ do
+ {
+ Field* fields = result->Fetch();
+ if (fields[0].GetUInt64() != 0)
+ banned = true;
+
+ if (!fields[1].GetString().empty())
+ _ipCountry = fields[1].GetString();
+
+ } while (result->NextRow());
+
+ if (banned)
+ {
+ SendAuthResponseError(AUTH_REJECT);
+ TC_LOG_ERROR("network", "WorldSocket::CheckIpCallback: Sent Auth Response (IP %s banned).", GetRemoteIpAddress().to_string().c_str());
+ DelayedCloseSocket();
+ return;
+ }
+ }
+
AsyncRead();
HandleSendAuthSession();
}
+bool WorldSocket::Update()
+{
+ if (!BaseSocket::Update())
+ return false;
+
+ {
+ std::lock_guard<std::mutex> guard(_queryLock);
+ if (_queryFuture.valid() && _queryFuture.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
+ {
+ auto callback = std::move(_queryCallback);
+ _queryCallback = nullptr;
+ callback(_queryFuture.get());
+ }
+ }
+
+ return true;
+}
+
void WorldSocket::HandleSendAuthSession()
{
WorldPacket packet(SMSG_AUTH_CHALLENGE, 37);
@@ -111,13 +166,15 @@ void WorldSocket::ReadHandler()
}
// just received fresh new payload
- if (!ReadDataHandler())
+ ReadDataHandlerResult result = ReadDataHandler();
+ _headerBuffer.Reset();
+ if (result != ReadDataHandlerResult::Ok)
{
- CloseSocket();
+ if (result != ReadDataHandlerResult::WaitingForQuery)
+ CloseSocket();
+
return;
}
-
- _headerBuffer.Reset();
}
AsyncRead();
@@ -145,7 +202,72 @@ bool WorldSocket::ReadHeaderHandler()
return true;
}
-bool WorldSocket::ReadDataHandler()
+struct AuthSession
+{
+ uint32 BattlegroupID = 0;
+ uint32 LoginServerType = 0;
+ uint32 RealmID = 0;
+ uint32 Build = 0;
+ uint32 LocalChallenge = 0;
+ uint32 LoginServerID = 0;
+ uint32 RegionID = 0;
+ uint64 DosResponse = 0;
+ uint8 Digest[SHA_DIGEST_LENGTH] = {};
+ std::string Account;
+ ByteBuffer AddonInfo;
+};
+
+struct AccountInfo
+{
+ uint32 Id;
+ BigNumber SessionKey;
+ std::string LastIP;
+ bool IsLockedToIP;
+ std::string LockCountry;
+ uint8 Expansion;
+ int64 MuteTime;
+ LocaleConstant Locale;
+ uint32 Recruiter;
+ std::string OS;
+ bool IsRectuiter;
+ AccountTypes Security;
+ bool IsBanned;
+
+ explicit AccountInfo(Field* fields)
+ {
+ // 0 1 2 3 4 5 6 7 8 9 10
+ // SELECT a.id, a.sessionkey, a.last_ip, a.locked, a.lock_country, a.expansion, a.mutetime, a.locale, a.recruiter, a.os, aa.gmLevel,
+ // 11 12
+ // ab.unbandate > UNIX_TIMESTAMP() OR ab.unbandate = ab.bandate, r.id
+ // FROM account a
+ // LEFT JOIN account_access aa ON a.id = aa.id AND aa.RealmID IN (-1, ?)
+ // LEFT JOIN account_banned ab ON a.id = ab.id
+ // LEFT JOIN account r ON a.id = r.recruiter
+ // WHERE a.username = ? ORDER BY aa.RealmID DESC LIMIT 1
+ Id = fields[0].GetUInt32();
+ SessionKey.SetHexStr(fields[1].GetCString());
+ LastIP = fields[2].GetString();
+ IsLockedToIP = fields[3].GetBool();
+ LockCountry = fields[4].GetString();
+ Expansion = fields[5].GetUInt8();
+ MuteTime = fields[6].GetInt64();
+ Locale = LocaleConstant(fields[7].GetUInt8());
+ Recruiter = fields[8].GetUInt32();
+ OS = fields[9].GetString();
+ Security = AccountTypes(fields[10].GetUInt8());
+ IsBanned = fields[11].GetUInt64() != 0;
+ IsRectuiter = fields[12].GetUInt32() != 0;
+
+ uint32 world_expansion = sWorld->getIntConfig(CONFIG_EXPANSION);
+ if (Expansion > world_expansion)
+ Expansion = world_expansion;
+
+ if (Locale >= TOTAL_LOCALES)
+ Locale = LOCALE_enUS;
+ }
+};
+
+WorldSocket::ReadDataHandlerResult WorldSocket::ReadDataHandler()
{
ClientPktHeader* header = reinterpret_cast<ClientPktHeader*>(_headerBuffer.GetReadPointer());
@@ -162,7 +284,7 @@ bool WorldSocket::ReadDataHandler()
{
case CMSG_PING:
LogOpcodeText(opcode, sessionGuard);
- return HandlePing(packet);
+ return HandlePing(packet) ? ReadDataHandlerResult::Ok : ReadDataHandlerResult::Error;
case CMSG_AUTH_SESSION:
LogOpcodeText(opcode, sessionGuard);
if (_authed)
@@ -170,11 +292,11 @@ bool WorldSocket::ReadDataHandler()
// locking just to safely log offending user is probably overkill but we are disconnecting him anyway
if (sessionGuard.try_lock())
TC_LOG_ERROR("network", "WorldSocket::ProcessIncoming: received duplicate CMSG_AUTH_SESSION from %s", _worldSession->GetPlayerInfo().c_str());
- return false;
+ return ReadDataHandlerResult::Error;
}
HandleAuthSession(packet);
- break;
+ return ReadDataHandlerResult::WaitingForQuery;
case CMSG_KEEP_ALIVE:
LogOpcodeText(opcode, sessionGuard);
break;
@@ -186,7 +308,7 @@ bool WorldSocket::ReadDataHandler()
{
TC_LOG_ERROR("network.opcode", "ProcessIncoming: Client not authed opcode = %u", uint32(opcode));
CloseSocket();
- return false;
+ return ReadDataHandlerResult::Error;
}
// Our Idle timer will reset on any non PING opcodes.
@@ -199,7 +321,7 @@ bool WorldSocket::ReadDataHandler()
}
}
- return true;
+ return ReadDataHandlerResult::Ok;
}
void WorldSocket::LogOpcodeText(uint16 opcode, std::unique_lock<std::mutex> const& guard) const
@@ -256,48 +378,35 @@ void WorldSocket::SendPacket(WorldPacket const& packet)
void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
{
- uint8 digest[SHA_DIGEST_LENGTH];
- uint32 clientSeed;
- uint8 security;
- uint32 id;
- LocaleConstant locale;
- std::string account;
- SHA1Hash sha;
- uint32 clientBuild;
- uint32 serverId, loginServerType, region, battlegroup, realmIndex;
- uint64 unk4;
- WorldPacket packet, SendAddonPacked;
- BigNumber k;
- bool wardenActive = sWorld->getBoolConfig(CONFIG_WARDEN_ENABLED);
+ std::shared_ptr<AuthSession> authSession = std::make_shared<AuthSession>();
// Read the content of the packet
- recvPacket >> clientBuild;
- recvPacket >> serverId; // Used for GRUNT only
- recvPacket >> account;
- recvPacket >> loginServerType; // 0 GRUNT, 1 Battle.net
- recvPacket >> clientSeed;
- recvPacket >> region >> battlegroup; // Used for Battle.net only
- recvPacket >> realmIndex; // realmId from auth_database.realmlist table
- recvPacket >> unk4;
- recvPacket.read(digest, 20);
-
- TC_LOG_DEBUG("network", "WorldSocket::HandleAuthSession: client %u, serverId %u, account %s, loginServerType %u, clientseed %u, realmIndex %u",
- clientBuild,
- serverId,
- account.c_str(),
- loginServerType,
- clientSeed,
- realmIndex);
+ recvPacket >> authSession->Build;
+ recvPacket >> authSession->LoginServerID;
+ recvPacket >> authSession->Account;
+ recvPacket >> authSession->LoginServerType;
+ recvPacket >> authSession->LocalChallenge;
+ recvPacket >> authSession->RegionID;
+ recvPacket >> authSession->BattlegroupID;
+ recvPacket >> authSession->RealmID; // realmId from auth_database.realmlist table
+ recvPacket >> authSession->DosResponse;
+ recvPacket.read(authSession->Digest, 20);
+ authSession->AddonInfo.append(recvPacket.contents() + recvPacket.rpos(), recvPacket.size() - recvPacket.rpos());
// Get the account information from the auth database
- // 0 1 2 3 4 5 6 7 8
- // SELECT id, sessionkey, last_ip, locked, expansion, mutetime, locale, recruiter, os FROM account WHERE username = ?
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME);
+ stmt->setInt32(0, int32(realmID));
+ stmt->setString(1, authSession->Account);
- stmt->setString(0, account);
-
- PreparedQueryResult result = LoginDatabase.Query(stmt);
+ {
+ std::lock_guard<std::mutex> guard(_queryLock);
+ _queryCallback = io_service().wrap(std::bind(&WorldSocket::HandleAuthSessionCallback, this, authSession, std::placeholders::_1));
+ _queryFuture = LoginDatabase.AsyncQuery(stmt);
+ }
+}
+void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<AuthSession> authSession, PreparedQueryResult result)
+{
// Stop if the account is not found
if (!result)
{
@@ -308,32 +417,20 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
return;
}
- Field* fields = result->Fetch();
-
- uint8 expansion = fields[4].GetUInt8();
- uint32 world_expansion = sWorld->getIntConfig(CONFIG_EXPANSION);
- if (expansion > world_expansion)
- expansion = world_expansion;
+ AccountInfo account(result->Fetch());
// For hook purposes, we get Remoteaddress at this point.
std::string address = GetRemoteIpAddress().to_string();
// As we don't know if attempted login process by ip works, we update last_attempt_ip right away
- stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LAST_ATTEMPT_IP);
-
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LAST_ATTEMPT_IP);
stmt->setString(0, address);
- stmt->setString(1, account);
-
+ stmt->setString(1, authSession->Account);
LoginDatabase.Execute(stmt);
// This also allows to check for possible "hack" attempts on account
- // id has to be fetched at this point, so that first actual account response that fails can be logged
- id = fields[0].GetUInt32();
-
- k.SetHexStr(fields[1].GetCString());
-
// even if auth credentials are bad, try using the session key we have - client cannot read auth response error without it
- _authCrypt.Init(&k);
+ _authCrypt.Init(&account.SessionKey);
// First reject the connection if packet contains invalid data or realm state doesn't allow logging in
if (sWorld->IsClosed())
@@ -344,7 +441,7 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
return;
}
- if (realmIndex != realmID)
+ if (authSession->RealmID != realmID)
{
SendAuthResponseError(REALM_LIST_REALM_NOT_FOUND);
TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Sent Auth Response (bad realm).");
@@ -352,13 +449,12 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
return;
}
- std::string os = fields[8].GetString();
-
// Must be done before WorldSession is created
- if (wardenActive && os != "Win" && os != "OSX")
+ bool wardenActive = sWorld->getBoolConfig(CONFIG_WARDEN_ENABLED);
+ if (wardenActive && account.OS != "Win" && account.OS != "OSX")
{
SendAuthResponseError(AUTH_REJECT);
- TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Client %s attempted to log in using invalid client OS (%s).", address.c_str(), os.c_str());
+ TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Client %s attempted to log in using invalid client OS (%s).", address.c_str(), account.OS.c_str());
DelayedCloseSocket();
return;
}
@@ -366,135 +462,112 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
// Check that Key and account name are the same on client and server
uint32 t = 0;
- sha.UpdateData(account);
+ SHA1Hash sha;
+ sha.UpdateData(authSession->Account);
sha.UpdateData((uint8*)&t, 4);
- sha.UpdateData((uint8*)&clientSeed, 4);
+ sha.UpdateData((uint8*)&authSession->LocalChallenge, 4);
sha.UpdateData((uint8*)&_authSeed, 4);
- sha.UpdateBigNumbers(&k, NULL);
+ sha.UpdateBigNumbers(&account.SessionKey, NULL);
sha.Finalize();
- if (memcmp(sha.GetDigest(), digest, SHA_DIGEST_LENGTH) != 0)
+ if (memcmp(sha.GetDigest(), authSession->Digest, SHA_DIGEST_LENGTH) != 0)
{
SendAuthResponseError(AUTH_FAILED);
- TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Authentication failed for account: %u ('%s') address: %s", id, account.c_str(), address.c_str());
+ TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Authentication failed for account: %u ('%s') address: %s", account.Id, authSession->Account.c_str(), address.c_str());
DelayedCloseSocket();
return;
}
///- Re-check ip locking (same check as in auth).
- if (fields[3].GetUInt8() == 1) // if ip is locked
+ if (account.IsLockedToIP)
{
- if (strcmp(fields[2].GetCString(), address.c_str()) != 0)
+ if (account.LastIP != address)
{
SendAuthResponseError(AUTH_FAILED);
- TC_LOG_DEBUG("network", "WorldSocket::HandleAuthSession: Sent Auth Response (Account IP differs. Original IP: %s, new IP: %s).", fields[2].GetCString(), address.c_str());
+ TC_LOG_DEBUG("network", "WorldSocket::HandleAuthSession: Sent Auth Response (Account IP differs. Original IP: %s, new IP: %s).", account.LastIP.c_str(), address.c_str());
// We could log on hook only instead of an additional db log, however action logger is config based. Better keep DB logging as well
- sScriptMgr->OnFailedAccountLogin(id);
+ sScriptMgr->OnFailedAccountLogin(account.Id);
+ DelayedCloseSocket();
+ return;
+ }
+ }
+ else if (!account.LockCountry.empty() && account.LockCountry != "00" && !_ipCountry.empty())
+ {
+ if (account.LockCountry != _ipCountry)
+ {
+ SendAuthResponseError(AUTH_FAILED);
+ TC_LOG_DEBUG("network", "WorldSocket::HandleAuthSession: Sent Auth Response (Account country differs. Original country: %s, new country: %s).", account.LockCountry.c_str(), _ipCountry.c_str());
+ // We could log on hook only instead of an additional db log, however action logger is config based. Better keep DB logging as well
+ sScriptMgr->OnFailedAccountLogin(account.Id);
DelayedCloseSocket();
return;
}
}
- int64 mutetime = fields[5].GetInt64();
+ int64 mutetime = account.MuteTime;
//! Negative mutetime indicates amount of seconds to be muted effective on next login - which is now.
if (mutetime < 0)
{
mutetime = time(NULL) + llabs(mutetime);
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_MUTE_TIME_LOGIN);
-
stmt->setInt64(0, mutetime);
- stmt->setUInt32(1, id);
-
+ stmt->setUInt32(1, account.Id);
LoginDatabase.Execute(stmt);
}
- locale = LocaleConstant(fields[6].GetUInt8());
- if (locale >= TOTAL_LOCALES)
- locale = LOCALE_enUS;
-
- uint32 recruiter = fields[7].GetUInt32();
- // Checks gmlevel per Realm
- stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_GMLEVEL_BY_REALMID);
-
- stmt->setUInt32(0, id);
- stmt->setInt32(1, int32(realmID));
-
- result = LoginDatabase.Query(stmt);
-
- if (!result)
- security = 0;
- else
- {
- fields = result->Fetch();
- security = fields[0].GetUInt8();
- }
-
- // Re-check account ban (same check as in auth)
- stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BANS);
-
- stmt->setUInt32(0, id);
- stmt->setString(1, address);
-
- PreparedQueryResult banresult = LoginDatabase.Query(stmt);
-
- if (banresult) // if account banned
+ if (account.IsBanned)
{
SendAuthResponseError(AUTH_BANNED);
TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Sent Auth Response (Account banned).");
- sScriptMgr->OnFailedAccountLogin(id);
+ sScriptMgr->OnFailedAccountLogin(account.Id);
DelayedCloseSocket();
return;
}
// Check locked state for server
AccountTypes allowedAccountType = sWorld->GetPlayerSecurityLimit();
- TC_LOG_DEBUG("network", "Allowed Level: %u Player Level %u", allowedAccountType, AccountTypes(security));
- if (allowedAccountType > SEC_PLAYER && AccountTypes(security) < allowedAccountType)
+ TC_LOG_DEBUG("network", "Allowed Level: %u Player Level %u", allowedAccountType, account.Security);
+ if (allowedAccountType > SEC_PLAYER && account.Security < allowedAccountType)
{
SendAuthResponseError(AUTH_UNAVAILABLE);
TC_LOG_DEBUG("network", "WorldSocket::HandleAuthSession: User tries to login but his security level is not enough");
- sScriptMgr->OnFailedAccountLogin(id);
+ sScriptMgr->OnFailedAccountLogin(account.Id);
DelayedCloseSocket();
return;
}
- TC_LOG_DEBUG("network", "WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.",
- account.c_str(),
- address.c_str());
-
- // Check if this user is by any chance a recruiter
- stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_RECRUITER);
-
- stmt->setUInt32(0, id);
-
- result = LoginDatabase.Query(stmt);
-
- bool isRecruiter = false;
- if (result)
- isRecruiter = true;
+ TC_LOG_DEBUG("network", "WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.", authSession->Account.c_str(), address.c_str());
// Update the last_ip in the database as it was successful for login
stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LAST_IP);
stmt->setString(0, address);
- stmt->setString(1, account);
+ stmt->setString(1, authSession->Account);
LoginDatabase.Execute(stmt);
// At this point, we can safely hook a successful login
- sScriptMgr->OnAccountLogin(id);
+ sScriptMgr->OnAccountLogin(account.Id);
_authed = true;
- _worldSession = new WorldSession(id, shared_from_this(), AccountTypes(security), expansion, mutetime, locale, recruiter, isRecruiter);
- _worldSession->LoadGlobalAccountData();
- _worldSession->LoadTutorialsData();
- _worldSession->ReadAddonsInfo(recvPacket);
- _worldSession->LoadPermissions();
+ _worldSession = new WorldSession(account.Id, std::move(authSession->Account), shared_from_this(), account.Security,
+ account.Expansion, mutetime, account.Locale, account.Recruiter, account.IsRectuiter);
+ _worldSession->ReadAddonsInfo(authSession->AddonInfo);
// Initialize Warden system only if it is enabled by config
if (wardenActive)
- _worldSession->InitWarden(&k, os);
+ _worldSession->InitWarden(&account.SessionKey, account.OS);
+
+ _queryCallback = io_service().wrap(std::bind(&WorldSocket::LoadSessionPermissionsCallback, this, std::placeholders::_1));
+ _queryFuture = _worldSession->LoadPermissionsAsync();
+ AsyncRead();
+}
+
+void WorldSocket::LoadSessionPermissionsCallback(PreparedQueryResult result)
+{
+ // RBAC must be loaded before adding session to check for skip queue permission
+ _worldSession->GetRBACData()->LoadFromDBCallback(result);
sWorld->AddSession(_worldSession);
}
@@ -509,6 +582,8 @@ void WorldSocket::SendAuthResponseError(uint8 code)
bool WorldSocket::HandlePing(WorldPacket& recvPacket)
{
+ using namespace std::chrono;
+
uint32 ping;
uint32 latency;
diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h
index 0f6acd0d72c..f0da520cf4c 100644
--- a/src/server/game/Server/WorldSocket.h
+++ b/src/server/game/Server/WorldSocket.h
@@ -45,8 +45,12 @@ struct ClientPktHeader
#pragma pack(pop)
+struct AuthSession;
+
class WorldSocket : public Socket<WorldSocket>
{
+ typedef Socket<WorldSocket> BaseSocket;
+
public:
WorldSocket(tcp::socket&& socket);
@@ -54,6 +58,7 @@ public:
WorldSocket& operator=(WorldSocket const& right) = delete;
void Start() override;
+ bool Update() override;
void SendPacket(WorldPacket const& packet);
@@ -61,9 +66,19 @@ protected:
void OnClose() override;
void ReadHandler() override;
bool ReadHeaderHandler();
- bool ReadDataHandler();
+
+ enum class ReadDataHandlerResult
+ {
+ Ok = 0,
+ Error = 1,
+ WaitingForQuery = 2
+ };
+
+ ReadDataHandlerResult ReadDataHandler();
private:
+ void CheckIpCallback(PreparedQueryResult result);
+
/// writes network.opcode log
/// accessing WorldSession is not threadsafe, only do it when holding _worldSessionLock
void LogOpcodeText(uint16 opcode, std::unique_lock<std::mutex> const& guard) const;
@@ -71,6 +86,8 @@ private:
void SendPacketAndLogOpcode(WorldPacket const& packet);
void HandleSendAuthSession();
void HandleAuthSession(WorldPacket& recvPacket);
+ void HandleAuthSessionCallback(std::shared_ptr<AuthSession> authSession, PreparedQueryResult result);
+ void LoadSessionPermissionsCallback(PreparedQueryResult result);
void SendAuthResponseError(uint8 code);
bool HandlePing(WorldPacket& recvPacket);
@@ -87,6 +104,11 @@ private:
MessageBuffer _headerBuffer;
MessageBuffer _packetBuffer;
+
+ std::mutex _queryLock;
+ PreparedQueryResultFuture _queryFuture;
+ std::function<void(PreparedQueryResult&&)> _queryCallback;
+ std::string _ipCountry;
};
#endif
diff --git a/src/server/game/Server/WorldSocketMgr.cpp b/src/server/game/Server/WorldSocketMgr.cpp
index 86c09ef6b6b..da35017cc2b 100644
--- a/src/server/game/Server/WorldSocketMgr.cpp
+++ b/src/server/game/Server/WorldSocketMgr.cpp
@@ -21,6 +21,7 @@
#include "ScriptMgr.h"
#include "WorldSocket.h"
#include "WorldSocketMgr.h"
+
#include <boost/system/error_code.hpp>
static void OnSocketAccept(tcp::socket&& sock)
diff --git a/src/server/game/Skills/SkillExtraItems.cpp b/src/server/game/Skills/SkillExtraItems.cpp
index 8df9ce86f9a..50e00b24133 100644
--- a/src/server/game/Skills/SkillExtraItems.cpp
+++ b/src/server/game/Skills/SkillExtraItems.cpp
@@ -20,11 +20,98 @@
#include "DatabaseEnv.h"
#include "Log.h"
#include "Player.h"
+#include "ObjectMgr.h"
#include <map>
// some type definitions
// no use putting them in the header file, they're only used in this .cpp
+// struct to store information about perfection procs
+// one entry per spell
+struct SkillPerfectItemEntry
+{
+ // the spell id of the spell required - it's named "specialization" to conform with SkillExtraItemEntry
+ uint32 requiredSpecialization;
+ // perfection proc chance
+ float perfectCreateChance;
+ // itemid of the resulting perfect item
+ uint32 perfectItemType;
+
+ SkillPerfectItemEntry()
+ : requiredSpecialization(0), perfectCreateChance(0.0f), perfectItemType(0) { }
+ SkillPerfectItemEntry(uint32 rS, float pCC, uint32 pIT)
+ : requiredSpecialization(rS), perfectCreateChance(pCC), perfectItemType(pIT) { }
+};
+
+// map to store perfection info. key = spellId of the creation spell, value is the perfectitementry as specified above
+typedef std::map<uint32, SkillPerfectItemEntry> SkillPerfectItemMap;
+
+SkillPerfectItemMap SkillPerfectItemStore;
+
+// loads the perfection proc info from DB
+void LoadSkillPerfectItemTable()
+{
+ uint32 oldMSTime = getMSTime();
+
+ SkillPerfectItemStore.clear(); // reload capability
+
+ // 0 1 2 3
+ QueryResult result = WorldDatabase.Query("SELECT spellId, requiredSpecialization, perfectCreateChance, perfectItemType FROM skill_perfect_item_template");
+
+ if (!result)
+ {
+ TC_LOG_ERROR("server.loading", ">> Loaded 0 spell perfection definitions. DB table `skill_perfect_item_template` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+
+ do /* fetch data and run sanity checks */
+ {
+ Field* fields = result->Fetch();
+
+ uint32 spellId = fields[0].GetUInt32();
+
+ if (!sSpellMgr->GetSpellInfo(spellId))
+ {
+ TC_LOG_ERROR("sql.sql", "Skill perfection data for spell %u has non-existent spell id in `skill_perfect_item_template`!", spellId);
+ continue;
+ }
+
+ uint32 requiredSpecialization = fields[1].GetUInt32();
+ if (!sSpellMgr->GetSpellInfo(requiredSpecialization))
+ {
+ TC_LOG_ERROR("sql.sql", "Skill perfection data for spell %u has non-existent required specialization spell id %u in `skill_perfect_item_template`!", spellId, requiredSpecialization);
+ continue;
+ }
+
+ float perfectCreateChance = fields[2].GetFloat();
+ if (perfectCreateChance <= 0.0f)
+ {
+ TC_LOG_ERROR("sql.sql", "Skill perfection data for spell %u has impossibly low proc chance in `skill_perfect_item_template`!", spellId);
+ continue;
+ }
+
+ uint32 perfectItemType = fields[3].GetUInt32();
+ if (!sObjectMgr->GetItemTemplate(perfectItemType))
+ {
+ TC_LOG_ERROR("sql.sql", "Skill perfection data for spell %u references non-existent perfect item id %u in `skill_perfect_item_template`!", spellId, perfectItemType);
+ continue;
+ }
+
+ SkillPerfectItemEntry& skillPerfectItemEntry = SkillPerfectItemStore[spellId];
+
+ skillPerfectItemEntry.requiredSpecialization = requiredSpecialization;
+ skillPerfectItemEntry.perfectCreateChance = perfectCreateChance;
+ skillPerfectItemEntry.perfectItemType = perfectItemType;
+
+ ++count;
+ }
+ while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u spell perfection definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
// struct to store information about extra item creation
// one entry for every spell that is able to create an extra item
struct SkillExtraItemEntry
@@ -112,6 +199,30 @@ void LoadSkillExtraItemTable()
TC_LOG_INFO("server.loading", ">> Loaded %u spell specialization definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
+bool CanCreatePerfectItem(Player* player, uint32 spellId, float &perfectCreateChance, uint32 &perfectItemType)
+{
+ SkillPerfectItemMap::const_iterator ret = SkillPerfectItemStore.find(spellId);
+ // no entry in DB means no perfection proc possible
+ if (ret == SkillPerfectItemStore.end())
+ return false;
+
+ SkillPerfectItemEntry const* thisEntry = &ret->second;
+ // lack of entry means no perfection proc possible
+ if (!thisEntry)
+ return false;
+
+ // if you don't have the spell needed, then no procs for you
+ if (!player->HasSpell(thisEntry->requiredSpecialization))
+ return false;
+
+ // set values as appropriate
+ perfectCreateChance = thisEntry->perfectCreateChance;
+ perfectItemType = thisEntry->perfectItemType;
+
+ // and tell the caller to start rolling the dice
+ return true;
+}
+
bool CanCreateExtraItems(Player* player, uint32 spellId, float &additionalChance, uint8 &additionalMax)
{
// get the info for the specified spell
diff --git a/src/server/game/Skills/SkillExtraItems.h b/src/server/game/Skills/SkillExtraItems.h
index 0cdfff74ed2..118c49ed00f 100644
--- a/src/server/game/Skills/SkillExtraItems.h
+++ b/src/server/game/Skills/SkillExtraItems.h
@@ -23,6 +23,10 @@
// predef classes used in functions
class Player;
+// returns true and sets the appropriate info if the player can create a perfect item with the given spellId
+bool CanCreatePerfectItem(Player* player, uint32 spellId, float &perfectCreateChance, uint32 &perfectItemType);
+// load perfection proc info from DB
+void LoadSkillPerfectItemTable();
// returns true and sets the appropriate info if the player can create extra items with the given spellId
bool CanCreateExtraItems(Player* player, uint32 spellId, float &additionalChance, uint8 &additionalMax);
// function to load the extra item creation info from DB
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 918b000a557..01f27a38e9c 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -25,15 +25,15 @@
#include "Player.h"
#include "Unit.h"
#include "ObjectAccessor.h"
+#include "CellImpl.h"
#include "Util.h"
#include "Spell.h"
#include "SpellHistory.h"
#include "SpellAuraEffects.h"
#include "Battleground.h"
#include "OutdoorPvPMgr.h"
-#include "Formulas.h"
#include "GridNotifiers.h"
-#include "CellImpl.h"
+#include "GridNotifiersImpl.h"
#include "ScriptMgr.h"
#include "Vehicle.h"
#include "Battlefield.h"
@@ -541,10 +541,7 @@ void AuraEffect::CalculatePeriodic(Unit* caster, bool create, bool load)
{
// Haste modifies periodic time of channeled spells
if (m_spellInfo->IsChanneled())
- {
- if (m_spellInfo->HasAttribute(SPELL_ATTR5_HASTE_AFFECT_DURATION))
- caster->ModSpellCastTime(m_spellInfo, m_amplitude);
- }
+ caster->ModSpellDurationTime(m_spellInfo, m_amplitude);
// and periodic time of auras affected by SPELL_AURA_PERIODIC_HASTE
else if (caster->HasAuraTypeWithAffectMask(SPELL_AURA_PERIODIC_HASTE, m_spellInfo) || m_spellInfo->HasAttribute(SPELL_ATTR5_HASTE_AFFECT_DURATION))
m_amplitude = int32(m_amplitude * caster->GetFloatValue(UNIT_MOD_CAST_SPEED));
@@ -1134,7 +1131,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
if (!spellInfo || !(spellInfo->HasAttribute(SPELL_ATTR0_PASSIVE) || spellInfo->HasAttribute(SPELL_ATTR0_HIDDEN_CLIENTSIDE)))
continue;
- if (spellInfo->Stances & (1<<(GetMiscValue()-1)))
+ if (spellInfo->Stances & (UI64LIT(1) << (GetMiscValue() - 1)))
target->CastSpell(target, itr->first, true, NULL, this);
}
@@ -1148,7 +1145,8 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(glyph->SpellId);
if (!spellInfo || !(spellInfo->HasAttribute(SPELL_ATTR0_PASSIVE) || spellInfo->HasAttribute(SPELL_ATTR0_HIDDEN_CLIENTSIDE)))
continue;
- if (spellInfo->Stances & (1<<(GetMiscValue()-1)))
+
+ if (spellInfo->Stances & (UI64LIT(1) << (GetMiscValue() - 1)))
target->CastSpell(target, glyph->SpellId, true, NULL, this);
}
}
@@ -1158,7 +1156,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
if (target->ToPlayer()->HasSpell(17007))
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(24932);
- if (spellInfo && spellInfo->Stances & (1<<(GetMiscValue()-1)))
+ if (spellInfo && spellInfo->Stances & (UI64LIT(1) << (GetMiscValue() - 1)))
target->CastSpell(target, 24932, true, NULL, this);
}
// Improved Barkskin - apply/remove armor bonus due to shapeshift
@@ -1278,7 +1276,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
for (Unit::AuraApplicationMap::iterator itr = tAuras.begin(); itr != tAuras.end();)
{
// Use the new aura to see on what stance the target will be
- uint32 newStance = (1<<((newAura ? newAura->GetMiscValue() : 0)-1));
+ uint64 newStance = newAura ? (UI64LIT(1) << (newAura->GetMiscValue() - 1)) : 0;
// If the stances are not compatible with the spell, remove it
if (itr->second->GetBase()->IsRemovedOnShapeLost(target) && !(itr->second->GetBase()->GetSpellInfo()->Stances & newStance))
@@ -1550,7 +1548,7 @@ void AuraEffect::HandlePhase(AuraApplication const* aurApp, uint8 mode, bool app
{
newPhase = PHASEMASK_NORMAL;
if (Creature* creature = target->ToCreature())
- if (CreatureData const* data = sObjectMgr->GetCreatureData(creature->GetDBTableGUIDLow()))
+ if (CreatureData const* data = sObjectMgr->GetCreatureData(creature->GetSpawnId()))
newPhase = data->phaseMask;
}
@@ -1865,43 +1863,43 @@ void AuraEffect::HandleAuraTransform(AuraApplication const* aurApp, uint8 mode,
{
// Blood Elf
case RACE_BLOODELF:
- target->SetDisplayId(target->getGender() == GENDER_MALE ? 17829 : 17830);
+ target->SetDisplayId(target->getGender() == GENDER_FEMALE ? 17830 : 17829);
break;
// Orc
case RACE_ORC:
- target->SetDisplayId(target->getGender() == GENDER_MALE ? 10139 : 10140);
+ target->SetDisplayId(target->getGender() == GENDER_FEMALE ? 10140 : 10139);
break;
// Troll
case RACE_TROLL:
- target->SetDisplayId(target->getGender() == GENDER_MALE ? 10135 : 10134);
+ target->SetDisplayId(target->getGender() == GENDER_FEMALE ? 10134 : 10135);
break;
// Tauren
case RACE_TAUREN:
- target->SetDisplayId(target->getGender() == GENDER_MALE ? 10136 : 10147);
+ target->SetDisplayId(target->getGender() == GENDER_FEMALE ? 10147 : 10136);
break;
// Undead
case RACE_UNDEAD_PLAYER:
- target->SetDisplayId(target->getGender() == GENDER_MALE ? 10146 : 10145);
+ target->SetDisplayId(target->getGender() == GENDER_FEMALE ? 10145 : 10146);
break;
// Draenei
case RACE_DRAENEI:
- target->SetDisplayId(target->getGender() == GENDER_MALE ? 17827 : 17828);
+ target->SetDisplayId(target->getGender() == GENDER_FEMALE ? 17828 : 17827);
break;
// Dwarf
case RACE_DWARF:
- target->SetDisplayId(target->getGender() == GENDER_MALE ? 10141 : 10142);
+ target->SetDisplayId(target->getGender() == GENDER_FEMALE ? 10142 : 10141);
break;
// Gnome
case RACE_GNOME:
- target->SetDisplayId(target->getGender() == GENDER_MALE ? 10148 : 10149);
+ target->SetDisplayId(target->getGender() == GENDER_FEMALE ? 10149 : 10148);
break;
// Human
case RACE_HUMAN:
- target->SetDisplayId(target->getGender() == GENDER_MALE ? 10137 : 10138);
+ target->SetDisplayId(target->getGender() == GENDER_FEMALE ? 10138 : 10137);
break;
// Night Elf
case RACE_NIGHTELF:
- target->SetDisplayId(target->getGender() == GENDER_MALE ? 10143 : 10144);
+ target->SetDisplayId(target->getGender() == GENDER_FEMALE ? 10144 : 10143);
break;
default:
break;
@@ -2799,7 +2797,7 @@ void AuraEffect::HandleModPossessPet(AuraApplication const* aurApp, uint8 mode,
// return;
Unit* target = aurApp->GetTarget();
- if (target->GetTypeId() != TYPEID_UNIT || !target->ToCreature()->IsPet())
+ if (target->GetTypeId() != TYPEID_UNIT || !target->IsPet())
return;
Pet* pet = target->ToPet();
@@ -3020,6 +3018,10 @@ void AuraEffect::HandleModStateImmunityMask(AuraApplication const* aurApp, uint8
switch (miscVal)
{
+ case 27:
+ target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SILENCE, apply);
+ aura_immunity_list.push_back(SPELL_AURA_MOD_SILENCE);
+ break;
case 96:
case 1615:
{
@@ -3460,7 +3462,7 @@ void AuraEffect::HandleAuraModResistance(AuraApplication const* aurApp, uint8 mo
if (GetMiscValue() & int32(1<<x))
{
target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(GetAmount()), apply);
- if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->IsPet())
+ if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet())
target->ApplyResistanceBuffModsMod(SpellSchools(x), GetAmount() > 0, (float)GetAmount(), apply);
}
}
@@ -3477,7 +3479,7 @@ void AuraEffect::HandleAuraModBaseResistancePCT(AuraApplication const* aurApp, u
if (target->GetTypeId() != TYPEID_PLAYER)
{
//pets only have base armor
- if (target->ToCreature()->IsPet() && (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL))
+ if (target->IsPet() && (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL))
target->HandleStatModifier(UNIT_MOD_ARMOR, BASE_PCT, float(GetAmount()), apply);
}
else
@@ -3514,7 +3516,7 @@ void AuraEffect::HandleModResistancePercent(AuraApplication const* aurApp, uint8
}
}
target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(GetAmount()), apply);
- if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->IsPet())
+ if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet())
{
target->ApplyResistanceBuffModsPercentMod(SpellSchools(i), true, (float)GetAmount(), apply);
target->ApplyResistanceBuffModsPercentMod(SpellSchools(i), false, (float)GetAmount(), apply);
@@ -3534,7 +3536,7 @@ void AuraEffect::HandleModBaseResistance(AuraApplication const* aurApp, uint8 mo
if (target->GetTypeId() != TYPEID_PLAYER)
{
//only pets have base stats
- if (target->ToCreature()->IsPet() && (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL))
+ if (target->IsPet() && (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL))
target->HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(GetAmount()), apply);
}
else
@@ -3591,13 +3593,13 @@ void AuraEffect::HandleAuraModStat(AuraApplication const* aurApp, uint8 mode, bo
if (spellGroupVal)
{
target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(spellGroupVal), !apply);
- if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->IsPet())
+ if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet())
target->ApplyStatBuffMod(Stats(i), float(spellGroupVal), !apply);
}
//target->ApplyStatMod(Stats(i), m_amount, apply);
target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(GetAmount()), apply);
- if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->IsPet())
+ if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet())
target->ApplyStatBuffMod(Stats(i), (float)GetAmount(), apply);
}
}
@@ -3724,7 +3726,7 @@ void AuraEffect::HandleModTotalPercentStat(AuraApplication const* aurApp, uint8
if (GetMiscValue() == i || GetMiscValue() == -1) // affect the same stats
{
target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(spellGroupVal), !apply);
- if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->IsPet())
+ if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet())
target->ApplyStatPercentBuffMod(Stats(i), float(spellGroupVal), !apply);
}
}
@@ -3745,12 +3747,12 @@ void AuraEffect::HandleModTotalPercentStat(AuraApplication const* aurApp, uint8
if (spellGroupVal2)
{
target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(spellGroupVal2), !apply);
- if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->IsPet())
+ if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet())
target->ApplyStatPercentBuffMod(Stats(i), float(spellGroupVal2), !apply);
}
target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(GetAmount()), apply);
- if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->IsPet())
+ if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet())
target->ApplyStatPercentBuffMod(Stats(i), float(GetAmount()), apply);
}
}
@@ -4641,17 +4643,10 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
{
if (caster)
{
- switch (caster->getGender())
- {
- case GENDER_FEMALE:
- caster->CastSpell(target, 37095, true, NULL, this); // Blood Elf Disguise
- break;
- case GENDER_MALE:
- caster->CastSpell(target, 37093, true, NULL, this);
- break;
- default:
- break;
- }
+ if (caster->getGender() == GENDER_FEMALE)
+ caster->CastSpell(target, 37095, true, NULL, this); // Blood Elf Disguise
+ else
+ caster->CastSpell(target, 37093, true, NULL, this);
}
break;
}
@@ -4681,15 +4676,10 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
case 46354: // Blood Elf Illusion
if (caster)
{
- switch (caster->getGender())
- {
- case GENDER_FEMALE:
- caster->CastSpell(target, 46356, true, NULL, this);
- break;
- case GENDER_MALE:
- caster->CastSpell(target, 46355, true, NULL, this);
- break;
- }
+ if (caster->getGender() == GENDER_FEMALE)
+ caster->CastSpell(target, 46356, true, NULL, this);
+ else
+ caster->CastSpell(target, 46355, true, NULL, this);
}
break;
case 46361: // Reinforced Net
@@ -5572,7 +5562,7 @@ void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster)
case 31347:
{
target->CastSpell(target, 31350, true, NULL, this);
- target->Kill(target);
+ target->KillSelf();
return;
}
// Spellcloth
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index 5479dcdbf00..93b8c3eb368 100644
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -323,7 +323,7 @@ Aura* Aura::Create(SpellInfo const* spellproto, uint8 effMask, WorldObject* owne
aura = new DynObjAura(spellproto, effMask, owner, caster, baseAmount, castItem, casterGUID);
break;
default:
- ASSERT(false);
+ ABORT();
return NULL;
}
// aura can be removed in Unit::_AddAura call
@@ -436,8 +436,8 @@ void Aura::_UnapplyForTarget(Unit* target, Unit* caster, AuraApplication * auraA
if (itr == m_applications.end())
{
TC_LOG_ERROR("spells", "Aura::_UnapplyForTarget, target:%u, caster:%u, spell:%u was not found in owners application map!",
- target->GetGUIDLow(), caster ? caster->GetGUIDLow() : 0, auraApp->GetBase()->GetSpellInfo()->Id);
- ASSERT(false);
+ target->GetGUID().GetCounter(), caster ? caster->GetGUID().GetCounter() : 0, auraApp->GetBase()->GetSpellInfo()->Id);
+ ABORT();
}
// aura has to be already applied
@@ -528,7 +528,7 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply)
else
{
// ok, we have one unit twice in target map (impossible, but...)
- ASSERT(false);
+ ABORT();
}
}
@@ -586,7 +586,7 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply)
TC_LOG_FATAL("spells", "Aura %u: Owner %s (map %u) is not in the same map as target %s (map %u).", GetSpellInfo()->Id,
GetOwner()->GetName().c_str(), GetOwner()->IsInWorld() ? GetOwner()->GetMap()->GetId() : uint32(-1),
itr->first->GetName().c_str(), itr->first->IsInWorld() ? itr->first->GetMap()->GetId() : uint32(-1));
- ASSERT(false);
+ ABORT();
}
itr->first->_CreateAuraApplication(this, itr->second);
++itr;
@@ -1022,9 +1022,6 @@ void Aura::UnregisterSingleTarget()
{
ASSERT(m_isSingleTarget);
Unit* caster = GetCaster();
- /// @todo find a better way to do this.
- if (!caster)
- caster = ObjectAccessor::GetObjectInOrOutOfWorld(GetCasterGUID(), (Unit*)NULL);
ASSERT(caster);
caster->GetSingleCastAuras().remove(this);
SetIsSingleTarget(false);
@@ -1305,6 +1302,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
if (AuraEffect const* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 3790, 1))
{
uint32 damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), GetEffect(0)->GetAmount(), DOT);
+ damage *= caster->SpellDamagePctDone(target, GetSpellInfo(), SPELL_DIRECT_DAMAGE);
damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT);
int32 basepoints0 = aurEff->GetAmount() * GetEffect(0)->GetTotalTicks() * int32(damage) / 100;
int32 heal = int32(CalculatePct(basepoints0, 15));
@@ -1418,16 +1416,6 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
default:
break;
}
- if (!caster)
- break;
- // Ice barrier - dispel/absorb remove
- if (removeMode == AURA_REMOVE_BY_ENEMY_SPELL && GetSpellInfo()->SpellFamilyFlags[1] & 0x1)
- {
- // Shattered Barrier
- if (AuraEffect* dummy = caster->GetDummyAuraEffect(SPELLFAMILY_MAGE, 2945, 0))
- if (roll_chance_i(dummy->GetSpellInfo()->ProcChance))
- caster->CastSpell(target, 55080, true, NULL, GetEffect(0));
- }
break;
case SPELLFAMILY_WARRIOR:
if (!caster)
@@ -1499,7 +1487,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
{
// This additional check is needed to add a minimal delay before cooldown in in effect
// to allow all bubbles broken by a single damage source proc mana return
- if (caster->GetSpellHistory()->GetRemainingCooldown(aura->GetId()) <= 11)
+ if (caster->GetSpellHistory()->GetRemainingCooldown(aura->GetSpellInfo()) <= 11)
break;
}
else // and add if needed
@@ -1932,9 +1920,7 @@ bool Aura::IsProcTriggeredOnEvent(AuraApplication* aurApp, ProcEventInfo& eventI
return false;
// do checks using conditions table
- ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_PROC, GetId());
- ConditionSourceInfo condInfo = ConditionSourceInfo(eventInfo.GetActor(), eventInfo.GetActionTarget());
- if (!sConditionMgr->IsObjectMeetToConditions(condInfo, conditions))
+ if (!sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_SPELL_PROC, GetId(), eventInfo.GetActor(), eventInfo.GetActionTarget()))
return false;
// AuraScript Hook
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 94bb90487bc..4f3b60d6f37 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -53,6 +53,7 @@
#include "SpellHistory.h"
#include "Battlefield.h"
#include "BattlefieldMgr.h"
+#include "TradeData.h"
extern pEffect SpellEffects[TOTAL_SPELL_EFFECTS];
@@ -210,10 +211,10 @@ ObjectGuid SpellCastTargets::GetOrigUnitTargetGUID() const
{
switch (m_origObjectTargetGUID.GetHigh())
{
- case HIGHGUID_PLAYER:
- case HIGHGUID_VEHICLE:
- case HIGHGUID_UNIT:
- case HIGHGUID_PET:
+ case HighGuid::Player:
+ case HighGuid::Vehicle:
+ case HighGuid::Unit:
+ case HighGuid::Pet:
return m_origObjectTargetGUID;
default:
return ObjectGuid();
@@ -728,7 +729,7 @@ void Spell::SelectExplicitTargets()
{
// check for explicit target redirection, for Grounding Totem for example
if (m_spellInfo->GetExplicitTargetMask() & TARGET_FLAG_UNIT_ENEMY
- || (m_spellInfo->GetExplicitTargetMask() & TARGET_FLAG_UNIT && !m_spellInfo->IsPositive()))
+ || (m_spellInfo->GetExplicitTargetMask() & TARGET_FLAG_UNIT && !m_caster->IsFriendlyTo(target)))
{
Unit* redirect;
switch (m_spellInfo->DmgClass)
@@ -1019,7 +1020,7 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar
break;
}
- ConditionList* condList = m_spellInfo->Effects[effIndex].ImplicitTargetConditions;
+ ConditionContainer* condList = m_spellInfo->Effects[effIndex].ImplicitTargetConditions;
// handle emergency case - try to use other provided targets if no conditions provided
if (targetType.GetCheckType() == TARGET_CHECK_ENTRY && (!condList || condList->empty()))
@@ -1066,8 +1067,8 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar
{
case TARGET_OBJECT_TYPE_UNIT:
{
- if (Unit* unitTarget = target->ToUnit())
- AddUnitTarget(unitTarget, effMask, true, false);
+ if (Unit* unit = target->ToUnit())
+ AddUnitTarget(unit, effMask, true, false);
else
{
TC_LOG_DEBUG("spells", "Spell::SelectImplicitNearbyTargets: OnObjectTargetSelect script hook for spell Id %u set object of wrong type, expected unit, got %s, effect %u", m_spellInfo->Id, target->GetGUID().GetTypeName(), effMask);
@@ -1105,7 +1106,7 @@ void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTarge
std::list<WorldObject*> targets;
SpellTargetObjectTypes objectType = targetType.GetObjectType();
SpellTargetCheckTypes selectionType = targetType.GetCheckType();
- ConditionList* condList = m_spellInfo->Effects[effIndex].ImplicitTargetConditions;
+ ConditionContainer* condList = m_spellInfo->Effects[effIndex].ImplicitTargetConditions;
float coneAngle = float(M_PI) / 2;
float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster) * m_spellValue->RadiusMod;
@@ -1132,8 +1133,8 @@ void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTarge
for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
{
- if (Unit* unitTarget = (*itr)->ToUnit())
- AddUnitTarget(unitTarget, effMask, false);
+ if (Unit* unit = (*itr)->ToUnit())
+ AddUnitTarget(unit, effMask, false);
else if (GameObject* gObjTarget = (*itr)->ToGameObject())
AddGOTarget(gObjTarget, effMask);
}
@@ -1213,8 +1214,8 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge
for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
{
- if (Unit* unitTarget = (*itr)->ToUnit())
- AddUnitTarget(unitTarget, effMask, false, true, center);
+ if (Unit* unit = (*itr)->ToUnit())
+ AddUnitTarget(unit, effMask, false, true, center);
else if (GameObject* gObjTarget = (*itr)->ToGameObject())
AddGOTarget(gObjTarget, effMask);
}
@@ -1415,7 +1416,7 @@ void Spell::SelectImplicitCasterObjectTargets(SpellEffIndex effIndex, SpellImpli
case TARGET_UNIT_PASSENGER_5:
case TARGET_UNIT_PASSENGER_6:
case TARGET_UNIT_PASSENGER_7:
- if (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->ToCreature()->IsVehicle())
+ if (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->IsVehicle())
target = m_caster->GetVehicleKit()->GetPassenger(targetType.GetTarget() - TARGET_UNIT_PASSENGER_0);
break;
default:
@@ -1472,8 +1473,8 @@ void Spell::SelectImplicitChainTargets(SpellEffIndex effIndex, SpellImplicitTarg
CallScriptObjectAreaTargetSelectHandlers(targets, effIndex, targetType);
for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
- if (Unit* unitTarget = (*itr)->ToUnit())
- AddUnitTarget(unitTarget, effMask, false);
+ if (Unit* unit = (*itr)->ToUnit())
+ AddUnitTarget(unit, effMask, false);
}
}
@@ -1528,12 +1529,12 @@ void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex)
if (m_spellInfo->CheckTarget(m_caster, *itr, true) != SPELL_CAST_OK)
continue;
- if (Unit* unitTarget = (*itr)->ToUnit())
+ if (Unit* unit = (*itr)->ToUnit())
{
- if (m_caster == *itr || m_caster->IsOnVehicle(unitTarget) || unitTarget->GetVehicle())
+ if (m_caster == *itr || m_caster->IsOnVehicle(unit) || unit->GetVehicle())
continue;
- if (Creature* creatureTarget = unitTarget->ToCreature())
+ if (Creature* creatureTarget = unit->ToCreature())
{
if (!(creatureTarget->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_PROJECTILE_COLLISION))
continue;
@@ -1682,8 +1683,8 @@ void Spell::SelectEffectTypeImplicitTargets(uint8 effIndex)
// player which not released his spirit is Unit, but target flag for it is TARGET_FLAG_CORPSE_MASK
if (targetMask & (TARGET_FLAG_UNIT_MASK | TARGET_FLAG_CORPSE_MASK))
{
- if (Unit* unitTarget = m_targets.GetUnitTarget())
- target = unitTarget;
+ if (Unit* unit = m_targets.GetUnitTarget())
+ target = unit;
else if (targetMask & TARGET_FLAG_CORPSE_MASK)
{
if (Corpse* corpseTarget = m_targets.GetCorpseTarget())
@@ -1698,8 +1699,8 @@ void Spell::SelectEffectTypeImplicitTargets(uint8 effIndex)
}
if (targetMask & TARGET_FLAG_ITEM_MASK)
{
- if (Item* itemTarget = m_targets.GetItemTarget())
- AddItemTarget(itemTarget, 1 << effIndex);
+ if (Item* item = m_targets.GetItemTarget())
+ AddItemTarget(item, 1 << effIndex);
return;
}
if (targetMask & TARGET_FLAG_GAMEOBJECT_MASK)
@@ -1725,7 +1726,7 @@ void Spell::SelectEffectTypeImplicitTargets(uint8 effIndex)
}
}
-uint32 Spell::GetSearcherTypeMask(SpellTargetObjectTypes objType, ConditionList* condList)
+uint32 Spell::GetSearcherTypeMask(SpellTargetObjectTypes objType, ConditionContainer* condList)
{
// this function selects which containers need to be searched for spell target
uint32 retMask = GRID_MAP_TYPE_MASK_ALL;
@@ -1793,7 +1794,7 @@ void Spell::SearchTargets(SEARCHER& searcher, uint32 containerMask, Unit* refere
}
}
-WorldObject* Spell::SearchNearbyTarget(float range, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionList* condList)
+WorldObject* Spell::SearchNearbyTarget(float range, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionContainer* condList)
{
WorldObject* target = NULL;
uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList);
@@ -1805,7 +1806,7 @@ WorldObject* Spell::SearchNearbyTarget(float range, SpellTargetObjectTypes objec
return target;
}
-void Spell::SearchAreaTargets(std::list<WorldObject*>& targets, float range, Position const* position, Unit* referer, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionList* condList)
+void Spell::SearchAreaTargets(std::list<WorldObject*>& targets, float range, Position const* position, Unit* referer, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionContainer* condList)
{
uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList);
if (!containerTypeMask)
@@ -1815,7 +1816,7 @@ void Spell::SearchAreaTargets(std::list<WorldObject*>& targets, float range, Pos
SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellAreaTargetCheck> > (searcher, containerTypeMask, m_caster, position, range);
}
-void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTargets, WorldObject* target, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectType, ConditionList* condList, bool isChainHeal)
+void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTargets, WorldObject* target, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectType, ConditionContainer* condList, bool isChainHeal)
{
// max dist for jump target selection
float jumpRadius = 0.0f;
@@ -1876,10 +1877,10 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar
uint32 maxHPDeficit = 0;
for (std::list<WorldObject*>::iterator itr = tempTargets.begin(); itr != tempTargets.end(); ++itr)
{
- if (Unit* unitTarget = (*itr)->ToUnit())
+ if (Unit* unit = (*itr)->ToUnit())
{
- uint32 deficit = unitTarget->GetMaxHealth() - unitTarget->GetHealth();
- if ((deficit > maxHPDeficit || foundItr == tempTargets.end()) && target->IsWithinDist(unitTarget, jumpRadius) && target->IsWithinLOSInMap(unitTarget))
+ uint32 deficit = unit->GetMaxHealth() - unit->GetHealth();
+ if ((deficit > maxHPDeficit || foundItr == tempTargets.end()) && target->IsWithinDist(unit, jumpRadius) && target->IsWithinLOSInMap(unit))
{
foundItr = itr;
maxHPDeficit = deficit;
@@ -1995,7 +1996,7 @@ void Spell::prepareDataForTriggerSystem(AuraEffect const* /*triggeredByAura*/)
m_procEx |= PROC_EX_INTERNAL_TRIGGERED;
}
// Totem casts require spellfamilymask defined in spell_proc_event to proc
- if (m_originalCaster && m_caster != m_originalCaster && m_caster->GetTypeId() == TYPEID_UNIT && m_caster->ToCreature()->IsTotem() && m_caster->IsControlledByPlayer())
+ if (m_originalCaster && m_caster != m_originalCaster && m_caster->GetTypeId() == TYPEID_UNIT && m_caster->IsTotem() && m_caster->IsControlledByPlayer())
m_procEx |= PROC_EX_INTERNAL_REQ_FAMILY;
}
@@ -2218,6 +2219,9 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
uint8 mask = target->effectMask;
Unit* unit = m_caster->GetGUID() == target->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, target->targetGUID);
+ if (!unit && !target->targetGUID.IsPlayer()) // only players may be targeted across maps
+ return;
+
if (!unit)
{
uint8 farMask = 0;
@@ -2230,7 +2234,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
if (!farMask)
return;
// find unit in world
- unit = ObjectAccessor::FindUnit(target->targetGUID);
+ unit = ObjectAccessor::FindPlayer(target->targetGUID);
if (!unit)
return;
@@ -2425,9 +2429,8 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
{
m_caster->CombatStart(unit, !m_spellInfo->HasAttribute(SPELL_ATTR3_NO_INITIAL_AGGRO));
- if (m_spellInfo->HasAttribute(SPELL_ATTR0_CU_AURA_CC))
- if (!unit->IsStandState())
- unit->SetStandState(UNIT_STAND_STATE_STAND);
+ if (!unit->IsStandState())
+ unit->SetStandState(UNIT_STAND_STATE_STAND);
}
if (spellHitTarget)
@@ -2511,8 +2514,8 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA
if (m_caster->_IsValidAttackTarget(unit, m_spellInfo))
{
unit->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_HITBYSPELL);
- /// @todo This is a hack. But we do not know what types of stealth should be interrupted by CC
- if (m_spellInfo->HasAttribute(SPELL_ATTR0_CU_AURA_CC) && unit->IsControlledByPlayer())
+
+ if (!m_spellInfo->HasAttribute(SPELL_ATTR0_CU_DONT_BREAK_STEALTH))
unit->RemoveAurasByType(SPELL_AURA_MOD_STEALTH);
}
else if (m_caster->IsFriendlyTo(unit))
@@ -2621,7 +2624,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA
// Haste modifies duration of channeled spells
if (m_spellInfo->IsChanneled())
- m_originalCaster->ModSpellCastTime(aurSpellInfo, duration, this);
+ m_originalCaster->ModSpellDurationTime(aurSpellInfo, duration, this);
// and duration of auras affected by SPELL_AURA_PERIODIC_HASTE
else if (m_originalCaster->HasAuraTypeWithAffectMask(SPELL_AURA_PERIODIC_HASTE, aurSpellInfo) || m_spellInfo->HasAttribute(SPELL_ATTR5_HASTE_AFFECT_DURATION))
duration = int32(duration * m_originalCaster->GetFloatValue(UNIT_MOD_CAST_SPEED));
@@ -2901,6 +2904,14 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered
triggeredByAura->GetBase()->SetDuration(0);
}
+ if (m_caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ m_caster->ToPlayer()->RestoreSpellMods(this);
+ // cleanup after mod system
+ // triggered spell pointer can be not removed in some cases
+ m_caster->ToPlayer()->SetSpellModTakingSpell(this, false);
+ }
+
SendCastResult(result);
finish(false);
@@ -3247,7 +3258,7 @@ void Spell::handle_immediate()
modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
// Apply haste mods
- m_caster->ModSpellCastTime(m_spellInfo, duration, this);
+ m_caster->ModSpellDurationTime(m_spellInfo, duration, this);
m_spellState = SPELL_STATE_CASTING;
m_caster->AddInterruptMask(m_spellInfo->ChannelInterruptFlags);
@@ -3420,7 +3431,7 @@ void Spell::_handle_finish_phase()
if (m_caster->m_extraAttacks && m_spellInfo->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS))
{
- if (Unit* victim = ObjectAccessor::FindUnit(m_targets.GetOrigUnitTargetGUID()))
+ if (Unit* victim = ObjectAccessor::GetUnit(*m_caster, m_targets.GetOrigUnitTargetGUID()))
m_caster->HandleProcExtraAttackFor(victim);
else
m_caster->m_extraAttacks = 0;
@@ -3542,14 +3553,14 @@ void Spell::finish(bool ok)
if (!ok)
return;
- if (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->ToCreature()->IsSummon())
+ if (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->IsSummon())
{
// Unsummon statue
uint32 spell = m_caster->GetUInt32Value(UNIT_CREATED_BY_SPELL);
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell);
if (spellInfo && spellInfo->SpellIconID == 2056)
{
- TC_LOG_DEBUG("spells", "Statue %d is unsummoned in spell %d finish", m_caster->GetGUIDLow(), m_spellInfo->Id);
+ TC_LOG_DEBUG("spells", "Statue %d is unsummoned in spell %d finish", m_caster->GetGUID().GetCounter(), m_spellInfo->Id);
m_caster->setDeathState(JUST_DIED);
return;
}
@@ -3754,6 +3765,10 @@ void Spell::SendSpellStart()
//TC_LOG_DEBUG("spells", "Sending SMSG_SPELL_START id=%u", m_spellInfo->Id);
uint32 castFlags = CAST_FLAG_UNKNOWN_2;
+ uint32 schoolImmunityMask = m_caster->GetSchoolImmunityMask();
+ uint32 mechanicImmunityMask = m_caster->GetMechanicImmunityMask();
+ if (schoolImmunityMask || mechanicImmunityMask)
+ castFlags |= CAST_FLAG_IMMUNITY;
if ((IsTriggered() && !m_spellInfo->IsAutoRepeatRangedSpell()) || m_triggeredByAuraSpell)
castFlags |= CAST_FLAG_PENDING;
@@ -3761,7 +3776,7 @@ void Spell::SendSpellStart()
if (m_spellInfo->HasAttribute(SPELL_ATTR0_REQ_AMMO))
castFlags |= CAST_FLAG_AMMO;
if ((m_caster->GetTypeId() == TYPEID_PLAYER ||
- (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->ToCreature()->IsPet()))
+ (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->IsPet()))
&& m_spellInfo->PowerType != POWER_HEALTH)
castFlags |= CAST_FLAG_POWER_LEFT_SELF;
@@ -3788,10 +3803,10 @@ void Spell::SendSpellStart()
if (castFlags & CAST_FLAG_AMMO)
WriteAmmoToPacket(&data);
- if (castFlags & CAST_FLAG_UNKNOWN_23)
+ if (castFlags & CAST_FLAG_IMMUNITY)
{
- data << uint32(0);
- data << uint32(0);
+ data << uint32(schoolImmunityMask);
+ data << uint32(mechanicImmunityMask);
}
m_caster->SendMessageToSet(&data, true);
@@ -3815,7 +3830,7 @@ void Spell::SendSpellGo()
castFlags |= CAST_FLAG_AMMO; // arrows/bullets visual
if ((m_caster->GetTypeId() == TYPEID_PLAYER ||
- (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->ToCreature()->IsPet()))
+ (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->IsPet()))
&& m_spellInfo->PowerType != POWER_HEALTH)
castFlags |= CAST_FLAG_POWER_LEFT_SELF; // should only be sent to self, but the current messaging doesn't make that possible
@@ -4229,7 +4244,7 @@ void Spell::TakeCastItem()
{
// This code is to avoid a crash
// I'm not sure, if this is really an error, but I guess every item needs a prototype
- TC_LOG_ERROR("spells", "Cast item has no item prototype highId=%d, lowId=%d", m_CastItem->GetGUIDHigh(), m_CastItem->GetGUIDLow());
+ TC_LOG_ERROR("spells", "Cast item has no item prototype %s", m_CastItem->GetGUID().ToString().c_str());
return;
}
@@ -4238,7 +4253,7 @@ void Spell::TakeCastItem()
for (int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
{
- if (proto->Spells[i].SpellId)
+ if (proto->Spells[i].SpellId > 0)
{
// item has limited charges
if (proto->Spells[i].SpellCharges)
@@ -4439,8 +4454,11 @@ void Spell::TakeRunePower(bool didHit)
modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, runeCost[i], this);
}
+ // Let's say we use a skill that requires a Frost rune. This is the order:
+ // - Frost rune
+ // - Death rune, originally a Frost rune
+ // - Death rune, any kind
runeCost[RUNE_DEATH] = 0; // calculated later
-
for (uint32 i = 0; i < MAX_RUNES; ++i)
{
RuneType rune = player->GetCurrentRune(i);
@@ -4452,8 +4470,32 @@ void Spell::TakeRunePower(bool didHit)
}
}
+ // Find a Death rune where the base rune matches the one we need
runeCost[RUNE_DEATH] = runeCost[RUNE_BLOOD] + runeCost[RUNE_UNHOLY] + runeCost[RUNE_FROST];
+ if (runeCost[RUNE_DEATH] > 0)
+ {
+ for (uint32 i = 0; i < MAX_RUNES; ++i)
+ {
+ RuneType rune = player->GetCurrentRune(i);
+ RuneType baseRune = player->GetBaseRune(i);
+ if (!player->GetRuneCooldown(i) && rune == RUNE_DEATH && runeCost[baseRune] > 0)
+ {
+ player->SetRuneCooldown(i, didHit ? player->GetRuneBaseCooldown(i) : uint32(RUNE_MISS_COOLDOWN), true);
+ player->SetLastUsedRune(rune);
+ runeCost[baseRune]--;
+ runeCost[rune]--;
+
+ // keep Death Rune type if missed
+ if (didHit)
+ player->RestoreBaseRune(i);
+
+ if (runeCost[RUNE_DEATH] == 0)
+ break;
+ }
+ }
+ }
+ // Grab any Death rune
if (runeCost[RUNE_DEATH] > 0)
{
for (uint32 i = 0; i < MAX_RUNES; ++i)
@@ -4626,7 +4668,7 @@ SpellCastResult Spell::CheckCast(bool strict)
return SPELL_FAILED_NOT_READY;
}
- if (!m_caster->GetSpellHistory()->IsReady(m_spellInfo))
+ if (!m_caster->GetSpellHistory()->IsReady(m_spellInfo, m_castItemEntry))
{
if (m_triggeredByAuraSpell)
return SPELL_FAILED_DONT_REPORT;
@@ -4747,10 +4789,8 @@ SpellCastResult Spell::CheckCast(bool strict)
// check spell cast conditions from database
{
- ConditionSourceInfo condInfo = ConditionSourceInfo(m_caster);
- condInfo.mConditionTargets[1] = m_targets.GetObjectTarget();
- ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL, m_spellInfo->Id);
- if (!conditions.empty() && !sConditionMgr->IsObjectMeetToConditions(condInfo, conditions))
+ ConditionSourceInfo condInfo = ConditionSourceInfo(m_caster, m_targets.GetObjectTarget());
+ if (!sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_SPELL, m_spellInfo->Id, condInfo))
{
// mLastFailedCondition can be NULL if there was an error processing the condition in Condition::Meets (i.e. wrong data for ConditionTarget or others)
if (condInfo.mLastFailedCondition && condInfo.mLastFailedCondition->ErrorType)
@@ -4972,12 +5012,12 @@ SpellCastResult Spell::CheckCast(bool strict)
case SPELL_EFFECT_LEARN_PET_SPELL:
{
// check target only for unit target case
- if (Unit* unitTarget = m_targets.GetUnitTarget())
+ if (Unit* unit = m_targets.GetUnitTarget())
{
if (m_caster->GetTypeId() != TYPEID_PLAYER)
return SPELL_FAILED_BAD_TARGETS;
- Pet* pet = unitTarget->ToPet();
+ Pet* pet = unit->ToPet();
if (!pet || pet->GetOwner() != m_caster)
return SPELL_FAILED_BAD_TARGETS;
@@ -5057,15 +5097,16 @@ SpellCastResult Spell::CheckCast(bool strict)
m_preGeneratedPath.SetPathLengthLimit(range);
// first try with raycast, if it fails fall back to normal path
- bool result = m_preGeneratedPath.CalculatePath(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ() + target->GetObjectSize(), false, true);
+ float targetObjectSize = std::min(target->GetObjectSize(), 4.0f);
+ bool result = m_preGeneratedPath.CalculatePath(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ() + targetObjectSize, false, true);
if (m_preGeneratedPath.GetPathType() & PATHFIND_SHORT)
return SPELL_FAILED_OUT_OF_RANGE;
- else if (!result || m_preGeneratedPath.GetPathType() & PATHFIND_NOPATH)
+ else if (!result || m_preGeneratedPath.GetPathType() & (PATHFIND_NOPATH | PATHFIND_INCOMPLETE))
{
- result = m_preGeneratedPath.CalculatePath(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ() + target->GetObjectSize(), false, false);
+ result = m_preGeneratedPath.CalculatePath(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ() + targetObjectSize, false, false);
if (m_preGeneratedPath.GetPathType() & PATHFIND_SHORT)
return SPELL_FAILED_OUT_OF_RANGE;
- else if (!result || m_preGeneratedPath.GetPathType() & PATHFIND_NOPATH)
+ else if (!result || m_preGeneratedPath.GetPathType() & (PATHFIND_NOPATH | PATHFIND_INCOMPLETE))
return SPELL_FAILED_NOPATH;
}
@@ -5347,7 +5388,7 @@ SpellCastResult Spell::CheckCast(bool strict)
if (Unit* target = m_targets.GetUnitTarget())
{
- if (target->GetTypeId() == TYPEID_UNIT && target->ToCreature()->IsVehicle())
+ if (target->GetTypeId() == TYPEID_UNIT && target->IsVehicle())
return SPELL_FAILED_BAD_IMPLICIT_TARGETS;
if (target->IsMounted())
@@ -5359,8 +5400,8 @@ SpellCastResult Spell::CheckCast(bool strict)
if (target->GetOwner() && target->GetOwner()->GetTypeId() == TYPEID_PLAYER)
return SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED;
- int32 damage = CalculateDamage(i, target);
- if (damage && int32(target->getLevel()) > damage)
+ int32 value = CalculateDamage(i, target);
+ if (value && int32(target->getLevel()) > value)
return SPELL_FAILED_HIGHLEVEL;
}
@@ -6003,7 +6044,7 @@ SpellCastResult Spell::CheckItems()
for (uint8 e = 0; e < MAX_ITEM_PROTO_SPELLS; ++e)
{
ItemTemplate const* proto = targetItem->GetTemplate();
- if (proto->Spells[e].SpellId && (
+ if (proto->Spells[e].SpellId > 0 && (
proto->Spells[e].SpellTrigger == ITEM_SPELLTRIGGER_ON_USE ||
proto->Spells[e].SpellTrigger == ITEM_SPELLTRIGGER_ON_NO_DELAY_USE))
{
@@ -6432,8 +6473,8 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff, Position const* lo
return false;
if (target->GetCharmerGUID())
return false;
- if (int32 damage = CalculateDamage(eff, target))
- if ((int32)target->getLevel() > damage)
+ if (int32 value = CalculateDamage(eff, target))
+ if ((int32)target->getLevel() > value)
return false;
break;
default:
@@ -6545,8 +6586,8 @@ SpellEvent::~SpellEvent()
else
{
TC_LOG_ERROR("spells", "~SpellEvent: %s %u tried to delete non-deletable spell %u. Was not deleted, causes memory leak.",
- (m_Spell->GetCaster()->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature"), m_Spell->GetCaster()->GetGUIDLow(), m_Spell->m_spellInfo->Id);
- ASSERT(false);
+ (m_Spell->GetCaster()->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature"), m_Spell->GetCaster()->GetGUID().GetCounter(), m_Spell->m_spellInfo->Id);
+ ABORT();
}
}
@@ -7004,7 +7045,7 @@ bool Spell::CallScriptEffectHandlers(SpellEffIndex effIndex, SpellEffectHandleMo
hookType = SPELL_SCRIPT_HOOK_EFFECT_HIT_TARGET;
break;
default:
- ASSERT(false);
+ ABORT();
return false;
}
(*scritr)->_PrepareScriptCall(hookType);
@@ -7272,7 +7313,7 @@ namespace Trinity
{
WorldObjectSpellTargetCheck::WorldObjectSpellTargetCheck(Unit* caster, Unit* referer, SpellInfo const* spellInfo,
- SpellTargetCheckTypes selectionType, ConditionList* condList) : _caster(caster), _referer(referer), _spellInfo(spellInfo),
+ SpellTargetCheckTypes selectionType, ConditionContainer* condList) : _caster(caster), _referer(referer), _spellInfo(spellInfo),
_targetSelectionType(selectionType), _condList(condList)
{
if (condList)
@@ -7346,7 +7387,7 @@ bool WorldObjectSpellTargetCheck::operator()(WorldObject* target)
}
WorldObjectSpellNearbyTargetCheck::WorldObjectSpellNearbyTargetCheck(float range, Unit* caster, SpellInfo const* spellInfo,
- SpellTargetCheckTypes selectionType, ConditionList* condList)
+ SpellTargetCheckTypes selectionType, ConditionContainer* condList)
: WorldObjectSpellTargetCheck(caster, caster, spellInfo, selectionType, condList), _range(range), _position(caster) { }
bool WorldObjectSpellNearbyTargetCheck::operator()(WorldObject* target)
@@ -7361,7 +7402,7 @@ bool WorldObjectSpellNearbyTargetCheck::operator()(WorldObject* target)
}
WorldObjectSpellAreaTargetCheck::WorldObjectSpellAreaTargetCheck(float range, Position const* position, Unit* caster,
- Unit* referer, SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionList* condList)
+ Unit* referer, SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionContainer* condList)
: WorldObjectSpellTargetCheck(caster, referer, spellInfo, selectionType, condList), _range(range), _position(position) { }
bool WorldObjectSpellAreaTargetCheck::operator()(WorldObject* target)
@@ -7372,7 +7413,7 @@ bool WorldObjectSpellAreaTargetCheck::operator()(WorldObject* target)
}
WorldObjectSpellConeTargetCheck::WorldObjectSpellConeTargetCheck(float coneAngle, float range, Unit* caster,
- SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionList* condList)
+ SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionContainer* condList)
: WorldObjectSpellAreaTargetCheck(range, caster, caster, caster, spellInfo, selectionType, condList), _coneAngle(coneAngle) { }
bool WorldObjectSpellConeTargetCheck::operator()(WorldObject* target)
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 1aac88ac602..6b96f56c538 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -374,12 +374,12 @@ class Spell
void SelectEffectTypeImplicitTargets(uint8 effIndex);
- uint32 GetSearcherTypeMask(SpellTargetObjectTypes objType, ConditionList* condList);
+ uint32 GetSearcherTypeMask(SpellTargetObjectTypes objType, ConditionContainer* condList);
template<class SEARCHER> void SearchTargets(SEARCHER& searcher, uint32 containerMask, Unit* referer, Position const* pos, float radius);
- WorldObject* SearchNearbyTarget(float range, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionList* condList = NULL);
- void SearchAreaTargets(std::list<WorldObject*>& targets, float range, Position const* position, Unit* referer, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionList* condList);
- void SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTargets, WorldObject* target, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectType, ConditionList* condList, bool isChainHeal);
+ WorldObject* SearchNearbyTarget(float range, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionContainer* condList = NULL);
+ void SearchAreaTargets(std::list<WorldObject*>& targets, float range, Position const* position, Unit* referer, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionContainer* condList);
+ void SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTargets, WorldObject* target, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectType, ConditionContainer* condList, bool isChainHeal);
GameObject* SearchSpellFocus();
@@ -583,6 +583,8 @@ class Spell
// Targets store structures and data
struct TargetInfo
{
+ // a bug in gcc-4.7 needs a destructor to call move operator instead of copy operator in std::vector remove
+ ~TargetInfo() { }
ObjectGuid targetGUID;
uint64 timeDelay;
SpellMissInfo missCondition:8;
@@ -712,10 +714,10 @@ namespace Trinity
SpellInfo const* _spellInfo;
SpellTargetCheckTypes _targetSelectionType;
ConditionSourceInfo* _condSrcInfo;
- ConditionList* _condList;
+ ConditionContainer* _condList;
WorldObjectSpellTargetCheck(Unit* caster, Unit* referer, SpellInfo const* spellInfo,
- SpellTargetCheckTypes selectionType, ConditionList* condList);
+ SpellTargetCheckTypes selectionType, ConditionContainer* condList);
~WorldObjectSpellTargetCheck();
bool operator()(WorldObject* target);
};
@@ -725,7 +727,7 @@ namespace Trinity
float _range;
Position const* _position;
WorldObjectSpellNearbyTargetCheck(float range, Unit* caster, SpellInfo const* spellInfo,
- SpellTargetCheckTypes selectionType, ConditionList* condList);
+ SpellTargetCheckTypes selectionType, ConditionContainer* condList);
bool operator()(WorldObject* target);
};
@@ -734,7 +736,7 @@ namespace Trinity
float _range;
Position const* _position;
WorldObjectSpellAreaTargetCheck(float range, Position const* position, Unit* caster,
- Unit* referer, SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionList* condList);
+ Unit* referer, SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionContainer* condList);
bool operator()(WorldObject* target);
};
@@ -742,7 +744,7 @@ namespace Trinity
{
float _coneAngle;
WorldObjectSpellConeTargetCheck(float coneAngle, float range, Unit* caster,
- SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionList* condList);
+ SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionContainer* condList);
bool operator()(WorldObject* target);
};
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 3829e12b790..b3ab72dcbff 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -441,7 +441,7 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
// Shadow Bite
else if (m_spellInfo->SpellFamilyFlags[1] & 0x400000)
{
- if (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->ToCreature()->IsPet())
+ if (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->IsPet())
{
if (Player* owner = m_caster->GetOwner()->ToPlayer())
{
@@ -1232,7 +1232,7 @@ void Spell::EffectUnlearnSpecialization(SpellEffIndex effIndex)
player->RemoveSpell(spellToUnlearn);
- TC_LOG_DEBUG("spells", "Spell: Player %u has unlearned spell %u from NpcGUID: %u", player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow());
+ TC_LOG_DEBUG("spells", "Spell: Player %u has unlearned spell %u from NpcGUID: %u", player->GetGUID().GetCounter(), spellToUnlearn, m_caster->GetGUID().GetCounter());
}
void Spell::EffectPowerDrain(SpellEffIndex effIndex)
@@ -1571,6 +1571,22 @@ void Spell::DoCreateItem(uint32 /*i*/, uint32 itemtype)
if (num_to_add > pProto->GetMaxStackSize())
num_to_add = pProto->GetMaxStackSize();
+ /* == gem perfection handling == */
+
+ // the chance of getting a perfect result
+ float perfectCreateChance = 0.0f;
+ // the resulting perfect item if successful
+ uint32 perfectItemType = itemtype;
+ // get perfection capability and chance
+ if (CanCreatePerfectItem(player, m_spellInfo->Id, perfectCreateChance, perfectItemType))
+ if (roll_chance_f(perfectCreateChance)) // if the roll succeeds...
+ newitemid = perfectItemType; // the perfect item replaces the regular one
+
+ /* == gem perfection handling over == */
+
+
+ /* == profession specialization handling == */
+
// init items_count to 1, since 1 item will be created regardless of specialization
int items_count=1;
// the chance to create additional items
@@ -1579,15 +1595,16 @@ void Spell::DoCreateItem(uint32 /*i*/, uint32 itemtype)
uint8 additionalMaxNum=0;
// get the chance and maximum number for creating extra items
if (CanCreateExtraItems(player, m_spellInfo->Id, additionalCreateChance, additionalMaxNum))
- {
// roll with this chance till we roll not to create or we create the max num
while (roll_chance_f(additionalCreateChance) && items_count <= additionalMaxNum)
++items_count;
- }
// really will be created more items
num_to_add *= items_count;
+ /* == profession specialization handling over == */
+
+
// can the player store the new item?
ItemPosCountVec dest;
uint32 no_space = 0;
@@ -1712,7 +1729,7 @@ void Spell::EffectPersistentAA(SpellEffIndex effIndex)
if (!caster->IsInWorld())
return;
DynamicObject* dynObj = new DynamicObject(false);
- if (!dynObj->CreateDynamicObject(sObjectMgr->GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), caster, m_spellInfo->Id, *destTarget, radius, DYNAMIC_OBJECT_AREA_SPELL))
+ if (!dynObj->CreateDynamicObject(caster->GetMap()->GenerateLowGuid<HighGuid::DynamicObject>(), caster, m_spellInfo->Id, *destTarget, radius, DYNAMIC_OBJECT_AREA_SPELL))
{
delete dynObj;
return;
@@ -1884,7 +1901,7 @@ void Spell::SendLoot(ObjectGuid guid, LootType loottype)
if (!gameObjTarget->isSpawned() && !player->IsGameMaster())
{
TC_LOG_ERROR("spells", "Possible hacking attempt: Player %s [guid: %u] tried to loot a gameobject [entry: %u id: %u] which is on respawn time without being in GM mode!",
- player->GetName().c_str(), player->GetGUIDLow(), gameObjTarget->GetEntry(), gameObjTarget->GetGUIDLow());
+ player->GetName().c_str(), player->GetGUID().GetCounter(), gameObjTarget->GetEntry(), gameObjTarget->GetGUID().GetCounter());
return;
}
// special case, already has GossipHello inside so return and avoid calling twice
@@ -1922,7 +1939,7 @@ void Spell::SendLoot(ObjectGuid guid, LootType loottype)
/// @todo possible must be moved to loot release (in different from linked triggering)
if (gameObjTarget->GetGOInfo()->chest.eventId)
{
- TC_LOG_DEBUG("spells", "Chest ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->chest.eventId, gameObjTarget->GetDBTableGUIDLow());
+ TC_LOG_DEBUG("spells", "Chest ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->chest.eventId, gameObjTarget->GetSpawnId());
player->GetMap()->ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->chest.eventId, player, gameObjTarget);
}
@@ -1991,7 +2008,7 @@ void Spell::EffectOpenLock(SpellEffIndex effIndex)
/// @todo Add script for spell 41920 - Filling, becouse server it freze when use this spell
// handle outdoor pvp object opening, return true if go was registered for handling
// these objects must have been spawned by outdoorpvp!
- else if (gameObjTarget->GetGOInfo()->type == GAMEOBJECT_TYPE_GOOBER && sOutdoorPvPMgr->HandleOpenGo(player, gameObjTarget->GetGUID()))
+ else if (gameObjTarget->GetGOInfo()->type == GAMEOBJECT_TYPE_GOOBER && sOutdoorPvPMgr->HandleOpenGo(player, gameObjTarget))
return;
lockId = goInfo->GetLockId();
guid = gameObjTarget->GetGUID();
@@ -2032,9 +2049,9 @@ void Spell::EffectOpenLock(SpellEffIndex effIndex)
if (gameObjTarget)
{
// Allow one skill-up until respawned
- if (!gameObjTarget->IsInSkillupList(player->GetGUIDLow()) &&
+ if (!gameObjTarget->IsInSkillupList(player->GetGUID().GetCounter()) &&
player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue))
- gameObjTarget->AddToSkillupList(player->GetGUIDLow());
+ gameObjTarget->AddToSkillupList(player->GetGUID().GetCounter());
}
else if (itemTarget)
{
@@ -2376,7 +2393,7 @@ void Spell::EffectLearnSpell(SpellEffIndex effIndex)
uint32 spellToLearn = (m_spellInfo->Id == 483 || m_spellInfo->Id == 55884) ? damage : m_spellInfo->Effects[effIndex].TriggerSpell;
player->LearnSpell(spellToLearn, false);
- TC_LOG_DEBUG("spells", "Spell: Player %u has learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow());
+ TC_LOG_DEBUG("spells", "Spell: Player %u has learned spell %u from NpcGUID=%u", player->GetGUID().GetCounter(), spellToLearn, m_caster->GetGUID().GetCounter());
}
void Spell::EffectDispel(SpellEffIndex effIndex)
@@ -2550,7 +2567,7 @@ void Spell::EffectAddFarsight(SpellEffIndex effIndex)
return;
DynamicObject* dynObj = new DynamicObject(true);
- if (!dynObj->CreateDynamicObject(sObjectMgr->GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, *destTarget, radius, DYNAMIC_OBJECT_FARSIGHT_FOCUS))
+ if (!dynObj->CreateDynamicObject(m_caster->GetMap()->GenerateLowGuid<HighGuid::DynamicObject>(), m_caster, m_spellInfo->Id, *destTarget, radius, DYNAMIC_OBJECT_FARSIGHT_FOCUS))
{
delete dynObj;
return;
@@ -2627,7 +2644,7 @@ void Spell::EffectAddHonor(SpellEffIndex /*effIndex*/)
if (m_CastItem)
{
unitTarget->ToPlayer()->RewardHonor(NULL, 1, damage/10);
- TC_LOG_DEBUG("spells", "SpellEffect::AddHonor (spell_id %u) rewards %d honor points (item %u) for player: %u", m_spellInfo->Id, damage/10, m_CastItem->GetEntry(), unitTarget->ToPlayer()->GetGUIDLow());
+ TC_LOG_DEBUG("spells", "SpellEffect::AddHonor (spell_id %u) rewards %d honor points (item %u) for player: %u", m_spellInfo->Id, damage/10, m_CastItem->GetEntry(), unitTarget->ToPlayer()->GetGUID().GetCounter());
return;
}
@@ -2636,13 +2653,13 @@ void Spell::EffectAddHonor(SpellEffIndex /*effIndex*/)
{
uint32 honor_reward = Trinity::Honor::hk_honor_at_level(unitTarget->getLevel(), float(damage));
unitTarget->ToPlayer()->RewardHonor(NULL, 1, honor_reward);
- TC_LOG_DEBUG("spells", "SpellEffect::AddHonor (spell_id %u) rewards %u honor points (scale) to player: %u", m_spellInfo->Id, honor_reward, unitTarget->ToPlayer()->GetGUIDLow());
+ TC_LOG_DEBUG("spells", "SpellEffect::AddHonor (spell_id %u) rewards %u honor points (scale) to player: %u", m_spellInfo->Id, honor_reward, unitTarget->ToPlayer()->GetGUID().GetCounter());
}
else
{
//maybe we have correct honor_gain in damage already
unitTarget->ToPlayer()->RewardHonor(NULL, 1, damage);
- TC_LOG_DEBUG("spells", "SpellEffect::AddHonor (spell_id %u) rewards %u honor points (non scale) for player: %u", m_spellInfo->Id, damage, unitTarget->ToPlayer()->GetGUIDLow());
+ TC_LOG_DEBUG("spells", "SpellEffect::AddHonor (spell_id %u) rewards %u honor points (non scale) for player: %u", m_spellInfo->Id, damage, unitTarget->ToPlayer()->GetGUID().GetCounter());
}
}
@@ -2981,7 +2998,7 @@ void Spell::EffectSummonPet(SpellEffIndex effIndex)
if (m_originalCaster)
{
owner = m_originalCaster->ToPlayer();
- if (!owner && m_originalCaster->ToCreature()->IsTotem())
+ if (!owner && m_originalCaster->IsTotem())
owner = m_originalCaster->GetCharmerOrOwnerPlayerOrPlayerItself();
}
@@ -3038,7 +3055,7 @@ void Spell::EffectSummonPet(SpellEffIndex effIndex)
if (m_caster->GetTypeId() == TYPEID_UNIT)
{
- if (m_caster->ToCreature()->IsTotem())
+ if (m_caster->IsTotem())
pet->SetReactState(REACT_AGGRESSIVE);
else
pet->SetReactState(REACT_DEFENSIVE);
@@ -3100,19 +3117,18 @@ void Spell::EffectTaunt(SpellEffIndex /*effIndex*/)
if (m_spellInfo->Id == 62124)
m_caster->CastSpell(unitTarget, 67485, true);
- // Also use this effect to set the taunter's threat to the taunted creature's highest value
- if (unitTarget->getThreatManager().getCurrentVictim())
+ if (!unitTarget->getThreatManager().getOnlineContainer().empty())
{
+ // Also use this effect to set the taunter's threat to the taunted creature's highest value
float myThreat = unitTarget->getThreatManager().getThreat(m_caster);
- float itsThreat = unitTarget->getThreatManager().getCurrentVictim()->getThreat();
- if (itsThreat > myThreat)
- unitTarget->getThreatManager().addThreat(m_caster, itsThreat - myThreat);
- }
+ float topThreat = unitTarget->getThreatManager().getOnlineContainer().getMostHated()->getThreat();
+ if (topThreat > myThreat)
+ unitTarget->getThreatManager().doAddThreat(m_caster, topThreat - myThreat);
- //Set aggro victim to caster
- if (!unitTarget->getThreatManager().getOnlineContainer().empty())
+ //Set aggro victim to caster
if (HostileReference* forcedVictim = unitTarget->getThreatManager().getOnlineContainer().getReferenceByTarget(m_caster))
unitTarget->getThreatManager().setCurrentVictim(forcedVictim);
+ }
if (unitTarget->ToCreature()->IsAIEnabled && !unitTarget->ToCreature()->HasReactState(REACT_PASSIVE))
unitTarget->ToCreature()->AI()->AttackStart(m_caster);
@@ -3409,9 +3425,9 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
uint32 eff_damage(std::max(weaponDamage, 0));
// Add melee damage bonuses (also check for negative)
- uint32 damage = m_caster->MeleeDamageBonusDone(unitTarget, eff_damage, m_attackType, m_spellInfo);
+ uint32 damageBonusDone = m_caster->MeleeDamageBonusDone(unitTarget, eff_damage, m_attackType, m_spellInfo);
- m_damage += unitTarget->MeleeDamageBonusTaken(m_caster, damage, m_attackType, m_spellInfo);
+ m_damage += unitTarget->MeleeDamageBonusTaken(m_caster, damageBonusDone, m_attackType, m_spellInfo);
}
void Spell::EffectThreat(SpellEffIndex /*effIndex*/)
@@ -3503,7 +3519,7 @@ void Spell::EffectSummonObjectWild(SpellEffIndex effIndex)
Map* map = target->GetMap();
- if (!pGameObj->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
+ if (!pGameObj->Create(map->GenerateLowGuid<HighGuid::GameObject>(), gameobject_id, map,
m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
{
delete pGameObj;
@@ -3528,7 +3544,7 @@ void Spell::EffectSummonObjectWild(SpellEffIndex effIndex)
if (uint32 linkedEntry = pGameObj->GetGOInfo()->GetLinkedGameObjectEntry())
{
GameObject* linkedGO = new GameObject;
- if (linkedGO->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map,
+ if (linkedGO->Create(map->GenerateLowGuid<HighGuid::GameObject>(), linkedEntry, map,
m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
{
linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0);
@@ -3665,9 +3681,9 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex)
case 54426:
if (unitTarget)
{
- int32 damage = int32(unitTarget->GetHealth()) - int32(unitTarget->CountPctFromMaxHealth(5));
- if (damage > 0)
- m_caster->CastCustomSpell(28375, SPELLVALUE_BASE_POINT0, damage, unitTarget);
+ int32 decimateDamage = int32(unitTarget->GetHealth()) - int32(unitTarget->CountPctFromMaxHealth(5));
+ if (decimateDamage > 0)
+ m_caster->CastCustomSpell(28375, SPELLVALUE_BASE_POINT0, decimateDamage, unitTarget);
}
return;
// Mirren's Drinking Hat
@@ -3869,7 +3885,7 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex)
}
case 52173: // Coyote Spirit Despawn
case 60243: // Blood Parrot Despawn
- if (unitTarget->GetTypeId() == TYPEID_UNIT && unitTarget->ToCreature()->IsSummon())
+ if (unitTarget->GetTypeId() == TYPEID_UNIT && unitTarget->IsSummon())
unitTarget->ToTempSummon()->UnSummon();
return;
case 52479: // Gift of the Harvester
@@ -3964,7 +3980,7 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex)
}
case 60123: // Lightwell
{
- if (m_caster->GetTypeId() != TYPEID_UNIT || !m_caster->ToCreature()->IsSummon())
+ if (m_caster->GetTypeId() != TYPEID_UNIT || !m_caster->IsSummon())
return;
uint32 spell_heal;
@@ -4127,7 +4143,7 @@ void Spell::EffectDuel(SpellEffIndex effIndex)
Player* target = unitTarget->ToPlayer();
// caster or target already have requested duel
- if (caster->duel || target->duel || !target->GetSocial() || target->GetSocial()->HasIgnore(caster->GetGUIDLow()))
+ if (caster->duel || target->duel || !target->GetSocial() || target->GetSocial()->HasIgnore(caster->GetGUID().GetCounter()))
return;
// Players can only fight a duel in zones with this flag
@@ -4151,7 +4167,7 @@ void Spell::EffectDuel(SpellEffIndex effIndex)
uint32 gameobject_id = m_spellInfo->Effects[effIndex].MiscValue;
Map* map = m_caster->GetMap();
- if (!pGameObj->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id,
+ if (!pGameObj->Create(map->GenerateLowGuid<HighGuid::GameObject>(), gameobject_id,
map, m_caster->GetPhaseMask(),
m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2,
m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2,
@@ -4217,7 +4233,7 @@ void Spell::EffectStuck(SpellEffIndex /*effIndex*/)
return;
TC_LOG_DEBUG("spells", "Spell Effect: Stuck");
- TC_LOG_DEBUG("spells", "Player %s (guid %u) used auto-unstuck future at map %u (%f, %f, %f)", player->GetName().c_str(), player->GetGUIDLow(), player->GetMapId(), player->GetPositionX(), player->GetPositionY(), player->GetPositionZ());
+ TC_LOG_DEBUG("spells", "Player %s (guid %u) used auto-unstuck future at map %u (%f, %f, %f)", player->GetName().c_str(), player->GetGUID().GetCounter(), player->GetMapId(), player->GetPositionX(), player->GetPositionY(), player->GetPositionZ());
if (player->IsInFlight())
return;
@@ -4357,11 +4373,14 @@ void Spell::EffectEnchantHeldItem(SpellEffIndex effIndex)
if (m_spellInfo->Effects[effIndex].MiscValue)
{
uint32 enchant_id = m_spellInfo->Effects[effIndex].MiscValue;
- int32 duration = m_spellInfo->GetDuration(); //Try duration index first ..
+ int32 duration = m_spellInfo->GetDuration(); // Try duration index first ..
if (!duration)
- duration = damage;//+1; //Base points after ..
+ duration = damage;//+1; // Base points after ..
if (!duration)
- duration = 10; //10 seconds for enchants which don't have listed duration
+ duration = 10 * IN_MILLISECONDS; // 10 seconds for enchants which don't have listed duration
+
+ if (m_spellInfo->Id == 14792) // Venomhide Poison
+ duration = 5 * MINUTE * IN_MILLISECONDS;
SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
if (!pEnchant)
@@ -4375,7 +4394,7 @@ void Spell::EffectEnchantHeldItem(SpellEffIndex effIndex)
return;
// Apply the temporary enchantment
- item->SetEnchantment(slot, enchant_id, duration*IN_MILLISECONDS, 0, m_caster->GetGUID());
+ item->SetEnchantment(slot, enchant_id, duration, 0, m_caster->GetGUID());
item_owner->ApplyEnchantment(item, slot, true);
}
}
@@ -4498,7 +4517,7 @@ void Spell::EffectSummonObject(SpellEffIndex effIndex)
m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE);
Map* map = m_caster->GetMap();
- if (!go->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map,
+ if (!go->Create(map->GenerateLowGuid<HighGuid::GameObject>(), go_id, map,
m_caster->GetPhaseMask(), x, y, z, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
{
delete go;
@@ -5127,7 +5146,7 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex)
GameObject* pGameObj = new GameObject;
- if (!pGameObj->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap,
+ if (!pGameObj->Create(cMap->GenerateLowGuid<HighGuid::GameObject>(), name_id, cMap,
m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
{
delete pGameObj;
@@ -5193,7 +5212,7 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex)
if (uint32 linkedEntry = pGameObj->GetGOInfo()->GetLinkedGameObjectEntry())
{
GameObject* linkedGO = new GameObject;
- if (linkedGO->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap,
+ if (linkedGO->Create(cMap->GenerateLowGuid<HighGuid::GameObject>(), linkedEntry, cMap,
m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
{
linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0);
@@ -5619,7 +5638,7 @@ void Spell::EffectGameObjectDamage(SpellEffIndex /*effIndex*/)
FactionTemplateEntry const* casterFaction = caster->GetFactionTemplateEntry();
FactionTemplateEntry const* targetFaction = sFactionTemplateStore.LookupEntry(gameObjTarget->GetUInt32Value(GAMEOBJECT_FACTION));
// Do not allow to damage GO's of friendly factions (ie: Wintergrasp Walls/Ulduar Storm Beacons)
- if ((casterFaction && targetFaction && !casterFaction->IsFriendlyTo(*targetFaction)) || !targetFaction)
+ if (!targetFaction || (casterFaction && targetFaction && !casterFaction->IsFriendlyTo(*targetFaction)))
gameObjTarget->ModifyHealth(-damage, caster, GetSpellInfo()->Id);
}
@@ -5719,7 +5738,7 @@ void Spell::EffectRenamePet(SpellEffIndex /*effIndex*/)
return;
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT ||
- !unitTarget->ToCreature()->IsPet() || ((Pet*)unitTarget)->getPetType() != HUNTER_PET)
+ !unitTarget->IsPet() || ((Pet*)unitTarget)->getPetType() != HUNTER_PET)
return;
unitTarget->SetByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED);
diff --git a/src/server/game/Spells/SpellHistory.cpp b/src/server/game/Spells/SpellHistory.cpp
index 09e3be690b1..faad54d0af7 100644
--- a/src/server/game/Spells/SpellHistory.cpp
+++ b/src/server/game/Spells/SpellHistory.cpp
@@ -41,8 +41,11 @@ struct SpellHistory::PersistenceHelper<Player>
if (!sSpellMgr->GetSpellInfo(*spellId))
return false;
+ cooldownEntry->SpellId = *spellId;
cooldownEntry->CooldownEnd = Clock::from_time_t(time_t(fields[2].GetUInt32()));
cooldownEntry->ItemId = fields[1].GetUInt32();
+ cooldownEntry->CategoryId = fields[3].GetUInt32();
+ cooldownEntry->CategoryEnd = Clock::from_time_t(time_t(fields[4].GetUInt32()));
return true;
}
@@ -51,6 +54,8 @@ struct SpellHistory::PersistenceHelper<Player>
stmt->setUInt32(index++, cooldown.first);
stmt->setUInt32(index++, cooldown.second.ItemId);
stmt->setUInt32(index++, uint32(Clock::to_time_t(cooldown.second.CooldownEnd)));
+ stmt->setUInt32(index++, cooldown.second.CategoryId);
+ stmt->setUInt32(index++, uint32(Clock::to_time_t(cooldown.second.CategoryEnd)));
}
};
@@ -68,8 +73,11 @@ struct SpellHistory::PersistenceHelper<Pet>
if (!sSpellMgr->GetSpellInfo(*spellId))
return false;
+ cooldownEntry->SpellId = *spellId;
cooldownEntry->CooldownEnd = Clock::from_time_t(time_t(fields[1].GetUInt32()));
cooldownEntry->ItemId = 0;
+ cooldownEntry->CategoryId = fields[2].GetUInt32();
+ cooldownEntry->CategoryEnd = Clock::from_time_t(time_t(fields[3].GetUInt32()));
return true;
}
@@ -77,6 +85,8 @@ struct SpellHistory::PersistenceHelper<Pet>
{
stmt->setUInt32(index++, cooldown.first);
stmt->setUInt32(index++, uint32(Clock::to_time_t(cooldown.second.CooldownEnd)));
+ stmt->setUInt32(index++, cooldown.second.CategoryId);
+ stmt->setUInt32(index++, uint32(Clock::to_time_t(cooldown.second.CategoryEnd)));
}
};
@@ -92,7 +102,11 @@ void SpellHistory::LoadFromDB(PreparedQueryResult cooldownsResult)
uint32 spellId;
CooldownEntry cooldown;
if (StatementInfo::ReadCooldown(cooldownsResult->Fetch(), &spellId, &cooldown))
+ {
_spellCooldowns[spellId] = cooldown;
+ if (cooldown.CategoryId)
+ _categoryCooldowns[cooldown.CategoryId] = &_spellCooldowns[spellId];
+ }
} while (cooldownsResult->NextRow());
}
@@ -125,10 +139,18 @@ void SpellHistory::Update()
{
SQLTransaction t;
Clock::time_point now = Clock::now();
+ for (auto itr = _categoryCooldowns.begin(); itr != _categoryCooldowns.end();)
+ {
+ if (itr->second->CategoryEnd < now)
+ itr = _categoryCooldowns.erase(itr);
+ else
+ ++itr;
+ }
+
for (auto itr = _spellCooldowns.begin(); itr != _spellCooldowns.end();)
{
if (itr->second.CooldownEnd < now)
- itr = _spellCooldowns.erase(itr);
+ itr = EraseCooldown(itr);
else
++itr;
}
@@ -136,29 +158,37 @@ void SpellHistory::Update()
void SpellHistory::HandleCooldowns(SpellInfo const* spellInfo, Item const* item, Spell* spell /*= nullptr*/)
{
+ HandleCooldowns(spellInfo, item ? item->GetEntry() : 0, spell);
+}
+
+void SpellHistory::HandleCooldowns(SpellInfo const* spellInfo, uint32 itemID, Spell* spell /*= nullptr*/)
+{
if (Player* player = _owner->ToPlayer())
{
// potions start cooldown until exiting combat
- if (item && (item->IsPotion() || spellInfo->IsCooldownStartedOnEvent()))
+ if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemID))
{
- player->SetLastPotionId(item->GetEntry());
- return;
+ if (itemTemplate->IsPotion() || spellInfo->IsCooldownStartedOnEvent())
+ {
+ player->SetLastPotionId(itemID);
+ return;
+ }
}
}
if (spellInfo->IsCooldownStartedOnEvent() || spellInfo->IsPassive() || (spell && spell->IsIgnoringCooldowns()))
return;
- StartCooldown(spellInfo, item ? item->GetEntry() : 0, spell);
+ StartCooldown(spellInfo, itemID, spell);
}
-bool SpellHistory::IsReady(SpellInfo const* spellInfo) const
+bool SpellHistory::IsReady(SpellInfo const* spellInfo, uint32 itemId /*= 0*/) const
{
if (spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE)
if (IsSchoolLocked(spellInfo->GetSchoolMask()))
return false;
- if (HasCooldown(spellInfo->Id))
+ if (HasCooldown(spellInfo->Id, itemId))
return false;
return true;
@@ -168,42 +198,33 @@ template<>
void SpellHistory::WritePacket<Pet>(WorldPacket& packet) const
{
Clock::time_point now = Clock::now();
-
+
uint8 cooldownsCount = _spellCooldowns.size();
packet << uint8(cooldownsCount);
for (auto const& spellCooldown : _spellCooldowns)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellCooldown.first);
- if (!spellInfo)
- {
- packet << uint32(0);
- packet << uint16(0);
- packet << uint32(0);
- packet << uint32(0);
- continue;
- }
-
- packet << uint32(spellCooldown.first); // spell ID
- packet << uint16(spellInfo->GetCategory()); // spell category
+ packet << uint32(spellCooldown.first); // spell ID
+ packet << uint16(spellCooldown.second.CategoryId); // spell category
if (!spellCooldown.second.OnHold)
{
- uint32 cooldownDuration = spellCooldown.second.CooldownEnd > now ? std::chrono::duration_cast<std::chrono::milliseconds>(spellCooldown.second.CooldownEnd - now).count() : 0;
- if (cooldownDuration <= 0)
+ std::chrono::milliseconds cooldownDuration = std::chrono::duration_cast<std::chrono::milliseconds>(spellCooldown.second.CooldownEnd - now);
+ if (cooldownDuration.count() <= 0)
{
packet << uint32(0);
packet << uint32(0);
continue;
}
- if (spellInfo->GetCategory())
+ std::chrono::milliseconds categoryDuration = std::chrono::duration_cast<std::chrono::milliseconds>(spellCooldown.second.CategoryEnd - now);
+ if (categoryDuration.count() > 0)
{
packet << uint32(0);
- packet << uint32(cooldownDuration);
+ packet << uint32(categoryDuration.count());
}
else
{
- packet << uint32(cooldownDuration);
+ packet << uint32(cooldownDuration.count());
packet << uint32(0);
}
}
@@ -216,23 +237,13 @@ void SpellHistory::WritePacket<Player>(WorldPacket& packet) const
Clock::time_point now = Clock::now();
Clock::time_point infTime = now + InfinityCooldownDelayCheck;
- uint16 cooldownsCount = _spellCooldowns.size();
- size_t dataPos = packet.wpos();
- packet << uint16(cooldownsCount);
+ packet << uint16(_spellCooldowns.size());
for (auto const& spellCooldown : _spellCooldowns)
{
- SpellInfo const* sEntry = sSpellMgr->GetSpellInfo(spellCooldown.first);
- if (!sEntry)
- {
- --cooldownsCount;
- continue;
- }
-
packet << uint32(spellCooldown.first);
-
packet << uint16(spellCooldown.second.ItemId); // cast item id
- packet << uint16(sEntry->GetCategory()); // spell category
+ packet << uint16(spellCooldown.second.CategoryId); // spell category
// send infinity cooldown in special format
if (spellCooldown.second.CooldownEnd >= infTime)
@@ -242,21 +253,26 @@ void SpellHistory::WritePacket<Player>(WorldPacket& packet) const
continue;
}
- uint32 cooldownDuration = spellCooldown.second.CooldownEnd > now ? std::chrono::duration_cast<std::chrono::milliseconds>(spellCooldown.second.CooldownEnd - now).count() : 0;
+ std::chrono::milliseconds cooldownDuration = std::chrono::duration_cast<std::chrono::milliseconds>(spellCooldown.second.CooldownEnd - now);
+ if (cooldownDuration.count() <= 0)
+ {
+ packet << uint32(0);
+ packet << uint32(0);
+ continue;
+ }
- if (sEntry->GetCategory()) // may be wrong, but anyway better than nothing...
+ std::chrono::milliseconds categoryDuration = std::chrono::duration_cast<std::chrono::milliseconds>(spellCooldown.second.CategoryEnd - now);
+ if (categoryDuration.count() >= 0)
{
packet << uint32(0); // cooldown
- packet << uint32(cooldownDuration); // category cooldown
+ packet << uint32(categoryDuration.count()); // category cooldown
}
else
{
- packet << uint32(cooldownDuration); // cooldown
+ packet << uint32(cooldownDuration.count()); // cooldown
packet << uint32(0); // category cooldown
}
}
-
- packet.put<uint16>(dataPos, cooldownsCount);
}
void SpellHistory::StartCooldown(SpellInfo const* spellInfo, uint32 itemId, Spell* spell /*= nullptr*/, bool onHold /*= false*/)
@@ -266,32 +282,7 @@ void SpellHistory::StartCooldown(SpellInfo const* spellInfo, uint32 itemId, Spel
int32 cooldown = -1;
int32 categoryCooldown = -1;
- // some special item spells without correct cooldown in SpellInfo
- // cooldown information stored in item prototype
- if (itemId)
- {
- if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId))
- {
- for (uint8 idx = 0; idx < MAX_ITEM_PROTO_SPELLS; ++idx)
- {
- if (uint32(proto->Spells[idx].SpellId) == spellInfo->Id)
- {
- categoryId = proto->Spells[idx].SpellCategory;
- cooldown = proto->Spells[idx].SpellCooldown;
- categoryCooldown = proto->Spells[idx].SpellCategoryCooldown;
- break;
- }
- }
- }
- }
-
- // if no cooldown found above then base at DBC data
- if (cooldown < 0 && categoryCooldown < 0)
- {
- categoryId = spellInfo->GetCategory();
- cooldown = spellInfo->RecoveryTime;
- categoryCooldown = spellInfo->CategoryRecoveryTime;
- }
+ GetCooldownDurations(spellInfo, itemId, &cooldown, &categoryId, &categoryCooldown);
Clock::time_point curTime = Clock::now();
Clock::time_point catrecTime;
@@ -351,7 +342,7 @@ void SpellHistory::StartCooldown(SpellInfo const* spellInfo, uint32 itemId, Spel
// self spell cooldown
if (recTime != curTime)
{
- AddCooldown(spellInfo->Id, itemId, recTime, onHold);
+ AddCooldown(spellInfo->Id, itemId, recTime, categoryId, catrecTime, onHold);
if (needsCooldownPacket)
{
@@ -363,73 +354,51 @@ void SpellHistory::StartCooldown(SpellInfo const* spellInfo, uint32 itemId, Spel
}
}
}
-
- // category spells
- if (categoryId && catrecTime != curTime)
- {
- SpellCategoryStore::const_iterator i_scstore = sSpellsByCategoryStore.find(categoryId);
- if (i_scstore != sSpellsByCategoryStore.end())
- {
- for (SpellCategorySet::const_iterator i_scset = i_scstore->second.begin(); i_scset != i_scstore->second.end(); ++i_scset)
- {
- if (*i_scset == spellInfo->Id) // skip main spell, already handled above
- continue;
-
- AddCooldown(*i_scset, itemId, catrecTime, onHold);
- }
- }
- }
}
void SpellHistory::SendCooldownEvent(SpellInfo const* spellInfo, uint32 itemId /*= 0*/, Spell* spell /*= nullptr*/, bool startCooldown /*= true*/)
{
- // start cooldowns at server side, if any
- if (startCooldown)
- StartCooldown(spellInfo, itemId, spell);
-
+ // Send activate cooldown timer (possible 0) at client side
if (Player* player = GetPlayerOwner())
{
- // Send activate cooldown timer (possible 0) at client side
- WorldPacket data(SMSG_COOLDOWN_EVENT, 4 + 8);
- data << uint32(spellInfo->Id);
- data << uint64(_owner->GetGUID());
- player->SendDirectMessage(&data);
-
uint32 category = spellInfo->GetCategory();
- if (category && spellInfo->CategoryRecoveryTime)
- {
- SpellCategoryStore::const_iterator ct = sSpellsByCategoryStore.find(category);
- if (ct != sSpellsByCategoryStore.end())
- {
- for (auto const& cooldownPair : _spellCooldowns)
- {
- uint32 categorySpell = cooldownPair.first;
- if (!ct->second.count(categorySpell))
- continue;
+ GetCooldownDurations(spellInfo, itemId, nullptr, &category, nullptr);
- if (categorySpell == spellInfo->Id) // skip main spell, already handled above
- continue;
-
- SpellInfo const* spellInfo2 = sSpellMgr->EnsureSpellInfo(categorySpell);
- if (!spellInfo2->IsCooldownStartedOnEvent())
- continue;
+ auto categoryItr = _categoryCooldowns.find(category);
+ if (categoryItr != _categoryCooldowns.end() && categoryItr->second->SpellId != spellInfo->Id)
+ {
+ WorldPacket data(SMSG_COOLDOWN_EVENT, 4 + 8);
+ data << uint32(categoryItr->second->SpellId);
+ data << uint64(_owner->GetGUID());
+ player->SendDirectMessage(&data);
- data.Initialize(SMSG_COOLDOWN_EVENT, 4 + 8);
- data << uint32(categorySpell);
- data << uint64(_owner->GetGUID());
- player->SendDirectMessage(&data);
- }
- }
+ if (startCooldown)
+ StartCooldown(sSpellMgr->EnsureSpellInfo(categoryItr->second->SpellId), itemId, spell);
}
+
+ WorldPacket data(SMSG_COOLDOWN_EVENT, 4 + 8);
+ data << uint32(spellInfo->Id);
+ data << uint64(_owner->GetGUID());
+ player->SendDirectMessage(&data);
}
+
+ // start cooldowns at server side, if any
+ if (startCooldown)
+ StartCooldown(spellInfo, itemId, spell);
}
-void SpellHistory::AddCooldown(uint32 spellId, uint32 itemId, Clock::time_point cooldownEnd, bool onHold /*= false*/)
+void SpellHistory::AddCooldown(uint32 spellId, uint32 itemId, Clock::time_point cooldownEnd, uint32 categoryId, Clock::time_point categoryEnd, bool onHold /*= false*/)
{
CooldownEntry& cooldownEntry = _spellCooldowns[spellId];
+ cooldownEntry.SpellId = spellId;
cooldownEntry.CooldownEnd = cooldownEnd;
cooldownEntry.ItemId = itemId;
+ cooldownEntry.CategoryId = categoryId;
+ cooldownEntry.CategoryEnd = categoryEnd;
cooldownEntry.OnHold = onHold;
+
+ if (categoryId)
+ _categoryCooldowns[categoryId] = &cooldownEntry;
}
void SpellHistory::ModifyCooldown(uint32 spellId, int32 cooldownModMs)
@@ -443,7 +412,7 @@ void SpellHistory::ModifyCooldown(uint32 spellId, int32 cooldownModMs)
if (itr->second.CooldownEnd + offset > now)
itr->second.CooldownEnd += offset;
else
- _spellCooldowns.erase(itr);
+ EraseCooldown(itr);
if (Player* playerOwner = GetPlayerOwner())
{
@@ -477,7 +446,7 @@ void SpellHistory::ResetCooldown(CooldownStorageType::iterator& itr, bool update
}
}
- itr = _spellCooldowns.erase(itr);
+ itr = EraseCooldown(itr);
}
void SpellHistory::ResetAllCooldowns()
@@ -492,31 +461,55 @@ void SpellHistory::ResetAllCooldowns()
SendClearCooldowns(cooldowns);
}
+ _categoryCooldowns.clear();
_spellCooldowns.clear();
}
-bool SpellHistory::HasCooldown(uint32 spellId) const
+bool SpellHistory::HasCooldown(SpellInfo const* spellInfo, uint32 itemId /*= 0*/) const
{
- return _spellCooldowns.count(spellId) != 0;
+ if (_spellCooldowns.count(spellInfo->Id) != 0)
+ return true;
+
+ uint32 category = 0;
+ GetCooldownDurations(spellInfo, itemId, nullptr, &category, nullptr);
+ if (!category)
+ return false;
+
+ return _categoryCooldowns.count(category) != 0;
}
-uint32 SpellHistory::GetRemainingCooldown(uint32 spellId) const
+bool SpellHistory::HasCooldown(uint32 spellId, uint32 itemId /*= 0*/) const
{
- auto itr = _spellCooldowns.find(spellId);
- if (itr == _spellCooldowns.end())
- return 0;
+ return HasCooldown(sSpellMgr->EnsureSpellInfo(spellId), itemId);
+}
+
+uint32 SpellHistory::GetRemainingCooldown(SpellInfo const* spellInfo) const
+{
+ Clock::time_point end;
+ auto itr = _spellCooldowns.find(spellInfo->Id);
+ if (itr != _spellCooldowns.end())
+ end = itr->second.CooldownEnd;
+ else
+ {
+ auto catItr = _categoryCooldowns.find(spellInfo->GetCategory());
+ if (catItr == _categoryCooldowns.end())
+ return 0;
+
+ end = catItr->second->CategoryEnd;
+ }
Clock::time_point now = Clock::now();
- if (itr->second.CooldownEnd < now)
+ if (end < now)
return 0;
- Clock::duration remaining = itr->second.CooldownEnd - now;
+ Clock::duration remaining = end - now;
return uint32(std::chrono::duration_cast<std::chrono::milliseconds>(remaining).count());
}
void SpellHistory::LockSpellSchool(SpellSchoolMask schoolMask, uint32 lockoutTime)
{
- Clock::time_point lockoutEnd = Clock::now() + std::chrono::duration_cast<Clock::duration>(std::chrono::milliseconds(lockoutTime));
+ Clock::time_point now = Clock::now();
+ Clock::time_point lockoutEnd = now + std::chrono::duration_cast<Clock::duration>(std::chrono::milliseconds(lockoutTime));
for (uint32 i = 0; i < MAX_SPELL_SCHOOL; ++i)
if (SpellSchoolMask(1 << i) & schoolMask)
_schoolLockouts[i] = lockoutEnd;
@@ -553,10 +546,10 @@ void SpellHistory::LockSpellSchool(SpellSchoolMask schoolMask, uint32 lockoutTim
if (spellInfo->PreventionType != SPELL_PREVENTION_TYPE_SILENCE)
continue;
- if ((schoolMask & spellInfo->GetSchoolMask()) && GetRemainingCooldown(spellId) < lockoutTime)
+ if ((schoolMask & spellInfo->GetSchoolMask()) && GetRemainingCooldown(spellInfo) < lockoutTime)
{
cooldowns[spellId] = lockoutTime;
- AddCooldown(spellId, 0, lockoutEnd);
+ AddCooldown(spellId, 0, lockoutEnd, 0, now);
}
}
@@ -637,6 +630,96 @@ void SpellHistory::BuildCooldownPacket(WorldPacket& data, uint8 flags, PacketCoo
}
}
+void SpellHistory::GetCooldownDurations(SpellInfo const* spellInfo, uint32 itemId, int32* cooldown, uint32* categoryId, int32* categoryCooldown)
+{
+ ASSERT(cooldown || categoryId || categoryCooldown);
+ int32 tmpCooldown = -1;
+ uint32 tmpCategoryId = 0;
+ int32 tmpCategoryCooldown = -1;
+
+ // some special item spells without correct cooldown in SpellInfo
+ // cooldown information stored in item prototype
+ if (itemId)
+ {
+ if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId))
+ {
+ for (uint8 idx = 0; idx < MAX_ITEM_PROTO_SPELLS; ++idx)
+ {
+ if (uint32(proto->Spells[idx].SpellId) == spellInfo->Id)
+ {
+ tmpCooldown = proto->Spells[idx].SpellCooldown;
+ tmpCategoryId = proto->Spells[idx].SpellCategory;
+ tmpCategoryCooldown = proto->Spells[idx].SpellCategoryCooldown;
+ break;
+ }
+ }
+ }
+ }
+
+ // if no cooldown found above then base at DBC data
+ if (tmpCooldown < 0 && tmpCategoryCooldown < 0)
+ {
+ tmpCooldown = spellInfo->RecoveryTime;
+ tmpCategoryId = spellInfo->GetCategory();
+ tmpCategoryCooldown = spellInfo->CategoryRecoveryTime;
+ }
+
+ if (cooldown)
+ *cooldown = tmpCooldown;
+ if (categoryId)
+ *categoryId = tmpCategoryId;
+ if (categoryCooldown)
+ *categoryCooldown = tmpCategoryCooldown;
+}
+
+void SpellHistory::SaveCooldownStateBeforeDuel()
+{
+ _spellCooldownsBeforeDuel = _spellCooldowns;
+}
+
+void SpellHistory::RestoreCooldownStateAfterDuel()
+{
+ // category cooldows are not preserved.
+ if (Player* player = _owner->ToPlayer())
+ {
+ // add all profession CDs created while in duel (if any)
+ for (auto itr = _spellCooldowns.begin(); itr != _spellCooldowns.end(); ++itr)
+ {
+ SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first);
+
+ if (spellInfo->RecoveryTime > 10 * MINUTE * IN_MILLISECONDS ||
+ spellInfo->CategoryRecoveryTime > 10 * MINUTE * IN_MILLISECONDS)
+ _spellCooldownsBeforeDuel[itr->first] = _spellCooldowns[itr->first];
+ }
+
+ // check for spell with onHold active before and during the duel
+ for (auto itr = _spellCooldownsBeforeDuel.begin(); itr != _spellCooldownsBeforeDuel.end(); ++itr)
+ {
+ if (!itr->second.OnHold && !_spellCooldowns[itr->first].OnHold)
+ _spellCooldowns[itr->first] = _spellCooldownsBeforeDuel[itr->first];
+ }
+
+ // update the client: restore old cooldowns
+ PacketCooldowns cooldowns;
+
+ for (auto itr = _spellCooldowns.begin(); itr != _spellCooldowns.end(); ++itr)
+ {
+ Clock::time_point now = Clock::now();
+ uint32 cooldownDuration = itr->second.CooldownEnd > now ? std::chrono::duration_cast<std::chrono::milliseconds>(itr->second.CooldownEnd - now).count() : 0;
+
+ // cooldownDuration must be between 0 and 10 minutes in order to avoid any visual bugs
+ if (cooldownDuration <= 0 || cooldownDuration > 10 * MINUTE * IN_MILLISECONDS || itr->second.OnHold)
+ continue;
+
+ cooldowns[itr->first] = cooldownDuration;
+ }
+
+ WorldPacket data;
+ BuildCooldownPacket(data, SPELL_COOLDOWN_FLAG_INCLUDE_EVENT_COOLDOWNS, cooldowns);
+ player->SendDirectMessage(&data);
+ }
+}
+
template void SpellHistory::LoadFromDB<Player>(PreparedQueryResult cooldownsResult);
template void SpellHistory::LoadFromDB<Pet>(PreparedQueryResult cooldownsResult);
template void SpellHistory::SaveToDB<Player>(SQLTransaction& trans);
diff --git a/src/server/game/Spells/SpellHistory.h b/src/server/game/Spells/SpellHistory.h
index f1533d57aef..db65cd50c3e 100644
--- a/src/server/game/Spells/SpellHistory.h
+++ b/src/server/game/Spells/SpellHistory.h
@@ -38,15 +38,16 @@ public:
struct CooldownEntry
{
- CooldownEntry() : ItemId(0), OnHold(false) { }
- CooldownEntry(Clock::time_point endTime, uint32 itemId) : CooldownEnd(endTime), ItemId(itemId), OnHold(false) { }
-
+ uint32 SpellId = 0;
Clock::time_point CooldownEnd;
- uint32 ItemId;
- bool OnHold;
+ uint32 ItemId = 0;
+ uint32 CategoryId = 0;
+ Clock::time_point CategoryEnd;
+ bool OnHold = false;
};
typedef std::unordered_map<uint32 /*spellId*/, CooldownEntry> CooldownStorageType;
+ typedef std::unordered_map<uint32 /*categoryId*/, CooldownEntry*> CategoryCooldownStorageType;
typedef std::unordered_map<uint32 /*categoryId*/, Clock::time_point> GlobalCooldownStorageType;
explicit SpellHistory(Unit* owner) : _owner(owner), _schoolLockouts() { }
@@ -60,7 +61,8 @@ public:
void Update();
void HandleCooldowns(SpellInfo const* spellInfo, Item const* item, Spell* spell = nullptr);
- bool IsReady(SpellInfo const* spellInfo) const;
+ void HandleCooldowns(SpellInfo const* spellInfo, uint32 itemID, Spell* spell = nullptr);
+ bool IsReady(SpellInfo const* spellInfo, uint32 itemId = 0) const;
template<class OwnerType>
void WritePacket(WorldPacket& packet) const;
@@ -74,10 +76,11 @@ public:
template<class Type, class Period>
void AddCooldown(uint32 spellId, uint32 itemId, std::chrono::duration<Type, Period> cooldownDuration)
{
- AddCooldown(spellId, itemId, Clock::now() + std::chrono::duration_cast<Clock::duration>(cooldownDuration));
+ Clock::time_point now = Clock::now();
+ AddCooldown(spellId, itemId, now + std::chrono::duration_cast<Clock::duration>(cooldownDuration), 0, now);
}
- void AddCooldown(uint32 spellId, uint32 itemId, Clock::time_point cooldownEnd, bool onHold = false);
+ void AddCooldown(uint32 spellId, uint32 itemId, Clock::time_point cooldownEnd, uint32 categoryId, Clock::time_point categoryEnd, bool onHold = false);
void ModifyCooldown(uint32 spellId, int32 cooldownModMs);
void ResetCooldown(uint32 spellId, bool update = false);
void ResetCooldown(CooldownStorageType::iterator& itr, bool update = false);
@@ -102,8 +105,9 @@ public:
}
void ResetAllCooldowns();
- bool HasCooldown(uint32 spellId) const;
- uint32 GetRemainingCooldown(uint32 spellId) const;
+ bool HasCooldown(SpellInfo const* spellInfo, uint32 itemId = 0) const;
+ bool HasCooldown(uint32 spellId, uint32 itemId = 0) const;
+ uint32 GetRemainingCooldown(SpellInfo const* spellInfo) const;
// School lockouts
void LockSpellSchool(SpellSchoolMask schoolMask, uint32 lockoutTime);
@@ -117,16 +121,27 @@ public:
void BuildCooldownPacket(WorldPacket& data, uint8 flags, uint32 spellId, uint32 cooldown) const;
CooldownStorageType::size_type GetCooldownsSizeForPacket() const { return _spellCooldowns.size(); }
-
+ void SaveCooldownStateBeforeDuel();
+ void RestoreCooldownStateAfterDuel();
+
private:
Player* GetPlayerOwner() const;
void SendClearCooldowns(std::vector<int32> const& cooldowns) const;
+ CooldownStorageType::iterator EraseCooldown(CooldownStorageType::iterator itr)
+ {
+ _categoryCooldowns.erase(itr->second.CategoryId);
+ return _spellCooldowns.erase(itr);
+ }
typedef std::unordered_map<uint32, uint32> PacketCooldowns;
void BuildCooldownPacket(WorldPacket& data, uint8 flags, PacketCooldowns const& cooldowns) const;
+ static void GetCooldownDurations(SpellInfo const* spellInfo, uint32 itemId, int32* cooldown, uint32* categoryId, int32* categoryCooldown);
+
Unit* _owner;
CooldownStorageType _spellCooldowns;
+ CooldownStorageType _spellCooldownsBeforeDuel;
+ CategoryCooldownStorageType _categoryCooldowns;
Clock::time_point _schoolLockouts[MAX_SPELL_SCHOOL];
GlobalCooldownStorageType _globalCooldowns;
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 789b95e3e14..6486a7eada7 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -776,8 +776,8 @@ SpellInfo::SpellInfo(SpellEntry const* spellEntry)
AttributesEx6 = spellEntry->AttributesEx6;
AttributesEx7 = spellEntry->AttributesEx7;
AttributesCu = 0;
- Stances = spellEntry->Stances;
- StancesNot = spellEntry->StancesNot;
+ Stances = MAKE_PAIR64(spellEntry->Stances[0], spellEntry->Stances[1]);
+ StancesNot = MAKE_PAIR64(spellEntry->StancesNot[0], spellEntry->StancesNot[1]);
Targets = spellEntry->Targets;
TargetCreatureType = spellEntry->TargetCreatureType;
RequiresSpellFocus = spellEntry->RequiresSpellFocus;
@@ -1309,7 +1309,7 @@ SpellCastResult SpellInfo::CheckShapeshift(uint32 form) const
(Effects[0].Effect == SPELL_EFFECT_LEARN_SPELL || Effects[1].Effect == SPELL_EFFECT_LEARN_SPELL || Effects[2].Effect == SPELL_EFFECT_LEARN_SPELL))
return SPELL_CAST_OK;
- uint32 stanceMask = (form ? 1 << (form - 1) : 0);
+ uint64 stanceMask = (form ? UI64LIT(1) << (form - 1) : 0);
if (stanceMask & StancesNot) // can explicitly not be cast in this stance
return SPELL_FAILED_NOT_SHAPESHIFT;
@@ -1489,6 +1489,7 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a
if (player && !player->CanFlyInZone(map_id, zone_id))
return SPELL_FAILED_INCORRECT_AREA;
}
+ break;
}
}
}
@@ -2657,7 +2658,7 @@ void SpellInfo::_UnloadImplicitTargetConditionLists()
// find the same instances of ConditionList and delete them.
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
- ConditionList* cur = Effects[i].ImplicitTargetConditions;
+ ConditionContainer* cur = Effects[i].ImplicitTargetConditions;
if (!cur)
continue;
for (uint8 j = i; j < MAX_SPELL_EFFECTS; ++j)
diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h
index cfa9877405d..d042f926d02 100644
--- a/src/server/game/Spells/SpellInfo.h
+++ b/src/server/game/Spells/SpellInfo.h
@@ -176,7 +176,7 @@ enum SpellCustomAttributes
SPELL_ATTR0_CU_CONE_LINE = 0x00000004,
SPELL_ATTR0_CU_SHARE_DAMAGE = 0x00000008,
SPELL_ATTR0_CU_NO_INITIAL_THREAT = 0x00000010,
- SPELL_ATTR0_CU_AURA_CC = 0x00000040,
+ SPELL_ATTR0_CU_DONT_BREAK_STEALTH = 0x00000040,
SPELL_ATTR0_CU_DIRECT_DAMAGE = 0x00000100,
SPELL_ATTR0_CU_CHARGE = 0x00000200,
SPELL_ATTR0_CU_PICKPOCKET = 0x00000400,
@@ -249,7 +249,7 @@ public:
uint32 ItemType;
uint32 TriggerSpell;
flag96 SpellClassMask;
- std::list<Condition*>* ImplicitTargetConditions;
+ std::vector<Condition*>* ImplicitTargetConditions;
SpellEffectInfo() : _spellInfo(NULL), _effIndex(0), Effect(0), ApplyAuraName(0), Amplitude(0), DieSides(0),
RealPointsPerLevel(0), BasePoints(0), PointsPerComboPoint(0), ValueMultiplier(0), DamageMultiplier(0),
@@ -306,8 +306,8 @@ public:
uint32 AttributesEx6;
uint32 AttributesEx7;
uint32 AttributesCu;
- uint32 Stances;
- uint32 StancesNot;
+ uint64 Stances;
+ uint64 StancesNot;
uint32 Targets;
uint32 TargetCreatureType;
uint32 RequiresSpellFocus;
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 13290320084..2d990ad3ed2 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -969,10 +969,10 @@ bool SpellMgr::CanSpellTriggerProcOnEvent(SpellProcEntry const& procEntry, ProcE
// check spell family name/flags (if set) for spells
if (eventInfo.GetTypeMask() & (PERIODIC_PROC_FLAG_MASK | SPELL_PROC_FLAG_MASK | PROC_FLAG_DONE_TRAP_ACTIVATION))
{
- if (procEntry.spellFamilyName && eventInfo.GetSpellInfo() && (procEntry.spellFamilyName != eventInfo.GetSpellInfo()->SpellFamilyName))
+ if (procEntry.spellFamilyName && eventInfo.GetSpellInfo() && (procEntry.spellFamilyName != eventInfo.EnsureSpellInfo()->SpellFamilyName))
return false;
- if (procEntry.spellFamilyMask && eventInfo.GetSpellInfo() && !(procEntry.spellFamilyMask & eventInfo.GetSpellInfo()->SpellFamilyFlags))
+ if (procEntry.spellFamilyMask && eventInfo.GetSpellInfo() && !(procEntry.spellFamilyMask & eventInfo.EnsureSpellInfo()->SpellFamilyFlags))
return false;
}
@@ -1609,8 +1609,8 @@ void SpellMgr::LoadSpellTargetPositions()
mSpellTargetPositions.clear(); // need for reload case
- // 0 1 2 3 4 5 6
- QueryResult result = WorldDatabase.Query("SELECT id, effIndex, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM spell_target_position");
+ // 0 1 2 3 4 5 6
+ QueryResult result = WorldDatabase.Query("SELECT ID, EffectIndex, MapID, PositionX, PositionY, PositionZ, Orientation FROM spell_target_position");
if (!result)
{
TC_LOG_INFO("server.loading", ">> Loaded 0 spell target coordinates. DB table `spell_target_position` is empty.");
@@ -2801,14 +2801,6 @@ void SpellMgr::LoadSpellInfoCustomAttributes()
{
switch (spellInfo->Effects[j].ApplyAuraName)
{
- case SPELL_AURA_MOD_POSSESS:
- case SPELL_AURA_MOD_CONFUSE:
- case SPELL_AURA_MOD_CHARM:
- case SPELL_AURA_AOE_CHARM:
- case SPELL_AURA_MOD_FEAR:
- case SPELL_AURA_MOD_STUN:
- spellInfo->AttributesCu |= SPELL_ATTR0_CU_AURA_CC;
- break;
case SPELL_AURA_PERIODIC_HEAL:
case SPELL_AURA_PERIODIC_DAMAGE:
case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
@@ -2901,22 +2893,6 @@ void SpellMgr::LoadSpellInfoCustomAttributes()
if (spellInfo->SpellVisual[0] == 3879)
spellInfo->AttributesCu |= SPELL_ATTR0_CU_CONE_BACK;
- switch (spellInfo->SpellFamilyName)
- {
- case SPELLFAMILY_WARRIOR:
- // Shout
- if (spellInfo->SpellFamilyFlags[0] & 0x20000 || spellInfo->SpellFamilyFlags[1] & 0x20)
- spellInfo->AttributesCu |= SPELL_ATTR0_CU_AURA_CC;
- break;
- case SPELLFAMILY_DRUID:
- // Roar
- if (spellInfo->SpellFamilyFlags[0] & 0x8)
- spellInfo->AttributesCu |= SPELL_ATTR0_CU_AURA_CC;
- break;
- default:
- break;
- }
-
spellInfo->_InitializeExplicitTargetMask();
}
@@ -2947,6 +2923,11 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->Speed = SPEED_CHARGE;
break;
}
+
+ // Passive talent auras cannot target pets
+ if (spellInfo->IsPassive() && GetTalentSpellCost(i))
+ if (spellInfo->Effects[j].TargetA.GetTarget() == TARGET_UNIT_PET)
+ spellInfo->Effects[j].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER);
}
if (spellInfo->ActiveIconID == 2158) // flight
@@ -3105,11 +3086,13 @@ void SpellMgr::LoadSpellInfoCorrections()
case 28796: // Poison Bolt Volly - Faerlina
spellInfo->MaxAffectedTargets = 5;
break;
+ case 54835: // Curse of the Plaguebringer - Noth (H)
+ spellInfo->MaxAffectedTargets = 8;
+ break;
case 40827: // Sinful Beam
case 40859: // Sinister Beam
case 40860: // Vile Beam
case 40861: // Wicked Beam
- case 54835: // Curse of the Plaguebringer - Noth (H)
case 54098: // Poison Bolt Volly - Faerlina (H)
spellInfo->MaxAffectedTargets = 10;
break;
@@ -3147,6 +3130,11 @@ void SpellMgr::LoadSpellInfoCorrections()
case 28200: // Ascendance (Talisman of Ascendance trinket)
spellInfo->ProcCharges = 6;
break;
+ case 49224: // Magic Suppression - DK
+ case 49610: // Magic Suppression - DK
+ case 49611: // Magic Suppression - DK
+ spellInfo->ProcCharges = 0;
+ break;
case 37408: // Oscillation Field
spellInfo->AttributesEx3 |= SPELL_ATTR3_STACK_FOR_DIFF_CASTERS;
break;
@@ -3158,6 +3146,11 @@ void SpellMgr::LoadSpellInfoCorrections()
// add corruption to affected spells
spellInfo->Effects[EFFECT_1].SpellClassMask[0] |= 2;
break;
+ case 57470: // Renewed Hope (Rank 1)
+ case 57472: // Renewed Hope (Rank 2)
+ // should also affect Flash Heal
+ spellInfo->Effects[EFFECT_0].SpellClassMask[0] |= 0x800;
+ break;
case 51852: // The Eye of Acherus (no spawn in phase 2 in db)
spellInfo->Effects[EFFECT_0].MiscValue |= 1;
break;
@@ -3170,13 +3163,13 @@ void SpellMgr::LoadSpellInfoCorrections()
// Master Shapeshifter: missing stance data for forms other than bear - bear version has correct data
// To prevent aura staying on target after talent unlearned
case 48420:
- spellInfo->Stances = 1 << (FORM_CAT - 1);
+ spellInfo->Stances = UI64LIT(1) << (FORM_CAT - 1);
break;
case 48421:
- spellInfo->Stances = 1 << (FORM_MOONKIN - 1);
+ spellInfo->Stances = UI64LIT(1) << (FORM_MOONKIN - 1);
break;
case 48422:
- spellInfo->Stances = 1 << (FORM_TREE - 1);
+ spellInfo->Stances = UI64LIT(1) << (FORM_TREE - 1);
break;
case 51466: // Elemental Oath (Rank 1)
case 51470: // Elemental Oath (Rank 2)
@@ -3235,6 +3228,9 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->Effects[EFFECT_1].BasePoints = -6; // -5%
break;
case 50526: // Wandering Plague
+ case 15290: // Vampiric Embrace
+ spellInfo->AttributesEx3 |= SPELL_ATTR3_NO_INITIAL_AGGRO;
+ break;
case 63675: // Improved Devouring Plague
spellInfo->AttributesEx3 |= SPELL_ATTR3_NO_DONE_BONUS;
break;
@@ -3342,6 +3338,19 @@ void SpellMgr::LoadSpellInfoCorrections()
//! HACK: This spell break quest complete for alliance and on retail not used °_O
spellInfo->Effects[EFFECT_0].Effect = 0;
break;
+ // VIOLET HOLD SPELLS
+ //
+ case 54258: // Water Globule (Ichoron)
+ case 54264: // Water Globule (Ichoron)
+ case 54265: // Water Globule (Ichoron)
+ case 54266: // Water Globule (Ichoron)
+ case 54267: // Water Globule (Ichoron)
+ // in 3.3.5 there is only one radius in dbc which is 0 yards in this case
+ // use max radius from 4.3.4
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_25_YARDS);
+ break;
+ // ENDOF VIOLET HOLD
+ //
// ULDUAR SPELLS
//
case 62374: // Pursued (Flame Leviathan)
@@ -3507,6 +3516,13 @@ void SpellMgr::LoadSpellInfoCorrections()
case 71415: // Orange Ooze Summon (Professor Putricide)
spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ANY);
break;
+ case 69783: // Ooze flood
+ case 69797: // Ooze flood
+ case 69799: // Ooze flood
+ case 69802: // Ooze flood
+ // Those spells are cast on creatures with same entry as caster while they have TARGET_UNIT_NEARBY_ENTRY.
+ spellInfo->AttributesEx |= SPELL_ATTR1_CANT_TARGET_SELF;
+ break;
case 71159: // Awaken Plagued Zombies
spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(21);
break;
diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp
index b347a982132..95857be27dc 100644
--- a/src/server/game/Spells/SpellScript.cpp
+++ b/src/server/game/Spells/SpellScript.cpp
@@ -15,10 +15,11 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <string>
#include "Spell.h"
#include "SpellAuras.h"
#include "SpellScript.h"
+#include "SpellMgr.h"
+#include <string>
bool _SpellScript::_Validate(SpellInfo const* entry)
{
@@ -84,9 +85,9 @@ uint8 _SpellScript::EffectHook::GetAffectedEffectsMask(SpellInfo const* spellEnt
return mask;
}
-bool _SpellScript::EffectHook::IsEffectAffected(SpellInfo const* spellEntry, uint8 effIndex)
+bool _SpellScript::EffectHook::IsEffectAffected(SpellInfo const* spellEntry, uint8 effIndexToCheck)
{
- return (GetAffectedEffectsMask(spellEntry) & 1 << effIndex) != 0;
+ return (GetAffectedEffectsMask(spellEntry) & 1 << effIndexToCheck) != 0;
}
std::string _SpellScript::EffectHook::EffIndexToString()
@@ -182,14 +183,14 @@ std::string SpellScript::EffectHandler::ToString()
return "Index: " + EffIndexToString() + " Name: " +_SpellScript::EffectNameCheck::ToString();
}
-bool SpellScript::EffectHandler::CheckEffect(SpellInfo const* spellEntry, uint8 effIndex)
+bool SpellScript::EffectHandler::CheckEffect(SpellInfo const* spellEntry, uint8 effIndexToCheck)
{
- return _SpellScript::EffectNameCheck::Check(spellEntry, effIndex);
+ return _SpellScript::EffectNameCheck::Check(spellEntry, effIndexToCheck);
}
-void SpellScript::EffectHandler::Call(SpellScript* spellScript, SpellEffIndex effIndex)
+void SpellScript::EffectHandler::Call(SpellScript* spellScript, SpellEffIndex effIndexToHandle)
{
- (spellScript->*pEffectHandlerScript)(effIndex);
+ (spellScript->*pEffectHandlerScript)(effIndexToHandle);
}
SpellScript::HitHandler::HitHandler(SpellHitFnType _pHitHandlerScript)
@@ -212,13 +213,13 @@ std::string SpellScript::TargetHook::ToString()
return oss.str();
}
-bool SpellScript::TargetHook::CheckEffect(SpellInfo const* spellEntry, uint8 effIndex)
+bool SpellScript::TargetHook::CheckEffect(SpellInfo const* spellEntry, uint8 effIndexToCheck)
{
if (!targetType)
return false;
- if (spellEntry->Effects[effIndex].TargetA.GetTarget() != targetType &&
- spellEntry->Effects[effIndex].TargetB.GetTarget() != targetType)
+ if (spellEntry->Effects[effIndexToCheck].TargetA.GetTarget() != targetType &&
+ spellEntry->Effects[effIndexToCheck].TargetB.GetTarget() != targetType)
return false;
SpellImplicitTargetInfo targetInfo(targetType);
@@ -641,8 +642,8 @@ SpellValue const* SpellScript::GetSpellValue()
bool AuraScript::_Validate(SpellInfo const* entry)
{
for (std::list<CheckAreaTargetHandler>::iterator itr = DoCheckAreaTarget.begin(); itr != DoCheckAreaTarget.end(); ++itr)
- if (!entry->HasAreaAuraEffect() && !entry->HasEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA))
- TC_LOG_ERROR("scripts", "Spell `%u` of script `%s` does not have area aura effect - handler bound to hook `DoCheckAreaTarget` of AuraScript won't be executed", entry->Id, m_scriptName->c_str());
+ if (!entry->HasAreaAuraEffect() && !entry->HasEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA) && !entry->HasEffect(SPELL_EFFECT_APPLY_AURA))
+ TC_LOG_ERROR("scripts", "Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `DoCheckAreaTarget` of AuraScript won't be executed", entry->Id, m_scriptName->c_str());
for (std::list<AuraDispelHandler>::iterator itr = OnDispel.begin(); itr != OnDispel.end(); ++itr)
if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect())
@@ -758,9 +759,9 @@ void AuraScript::AuraDispelHandler::Call(AuraScript* auraScript, DispelInfo* _di
AuraScript::EffectBase::EffectBase(uint8 _effIndex, uint16 _effName)
: _SpellScript::EffectAuraNameCheck(_effName), _SpellScript::EffectHook(_effIndex) { }
-bool AuraScript::EffectBase::CheckEffect(SpellInfo const* spellEntry, uint8 effIndex)
+bool AuraScript::EffectBase::CheckEffect(SpellInfo const* spellEntry, uint8 effIndexToCheck)
{
- return _SpellScript::EffectAuraNameCheck::Check(spellEntry, effIndex);
+ return _SpellScript::EffectAuraNameCheck::Check(spellEntry, effIndexToCheck);
}
std::string AuraScript::EffectBase::ToString()
diff --git a/src/server/game/Texts/CreatureTextMgr.cpp b/src/server/game/Texts/CreatureTextMgr.cpp
index 5fbc4b8ae1e..034fe96306e 100644
--- a/src/server/game/Texts/CreatureTextMgr.cpp
+++ b/src/server/game/Texts/CreatureTextMgr.cpp
@@ -77,7 +77,7 @@ void CreatureTextMgr::LoadCreatureTexts()
uint32 oldMSTime = getMSTime();
mTextMap.clear(); // for reload case
- mTextRepeatMap.clear(); //reset all currently used temp texts
+ //all currently used temp texts are NOT reset
PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_CREATURE_TEXT);
PreparedQueryResult result = WorldDatabase.Query(stmt);
@@ -202,7 +202,7 @@ uint32 CreatureTextMgr::SendChat(Creature* source, uint8 textGroup, WorldObject
CreatureTextMap::const_iterator sList = mTextMap.find(source->GetEntry());
if (sList == mTextMap.end())
{
- TC_LOG_ERROR("sql.sql", "CreatureTextMgr: Could not find Text for Creature %s (Entry %u, GUID %u) in 'creature_text' table. Ignoring.", source->GetName().c_str(), source->GetEntry(), source->GetGUIDLow());
+ TC_LOG_ERROR("sql.sql", "CreatureTextMgr: Could not find Text for Creature %s (Entry %u, GUID %u) in 'creature_text' table. Ignoring.", source->GetName().c_str(), source->GetEntry(), source->GetGUID().GetCounter());
return 0;
}
@@ -210,7 +210,7 @@ uint32 CreatureTextMgr::SendChat(Creature* source, uint8 textGroup, WorldObject
CreatureTextHolder::const_iterator itr = textHolder.find(textGroup);
if (itr == textHolder.end())
{
- TC_LOG_ERROR("sql.sql", "CreatureTextMgr: Could not find TextGroup %u for Creature %s (Entry %u, GUID %u) in 'creature_text' table. Ignoring.", uint32(textGroup), source->GetName().c_str(), source->GetEntry(), source->GetGUIDLow());
+ TC_LOG_ERROR("sql.sql", "CreatureTextMgr: Could not find TextGroup %u for Creature %s (Entry %u, GUID %u) in 'creature_text' table. Ignoring.", uint32(textGroup), source->GetName().c_str(), source->GetEntry(), source->GetGUID().GetCounter());
return 0;
}
@@ -224,13 +224,7 @@ uint32 CreatureTextMgr::SendChat(Creature* source, uint8 textGroup, WorldObject
if (tempGroup.empty())
{
- CreatureTextRepeatMap::iterator mapItr = mTextRepeatMap.find(source->GetGUID());
- if (mapItr != mTextRepeatMap.end())
- {
- CreatureTextRepeatGroup::iterator groupItr = mapItr->second.find(textGroup);
- groupItr->second.clear();
- }
-
+ source->ClearTextRepeatGroup(textGroup);
tempGroup = textGroupContainer;
}
@@ -299,7 +293,7 @@ uint32 CreatureTextMgr::SendChat(Creature* source, uint8 textGroup, WorldObject
SendChatPacket(finalSource, builder, finalType, whisperTarget, range, team, gmOnly);
}
- if (isEqualChanced || (!isEqualChanced && totalChance == 100.0f))
+ if (isEqualChanced || totalChance == 100.0f)
SetRepeatId(source, textGroup, iter->id);
return iter->duration;
@@ -426,26 +420,14 @@ void CreatureTextMgr::SetRepeatId(Creature* source, uint8 textGroup, uint8 id)
if (!source)
return;
- CreatureTextRepeatIds& repeats = mTextRepeatMap[source->GetGUID()][textGroup];
- if (std::find(repeats.begin(), repeats.end(), id) == repeats.end())
- repeats.push_back(id);
- else
- TC_LOG_ERROR("sql.sql", "CreatureTextMgr: TextGroup %u for Creature(%s) GuidLow %u Entry %u, id %u already added", uint32(textGroup), source->GetName().c_str(), source->GetGUIDLow(), source->GetEntry(), uint32(id));
+ source->SetTextRepeatId(textGroup, id);
}
CreatureTextRepeatIds CreatureTextMgr::GetRepeatGroup(Creature* source, uint8 textGroup)
{
ASSERT(source);//should never happen
- CreatureTextRepeatIds ids;
- CreatureTextRepeatMap::const_iterator mapItr = mTextRepeatMap.find(source->GetGUID());
- if (mapItr != mTextRepeatMap.end())
- {
- CreatureTextRepeatGroup::const_iterator groupItr = (*mapItr).second.find(textGroup);
- if (groupItr != mapItr->second.end())
- ids = groupItr->second;
- }
- return ids;
+ return source->GetTextRepeatGroup(textGroup);
}
bool CreatureTextMgr::TextExist(uint32 sourceEntry, uint8 textGroup)
diff --git a/src/server/game/Texts/CreatureTextMgr.h b/src/server/game/Texts/CreatureTextMgr.h
index 6ee1e82ce66..237aedd49d0 100644
--- a/src/server/game/Texts/CreatureTextMgr.h
+++ b/src/server/game/Texts/CreatureTextMgr.h
@@ -75,11 +75,6 @@ typedef std::unordered_map<uint32, CreatureTextHolder> CreatureTextMap; // a
typedef std::map<CreatureTextId, CreatureTextLocale> LocaleCreatureTextMap;
-//used for handling non-repeatable random texts
-typedef std::vector<uint8> CreatureTextRepeatIds;
-typedef std::unordered_map<uint8, CreatureTextRepeatIds> CreatureTextRepeatGroup;
-typedef std::unordered_map<ObjectGuid, CreatureTextRepeatGroup> CreatureTextRepeatMap;//guid based
-
class CreatureTextMgr
{
private:
@@ -115,7 +110,6 @@ class CreatureTextMgr
float GetRangeForChatType(ChatMsg msgType) const;
CreatureTextMap mTextMap;
- CreatureTextRepeatMap mTextRepeatMap;
LocaleCreatureTextMap mLocaleTextMap;
};
diff --git a/src/server/game/Tickets/TicketMgr.cpp b/src/server/game/Tickets/TicketMgr.cpp
index db37989bfc3..b4b3b8267c6 100644
--- a/src/server/game/Tickets/TicketMgr.cpp
+++ b/src/server/game/Tickets/TicketMgr.cpp
@@ -32,11 +32,11 @@ inline float GetAge(uint64 t) { return float(time(NULL) - t) / DAY; }
///////////////////////////////////////////////////////////////////////////////////////////////////
// GM ticket
-GmTicket::GmTicket() : _id(0), _posX(0), _posY(0), _posZ(0), _mapId(0), _createTime(0), _lastModifiedTime(0),
+GmTicket::GmTicket() : _id(0), _type(TICKET_TYPE_OPEN), _posX(0), _posY(0), _posZ(0), _mapId(0), _createTime(0), _lastModifiedTime(0),
_completed(false), _escalatedStatus(TICKET_UNASSIGNED), _viewed(false),
_needResponse(false), _needMoreHelp(false) { }
-GmTicket::GmTicket(Player* player) : _posX(0), _posY(0), _posZ(0), _mapId(0), _createTime(time(NULL)), _lastModifiedTime(time(NULL)),
+GmTicket::GmTicket(Player* player) : _type(TICKET_TYPE_OPEN), _posX(0), _posY(0), _posZ(0), _mapId(0), _createTime(time(NULL)), _lastModifiedTime(time(NULL)),
_completed(false), _escalatedStatus(TICKET_UNASSIGNED), _viewed(false),
_needResponse(false), _needMoreHelp(false)
{
@@ -49,11 +49,12 @@ GmTicket::~GmTicket() { }
bool GmTicket::LoadFromDB(Field* fields)
{
- // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
- // ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, haveTicket
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
+ // id, type, playerGuid, name, description, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, needMoreHelp
uint8 index = 0;
_id = fields[ index].GetUInt32();
- _playerGuid = ObjectGuid(HIGHGUID_PLAYER, fields[++index].GetUInt32());
+ _type = TicketType(fields[++index].GetUInt8());
+ _playerGuid = ObjectGuid(HighGuid::Player, fields[++index].GetUInt32());
_playerName = fields[++index].GetString();
_message = fields[++index].GetString();
_createTime = fields[++index].GetUInt32();
@@ -63,7 +64,7 @@ bool GmTicket::LoadFromDB(Field* fields)
_posZ = fields[++index].GetFloat();
_lastModifiedTime = fields[++index].GetUInt32();
_closedBy = ObjectGuid(uint64(fields[++index].GetInt32()));
- _assignedTo = ObjectGuid(HIGHGUID_PLAYER, fields[++index].GetUInt32());
+ _assignedTo = ObjectGuid(HighGuid::Player, fields[++index].GetUInt32());
_comment = fields[++index].GetString();
_response = fields[++index].GetString();
_completed = fields[++index].GetBool();
@@ -75,11 +76,12 @@ bool GmTicket::LoadFromDB(Field* fields)
void GmTicket::SaveToDB(SQLTransaction& trans) const
{
- // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
- // ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, completed, escalated, viewed
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
+ // id, type, playerGuid, name, description, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, needMoreHelp, resolvedBy
uint8 index = 0;
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_GM_TICKET);
stmt->setUInt32( index, _id);
+ stmt->setUInt8 (++index, uint8(_type));
stmt->setUInt32(++index, _playerGuid.GetCounter());
stmt->setString(++index, _playerName);
stmt->setString(++index, _message);
@@ -97,6 +99,7 @@ void GmTicket::SaveToDB(SQLTransaction& trans) const
stmt->setUInt8 (++index, uint8(_escalatedStatus));
stmt->setBool (++index, _viewed);
stmt->setBool (++index, _needMoreHelp);
+ stmt->setInt32 (++index, int32(_resolvedBy.GetCounter()));
CharacterDatabase.ExecuteOrAppend(trans, stmt);
}
@@ -296,7 +299,7 @@ void TicketMgr::LoadTickets()
PreparedQueryResult result = CharacterDatabase.Query(stmt);
if (!result)
{
- TC_LOG_INFO("server.loading", ">> Loaded 0 GM tickets. DB table `gm_tickets` is empty!");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 GM tickets. DB table `gm_ticket` is empty!");
return;
}
@@ -333,7 +336,7 @@ void TicketMgr::LoadSurveys()
_lastSurveyId = 0;
uint32 oldMSTime = getMSTime();
- if (QueryResult result = CharacterDatabase.Query("SELECT MAX(surveyId) FROM gm_surveys"))
+ if (QueryResult result = CharacterDatabase.Query("SELECT MAX(surveyId) FROM gm_survey"))
_lastSurveyId = (*result)[0].GetUInt32();
TC_LOG_INFO("server.loading", ">> Loaded GM Survey count from database in %u ms", GetMSTimeDiffToNow(oldMSTime));
@@ -361,6 +364,19 @@ void TicketMgr::CloseTicket(uint32 ticketId, ObjectGuid source)
}
}
+void TicketMgr::ResolveAndCloseTicket(uint32 ticketId, ObjectGuid source)
+{
+ if (GmTicket* ticket = GetTicket(ticketId))
+ {
+ SQLTransaction trans = SQLTransaction(nullptr);
+ ticket->SetClosedBy(source);
+ ticket->SetResolvedBy(source);
+ if (source)
+ --_openTicketCount;
+ ticket->SaveToDB(trans);
+ }
+}
+
void TicketMgr::RemoveTicket(uint32 ticketId)
{
if (GmTicket* ticket = GetTicket(ticketId))
diff --git a/src/server/game/Tickets/TicketMgr.h b/src/server/game/Tickets/TicketMgr.h
index e9892c22edc..a90a1ec0206 100644
--- a/src/server/game/Tickets/TicketMgr.h
+++ b/src/server/game/Tickets/TicketMgr.h
@@ -77,6 +77,13 @@ enum LagReportType
LAG_REPORT_TYPE_SPELL = 6
};
+enum TicketType
+{
+ TICKET_TYPE_OPEN = 0,
+ TICKET_TYPE_CLOSED = 1,
+ TICKET_TYPE_CHARACTER_DELETED = 2,
+};
+
class GmTicket
{
public:
@@ -84,7 +91,7 @@ public:
GmTicket(Player* player);
~GmTicket();
- bool IsClosed() const { return !_closedBy.IsEmpty(); }
+ bool IsClosed() const { return _type != TICKET_TYPE_OPEN; }
bool IsCompleted() const { return _completed; }
bool IsFromPlayer(ObjectGuid guid) const { return guid == _playerGuid; }
bool IsAssigned() const { return !_assignedTo.IsEmpty(); }
@@ -118,7 +125,8 @@ public:
else if (_escalatedStatus == TICKET_UNASSIGNED)
_escalatedStatus = TICKET_ASSIGNED;
}
- void SetClosedBy(ObjectGuid value) { _closedBy = value; }
+ void SetClosedBy(ObjectGuid value) { _closedBy = value; _type = TICKET_TYPE_CLOSED; }
+ void SetResolvedBy(ObjectGuid value) { _resolvedBy = value; }
void SetCompleted() { _completed = true; }
void SetMessage(std::string const& message)
{
@@ -149,6 +157,7 @@ public:
private:
uint32 _id;
+ TicketType _type; // 0 = Open, 1 = Closed, 2 = Character deleted
ObjectGuid _playerGuid;
std::string _playerName;
float _posX;
@@ -158,7 +167,8 @@ private:
std::string _message;
uint64 _createTime;
uint64 _lastModifiedTime;
- ObjectGuid _closedBy; // 0 = Open, -1 = Console, playerGuid = player abandoned ticket, other = GM who closed it.
+ ObjectGuid _closedBy; // 0 = Open or Closed by Console (if type = 1), playerGuid = GM who closed it or player abandoned ticket or read the GM response message.
+ ObjectGuid _resolvedBy; // 0 = Open or Resolved by Console (if type = 1), playerGuid = GM who resolved it by closing or completing the ticket.
ObjectGuid _assignedTo;
std::string _comment;
bool _completed;
@@ -216,6 +226,7 @@ public:
void AddTicket(GmTicket* ticket);
void CloseTicket(uint32 ticketId, ObjectGuid source);
+ void ResolveAndCloseTicket(uint32 ticketId, ObjectGuid source); // used when GM resolves a ticket by simply closing it
void RemoveTicket(uint32 ticketId);
bool GetStatus() const { return _status; }
diff --git a/src/server/game/Tools/CharacterDatabaseCleaner.cpp b/src/server/game/Tools/CharacterDatabaseCleaner.cpp
index 78bc1b799de..815212aa53d 100644
--- a/src/server/game/Tools/CharacterDatabaseCleaner.cpp
+++ b/src/server/game/Tools/CharacterDatabaseCleaner.cpp
@@ -147,7 +147,7 @@ bool CharacterDatabaseCleaner::TalentCheck(uint32 talent_id)
void CharacterDatabaseCleaner::CleanCharacterTalent()
{
- CharacterDatabase.DirectPExecute("DELETE FROM character_talent WHERE spec > %u", MAX_TALENT_SPECS);
+ CharacterDatabase.DirectPExecute("DELETE FROM character_talent WHERE talentGroup > %u", MAX_TALENT_SPECS);
CheckUnique("spell", "character_talent", &TalentCheck);
}
diff --git a/src/server/game/Tools/PlayerDump.cpp b/src/server/game/Tools/PlayerDump.cpp
index 83100d3fbec..0a47da1c788 100644
--- a/src/server/game/Tools/PlayerDump.cpp
+++ b/src/server/game/Tools/PlayerDump.cpp
@@ -21,6 +21,7 @@
#include "DatabaseEnv.h"
#include "UpdateFields.h"
#include "ObjectMgr.h"
+#include "Player.h"
#include "AccountMgr.h"
#include "World.h"
@@ -63,11 +64,15 @@ static DumpTable dumpTables[DUMP_TABLE_COUNT] =
};
// Low level functions
-static bool findtoknth(std::string &str, int n, std::string::size_type &s, std::string::size_type &e)
+static bool FindTokNth(std::string const& str, uint32 n, std::string::size_type& s, std::string::size_type& e)
{
- int i; s = e = 0;
- std::string::size_type size = str.size();
- for (i = 1; s < size && i < n; s++) if (str[s] == ' ') ++i;
+ s = e = 0;
+
+ uint32 i = 1;
+ for (; s < str.size() && i < n; ++s)
+ if (str[s] == ' ')
+ ++i;
+
if (i < n)
return false;
@@ -76,80 +81,86 @@ static bool findtoknth(std::string &str, int n, std::string::size_type &s, std::
return e != std::string::npos;
}
-std::string gettoknth(std::string &str, int n)
+std::string GetTokNth(std::string const& str, uint32 n)
{
std::string::size_type s = 0, e = 0;
- if (!findtoknth(str, n, s, e))
+ if (!FindTokNth(str, n, s, e))
return "";
- return str.substr(s, e-s);
+ return str.substr(s, e - s);
}
-bool findnth(std::string &str, int n, std::string::size_type &s, std::string::size_type &e)
+bool FindNth(std::string const& str, uint32 n, std::string::size_type& s, std::string::size_type& e)
{
- s = str.find("VALUES ('")+9;
- if (s == std::string::npos) return false;
+ s = str.find("VALUES ('") + 9;
+ if (s == std::string::npos)
+ return false;
do
{
e = str.find('\'', s);
- if (e == std::string::npos) return false;
- } while (str[e-1] == '\\');
+ if (e == std::string::npos)
+ return false;
+ } while (str[e - 1] == '\\');
- for (int i = 1; i < n; ++i)
+ for (uint32 i = 1; i < n; ++i)
{
do
{
- s = e+4;
+ s = e + 4;
e = str.find('\'', s);
- if (e == std::string::npos) return false;
- } while (str[e-1] == '\\');
+ if (e == std::string::npos)
+ return false;
+ } while (str[e - 1] == '\\');
}
return true;
}
-std::string gettablename(std::string &str)
+std::string GetTableName(std::string const& str)
{
- std::string::size_type s = 13;
+ static std::string::size_type const s = 13;
std::string::size_type e = str.find(_TABLE_SIM_, s);
if (e == std::string::npos)
return "";
- return str.substr(s, e-s);
+ return str.substr(s, e - s);
}
-bool changenth(std::string &str, int n, char const* with, bool insert = false, bool nonzero = false)
+bool ChangeNth(std::string& str, uint32 n, char const* with, bool insert = false, bool allowZero = false)
{
std::string::size_type s, e;
- if (!findnth(str, n, s, e))
+ if (!FindNth(str, n, s, e))
return false;
- if (nonzero && str.substr(s, e-s) == "0")
+ if (allowZero && str.substr(s, e - s) == "0")
return true; // not an error
+
if (!insert)
- str.replace(s, e-s, with);
+ str.replace(s, e - s, with);
else
str.insert(s, with);
return true;
}
-std::string getnth(std::string &str, int n)
+std::string GetNth(std::string& str, uint32 n)
{
std::string::size_type s, e;
- if (!findnth(str, n, s, e))
+ if (!FindNth(str, n, s, e))
return "";
return str.substr(s, e-s);
}
-bool changetoknth(std::string &str, int n, char const* with, bool insert = false, bool nonzero = false)
+bool ChangeTokNth(std::string& str, uint32 n, char const* with, bool insert = false, bool allowZero = false)
{
std::string::size_type s = 0, e = 0;
- if (!findtoknth(str, n, s, e))
+ if (!FindTokNth(str, n, s, e))
return false;
- if (nonzero && str.substr(s, e-s) == "0")
+
+ if (allowZero && str.substr(s, e - s) == "0")
return true; // not an error
+
if (!insert)
str.replace(s, e-s, with);
else
@@ -158,41 +169,28 @@ bool changetoknth(std::string &str, int n, char const* with, bool insert = false
return true;
}
-uint32 registerNewGuid(uint32 oldGuid, std::map<uint32, uint32> &guidMap, uint32 hiGuid)
+ObjectGuid::LowType RegisterNewGuid(ObjectGuid::LowType oldGuid, PlayerDump::DumpGuidMap& guidMap, ObjectGuid::LowType guidOffset)
{
- std::map<uint32, uint32>::const_iterator itr = guidMap.find(oldGuid);
+ PlayerDumpWriter::DumpGuidMap::const_iterator itr = guidMap.find(oldGuid);
if (itr != guidMap.end())
return itr->second;
- uint32 newguid = hiGuid + guidMap.size();
+ ObjectGuid::LowType newguid = guidOffset + guidMap.size();
guidMap[oldGuid] = newguid;
return newguid;
}
-bool changeGuid(std::string &str, int n, std::map<uint32, uint32> &guidMap, uint32 hiGuid, bool nonzero = false)
+bool ChangeGuid(std::string& str, uint32 n, PlayerDump::DumpGuidMap& guidMap, ObjectGuid::LowType guidOffset, bool allowZero = false)
{
- char chritem[20];
- uint32 oldGuid = atoi(getnth(str, n).c_str());
- if (nonzero && oldGuid == 0)
+ ObjectGuid::LowType oldGuid = strtoull(GetNth(str, n).c_str(), nullptr, 10);
+ if (allowZero && !oldGuid)
return true; // not an error
- uint32 newGuid = registerNewGuid(oldGuid, guidMap, hiGuid);
- snprintf(chritem, 20, "%u", newGuid);
-
- return changenth(str, n, chritem, false, nonzero);
-}
-
-bool changetokGuid(std::string &str, int n, std::map<uint32, uint32> &guidMap, uint32 hiGuid, bool nonzero = false)
-{
char chritem[20];
- uint32 oldGuid = atoi(gettoknth(str, n).c_str());
- if (nonzero && oldGuid == 0)
- return true; // not an error
-
- uint32 newGuid = registerNewGuid(oldGuid, guidMap, hiGuid);
+ ObjectGuid::LowType newGuid = RegisterNewGuid(oldGuid, guidMap, guidOffset);
snprintf(chritem, 20, "%u", newGuid);
- return changetoknth(str, n, chritem, false, nonzero);
+ return ChangeNth(str, n, chritem, false, allowZero);
}
std::string CreateDumpString(char const* tableName, QueryResult result)
@@ -216,57 +214,54 @@ std::string CreateDumpString(char const* tableName, QueryResult result)
return ss.str();
}
-std::string PlayerDumpWriter::GenerateWhereStr(char const* field, uint32 guid)
+std::string PlayerDumpWriter::GenerateWhereStr(char const* field, ObjectGuid::LowType guid)
{
std::ostringstream wherestr;
wherestr << field << " = '" << guid << '\'';
return wherestr.str();
}
-std::string PlayerDumpWriter::GenerateWhereStr(char const* field, GUIDs const& guids, GUIDs::const_iterator& itr)
+std::string PlayerDumpWriter::GenerateWhereStr(char const* field, DumpGuidSet const& guids, DumpGuidSet::const_iterator& itr)
{
std::ostringstream wherestr;
wherestr << field << " IN ('";
- for (; itr != guids.end(); ++itr)
+ for (; itr != guids.end();)
{
wherestr << *itr;
+ ++itr;
if (wherestr.str().size() > MAX_QUERY_LEN - 50) // near to max query
- {
- ++itr;
break;
- }
- GUIDs::const_iterator itr2 = itr;
- if (++itr2 != guids.end())
+ if (itr != guids.end())
wherestr << "', '";
}
wherestr << "')";
return wherestr.str();
}
-void StoreGUID(QueryResult result, uint32 field, std::set<uint32>& guids)
+void StoreGUID(QueryResult result, uint32 field, PlayerDump::DumpGuidSet &guids)
{
Field* fields = result->Fetch();
- uint32 guid = fields[field].GetUInt32();
+ ObjectGuid::LowType guid = fields[field].GetUInt32();
if (guid)
guids.insert(guid);
}
-void StoreGUID(QueryResult result, uint32 data, uint32 field, std::set<uint32>& guids)
+void StoreGUID(QueryResult result, uint32 data, uint32 field, PlayerDump::DumpGuidSet& guids)
{
Field* fields = result->Fetch();
std::string dataStr = fields[data].GetString();
- uint32 guid = atoi(gettoknth(dataStr, field).c_str());
+ ObjectGuid::LowType guid = strtoull(GetTokNth(dataStr, field).c_str(), nullptr, 10);
if (guid)
guids.insert(guid);
}
// Writing - High-level functions
-bool PlayerDumpWriter::DumpTable(std::string& dump, uint32 guid, char const*tableFrom, char const*tableTo, DumpTableType type)
+bool PlayerDumpWriter::DumpTable(std::string& dump, ObjectGuid::LowType guid, char const* tableFrom, char const* tableTo, DumpTableType type)
{
- GUIDs const* guids = NULL;
- char const* fieldname = NULL;
+ DumpGuidSet const* guids = nullptr;
+ char const* fieldname = nullptr;
switch (type)
{
@@ -281,20 +276,20 @@ bool PlayerDumpWriter::DumpTable(std::string& dump, uint32 guid, char const*tabl
// for guid set stop if set is empty
if (guids && guids->empty())
- return true; // nothing to do
+ return true; // nothing to do
// setup for guids case start position
- GUIDs::const_iterator guids_itr;
+ DumpGuidSet::const_iterator guidsItr;
if (guids)
- guids_itr = guids->begin();
+ guidsItr = guids->begin();
do
{
std::string wherestr;
- if (guids) // set case, get next guids string
- wherestr = GenerateWhereStr(fieldname, *guids, guids_itr);
- else // not set case, get single guid string
+ if (guids) // set case, get next guids string
+ wherestr = GenerateWhereStr(fieldname, *guids, guidsItr);
+ else // not set case, get single guid string
wherestr = GenerateWhereStr(fieldname, guid);
QueryResult result = CharacterDatabase.PQuery("SELECT * FROM %s WHERE %s", tableFrom, wherestr.c_str());
@@ -336,16 +331,16 @@ bool PlayerDumpWriter::DumpTable(std::string& dump, uint32 guid, char const*tabl
}
while (result->NextRow());
}
- while (guids && guids_itr != guids->end()); // not set case iterate single time, set case iterate for all guids
+ while (guids && guidsItr != guids->end()); // not set case iterate single time, set case iterate for all guids
return true;
}
-bool PlayerDumpWriter::GetDump(uint32 guid, std::string &dump)
+bool PlayerDumpWriter::GetDump(ObjectGuid::LowType guid, std::string &dump)
{
dump = "IMPORTANT NOTE: THIS DUMPFILE IS MADE FOR USE WITH THE 'PDUMP' COMMAND ONLY - EITHER THROUGH INGAME CHAT OR ON CONSOLE!\n";
dump += "IMPORTANT NOTE: DO NOT apply it directly - it will irreversibly DAMAGE and CORRUPT your database! You have been warned!\n\n";
- for (int i = 0; i < DUMP_TABLE_COUNT; ++i)
+ for (uint8 i = 0; i < DUMP_TABLE_COUNT; ++i)
if (!DumpTable(dump, guid, dumpTables[i].name, dumpTables[i].name, dumpTables[i].type))
return false;
@@ -355,17 +350,19 @@ bool PlayerDumpWriter::GetDump(uint32 guid, std::string &dump)
return true;
}
-DumpReturn PlayerDumpWriter::WriteDump(const std::string& file, uint32 guid)
+DumpReturn PlayerDumpWriter::WriteDump(const std::string& file, ObjectGuid::LowType guid)
{
if (sWorld->getBoolConfig(CONFIG_PDUMP_NO_PATHS))
if (strstr(file.c_str(), "\\") || strstr(file.c_str(), "/"))
return DUMP_FILE_OPEN_ERROR;
+
if (sWorld->getBoolConfig(CONFIG_PDUMP_NO_OVERWRITE))
if (FILE* f = fopen(file.c_str(), "r"))
{
fclose(f);
return DUMP_FILE_OPEN_ERROR;
}
+
FILE* fout = fopen(file.c_str(), "w");
if (!fout)
return DUMP_FILE_OPEN_ERROR;
@@ -383,9 +380,9 @@ DumpReturn PlayerDumpWriter::WriteDump(const std::string& file, uint32 guid)
// Reading - High-level functions
#define ROLLBACK(DR) {fclose(fin); return (DR);}
-void fixNULLfields(std::string &line)
+void fixNULLfields(std::string& line)
{
- std::string nullString("'NULL'");
+ static std::string const nullString("'NULL'");
size_t pos = line.find(nullString);
while (pos != std::string::npos)
{
@@ -394,7 +391,7 @@ void fixNULLfields(std::string &line)
}
}
-DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, std::string name, uint32 guid)
+DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, std::string name, ObjectGuid::LowType guid)
{
uint32 charcount = AccountMgr::GetCharactersCount(account);
if (charcount >= 10)
@@ -404,28 +401,32 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s
if (!fin)
return DUMP_FILE_OPEN_ERROR;
- char newguid[20], chraccount[20], newpetid[20], currpetid[20], lastpetid[20];
+ char newguid[20], chraccount[20];
// make sure the same guid doesn't already exist and is safe to use
bool incHighest = true;
- if (guid != 0 && guid < sObjectMgr->_hiCharGuid)
+ if (guid && guid < sObjectMgr->GetGenerator<HighGuid::Player>().GetNextAfterMaxUsed())
+
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_GUID);
stmt->setUInt32(0, guid);
PreparedQueryResult result = CharacterDatabase.Query(stmt);
if (result)
- guid = sObjectMgr->_hiCharGuid; // use first free if exists
- else incHighest = false;
+ guid = sObjectMgr->GetGenerator<HighGuid::Player>().GetNextAfterMaxUsed(); // use first free if exists
+
+ else
+ incHighest = false;
}
else
- guid = sObjectMgr->_hiCharGuid;
+ guid = sObjectMgr->GetGenerator<HighGuid::Player>().GetNextAfterMaxUsed();
+
// normalize the name if specified and check if it exists
if (!normalizePlayerName(name))
name.clear();
- if (ObjectMgr::CheckPlayerName(name, true) == CHAR_NAME_SUCCESS)
+ if (ObjectMgr::CheckPlayerName(name, sWorld->GetDefaultDbcLocale(), true) == CHAR_NAME_SUCCESS)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME);
stmt->setString(0, name);
@@ -441,22 +442,22 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s
snprintf(newguid, 20, "%u", guid);
snprintf(chraccount, 20, "%u", account);
- snprintf(newpetid, 20, "%u", sObjectMgr->GeneratePetNumber());
- snprintf(lastpetid, 20, "%s", "");
- std::map<uint32, uint32> items;
- std::map<uint32, uint32> mails;
- char buf[32000] = "";
+ DumpGuidMap items;
+ DumpGuidMap mails;
+ char buf[32000];
+ memset(buf, 0, sizeof(buf));
- typedef std::map<uint32, uint32> PetIds; // old->new petid relation
- typedef PetIds::value_type PetIdsPair;
- PetIds petids;
+ typedef std::map<uint32 /*old*/, uint32 /*new*/> PetIds;
+ PetIds petIds;
uint8 gender = GENDER_NONE;
uint8 race = RACE_NONE;
uint8 playerClass = 0;
uint8 level = 1;
+ ObjectGuid::LowType itemLowGuidOffset = sObjectMgr->GetGenerator<HighGuid::Item>().GetNextAfterMaxUsed();
+
SQLTransaction trans = CharacterDatabase.BeginTransaction();
while (!feof(fin))
{
@@ -492,7 +493,7 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s
*/
// determine table name and load type
- std::string tn = gettablename(line);
+ std::string tn = GetTableName(line);
if (tn.empty())
{
TC_LOG_ERROR("misc", "LoadPlayerDump: Can't extract table name from line: '%s'!", line.c_str());
@@ -521,142 +522,139 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s
{
case DTT_CHARACTER:
{
- if (!changenth(line, 1, newguid)) // characters.guid update
+ if (!ChangeNth(line, 1, newguid)) // characters.guid update
ROLLBACK(DUMP_FILE_BROKEN);
- if (!changenth(line, 2, chraccount)) // characters.account update
+ if (!ChangeNth(line, 2, chraccount)) // characters.account update
ROLLBACK(DUMP_FILE_BROKEN);
- race = uint8(atoul(getnth(line, 4).c_str()));
- playerClass = uint8(atoul(getnth(line, 5).c_str()));
- gender = uint8(atoul(getnth(line, 6).c_str()));
- level = uint8(atoul(getnth(line, 7).c_str()));
+ race = uint8(atoul(GetNth(line, 4).c_str()));
+ playerClass = uint8(atoul(GetNth(line, 5).c_str()));
+ gender = uint8(atoul(GetNth(line, 6).c_str()));
+ level = uint8(atoul(GetNth(line, 7).c_str()));
if (name.empty())
{
// check if the original name already exists
- name = getnth(line, 3);
+ name = GetNth(line, 3);
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME);
stmt->setString(0, name);
PreparedQueryResult result = CharacterDatabase.Query(stmt);
if (result)
- if (!changenth(line, 37, "1")) // characters.at_login set to "rename on login"
+ if (!ChangeNth(line, 37, "1")) // characters.at_login set to "rename on login"
ROLLBACK(DUMP_FILE_BROKEN);
}
- else if (!changenth(line, 3, name.c_str())) // characters.name
+ else if (!ChangeNth(line, 3, name.c_str())) // characters.name
ROLLBACK(DUMP_FILE_BROKEN);
const char null[5] = "NULL";
- if (!changenth(line, 69, null)) // characters.deleteInfos_Account
+ if (!ChangeNth(line, 69, null)) // characters.deleteInfos_Account
ROLLBACK(DUMP_FILE_BROKEN);
- if (!changenth(line, 70, null)) // characters.deleteInfos_Name
+ if (!ChangeNth(line, 70, null)) // characters.deleteInfos_Name
ROLLBACK(DUMP_FILE_BROKEN);
- if (!changenth(line, 71, null)) // characters.deleteDate
+ if (!ChangeNth(line, 71, null)) // characters.deleteDate
ROLLBACK(DUMP_FILE_BROKEN);
break;
}
case DTT_CHAR_TABLE:
{
- if (!changenth(line, 1, newguid)) // character_*.guid update
+ if (!ChangeNth(line, 1, newguid)) // character_*.guid update
ROLLBACK(DUMP_FILE_BROKEN);
break;
}
case DTT_EQSET_TABLE:
{
- if (!changenth(line, 1, newguid))
+ if (!ChangeNth(line, 1, newguid))
ROLLBACK(DUMP_FILE_BROKEN); // character_equipmentsets.guid
char newSetGuid[24];
snprintf(newSetGuid, 24, UI64FMTD, sObjectMgr->GenerateEquipmentSetGuid());
- if (!changenth(line, 2, newSetGuid))
+ if (!ChangeNth(line, 2, newSetGuid))
ROLLBACK(DUMP_FILE_BROKEN); // character_equipmentsets.setguid
+
+ for (uint8 slot = 0; slot < EQUIPMENT_SLOT_END; ++slot)
+ if (!ChangeGuid(line, 7 + slot, items, itemLowGuidOffset, true))
+ ROLLBACK(DUMP_FILE_BROKEN); // character_equipmentsets.item
break;
}
case DTT_INVENTORY:
{
- if (!changenth(line, 1, newguid)) // character_inventory.guid update
+ if (!ChangeNth(line, 1, newguid)) // character_inventory.guid update
ROLLBACK(DUMP_FILE_BROKEN);
- if (!changeGuid(line, 2, items, sObjectMgr->_hiItemGuid, true))
+ if (!ChangeGuid(line, 2, items, itemLowGuidOffset, true))
ROLLBACK(DUMP_FILE_BROKEN); // character_inventory.bag update
- if (!changeGuid(line, 4, items, sObjectMgr->_hiItemGuid))
+ if (!ChangeGuid(line, 4, items, itemLowGuidOffset))
ROLLBACK(DUMP_FILE_BROKEN); // character_inventory.item update
break;
}
case DTT_MAIL: // mail
{
- if (!changeGuid(line, 1, mails, sObjectMgr->_mailId))
+ if (!ChangeGuid(line, 1, mails, sObjectMgr->_mailId))
ROLLBACK(DUMP_FILE_BROKEN); // mail.id update
- if (!changenth(line, 6, newguid)) // mail.receiver update
+ if (!ChangeNth(line, 6, newguid)) // mail.receiver update
ROLLBACK(DUMP_FILE_BROKEN);
break;
}
case DTT_MAIL_ITEM: // mail_items
{
- if (!changeGuid(line, 1, mails, sObjectMgr->_mailId))
+ if (!ChangeGuid(line, 1, mails, sObjectMgr->_mailId))
ROLLBACK(DUMP_FILE_BROKEN); // mail_items.id
- if (!changeGuid(line, 2, items, sObjectMgr->_hiItemGuid))
+ if (!ChangeGuid(line, 2, items, itemLowGuidOffset))
ROLLBACK(DUMP_FILE_BROKEN); // mail_items.item_guid
- if (!changenth(line, 3, newguid)) // mail_items.receiver
+ if (!ChangeNth(line, 3, newguid)) // mail_items.receiver
ROLLBACK(DUMP_FILE_BROKEN);
break;
}
case DTT_ITEM:
{
// item, owner, data field:item, owner guid
- if (!changeGuid(line, 1, items, sObjectMgr->_hiItemGuid))
+ if (!ChangeGuid(line, 1, items, itemLowGuidOffset))
ROLLBACK(DUMP_FILE_BROKEN); // item_instance.guid update
- if (!changenth(line, 3, newguid)) // item_instance.owner_guid update
+ if (!ChangeNth(line, 3, newguid)) // item_instance.owner_guid update
ROLLBACK(DUMP_FILE_BROKEN);
break;
}
case DTT_ITEM_GIFT:
{
- if (!changenth(line, 1, newguid)) // character_gifts.guid update
+ if (!ChangeNth(line, 1, newguid)) // character_gifts.guid update
ROLLBACK(DUMP_FILE_BROKEN);
- if (!changeGuid(line, 2, items, sObjectMgr->_hiItemGuid))
+ if (!ChangeGuid(line, 2, items, itemLowGuidOffset))
ROLLBACK(DUMP_FILE_BROKEN); // character_gifts.item_guid update
break;
}
case DTT_PET:
{
- //store a map of old pet id to new inserted pet id for use by type 5 tables
- snprintf(currpetid, 20, "%s", getnth(line, 1).c_str());
- if (*lastpetid == '\0')
- snprintf(lastpetid, 20, "%s", currpetid);
- if (strcmp(lastpetid, currpetid) != 0)
- {
- snprintf(newpetid, 20, "%u", sObjectMgr->GeneratePetNumber());
- snprintf(lastpetid, 20, "%s", currpetid);
- }
+ // store a map of old pet id to new inserted pet id for use by DTT_PET_TABLE tables
+ std::string petIdStr = GetNth(line, 1);
- std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid));
+ uint32 currentPetId = atoul(petIdStr.c_str());
- if (petids_iter == petids.end())
- {
- petids.insert(PetIdsPair(atoi(currpetid), atoi(newpetid)));
- }
+ PetIds::const_iterator petIdsItr = petIds.find(currentPetId);
+ if (petIdsItr != petIds.end()) // duplicate pets
+ ROLLBACK(DUMP_FILE_BROKEN);
- if (!changenth(line, 1, newpetid)) // character_pet.id update
+ uint32 newPetId = sObjectMgr->GeneratePetNumber();
+ petIds[currentPetId] = newPetId;
+
+ if (!ChangeNth(line, 1, std::to_string(newPetId).c_str())) // character_pet.id update
ROLLBACK(DUMP_FILE_BROKEN);
- if (!changenth(line, 3, newguid)) // character_pet.owner update
+ if (!ChangeNth(line, 3, newguid)) // character_pet.owner update
ROLLBACK(DUMP_FILE_BROKEN);
break;
}
case DTT_PET_TABLE: // pet_aura, pet_spell, pet_spell_cooldown
{
- snprintf(currpetid, 20, "%s", getnth(line, 1).c_str());
+ std::string petIdStr = GetNth(line, 1);
// lookup currpetid and match to new inserted pet id
- std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid));
- if (petids_iter == petids.end()) // couldn't find new inserted id
+ PetIds::const_iterator petIdsItr = petIds.find(atoul(petIdStr.c_str()));
+ if (petIdsItr == petIds.end()) // couldn't find new inserted id
ROLLBACK(DUMP_FILE_BROKEN);
- snprintf(newpetid, 20, "%d", petids_iter->second);
-
- if (!changenth(line, 1, newpetid))
+ if (!ChangeNth(line, 1, std::to_string(petIdsItr->second).c_str()))
ROLLBACK(DUMP_FILE_BROKEN);
break;
@@ -674,13 +672,15 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s
CharacterDatabase.CommitTransaction(trans);
// in case of name conflict player has to rename at login anyway
- sWorld->AddCharacterNameData(ObjectGuid(HIGHGUID_PLAYER, guid), name, gender, race, playerClass, level);
+ sWorld->AddCharacterInfo(ObjectGuid(HighGuid::Player, guid), account, name, gender, race, playerClass, level);
+
+ sObjectMgr->GetGenerator<HighGuid::Item>().Set(sObjectMgr->GetGenerator<HighGuid::Item>().GetNextAfterMaxUsed() + items.size());
- sObjectMgr->_hiItemGuid += items.size();
sObjectMgr->_mailId += mails.size();
if (incHighest)
- ++sObjectMgr->_hiCharGuid;
+ sObjectMgr->GetGenerator<HighGuid::Player>().Generate();
+
fclose(fin);
diff --git a/src/server/game/Tools/PlayerDump.h b/src/server/game/Tools/PlayerDump.h
index 5a26c10b7d8..5cdcc4b6bb8 100644
--- a/src/server/game/Tools/PlayerDump.h
+++ b/src/server/game/Tools/PlayerDump.h
@@ -22,6 +22,7 @@
#include <string>
#include <map>
#include <set>
+#include "ObjectGuid.h"
enum DumpTableType
{
@@ -63,6 +64,10 @@ enum DumpReturn
class PlayerDump
{
+ public:
+ typedef std::set<ObjectGuid::LowType> DumpGuidSet;
+ typedef std::map<ObjectGuid::LowType, ObjectGuid::LowType> DumpGuidMap;
+
protected:
PlayerDump() { }
};
@@ -72,18 +77,17 @@ class PlayerDumpWriter : public PlayerDump
public:
PlayerDumpWriter() { }
- bool GetDump(uint32 guid, std::string& dump);
- DumpReturn WriteDump(std::string const& file, uint32 guid);
- private:
- typedef std::set<uint32> GUIDs;
+ bool GetDump(ObjectGuid::LowType guid, std::string& dump);
+ DumpReturn WriteDump(std::string const& file, ObjectGuid::LowType guid);
- bool DumpTable(std::string& dump, uint32 guid, char const*tableFrom, char const*tableTo, DumpTableType type);
- std::string GenerateWhereStr(char const* field, GUIDs const& guids, GUIDs::const_iterator& itr);
- std::string GenerateWhereStr(char const* field, uint32 guid);
+ private:
+ bool DumpTable(std::string& dump, ObjectGuid::LowType guid, char const* tableFrom, char const* tableTo, DumpTableType type);
+ std::string GenerateWhereStr(char const* field, DumpGuidSet const& guids, DumpGuidSet::const_iterator& itr);
+ std::string GenerateWhereStr(char const* field, ObjectGuid::LowType guid);
- GUIDs pets;
- GUIDs mails;
- GUIDs items;
+ DumpGuidSet pets;
+ DumpGuidSet mails;
+ DumpGuidSet items;
};
class PlayerDumpReader : public PlayerDump
@@ -91,7 +95,7 @@ class PlayerDumpReader : public PlayerDump
public:
PlayerDumpReader() { }
- DumpReturn LoadDump(std::string const& file, uint32 account, std::string name, uint32 guid);
+ DumpReturn LoadDump(std::string const& file, uint32 account, std::string name, ObjectGuid::LowType guid);
};
#endif
diff --git a/src/server/game/Warden/Warden.cpp b/src/server/game/Warden/Warden.cpp
index ecf7697db0d..69facc6895b 100644
--- a/src/server/game/Warden/Warden.cpp
+++ b/src/server/game/Warden/Warden.cpp
@@ -22,12 +22,13 @@
#include "Log.h"
#include "Opcodes.h"
#include "ByteBuffer.h"
-#include <openssl/sha.h>
#include "World.h"
#include "Util.h"
#include "Warden.h"
#include "AccountMgr.h"
+#include <openssl/sha.h>
+
Warden::Warden() : _session(NULL), _inputCrypto(16), _outputCrypto(16), _checkTimer(10000/*10 sec*/), _clientResponseTimer(0),
_dataSent(false), _previousTimestamp(0), _module(NULL), _initialized(false)
{
diff --git a/src/server/game/Warden/WardenMac.cpp b/src/server/game/Warden/WardenMac.cpp
index 2eccd4c46ff..8abd48bd3f7 100644
--- a/src/server/game/Warden/WardenMac.cpp
+++ b/src/server/game/Warden/WardenMac.cpp
@@ -23,13 +23,14 @@
#include "Log.h"
#include "Opcodes.h"
#include "ByteBuffer.h"
-#include <openssl/md5.h>
#include "World.h"
#include "Player.h"
#include "Util.h"
#include "WardenMac.h"
#include "WardenModuleMac.h"
+#include <openssl/md5.h>
+
WardenMac::WardenMac() : Warden() { }
WardenMac::~WardenMac() { }
diff --git a/src/server/game/Warden/WardenWin.cpp b/src/server/game/Warden/WardenWin.cpp
index 7db5e8f39e5..2fe11a7eeed 100644
--- a/src/server/game/Warden/WardenWin.cpp
+++ b/src/server/game/Warden/WardenWin.cpp
@@ -24,7 +24,6 @@
#include "Log.h"
#include "Opcodes.h"
#include "ByteBuffer.h"
-#include <openssl/md5.h>
#include "Database/DatabaseEnv.h"
#include "World.h"
#include "Player.h"
@@ -32,6 +31,7 @@
#include "WardenWin.h"
#include "WardenModuleWin.h"
#include "WardenCheckMgr.h"
+#include <openssl/md5.h>
WardenWin::WardenWin() : Warden(), _serverTicks(0) {}
diff --git a/src/server/game/Weather/WeatherMgr.cpp b/src/server/game/Weather/WeatherMgr.cpp
index 9100dd464b9..ff55d2d9a27 100644
--- a/src/server/game/Weather/WeatherMgr.cpp
+++ b/src/server/game/Weather/WeatherMgr.cpp
@@ -25,7 +25,6 @@
#include "Log.h"
#include "ObjectMgr.h"
#include "Player.h"
-#include "WorldPacket.h"
#include "WorldSession.h"
namespace WeatherMgr
@@ -132,7 +131,7 @@ void LoadWeatherData()
}
}
- wzc.ScriptId = sObjectMgr->GetScriptId(fields[13].GetCString());
+ wzc.ScriptId = sObjectMgr->GetScriptId(fields[13].GetString());
++count;
}
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 5f54154fab1..c41caa8f955 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -51,11 +51,11 @@
#include "OutdoorPvPMgr.h"
#include "Player.h"
#include "PoolMgr.h"
+#include "GitRevision.h"
#include "ScriptMgr.h"
#include "SkillDiscovery.h"
#include "SkillExtraItems.h"
#include "SmartAI.h"
-#include "SystemConfig.h"
#include "TicketMgr.h"
#include "TransportMgr.h"
#include "Unit.h"
@@ -269,10 +269,7 @@ void World::AddSession_(WorldSession* s)
return;
}
- s->SendAuthResponse(AUTH_OK, true);
- s->SendAddonsInfo();
- s->SendClientCacheVersion(sWorld->getIntConfig(CONFIG_CLIENTCACHE_VERSION));
- s->SendTutorialsData();
+ s->InitializeSession();
UpdateMaxSessionCounters();
@@ -362,15 +359,7 @@ bool World::RemoveQueuedPlayer(WorldSession* sess)
if ((!m_playerLimit || sessions < m_playerLimit) && !m_QueuedPlayer.empty())
{
WorldSession* pop_sess = m_QueuedPlayer.front();
- pop_sess->SetInQueue(false);
- pop_sess->ResetTimeOutTime();
- pop_sess->SendAuthWaitQue(0);
- pop_sess->SendAddonsInfo();
-
- pop_sess->SendClientCacheVersion(sWorld->getIntConfig(CONFIG_CLIENTCACHE_VERSION));
- pop_sess->SendAccountDataTimes(GLOBAL_CACHE_MASK);
- pop_sess->SendTutorialsData();
-
+ pop_sess->InitializeSession();
m_QueuedPlayer.pop_front();
// update iter to point first queued socket or end() if queue is empty now
@@ -406,6 +395,7 @@ void World::LoadConfigSettings(bool reload)
///- Read ticket system setting from the config file
m_bool_configs[CONFIG_ALLOW_TICKETS] = sConfigMgr->GetBoolDefault("AllowTickets", true);
+ m_bool_configs[CONFIG_DELETE_CHARACTER_TICKET_TRACE] = sConfigMgr->GetBoolDefault("DeletedCharacterTicketTrace", false);
///- Get string for new logins (newly created characters)
SetNewCharString(sConfigMgr->GetStringDefault("PlayerStart.String", ""));
@@ -456,6 +446,7 @@ void World::LoadConfigSettings(bool reload)
rate_values[RATE_DROP_ITEM_REFERENCED_AMOUNT] = sConfigMgr->GetFloatDefault("Rate.Drop.Item.ReferencedAmount", 1.0f);
rate_values[RATE_DROP_MONEY] = sConfigMgr->GetFloatDefault("Rate.Drop.Money", 1.0f);
rate_values[RATE_XP_KILL] = sConfigMgr->GetFloatDefault("Rate.XP.Kill", 1.0f);
+ rate_values[RATE_XP_BG_KILL] = sConfigMgr->GetFloatDefault("Rate.XP.BattlegroundKill", 1.0f);
rate_values[RATE_XP_QUEST] = sConfigMgr->GetFloatDefault("Rate.XP.Quest", 1.0f);
rate_values[RATE_XP_EXPLORE] = sConfigMgr->GetFloatDefault("Rate.XP.Explore", 1.0f);
rate_values[RATE_REPAIRCOST] = sConfigMgr->GetFloatDefault("Rate.RepairCost", 1.0f);
@@ -1037,6 +1028,7 @@ void World::LoadConfigSettings(bool reload)
m_bool_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE] = sConfigMgr->GetBoolDefault("Battleground.QueueAnnouncer.Enable", false);
m_bool_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY] = sConfigMgr->GetBoolDefault("Battleground.QueueAnnouncer.PlayerOnly", false);
m_bool_configs[CONFIG_BATTLEGROUND_STORE_STATISTICS_ENABLE] = sConfigMgr->GetBoolDefault("Battleground.StoreStatistics.Enable", false);
+ m_bool_configs[CONFIG_BATTLEGROUND_TRACK_DESERTERS] = sConfigMgr->GetBoolDefault("Battleground.TrackDeserters.Enable", false);
m_int_configs[CONFIG_BATTLEGROUND_INVITATION_TYPE] = sConfigMgr->GetIntDefault ("Battleground.InvitationType", 0);
m_int_configs[CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER] = sConfigMgr->GetIntDefault ("Battleground.PrematureFinishTimer", 5 * MINUTE * IN_MILLISECONDS);
m_int_configs[CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH] = sConfigMgr->GetIntDefault ("Battleground.PremadeGroupWaitForMatch", 30 * MINUTE * IN_MILLISECONDS);
@@ -1190,6 +1182,8 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_MAX_WHO] = sConfigMgr->GetIntDefault("MaxWhoListReturns", 49);
m_bool_configs[CONFIG_START_ALL_SPELLS] = sConfigMgr->GetBoolDefault("PlayerStart.AllSpells", false);
m_int_configs[CONFIG_HONOR_AFTER_DUEL] = sConfigMgr->GetIntDefault("HonorPointsAfterDuel", 0);
+ m_bool_configs[CONFIG_RESET_DUEL_COOLDOWNS] = sConfigMgr->GetBoolDefault("ResetDuelCooldowns", false);
+ m_bool_configs[CONFIG_RESET_DUEL_HEALTH_MANA] = sConfigMgr->GetBoolDefault("ResetDuelHealthMana", false);
m_bool_configs[CONFIG_START_ALL_EXPLORED] = sConfigMgr->GetBoolDefault("PlayerStart.MapsExplored", false);
m_bool_configs[CONFIG_START_ALL_REP] = sConfigMgr->GetBoolDefault("PlayerStart.AllReputation", false);
m_bool_configs[CONFIG_ALWAYS_MAXSKILL] = sConfigMgr->GetBoolDefault("AlwaysMaxWeaponSkill", false);
@@ -1299,7 +1293,7 @@ void World::LoadConfigSettings(bool reload)
sScriptMgr->OnConfigLoad(reload);
}
-extern void LoadGameObjectModelList();
+extern void LoadGameObjectModelList(std::string const& dataPath);
/// Initialize the World
void World::SetInitialWorldSettings()
@@ -1365,16 +1359,22 @@ void World::SetInitialWorldSettings()
LoginDatabase.PExecute("UPDATE realmlist SET icon = %u, timezone = %u WHERE id = '%d'", server_type, realm_zone, realmID); // One-time query
- ///- Remove the bones (they should not exist in DB though) and old corpses after a restart
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_OLD_CORPSES);
- stmt->setUInt32(0, 3 * DAY);
- CharacterDatabase.Execute(stmt);
-
///- Load the DBC files
TC_LOG_INFO("server.loading", "Initialize data stores...");
LoadDBCStores(m_dataPath);
DetectDBCLang();
+ std::vector<uint32> mapIds;
+ for (uint32 mapId = 0; mapId < sMapStore.GetNumRows(); mapId++)
+ if (sMapStore.LookupEntry(mapId))
+ mapIds.push_back(mapId);
+
+ if (VMAP::VMapManager2* vmmgr2 = dynamic_cast<VMAP::VMapManager2*>(VMAP::VMapFactory::createOrGetVMapManager()))
+ vmmgr2->InitializeThreadUnsafe(mapIds);
+
+ MMAP::MMapManager* mmmgr = MMAP::MMapFactory::createOrGetMMapManager();
+ mmmgr->InitializeThreadUnsafe(mapIds);
+
TC_LOG_INFO("server.loading", "Loading SpellInfo store...");
sSpellMgr->LoadSpellInfoStore();
@@ -1388,7 +1388,7 @@ void World::SetInitialWorldSettings()
sSpellMgr->LoadSpellInfoCustomAttributes();
TC_LOG_INFO("server.loading", "Loading GameObject models...");
- LoadGameObjectModelList();
+ LoadGameObjectModelList(m_dataPath);
TC_LOG_INFO("server.loading", "Loading Script Names...");
sObjectMgr->LoadScriptNames();
@@ -1523,10 +1523,16 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading Gameobject Data...");
sObjectMgr->LoadGameobjects();
-
+
TC_LOG_INFO("server.loading", "Loading GameObject Addon Data...");
sObjectMgr->LoadGameObjectAddons(); // must be after LoadGameObjectTemplate() and LoadGameobjects()
+ TC_LOG_INFO("server.loading", "Loading GameObject Quest Items...");
+ sObjectMgr->LoadGameObjectQuestItems();
+
+ TC_LOG_INFO("server.loading", "Loading Creature Quest Items...");
+ sObjectMgr->LoadCreatureQuestItems();
+
TC_LOG_INFO("server.loading", "Loading Creature Linked Respawn...");
sObjectMgr->LoadLinkedRespawn(); // must be after LoadCreatures(), LoadGameObjects()
@@ -1619,9 +1625,6 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading pet level stats...");
sObjectMgr->LoadPetLevelInfo();
- TC_LOG_INFO("server.loading", "Loading Player Corpses...");
- sObjectMgr->LoadCorpses();
-
TC_LOG_INFO("server.loading", "Loading Player level dependent mail rewards...");
sObjectMgr->LoadMailLevelRewards();
@@ -1634,6 +1637,9 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading Skill Extra Item Table...");
LoadSkillExtraItemTable();
+ TC_LOG_INFO("server.loading", "Loading Skill Perfection Data Table...");
+ LoadSkillPerfectItemTable();
+
TC_LOG_INFO("server.loading", "Loading Skill Fishing base level requirements...");
sObjectMgr->LoadFishingBaseSkillLevel();
@@ -1711,6 +1717,9 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading faction change spell pairs...");
sObjectMgr->LoadFactionChangeSpells();
+ TC_LOG_INFO("server.loading", "Loading faction change quest pairs...");
+ sObjectMgr->LoadFactionChangeQuests();
+
TC_LOG_INFO("server.loading", "Loading faction change item pairs...");
sObjectMgr->LoadFactionChangeItems();
@@ -1769,7 +1778,7 @@ void World::SetInitialWorldSettings()
m_startTime = m_gameTime;
LoginDatabase.PExecute("INSERT INTO uptime (realmid, starttime, uptime, revision) VALUES(%u, %u, 0, '%s')",
- realmID, uint32(m_startTime), _FULLVERSION); // One-time query
+ realmID, uint32(m_startTime), GitRevision::GetFullVersion()); // One-time query
m_timers[WUPDATE_WEATHERS].SetInterval(1*IN_MILLISECONDS);
m_timers[WUPDATE_AUCTIONS].SetInterval(MINUTE*IN_MILLISECONDS);
@@ -1864,7 +1873,7 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Calculate guild limitation(s) reset time...");
InitGuildResetTime();
- LoadCharacterNameData();
+ LoadCharacterInfoStore();
uint32 startupDuration = GetMSTimeDiffToNow(startupBegin);
@@ -2138,7 +2147,10 @@ void World::Update(uint32 diff)
if (m_timers[WUPDATE_CORPSES].Passed())
{
m_timers[WUPDATE_CORPSES].Reset();
- sObjectAccessor->RemoveOldCorpses();
+ sMapMgr->DoForAllMaps([](Map* map)
+ {
+ map->RemoveOldCorpses();
+ });
}
///- Process Game events when necessary
@@ -2489,7 +2501,7 @@ bool World::RemoveBanAccount(BanMode mode, std::string const& nameOrIP)
BanReturn World::BanCharacter(std::string const& name, std::string const& duration, std::string const& reason, std::string const& author)
{
Player* pBanned = ObjectAccessor::FindConnectedPlayerByName(name);
- uint32 guid = 0;
+ ObjectGuid::LowType guid = 0;
uint32 duration_secs = TimeStringToSecs(duration);
@@ -2506,7 +2518,7 @@ BanReturn World::BanCharacter(std::string const& name, std::string const& durati
guid = (*resultCharacter)[0].GetUInt32();
}
else
- guid = pBanned->GetGUIDLow();
+ guid = pBanned->GetGUID().GetCounter();
// make sure there is only one active ban
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHARACTER_BAN);
@@ -2530,7 +2542,7 @@ BanReturn World::BanCharacter(std::string const& name, std::string const& durati
bool World::RemoveBanCharacter(std::string const& name)
{
Player* pBanned = ObjectAccessor::FindConnectedPlayerByName(name);
- uint32 guid = 0;
+ ObjectGuid::LowType guid = 0;
/// Pick a player to ban if not online
if (!pBanned)
@@ -2545,7 +2557,7 @@ bool World::RemoveBanCharacter(std::string const& name)
guid = (*resultCharacter)[0].GetUInt32();
}
else
- guid = pBanned->GetGUIDLow();
+ guid = pBanned->GetGUID().GetCounter();
if (!guid)
return false;
@@ -3152,6 +3164,15 @@ void World::ProcessQueryCallbacks()
}
}
+CharacterInfo const* World::GetCharacterInfo(ObjectGuid const& guid) const
+{
+ CharacterInfoContainer::const_iterator itr = _characterInfoStore.find(guid);
+ if (itr != _characterInfoStore.end())
+ return &itr->second;
+
+ return nullptr;
+}
+
/**
* @brief Loads several pieces of information on server startup with the GUID
* There is no further database query necessary.
@@ -3161,87 +3182,78 @@ void World::ProcessQueryCallbacks()
* @return Name, Gender, Race, Class and Level of player character
* Example Usage:
* @code
-* CharacterNameData const* nameData = sWorld->GetCharacterNameData(GUID);
-* if (!nameData)
+* CharacterInfo const* characterInfo = sWorld->GetCharacterInfo(GUID);
+* if (!characterInfo)
* return;
*
-* std::string playerName = nameData->m_name;
-* uint8 playerGender = nameData->m_gender;
-* uint8 playerRace = nameData->m_race;
-* uint8 playerClass = nameData->m_class;
-* uint8 playerLevel = nameData->m_level;
+* std::string playerName = characterInfo->Name;
+* uint8 playerGender = characterInfo->Sex;
+* uint8 playerRace = characterInfo->Race;
+* uint8 playerClass = characterInfo->Class;
+* uint8 playerLevel = characterInfo->Level;
* @endcode
**/
-void World::LoadCharacterNameData()
+void World::LoadCharacterInfoStore()
{
- TC_LOG_INFO("server.loading", "Loading character name data");
+ TC_LOG_INFO("server.loading", "Loading character info store");
- QueryResult result = CharacterDatabase.Query("SELECT guid, name, race, gender, class, level FROM characters WHERE deleteDate IS NULL");
+ _characterInfoStore.clear();
+
+ QueryResult result = CharacterDatabase.Query("SELECT guid, name, account, race, gender, class, level FROM characters");
if (!result)
{
TC_LOG_INFO("server.loading", "No character name data loaded, empty query");
return;
}
- uint32 count = 0;
-
do
{
Field* fields = result->Fetch();
- AddCharacterNameData(ObjectGuid(HIGHGUID_PLAYER, fields[0].GetUInt32()), fields[1].GetString(),
- fields[3].GetUInt8() /*gender*/, fields[2].GetUInt8() /*race*/, fields[4].GetUInt8() /*class*/, fields[5].GetUInt8() /*level*/);
- ++count;
+ AddCharacterInfo(ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt32()), fields[2].GetUInt32(), fields[1].GetString(),
+ fields[4].GetUInt8() /*gender*/, fields[3].GetUInt8() /*race*/, fields[5].GetUInt8() /*class*/, fields[6].GetUInt8() /*level*/);
} while (result->NextRow());
- TC_LOG_INFO("server.loading", "Loaded name data for %u characters", count);
+ TC_LOG_INFO("server.loading", "Loaded character infos for " SZFMTD " characters", _characterInfoStore.size());
}
-void World::AddCharacterNameData(ObjectGuid guid, std::string const& name, uint8 gender, uint8 race, uint8 playerClass, uint8 level)
+void World::AddCharacterInfo(ObjectGuid const& guid, uint32 accountId, std::string const& name, uint8 gender, uint8 race, uint8 playerClass, uint8 level)
{
- CharacterNameData& data = _characterNameDataMap[guid];
- data.m_name = name;
- data.m_race = race;
- data.m_gender = gender;
- data.m_class = playerClass;
- data.m_level = level;
+ CharacterInfo& data = _characterInfoStore[guid];
+ data.Name = name;
+ data.AccountId = accountId;
+ data.Race = race;
+ data.Sex = gender;
+ data.Class = playerClass;
+ data.Level = level;
}
-void World::UpdateCharacterNameData(ObjectGuid guid, std::string const& name, uint8 gender /*= GENDER_NONE*/, uint8 race /*= RACE_NONE*/)
+void World::UpdateCharacterInfo(ObjectGuid const& guid, std::string const& name, uint8 gender /*= GENDER_NONE*/, uint8 race /*= RACE_NONE*/)
{
- std::map<ObjectGuid, CharacterNameData>::iterator itr = _characterNameDataMap.find(guid);
- if (itr == _characterNameDataMap.end())
+ CharacterInfoContainer::iterator itr = _characterInfoStore.find(guid);
+ if (itr == _characterInfoStore.end())
return;
- itr->second.m_name = name;
+ itr->second.Name = name;
if (gender != GENDER_NONE)
- itr->second.m_gender = gender;
+ itr->second.Sex = gender;
if (race != RACE_NONE)
- itr->second.m_race = race;
+ itr->second.Race = race;
WorldPacket data(SMSG_INVALIDATE_PLAYER, 8);
data << guid;
SendGlobalMessage(&data);
}
-void World::UpdateCharacterNameDataLevel(ObjectGuid guid, uint8 level)
+void World::UpdateCharacterInfoLevel(ObjectGuid const& guid, uint8 level)
{
- std::map<ObjectGuid, CharacterNameData>::iterator itr = _characterNameDataMap.find(guid);
- if (itr == _characterNameDataMap.end())
+ CharacterInfoContainer::iterator itr = _characterInfoStore.find(guid);
+ if (itr == _characterInfoStore.end())
return;
- itr->second.m_level = level;
-}
-
-CharacterNameData const* World::GetCharacterNameData(ObjectGuid guid) const
-{
- std::map<ObjectGuid, CharacterNameData>::const_iterator itr = _characterNameDataMap.find(guid);
- if (itr != _characterNameDataMap.end())
- return &itr->second;
- else
- return NULL;
+ itr->second.Level = level;
}
void World::ReloadRBAC()
@@ -3252,3 +3264,9 @@ void World::ReloadRBAC()
if (WorldSession* session = itr->second)
session->InvalidateRBACData();
}
+
+void World::RemoveOldCorpses()
+{
+ m_timers[WUPDATE_CORPSES].SetCurrent(m_timers[WUPDATE_CORPSES].GetInterval());
+}
+
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index af89adcb04e..133ac3f2386 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -124,6 +124,7 @@ enum WorldBoolConfigs
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE,
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY,
CONFIG_BATTLEGROUND_STORE_STATISTICS_ENABLE,
+ CONFIG_BATTLEGROUND_TRACK_DESERTERS,
CONFIG_BG_XP_FOR_KILL,
CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS,
CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE,
@@ -143,6 +144,7 @@ enum WorldBoolConfigs
CONFIG_SHOW_BAN_IN_WORLD,
CONFIG_AUTOBROADCAST,
CONFIG_ALLOW_TICKETS,
+ CONFIG_DELETE_CHARACTER_TICKET_TRACE,
CONFIG_DBC_ENFORCE_ITEM_ATTRIBUTES,
CONFIG_PRESERVE_CUSTOM_CHANNELS,
CONFIG_PDUMP_NO_PATHS,
@@ -161,6 +163,8 @@ enum WorldBoolConfigs
CONFIG_ALLOW_TRACK_BOTH_RESOURCES,
CONFIG_CALCULATE_CREATURE_ZONE_AREA_DATA,
CONFIG_CALCULATE_GAMEOBJECT_ZONE_AREA_DATA,
+ CONFIG_RESET_DUEL_COOLDOWNS,
+ CONFIG_RESET_DUEL_HEALTH_MANA,
BOOL_CONFIG_VALUE_COUNT
};
@@ -373,6 +377,7 @@ enum Rates
RATE_DROP_ITEM_REFERENCED_AMOUNT,
RATE_DROP_MONEY,
RATE_XP_KILL,
+ RATE_XP_BG_KILL,
RATE_XP_QUEST,
RATE_XP_EXPLORE,
RATE_REPAIRCOST,
@@ -522,13 +527,14 @@ private:
typedef std::unordered_map<uint32, WorldSession*> SessionMap;
-struct CharacterNameData
+struct CharacterInfo
{
- std::string m_name;
- uint8 m_class;
- uint8 m_race;
- uint8 m_gender;
- uint8 m_level;
+ std::string Name;
+ uint32 AccountId;
+ uint8 Class;
+ uint8 Race;
+ uint8 Sex;
+ uint8 Level;
};
/// The World
@@ -748,12 +754,12 @@ class World
void UpdateAreaDependentAuras();
- CharacterNameData const* GetCharacterNameData(ObjectGuid guid) const;
- void AddCharacterNameData(ObjectGuid guid, std::string const& name, uint8 gender, uint8 race, uint8 playerClass, uint8 level);
- void UpdateCharacterNameData(ObjectGuid guid, std::string const& name, uint8 gender = GENDER_NONE, uint8 race = RACE_NONE);
- void UpdateCharacterNameDataLevel(ObjectGuid guid, uint8 level);
- void DeleteCharacterNameData(ObjectGuid guid) { _characterNameDataMap.erase(guid); }
- bool HasCharacterNameData(ObjectGuid guid) { return _characterNameDataMap.find(guid) != _characterNameDataMap.end(); }
+ CharacterInfo const* GetCharacterInfo(ObjectGuid const& guid) const;
+ void AddCharacterInfo(ObjectGuid const& guid, uint32 accountId, std::string const& name, uint8 gender, uint8 race, uint8 playerClass, uint8 level);
+ void DeleteCharacterInfo(ObjectGuid const& guid) { _characterInfoStore.erase(guid); }
+ bool HasCharacterInfo(ObjectGuid const& guid) { return _characterInfoStore.find(guid) != _characterInfoStore.end(); }
+ void UpdateCharacterInfo(ObjectGuid const& guid, std::string const& name, uint8 gender = GENDER_NONE, uint8 race = RACE_NONE);
+ void UpdateCharacterInfoLevel(ObjectGuid const& guid, uint8 level);
uint32 GetCleaningFlags() const { return m_CleaningFlags; }
void SetCleaningFlags(uint32 flags) { m_CleaningFlags = flags; }
@@ -761,6 +767,8 @@ class World
void ReloadRBAC();
+ void RemoveOldCorpses();
+
protected:
void _UpdateGameTime();
// callback for UpdateRealmCharacters
@@ -858,8 +866,9 @@ class World
typedef std::map<uint8, uint8> AutobroadcastsWeightMap;
AutobroadcastsWeightMap m_AutobroadcastsWeights;
- std::map<ObjectGuid, CharacterNameData> _characterNameDataMap;
- void LoadCharacterNameData();
+ typedef std::unordered_map<ObjectGuid, CharacterInfo> CharacterInfoContainer;
+ CharacterInfoContainer _characterInfoStore;
+ void LoadCharacterInfoStore();
void ProcessQueryCallbacks();
std::deque<std::future<PreparedQueryResult>> m_realmCharCallbacks;