aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.h9
-rw-r--r--src/server/game/Battlegrounds/BattlegroundMgr.cpp2
-rw-r--r--src/server/game/Chat/Chat.cpp1
-rw-r--r--src/server/game/Conditions/ConditionMgr.cpp5
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.cpp7
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp2
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp3
-rw-r--r--src/server/game/Entities/Player/Player.cpp3
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp7
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp82
-rw-r--r--src/server/game/Groups/Group.cpp18
-rw-r--r--src/server/game/Handlers/LootHandler.cpp2
-rw-r--r--src/server/game/Spells/Spell.cpp4
-rw-r--r--src/server/game/Spells/SpellMgr.cpp4
-rw-r--r--src/server/game/Spells/SpellScript.cpp4
-rw-r--r--src/server/game/World/World.cpp3
-rw-r--r--src/server/scripts/Commands/cs_tele.cpp2
-rw-r--r--src/server/scripts/Kalimdor/ZulFarrak/instance_zulfarrak.cpp1
-rw-r--r--src/server/scripts/Spells/spell_holiday.cpp56
-rw-r--r--src/server/shared/Database/DatabaseLoader.cpp3
-rw-r--r--src/server/shared/Updater/DBUpdater.cpp13
-rw-r--r--src/server/shared/Updater/DBUpdater.h13
-rw-r--r--src/server/shared/Updater/UpdateFetcher.cpp19
-rw-r--r--src/server/shared/Updater/UpdateFetcher.h2
-rw-r--r--src/server/shared/Utilities/TaskScheduler.cpp34
-rw-r--r--src/server/shared/Utilities/TaskScheduler.h48
26 files changed, 259 insertions, 88 deletions
diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h
index a3d75f1889b..51628eded54 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.h
+++ b/src/server/game/AI/SmartScripts/SmartScript.h
@@ -247,7 +247,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/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
index 95a51f6d915..8e5766407f1 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.");
diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp
index 1716aa73525..3cbdcbcaff1 100644
--- a/src/server/game/Chat/Chat.cpp
+++ b/src/server/game/Chat/Chat.cpp
@@ -78,6 +78,7 @@ ChatCommand* ChatHandler::getCommandTable()
// cache top-level commands
size_t added = 0;
+ free(commandTableCache);
commandTableCache = (ChatCommand*)malloc(sizeof(ChatCommand) * total);
ASSERT(commandTableCache);
memset(commandTableCache, 0, sizeof(ChatCommand) * total);
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index 25fbef2ca86..b05f9ac2a0d 100644
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -1535,6 +1535,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 +1558,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
diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp
index 5ad94948cd0..59eedaaffed 100644
--- a/src/server/game/DungeonFinding/LFGMgr.cpp
+++ b/src/server/game/DungeonFinding/LFGMgr.cpp
@@ -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;
}
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 809c76c260a..a91bbf00735 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -1507,11 +1507,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(true);
}
}
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index a4b140b9878..9dfa603dd7c 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -1757,6 +1757,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
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 275dbf92dca..3b2e302dd8a 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -23657,6 +23657,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);
}
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index a58fde1e3a3..9b0da57fa31 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -12294,6 +12294,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)
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index e540824e71c..b9d828b2dfd 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -1147,8 +1147,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)
{
@@ -1283,8 +1283,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)
{
@@ -3800,8 +3800,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,26 +3965,26 @@ 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, "
+ //0 1 2 3 4 5 6 7 8 9 10 11 12
+ "ID, Method, QuestLevel, MinLevel, MaxLevel, QuestSortID, QuestType, SuggestedGroupNum, 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, "
+ "RewardMailTemplateId, RewardMailDelay, SourceItemId, SourceItemCount, SourceSpellId, Flags, SpecialFlags, RewardTitle, RequiredPlayerKills, RewardTalents, RewardArenaPoints, "
+ // 43 44 45 46 47 48 49 50
+ "RewardItem1, RewardItem2, RewardItem3, RewardItem4, RewardAmount1, RewardAmount2, RewardAmount3, RewardAmount4, "
+ // 51 52 53 54 55 56 57 58 59 60 61 62
+ "RewardChoiceItemID1, RewardChoiceItemID2, RewardChoiceItemID3, RewardChoiceItemID4, RewardChoiceItemID5, RewardChoiceItemID6, RewardChoiceItemQuantity1, RewardChoiceItemQuantity2, RewardChoiceItemQuantity3, RewardChoiceItemQuantity4, RewardChoiceItemQuantity5, RewardChoiceItemQuantity6, "
+ // 63 64 65 66 67 68 69 70 71 72
+ "RewardFactionID1, RewardFactionID2, RewardFactionID3, RewardFactionID4, RewardFactionID5, RewardFactionValue1, RewardFactionValue2, RewardFactionValue3, RewardFactionValue4, RewardFactionValue5, "
// 73 74 75 76 77
- "RewardFactionValueIdOverride1, RewardFactionValueIdOverride2, RewardFactionValueIdOverride3, RewardFactionValueIdOverride4, RewardFactionValueIdOverride5, "
+ "RewardFactionOverride1, RewardFactionOverride2, RewardFactionOverride3, RewardFactionOverride4, RewardFactionOverride5, "
// 78 79 80 81
"PointMapId, PointX, PointY, PointOption, "
- // 82 83 84 85 86 87 88
- "Title, Objectives, Details, EndText, OfferRewardText, RequestItemsText, CompletedText, "
+ // 82 83 84 85 86 87 88
+ "LogTitle, LogDescription, QuestDescription, EndText, OfferRewardText, RequestItemsText, QuestCompletionLog, "
// 89 90 91 92 93 94 95 96
"RequiredNpcOrGo1, RequiredNpcOrGo2, RequiredNpcOrGo3, RequiredNpcOrGo4, RequiredNpcOrGoCount1, RequiredNpcOrGoCount2, RequiredNpcOrGoCount3, RequiredNpcOrGoCount4, "
// 97 98 99 100 101 102 103 104
@@ -5178,8 +5178,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)
{
@@ -5392,14 +5392,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");
@@ -6158,8 +6158,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.");
@@ -6599,9 +6599,9 @@ void ObjectMgr::LoadGameObjectTemplate()
// 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, "
+ "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 "
+ "Data13, Data14, Data15, Data16, Data17, Data18, Data19, Data20, Data21, Data22, Data23, AIName, ScriptName "
"FROM gameobject_template");
if (!result)
@@ -7188,8 +7188,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 +7234,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 +7243,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;
@@ -8217,9 +8217,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)
{
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index 2e81bdd1af8..f89c0e73008 100644
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -936,7 +936,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++;
@@ -1021,7 +1021,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;
@@ -1080,7 +1080,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())
@@ -1155,7 +1155,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 +1231,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 +1243,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 +1743,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 +1754,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 +1767,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;
diff --git a/src/server/game/Handlers/LootHandler.cpp b/src/server/game/Handlers/LootHandler.cpp
index b4f19234df9..26d1737257e 100644
--- a/src/server/game/Handlers/LootHandler.cpp
+++ b/src/server/game/Handlers/LootHandler.cpp
@@ -176,7 +176,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/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 94bb90487bc..ff7c6a86ae8 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -5060,12 +5060,12 @@ SpellCastResult Spell::CheckCast(bool strict)
bool result = m_preGeneratedPath.CalculatePath(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ() + target->GetObjectSize(), 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);
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;
}
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 13290320084..53b44fdd5cc 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -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.");
diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp
index b347a982132..09f557dc63b 100644
--- a/src/server/game/Spells/SpellScript.cpp
+++ b/src/server/game/Spells/SpellScript.cpp
@@ -641,8 +641,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())
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 5f54154fab1..c4b2eb768c6 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1711,6 +1711,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();
diff --git a/src/server/scripts/Commands/cs_tele.cpp b/src/server/scripts/Commands/cs_tele.cpp
index e488aa0e607..8e82f9980d3 100644
--- a/src/server/scripts/Commands/cs_tele.cpp
+++ b/src/server/scripts/Commands/cs_tele.cpp
@@ -319,7 +319,7 @@ public:
}
MapEntry const* map = sMapStore.LookupEntry(tele->mapId);
- if (!map || map->IsBattlegroundOrArena())
+ if (!map || (map->IsBattlegroundOrArena() && (me->GetMapId() != tele->mapId || !me->IsGameMaster())))
{
handler->SendSysMessage(LANG_CANNOT_TELE_TO_BG);
handler->SetSentErrorMessage(true);
diff --git a/src/server/scripts/Kalimdor/ZulFarrak/instance_zulfarrak.cpp b/src/server/scripts/Kalimdor/ZulFarrak/instance_zulfarrak.cpp
index 46e831b0f83..7bd197774bc 100644
--- a/src/server/scripts/Kalimdor/ZulFarrak/instance_zulfarrak.cpp
+++ b/src/server/scripts/Kalimdor/ZulFarrak/instance_zulfarrak.cpp
@@ -111,6 +111,7 @@ public:
instance_zulfarrak_InstanceMapScript(Map* map) : InstanceScript(map)
{
SetHeaders(DataHeader);
+ GahzRillaEncounter = NOT_STARTED;
PyramidPhase = 0;
major_wave_Timer = 0;
minor_wave_Timer = 0;
diff --git a/src/server/scripts/Spells/spell_holiday.cpp b/src/server/scripts/Spells/spell_holiday.cpp
index 93e13667cb0..a1b218010aa 100644
--- a/src/server/scripts/Spells/spell_holiday.cpp
+++ b/src/server/scripts/Spells/spell_holiday.cpp
@@ -824,6 +824,60 @@ class spell_brewfest_barker_bunny : public SpellScriptLoader
}
};
+enum TorchSpells
+{
+ SPELL_TORCH_TOSSING_TRAINING = 45716,
+ SPELL_TORCH_TOSSING_PRACTICE = 46630,
+ SPELL_TORCH_TOSSING_TRAINING_SUCCESS_ALLIANCE = 45719,
+ SPELL_TORCH_TOSSING_TRAINING_SUCCESS_HORDE = 46651,
+ SPELL_BRAZIERS_HIT = 45724
+};
+
+// 45724 - Braziers Hit!
+class spell_midsummer_braziers_hit : public SpellScriptLoader
+{
+ public:
+ spell_midsummer_braziers_hit() : SpellScriptLoader("spell_midsummer_braziers_hit") { }
+
+ class spell_midsummer_braziers_hit_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_midsummer_braziers_hit_AuraScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_TORCH_TOSSING_TRAINING) || !sSpellMgr->GetSpellInfo(SPELL_TORCH_TOSSING_PRACTICE))
+ return false;
+ return true;
+ }
+
+ void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Player* player = GetTarget()->ToPlayer();
+ if (!player)
+ return;
+
+ if ((player->HasAura(SPELL_TORCH_TOSSING_TRAINING) && GetStackAmount() == 8) || (player->HasAura(SPELL_TORCH_TOSSING_PRACTICE) && GetStackAmount() == 20))
+ {
+ if (player->GetTeam() == ALLIANCE)
+ player->CastSpell(player, SPELL_TORCH_TOSSING_TRAINING_SUCCESS_ALLIANCE, true);
+ else if (player->GetTeam() == HORDE)
+ player->CastSpell(player, SPELL_TORCH_TOSSING_TRAINING_SUCCESS_HORDE, true);
+ Remove();
+ }
+ }
+
+ void Register() override
+ {
+ AfterEffectApply += AuraEffectApplyFn(spell_midsummer_braziers_hit_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AuraEffectHandleModes(AURA_EFFECT_HANDLE_REAPPLY));
+ }
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_midsummer_braziers_hit_AuraScript();
+ }
+};
+
void AddSC_holiday_spell_scripts()
{
// Love is in the Air
@@ -850,4 +904,6 @@ void AddSC_holiday_spell_scripts()
new spell_brewfest_relay_race_intro_force_player_to_throw();
new spell_brewfest_dismount_ram();
new spell_brewfest_barker_bunny();
+ // Midsummer Fire Festival
+ new spell_midsummer_braziers_hit();
}
diff --git a/src/server/shared/Database/DatabaseLoader.cpp b/src/server/shared/Database/DatabaseLoader.cpp
index 36ee4b12c83..a3e2083fff4 100644
--- a/src/server/shared/Database/DatabaseLoader.cpp
+++ b/src/server/shared/Database/DatabaseLoader.cpp
@@ -117,6 +117,9 @@ DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool<T>& pool, std::st
bool DatabaseLoader::Load()
{
+ if (!_updateFlags)
+ TC_LOG_INFO("sql.updates", "Automatic database updates are disabled for all databases!");
+
if (!OpenDatabases())
return false;
diff --git a/src/server/shared/Updater/DBUpdater.cpp b/src/server/shared/Updater/DBUpdater.cpp
index 20ded669cec..fd91e94b78f 100644
--- a/src/server/shared/Updater/DBUpdater.cpp
+++ b/src/server/shared/Updater/DBUpdater.cpp
@@ -239,10 +239,10 @@ bool DBUpdater<T>::Update(DatabaseWorkerPool<T>& pool)
[&](Path const& file) { DBUpdater<T>::ApplyFile(pool, file); },
[&](std::string const& query) -> QueryResult { return DBUpdater<T>::Retrieve(pool, query); });
- uint32 count;
+ UpdateResult result;
try
{
- count = updateFetcher.Update(
+ result = updateFetcher.Update(
sConfigMgr->GetBoolDefault("Updates.Redundancy", true),
sConfigMgr->GetBoolDefault("Updates.AllowRehash", true),
sConfigMgr->GetBoolDefault("Updates.ArchivedRedundancy", false),
@@ -253,10 +253,13 @@ bool DBUpdater<T>::Update(DatabaseWorkerPool<T>& pool)
return false;
}
- if (!count)
- TC_LOG_INFO("sql.updates", ">> %s database is up-to-date!", DBUpdater<T>::GetTableName().c_str());
+ std::string const info = Trinity::StringFormat("Containing " SZFMTD " new and " SZFMTD " archived updates.",
+ result.recent, result.archived);
+
+ if (!result.updated)
+ TC_LOG_INFO("sql.updates", ">> %s database is up-to-date! %s", DBUpdater<T>::GetTableName().c_str(), info.c_str());
else
- TC_LOG_INFO("sql.updates", ">> Applied %d %s.", count, count == 1 ? "query" : "queries");
+ TC_LOG_INFO("sql.updates", ">> Applied " SZFMTD " %s. %s", result.updated, result.updated == 1 ? "query" : "queries", info.c_str());
return true;
}
diff --git a/src/server/shared/Updater/DBUpdater.h b/src/server/shared/Updater/DBUpdater.h
index 0caf8a438fb..a2b12bed235 100644
--- a/src/server/shared/Updater/DBUpdater.h
+++ b/src/server/shared/Updater/DBUpdater.h
@@ -41,6 +41,19 @@ enum BaseLocation
LOCATION_DOWNLOAD
};
+struct UpdateResult
+{
+ UpdateResult()
+ : updated(0), recent(0), archived(0) { }
+
+ UpdateResult(size_t const updated_, size_t const recent_, size_t const archived_)
+ : updated(updated_), recent(recent_), archived(archived_) { }
+
+ size_t updated;
+ size_t recent;
+ size_t archived;
+};
+
template <class T>
class DBUpdater
{
diff --git a/src/server/shared/Updater/UpdateFetcher.cpp b/src/server/shared/Updater/UpdateFetcher.cpp
index a4bdd193743..ec023928b99 100644
--- a/src/server/shared/Updater/UpdateFetcher.cpp
+++ b/src/server/shared/Updater/UpdateFetcher.cpp
@@ -154,17 +154,27 @@ UpdateFetcher::SQLUpdate UpdateFetcher::ReadSQLUpdate(boost::filesystem::path co
return update;
}
-uint32 UpdateFetcher::Update(bool const redundancyChecks, bool const allowRehash, bool const archivedRedundancy, int32 const cleanDeadReferencesMaxCount) const
+UpdateResult UpdateFetcher::Update(bool const redundancyChecks, bool const allowRehash, bool const archivedRedundancy, int32 const cleanDeadReferencesMaxCount) const
{
LocaleFileStorage const available = GetFileList();
AppliedFileStorage applied = ReceiveAppliedFiles();
+ size_t countRecentUpdates = 0;
+ size_t countArchivedUpdates = 0;
+
+ // Count updates
+ for (auto const& entry : applied)
+ if (entry.second.state == RELEASED)
+ ++countRecentUpdates;
+ else
+ ++countArchivedUpdates;
+
// Fill hash to name cache
HashToFileNameStorage hashToName;
for (auto entry : applied)
hashToName.insert(std::make_pair(entry.second.hash, entry.first));
- uint32 importedUpdates = 0;
+ size_t importedUpdates = 0;
for (auto const& availableQuery : available)
{
@@ -314,7 +324,7 @@ uint32 UpdateFetcher::Update(bool const redundancyChecks, bool const allowRehash
}
}
- return importedUpdates;
+ return UpdateResult(importedUpdates, countRecentUpdates, countArchivedUpdates);
}
std::string UpdateFetcher::CalculateHash(SQLUpdate const& query) const
@@ -329,7 +339,6 @@ std::string UpdateFetcher::CalculateHash(SQLUpdate const& query) const
uint32 UpdateFetcher::Apply(Path const& path) const
{
using Time = std::chrono::high_resolution_clock;
- using ms = std::chrono::milliseconds;
// Benchmark query speed
auto const begin = Time::now();
@@ -338,7 +347,7 @@ uint32 UpdateFetcher::Apply(Path const& path) const
_applyFile(path);
// Return time the query took to apply
- return std::chrono::duration_cast<ms>(Time::now() - begin).count();
+ return std::chrono::duration_cast<std::chrono::milliseconds>(Time::now() - begin).count();
}
void UpdateFetcher::UpdateEntry(AppliedFileEntry const& entry, uint32 const speed) const
diff --git a/src/server/shared/Updater/UpdateFetcher.h b/src/server/shared/Updater/UpdateFetcher.h
index fa142547873..4ff8c93bc76 100644
--- a/src/server/shared/Updater/UpdateFetcher.h
+++ b/src/server/shared/Updater/UpdateFetcher.h
@@ -35,7 +35,7 @@ public:
std::function<void(Path const& path)> const& applyFile,
std::function<QueryResult(std::string const&)> const& retrieve);
- uint32 Update(bool const redundancyChecks, bool const allowRehash,
+ UpdateResult Update(bool const redundancyChecks, bool const allowRehash,
bool const archivedRedundancy, int32 const cleanDeadReferencesMaxCount) const;
private:
diff --git a/src/server/shared/Utilities/TaskScheduler.cpp b/src/server/shared/Utilities/TaskScheduler.cpp
index 4b261413fd9..04a4071d1f5 100644
--- a/src/server/shared/Utilities/TaskScheduler.cpp
+++ b/src/server/shared/Utilities/TaskScheduler.cpp
@@ -17,16 +17,22 @@
#include "TaskScheduler.h"
-TaskScheduler& TaskScheduler::Update()
+TaskScheduler& TaskScheduler::ClearValidator()
+{
+ _predicate = EmptyValidator;
+ return *this;
+}
+
+TaskScheduler& TaskScheduler::Update(success_t const& callback)
{
_now = clock_t::now();
- Dispatch();
+ Dispatch(callback);
return *this;
}
-TaskScheduler& TaskScheduler::Update(size_t const milliseconds)
+TaskScheduler& TaskScheduler::Update(size_t const milliseconds, success_t const& callback)
{
- return Update(std::chrono::milliseconds(milliseconds));
+ return Update(std::chrono::milliseconds(milliseconds), callback);
}
TaskScheduler& TaskScheduler::Async(std::function<void()> const& callable)
@@ -66,15 +72,26 @@ TaskScheduler& TaskScheduler::InsertTask(TaskContainer task)
return *this;
}
-void TaskScheduler::Dispatch()
+void TaskScheduler::Dispatch(success_t const& callback)
{
+ // If the validation failed abort the dispatching here.
+ if (!_predicate())
+ return;
+
// Process all asyncs
while (!_asyncHolder.empty())
{
_asyncHolder.front()();
_asyncHolder.pop();
+
+ // If the validation failed abort the dispatching here.
+ if (!_predicate())
+ return;
}
+ if (_task_holder.IsEmpty())
+ return;
+
while (!_task_holder.IsEmpty())
{
if (_task_holder.First()->_end > _now)
@@ -86,7 +103,14 @@ void TaskScheduler::Dispatch()
// Invoke the context
context.Invoke();
+
+ // If the validation failed abort the dispatching here.
+ if (!_predicate())
+ return;
}
+
+ // On finish call the final callback
+ callback();
}
void TaskScheduler::TaskQueue::Push(TaskContainer&& task)
diff --git a/src/server/shared/Utilities/TaskScheduler.h b/src/server/shared/Utilities/TaskScheduler.h
index 98e210e55b1..d45835b5f17 100644
--- a/src/server/shared/Utilities/TaskScheduler.h
+++ b/src/server/shared/Utilities/TaskScheduler.h
@@ -60,6 +60,10 @@ class TaskScheduler
typedef uint32 repeated_t;
// Task handle type
typedef std::function<void(TaskContext)> task_handler_t;
+ // Predicate type
+ typedef std::function<bool()> predicate_t;
+ // Success handle type
+ typedef std::function<void()> success_t;
class Task
{
@@ -163,27 +167,57 @@ class TaskScheduler
/// the next update tick.
AsyncHolder _asyncHolder;
+ predicate_t _predicate;
+
+ static bool EmptyValidator()
+ {
+ return true;
+ }
+
+ static void EmptyCallback()
+ {
+ }
+
public:
- TaskScheduler() : self_reference(this, [](TaskScheduler const*) { }),
- _now(clock_t::now()) { }
+ TaskScheduler()
+ : self_reference(this, [](TaskScheduler const*) { }), _now(clock_t::now()), _predicate(EmptyValidator) { }
+
+ template<typename P>
+ TaskScheduler(P&& predicate)
+ : self_reference(this, [](TaskScheduler const*) { }), _now(clock_t::now()), _predicate(std::forward<P>(predicate)) { }
TaskScheduler(TaskScheduler const&) = delete;
TaskScheduler(TaskScheduler&&) = delete;
TaskScheduler& operator= (TaskScheduler const&) = delete;
TaskScheduler& operator= (TaskScheduler&&) = delete;
+ /// Sets a validator which is asked if tasks are allowed to be executed.
+ template<typename P>
+ TaskScheduler& SetValidator(P&& predicate)
+ {
+ _predicate = std::forward<P>(predicate);
+ return *this;
+ }
+
+ /// Clears the validator which is asked if tasks are allowed to be executed.
+ TaskScheduler& ClearValidator();
+
/// Update the scheduler to the current time.
- TaskScheduler& Update();
+ /// Calls the optional callback on successfully finish.
+ TaskScheduler& Update(success_t const& callback = EmptyCallback);
/// Update the scheduler with a difftime in ms.
- TaskScheduler& Update(size_t const milliseconds);
+ /// Calls the optional callback on successfully finish.
+ TaskScheduler& Update(size_t const milliseconds, success_t const& callback = EmptyCallback);
/// Update the scheduler with a difftime.
+ /// Calls the optional callback on successfully finish.
template<class _Rep, class _Period>
- TaskScheduler& Update(std::chrono::duration<_Rep, _Period> const& difftime)
+ TaskScheduler& Update(std::chrono::duration<_Rep, _Period> const& difftime,
+ success_t const& callback = EmptyCallback)
{
_now += difftime;
- Dispatch();
+ Dispatch(callback);
return *this;
}
@@ -370,7 +404,7 @@ private:
}
/// Dispatch remaining tasks
- void Dispatch();
+ void Dispatch(success_t const& callback);
};
class TaskContext