aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.h2
-rw-r--r--src/server/game/Accounts/RBAC.h17
-rw-r--r--src/server/game/AuctionHouseBot/AuctionHouseBot.cpp426
-rw-r--r--src/server/game/AuctionHouseBot/AuctionHouseBot.h280
-rw-r--r--src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.cpp432
-rw-r--r--src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.h96
-rw-r--r--src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp1029
-rw-r--r--src/server/game/AuctionHouseBot/AuctionHouseBotSeller.h147
-rw-r--r--src/server/game/Battlegrounds/ArenaTeam.cpp2
-rw-r--r--src/server/game/Battlegrounds/Battleground.cpp43
-rw-r--r--src/server/game/Battlegrounds/BattlegroundScore.h13
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAB.h3
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAV.h6
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundEY.h2
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundIC.h3
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundSA.h3
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundWS.h3
-rw-r--r--src/server/game/CMakeLists.txt3
-rw-r--r--src/server/game/Chat/Chat.cpp2
-rw-r--r--src/server/game/Chat/Chat.h2
-rw-r--r--src/server/game/Entities/Item/Item.cpp10
-rw-r--r--src/server/game/Entities/Object/Object.h2
-rw-r--r--src/server/game/Entities/Player/Player.cpp21
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp13
-rw-r--r--src/server/game/Guilds/Guild.h3
-rw-r--r--src/server/game/Maps/Map.cpp2
-rw-r--r--src/server/game/Miscellaneous/Language.h29
-rw-r--r--src/server/game/Scripting/ScriptLoader.cpp2
-rw-r--r--src/server/game/Scripting/ScriptMgr.cpp5
-rw-r--r--src/server/game/Scripting/ScriptMgr.h4
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp34
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.h19
-rw-r--r--src/server/game/Spells/SpellMgr.cpp10
-rw-r--r--src/server/game/World/World.cpp18
-rw-r--r--src/server/game/World/World.h3
-rw-r--r--src/server/scripts/CMakeLists.txt1
-rw-r--r--src/server/scripts/Commands/cs_ahbot.cpp251
-rw-r--r--src/server/scripts/Commands/cs_guild.cpp44
-rw-r--r--src/server/scripts/Commands/cs_lookup.cpp2
-rw-r--r--src/server/scripts/Commands/cs_misc.cpp2
-rw-r--r--src/server/scripts/Commands/cs_modify.cpp2
-rw-r--r--src/server/scripts/Commands/cs_quest.cpp4
-rw-r--r--src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp8
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp113
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/boss_arcanist_doan.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/boss_azshir_the_sleepless.cpp13
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/boss_bloodmage_thalnos.cpp11
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/boss_herod.cpp11
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/boss_houndmaster_loksey.cpp7
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/boss_scorn.cpp15
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/scarlet_monastery.h7
-rw-r--r--src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp14
-rw-r--r--src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp2
-rw-r--r--src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp9
-rw-r--r--src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp6
-rw-r--r--src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp10
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/instance_trial_of_the_champion.cpp6
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp2
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h3
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp8
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp12
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp18
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp3
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp8
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp22
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp3
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp2
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp9
-rw-r--r--src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp9
-rw-r--r--src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp12
-rw-r--r--src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp22
-rw-r--r--src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp9
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp9
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp6
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp1409
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp2
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp23
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp9
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h2
-rw-r--r--src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_ymiron.cpp9
-rw-r--r--src/server/scripts/Northrend/VioletHold/violet_hold.cpp31
-rw-r--r--src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_grandmaster_vorpil.cpp3
-rw-r--r--src/server/scripts/Outland/CoilfangReservoir/SteamVault/boss_hydromancer_thespia.cpp5
-rw-r--r--src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp6
-rw-r--r--src/server/scripts/Outland/TempestKeep/botanica/boss_thorngrin_the_tender.cpp5
-rw-r--r--src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp3
-rw-r--r--src/server/scripts/Outland/zone_blades_edge_mountains.cpp2
-rw-r--r--src/server/scripts/Spells/spell_quest.cpp33
-rw-r--r--src/server/scripts/Spells/spell_shaman.cpp2
-rw-r--r--src/server/scripts/World/item_scripts.cpp2
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.cpp6
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.h4
-rw-r--r--src/server/worldserver/RemoteAccess/RASession.cpp8
-rw-r--r--src/server/worldserver/worldserver.conf.dist360
97 files changed, 5040 insertions, 276 deletions
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
index fbcffb47b7c..c79deb5d960 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
@@ -466,7 +466,7 @@ enum SMART_ACTION
SMART_ACTION_SET_VISIBILITY = 47, // on/off
SMART_ACTION_SET_ACTIVE = 48, // on/off
SMART_ACTION_ATTACK_START = 49, //
- SMART_ACTION_SUMMON_GO = 50, // GameObjectID, DespawnTime in ms,
+ SMART_ACTION_SUMMON_GO = 50, // GameObjectID, DespawnTime in s
SMART_ACTION_KILL_UNIT = 51, //
SMART_ACTION_ACTIVATE_TAXI = 52, // TaxiID
SMART_ACTION_WP_START = 53, // run/walk, pathID, canRepeat, quest, despawntime, reactState
diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h
index 855ffd51bb8..020ed1a686a 100644
--- a/src/server/game/Accounts/RBAC.h
+++ b/src/server/game/Accounts/RBAC.h
@@ -681,6 +681,23 @@ enum RBACPermissions
RBAC_PERM_COMMAND_MODIFY_CURRENCY = 775, // only 4.3.4
RBAC_PERM_COMMAND_DEBUG_PHASE = 776, // only 4.3.4
RBAC_PERM_COMMAND_MAILBOX = 777,
+ RBAC_PERM_COMMAND_AHBOT = 778,
+ RBAC_PERM_COMMAND_AHBOT_ITEMS = 779,
+ RBAC_PERM_COMMAND_AHBOT_ITEMS_GRAY = 780,
+ RBAC_PERM_COMMAND_AHBOT_ITEMS_WHITE = 781,
+ RBAC_PERM_COMMAND_AHBOT_ITEMS_GREEN = 782,
+ RBAC_PERM_COMMAND_AHBOT_ITEMS_BLUE = 783,
+ RBAC_PERM_COMMAND_AHBOT_ITEMS_PURPLE = 784,
+ RBAC_PERM_COMMAND_AHBOT_ITEMS_ORANGE = 785,
+ RBAC_PERM_COMMAND_AHBOT_ITEMS_YELLOW = 786,
+ RBAC_PERM_COMMAND_AHBOT_RATIO = 787,
+ RBAC_PERM_COMMAND_AHBOT_RATIO_ALLIANCE = 788,
+ RBAC_PERM_COMMAND_AHBOT_RATIO_HORDE = 789,
+ RBAC_PERM_COMMAND_AHBOT_RATIO_NEUTRAL = 790,
+ RBAC_PERM_COMMAND_AHBOT_REBUILD = 791,
+ RBAC_PERM_COMMAND_AHBOT_RELOAD = 792,
+ RBAC_PERM_COMMAND_AHBOT_STATUS = 793,
+ RBAC_PERM_COMMAND_GUILD_INFO = 794,
// custom permissions 1000+
RBAC_PERM_MAX
diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBot.cpp b/src/server/game/AuctionHouseBot/AuctionHouseBot.cpp
new file mode 100644
index 00000000000..6bf5fa0aaa5
--- /dev/null
+++ b/src/server/game/AuctionHouseBot/AuctionHouseBot.cpp
@@ -0,0 +1,426 @@
+/*
+ * Copyright (C) 2008-2014 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 "Log.h"
+#include "Item.h"
+#include "World.h"
+#include "Config.h"
+#include "AuctionHouseMgr.h"
+#include "AuctionHouseBot.h"
+#include "AuctionHouseBotBuyer.h"
+#include "AuctionHouseBotSeller.h"
+
+bool AuctionBotConfig::Initialize()
+{
+ GetConfigFromFile();
+
+ if (!GetConfig(CONFIG_AHBOT_BUYER_ENABLED) && !GetConfig(CONFIG_AHBOT_SELLER_ENABLED))
+ {
+ TC_LOG_INFO("ahbot", "AHBOT is Disabled.");
+ return false;
+ }
+
+ if (GetConfig(CONFIG_AHBOT_ALLIANCE_ITEM_AMOUNT_RATIO) == 0 && GetConfig(CONFIG_AHBOT_HORDE_ITEM_AMOUNT_RATIO) == 0 && GetConfig(CONFIG_AHBOT_NEUTRAL_ITEM_AMOUNT_RATIO) == 0 &&
+ !GetConfig(CONFIG_AHBOT_BUYER_ALLIANCE_ENABLED) && !GetConfig(CONFIG_AHBOT_BUYER_HORDE_ENABLED) && !GetConfig(CONFIG_AHBOT_BUYER_NEUTRAL_ENABLED))
+ {
+ TC_LOG_INFO("ahbot", "All feature of AuctionHouseBot are disabled!");
+ return false;
+ }
+
+ if (GetConfig(CONFIG_AHBOT_ALLIANCE_ITEM_AMOUNT_RATIO) == 0 && GetConfig(CONFIG_AHBOT_HORDE_ITEM_AMOUNT_RATIO) == 0 && GetConfig(CONFIG_AHBOT_NEUTRAL_ITEM_AMOUNT_RATIO) == 0)
+ TC_LOG_INFO("ahbot", "AuctionHouseBot SELLER is disabled!");
+
+ if (!GetConfig(CONFIG_AHBOT_BUYER_ALLIANCE_ENABLED) && !GetConfig(CONFIG_AHBOT_BUYER_HORDE_ENABLED) && !GetConfig(CONFIG_AHBOT_BUYER_NEUTRAL_ENABLED))
+ TC_LOG_INFO("ahbot", "AuctionHouseBot BUYER is disabled!");
+
+ _itemsPerCycleBoost = GetConfig(CONFIG_AHBOT_ITEMS_PER_CYCLE_BOOST);
+ _itemsPerCycleNormal = GetConfig(CONFIG_AHBOT_ITEMS_PER_CYCLE_NORMAL);
+
+ return true;
+}
+
+void AuctionBotConfig::SetConfig(AuctionBotConfigUInt32Values index, char const* fieldname, uint32 defvalue)
+{
+ SetConfig(index, sConfigMgr->GetIntDefault(fieldname, defvalue));
+
+ if (int32(GetConfig(index)) < 0)
+ {
+ TC_LOG_ERROR("ahbot", "AHBot: %s (%i) can't be negative. Using %u instead.", fieldname, int32(GetConfig(index)), defvalue);
+ SetConfig(index, defvalue);
+ }
+}
+
+void AuctionBotConfig::SetConfigMax(AuctionBotConfigUInt32Values index, char const* fieldname, uint32 defvalue, uint32 maxvalue)
+{
+ SetConfig(index, sConfigMgr->GetIntDefault(fieldname, defvalue));
+
+ if (GetConfig(index) > maxvalue)
+ {
+ TC_LOG_ERROR("ahbot", "AHBot: %s (%u) must be in range 0...%u. Using %u instead.", fieldname, GetConfig(index), maxvalue, maxvalue);
+ SetConfig(index, maxvalue);
+ }
+}
+
+void AuctionBotConfig::SetConfigMinMax(AuctionBotConfigUInt32Values index, char const* fieldname, uint32 defvalue, uint32 minvalue, uint32 maxvalue)
+{
+ SetConfig(index, sConfigMgr->GetIntDefault(fieldname, defvalue));
+
+ if (GetConfig(index) > maxvalue)
+ {
+ TC_LOG_ERROR("ahbot", "AHBot: %s (%u) must be in range %u...%u. Using %u instead.", fieldname, GetConfig(index), minvalue, maxvalue, maxvalue);
+ SetConfig(index, maxvalue);
+ }
+
+ if (GetConfig(index) < minvalue)
+ {
+ TC_LOG_ERROR("ahbot", "AHBot: %s (%u) must be in range %u...%u. Using %u instead.", fieldname, GetConfig(index), minvalue, maxvalue, minvalue);
+ SetConfig(index, minvalue);
+ }
+}
+
+void AuctionBotConfig::SetConfig(AuctionBotConfigBoolValues index, char const* fieldname, bool defvalue)
+{
+ SetConfig(index, sConfigMgr->GetBoolDefault(fieldname, defvalue));
+}
+
+//Get AuctionHousebot configuration file
+void AuctionBotConfig::GetConfigFromFile()
+{
+ SetConfigMax(CONFIG_AHBOT_ALLIANCE_ITEM_AMOUNT_RATIO, "AuctionHouseBot.Alliance.Items.Amount.Ratio", 100, 10000);
+ SetConfigMax(CONFIG_AHBOT_HORDE_ITEM_AMOUNT_RATIO, "AuctionHouseBot.Horde.Items.Amount.Ratio", 100, 10000);
+ SetConfigMax(CONFIG_AHBOT_NEUTRAL_ITEM_AMOUNT_RATIO, "AuctionHouseBot.Neutral.Items.Amount.Ratio", 100, 10000);
+
+ SetAHBotIncludes(sConfigMgr->GetStringDefault("AuctionHouseBot.forceIncludeItems", ""));
+ SetAHBotExcludes(sConfigMgr->GetStringDefault("AuctionHouseBot.forceExcludeItems", ""));
+
+ SetConfig(CONFIG_AHBOT_BUYER_ALLIANCE_ENABLED, "AuctionHouseBot.Buyer.Alliance.Enabled", false);
+ 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_ITEMS_VENDOR, "AuctionHouseBot.Items.Vendor", false);
+ SetConfig(CONFIG_AHBOT_ITEMS_LOOT, "AuctionHouseBot.Items.Loot", true);
+ SetConfig(CONFIG_AHBOT_ITEMS_MISC, "AuctionHouseBot.Items.Misc", false);
+
+ SetConfig(CONFIG_AHBOT_BIND_NO, "AuctionHouseBot.Bind.No", true);
+ SetConfig(CONFIG_AHBOT_BIND_PICKUP, "AuctionHouseBot.Bind.Pickup", false);
+ SetConfig(CONFIG_AHBOT_BIND_EQUIP, "AuctionHouseBot.Bind.Equip", true);
+ SetConfig(CONFIG_AHBOT_BIND_USE, "AuctionHouseBot.Bind.Use", true);
+ SetConfig(CONFIG_AHBOT_BIND_QUEST, "AuctionHouseBot.Bind.Quest", false);
+ SetConfig(CONFIG_AHBOT_LOCKBOX_ENABLED, "AuctionHouseBot.LockBox.Enabled", false);
+
+ SetConfig(CONFIG_AHBOT_BUYPRICE_SELLER, "AuctionHouseBot.BuyPrice.Seller", true);
+
+ SetConfig(CONFIG_AHBOT_ITEMS_PER_CYCLE_BOOST, "AuctionHouseBot.ItemsPerCycle.Boost", 1000);
+ SetConfig(CONFIG_AHBOT_ITEMS_PER_CYCLE_NORMAL, "AuctionHouseBot.ItemsPerCycle.Normal", 20);
+
+ SetConfig(CONFIG_AHBOT_ITEM_MIN_ITEM_LEVEL, "AuctionHouseBot.Items.ItemLevel.Min", 0);
+ SetConfig(CONFIG_AHBOT_ITEM_MAX_ITEM_LEVEL, "AuctionHouseBot.Items.ItemLevel.Max", 0);
+ SetConfig(CONFIG_AHBOT_ITEM_MIN_REQ_LEVEL, "AuctionHouseBot.Items.ReqLevel.Min", 0);
+ SetConfig(CONFIG_AHBOT_ITEM_MAX_REQ_LEVEL, "AuctionHouseBot.Items.ReqLevel.Max", 0);
+ SetConfig(CONFIG_AHBOT_ITEM_MIN_SKILL_RANK, "AuctionHouseBot.Items.ReqSkill.Min", 0);
+ SetConfig(CONFIG_AHBOT_ITEM_MAX_SKILL_RANK, "AuctionHouseBot.Items.ReqSkill.Max", 0);
+
+ SetConfig(CONFIG_AHBOT_ITEM_GRAY_AMOUNT, "AuctionHouseBot.Items.Amount.Gray", 0);
+ SetConfig(CONFIG_AHBOT_ITEM_WHITE_AMOUNT, "AuctionHouseBot.Items.Amount.White", 2000);
+ SetConfig(CONFIG_AHBOT_ITEM_GREEN_AMOUNT, "AuctionHouseBot.Items.Amount.Green", 2500);
+ SetConfig(CONFIG_AHBOT_ITEM_BLUE_AMOUNT, "AuctionHouseBot.Items.Amount.Blue", 1500);
+ SetConfig(CONFIG_AHBOT_ITEM_PURPLE_AMOUNT, "AuctionHouseBot.Items.Amount.Purple", 500);
+ SetConfig(CONFIG_AHBOT_ITEM_ORANGE_AMOUNT, "AuctionHouseBot.Items.Amount.Orange", 0);
+ SetConfig(CONFIG_AHBOT_ITEM_YELLOW_AMOUNT, "AuctionHouseBot.Items.Amount.Yellow", 0);
+
+ SetConfigMax(CONFIG_AHBOT_CLASS_CONSUMABLE_AMOUNT, "AuctionHouseBot.Class.Consumable", 6, 10);
+ SetConfigMax(CONFIG_AHBOT_CLASS_CONTAINER_AMOUNT, "AuctionHouseBot.Class.Container", 4, 10);
+ SetConfigMax(CONFIG_AHBOT_CLASS_WEAPON_AMOUNT, "AuctionHouseBot.Class.Weapon", 8, 10);
+ SetConfigMax(CONFIG_AHBOT_CLASS_GEM_AMOUNT, "AuctionHouseBot.Class.Gem", 3, 10);
+ SetConfigMax(CONFIG_AHBOT_CLASS_ARMOR_AMOUNT, "AuctionHouseBot.Class.Armor", 8, 10);
+ SetConfigMax(CONFIG_AHBOT_CLASS_REAGENT_AMOUNT, "AuctionHouseBot.Class.Reagent", 1, 10);
+ SetConfigMax(CONFIG_AHBOT_CLASS_PROJECTILE_AMOUNT, "AuctionHouseBot.Class.Projectile", 2, 10);
+ SetConfigMax(CONFIG_AHBOT_CLASS_TRADEGOOD_AMOUNT, "AuctionHouseBot.Class.TradeGood", 10, 10);
+ SetConfigMax(CONFIG_AHBOT_CLASS_GENERIC_AMOUNT, "AuctionHouseBot.Class.Generic", 1, 10);
+ SetConfigMax(CONFIG_AHBOT_CLASS_RECIPE_AMOUNT, "AuctionHouseBot.Class.Recipe", 6, 10);
+ SetConfigMax(CONFIG_AHBOT_CLASS_QUIVER_AMOUNT, "AuctionHouseBot.Class.Quiver", 1, 10);
+ SetConfigMax(CONFIG_AHBOT_CLASS_QUEST_AMOUNT, "AuctionHouseBot.Class.Quest", 1, 10);
+ SetConfigMax(CONFIG_AHBOT_CLASS_KEY_AMOUNT, "AuctionHouseBot.Class.Key", 1, 10);
+ SetConfigMax(CONFIG_AHBOT_CLASS_MISC_AMOUNT, "AuctionHouseBot.Class.Misc", 5, 10);
+ SetConfigMax(CONFIG_AHBOT_CLASS_GLYPH_AMOUNT, "AuctionHouseBot.Class.Glyph", 3, 10);
+
+ SetConfig(CONFIG_AHBOT_ALLIANCE_PRICE_RATIO, "AuctionHouseBot.Alliance.Price.Ratio", 100);
+ SetConfig(CONFIG_AHBOT_HORDE_PRICE_RATIO, "AuctionHouseBot.Horde.Price.Ratio", 100);
+ SetConfig(CONFIG_AHBOT_NEUTRAL_PRICE_RATIO, "AuctionHouseBot.Neutral.Price.Ratio", 100);
+
+ SetConfig(CONFIG_AHBOT_ITEM_GRAY_PRICE_RATIO, "AuctionHouseBot.Items.Gray.Price.Ratio", 100);
+ SetConfig(CONFIG_AHBOT_ITEM_WHITE_PRICE_RATIO, "AuctionHouseBot.Items.White.Price.Ratio", 100);
+ SetConfig(CONFIG_AHBOT_ITEM_GREEN_PRICE_RATIO, "AuctionHouseBot.Items.Green.Price.Ratio", 100);
+ SetConfig(CONFIG_AHBOT_ITEM_BLUE_PRICE_RATIO, "AuctionHouseBot.Items.Blue.Price.Ratio", 100);
+ SetConfig(CONFIG_AHBOT_ITEM_PURPLE_PRICE_RATIO, "AuctionHouseBot.Items.Purple.Price.Ratio", 100);
+ SetConfig(CONFIG_AHBOT_ITEM_ORANGE_PRICE_RATIO, "AuctionHouseBot.Items.Orange.Price.Ratio", 100);
+ SetConfig(CONFIG_AHBOT_ITEM_YELLOW_PRICE_RATIO, "AuctionHouseBot.Items.Yellow.Price.Ratio", 100);
+
+ SetConfig(CONFIG_AHBOT_CLASS_CONSUMABLE_PRICE_RATIO, "AuctionHouseBot.Class.Consumable.Price.Ratio", 100);
+ SetConfig(CONFIG_AHBOT_CLASS_CONTAINER_PRICE_RATIO, "AuctionHouseBot.Class.Container.Price.Ratio", 100);
+ SetConfig(CONFIG_AHBOT_CLASS_WEAPON_PRICE_RATIO, "AuctionHouseBot.Class.Weapon.Price.Ratio", 100);
+ SetConfig(CONFIG_AHBOT_CLASS_GEM_PRICE_RATIO, "AuctionHouseBot.Class.Gem.Price.Ratio", 100);
+ SetConfig(CONFIG_AHBOT_CLASS_ARMOR_PRICE_RATIO, "AuctionHouseBot.Class.Armor.Price.Ratio", 100);
+ SetConfig(CONFIG_AHBOT_CLASS_REAGENT_PRICE_RATIO, "AuctionHouseBot.Class.Reagent.Price.Ratio", 100);
+ SetConfig(CONFIG_AHBOT_CLASS_PROJECTILE_PRICE_RATIO, "AuctionHouseBot.Class.Projectile.Price.Ratio", 100);
+ SetConfig(CONFIG_AHBOT_CLASS_TRADEGOOD_PRICE_RATIO, "AuctionHouseBot.Class.TradeGood.Price.Ratio", 100);
+ SetConfig(CONFIG_AHBOT_CLASS_GENERIC_PRICE_RATIO, "AuctionHouseBot.Class.Generic.Price.Ratio", 100);
+ SetConfig(CONFIG_AHBOT_CLASS_RECIPE_PRICE_RATIO, "AuctionHouseBot.Class.Recipe.Price.Ratio", 100);
+ SetConfig(CONFIG_AHBOT_CLASS_QUIVER_PRICE_RATIO, "AuctionHouseBot.Class.Quiver.Price.Ratio", 100);
+ SetConfig(CONFIG_AHBOT_CLASS_QUEST_PRICE_RATIO, "AuctionHouseBot.Class.Quest.Price.Ratio", 100);
+ SetConfig(CONFIG_AHBOT_CLASS_KEY_PRICE_RATIO, "AuctionHouseBot.Class.Key.Price.Ratio", 100);
+ SetConfig(CONFIG_AHBOT_CLASS_MISC_PRICE_RATIO, "AuctionHouseBot.Class.Misc.Price.Ratio", 100);
+ SetConfig(CONFIG_AHBOT_CLASS_GLYPH_PRICE_RATIO, "AuctionHouseBot.Class.Glyph.Price.Ratio", 100);
+
+ SetConfig(CONFIG_AHBOT_CLASS_CONSUMABLE_ALLOW_ZERO, "AuctionHouseBot.Class.Consumable.Allow.Zero", false);
+ SetConfig(CONFIG_AHBOT_CLASS_CONTAINER_ALLOW_ZERO, "AuctionHouseBot.Class.Container.Allow.Zero", false);
+ SetConfig(CONFIG_AHBOT_CLASS_WEAPON_ALLOW_ZERO, "AuctionHouseBot.Class.Weapon.Allow.Zero", false);
+ SetConfig(CONFIG_AHBOT_CLASS_GEM_ALLOW_ZERO, "AuctionHouseBot.Class.Gem.Allow.Zero", false);
+ SetConfig(CONFIG_AHBOT_CLASS_ARMOR_ALLOW_ZERO, "AuctionHouseBot.Class.Armor.Allow.Zero", false);
+ SetConfig(CONFIG_AHBOT_CLASS_REAGENT_ALLOW_ZERO, "AuctionHouseBot.Class.Reagent.Allow.Zero", false);
+ SetConfig(CONFIG_AHBOT_CLASS_PROJECTILE_ALLOW_ZERO, "AuctionHouseBot.Class.Projectile.Allow.Zero", false);
+ SetConfig(CONFIG_AHBOT_CLASS_TRADEGOOD_ALLOW_ZERO, "AuctionHouseBot.Class.TradeGood.Allow.Zero", false);
+ SetConfig(CONFIG_AHBOT_CLASS_RECIPE_ALLOW_ZERO, "AuctionHouseBot.Class.Recipe.Allow.Zero", false);
+ SetConfig(CONFIG_AHBOT_CLASS_QUIVER_ALLOW_ZERO, "AuctionHouseBot.Class.Quiver.Allow.Zero", false);
+ SetConfig(CONFIG_AHBOT_CLASS_QUEST_ALLOW_ZERO, "AuctionHouseBot.Class.Quest.Allow.Zero", false);
+ SetConfig(CONFIG_AHBOT_CLASS_KEY_ALLOW_ZERO, "AuctionHouseBot.Class.Key.Allow.Zero", false);
+ SetConfig(CONFIG_AHBOT_CLASS_MISC_ALLOW_ZERO, "AuctionHouseBot.Class.Misc.Allow.Zero", false);
+ SetConfig(CONFIG_AHBOT_CLASS_GLYPH_ALLOW_ZERO, "AuctionHouseBot.Class.Glyph.Allow.Zero", false);
+
+ SetConfig(CONFIG_AHBOT_MINTIME, "AuctionHouseBot.MinTime", 1);
+ SetConfig(CONFIG_AHBOT_MAXTIME, "AuctionHouseBot.MaxTime", 72);
+
+ SetConfigMinMax(CONFIG_AHBOT_BUYER_CHANCE_RATIO_ALLIANCE, "AuctionHouseBot.Buyer.Alliance.Chance.Ratio", 3, 1, 100);
+ SetConfigMinMax(CONFIG_AHBOT_BUYER_CHANCE_RATIO_HORDE, "AuctionHouseBot.Buyer.Horde.Chance.Ratio", 3, 1, 100);
+ SetConfigMinMax(CONFIG_AHBOT_BUYER_CHANCE_RATIO_NEUTRAL, "AuctionHouseBot.Buyer.Neutral.Chance.Ratio", 3, 1, 100);
+ SetConfigMinMax(CONFIG_AHBOT_BUYER_RECHECK_INTERVAL, "AuctionHouseBot.Buyer.Recheck.Interval", 20, 1, DAY / MINUTE);
+
+ SetConfig(CONFIG_AHBOT_SELLER_ENABLED, "AuctionHouseBot.Seller.Enabled", false);
+ SetConfig(CONFIG_AHBOT_BUYER_ENABLED, "AuctionHouseBot.Buyer.Enabled", false);
+ SetConfig(CONFIG_AHBOT_BUYPRICE_BUYER, "AuctionHouseBot.Buyer.Buyprice", true);
+
+ SetConfig(CONFIG_AHBOT_CLASS_MISC_MOUNT_MIN_REQ_LEVEL, "AuctionHouseBot.Class.Misc.Mount.ReqLevel.Min", 0);
+ SetConfig(CONFIG_AHBOT_CLASS_MISC_MOUNT_MAX_REQ_LEVEL, "AuctionHouseBot.Class.Misc.Mount.ReqLevel.Max", 0);
+ SetConfig(CONFIG_AHBOT_CLASS_MISC_MOUNT_MIN_SKILL_RANK, "AuctionHouseBot.Class.Misc.Mount.ReqSkill.Min", 0);
+ SetConfig(CONFIG_AHBOT_CLASS_MISC_MOUNT_MAX_SKILL_RANK, "AuctionHouseBot.Class.Misc.Mount.ReqSkill.Max", 0);
+ SetConfig(CONFIG_AHBOT_CLASS_GLYPH_MIN_REQ_LEVEL, "AuctionHouseBot.Class.Glyph.ReqLevel.Min", 0);
+ SetConfig(CONFIG_AHBOT_CLASS_GLYPH_MAX_REQ_LEVEL, "AuctionHouseBot.Class.Glyph.ReqLevel.Max", 0);
+ SetConfig(CONFIG_AHBOT_CLASS_GLYPH_MIN_ITEM_LEVEL, "AuctionHouseBot.Class.Glyph.ItemLevel.Min", 0);
+ SetConfig(CONFIG_AHBOT_CLASS_GLYPH_MAX_ITEM_LEVEL, "AuctionHouseBot.Class.Glyph.ItemLevel.Max", 0);
+ SetConfig(CONFIG_AHBOT_CLASS_TRADEGOOD_MIN_ITEM_LEVEL, "AuctionHouseBot.Class.TradeGood.ItemLevel.Min", 0);
+ SetConfig(CONFIG_AHBOT_CLASS_TRADEGOOD_MAX_ITEM_LEVEL, "AuctionHouseBot.Class.TradeGood.ItemLevel.Max", 0);
+ SetConfig(CONFIG_AHBOT_CLASS_CONTAINER_MIN_ITEM_LEVEL, "AuctionHouseBot.Class.Container.ItemLevel.Min", 0);
+ SetConfig(CONFIG_AHBOT_CLASS_CONTAINER_MAX_ITEM_LEVEL, "AuctionHouseBot.Class.Container.ItemLevel.Max", 0);
+}
+
+char const* AuctionBotConfig::GetHouseTypeName(AuctionHouseType houseType)
+{
+ static char const* names[MAX_AUCTION_HOUSE_TYPE] = { "Alliance", "Horde", "Neutral" };
+ return names[houseType];
+}
+
+uint32 AuctionBotConfig::GetConfigItemAmountRatio(AuctionHouseType houseType) const
+{
+ switch (houseType)
+ {
+ case AUCTION_HOUSE_ALLIANCE:
+ return GetConfig(CONFIG_AHBOT_ALLIANCE_ITEM_AMOUNT_RATIO);
+ case AUCTION_HOUSE_HORDE:
+ return GetConfig(CONFIG_AHBOT_HORDE_ITEM_AMOUNT_RATIO);
+ default:
+ return GetConfig(CONFIG_AHBOT_NEUTRAL_ITEM_AMOUNT_RATIO);
+ }
+}
+
+bool AuctionBotConfig::GetConfigBuyerEnabled(AuctionHouseType houseType) const
+{
+ switch (houseType)
+ {
+ case AUCTION_HOUSE_ALLIANCE:
+ return GetConfig(CONFIG_AHBOT_BUYER_ALLIANCE_ENABLED);
+ case AUCTION_HOUSE_HORDE:
+ return GetConfig(CONFIG_AHBOT_BUYER_HORDE_ENABLED);
+ default:
+ return GetConfig(CONFIG_AHBOT_BUYER_NEUTRAL_ENABLED);
+ }
+}
+
+uint32 AuctionBotConfig::GetConfigItemQualityAmount(AuctionQuality quality) const
+{
+ switch (quality)
+ {
+ case AUCTION_QUALITY_GRAY:
+ return GetConfig(CONFIG_AHBOT_ITEM_GRAY_AMOUNT);
+ case AUCTION_QUALITY_WHITE:
+ return GetConfig(CONFIG_AHBOT_ITEM_WHITE_AMOUNT);
+ case AUCTION_QUALITY_GREEN:
+ return GetConfig(CONFIG_AHBOT_ITEM_GREEN_AMOUNT);
+ case AUCTION_QUALITY_BLUE:
+ return GetConfig(CONFIG_AHBOT_ITEM_BLUE_AMOUNT);
+ case AUCTION_QUALITY_PURPLE:
+ return GetConfig(CONFIG_AHBOT_ITEM_PURPLE_AMOUNT);
+ case AUCTION_QUALITY_ORANGE:
+ return GetConfig(CONFIG_AHBOT_ITEM_ORANGE_AMOUNT);
+ default:
+ return GetConfig(CONFIG_AHBOT_ITEM_YELLOW_AMOUNT);
+ }
+}
+
+AuctionHouseBot::AuctionHouseBot(): _buyer(nullptr), _seller(nullptr), _operationSelector(0)
+{
+}
+
+AuctionHouseBot::~AuctionHouseBot()
+{
+ delete _buyer;
+ delete _seller;
+}
+
+void AuctionHouseBot::InitializeAgents()
+{
+ if (sAuctionBotConfig->GetConfig(CONFIG_AHBOT_SELLER_ENABLED))
+ {
+ delete _seller;
+
+ _seller = new AuctionBotSeller();
+ if (!_seller->Initialize())
+ {
+ delete _seller;
+ _seller = nullptr;
+ }
+ }
+
+ if (sAuctionBotConfig->GetConfig(CONFIG_AHBOT_BUYER_ENABLED))
+ {
+ delete _buyer;
+
+ _buyer = new AuctionBotBuyer();
+ if (!_buyer->Initialize())
+ {
+ delete _buyer;
+ _buyer = nullptr;
+ }
+ }
+}
+
+void AuctionHouseBot::Initialize()
+{
+ if (sAuctionBotConfig->Initialize())
+ InitializeAgents();
+}
+
+void AuctionHouseBot::SetItemsRatio(uint32 al, uint32 ho, uint32 ne)
+{
+ if (_seller)
+ _seller->SetItemsRatio(al, ho, ne);
+}
+
+void AuctionHouseBot::SetItemsRatioForHouse(AuctionHouseType house, uint32 val)
+{
+ if (_seller)
+ _seller->SetItemsRatioForHouse(house, val);
+}
+
+void AuctionHouseBot::SetItemsAmount(uint32(&vals)[MAX_AUCTION_QUALITY])
+{
+ if (_seller)
+ _seller->SetItemsAmount(vals);
+}
+
+void AuctionHouseBot::SetItemsAmountForQuality(AuctionQuality quality, uint32 val)
+{
+ if (_seller)
+ _seller->SetItemsAmountForQuality(quality, val);
+}
+
+void AuctionHouseBot::ReloadAllConfig()
+{
+ sAuctionBotConfig->Reload();
+ InitializeAgents();
+}
+
+void AuctionHouseBot::PrepareStatusInfos(AuctionHouseBotStatusInfo& statusInfo)
+{
+ for (uint32 i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
+ {
+ statusInfo[i].ItemsCount = 0;
+
+ for (int j = 0; j < MAX_AUCTION_QUALITY; ++j)
+ statusInfo[i].QualityInfo[j] = 0;
+
+ AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(AuctionHouseType(i));
+ for (AuctionHouseObject::AuctionEntryMap::const_iterator itr = auctionHouse->GetAuctionsBegin(); itr != auctionHouse->GetAuctionsEnd(); ++itr)
+ {
+ AuctionEntry* auctionEntry = itr->second;
+ if (Item* item = sAuctionMgr->GetAItem(auctionEntry->itemGUIDLow))
+ {
+ ItemTemplate const* prototype = item->GetTemplate();
+ if (!auctionEntry->owner) // Add only ahbot items
+ {
+ if (prototype->Quality < MAX_AUCTION_QUALITY)
+ ++statusInfo[i].QualityInfo[prototype->Quality];
+
+ ++statusInfo[i].ItemsCount;
+ }
+ }
+ }
+ }
+}
+
+void AuctionHouseBot::Rebuild(bool all)
+{
+ for (uint32 i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
+ {
+ AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(AuctionHouseType(i));
+ for (AuctionHouseObject::AuctionEntryMap::const_iterator itr = auctionHouse->GetAuctionsBegin(); itr != auctionHouse->GetAuctionsEnd(); ++itr)
+ if (!itr->second->owner) // ahbot auction
+ if (all || itr->second->bid == 0) // expire now auction if no bid or forced
+ itr->second->expire_time = sWorld->GetGameTime();
+ }
+}
+
+void AuctionHouseBot::Update()
+{
+ // nothing do...
+ if (!_buyer && !_seller)
+ return;
+
+ // scan all possible update cases until first success
+ for (uint32 count = 0; count < 2 * MAX_AUCTION_HOUSE_TYPE; ++count)
+ {
+ bool successStep = false;
+
+ if (_operationSelector < MAX_AUCTION_HOUSE_TYPE)
+ {
+ if (_seller)
+ successStep = _seller->Update(AuctionHouseType(_operationSelector));
+ }
+ else
+ {
+ if (_buyer)
+ successStep = _buyer->Update(AuctionHouseType(_operationSelector - MAX_AUCTION_HOUSE_TYPE));
+ }
+
+ ++_operationSelector;
+ if (_operationSelector >= 2 * MAX_AUCTION_HOUSE_TYPE)
+ _operationSelector = 0;
+
+ // one success update per call
+ if (successStep)
+ break;
+ }
+}
diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBot.h b/src/server/game/AuctionHouseBot/AuctionHouseBot.h
new file mode 100644
index 00000000000..04ca96dfdd9
--- /dev/null
+++ b/src/server/game/AuctionHouseBot/AuctionHouseBot.h
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2008-2014 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 AUCTION_HOUSE_BOT_H
+#define AUCTION_HOUSE_BOT_H
+
+#include "Define.h"
+
+class AuctionBotSeller;
+class AuctionBotBuyer;
+
+// shadow of ItemQualities with skipped ITEM_QUALITY_HEIRLOOM, anything after ITEM_QUALITY_ARTIFACT(6) in fact
+enum AuctionQuality
+{
+ AUCTION_QUALITY_GRAY = ITEM_QUALITY_POOR,
+ AUCTION_QUALITY_WHITE = ITEM_QUALITY_NORMAL,
+ AUCTION_QUALITY_GREEN = ITEM_QUALITY_UNCOMMON,
+ AUCTION_QUALITY_BLUE = ITEM_QUALITY_RARE,
+ AUCTION_QUALITY_PURPLE = ITEM_QUALITY_EPIC,
+ AUCTION_QUALITY_ORANGE = ITEM_QUALITY_LEGENDARY,
+ AUCTION_QUALITY_YELLOW = ITEM_QUALITY_ARTIFACT,
+};
+
+#define MAX_AUCTION_QUALITY 7
+
+enum AuctionHouseType
+{
+ AUCTION_HOUSE_ALLIANCE = 0,
+ AUCTION_HOUSE_HORDE = 1,
+ AUCTION_HOUSE_NEUTRAL = 2
+};
+
+#define MAX_AUCTION_HOUSE_TYPE 3
+
+enum AuctionBotConfigUInt32Values
+{
+ CONFIG_AHBOT_MAXTIME,
+ CONFIG_AHBOT_MINTIME,
+ CONFIG_AHBOT_ITEMS_PER_CYCLE_BOOST,
+ CONFIG_AHBOT_ITEMS_PER_CYCLE_NORMAL,
+ CONFIG_AHBOT_ALLIANCE_ITEM_AMOUNT_RATIO,
+ CONFIG_AHBOT_HORDE_ITEM_AMOUNT_RATIO,
+ CONFIG_AHBOT_NEUTRAL_ITEM_AMOUNT_RATIO,
+ CONFIG_AHBOT_ITEM_MIN_ITEM_LEVEL,
+ CONFIG_AHBOT_ITEM_MAX_ITEM_LEVEL,
+ CONFIG_AHBOT_ITEM_MIN_REQ_LEVEL,
+ CONFIG_AHBOT_ITEM_MAX_REQ_LEVEL,
+ CONFIG_AHBOT_ITEM_MIN_SKILL_RANK,
+ CONFIG_AHBOT_ITEM_MAX_SKILL_RANK,
+ CONFIG_AHBOT_ITEM_GRAY_AMOUNT,
+ CONFIG_AHBOT_ITEM_WHITE_AMOUNT,
+ CONFIG_AHBOT_ITEM_GREEN_AMOUNT,
+ CONFIG_AHBOT_ITEM_BLUE_AMOUNT,
+ CONFIG_AHBOT_ITEM_PURPLE_AMOUNT,
+ CONFIG_AHBOT_ITEM_ORANGE_AMOUNT,
+ CONFIG_AHBOT_ITEM_YELLOW_AMOUNT,
+ CONFIG_AHBOT_CLASS_CONSUMABLE_AMOUNT,
+ CONFIG_AHBOT_CLASS_CONTAINER_AMOUNT,
+ CONFIG_AHBOT_CLASS_WEAPON_AMOUNT,
+ CONFIG_AHBOT_CLASS_GEM_AMOUNT,
+ CONFIG_AHBOT_CLASS_ARMOR_AMOUNT,
+ CONFIG_AHBOT_CLASS_REAGENT_AMOUNT,
+ CONFIG_AHBOT_CLASS_PROJECTILE_AMOUNT,
+ CONFIG_AHBOT_CLASS_TRADEGOOD_AMOUNT,
+ CONFIG_AHBOT_CLASS_GENERIC_AMOUNT,
+ CONFIG_AHBOT_CLASS_RECIPE_AMOUNT,
+ CONFIG_AHBOT_CLASS_QUIVER_AMOUNT,
+ CONFIG_AHBOT_CLASS_QUEST_AMOUNT,
+ CONFIG_AHBOT_CLASS_KEY_AMOUNT,
+ CONFIG_AHBOT_CLASS_MISC_AMOUNT,
+ CONFIG_AHBOT_CLASS_GLYPH_AMOUNT,
+ CONFIG_AHBOT_ALLIANCE_PRICE_RATIO,
+ CONFIG_AHBOT_HORDE_PRICE_RATIO,
+ CONFIG_AHBOT_NEUTRAL_PRICE_RATIO,
+ CONFIG_AHBOT_ITEM_GRAY_PRICE_RATIO,
+ CONFIG_AHBOT_ITEM_WHITE_PRICE_RATIO,
+ CONFIG_AHBOT_ITEM_GREEN_PRICE_RATIO,
+ CONFIG_AHBOT_ITEM_BLUE_PRICE_RATIO,
+ CONFIG_AHBOT_ITEM_PURPLE_PRICE_RATIO,
+ CONFIG_AHBOT_ITEM_ORANGE_PRICE_RATIO,
+ CONFIG_AHBOT_ITEM_YELLOW_PRICE_RATIO,
+ CONFIG_AHBOT_CLASS_CONSUMABLE_PRICE_RATIO,
+ CONFIG_AHBOT_CLASS_CONTAINER_PRICE_RATIO,
+ CONFIG_AHBOT_CLASS_WEAPON_PRICE_RATIO,
+ CONFIG_AHBOT_CLASS_GEM_PRICE_RATIO,
+ CONFIG_AHBOT_CLASS_ARMOR_PRICE_RATIO,
+ CONFIG_AHBOT_CLASS_REAGENT_PRICE_RATIO,
+ CONFIG_AHBOT_CLASS_PROJECTILE_PRICE_RATIO,
+ CONFIG_AHBOT_CLASS_TRADEGOOD_PRICE_RATIO,
+ CONFIG_AHBOT_CLASS_GENERIC_PRICE_RATIO,
+ CONFIG_AHBOT_CLASS_RECIPE_PRICE_RATIO,
+ CONFIG_AHBOT_CLASS_MONEY_PRICE_RATIO,
+ CONFIG_AHBOT_CLASS_QUIVER_PRICE_RATIO,
+ CONFIG_AHBOT_CLASS_QUEST_PRICE_RATIO,
+ CONFIG_AHBOT_CLASS_KEY_PRICE_RATIO,
+ CONFIG_AHBOT_CLASS_PERMANENT_PRICE_RATIO,
+ CONFIG_AHBOT_CLASS_MISC_PRICE_RATIO,
+ CONFIG_AHBOT_CLASS_GLYPH_PRICE_RATIO,
+ CONFIG_AHBOT_BUYER_CHANCE_RATIO_ALLIANCE,
+ CONFIG_AHBOT_BUYER_CHANCE_RATIO_HORDE,
+ CONFIG_AHBOT_BUYER_CHANCE_RATIO_NEUTRAL,
+ CONFIG_AHBOT_BUYER_RECHECK_INTERVAL,
+ CONFIG_AHBOT_CLASS_MISC_MOUNT_MIN_REQ_LEVEL,
+ CONFIG_AHBOT_CLASS_MISC_MOUNT_MAX_REQ_LEVEL,
+ CONFIG_AHBOT_CLASS_MISC_MOUNT_MIN_SKILL_RANK,
+ CONFIG_AHBOT_CLASS_MISC_MOUNT_MAX_SKILL_RANK,
+ CONFIG_AHBOT_CLASS_GLYPH_MIN_REQ_LEVEL,
+ CONFIG_AHBOT_CLASS_GLYPH_MAX_REQ_LEVEL,
+ CONFIG_AHBOT_CLASS_GLYPH_MIN_ITEM_LEVEL,
+ CONFIG_AHBOT_CLASS_GLYPH_MAX_ITEM_LEVEL,
+ CONFIG_AHBOT_CLASS_TRADEGOOD_MIN_ITEM_LEVEL,
+ CONFIG_AHBOT_CLASS_TRADEGOOD_MAX_ITEM_LEVEL,
+ CONFIG_AHBOT_CLASS_CONTAINER_MIN_ITEM_LEVEL,
+ CONFIG_AHBOT_CLASS_CONTAINER_MAX_ITEM_LEVEL,
+ CONFIG_UINT32_AHBOT_UINT32_COUNT
+};
+
+enum AuctionBotConfigBoolValues
+{
+ CONFIG_AHBOT_BUYER_ALLIANCE_ENABLED,
+ CONFIG_AHBOT_BUYER_HORDE_ENABLED,
+ CONFIG_AHBOT_BUYER_NEUTRAL_ENABLED,
+ CONFIG_AHBOT_ITEMS_VENDOR,
+ CONFIG_AHBOT_ITEMS_LOOT,
+ CONFIG_AHBOT_ITEMS_MISC,
+ CONFIG_AHBOT_BIND_NO,
+ CONFIG_AHBOT_BIND_PICKUP,
+ CONFIG_AHBOT_BIND_EQUIP,
+ CONFIG_AHBOT_BIND_USE,
+ CONFIG_AHBOT_BIND_QUEST,
+ CONFIG_AHBOT_BUYPRICE_SELLER,
+ CONFIG_AHBOT_BUYPRICE_BUYER,
+ CONFIG_AHBOT_SELLER_ENABLED,
+ CONFIG_AHBOT_BUYER_ENABLED,
+ CONFIG_AHBOT_LOCKBOX_ENABLED,
+ CONFIG_AHBOT_CLASS_CONSUMABLE_ALLOW_ZERO,
+ CONFIG_AHBOT_CLASS_CONTAINER_ALLOW_ZERO,
+ CONFIG_AHBOT_CLASS_WEAPON_ALLOW_ZERO,
+ CONFIG_AHBOT_CLASS_GEM_ALLOW_ZERO,
+ CONFIG_AHBOT_CLASS_ARMOR_ALLOW_ZERO,
+ CONFIG_AHBOT_CLASS_REAGENT_ALLOW_ZERO,
+ CONFIG_AHBOT_CLASS_PROJECTILE_ALLOW_ZERO,
+ CONFIG_AHBOT_CLASS_TRADEGOOD_ALLOW_ZERO,
+ CONFIG_AHBOT_CLASS_RECIPE_ALLOW_ZERO,
+ CONFIG_AHBOT_CLASS_QUIVER_ALLOW_ZERO,
+ CONFIG_AHBOT_CLASS_QUEST_ALLOW_ZERO,
+ CONFIG_AHBOT_CLASS_KEY_ALLOW_ZERO,
+ CONFIG_AHBOT_CLASS_MISC_ALLOW_ZERO,
+ CONFIG_AHBOT_CLASS_GLYPH_ALLOW_ZERO,
+ CONFIG_UINT32_AHBOT_BOOL_COUNT
+};
+
+// All basic config data used by other AHBot classes for self-configure.
+class AuctionBotConfig
+{
+private:
+ AuctionBotConfig(): _itemsPerCycleBoost(1000), _itemsPerCycleNormal(20) {}
+ ~AuctionBotConfig() {}
+ AuctionBotConfig(const AuctionBotConfig&);
+ AuctionBotConfig& operator=(const AuctionBotConfig&);
+
+public:
+ static AuctionBotConfig* instance()
+ {
+ static AuctionBotConfig instance;
+ return &instance;
+ }
+
+ bool Initialize();
+ const std::string& GetAHBotIncludes() const { return _AHBotIncludes; }
+ const std::string& GetAHBotExcludes() const { return _AHBotExcludes; }
+
+ uint32 GetConfig(AuctionBotConfigUInt32Values index) const { return _configUint32Values[index]; }
+ bool GetConfig(AuctionBotConfigBoolValues index) const { return _configBoolValues[index]; }
+ void SetConfig(AuctionBotConfigBoolValues index, bool value) { _configBoolValues[index] = value; }
+ void SetConfig(AuctionBotConfigUInt32Values index, uint32 value) { _configUint32Values[index] = value; }
+
+ uint32 GetConfigItemAmountRatio(AuctionHouseType houseType) const;
+ bool GetConfigBuyerEnabled(AuctionHouseType houseType) const;
+ uint32 GetConfigItemQualityAmount(AuctionQuality quality) const;
+
+ uint32 GetItemPerCycleBoost() const { return _itemsPerCycleBoost; }
+ uint32 GetItemPerCycleNormal() const { return _itemsPerCycleNormal; }
+ void Reload() { GetConfigFromFile(); }
+
+ static char const* GetHouseTypeName(AuctionHouseType houseType);
+
+private:
+ std::string _AHBotIncludes;
+ std::string _AHBotExcludes;
+ uint32 _itemsPerCycleBoost;
+ uint32 _itemsPerCycleNormal;
+
+ uint32 _configUint32Values[CONFIG_UINT32_AHBOT_UINT32_COUNT];
+ bool _configBoolValues[CONFIG_UINT32_AHBOT_BOOL_COUNT];
+
+ void SetAHBotIncludes(const std::string& AHBotIncludes) { _AHBotIncludes = AHBotIncludes; }
+ void SetAHBotExcludes(const std::string& AHBotExcludes) { _AHBotExcludes = AHBotExcludes; }
+
+ void SetConfig(AuctionBotConfigUInt32Values index, char const* fieldname, uint32 defvalue);
+ 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 GetConfigFromFile();
+};
+
+#define sAuctionBotConfig AuctionBotConfig::instance()
+
+class AuctionBotAgent
+{
+public:
+ AuctionBotAgent() {}
+ virtual ~AuctionBotAgent() {}
+ virtual bool Initialize() = 0;
+ virtual bool Update(AuctionHouseType houseType) = 0;
+};
+
+struct AuctionHouseBotStatusInfoPerType
+{
+ uint32 ItemsCount;
+ uint32 QualityInfo[MAX_AUCTION_QUALITY];
+};
+
+typedef AuctionHouseBotStatusInfoPerType AuctionHouseBotStatusInfo[MAX_AUCTION_HOUSE_TYPE];
+
+// This class handle both Selling and Buying method
+// (holder of AuctionBotBuyer and AuctionBotSeller objects)
+class AuctionHouseBot
+{
+private:
+ AuctionHouseBot();
+ ~AuctionHouseBot();
+ AuctionHouseBot(const AuctionHouseBot&);
+ AuctionHouseBot& operator=(const AuctionHouseBot&);
+
+public:
+ static AuctionHouseBot* instance()
+ {
+ static AuctionHouseBot instance;
+ return &instance;
+ }
+
+ void Update();
+ void Initialize();
+
+ // Followed method is mainly used by cs_ahbot.cpp for in-game/console command
+ void SetItemsRatio(uint32 al, uint32 ho, uint32 ne);
+ void SetItemsRatioForHouse(AuctionHouseType house, uint32 val);
+ void SetItemsAmount(uint32(&vals)[MAX_AUCTION_QUALITY]);
+ void SetItemsAmountForQuality(AuctionQuality quality, uint32 val);
+ void ReloadAllConfig();
+ void Rebuild(bool all);
+
+ void PrepareStatusInfos(AuctionHouseBotStatusInfo& statusInfo);
+private:
+ void InitializeAgents();
+
+ AuctionBotBuyer* _buyer;
+ AuctionBotSeller* _seller;
+
+ uint32 _operationSelector; // 0..2*MAX_AUCTION_HOUSE_TYPE-1
+};
+
+#define sAuctionBot AuctionHouseBot::instance()
+
+#endif
diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.cpp b/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.cpp
new file mode 100644
index 00000000000..0043482c77f
--- /dev/null
+++ b/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.cpp
@@ -0,0 +1,432 @@
+/*
+ * Copyright (C) 2008-2014 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 "Log.h"
+#include "Item.h"
+#include "ItemPrototype.h"
+#include "AuctionHouseBotBuyer.h"
+
+AuctionBotBuyer::AuctionBotBuyer(): _checkInterval(20)
+{
+ // Define faction for our main data class.
+ for (int i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
+ _houseConfig[i].Initialize(AuctionHouseType(i));
+}
+
+AuctionBotBuyer::~AuctionBotBuyer()
+{
+}
+
+bool AuctionBotBuyer::Initialize()
+{
+ LoadConfig();
+
+ bool activeHouse = false;
+ for (int i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
+ {
+ if (_houseConfig[i].BuyerEnabled)
+ {
+ activeHouse = true;
+ break;
+ }
+ }
+
+ if (!activeHouse)
+ return false;
+
+ //load Check interval
+ _checkInterval = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_BUYER_RECHECK_INTERVAL) * MINUTE;
+ TC_LOG_DEBUG("ahbot", "AHBot buyer interval between 2 check = %u", _checkInterval);
+ return true;
+}
+
+void AuctionBotBuyer::LoadBuyerValues(BuyerConfiguration& config)
+{
+ uint32 factionChance;
+
+ switch (config.GetHouseType())
+ {
+ case AUCTION_HOUSE_ALLIANCE:
+ config.BuyerPriceRatio = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ALLIANCE_PRICE_RATIO) + 50;
+ factionChance = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_BUYER_CHANCE_RATIO_ALLIANCE);
+ break;
+ case AUCTION_HOUSE_HORDE:
+ config.BuyerPriceRatio = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_HORDE_PRICE_RATIO) + 50;
+ factionChance = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_BUYER_CHANCE_RATIO_HORDE);
+ break;
+ default:
+ config.BuyerPriceRatio = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_NEUTRAL_PRICE_RATIO) + 50;
+ factionChance = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_BUYER_CHANCE_RATIO_NEUTRAL);
+ break;
+ }
+
+ config.FactionChance = 5000 * factionChance;
+}
+
+void AuctionBotBuyer::LoadConfig()
+{
+ for (int i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
+ {
+ _houseConfig[i].BuyerEnabled = sAuctionBotConfig->GetConfigBuyerEnabled(AuctionHouseType(i));
+ if (_houseConfig[i].BuyerEnabled)
+ LoadBuyerValues(_houseConfig[i]);
+ }
+}
+
+uint32 AuctionBotBuyer::GetBuyableEntry(BuyerConfiguration& config)
+{
+ config.SameItemInfo.clear();
+ uint32 count = 0;
+ time_t now = time(nullptr);
+
+ AuctionHouseObject* house = sAuctionMgr->GetAuctionsMap(config.GetHouseType());
+ for (AuctionHouseObject::AuctionEntryMap::const_iterator itr = house->GetAuctionsBegin(); itr != house->GetAuctionsEnd(); ++itr)
+ {
+ AuctionEntry* entry = itr->second;
+ Item* item = sAuctionMgr->GetAItem(entry->itemGUIDLow);
+ if (item)
+ {
+ ItemTemplate const * prototype = item->GetTemplate();
+ if (prototype)
+ {
+ ++config.SameItemInfo[item->GetEntry()].ItemCount; // Structure constructor will make sure Element are correctly initialized if entry is created here.
+ config.SameItemInfo[item->GetEntry()].BuyPrice = config.SameItemInfo[item->GetEntry()].BuyPrice + (itr->second->buyout / item->GetCount());
+ config.SameItemInfo[item->GetEntry()].BidPrice = config.SameItemInfo[item->GetEntry()].BidPrice + (itr->second->startbid / item->GetCount());
+ if (itr->second->buyout != 0)
+ {
+ if (itr->second->buyout / item->GetCount() < config.SameItemInfo[item->GetEntry()].MinBuyPrice)
+ config.SameItemInfo[item->GetEntry()].MinBuyPrice = itr->second->buyout / item->GetCount();
+ else if (config.SameItemInfo[item->GetEntry()].MinBuyPrice == 0)
+ config.SameItemInfo[item->GetEntry()].MinBuyPrice = itr->second->buyout / item->GetCount();
+ }
+ if (itr->second->startbid / item->GetCount() < config.SameItemInfo[item->GetEntry()].MinBidPrice)
+ config.SameItemInfo[item->GetEntry()].MinBidPrice = itr->second->startbid / item->GetCount();
+ else if (config.SameItemInfo[item->GetEntry()].MinBidPrice == 0)
+ config.SameItemInfo[item->GetEntry()].MinBidPrice = itr->second->startbid / item->GetCount();
+
+ if (!entry->owner)
+ {
+
+ if (entry->bid != 0 && entry->bidder) // Add bid by player
+ {
+ config.CheckedEntry[entry->Id].LastExist = now;
+ config.CheckedEntry[entry->Id].AuctionId = entry->Id;
+ ++count;
+ }
+ }
+ else
+ {
+ if (entry->bid != 0)
+ {
+ if (entry->bidder)
+ {
+ config.CheckedEntry[entry->Id].LastExist = now;
+ config.CheckedEntry[entry->Id].AuctionId = entry->Id;
+ ++count;
+ }
+ }
+ else
+ {
+ config.CheckedEntry[entry->Id].LastExist = now;
+ config.CheckedEntry[entry->Id].AuctionId = entry->Id;
+ ++count;
+ }
+ }
+ }
+ }
+ }
+
+ TC_LOG_DEBUG("ahbot", "AHBot: %u items added to buyable vector for ah type: %u", count, config.GetHouseType());
+ TC_LOG_DEBUG("ahbot", "AHBot: SameItemInfo size = %u", (uint32)config.SameItemInfo.size());
+ return count;
+}
+
+void AuctionBotBuyer::PrepareListOfEntry(BuyerConfiguration& config)
+{
+ time_t now = time(nullptr) - 5;
+
+ for (CheckEntryMap::iterator itr = config.CheckedEntry.begin(); itr != config.CheckedEntry.end();)
+ {
+ if (itr->second.LastExist < (now - 5))
+ config.CheckedEntry.erase(itr++);
+ else
+ ++itr;
+ }
+
+ TC_LOG_DEBUG("ahbot", "AHBot: CheckedEntry size = %u", (uint32)config.CheckedEntry.size());
+}
+
+bool AuctionBotBuyer::IsBuyableEntry(uint32 buyoutPrice, double inGameBuyPrice, double maxBuyablePrice, uint32 minBuyPrice, uint32 maxChance, uint32 chanceRatio)
+{
+ double ratio = 0;
+ uint32 chance = 0;
+
+ if (buyoutPrice <= minBuyPrice)
+ {
+ if (buyoutPrice <= maxBuyablePrice)
+ chance = maxChance;
+ else
+ {
+
+ if (buyoutPrice > 0 && maxBuyablePrice > 0)
+ {
+ ratio = buyoutPrice / maxBuyablePrice;
+ if (ratio < 10)
+ chance = maxChance - (ratio * maxChance / 10);
+ else
+ chance = 1;
+ }
+ }
+ }
+ else if (buyoutPrice <= inGameBuyPrice)
+ {
+ if (buyoutPrice <= maxBuyablePrice)
+ chance = maxChance / 5;
+ else
+ {
+
+ if (buyoutPrice > 0 && maxBuyablePrice > 0)
+ {
+ ratio = buyoutPrice / maxBuyablePrice;
+ if (ratio < 10)
+ chance = (maxChance / 5) - (ratio * maxChance / 50);
+ else
+ chance = 1;
+ }
+ }
+ }
+ else if (buyoutPrice <= maxBuyablePrice)
+ chance = maxChance / 10;
+ else
+ {
+ if (buyoutPrice > 0 && maxBuyablePrice > 0)
+ {
+ ratio = buyoutPrice / maxBuyablePrice;
+ if (ratio < 10)
+ chance = (maxChance / 5) - (ratio* maxChance / 50);
+ else
+ chance = 0;
+ }
+ else
+ chance = 0;
+ }
+
+ if (urand(1, chanceRatio) <= chance)
+ {
+ TC_LOG_DEBUG("ahbot", "AHBot: WIN BUY! Chance = %u, num = %u.", chance, chanceRatio);
+ return true;
+ }
+ else
+ {
+ TC_LOG_DEBUG("ahbot", "AHBot: LOOSE BUY! Chance = %u, num = %u.", chance, chanceRatio);
+ return false;
+ }
+}
+
+bool AuctionBotBuyer::IsBidableEntry(uint32 bidPrice, double inGameBuyPrice, double maxBidablePrice, uint32 minBidPrice, uint32 maxChance, uint32 chanceRatio)
+{
+ double ratio = 0;
+ uint32 chance = 0;
+
+ if (bidPrice <= minBidPrice)
+ {
+ if (inGameBuyPrice != 0 && bidPrice < inGameBuyPrice - (inGameBuyPrice / 30))
+ chance = maxChance;
+ else
+ {
+ if (bidPrice < maxBidablePrice)
+ {
+ ratio = maxBidablePrice / bidPrice;
+ if (ratio < 3)
+ chance = maxChance / 500 * ratio;
+ else
+ chance = maxChance / 500;
+ }
+ }
+ }
+ else if (bidPrice < (inGameBuyPrice - (inGameBuyPrice / 30)))
+ chance = (maxChance / 10);
+ else
+ {
+ if (bidPrice < maxBidablePrice)
+ {
+ ratio = maxBidablePrice / bidPrice;
+ if (ratio < 4)
+ chance = maxChance / 1000 * ratio;
+ else
+ chance = maxChance / 1000;
+ }
+ }
+
+ if (urand(1, chanceRatio) <= chance)
+ {
+ TC_LOG_DEBUG("ahbot", "AHBot: WIN BID! Chance = %u, num = %u.", chance, chanceRatio);
+ return true;
+ }
+ else
+ {
+ TC_LOG_DEBUG("ahbot", "AHBot: LOOSE BID! Chance = %u, num = %u.", chance, chanceRatio);
+ return false;
+ }
+}
+
+void AuctionBotBuyer::PlaceBidToEntry(AuctionEntry* auction, uint32 bidPrice)
+{
+ TC_LOG_DEBUG("ahbot", "AHBot: Bid placed to entry %u, %.2fg", auction->Id, float(bidPrice) / 10000.0f);
+ auction->bid = bidPrice;
+}
+
+void AuctionBotBuyer::BuyEntry(AuctionEntry* auction)
+{
+ TC_LOG_DEBUG("ahbot", "AHBot: Entry %u bought at %.2fg", auction->Id, float(auction->buyout) / 10000.0f);
+ auction->bid = auction->buyout;
+}
+
+void AuctionBotBuyer::AddNewAuctionBuyerBotBid(BuyerConfiguration& config)
+{
+ AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(config.GetHouseType());
+
+ PrepareListOfEntry(config);
+
+ time_t now = time(nullptr);
+ uint32 buyCycles;
+ if (config.CheckedEntry.size() > sAuctionBotConfig->GetItemPerCycleBoost())
+ {
+ buyCycles = sAuctionBotConfig->GetItemPerCycleBoost();
+ TC_LOG_DEBUG("ahbot", "AHBot: Boost value used for Buyer! (if this happens often adjust both ItemsPerCycle in worldserver.conf)");
+ }
+ else
+ buyCycles = sAuctionBotConfig->GetItemPerCycleNormal();
+
+ for (CheckEntryMap::iterator itr = config.CheckedEntry.begin(); itr != config.CheckedEntry.end();)
+ {
+ AuctionEntry* auction = auctionHouse->GetAuction(itr->second.AuctionId);
+ if (!auction) // is auction not active now
+ {
+ TC_LOG_DEBUG("ahbot", "AHBot: Entry %u doesn't exists, perhaps bought already?",
+ itr->second.AuctionId);
+
+ config.CheckedEntry.erase(itr++);
+ continue;
+ }
+
+ if (itr->second.LastChecked != 0 && (now - itr->second.LastChecked) <= _checkInterval)
+ {
+ TC_LOG_DEBUG("ahbot", "AHBot: In time interval wait for entry %u!", auction->Id);
+ ++itr;
+ continue;
+ }
+
+ if (buyCycles == 0)
+ break;
+
+ uint32 maxChance = 5000;
+
+ Item* item = sAuctionMgr->GetAItem(auction->itemGUIDLow);
+ if (!item) // auction item not accessible, possible auction in payment pending mode
+ {
+ config.CheckedEntry.erase(itr++);
+ continue;
+ }
+
+ ItemTemplate const* prototype = item->GetTemplate();
+
+ uint32 basePrice = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_BUYPRICE_BUYER) ? prototype->BuyPrice : prototype->SellPrice;
+ basePrice *= item->GetCount();
+
+ double maxBuyablePrice = (basePrice * config.BuyerPriceRatio) / 100;
+ BuyerItemInfoMap::iterator sameItemItr = config.SameItemInfo.find(item->GetEntry());
+ uint32 buyoutPrice = auction->buyout / item->GetCount();
+
+ uint32 bidPrice;
+ uint32 bidPriceByItem;
+ if (auction->bid >= auction->startbid)
+ {
+ bidPrice = auction->GetAuctionOutBid();
+ bidPriceByItem = auction->bid / item->GetCount();
+ }
+ else
+ {
+ bidPrice = auction->startbid;
+ bidPriceByItem = auction->startbid / item->GetCount();
+ }
+
+ double inGameBuyPrice;
+ double inGameBidPrice;
+ if (sameItemItr == config.SameItemInfo.end())
+ {
+ inGameBuyPrice = 0;
+ inGameBidPrice = 0;
+ }
+ else
+ {
+ if (sameItemItr->second.ItemCount == 1)
+ maxBuyablePrice = maxBuyablePrice * 5; // if only one item exist can be bought if the price is high too.
+ inGameBuyPrice = sameItemItr->second.BuyPrice / sameItemItr->second.ItemCount;
+ inGameBidPrice = sameItemItr->second.BidPrice / sameItemItr->second.ItemCount;
+ }
+
+ double maxBidablePrice = maxBuyablePrice - (maxBuyablePrice / 30); // Max Bidable price defined to 70% of max buyable price
+
+ TC_LOG_DEBUG("ahbot", "AHBot: Auction added with data:");
+ TC_LOG_DEBUG("ahbot", "AHBot: MaxPrice of Entry %u is %.1fg.", itr->second.AuctionId, maxBuyablePrice / 10000);
+ TC_LOG_DEBUG("ahbot", "AHBot: GamePrice buy=%.1fg, bid=%.1fg.", inGameBuyPrice / 10000, inGameBidPrice / 10000);
+ TC_LOG_DEBUG("ahbot", "AHBot: Minimal price see in AH Buy=%ug, Bid=%ug.",
+ sameItemItr->second.MinBuyPrice / 10000, sameItemItr->second.MinBidPrice / 10000);
+ TC_LOG_DEBUG("ahbot", "AHBot: Actual Entry price, Buy=%ug, Bid=%ug.", buyoutPrice / 10000, bidPrice / 10000);
+
+ if (!auction->owner) // Original auction owner
+ maxChance = maxChance / 5; // if Owner is AHBot this mean player placed bid on this auction. We divide by 5 chance for AhBuyer to place bid on it. (This make more challenge than ignore entry)
+ if (auction->buyout != 0) // Is the item directly buyable?
+ {
+ if (IsBuyableEntry(buyoutPrice, inGameBuyPrice, maxBuyablePrice, sameItemItr->second.MinBuyPrice, maxChance, config.FactionChance))
+ {
+ if (IsBidableEntry(bidPriceByItem, inGameBuyPrice, maxBidablePrice, sameItemItr->second.MinBidPrice, maxChance / 2, config.FactionChance))
+ {
+ if (urand(0, 5) == 0)
+ PlaceBidToEntry(auction, bidPrice);
+ else
+ BuyEntry(auction);
+ }
+ else
+ BuyEntry(auction);
+ }
+ else if (IsBidableEntry(bidPriceByItem, inGameBuyPrice, maxBidablePrice, sameItemItr->second.MinBidPrice, maxChance / 2, config.FactionChance))
+ PlaceBidToEntry(auction, bidPrice);
+ }
+ else if (IsBidableEntry(bidPriceByItem, inGameBuyPrice, maxBidablePrice, sameItemItr->second.MinBidPrice, maxChance, config.FactionChance))
+ PlaceBidToEntry(auction, bidPrice);
+
+ itr->second.LastChecked = now;
+ --buyCycles;
+
+ ++itr;
+ }
+}
+
+bool AuctionBotBuyer::Update(AuctionHouseType houseType)
+{
+ if (sAuctionBotConfig->GetConfigBuyerEnabled(houseType))
+ {
+ TC_LOG_DEBUG("ahbot", "AHBot: %s buying ...", AuctionBotConfig::GetHouseTypeName(houseType));
+ if (GetBuyableEntry(_houseConfig[houseType]) > 0)
+ AddNewAuctionBuyerBotBid(_houseConfig[houseType]);
+ return true;
+ }
+
+ return false;
+}
diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.h b/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.h
new file mode 100644
index 00000000000..1148435f1c1
--- /dev/null
+++ b/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2008-2014 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 AUCTION_HOUSE_BOT_BUYER_H
+#define AUCTION_HOUSE_BOT_BUYER_H
+
+#include "Define.h"
+#include "AuctionHouseMgr.h"
+#include "AuctionHouseBot.h"
+
+struct BuyerAuctionEval
+{
+ BuyerAuctionEval(): AuctionId(0), LastChecked(0), LastExist(0) {}
+
+ uint32 AuctionId;
+ time_t LastChecked;
+ time_t LastExist;
+};
+
+struct BuyerItemInfo
+{
+ BuyerItemInfo(): ItemCount(0), BuyPrice(0), BidPrice(0), MinBuyPrice(0), MinBidPrice(0) {}
+
+ uint32 ItemCount;
+ double BuyPrice;
+ double BidPrice;
+ uint32 MinBuyPrice;
+ uint32 MinBidPrice;
+};
+
+typedef std::map<uint32, BuyerItemInfo> BuyerItemInfoMap;
+typedef std::map<uint32, BuyerAuctionEval> CheckEntryMap;
+
+struct BuyerConfiguration
+{
+ BuyerConfiguration(): FactionChance(3), BuyerEnabled(false), BuyerPriceRatio(100), _houseType(AUCTION_HOUSE_NEUTRAL) {}
+
+ void Initialize(AuctionHouseType houseType)
+ {
+ _houseType = houseType;
+ }
+
+ AuctionHouseType GetHouseType() const { return _houseType; }
+
+ BuyerItemInfoMap SameItemInfo;
+ CheckEntryMap CheckedEntry;
+ uint32 FactionChance;
+ bool BuyerEnabled;
+ uint32 BuyerPriceRatio;
+
+private:
+ AuctionHouseType _houseType;
+};
+
+// This class handle all Buyer method
+// (holder of AuctionBotConfig for each auction house type)
+class AuctionBotBuyer : public AuctionBotAgent
+{
+public:
+ AuctionBotBuyer();
+ ~AuctionBotBuyer() override;
+
+ bool Initialize() override;
+ bool Update(AuctionHouseType houseType) override;
+
+ void LoadConfig();
+ void AddNewAuctionBuyerBotBid(BuyerConfiguration& config);
+
+private:
+ uint32 _checkInterval;
+ BuyerConfiguration _houseConfig[MAX_AUCTION_HOUSE_TYPE];
+
+ void LoadBuyerValues(BuyerConfiguration& config);
+ bool IsBuyableEntry(uint32 buyoutPrice, double inGameBuyPrice, double maxBuyablePrice, uint32 minBuyPrice, uint32 maxChance, uint32 chanceRatio);
+ bool IsBidableEntry(uint32 bidPrice, double inGameBuyPrice, double maxBidablePrice, uint32 minBidPrice, uint32 maxChance, uint32 chanceRatio);
+ void PlaceBidToEntry(AuctionEntry* auction, uint32 bidPrice);
+ void BuyEntry(AuctionEntry* auction);
+ void PrepareListOfEntry(BuyerConfiguration& config);
+ uint32 GetBuyableEntry(BuyerConfiguration& config);
+};
+
+#endif
diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp
new file mode 100644
index 00000000000..13aa1f22fa3
--- /dev/null
+++ b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp
@@ -0,0 +1,1029 @@
+/*
+ * Copyright (C) 2008-2014 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 "Log.h"
+#include "DBCStores.h"
+#include "ObjectMgr.h"
+#include "AuctionHouseMgr.h"
+#include "AuctionHouseBotSeller.h"
+
+AuctionBotSeller::AuctionBotSeller()
+{
+ // Define faction for our main data class.
+ for (int i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
+ _houseConfig[i].Initialize(AuctionHouseType(i));
+}
+
+AuctionBotSeller::~AuctionBotSeller()
+{
+}
+
+bool AuctionBotSeller::Initialize()
+{
+ std::vector<uint32> npcItems;
+ std::vector<uint32> lootItems;
+ std::vector<uint32> includeItems;
+ std::vector<uint32> excludeItems;
+
+ TC_LOG_DEBUG("ahbot", "AHBot seller filters:");
+
+ {
+ std::stringstream includeStream(sAuctionBotConfig->GetAHBotIncludes());
+ std::string temp;
+ while (getline(includeStream, temp, ','))
+ includeItems.push_back(atoi(temp.c_str()));
+ }
+
+ {
+ std::stringstream excludeStream(sAuctionBotConfig->GetAHBotExcludes());
+ std::string temp;
+ while (getline(excludeStream, temp, ','))
+ excludeItems.push_back(atoi(temp.c_str()));
+ }
+
+ TC_LOG_DEBUG("ahbot", "Forced Inclusion %u items", (uint32)includeItems.size());
+ TC_LOG_DEBUG("ahbot", "Forced Exclusion %u items", (uint32)excludeItems.size());
+
+ TC_LOG_DEBUG("ahbot", "Loading npc vendor items for filter..");
+ const CreatureTemplateContainer* creatures = sObjectMgr->GetCreatureTemplates();
+ std::set<uint32> tempItems;
+ for (CreatureTemplateContainer::const_iterator it = creatures->begin(); it != creatures->end(); ++it)
+ {
+ if (const VendorItemData* data = sObjectMgr->GetNpcVendorItemList(it->first))
+ {
+ for (VendorItemList::const_iterator it2 = data->m_items.begin(); it2 != data->m_items.end(); ++it2)
+ tempItems.insert((*it2)->item);
+ }
+ }
+ for (std::set<uint32>::const_iterator it = tempItems.begin(); it != tempItems.end(); ++it)
+ npcItems.push_back(*it);
+
+ TC_LOG_DEBUG("ahbot", "Npc vendor filter has %u items", (uint32)npcItems.size());
+
+ TC_LOG_DEBUG("ahbot", "Loading loot items for filter..");
+ QueryResult result = WorldDatabase.PQuery(
+ "SELECT `item` FROM `creature_loot_template` UNION "
+ "SELECT `item` FROM `disenchant_loot_template` UNION "
+ "SELECT `item` FROM `fishing_loot_template` UNION "
+ "SELECT `item` FROM `gameobject_loot_template` UNION "
+ "SELECT `item` FROM `item_loot_template` UNION "
+ "SELECT `item` FROM `milling_loot_template` UNION "
+ "SELECT `item` FROM `pickpocketing_loot_template` UNION "
+ "SELECT `item` FROM `prospecting_loot_template` UNION "
+ "SELECT `item` FROM `skinning_loot_template` UNION "
+ "SELECT `item` FROM `spell_loot_template`");
+
+ if (result)
+ {
+ do
+ {
+ Field* fields = result->Fetch();
+
+ uint32 entry = fields[0].GetUInt32();
+ if (!entry)
+ continue;
+
+ lootItems.push_back(entry);
+ } while (result->NextRow());
+ }
+
+ TC_LOG_DEBUG("ahbot", "Loot filter has %u items", (uint32)lootItems.size());
+ TC_LOG_DEBUG("ahbot", "Sorting and cleaning items for AHBot seller...");
+
+ uint32 itemsAdded = 0;
+
+ for (uint32 itemId = 0; itemId < sItemStore.GetNumRows(); ++itemId)
+ {
+ ItemTemplate const* prototype = sObjectMgr->GetItemTemplate(itemId);
+
+ if (!prototype)
+ continue;
+
+ // skip items with too high quality (code can't properly work with its)
+ if (prototype->Quality >= MAX_AUCTION_QUALITY)
+ continue;
+
+ // forced exclude filter
+ bool isExcludeItem = false;
+ for (size_t i = 0; i < excludeItems.size() && !isExcludeItem; ++i)
+ if (itemId == excludeItems[i])
+ isExcludeItem = true;
+
+ if (isExcludeItem)
+ continue;
+
+ // forced include filter
+ bool isForcedIncludeItem = false;
+ for (size_t i = 0; i < includeItems.size() && !isForcedIncludeItem; ++i)
+ if (itemId == includeItems[i])
+ isForcedIncludeItem = true;
+
+ if (isForcedIncludeItem)
+ {
+ _itemPool[prototype->Quality][prototype->Class].push_back(itemId);
+ ++itemsAdded;
+ continue;
+ }
+
+ // bounding filters
+ switch (prototype->Bonding)
+ {
+ case NO_BIND:
+ if (!sAuctionBotConfig->GetConfig(CONFIG_AHBOT_BIND_NO))
+ continue;
+ break;
+ case BIND_WHEN_PICKED_UP:
+ if (!sAuctionBotConfig->GetConfig(CONFIG_AHBOT_BIND_PICKUP))
+ continue;
+ break;
+ case BIND_WHEN_EQUIPED:
+ if (!sAuctionBotConfig->GetConfig(CONFIG_AHBOT_BIND_EQUIP))
+ continue;
+ break;
+ case BIND_WHEN_USE:
+ if (!sAuctionBotConfig->GetConfig(CONFIG_AHBOT_BIND_USE))
+ continue;
+ break;
+ case BIND_QUEST_ITEM:
+ if (!sAuctionBotConfig->GetConfig(CONFIG_AHBOT_BIND_QUEST))
+ continue;
+ break;
+ default:
+ continue;
+ }
+
+ bool allowZero = false;
+ switch (prototype->Class)
+ {
+ case ITEM_CLASS_CONSUMABLE:
+ allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONSUMABLE_ALLOW_ZERO); break;
+ case ITEM_CLASS_CONTAINER:
+ allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONTAINER_ALLOW_ZERO); break;
+ case ITEM_CLASS_WEAPON:
+ allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_WEAPON_ALLOW_ZERO); break;
+ case ITEM_CLASS_GEM:
+ allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GEM_ALLOW_ZERO); break;
+ case ITEM_CLASS_ARMOR:
+ allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_ARMOR_ALLOW_ZERO); break;
+ case ITEM_CLASS_REAGENT:
+ allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_REAGENT_ALLOW_ZERO); break;
+ case ITEM_CLASS_PROJECTILE:
+ allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_PROJECTILE_ALLOW_ZERO); break;
+ case ITEM_CLASS_TRADE_GOODS:
+ allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_TRADEGOOD_ALLOW_ZERO); break;
+ case ITEM_CLASS_RECIPE:
+ allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RECIPE_ALLOW_ZERO); break;
+ case ITEM_CLASS_QUIVER:
+ allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_QUIVER_ALLOW_ZERO); break;
+ case ITEM_CLASS_QUEST:
+ allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_QUEST_ALLOW_ZERO); break;
+ case ITEM_CLASS_KEY:
+ allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_KEY_ALLOW_ZERO); break;
+ case ITEM_CLASS_MISC:
+ allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_MISC_ALLOW_ZERO); break;
+ case ITEM_CLASS_GLYPH:
+ allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GLYPH_ALLOW_ZERO); break;
+ default:
+ allowZero = false;
+ }
+
+ // Filter out items with no buy/sell price unless otherwise flagged in the config.
+ if (!allowZero)
+ {
+ if (sAuctionBotConfig->GetConfig(CONFIG_AHBOT_BUYPRICE_SELLER))
+ {
+ if (prototype->BuyPrice == 0)
+ continue;
+ }
+ else
+ {
+ if (prototype->SellPrice == 0)
+ continue;
+ }
+ }
+
+ // vendor filter
+ if (!sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEMS_VENDOR))
+ {
+ bool isVendorItem = false;
+ for (size_t i = 0; i < npcItems.size() && !isVendorItem; ++i)
+ if (itemId == npcItems[i])
+ isVendorItem = true;
+
+ if (isVendorItem)
+ continue;
+ }
+
+ // loot filter
+ if (!sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEMS_LOOT))
+ {
+ bool isLootItem = false;
+ for (size_t i = 0; i < lootItems.size() && !isLootItem; ++i)
+ if (itemId == lootItems[i])
+ isLootItem = true;
+
+ if (isLootItem)
+ continue;
+ }
+
+ // not vendor/loot filter
+ if (!sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEMS_MISC))
+ {
+ bool isVendorItem = false;
+ bool isLootItem = false;
+
+ for (size_t i = 0; i < npcItems.size() && !isVendorItem; ++i)
+ if (itemId == npcItems[i])
+ isVendorItem = true;
+
+ for (size_t i = 0; i < lootItems.size() && !isLootItem; ++i)
+ if (itemId == lootItems[i])
+ isLootItem = true;
+
+ if (!isLootItem && !isVendorItem)
+ continue;
+ }
+
+ // item class/subclass specific filters
+ switch (prototype->Class)
+ {
+ case ITEM_CLASS_ARMOR:
+ case ITEM_CLASS_WEAPON:
+ {
+ if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_MIN_ITEM_LEVEL))
+ if (prototype->ItemLevel < value)
+ continue;
+ if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_MAX_ITEM_LEVEL))
+ if (prototype->ItemLevel > value)
+ continue;
+ if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_MIN_REQ_LEVEL))
+ if (prototype->RequiredLevel < value)
+ continue;
+ if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_MAX_REQ_LEVEL))
+ if (prototype->RequiredLevel > value)
+ continue;
+ if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_MIN_SKILL_RANK))
+ if (prototype->RequiredSkillRank < value)
+ continue;
+ if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_MAX_SKILL_RANK))
+ if (prototype->RequiredSkillRank > value)
+ continue;
+ break;
+ }
+ case ITEM_CLASS_RECIPE:
+ case ITEM_CLASS_CONSUMABLE:
+ case ITEM_CLASS_PROJECTILE:
+ {
+ if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_MIN_REQ_LEVEL))
+ if (prototype->RequiredLevel < value)
+ continue;
+ if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_MAX_REQ_LEVEL))
+ if (prototype->RequiredLevel > value)
+ continue;
+ if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_MIN_SKILL_RANK))
+ if (prototype->RequiredSkillRank < value)
+ continue;
+ if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_MAX_SKILL_RANK))
+ if (prototype->RequiredSkillRank > value)
+ continue;
+ break;
+ }
+ case ITEM_CLASS_MISC:
+ if (prototype->SubClass == ITEM_SUBCLASS_JUNK_MOUNT)
+ {
+ if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_MISC_MOUNT_MIN_REQ_LEVEL))
+ if (prototype->RequiredLevel < value)
+ continue;
+ if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_MISC_MOUNT_MAX_REQ_LEVEL))
+ if (prototype->RequiredLevel > value)
+ continue;
+ if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_MISC_MOUNT_MIN_SKILL_RANK))
+ if (prototype->RequiredSkillRank < value)
+ continue;
+ if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_MISC_MOUNT_MAX_SKILL_RANK))
+ if (prototype->RequiredSkillRank > value)
+ continue;
+ }
+
+ if (prototype->Flags & ITEM_FLAG_UNLOCKED)
+ {
+ // skip any not locked lootable items (mostly quest specific or reward cases)
+ if (!prototype->LockID)
+ continue;
+
+ if (!sAuctionBotConfig->GetConfig(CONFIG_AHBOT_LOCKBOX_ENABLED))
+ continue;
+ }
+
+ break;
+ case ITEM_CLASS_GLYPH:
+ {
+ if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GLYPH_MIN_REQ_LEVEL))
+ if (prototype->RequiredLevel < value)
+ continue;
+ if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GLYPH_MAX_REQ_LEVEL))
+ if (prototype->RequiredLevel > value)
+ continue;
+ if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GLYPH_MIN_ITEM_LEVEL))
+ if (prototype->RequiredLevel < value)
+ continue;
+ if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GLYPH_MAX_ITEM_LEVEL))
+ if (prototype->RequiredLevel > value)
+ continue;
+ break;
+ }
+ case ITEM_CLASS_TRADE_GOODS:
+ {
+ if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_TRADEGOOD_MIN_ITEM_LEVEL))
+ if (prototype->ItemLevel < value)
+ continue;
+ if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_TRADEGOOD_MAX_ITEM_LEVEL))
+ if (prototype->ItemLevel > value)
+ continue;
+ break;
+ }
+ case ITEM_CLASS_CONTAINER:
+ case ITEM_CLASS_QUIVER:
+ {
+ if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONTAINER_MIN_ITEM_LEVEL))
+ if (prototype->ItemLevel < value)
+ continue;
+ if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONTAINER_MAX_ITEM_LEVEL))
+ if (prototype->ItemLevel > value)
+ continue;
+ break;
+ }
+ }
+
+ _itemPool[prototype->Quality][prototype->Class].push_back(itemId);
+ ++itemsAdded;
+ }
+
+ if (!itemsAdded)
+ {
+ TC_LOG_ERROR("ahbot", "AuctionHouseBot seller not have items, disabled.");
+ sAuctionBotConfig->SetConfig(CONFIG_AHBOT_ALLIANCE_ITEM_AMOUNT_RATIO, 0);
+ sAuctionBotConfig->SetConfig(CONFIG_AHBOT_HORDE_ITEM_AMOUNT_RATIO, 0);
+ sAuctionBotConfig->SetConfig(CONFIG_AHBOT_NEUTRAL_ITEM_AMOUNT_RATIO, 0);
+ return false;
+ }
+
+ TC_LOG_DEBUG("ahbot", "AuctionHouseBot seller will use %u items to fill auction house (according your config choices)", itemsAdded);
+
+ LoadConfig();
+
+ TC_LOG_DEBUG("ahbot", "Items loaded \tGray\tWhite\tGreen\tBlue\tPurple\tOrange\tYellow");
+ for (uint32 i = 0; i < MAX_ITEM_CLASS; ++i)
+ TC_LOG_DEBUG("ahbot", "\t\t%u\t%u\t%u\t%u\t%u\t%u\t%u",
+ (uint32)_itemPool[0][i].size(), (uint32)_itemPool[1][i].size(), (uint32)_itemPool[2][i].size(),
+ (uint32)_itemPool[3][i].size(), (uint32)_itemPool[4][i].size(), (uint32)_itemPool[5][i].size(),
+ (uint32)_itemPool[6][i].size());
+
+ TC_LOG_DEBUG("ahbot", "AHBot seller configuration data loaded and initialized");
+ return true;
+}
+
+void AuctionBotSeller::LoadConfig()
+{
+ for (int i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
+ if (sAuctionBotConfig->GetConfigItemAmountRatio(AuctionHouseType(i)))
+ LoadSellerValues(_houseConfig[i]);
+}
+
+void AuctionBotSeller::LoadItemsQuantity(SellerConfiguration& config)
+{
+ uint32 ratio = sAuctionBotConfig->GetConfigItemAmountRatio(config.GetHouseType());
+
+ config.SetItemsAmountPerQuality(AUCTION_QUALITY_GRAY, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_GRAY_AMOUNT) * ratio / 100);
+ config.SetItemsAmountPerQuality(AUCTION_QUALITY_WHITE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_WHITE_AMOUNT) * ratio / 100);
+ config.SetItemsAmountPerQuality(AUCTION_QUALITY_GREEN, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_GREEN_AMOUNT) * ratio / 100);
+ config.SetItemsAmountPerQuality(AUCTION_QUALITY_BLUE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_BLUE_AMOUNT) * ratio / 100);
+ config.SetItemsAmountPerQuality(AUCTION_QUALITY_PURPLE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_PURPLE_AMOUNT) * ratio / 100);
+ config.SetItemsAmountPerQuality(AUCTION_QUALITY_ORANGE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_ORANGE_AMOUNT) * ratio / 100);
+ config.SetItemsAmountPerQuality(AUCTION_QUALITY_YELLOW, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_YELLOW_AMOUNT) * ratio / 100);
+
+ // Set quantity wanted but only on possible item color
+ // This avoid any no-exist class-color items selection by random items create function
+ // ============================================================================================
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GRAY, ITEM_CLASS_CONSUMABLE, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GRAY, ITEM_CLASS_CONTAINER, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GRAY, ITEM_CLASS_WEAPON, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_WEAPON_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GRAY, ITEM_CLASS_GEM, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GRAY, ITEM_CLASS_ARMOR, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_ARMOR_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GRAY, ITEM_CLASS_REAGENT, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GRAY, ITEM_CLASS_PROJECTILE, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GRAY, ITEM_CLASS_TRADE_GOODS, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_TRADEGOOD_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GRAY, ITEM_CLASS_GENERIC, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GRAY, ITEM_CLASS_RECIPE, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GRAY, ITEM_CLASS_QUIVER, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GRAY, ITEM_CLASS_QUEST, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_QUEST_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GRAY, ITEM_CLASS_KEY, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GRAY, ITEM_CLASS_MISC, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_MISC_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GRAY, ITEM_CLASS_GLYPH, 0);
+
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_WHITE, ITEM_CLASS_CONSUMABLE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONSUMABLE_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_WHITE, ITEM_CLASS_CONTAINER, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONTAINER_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_WHITE, ITEM_CLASS_WEAPON, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_WEAPON_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_WHITE, ITEM_CLASS_GEM, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GEM_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_WHITE, ITEM_CLASS_ARMOR, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_ARMOR_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_WHITE, ITEM_CLASS_REAGENT, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_REAGENT_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_WHITE, ITEM_CLASS_PROJECTILE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_PROJECTILE_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_WHITE, ITEM_CLASS_TRADE_GOODS, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_TRADEGOOD_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_WHITE, ITEM_CLASS_GENERIC, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GENERIC_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_WHITE, ITEM_CLASS_RECIPE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RECIPE_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_WHITE, ITEM_CLASS_QUIVER, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_QUIVER_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_WHITE, ITEM_CLASS_QUEST, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_QUEST_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_WHITE, ITEM_CLASS_KEY, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_KEY_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_WHITE, ITEM_CLASS_MISC, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_MISC_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_WHITE, ITEM_CLASS_GLYPH, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GLYPH_AMOUNT));
+
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREEN, ITEM_CLASS_CONSUMABLE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONSUMABLE_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREEN, ITEM_CLASS_CONTAINER, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONTAINER_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREEN, ITEM_CLASS_WEAPON, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_WEAPON_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREEN, ITEM_CLASS_GEM, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GEM_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREEN, ITEM_CLASS_ARMOR, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_ARMOR_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREEN, ITEM_CLASS_REAGENT, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREEN, ITEM_CLASS_PROJECTILE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_PROJECTILE_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREEN, ITEM_CLASS_TRADE_GOODS, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_TRADEGOOD_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREEN, ITEM_CLASS_GENERIC, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREEN, ITEM_CLASS_RECIPE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RECIPE_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREEN, ITEM_CLASS_QUIVER, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_QUIVER_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREEN, ITEM_CLASS_QUEST, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_QUEST_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREEN, ITEM_CLASS_KEY, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_KEY_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREEN, ITEM_CLASS_MISC, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_MISC_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREEN, ITEM_CLASS_GLYPH, 0);
+
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_BLUE, ITEM_CLASS_CONSUMABLE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONSUMABLE_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_BLUE, ITEM_CLASS_CONTAINER, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONTAINER_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_BLUE, ITEM_CLASS_WEAPON, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_WEAPON_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_BLUE, ITEM_CLASS_GEM, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GEM_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_BLUE, ITEM_CLASS_ARMOR, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_ARMOR_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_BLUE, ITEM_CLASS_REAGENT, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_BLUE, ITEM_CLASS_PROJECTILE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_PROJECTILE_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_BLUE, ITEM_CLASS_TRADE_GOODS, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_TRADEGOOD_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_BLUE, ITEM_CLASS_GENERIC, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_BLUE, ITEM_CLASS_RECIPE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RECIPE_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_BLUE, ITEM_CLASS_QUIVER, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_QUIVER_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_BLUE, ITEM_CLASS_QUEST, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_QUEST_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_BLUE, ITEM_CLASS_KEY, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_BLUE, ITEM_CLASS_MISC, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_MISC_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_BLUE, ITEM_CLASS_GLYPH, 0);
+
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_PURPLE, ITEM_CLASS_CONSUMABLE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONSUMABLE_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_PURPLE, ITEM_CLASS_CONTAINER, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONTAINER_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_PURPLE, ITEM_CLASS_WEAPON, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_WEAPON_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_PURPLE, ITEM_CLASS_GEM, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GEM_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_PURPLE, ITEM_CLASS_ARMOR, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_ARMOR_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_PURPLE, ITEM_CLASS_REAGENT, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_PURPLE, ITEM_CLASS_PROJECTILE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_PROJECTILE_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_PURPLE, ITEM_CLASS_TRADE_GOODS, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_TRADEGOOD_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_PURPLE, ITEM_CLASS_GENERIC, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_PURPLE, ITEM_CLASS_RECIPE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RECIPE_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_PURPLE, ITEM_CLASS_QUIVER, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_PURPLE, ITEM_CLASS_QUEST, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_QUEST_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_PURPLE, ITEM_CLASS_KEY, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_PURPLE, ITEM_CLASS_MISC, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_MISC_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_PURPLE, ITEM_CLASS_GLYPH, 0);
+
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_ORANGE, ITEM_CLASS_CONSUMABLE, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_ORANGE, ITEM_CLASS_CONTAINER, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_ORANGE, ITEM_CLASS_WEAPON, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_WEAPON_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_ORANGE, ITEM_CLASS_GEM, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_ORANGE, ITEM_CLASS_ARMOR, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_ARMOR_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_ORANGE, ITEM_CLASS_REAGENT, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_ORANGE, ITEM_CLASS_PROJECTILE, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_ORANGE, ITEM_CLASS_TRADE_GOODS, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_TRADEGOOD_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_ORANGE, ITEM_CLASS_GENERIC, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_ORANGE, ITEM_CLASS_RECIPE, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_ORANGE, ITEM_CLASS_QUIVER, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_ORANGE, ITEM_CLASS_QUEST, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_ORANGE, ITEM_CLASS_KEY, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_ORANGE, ITEM_CLASS_MISC, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_ORANGE, ITEM_CLASS_GLYPH, 0);
+
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_CONSUMABLE, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_CONTAINER, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_WEAPON, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_WEAPON_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_GEM, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_ARMOR, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_ARMOR_AMOUNT));
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_REAGENT, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_PROJECTILE, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_TRADE_GOODS, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_GENERIC, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_RECIPE, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_QUIVER, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_QUEST, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_KEY, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_MISC, 0);
+ config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_GLYPH, 0);
+ // ============================================================================================
+
+ // Set the best value to get nearest amount of items wanted
+ for (uint32 j = 0; j < MAX_AUCTION_QUALITY; ++j)
+ {
+ uint32 index = config.GetItemsAmountPerQuality(AuctionQuality(j)) /
+ (sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONSUMABLE_AMOUNT) + sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONTAINER_AMOUNT) + sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_WEAPON_AMOUNT) +
+ sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GEM_AMOUNT) + sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_ARMOR_AMOUNT) + sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_REAGENT_AMOUNT) +
+ sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_PROJECTILE_AMOUNT) + sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_TRADEGOOD_AMOUNT) + sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GENERIC_AMOUNT) +
+ sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RECIPE_AMOUNT) + sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_QUIVER_AMOUNT) + sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_QUEST_AMOUNT) +
+ sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_KEY_AMOUNT) + sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_MISC_AMOUNT) + sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GLYPH_AMOUNT));
+
+ for (uint32 i = 0; i < MAX_ITEM_CLASS; ++i)
+ config.SetItemsAmountPerClass(AuctionQuality(j), ItemClass(i), index);
+ }
+}
+
+void AuctionBotSeller::LoadSellerValues(SellerConfiguration& config)
+{
+ LoadItemsQuantity(config);
+ uint32 PriceRatio;
+ switch (config.GetHouseType())
+ {
+ case AUCTION_HOUSE_ALLIANCE:
+ PriceRatio = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ALLIANCE_PRICE_RATIO);
+ break;
+ case AUCTION_HOUSE_HORDE:
+ PriceRatio = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_HORDE_PRICE_RATIO);
+ break;
+ default:
+ PriceRatio = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_NEUTRAL_PRICE_RATIO);
+ break;
+ }
+
+ config.SetPriceRatioPerQuality(AUCTION_QUALITY_GRAY, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_GRAY_PRICE_RATIO) / 100);
+ config.SetPriceRatioPerQuality(AUCTION_QUALITY_WHITE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_WHITE_PRICE_RATIO) / 100);
+ config.SetPriceRatioPerQuality(AUCTION_QUALITY_GREEN, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_GREEN_PRICE_RATIO) / 100);
+ config.SetPriceRatioPerQuality(AUCTION_QUALITY_BLUE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_BLUE_PRICE_RATIO) / 100);
+ config.SetPriceRatioPerQuality(AUCTION_QUALITY_PURPLE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_PURPLE_PRICE_RATIO) / 100);
+ config.SetPriceRatioPerQuality(AUCTION_QUALITY_ORANGE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_ORANGE_PRICE_RATIO) / 100);
+ config.SetPriceRatioPerQuality(AUCTION_QUALITY_YELLOW, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_YELLOW_PRICE_RATIO) / 100);
+
+ config.SetPriceRatioPerClass(ITEM_CLASS_CONSUMABLE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONSUMABLE_PRICE_RATIO));
+ config.SetPriceRatioPerClass(ITEM_CLASS_CONTAINER, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONTAINER_PRICE_RATIO));
+ config.SetPriceRatioPerClass(ITEM_CLASS_WEAPON, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_WEAPON_PRICE_RATIO));
+ config.SetPriceRatioPerClass(ITEM_CLASS_GEM, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GEM_PRICE_RATIO));
+ config.SetPriceRatioPerClass(ITEM_CLASS_ARMOR, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_ARMOR_PRICE_RATIO));
+ config.SetPriceRatioPerClass(ITEM_CLASS_REAGENT, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_REAGENT_PRICE_RATIO));
+ config.SetPriceRatioPerClass(ITEM_CLASS_PROJECTILE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_PROJECTILE_PRICE_RATIO));
+ config.SetPriceRatioPerClass(ITEM_CLASS_TRADE_GOODS, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_TRADEGOOD_PRICE_RATIO));
+ config.SetPriceRatioPerClass(ITEM_CLASS_GENERIC, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GENERIC_PRICE_RATIO));
+ config.SetPriceRatioPerClass(ITEM_CLASS_RECIPE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RECIPE_PRICE_RATIO));
+ config.SetPriceRatioPerClass(ITEM_CLASS_MONEY, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_MONEY_PRICE_RATIO));
+ config.SetPriceRatioPerClass(ITEM_CLASS_QUIVER, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_QUIVER_PRICE_RATIO));
+ config.SetPriceRatioPerClass(ITEM_CLASS_QUEST, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_QUEST_PRICE_RATIO));
+ config.SetPriceRatioPerClass(ITEM_CLASS_KEY, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_KEY_PRICE_RATIO));
+ config.SetPriceRatioPerClass(ITEM_CLASS_PERMANENT, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_PERMANENT_PRICE_RATIO));
+ config.SetPriceRatioPerClass(ITEM_CLASS_MISC, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_MISC_PRICE_RATIO));
+ config.SetPriceRatioPerClass(ITEM_CLASS_GLYPH, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GLYPH_PRICE_RATIO));
+
+ //load min and max auction times
+ config.SetMinTime(sAuctionBotConfig->GetConfig(CONFIG_AHBOT_MINTIME));
+ config.SetMaxTime(sAuctionBotConfig->GetConfig(CONFIG_AHBOT_MAXTIME));
+
+ TC_LOG_DEBUG("ahbot", "AHBot: minTime = %u", config.GetMinTime());
+ TC_LOG_DEBUG("ahbot", "AHBot: maxTime = %u", config.GetMaxTime());
+
+ TC_LOG_DEBUG("ahbot", "AHBot: For AH type %u", config.GetHouseType());
+ TC_LOG_DEBUG("ahbot", "AHBot: GrayItems = %u", config.GetItemsAmountPerQuality(AUCTION_QUALITY_GRAY));
+ TC_LOG_DEBUG("ahbot", "AHBot: WhiteItems = %u", config.GetItemsAmountPerQuality(AUCTION_QUALITY_WHITE));
+ TC_LOG_DEBUG("ahbot", "AHBot: GreenItems = %u", config.GetItemsAmountPerQuality(AUCTION_QUALITY_GREEN));
+ TC_LOG_DEBUG("ahbot", "AHBot: BlueItems = %u", config.GetItemsAmountPerQuality(AUCTION_QUALITY_BLUE));
+ TC_LOG_DEBUG("ahbot", "AHBot: PurpleItems = %u", config.GetItemsAmountPerQuality(AUCTION_QUALITY_PURPLE));
+ TC_LOG_DEBUG("ahbot", "AHBot: OrangeItems = %u", config.GetItemsAmountPerQuality(AUCTION_QUALITY_ORANGE));
+ TC_LOG_DEBUG("ahbot", "AHBot: YellowItems = %u", config.GetItemsAmountPerQuality(AUCTION_QUALITY_YELLOW));
+}
+
+// Set static of items on one AH faction.
+// Fill ItemInfos object with real content of AH.
+uint32 AuctionBotSeller::SetStat(SellerConfiguration& config)
+{
+ AllItemsArray itemsSaved(MAX_AUCTION_QUALITY, std::vector<uint32>(MAX_ITEM_CLASS));
+
+ AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(config.GetHouseType());
+ for (AuctionHouseObject::AuctionEntryMap::const_iterator itr = auctionHouse->GetAuctionsBegin(); itr != auctionHouse->GetAuctionsEnd(); ++itr)
+ {
+ AuctionEntry* auctionEntry = itr->second;
+ Item* item = sAuctionMgr->GetAItem(auctionEntry->itemGUIDLow);
+ if (item)
+ {
+ ItemTemplate const* prototype = item->GetTemplate();
+ if (prototype)
+ if (!auctionEntry->owner) // Add only ahbot items
+ ++itemsSaved[prototype->Quality][prototype->Class];
+ }
+ }
+
+ uint32 count = 0;
+ for (uint32 j = 0; j < MAX_AUCTION_QUALITY; ++j)
+ {
+ for (uint32 i = 0; i < MAX_ITEM_CLASS; ++i)
+ {
+ config.SetMissedItemsPerClass((AuctionQuality)j, (ItemClass)i, itemsSaved[j][i]);
+ count += config.GetMissedItemsPerClass((AuctionQuality)j, (ItemClass)i);
+ }
+ }
+
+ TC_LOG_DEBUG("ahbot", "AHBot: Missed Item \tGray\tWhite\tGreen\tBlue\tPurple\tOrange\tYellow");
+ for (uint32 i = 0; i < MAX_ITEM_CLASS; ++i)
+ {
+ TC_LOG_DEBUG("ahbot", "AHBot: \t\t%u\t%u\t%u\t%u\t%u\t%u\t%u",
+ config.GetMissedItemsPerClass(AUCTION_QUALITY_GRAY, (ItemClass)i),
+ config.GetMissedItemsPerClass(AUCTION_QUALITY_WHITE, (ItemClass)i),
+ config.GetMissedItemsPerClass(AUCTION_QUALITY_GREEN, (ItemClass)i),
+ config.GetMissedItemsPerClass(AUCTION_QUALITY_BLUE, (ItemClass)i),
+ config.GetMissedItemsPerClass(AUCTION_QUALITY_PURPLE, (ItemClass)i),
+ config.GetMissedItemsPerClass(AUCTION_QUALITY_ORANGE, (ItemClass)i),
+ config.GetMissedItemsPerClass(AUCTION_QUALITY_YELLOW, (ItemClass)i));
+ }
+ config.LastMissedItem = count;
+
+ return count;
+}
+
+// getRandomArray is used to make viable the possibility to add any of missed item in place of first one to last one.
+bool AuctionBotSeller::GetItemsToSell(SellerConfiguration& config, ItemsToSellArray& itemsToSellArray, AllItemsArray const& addedItem)
+{
+ itemsToSellArray.clear();
+ bool found = false;
+
+ for (uint32 j = 0; j < MAX_AUCTION_QUALITY; ++j)
+ {
+ for (uint32 i = 0; i < MAX_ITEM_CLASS; ++i)
+ {
+ if (config.GetMissedItemsPerClass(AuctionQuality(j), ItemClass(i)) > addedItem[j][i] && !_itemPool[j][i].empty())
+ {
+ ItemToSell miss_item;
+ miss_item.Color = j;
+ miss_item.Itemclass = i;
+ itemsToSellArray.push_back(miss_item);
+ found = true;
+ }
+ }
+ }
+
+ return found;
+}
+
+// Set items price. All important value are passed by address.
+void AuctionBotSeller::SetPricesOfItem(ItemTemplate const* itemProto, SellerConfiguration& config, uint32& buyp, uint32& bidp, uint32 stackCount)
+{
+ uint32 classRatio = config.GetPriceRatioPerClass(ItemClass(itemProto->Class));
+ uint32 qualityRatio = config.GetPriceRatioPerQuality(AuctionQuality(itemProto->Quality));
+ uint32 priceRatio = (classRatio * qualityRatio) / 100;
+
+ uint32 buyPrice = itemProto->BuyPrice;
+ uint32 sellPrice = itemProto->SellPrice;
+
+ if (buyPrice == 0)
+ {
+ if (sellPrice > 0)
+ buyPrice = sellPrice * GetSellModifier(itemProto);
+ else
+ {
+ uint32 divisor = ((itemProto->Class == 2 || itemProto->Class == 4) ? 284 : 80);
+ uint32 tempLevel = (itemProto->ItemLevel == 0 ? 1 : itemProto->ItemLevel);
+ uint32 tempQuality = (itemProto->Quality == 0 ? 1 : itemProto->Quality);
+
+ buyPrice = tempLevel * tempQuality * GetBuyModifier(itemProto)* tempLevel / divisor;
+ }
+ }
+
+ if (sellPrice == 0)
+ sellPrice = (buyPrice > 10 ? buyPrice / GetSellModifier(itemProto) : buyPrice);
+
+ if (!sAuctionBotConfig->GetConfig(CONFIG_AHBOT_BUYPRICE_SELLER))
+ buyPrice = sellPrice;
+
+ uint32 basePrice = (buyPrice * stackCount * priceRatio) / (itemProto->Class == 6 ? 200 : itemProto->BuyCount) / 100;
+ uint32 range = basePrice * 0.04;
+
+ buyp = urand(basePrice - range, basePrice + range) + 1;
+
+ basePrice = buyp * .5;
+ range = buyp * .4;
+ bidp = urand(basePrice - range, basePrice + range) + 1;
+}
+
+// Determine the multiplier for the sell price of any weapon without a buy price.
+uint32 AuctionBotSeller::GetSellModifier(ItemTemplate const* prototype)
+{
+ switch (prototype->Class)
+ {
+ case ITEM_CLASS_WEAPON:
+ case ITEM_CLASS_ARMOR:
+ case ITEM_CLASS_REAGENT:
+ case ITEM_CLASS_PROJECTILE:
+ return 5;
+ default:
+ return 4;
+ }
+}
+
+// Return the modifier by which the item's level and quality will be modified by to derive a relatively accurate price.
+uint32 AuctionBotSeller::GetBuyModifier(ItemTemplate const* prototype)
+{
+ switch (prototype->Class)
+ {
+ case ITEM_CLASS_CONSUMABLE:
+ {
+ switch (prototype->SubClass)
+ {
+ case ITEM_SUBCLASS_CONSUMABLE:
+ return 100;
+ case ITEM_SUBCLASS_FLASK:
+ return 400;
+ case ITEM_SUBCLASS_SCROLL:
+ return 15;
+ case ITEM_SUBCLASS_ITEM_ENHANCEMENT:
+ return 250;
+ case ITEM_SUBCLASS_BANDAGE:
+ return 125;
+ default:
+ return 300;
+ }
+ }
+ case ITEM_CLASS_WEAPON:
+ {
+ switch (prototype->SubClass)
+ {
+ case ITEM_SUBCLASS_WEAPON_AXE:
+ case ITEM_SUBCLASS_WEAPON_MACE:
+ case ITEM_SUBCLASS_WEAPON_SWORD:
+ case ITEM_SUBCLASS_WEAPON_FIST:
+ case ITEM_SUBCLASS_WEAPON_DAGGER:
+ return 1200;
+ case ITEM_SUBCLASS_WEAPON_AXE2:
+ case ITEM_SUBCLASS_WEAPON_MACE2:
+ case ITEM_SUBCLASS_WEAPON_POLEARM:
+ case ITEM_SUBCLASS_WEAPON_SWORD2:
+ case ITEM_SUBCLASS_WEAPON_STAFF:
+ return 1500;
+ case ITEM_SUBCLASS_WEAPON_THROWN:
+ return 350;
+ default:
+ return 1000;
+ }
+ }
+ case ITEM_CLASS_ARMOR:
+ {
+ switch (prototype->SubClass)
+ {
+ case ITEM_SUBCLASS_ARMOR_MISC:
+ case ITEM_SUBCLASS_ARMOR_CLOTH:
+ return 500;
+ case ITEM_SUBCLASS_ARMOR_LEATHER:
+ return 600;
+ case ITEM_SUBCLASS_ARMOR_MAIL:
+ return 700;
+ case ITEM_SUBCLASS_ARMOR_PLATE:
+ case ITEM_SUBCLASS_ARMOR_SHIELD:
+ return 800;
+ default:
+ return 400;
+ }
+ }
+ case ITEM_CLASS_REAGENT:
+ case ITEM_CLASS_PROJECTILE:
+ return 50;
+ case ITEM_CLASS_TRADE_GOODS:
+ {
+ switch (prototype->SubClass)
+ {
+ case ITEM_SUBCLASS_TRADE_GOODS:
+ case ITEM_SUBCLASS_PARTS:
+ case ITEM_SUBCLASS_MEAT:
+ return 50;
+ case ITEM_SUBCLASS_EXPLOSIVES:
+ return 250;
+ case ITEM_SUBCLASS_DEVICES:
+ return 500;
+ case ITEM_SUBCLASS_ELEMENTAL:
+ case ITEM_SUBCLASS_TRADE_GOODS_OTHER:
+ case ITEM_SUBCLASS_ENCHANTING:
+ return 300;
+ default:
+ return 100;
+ }
+ }
+ case ITEM_CLASS_QUEST: return 1000;
+ case ITEM_CLASS_KEY: return 3000;
+ default:
+ return 500;
+ }
+}
+
+void AuctionBotSeller::SetItemsRatio(uint32 al, uint32 ho, uint32 ne)
+{
+ sAuctionBotConfig->SetConfig(CONFIG_AHBOT_ALLIANCE_ITEM_AMOUNT_RATIO, std::max(al, 100000u));
+ sAuctionBotConfig->SetConfig(CONFIG_AHBOT_HORDE_ITEM_AMOUNT_RATIO, std::max(ho, 100000u));
+ sAuctionBotConfig->SetConfig(CONFIG_AHBOT_NEUTRAL_ITEM_AMOUNT_RATIO, std::max(ne, 100000u));
+
+ for (int i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
+ LoadItemsQuantity(_houseConfig[i]);
+}
+
+void AuctionBotSeller::SetItemsRatioForHouse(AuctionHouseType house, uint32 val)
+{
+ val = std::max(val, 10000u); // apply same upper limit as used for config load
+
+ switch (house)
+ {
+ case AUCTION_HOUSE_ALLIANCE: sAuctionBotConfig->SetConfig(CONFIG_AHBOT_ALLIANCE_ITEM_AMOUNT_RATIO, val); break;
+ case AUCTION_HOUSE_HORDE: sAuctionBotConfig->SetConfig(CONFIG_AHBOT_HORDE_ITEM_AMOUNT_RATIO, val); break;
+ default: sAuctionBotConfig->SetConfig(CONFIG_AHBOT_NEUTRAL_ITEM_AMOUNT_RATIO, val); break;
+ }
+
+ LoadItemsQuantity(_houseConfig[house]);
+}
+
+void AuctionBotSeller::SetItemsAmount(uint32(&vals)[MAX_AUCTION_QUALITY])
+{
+ sAuctionBotConfig->SetConfig(CONFIG_AHBOT_ITEM_GRAY_AMOUNT, vals[AUCTION_QUALITY_GRAY]);
+ sAuctionBotConfig->SetConfig(CONFIG_AHBOT_ITEM_WHITE_AMOUNT, vals[AUCTION_QUALITY_WHITE]);
+ sAuctionBotConfig->SetConfig(CONFIG_AHBOT_ITEM_GREEN_AMOUNT, vals[AUCTION_QUALITY_GREEN]);
+ sAuctionBotConfig->SetConfig(CONFIG_AHBOT_ITEM_BLUE_AMOUNT, vals[AUCTION_QUALITY_BLUE]);
+ sAuctionBotConfig->SetConfig(CONFIG_AHBOT_ITEM_PURPLE_AMOUNT, vals[AUCTION_QUALITY_PURPLE]);
+ sAuctionBotConfig->SetConfig(CONFIG_AHBOT_ITEM_ORANGE_AMOUNT, vals[AUCTION_QUALITY_ORANGE]);
+ sAuctionBotConfig->SetConfig(CONFIG_AHBOT_ITEM_YELLOW_AMOUNT, vals[AUCTION_QUALITY_YELLOW]);
+
+ for (int i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
+ LoadItemsQuantity(_houseConfig[i]);
+}
+
+void AuctionBotSeller::SetItemsAmountForQuality(AuctionQuality quality, uint32 val)
+{
+ switch (quality)
+ {
+ case AUCTION_QUALITY_GRAY:
+ sAuctionBotConfig->SetConfig(CONFIG_AHBOT_ITEM_GRAY_AMOUNT, val); break;
+ case AUCTION_QUALITY_WHITE:
+ sAuctionBotConfig->SetConfig(CONFIG_AHBOT_ITEM_WHITE_AMOUNT, val); break;
+ case AUCTION_QUALITY_GREEN:
+ sAuctionBotConfig->SetConfig(CONFIG_AHBOT_ITEM_GREEN_AMOUNT, val); break;
+ case AUCTION_QUALITY_BLUE:
+ sAuctionBotConfig->SetConfig(CONFIG_AHBOT_ITEM_BLUE_AMOUNT, val); break;
+ case AUCTION_QUALITY_PURPLE:
+ sAuctionBotConfig->SetConfig(CONFIG_AHBOT_ITEM_PURPLE_AMOUNT, val); break;
+ case AUCTION_QUALITY_ORANGE:
+ sAuctionBotConfig->SetConfig(CONFIG_AHBOT_ITEM_ORANGE_AMOUNT, val); break;
+ default:
+ sAuctionBotConfig->SetConfig(CONFIG_AHBOT_ITEM_YELLOW_AMOUNT, val); break;
+ }
+
+ for (int i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
+ LoadItemsQuantity(_houseConfig[i]);
+}
+
+// Add new auction to one of the factions.
+// Faction and setting associated is defined passed argument ( config )
+void AuctionBotSeller::AddNewAuctions(SellerConfiguration& config)
+{
+ uint32 count = 0;
+ uint32 items = 0;
+
+ // If there is large amount of items missed we can use boost value to get fast filled AH
+ if (config.LastMissedItem > sAuctionBotConfig->GetItemPerCycleBoost())
+ {
+ items = sAuctionBotConfig->GetItemPerCycleBoost();
+ TC_LOG_DEBUG("ahbot", "AHBot: Boost value used to fill AH! (if this happens often adjust both ItemsPerCycle in worldserver.conf)");
+ }
+ else
+ items = sAuctionBotConfig->GetItemPerCycleNormal();
+
+ uint32 houseid = 0;
+ uint32 auctioneer = 0;
+ switch (config.GetHouseType())
+ {
+ case AUCTION_HOUSE_ALLIANCE:
+ houseid = 1; auctioneer = 79707; break;
+ case AUCTION_HOUSE_HORDE:
+ houseid = 6; auctioneer = 4656; break;
+ default:
+ houseid = 7; auctioneer = 23442; break;
+ }
+
+ AuctionHouseEntry const* ahEntry = sAuctionHouseStore.LookupEntry(houseid);
+
+ AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(config.GetHouseType());
+
+ ItemsToSellArray itemsToSell;
+ AllItemsArray allItems(MAX_AUCTION_QUALITY, std::vector<uint32>(MAX_ITEM_CLASS));
+ // Main loop
+ // getRandomArray will give what categories of items should be added (return true if there is at least 1 items missed)
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+ while (GetItemsToSell(config, itemsToSell, allItems) && items > 0)
+ {
+ --items;
+
+ // Select random position from missed items table
+ uint32 pos = urand(0, itemsToSell.size() - 1);
+
+ // Set itemId with random item ID for selected categories and color, from _itemPool table
+ uint32 itemId = _itemPool[itemsToSell[pos].Color][itemsToSell[pos].Itemclass][urand(0, _itemPool[itemsToSell[pos].Color][itemsToSell[pos].Itemclass].size() - 1)];
+ ++allItems[itemsToSell[pos].Color][itemsToSell[pos].Itemclass]; // Helper table to avoid rescan from DB in this loop. (has we add item in random orders)
+
+ if (!itemId)
+ {
+ TC_LOG_DEBUG("ahbot", "AHBot: Item entry 0 auction creating attempt.");
+ continue;
+ }
+
+ ItemTemplate const* prototype = sObjectMgr->GetItemTemplate(itemId);
+ if (!prototype)
+ {
+ TC_LOG_DEBUG("ahbot", "AHBot: Unknown item %u auction creating attempt.", itemId);
+ continue;
+ }
+
+ uint32 stackCount = urand(1, prototype->GetMaxStackSize());
+
+ Item* item = Item::CreateItem(itemId, stackCount);
+ if (!item)
+ {
+ TC_LOG_ERROR("ahbot", "AHBot: Item::CreateItem() returned NULL for item %u (stack: %u)", itemId, stackCount);
+ return;
+ }
+
+ // Update the just created item so that if it needs random properties it has them.
+ // Ex: Notched Shortsword of Stamina will only generate as a Notched Shortsword without this.
+ if (int32 randomPropertyId = Item::GenerateItemRandomPropertyId(itemId))
+ item->SetItemRandomProperties(randomPropertyId);
+
+ uint32 buyoutPrice;
+ uint32 bidPrice = 0;
+
+ // Price of items are set here
+ SetPricesOfItem(prototype, config, buyoutPrice, bidPrice, stackCount);
+
+ // Deposit time
+ uint32 etime = urand(1, 3);
+ switch (etime)
+ {
+ case 1:
+ etime = 43200;
+ break;
+ case 2:
+ etime = 86400;
+ break;
+ case 3:
+ etime = 172800;
+ break;
+ default:
+ etime = 86400;
+ break;
+ }
+
+ AuctionEntry* auctionEntry = new AuctionEntry();
+ auctionEntry->Id = sObjectMgr->GenerateAuctionID();
+ auctionEntry->owner = 0;
+ auctionEntry->itemGUIDLow = item->GetGUIDLow();
+ auctionEntry->itemEntry = item->GetEntry();
+ auctionEntry->startbid = bidPrice;
+ auctionEntry->buyout = buyoutPrice;
+ auctionEntry->auctioneer = auctioneer;
+ auctionEntry->bidder = 0;
+ auctionEntry->bid = 0;
+ auctionEntry->deposit = sAuctionMgr->GetAuctionDeposit(ahEntry, etime, item, stackCount);
+ auctionEntry->auctionHouseEntry = ahEntry;
+ auctionEntry->expire_time = time(NULL) + urand(config.GetMinTime(), config.GetMaxTime()) * HOUR;
+
+ item->SaveToDB(trans);
+ sAuctionMgr->AddAItem(item);
+ auctionHouse->AddAuction(auctionEntry);
+ auctionEntry->SaveToDB(trans);
+
+ auctionHouse->AddAuction(auctionEntry);
+
+ ++count;
+ }
+ CharacterDatabase.CommitTransaction(trans);
+
+ TC_LOG_DEBUG("ahbot", "AHBot: Added %u items to auction", count);
+}
+
+bool AuctionBotSeller::Update(AuctionHouseType houseType)
+{
+ if (sAuctionBotConfig->GetConfigItemAmountRatio(houseType) > 0)
+ {
+ TC_LOG_DEBUG("ahbot", "AHBot: %s selling ...", AuctionBotConfig::GetHouseTypeName(houseType));
+ if (SetStat(_houseConfig[houseType]))
+ AddNewAuctions(_houseConfig[houseType]);
+ return true;
+ }
+ else
+ return false;
+}
diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.h b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.h
new file mode 100644
index 00000000000..014fe23f71a
--- /dev/null
+++ b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2008-2014 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 AUCTION_HOUSE_BOT_SELLER_H
+#define AUCTION_HOUSE_BOT_SELLER_H
+
+#include "Define.h"
+#include "ItemPrototype.h"
+#include "AuctionHouseBot.h"
+
+struct ItemToSell
+{
+ uint32 Color;
+ uint32 Itemclass;
+};
+
+typedef std::vector<ItemToSell> ItemsToSellArray;
+typedef std::vector<std::vector<uint32>> AllItemsArray;
+
+struct SellerItemClassInfo
+{
+ SellerItemClassInfo(): AmountOfItems(0), MissItems(0), Quantity(0), PriceRatio(0) {}
+
+ uint32 AmountOfItems;
+ uint32 MissItems;
+ uint32 Quantity;
+ uint32 PriceRatio;
+};
+
+struct SellerItemInfo
+{
+ SellerItemInfo(): AmountOfItems(0), MissItems(0), PriceRatio(0) {}
+
+ uint32 AmountOfItems;
+ uint32 MissItems;
+ uint32 PriceRatio;
+
+ SellerItemClassInfo ItemClassInfos[MAX_ITEM_CLASS];
+};
+
+class SellerConfiguration
+{
+public:
+ SellerConfiguration(): LastMissedItem(0), _houseType(AUCTION_HOUSE_NEUTRAL), _minTime(1), _maxTime(72)
+ {
+ }
+
+ ~SellerConfiguration() {}
+
+ void Initialize(AuctionHouseType houseType)
+ {
+ _houseType = houseType;
+ }
+
+ AuctionHouseType GetHouseType() const { return _houseType; }
+
+ uint32 LastMissedItem;
+
+ void SetMinTime(uint32 value)
+ {
+ _minTime = value;
+ }
+ uint32 GetMinTime() const
+ {
+ return std::min(1u, std::min(_minTime, _maxTime));
+ }
+
+ void SetMaxTime(uint32 value) { _maxTime = value; }
+ uint32 GetMaxTime() const { return _maxTime; }
+ // Data access classified by item class and item quality
+ void SetItemsAmountPerClass(AuctionQuality quality, ItemClass itemclass, uint32 amount) { _ItemInfo[quality].ItemClassInfos[itemclass].AmountOfItems = amount * _ItemInfo[quality].ItemClassInfos[itemclass].Quantity; }
+ uint32 GetItemsAmountPerClass(AuctionQuality quality, ItemClass itemclass) const { return _ItemInfo[quality].ItemClassInfos[itemclass].AmountOfItems; }
+ void SetItemsQuantityPerClass(AuctionQuality quality, ItemClass itemclass, uint32 qty) { _ItemInfo[quality].ItemClassInfos[itemclass].Quantity = qty; }
+ uint32 GetItemsQuantityPerClass(AuctionQuality quality, ItemClass itemclass) const { return _ItemInfo[quality].ItemClassInfos[itemclass].Quantity; }
+ void SetMissedItemsPerClass(AuctionQuality quality, ItemClass itemclass, uint32 found)
+ {
+ if (_ItemInfo[quality].ItemClassInfos[itemclass].AmountOfItems > found)
+ _ItemInfo[quality].ItemClassInfos[itemclass].MissItems = _ItemInfo[quality].ItemClassInfos[itemclass].AmountOfItems - found;
+ else
+ _ItemInfo[quality].ItemClassInfos[itemclass].MissItems = 0;
+ }
+ uint32 GetMissedItemsPerClass(AuctionQuality quality, ItemClass itemclass) const { return _ItemInfo[quality].ItemClassInfos[itemclass].MissItems; }
+
+ // Data for every quality of item
+ void SetItemsAmountPerQuality(AuctionQuality quality, uint32 cnt) { _ItemInfo[quality].AmountOfItems = cnt; }
+ uint32 GetItemsAmountPerQuality(AuctionQuality quality) const { return _ItemInfo[quality].AmountOfItems; }
+ void SetPriceRatioPerQuality(AuctionQuality quality, uint32 value) { _ItemInfo[quality].PriceRatio = value; }
+ uint32 GetPriceRatioPerQuality(AuctionQuality quality) const { return _ItemInfo[quality].PriceRatio; }
+ void SetPriceRatioPerClass(ItemClass item, uint32 value) { _ItemInfo[0].ItemClassInfos[item].PriceRatio = value; }
+ uint32 GetPriceRatioPerClass(ItemClass item) const { return _ItemInfo[0].ItemClassInfos[item].PriceRatio; }
+
+private:
+ AuctionHouseType _houseType;
+ uint32 _minTime;
+ uint32 _maxTime;
+ SellerItemInfo _ItemInfo[MAX_AUCTION_QUALITY];
+};
+
+// This class handle all Selling method
+// (holder of AHB_Seller_Config data for each auction house type)
+class AuctionBotSeller : public AuctionBotAgent
+{
+public:
+ typedef std::vector<uint32> ItemPool;
+
+ AuctionBotSeller();
+ ~AuctionBotSeller() override;
+
+ bool Initialize() override;
+ bool Update(AuctionHouseType houseType) override;
+
+ void AddNewAuctions(SellerConfiguration& config);
+ void SetItemsRatio(uint32 al, uint32 ho, uint32 ne);
+ void SetItemsRatioForHouse(AuctionHouseType house, uint32 val);
+ void SetItemsAmount(uint32(&vals)[MAX_AUCTION_QUALITY]);
+ void SetItemsAmountForQuality(AuctionQuality quality, uint32 val);
+ void LoadConfig();
+
+private:
+ SellerConfiguration _houseConfig[MAX_AUCTION_HOUSE_TYPE];
+
+ ItemPool _itemPool[MAX_AUCTION_QUALITY][MAX_ITEM_CLASS];
+
+ void LoadSellerValues(SellerConfiguration& config);
+ uint32 SetStat(SellerConfiguration& config);
+ bool GetItemsToSell(SellerConfiguration& config, ItemsToSellArray& itemsToSellArray, AllItemsArray const& addedItem);
+ void SetPricesOfItem(ItemTemplate const* itemProto, SellerConfiguration& config, uint32& buyp, uint32& bidp, uint32 stackcnt);
+ void LoadItemsQuantity(SellerConfiguration& config);
+ static uint32 GetBuyModifier(ItemTemplate const* prototype);
+ static uint32 GetSellModifier(ItemTemplate const* itemProto);
+};
+
+#endif
diff --git a/src/server/game/Battlegrounds/ArenaTeam.cpp b/src/server/game/Battlegrounds/ArenaTeam.cpp
index 1bc83cccaa0..e58c09251ba 100644
--- a/src/server/game/Battlegrounds/ArenaTeam.cpp
+++ b/src/server/game/Battlegrounds/ArenaTeam.cpp
@@ -240,7 +240,7 @@ bool ArenaTeam::LoadMembersFromDB(QueryResult result)
newMember.Name = fields[6].GetString();
newMember.Class = fields[7].GetUInt8();
newMember.PersonalRating = fields[8].GetUInt16();
- newMember.MatchMakerRating = fields[9].GetUInt16() > 0 ? fields[9].GetUInt16() : 1500;
+ newMember.MatchMakerRating = fields[9].GetUInt16() > 0 ? fields[9].GetUInt16() : sWorld->getIntConfig(CONFIG_ARENA_START_MATCHMAKER_RATING);
// Delete member if character information is missing
if (newMember.Name.empty())
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index 3a59ffa8cf9..e95e135d8ce 100644
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -733,6 +733,27 @@ void Battleground::EndBattleground(uint32 winner)
SetWinner(BG_TEAM_NEUTRAL);
}
+ PreparedStatement* stmt = nullptr;
+ uint64 battlegroundId = 1;
+ if (isBattleground() && sWorld->getBoolConfig(CONFIG_BATTLEGROUND_STORE_STATISTICS_ENABLE))
+ {
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PVPSTATS_MAXID);
+ PreparedQueryResult result = CharacterDatabase.Query(stmt);
+
+ if (result)
+ {
+ Field* fields = result->Fetch();
+ battlegroundId = fields[0].GetUInt64() + 1;
+ }
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PVPSTATS_BATTLEGROUND);
+ stmt->setUInt64(0, battlegroundId);
+ stmt->setUInt8(1, GetWinner());
+ stmt->setUInt8(2, m_BracketId + 1);
+ stmt->setUInt8(3, GetTypeID(true));
+ CharacterDatabase.Execute(stmt);
+ }
+
SetStatus(STATUS_WAIT_LEAVE);
//we must set it this way, because end time is sent in packet!
m_EndTime = TIME_TO_AUTOREMOVE;
@@ -770,6 +791,28 @@ void Battleground::EndBattleground(uint32 winner)
uint32 loser_kills = player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_LOSER_HONOR_LAST) : sWorld->getIntConfig(CONFIG_BG_REWARD_LOSER_HONOR_FIRST);
uint32 winner_arena = player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_ARENA_LAST) : sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_ARENA_FIRST);
+ 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());
+
+ CharacterDatabase.Execute(stmt);
+ }
+
// Reward winner team
if (team == winner)
{
diff --git a/src/server/game/Battlegrounds/BattlegroundScore.h b/src/server/game/Battlegrounds/BattlegroundScore.h
index 81aca355be8..f91c2aae579 100644
--- a/src/server/game/Battlegrounds/BattlegroundScore.h
+++ b/src/server/game/Battlegrounds/BattlegroundScore.h
@@ -107,6 +107,19 @@ struct BattlegroundScore
// For Logging purpose
virtual std::string ToString() const { return ""; }
+ uint32 GetKillingBlows() const { return KillingBlows; }
+ uint32 GetDeaths() const { return Deaths; }
+ uint32 GetHonorableKills() const { return HonorableKills; }
+ uint32 GetBonusHonor() const { return BonusHonor; }
+ uint32 GetDamageDone() const { return DamageDone; }
+ uint32 GetHealingDone() const { return HealingDone; }
+
+ virtual uint32 GetAttr1() const { return 0; }
+ virtual uint32 GetAttr2() const { return 0; }
+ virtual uint32 GetAttr3() const { return 0; }
+ virtual uint32 GetAttr4() const { return 0; }
+ virtual uint32 GetAttr5() const { return 0; }
+
uint64 PlayerGuid;
// Default score, present in every type
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.h b/src/server/game/Battlegrounds/Zones/BattlegroundAB.h
index 7655880117f..aed82efd5cb 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.h
@@ -267,6 +267,9 @@ struct BattlegroundABScore final : public BattlegroundScore
data << uint32(BasesDefended);
}
+ uint32 GetAttr1() const final override { return BasesAssaulted; }
+ uint32 GetAttr2() const final override { return BasesDefended; }
+
uint32 BasesAssaulted;
uint32 BasesDefended;
};
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.h b/src/server/game/Battlegrounds/Zones/BattlegroundAV.h
index 882d729c1e8..b56ec2ca489 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.h
@@ -1568,6 +1568,12 @@ struct BattlegroundAVScore final : public BattlegroundScore
data << uint32(MinesCaptured);
}
+ uint32 GetAttr1() const final override { return GraveyardsAssaulted; }
+ uint32 GetAttr2() const final override { return GraveyardsDefended; }
+ uint32 GetAttr3() const final override { return TowersAssaulted; }
+ uint32 GetAttr4() const final override { return TowersDefended; }
+ uint32 GetAttr5() const final override { return MinesCaptured; }
+
uint32 GraveyardsAssaulted;
uint32 GraveyardsDefended;
uint32 TowersAssaulted;
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.h b/src/server/game/Battlegrounds/Zones/BattlegroundEY.h
index 4a146a17917..408037b254e 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.h
@@ -349,6 +349,8 @@ struct BattlegroundEYScore final : public BattlegroundScore
data << uint32(FlagCaptures);
}
+ uint32 GetAttr1() const final override { return FlagCaptures; }
+
uint32 FlagCaptures;
};
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.h b/src/server/game/Battlegrounds/Zones/BattlegroundIC.h
index 5a9b47ec9b5..c772078a647 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.h
@@ -878,6 +878,9 @@ struct BattlegroundICScore final : public BattlegroundScore
data << uint32(BasesDefended);
}
+ uint32 GetAttr1() const final override { return BasesAssaulted; }
+ uint32 GetAttr2() const final override { return BasesDefended; }
+
uint32 BasesAssaulted;
uint32 BasesDefended;
};
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundSA.h b/src/server/game/Battlegrounds/Zones/BattlegroundSA.h
index 627c23850d2..eae9e02ba9e 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundSA.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundSA.h
@@ -538,6 +538,9 @@ struct BattlegroundSAScore final : public BattlegroundScore
data << uint32(GatesDestroyed);
}
+ uint32 GetAttr1() const final override { return DemolishersDestroyed; }
+ uint32 GetAttr2() const final override { return GatesDestroyed; }
+
uint32 DemolishersDestroyed;
uint32 GatesDestroyed;
};
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.h b/src/server/game/Battlegrounds/Zones/BattlegroundWS.h
index d29715c982b..71bd5d53047 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.h
@@ -177,6 +177,9 @@ struct BattlegroundWGScore final : public BattlegroundScore
data << uint32(FlagReturns);
}
+ uint32 GetAttr1() const final override { return FlagCaptures; }
+ uint32 GetAttr2() const final override { return FlagReturns; }
+
uint32 FlagCaptures;
uint32 FlagReturns;
};
diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt
index 532900c0438..d7d14e7bda4 100644
--- a/src/server/game/CMakeLists.txt
+++ b/src/server/game/CMakeLists.txt
@@ -13,6 +13,7 @@ file(GLOB_RECURSE sources_Achievements Achievements/*.cpp Achievements/*.h)
file(GLOB_RECURSE sources_Addons Addons/*.cpp Addons/*.h)
file(GLOB_RECURSE sources_AI AI/*.cpp AI/*.h)
file(GLOB_RECURSE sources_AuctionHouse AuctionHouse/*.cpp AuctionHouse/*.h)
+file(GLOB_RECURSE sources_AuctionHouseBot AuctionHouseBot/*.cpp AuctionHouseBot/*.h)
file(GLOB_RECURSE sources_Battlefield Battlefield/*.cpp Battlefield/*.h)
file(GLOB_RECURSE sources_Battlegrounds Battlegrounds/*.cpp Battlegrounds/*.h)
file(GLOB_RECURSE sources_Calendar Calendar/*.cpp Calendar/*.h)
@@ -63,6 +64,7 @@ set(game_STAT_SRCS
${sources_Addons}
${sources_AI}
${sources_AuctionHouse}
+ ${sources_AuctionHouseBot}
${sources_Battlefield}
${sources_Battlegrounds}
${sources_Calendar}
@@ -136,6 +138,7 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/AI/ScriptedAI
${CMAKE_CURRENT_SOURCE_DIR}/AI/SmartScripts
${CMAKE_CURRENT_SOURCE_DIR}/AuctionHouse
+ ${CMAKE_CURRENT_SOURCE_DIR}/AuctionHouseBot
${CMAKE_CURRENT_SOURCE_DIR}/Battlefield
${CMAKE_CURRENT_SOURCE_DIR}/Battlefield/Zones
${CMAKE_CURRENT_SOURCE_DIR}/Battlegrounds
diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp
index 50f67d4f920..265197e9c3b 100644
--- a/src/server/game/Chat/Chat.cpp
+++ b/src/server/game/Chat/Chat.cpp
@@ -1148,7 +1148,7 @@ bool ChatHandler::extractPlayerTarget(char* args, Player** player, uint64* playe
}
else
{
- Player* pl = getSelectedPlayer();
+ Player* pl = getSelectedPlayerOrSelf();
// if allowed player pointer
if (player)
*player = pl;
diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h
index 32820de0fc2..c0e3da32b3f 100644
--- a/src/server/game/Chat/Chat.h
+++ b/src/server/game/Chat/Chat.h
@@ -112,7 +112,7 @@ class ChatHandler
GameTele const* extractGameTeleFromLink(char* text);
bool GetPlayerGroupAndGUIDByName(const char* cname, Player* &player, Group* &group, uint64 &guid, bool offline = false);
std::string extractPlayerNameFromLink(char* text);
- // select by arg (name/link) or in-game selection online/offline player
+ // select by arg (name/link) or in-game selection online/offline player or self if a creature is selected
bool extractPlayerTarget(char* args, Player** player, uint64* player_guid = NULL, std::string* player_name = NULL);
std::string playerLink(std::string const& name) const { return m_session ? "|cffffffff|Hplayer:"+name+"|h["+name+"]|h|r" : name; }
diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp
index 6894dd86493..5a4ef765a6e 100644
--- a/src/server/game/Entities/Item/Item.cpp
+++ b/src/server/game/Entities/Item/Item.cpp
@@ -690,8 +690,11 @@ void Item::SetState(ItemUpdateState state, Player* forplayer)
if (uState == ITEM_NEW && state == ITEM_REMOVED)
{
// pretend the item never existed
- RemoveFromUpdateQueueOf(forplayer);
- forplayer->DeleteRefundReference(GetGUIDLow());
+ if (forplayer)
+ {
+ RemoveFromUpdateQueueOf(forplayer);
+ forplayer->DeleteRefundReference(GetGUIDLow());
+ }
delete this;
return;
}
@@ -701,7 +704,8 @@ void Item::SetState(ItemUpdateState state, Player* forplayer)
if (uState != ITEM_NEW)
uState = state;
- AddToUpdateQueueOf(forplayer);
+ if (forplayer)
+ AddToUpdateQueueOf(forplayer);
}
else
{
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index cdc61f8b2ff..85381c1dfd9 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -700,7 +700,7 @@ class WorldObject : public Object, public WorldLocation
TempSummon* SummonCreature(uint32 id, Position const &pos, TempSummonType spwtype = TEMPSUMMON_MANUAL_DESPAWN, uint32 despwtime = 0, uint32 vehId = 0) const;
TempSummon* SummonCreature(uint32 id, float x, float y, float z, float ang = 0, TempSummonType spwtype = TEMPSUMMON_MANUAL_DESPAWN, uint32 despwtime = 0) const;
- GameObject* SummonGameObject(uint32 entry, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime);
+ GameObject* SummonGameObject(uint32 entry, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime /* s */);
Creature* SummonTrigger(float x, float y, float z, float ang, uint32 dur, CreatureAI* (*GetAI)(Creature*) = NULL);
void SummonCreatureGroup(uint8 group, std::list<TempSummon*>* list = NULL);
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 1fc1cd9f7b8..71a7f4b160e 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -15296,6 +15296,19 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
Item* item = StoreNewItem(dest, itemId, true, Item::GenerateItemRandomPropertyId(itemId));
SendNewItem(item, quest->RewardItemIdCount[i], true, false);
}
+ else if (quest->IsDFQuest())
+ {
+ MailSender sender(MAIL_CREATURE, 34337 /* The Postmaster */ );
+ MailDraft draft("Recovered Item", "We recovered a lost item in the twisting nether and noted that it was yours.$B$BPlease find said object enclosed."); // This is the text used in Cataclysm, it probably wasn't changed.
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+ if (Item* item = Item::CreateItem(quest->RewardItemId[i], quest->RewardItemIdCount[i], 0))
+ {
+ item->SaveToDB(trans);
+ draft.AddItem(item);
+ }
+ draft.SendMailTo(trans, MailReceiver(this, this->GetGUIDLow()), sender);
+ CharacterDatabase.CommitTransaction(trans);
+ }
}
}
}
@@ -15309,7 +15322,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
bool rewarded = (m_RewardedQuests.find(quest_id) != m_RewardedQuests.end());
// Not give XP in case already completed once repeatable quest
- uint32 XP = rewarded ? 0 : uint32(quest->XPValue(this)*sWorld->getRate(RATE_XP_QUEST));
+ uint32 XP = rewarded && !quest->IsDFQuest() ? 0 : uint32(quest->XPValue(this)*sWorld->getRate(RATE_XP_QUEST));
// handle SPELL_AURA_MOD_XP_QUEST_PCT auras
Unit::AuraEffectList const& ModXPPctAuras = GetAuraEffectsByType(SPELL_AURA_MOD_XP_QUEST_PCT);
@@ -15435,6 +15448,10 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
void Player::FailQuest(uint32 questId)
{
+ // Already complete quests shouldn't turn failed.
+ if (GetQuestStatus(questId) == QUEST_STATUS_COMPLETE)
+ return;
+
if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId))
{
SetQuestStatus(questId, QUEST_STATUS_FAILED);
@@ -22684,6 +22701,8 @@ bool Player::ModifyMoney(int32 amount, bool sendError /*= true*/)
SetMoney(GetMoney() + amount);
else
{
+ sScriptMgr->OnPlayerMoneyLimit(this, amount);
+
if (sendError)
SendEquipError(EQUIP_ERR_TOO_MUCH_GOLD, NULL, NULL);
return false;
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index d75e7db11fe..bfa57ef64b8 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -14333,7 +14333,18 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
// Remove charge (aura can be removed by triggers)
if (prepare && useCharges && takeCharges)
- i->aura->DropCharge();
+ {
+ // Set charge drop delay (only for missiles)
+ if ((procExtra & PROC_EX_REFLECT) && target && procSpell && procSpell->Speed > 0.0f)
+ {
+ // Set up missile speed based delay (from Spell.cpp: Spell::AddUnitTarget()::L2237)
+ uint32 delay = uint32(std::floor(std::max<float>(target->GetDistance(this), 5.0f) / procSpell->Speed * 1000.0f));
+ // Schedule charge drop
+ i->aura->DropChargeDelayed(delay);
+ }
+ else
+ i->aura->DropCharge();
+ }
i->aura->CallScriptAfterProcHandlers(aurApp, eventInfo);
diff --git a/src/server/game/Guilds/Guild.h b/src/server/game/Guilds/Guild.h
index 8c7b926a700..375d39cf232 100644
--- a/src/server/game/Guilds/Guild.h
+++ b/src/server/game/Guilds/Guild.h
@@ -657,6 +657,9 @@ public:
std::string const& GetName() const { return m_name; }
std::string const& GetMOTD() const { return m_motd; }
std::string const& GetInfo() const { return m_info; }
+ uint32 GetMemberCount() const { return m_members.size(); }
+ time_t GetCreatedDate() const { return m_createdDate; }
+ uint64 GetBankMoney() const { return m_bankMoney; }
bool SetName(std::string const& name);
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 243a931d463..9e29fb01c3b 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -159,7 +159,7 @@ void Map::LoadMap(int gx, int gy, bool reload)
// load grid map for base map
if (!m_parentMap->GridMaps[gx][gy])
- m_parentMap->EnsureGridCreated_i(GridCoord(63-gx, 63-gy));
+ m_parentMap->EnsureGridCreated(GridCoord(63-gx, 63-gy));
((MapInstanced*)(m_parentMap))->AddGridMapReference(GridCoord(gx, gy));
GridMaps[gx][gy] = m_parentMap->GridMaps[gx][gy];
diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h
index f4d1bc03144..cb868097ac6 100644
--- a/src/server/game/Miscellaneous/Language.h
+++ b/src/server/game/Miscellaneous/Language.h
@@ -941,7 +941,34 @@ enum TrinityStrings
LANG_LIST_MAIL_INFO_3 = 1154,
LANG_LIST_MAIL_INFO_ITEM = 1155,
LANG_LIST_MAIL_NOT_FOUND = 1156,
- // Room for more level 3 1157-1199 not used
+ LANG_AHBOT_RELOAD_OK = 1157,
+ LANG_AHBOT_STATUS_BAR_CONSOLE = 1158,
+ LANG_AHBOT_STATUS_MIDBAR_CONSOLE = 1159,
+ LANG_AHBOT_STATUS_TITLE1_CONSOLE = 1160,
+ LANG_AHBOT_STATUS_TITLE1_CHAT = 1161,
+ LANG_AHBOT_STATUS_FORMAT_CONSOLE = 1162,
+ LANG_AHBOT_STATUS_FORMAT_CHAT = 1163,
+ LANG_AHBOT_STATUS_ITEM_COUNT = 1164,
+ LANG_AHBOT_STATUS_ITEM_RATIO = 1165,
+ LANG_AHBOT_STATUS_TITLE2_CONSOLE = 1166,
+ LANG_AHBOT_STATUS_TITLE2_CHAT = 1167,
+ LANG_AHBOT_QUALITY_GRAY = 1168,
+ LANG_AHBOT_QUALITY_WHITE = 1169,
+ LANG_AHBOT_QUALITY_GREEN = 1170,
+ LANG_AHBOT_QUALITY_BLUE = 1171,
+ LANG_AHBOT_QUALITY_PURPLE = 1172,
+ LANG_AHBOT_QUALITY_ORANGE = 1173,
+ LANG_AHBOT_QUALITY_YELLOW = 1174,
+ LANG_AHBOT_ITEMS_AMOUNT = 1175,
+ LANG_AHBOT_ITEMS_RATIO = 1176,
+ LANG_GUILD_INFO_NAME = 1177,
+ LANG_GUILD_INFO_GUILD_MASTER = 1178,
+ LANG_GUILD_INFO_CREATION_DATE = 1179,
+ LANG_GUILD_INFO_MEMBER_COUNT = 1180,
+ 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
// Debug commands
LANG_CINEMATIC_NOT_EXIST = 1200,
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index d036d438926..ed6c5430674 100644
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -47,6 +47,7 @@ void AddSC_SmartScripts();
//Commands
void AddSC_account_commandscript();
void AddSC_achievement_commandscript();
+void AddSC_ahbot_commandscript();
void AddSC_arena_commandscript();
void AddSC_ban_commandscript();
void AddSC_bf_commandscript();
@@ -749,6 +750,7 @@ void AddCommandScripts()
{
AddSC_account_commandscript();
AddSC_achievement_commandscript();
+ AddSC_ahbot_commandscript();
AddSC_arena_commandscript();
AddSC_ban_commandscript();
AddSC_bf_commandscript();
diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp
index daa4c36a442..d13c81ed059 100644
--- a/src/server/game/Scripting/ScriptMgr.cpp
+++ b/src/server/game/Scripting/ScriptMgr.cpp
@@ -1180,6 +1180,11 @@ void ScriptMgr::OnPlayerMoneyChanged(Player* player, int32& amount)
FOREACH_SCRIPT(PlayerScript)->OnMoneyChanged(player, amount);
}
+void ScriptMgr::OnPlayerMoneyLimit(Player* player, int32 amount)
+{
+ FOREACH_SCRIPT(PlayerScript)->OnMoneyLimit(player, amount);
+}
+
void ScriptMgr::OnGivePlayerXP(Player* player, uint32& amount, Unit* victim)
{
FOREACH_SCRIPT(PlayerScript)->OnGiveXP(player, amount, victim);
diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h
index ea25d51dab2..499d7ff6c09 100644
--- a/src/server/game/Scripting/ScriptMgr.h
+++ b/src/server/game/Scripting/ScriptMgr.h
@@ -706,6 +706,9 @@ class PlayerScript : public UnitScript
// Called when a player's money is modified (before the modification is done)
virtual void OnMoneyChanged(Player* /*player*/, int32& /*amount*/) { }
+ // Called when a player's money is at limit (amount = money tried to add)
+ virtual void OnMoneyLimit(Player* /*player*/, int32 /*amount*/) { }
+
// Called when a player gains XP (before anything is given)
virtual void OnGiveXP(Player* /*player*/, uint32& /*amount*/, Unit* /*victim*/) { }
@@ -1053,6 +1056,7 @@ class ScriptMgr
void OnPlayerFreeTalentPointsChanged(Player* player, uint32 newPoints);
void OnPlayerTalentsReset(Player* player, bool noCost);
void OnPlayerMoneyChanged(Player* player, int32& amount);
+ void OnPlayerMoneyLimit(Player* player, int32 amount);
void OnGivePlayerXP(Player* player, uint32& amount, Unit* victim);
void OnPlayerReputationChange(Player* player, uint32 factionID, int32& standing, bool incremental);
void OnPlayerDuelRequest(Player* target, Player* challenger);
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index 348869075ee..07cfa80f297 100644
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -335,7 +335,7 @@ m_spellInfo(spellproto), m_casterGuid(casterGUID ? casterGUID : caster->GetGUID(
m_castItemGuid(castItem ? castItem->GetGUID() : 0), m_applyTime(time(NULL)),
m_owner(owner), m_timeCla(0), m_updateTargetMapInterval(0),
m_casterLevel(caster ? caster->getLevel() : m_spellInfo->SpellLevel), m_procCharges(0), m_stackAmount(1),
-m_isRemoved(false), m_isSingleTarget(false), m_isUsingCharges(false)
+m_isRemoved(false), m_isSingleTarget(false), m_isUsingCharges(false), m_dropEvent(nullptr)
{
if (m_spellInfo->ManaPerSecond || m_spellInfo->ManaPerSecondPerLevel)
m_timeCla = 1 * IN_MILLISECONDS;
@@ -467,6 +467,12 @@ void Aura::_Remove(AuraRemoveMode removeMode)
target->_UnapplyAura(aurApp, removeMode);
appItr = m_applications.begin();
}
+
+ if (m_dropEvent)
+ {
+ m_dropEvent->to_Abort = true;
+ m_dropEvent = nullptr;
+ }
}
void Aura::UpdateTargetMap(Unit* caster, bool apply)
@@ -815,6 +821,26 @@ bool Aura::ModCharges(int32 num, AuraRemoveMode removeMode)
return false;
}
+void Aura::ModChargesDelayed(int32 num, AuraRemoveMode removeMode)
+{
+ m_dropEvent = nullptr;
+ ModCharges(num, removeMode);
+}
+
+void Aura::DropChargeDelayed(uint32 delay, AuraRemoveMode removeMode)
+{
+ // aura is already during delayed charge drop
+ if (m_dropEvent)
+ return;
+ // only units have events
+ Unit* owner = m_owner->ToUnit();
+ if (!owner)
+ return;
+
+ m_dropEvent = new ChargeDropEvent(this, removeMode);
+ owner->m_Events.AddEvent(m_dropEvent, owner->m_Events.CalculateTime(delay));
+}
+
void Aura::SetStackAmount(uint8 stackAmount)
{
m_stackAmount = stackAmount;
@@ -2538,3 +2564,9 @@ void DynObjAura::FillTargetMap(std::map<Unit*, uint8> & targets, Unit* /*caster*
}
}
+bool ChargeDropEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
+{
+ // _base is always valid (look in Aura::_Remove())
+ _base->ModChargesDelayed(-1, _mode);
+ return true;
+}
diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h
index e578c0ffc3a..1266bf5c6ec 100644
--- a/src/server/game/Spells/Auras/SpellAuras.h
+++ b/src/server/game/Spells/Auras/SpellAuras.h
@@ -34,6 +34,7 @@ class Aura;
class DynamicObject;
class AuraScript;
class ProcInfo;
+class ChargeDropEvent;
// update aura target map every 500 ms instead of every update - reduce amount of grid searcher calls
#define UPDATE_TARGET_MAP_INTERVAL 500
@@ -131,7 +132,7 @@ class Aura
void SetDuration(int32 duration, bool withMods = false);
void RefreshDuration(bool withMods = false);
void RefreshTimers();
- bool IsExpired() const { return !GetDuration();}
+ bool IsExpired() const { return !GetDuration() && !m_dropEvent; }
bool IsPermanent() const { return GetMaxDuration() == -1; }
uint8 GetCharges() const { return m_procCharges; }
@@ -140,6 +141,8 @@ class Aura
uint8 CalcMaxCharges() const { return CalcMaxCharges(GetCaster()); }
bool ModCharges(int32 num, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT);
bool DropCharge(AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT) { return ModCharges(-1, removeMode); }
+ void ModChargesDelayed(int32 num, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT);
+ void DropChargeDelayed(uint32 delay, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT);
uint8 GetStackAmount() const { return m_stackAmount; }
void SetStackAmount(uint8 num);
@@ -264,6 +267,8 @@ class Aura
bool m_isSingleTarget:1; // true if it's a single target spell and registered at caster - can change at spell steal for example
bool m_isUsingCharges:1;
+ ChargeDropEvent* m_dropEvent;
+
private:
Unit::AuraApplicationList m_removedApplications;
};
@@ -299,4 +304,16 @@ class DynObjAura : public Aura
void FillTargetMap(std::map<Unit*, uint8> & targets, Unit* caster) override;
};
+
+class ChargeDropEvent : public BasicEvent
+{
+ friend class Aura;
+ protected:
+ ChargeDropEvent(Aura* base, AuraRemoveMode mode) : _base(base), _mode(mode) { }
+ bool Execute(uint64 /*e_time*/, uint32 /*p_time*/);
+
+ private:
+ Aura* _base;
+ AuraRemoveMode _mode;
+};
#endif
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index bc97744fe32..8e0c8c8bd01 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -3350,6 +3350,16 @@ void SpellMgr::LoadSpellInfoCorrections()
// that will be clear if we get more spells with problem like this
spellInfo->AttributesEx |= SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY;
break;
+ case 63414: // Spinning Up (Mimiron)
+ spellInfo->Effects[EFFECT_0].TargetB = SpellImplicitTargetInfo(TARGET_UNIT_CASTER);
+ spellInfo->ChannelInterruptFlags = 0;
+ break;
+ case 63036: // Rocket Strike (Mimiron)
+ spellInfo->Speed = 0;
+ break;
+ case 64668: // Magnetic Field (Mimiron)
+ spellInfo->Mechanic = MECHANIC_NONE;
+ break;
case 64468: // Empowering Shadows (Yogg-Saron)
case 64486: // Empowering Shadows (Yogg-Saron)
spellInfo->MaxAffectedTargets = 3; // same for both modes?
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 4de9cb34df6..f9c8c800ca5 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -23,6 +23,7 @@
#include "World.h"
#include "AchievementMgr.h"
#include "ArenaTeamMgr.h"
+#include "AuctionHouseBot.h"
#include "AuctionHouseMgr.h"
#include "BattlefieldMgr.h"
#include "BattlegroundMgr.h"
@@ -1021,6 +1022,7 @@ void World::LoadConfigSettings(bool reload)
m_bool_configs[CONFIG_BATTLEGROUND_CAST_DESERTER] = sConfigMgr->GetBoolDefault("Battleground.CastDeserter", true);
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_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);
@@ -1254,6 +1256,9 @@ void World::LoadConfigSettings(bool reload)
m_bool_configs[CONFIG_IP_BASED_ACTION_LOGGING] = sConfigMgr->GetBoolDefault("Allow.IP.Based.Action.Logging", false);
+ // AHBot
+ m_int_configs[CONFIG_AHBOT_UPDATE_INTERVAL] = sConfigMgr->GetIntDefault("AuctionHouseBot.Update.Interval", 20);
+
// call ScriptMgr if we're reloading the configuration
if (reload)
sScriptMgr->OnConfigLoad(reload);
@@ -1739,6 +1744,9 @@ void World::SetInitialWorldSettings()
m_timers[WUPDATE_AUTOBROADCAST].SetInterval(getIntConfig(CONFIG_AUTOBROADCAST_INTERVAL));
m_timers[WUPDATE_DELETECHARS].SetInterval(DAY*IN_MILLISECONDS); // check for chars to delete every day
+ // for AhBot
+ m_timers[WUPDATE_AHBOT].SetInterval(getIntConfig(CONFIG_AHBOT_UPDATE_INTERVAL) * IN_MILLISECONDS); // every 20 sec
+
m_timers[WUPDATE_PINGDB].SetInterval(getIntConfig(CONFIG_DB_PING_INTERVAL)*MINUTE*IN_MILLISECONDS); // Mysql ping time in minutes
//to set mailtimer to return mails every day between 4 and 5 am
@@ -1766,6 +1774,9 @@ void World::SetInitialWorldSettings()
// Delete all characters which have been deleted X days before
Player::DeleteOldCharacters();
+ TC_LOG_INFO("server.loading", "Initialize AuctionHouseBot...");
+ sAuctionBot->Initialize();
+
// Delete all custom channels which haven't been used for PreserveCustomChannelDuration days.
Channel::CleanOldChannelsInDB();
@@ -1998,6 +2009,13 @@ void World::Update(uint32 diff)
sAuctionMgr->Update();
}
+ /// <li> Handle AHBot operations
+ if (m_timers[WUPDATE_AHBOT].Passed())
+ {
+ sAuctionBot->Update();
+ m_timers[WUPDATE_AHBOT].Reset();
+ }
+
/// <li> Handle session updates when the timer has passed
RecordTimeDiff(NULL);
UpdateSessions(diff);
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index cb87e1739c2..b77f8777bdc 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -76,6 +76,7 @@ enum WorldTimers
WUPDATE_AUTOBROADCAST,
WUPDATE_MAILBOXQUEUE,
WUPDATE_DELETECHARS,
+ WUPDATE_AHBOT,
WUPDATE_PINGDB,
WUPDATE_COUNT
};
@@ -121,6 +122,7 @@ enum WorldBoolConfigs
CONFIG_BATTLEGROUND_CAST_DESERTER,
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE,
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY,
+ CONFIG_BATTLEGROUND_STORE_STATISTICS_ENABLE,
CONFIG_BG_XP_FOR_KILL,
CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS,
CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE,
@@ -332,6 +334,7 @@ enum WorldIntConfigs
CONFIG_BG_REWARD_LOSER_HONOR_LAST,
CONFIG_BIRTHDAY_TIME,
CONFIG_CREATURE_PICKPOCKET_REFILL,
+ CONFIG_AHBOT_UPDATE_INTERVAL,
INT_CONFIG_VALUE_COUNT
};
diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt
index ba2709f0a23..f193cf4aa6a 100644
--- a/src/server/scripts/CMakeLists.txt
+++ b/src/server/scripts/CMakeLists.txt
@@ -78,6 +78,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/server/game/AI/ScriptedAI
${CMAKE_SOURCE_DIR}/src/server/game/AI/SmartScripts
${CMAKE_SOURCE_DIR}/src/server/game/AuctionHouse
+ ${CMAKE_SOURCE_DIR}/src/server/game/AuctionHouseBot
${CMAKE_SOURCE_DIR}/src/server/game/Battlefield
${CMAKE_SOURCE_DIR}/src/server/game/Battlefield/Zones
${CMAKE_SOURCE_DIR}/src/server/game/Battlegrounds
diff --git a/src/server/scripts/Commands/cs_ahbot.cpp b/src/server/scripts/Commands/cs_ahbot.cpp
new file mode 100644
index 00000000000..04647d51ff0
--- /dev/null
+++ b/src/server/scripts/Commands/cs_ahbot.cpp
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2008-2014 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 "ScriptMgr.h"
+#include "Chat.h"
+#include "Language.h"
+#include "AuctionHouseBot.h"
+
+static const uint32 ahbotQualityIds[MAX_AUCTION_QUALITY] =
+{
+ LANG_AHBOT_QUALITY_GRAY, LANG_AHBOT_QUALITY_WHITE,
+ LANG_AHBOT_QUALITY_GREEN, LANG_AHBOT_QUALITY_BLUE,
+ LANG_AHBOT_QUALITY_PURPLE, LANG_AHBOT_QUALITY_ORANGE,
+ LANG_AHBOT_QUALITY_YELLOW
+};
+
+class ahbot_commandscript : public CommandScript
+{
+public:
+ ahbot_commandscript(): CommandScript("ahbot_commandscript") {}
+
+ ChatCommand* GetCommands() const
+ {
+ static ChatCommand ahbotItemsAmountCommandTable[] =
+ {
+ { "gray", rbac::RBAC_PERM_COMMAND_AHBOT_ITEMS_GRAY, true, &HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_GRAY>, "", NULL },
+ { "white", rbac::RBAC_PERM_COMMAND_AHBOT_ITEMS_WHITE, true, &HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_WHITE>, "", NULL },
+ { "green", rbac::RBAC_PERM_COMMAND_AHBOT_ITEMS_GREEN, true, &HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_GREEN>, "", NULL },
+ { "blue", rbac::RBAC_PERM_COMMAND_AHBOT_ITEMS_BLUE, true, &HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_BLUE>, "", NULL },
+ { "purple", rbac::RBAC_PERM_COMMAND_AHBOT_ITEMS_PURPLE, true, &HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_PURPLE>, "", NULL },
+ { "orange", rbac::RBAC_PERM_COMMAND_AHBOT_ITEMS_ORANGE, true, &HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_ORANGE>, "", NULL },
+ { "yellow", rbac::RBAC_PERM_COMMAND_AHBOT_ITEMS_YELLOW, true, &HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_YELLOW>, "", NULL },
+ { "", rbac::RBAC_PERM_COMMAND_AHBOT_ITEMS, true, &HandleAHBotItemsAmountCommand, "", NULL },
+ { NULL, 0, true, NULL, "", NULL }
+ };
+
+ static ChatCommand ahbotItemsRatioCommandTable[] =
+ {
+ { "alliance", rbac::RBAC_PERM_COMMAND_AHBOT_RATIO_ALLIANCE, true, &HandleAHBotItemsRatioHouseCommand<AUCTION_HOUSE_ALLIANCE>, "", NULL },
+ { "horde", rbac::RBAC_PERM_COMMAND_AHBOT_RATIO_HORDE, true, &HandleAHBotItemsRatioHouseCommand<AUCTION_HOUSE_HORDE>, "", NULL },
+ { "neutral", rbac::RBAC_PERM_COMMAND_AHBOT_RATIO_NEUTRAL, true, &HandleAHBotItemsRatioHouseCommand<AUCTION_HOUSE_NEUTRAL>, "", NULL },
+ { "", rbac::RBAC_PERM_COMMAND_AHBOT_RATIO, true, &HandleAHBotItemsRatioCommand, "", NULL },
+ { NULL, 0, true, NULL, "", NULL }
+ };
+
+ static ChatCommand ahbotCommandTable[] =
+ {
+ { "items", rbac::RBAC_PERM_COMMAND_AHBOT_ITEMS, true, NULL, "", ahbotItemsAmountCommandTable },
+ { "ratio", rbac::RBAC_PERM_COMMAND_AHBOT_RATIO, true, NULL, "", ahbotItemsRatioCommandTable },
+ { "rebuild", rbac::RBAC_PERM_COMMAND_AHBOT_REBUILD, true, &HandleAHBotRebuildCommand, "", NULL },
+ { "reload", rbac::RBAC_PERM_COMMAND_AHBOT_RELOAD, true, &HandleAHBotReloadCommand, "", NULL },
+ { "status", rbac::RBAC_PERM_COMMAND_AHBOT_STATUS, true, &HandleAHBotStatusCommand, "", NULL },
+ { NULL, 0, true, NULL, "", NULL }
+ };
+
+ static ChatCommand commandTable[] =
+ {
+ { "ahbot", rbac::RBAC_PERM_COMMAND_AHBOT, false, NULL, "", ahbotCommandTable },
+ { NULL, 0, false, NULL, "", NULL }
+ };
+
+ return commandTable;
+ }
+
+ static bool HandleAHBotItemsAmountCommand(ChatHandler* handler, const char* args)
+ {
+ uint32 qVals[MAX_AUCTION_QUALITY];
+ char* arg = strtok((char*)args, " ");
+ for (int i = 0; i < MAX_AUCTION_QUALITY; ++i)
+ {
+ if (!arg)
+ return false;
+ qVals[i] = atoi(arg);
+ arg = strtok(NULL, " ");
+ }
+
+ sAuctionBot->SetItemsAmount(qVals);
+
+ for (int i = 0; i < MAX_AUCTION_QUALITY; ++i)
+ handler->PSendSysMessage(LANG_AHBOT_ITEMS_AMOUNT, handler->GetTrinityString(ahbotQualityIds[i]), sAuctionBotConfig->GetConfigItemQualityAmount(AuctionQuality(i)));
+
+ return true;
+ }
+
+ template <AuctionQuality Q>
+ static bool HandleAHBotItemsAmountQualityCommand(ChatHandler* handler, const char* args)
+ {
+ char* arg = strtok((char*)args, " ");
+ if (!arg)
+ return false;
+ uint32 qualityVal = atoi(arg);
+
+ sAuctionBot->SetItemsAmountForQuality(Q, qualityVal);
+ handler->PSendSysMessage(LANG_AHBOT_ITEMS_AMOUNT, handler->GetTrinityString(ahbotQualityIds[Q]),
+ sAuctionBotConfig->GetConfigItemQualityAmount(Q));
+
+ return true;
+ }
+
+ static bool HandleAHBotItemsRatioCommand(ChatHandler* handler, const char* args)
+ {
+ uint32 rVal[MAX_AUCTION_QUALITY];
+ char* arg = strtok((char*)args, " ");
+ for (int i = 0; i < MAX_AUCTION_QUALITY; ++i)
+ {
+ if (!arg)
+ return false;
+ rVal[i] = atoi(arg);
+ arg = strtok(NULL, " ");
+ }
+
+ sAuctionBot->SetItemsRatio(rVal[0], rVal[1], rVal[2]);
+
+ for (int i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
+ handler->PSendSysMessage(LANG_AHBOT_ITEMS_RATIO, AuctionBotConfig::GetHouseTypeName(AuctionHouseType(i)), sAuctionBotConfig->GetConfigItemAmountRatio(AuctionHouseType(i)));
+ return true;
+ }
+
+ template<AuctionHouseType H>
+ static bool HandleAHBotItemsRatioHouseCommand(ChatHandler* handler, const char* args)
+ {
+ char* arg = strtok((char*)args, " ");
+ if (!arg)
+ return false;
+ uint32 ratioVal = atoi(arg);
+
+ sAuctionBot->SetItemsRatioForHouse(H, ratioVal);
+ handler->PSendSysMessage(LANG_AHBOT_ITEMS_RATIO, AuctionBotConfig::GetHouseTypeName(H), sAuctionBotConfig->GetConfigItemAmountRatio(H));
+ return true;
+ }
+
+ static bool HandleAHBotRebuildCommand(ChatHandler* /*handler*/, const char* args)
+ {
+ char* arg = strtok((char*)args, " ");
+ if (!arg)
+ return false;
+
+ bool all = false;
+ if (strcmp(arg, "all") == 0)
+ all = true;
+
+ sAuctionBot->Rebuild(all);
+ return true;
+ }
+
+ static bool HandleAHBotReloadCommand(ChatHandler* handler, const char* /*args*/)
+ {
+ sAuctionBot->ReloadAllConfig();
+ handler->SendSysMessage(LANG_AHBOT_RELOAD_OK);
+ return true;
+ }
+
+ static bool HandleAHBotStatusCommand(ChatHandler* handler, const char* args)
+ {
+ char* arg = strtok((char*)args, " ");
+ if (!arg)
+ return false;
+
+ bool all = false;
+ if (strcmp(arg, "all") == 0)
+ all = true;
+
+ AuctionHouseBotStatusInfo statusInfo;
+ sAuctionBot->PrepareStatusInfos(statusInfo);
+
+ WorldSession* session = handler->GetSession();
+
+ if (!session)
+ {
+ handler->SendSysMessage(LANG_AHBOT_STATUS_BAR_CONSOLE);
+ handler->SendSysMessage(LANG_AHBOT_STATUS_TITLE1_CONSOLE);
+ handler->SendSysMessage(LANG_AHBOT_STATUS_MIDBAR_CONSOLE);
+ }
+ else
+ handler->SendSysMessage(LANG_AHBOT_STATUS_TITLE1_CHAT);
+
+ uint32 fmtId = session ? LANG_AHBOT_STATUS_FORMAT_CHAT : LANG_AHBOT_STATUS_FORMAT_CONSOLE;
+
+ handler->PSendSysMessage(fmtId, handler->GetTrinityString(LANG_AHBOT_STATUS_ITEM_COUNT),
+ statusInfo[AUCTION_HOUSE_ALLIANCE].ItemsCount,
+ statusInfo[AUCTION_HOUSE_HORDE].ItemsCount,
+ statusInfo[AUCTION_HOUSE_NEUTRAL].ItemsCount,
+ statusInfo[AUCTION_HOUSE_ALLIANCE].ItemsCount +
+ statusInfo[AUCTION_HOUSE_HORDE].ItemsCount +
+ statusInfo[AUCTION_HOUSE_NEUTRAL].ItemsCount);
+
+ if (all)
+ {
+ handler->PSendSysMessage(fmtId, handler->GetTrinityString(LANG_AHBOT_STATUS_ITEM_RATIO),
+ sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ALLIANCE_ITEM_AMOUNT_RATIO),
+ sAuctionBotConfig->GetConfig(CONFIG_AHBOT_HORDE_ITEM_AMOUNT_RATIO),
+ sAuctionBotConfig->GetConfig(CONFIG_AHBOT_NEUTRAL_ITEM_AMOUNT_RATIO),
+ sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ALLIANCE_ITEM_AMOUNT_RATIO) +
+ sAuctionBotConfig->GetConfig(CONFIG_AHBOT_HORDE_ITEM_AMOUNT_RATIO) +
+ sAuctionBotConfig->GetConfig(CONFIG_AHBOT_NEUTRAL_ITEM_AMOUNT_RATIO));
+
+ if (!session)
+ {
+ handler->SendSysMessage(LANG_AHBOT_STATUS_BAR_CONSOLE);
+ handler->SendSysMessage(LANG_AHBOT_STATUS_TITLE2_CONSOLE);
+ handler->SendSysMessage(LANG_AHBOT_STATUS_MIDBAR_CONSOLE);
+ }
+ else
+ handler->SendSysMessage(LANG_AHBOT_STATUS_TITLE2_CHAT);
+
+ for (int i = 0; i < MAX_AUCTION_QUALITY; ++i)
+ handler->PSendSysMessage(fmtId, handler->GetTrinityString(ahbotQualityIds[i]),
+ statusInfo[AUCTION_HOUSE_ALLIANCE].QualityInfo[i],
+ statusInfo[AUCTION_HOUSE_HORDE].QualityInfo[i],
+ statusInfo[AUCTION_HOUSE_NEUTRAL].QualityInfo[i],
+ sAuctionBotConfig->GetConfigItemQualityAmount(AuctionQuality(i)));
+ }
+
+ if (!session)
+ handler->SendSysMessage(LANG_AHBOT_STATUS_BAR_CONSOLE);
+
+ return true;
+ }
+
+};
+
+template bool ahbot_commandscript::HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_GRAY>(ChatHandler* handler, const char*);
+template bool ahbot_commandscript::HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_WHITE>(ChatHandler* handler, const char*);
+template bool ahbot_commandscript::HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_GREEN>(ChatHandler* handler, const char*);
+template bool ahbot_commandscript::HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_BLUE>(ChatHandler* handler, const char*);
+template bool ahbot_commandscript::HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_PURPLE>(ChatHandler* handler, const char*);
+template bool ahbot_commandscript::HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_ORANGE>(ChatHandler* handler, const char*);
+template bool ahbot_commandscript::HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_YELLOW>(ChatHandler* handler, const char*);
+
+template bool ahbot_commandscript::HandleAHBotItemsRatioHouseCommand<AUCTION_HOUSE_ALLIANCE>(ChatHandler* handler, const char*);
+template bool ahbot_commandscript::HandleAHBotItemsRatioHouseCommand<AUCTION_HOUSE_HORDE>(ChatHandler* handler, const char*);
+template bool ahbot_commandscript::HandleAHBotItemsRatioHouseCommand<AUCTION_HOUSE_NEUTRAL>(ChatHandler* handler, const char*);
+
+void AddSC_ahbot_commandscript()
+{
+ new ahbot_commandscript();
+}
diff --git a/src/server/scripts/Commands/cs_guild.cpp b/src/server/scripts/Commands/cs_guild.cpp
index 86213291367..7b074087c0f 100644
--- a/src/server/scripts/Commands/cs_guild.cpp
+++ b/src/server/scripts/Commands/cs_guild.cpp
@@ -44,6 +44,7 @@ public:
{ "uninvite", rbac::RBAC_PERM_COMMAND_GUILD_UNINVITE, true, &HandleGuildUninviteCommand, "", NULL },
{ "rank", rbac::RBAC_PERM_COMMAND_GUILD_RANK, true, &HandleGuildRankCommand, "", NULL },
{ "rename", rbac::RBAC_PERM_COMMAND_GUILD_RENAME, true, &HandleGuildRenameCommand, "", NULL },
+ { "info", rbac::RBAC_PERM_COMMAND_GUILD_INFO, true, &HandleGuildInfoCommand, "", NULL },
{ NULL, 0, false, NULL, "", NULL }
};
static ChatCommand commandTable[] =
@@ -243,6 +244,49 @@ public:
handler->PSendSysMessage(LANG_GUILD_RENAME_DONE, oldGuildStr, newGuildStr);
return true;
}
+
+ static bool HandleGuildInfoCommand(ChatHandler* handler, char const* args)
+ {
+ Guild* guild = nullptr;
+
+ if (args && strlen(args) > 0)
+ {
+ if (isNumeric(args))
+ {
+ uint32 guildId = uint32(atoi(args));
+ guild = sGuildMgr->GetGuildById(guildId);
+ }
+ else
+ {
+ std::string guildName = args;
+ guild = sGuildMgr->GetGuildByName(guildName);
+ }
+ }
+ else if (Player* target = handler->getSelectedPlayerOrSelf())
+ guild = target->GetGuild();
+
+ if (!guild)
+ return false;
+
+ // Display Guild Information
+ handler->PSendSysMessage(LANG_GUILD_INFO_NAME, guild->GetName().c_str(), guild->GetId()); // Guild Id + Name
+
+ std::string guildMasterName;
+ if (sObjectMgr->GetPlayerNameByGUID(guild->GetLeaderGUID(), guildMasterName))
+ handler->PSendSysMessage(LANG_GUILD_INFO_GUILD_MASTER, guildMasterName.c_str(), guild->GetLeaderGUID()); // Guild Master
+
+ // Format creation date
+ char createdDateStr[20];
+ time_t createdDate = guild->GetCreatedDate();
+ strftime(createdDateStr, 20, "%Y-%m-%d %H:%M:%S", localtime(&createdDate));
+
+ handler->PSendSysMessage(LANG_GUILD_INFO_CREATION_DATE, createdDateStr); // Creation Date
+ handler->PSendSysMessage(LANG_GUILD_INFO_MEMBER_COUNT, guild->GetMemberCount()); // Number of Members
+ handler->PSendSysMessage(LANG_GUILD_INFO_BANK_GOLD, guild->GetBankMoney() / 100 / 100); // Bank Gold (in gold coins)
+ handler->PSendSysMessage(LANG_GUILD_INFO_MOTD, guild->GetMOTD().c_str()); // Message of the Day
+ handler->PSendSysMessage(LANG_GUILD_INFO_EXTRA_INFO, guild->GetInfo().c_str()); // Extra Information
+ return true;
+ }
};
void AddSC_guild_commandscript()
diff --git a/src/server/scripts/Commands/cs_lookup.cpp b/src/server/scripts/Commands/cs_lookup.cpp
index ee307a1d065..dc00ad047da 100644
--- a/src/server/scripts/Commands/cs_lookup.cpp
+++ b/src/server/scripts/Commands/cs_lookup.cpp
@@ -628,7 +628,7 @@ public:
return false;
// can be NULL at console call
- Player* target = handler->getSelectedPlayer();
+ Player* target = handler->getSelectedPlayerOrSelf();
std::string namePart = args;
std::wstring wNamePart;
diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp
index a3848c00877..9cb7173556a 100644
--- a/src/server/scripts/Commands/cs_misc.cpp
+++ b/src/server/scripts/Commands/cs_misc.cpp
@@ -662,7 +662,7 @@ public:
static bool HandleCooldownCommand(ChatHandler* handler, char const* args)
{
- Player* target = handler->getSelectedPlayer();
+ Player* target = handler->getSelectedPlayerOrSelf();
if (!target)
{
handler->SendSysMessage(LANG_PLAYER_NOT_FOUND);
diff --git a/src/server/scripts/Commands/cs_modify.cpp b/src/server/scripts/Commands/cs_modify.cpp
index 5dbe95b3e54..f70f17232eb 100644
--- a/src/server/scripts/Commands/cs_modify.cpp
+++ b/src/server/scripts/Commands/cs_modify.cpp
@@ -98,7 +98,7 @@ public:
return false;
}
- Player* target = handler->getSelectedPlayer();
+ Player* target = handler->getSelectedPlayerOrSelf();
if (!target)
{
handler->SendSysMessage(LANG_NO_CHAR_SELECTED);
diff --git a/src/server/scripts/Commands/cs_quest.cpp b/src/server/scripts/Commands/cs_quest.cpp
index 6004cd0bc89..08603279824 100644
--- a/src/server/scripts/Commands/cs_quest.cpp
+++ b/src/server/scripts/Commands/cs_quest.cpp
@@ -53,7 +53,7 @@ public:
static bool HandleQuestAdd(ChatHandler* handler, const char* args)
{
- Player* player = handler->getSelectedPlayer();
+ Player* player = handler->getSelectedPlayerOrSelf();
if (!player)
{
handler->SendSysMessage(LANG_NO_CHAR_SELECTED);
@@ -151,7 +151,7 @@ public:
static bool HandleQuestComplete(ChatHandler* handler, const char* args)
{
- Player* player = handler->getSelectedPlayer();
+ Player* player = handler->getSelectedPlayerOrSelf();
if (!player)
{
handler->SendSysMessage(LANG_NO_CHAR_SELECTED);
diff --git a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp
index b171bf014c7..220cf0c92b4 100644
--- a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp
+++ b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp
@@ -317,7 +317,7 @@ public:
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[9], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000);
break;
case 2:
- if (GameObject* go = me->SummonGameObject(183410, -533.140f, -105.322f, -156.016f, 0, 0, 0, 0, 0, 1000))
+ if (GameObject* go = me->SummonGameObject(183410, -533.140f, -105.322f, -156.016f, 0, 0, 0, 0, 0, 1))
{
GoSummonList.push_back(go->GetGUID());
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); //We can't use it!
@@ -332,7 +332,7 @@ public:
Talk(SAY_BLASTMASTER_7);
break;
case 4:
- if (GameObject* go = me->SummonGameObject(183410, -542.199f, -96.854f, -155.790f, 0, 0, 0, 0, 0, 1000))
+ if (GameObject* go = me->SummonGameObject(183410, -542.199f, -96.854f, -155.790f, 0, 0, 0, 0, 0, 1))
{
GoSummonList.push_back(go->GetGUID());
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
@@ -346,7 +346,7 @@ public:
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[14], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000);
break;
case 6:
- if (GameObject* go = me->SummonGameObject(183410, -507.820f, -103.333f, -151.353f, 0, 0, 0, 0, 0, 1000))
+ if (GameObject* go = me->SummonGameObject(183410, -507.820f, -103.333f, -151.353f, 0, 0, 0, 0, 0, 1))
{
GoSummonList.push_back(go->GetGUID());
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); //We can't use it!
@@ -354,7 +354,7 @@ public:
}
break;
case 7:
- if (GameObject* go = me->SummonGameObject(183410, -511.829f, -86.249f, -151.431f, 0, 0, 0, 0, 0, 1000))
+ if (GameObject* go = me->SummonGameObject(183410, -511.829f, -86.249f, -151.431f, 0, 0, 0, 0, 0, 1))
{
GoSummonList.push_back(go->GetGUID());
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); //We can't use it!
diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
index ae6aaef9999..95990f18829 100644
--- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
@@ -26,6 +26,7 @@
#include "Player.h"
#include "SpellInfo.h"
#include "CreatureTextMgr.h"
+#include "MoveSplineInit.h"
/*######
##Quest 12848
@@ -322,6 +323,117 @@ public:
};
+ /*######
+## npc_eye_of_acherus
+######*/
+
+enum EyeOfAcherus
+{
+ SPELL_EYE_VISUAL = 51892,
+ SPELL_EYE_FLIGHT_BOOST = 51923,
+ SPELL_EYE_FLIGHT = 51890,
+
+ EVENT_MOVE_START = 1,
+
+ TALK_MOVE_START = 0,
+ TALK_CONTROL = 1,
+
+ POINT_EYE_FALL = 1,
+ POINT_EYE_MOVE_END = 3
+};
+
+Position const EyeOFAcherusFallPoint = { 2361.21f, -5660.45f, 496.7444f, 0.0f };
+
+class npc_eye_of_acherus : public CreatureScript
+{
+ public:
+ npc_eye_of_acherus() : CreatureScript("npc_eye_of_acherus") { }
+
+ struct npc_eye_of_acherusAI : public ScriptedAI
+ {
+ npc_eye_of_acherusAI(Creature* creature) : ScriptedAI(creature)
+ {
+ me->SetDisplayId(me->GetCreatureTemplate()->Modelid1);
+ if (Player* owner = me->GetCharmerOrOwner()->ToPlayer())
+ owner->SendAutoRepeatCancel(me);
+
+ me->SetReactState(REACT_PASSIVE);
+
+ me->GetMotionMaster()->MovePoint(POINT_EYE_FALL, EyeOFAcherusFallPoint, false);
+
+ Movement::MoveSplineInit init(me);
+ init.MoveTo(EyeOFAcherusFallPoint.GetPositionX(), EyeOFAcherusFallPoint.GetPositionY(), EyeOFAcherusFallPoint.GetPositionZ(), false);
+ init.SetFall();
+ init.Launch();
+ }
+
+ void OnCharmed(bool /*apply*/) override { }
+
+ void UpdateAI(uint32 diff) override
+ {
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_MOVE_START:
+ {
+ DoCast(me, SPELL_EYE_FLIGHT_BOOST);
+
+ me->SetControlled(false, UNIT_STATE_ROOT);
+ if (Player* owner = me->GetCharmerOrOwner()->ToPlayer())
+ {
+ for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i)
+ me->SetSpeed(UnitMoveType(i), owner->GetSpeedRate(UnitMoveType(i)), true);
+ Talk(TALK_MOVE_START, owner);
+ }
+ me->GetMotionMaster()->MovePath(me->GetEntry() * 100, false);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+
+ void MovementInform(uint32 movementType, uint32 pointId) override
+ {
+ if (movementType == WAYPOINT_MOTION_TYPE && pointId == POINT_EYE_MOVE_END - 1)
+ {
+ me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE);
+ me->RemoveAllAuras();
+
+ if (Player* owner = me->GetCharmerOrOwner()->ToPlayer())
+ {
+ owner->RemoveAura(SPELL_EYE_FLIGHT_BOOST);
+ for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i)
+ me->SetSpeed(UnitMoveType(i), owner->GetSpeedRate(UnitMoveType(i)), true);
+
+ TalkToMap(TALK_CONTROL, owner);
+ }
+ me->SetDisableGravity(false);
+ DoCast(me, SPELL_EYE_FLIGHT);
+ }
+
+ if (movementType == POINT_MOTION_TYPE && pointId == POINT_EYE_FALL)
+ {
+ me->SetDisableGravity(true);
+ me->SetControlled(true, UNIT_STATE_ROOT);
+ _events.ScheduleEvent(EVENT_MOVE_START, 5000);
+ }
+ }
+
+ private:
+ EventMap _events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return new npc_eye_of_acherusAI(creature);
+ }
+};
+
/*######
## npc_death_knight_initiate
######*/
@@ -1079,6 +1191,7 @@ void AddSC_the_scarlet_enclave_c1()
new npc_unworthy_initiate();
new npc_unworthy_initiate_anchor();
new go_acherus_soul_prison();
+ new npc_eye_of_acherus();
new npc_death_knight_initiate();
new npc_salanar_the_horseman();
new npc_dark_rider_of_acherus();
diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp
index 72757387b1c..e202e55e675 100644
--- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp
@@ -1138,7 +1138,7 @@ public:
case 48: // Show the cleansing effect (dawn of light)
//if (GameObject* go = me->GetMap()->GetGameObject(uiDawnofLightGUID))
// go->SetPhaseMask(128, true);
- me->SummonGameObject(GO_LIGHT_OF_DAWN, 2283.896f, -5287.914f, 83.066f, 0, 0, 0, 0, 0, 30000);
+ me->SummonGameObject(GO_LIGHT_OF_DAWN, 2283.896f, -5287.914f, 83.066f, 0, 0, 0, 0, 0, 30);
if (Creature* temp = ObjectAccessor::GetCreature(*me, uiTirionGUID))
{
if (temp->HasAura(SPELL_REBIRTH_OF_THE_ASHBRINGER, 0))
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_arcanist_doan.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_arcanist_doan.cpp
index 26937a83e63..cdfcede1c93 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_arcanist_doan.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_arcanist_doan.cpp
@@ -124,7 +124,7 @@ class boss_arcanist_doan : public CreatureScript
CreatureAI* GetAI(Creature* creature) const override
{
- return GetInstanceAI<boss_arcanist_doanAI>(creature);
+ return GetScarletMonasteryAI<boss_arcanist_doanAI>(creature);
}
};
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_azshir_the_sleepless.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_azshir_the_sleepless.cpp
index 71a5343d160..c3c74e4c83d 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_azshir_the_sleepless.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_azshir_the_sleepless.cpp
@@ -15,13 +15,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Boss_Azshir_the_Sleepless
-SD%Complete: 80
-SDComment:
-SDCategory: Scarlet Monastery
-EndScriptData */
-
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "scarlet_monastery.h"
@@ -70,9 +63,9 @@ class boss_azshir_the_sleepless : public CreatureScript
_JustDied();
}
- void DamageTaken(Unit* /*done_by*/, uint32& /*damage*/) override
+ void DamageTaken(Unit* /*attacker*/, uint32& damage) override
{
- if (HealthBelowPct(50) && !_siphon)
+ if (!_siphon && me->HealthBelowPctDamaged(50, damage))
{
DoCastVictim(SPELL_SOUL_SIPHON);
events.ScheduleEvent(EVENT_SOUL_SIPHON, 20000);
@@ -120,7 +113,7 @@ class boss_azshir_the_sleepless : public CreatureScript
CreatureAI* GetAI(Creature* creature) const override
{
- return GetInstanceAI<boss_azshir_the_sleeplessAI>(creature);
+ return GetScarletMonasteryAI<boss_azshir_the_sleeplessAI>(creature);
}
};
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_bloodmage_thalnos.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_bloodmage_thalnos.cpp
index 18369c7adfc..14698faaa97 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_bloodmage_thalnos.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_bloodmage_thalnos.cpp
@@ -80,9 +80,9 @@ class boss_bloodmage_thalnos : public CreatureScript
Talk(SAY_KILL);
}
- void DamageTaken(Unit* /*done_by*/, uint32& /*damage*/) override
+ void DamageTaken(Unit* /*attacker*/, uint32& damage) override
{
- if (HealthBelowPct(35) && !_hpYell)
+ if (!_hpYell && me->HealthBelowPctDamaged(35, damage))
{
Talk(SAY_HEALTH);
_hpYell = true;
@@ -114,18 +114,13 @@ class boss_bloodmage_thalnos : public CreatureScript
}
}
- void UpdateAI(uint32 diff) override
- {
- BossAI::UpdateAI(diff);
- }
-
private:
bool _hpYell;
};
CreatureAI* GetAI(Creature* creature) const override
{
- return GetInstanceAI<boss_bloodmage_thalnosAI>(creature);
+ return GetScarletMonasteryAI<boss_bloodmage_thalnosAI>(creature);
}
};
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_herod.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_herod.cpp
index d1d25dd2ba6..d77334785ef 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_herod.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_herod.cpp
@@ -100,9 +100,9 @@ class boss_herod : public CreatureScript
me->SummonCreature(NPC_SCARLET_TRAINEE, ScarletTraineePos, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000);
}
- void DamageTaken(Unit* /*done_by*/, uint32& /*damage*/) override
+ void DamageTaken(Unit* /*attacker*/, uint32& damage) override
{
- if (HealthBelowPct(30) && !_enrage)
+ if (!_enrage && me->HealthBelowPctDamaged(30, damage))
{
Talk(EMOTE_ENRAGE);
Talk(SAY_ENRAGE);
@@ -129,18 +129,13 @@ class boss_herod : public CreatureScript
}
}
- void UpdateAI(uint32 diff) override
- {
- BossAI::UpdateAI(diff);
- }
-
private:
bool _enrage;
};
CreatureAI* GetAI(Creature* creature) const override
{
- return GetInstanceAI<boss_herodAI>(creature);
+ return GetScarletMonasteryAI<boss_herodAI>(creature);
}
};
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_houndmaster_loksey.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_houndmaster_loksey.cpp
index 40c7667843b..0e1b51f9a83 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_houndmaster_loksey.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_houndmaster_loksey.cpp
@@ -73,16 +73,11 @@ class boss_houndmaster_loksey : public CreatureScript
break;
}
}
-
- void UpdateAI(uint32 diff) override
- {
- BossAI::UpdateAI(diff);
- }
};
CreatureAI* GetAI(Creature* creature) const override
{
- return GetInstanceAI<boss_houndmaster_lokseyAI>(creature);
+ return GetScarletMonasteryAI<boss_houndmaster_lokseyAI>(creature);
}
};
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_scorn.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_scorn.cpp
index 24efd7017ec..d64e556c011 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_scorn.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_scorn.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -16,13 +15,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Boss_Scorn
-SD%Complete: 100
-SDComment:
-SDCategory: Scarlet Monastery
-EndScriptData */
-
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "scarlet_monastery.h"
@@ -95,16 +87,11 @@ class boss_scorn : public CreatureScript
break;
}
}
-
- void UpdateAI(uint32 diff) override
- {
- BossAI::UpdateAI(diff);
- }
};
CreatureAI* GetAI(Creature* creature) const override
{
- return GetInstanceAI<boss_scornAI>(creature);
+ return GetScarletMonasteryAI<boss_scornAI>(creature);
}
};
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp
index 78837912688..dc65bd42bf4 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp
@@ -28,7 +28,7 @@ DoorData const doorData[] =
class instance_scarlet_monastery : public InstanceMapScript
{
public:
- instance_scarlet_monastery() : InstanceMapScript("instance_scarlet_monastery", 189) { }
+ instance_scarlet_monastery() : InstanceMapScript(SMScriptName, 189) { }
struct instance_scarlet_monastery_InstanceMapScript : public InstanceScript
{
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/scarlet_monastery.h b/src/server/scripts/EasternKingdoms/ScarletMonastery/scarlet_monastery.h
index d4ce3f1614f..a74efba751f 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/scarlet_monastery.h
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/scarlet_monastery.h
@@ -18,6 +18,7 @@
#ifndef SCARLET_M_
#define SCARLET_M_
+#define SMScriptName "instance_scarlet_monastery"
uint32 const EncounterCount = 10;
enum DataTypes
@@ -57,4 +58,10 @@ enum GameObjectIds
GO_PUMPKIN_SHRINE = 186267
};
+template<class AI>
+inline AI* GetScarletMonasteryAI(Creature* creature)
+{
+ return GetInstanceAI<AI>(creature, SMScriptName);
+}
+
#endif // SCARLET_M_
diff --git a/src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp b/src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp
index 0f33103fc2c..789a5c3a874 100644
--- a/src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp
+++ b/src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp
@@ -183,13 +183,13 @@ public:
/*
void UseLastStatue(GameObject* go)
{
- AtalaiStatue1->SummonGameObject(GO_ATALAI_LIGHT2, AtalaiStatue1->GetPositionX(), AtalaiStatue1->GetPositionY(), AtalaiStatue1->GetPositionZ(), 0, 0, 0, 0, 0, 100000);
- AtalaiStatue2->SummonGameObject(GO_ATALAI_LIGHT2, AtalaiStatue2->GetPositionX(), AtalaiStatue2->GetPositionY(), AtalaiStatue2->GetPositionZ(), 0, 0, 0, 0, 0, 100000);
- AtalaiStatue3->SummonGameObject(GO_ATALAI_LIGHT2, AtalaiStatue3->GetPositionX(), AtalaiStatue3->GetPositionY(), AtalaiStatue3->GetPositionZ(), 0, 0, 0, 0, 0, 100000);
- AtalaiStatue4->SummonGameObject(GO_ATALAI_LIGHT2, AtalaiStatue4->GetPositionX(), AtalaiStatue4->GetPositionY(), AtalaiStatue4->GetPositionZ(), 0, 0, 0, 0, 0, 100000);
- AtalaiStatue5->SummonGameObject(GO_ATALAI_LIGHT2, AtalaiStatue5->GetPositionX(), AtalaiStatue5->GetPositionY(), AtalaiStatue5->GetPositionZ(), 0, 0, 0, 0, 0, 100000);
- AtalaiStatue6->SummonGameObject(GO_ATALAI_LIGHT2, AtalaiStatue6->GetPositionX(), AtalaiStatue6->GetPositionY(), AtalaiStatue6->GetPositionZ(), 0, 0, 0, 0, 0, 100000);
- go->SummonGameObject(148838, -488.997, 96.61, -189.019, -1.52, 0, 0, 0, 0, 100000);
+ AtalaiStatue1->SummonGameObject(GO_ATALAI_LIGHT2, AtalaiStatue1->GetPositionX(), AtalaiStatue1->GetPositionY(), AtalaiStatue1->GetPositionZ(), 0, 0, 0, 0, 0, 100);
+ AtalaiStatue2->SummonGameObject(GO_ATALAI_LIGHT2, AtalaiStatue2->GetPositionX(), AtalaiStatue2->GetPositionY(), AtalaiStatue2->GetPositionZ(), 0, 0, 0, 0, 0, 100);
+ AtalaiStatue3->SummonGameObject(GO_ATALAI_LIGHT2, AtalaiStatue3->GetPositionX(), AtalaiStatue3->GetPositionY(), AtalaiStatue3->GetPositionZ(), 0, 0, 0, 0, 0, 100);
+ AtalaiStatue4->SummonGameObject(GO_ATALAI_LIGHT2, AtalaiStatue4->GetPositionX(), AtalaiStatue4->GetPositionY(), AtalaiStatue4->GetPositionZ(), 0, 0, 0, 0, 0, 100);
+ AtalaiStatue5->SummonGameObject(GO_ATALAI_LIGHT2, AtalaiStatue5->GetPositionX(), AtalaiStatue5->GetPositionY(), AtalaiStatue5->GetPositionZ(), 0, 0, 0, 0, 0, 100);
+ AtalaiStatue6->SummonGameObject(GO_ATALAI_LIGHT2, AtalaiStatue6->GetPositionX(), AtalaiStatue6->GetPositionY(), AtalaiStatue6->GetPositionZ(), 0, 0, 0, 0, 0, 100);
+ go->SummonGameObject(148838, -488.997, 96.61, -189.019, -1.52, 0, 0, 0, 0, 100);
}
*/
diff --git a/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp b/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp
index ce9ed4f36c8..3e15a80fd74 100644
--- a/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp
+++ b/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp
@@ -204,7 +204,7 @@ public:
case EVENT_COMPLETE:
{
DoCast(me, SPELL_IDOM_ROOM_CAMERA_SHAKE);
- me->SummonGameObject(GO_BELNISTRASZS_BRAZIER, 2577.196f, 947.0781f, 53.16757f, 2.356195f, 0, 0, 0.9238796f, 0.3826832f, 3600000);
+ me->SummonGameObject(GO_BELNISTRASZS_BRAZIER, 2577.196f, 947.0781f, 53.16757f, 2.356195f, 0, 0, 0.9238796f, 0.3826832f, 3600);
std::list<WorldObject*> ClusterList;
Trinity::AllWorldObjectsInRange objects(me, 50.0f);
Trinity::WorldObjectListSearcher<Trinity::AllWorldObjectsInRange> searcher(me, ClusterList, objects);
diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp
index bc6807c54d9..905761ce359 100644
--- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp
+++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp
@@ -39,11 +39,8 @@ enum Spells
SPELL_SPHERE_VISUAL = 56075,
SPELL_GIFT_OF_THE_HERALD = 56219,
SPELL_CYCLONE_STRIKE = 56855, // Self
- SPELL_CYCLONE_STRIKE_H = 60030,
SPELL_LIGHTNING_BOLT = 56891, // 40Y
- SPELL_LIGHTNING_BOLT_H = 60032, // 40Y
- SPELL_THUNDERSHOCK = 56926, // 30Y
- SPELL_THUNDERSHOCK_H = 60029 // 30Y
+ SPELL_THUNDERSHOCK = 56926 // 30Y
};
const Position JedogaPosition[2] =
@@ -296,7 +293,7 @@ public:
if (uiBoltTimer <= diff)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
- me->CastSpell(target, DUNGEON_MODE(SPELL_LIGHTNING_BOLT, SPELL_LIGHTNING_BOLT_H), false);
+ me->CastSpell(target, SPELL_LIGHTNING_BOLT, false);
uiBoltTimer = urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS);
} else uiBoltTimer -= diff;
@@ -304,7 +301,7 @@ public:
if (uiThunderTimer <= diff)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
- me->CastSpell(target, DUNGEON_MODE(SPELL_THUNDERSHOCK, SPELL_THUNDERSHOCK_H), false);
+ me->CastSpell(target, SPELL_THUNDERSHOCK, false);
uiThunderTimer = urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS);
} else uiThunderTimer -= diff;
diff --git a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp
index 81e124cf5bc..4c3ca322574 100644
--- a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp
+++ b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp
@@ -41,9 +41,7 @@ enum Enums
SPELL_BERSERK = 61632, // Increases the caster's attack speed by 150% and all damage it deals by 500% for 5 min.
SPELL_CLEAVE = 56909, // Inflicts 35% weapon damage to an enemy and its nearest allies, affecting up to 10 targets.
SPELL_FLAME_BREATH = 56908, // Inflicts 8750 to 11250 Fire damage to enemies in a cone in front of the caster.
- SPELL_FLAME_BREATH_H = 58956, // Inflicts 10938 to 14062 Fire damage to enemies in a cone in front of the caster.
SPELL_TAIL_LASH = 56910, // A sweeping tail strike hits all enemies behind the caster, inflicting 3063 to 3937 damage and stunning them for 2 sec.
- SPELL_TAIL_LASH_H = 58957, // A sweeping tail strike hits all enemies behind the caster, inflicting 4375 to 5625 damage and stunning them for 2 sec.
SPELL_WILL_OF_SARTHARION = 61254, // Sartharion's presence bolsters the resolve of the Twilight Drakes, increasing their total health by 25%. This effect also increases Sartharion's health by 25%.
SPELL_LAVA_STRIKE = 57571, // (Real spell cast should be 57578) 57571 then trigger visual missile, then summon Lava Blaze on impact(spell 57572)
SPELL_TWILIGHT_REVENGE = 60639,
@@ -443,11 +441,11 @@ public:
break;
case EVENT_FLAME_BREATH:
Talk(SAY_SARTHARION_BREATH);
- DoCastVictim(RAID_MODE(SPELL_FLAME_BREATH, SPELL_FLAME_BREATH_H));
+ DoCastVictim(SPELL_FLAME_BREATH);
events.ScheduleEvent(EVENT_FLAME_BREATH, urand(25000, 35000));
break;
case EVENT_TAIL_SWEEP:
- DoCastVictim(RAID_MODE(SPELL_TAIL_LASH, SPELL_TAIL_LASH_H));
+ DoCastVictim(SPELL_TAIL_LASH);
events.ScheduleEvent(EVENT_TAIL_SWEEP, urand(15000, 20000));
break;
case EVENT_CLEAVE_ATTACK:
diff --git a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp
index e332e7959ce..0a712b69771 100644
--- a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp
+++ b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp
@@ -29,10 +29,7 @@ enum Enums
SPELL_TWILIGHT_RESIDUE = 61885, // makes immune to shadow damage, applied when leave phase
//Miniboses (Vesperon, Shadron, Tenebron)
- SPELL_SHADOW_BREATH_H = 59126, // Inflicts 8788 to 10212 Fire damage to enemies in a cone in front of the caster.
SPELL_SHADOW_BREATH = 57570, // Inflicts 6938 to 8062 Fire damage to enemies in a cone in front of the caster.
-
- SPELL_SHADOW_FISSURE_H = 59127, // Deals 9488 to 13512 Shadow damage to any enemy within the Shadow fissure after 5 sec.
SPELL_SHADOW_FISSURE = 57579, // Deals 6188 to 8812 Shadow damage to any enemy within the Shadow fissure after 5 sec.
//Vesperon
@@ -49,7 +46,6 @@ enum Enums
SPELL_GIFT_OF_TWILIGTH_SHA = 57835, // TARGET_SCRIPT shadron
SPELL_GIFT_OF_TWILIGTH_SAR = 58766, // TARGET_SCRIPT sartharion
SPELL_VOID_BLAST = 57581, // Twilight Fissure
- SPELL_VOID_BLAST_H = 59128,
//Tenebron
//in the portal spawns 6 eggs, if not killed in time (approx. 20s) they will hatch, whelps can cast 60708
@@ -382,12 +378,12 @@ struct dummy_dragonAI : public ScriptedAI
{
case EVENT_SHADOW_FISSURE:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
- DoCast(target, RAID_MODE(SPELL_SHADOW_FISSURE, SPELL_SHADOW_FISSURE));
+ DoCast(target, SPELL_SHADOW_FISSURE);
events.ScheduleEvent(eventId, urand(15000, 20000));
break;
case EVENT_SHADOW_BREATH:
Talk(SAY_BREATH);
- DoCastVictim(RAID_MODE(SPELL_SHADOW_BREATH, SPELL_SHADOW_BREATH_H));
+ DoCastVictim(SPELL_SHADOW_BREATH);
events.ScheduleEvent(eventId, urand(20000, 25000));
break;
default:
@@ -949,7 +945,7 @@ public:
if (events.ExecuteEvent() == EVENT_VOID_BLAST)
{
- DoCastAOE(RAID_MODE(SPELL_VOID_BLAST, SPELL_VOID_BLAST_H));
+ DoCastAOE(SPELL_VOID_BLAST);
////twilight realm
//DoCastVictim(57620, true);
//DoCastVictim(57874, true);
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/instance_trial_of_the_champion.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/instance_trial_of_the_champion.cpp
index ac8a7969c9d..5209e8b2f94 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/instance_trial_of_the_champion.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/instance_trial_of_the_champion.cpp
@@ -194,7 +194,7 @@ public:
{
pAnnouncer->GetMotionMaster()->MovePoint(0, 748.309f, 619.487f, 411.171f);
pAnnouncer->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
- pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_CHAMPIONS_LOOT_H : GO_CHAMPIONS_LOOT, 746.59f, 618.49f, 411.09f, 1.42f, 0, 0, 0, 0, 90000000);
+ pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_CHAMPIONS_LOOT_H : GO_CHAMPIONS_LOOT, 746.59f, 618.49f, 411.09f, 1.42f, 0, 0, 0, 0, 90000);
}
}
}
@@ -217,7 +217,7 @@ public:
{
pAnnouncer->GetMotionMaster()->MovePoint(0, 748.309f, 619.487f, 411.171f);
pAnnouncer->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
- pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_EADRIC_LOOT_H : GO_EADRIC_LOOT, 746.59f, 618.49f, 411.09f, 1.42f, 0, 0, 0, 0, 90000000);
+ pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_EADRIC_LOOT_H : GO_EADRIC_LOOT, 746.59f, 618.49f, 411.09f, 1.42f, 0, 0, 0, 0, 90000);
}
break;
case BOSS_ARGENT_CHALLENGE_P:
@@ -226,7 +226,7 @@ public:
{
pAnnouncer->GetMotionMaster()->MovePoint(0, 748.309f, 619.487f, 411.171f);
pAnnouncer->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
- pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_PALETRESS_LOOT_H : GO_PALETRESS_LOOT, 746.59f, 618.49f, 411.09f, 1.42f, 0, 0, 0, 0, 90000000);
+ pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_PALETRESS_LOOT_H : GO_PALETRESS_LOOT, 746.59f, 618.49f, 411.09f, 1.42f, 0, 0, 0, 0, 90000);
}
break;
}
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp
index 6a664ec7f8d..7af55ec37ea 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp
@@ -465,7 +465,7 @@ class npc_swarm_scarab : public CreatureScript
void JustDied(Unit* killer) override
{
- DoCast(killer, RAID_MODE(SPELL_TRAITOR_KING_10, SPELL_TRAITOR_KING_25));
+ DoCast(killer, SPELL_TRAITOR_KING);
}
void UpdateAI(uint32 diff) override
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h
index 8a62453d7c1..dc0f390f8e0 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h
@@ -293,8 +293,7 @@ enum AchievementData
SPELL_WORMS_KILLED_IN_10_SECONDS = 68523,
SPELL_CHAMPIONS_KILLED_IN_MINUTE = 68620,
SPELL_DEFEAT_FACTION_CHAMPIONS = 68184,
- SPELL_TRAITOR_KING_10 = 68186,
- SPELL_TRAITOR_KING_25 = 68515,
+ SPELL_TRAITOR_KING = 68186,
// Timed events
EVENT_START_TWINS_FIGHT = 21853
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
index 1ff7e1b1352..9d24ad062df 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
@@ -643,7 +643,7 @@ class spell_marrowgar_bone_spike_graveyard : public SpellScriptLoader
for (std::list<Unit*>::const_iterator itr = targets.begin(); itr != targets.end(); ++itr, ++i)
{
Unit* target = *itr;
- target->CastCustomSpell(BoneSpikeSummonId[i], SPELLVALUE_BASE_POINT0, 0, target, true);
+ target->CastSpell(target, BoneSpikeSummonId[i], true);
}
marrowgarAI->Talk(SAY_BONESPIKE);
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
index f60a7ba278b..11f20129b3e 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
@@ -1269,7 +1269,13 @@ class spell_putricide_mutated_plague : public SpellScriptLoader
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
uint32 healSpell = uint32(GetSpellInfo()->Effects[EFFECT_0].CalcValue());
- GetTarget()->CastSpell(GetTarget(), healSpell, true, NULL, NULL, GetCasterGUID());
+ SpellInfo const* healSpellInfo = sSpellMgr->GetSpellInfo(healSpell);
+
+ if (!healSpellInfo)
+ return;
+
+ int32 heal = healSpellInfo->Effects[0].CalcValue() * GetStackAmount();
+ GetTarget()->CastCustomSpell(healSpell, SPELLVALUE_BASE_POINT0, heal, GetTarget(), true, NULL, NULL, GetCasterGUID());
}
void Register() override
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp
index 2a587e535a3..676e4134f11 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp
@@ -38,10 +38,8 @@ enum Events
enum Spells
{
- SPELL_IMPALE_10 = 28783,
- SPELL_IMPALE_25 = 56090,
- SPELL_LOCUST_SWARM_10 = 28785,
- SPELL_LOCUST_SWARM_25 = 54021,
+ SPELL_IMPALE = 28783,
+ SPELL_LOCUST_SWARM = 28785,
SPELL_SUMMON_CORPSE_SCARABS_PLR = 29105, // This spawns 5 corpse scarabs on top of player
SPELL_SUMMON_CORPSE_SCARABS_MOB = 28864, // This spawns 10 corpse scarabs on top of dead guards
SPELL_BERSERK = 27680
@@ -154,14 +152,14 @@ public:
case EVENT_IMPALE:
//Cast Impale on a random target
//Do NOT cast it when we are afflicted by locust swarm
- if (!me->HasAura(RAID_MODE(SPELL_LOCUST_SWARM_10, SPELL_LOCUST_SWARM_25)))
+ if (!me->HasAura(sSpellMgr->GetSpellIdForDifficulty(SPELL_LOCUST_SWARM, me)))
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- DoCast(target, RAID_MODE(SPELL_IMPALE_10, SPELL_IMPALE_25));
+ DoCast(target, SPELL_IMPALE);
events.ScheduleEvent(EVENT_IMPALE, urand(10000, 20000));
break;
case EVENT_LOCUST:
/// @todo Add Text
- DoCast(me, RAID_MODE(SPELL_LOCUST_SWARM_10, SPELL_LOCUST_SWARM_25));
+ DoCast(me, SPELL_LOCUST_SWARM);
DoSummon(NPC_CRYPT_GUARD, GuardSummonPos, 0, TEMPSUMMON_CORPSE_DESPAWN);
events.ScheduleEvent(EVENT_LOCUST, 90000);
break;
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp
index 3d42827c0a8..ec273d5f6e8 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp
@@ -31,16 +31,12 @@ enum Yells
enum Spells
{
SPELL_POISON_BOLT_VOLLEY = 28796,
- H_SPELL_POISON_BOLT_VOLLEY = 54098,
SPELL_RAIN_OF_FIRE = 28794,
- H_SPELL_RAIN_OF_FIRE = 54099,
SPELL_FRENZY = 28798,
- H_SPELL_FRENZY = 54100,
- SPELL_WIDOWS_EMBRACE = 28732,
- H_SPELL_WIDOWS_EMBRACE = 54097
+ SPELL_WIDOWS_EMBRACE = 28732
};
-#define SPELL_WIDOWS_EMBRACE_HELPER RAID_MODE(SPELL_WIDOWS_EMBRACE, H_SPELL_WIDOWS_EMBRACE)
+#define SPELL_WIDOWS_EMBRACE_HELPER RAID_MODE<uint32>(28732, 54097)
enum Events
{
@@ -108,7 +104,7 @@ class boss_faerlina : public CreatureScript
void SpellHit(Unit* caster, SpellInfo const* spell) override
{
- if (spell->Id == SPELL_WIDOWS_EMBRACE || spell->Id == H_SPELL_WIDOWS_EMBRACE)
+ if (spell->Id == SPELL_WIDOWS_EMBRACE_HELPER)
{
/// @todo Add Text
++_frenzyDispels;
@@ -133,7 +129,7 @@ class boss_faerlina : public CreatureScript
if (_delayFrenzy && !me->HasAura(SPELL_WIDOWS_EMBRACE_HELPER))
{
_delayFrenzy = false;
- DoCast(me, RAID_MODE(SPELL_FRENZY, H_SPELL_FRENZY), true);
+ DoCast(me, SPELL_FRENZY, true);
}
events.Update(diff);
@@ -147,18 +143,18 @@ class boss_faerlina : public CreatureScript
{
case EVENT_POISON:
if (!me->HasAura(SPELL_WIDOWS_EMBRACE_HELPER))
- DoCastAOE(RAID_MODE(SPELL_POISON_BOLT_VOLLEY, H_SPELL_POISON_BOLT_VOLLEY));
+ DoCastAOE(SPELL_POISON_BOLT_VOLLEY);
events.ScheduleEvent(EVENT_POISON, urand(8000, 15000));
break;
case EVENT_FIRE:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- DoCast(target, RAID_MODE(SPELL_RAIN_OF_FIRE, H_SPELL_RAIN_OF_FIRE));
+ DoCast(target, SPELL_RAIN_OF_FIRE);
events.ScheduleEvent(EVENT_FIRE, urand(6000, 18000));
break;
case EVENT_FRENZY:
/// @todo Add Text
if (!me->HasAura(SPELL_WIDOWS_EMBRACE_HELPER))
- DoCast(me, RAID_MODE(SPELL_FRENZY, H_SPELL_FRENZY));
+ DoCast(me, SPELL_FRENZY);
else
_delayFrenzy = true;
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp b/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp
index fa5a0c47808..648fc3c87d2 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp
@@ -35,7 +35,6 @@ enum Spells
{
SPELL_HARVEST_SOUL = 28679,
SPELL_SHADOW_BOLT = 29317,
- H_SPELL_SHADOW_BOLT = 56405,
SPELL_INFORM_LIVE_TRAINEE = 27892,
SPELL_INFORM_LIVE_KNIGHT = 27928,
SPELL_INFORM_LIVE_RIDER = 27935,
@@ -459,7 +458,7 @@ class boss_gothik : public CreatureScript
}
break;
case EVENT_BOLT:
- DoCastVictim(RAID_MODE(SPELL_SHADOW_BOLT, H_SPELL_SHADOW_BOLT));
+ DoCastVictim(SPELL_SHADOW_BOLT);
events.ScheduleEvent(EVENT_BOLT, 1000);
break;
case EVENT_HARVEST:
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp b/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp
index 5702987cc5a..9987802a165 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp
@@ -27,9 +27,7 @@ enum Spells
SPELL_WARN_NECROTIC_AURA = 59481,
SPELL_SUMMON_SPORE = 29234,
SPELL_DEATHBLOOM = 29865,
- H_SPELL_DEATHBLOOM = 55053,
- SPELL_INEVITABLE_DOOM = 29204,
- H_SPELL_INEVITABLE_DOOM = 55052
+ SPELL_INEVITABLE_DOOM = 29204
};
enum Texts
@@ -111,12 +109,12 @@ class boss_loatheb : public CreatureScript
events.ScheduleEvent(EVENT_NECROTIC_AURA_FADING, 14000);
break;
case EVENT_DEATHBLOOM:
- DoCastAOE(RAID_MODE(SPELL_DEATHBLOOM, H_SPELL_DEATHBLOOM));
+ DoCastAOE(SPELL_DEATHBLOOM);
events.ScheduleEvent(EVENT_DEATHBLOOM, 30000);
break;
case EVENT_INEVITABLE_DOOM:
_doomCounter++;
- DoCastAOE(RAID_MODE(SPELL_INEVITABLE_DOOM, H_SPELL_INEVITABLE_DOOM));
+ DoCastAOE(SPELL_INEVITABLE_DOOM);
events.ScheduleEvent(EVENT_INEVITABLE_DOOM, std::max(120000 - _doomCounter * 15000, 15000)); // needs to be confirmed
break;
case EVENT_SPORE:
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp b/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp
index 7f7adefc2fb..5b02b7a2009 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp
@@ -23,14 +23,10 @@
enum Spells
{
SPELL_WEB_WRAP = 28622,
- SPELL_WEB_SPRAY_10 = 29484,
- SPELL_WEB_SPRAY_25 = 54125,
- SPELL_POISON_SHOCK_10 = 28741,
- SPELL_POISON_SHOCK_25 = 54122,
- SPELL_NECROTIC_POISON_10 = 28776,
- SPELL_NECROTIC_POISON_25 = 54121,
- SPELL_FRENZY_10 = 54123,
- SPELL_FRENZY_25 = 54124,
+ SPELL_WEB_SPRAY = 29484,
+ SPELL_POISON_SHOCK = 28741,
+ SPELL_NECROTIC_POISON = 28776,
+ SPELL_FRENZY = 54123
};
enum Creatures
@@ -108,7 +104,7 @@ public:
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0, true, -SPELL_WEB_WRAP))
{
- target->RemoveAura(RAID_MODE(SPELL_WEB_SPRAY_10, SPELL_WEB_SPRAY_25));
+ target->RemoveAura(sSpellMgr->GetSpellIdForDifficulty(SPELL_WEB_SPRAY, me));
uint8 pos = rand32() % MAX_POS_WRAP;
target->GetMotionMaster()->MoveJump(PosWrap[pos].GetPositionX(), PosWrap[pos].GetPositionY(), PosWrap[pos].GetPositionZ(), 20, 20);
if (Creature* wrap = DoSummon(NPC_WEB_WRAP, PosWrap[pos], 0, TEMPSUMMON_CORPSE_DESPAWN))
@@ -118,19 +114,19 @@ public:
events.ScheduleEvent(EVENT_WRAP, 40000);
break;
case EVENT_SPRAY:
- DoCastAOE(RAID_MODE(SPELL_WEB_SPRAY_10, SPELL_WEB_SPRAY_25));
+ DoCastAOE(SPELL_WEB_SPRAY);
events.ScheduleEvent(EVENT_SPRAY, 40000);
break;
case EVENT_SHOCK:
- DoCastAOE(RAID_MODE(SPELL_POISON_SHOCK_10, SPELL_POISON_SHOCK_25));
+ DoCastAOE(SPELL_POISON_SHOCK);
events.ScheduleEvent(EVENT_SHOCK, urand(10000, 20000));
break;
case EVENT_POISON:
- DoCastVictim(RAID_MODE(SPELL_NECROTIC_POISON_10, SPELL_NECROTIC_POISON_25));
+ DoCastVictim(SPELL_NECROTIC_POISON);
events.ScheduleEvent(EVENT_POISON, urand(10000, 20000));
break;
case EVENT_FRENZY:
- DoCast(me, RAID_MODE(SPELL_FRENZY_10, SPELL_FRENZY_25), true);
+ DoCast(me, SPELL_FRENZY, true);
events.ScheduleEvent(EVENT_FRENZY, 600000);
break;
case EVENT_SUMMON:
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp b/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp
index a47b75ec234..3e8a54f7cec 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp
@@ -22,7 +22,6 @@
enum Spells
{
SPELL_HATEFUL_STRIKE = 41926,
- H_SPELL_HATEFUL_STRIKE = 59192,
SPELL_FRENZY = 28131,
SPELL_BERSERK = 26662,
SPELL_SLIME_BOLT = 32309
@@ -127,7 +126,7 @@ public:
if (!pMostHPTarget)
pMostHPTarget = me->GetVictim();
- DoCast(pMostHPTarget, RAID_MODE(SPELL_HATEFUL_STRIKE, H_SPELL_HATEFUL_STRIKE), true);
+ DoCast(pMostHPTarget, SPELL_HATEFUL_STRIKE, true);
events.ScheduleEvent(EVENT_HATEFUL, 1000);
break;
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp b/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp
index 6a3927d4aa0..ea345c0dee0 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp
@@ -140,7 +140,7 @@ class boss_sapphiron : public CreatureScript
IceBlockMap::iterator itr = _iceblocks.find(target->GetGUID());
if (itr != _iceblocks.end() && !itr->second)
{
- if (GameObject* iceblock = me->SummonGameObject(GO_ICEBLOCK, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, 0, 0, 0, 0, 25000))
+ if (GameObject* iceblock = me->SummonGameObject(GO_ICEBLOCK, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, 0, 0, 0, 0, 25))
itr->second = iceblock->GetGUID();
}
}
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp
index 34e21336547..0dfae16323b 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp
@@ -32,7 +32,6 @@ enum StalaggYells
enum StalagSpells
{
SPELL_POWERSURGE = 28134,
- H_SPELL_POWERSURGE = 54529,
SPELL_MAGNETIC_PULL = 28338,
SPELL_STALAGG_TESLA = 28097
};
@@ -48,7 +47,6 @@ enum FeugenYells
enum FeugenSpells
{
SPELL_STATICFIELD = 28135,
- H_SPELL_STATICFIELD = 54528,
SPELL_FEUGEN_TESLA = 28109
};
@@ -80,7 +78,6 @@ enum ThaddiusSpells
SPELL_POLARITY_SHIFT = 28089,
SPELL_BALL_LIGHTNING = 28299,
SPELL_CHAIN_LIGHTNING = 28167,
- H_SPELL_CHAIN_LIGHTNING = 54531,
SPELL_BERSERK = 27680,
SPELL_POSITIVE_CHARGE = 28062,
SPELL_POSITIVE_CHARGE_STACK = 29659,
@@ -258,7 +255,7 @@ public:
events.ScheduleEvent(EVENT_SHIFT, 30000);
return;
case EVENT_CHAIN:
- DoCastVictim(RAID_MODE(SPELL_CHAIN_LIGHTNING, H_SPELL_CHAIN_LIGHTNING));
+ DoCastVictim(SPELL_CHAIN_LIGHTNING);
events.ScheduleEvent(EVENT_CHAIN, urand(10000, 20000));
return;
case EVENT_BERSERK:
@@ -358,7 +355,7 @@ public:
if (powerSurgeTimer <= uiDiff)
{
- DoCast(me, RAID_MODE(SPELL_POWERSURGE, H_SPELL_POWERSURGE));
+ DoCast(me, SPELL_POWERSURGE);
powerSurgeTimer = urand(15000, 20000);
} else powerSurgeTimer -= uiDiff;
@@ -424,7 +421,7 @@ public:
if (staticFieldTimer <= uiDiff)
{
- DoCast(me, RAID_MODE(SPELL_STATICFIELD, H_SPELL_STATICFIELD));
+ DoCast(me, SPELL_STATICFIELD);
staticFieldTimer = 5000;
} else staticFieldTimer -= uiDiff;
diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp
index 83082b18d73..ae48dd7aa9a 100644
--- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp
+++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp
@@ -28,17 +28,14 @@
enum Spells
{
SPELL_BALL_LIGHTNING = 52780,
- H_SPELL_BALL_LIGHTNING = 59800,
SPELL_STATIC_OVERLOAD = 52658,
- H_SPELL_STATIC_OVERLOAD = 59795,
SPELL_DISPERSE = 52770,
SPELL_SUMMON_SPARK = 52746,
SPELL_SPARK_DESPAWN = 52776,
- //Spark of Ionar
- SPELL_SPARK_VISUAL_TRIGGER = 52667,
- H_SPELL_SPARK_VISUAL_TRIGGER = 59833
+ // Spark of Ionar
+ SPELL_SPARK_VISUAL_TRIGGER = 52667
};
enum Yells
@@ -193,7 +190,7 @@ public:
{
lSparkList.Summon(summoned);
- summoned->CastSpell(summoned, DUNGEON_MODE(SPELL_SPARK_VISUAL_TRIGGER, H_SPELL_SPARK_VISUAL_TRIGGER), true);
+ summoned->CastSpell(summoned, SPELL_SPARK_VISUAL_TRIGGER, true);
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
{
diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp
index 576fc4492f1..98d7d629756 100644
--- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp
+++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp
@@ -45,11 +45,9 @@ enum Yells
enum Spells
{
SPELL_ARC_LIGHTNING = 52921,
- SPELL_LIGHTNING_NOVA_N = 52960,
- SPELL_LIGHTNING_NOVA_H = 59835,
+ SPELL_LIGHTNING_NOVA = 52960,
- SPELL_PULSING_SHOCKWAVE_N = 52961,
- SPELL_PULSING_SHOCKWAVE_H = 59836,
+ SPELL_PULSING_SHOCKWAVE = 52961,
SPELL_PULSING_SHOCKWAVE_AURA = 59414
};
@@ -134,7 +132,7 @@ public:
DoCast(me, SPELL_PULSING_SHOCKWAVE_AURA, true);
me->ClearUnitState(UNIT_STATE_CASTING); // this flag breaks movement
- DoCast(me, SPELL_PULSING_SHOCKWAVE_N, true);
+ DoCast(me, SPELL_PULSING_SHOCKWAVE, true);
m_uiResumePulsingShockwave_Timer = 0;
}
else
@@ -155,9 +153,9 @@ public:
{
Talk(SAY_NOVA);
Talk(EMOTE_NOVA);
- DoCast(me, SPELL_LIGHTNING_NOVA_N);
+ DoCast(me, SPELL_LIGHTNING_NOVA);
- me->RemoveAurasDueToSpell(DUNGEON_MODE<uint32>(SPELL_PULSING_SHOCKWAVE_N, SPELL_PULSING_SHOCKWAVE_H));
+ me->RemoveAurasDueToSpell(sSpellMgr->GetSpellIdForDifficulty(SPELL_PULSING_SHOCKWAVE, me));
m_uiResumePulsingShockwave_Timer = DUNGEON_MODE(5000, 4000); // Pause Pulsing Shockwave aura
m_uiLightningNova_Timer = urand(20000, 21000);
}
diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp
index b424ce01b06..31805d3404f 100644
--- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp
+++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp
@@ -39,10 +39,8 @@ enum Enums
EMOTE_TO_ANVIL = 5,
EMOTE_SHATTER = 6,
- SPELL_HEAT_N = 52387,
- SPELL_HEAT_H = 59528,
- SPELL_SHATTERING_STOMP_N = 52237,
- SPELL_SHATTERING_STOMP_H = 59529,
+ SPELL_HEAT = 52387,
+ SPELL_SHATTERING_STOMP = 52237,
SPELL_TEMPER = 52238,
SPELL_TEMPER_DUMMY = 52654,
@@ -51,10 +49,8 @@ enum Enums
// Molten Golem
SPELL_BLAST_WAVE = 23113,
- SPELL_IMMOLATION_STRIKE_N = 52433,
- SPELL_IMMOLATION_STRIKE_H = 59530,
- SPELL_SHATTER_N = 52429,
- SPELL_SHATTER_H = 59527,
+ SPELL_IMMOLATION_STRIKE = 52433,
+ SPELL_SHATTER = 52429,
NPC_VOLKHAN_ANVIL = 28823,
NPC_MOLTEN_GOLEM = 28695,
@@ -184,7 +180,7 @@ public:
// Only shatter brittle golems
if (temp->IsAlive() && temp->GetEntry() == NPC_BRITTLE_GOLEM)
{
- temp->CastSpell(temp, DUNGEON_MODE(SPELL_SHATTER_N, SPELL_SHATTER_H), false);
+ temp->CastSpell(temp, SPELL_SHATTER, false);
GolemsShattered += 1;
}
}
@@ -201,7 +197,7 @@ public:
summoned->GetMotionMaster()->MoveFollow(target, 0.0f, 0.0f);
// Why healing when just summoned?
- summoned->CastSpell(summoned, DUNGEON_MODE(SPELL_HEAT_N, SPELL_HEAT_H), false, NULL, NULL, me->GetGUID());
+ summoned->CastSpell(summoned, SPELL_HEAT, false, NULL, NULL, me->GetGUID());
}
}
@@ -253,7 +249,7 @@ public:
// Should he stomp even if he has no brittle golem to shatter?
Talk(SAY_STOMP);
- DoCast(me, SPELL_SHATTERING_STOMP_N);
+ DoCast(me, SPELL_SHATTERING_STOMP);
Talk(EMOTE_SHATTER);
@@ -418,7 +414,7 @@ public:
void SpellHit(Unit* /*pCaster*/, const SpellInfo* pSpell) override
{
// This is the dummy effect of the spells
- if (pSpell->Id == SPELL_SHATTER_N || pSpell->Id == SPELL_SHATTER_H)
+ if (pSpell->Id == sSpellMgr->GetSpellIdForDifficulty(SPELL_SHATTER, me))
if (me->GetEntry() == NPC_BRITTLE_GOLEM)
me->DespawnOrUnsummon();
}
@@ -439,7 +435,7 @@ public:
if (m_uiImmolation_Timer <= uiDiff)
{
- DoCastVictim(SPELL_IMMOLATION_STRIKE_N);
+ DoCastVictim(SPELL_IMMOLATION_STRIKE);
m_uiImmolation_Timer = 5000;
}
else
diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp
index 683eb97a4f7..4ff0bd1e5cb 100644
--- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp
+++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp
@@ -102,15 +102,12 @@ enum Spells
// Kadrak
SPELL_GLARE_OF_THE_TRIBUNAL = 50988,
- H_SPELL_GLARE_OF_THE_TRIBUNAL = 59868,
// Marnak
SPELL_DARK_MATTER = 51012,
- H_SPELL_DARK_MATTER = 59868,
// Abedneum
SPELL_SEARING_GAZE = 51136,
- H_SPELL_SEARING_GAZE = 59867,
SPELL_REWARD_ACHIEVEMENT = 59046,
};
@@ -214,7 +211,7 @@ public:
if (Creature* pKaddrak = ObjectAccessor::GetCreature(*me, *itr))
{
if (pKaddrak->IsAlive())
- pKaddrak->CastSpell(target, DUNGEON_MODE(SPELL_GLARE_OF_THE_TRIBUNAL, H_SPELL_GLARE_OF_THE_TRIBUNAL), true);
+ pKaddrak->CastSpell(target, SPELL_GLARE_OF_THE_TRIBUNAL, true);
}
}
uiKaddrakEncounterTimer = 1500;
@@ -230,7 +227,7 @@ public:
{
summon->SetDisplayId(11686);
summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- summon->CastSpell(target, DUNGEON_MODE(SPELL_DARK_MATTER, H_SPELL_DARK_MATTER), true);
+ summon->CastSpell(target, SPELL_DARK_MATTER, true);
}
}
uiMarnakEncounterTimer = urand(30000, 31000);
@@ -246,7 +243,7 @@ public:
{
summon->SetDisplayId(11686);
summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- summon->CastSpell(target, DUNGEON_MODE(SPELL_SEARING_GAZE, H_SPELL_SEARING_GAZE), true);
+ summon->CastSpell(target, SPELL_SEARING_GAZE, true);
}
}
uiAbedneumEncounterTimer = urand(30000, 31000);
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp
index 9a08f01c279..60698aac95e 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp
@@ -54,8 +54,7 @@ enum AssemblySpells
SPELL_CHAIN_LIGHTNING = 61879,
SPELL_OVERLOAD = 61869,
SPELL_LIGHTNING_WHIRL = 61915,
- SPELL_LIGHTNING_TENDRILS_10M = 61887,
- SPELL_LIGHTNING_TENDRILS_25M = 63486,
+ SPELL_LIGHTNING_TENDRILS = 61887,
SPELL_LIGHTNING_TENDRILS_VISUAL = 61883,
SPELL_STORMSHIELD = 64187
};
@@ -561,8 +560,8 @@ class boss_stormcaller_brundir : public CreatureScript
break;
case EVENT_LIGHTNING_TENDRILS:
Talk(SAY_BRUNDIR_FLIGHT);
- DoCast(RAID_MODE(SPELL_LIGHTNING_TENDRILS_10M, SPELL_LIGHTNING_TENDRILS_25M));
- DoCast(SPELL_LIGHTNING_TENDRILS_VISUAL);
+ DoCast(me, SPELL_LIGHTNING_TENDRILS);
+ DoCast(me, SPELL_LIGHTNING_TENDRILS_VISUAL);
me->AttackStop();
//me->SetLevitate(true);
me->GetMotionMaster()->Initialize();
@@ -592,7 +591,7 @@ class boss_stormcaller_brundir : public CreatureScript
break;
case EVENT_GROUND:
//me->SetLevitate(false);
- me->RemoveAurasDueToSpell(RAID_MODE(SPELL_LIGHTNING_TENDRILS_10M, SPELL_LIGHTNING_TENDRILS_25M));
+ me->RemoveAurasDueToSpell(sSpellMgr->GetSpellIdForDifficulty(SPELL_LIGHTNING_TENDRILS, me));
me->RemoveAurasDueToSpell(SPELL_LIGHTNING_TENDRILS_VISUAL);
DoStartMovement(me->GetVictim());
events.CancelEvent(EVENT_GROUND);
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp
index 7f4d585b0a4..a3d80beb546 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp
@@ -324,6 +324,12 @@ class boss_hodir : public CreatureScript
void Reset() override
{
+ gettingColdInHereTimer = 0;
+ gettingColdInHere = false;
+ cheeseTheFreeze = false;
+ iHaveTheCoolestFriends = false;
+ iCouldSayThatThisCacheWasRare = false;
+
_Reset();
me->SetReactState(REACT_PASSIVE);
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
index 69240866742..3a137a8658e 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
@@ -172,7 +172,7 @@ enum Spells
SPELL_MAGNETIC_CORE = 64436,
SPELL_MAGNETIC_CORE_VISUAL = 64438,
SPELL_HALF_HEAL = 64188,
- SPELL_CLEAR_ALL_DEBUFFS = 34098, // TODO: make use of this spell...
+ SPELL_CLEAR_ALL_DEBUFFS = 34098, /// @todo: make use of this spell...
SPELL_FREEZE_ANIM_STUN = 63354, // used to prevent mkii from doing stuff?..
SPELL_FREEZE_ANIM = 16245 // Idle aura. Freezes animation.
};
@@ -303,17 +303,21 @@ enum Actions
enum Phases
{
- // Leviathan MK II
- PHASE_LEVIATHAN_SOLO = 1,
- PHASE_LEVIATHAN_ASSEMBLED,
-
- // VX-001
- PHASE_VX001_SOLO,
- PHASE_VX001_ASSEMBLED,
+ PHASE_LEVIATHAN_MK_II = 1,
+ PHASE_VX_001,
+ PHASE_AERIAL_COMMAND_UNIT,
+ PHASE_VOL7RON
+};
- // Aerial Command Unit
- PHASE_AERIAL_SOLO,
- PHASE_AERIAL_ASSEMBLED
+enum Waypoints
+{
+ WP_MKII_P1_IDLE = 1,
+ WP_MKII_P4_POS_1,
+ WP_MKII_P4_POS_2,
+ WP_MKII_P4_POS_3,
+ WP_MKII_P4_POS_4,
+ WP_MKII_P4_POS_5,
+ WP_AERIAL_P4_POS
};
uint32 const RepairSpells[4] =
@@ -324,7 +328,1321 @@ uint32 const RepairSpells[4] =
SPELL_SEAT_5
};
-// 63801 Bomb Bot
+Position const VehicleRelocation[] =
+{
+ { 0.0f, 0.0f, 0.0f},
+ { 2792.070f, 2596.320f, 364.3136f }, // WP_MKII_P1_IDLE
+ { 2765.945f, 2571.095f, 364.0636f }, // WP_MKII_P4_POS_1
+ { 2768.195f, 2573.095f, 364.0636f }, // WP_MKII_P4_POS_2
+ { 2763.820f, 2568.870f, 364.3136f }, // WP_MKII_P4_POS_3
+ { 2761.215f, 2568.875f, 364.0636f }, // WP_MKII_P4_POS_4
+ { 2744.610f, 2569.380f, 364.3136f }, // WP_MKII_P4_POS_5
+ { 2748.513f, 2569.051f, 364.3136f } // WP_AERIAL_P4_POS
+};
+
+Position const VX001SummonPos = { 2744.431f, 2569.385f, 364.3968f, 3.141593f };
+Position const ACUSummonPos = { 2744.650f, 2569.460f, 380.0000f, 0.0f };
+
+static bool IsEncounterFinished(Unit* who)
+{
+ InstanceScript* instance = who->GetInstanceScript();
+
+ Creature* mkii = ObjectAccessor::GetCreature(*who, instance->GetData64(DATA_LEVIATHAN_MK_II));
+ Creature* vx001 = ObjectAccessor::GetCreature(*who, instance->GetData64(DATA_VX_001));
+ Creature* aerial = ObjectAccessor::GetCreature(*who, instance->GetData64(DATA_AERIAL_COMMAND_UNIT));
+ if (!mkii || !vx001 || !aerial)
+ return false;
+
+ if (mkii->getStandState() == UNIT_STAND_STATE_DEAD &&
+ vx001->getStandState() == UNIT_STAND_STATE_DEAD &&
+ aerial->getStandState() == UNIT_STAND_STATE_DEAD)
+ {
+ who->Kill(mkii);
+ who->Kill(vx001);
+ who->Kill(aerial);
+ mkii->DespawnOrUnsummon(120000);
+ vx001->DespawnOrUnsummon(120000);
+ aerial->DespawnOrUnsummon(120000);
+ if (Creature* mimiron = ObjectAccessor::GetCreature(*who, instance->GetData64(BOSS_MIMIRON)))
+ mimiron->AI()->JustDied(who);
+ return true;
+ }
+ return false;
+}
+
+class boss_mimiron : public CreatureScript
+{
+ public:
+ boss_mimiron() : CreatureScript("boss_mimiron") { }
+
+ struct boss_mimironAI : public BossAI
+ {
+ boss_mimironAI(Creature* creature) : BossAI(creature, BOSS_MIMIRON)
+ {
+ me->SetReactState(REACT_PASSIVE);
+ _fireFighter = false;
+ }
+
+ void DoAction(int32 action) override
+ {
+ switch (action)
+ {
+ case DO_ACTIVATE_VX001:
+ events.ScheduleEvent(EVENT_VX001_ACTIVATION_1, 1000);
+ break;
+ case DO_ACTIVATE_AERIAL:
+ events.ScheduleEvent(EVENT_AERIAL_ACTIVATION_1, 5000);
+ break;
+ case DO_ACTIVATE_V0L7R0N_1:
+ Talk(SAY_AERIAL_DEATH);
+ if (Creature* mkii = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_LEVIATHAN_MK_II)))
+ mkii->GetMotionMaster()->MovePoint(WP_MKII_P4_POS_1, VehicleRelocation[WP_MKII_P4_POS_1]);
+ break;
+ case DO_ACTIVATE_V0L7R0N_2:
+ events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_1, 1000);
+ break;
+ case DO_ACTIVATE_HARD_MODE:
+ _fireFighter = true;
+ DoZoneInCombat(me);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void EnterCombat(Unit* /*who*/) override
+ {
+ if (!me->GetVehicleBase())
+ return;
+
+ _EnterCombat();
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ me->RemoveAurasDueToSpell(SPELL_WELD);
+ DoCast(me->GetVehicleBase(), SPELL_SEAT_6);
+
+ if (GameObject* button = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_MIMIRON_BUTTON)))
+ button->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
+
+ if (_fireFighter)
+ events.ScheduleEvent(EVENT_SUMMON_FLAMES, 3000);
+ events.ScheduleEvent(EVENT_INTRO_1, 1500);
+ }
+
+ void JustDied(Unit* /*who*/) override
+ {
+ instance->SetBossState(BOSS_MIMIRON, DONE);
+ events.Reset();
+ me->CombatStop(true);
+ me->SetDisableGravity(false);
+ DoCast(me, SPELL_SLEEP_VISUAL_1);
+ DoCastAOE(SPELL_DESPAWN_ASSAULT_BOTS);
+ me->ExitVehicle();
+ // ExitVehicle() offset position is not implemented, so we make up for that with MoveJump()...
+ me->GetMotionMaster()->MoveJump(me->GetPositionX() + (10.f * std::cos(me->GetOrientation())), me->GetPositionY() + (10.f * std::sin(me->GetOrientation())), me->GetPositionZ(), 10.f, 5.f);
+ events.ScheduleEvent(EVENT_OUTTRO_1, 7000);
+ }
+
+ void Reset() override
+ {
+ if (instance->GetBossState(BOSS_MIMIRON) == DONE) // Mimiron will attempt to reset because he is not dead and will be set to friendly before despawning.
+ return;
+
+ _Reset();
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+
+ if (GameObject* elevator = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_MIMIRON_ELEVATOR)))
+ elevator->SetGoState(GO_STATE_ACTIVE);
+
+ if (_fireFighter)
+ if (Creature* computer = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_COMPUTER)))
+ computer->AI()->DoAction(DO_DEACTIVATE_COMPUTER);
+
+ if (GameObject* button = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_MIMIRON_BUTTON)))
+ {
+ button->SetGoState(GO_STATE_READY);
+ button->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
+ }
+
+ _fireFighter = false;
+ DoCast(me, SPELL_WELD);
+
+ if (Unit* mkii = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_LEVIATHAN_MK_II)))
+ DoCast(mkii, SPELL_SEAT_3);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if ((!UpdateVictim() || !CheckInRoom()) && instance->GetBossState(BOSS_MIMIRON) != DONE)
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_SUMMON_FLAMES:
+ if (Unit* worldtrigger = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_MIMIRON_WORLD_TRIGGER)))
+ worldtrigger->CastCustomSpell(SPELL_SCRIPT_EFFECT_SUMMON_FLAMES_INITIAL, SPELLVALUE_MAX_TARGETS, 3, NULL, true, NULL, NULL, me->GetGUID());
+ events.RescheduleEvent(EVENT_SUMMON_FLAMES, 28000);
+ break;
+ case EVENT_INTRO_1:
+ Talk(_fireFighter ? SAY_HARDMODE_ON : SAY_MKII_ACTIVATE);
+ events.ScheduleEvent(EVENT_INTRO_2, 5000);
+ break;
+ case EVENT_INTRO_2:
+ if (Unit* mkii = me->GetVehicleBase())
+ {
+ DoCast(mkii, SPELL_SEAT_7);
+ mkii->RemoveAurasDueToSpell(SPELL_FREEZE_ANIM);
+ mkii->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
+ }
+ events.ScheduleEvent(EVENT_INTRO_3, 2000);
+ break;
+ case EVENT_INTRO_3:
+ if (Creature* mkii = me->GetVehicleCreatureBase())
+ mkii->AI()->DoAction(_fireFighter ? DO_HARDMODE_MKII : DO_START_MKII);
+ break;
+ case EVENT_VX001_ACTIVATION_1:
+ if (Unit* mkii = me->GetVehicleBase())
+ mkii->SetFacingTo(3.686f); // fix magic number
+ events.ScheduleEvent(EVENT_VX001_ACTIVATION_2, 1000);
+ break;
+ case EVENT_VX001_ACTIVATION_2:
+ if (Unit* mkii = me->GetVehicleBase())
+ DoCast(mkii, SPELL_SEAT_6);
+ events.ScheduleEvent(EVENT_VX001_ACTIVATION_3, 1000);
+ break;
+ case EVENT_VX001_ACTIVATION_3:
+ Talk(SAY_MKII_DEATH);
+ events.ScheduleEvent(EVENT_VX001_ACTIVATION_4, 5000);
+ break;
+ case EVENT_VX001_ACTIVATION_4:
+ if (GameObject* elevator = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_MIMIRON_ELEVATOR)))
+ elevator->SetGoState(GO_STATE_READY);
+ if (Unit* worldtrigger = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_MIMIRON_WORLD_TRIGGER)))
+ worldtrigger->CastSpell(worldtrigger, SPELL_ELEVATOR_KNOCKBACK);
+ events.ScheduleEvent(EVENT_VX001_ACTIVATION_5, 6000);
+ break;
+ case EVENT_VX001_ACTIVATION_5:
+ if (GameObject* elevator = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_MIMIRON_ELEVATOR)))
+ elevator->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE);
+ if (Creature* vx001 = me->SummonCreature(NPC_VX_001, VX001SummonPos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 120000))
+ vx001->CastSpell(vx001, SPELL_FREEZE_ANIM);
+ events.ScheduleEvent(EVENT_VX001_ACTIVATION_6, 19000);
+ break;
+ case EVENT_VX001_ACTIVATION_6:
+ if (Unit* vx001 = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_VX_001)))
+ DoCast(vx001, SPELL_SEAT_1);
+ events.ScheduleEvent(EVENT_VX001_ACTIVATION_7, 3500);
+ break;
+ case EVENT_VX001_ACTIVATION_7:
+ Talk(SAY_VX001_ACTIVATE);
+ events.ScheduleEvent(EVENT_VX001_ACTIVATION_8, 4000);
+ break;
+ case EVENT_VX001_ACTIVATION_8:
+ if (Unit* vx001 = me->GetVehicleBase())
+ DoCast(vx001, SPELL_SEAT_2);
+ events.ScheduleEvent(EVENT_VX001_ACTIVATION_9, 3000);
+ break;
+ case EVENT_VX001_ACTIVATION_9:
+ if (Creature* vx001 = me->GetVehicleCreatureBase())
+ vx001->AI()->DoAction(_fireFighter ? DO_HARDMODE_VX001 : DO_START_VX001);
+ break;
+ case EVENT_AERIAL_ACTIVATION_1:
+ if (Unit* mkii = me->GetVehicleBase())
+ DoCast(mkii, SPELL_SEAT_5);
+ events.ScheduleEvent(EVENT_AERIAL_ACTIVATION_2, 2500);
+ break;
+ case EVENT_AERIAL_ACTIVATION_2:
+ Talk(SAY_VX001_DEATH);
+ events.ScheduleEvent(EVENT_AERIAL_ACTIVATION_3, 5000);
+ break;
+ case EVENT_AERIAL_ACTIVATION_3:
+ me->SummonCreature(NPC_AERIAL_COMMAND_UNIT, ACUSummonPos, TEMPSUMMON_MANUAL_DESPAWN);
+ events.ScheduleEvent(EVENT_AERIAL_ACTIVATION_4, 5000);
+ break;
+ case EVENT_AERIAL_ACTIVATION_4:
+ if (Unit* aerial = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_AERIAL_COMMAND_UNIT)))
+ me->CastSpell(aerial, SPELL_SEAT_1);
+ events.ScheduleEvent(EVENT_AERIAL_ACTIVATION_5, 2000);
+ break;
+ case EVENT_AERIAL_ACTIVATION_5:
+ Talk(SAY_AERIAL_ACTIVATE);
+ events.ScheduleEvent(EVENT_AERIAL_ACTIVATION_6, 8000);
+ break;
+ case EVENT_AERIAL_ACTIVATION_6:
+ if (Creature* acu = me->GetVehicleCreatureBase())
+ acu->AI()->DoAction(_fireFighter? DO_HARDMODE_AERIAL : DO_START_AERIAL);
+ break;
+ case EVENT_VOL7RON_ACTIVATION_1:
+ if (Creature* mkii = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_LEVIATHAN_MK_II)))
+ mkii->SetFacingTo(float(M_PI));
+ events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_2, 1000);
+ break;
+ case EVENT_VOL7RON_ACTIVATION_2:
+ if (Creature* mkii = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_LEVIATHAN_MK_II)))
+ {
+ if (Creature* vx001 = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_VX_001)))
+ {
+ vx001->RemoveAurasDueToSpell(SPELL_TORSO_DISABLED);
+ vx001->CastSpell(mkii, SPELL_MOUNT_MKII);
+ }
+ }
+ events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_3, 4500);
+ break;
+ case EVENT_VOL7RON_ACTIVATION_3:
+ if (Creature* mkii = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_LEVIATHAN_MK_II)))
+ mkii->GetMotionMaster()->MovePoint(WP_MKII_P4_POS_4, VehicleRelocation[WP_MKII_P4_POS_4]);
+ events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_4, 5000);
+ break;
+ case EVENT_VOL7RON_ACTIVATION_4:
+ if (Creature* vx001 = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_VX_001)))
+ {
+ if (Creature* aerial = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_AERIAL_COMMAND_UNIT)))
+ {
+ aerial->GetMotionMaster()->MoveLand(0, (aerial->GetPositionX(), aerial->GetPositionY(), aerial->GetPositionZMinusOffset()));
+ aerial->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
+ aerial->CastSpell(vx001, SPELL_MOUNT_VX_001);
+ aerial->CastSpell(aerial, SPELL_HALF_HEAL);
+ }
+ }
+ events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_5, 4000);
+ break;
+ case EVENT_VOL7RON_ACTIVATION_5:
+ Talk(SAY_V07TRON_ACTIVATE);
+ events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_6, 3000);
+ break;
+ case EVENT_VOL7RON_ACTIVATION_6:
+ if (Creature* vx001 = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_VX_001)))
+ DoCast(vx001, SPELL_SEAT_2);
+ events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_7, 5000);
+ break;
+ case EVENT_VOL7RON_ACTIVATION_7:
+ for (uint8 data = DATA_LEVIATHAN_MK_II; data <= DATA_AERIAL_COMMAND_UNIT; ++data)
+ if (Creature* mimironVehicle = ObjectAccessor::GetCreature(*me, instance->GetData64(data)))
+ mimironVehicle->AI()->DoAction(DO_ASSEMBLED_COMBAT);
+ break;
+ case EVENT_OUTTRO_1:
+ me->RemoveAurasDueToSpell(SPELL_SLEEP_VISUAL_1);
+ DoCast(me, SPELL_SLEEP_VISUAL_2);
+ me->setFaction(35);
+ events.ScheduleEvent(EVENT_OUTTRO_2, 3000);
+ break;
+ case EVENT_OUTTRO_2:
+ Talk(SAY_V07TRON_DEATH);
+ if (_fireFighter)
+ {
+ if (Creature* computer = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_COMPUTER)))
+ computer->AI()->DoAction(DO_DEACTIVATE_COMPUTER);
+ me->SummonGameObject(RAID_MODE(GO_CACHE_OF_INNOVATION_FIREFIGHTER, GO_CACHE_OF_INNOVATION_FIREFIGHTER_HERO), 2744.040f, 2569.352f, 364.3135f, 3.124123f, 0.f, 0.f, 0.9999619f, 0.008734641f, 604800);
+ }
+ else
+ me->SummonGameObject(RAID_MODE(GO_CACHE_OF_INNOVATION, GO_CACHE_OF_INNOVATION_HERO), 2744.040f, 2569.352f, 364.3135f, 3.124123f, 0.f, 0.f, 0.9999619f, 0.008734641f, 604800);
+ events.ScheduleEvent(EVENT_OUTTRO_3, 11000);
+ break;
+ case EVENT_OUTTRO_3:
+ DoCast(me, SPELL_TELEPORT_VISUAL);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ me->DespawnOrUnsummon(1000); // sniffs say 6 sec after, but it doesnt matter.
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private:
+ bool _fireFighter;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetUlduarAI<boss_mimironAI>(creature);
+ }
+};
+
+class boss_leviathan_mk_ii : public CreatureScript
+{
+ public:
+ boss_leviathan_mk_ii() : CreatureScript("boss_leviathan_mk_ii") { }
+
+ struct boss_leviathan_mk_iiAI : public BossAI
+ {
+ boss_leviathan_mk_iiAI(Creature* creature) : BossAI(creature, BOSS_MIMIRON)
+ {
+ _fireFighter = false;
+ _setupMine = true;
+ _setupBomb = true;
+ _setupRocket = true;
+ }
+
+ void DamageTaken(Unit* who, uint32 &damage) override
+ {
+ if (damage >= me->GetHealth())
+ {
+ damage = me->GetHealth() - 1; // Let creature fall to 1 hp, but do not let it die or damage itself with SetHealth().
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ DoCast(me, SPELL_VEHICLE_DAMAGED, true);
+ me->AttackStop();
+ me->SetReactState(REACT_PASSIVE);
+ me->RemoveAllAurasExceptType(SPELL_AURA_CONTROL_VEHICLE, SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT);
+
+ if (events.IsInPhase(PHASE_LEVIATHAN_MK_II))
+ {
+ me->CastStop();
+ if (Unit* turret = me->GetVehicleKit()->GetPassenger(3))
+ turret->Kill(turret);
+
+ me->SetSpeed(MOVE_RUN, 1.5f, true);
+ me->GetMotionMaster()->MovePoint(WP_MKII_P1_IDLE, VehicleRelocation[WP_MKII_P1_IDLE]);
+ }
+ else if (events.IsInPhase(PHASE_VOL7RON))
+ {
+ me->SetStandState(UNIT_STAND_STATE_DEAD);
+
+ if (IsEncounterFinished(who))
+ return;
+
+ me->CastStop();
+ DoCast(me, SPELL_SELF_REPAIR);
+ }
+ events.Reset();
+ }
+ }
+
+ void DoAction(int32 action) override
+ {
+ switch (action)
+ {
+ case DO_HARDMODE_MKII:
+ _fireFighter = true;
+ DoCast(me, SPELL_EMERGENCY_MODE);
+ DoCastAOE(SPELL_EMERGENCY_MODE_TURRET);
+ events.ScheduleEvent(EVENT_FLAME_SUPPRESSANT_MK, 60000, 0, PHASE_LEVIATHAN_MK_II);
+ // Missing break intended.
+ case DO_START_MKII:
+ me->SetReactState(REACT_AGGRESSIVE);
+ events.SetPhase(PHASE_LEVIATHAN_MK_II);
+
+ events.ScheduleEvent(EVENT_NAPALM_SHELL, 3000, 0, PHASE_LEVIATHAN_MK_II);
+ events.ScheduleEvent(EVENT_PLASMA_BLAST, 15000, 0, PHASE_LEVIATHAN_MK_II);
+ events.ScheduleEvent(EVENT_PROXIMITY_MINE, 5000);
+ events.ScheduleEvent(EVENT_SHOCK_BLAST, 18000);
+ break;
+ case DO_ASSEMBLED_COMBAT:
+ me->SetStandState(UNIT_STAND_STATE_STAND);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
+ me->SetReactState(REACT_AGGRESSIVE);
+
+ events.SetPhase(PHASE_VOL7RON);
+ events.ScheduleEvent(EVENT_PROXIMITY_MINE, 15000);
+ events.ScheduleEvent(EVENT_SHOCK_BLAST, 45000);
+ break;
+ default:
+ break;
+ }
+ }
+
+ uint32 GetData(uint32 type) const override
+ {
+ switch (type)
+ {
+ case DATA_SETUP_MINE:
+ return _setupMine;
+ case DATA_SETUP_BOMB:
+ return _setupBomb;
+ case DATA_SETUP_ROCKET:
+ return _setupRocket;
+ case DATA_FIREFIGHTER:
+ return _fireFighter;
+ default:
+ return 0;
+ }
+ }
+
+ void JustSummoned(Creature* summon) override
+ {
+ summons.Summon(summon);
+ }
+
+ void KilledUnit(Unit* victim) override
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON)))
+ mimiron->AI()->Talk(events.IsInPhase(PHASE_LEVIATHAN_MK_II) ? SAY_MKII_SLAY : SAY_V07TRON_SLAY);
+ }
+
+ void MovementInform(uint32 type, uint32 point) override
+ {
+ if (type != POINT_MOTION_TYPE)
+ return;
+
+ switch (point)
+ {
+ case WP_MKII_P1_IDLE:
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ DoCast(me, SPELL_HALF_HEAL);
+
+ if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON)))
+ mimiron->AI()->DoAction(DO_ACTIVATE_VX001);
+ break;
+ case WP_MKII_P4_POS_1:
+ events.ScheduleEvent(EVENT_MOVE_POINT_2, 1);
+ break;
+ case WP_MKII_P4_POS_2:
+ events.ScheduleEvent(EVENT_MOVE_POINT_3, 1);
+ break;
+ case WP_MKII_P4_POS_3:
+ if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON)))
+ mimiron->AI()->DoAction(DO_ACTIVATE_V0L7R0N_2);
+ break;
+ case WP_MKII_P4_POS_4:
+ events.ScheduleEvent(EVENT_MOVE_POINT_5, 1);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void Reset() override
+ {
+ _Reset();
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
+ me->SetReactState(REACT_PASSIVE);
+ _fireFighter = false;
+ _setupMine = true;
+ _setupBomb = true;
+ _setupRocket = true;
+ DoCast(me, SPELL_FREEZE_ANIM);
+ }
+
+ void SetData(uint32 id, uint32 data) override
+ {
+ switch (id)
+ {
+ case DATA_SETUP_MINE:
+ _setupMine = data != 0;
+ break;
+ case DATA_SETUP_BOMB:
+ _setupBomb = data != 0;
+ break;
+ case DATA_SETUP_ROCKET:
+ _setupRocket = data != 0;
+ break;
+ default:
+ break;
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim() || !CheckInRoom())
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_PROXIMITY_MINE:
+ DoCastAOE(SPELL_PROXIMITY_MINES);
+ events.RescheduleEvent(EVENT_PROXIMITY_MINE, 35000);
+ break;
+ case EVENT_PLASMA_BLAST:
+ DoCastVictim(SPELL_SCRIPT_EFFECT_PLASMA_BLAST);
+ events.RescheduleEvent(EVENT_PLASMA_BLAST, urand(30000, 45000), 0, PHASE_LEVIATHAN_MK_II);
+
+ if (events.GetTimeUntilEvent(EVENT_NAPALM_SHELL) < 9000)
+ events.RescheduleEvent(EVENT_NAPALM_SHELL, 9000, 0, PHASE_LEVIATHAN_MK_II); // The actual spell is cast by the turret, we should not let it interrupt itself.
+ break;
+ case EVENT_SHOCK_BLAST:
+ DoCastAOE(SPELL_SHOCK_BLAST);
+ events.RescheduleEvent(EVENT_SHOCK_BLAST, urand(34000, 36000));
+ break;
+ case EVENT_FLAME_SUPPRESSANT_MK:
+ DoCastAOE(SPELL_FLAME_SUPPRESSANT_MK);
+ events.RescheduleEvent(EVENT_FLAME_SUPPRESSANT_MK, 60000, 0, PHASE_LEVIATHAN_MK_II);
+ break;
+ case EVENT_NAPALM_SHELL:
+ DoCastAOE(SPELL_FORCE_CAST_NAPALM_SHELL);
+ events.RescheduleEvent(EVENT_NAPALM_SHELL, urand(6000, 15000), 0, PHASE_LEVIATHAN_MK_II);
+
+ if (events.GetTimeUntilEvent(EVENT_PLASMA_BLAST) < 2000)
+ events.RescheduleEvent(EVENT_PLASMA_BLAST, 2000, 0, PHASE_LEVIATHAN_MK_II); // The actual spell is cast by the turret, we should not let it interrupt itself.
+ break;
+ case EVENT_MOVE_POINT_2:
+ me->GetMotionMaster()->MovePoint(WP_MKII_P4_POS_2, VehicleRelocation[WP_MKII_P4_POS_2]);
+ break;
+ case EVENT_MOVE_POINT_3:
+ me->GetMotionMaster()->MovePoint(WP_MKII_P4_POS_3, VehicleRelocation[WP_MKII_P4_POS_3]);
+ break;
+ case EVENT_MOVE_POINT_5:
+ me->GetMotionMaster()->MovePoint(WP_MKII_P4_POS_5, VehicleRelocation[WP_MKII_P4_POS_5]);
+ break;
+ default:
+ break;
+ }
+ }
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ bool _fireFighter;
+ bool _setupMine;
+ bool _setupBomb;
+ bool _setupRocket;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetUlduarAI<boss_leviathan_mk_iiAI>(creature);
+ }
+};
+
+class boss_vx_001 : public CreatureScript
+{
+ public:
+ boss_vx_001() : CreatureScript("boss_vx_001") { }
+
+ struct boss_vx_001AI : public BossAI
+ {
+ boss_vx_001AI(Creature* creature) : BossAI(creature, BOSS_MIMIRON)
+ {
+ me->SetDisableGravity(true); // This is the unfold visual state of VX-001, it has to be set on create as it requires an objectupdate if set later.
+ me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_SPECIAL_UNARMED); // This is a hack to force the yet to be unfolded visual state.
+ me->SetReactState(REACT_PASSIVE);
+ _fireFighter = false;
+ }
+
+ void DamageTaken(Unit* who, uint32 &damage) override
+ {
+ if (damage >= me->GetHealth())
+ {
+ damage = me->GetHealth() - 1; // Let creature fall to 1 hp, but do not let it die or damage itself with SetHealth().
+ me->AttackStop();
+ DoCast(me, SPELL_VEHICLE_DAMAGED, true);
+ me->RemoveAllAurasExceptType(SPELL_AURA_CONTROL_VEHICLE, SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT);
+
+ if (events.IsInPhase(PHASE_VX_001))
+ {
+ me->CastStop();
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); // | UNIT_FLAG_NOT_SELECTABLE);
+ DoCast(me, SPELL_HALF_HEAL); // has no effect, wat
+ DoCast(me, SPELL_TORSO_DISABLED);
+ if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON)))
+ mimiron->AI()->DoAction(DO_ACTIVATE_AERIAL);
+ }
+ else if (events.IsInPhase(PHASE_VOL7RON))
+ {
+ me->SetStandState(UNIT_STAND_STATE_DEAD);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+
+ if (IsEncounterFinished(who))
+ return;
+
+ me->CastStop();
+ DoCast(me, SPELL_SELF_REPAIR);
+ }
+ events.Reset();
+ }
+ }
+
+ void DoAction(int32 action) override
+ {
+ switch (action)
+ {
+ case DO_HARDMODE_VX001:
+ _fireFighter = true;
+ DoCast(me, SPELL_EMERGENCY_MODE);
+ events.ScheduleEvent(EVENT_FROST_BOMB, 1000);
+ events.ScheduleEvent(EVENT_FLAME_SUPPRESSANT_VX, 6000);
+ // Missing break intended.
+ case DO_START_VX001:
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
+ me->RemoveAurasDueToSpell(SPELL_FREEZE_ANIM);
+ me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); // Remove emotestate.
+ //me->SetUInt32Value(UNIT_FIELD_BYTES_1, 33554432); Blizzard handles hover animation like this it seems.
+ DoCast(me, SPELL_HEAT_WAVE_AURA);
+
+ events.SetPhase(PHASE_VX_001);
+ events.ScheduleEvent(EVENT_ROCKET_STRIKE, 20000);
+ events.ScheduleEvent(EVENT_SPINNING_UP, urand(30000, 35000));
+ events.ScheduleEvent(EVENT_RAPID_BURST, 500, 0, PHASE_VX_001);
+ break;
+ case DO_ASSEMBLED_COMBAT:
+ me->SetStandState(UNIT_STAND_STATE_STAND);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
+
+ events.SetPhase(PHASE_VOL7RON);
+ events.ScheduleEvent(EVENT_ROCKET_STRIKE, 20000);
+ events.ScheduleEvent(EVENT_SPINNING_UP, urand(30000, 35000));
+ events.ScheduleEvent(EVENT_HAND_PULSE, 500, 0, PHASE_VOL7RON);
+ if (_fireFighter)
+ events.ScheduleEvent(EVENT_FROST_BOMB, 1000);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void EnterEvadeMode() override
+ {
+ summons.DespawnAll();
+ }
+
+ void JustSummoned(Creature* summon) override
+ {
+ summons.Summon(summon);
+ if (summon->GetEntry() == NPC_BURST_TARGET)
+ summon->CastSpell(me, SPELL_RAPID_BURST_TARGET_ME);
+ }
+
+ void KilledUnit(Unit* victim) override
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON)))
+ mimiron->AI()->Talk(events.IsInPhase(PHASE_VX_001) ? SAY_VX001_SLAY : SAY_V07TRON_SLAY);
+ }
+
+ void SpellHit(Unit* caster, SpellInfo const* /*spellProto*/) override
+ {
+ if (caster->GetEntry() == NPC_BURST_TARGET && !me->HasUnitState(UNIT_STATE_CASTING))
+ DoCast(caster, SPELL_RAPID_BURST);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ // Handle rotation during SPELL_SPINNING_UP, SPELL_P3WX2_LASER_BARRAGE, SPELL_RAPID_BURST, and SPELL_HAND_PULSE_LEFT/RIGHT
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ {
+ if (Creature* channelTarget = ObjectAccessor::GetCreature(*me, me->GetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT)))
+ me->SetFacingToObject(channelTarget);
+ return;
+ }
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_RAPID_BURST:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 120, true))
+ DoCast(target, SPELL_SUMMON_BURST_TARGET);
+ events.RescheduleEvent(EVENT_RAPID_BURST, 3000, 0, PHASE_VX_001);
+ break;
+ case EVENT_ROCKET_STRIKE:
+ DoCastAOE(events.IsInPhase(PHASE_VX_001) ? SPELL_ROCKET_STRIKE_LEFT : SPELL_ROCKET_STRIKE_BOTH);
+ events.ScheduleEvent(EVENT_RELOAD, 10000);
+ events.RescheduleEvent(EVENT_ROCKET_STRIKE, urand(20000, 25000));
+ break;
+ case EVENT_RELOAD:
+ for (uint8 seat = 6; seat <= 7; seat++)
+ if (Unit* rocket = me->GetVehicleKit()->GetPassenger(seat))
+ rocket->SetDisplayId(rocket->GetNativeDisplayId());
+ break;
+ case EVENT_HAND_PULSE:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 120, true))
+ DoCast(target, urand(0, 1) == 0 ? SPELL_HAND_PULSE_LEFT : SPELL_HAND_PULSE_RIGHT);
+ events.RescheduleEvent(EVENT_HAND_PULSE, urand(1500, 3000), 0, PHASE_VOL7RON);
+ break;
+ case EVENT_FROST_BOMB:
+ DoCastAOE(SPELL_SCRIPT_EFFECT_FROST_BOMB);
+ events.RescheduleEvent(EVENT_FROST_BOMB, 45000);
+ break;
+ case EVENT_SPINNING_UP:
+ DoCastAOE(SPELL_SPINNING_UP);
+ events.DelayEvents(14000);
+ events.RescheduleEvent(EVENT_SPINNING_UP, urand(55000, 65000));
+ break;
+ case EVENT_FLAME_SUPPRESSANT_VX:
+ DoCastAOE(SPELL_FLAME_SUPPRESSANT_VX);
+ events.RescheduleEvent(EVENT_FLAME_SUPPRESSANT_VX, urand(10000, 12000), 0, PHASE_VX_001);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private:
+ bool _fireFighter;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetUlduarAI<boss_vx_001AI>(creature);
+ }
+};
+
+class boss_aerial_command_unit : public CreatureScript
+{
+ public:
+ boss_aerial_command_unit() : CreatureScript("boss_aerial_command_unit") { }
+
+ struct boss_aerial_command_unitAI : public BossAI
+ {
+ boss_aerial_command_unitAI(Creature* creature) : BossAI(creature, BOSS_MIMIRON)
+ {
+ me->SetReactState(REACT_PASSIVE);
+ fireFigther = false;
+ }
+
+ void DamageTaken(Unit* who, uint32 &damage) override
+ {
+ if (damage >= me->GetHealth())
+ {
+ damage = me->GetHealth() - 1; // Let creature fall to 1 hp, but do not let it die or damage itself with SetHealth().
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ me->AttackStop();
+ me->SetReactState(REACT_PASSIVE);
+ DoCast(me, SPELL_VEHICLE_DAMAGED, true);
+ me->RemoveAllAurasExceptType(SPELL_AURA_CONTROL_VEHICLE, SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT);
+
+ if (events.IsInPhase(PHASE_AERIAL_COMMAND_UNIT))
+ {
+ me->GetMotionMaster()->Clear(true);
+ me->GetMotionMaster()->MovePoint(WP_AERIAL_P4_POS, VehicleRelocation[WP_AERIAL_P4_POS]);
+ }
+ else if (events.IsInPhase(PHASE_VOL7RON))
+ {
+ me->SetStandState(UNIT_STAND_STATE_DEAD);
+
+ if (IsEncounterFinished(who))
+ return;
+
+ me->CastStop();
+ DoCast(me, SPELL_SELF_REPAIR);
+ }
+ events.Reset();
+ }
+ }
+
+ void DoAction(int32 action) override
+ {
+ switch (action)
+ {
+ case DO_HARDMODE_AERIAL:
+ fireFigther = true;
+ DoCast(me, SPELL_EMERGENCY_MODE);
+ events.ScheduleEvent(EVENT_SUMMON_FIRE_BOTS, 1000, 0, PHASE_AERIAL_COMMAND_UNIT);
+ // Missing break intended.
+ case DO_START_AERIAL:
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
+ me->SetReactState(REACT_AGGRESSIVE);
+
+ events.SetPhase(PHASE_AERIAL_COMMAND_UNIT);
+ events.ScheduleEvent(EVENT_SUMMON_JUNK_BOT, 5000, 0, PHASE_AERIAL_COMMAND_UNIT);
+ events.ScheduleEvent(EVENT_SUMMON_ASSAULT_BOT, 9000, 0, PHASE_AERIAL_COMMAND_UNIT);
+ events.ScheduleEvent(EVENT_SUMMON_BOMB_BOT, 9000, 0, PHASE_AERIAL_COMMAND_UNIT);
+ break;
+ case DO_DISABLE_AERIAL:
+ me->CastStop();
+ me->AttackStop();
+ me->SetReactState(REACT_PASSIVE);
+ me->GetMotionMaster()->MoveFall();
+ events.DelayEvents(23000);
+ break;
+ case DO_ENABLE_AERIAL:
+ me->SetReactState(REACT_AGGRESSIVE);
+ break;
+ case DO_ASSEMBLED_COMBAT:
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
+ me->SetReactState(REACT_AGGRESSIVE);
+ me->SetStandState(UNIT_STAND_STATE_STAND);
+ events.SetPhase(PHASE_VOL7RON);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void EnterEvadeMode() override
+ {
+ summons.DespawnAll();
+ }
+
+ void JustSummoned(Creature* summon) override
+ {
+ if (fireFigther && (summon->GetEntry() == NPC_ASSAULT_BOT || summon->GetEntry() == NPC_JUNK_BOT))
+ summon->CastSpell(summon, SPELL_EMERGENCY_MODE);
+ BossAI::JustSummoned(summon);
+ }
+
+ void KilledUnit(Unit* victim) override
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON)))
+ mimiron->AI()->Talk(events.IsInPhase(PHASE_AERIAL_COMMAND_UNIT) ? SAY_AERIAL_SLAY : SAY_V07TRON_SLAY);
+ }
+
+ void MovementInform(uint32 type, uint32 point) override
+ {
+ if (type == POINT_MOTION_TYPE && point == WP_AERIAL_P4_POS)
+ {
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+
+ if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON)))
+ mimiron->AI()->DoAction(DO_ACTIVATE_V0L7R0N_1);
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_SUMMON_FIRE_BOTS:
+ me->CastCustomSpell(SPELL_SUMMON_FIRE_BOT_TRIGGER, SPELLVALUE_MAX_TARGETS, 3, NULL, true);
+ events.RescheduleEvent(EVENT_SUMMON_FIRE_BOTS, 45000, 0, PHASE_AERIAL_COMMAND_UNIT);
+ break;
+ case EVENT_SUMMON_JUNK_BOT:
+ me->CastCustomSpell(SPELL_SUMMON_JUNK_BOT_TRIGGER, SPELLVALUE_MAX_TARGETS, 1, NULL, true);
+ events.RescheduleEvent(EVENT_SUMMON_JUNK_BOT, urand(11000, 12000), 0, PHASE_AERIAL_COMMAND_UNIT);
+ break;
+ case EVENT_SUMMON_ASSAULT_BOT:
+ me->CastCustomSpell(SPELL_SUMMON_ASSAULT_BOT_TRIGGER, SPELLVALUE_MAX_TARGETS, 1, NULL, true);
+ events.RescheduleEvent(EVENT_SUMMON_ASSAULT_BOT, 30000, 0, PHASE_AERIAL_COMMAND_UNIT);
+ break;
+ case EVENT_SUMMON_BOMB_BOT:
+ DoCast(me, SPELL_SUMMON_BOMB_BOT);
+ events.RescheduleEvent(EVENT_SUMMON_BOMB_BOT, urand(15000, 20000), 0, PHASE_AERIAL_COMMAND_UNIT);
+ break;
+ default:
+ break;
+ }
+ }
+ DoSpellAttackIfReady(events.IsInPhase(PHASE_AERIAL_COMMAND_UNIT) ? SPELL_PLASMA_BALL_P1 : SPELL_PLASMA_BALL_P2);
+ }
+
+ private:
+ bool fireFigther;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetUlduarAI<boss_aerial_command_unitAI>(creature);
+ }
+};
+
+class npc_mimiron_assault_bot : public CreatureScript
+{
+ public:
+ npc_mimiron_assault_bot() : CreatureScript("npc_mimiron_assault_bot") { }
+
+ struct npc_mimiron_assault_botAI : public ScriptedAI
+ {
+ npc_mimiron_assault_botAI(Creature* creature) : ScriptedAI(creature)
+ {
+ }
+
+ void EnterCombat(Unit* /*who*/) override
+ {
+ events.ScheduleEvent(EVENT_MAGNETIC_FIELD, 14000);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_ROOT))
+ {
+ if (Unit* newTarget = SelectTarget(SELECT_TARGET_NEAREST, 0, 30.0f, true))
+ {
+ me->DeleteThreatList();
+ AttackStart(newTarget);
+ }
+ }
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_MAGNETIC_FIELD:
+ DoCastVictim(SPELL_MAGNETIC_FIELD);
+ me->ClearUnitState(UNIT_STATE_CASTING);
+ events.RescheduleEvent(EVENT_MAGNETIC_FIELD, 30000);
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetUlduarAI<npc_mimiron_assault_botAI>(creature);
+ }
+};
+
+class npc_mimiron_emergency_fire_bot : public CreatureScript
+{
+ public:
+ npc_mimiron_emergency_fire_bot() : CreatureScript("npc_mimiron_emergency_fire_bot") { }
+
+ struct npc_mimiron_emergency_fire_botAI : public ScriptedAI
+ {
+ npc_mimiron_emergency_fire_botAI(Creature* creature) : ScriptedAI(creature)
+ {
+ me->SetReactState(REACT_PASSIVE);
+ isWaterSprayReady = true;
+ moveNew = true;
+ }
+
+ uint32 GetData(uint32 id) const override
+ {
+ if (id == DATA_WATERSPRAY)
+ return isWaterSprayReady;
+ if (id == DATA_MOVE_NEW)
+ return moveNew;
+ return 0;
+ }
+
+ void SetData(uint32 id, uint32 data) override
+ {
+ if (id == DATA_WATERSPRAY)
+ isWaterSprayReady = false;
+ else if (id == DATA_MOVE_NEW)
+ moveNew = data ? true : false;
+ }
+
+ void Reset() override
+ {
+ events.ScheduleEvent(EVENT_WATER_SPRAY, 7000);
+ isWaterSprayReady = true;
+ moveNew = true;
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!isWaterSprayReady)
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_WATER_SPRAY:
+ isWaterSprayReady = true;
+ events.RescheduleEvent(EVENT_WATER_SPRAY, urand(7000, 9000));
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private:
+ EventMap events;
+ bool isWaterSprayReady;
+ bool moveNew;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetUlduarAI<npc_mimiron_emergency_fire_botAI>(creature);
+ }
+};
+
+class npc_mimiron_computer : public CreatureScript
+{
+ public:
+ npc_mimiron_computer() : CreatureScript("npc_mimiron_computer") { }
+
+ struct npc_mimiron_computerAI : public ScriptedAI
+ {
+ npc_mimiron_computerAI(Creature* creature) : ScriptedAI(creature)
+ {
+ instance = me->GetInstanceScript();
+ }
+
+ void DoAction(int32 action) override
+ {
+ switch (action)
+ {
+ case DO_ACTIVATE_COMPUTER:
+ Talk(SAY_SELF_DESTRUCT_INITIATED);
+ events.ScheduleEvent(EVENT_SELF_DESTRUCT_10, 3000);
+ break;
+ case DO_DEACTIVATE_COMPUTER:
+ Talk(SAY_SELF_DESTRUCT_TERMINATED);
+ me->RemoveAurasDueToSpell(SPELL_SELF_DESTRUCTION_AURA);
+ me->RemoveAurasDueToSpell(SPELL_SELF_DESTRUCTION_VISUAL);
+ events.Reset();
+ break;
+ default:
+ break;
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_SELF_DESTRUCT_10:
+ Talk(SAY_SELF_DESTRUCT_10);
+ if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON)))
+ mimiron->AI()->DoAction(DO_ACTIVATE_HARD_MODE);
+ events.ScheduleEvent(EVENT_SELF_DESTRUCT_9, 60000);
+ break;
+ case EVENT_SELF_DESTRUCT_9:
+ Talk(SAY_SELF_DESTRUCT_9);
+ events.ScheduleEvent(EVENT_SELF_DESTRUCT_8, 60000);
+ break;
+ case EVENT_SELF_DESTRUCT_8:
+ Talk(SAY_SELF_DESTRUCT_8);
+ events.ScheduleEvent(EVENT_SELF_DESTRUCT_7, 60000);
+ break;
+ case EVENT_SELF_DESTRUCT_7:
+ Talk(SAY_SELF_DESTRUCT_7);
+ events.ScheduleEvent(EVENT_SELF_DESTRUCT_6, 60000);
+ break;
+ case EVENT_SELF_DESTRUCT_6:
+ Talk(SAY_SELF_DESTRUCT_6);
+ events.ScheduleEvent(EVENT_SELF_DESTRUCT_5, 60000);
+ break;
+ case EVENT_SELF_DESTRUCT_5:
+ Talk(SAY_SELF_DESTRUCT_5);
+ events.ScheduleEvent(EVENT_SELF_DESTRUCT_4, 60000);
+ break;
+ case EVENT_SELF_DESTRUCT_4:
+ Talk(SAY_SELF_DESTRUCT_4);
+ events.ScheduleEvent(EVENT_SELF_DESTRUCT_3, 60000);
+ break;
+ case EVENT_SELF_DESTRUCT_3:
+ Talk(SAY_SELF_DESTRUCT_3);
+ events.ScheduleEvent(EVENT_SELF_DESTRUCT_2, 60000);
+ break;
+ case EVENT_SELF_DESTRUCT_2:
+ Talk(SAY_SELF_DESTRUCT_2);
+ events.ScheduleEvent(EVENT_SELF_DESTRUCT_1, 60000);
+ break;
+ case EVENT_SELF_DESTRUCT_1:
+ Talk(SAY_SELF_DESTRUCT_1);
+ events.ScheduleEvent(EVENT_SELF_DESTRUCT_FINALIZED, 60000);
+ break;
+ case EVENT_SELF_DESTRUCT_FINALIZED:
+ Talk(SAY_SELF_DESTRUCT_FINALIZED);
+ if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON)))
+ mimiron->AI()->DoAction(DO_ACTIVATE_SELF_DESTRUCT);
+ DoCast(me, SPELL_SELF_DESTRUCTION_AURA);
+ DoCast(me, SPELL_SELF_DESTRUCTION_VISUAL);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private:
+ InstanceScript* instance;
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetUlduarAI<npc_mimiron_computerAI>(creature);
+ }
+};
+
+class npc_mimiron_flames : public CreatureScript
+{
+ public:
+ npc_mimiron_flames() : CreatureScript("npc_mimiron_flames") { }
+
+ struct npc_mimiron_flamesAI : public ScriptedAI
+ {
+ npc_mimiron_flamesAI(Creature* creature) : ScriptedAI(creature)
+ {
+ instance = me->GetInstanceScript();
+ }
+
+ void Reset() override // Reset is possibly more suitable for this case.
+ {
+ events.ScheduleEvent(EVENT_SPREAD_FLAMES, 4000);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (instance->GetBossState(BOSS_MIMIRON) != IN_PROGRESS)
+ me->DespawnOrUnsummon();
+
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_SPREAD_FLAMES:
+ DoCastAOE(SPELL_SUMMON_FLAMES_SPREAD_TRIGGER);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private:
+ InstanceScript* instance;
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetUlduarAI<npc_mimiron_flamesAI>(creature);
+ }
+};
+
+class npc_mimiron_frost_bomb : public CreatureScript
+{
+ public:
+ npc_mimiron_frost_bomb() : CreatureScript("npc_mimiron_frost_bomb") { }
+
+ struct npc_mimiron_frost_bombAI : public ScriptedAI
+ {
+ npc_mimiron_frost_bombAI(Creature* creature) : ScriptedAI(creature)
+ {
+ }
+
+ void Reset() override
+ {
+ events.ScheduleEvent(EVENT_FROST_BOMB_EXPLOSION, 10000);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_FROST_BOMB_EXPLOSION:
+ DoCastAOE(SPELL_FROST_BOMB_EXPLOSION);
+ events.ScheduleEvent(EVENT_FROST_BOMB_CLEAR_FIRES, 3000);
+ break;
+ case EVENT_FROST_BOMB_CLEAR_FIRES:
+ DoCastAOE(SPELL_CLEAR_FIRES);
+ me->DespawnOrUnsummon(3000);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private:
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetUlduarAI<npc_mimiron_frost_bombAI>(creature);
+ }
+};
+
+class npc_mimiron_proximity_mine : public CreatureScript
+{
+ public:
+ npc_mimiron_proximity_mine() : CreatureScript("npc_mimiron_proximity_mine") { }
+
+ struct npc_mimiron_proximity_mineAI : public ScriptedAI
+ {
+ npc_mimiron_proximity_mineAI(Creature* creature) : ScriptedAI(creature)
+ {
+ }
+
+ void Reset() override
+ {
+ events.ScheduleEvent(EVENT_PROXIMITY_MINE_ARM, 1500);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_PROXIMITY_MINE_ARM:
+ DoCast(me, SPELL_PROXIMITY_MINE_PERIODIC_TRIGGER);
+ events.ScheduleEvent(EVENT_PROXIMITY_MINE_DETONATION, 33500);
+ break;
+ case EVENT_PROXIMITY_MINE_DETONATION:
+ if (me->HasAura(SPELL_PROXIMITY_MINE_PERIODIC_TRIGGER))
+ DoCastAOE(SPELL_PROXIMITY_MINE_EXPLOSION);
+ me->DespawnOrUnsummon(1000);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private:
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetUlduarAI<npc_mimiron_proximity_mineAI>(creature);
+ }
+};
+
+class go_mimiron_hardmode_button : public GameObjectScript
+{
+ public:
+ go_mimiron_hardmode_button() : GameObjectScript("go_mimiron_hardmode_button") { }
+
+ bool OnGossipHello(Player* /*player*/, GameObject* go)
+ {
+ InstanceScript* instance = go->GetInstanceScript();
+ if (!instance)
+ return false;
+
+ if (Creature* computer = ObjectAccessor::GetCreature(*go, instance->GetData64(DATA_COMPUTER)))
+ computer->AI()->DoAction(DO_ACTIVATE_COMPUTER);
+ go->SetGoState(GO_STATE_ACTIVE);
+ go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
+ return true;
+ }
+};
+
+// 63801 - Bomb Bot
class spell_mimiron_bomb_bot : public SpellScriptLoader
{
public:
@@ -538,7 +1856,7 @@ class spell_mimiron_magnetic_core : public SpellScriptLoader
{
if (Creature* target = GetTarget()->ToCreature())
{
- target->GetAI()->DoAction(DO_DISABLE_AERIAL);
+ target->AI()->DoAction(DO_DISABLE_AERIAL);
target->CastSpell(target, SPELL_MAGNETIC_CORE_VISUAL, true);
}
}
@@ -547,7 +1865,7 @@ class spell_mimiron_magnetic_core : public SpellScriptLoader
{
if (Creature* target = GetTarget()->ToCreature())
{
- target->GetAI()->DoAction(DO_ENABLE_AERIAL);
+ target->AI()->DoAction(DO_ENABLE_AERIAL);
target->RemoveAurasDueToSpell(SPELL_MAGNETIC_CORE_VISUAL);
}
}
@@ -1426,8 +2744,66 @@ class spell_mimiron_weld : public SpellScriptLoader
}
};
+class achievement_setup_boom : public AchievementCriteriaScript
+{
+ public:
+ achievement_setup_boom() : AchievementCriteriaScript("achievement_setup_boom") { }
+
+ bool OnCheck(Player* /*source*/, Unit* target)
+ {
+ return target && target->GetAI()->GetData(DATA_SETUP_BOMB);
+ }
+};
+
+class achievement_setup_mine : public AchievementCriteriaScript
+{
+ public:
+ achievement_setup_mine() : AchievementCriteriaScript("achievement_setup_mine") { }
+
+ bool OnCheck(Player* /*source*/, Unit* target)
+ {
+ return target && target->GetAI()->GetData(DATA_SETUP_MINE);
+ }
+};
+
+class achievement_setup_rocket : public AchievementCriteriaScript
+{
+ public:
+ achievement_setup_rocket() : AchievementCriteriaScript("achievement_setup_rocket") { }
+
+ bool OnCheck(Player* /*source*/, Unit* target)
+ {
+ return target && target->GetAI()->GetData(DATA_SETUP_ROCKET);
+ }
+};
+
+class achievement_firefighter : public AchievementCriteriaScript
+{
+ public:
+ achievement_firefighter() : AchievementCriteriaScript("achievement_firefighter") { }
+
+ bool OnCheck(Player* /*source*/, Unit* target)
+ {
+ return target && target->GetAI()->GetData(DATA_FIREFIGHTER);
+ }
+};
+
void AddSC_boss_mimiron()
{
+ new boss_aerial_command_unit();
+ new boss_leviathan_mk_ii();
+ new boss_mimiron();
+ new boss_vx_001();
+
+ new npc_mimiron_assault_bot();
+ new npc_mimiron_emergency_fire_bot();
+ new npc_mimiron_computer();
+ new npc_mimiron_flames();
+ new npc_mimiron_frost_bomb();
+ new npc_mimiron_proximity_mine();
+
+ new go_mimiron_hardmode_button();
+
new spell_mimiron_bomb_bot();
new spell_mimiron_clear_fires();
new spell_mimiron_despawn_assault_bots();
@@ -1454,4 +2830,9 @@ void AddSC_boss_mimiron()
new spell_mimiron_summon_junk_bot();
new spell_mimiron_summon_junk_bot_target();
new spell_mimiron_weld();
+
+ new achievement_setup_boom();
+ new achievement_setup_mine();
+ new achievement_setup_rocket();
+ new achievement_firefighter();
}
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp
index 399113e18c8..f5fe255fdf3 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp
@@ -242,7 +242,7 @@ class boss_razorscale_controller : public CreatureScript
break;
case ACTION_PLACE_BROKEN_HARPOON:
for (uint8 n = 0; n < RAID_MODE(2, 4); n++)
- me->SummonGameObject(GO_RAZOR_BROKEN_HARPOON, PosHarpoon[n].GetPositionX(), PosHarpoon[n].GetPositionY(), PosHarpoon[n].GetPositionZ(), 2.286f, 0, 0, 0, 0, 180000);
+ me->SummonGameObject(GO_RAZOR_BROKEN_HARPOON, PosHarpoon[n].GetPositionX(), PosHarpoon[n].GetPositionY(), PosHarpoon[n].GetPositionZ(), 2.286f, 0, 0, 0, 0, 180);
break;
}
}
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp
index 8520e317ba3..1d2b1b24322 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp
@@ -36,17 +36,14 @@
enum Spells
{
SPELL_TYMPANIC_TANTRUM = 62776,
- SPELL_SEARING_LIGHT_10 = 63018,
- SPELL_SEARING_LIGHT_25 = 65121,
+ SPELL_SEARING_LIGHT = 63018,
SPELL_SUMMON_LIFE_SPARK = 64210,
SPELL_SUMMON_VOID_ZONE = 64203,
- SPELL_GRAVITY_BOMB_10 = 63024,
- SPELL_GRAVITY_BOMB_25 = 64234,
+ SPELL_GRAVITY_BOMB = 63024,
- SPELL_HEARTBREAK_10 = 65737,
- SPELL_HEARTBREAK_25 = 64193,
+ SPELL_HEARTBREAK = 65737,
// Cast by 33337 at Heartbreak:
SPELL_RECHARGE_PUMMELER = 62831, // Summons 33344
@@ -66,12 +63,10 @@ enum Spells
SPELL_SUBMERGE = 37751,
//------------------VOID ZONE--------------------
- SPELL_VOID_ZONE_10 = 64203,
- SPELL_VOID_ZONE_25 = 64235,
+ SPELL_VOID_ZONE = 64203,
// Life Spark
- SPELL_STATIC_CHARGED_10 = 64227,
- SPELL_STATIC_CHARGED_25 = 64236,
+ SPELL_STATIC_CHARGED = 64227,
SPELL_SHOCK = 64230,
//----------------XT-002 HEART-------------------
@@ -279,13 +274,13 @@ class boss_xt002 : public CreatureScript
{
case EVENT_SEARING_LIGHT:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- DoCast(target, RAID_MODE(SPELL_SEARING_LIGHT_10, SPELL_SEARING_LIGHT_25));
+ DoCast(target, SPELL_SEARING_LIGHT);
events.ScheduleEvent(EVENT_SEARING_LIGHT, TIMER_SEARING_LIGHT);
break;
case EVENT_GRAVITY_BOMB:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- DoCast(target, RAID_MODE(SPELL_GRAVITY_BOMB_10, SPELL_GRAVITY_BOMB_25));
+ DoCast(target, SPELL_GRAVITY_BOMB);
events.ScheduleEvent(EVENT_GRAVITY_BOMB, TIMER_GRAVITY_BOMB);
break;
@@ -304,7 +299,7 @@ class boss_xt002 : public CreatureScript
break;
case EVENT_ENTER_HARD_MODE:
me->SetFullHealth();
- DoCast(me, RAID_MODE(SPELL_HEARTBREAK_10, SPELL_HEARTBREAK_25), true);
+ DoCast(me, SPELL_HEARTBREAK, true);
me->AddLootMode(LOOT_MODE_HARD_MODE_1);
_hardMode = true;
SetPhaseOne();
@@ -735,7 +730,7 @@ class npc_life_spark : public CreatureScript
void Reset() override
{
- DoCast(me, RAID_MODE(SPELL_STATIC_CHARGED_10, SPELL_STATIC_CHARGED_25));
+ DoCast(me, SPELL_STATIC_CHARGED);
_shockTimer = 0; // first one is immediate.
}
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
index 1f9bfe4c3f3..a074ce28181 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
@@ -15,12 +15,13 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "ulduar.h"
+#include "InstanceScript.h"
#include "Player.h"
#include "ScriptedCreature.h"
#include "ScriptMgr.h"
#include "SpellScript.h"
#include "WorldPacket.h"
+#include "ulduar.h"
static DoorData const doorData[] =
{
@@ -821,10 +822,6 @@ class instance_ulduar : public InstanceMapScript
case DATA_UNBROKEN:
Unbroken = data != 0;
break;
- case DATA_MIMIRON_ELEVATOR:
- if (GameObject* gameObject = instance->GetGameObject(MimironElevatorGUID))
- gameObject->SetGoState((GOState)data);
- break;
case DATA_ILLUSION:
illusion = data;
break;
@@ -924,6 +921,8 @@ class instance_ulduar : public InstanceMapScript
return MimironComputerGUID;
case DATA_MIMIRON_WORLD_TRIGGER:
return MimironWorldTriggerGUID;
+ case DATA_MIMIRON_ELEVATOR:
+ return MimironElevatorGUID;
case DATA_MIMIRON_BUTTON:
return MimironButtonGUID;
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h
index 81cb469318f..5dfc2b54f6e 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h
@@ -18,8 +18,6 @@
#ifndef DEF_ULDUAR_H
#define DEF_ULDUAR_H
-#include "InstanceScript.h"
-#include "ObjectMgr.h"
#define UlduarScriptName "instance_ulduar"
extern Position const ObservationRingKeepersPos[4];
diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_ymiron.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_ymiron.cpp
index dfef80133c4..01e09ca2f9a 100644
--- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_ymiron.cpp
+++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_ymiron.cpp
@@ -31,15 +31,11 @@ Script Data End */
enum Spells
{
SPELL_BANE = 48294,
- H_SPELL_BANE = 59301,
SPELL_DARK_SLASH = 48292,
SPELL_FETID_ROT = 48291,
- H_SPELL_FETID_ROT = 59300,
SPELL_SCREAMS_OF_THE_DEAD = 51750,
SPELL_SPIRIT_BURST = 48529,
- H_SPELL_SPIRIT_BURST = 59305,
SPELL_SPIRIT_STRIKE = 48423,
- H_SPELL_SPIRIT_STRIKE = 59304,
SPELL_ANCESTORS_VENGEANCE = 16939,
SPELL_SUMMON_AVENGING_SPIRIT = 48592,
@@ -48,8 +44,7 @@ enum Spells
SPELL_CHANNEL_SPIRIT_TO_YMIRON = 48316,
SPELL_CHANNEL_YMIRON_TO_SPIRIT = 48307,
- SPELL_SPIRIT_FOUNT = 48380,
- H_SPELL_SPIRIT_FOUNT = 59320
+ SPELL_SPIRIT_FOUNT = 48380
};
//not in db
@@ -278,7 +273,7 @@ public:
if (Creature* temp = me->SummonCreature(NPC_SPIRIT_FOUNT, 385.0f + rand32() % 10, -330.0f + rand32() % 10, 104.756f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 180000))
{
temp->SetSpeed(MOVE_RUN, 0.4f);
- temp->CastSpell(temp, DUNGEON_MODE(SPELL_SPIRIT_FOUNT, H_SPELL_SPIRIT_FOUNT), true);
+ temp->CastSpell(temp, SPELL_SPIRIT_FOUNT, true);
temp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
temp->SetDisplayId(11686);
m_uiOrbGUID = temp->GetGUID();
diff --git a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp
index 9e2bb85e27a..1c106f399de 100644
--- a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp
+++ b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp
@@ -50,7 +50,6 @@ enum AzureInvaderSpells
{
SPELL_CLEAVE = 15496,
SPELL_IMPALE = 58459,
- H_SPELL_IMPALE = 59256,
SPELL_BRUTAL_STRIKE = 58460,
SPELL_SUNDER_ARMOR = 58461
};
@@ -58,23 +57,17 @@ enum AzureInvaderSpells
enum AzureSellbreakerSpells
{
SPELL_ARCANE_BLAST = 58462,
- H_SPELL_ARCANE_BLAST = 59257,
SPELL_SLOW = 25603,
SPELL_CHAINS_OF_ICE = 58464,
- SPELL_CONE_OF_COLD = 58463,
- H_SPELL_CONE_OF_COLD = 59258
+ SPELL_CONE_OF_COLD = 58463
};
enum AzureBinderSpells
{
SPELL_ARCANE_BARRAGE = 58456,
- H_SPELL_ARCANE_BARRAGE = 59248,
SPELL_ARCANE_EXPLOSION = 58455,
- H_SPELL_ARCANE_EXPLOSION = 59245,
SPELL_FROST_NOVA = 58458,
- H_SPELL_FROST_NOVA = 59253,
- SPELL_FROSTBOLT = 58457,
- H_SPELL_FROSTBOLT = 59251,
+ SPELL_FROSTBOLT = 58457
};
enum AzureMageSlayerSpells
@@ -92,9 +85,7 @@ enum AzureCaptainSpells
enum AzureSorcerorSpells
{
SPELL_ARCANE_STREAM = 60181,
- H_SPELL_ARCANE_STREAM = 60204,
- SPELL_MANA_DETONATION = 60182,
- H_SPELL_MANA_DETONATION = 60205
+ SPELL_MANA_DETONATION = 60182
};
enum AzureRaiderSpells
@@ -912,7 +903,7 @@ public:
{
if (uiArcaneExplosionTimer <= diff)
{
- DoCast(DUNGEON_MODE(SPELL_ARCANE_EXPLOSION, H_SPELL_ARCANE_EXPLOSION));
+ DoCast(SPELL_ARCANE_EXPLOSION);
uiArcaneExplosionTimer = 5000;
} else uiArcaneExplosionTimer -= diff;
@@ -920,7 +911,7 @@ public:
{
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
if (target)
- DoCast(target, DUNGEON_MODE(SPELL_ARCANE_BARRAGE, H_SPELL_ARCANE_BARRAGE));
+ DoCast(target, SPELL_ARCANE_BARRAGE);
uiArcainBarrageTimer = 6000;
} else uiArcainBarrageTimer -= diff;
}
@@ -929,7 +920,7 @@ public:
{
if (uiFrostNovaTimer <= diff)
{
- DoCast(DUNGEON_MODE(SPELL_FROST_NOVA, H_SPELL_FROST_NOVA));
+ DoCast(SPELL_FROST_NOVA);
uiFrostNovaTimer = 5000;
} else uiFrostNovaTimer -= diff;
@@ -937,7 +928,7 @@ public:
{
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
if (target)
- DoCast(target, DUNGEON_MODE(SPELL_FROSTBOLT, H_SPELL_FROSTBOLT));
+ DoCast(target, SPELL_FROSTBOLT);
uiFrostboltTimer = 6000;
} else uiFrostboltTimer -= diff;
}
@@ -1164,7 +1155,7 @@ public:
{
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
if (target)
- DoCast(target, DUNGEON_MODE(SPELL_ARCANE_BLAST, H_SPELL_ARCANE_BLAST));
+ DoCast(target, SPELL_ARCANE_BLAST);
uiArcaneBlastTimer = 6000;
} else uiArcaneBlastTimer -= diff;
@@ -1189,7 +1180,7 @@ public:
if (uiConeOfColdTimer <= diff)
{
- DoCast(DUNGEON_MODE(SPELL_CONE_OF_COLD, H_SPELL_CONE_OF_COLD));
+ DoCast(SPELL_CONE_OF_COLD);
uiConeOfColdTimer = 5000;
} else uiConeOfColdTimer -= diff;
}
@@ -1296,14 +1287,14 @@ public:
{
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
if (target)
- DoCast(target, DUNGEON_MODE(SPELL_ARCANE_STREAM, H_SPELL_ARCANE_STREAM));
+ DoCast(target, SPELL_ARCANE_STREAM);
uiArcaneStreamTimer = urand(0, 5000)+5000;
uiArcaneStreamTimerStartingValueHolder = uiArcaneStreamTimer;
} else uiArcaneStreamTimer -= diff;
if (uiManaDetonationTimer <= diff && uiArcaneStreamTimer >=1500 && uiArcaneStreamTimer <= uiArcaneStreamTimerStartingValueHolder/2)
{
- DoCast(DUNGEON_MODE(SPELL_MANA_DETONATION, H_SPELL_MANA_DETONATION));
+ DoCast(SPELL_MANA_DETONATION);
uiManaDetonationTimer = urand(2000, 6000);
} else uiManaDetonationTimer -= diff;
diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_grandmaster_vorpil.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_grandmaster_vorpil.cpp
index d454b646647..905fe67af97 100644
--- a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_grandmaster_vorpil.cpp
+++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_grandmaster_vorpil.cpp
@@ -52,7 +52,6 @@ enum GrandmasterVorpil
SPELL_SACRIFICE = 33587,
SPELL_SHADOW_NOVA = 33846,
SPELL_EMPOWERING_SHADOWS = 33783,
- H_SPELL_EMPOWERING_SHADOWS = 39364,
NPC_VOID_PORTAL = 19224,
SPELL_SUMMON_PORTAL = 33566,
@@ -245,7 +244,7 @@ class npc_voidtraveler : public CreatureScript
if (_sacrificed)
{
- DoCastAOE(DUNGEON_MODE(SPELL_EMPOWERING_SHADOWS, H_SPELL_EMPOWERING_SHADOWS), true);
+ DoCastAOE(SPELL_EMPOWERING_SHADOWS, true);
DoCast(me, SPELL_SHADOW_NOVA, true);
me->Kill(me);
return;
diff --git a/src/server/scripts/Outland/CoilfangReservoir/SteamVault/boss_hydromancer_thespia.cpp b/src/server/scripts/Outland/CoilfangReservoir/SteamVault/boss_hydromancer_thespia.cpp
index d4fdb262c8e..dfbc49e1e34 100644
--- a/src/server/scripts/Outland/CoilfangReservoir/SteamVault/boss_hydromancer_thespia.cpp
+++ b/src/server/scripts/Outland/CoilfangReservoir/SteamVault/boss_hydromancer_thespia.cpp
@@ -110,11 +110,6 @@ class boss_hydromancer_thespia : public CreatureScript
break;
}
}
-
- void UpdateAI(uint32 diff) override
- {
- BossAI::UpdateAI(diff);
- }
};
CreatureAI* GetAI(Creature* creature) const override
diff --git a/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp b/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp
index 839dd800721..d2a93caf7a3 100644
--- a/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp
+++ b/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp
@@ -43,9 +43,7 @@ enum Says
enum Spells
{
SPELL_FIREBALL = 34653,
- SPELL_FIREBALL_H = 36920,
SPELL_CONE_OF_FIRE = 30926,
- SPELL_CONE_OF_FIRE_H = 36921,
SPELL_SUMMON_LIQUID_FIRE = 23971,
SPELL_SUMMON_LIQUID_FIRE_H = 30928,
SPELL_BELLOWING_ROAR = 39427,
@@ -116,7 +114,7 @@ class boss_nazan : public CreatureScript
if (Fireball_Timer <= diff)
{
if (Unit* victim = SelectTarget(SELECT_TARGET_RANDOM, 0))
- DoCast(victim, DUNGEON_MODE(SPELL_FIREBALL, SPELL_FIREBALL_H), true);
+ DoCast(victim, SPELL_FIREBALL, true);
Fireball_Timer = urand(4000, 7000);
}
else
@@ -156,7 +154,7 @@ class boss_nazan : public CreatureScript
{
if (ConeOfFire_Timer <= diff)
{
- DoCast(me, DUNGEON_MODE(SPELL_CONE_OF_FIRE, SPELL_CONE_OF_FIRE_H));
+ DoCast(me, SPELL_CONE_OF_FIRE);
ConeOfFire_Timer = 12000;
Fireball_Timer = 4000;
}
diff --git a/src/server/scripts/Outland/TempestKeep/botanica/boss_thorngrin_the_tender.cpp b/src/server/scripts/Outland/TempestKeep/botanica/boss_thorngrin_the_tender.cpp
index d2a1d101ae4..9114027b9fb 100644
--- a/src/server/scripts/Outland/TempestKeep/botanica/boss_thorngrin_the_tender.cpp
+++ b/src/server/scripts/Outland/TempestKeep/botanica/boss_thorngrin_the_tender.cpp
@@ -34,8 +34,7 @@ enum Says
enum Spells
{
SPELL_SACRIFICE = 34661,
- SPELL_HELLFIRE_NORMAL = 34659,
- SPELL_HELLFIRE_HEROIC = 39131,
+ SPELL_HELLFIRE = 34659,
SPELL_ENRAGE = 34670
};
@@ -119,7 +118,7 @@ class boss_thorngrin_the_tender : public CreatureScript
break;
case EVENT_HELLFIRE:
Talk(SAY_CAST_HELLFIRE);
- DoCastVictim(DUNGEON_MODE(SPELL_HELLFIRE_NORMAL, SPELL_HELLFIRE_HEROIC), true);
+ DoCastVictim(SPELL_HELLFIRE, true);
events.ScheduleEvent(EVENT_HELLFIRE, IsHeroic() ? urand(17400, 19300) : 18000);
break;
case EVENT_ENRAGE:
diff --git a/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp b/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp
index bbb384ed0f8..8bc9d0982e3 100644
--- a/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp
+++ b/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp
@@ -40,7 +40,6 @@ enum Spells
WAR_STOMP = 34716,
SUMMON_TREANTS = 34727, // DBC: 34727, 34731, 34733, 34734, 34736, 34739, 34741 (with Ancestral Life spell 34742) // won't work (guardian summon)
ARCANE_VOLLEY = 36705,
- ARCANE_VOLLEY_H = 39133,
SPELL_HEAL_FATHER = 6262
};
@@ -208,7 +207,7 @@ class boss_warp_splinter : public CreatureScript
//Check for Arcane Volley
if (Arcane_Volley_Timer <= diff)
{
- DoCastVictim(DUNGEON_MODE(ARCANE_VOLLEY, ARCANE_VOLLEY_H));
+ DoCastVictim(ARCANE_VOLLEY);
Arcane_Volley_Timer = urand(20000, 35000);
}
else
diff --git a/src/server/scripts/Outland/zone_blades_edge_mountains.cpp b/src/server/scripts/Outland/zone_blades_edge_mountains.cpp
index d54eb6fff8c..03b8e7e69c8 100644
--- a/src/server/scripts/Outland/zone_blades_edge_mountains.cpp
+++ b/src/server/scripts/Outland/zone_blades_edge_mountains.cpp
@@ -1143,7 +1143,7 @@ public:
{
// Spell 37392 does not exist in dbc, manually spawning
me->SummonCreature(NPC_OSCILLATING_FREQUENCY_SCANNER_TOP_BUNNY, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 0.5f, me->GetOrientation(), TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 50000);
- me->SummonGameObject(GO_OSCILLATING_FREQUENCY_SCANNER, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), 0, 0, 0, 0, 50000);
+ me->SummonGameObject(GO_OSCILLATING_FREQUENCY_SCANNER, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), 0, 0, 0, 0, 50);
me->DespawnOrUnsummon(50000);
}
diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp
index 173e03fef7c..f17aac51519 100644
--- a/src/server/scripts/Spells/spell_quest.cpp
+++ b/src/server/scripts/Spells/spell_quest.cpp
@@ -2026,7 +2026,6 @@ class spell_q12308_escape_from_silverbrook_summon_worgen : public SpellScriptLoa
}
};
-
enum DeathComesFromOnHigh
{
SPELL_FORGE_CREDIT = 51974,
@@ -2097,6 +2096,37 @@ class spell_q12641_death_comes_from_on_high : public SpellScriptLoader
}
};
+// 52694 - Recall Eye of Acherus
+class spell_q12641_recall_eye_of_acherus : public SpellScriptLoader
+{
+ public:
+ spell_q12641_recall_eye_of_acherus() : SpellScriptLoader("spell_q12641_recall_eye_of_acherus") { }
+
+ class spell_q12641_recall_eye_of_acherus_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_q12641_recall_eye_of_acherus_SpellScript);
+
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ if (Player* player = GetCaster()->GetCharmerOrOwner()->ToPlayer())
+ {
+ player->StopCastingCharm();
+ player->StopCastingBindSight();
+ }
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_q12641_recall_eye_of_acherus_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_q12641_recall_eye_of_acherus_SpellScript();
+ }
+};
+
// 51769 - Emblazon Runeblade
class spell_q12619_emblazon_runeblade : public SpellScriptLoader
{
@@ -2364,6 +2394,7 @@ void AddSC_quest_spell_scripts()
new spell_q12308_escape_from_silverbrook_summon_worgen();
new spell_q12308_escape_from_silverbrook();
new spell_q12641_death_comes_from_on_high();
+ new spell_q12641_recall_eye_of_acherus();
new spell_q12619_emblazon_runeblade();
new spell_q12619_emblazon_runeblade_effect();
new spell_q12919_gymers_grab();
diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp
index 593ce9a54de..bba1f4e298b 100644
--- a/src/server/scripts/Spells/spell_shaman.cpp
+++ b/src/server/scripts/Spells/spell_shaman.cpp
@@ -312,7 +312,7 @@ class spell_sha_earth_shield : public SpellScriptLoader
amount = GetUnitOwner()->SpellHealingBonusTaken(caster, GetSpellInfo(), amount, HEAL);
//! WORKAROUND
- // If target is affected by healing reduction, modifier is guaranteed to be negative
+ // If target is affected by healing reduction, modifier is guaranteed to be negative
// value (e.g. -50). To revert the effect, multiply amount with reciprocal of relative value:
// (100 / ((-1) * modifier)) * 100 = (-1) * 100 * 100 / modifier = -10000 / modifier
if (int32 modifier = GetUnitOwner()->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HEALING_PCT))
diff --git a/src/server/scripts/World/item_scripts.cpp b/src/server/scripts/World/item_scripts.cpp
index 4cf2ef971eb..a191f37c76c 100644
--- a/src/server/scripts/World/item_scripts.cpp
+++ b/src/server/scripts/World/item_scripts.cpp
@@ -241,7 +241,7 @@ public:
float x, y, z;
go->GetClosePoint(x, y, z, go->GetObjectSize() / 3, 7.0f);
- go->SummonGameObject(GO_HIGH_QUALITY_FUR, go->GetPositionX(), go->GetPositionY(), go->GetPositionZ(), 0, 0, 0, 0, 0, 1000);
+ go->SummonGameObject(GO_HIGH_QUALITY_FUR, go->GetPositionX(), go->GetPositionY(), go->GetPositionZ(), 0, 0, 0, 0, 0, 1);
if (TempSummon* summon = player->SummonCreature(NPC_NESINGWARY_TRAPPER, x, y, z, go->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 1000))
{
summon->SetVisible(false);
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
index 24e61e7399a..0669d0b84f9 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
@@ -600,4 +600,10 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_UPD_CHAR_PET_SLOT_BY_ID, "UPDATE character_pet SET slot = ? WHERE owner = ? AND id = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_PET_BY_ID, "DELETE FROM character_pet WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_PET_BY_SLOT, "DELETE FROM character_pet WHERE owner = ? AND (slot = ? OR slot > ?)", CONNECTION_ASYNC);
+
+ // PvPstats
+ PrepareStatement(CHAR_SEL_PVPSTATS_MAXID, "SELECT MAX(id) FROM pvpstats_battlegrounds", CONNECTION_SYNCH);
+ PrepareStatement(CHAR_INS_PVPSTATS_BATTLEGROUND, "INSERT INTO pvpstats_battlegrounds (id, winner_faction, bracket_id, type, date) VALUES (?, ?, ?, ?, NOW())", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_PVPSTATS_PLAYER, "INSERT INTO pvpstats_players (battleground_id, character_guid, score_killing_blows, score_deaths, score_honorable_kills, score_bonus_honor, score_damage_done, score_healing_done, attr_1, attr_2, attr_3, attr_4, attr_5) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+
}
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h
index c73f0df8d00..19b5fef82eb 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.h
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.h
@@ -534,6 +534,10 @@ enum CharacterDatabaseStatements
CHAR_DEL_ITEMCONTAINER_MONEY,
CHAR_INS_ITEMCONTAINER_MONEY,
+ CHAR_SEL_PVPSTATS_MAXID,
+ CHAR_INS_PVPSTATS_BATTLEGROUND,
+ CHAR_INS_PVPSTATS_PLAYER,
+
MAX_CHARACTERDATABASE_STATEMENTS
};
diff --git a/src/server/worldserver/RemoteAccess/RASession.cpp b/src/server/worldserver/RemoteAccess/RASession.cpp
index 846a4eb39e3..9892019ae5a 100644
--- a/src/server/worldserver/RemoteAccess/RASession.cpp
+++ b/src/server/worldserver/RemoteAccess/RASession.cpp
@@ -31,12 +31,12 @@ using boost::asio::ip::tcp;
void RASession::Start()
{
- boost::asio::socket_base::bytes_readable command(true);
- _socket.io_control(command);
- std::size_t bytes_readable = command.get();
+ // wait 1 second for active connections to send negotiation request
+ for (int counter = 0; counter < 10 && _socket.available() == 0; counter++)
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
// Check if there are bytes available, if they are, then the client is requesting the negotiation
- if (bytes_readable > 0)
+ if (_socket.available() > 0)
{
// Handle subnegotiation
boost::array<char, 1024> buf;
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index d98a061b9f3..9a78d74bb45 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -2060,6 +2060,14 @@ Battleground.QueueAnnouncer.Enable = 0
Battleground.QueueAnnouncer.PlayerOnly = 0
#
+# Battleground.StoreStatistics.Enable
+# Description: Store Battleground scores in the database.
+# Default: 0 - (Disabled)
+# 1 - (Enabled)
+
+Battleground.StoreStatistics.Enable = 0
+
+#
# Battleground.InvitationType
# Description: Set Battleground invitation type.
# Default: 0 - (Normal, Invite as much players to battlegrounds as queued,
@@ -2622,6 +2630,357 @@ UI.ShowQuestLevelsInDialogs = 0
#
###################################################################################################
+###################################
+# Auction House Bot Configuration #
+###################################
+
+###################################################################################################################
+# AUCTION HOUSE BOT SETTINGS
+#
+# AuctionHouseBot.Update.Interval
+# Description: Interval in seconds for AHBot to get updated
+# Default: 20
+#
+
+AuctionHouseBot.Update.Interval = 20
+
+#
+# AuctionHouseBot.Seller.Enabled
+# Description: General enable or disable AuctionHouseBot Seller functionality
+# Default: 0 - (Disabled)
+# 1 - (Enabled)
+
+AuctionHouseBot.Seller.Enabled = 0
+
+#
+# AuctionHouseBot.Alliance.Items.Amount.Ratio
+# Description: Enable/Disable (disabled if 0) the part of AHBot that puts items up for auction on Alliance AH
+# Default: 100 - (Enabled with 100% of items specified in AuctionHouse.Items.Amount.color section)
+
+AuctionHouseBot.Alliance.Items.Amount.Ratio = 100
+
+#
+# AuctionHouseBot.Horde.Items.Amount.Ratio
+# Enable/Disable (disabled if 0) the part of AHBot that puts items up for auction on Horde AH
+# Default: 100 (Enabled with 100% of items specified in AuctionHouse.Items.Amount.color section)
+
+AuctionHouseBot.Horde.Items.Amount.Ratio = 100
+
+#
+# AuctionHouseBot.Neutral.Items.Amount.Ratio
+# Description: Enable/Disable (disabled if 0) the part of AHBot that puts items up for auction on Neutral AH
+# Default: 100 - (Enabled with 100% of items specified in AuctionHouse.Items.Amount.color section)
+
+AuctionHouseBot.Neutral.Items.Amount.Ratio = 100
+
+#
+# AuctionHouseBot.MinTime
+# Description: Minimum time for the new auction in hours
+# Default: 1 - (Hour)
+
+AuctionHouseBot.MinTime = 1
+
+#
+# AuctionHouseBot.MaxTime
+# Description: Maximum time for the new auction in hours
+# Default: 72 - (Hours)
+
+AuctionHouseBot.MaxTime = 72
+
+#
+# AuctionHouseBot.Items.Vendor
+# Description: Include items that can be bought from vendors.
+# Default: 0 - (Disabled)
+# 1 - (Enabled)
+
+AuctionHouseBot.Items.Vendor = 0
+
+#
+# AuctionHouseBot.Items.Loot
+# Description: Include items that can be looted or fished for.
+# Default: 1 - (Enabled)
+# 0 - (Disabled)
+
+AuctionHouseBot.Items.Loot = 1
+
+#
+# AuctionHouseBot.Items.Misc
+# Description: Include misc. items.
+# Default: 0 - (Disabled)
+# 1 - (Enabled)
+
+AuctionHouseBot.Items.Misc = 0
+
+#
+# AuctionHouseBot.Bind.*
+# Description: Indicates which bonding types to allow the bot to put up for auction
+# No - Items that don't bind Default 1 (Allowed)
+# Pickup - Items that bind on pickup Default 0 (Not Allowed)
+# Equip - Items that bind on equip Default 1 (Allowed)
+# Use - Items that bind on use Default 1 (Allowed)
+# Quest - Quest Items Default 0 (Not Allowed)
+# Values: 0 - (Disabled)
+# 1 - (Enabled)
+
+AuctionHouseBot.Bind.No = 1
+AuctionHouseBot.Bind.Pickup = 0
+AuctionHouseBot.Bind.Equip = 1
+AuctionHouseBot.Bind.Use = 1
+AuctionHouseBot.Bind.Quest = 0
+
+#
+# AuctionHouseBot.LockBox.Enabled
+# Description: Enable or not lockbox in auctionhouse
+# Default 0 - (Disabled)
+# 1 - (Enabled)
+
+AuctionHouseBot.LockBox.Enabled = 0
+
+#
+# AuctionHouseBot.ItemsPerCycle.Boost
+# Description: This value is used to fill AH faster than normal when there is more than this value on missed items (not auctioned items).
+# Usually this value is only used once on server start with empty auction table.
+# Default: 1000
+
+AuctionHouseBot.ItemsPerCycle.Boost = 1000
+
+#
+# AuctionHouseBot.ItemsPerCycle.Normal
+# Description: This value is used to fill AH for sold and expired items. A high value will be more resource intensive
+# Usually this value is used always when auction table is already initialised.
+# Default: 20
+
+AuctionHouseBot.ItemsPerCycle.Normal = 20
+
+#
+# AuctionHouseBot.BuyPrice.Seller
+# Description: Should the Seller use BuyPrice or SellPrice to determine Bid Prices
+# Default: 1 - (use SellPrice)
+# 0 - (use BuyPrice)
+
+AuctionHouseBot.BuyPrice.Seller = 1
+
+#
+# AuctionHouseBot.Alliance.Price.Ratio
+# Description: Percentage by which the price of items selled on Alliance Auction House is incremented / decreased
+# Default: 100 - (Not modify)
+
+AuctionHouseBot.Alliance.Price.Ratio = 100
+
+#
+# AuctionHouseBot.Horde.Price.Ratio
+# Description: Percentage by which the price of items selled on Horde Auction House is incremented / decreased
+# Default: 100 - (Not modify)
+
+AuctionHouseBot.Horde.Price.Ratio = 100
+
+#
+# AuctionHouseBot.Neutral.Price.Ratio
+# Description: Percentage by which the price of items selled on Neutral Auction House is incremented / decreased
+# Default: 100 - (Not modify)
+
+AuctionHouseBot.Neutral.Price.Ratio = 100
+
+#
+# AuctionHouseBot.Items.ItemLevel.*
+# Description: Prevent seller from listing items below/above this item level
+# Default: 0 - (Disabled)
+
+AuctionHouseBot.Items.ItemLevel.Min = 0
+AuctionHouseBot.Items.ItemLevel.Max = 0
+
+#
+# AuctionHouseBot.Items.ReqLevel.*
+# Prevent seller from listing items below/above this required level
+# Default: - 0 (Disabled)
+
+AuctionHouseBot.Items.ReqLevel.Min = 0
+AuctionHouseBot.Items.ReqLevel.Max = 0
+
+#
+# AuctionHouseBot.Items.ReqSkill.*
+# Description: Prevent seller from listing items below/above this skill level
+# Default: 0 - (Disabled)
+# 1 - (Enabled)
+
+AuctionHouseBot.Items.ReqSkill.Min = 0
+AuctionHouseBot.Items.ReqSkill.Max = 0
+
+#
+# AuctionHouseBot.Items.Amount.*
+# Description: Define here for every item qualities how many items you want to be shown in Auction House
+# This value will be adjusted by AuctionHouseBot.FACTION.Items.Amount.Ratio to define the exact amount of
+# items that will finally be shown on Auction House
+# Default: 0, 2000, 2500, 1500, 1000, 0, 0 (Gray, white, green, blue, purple, orange, yellow)
+
+AuctionHouseBot.Items.Amount.Gray = 0
+AuctionHouseBot.Items.Amount.White = 2000
+AuctionHouseBot.Items.Amount.Green = 2500
+AuctionHouseBot.Items.Amount.Blue = 1500
+AuctionHouseBot.Items.Amount.Purple = 1000
+AuctionHouseBot.Items.Amount.Orange = 0
+AuctionHouseBot.Items.Amount.Yellow = 0
+
+#
+# AustionHouseBot.Class.*
+# Description: Here you can set the class of items you prefer to be show on AH
+# These value are sorted by preference, from 0 (disabled) to 10 (max. preference)
+# Default: Consumable: 6
+# Container: 4
+# Weapon: 8
+# Gem: 3
+# Armor: 8
+# Reagent: 1
+# Projectile: 2
+# TradeGod: 10
+# Generic: 1
+# Recipe: 6
+# Quiver: 1
+# Quest: 1
+# Key: 1
+# Misc: 5
+# Glyph: 3
+
+AuctionHouseBot.Class.Consumable = 6
+AuctionHouseBot.Class.Container = 4
+AuctionHouseBot.Class.Weapon = 8
+AuctionHouseBot.Class.Gem = 3
+AuctionHouseBot.Class.Armor = 8
+AuctionHouseBot.Class.Reagent = 1
+AuctionHouseBot.Class.Projectile = 2
+AuctionHouseBot.Class.TradeGood = 10
+AuctionHouseBot.Class.Generic = 1
+AuctionHouseBot.Class.Recipe = 6
+AuctionHouseBot.Class.Quiver = 1
+AuctionHouseBot.Class.Quest = 1
+AuctionHouseBot.Class.Key = 1
+AuctionHouseBot.Class.Misc = 5
+AuctionHouseBot.Class.Glyph = 3
+
+###################################################################################################################
+#
+# AHBot ITEM FINE TUNING
+# The following are usefull for limiting what character levels can
+# benefit from the auction house
+#
+# AuctionHouseBot.Class.Misc.Mount.ReqLevel.*
+# Description: Prevent seller from listing mounts below/above this required level
+# Default: 0
+
+AuctionHouseBot.Class.Misc.Mount.ReqLevel.Min = 0
+AuctionHouseBot.Class.Misc.Mount.ReqLevel.Max = 0
+
+#
+# AuctionHouseBot.Class.Misc.Mount.ReqSkill.*
+# Description: Prevent seller from listing mounts below/above this skill level
+# Default: 0
+
+AuctionHouseBot.Class.Misc.Mount.ReqSkill.Min = 0
+AuctionHouseBot.Class.Misc.Mount.ReqSkill.Max = 0
+
+#
+# AuctionHouseBot.Class.Glyph.ReqLevel.*
+# Description: Prevent seller from listing glyphs below/above this required level
+# Default: 0
+
+AuctionHouseBot.Class.Glyph.ReqLevel.Min = 0
+AuctionHouseBot.Class.Glyph.ReqLevel.Max = 0
+
+#
+# AuctionHouseBot.Class.Glyph.ItemLevel.*
+# Description: Prevent seller from listing glyphs below/above this item level
+# Default: 0
+
+AuctionHouseBot.Class.Glyph.ItemLevel.Min = 0
+AuctionHouseBot.Class.Glyph.ItemLevel.Max = 0
+
+#
+# AuctionHouseBot.Class.TradeGood.ItemLevel.*
+# Description: Prevent seller from listing trade good items below/above this item level
+# Default: 0
+
+AuctionHouseBot.Class.TradeGood.ItemLevel.Min = 0
+AuctionHouseBot.Class.TradeGood.ItemLevel.Max = 0
+
+#
+# AuctionHouseBot.Class.Container.ItemLevel.*
+# Description: Prevent seller from listing contianers below/above this item level
+# Default: 0
+
+AuctionHouseBot.Class.Container.ItemLevel.Min = 0
+AuctionHouseBot.Class.Container.ItemLevel.Max = 0
+
+#
+# AuctionHouseBot.forceIncludeItems
+# Description: Include these items and ignore ALL filters
+# List of ids with delimiter ','
+# Default: ""
+
+AuctionHouseBot.forceIncludeItems = ""
+
+#
+# AuctionHouseBot.forceExcludeItems
+# Description: Exclude these items even if they would pass the filters
+# List of ids with delimiter ','
+# Example: "21878,27774,27811,28117,28122,43949" (this removes old items)
+# Default: ""
+#
+
+AuctionHouseBot.forceExcludeItems = ""
+
+#
+###################################################################################################################
+
+###################################################################################################################
+# AHBot Buyer config
+#
+# AuctionHouseBot.Buyer.Enabled
+# Description: General enable or disable AuctionHouseBot Buyer functionality
+# Default: 0 - (Disabled)
+# 1 - (Enabled)
+
+AuctionHouseBot.Buyer.Enabled = 0
+
+#
+# AuctionHouseBot.Buyer.FACTION.Enabled
+# Description: Enable or disable buyer independently by faction
+# Default: 0 - (Disabled)
+# 1 - (Enabled)
+
+AuctionHouseBot.Buyer.Alliance.Enabled = 0
+AuctionHouseBot.Buyer.Horde.Enabled = 0
+AuctionHouseBot.Buyer.Neutral.Enabled = 0
+
+#
+# AuctionHouseBot.BuyPrice.Buyer
+# Description: Should the Buyer use BuyPrice or SellPrice to determine Bid Prices
+# Default: 1 - (use BuyPrice)
+# 0 - (use SellPrice)
+
+AuctionHouseBot.Buyer.Buyprice = 1
+
+#
+# AuctionHouseBot.Buyer.Recheck.Interval
+# Description: This specifies the time interval (in minutes) between two evaluations of the same selled item.
+# The lesser this value is, the more chances you give for item to be bought by ahbot.
+# Default: 20 (20min.)
+
+AuctionHouseBot.Buyer.Recheck.Interval = 20
+
+#
+# AuctionHouseBot.Buyer.Alliance.Chance.Ratio
+# Description: Chance ratio for the buyer to buy an item. Higher the value, lesser the probability
+# Example: 3 (1 out of 3 change, that is, 33%).
+# Default: 3
+#
+
+AuctionHouseBot.Buyer.Alliance.Chance.Ratio = 3
+AuctionHouseBot.Buyer.Horde.Chance.Ratio = 3
+AuctionHouseBot.Buyer.Neutral.Chance.Ratio = 3
+
+#
+###################################################################################################################
+
###################################################################################################
# LOGGING SYSTEM SETTINGS
#
@@ -2718,6 +3077,7 @@ Logger.commands.gm=3,Console GM
Logger.sql.sql=5,Console DBErrors
#Logger.achievement=3,Console Server
+#Logger.ahbot=3,Console Server
#Logger.auctionHouse=3,Console Server
#Logger.bg.arena=3,Console Server
#Logger.bg.battlefield=3,Console Server