diff --git a/.gitignore b/.gitignore index 06b6c10a8f..d8613487bb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ !.gitignore +.cache/ +build/ + # #Generic # diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index 81668a9559..67e1283c88 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -544,8 +544,8 @@ AiPlayerbot.AutoGearQualityLimit = 3 # Max iLVL Phase 1(MC, Ony, ZG) = 78 | Phase 2(BWL) = 83 | Phase 2.5(AQ40) = 88 | Phase 3(Naxx40) = 92 # TBC # Max iLVL Tier 4 = 120 | Tier 5 = 133 | Tier 6 = 164 -# Max iLVL Phase 1(Kara, Gruul, Mag) = 125 | Phase 1.5(ZA) = 138 | Phase 2(SC, TK) = 141 | Phase 3(Hyjal, BT) = 156 | Phase 4(Sunwell) = 164 -# Wotlk +# Max iLVL Phase 1(Kara, Gruul, Mag) = 125 | Phase 2(SSC, TK, ZA) = 141 | Phase 3(Hyjal, BT) = 156 | Phase 4(Sunwell) = 164 +# WotLK # Max iLVL Tier 7(10/25) = 200/213 | Tier 8(10/25) = 225/232 | Tier 9(10/25) = 232/245 | Tier 10(10/25/HC) = 251/264/290 # Max iLVL Phase 1(Naxx) = 224 | Phase 2(Ulduar) = 245 | Phase 3(ToC) = 258 | Phase 4(ICC) = 290 # Default: 0 (no limit) @@ -677,6 +677,17 @@ AiPlayerbot.EnableRandomBotTrading = 1 # Configure message prefixes which will be excluded in analysis in trade action to open trade window AiPlayerbot.TradeActionExcludedPrefixes = "RPLL_H_,DBMv4,{звезда} Questie,{rt1} Questie" +# This option will prevent ALL random bots from being randomized. +# It does not prevent periodic teleport. +# Without it, random bots will be periodically randomized unless they are in a guild +# with at least one character who is not a random bot. +AiPlayerbot.DisableRandomBotPeriodicRandomization = 1 + +# This option will prevent ALL random bots from being periodically teleported. +# THIS SHOULD NOT BE ENABLED AT ALL TIMES. It exists mostly for debugging purposes. +# Disabling periodic teleport will make the bots almost unable to reach new areas. +AiPlayerbot.DisableRandomBotPeriodicTeleportation = 0 + # # # @@ -736,7 +747,7 @@ AiPlayerbot.RandomGearQualityLimit = 3 # TBC # Max iLVL Tier 4 = 120 | Tier 5 = 133 | Tier 6 = 164 # Max iLVL Phase 1(Kara, Gruul, Mag) = 125 | Phase 2(SSC, TK, ZA) = 141 | Phase 3(Hyjal, BT) = 156 | Phase 4(Sunwell) = 164 -# Wotlk +# WotLK # Max iLVL Tier 7(10/25) = 200/213 | Tier 8(10/25) = 225/232 | Tier 9(10/25) = 232/245 | Tier 10(10/25/HC) = 251/264/290 # Max iLVL Phase 1(Naxx) = 224 | Phase 2(Ulduar) = 245 | Phase 3(ToC) = 258 | Phase 4(ICC) = 290 # Default: 0 (no limit) @@ -990,7 +1001,7 @@ AiPlayerbot.ZoneBracket.3433 = 10,22 AiPlayerbot.ZoneBracket.3525 = 10,21 # Classic WoW - High-level zones: -# Deadwind Pass (Zone ID: 10 Default Min,Max: 19,33) +# Duskwood (Zone ID: 10 Default Min,Max: 19,33) # Wetlands (Zone ID: 11 Default Min,Max: 21,30) # Redridge Mountains (Zone ID: 44 Default Min,Max: 16,28) # Hillsbrad Foothills (Zone ID: 267 Default Min,Max: 20,34) @@ -1624,7 +1635,7 @@ AiPlayerbot.PremadeSpecLink.9.1.60 = -003203301135112530135201051 AiPlayerbot.PremadeSpecLink.9.1.70 = -003203301135112530135201051-55 AiPlayerbot.PremadeSpecLink.9.1.80 = -003203301135112530135221351-55000005 AiPlayerbot.PremadeSpecName.9.2 = destro pve -AiPlayerbot.PremadeSpecGlyph.9.2 = 45785,43390,50077,43394,43393,42454 +AiPlayerbot.PremadeSpecGlyph.9.2 = 45785,43390,42454,43394,43393,45785 AiPlayerbot.PremadeSpecLink.9.2.60 = --05203215200231051305031151 AiPlayerbot.PremadeSpecLink.9.2.80 = 23-0302-05203215220331051335231351 AiPlayerbot.PremadeSpecName.9.3 = affli pvp diff --git a/data/sql/playerbots/updates/2026_01_31_00_ai_playerbot_multi_pvp_text_variables.sql b/data/sql/playerbots/updates/2026_01_31_00_ai_playerbot_multi_pvp_text_variables.sql new file mode 100644 index 0000000000..9889147f60 --- /dev/null +++ b/data/sql/playerbots/updates/2026_01_31_00_ai_playerbot_multi_pvp_text_variables.sql @@ -0,0 +1,101 @@ +-- ######################################################### +-- Playerbots - Add PVP / Arena texts for TellPvpAction +-- Localized for all WotLK locales (koKR, frFR, deDE, zhCN, +-- zhTW, esES, esMX, ruRU) +-- ######################################################### + +-- --------------------------------------------------------- +-- pvp_currency +-- [PVP] Arena points: %arena_points | Honor Points: %honor_points +-- --------------------------------------------------------- +INSERT INTO `ai_playerbot_texts` + (`name`, `text`, `say_type`, `reply_type`, + `text_loc1`, `text_loc2`, `text_loc3`, `text_loc4`, + `text_loc5`, `text_loc6`, `text_loc7`, `text_loc8`) +SELECT + 'pvp_currency', + '[PVP] Arena points: %arena_points | Honor Points: %honor_points', + 0, 0, + -- koKR + '[PVP] 투기장 점수: %arena_points | 명예 점수: %honor_points', + -- frFR + '[PVP] Points d''arène : %arena_points | Points d''honneur : %honor_points', + -- deDE + '[PVP] Arenapunkte: %arena_points | Ehrenpunkte: %honor_points', + -- zhCN + '[PVP] 竞技场点数:%arena_points | 荣誉点数:%honor_points', + -- zhTW + '[PVP] 競技場點數:%arena_points | 榮譽點數:%honor_points', + -- esES + '[PVP] Puntos de arena: %arena_points | Puntos de honor: %honor_points', + -- esMX + '[PVP] Puntos de arena: %arena_points | Puntos de honor: %honor_points', + -- ruRU + '[PVP] Очки арены: %arena_points | Очки чести: %honor_points' +WHERE NOT EXISTS ( + SELECT 1 FROM `ai_playerbot_texts` WHERE `name` = 'pvp_currency' +); + +-- --------------------------------------------------------- +-- pvp_arena_team +-- [PVP] %bracket: <%team_name> (rating %team_rating) +-- --------------------------------------------------------- +INSERT INTO `ai_playerbot_texts` + (`name`, `text`, `say_type`, `reply_type`, + `text_loc1`, `text_loc2`, `text_loc3`, `text_loc4`, + `text_loc5`, `text_loc6`, `text_loc7`, `text_loc8`) +SELECT + 'pvp_arena_team', + '[PVP] %bracket: <%team_name> (rating %team_rating)', + 0, 0, + -- koKR + '[PVP] %bracket: <%team_name> (평점 %team_rating)', + -- frFR + '[PVP] %bracket : <%team_name> (cote %team_rating)', + -- deDE + '[PVP] %bracket: <%team_name> (Wertung %team_rating)', + -- zhCN + '[PVP] %bracket: <%team_name> (评分 %team_rating)', + -- zhTW + '[PVP] %bracket: <%team_name> (評分 %team_rating)', + -- esES + '[PVP] %bracket: <%team_name> (índice %team_rating)', + -- esMX + '[PVP] %bracket: <%team_name> (índice %team_rating)', + -- ruRU + '[PVP] %bracket: <%team_name> (рейтинг %team_rating)' +WHERE NOT EXISTS ( + SELECT 1 FROM `ai_playerbot_texts` WHERE `name` = 'pvp_arena_team' +); + +-- --------------------------------------------------------- +-- pvp_no_arena_team +-- [PVP] I have no Arena Team. +-- --------------------------------------------------------- +INSERT INTO `ai_playerbot_texts` + (`name`, `text`, `say_type`, `reply_type`, + `text_loc1`, `text_loc2`, `text_loc3`, `text_loc4`, + `text_loc5`, `text_loc6`, `text_loc7`, `text_loc8`) +SELECT + 'pvp_no_arena_team', + '[PVP] I have no Arena Team.', + 0, 0, + -- koKR + '[PVP] 투기장 팀이 없습니다.', + -- frFR + '[PVP] Je n''ai aucune équipe d''arène.', + -- deDE + '[PVP] Ich habe kein Arenateam.', + -- zhCN + '[PVP] 我没有竞技场战队。', + -- zhTW + '[PVP] 我沒有競技場隊伍。', + -- esES + '[PVP] No tengo equipo de arena.', + -- esMX + '[PVP] No tengo equipo de arena.', + -- ruRU + '[PVP] У меня нет команды арены.' +WHERE NOT EXISTS ( + SELECT 1 FROM `ai_playerbot_texts` WHERE `name` = 'pvp_no_arena_team' +); diff --git a/src/Ai/Base/ActionContext.h b/src/Ai/Base/ActionContext.h deleted file mode 100644 index 93bba4afee..0000000000 --- a/src/Ai/Base/ActionContext.h +++ /dev/null @@ -1,459 +0,0 @@ -/* - * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it - * and/or modify it under version 3 of the License, or (at your option), any later version. - */ - -#ifndef _PLAYERBOT_ACTIONCONTEXT_H -#define _PLAYERBOT_ACTIONCONTEXT_H - -#include "AddLootAction.h" -#include "AttackAction.h" -#include "ShareQuestAction.h" -#include "BattleGroundTactics.h" -#include "AutoMaintenanceOnLevelupAction.h" -#include "BattleGroundJoinAction.h" -#include "BattleGroundTactics.h" -#include "BuyAction.h" -#include "CastCustomSpellAction.h" -#include "ChangeStrategyAction.h" -#include "ChangeTalentsAction.h" -#include "CheckMailAction.h" -#include "CheckValuesAction.h" -#include "ChooseRpgTargetAction.h" -#include "ChooseTargetActions.h" -#include "ChooseTravelTargetAction.h" -#include "CombatActions.h" -#include "DelayAction.h" -#include "DestroyItemAction.h" -#include "EmoteAction.h" -#include "FollowActions.h" -#include "GenericActions.h" -#include "GenericSpellActions.h" -#include "GiveItemAction.h" -#include "GreetAction.h" -#include "GuildAcceptAction.h" -#include "GuildCreateActions.h" -#include "GuildManagementActions.h" -#include "ImbueAction.h" -#include "InviteToGroupAction.h" -#include "LeaveGroupAction.h" -#include "LootAction.h" -#include "LootRollAction.h" -#include "MoveToRpgTargetAction.h" -#include "MoveToTravelTargetAction.h" -#include "MovementActions.h" -#include "NonCombatActions.h" -#include "OutfitAction.h" -#include "PositionAction.h" -#include "DropQuestAction.h" -#include "RandomBotUpdateAction.h" -#include "ReachTargetActions.h" -#include "ReleaseSpiritAction.h" -#include "RemoveAuraAction.h" -#include "ResetInstancesAction.h" -#include "RevealGatheringItemAction.h" -#include "RpgAction.h" -#include "RpgSubActions.h" -#include "RtiAction.h" -#include "SayAction.h" -#include "StayActions.h" -#include "SuggestWhatToDoAction.h" -#include "TravelAction.h" -#include "VehicleActions.h" -#include "WorldBuffAction.h" -#include "XpGainAction.h" -#include "NewRpgAction.h" -#include "FishingAction.h" -#include "CancelChannelAction.h" - -class PlayerbotAI; - -class ActionContext : public NamedObjectContext -{ -public: - ActionContext() - { - creators["mark rti"] = &ActionContext::mark_rti; - creators["set return position"] = &ActionContext::set_return_position; - creators["rpg"] = &ActionContext::rpg; - creators["crpg"] = &ActionContext::crpg; - creators["choose rpg target"] = &ActionContext::choose_rpg_target; - creators["move to rpg target"] = &ActionContext::move_to_rpg_target; - creators["travel"] = &ActionContext::travel; - creators["choose travel target"] = &ActionContext::choose_travel_target; - creators["move to travel target"] = &ActionContext::move_to_travel_target; - creators["move out of collision"] = &ActionContext::move_out_of_collision; - creators["move random"] = &ActionContext::move_random; - creators["attack"] = &ActionContext::melee; - creators["melee"] = &ActionContext::melee; - creators["switch to melee"] = &ActionContext::switch_to_melee; - creators["switch to ranged"] = &ActionContext::switch_to_ranged; - creators["reach spell"] = &ActionContext::ReachSpell; - creators["reach melee"] = &ActionContext::ReachMelee; - creators["reach party member to heal"] = &ActionContext::reach_party_member_to_heal; - creators["reach party member to resurrect"] = &ActionContext::reach_party_member_to_resurrect; - creators["flee"] = &ActionContext::flee; - creators["flee with pet"] = &ActionContext::flee_with_pet; - creators["avoid aoe"] = &ActionContext::avoid_aoe; - creators["combat formation move"] = &ActionContext::combat_formation_move; - creators["tank face"] = &ActionContext::tank_face; - creators["rear flank"] = &ActionContext::rear_flank; - creators["disperse set"] = &ActionContext::disperse_set; - creators["gift of the naaru"] = &ActionContext::gift_of_the_naaru; - creators["shoot"] = &ActionContext::shoot; - creators["lifeblood"] = &ActionContext::lifeblood; - creators["arcane torrent"] = &ActionContext::arcane_torrent; - creators["end pull"] = &ActionContext::end_pull; - creators["healthstone"] = &ActionContext::healthstone; - creators["healing potion"] = &ActionContext::healing_potion; - creators["mana potion"] = &ActionContext::mana_potion; - creators["food"] = &ActionContext::food; - creators["drink"] = &ActionContext::drink; - creators["tank assist"] = &ActionContext::tank_assist; - creators["dps assist"] = &ActionContext::dps_assist; - creators["dps aoe"] = &ActionContext::dps_aoe; - creators["attack rti target"] = &ActionContext::attack_rti_target; - creators["loot"] = &ActionContext::loot; - creators["add loot"] = &ActionContext::add_loot; - creators["add gathering loot"] = &ActionContext::add_gathering_loot; - creators["add all loot"] = &ActionContext::add_all_loot; - creators["release loot"] = &ActionContext::release_loot; - creators["shoot"] = &ActionContext::shoot; - creators["follow"] = &ActionContext::follow; - creators["move from group"] = &ActionContext::move_from_group; - creators["flee to group leader"] = &ActionContext::flee_to_group_leader; - creators["runaway"] = &ActionContext::runaway; - creators["stay"] = &ActionContext::stay; - creators["sit"] = &ActionContext::sit; - creators["attack anything"] = &ActionContext::attack_anything; - creators["attack least hp target"] = &ActionContext::attack_least_hp_target; - creators["attack enemy player"] = &ActionContext::attack_enemy_player; - creators["emote"] = &ActionContext::emote; - creators["talk"] = &ActionContext::talk; - creators["suggest what to do"] = &ActionContext::suggest_what_to_do; - creators["suggest trade"] = &ActionContext::suggest_trade; - creators["suggest dungeon"] = &ActionContext::suggest_dungeon; - creators["return"] = &ActionContext::_return; - creators["move to loot"] = &ActionContext::move_to_loot; - creators["open loot"] = &ActionContext::open_loot; - creators["guard"] = &ActionContext::guard; - creators["return to stay position"] = &ActionContext::return_to_stay_position; - creators["move out of enemy contact"] = &ActionContext::move_out_of_enemy_contact; - creators["set facing"] = &ActionContext::set_facing; - creators["set behind"] = &ActionContext::set_behind; - creators["attack duel opponent"] = &ActionContext::attack_duel_opponent; - creators["drop target"] = &ActionContext::drop_target; - creators["check mail"] = &ActionContext::check_mail; - creators["say"] = &ActionContext::say; - creators["reveal gathering item"] = &ActionContext::reveal_gathering_item; - creators["outfit"] = &ActionContext::outfit; - creators["random bot update"] = &ActionContext::random_bot_update; - creators["delay"] = &ActionContext::delay; - creators["greet"] = &ActionContext::greet; - creators["check values"] = &ActionContext::check_values; - creators["ra"] = &ActionContext::ra; - creators["apply poison"] = &ActionContext::apply_poison; - creators["apply stone"] = &ActionContext::apply_stone; - creators["apply oil"] = &ActionContext::apply_oil; - creators["try emergency"] = &ActionContext::try_emergency; - creators["give food"] = &ActionContext::give_food; - creators["give water"] = &ActionContext::give_water; - creators["mount"] = &ActionContext::mount; - creators["war stomp"] = &ActionContext::war_stomp; - creators["blood fury"] = &ActionContext::blood_fury; - creators["berserking"] = &ActionContext::berserking; - creators["use trinket"] = &ActionContext::use_trinket; - creators["auto talents"] = &ActionContext::auto_talents; - creators["auto share quest"] = &ActionContext::auto_share_quest; - creators["auto maintenance on levelup"] = &ActionContext::auto_maintenance_on_levelup; - creators["xp gain"] = &ActionContext::xp_gain; - creators["invite nearby"] = &ActionContext::invite_nearby; - creators["invite guild"] = &ActionContext::invite_guild; - creators["leave far away"] = &ActionContext::leave_far_away; - creators["move to dark portal"] = &ActionContext::move_to_dark_portal; - creators["move from dark portal"] = &ActionContext::move_from_dark_portal; - creators["use dark portal azeroth"] = &ActionContext::use_dark_portal_azeroth; - creators["world buff"] = &ActionContext::world_buff; - creators["hearthstone"] = &ActionContext::hearthstone; - creators["cast random spell"] = &ActionContext::cast_random_spell; - creators["free bg join"] = &ActionContext::free_bg_join; - creators["use random recipe"] = &ActionContext::use_random_recipe; - creators["use random quest item"] = &ActionContext::use_random_quest_item; - creators["craft random item"] = &ActionContext::craft_random_item; - creators["smart destroy item"] = &ActionContext::smart_destroy_item; - creators["disenchant random item"] = &ActionContext::disenchant_random_item; - creators["enchant random item"] = &ActionContext::enchant_random_item; - creators["reset instances"] = &ActionContext::reset_instances; - creators["buy petition"] = &ActionContext::buy_petition; - creators["offer petition"] = &ActionContext::offer_petition; - creators["offer petition nearby"] = &ActionContext::offer_petition_nearby; - creators["turn in petition"] = &ActionContext::turn_in_petition; - creators["buy tabard"] = &ActionContext::buy_tabard; - creators["guild manage nearby"] = &ActionContext::guild_manage_nearby; - creators["clean quest log"] = &ActionContext::clean_quest_log; - creators["move near water"] = &ActionContext::move_near_water; - creators["go fishing"] = &ActionContext::go_fishing; - creators["use fishing bobber"] = &ActionContext::use_fishing_bobber; - creators["end master fishing"] = &ActionContext::end_master_fishing; - creators["remove bobber strategy"] = &ActionContext::remove_bobber_strategy; - creators["roll"] = &ActionContext::roll_action; - creators["cancel channel"] = &ActionContext::cancel_channel; - - // BG Tactics - creators["bg tactics"] = &ActionContext::bg_tactics; - creators["bg move to start"] = &ActionContext::bg_move_to_start; - creators["bg reset objective force"] = &ActionContext::bg_reset_objective_force; - creators["bg move to objective"] = &ActionContext::bg_move_to_objective; - creators["bg select objective"] = &ActionContext::bg_select_objective; - creators["bg check objective"] = &ActionContext::bg_check_objective; - creators["bg attack fc"] = &ActionContext::bg_attack_fc; - creators["bg protect fc"] = &ActionContext::bg_protect_fc; - creators["bg use buff"] = &ActionContext::bg_use_buff; - creators["attack enemy flag carrier"] = &ActionContext::attack_enemy_fc; - creators["bg check flag"] = &ActionContext::bg_check_flag; - - // Vehicles - creators["enter vehicle"] = &ActionContext::enter_vehicle; - creators["leave vehicle"] = &ActionContext::leave_vehicle; - creators["hurl boulder"] = &ActionContext::hurl_boulder; - creators["ram"] = &ActionContext::ram; - creators["steam rush"] = &ActionContext::steam_rush; - creators["steam blast"] = &ActionContext::steam_blast; - creators["napalm"] = &ActionContext::napalm; - creators["fire cannon"] = &ActionContext::fire_cannon; - creators["incendiary rocket"] = &ActionContext::incendiary_rocket; - creators["rocket blast"] = &ActionContext::rocket_blast; - creators["blade salvo"] = &ActionContext::blade_salvo; - creators["glaive throw"] = &ActionContext::glaive_throw; - - //Rpg - creators["rpg stay"] = &ActionContext::rpg_stay; - creators["rpg work"] = &ActionContext::rpg_work; - creators["rpg emote"] = &ActionContext::rpg_emote; - creators["rpg cancel"] = &ActionContext::rpg_cancel; - creators["rpg taxi"] = &ActionContext::rpg_taxi; - creators["rpg discover"] = &ActionContext::rpg_discover; - creators["rpg start quest"] = &ActionContext::rpg_start_quest; - creators["rpg end quest"] = &ActionContext::rpg_end_quest; - creators["rpg buy"] = &ActionContext::rpg_buy; - creators["rpg sell"] = &ActionContext::rpg_sell; - creators["rpg repair"] = &ActionContext::rpg_repair; - creators["rpg train"] = &ActionContext::rpg_train; - creators["rpg heal"] = &ActionContext::rpg_heal; - creators["rpg home bind"] = &ActionContext::rpg_home_bind; - creators["rpg queue bg"] = &ActionContext::rpg_queue_bg; - creators["rpg buy petition"] = &ActionContext::rpg_buy_petition; - creators["rpg use"] = &ActionContext::rpg_use; - creators["rpg spell"] = &ActionContext::rpg_spell; - creators["rpg craft"] = &ActionContext::rpg_craft; - creators["rpg trade useful"] = &ActionContext::rpg_trade_useful; - creators["rpg duel"] = &ActionContext::rpg_duel; - creators["rpg mount anim"] = &ActionContext::rpg_mount_anim; - - creators["toggle pet spell"] = &ActionContext::toggle_pet_spell; - creators["pet attack"] = &ActionContext::pet_attack; - creators["set pet stance"] = &ActionContext::set_pet_stance; - - creators["new rpg status update"] = &ActionContext::new_rpg_status_update; - creators["new rpg go grind"] = &ActionContext::new_rpg_go_grind; - creators["new rpg go camp"] = &ActionContext::new_rpg_go_camp; - creators["new rpg wander random"] = &ActionContext::new_rpg_wander_random; - creators["new rpg wander npc"] = &ActionContext::new_rpg_wander_npc; - creators["new rpg do quest"] = &ActionContext::new_rpg_do_quest; - creators["new rpg travel flight"] = &ActionContext::new_rpg_travel_flight; - } - -private: - static Action* give_water(PlayerbotAI* botAI) { return new GiveWaterAction(botAI); } - static Action* give_food(PlayerbotAI* botAI) { return new GiveFoodAction(botAI); } - static Action* ra(PlayerbotAI* botAI) { return new RemoveAuraAction(botAI); } - static Action* mark_rti(PlayerbotAI* botAI) { return new MarkRtiAction(botAI); } - static Action* set_return_position(PlayerbotAI* botAI) { return new SetReturnPositionAction(botAI); } - static Action* rpg(PlayerbotAI* botAI) { return new RpgAction(botAI); } - static Action* crpg(PlayerbotAI* botAI) { return new CRpgAction(botAI); } - static Action* choose_rpg_target(PlayerbotAI* botAI) { return new ChooseRpgTargetAction(botAI); } - static Action* move_to_rpg_target(PlayerbotAI* botAI) { return new MoveToRpgTargetAction(botAI); } - static Action* travel(PlayerbotAI* botAI) { return new TravelAction(botAI); } - static Action* choose_travel_target(PlayerbotAI* botAI) { return new ChooseTravelTargetAction(botAI); } - static Action* move_to_travel_target(PlayerbotAI* botAI) { return new MoveToTravelTargetAction(botAI); } - static Action* move_out_of_collision(PlayerbotAI* botAI) { return new MoveOutOfCollisionAction(botAI); } - static Action* move_random(PlayerbotAI* botAI) { return new MoveRandomAction(botAI); } - static Action* check_values(PlayerbotAI* botAI) { return new CheckValuesAction(botAI); } - static Action* greet(PlayerbotAI* botAI) { return new GreetAction(botAI); } - static Action* check_mail(PlayerbotAI* botAI) { return new CheckMailAction(botAI); } - static Action* drop_target(PlayerbotAI* botAI) { return new DropTargetAction(botAI); } - static Action* attack_duel_opponent(PlayerbotAI* botAI) { return new AttackDuelOpponentAction(botAI); } - static Action* guard(PlayerbotAI* botAI) { return new GuardAction(botAI); } - static Action* return_to_stay_position(PlayerbotAI* botAI) { return new ReturnToStayPositionAction(botAI); } - static Action* open_loot(PlayerbotAI* botAI) { return new OpenLootAction(botAI); } - static Action* move_to_loot(PlayerbotAI* botAI) { return new MoveToLootAction(botAI); } - static Action* _return(PlayerbotAI* botAI) { return new ReturnAction(botAI); } - static Action* shoot(PlayerbotAI* botAI) { return new CastShootAction(botAI); } - static Action* melee(PlayerbotAI* botAI) { return new MeleeAction(botAI); } - static Action* switch_to_melee(PlayerbotAI* botAI) { return new SwitchToMeleeAction(botAI); } - static Action* switch_to_ranged(PlayerbotAI* botAI) { return new SwitchToRangedAction(botAI); } - static Action* ReachSpell(PlayerbotAI* botAI) { return new ReachSpellAction(botAI); } - static Action* ReachMelee(PlayerbotAI* botAI) { return new ReachMeleeAction(botAI); } - static Action* reach_party_member_to_heal(PlayerbotAI* botAI) { return new ReachPartyMemberToHealAction(botAI); } - static Action* reach_party_member_to_resurrect(PlayerbotAI* botAI) { return new ReachPartyMemberToResurrectAction(botAI); } - static Action* flee(PlayerbotAI* botAI) { return new FleeAction(botAI); } - static Action* flee_with_pet(PlayerbotAI* botAI) { return new FleeWithPetAction(botAI); } - static Action* avoid_aoe(PlayerbotAI* botAI) { return new AvoidAoeAction(botAI); } - static Action* combat_formation_move(PlayerbotAI* botAI) { return new CombatFormationMoveAction(botAI); } - static Action* tank_face(PlayerbotAI* botAI) { return new TankFaceAction(botAI); } - static Action* rear_flank(PlayerbotAI* botAI) { return new RearFlankAction(botAI); } - static Action* disperse_set(PlayerbotAI* botAI) { return new DisperseSetAction(botAI); } - static Action* gift_of_the_naaru(PlayerbotAI* botAI) { return new CastGiftOfTheNaaruAction(botAI); } - static Action* lifeblood(PlayerbotAI* botAI) { return new CastLifeBloodAction(botAI); } - static Action* arcane_torrent(PlayerbotAI* botAI) { return new CastArcaneTorrentAction(botAI); } - static Action* mana_tap(PlayerbotAI* botAI) { return new CastManaTapAction(botAI); } - static Action* end_pull(PlayerbotAI* botAI) { return new ChangeCombatStrategyAction(botAI, "-pull"); } - static Action* cancel_channel(PlayerbotAI* botAI) { return new CancelChannelAction(botAI); } - - static Action* emote(PlayerbotAI* botAI) { return new EmoteAction(botAI); } - static Action* talk(PlayerbotAI* botAI) { return new TalkAction(botAI); } - static Action* suggest_what_to_do(PlayerbotAI* botAI) { return new SuggestWhatToDoAction(botAI); } - static Action* suggest_trade(PlayerbotAI* botAI) { return new SuggestTradeAction(botAI); } - static Action* suggest_dungeon(PlayerbotAI* botAI) { return new SuggestDungeonAction(botAI); } - static Action* attack_anything(PlayerbotAI* botAI) { return new AttackAnythingAction(botAI); } - static Action* attack_least_hp_target(PlayerbotAI* botAI) { return new AttackLeastHpTargetAction(botAI); } - static Action* attack_enemy_player(PlayerbotAI* botAI) { return new AttackEnemyPlayerAction(botAI); } - static Action* stay(PlayerbotAI* botAI) { return new StayAction(botAI); } - static Action* sit(PlayerbotAI* botAI) { return new SitAction(botAI); } - static Action* runaway(PlayerbotAI* botAI) { return new RunAwayAction(botAI); } - static Action* follow(PlayerbotAI* botAI) { return new FollowAction(botAI); } - static Action* move_from_group(PlayerbotAI* botAI) { return new MoveFromGroupAction(botAI); } - static Action* flee_to_group_leader(PlayerbotAI* botAI) { return new FleeToGroupLeaderAction(botAI); } - static Action* add_gathering_loot(PlayerbotAI* botAI) { return new AddGatheringLootAction(botAI); } - static Action* add_loot(PlayerbotAI* botAI) { return new AddLootAction(botAI); } - static Action* add_all_loot(PlayerbotAI* botAI) { return new AddAllLootAction(botAI); } - static Action* loot(PlayerbotAI* botAI) { return new LootAction(botAI); } - static Action* release_loot(PlayerbotAI* botAI) { return new ReleaseLootAction(botAI); } - static Action* dps_assist(PlayerbotAI* botAI) { return new DpsAssistAction(botAI); } - static Action* dps_aoe(PlayerbotAI* botAI) { return new DpsAoeAction(botAI); } - static Action* attack_rti_target(PlayerbotAI* botAI) { return new AttackRtiTargetAction(botAI); } - static Action* tank_assist(PlayerbotAI* botAI) { return new TankAssistAction(botAI); } - static Action* drink(PlayerbotAI* botAI) { return new DrinkAction(botAI); } - static Action* food(PlayerbotAI* botAI) { return new EatAction(botAI); } - static Action* mana_potion(PlayerbotAI* botAI) { return new UseManaPotion(botAI); } - static Action* healing_potion(PlayerbotAI* botAI) { return new UseHealingPotion(botAI); } - static Action* healthstone(PlayerbotAI* botAI) { return new UseItemAction(botAI, "healthstone"); } - static Action* move_out_of_enemy_contact(PlayerbotAI* botAI) { return new MoveOutOfEnemyContactAction(botAI); } - static Action* set_facing(PlayerbotAI* botAI) { return new SetFacingTargetAction(botAI); } - static Action* set_behind(PlayerbotAI* botAI) { return new SetBehindTargetAction(botAI); } - static Action* say(PlayerbotAI* botAI) { return new SayAction(botAI); } - static Action* reveal_gathering_item(PlayerbotAI* botAI) { return new RevealGatheringItemAction(botAI); } - static Action* outfit(PlayerbotAI* botAI) { return new OutfitAction(botAI); } - static Action* random_bot_update(PlayerbotAI* botAI) { return new RandomBotUpdateAction(botAI); } - static Action* delay(PlayerbotAI* botAI) { return new DelayAction(botAI); } - - static Action* apply_poison(PlayerbotAI* botAI) { return new ImbueWithPoisonAction(botAI); } - static Action* apply_oil(PlayerbotAI* botAI) { return new ImbueWithOilAction(botAI); } - static Action* apply_stone(PlayerbotAI* botAI) { return new ImbueWithStoneAction(botAI); } - static Action* try_emergency(PlayerbotAI* botAI) { return new TryEmergencyAction(botAI); } - static Action* mount(PlayerbotAI* botAI) { return new CastSpellAction(botAI, "mount"); } - static Action* war_stomp(PlayerbotAI* botAI) { return new CastWarStompAction(botAI); } - static Action* blood_fury(PlayerbotAI* botAI) { return new CastBloodFuryAction(botAI); } - static Action* berserking(PlayerbotAI* botAI) { return new CastBerserkingAction(botAI); } - static Action* use_trinket(PlayerbotAI* botAI) { return new UseTrinketAction(botAI); } - static Action* auto_talents(PlayerbotAI* botAI) { return new AutoSetTalentsAction(botAI); } - static Action* auto_share_quest(PlayerbotAI* ai) { return new AutoShareQuestAction(ai); } - static Action* auto_maintenance_on_levelup(PlayerbotAI* botAI) { return new AutoMaintenanceOnLevelupAction(botAI); } - static Action* xp_gain(PlayerbotAI* botAI) { return new XpGainAction(botAI); } - static Action* invite_nearby(PlayerbotAI* botAI) { return new InviteNearbyToGroupAction(botAI); } - static Action* invite_guild(PlayerbotAI* botAI) { return new InviteGuildToGroupAction(botAI); } - static Action* leave_far_away(PlayerbotAI* botAI) { return new LeaveFarAwayAction(botAI); } - static Action* move_to_dark_portal(PlayerbotAI* botAI) { return new MoveToDarkPortalAction(botAI); } - static Action* use_dark_portal_azeroth(PlayerbotAI* botAI) { return new DarkPortalAzerothAction(botAI); } - static Action* move_from_dark_portal(PlayerbotAI* botAI) { return new MoveFromDarkPortalAction(botAI); } - static Action* world_buff(PlayerbotAI* botAI) { return new WorldBuffAction(botAI); } - static Action* hearthstone(PlayerbotAI* botAI) { return new UseHearthStone(botAI); } - static Action* cast_random_spell(PlayerbotAI* botAI) { return new CastRandomSpellAction(botAI); } - static Action* free_bg_join(PlayerbotAI* botAI) { return new FreeBGJoinAction(botAI); } - - static Action* use_random_recipe(PlayerbotAI* botAI) { return new UseRandomRecipe(botAI); } - static Action* use_random_quest_item(PlayerbotAI* botAI) { return new UseRandomQuestItem(botAI); } - static Action* craft_random_item(PlayerbotAI* botAI) { return new CraftRandomItemAction(botAI); } - static Action* smart_destroy_item(PlayerbotAI* botAI) { return new SmartDestroyItemAction(botAI); } - static Action* disenchant_random_item(PlayerbotAI* botAI) { return new DisEnchantRandomItemAction(botAI); } - static Action* enchant_random_item(PlayerbotAI* botAI) { return new EnchantRandomItemAction(botAI); } - static Action* reset_instances(PlayerbotAI* botAI) { return new ResetInstancesAction(botAI); } - static Action* buy_petition(PlayerbotAI* botAI) { return new BuyPetitionAction(botAI); } - static Action* offer_petition(PlayerbotAI* botAI) { return new PetitionOfferAction(botAI); } - static Action* offer_petition_nearby(PlayerbotAI* botAI) { return new PetitionOfferNearbyAction(botAI); } - static Action* turn_in_petition(PlayerbotAI* botAI) { return new PetitionTurnInAction(botAI); } - static Action* buy_tabard(PlayerbotAI* botAI) { return new BuyTabardAction(botAI); } - static Action* guild_manage_nearby(PlayerbotAI* botAI) { return new GuildManageNearbyAction(botAI); } - static Action* clean_quest_log(PlayerbotAI* botAI) { return new CleanQuestLogAction(botAI); } - static Action* move_near_water(PlayerbotAI* botAI) { return new MoveNearWaterAction(botAI); } - static Action* go_fishing(PlayerbotAI* botAI) { return new FishingAction(botAI);} - static Action* use_fishing_bobber(PlayerbotAI* botAI) { return new UseBobberAction(botAI);} - static Action* end_master_fishing(PlayerbotAI* botAI) { return new EndMasterFishingAction(botAI); } - static Action* remove_bobber_strategy(PlayerbotAI* botAI) { return new RemoveBobberStrategyAction(botAI); } - static Action* roll_action(PlayerbotAI* botAI) { return new RollAction(botAI); } - - // BG Tactics - static Action* bg_tactics(PlayerbotAI* botAI) { return new BGTactics(botAI); } - static Action* bg_move_to_start(PlayerbotAI* botAI) { return new BGTactics(botAI, "move to start"); } - static Action* bg_reset_objective_force(PlayerbotAI* botAI) { return new BGTactics(botAI, "reset objective force"); } - static Action* bg_move_to_objective(PlayerbotAI* botAI) { return new BGTactics(botAI, "move to objective"); } - static Action* bg_select_objective(PlayerbotAI* botAI) { return new BGTactics(botAI, "select objective"); } - static Action* bg_check_objective(PlayerbotAI* botAI) { return new BGTactics(botAI, "check objective"); } - static Action* bg_attack_fc(PlayerbotAI* botAI) { return new BGTactics(botAI, "attack fc"); } - static Action* bg_protect_fc(PlayerbotAI* botAI) { return new BGTactics(botAI, "protect fc"); } - static Action* attack_enemy_fc(PlayerbotAI* botAI) { return new AttackEnemyFlagCarrierAction(botAI); } - static Action* bg_use_buff(PlayerbotAI* botAI) { return new BGTactics(botAI, "use buff"); } - static Action* bg_check_flag(PlayerbotAI* botAI) { return new BGTactics(botAI, "check flag"); } - - // Vehicles - static Action* enter_vehicle(PlayerbotAI* botAI) { return new EnterVehicleAction(botAI); } - static Action* leave_vehicle(PlayerbotAI* botAI) { return new LeaveVehicleAction(botAI); } - static Action* hurl_boulder(PlayerbotAI* botAI) { return new CastHurlBoulderAction(botAI); } - static Action* ram(PlayerbotAI* botAI) { return new CastRamAction(botAI); } - static Action* steam_blast(PlayerbotAI* botAI) { return new CastSteamBlastAction(botAI); } - static Action* steam_rush(PlayerbotAI* botAI) { return new CastSteamRushAction(botAI); } - static Action* napalm(PlayerbotAI* botAI) { return new CastNapalmAction(botAI); } - static Action* fire_cannon(PlayerbotAI* botAI) { return new CastFireCannonAction(botAI); } - static Action* incendiary_rocket(PlayerbotAI* botAI) { return new CastIncendiaryRocketAction(botAI); } - static Action* rocket_blast(PlayerbotAI* botAI) { return new CastRocketBlastAction(botAI); } - static Action* glaive_throw(PlayerbotAI* botAI) { return new CastGlaiveThrowAction(botAI); } - static Action* blade_salvo(PlayerbotAI* botAI) { return new CastBladeSalvoAction(botAI); } - - // Rpg - static Action* rpg_stay(PlayerbotAI* botAI) { return new RpgStayAction(botAI); } - static Action* rpg_work(PlayerbotAI* botAI) { return new RpgWorkAction(botAI); } - static Action* rpg_emote(PlayerbotAI* botAI) { return new RpgEmoteAction(botAI); } - static Action* rpg_cancel(PlayerbotAI* botAI) { return new RpgCancelAction(botAI); } - static Action* rpg_taxi(PlayerbotAI* botAI) { return new RpgTaxiAction(botAI); } - static Action* rpg_discover(PlayerbotAI* botAI) { return new RpgDiscoverAction(botAI); } - static Action* rpg_start_quest(PlayerbotAI* botAI) { return new RpgStartQuestAction(botAI); } - static Action* rpg_end_quest(PlayerbotAI* botAI) { return new RpgEndQuestAction(botAI); } - static Action* rpg_buy(PlayerbotAI* botAI) { return new RpgBuyAction(botAI); } - static Action* rpg_sell(PlayerbotAI* botAI) { return new RpgSellAction(botAI); } - static Action* rpg_repair(PlayerbotAI* botAI) { return new RpgRepairAction(botAI); } - static Action* rpg_train(PlayerbotAI* botAI) { return new RpgTrainAction(botAI); } - static Action* rpg_heal(PlayerbotAI* botAI) { return new RpgHealAction(botAI); } - static Action* rpg_home_bind(PlayerbotAI* botAI) { return new RpgHomeBindAction(botAI); } - static Action* rpg_queue_bg(PlayerbotAI* botAI) { return new RpgQueueBgAction(botAI); } - static Action* rpg_buy_petition(PlayerbotAI* botAI) { return new RpgBuyPetitionAction(botAI); } - static Action* rpg_use(PlayerbotAI* botAI) { return new RpgUseAction(botAI); } - static Action* rpg_spell(PlayerbotAI* botAI) { return new RpgSpellAction(botAI); } - static Action* rpg_craft(PlayerbotAI* botAI) { return new RpgCraftAction(botAI); } - static Action* rpg_trade_useful(PlayerbotAI* botAI) { return new RpgTradeUsefulAction(botAI); } - static Action* rpg_duel(PlayerbotAI* botAI) { return new RpgDuelAction(botAI); } - static Action* rpg_mount_anim(PlayerbotAI* botAI) { return new RpgMountAnimAction(botAI); } - - static Action* toggle_pet_spell(PlayerbotAI* ai) { return new TogglePetSpellAutoCastAction(ai); } - static Action* pet_attack(PlayerbotAI* ai) { return new PetAttackAction(ai); } - static Action* set_pet_stance(PlayerbotAI* ai) { return new SetPetStanceAction(ai); } - - static Action* new_rpg_status_update(PlayerbotAI* ai) { return new NewRpgStatusUpdateAction(ai); } - static Action* new_rpg_go_grind(PlayerbotAI* ai) { return new NewRpgGoGrindAction(ai); } - static Action* new_rpg_go_camp(PlayerbotAI* ai) { return new NewRpgGoCampAction(ai); } - static Action* new_rpg_wander_random(PlayerbotAI* ai) { return new NewRpgWanderRandomAction(ai); } - static Action* new_rpg_wander_npc(PlayerbotAI* ai) { return new NewRpgWanderNpcAction(ai); } - static Action* new_rpg_do_quest(PlayerbotAI* ai) { return new NewRpgDoQuestAction(ai); } - static Action* new_rpg_travel_flight(PlayerbotAI* ai) { return new NewRpgTravelFlightAction(ai); } -}; - -#endif diff --git a/src/Ai/Base/Actions/AcceptBattlegroundInvitationAction.cpp b/src/Ai/Base/Actions/AcceptBattlegroundInvitationAction.cpp index 96d61d4ba3..e302927ac8 100644 --- a/src/Ai/Base/Actions/AcceptBattlegroundInvitationAction.cpp +++ b/src/Ai/Base/Actions/AcceptBattlegroundInvitationAction.cpp @@ -6,9 +6,9 @@ #include "AcceptBattlegroundInvitationAction.h" #include "Event.h" -#include "Playerbots.h" +#include "PlayerbotAI.h" -bool AcceptBgInvitationAction::Execute(Event event) +bool AcceptBgInvitationAction::Execute(Event) { uint8 type = 0; // arenatype if arena uint8 unk2 = 0; // unk, can be 0x0 (may be if was invited?) and 0x1 @@ -18,9 +18,9 @@ bool AcceptBgInvitationAction::Execute(Event event) WorldPacket packet(CMSG_BATTLEFIELD_PORT, 20); packet << type << unk2 << (uint32)bgTypeId_ << unk << action; - // packet << bgTypeId_ << action; bot->GetSession()->HandleBattleFieldPortOpcode(packet); botAI->ResetStrategies(); + return true; } diff --git a/src/Ai/Base/Actions/AcceptInvitationAction.cpp b/src/Ai/Base/Actions/AcceptInvitationAction.cpp index 5e0bffc47f..1be3c0921a 100644 --- a/src/Ai/Base/Actions/AcceptInvitationAction.cpp +++ b/src/Ai/Base/Actions/AcceptInvitationAction.cpp @@ -46,10 +46,10 @@ bool AcceptInvitationAction::Execute(Event event) if (!bot->GetGroup() || !bot->GetGroup()->IsMember(inviter->GetGUID())) return false; - if (sRandomPlayerbotMgr->IsRandomBot(bot)) + if (sRandomPlayerbotMgr.IsRandomBot(bot)) botAI->SetMaster(inviter); // else - // sPlayerbotRepository->Save(botAI); + // PlayerbotRepository::instance().Save(botAI); botAI->ResetStrategies(); botAI->ChangeStrategy("+follow,-lfg,-bg", BOT_STATE_NON_COMBAT); @@ -57,7 +57,7 @@ bool AcceptInvitationAction::Execute(Event event) botAI->TellMaster("Hello"); - if (sPlayerbotAIConfig->summonWhenGroup && bot->GetDistance(inviter) > sPlayerbotAIConfig->sightDistance) + if (sPlayerbotAIConfig.summonWhenGroup && bot->GetDistance(inviter) > sPlayerbotAIConfig.sightDistance) { Teleport(inviter, bot, true); } diff --git a/src/Ai/Base/Actions/AddLootAction.cpp b/src/Ai/Base/Actions/AddLootAction.cpp index 9e16ee2d3a..0b6a85d29a 100644 --- a/src/Ai/Base/Actions/AddLootAction.cpp +++ b/src/Ai/Base/Actions/AddLootAction.cpp @@ -22,7 +22,7 @@ bool AddLootAction::Execute(Event event) return AI_VALUE(LootObjectStack*, "available loot")->Add(guid); } -bool AddAllLootAction::Execute(Event event) +bool AddAllLootAction::Execute(Event) { bool added = false; diff --git a/src/Ai/Base/Actions/AreaTriggerAction.cpp b/src/Ai/Base/Actions/AreaTriggerAction.cpp index f480277825..77e992b5ca 100644 --- a/src/Ai/Base/Actions/AreaTriggerAction.cpp +++ b/src/Ai/Base/Actions/AreaTriggerAction.cpp @@ -50,7 +50,7 @@ bool ReachAreaTriggerAction::Execute(Event event) /*forceDestination*/ false); float distance = bot->GetDistance(at->x, at->y, at->z); - float delay = 1000.0f * distance / bot->GetSpeed(MOVE_RUN) + sPlayerbotAIConfig->reactDelay; + float delay = 1000.0f * distance / bot->GetSpeed(MOVE_RUN) + sPlayerbotAIConfig.reactDelay; botAI->TellError("Wait for me"); botAI->SetNextCheckDelay(delay); context->GetValue("last area trigger")->Get().lastAreaTrigger = triggerId; @@ -58,7 +58,7 @@ bool ReachAreaTriggerAction::Execute(Event event) return true; } -bool AreaTriggerAction::Execute(Event event) +bool AreaTriggerAction::Execute(Event) { LastMovement& movement = context->GetValue("last area trigger")->Get(); diff --git a/src/Ai/Base/Actions/AttackAction.cpp b/src/Ai/Base/Actions/AttackAction.cpp index 2b8c486f8b..87bbd31c6b 100644 --- a/src/Ai/Base/Actions/AttackAction.cpp +++ b/src/Ai/Base/Actions/AttackAction.cpp @@ -87,8 +87,8 @@ bool AttackAction::Attack(Unit* target, bool /*with_pet*/ /*true*/) // Check if bot OR target is in prohibited zone/area (skip for duels) if ((target->IsPlayer() || target->IsPet()) && (!bot->duel || bot->duel->Opponent != target) && - (sPlayerbotAIConfig->IsPvpProhibited(bot->GetZoneId(), bot->GetAreaId()) || - sPlayerbotAIConfig->IsPvpProhibited(target->GetZoneId(), target->GetAreaId()))) + (sPlayerbotAIConfig.IsPvpProhibited(bot->GetZoneId(), bot->GetAreaId()) || + sPlayerbotAIConfig.IsPvpProhibited(target->GetZoneId(), target->GetAreaId()))) { if (verbose) botAI->TellError("I cannot attack other players in PvP prohibited areas."); @@ -160,7 +160,7 @@ bool AttackAction::Attack(Unit* target, bool /*with_pet*/ /*true*/) } if (botAI->CanMove() && !bot->HasInArc(CAST_ANGLE_IN_FRONT, target)) - sServerFacade->SetFacingTo(bot, target); + ServerFacade::instance().SetFacingTo(bot, target); botAI->ChangeEngine(BOT_STATE_COMBAT); diff --git a/src/Ai/Base/Actions/AutoMaintenanceOnLevelupAction.cpp b/src/Ai/Base/Actions/AutoMaintenanceOnLevelupAction.cpp index 6939e5c925..2a92715afa 100644 --- a/src/Ai/Base/Actions/AutoMaintenanceOnLevelupAction.cpp +++ b/src/Ai/Base/Actions/AutoMaintenanceOnLevelupAction.cpp @@ -1,25 +1,26 @@ #include "AutoMaintenanceOnLevelupAction.h" -#include "GuildMgr.h" +#include "SpellMgr.h" + #include "PlayerbotAIConfig.h" #include "PlayerbotFactory.h" -#include "Playerbots.h" #include "RandomPlayerbotMgr.h" #include "SharedDefines.h" #include "BroadcastHelper.h" -bool AutoMaintenanceOnLevelupAction::Execute(Event event) +bool AutoMaintenanceOnLevelupAction::Execute(Event) { AutoPickTalents(); AutoLearnSpell(); AutoUpgradeEquip(); AutoTeleportForLevel(); + return true; } void AutoMaintenanceOnLevelupAction::AutoTeleportForLevel() { - if (!sPlayerbotAIConfig->autoTeleportForLevel || !sRandomPlayerbotMgr->IsRandomBot(bot)) + if (!sPlayerbotAIConfig.autoTeleportForLevel || !sRandomPlayerbotMgr.IsRandomBot(bot)) { return; } @@ -27,13 +28,13 @@ void AutoMaintenanceOnLevelupAction::AutoTeleportForLevel() { return; } - sRandomPlayerbotMgr->RandomTeleportForLevel(bot); + sRandomPlayerbotMgr.RandomTeleportForLevel(bot); return; } void AutoMaintenanceOnLevelupAction::AutoPickTalents() { - if (!sPlayerbotAIConfig->autoPickTalents || !sRandomPlayerbotMgr->IsRandomBot(bot)) + if (!sPlayerbotAIConfig.autoPickTalents || !sRandomPlayerbotMgr.IsRandomBot(bot)) return; if (bot->GetFreeTalentPoints() <= 0) @@ -65,14 +66,14 @@ void AutoMaintenanceOnLevelupAction::AutoLearnSpell() void AutoMaintenanceOnLevelupAction::LearnSpells(std::ostringstream* out) { BroadcastHelper::BroadcastLevelup(botAI, bot); - if (sPlayerbotAIConfig->autoLearnTrainerSpells && sRandomPlayerbotMgr->IsRandomBot(bot)) + if (sPlayerbotAIConfig.autoLearnTrainerSpells && sRandomPlayerbotMgr.IsRandomBot(bot)) LearnTrainerSpells(out); - if (sPlayerbotAIConfig->autoLearnQuestSpells && sRandomPlayerbotMgr->IsRandomBot(bot)) + if (sPlayerbotAIConfig.autoLearnQuestSpells && sRandomPlayerbotMgr.IsRandomBot(bot)) LearnQuestSpells(out); } -void AutoMaintenanceOnLevelupAction::LearnTrainerSpells(std::ostringstream* out) +void AutoMaintenanceOnLevelupAction::LearnTrainerSpells(std::ostringstream*) { PlayerbotFactory factory(bot, bot->GetLevel()); factory.InitSkills(); @@ -166,7 +167,7 @@ std::string const AutoMaintenanceOnLevelupAction::FormatSpell(SpellInfo const* s void AutoMaintenanceOnLevelupAction::AutoUpgradeEquip() { - if (!sPlayerbotAIConfig->autoUpgradeEquip || !sRandomPlayerbotMgr->IsRandomBot(bot)) + if (!sPlayerbotAIConfig.autoUpgradeEquip || !sRandomPlayerbotMgr.IsRandomBot(bot)) return; PlayerbotFactory factory(bot, bot->GetLevel()); @@ -180,9 +181,9 @@ void AutoMaintenanceOnLevelupAction::AutoUpgradeEquip() factory.InitConsumables(); factory.InitPotions(); - if (!sPlayerbotAIConfig->equipmentPersistence || bot->GetLevel() < sPlayerbotAIConfig->equipmentPersistenceLevel) + if (!sPlayerbotAIConfig.equipmentPersistence || bot->GetLevel() < sPlayerbotAIConfig.equipmentPersistenceLevel) { - if (sPlayerbotAIConfig->incrementalGearInit) + if (sPlayerbotAIConfig.incrementalGearInit) factory.InitEquipment(true); } } diff --git a/src/Ai/Base/Actions/BankAction.cpp b/src/Ai/Base/Actions/BankAction.cpp index 4d8d6c4d8c..1e6a0bc93f 100644 --- a/src/Ai/Base/Actions/BankAction.cpp +++ b/src/Ai/Base/Actions/BankAction.cpp @@ -27,7 +27,7 @@ bool BankAction::Execute(Event event) return false; } -bool BankAction::ExecuteBank(std::string const text, Unit* bank) +bool BankAction::ExecuteBank(std::string const text, Unit*) { if (text.empty() || text == "?") { diff --git a/src/Ai/Base/Actions/BattleGroundJoinAction.cpp b/src/Ai/Base/Actions/BattleGroundJoinAction.cpp index 542c7566ff..3107f39873 100644 --- a/src/Ai/Base/Actions/BattleGroundJoinAction.cpp +++ b/src/Ai/Base/Actions/BattleGroundJoinAction.cpp @@ -13,9 +13,8 @@ #include "PlayerbotAI.h" #include "Playerbots.h" #include "PositionValue.h" -#include "UpdateTime.h" -bool BGJoinAction::Execute(Event event) +bool BGJoinAction::Execute(Event) { uint32 queueType = AI_VALUE(uint32, "bg type"); if (!queueType) // force join to fill bg @@ -25,8 +24,6 @@ bool BGJoinAction::Execute(Event event) BattlegroundQueueTypeId queueTypeId = (BattlegroundQueueTypeId)bgList[urand(0, bgList.size() - 1)]; BattlegroundTypeId bgTypeId = BattlegroundMgr::BGTemplateId(queueTypeId); - BattlegroundBracketId bracketId; - bool isArena = false; bool isRated = false; Battleground* bg = sBattlegroundMgr->GetBattlegroundTemplate(bgTypeId); @@ -38,12 +35,8 @@ bool BGJoinAction::Execute(Event event) if (!pvpDiff) return false; - bracketId = pvpDiff->GetBracketId(); - if (ArenaType type = ArenaType(BattlegroundMgr::BGArenaType(queueTypeId))) { - isArena = true; - std::vector::iterator i = find(ratedList.begin(), ratedList.end(), queueTypeId); if (i != ratedList.end()) isRated = true; @@ -89,7 +82,7 @@ bool BGJoinAction::gatherArenaTeam(ArenaType type) // continue; if (offline) - sRandomPlayerbotMgr->AddPlayerBot(itr->Guid, 0); + sRandomPlayerbotMgr.AddPlayerBot(itr->Guid, 0); if (member) { @@ -100,7 +93,7 @@ bool BGJoinAction::gatherArenaTeam(ArenaType type) if (member->GetGroup() && memberBotAI->HasRealPlayerMaster()) continue; - if (!sPlayerbotAIConfig->IsInRandomAccountList(member->GetSession()->GetAccountId())) + if (!sPlayerbotAIConfig.IsInRandomAccountList(member->GetSession()->GetAccountId())) continue; if (member->IsInCombat()) @@ -250,13 +243,13 @@ bool BGJoinAction::shouldJoinBg(BattlegroundQueueTypeId queueTypeId, Battlegroun TeamSize = (uint32)type; // Check if bots should join Rated Arena (Only captains can queue) - uint32 ratedArenaBotCount = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].ratedArenaBotCount; + uint32 ratedArenaBotCount = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].ratedArenaBotCount; uint32 ratedArenaPlayerCount = - sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].ratedArenaPlayerCount; + sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].ratedArenaPlayerCount; uint32 ratedArenaInstanceCount = - sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].ratedArenaInstanceCount; + sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].ratedArenaInstanceCount; uint32 activeRatedArenaQueue = - sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].activeRatedArenaQueue; + sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].activeRatedArenaQueue; bool isRated = (ratedArenaBotCount + ratedArenaPlayerCount) < (BracketSize * (activeRatedArenaQueue + ratedArenaInstanceCount)); @@ -265,7 +258,7 @@ bool BGJoinAction::shouldJoinBg(BattlegroundQueueTypeId queueTypeId, Battlegroun { if (sArenaTeamMgr->GetArenaTeamByCaptain(bot->GetGUID(), type)) { - sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].ratedArenaBotCount += TeamSize; + sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].ratedArenaBotCount += TeamSize; ratedList.push_back(queueTypeId); return true; } @@ -274,13 +267,13 @@ bool BGJoinAction::shouldJoinBg(BattlegroundQueueTypeId queueTypeId, Battlegroun // Check if bots should join Skirmish Arena // We have extra bots queue because same faction can vs each other but can't be in the same group. uint32 skirmishArenaBotCount = - sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].skirmishArenaBotCount; + sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].skirmishArenaBotCount; uint32 skirmishArenaPlayerCount = - sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].skirmishArenaPlayerCount; + sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].skirmishArenaPlayerCount; uint32 skirmishArenaInstanceCount = - sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].skirmishArenaInstanceCount; + sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].skirmishArenaInstanceCount; uint32 activeSkirmishArenaQueue = - sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].activeSkirmishArenaQueue; + sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].activeSkirmishArenaQueue; uint32 maxRequiredSkirmishBots = BracketSize * (activeSkirmishArenaQueue + skirmishArenaInstanceCount); if (maxRequiredSkirmishBots != 0) maxRequiredSkirmishBots = maxRequiredSkirmishBots + TeamSize; @@ -294,12 +287,12 @@ bool BGJoinAction::shouldJoinBg(BattlegroundQueueTypeId queueTypeId, Battlegroun } // Check if bots should join Battleground - uint32 bgAllianceBotCount = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgAllianceBotCount; - uint32 bgAlliancePlayerCount = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgAlliancePlayerCount; - uint32 bgHordeBotCount = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgHordeBotCount; - uint32 bgHordePlayerCount = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgHordePlayerCount; - uint32 activeBgQueue = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].activeBgQueue; - uint32 bgInstanceCount = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgInstanceCount; + uint32 bgAllianceBotCount = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgAllianceBotCount; + uint32 bgAlliancePlayerCount = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgAlliancePlayerCount; + uint32 bgHordeBotCount = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgHordeBotCount; + uint32 bgHordePlayerCount = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgHordePlayerCount; + uint32 activeBgQueue = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].activeBgQueue; + uint32 bgInstanceCount = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgInstanceCount; if (teamId == TEAM_ALLIANCE) { @@ -318,7 +311,7 @@ bool BGJoinAction::shouldJoinBg(BattlegroundQueueTypeId queueTypeId, Battlegroun bool BGJoinAction::isUseful() { // do not try if BG bots disabled - if (!sPlayerbotAIConfig->randomBotJoinBG) + if (!sPlayerbotAIConfig.randomBotJoinBG) return false; // can't queue while in BG/Arena @@ -409,8 +402,6 @@ bool BGJoinAction::JoinQueue(uint32 type) bracketId = pvpDiff->GetBracketId(); - uint32 BracketSize = bg->GetMaxPlayersPerTeam() * 2; - uint32 TeamSize = bg->GetMaxPlayersPerTeam(); TeamId teamId = bot->GetTeamId(); // check if already in queue @@ -440,7 +431,7 @@ bool BGJoinAction::JoinQueue(uint32 type) // get battlemaster // Unit* unit = botAI->GetUnit(AI_VALUE2(CreatureData const*, "bg master", bgTypeId)); - Unit* unit = botAI->GetUnit(sRandomPlayerbotMgr->GetBattleMasterGUID(bot, bgTypeId)); + Unit* unit = botAI->GetUnit(sRandomPlayerbotMgr.GetBattleMasterGUID(bot, bgTypeId)); if (!unit && isArena) { botAI->GetAiObjectContext()->GetValue("bg type")->Set(0); @@ -450,7 +441,7 @@ bool BGJoinAction::JoinQueue(uint32 type) // This breaks groups as refresh includes a remove from group function call. // refresh food/regs - // sRandomPlayerbotMgr->Refresh(bot); + // sRandomPlayerbotMgr.Refresh(bot); bool joinAsGroup = bot->GetGroup() && bot->GetGroup()->GetLeaderGUID() == bot->GetGUID(); @@ -487,8 +478,6 @@ bool BGJoinAction::JoinQueue(uint32 type) if (isArena) { isArena = true; - BracketSize = type * 2; - TeamSize = type; isRated = botAI->GetAiObjectContext()->GetValue("arena type")->Get(); if (joinAsGroup) @@ -523,23 +512,23 @@ bool BGJoinAction::JoinQueue(uint32 type) { if (!isRated) { - sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].skirmishArenaBotCount++; + sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].skirmishArenaBotCount++; } } else if (!joinAsGroup) { if (teamId == TEAM_ALLIANCE) - sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgAllianceBotCount++; + sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgAllianceBotCount++; else - sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgHordeBotCount++; + sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgHordeBotCount++; } else { if (teamId == TEAM_ALLIANCE) - sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgAllianceBotCount += + sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgAllianceBotCount += bot->GetGroup()->GetMembersCount(); else - sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgHordeBotCount += + sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgHordeBotCount += bot->GetGroup()->GetMembersCount(); } @@ -588,13 +577,13 @@ bool FreeBGJoinAction::shouldJoinBg(BattlegroundQueueTypeId queueTypeId, Battleg TeamSize = (uint32)type; // Check if bots should join Rated Arena (Only captains can queue) - uint32 ratedArenaBotCount = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].ratedArenaBotCount; + uint32 ratedArenaBotCount = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].ratedArenaBotCount; uint32 ratedArenaPlayerCount = - sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].ratedArenaPlayerCount; + sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].ratedArenaPlayerCount; uint32 ratedArenaInstanceCount = - sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].ratedArenaInstanceCount; + sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].ratedArenaInstanceCount; uint32 activeRatedArenaQueue = - sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].activeRatedArenaQueue; + sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].activeRatedArenaQueue; bool isRated = (ratedArenaBotCount + ratedArenaPlayerCount) < (BracketSize * (activeRatedArenaQueue + ratedArenaInstanceCount)); @@ -603,7 +592,7 @@ bool FreeBGJoinAction::shouldJoinBg(BattlegroundQueueTypeId queueTypeId, Battleg { if (sArenaTeamMgr->GetArenaTeamByCaptain(bot->GetGUID(), type)) { - sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].ratedArenaBotCount += TeamSize; + sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].ratedArenaBotCount += TeamSize; ratedList.push_back(queueTypeId); return true; } @@ -612,13 +601,13 @@ bool FreeBGJoinAction::shouldJoinBg(BattlegroundQueueTypeId queueTypeId, Battleg // Check if bots should join Skirmish Arena // We have extra bots queue because same faction can vs each other but can't be in the same group. uint32 skirmishArenaBotCount = - sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].skirmishArenaBotCount; + sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].skirmishArenaBotCount; uint32 skirmishArenaPlayerCount = - sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].skirmishArenaPlayerCount; + sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].skirmishArenaPlayerCount; uint32 skirmishArenaInstanceCount = - sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].skirmishArenaInstanceCount; + sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].skirmishArenaInstanceCount; uint32 activeSkirmishArenaQueue = - sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].activeSkirmishArenaQueue; + sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].activeSkirmishArenaQueue; uint32 maxRequiredSkirmishBots = BracketSize * (activeSkirmishArenaQueue + skirmishArenaInstanceCount); if (maxRequiredSkirmishBots != 0) maxRequiredSkirmishBots = maxRequiredSkirmishBots + TeamSize; @@ -632,12 +621,12 @@ bool FreeBGJoinAction::shouldJoinBg(BattlegroundQueueTypeId queueTypeId, Battleg } // Check if bots should join Battleground - uint32 bgAllianceBotCount = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgAllianceBotCount; - uint32 bgAlliancePlayerCount = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgAlliancePlayerCount; - uint32 bgHordeBotCount = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgHordeBotCount; - uint32 bgHordePlayerCount = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgHordePlayerCount; - uint32 activeBgQueue = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].activeBgQueue; - uint32 bgInstanceCount = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgInstanceCount; + uint32 bgAllianceBotCount = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgAllianceBotCount; + uint32 bgAlliancePlayerCount = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgAlliancePlayerCount; + uint32 bgHordeBotCount = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgHordeBotCount; + uint32 bgHordePlayerCount = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgHordePlayerCount; + uint32 activeBgQueue = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].activeBgQueue; + uint32 bgInstanceCount = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgInstanceCount; if (teamId == TEAM_ALLIANCE) { @@ -653,7 +642,7 @@ bool FreeBGJoinAction::shouldJoinBg(BattlegroundQueueTypeId queueTypeId, Battleg return false; } -bool BGLeaveAction::Execute(Event event) +bool BGLeaveAction::Execute(Event) { if (!(bot->InBattlegroundQueue() || bot->InBattleground())) return false; @@ -670,7 +659,7 @@ bool BGLeaveAction::Execute(Event event) uint16 unk = 0x1F90; uint8 unk2 = 0x0; bool isArena = false; - bool IsRandomBot = sRandomPlayerbotMgr->IsRandomBot(bot); + bool IsRandomBot = sRandomPlayerbotMgr.IsRandomBot(bot); ArenaType arenaType = ArenaType(BattlegroundMgr::BGArenaType(queueTypeId)); if (arenaType) @@ -709,7 +698,7 @@ bool BGStatusAction::LeaveBG(PlayerbotAI* botAI) if (!bg) return false; bool isArena = bg->isArena(); - bool isRandomBot = sRandomPlayerbotMgr->IsRandomBot(bot); + bool isRandomBot = sRandomPlayerbotMgr.IsRandomBot(bot); if (isRandomBot) botAI->SetMaster(nullptr); @@ -805,7 +794,7 @@ bool BGStatusAction::Execute(Event event) break; } - bool IsRandomBot = sRandomPlayerbotMgr->IsRandomBot(bot); + bool IsRandomBot = sRandomPlayerbotMgr.IsRandomBot(bot); BattlegroundQueueTypeId queueTypeId = bot->GetBattlegroundQueueTypeId(QueueSlot); BattlegroundTypeId _bgTypeId = BattlegroundMgr::BGTemplateId(queueTypeId); if (!queueTypeId) @@ -958,10 +947,10 @@ bool BGStatusAction::Execute(Event event) //TeamId teamId = bot->GetTeamId(); //not used, line marked for removal. bool realPlayers = false; if (isRated) - realPlayers = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].ratedArenaPlayerCount > 0; + realPlayers = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].ratedArenaPlayerCount > 0; else realPlayers = - sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].skirmishArenaPlayerCount > 0; + sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].skirmishArenaPlayerCount > 0; if (realPlayers) return false; @@ -1064,7 +1053,7 @@ bool BGStatusAction::Execute(Event event) return true; } -bool BGStatusCheckAction::Execute(Event event) +bool BGStatusCheckAction::Execute(Event) { if (bot->IsBeingTeleported()) return false; @@ -1080,7 +1069,7 @@ bool BGStatusCheckAction::Execute(Event event) bool BGStatusCheckAction::isUseful() { return bot->InBattlegroundQueue(); } -bool BGStrategyCheckAction::Execute(Event event) +bool BGStrategyCheckAction::Execute(Event) { bool inside_bg = bot->InBattleground() && bot->GetBattleground(); ; diff --git a/src/Ai/Base/Actions/BattleGroundTactics.cpp b/src/Ai/Base/Actions/BattleGroundTactics.cpp index 827ab01970..598e2cc939 100644 --- a/src/Ai/Base/Actions/BattleGroundTactics.cpp +++ b/src/Ai/Base/Actions/BattleGroundTactics.cpp @@ -1276,7 +1276,7 @@ static std::pair IC_AttackObjectives[] = { // useful commands for fixing BG bugs and checking waypoints/paths bool BGTactics::HandleConsoleCommand(ChatHandler* handler, char const* args) { - if (!sPlayerbotAIConfig->enabled) + if (!sPlayerbotAIConfig.enabled) { handler->PSendSysMessage("|cffff0000Playerbot system is currently disabled!"); return true; @@ -1364,8 +1364,8 @@ std::string const BGTactics::HandleConsoleCommandPrivate(WorldSession* session, } } } - uint32 min = 0u; - uint32 max = vPaths->size() - 1; + int64_t min = 0u; + int64_t max = vPaths->size() - 1; if (num >= 0) // num specified or found { if (num > max) @@ -1557,7 +1557,7 @@ bool BGTactics::eyJumpDown() // // actual bg tactics below // -bool BGTactics::Execute(Event event) +bool BGTactics::Execute(Event) { Battleground* bg = bot->GetBattleground(); if (!bg) @@ -2185,16 +2185,6 @@ bool BGTactics::selectObjective(bool reset) case 3: // Balanced defendersProhab = 3; break; - case 4: - case 5: - case 6: - case 7: // Heavy Offense - defendersProhab = 1; - break; - case 8: - case 9: // Heavy Defense - defendersProhab = 6; - break; } if (enemyStrategy == WS_STRATEGY_DEFENSIVE) @@ -2219,16 +2209,21 @@ bool BGTactics::selectObjective(bool reset) if (urand(0, 99) < 20 && teamFC) { target.Relocate(teamFC->GetPositionX(), teamFC->GetPositionY(), teamFC->GetPositionZ()); - if (sServerFacade->GetDistance2d(bot, teamFC) < 33.0f) + if (ServerFacade::instance().GetDistance2d(bot, teamFC) < 33.0f) Follow(teamFC); } else target.Relocate(enemyFC->GetPositionX(), enemyFC->GetPositionY(), enemyFC->GetPositionZ()); } // Graveyard Camping if in lead - else if (!hasFlag && role < 8 && - (team == TEAM_ALLIANCE && allianceScore == 2 && hordeScore == 0) || - (team == TEAM_HORDE && hordeScore == 2 && allianceScore == 0)) + else if ( + !hasFlag + && role < 8 + && ( + (team == TEAM_ALLIANCE && allianceScore == 2 && hordeScore == 0) + || (team == TEAM_HORDE && hordeScore == 2 && allianceScore == 0) + ) + ) { if (team == TEAM_ALLIANCE) SetSafePos(WS_GY_CAMPING_HORDE, 10.0f); @@ -2263,7 +2258,7 @@ bool BGTactics::selectObjective(bool reset) if (urand(0, 99) < 70) { target.Relocate(teamFC->GetPositionX(), teamFC->GetPositionY(), teamFC->GetPositionZ()); - if (sServerFacade->GetDistance2d(bot, teamFC) < 33.0f) + if (ServerFacade::instance().GetDistance2d(bot, teamFC) < 33.0f) Follow(teamFC); } } @@ -2284,7 +2279,7 @@ bool BGTactics::selectObjective(bool reset) { // Assist own FC if not pursuing enemy FC target.Relocate(teamFC->GetPositionX(), teamFC->GetPositionY(), teamFC->GetPositionZ()); - if (sServerFacade->GetDistance2d(bot, teamFC) < 33.0f) + if (ServerFacade::instance().GetDistance2d(bot, teamFC) < 33.0f) Follow(teamFC); } else if (urand(0, 99) < 5) @@ -2497,7 +2492,6 @@ bool BGTactics::selectObjective(bool reset) EYBotStrategy strategyHorde = static_cast(GetBotStrategyForTeam(bg, TEAM_HORDE)); EYBotStrategy strategyAlliance = static_cast(GetBotStrategyForTeam(bg, TEAM_ALLIANCE)); EYBotStrategy strategy = (team == TEAM_ALLIANCE) ? strategyAlliance : strategyHorde; - EYBotStrategy enemyStrategy = (team == TEAM_ALLIANCE) ? strategyHorde : strategyAlliance; auto IsOwned = [&](uint32 nodeId) -> bool { return eyeOfTheStormBG->GetCapturePointInfo(nodeId)._ownerTeamId == team; }; @@ -3197,11 +3191,11 @@ bool BGTactics::moveToObjective(bool ignoreDist) return true; } - if (!ignoreDist && sServerFacade->IsDistanceGreaterThan(sServerFacade->GetDistance2d(bot, pos.x, pos.y), 100.0f)) + if (!ignoreDist && ServerFacade::instance().IsDistanceGreaterThan(ServerFacade::instance().GetDistance2d(bot, pos.x, pos.y), 100.0f)) { // std::ostringstream out; // out << "It is too far away! " << pos.x << ", " << pos.y << ", Distance: " << - // sServerFacade->GetDistance2d(bot, pos.x, pos.y); bot->Say(out.str(), LANG_UNIVERSAL); + // ServerFacade::instance().GetDistance2d(bot, pos.x, pos.y); bot->Say(out.str(), LANG_UNIVERSAL); return false; } @@ -3213,7 +3207,7 @@ bool BGTactics::moveToObjective(bool ignoreDist) } // std::ostringstream out; out << "Moving to objective " << pos.x << ", " << pos.y << ", Distance: " << - // sServerFacade->GetDistance2d(bot, pos.x, pos.y); bot->Say(out.str(), LANG_UNIVERSAL); + // ServerFacade::instance().GetDistance2d(bot, pos.x, pos.y); bot->Say(out.str(), LANG_UNIVERSAL); // dont increase from 1.5 will cause bugs with horde capping AV towers return MoveNear(bot->GetMapId(), pos.x, pos.y, pos.z, 1.5f); @@ -3231,7 +3225,6 @@ bool BGTactics::selectObjectiveWp(std::vector const& vPaths) if (bgType == BATTLEGROUND_RB) bgType = bg->GetBgTypeID(true); - PositionMap& posMap = context->GetValue("position")->Get(); PositionInfo pos = context->GetValue("position")->Get()["bg objective"]; if (!pos.isSet()) return false; @@ -3326,7 +3319,9 @@ bool BGTactics::selectObjectiveWp(std::vector const& vPaths) // don't pick path where bot is already closest to the paths closest point to target (it means path cant lead it // anywhere) don't pick path where closest point is too far away - if (closestPointIndex == (reverse ? 0 : path->size() - 1) || closestPointDistToBot > botDistanceLimit) + const int64_t pathSize = path->size() - 1; + + if (closestPointIndex == (reverse ? 0 : pathSize) || closestPointDistToBot > botDistanceLimit) continue; // creates a score based on dist-to-bot and dist-to-destination, where lower is better, and dist-to-bot is more @@ -3433,7 +3428,7 @@ bool BGTactics::moveToObjectiveWp(BattleBotPath* const& currentPath, uint32 curr // out << "WP: "; // reverse ? out << currPoint << " <<< -> " << nPoint : out << currPoint << ">>> ->" << nPoint; // out << ", " << nextPoint.x << ", " << nextPoint.y << " Path Size: " << currentPath->size() << ", Dist: " << - // sServerFacade->GetDistance2d(bot, nextPoint.x, nextPoint.y); bot->Say(out.str(), LANG_UNIVERSAL); + // ServerFacade::instance().GetDistance2d(bot, nextPoint.x, nextPoint.y); bot->Say(out.str(), LANG_UNIVERSAL); return MoveTo(bot->GetMapId(), nextPoint.x + frand(-2, 2), nextPoint.y + frand(-2, 2), nextPoint.z); } @@ -4039,9 +4034,9 @@ bool BGTactics::useBuff() if (closeObjects.empty()) return false; - bool needRegen = bot->GetHealthPct() < sPlayerbotAIConfig->mediumHealth || + bool needRegen = bot->GetHealthPct() < sPlayerbotAIConfig.mediumHealth || (AI_VALUE2(bool, "has mana", "self target") && - AI_VALUE2(uint8, "mana", "self target") < sPlayerbotAIConfig->mediumMana); + AI_VALUE2(uint8, "mana", "self target") < sPlayerbotAIConfig.mediumMana); bool needSpeed = (bgType != BATTLEGROUND_WS || bot->HasAura(BG_WS_SPELL_WARSONG_FLAG) || bot->HasAura(BG_WS_SPELL_SILVERWING_FLAG) || bot->HasAura(BG_EY_NETHERSTORM_FLAG_SPELL)) || !(teamFlagTaken() || flagTaken()); @@ -4057,7 +4052,7 @@ bool BGTactics::useBuff() continue; // use speed buff only if close - if (sServerFacade->IsDistanceGreaterThan(sServerFacade->GetDistance2d(bot, go), + if (ServerFacade::instance().IsDistanceGreaterThan(ServerFacade::instance().GetDistance2d(bot, go), go->GetEntry() == Buff_Entries[0] ? 20.0f : 50.0f)) continue; @@ -4107,7 +4102,7 @@ uint32 BGTactics::getPlayersInArea(TeamId teamId, Position point, float range, b if (!combat && player->IsInCombat()) continue; - if (sServerFacade->GetDistance2d(player, point.GetPositionX(), point.GetPositionY()) < range) + if (ServerFacade::instance().GetDistance2d(player, point.GetPositionX(), point.GetPositionY()) < range) ++defCount; } } @@ -4191,9 +4186,9 @@ bool BGTactics::IsLockedInsideKeep() // get closest portal if (bot->GetTeamId() == TEAM_ALLIANCE && go->GetEntry() == GO_TELEPORTER_4) { - float tempDist = sServerFacade->GetDistance2d(bot, go->GetPositionX(), go->GetPositionY()); + float tempDist = ServerFacade::instance().GetDistance2d(bot, go->GetPositionX(), go->GetPositionY()); - if (sServerFacade->IsDistanceLessThan(tempDist, closestDistance)) + if (ServerFacade::instance().IsDistanceLessThan(tempDist, closestDistance)) { closestDistance = tempDist; closestPortal = go; @@ -4204,9 +4199,9 @@ bool BGTactics::IsLockedInsideKeep() // get closest portal if (bot->GetTeamId() == TEAM_HORDE && go->GetEntry() == GO_TELEPORTER_2) { - float tempDist = sServerFacade->GetDistance2d(bot, go->GetPositionX(), go->GetPositionY()); + float tempDist = ServerFacade::instance().GetDistance2d(bot, go->GetPositionX(), go->GetPositionY()); - if (sServerFacade->IsDistanceLessThan(tempDist, closestDistance)) + if (ServerFacade::instance().IsDistanceLessThan(tempDist, closestDistance)) { closestDistance = tempDist; closestPortal = go; @@ -4249,11 +4244,11 @@ bool BGTactics::IsLockedInsideKeep() return false; } -bool ArenaTactics::Execute(Event event) +bool ArenaTactics::Execute(Event) { if (!bot->InBattleground()) { - bool IsRandomBot = sRandomPlayerbotMgr->IsRandomBot(bot->GetGUID().GetCounter()); + bool IsRandomBot = sRandomPlayerbotMgr.IsRandomBot(bot->GetGUID().GetCounter()); botAI->ChangeStrategy("-arena", BOT_STATE_COMBAT); botAI->ChangeStrategy("-arena", BOT_STATE_NON_COMBAT); botAI->ResetStrategies(!IsRandomBot); diff --git a/src/Ai/Base/Actions/BattleGroundTactics/BattlegroundTacticsCheckFlag.h b/src/Ai/Base/Actions/BattleGroundTactics/BattlegroundTacticsCheckFlag.h new file mode 100644 index 0000000000..90cf120454 --- /dev/null +++ b/src/Ai/Base/Actions/BattleGroundTactics/BattlegroundTacticsCheckFlag.h @@ -0,0 +1,10 @@ +#pragma once + +#include "BattleGroundTactics.h" + +class BattlegroundTacticsCheckFlag : public BGTactics +{ +public: + BattlegroundTacticsCheckFlag(PlayerbotAI* botAI) : BGTactics(botAI, "check flag") {} + ~BattlegroundTacticsCheckFlag() override = default; +}; diff --git a/src/Ai/Base/Actions/BattleGroundTactics/BattlegroundTacticsCheckObjective.h b/src/Ai/Base/Actions/BattleGroundTactics/BattlegroundTacticsCheckObjective.h new file mode 100644 index 0000000000..aac482ac15 --- /dev/null +++ b/src/Ai/Base/Actions/BattleGroundTactics/BattlegroundTacticsCheckObjective.h @@ -0,0 +1,10 @@ +#pragma once + +#include "BattleGroundTactics.h" + +class BattlegroundTacticsCheckObjective : public BGTactics +{ +public: + BattlegroundTacticsCheckObjective(PlayerbotAI* botAI) : BGTactics(botAI, "check objective") {} + ~BattlegroundTacticsCheckObjective() override = default; +}; diff --git a/src/Ai/Base/Actions/BattleGroundTactics/BattlegroundTacticsMoveToObjective.h b/src/Ai/Base/Actions/BattleGroundTactics/BattlegroundTacticsMoveToObjective.h new file mode 100644 index 0000000000..baa82acee6 --- /dev/null +++ b/src/Ai/Base/Actions/BattleGroundTactics/BattlegroundTacticsMoveToObjective.h @@ -0,0 +1,10 @@ +#pragma once + +#include "BattleGroundTactics.h" + +class BattlegroundTacticsMoveToObjective : public BGTactics +{ +public: + BattlegroundTacticsMoveToObjective(PlayerbotAI* botAI) : BGTactics(botAI, "move to objective") {} + ~BattlegroundTacticsMoveToObjective() override = default; +}; diff --git a/src/Ai/Base/Actions/BattleGroundTactics/BattlegroundTacticsMoveToStart.h b/src/Ai/Base/Actions/BattleGroundTactics/BattlegroundTacticsMoveToStart.h new file mode 100644 index 0000000000..bdd09fbdc6 --- /dev/null +++ b/src/Ai/Base/Actions/BattleGroundTactics/BattlegroundTacticsMoveToStart.h @@ -0,0 +1,10 @@ +#pragma once + +#include "BattleGroundTactics.h" + +class BattlegroundTacticsMoveToStart : public BGTactics +{ +public: + BattlegroundTacticsMoveToStart(PlayerbotAI* botAI) : BGTactics(botAI, "move to start") {} + ~BattlegroundTacticsMoveToStart() override = default; +}; diff --git a/src/Ai/Base/Actions/BattleGroundTactics/BattlegroundTacticsProtectFC.h b/src/Ai/Base/Actions/BattleGroundTactics/BattlegroundTacticsProtectFC.h new file mode 100644 index 0000000000..64923d41f0 --- /dev/null +++ b/src/Ai/Base/Actions/BattleGroundTactics/BattlegroundTacticsProtectFC.h @@ -0,0 +1,10 @@ +#pragma once + +#include "BattleGroundTactics.h" + +class BattlegroundTacticsProtectFC : public BGTactics +{ +public: + BattlegroundTacticsProtectFC(PlayerbotAI* botAI) : BGTactics(botAI, "protect fc") {} + ~BattlegroundTacticsProtectFC() override = default; +}; diff --git a/src/Ai/Base/Actions/BattleGroundTactics/BattlegroundTacticsResetObjectiveForce.h b/src/Ai/Base/Actions/BattleGroundTactics/BattlegroundTacticsResetObjectiveForce.h new file mode 100644 index 0000000000..10287e2b6e --- /dev/null +++ b/src/Ai/Base/Actions/BattleGroundTactics/BattlegroundTacticsResetObjectiveForce.h @@ -0,0 +1,10 @@ +#pragma once + +#include "BattleGroundTactics.h" + +class BattlegroundTacticsResetObjectiveForce : public BGTactics +{ +public: + BattlegroundTacticsResetObjectiveForce(PlayerbotAI* botAI) : BGTactics(botAI, "reset objective force") {} + ~BattlegroundTacticsResetObjectiveForce() override = default; +}; diff --git a/src/Ai/Base/Actions/BattleGroundTactics/BattlegroundTacticsUseBuff.h b/src/Ai/Base/Actions/BattleGroundTactics/BattlegroundTacticsUseBuff.h new file mode 100644 index 0000000000..f5c8332b2c --- /dev/null +++ b/src/Ai/Base/Actions/BattleGroundTactics/BattlegroundTacticsUseBuff.h @@ -0,0 +1,10 @@ +#pragma once + +#include "BattleGroundTactics.h" + +class BattlegroundTacticsUseBuff : public BGTactics +{ +public: + BattlegroundTacticsUseBuff(PlayerbotAI* botAI) : BGTactics(botAI, "use buff") {} + ~BattlegroundTacticsUseBuff() override = default; +}; diff --git a/src/Ai/Base/Actions/BossAuraActions.cpp b/src/Ai/Base/Actions/BossAuraActions.cpp index d711559ee5..530f90e7a1 100644 --- a/src/Ai/Base/Actions/BossAuraActions.cpp +++ b/src/Ai/Base/Actions/BossAuraActions.cpp @@ -9,6 +9,9 @@ #include "BossAuraActions.h" #include "BossAuraTriggers.h" +#include "HunterActions.h" +#include "PaladinActions.h" +#include "CreateNextAction.h" const std::string ADD_STRATEGY_CHAR = "+"; @@ -18,11 +21,11 @@ bool BossFireResistanceAction::isUseful() return bossFireResistanceTrigger.IsActive(); } -bool BossFireResistanceAction::Execute(Event event) +bool BossFireResistanceAction::Execute(Event) { PaladinFireResistanceStrategy paladinFireResistanceStrategy(botAI); botAI->ChangeStrategy(ADD_STRATEGY_CHAR + paladinFireResistanceStrategy.getName(), BotState::BOT_STATE_COMBAT); - botAI->DoSpecificAction("fire resistance aura", Event(), true); + botAI->DoSpecificAction(CreateNextAction(1.0f).factory, Event(), true); return true; } @@ -32,11 +35,11 @@ bool BossFrostResistanceAction::isUseful() return bossFrostResistanceTrigger.IsActive(); } -bool BossFrostResistanceAction::Execute(Event event) +bool BossFrostResistanceAction::Execute(Event) { PaladinFrostResistanceStrategy paladinFrostResistanceStrategy(botAI); botAI->ChangeStrategy(ADD_STRATEGY_CHAR + paladinFrostResistanceStrategy.getName(), BotState::BOT_STATE_COMBAT); - botAI->DoSpecificAction("frost resistance aura", Event(), true); + botAI->DoSpecificAction(CreateNextAction(1.0f).factory, Event(), true); return true; } @@ -46,11 +49,11 @@ bool BossNatureResistanceAction::isUseful() return bossNatureResistanceTrigger.IsActive(); } -bool BossNatureResistanceAction::Execute(Event event) +bool BossNatureResistanceAction::Execute(Event) { HunterNatureResistanceStrategy hunterNatureResistanceStrategy(botAI); botAI->ChangeStrategy(ADD_STRATEGY_CHAR + hunterNatureResistanceStrategy.getName(), BotState::BOT_STATE_COMBAT); - botAI->DoSpecificAction("aspect of the wild", Event(), true); + botAI->DoSpecificAction(CreateNextAction(1.0f).factory, Event(), true); return true; } @@ -60,10 +63,10 @@ bool BossShadowResistanceAction::isUseful() return bossShadowResistanceTrigger.IsActive(); } -bool BossShadowResistanceAction::Execute(Event event) +bool BossShadowResistanceAction::Execute(Event) { PaladinShadowResistanceStrategy paladinShadowResistanceStrategy(botAI); botAI->ChangeStrategy(ADD_STRATEGY_CHAR + paladinShadowResistanceStrategy.getName(), BotState::BOT_STATE_COMBAT); - botAI->DoSpecificAction("shadow resistance aura", Event(), true); + botAI->DoSpecificAction(CreateNextAction(1.0f).factory, Event(), true); return true; } diff --git a/src/Ai/Base/Actions/BossAuraActions.h b/src/Ai/Base/Actions/BossAuraActions.h index e31be8c4e0..e4d0de660e 100644 --- a/src/Ai/Base/Actions/BossAuraActions.h +++ b/src/Ai/Base/Actions/BossAuraActions.h @@ -15,10 +15,12 @@ class PlayerbotAI; class BossFireResistanceAction : public Action { public: - BossFireResistanceAction(PlayerbotAI* botAI, std::string const bossName) + BossFireResistanceAction(PlayerbotAI* botAI, std::string const bossName = "none") : Action(botAI, bossName + " fire resistance action"), bossName(bossName) { } + ~BossFireResistanceAction() override = default; + bool Execute(Event event) override; bool isUseful() override; @@ -29,10 +31,12 @@ class BossFireResistanceAction : public Action class BossFrostResistanceAction : public Action { public: - BossFrostResistanceAction(PlayerbotAI* botAI, std::string const bossName) + BossFrostResistanceAction(PlayerbotAI* botAI, std::string const bossName = "none") : Action(botAI, bossName + " frost resistance action"), bossName(bossName) { } + ~BossFrostResistanceAction() override = default; + bool Execute(Event event) override; bool isUseful() override; @@ -43,10 +47,12 @@ class BossFrostResistanceAction : public Action class BossNatureResistanceAction : public Action { public: - BossNatureResistanceAction(PlayerbotAI* botAI, std::string const bossName) + BossNatureResistanceAction(PlayerbotAI* botAI, std::string const bossName = "none") : Action(botAI, bossName + " nature resistance action"), bossName(bossName) { } + ~BossNatureResistanceAction() override = default; + bool Execute(Event event) override; bool isUseful() override; @@ -57,10 +63,12 @@ class BossNatureResistanceAction : public Action class BossShadowResistanceAction : public Action { public: - BossShadowResistanceAction(PlayerbotAI* botAI, std::string const bossName) + BossShadowResistanceAction(PlayerbotAI* botAI, std::string const bossName = "none") : Action(botAI, bossName + " shadow resistance action"), bossName(bossName) { } + ~BossShadowResistanceAction() override = default; + bool Execute(Event event) override; bool isUseful() override; diff --git a/src/Ai/Base/Actions/BuyAction.cpp b/src/Ai/Base/Actions/BuyAction.cpp index 1e8ec7e5c4..eb6b9db577 100644 --- a/src/Ai/Base/Actions/BuyAction.cpp +++ b/src/Ai/Base/Actions/BuyAction.cpp @@ -6,6 +6,8 @@ #include "BuyAction.h" #include "BudgetValues.h" +#include "CreateNextAction.h" +#include "EquipAction.h" #include "Event.h" #include "ItemCountValue.h" #include "ItemUsageValue.h" @@ -175,7 +177,7 @@ bool BuyAction::Execute(Event event) if (needMoneyFor == NeedMoneyFor::gear) { - botAI->DoSpecificAction("equip upgrades"); + botAI->DoSpecificAction(CreateNextAction(1.0f).factory); } } } @@ -206,7 +208,7 @@ bool BuyAction::Execute(Event event) if (usage == ITEM_USAGE_REPLACE || usage == ITEM_USAGE_EQUIP || usage == ITEM_USAGE_BAD_EQUIP || usage == ITEM_USAGE_BROKEN_EQUIP) { - botAI->DoSpecificAction("equip upgrades"); + botAI->DoSpecificAction(CreateNextAction(1.0f).factory); break; } } diff --git a/src/Ai/Base/Actions/CancelChannelAction.cpp b/src/Ai/Base/Actions/CancelChannelAction.cpp index 9f359f392b..314430844f 100644 --- a/src/Ai/Base/Actions/CancelChannelAction.cpp +++ b/src/Ai/Base/Actions/CancelChannelAction.cpp @@ -7,12 +7,14 @@ #include "Player.h" #include "PlayerbotAI.h" -bool CancelChannelAction::Execute(Event event) +bool CancelChannelAction::Execute(Event) { if (bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) { bot->InterruptSpell(CURRENT_CHANNELED_SPELL); + return true; } + return false; } diff --git a/src/Ai/Base/Actions/CastCustomSpellAction.cpp b/src/Ai/Base/Actions/CastCustomSpellAction.cpp index 417ffb50d3..48c61f3902 100644 --- a/src/Ai/Base/Actions/CastCustomSpellAction.cpp +++ b/src/Ai/Base/Actions/CastCustomSpellAction.cpp @@ -130,10 +130,10 @@ bool CastCustomSpellAction::Execute(Event event) return false; } - if (target != bot && !bot->HasInArc(CAST_ANGLE_IN_FRONT, target, sPlayerbotAIConfig->sightDistance)) + if (target != bot && !bot->HasInArc(CAST_ANGLE_IN_FRONT, target, sPlayerbotAIConfig.sightDistance)) { - sServerFacade->SetFacingTo(bot, target); - botAI->SetNextCheckDelay(sPlayerbotAIConfig->reactDelay); + ServerFacade::instance().SetFacingTo(bot, target); + botAI->SetNextCheckDelay(sPlayerbotAIConfig.reactDelay); msg << "cast " << text; botAI->HandleCommand(CHAT_MSG_WHISPER, msg.str(), master); @@ -286,7 +286,7 @@ bool CastRandomSpellAction::Execute(Event event) if (isCast) { - if (MultiCast && ((wo && bot->HasInArc(CAST_ANGLE_IN_FRONT, wo, sPlayerbotAIConfig->sightDistance)))) + if (MultiCast && ((wo && bot->HasInArc(CAST_ANGLE_IN_FRONT, wo, sPlayerbotAIConfig.sightDistance)))) { std::ostringstream cmd; cmd << "castnc " << chat->FormatWorldobject(wo) + " " << spellId << " " << 19; @@ -334,7 +334,7 @@ bool CastRandomSpellAction::castSpell(uint32 spellId, WorldObject* wo) return botAI->CastSpell(spellId, wo->GetPositionX(), wo->GetPositionY(), wo->GetPositionZ()); } -bool DisEnchantRandomItemAction::Execute(Event event) +bool DisEnchantRandomItemAction::Execute(Event) { std::vector items = AI_VALUE2(std::vector, "inventory items", "usage " + std::to_string(ITEM_USAGE_DISENCHANT)); diff --git a/src/Ai/Base/Actions/CastCustomSpellAction.h b/src/Ai/Base/Actions/CastCustomSpellAction.h index ed53b18a5a..67bbb6ccc5 100644 --- a/src/Ai/Base/Actions/CastCustomSpellAction.h +++ b/src/Ai/Base/Actions/CastCustomSpellAction.h @@ -21,7 +21,7 @@ class CastCustomSpellAction : public InventoryAction } bool Execute(Event event) override; - virtual std::string const castString(WorldObject* target) { return "cast"; } + virtual std::string const castString(WorldObject*) { return "cast"; } protected: bool ncCast = false; @@ -49,7 +49,7 @@ class CastRandomSpellAction : public ListSpellsAction bool isUseful() override { return false; } virtual bool AcceptSpell(SpellInfo const* spellInfo); - virtual uint32 GetSpellPriority(SpellInfo const* spellInfo) { return 1; } + virtual uint32 GetSpellPriority(SpellInfo const*) { return 1; } virtual bool castSpell(uint32 spellId, WorldObject* wo); bool Execute(Event event) override; diff --git a/src/Ai/Base/Actions/ChangeStrategyAction.cpp b/src/Ai/Base/Actions/ChangeStrategyAction.cpp index d17cd005d3..b4fe5faaf2 100644 --- a/src/Ai/Base/Actions/ChangeStrategyAction.cpp +++ b/src/Ai/Base/Actions/ChangeStrategyAction.cpp @@ -24,7 +24,7 @@ bool ChangeCombatStrategyAction::Execute(Event event) case '+': case '-': case '~': - sPlayerbotRepository->Save(botAI); + PlayerbotRepository::instance().Save(botAI); break; case '?': break; @@ -40,7 +40,7 @@ bool ChangeNonCombatStrategyAction::Execute(Event event) std::string const text = event.getParam(); uint32 account = bot->GetSession()->GetAccountId(); - if (sPlayerbotAIConfig->IsInRandomAccountList(account) && botAI->GetMaster() && + if (sPlayerbotAIConfig.IsInRandomAccountList(account) && botAI->GetMaster() && botAI->GetMaster()->GetSession()->GetSecurity() < SEC_GAMEMASTER) { if (text.find("loot") != std::string::npos || text.find("gather") != std::string::npos) @@ -62,7 +62,7 @@ bool ChangeNonCombatStrategyAction::Execute(Event event) case '+': case '-': case '~': - sPlayerbotRepository->Save(botAI); + PlayerbotRepository::instance().Save(botAI); break; case '?': break; diff --git a/src/Ai/Base/Actions/ChangeStrategyAction.h b/src/Ai/Base/Actions/ChangeStrategyAction.h index b9d0ee866c..a36971f798 100644 --- a/src/Ai/Base/Actions/ChangeStrategyAction.h +++ b/src/Ai/Base/Actions/ChangeStrategyAction.h @@ -34,4 +34,11 @@ class ChangeDeadStrategyAction : public Action bool Execute(Event event) override; }; +class EndPullAction : public ChangeCombatStrategyAction +{ +public: + EndPullAction(PlayerbotAI* botAI, std::string const name = "-pull") : ChangeCombatStrategyAction(botAI, name) {} + ~EndPullAction() override = default; +}; + #endif diff --git a/src/Ai/Base/Actions/ChangeTalentsAction.cpp b/src/Ai/Base/Actions/ChangeTalentsAction.cpp index c50e4a9274..a2c6f1e34b 100644 --- a/src/Ai/Base/Actions/ChangeTalentsAction.cpp +++ b/src/Ai/Base/Actions/ChangeTalentsAction.cpp @@ -10,9 +10,9 @@ #include "Event.h" #include "PlayerbotAIConfig.h" #include "PlayerbotFactory.h" -#include "Playerbots.h" #include "AiObjectContext.h" #include "Log.h" +#include "RandomPlayerbotMgr.h" bool ChangeTalentsAction::Execute(Event event) { @@ -110,20 +110,20 @@ std::string ChangeTalentsAction::SpecList() std::ostringstream out; for (int specNo = 0; specNo < MAX_SPECNO; ++specNo) { - if (sPlayerbotAIConfig->premadeSpecName[cls][specNo].size() == 0) + if (sPlayerbotAIConfig.premadeSpecName[cls][specNo].size() == 0) { break; } specFound++; std::ostringstream out; - std::vector> parsed = sPlayerbotAIConfig->parsedSpecLinkOrder[cls][specNo][80]; + std::vector> parsed = sPlayerbotAIConfig.parsedSpecLinkOrder[cls][specNo][80]; std::unordered_map tabCount; tabCount[0] = tabCount[1] = tabCount[2] = 0; for (auto& item : parsed) { tabCount[item[0]] += item[3]; } - out << specFound << ". " << sPlayerbotAIConfig->premadeSpecName[cls][specNo] << " ("; + out << specFound << ". " << sPlayerbotAIConfig.premadeSpecName[cls][specNo] << " ("; out << tabCount[0] << "-" << tabCount[1] << "-" << tabCount[2] << ")"; botAI->TellMasterNoFacing(out.str()); } @@ -137,11 +137,11 @@ std::string ChangeTalentsAction::SpecPick(std::string param) // int specFound = 0; //not used, line marked for removal. for (int specNo = 0; specNo < MAX_SPECNO; ++specNo) { - if (sPlayerbotAIConfig->premadeSpecName[cls][specNo].size() == 0) + if (sPlayerbotAIConfig.premadeSpecName[cls][specNo].size() == 0) { break; } - if (sPlayerbotAIConfig->premadeSpecName[cls][specNo] == param) + if (sPlayerbotAIConfig.premadeSpecName[cls][specNo] == param) { PlayerbotFactory::InitTalentsBySpecNo(bot, specNo, true); @@ -149,7 +149,7 @@ std::string ChangeTalentsAction::SpecPick(std::string param) factory.InitGlyphs(false); std::ostringstream out; - out << "Picking " << sPlayerbotAIConfig->premadeSpecName[cls][specNo]; + out << "Picking " << sPlayerbotAIConfig.premadeSpecName[cls][specNo]; return out.str(); } } @@ -176,7 +176,7 @@ std::string ChangeTalentsAction::SpecApply(std::string param) // std::vector ChangeTalentsAction::getPremadePaths(std::string const findName) // { // std::vector ret; -// // for (auto& path : sPlayerbotAIConfig->classSpecs[bot->getClass()].talentPath) +// // for (auto& path : sPlayerbotAIConfig.classSpecs[bot->getClass()].talentPath) // // { // // if (findName.empty() || path.name.find(findName) != std::string::npos) // // { @@ -191,7 +191,7 @@ std::string ChangeTalentsAction::SpecApply(std::string param) // { // std::vector ret; -// // for (auto& path : sPlayerbotAIConfig->classSpecs[bot->getClass()].talentPath) +// // for (auto& path : sPlayerbotAIConfig.classSpecs[bot->getClass()].talentPath) // // { // // TalentSpec newSpec = *GetBestPremadeSpec(path.id); // // newSpec.CropTalents(bot->GetLevel()); @@ -206,7 +206,7 @@ std::string ChangeTalentsAction::SpecApply(std::string param) // TalentPath* ChangeTalentsAction::getPremadePath(uint32 id) // { -// // for (auto& path : sPlayerbotAIConfig->classSpecs[bot->getClass()].talentPath) +// // for (auto& path : sPlayerbotAIConfig.classSpecs[bot->getClass()].talentPath) // // { // // if (id == path.id) // // { @@ -214,7 +214,7 @@ std::string ChangeTalentsAction::SpecApply(std::string param) // // } // // } -// // return &sPlayerbotAIConfig->classSpecs[bot->getClass()].talentPath[0]; +// // return &sPlayerbotAIConfig.classSpecs[bot->getClass()].talentPath[0]; // return nullptr; // } @@ -270,9 +270,9 @@ std::string ChangeTalentsAction::SpecApply(std::string param) // return false; // } -// uint32 specNo = sRandomPlayerbotMgr->GetValue(bot->GetGUID().GetCounter(), "specNo"); +// uint32 specNo = sRandomPlayerbotMgr.GetValue(bot->GetGUID().GetCounter(), "specNo"); // uint32 specId = specNo - 1; -// std::string specLink = sRandomPlayerbotMgr->GetData(bot->GetGUID().GetCounter(), "specLink"); +// std::string specLink = sRandomPlayerbotMgr.GetData(bot->GetGUID().GetCounter(), "specLink"); // //Continue the current spec // if (specNo > 0) @@ -319,15 +319,15 @@ std::string ChangeTalentsAction::SpecApply(std::string param) // specId = -1; // // specLink = ""; // } -// else if (paths.size() > 1 && false/*!sPlayerbotAIConfig->autoPickTalents*/ && -// !sRandomPlayerbotMgr->IsRandomBot(bot)) +// else if (paths.size() > 1 && false/*!sPlayerbotAIConfig.autoPickTalents*/ && +// !sRandomPlayerbotMgr.IsRandomBot(bot)) // { // *out << "Found multiple specs: "; // listPremadePaths(paths, out); // } // else // { -// specId = PickPremadePath(paths, sRandomPlayerbotMgr->IsRandomBot(bot))->id; +// specId = PickPremadePath(paths, sRandomPlayerbotMgr.IsRandomBot(bot))->id; // TalentSpec newSpec = *GetBestPremadeSpec(specId); // specLink = newSpec.GetTalentLink(); // newSpec.CropTalents(bot->GetLevel()); @@ -341,12 +341,12 @@ std::string ChangeTalentsAction::SpecApply(std::string param) // } // } -// sRandomPlayerbotMgr->SetValue(bot->GetGUID().GetCounter(), "specNo", specId + 1); +// sRandomPlayerbotMgr.SetValue(bot->GetGUID().GetCounter(), "specNo", specId + 1); // if (!specLink.empty() && specId == -1) -// sRandomPlayerbotMgr->SetValue(bot->GetGUID().GetCounter(), "specLink", 1, specLink); +// sRandomPlayerbotMgr.SetValue(bot->GetGUID().GetCounter(), "specLink", 1, specLink); // else -// sRandomPlayerbotMgr->SetValue(bot->GetGUID().GetCounter(), "specLink", 0); +// sRandomPlayerbotMgr.SetValue(bot->GetGUID().GetCounter(), "specLink", 0); // return (specNo == 0) ? false : true; // } @@ -364,15 +364,15 @@ std::string ChangeTalentsAction::SpecApply(std::string param) // if (path->talentSpec.size()) // return &path->talentSpec.back(); -// // return &sPlayerbotAIConfig->classSpecs[bot->getClassMask()].baseSpec; +// // return &sPlayerbotAIConfig.classSpecs[bot->getClassMask()].baseSpec; // return nullptr; // } -bool AutoSetTalentsAction::Execute(Event event) +bool AutoSetTalentsAction::Execute(Event) { std::ostringstream out; - if (!sPlayerbotAIConfig->autoPickTalents || !sRandomPlayerbotMgr->IsRandomBot(bot)) + if (!PlayerbotAIConfig::instance().autoPickTalents || !RandomPlayerbotMgr::instance().IsRandomBot(bot)) return false; if (bot->GetFreeTalentPoints() <= 0) diff --git a/src/Ai/Base/Actions/ChatShortcutActions.cpp b/src/Ai/Base/Actions/ChatShortcutActions.cpp index 02c306b8f7..18a417c35e 100644 --- a/src/Ai/Base/Actions/ChatShortcutActions.cpp +++ b/src/Ai/Base/Actions/ChatShortcutActions.cpp @@ -42,7 +42,7 @@ void PositionsResetAction::SetStayPosition(float x, float y, float z) posMap["stay"] = pos; } -bool FollowChatShortcutAction::Execute(Event event) +bool FollowChatShortcutAction::Execute(Event) { Player* master = GetMaster(); if (!master) @@ -74,7 +74,7 @@ bool FollowChatShortcutAction::Execute(Event event) else { WorldLocation loc = formation->GetLocation(); - if (Formation::IsNullLocation(loc) || loc.GetMapId() == -1) + if (Formation::IsNullLocation(loc)) return false; MovementPriority priority = botAI->GetState() == BOT_STATE_COMBAT ? MovementPriority::MOVEMENT_COMBAT : MovementPriority::MOVEMENT_NORMAL; @@ -82,7 +82,7 @@ bool FollowChatShortcutAction::Execute(Event event) true, priority); } - if (Pet* pet = bot->GetPet()) + if (bot->GetPet() != nullptr) { botAI->PetFollow(); } @@ -96,7 +96,7 @@ bool FollowChatShortcutAction::Execute(Event event) /* Default mechanics takes care of this now. if (bot->GetMapId() != master->GetMapId() || (master && bot->GetDistance(master) > - sPlayerbotAIConfig->sightDistance)) + sPlayerbotAIConfig.sightDistance)) { if (bot->isDead()) { @@ -116,7 +116,7 @@ bool FollowChatShortcutAction::Execute(Event event) return true; } -bool StayChatShortcutAction::Execute(Event event) +bool StayChatShortcutAction::Execute(Event) { Player* master = GetMaster(); if (!master) @@ -133,7 +133,7 @@ bool StayChatShortcutAction::Execute(Event event) return true; } -bool MoveFromGroupChatShortcutAction::Execute(Event event) +bool MoveFromGroupChatShortcutAction::Execute(Event) { Player* master = GetMaster(); if (!master) @@ -148,7 +148,7 @@ bool MoveFromGroupChatShortcutAction::Execute(Event event) return true; } -bool FleeChatShortcutAction::Execute(Event event) +bool FleeChatShortcutAction::Execute(Event) { Player* master = GetMaster(); if (!master) @@ -161,7 +161,7 @@ bool FleeChatShortcutAction::Execute(Event event) ResetReturnPosition(); ResetStayPosition(); - if (bot->GetMapId() != master->GetMapId() || bot->GetDistance(master) > sPlayerbotAIConfig->sightDistance) + if (bot->GetMapId() != master->GetMapId() || bot->GetDistance(master) > sPlayerbotAIConfig.sightDistance) { botAI->TellError("I will not flee with you - too far away"); return true; @@ -171,7 +171,7 @@ bool FleeChatShortcutAction::Execute(Event event) return true; } -bool GoawayChatShortcutAction::Execute(Event event) +bool GoawayChatShortcutAction::Execute(Event) { Player* master = GetMaster(); if (!master) @@ -188,7 +188,7 @@ bool GoawayChatShortcutAction::Execute(Event event) return true; } -bool GrindChatShortcutAction::Execute(Event event) +bool GrindChatShortcutAction::Execute(Event) { Player* master = GetMaster(); if (!master) @@ -204,7 +204,7 @@ bool GrindChatShortcutAction::Execute(Event event) return true; } -bool TankAttackChatShortcutAction::Execute(Event event) +bool TankAttackChatShortcutAction::Execute(Event) { Player* master = GetMaster(); if (!master) @@ -224,7 +224,7 @@ bool TankAttackChatShortcutAction::Execute(Event event) return true; } -bool MaxDpsChatShortcutAction::Execute(Event event) +bool MaxDpsChatShortcutAction::Execute(Event) { Player* master = GetMaster(); if (!master) @@ -241,7 +241,7 @@ bool MaxDpsChatShortcutAction::Execute(Event event) return true; } -bool BwlChatShortcutAction::Execute(Event event) +bool BwlChatShortcutAction::Execute(Event) { Player* master = GetMaster(); if (!master) diff --git a/src/Ai/Base/Actions/CheatAction.cpp b/src/Ai/Base/Actions/CheatAction.cpp index b3f4ec5cf7..790134e953 100644 --- a/src/Ai/Base/Actions/CheatAction.cpp +++ b/src/Ai/Base/Actions/CheatAction.cpp @@ -86,7 +86,7 @@ void CheatAction::ListCheats() for (int i = 0; i < log2((uint32)BotCheatMask::maxMask); i++) { BotCheatMask cheatMask = BotCheatMask(1 << i); - if ((uint32)cheatMask & (uint32)sPlayerbotAIConfig->botCheatMask) + if ((uint32)cheatMask & (uint32)sPlayerbotAIConfig.botCheatMask) out << "[conf:" << GetCheatName(BotCheatMask(cheatMask)) << "]"; else if (botAI->HasCheat(cheatMask)) out << "[" << GetCheatName(BotCheatMask(cheatMask)) << "]"; diff --git a/src/Ai/Base/Actions/CheckMailAction.cpp b/src/Ai/Base/Actions/CheckMailAction.cpp index 85df168f58..25c82a0ade 100644 --- a/src/Ai/Base/Actions/CheckMailAction.cpp +++ b/src/Ai/Base/Actions/CheckMailAction.cpp @@ -7,9 +7,10 @@ #include "Event.h" #include "GuildTaskMgr.h" -#include "Playerbots.h" +#include "PlayerbotAIConfig.h" +#include "PlayerbotAI.h" -bool CheckMailAction::Execute(Event event) +bool CheckMailAction::Execute(Event) { WorldPacket p; bot->GetSession()->HandleQueryNextMailTime(p); @@ -28,7 +29,7 @@ bool CheckMailAction::Execute(Event event) continue; uint32 account = owner->GetSession()->GetAccountId(); - if (sPlayerbotAIConfig->IsInRandomAccountList(account)) + if (PlayerbotAIConfig::instance().IsInRandomAccountList(account)) continue; ProcessMail(mail, owner, trans); @@ -80,7 +81,7 @@ void CheckMailAction::ProcessMail(Mail* mail, Player* owner, CharacterDatabaseTr if (!item) continue; - if (!sGuildTaskMgr->CheckItemTask(i->item_template, item->GetCount(), owner, bot, true)) + if (!GuildTaskMgr::instance().CheckItemTask(i->item_template, item->GetCount(), owner, bot, true)) { std::ostringstream body; body << "Hello, " << owner->GetName() << ",\n"; diff --git a/src/Ai/Base/Actions/CheckMountStateAction.cpp b/src/Ai/Base/Actions/CheckMountStateAction.cpp index bf7a3a169a..5ab7cc0f92 100644 --- a/src/Ai/Base/Actions/CheckMountStateAction.cpp +++ b/src/Ai/Base/Actions/CheckMountStateAction.cpp @@ -89,7 +89,7 @@ bool CheckMountStateAction::isUseful() return false; // Not useful when level lower than minimum required - if (bot->GetLevel() < sPlayerbotAIConfig->useGroundMountAtMinLevel) + if (bot->GetLevel() < sPlayerbotAIConfig.useGroundMountAtMinLevel) return false; // Allow mounting while transformed only if the form allows it @@ -402,7 +402,7 @@ float CheckMountStateAction::CalculateDismountDistance() const // Warrior bots should dismount far enough to charge (because it's important for generating some initial rage), // a real player would be riding toward enemy mashing the charge key but the bots won't cast charge while mounted. bool isMelee = PlayerbotAI::IsMelee(bot); - float dismountDistance = isMelee ? sPlayerbotAIConfig->meleeDistance + 2.0f : sPlayerbotAIConfig->spellDistance + 2.0f; + float dismountDistance = isMelee ? sPlayerbotAIConfig.meleeDistance + 2.0f : sPlayerbotAIConfig.spellDistance + 2.0f; return bot->getClass() == CLASS_WARRIOR ? std::max(18.0f, dismountDistance) : dismountDistance; } @@ -413,7 +413,7 @@ float CheckMountStateAction::CalculateMountDistance() const // seconds: // 21 / 7 = 21 / 14 + 1.5 = 3 (7 = dismounted speed 14 = epic-mount speed 1.5 = mount-spell cast time) bool isMelee = PlayerbotAI::IsMelee(bot); - float baseDistance = isMelee ? sPlayerbotAIConfig->meleeDistance + 10.0f : sPlayerbotAIConfig->spellDistance + 10.0f; + float baseDistance = isMelee ? sPlayerbotAIConfig.meleeDistance + 10.0f : sPlayerbotAIConfig.spellDistance + 10.0f; return std::max(21.0f, baseDistance); } @@ -440,7 +440,7 @@ int32 CheckMountStateAction::CalculateMasterMountSpeed(Player* master, const Mou int32 ridingSkill = bot->GetPureSkillValue(SKILL_RIDING); int32 botLevel = bot->GetLevel(); - if (ridingSkill <= 75 && botLevel < static_cast(sPlayerbotAIConfig->useFastGroundMountAtMinLevel)) + if (ridingSkill <= 75 && botLevel < static_cast(sPlayerbotAIConfig.useFastGroundMountAtMinLevel)) return 59; // If there is a master and bot not in BG, use master's aura effects. diff --git a/src/Ai/Base/Actions/CheckValuesAction.cpp b/src/Ai/Base/Actions/CheckValuesAction.cpp index 1fc0d4c3a1..2b001d82f9 100644 --- a/src/Ai/Base/Actions/CheckValuesAction.cpp +++ b/src/Ai/Base/Actions/CheckValuesAction.cpp @@ -6,12 +6,15 @@ #include "CheckValuesAction.h" #include "Event.h" -#include "Playerbots.h" #include "ServerFacade.h" +#include "PlayerbotAI.h" +#include "TravelNode.h" +#include "AiObjectContext.h" + CheckValuesAction::CheckValuesAction(PlayerbotAI* botAI) : Action(botAI, "check values") {} -bool CheckValuesAction::Execute(Event event) +bool CheckValuesAction::Execute(Event) { if (botAI->HasStrategy("debug move", BOT_STATE_NON_COMBAT)) { @@ -20,7 +23,7 @@ bool CheckValuesAction::Execute(Event event) if (botAI->HasStrategy("map", BOT_STATE_NON_COMBAT) || botAI->HasStrategy("map full", BOT_STATE_NON_COMBAT)) { - sTravelNodeMap->manageNodes(bot, botAI->HasStrategy("map full", BOT_STATE_NON_COMBAT)); + TravelNodeMap::instance().manageNodes(bot, botAI->HasStrategy("map full", BOT_STATE_NON_COMBAT)); } GuidVector possible_targets = *context->GetValue("possible targets"); diff --git a/src/Ai/Base/Actions/ChooseRpgTargetAction.cpp b/src/Ai/Base/Actions/ChooseRpgTargetAction.cpp index a888aa14ee..e4848515a8 100644 --- a/src/Ai/Base/Actions/ChooseRpgTargetAction.cpp +++ b/src/Ai/Base/Actions/ChooseRpgTargetAction.cpp @@ -6,7 +6,6 @@ #include #include "ChooseRpgTargetAction.h" -#include "BattlegroundMgr.h" #include "BudgetValues.h" #include "ChatHelper.h" #include "Event.h" @@ -14,9 +13,9 @@ #include "GuildCreateActions.h" #include "Playerbots.h" #include "RpgSubActions.h" -#include "Util.h" #include "ServerFacade.h" #include "PossibleRpgTargetsValue.h" +#include "RpgSubActions.h" bool ChooseRpgTargetAction::HasSameTarget(ObjectGuid guid, uint32 max, GuidVector const& nearGuids) { @@ -84,9 +83,9 @@ float ChooseRpgTargetAction::getMaxRelevance(GuidPosition guidP) for (NextAction nextAction : nextActions) { - Action* action = botAI->GetAiObjectContext()->GetAction(nextAction.getName()); + std::unique_ptr action = nextAction.factory(this->botAI); - if (dynamic_cast(action)) + if (dynamic_cast(action.get())) isRpg = true; } @@ -112,21 +111,17 @@ float ChooseRpgTargetAction::getMaxRelevance(GuidPosition guidP) return floor((maxRelevance - 1.0) * 1000.0f); } -bool ChooseRpgTargetAction::Execute(Event event) +bool ChooseRpgTargetAction::Execute(Event) { - //TravelTarget* travelTarget = AI_VALUE(TravelTarget*, "travel target"); //not used, line marked for removal. Player* master = botAI->GetMaster(); GuidPosition masterRpgTarget; - if (master && master != bot && GET_PLAYERBOT_AI(master) && master->GetMapId() == bot->GetMapId() && !master->IsBeingTeleported()) + + if (master == nullptr || master == bot || GET_PLAYERBOT_AI(master) == nullptr || master->GetMapId() != bot->GetMapId() || master->IsBeingTeleported()) { - Player* player = botAI->GetMaster(); - //GuidPosition masterRpgTarget = PAI_VALUE(GuidPosition, "rpg target"); //not used, line marked for removal. - } - else master = nullptr; + } std::unordered_map targets; - // uint32 num = 0; //not used, line marked for removal. GuidVector possibleTargets = AI_VALUE(GuidVector, "possible rpg targets"); GuidVector possibleObjects = AI_VALUE(GuidVector, "nearest game objects no los"); GuidVector possiblePlayers = AI_VALUE(GuidVector, "nearest friendly players"); @@ -248,7 +243,7 @@ bool ChooseRpgTargetAction::Execute(Event event) } std::mt19937 gen(time(0)); - sTravelMgr->weighted_shuffle(guidps.begin(), guidps.end(), relevances.begin(), relevances.end(), gen); + TravelMgr::instance().weighted_shuffle(guidps.begin(), guidps.end(), relevances.begin(), relevances.end(), gen); GuidPosition guidP(guidps.front()); if (!guidP) @@ -279,7 +274,7 @@ bool ChooseRpgTargetAction::isUseful() GuidPosition guidP = AI_VALUE(GuidPosition, "rpg target"); - if (guidP && guidP.distance(bot) < sPlayerbotAIConfig->reactDistance * 2) + if (guidP && guidP.distance(bot) < sPlayerbotAIConfig.reactDistance * 2) return false; // TravelTarget* travelTarget = AI_VALUE(TravelTarget*, "travel target"); //not used, line marked for removal. @@ -330,7 +325,7 @@ bool ChooseRpgTargetAction::isFollowValid(Player* bot, WorldPosition pos) if (!botAI->HasStrategy("follow", BOT_STATE_NON_COMBAT)) return true; - if (bot->GetDistance(groupLeader) > sPlayerbotAIConfig->rpgDistance * 2) + if (bot->GetDistance(groupLeader) > sPlayerbotAIConfig.rpgDistance * 2) return false; Formation* formation = AI_VALUE(Formation*, "formation"); @@ -339,8 +334,14 @@ bool ChooseRpgTargetAction::isFollowValid(Player* bot, WorldPosition pos) if (!botAI->HasActivePlayerMaster() && distance < 50.0f) { Player* player = groupLeader; - if (groupLeader && !groupLeader->isMoving() || - PAI_VALUE(WorldPosition, "last long move").distance(pos) < sPlayerbotAIConfig->reactDistance) + + if ( + ( + groupLeader != nullptr + && !groupLeader->isMoving() + ) + || PAI_VALUE(WorldPosition, "last long move").distance(pos) < sPlayerbotAIConfig.reactDistance + ) return true; } diff --git a/src/Ai/Base/Actions/ChooseTargetActions.cpp b/src/Ai/Base/Actions/ChooseTargetActions.cpp index ab533e7136..793f61000e 100644 --- a/src/Ai/Base/Actions/ChooseTargetActions.cpp +++ b/src/Ai/Base/Actions/ChooseTargetActions.cpp @@ -20,13 +20,13 @@ bool AttackEnemyPlayerAction::isUseful() if (PlayerHasFlag::IsCapturingFlag(bot)) return false; - return !sPlayerbotAIConfig->IsPvpProhibited(bot->GetZoneId(), bot->GetAreaId()); + return !sPlayerbotAIConfig.IsPvpProhibited(bot->GetZoneId(), bot->GetAreaId()); } bool AttackEnemyFlagCarrierAction::isUseful() { Unit* target = context->GetValue("enemy flag carrier")->Get(); - return target && sServerFacade->IsDistanceLessOrEqualThan(sServerFacade->GetDistance2d(bot, target), 100.0f) && + return target && ServerFacade::instance().IsDistanceLessOrEqualThan(ServerFacade::instance().GetDistance2d(bot, target), 100.0f) && PlayerHasFlag::IsCapturingFlag(bot); } @@ -61,7 +61,7 @@ bool AttackAnythingAction::isUseful() return true; } -bool DropTargetAction::Execute(Event event) +bool DropTargetAction::Execute(Event) { Unit* target = context->GetValue("current target")->Get(); if (target && target->isDead()) @@ -111,20 +111,30 @@ bool DropTargetAction::Execute(Event event) bool AttackAnythingAction::Execute(Event event) { bool result = AttackAction::Execute(event); - if (result) + + if (!result) { - if (Unit* grindTarget = GetTarget()) - { - if (char const* grindName = grindTarget->GetName().c_str()) - { - context->GetValue("pull target")->Set(grindTarget->GetGUID()); - bot->GetMotionMaster()->Clear(); - // bot->StopMoving(); - } - } + return false; + } + + const Unit* const grindTarget = this->GetTarget(); + + if (grindTarget == nullptr) + { + return true; + } + + const std::string& grindTargetName = grindTarget->GetName(); + + if (grindTargetName.empty()) + { + return true; } - return result; + this->context->GetValue("pull target")->Set(grindTarget->GetGUID()); + this->bot->GetMotionMaster()->Clear(); + + return true; } bool AttackAnythingAction::isPossible() { return AttackAction::isPossible() && GetTarget(); } @@ -137,7 +147,7 @@ bool DpsAssistAction::isUseful() return true; } -bool AttackRtiTargetAction::Execute(Event event) +bool AttackRtiTargetAction::Execute(Event) { Unit* rtiTarget = AI_VALUE(Unit*, "rti target"); diff --git a/src/Ai/Base/Actions/ChooseTravelTargetAction.cpp b/src/Ai/Base/Actions/ChooseTravelTargetAction.cpp index cf6dddd40c..761efc5b62 100644 --- a/src/Ai/Base/Actions/ChooseTravelTargetAction.cpp +++ b/src/Ai/Base/Actions/ChooseTravelTargetAction.cpp @@ -9,7 +9,7 @@ #include "LootObjectStack.h" #include "Playerbots.h" -bool ChooseTravelTargetAction::Execute(Event event) +bool ChooseTravelTargetAction::Execute(Event) { // Player* requester = event.getOwner() ? event.getOwner() : GetMaster(); //not used, line marked for removal. @@ -103,13 +103,13 @@ void ChooseTravelTargetAction::getNewTarget(TravelTarget* newTarget, TravelTarge if (urand(1, 100) > 50) { // Turn in quests for money. - foundTarget = SetQuestTarget(newTarget, true, false, true, true); + foundTarget = SetQuestTarget(newTarget, false, true, true); } if (!foundTarget) { // Find new (low) level quests - foundTarget = SetQuestTarget(newTarget, false, true, false, false); + foundTarget = SetQuestTarget(newTarget, true, false, false); } } else @@ -150,7 +150,7 @@ void ChooseTravelTargetAction::getNewTarget(TravelTarget* newTarget, TravelTarge if (!foundTarget && urand(1, 100) > 5) { // Do any nearby - foundTarget = SetQuestTarget(newTarget, false, true, true, true); + foundTarget = SetQuestTarget(newTarget, true, true, true); } //Explore a nearby unexplored area. @@ -232,15 +232,6 @@ void ChooseTravelTargetAction::ReportTravelTarget(TravelTarget* newTarget, Trave QuestTravelDestination* QuestDestination = (QuestTravelDestination*)destination; Quest const* quest = QuestDestination->GetQuestTemplate(); WorldPosition botLocation(bot); - - CreatureTemplate const* cInfo = nullptr; - GameObjectTemplate const* gInfo = nullptr; - - if (destination->getEntry() > 0) - cInfo = sObjectMgr->GetCreatureTemplate(destination->getEntry()); - else - gInfo = sObjectMgr->GetGameObjectTemplate(destination->getEntry() * -1); - std::string Sub; if (newTarget->isGroupCopy()) @@ -366,7 +357,7 @@ bool ChooseTravelTargetAction::getBestDestination(std::vector availablePoints = - sTravelMgr->getNextPoint(&botLocation, *activePoints); // Pick a good point. + TravelMgr::instance().getNextPoint(&botLocation, *activePoints); // Pick a good point. if (availablePoints.empty()) // No points available. return false; @@ -478,7 +469,7 @@ bool ChooseTravelTargetAction::SetCurrentTarget(TravelTarget* target, TravelTarg return target->isActive(); } -bool ChooseTravelTargetAction::SetQuestTarget(TravelTarget* target, bool onlyCompleted, bool newQuests, bool activeQuests, bool completedQuests) +bool ChooseTravelTargetAction::SetQuestTarget(TravelTarget* target, bool newQuests, bool activeQuests, bool completedQuests) { std::vector activeDestinations; std::vector activePoints; @@ -488,7 +479,7 @@ bool ChooseTravelTargetAction::SetQuestTarget(TravelTarget* target, bool onlyCom if (newQuests) { // Prefer new quests near the player at lower levels. - activeDestinations = sTravelMgr->getQuestTravelDestinations(bot, -1, true, false, 400 + bot->GetLevel() * 10); + activeDestinations = TravelMgr::instance().getQuestTravelDestinations(bot, -1, true, false, 400 + bot->GetLevel() * 10); } if (activeQuests || completedQuests) { @@ -510,7 +501,7 @@ bool ChooseTravelTargetAction::SetQuestTarget(TravelTarget* target, bool onlyCom continue; //Find quest takers or objectives - std::vector questDestinations = sTravelMgr->getQuestTravelDestinations(bot, questId, true, false, 0); + std::vector questDestinations = TravelMgr::instance().getQuestTravelDestinations(bot, questId, true, false, 0); if (onlyClassQuest && activeDestinations.size() && questDestinations.size()) //Only do class quests if we have any. { @@ -525,7 +516,7 @@ bool ChooseTravelTargetAction::SetQuestTarget(TravelTarget* target, bool onlyCom } } if (newQuests && activeDestinations.empty()) - activeDestinations = sTravelMgr->getQuestTravelDestinations(bot, -1, true, false); //If we really don't find any new quests look futher away. + activeDestinations = TravelMgr::instance().getQuestTravelDestinations(bot, -1, true, false); //If we really don't find any new quests look futher away. if (botAI->HasStrategy("debug travel", BotState::BOT_STATE_NON_COMBAT)) botAI->TellMasterNoFacing(std::to_string(activeDestinations.size()) + " quest destinations found."); @@ -547,7 +538,7 @@ bool ChooseTravelTargetAction::SetNewQuestTarget(TravelTarget* target) // Find quest givers. std::vector TravelDestinations = - sTravelMgr->getQuestTravelDestinations(bot, -1, botAI->HasRealPlayerMaster()); + TravelMgr::instance().getQuestTravelDestinations(bot, -1, botAI->HasRealPlayerMaster()); activeDestinations.insert(activeDestinations.end(), TravelDestinations.begin(), TravelDestinations.end()); @@ -576,7 +567,7 @@ bool ChooseTravelTargetAction::SetRpgTarget(TravelTarget* target) // Find rpg npcs std::vector TravelDestinations = - sTravelMgr->getRpgTravelDestinations(bot, botAI->HasRealPlayerMaster()); + TravelMgr::instance().getRpgTravelDestinations(bot, botAI->HasRealPlayerMaster()); activeDestinations.insert(activeDestinations.end(), TravelDestinations.begin(), TravelDestinations.end()); @@ -605,7 +596,7 @@ bool ChooseTravelTargetAction::SetGrindTarget(TravelTarget* target) // Find grind mobs. std::vector TravelDestinations = - sTravelMgr->getGrindTravelDestinations(bot, botAI->HasRealPlayerMaster()); + TravelMgr::instance().getGrindTravelDestinations(bot, botAI->HasRealPlayerMaster()); activeDestinations.insert(activeDestinations.end(), TravelDestinations.begin(), TravelDestinations.end()); @@ -634,7 +625,7 @@ bool ChooseTravelTargetAction::SetBossTarget(TravelTarget* target) // Find boss mobs. std::vector TravelDestinations = - sTravelMgr->getBossTravelDestinations(bot, botAI->HasRealPlayerMaster()); + TravelMgr::instance().getBossTravelDestinations(bot, botAI->HasRealPlayerMaster()); activeDestinations.insert(activeDestinations.end(), TravelDestinations.begin(), TravelDestinations.end()); @@ -662,7 +653,7 @@ bool ChooseTravelTargetAction::SetExploreTarget(TravelTarget* target) WorldPosition botLocation(bot); // Find quest givers. - std::vector TravelDestinations = sTravelMgr->getExploreTravelDestinations(bot, true, true); + std::vector TravelDestinations = TravelMgr::instance().getExploreTravelDestinations(bot, true, true); activeDestinations.insert(activeDestinations.end(), TravelDestinations.begin(), TravelDestinations.end()); /* @@ -681,7 +672,7 @@ bool ChooseTravelTargetAction::SetExploreTarget(TravelTarget* target) if (activePoints.empty()) { - TravelDestinations = sTravelMgr->getExploreTravelDestinations(bot, botAI->HasRealPlayerMaster()); + TravelDestinations = TravelMgr::instance().getExploreTravelDestinations(bot, botAI->HasRealPlayerMaster()); for (auto& activeTarget : activeDestinations) { @@ -710,7 +701,7 @@ bool ChooseTravelTargetAction::SetNpcFlagTarget(TravelTarget* target, std::vecto std::vector dests; - for (auto& d : sTravelMgr->getRpgTravelDestinations(bot, true, true)) + for (auto& d : TravelMgr::instance().getRpgTravelDestinations(bot, true, true)) { if (!d->getEntry()) continue; @@ -813,7 +804,7 @@ std::vector TravelMgr::getBossTravelDestinations(Player* bot bool ChooseTravelTargetAction::SetNullTarget(TravelTarget* target) { - target->setTarget(sTravelMgr->nullTravelDestination, sTravelMgr->nullWorldPosition, true); + target->setTarget(TravelMgr::instance().nullTravelDestination, TravelMgr::instance().nullWorldPosition, true); return true; } @@ -823,16 +814,12 @@ char* strstri(char const* haystack, char const* needle); TravelDestination* ChooseTravelTargetAction::FindDestination(Player* bot, std::string const name, bool zones, bool npcs, bool quests, bool mobs, bool bosses) { - PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); - - // AiObjectContext* context = botAI->GetAiObjectContext(); //not used, line marked for removal. - std::vector dests; //Quests if (quests) { - for (auto& d : sTravelMgr->getQuestTravelDestinations(bot, 0, true, true)) + for (auto& d : TravelMgr::instance().getQuestTravelDestinations(bot, 0, true, true)) { if (strstri(d->getTitle().c_str(), name.c_str())) dests.push_back(d); @@ -842,7 +829,7 @@ TravelDestination* ChooseTravelTargetAction::FindDestination(Player* bot, std::s //Zones if (zones) { - for (auto& d : sTravelMgr->getExploreTravelDestinations(bot, true, true)) + for (auto& d : TravelMgr::instance().getExploreTravelDestinations(bot, true, true)) { if (strstri(d->getTitle().c_str(), name.c_str())) dests.push_back(d); @@ -852,7 +839,7 @@ TravelDestination* ChooseTravelTargetAction::FindDestination(Player* bot, std::s //Npcs if (npcs) { - for (auto& d : sTravelMgr->getRpgTravelDestinations(bot, true, true)) + for (auto& d : TravelMgr::instance().getRpgTravelDestinations(bot, true, true)) { if (strstri(d->getTitle().c_str(), name.c_str())) dests.push_back(d); @@ -862,7 +849,7 @@ TravelDestination* ChooseTravelTargetAction::FindDestination(Player* bot, std::s //Mobs if (mobs) { - for (auto& d : sTravelMgr->getGrindTravelDestinations(bot, true, true, 5000.0f)) + for (auto& d : TravelMgr::instance().getGrindTravelDestinations(bot, true, true, 5000.0f)) { if (strstri(d->getTitle().c_str(), name.c_str())) dests.push_back(d); @@ -872,7 +859,7 @@ TravelDestination* ChooseTravelTargetAction::FindDestination(Player* bot, std::s //Bosses if (bosses) { - for (auto& d : sTravelMgr->getBossTravelDestinations(bot, true, true)) + for (auto& d : TravelMgr::instance().getBossTravelDestinations(bot, true, true)) { if (strstri(d->getTitle().c_str(), name.c_str())) dests.push_back(d); @@ -934,14 +921,16 @@ bool ChooseTravelTargetAction::needForQuest(Unit* target) for (int j = 0; j < QUEST_OBJECTIVES_COUNT; j++) { - int32 entry = questTemplate->RequiredNpcOrGo[j]; + int32_t entry = questTemplate->RequiredNpcOrGo[j]; - if (entry && entry > 0) + if (entry > 0) { int required = questTemplate->RequiredNpcOrGoCount[j]; int available = questStatus.CreatureOrGOCount[j]; - if (required && available < required && (target->GetEntry() == entry || justCheck)) + const int64_t targetEntry = target->GetEntry(); + + if (required && available < required && (targetEntry == entry || justCheck)) return true; } diff --git a/src/Ai/Base/Actions/ChooseTravelTargetAction.h b/src/Ai/Base/Actions/ChooseTravelTargetAction.h index 2ec026dc20..7a259612ec 100644 --- a/src/Ai/Base/Actions/ChooseTravelTargetAction.h +++ b/src/Ai/Base/Actions/ChooseTravelTargetAction.h @@ -36,7 +36,7 @@ class ChooseTravelTargetAction : public MovementAction bool getBestDestination(std::vector* activeDestinations, std::vector* activePoints); bool SetGroupTarget(TravelTarget* target); bool SetCurrentTarget(TravelTarget* target, TravelTarget* oldTarget); - bool SetQuestTarget(TravelTarget* target, bool onlyCompleted = false, bool newQuests = true, bool activeQuests = true, bool completedQuests = true); + bool SetQuestTarget(TravelTarget* target, bool newQuests = true, bool activeQuests = true, bool completedQuests = true); bool SetNewQuestTarget(TravelTarget* target); bool SetRpgTarget(TravelTarget* target); bool SetGrindTarget(TravelTarget* target); diff --git a/src/Ai/Base/Actions/CombatActions.cpp b/src/Ai/Base/Actions/CombatActions.cpp index fe29a11b4f..2f687d5e03 100644 --- a/src/Ai/Base/Actions/CombatActions.cpp +++ b/src/Ai/Base/Actions/CombatActions.cpp @@ -25,7 +25,7 @@ bool SwitchToMeleeAction::isUseful() return botAI->HasStrategy("ranged", BOT_STATE_COMBAT) && ((bot->IsInCombat() && target && (target->GetVictim() == bot && (!bot->GetGroup() || lastFlee) && - sServerFacade->IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", "current target"), 8.0f))) || + ServerFacade::instance().IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", "current target"), 8.0f))) || (!bot->IsInCombat())); } @@ -47,7 +47,7 @@ bool SwitchToRangedAction::isUseful() return botAI->HasStrategy("close", BOT_STATE_COMBAT) && hasAmmo && ((bot->IsInCombat() && target && ((target->GetVictim() != bot || target->GetTarget() != bot->GetGUID()) || - sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", "current target"), 8.0f))) || + ServerFacade::instance().IsDistanceGreaterThan(AI_VALUE2(float, "distance", "current target"), 8.0f))) || (!bot->IsInCombat())); } diff --git a/src/Ai/Base/Actions/CustomStrategyEditAction.cpp b/src/Ai/Base/Actions/CustomStrategyEditAction.cpp index a8e83e87c2..36ea8b29d0 100644 --- a/src/Ai/Base/Actions/CustomStrategyEditAction.cpp +++ b/src/Ai/Base/Actions/CustomStrategyEditAction.cpp @@ -5,9 +5,10 @@ #include "CustomStrategyEditAction.h" +#include "AiObjectContext.h" #include "CustomStrategy.h" #include "Event.h" -#include "Playerbots.h" +#include "PlayerbotAI.h" bool CustomStrategyEditAction::Execute(Event event) { diff --git a/src/Ai/Base/Actions/DebugAction.cpp b/src/Ai/Base/Actions/DebugAction.cpp index 11a0bf26a0..cff3c9c457 100644 --- a/src/Ai/Base/Actions/DebugAction.cpp +++ b/src/Ai/Base/Actions/DebugAction.cpp @@ -7,7 +7,11 @@ #include "ChooseTravelTargetAction.h" #include "MapMgr.h" -#include "Playerbots.h" +#include "TravelMgr.h" +#include "Player.h" +#include "PlayerbotAI.h" +#include "SpellMgr.h" +#include "Spell.h" bool DebugAction::Execute(Event event) { @@ -19,7 +23,7 @@ bool DebugAction::Execute(Event event) if (text == "scan") { - sPlayerbotAIConfig->openLog("scan.csv", "w"); + sPlayerbotAIConfig.openLog("scan.csv", "w"); uint32 i = 0; for (auto p : WorldPosition().getCreaturesNear()) @@ -36,15 +40,15 @@ bool DebugAction::Execute(Event event) pos.printWKT(out); - sPlayerbotAIConfig->log("scan.csv", out.str().c_str()); + sPlayerbotAIConfig.log("scan.csv", out.str().c_str()); if (zoneId == 0 && areaId == 0) { - sPlayerbotAIConfig->log("x", out.str().c_str()); + sPlayerbotAIConfig.log("x", out.str().c_str()); } else { - sPlayerbotAIConfig->log("y", out.str().c_str()); + sPlayerbotAIConfig.log("y", out.str().c_str()); } i = zoneId; @@ -53,8 +57,8 @@ bool DebugAction::Execute(Event event) } else if (text.find("printmap") != std::string::npos) { - sTravelNodeMap->printMap(); - sTravelNodeMap->printNodeStore(); + TravelNodeMap::instance().printMap(); + TravelNodeMap::instance().printNodeStore(); return true; } else if (text.find("travel ") != std::string::npos) @@ -72,7 +76,7 @@ bool DebugAction::Execute(Event event) return false; std::vector beginPath, endPath; - TravelNodeRoute route = sTravelNodeMap->getRoute(botPos, *points.front(), beginPath, bot); + TravelNodeRoute route = TravelNodeMap::instance().getRoute(botPos, *points.front(), beginPath, bot); std::ostringstream out; out << "Traveling to " << dest->getTitle() << ": "; @@ -108,7 +112,7 @@ bool DebugAction::Execute(Event event) out << quest->GetTitle() << ": "; - QuestContainer* cont = sTravelMgr->quests[questId]; + QuestContainer* cont = TravelMgr::instance().quests[questId]; for (auto g : cont->questGivers) { @@ -135,11 +139,11 @@ bool DebugAction::Execute(Event event) else if (text.find("quest") != std::string::npos) { std::ostringstream out; - out << sTravelMgr->quests.size() << " quests "; + out << TravelMgr::instance().quests.size() << " quests "; uint32 noT = 0, noG = 0, noO = 0; - for (auto q : sTravelMgr->quests) + for (auto q : TravelMgr::instance().quests) { if (q.second->questGivers.empty()) noG++; @@ -164,7 +168,7 @@ bool DebugAction::Execute(Event event) // uint32 noT = 0, noG = 0, noO = 0; //not used, line marked for removal. - for (auto q : sTravelMgr->quests) + for (auto q : TravelMgr::instance().quests) { Quest const* quest = sObjectMgr->GetQuestTemplate(q.first); @@ -194,16 +198,16 @@ bool DebugAction::Execute(Event event) std::string const name = "USER:" + text.substr(9); - /* TravelNode* startNode = */ sTravelNodeMap->addNode(pos, name, false, false); // startNode not used, but addNode as side effect, fragment marked for removal. + /* TravelNode* startNode = */ TravelNodeMap::instance().addNode(pos, name, false, false); // startNode not used, but addNode as side effect, fragment marked for removal. - for (auto& endNode : sTravelNodeMap->getNodes(pos, 2000)) + for (auto& endNode : TravelNodeMap::instance().getNodes(pos, 2000)) { endNode->setLinked(false); } botAI->TellMasterNoFacing("Node " + name + " created."); - sTravelNodeMap->setHasToGen(); + TravelNodeMap::instance().setHasToGen(); return true; } @@ -211,7 +215,7 @@ bool DebugAction::Execute(Event event) { WorldPosition pos(bot); - TravelNode* startNode = sTravelNodeMap->getNode(pos, nullptr, 50); + TravelNode* startNode = TravelNodeMap::instance().getNode(pos, nullptr, 50); if (!startNode) return false; @@ -221,24 +225,24 @@ bool DebugAction::Execute(Event event) botAI->TellMasterNoFacing("Node can not be removed."); } - sTravelNodeMap->m_nMapMtx.lock(); - sTravelNodeMap->removeNode(startNode); + TravelNodeMap::instance().m_nMapMtx.lock(); + TravelNodeMap::instance().removeNode(startNode); botAI->TellMasterNoFacing("Node removed."); - sTravelNodeMap->m_nMapMtx.unlock(); + TravelNodeMap::instance().m_nMapMtx.unlock(); - sTravelNodeMap->setHasToGen(); + TravelNodeMap::instance().setHasToGen(); return true; } else if (text.find("reset node") != std::string::npos) { - for (auto& node : sTravelNodeMap->getNodes()) + for (auto& node : TravelNodeMap::instance().getNodes()) node->setLinked(false); return true; } else if (text.find("reset path") != std::string::npos) { - for (auto& node : sTravelNodeMap->getNodes()) + for (auto& node : TravelNodeMap::instance().getNodes()) for (auto& path : *node->getLinks()) node->removeLinkTo(path.first, true); return true; @@ -246,23 +250,23 @@ bool DebugAction::Execute(Event event) else if (text.find("gen node") != std::string::npos) { // Pathfinder - sTravelNodeMap->generateNodes(); + TravelNodeMap::instance().generateNodes(); return true; } else if (text.find("gen path") != std::string::npos) { - sTravelNodeMap->generatePaths(); + TravelNodeMap::instance().generatePaths(); return true; } else if (text.find("crop path") != std::string::npos) { - sTravelNodeMap->removeUselessPaths(); + TravelNodeMap::instance().removeUselessPaths(); return true; } else if (text.find("save node") != std::string::npos) { - sTravelNodeMap->printNodeStore(); - sTravelNodeMap->saveNodeStore(); + TravelNodeMap::instance().printNodeStore(); + TravelNodeMap::instance().saveNodeStore(); return true; } else if (text.find("load node") != std::string::npos) @@ -270,8 +274,8 @@ bool DebugAction::Execute(Event event) std::thread t( [] { - sTravelNodeMap->removeNodes(); - sTravelNodeMap->loadNodeStore(); + TravelNodeMap::instance().removeNodes(); + TravelNodeMap::instance().loadNodeStore(); }); t.detach(); @@ -282,7 +286,7 @@ bool DebugAction::Execute(Event event) { WorldPosition pos(bot); - std::vector nodes = sTravelNodeMap->getNodes(pos, 500); + std::vector nodes = TravelNodeMap::instance().getNodes(pos, 500); for (auto& node : nodes) { @@ -516,7 +520,7 @@ bool DebugAction::Execute(Event event) botPos.setY(botPos.getY() + (dy - 5) * 5); botPos.setZ(botPos.getHeight()); - Creature* wpCreature = bot->SummonCreature(effect, botPos.getX(), botPos.getY(), botPos.getZ(), 0, + bot->SummonCreature(effect, botPos.getX(), botPos.getY(), botPos.getZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 10000.0f); } } diff --git a/src/Ai/Base/Actions/DelayAction.cpp b/src/Ai/Base/Actions/DelayAction.cpp index 8d47912fe4..9d9affa36b 100644 --- a/src/Ai/Base/Actions/DelayAction.cpp +++ b/src/Ai/Base/Actions/DelayAction.cpp @@ -6,15 +6,19 @@ #include "DelayAction.h" #include "Event.h" -#include "Playerbots.h" +#include "PlayerbotAI.h" +#include "PlayerbotAIConfig.h" -bool DelayAction::Execute(Event event) +bool DelayAction::Execute(Event) { - uint32 delay = sPlayerbotAIConfig->passiveDelay + sPlayerbotAIConfig->globalCoolDown; + const uint32 delay = PlayerbotAIConfig::instance().passiveDelay + PlayerbotAIConfig::instance().globalCoolDown; botAI->SetNextCheckDelay(delay); return true; } -bool DelayAction::isUseful() { return !botAI->AllowActivity(ALL_ACTIVITY); } +bool DelayAction::isUseful() +{ + return !botAI->AllowActivity(ALL_ACTIVITY); +} diff --git a/src/Ai/Base/Actions/DestroyItemAction.cpp b/src/Ai/Base/Actions/DestroyItemAction.cpp index 0fce4ad701..cd5fbfebec 100644 --- a/src/Ai/Base/Actions/DestroyItemAction.cpp +++ b/src/Ai/Base/Actions/DestroyItemAction.cpp @@ -39,7 +39,7 @@ void DestroyItemAction::DestroyItem(FindItemVisitor* visitor) bool SmartDestroyItemAction::isUseful() { return !botAI->HasActivePlayerMaster(); } -bool SmartDestroyItemAction::Execute(Event event) +bool SmartDestroyItemAction::Execute(Event) { uint8 bagSpace = AI_VALUE(uint8, "bag space"); diff --git a/src/Ai/Base/Actions/DropQuestAction.cpp b/src/Ai/Base/Actions/DropQuestAction.cpp index 48e571eb3e..b3cba9c560 100644 --- a/src/Ai/Base/Actions/DropQuestAction.cpp +++ b/src/Ai/Base/Actions/DropQuestAction.cpp @@ -67,7 +67,7 @@ bool CleanQuestLogAction::Execute(Event event) return false; } - if (!sPlayerbotAIConfig->dropObsoleteQuests) + if (!sPlayerbotAIConfig.dropObsoleteQuests) { return false; } diff --git a/src/Ai/Base/Actions/EmoteAction.cpp b/src/Ai/Base/Actions/EmoteAction.cpp index 1770ca2b75..8e2c9f67b1 100644 --- a/src/Ai/Base/Actions/EmoteAction.cpp +++ b/src/Ai/Base/Actions/EmoteAction.cpp @@ -6,7 +6,6 @@ #include "EmoteAction.h" #include "Event.h" -#include "PlayerbotTextMgr.h" #include "Playerbots.h" #include "ServerFacade.h" @@ -88,7 +87,7 @@ void EmoteActionBase::InitEmotes() bool EmoteActionBase::Emote(Unit* target, uint32 type, bool textEmote) { - if (target && !bot->HasInArc(static_cast(M_PI), target, sPlayerbotAIConfig->sightDistance)) + if (target && !bot->HasInArc(static_cast(M_PI), target, sPlayerbotAIConfig.sightDistance)) bot->SetFacingToObject(target); ObjectGuid oldSelection = bot->GetTarget(); @@ -100,7 +99,7 @@ bool EmoteActionBase::Emote(Unit* target, uint32 type, bool textEmote) if (player) { PlayerbotAI* playerBotAI = GET_PLAYERBOT_AI(player); - if (playerBotAI && !player->HasInArc(static_cast(M_PI), bot, sPlayerbotAIConfig->sightDistance)) + if (playerBotAI && !player->HasInArc(static_cast(M_PI), bot, sPlayerbotAIConfig.sightDistance)) { player->SetFacingToObject(bot); } @@ -133,7 +132,7 @@ Unit* EmoteActionBase::GetTarget() for (GuidVector::iterator i = nfp.begin(); i != nfp.end(); ++i) { Unit* unit = botAI->GetUnit(*i); - if (unit && sServerFacade->GetDistance2d(bot, unit) < sPlayerbotAIConfig->tooCloseDistance) + if (unit && ServerFacade::instance().GetDistance2d(bot, unit) < sPlayerbotAIConfig.tooCloseDistance) targets.push_back(unit); } @@ -618,8 +617,8 @@ bool EmoteActionBase::ReceiveEmote(Player* source, uint32 emote, bool verbal) break; } - if (source && !bot->isMoving() && !bot->HasInArc(static_cast(M_PI), source, sPlayerbotAIConfig->farDistance)) - sServerFacade->SetFacingTo(bot, source); + if (source && !bot->isMoving() && !bot->HasInArc(static_cast(M_PI), source, sPlayerbotAIConfig.farDistance)) + ServerFacade::instance().SetFacingTo(bot, source); if (verbal) { @@ -689,7 +688,7 @@ bool EmoteAction::Execute(Event event) p >> emoteId >> source; pSource = ObjectAccessor::FindPlayer(source); - if (pSource && pSource != bot && sServerFacade->GetDistance2d(bot, pSource) < sPlayerbotAIConfig->farDistance && + if (pSource && pSource != bot && ServerFacade::instance().GetDistance2d(bot, pSource) < sPlayerbotAIConfig.farDistance && emoteId != EMOTE_ONESHOT_NONE) { if ((pSource->GetGUID() != bot->GetGUID()) && @@ -737,7 +736,7 @@ bool EmoteAction::Execute(Event event) // time_t lastEmote = AI_VALUE2(time_t, "last emote", qualifier); //not used, line marked for removal. botAI->GetAiObjectContext() ->GetValue("last emote", qualifier) - ->Set(time(nullptr) + urand(1000, sPlayerbotAIConfig->repeatDelay) / 1000); + ->Set(time(nullptr) + urand(1000, sPlayerbotAIConfig.repeatDelay) / 1000); param = qualifier; } @@ -787,7 +786,7 @@ bool EmoteAction::isUseful() return time(nullptr) >= lastEmote; } -bool TalkAction::Execute(Event event) +bool TalkAction::Execute(Event) { Unit* target = botAI->GetUnit(AI_VALUE(ObjectGuid, "talk target")); if (!target) diff --git a/src/Ai/Base/Actions/EquipAction.cpp b/src/Ai/Base/Actions/EquipAction.cpp index 9f4a67ca90..e0770abe19 100644 --- a/src/Ai/Base/Actions/EquipAction.cpp +++ b/src/Ai/Base/Actions/EquipAction.cpp @@ -85,8 +85,8 @@ void EquipAction::EquipItem(Item* item) if (itemProto->Class == ITEM_CLASS_CONTAINER) { // Attempt to equip as a bag - Bag* pBag = reinterpret_cast(item); uint8 newBagSlot = GetSmallestBagSlot(); + if (newBagSlot > 0) { uint16 src = ((bagIndex << 8) | slot); @@ -330,7 +330,7 @@ void EquipAction::EquipItem(Item* item) bool EquipUpgradesAction::Execute(Event event) { - if (!sPlayerbotAIConfig->autoEquipUpgradeLoot && !sRandomPlayerbotMgr->IsRandomBot(bot)) + if (!sPlayerbotAIConfig.autoEquipUpgradeLoot && !sRandomPlayerbotMgr.IsRandomBot(bot)) return false; if (event.GetSource() == "trade status") @@ -397,7 +397,7 @@ bool EquipUpgradesAction::Execute(Event event) return true; } -bool EquipUpgradeAction::Execute(Event event) +bool EquipUpgradeAction::Execute(Event) { CollectItemsVisitor visitor; IterateItems(&visitor, ITERATE_ITEMS_IN_BAGS); diff --git a/src/Ai/Base/Actions/FishingAction.cpp b/src/Ai/Base/Actions/FishingAction.cpp index dc431d3425..c38cbe576a 100644 --- a/src/Ai/Base/Actions/FishingAction.cpp +++ b/src/Ai/Base/Actions/FishingAction.cpp @@ -8,6 +8,7 @@ #include "Event.h" #include "GridNotifiers.h" +// Required due to poor AC implementation #include "GridNotifiersImpl.h" #include "ItemPackets.h" #include "LastMovementValue.h" @@ -246,7 +247,7 @@ WorldPosition FindFishingHole(PlayerbotAI* botAI) return WorldPosition(); } -bool MoveNearWaterAction::Execute(Event event) +bool MoveNearWaterAction::Execute(Event) { WorldPosition landSpot = AI_VALUE(WorldPosition, "fishing spot"); if (landSpot.IsValid()) @@ -272,9 +273,9 @@ bool MoveNearWaterAction::isPossible() float fishingSearchWindow; if (master) - fishingSearchWindow = sPlayerbotAIConfig->fishingDistanceFromMaster; + fishingSearchWindow = sPlayerbotAIConfig.fishingDistanceFromMaster; else - fishingSearchWindow = sPlayerbotAIConfig->fishingDistance; + fishingSearchWindow = sPlayerbotAIConfig.fishingDistance; WorldPosition fishingHole = FindFishingHole(botAI); @@ -292,7 +293,6 @@ bool MoveNearWaterAction::isPossible() // Water spot is out of range, lets look for a spot to move to for the fishing hole. if (distance > MAX_DISTANCE_TO_WATER || distance < MIN_DISTANCE_TO_WATER) { - float angle = bot->GetAngle(fishingHole.GetPositionX(), fishingHole.GetPositionY()); WorldPosition landSpot = FindLandRadialFromPosition(botAI, fishingHole, MIN_DISTANCE_TO_WATER, MAX_DISTANCE_TO_WATER, SEARCH_INCREMENT, fishingSearchWindow, 32); if (landSpot.IsValid()) { @@ -323,7 +323,6 @@ bool MoveNearWaterAction::isPossible() if (!water.IsValid()) return false; - bool hasLOS = bot->IsWithinLOS(water.GetPositionX(), water.GetPositionY(), water.GetPositionZ()); float angle = bot->GetAngle(water.GetPositionX(), water.GetPositionY()); WorldPosition landSpot = FindLandFromPosition(botAI, 0.0f, MAX_DISTANCE_TO_WATER, 1.0f, angle, water, fishingSearchWindow, false); @@ -336,7 +335,7 @@ bool MoveNearWaterAction::isPossible() return false; } -bool EquipFishingPoleAction::Execute(Event event) +bool EquipFishingPoleAction::Execute(Event) { if (!_pole) return false; @@ -385,7 +384,7 @@ bool EquipFishingPoleAction::isUseful() } } - if (sRandomPlayerbotMgr->IsRandomBot(bot)) + if (sRandomPlayerbotMgr.IsRandomBot(bot)) { bot->StoreNewItemInBestSlots(FISHING_POLE, 1); // Try to get a fishing pole return true; @@ -396,7 +395,7 @@ bool EquipFishingPoleAction::isUseful() return false; std::string masterName = master->GetName(); - std::string text = sPlayerbotTextMgr->GetBotTextOrDefault( + std::string text = PlayerbotTextMgr::instance().GetBotTextOrDefault( "no_fishing_pole_error", "I don't have a Fishing Pole",{}); botAI->Whisper(text, masterName); @@ -463,7 +462,7 @@ bool UseBobberAction::isUseful() return AI_VALUE(bool, "can use fishing bobber"); } -bool UseBobberAction::Execute(Event event) +bool UseBobberAction::Execute(Event) { GuidVector gos = AI_VALUE(GuidVector, "nearest game objects no los"); for (auto const& guid : gos) @@ -485,7 +484,7 @@ bool UseBobberAction::Execute(Event event) return false; } -bool EndMasterFishingAction::Execute(Event event) +bool EndMasterFishingAction::Execute(Event) { botAI->ChangeStrategy("-master fishing", BOT_STATE_NON_COMBAT); return true; @@ -499,11 +498,11 @@ bool EndMasterFishingAction::isUseful() return false; WorldPosition nearWater = FindWaterRadial(bot, bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), - bot->GetMap(), bot->GetPhaseMask(), MIN_DISTANCE_TO_WATER, sPlayerbotAIConfig->endFishingWithMaster, 10.0f); + bot->GetMap(), bot->GetPhaseMask(), MIN_DISTANCE_TO_WATER, sPlayerbotAIConfig.endFishingWithMaster, 10.0f); return !nearWater.IsValid(); } -bool RemoveBobberStrategyAction::Execute(Event event) +bool RemoveBobberStrategyAction::Execute(Event) { botAI->ChangeStrategy("-use bobber", BOT_STATE_NON_COMBAT); return true; diff --git a/src/Ai/Base/Actions/FollowActions.cpp b/src/Ai/Base/Actions/FollowActions.cpp index 2593ea28e5..cfed8ae620 100644 --- a/src/Ai/Base/Actions/FollowActions.cpp +++ b/src/Ai/Base/Actions/FollowActions.cpp @@ -5,17 +5,14 @@ #include "FollowActions.h" -#include - #include "Event.h" #include "Formations.h" #include "LastMovementValue.h" #include "PlayerbotAI.h" #include "Playerbots.h" #include "ServerFacade.h" -#include "SharedDefines.h" -bool FollowAction::Execute(Event event) +bool FollowAction::Execute(Event) { Formation* formation = AI_VALUE(Formation*, "formation"); std::string const target = formation->GetTargetName(); @@ -28,7 +25,7 @@ bool FollowAction::Execute(Event event) else { WorldLocation loc = formation->GetLocation(); - if (Formation::IsNullLocation(loc) || loc.GetMapId() == -1) + if (Formation::IsNullLocation(loc)) return false; MovementPriority priority = botAI->GetState() == BOT_STATE_COMBAT ? MovementPriority::MOVEMENT_COMBAT : MovementPriority::MOVEMENT_NORMAL; @@ -44,7 +41,7 @@ bool FollowAction::Execute(Event event) // botAI->PetFollow(); // } // if (moved) - // botAI->SetNextCheckDelay(sPlayerbotAIConfig->reactDelay); + // botAI->SetNextCheckDelay(sPlayerbotAIConfig.reactDelay); return moved; } @@ -98,9 +95,9 @@ bool FollowAction::isUseful() distance = bot->GetDistance(loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ()); } if (botAI->HasStrategy("master fishing", BOT_STATE_NON_COMBAT)) - return sServerFacade->IsDistanceGreaterThan(distance, sPlayerbotAIConfig->fishingDistanceFromMaster); + return ServerFacade::instance().IsDistanceGreaterThan(distance, sPlayerbotAIConfig.fishingDistanceFromMaster); - return sServerFacade->IsDistanceGreaterThan(distance, formation->GetMaxDistance()); + return ServerFacade::instance().IsDistanceGreaterThan(distance, formation->GetMaxDistance()); } bool FollowAction::CanDeadFollow(Unit* target) @@ -116,7 +113,7 @@ bool FollowAction::CanDeadFollow(Unit* target) return true; } -bool FleeToGroupLeaderAction::Execute(Event event) +bool FleeToGroupLeaderAction::Execute(Event) { Unit* fTarget = AI_VALUE(Unit*, "group leader"); bool canFollow = Follow(fTarget); @@ -130,7 +127,7 @@ bool FleeToGroupLeaderAction::Execute(Event event) WorldPosition bosPos(bot); float distance = bosPos.fDist(targetPos); - if (distance < sPlayerbotAIConfig->reactDistance * 3) + if (distance < sPlayerbotAIConfig.reactDistance * 3) { if (!urand(0, 3)) botAI->TellMaster("I am close, wait for me!"); diff --git a/src/Ai/Base/Actions/GenericActions.cpp b/src/Ai/Base/Actions/GenericActions.cpp index 184b17715d..cb4f4fb9e6 100644 --- a/src/Ai/Base/Actions/GenericActions.cpp +++ b/src/Ai/Base/Actions/GenericActions.cpp @@ -11,8 +11,6 @@ #include "CreatureAI.h" #include "Playerbots.h" #include "CharmInfo.h" -#include "SharedDefines.h" -#include "ObjectGuid.h" #include "SpellMgr.h" #include "SpellInfo.h" #include @@ -54,7 +52,7 @@ bool MeleeAction::isUseful() return true; } -bool TogglePetSpellAutoCastAction::Execute(Event event) +bool TogglePetSpellAutoCastAction::Execute(Event) { Pet* pet = bot->GetPet(); if (!pet) @@ -113,13 +111,13 @@ bool TogglePetSpellAutoCastAction::Execute(Event event) } // Debug message if pet spells have been toggled and debug is enabled - if (toggled && sPlayerbotAIConfig->petChatCommandDebug == 1) + if (toggled && sPlayerbotAIConfig.petChatCommandDebug == 1) botAI->TellMaster("Pet autocast spells have been toggled."); return toggled; } -bool PetAttackAction::Execute(Event event) +bool PetAttackAction::Execute(Event) { Guardian* pet = bot->GetGuardianPet(); if (!pet) @@ -185,7 +183,7 @@ bool SetPetStanceAction::Execute(Event /*event*/) } // Get the default pet stance from the configuration - int32 stance = sPlayerbotAIConfig->defaultPetStance; + int32 stance = sPlayerbotAIConfig.defaultPetStance; ReactStates react = REACT_DEFENSIVE; std::string stanceText = "defensive (from config, fallback)"; @@ -221,7 +219,7 @@ bool SetPetStanceAction::Execute(Event /*event*/) } // If debug is enabled in config, inform the master of the new stance - if (sPlayerbotAIConfig->petChatCommandDebug == 1) + if (sPlayerbotAIConfig.petChatCommandDebug == 1) botAI->TellMaster("Pet stance set to " + stanceText + " (applied to all pets/guardians)."); return true; diff --git a/src/Ai/Base/Actions/GenericBuffUtils.cpp b/src/Ai/Base/Actions/GenericBuffUtils.cpp index 1ac71bad4e..e33c12f180 100644 --- a/src/Ai/Base/Actions/GenericBuffUtils.cpp +++ b/src/Ai/Base/Actions/GenericBuffUtils.cpp @@ -87,7 +87,7 @@ namespace ai::buff { std::string castName = baseName; Group* g = bot->GetGroup(); - if (!g || g->GetMembersCount() < static_cast(sPlayerbotAIConfig->minBotsForGreaterBuff)) + if (!g || g->GetMembersCount() < static_cast(sPlayerbotAIConfig.minBotsForGreaterBuff)) return castName; // Group too small: stay in solo mode if (std::string const groupName = GroupVariantFor(baseName); !groupName.empty()) @@ -114,7 +114,7 @@ namespace ai::buff time_t now = std::time(nullptr); uint32 botLow = static_cast(bot->GetGUID().GetCounter()); time_t& last = s_lastWarn[ std::make_pair(botLow, groupName) ]; - if (!last || now - last >= sPlayerbotAIConfig->rpWarningCooldown) // Configurable anti-spam + if (!last || now - last >= sPlayerbotAIConfig.rpWarningCooldown) // Configurable anti-spam { // DB Key choice in regard of the buff std::string key; @@ -132,7 +132,7 @@ namespace ai::buff placeholders["%group_spell"] = groupName; placeholders["%base_spell"] = baseName; - std::string announceText = sPlayerbotTextMgr->GetBotTextOrDefault(key, + std::string announceText = PlayerbotTextMgr::instance().GetBotTextOrDefault(key, "Out of components for %group_spell. Using %base_spell!", placeholders); announce(announceText); diff --git a/src/Ai/Base/Actions/GenericSpellActions.cpp b/src/Ai/Base/Actions/GenericSpellActions.cpp index af06a457f0..85e65c7b79 100644 --- a/src/Ai/Base/Actions/GenericSpellActions.cpp +++ b/src/Ai/Base/Actions/GenericSpellActions.cpp @@ -17,19 +17,17 @@ #include "WorldPacket.h" #include "Group.h" #include "Chat.h" -#include "Language.h" #include "GenericBuffUtils.h" #include "PlayerbotAI.h" using ai::buff::MakeAuraQualifierForBuff; -using ai::buff::UpgradeToGroupIfAppropriate; CastSpellAction::CastSpellAction(PlayerbotAI* botAI, std::string const spell) - : Action(botAI, spell), range(botAI->GetRange("spell")), spell(spell) + : Action(botAI, spell), spell(spell), range(botAI->GetRange("spell")) { } -bool CastSpellAction::Execute(Event event) +bool CastSpellAction::Execute(Event) { if (spell == "conjure food" || spell == "conjure water") { @@ -82,7 +80,7 @@ bool CastSpellAction::isPossible() { if (botAI->IsInVehicle() && !botAI->IsInVehicle(false, false, true)) { - if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && botAI->HasRealPlayerMaster())) + if (!sPlayerbotAIConfig.logInGroupOnly || (bot->GetGroup() && botAI->HasRealPlayerMaster())) { LOG_DEBUG("playerbots", "Can cast spell failed. Vehicle. - bot name: {}", bot->GetName()); } @@ -94,7 +92,7 @@ bool CastSpellAction::isPossible() if (spell == "mount" && bot->IsInCombat()) { - if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && botAI->HasRealPlayerMaster())) + if (!sPlayerbotAIConfig.logInGroupOnly || (bot->GetGroup() && botAI->HasRealPlayerMaster())) { LOG_DEBUG("playerbots", "Can cast spell failed. Mount. - bot name: {}", bot->GetName()); } @@ -133,7 +131,19 @@ bool CastSpellAction::isUseful() return spellTarget && AI_VALUE2(bool, "spell cast useful", - spell); // && sServerFacade->GetDistance2d(bot, spellTarget) <= (range + combatReach); + spell); // && ServerFacade::instance().GetDistance2d(bot, spellTarget) <= (range + combatReach); +} + +bool CastReachTargetSpellAction::isUseful() +{ + // do not move while staying + if (botAI->HasStrategy("stay", botAI->GetState())) + { + return false; + } + + return ServerFacade::instance().IsDistanceGreaterThan(AI_VALUE2(float, "distance", "current target"), + (distance + sPlayerbotAIConfig.contactDistance)); } CastMeleeSpellAction::CastMeleeSpellAction(PlayerbotAI* botAI, std::string const spell) : CastSpellAction(botAI, spell) @@ -172,13 +182,27 @@ bool CastMeleeDebuffSpellAction::isUseful() bool CastAuraSpellAction::isUseful() { - if (!GetTarget() || !CastSpellAction::isUseful()) + Unit* const target = this->GetTarget(); + + if (target == nullptr || !CastSpellAction::isUseful()) + { return false; - Aura* aura = botAI->GetAura(spell, GetTarget(), isOwner, checkDuration); - if (!aura) + } + + const Aura* const aura = botAI->GetAura(this->spell, target, this->isOwner, this->checkDuration); + + if (aura == nullptr) + { return true; - if (beforeDuration && aura->GetDuration() < beforeDuration) + } + + const int64_t& signedBeforeDuration = this->beforeDuration; + + if (signedBeforeDuration > 0 && aura->GetDuration() < signedBeforeDuration) + { return true; + } + return false; } @@ -207,7 +231,7 @@ bool CastEnchantItemAction::isPossible() CastHealingSpellAction::CastHealingSpellAction(PlayerbotAI* botAI, std::string const spell, uint8 estAmount, HealingManaEfficiency manaEfficiency, bool isOwner) - : CastAuraSpellAction(botAI, spell, isOwner), estAmount(estAmount), manaEfficiency(manaEfficiency) + : CastAuraSpellAction(botAI, spell, isOwner), manaEfficiency(manaEfficiency), estAmount(estAmount) { range = botAI->GetRange("heal"); } @@ -233,7 +257,7 @@ Value* BuffOnPartyAction::GetTargetValue() return context->GetValue("party member without aura", MakeAuraQualifierForBuff(spell)); } -bool BuffOnPartyAction::Execute(Event event) +bool BuffOnPartyAction::Execute(Event) { std::string castName = spell; // default = mono @@ -290,7 +314,7 @@ Value* CastSnareSpellAction::GetTargetValue() { return context->GetValue< Value* CastCrowdControlSpellAction::GetTargetValue() { return context->GetValue("cc target", getName()); } -bool CastCrowdControlSpellAction::Execute(Event event) { return botAI->CastSpell(getName(), GetTarget()); } +bool CastCrowdControlSpellAction::Execute(Event) { return botAI->CastSpell(getName(), GetTarget()); } bool CastCrowdControlSpellAction::isPossible() { return botAI->CanCastSpell(getName(), GetTarget()); } @@ -308,13 +332,13 @@ bool CastVehicleSpellAction::isPossible() bool CastVehicleSpellAction::isUseful() { return botAI->IsInVehicle(false, true); } -bool CastVehicleSpellAction::Execute(Event event) +bool CastVehicleSpellAction::Execute(Event) { uint32 spellId = AI_VALUE2(uint32, "vehicle spell id", spell); return botAI->CastVehicleSpell(spellId, GetTarget()); } -bool UseTrinketAction::Execute(Event event) +bool UseTrinketAction::Execute(Event) { Item* trinket1 = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_TRINKET1); diff --git a/src/Ai/Base/Actions/GenericSpellActions.h b/src/Ai/Base/Actions/GenericSpellActions.h index b148b93ff6..07031cbbe7 100644 --- a/src/Ai/Base/Actions/GenericSpellActions.h +++ b/src/Ai/Base/Actions/GenericSpellActions.h @@ -7,8 +7,10 @@ #define _PLAYERBOT_GENERICSPELLACTIONS_H #include "Action.h" +#include "CreateNextAction.h" #include "PlayerbotAI.h" #include "PlayerbotAIConfig.h" +#include "ReachTargetActions.h" #include "UseItemAction.h" #include "Value.h" @@ -39,6 +41,20 @@ class CastSpellAction : public Action float range; }; +class CastReachTargetSpellAction : public CastSpellAction +{ +public: + CastReachTargetSpellAction(PlayerbotAI* botAI, std::string const spell, float distance) + : CastSpellAction(botAI, spell), distance(distance) + { + } + + bool isUseful() override; + +protected: + float distance; +}; + class CastAuraSpellAction : public CastSpellAction { public: @@ -199,10 +215,11 @@ class ResurrectPartyMemberAction : public CastSpellAction std::string const GetTargetName() override { return "party member to resurrect"; } std::vector getPrerequisites() override { - return NextAction::merge( - { NextAction("reach party member to resurrect") }, - Action::getPrerequisites() - ); + std::vector prerequisites = Action::getPrerequisites(); + + prerequisites.push_back(CreateNextAction(1.0f)); + + return prerequisites; } }; diff --git a/src/Ai/Base/Actions/GiveItemAction.cpp b/src/Ai/Base/Actions/GiveItemAction.cpp index 6e2d6744ec..029d16f513 100644 --- a/src/Ai/Base/Actions/GiveItemAction.cpp +++ b/src/Ai/Base/Actions/GiveItemAction.cpp @@ -11,7 +11,7 @@ std::vector split(std::string const s, char delim); -bool GiveItemAction::Execute(Event event) +bool GiveItemAction::Execute(Event) { Unit* target = GetTarget(); if (!target) @@ -28,7 +28,6 @@ bool GiveItemAction::Execute(Event event) if (receiverAi->GetAiObjectContext()->GetValue("item count", item)->Get()) return true; - bool moved = false; std::vector items = InventoryAction::parseItems(item, ITERATE_ITEMS_IN_BAGS); for (Item* item : items) { @@ -42,7 +41,6 @@ bool GiveItemAction::Execute(Event event) bot->MoveItemFromInventory(item->GetBagSlot(), item->GetSlot(), true); item->SetOwnerGUID(target->GetGUID()); receiver->MoveItemToInventory(dest, item, true); - moved = true; std::ostringstream out; out << "Got " << chat->FormatItem(item->GetTemplate(), item->GetCount()) << " from " << bot->GetName(); @@ -64,7 +62,7 @@ Unit* GiveItemAction::GetTarget() { return AI_VALUE2(Unit*, "party member withou bool GiveItemAction::isUseful() { - return GetTarget() && AI_VALUE2(uint8, "mana", "self target") > sPlayerbotAIConfig->lowMana; + return GetTarget() && AI_VALUE2(uint8, "mana", "self target") > sPlayerbotAIConfig.lowMana; } Unit* GiveFoodAction::GetTarget() { return AI_VALUE(Unit*, "party member without food"); } @@ -74,7 +72,7 @@ bool GiveFoodAction::isUseful() if (!GetTarget()) return false; - bool isRandomBot = GetTarget()->IsPlayer() && sRandomPlayerbotMgr->IsRandomBot((Player*)GetTarget()); + bool isRandomBot = GetTarget()->IsPlayer() && sRandomPlayerbotMgr.IsRandomBot((Player*)GetTarget()); return !isRandomBot || (isRandomBot && !botAI->HasCheat(BotCheatMask::food)); } @@ -86,7 +84,7 @@ bool GiveWaterAction::isUseful() if (!GetTarget()) return false; - bool isRandomBot = GetTarget()->IsPlayer() && sRandomPlayerbotMgr->IsRandomBot((Player*)GetTarget()); + bool isRandomBot = GetTarget()->IsPlayer() && sRandomPlayerbotMgr.IsRandomBot((Player*)GetTarget()); return !isRandomBot || (isRandomBot && !botAI->HasCheat(BotCheatMask::food)); } diff --git a/src/Ai/Base/Actions/GoAction.cpp b/src/Ai/Base/Actions/GoAction.cpp index 1b8cd62a2a..61a7550c2b 100644 --- a/src/Ai/Base/Actions/GoAction.cpp +++ b/src/Ai/Base/Actions/GoAction.cpp @@ -61,7 +61,7 @@ bool GoAction::Execute(Event event) else { botAI->TellMasterNoFacing("Clearing travel target"); - target->setTarget(sTravelMgr->nullTravelDestination, sTravelMgr->nullWorldPosition); + target->setTarget(TravelMgr::instance().nullTravelDestination, TravelMgr::instance().nullWorldPosition); target->setForced(false); return true; } @@ -75,8 +75,8 @@ bool GoAction::Execute(Event event) if (GameObject* go = botAI->GetGameObject(guid)) if (go->isSpawned()) { - if (sServerFacade->IsDistanceGreaterThan(sServerFacade->GetDistance2d(bot, go), - sPlayerbotAIConfig->reactDistance)) + if (ServerFacade::instance().IsDistanceGreaterThan(ServerFacade::instance().GetDistance2d(bot, go), + sPlayerbotAIConfig.reactDistance)) { botAI->TellError("It is too far away"); return false; @@ -86,7 +86,7 @@ bool GoAction::Execute(Event event) out << "Moving to " << ChatHelper::FormatGameobject(go); botAI->TellMasterNoFacing(out.str()); return MoveNear(bot->GetMapId(), go->GetPositionX(), go->GetPositionY(), go->GetPositionZ() + 0.5f, - sPlayerbotAIConfig->followDistance); + sPlayerbotAIConfig.followDistance); } } return false; @@ -106,7 +106,7 @@ bool GoAction::Execute(Event event) out << "Moving to " << unit->GetName(); botAI->TellMasterNoFacing(out.str()); return MoveNear(bot->GetMapId(), unit->GetPositionX(), unit->GetPositionY(), - unit->GetPositionZ() + 0.5f, sPlayerbotAIConfig->followDistance); + unit->GetPositionZ() + 0.5f, sPlayerbotAIConfig.followDistance); } } @@ -176,8 +176,8 @@ bool GoAction::Execute(Event event) float z = bot->GetPositionZ(); bot->UpdateAllowedPositionZ(x, y, z); - if (sServerFacade->IsDistanceGreaterThan(sServerFacade->GetDistance2d(bot, x, y), - sPlayerbotAIConfig->reactDistance)) + if (ServerFacade::instance().IsDistanceGreaterThan(ServerFacade::instance().GetDistance2d(bot, x, y), + sPlayerbotAIConfig.reactDistance)) { botAI->TellMaster("It is too far away"); return false; @@ -203,14 +203,14 @@ bool GoAction::Execute(Event event) out << "Moving to " << x1 << "," << y1; botAI->TellMasterNoFacing(out.str()); - return MoveNear(bot->GetMapId(), x, y, z + 0.5f, sPlayerbotAIConfig->followDistance); + return MoveNear(bot->GetMapId(), x, y, z + 0.5f, sPlayerbotAIConfig.followDistance); } PositionInfo pos = context->GetValue("position")->Get()[param]; if (pos.isSet()) { - if (sServerFacade->IsDistanceGreaterThan(sServerFacade->GetDistance2d(bot, pos.x, pos.y), - sPlayerbotAIConfig->reactDistance)) + if (ServerFacade::instance().IsDistanceGreaterThan(ServerFacade::instance().GetDistance2d(bot, pos.x, pos.y), + sPlayerbotAIConfig.reactDistance)) { botAI->TellError("It is too far away"); return false; @@ -219,7 +219,7 @@ bool GoAction::Execute(Event event) std::ostringstream out; out << "Moving to position " << param; botAI->TellMasterNoFacing(out.str()); - return MoveNear(bot->GetMapId(), pos.x, pos.y, pos.z + 0.5f, sPlayerbotAIConfig->followDistance); + return MoveNear(bot->GetMapId(), pos.x, pos.y, pos.z + 0.5f, sPlayerbotAIConfig.followDistance); } botAI->TellMaster("Whisper 'go x,y', 'go [game object]', 'go unit' or 'go position' and I will go there"); diff --git a/src/Ai/Base/Actions/GreetAction.cpp b/src/Ai/Base/Actions/GreetAction.cpp index 87bf2c5ffb..630f969398 100644 --- a/src/Ai/Base/Actions/GreetAction.cpp +++ b/src/Ai/Base/Actions/GreetAction.cpp @@ -10,7 +10,7 @@ GreetAction::GreetAction(PlayerbotAI* botAI) : Action(botAI, "greet") {} -bool GreetAction::Execute(Event event) +bool GreetAction::Execute(Event) { ObjectGuid guid = AI_VALUE(ObjectGuid, "new player nearby"); if (!guid || !guid.IsPlayer()) @@ -20,7 +20,7 @@ bool GreetAction::Execute(Event event) if (!player) return false; - if (!bot->HasInArc(CAST_ANGLE_IN_FRONT, player, sPlayerbotAIConfig->sightDistance)) + if (!bot->HasInArc(CAST_ANGLE_IN_FRONT, player, sPlayerbotAIConfig.sightDistance)) bot->SetFacingToObject(player); ObjectGuid oldSel = bot->GetTarget(); diff --git a/src/Ai/Base/Actions/GuildBankAction.cpp b/src/Ai/Base/Actions/GuildBankAction.cpp index 2d9c74ff69..2de53864d3 100644 --- a/src/Ai/Base/Actions/GuildBankAction.cpp +++ b/src/Ai/Base/Actions/GuildBankAction.cpp @@ -6,7 +6,8 @@ #include "GuildBankAction.h" #include "GuildMgr.h" -#include "Playerbots.h" +#include "PlayerbotAI.h" +#include "AiObjectContext.h" bool GuildBankAction::Execute(Event event) { @@ -52,7 +53,7 @@ bool GuildBankAction::Execute(std::string const text, GameObject* bank) return result; } -bool GuildBankAction::MoveFromCharToBank(Item* item, GameObject* bank) +bool GuildBankAction::MoveFromCharToBank(Item* item, GameObject*) { uint32 playerSlot = item->GetSlot(); uint32 playerBag = item->GetBagSlot(); diff --git a/src/Ai/Base/Actions/GuildCreateActions.cpp b/src/Ai/Base/Actions/GuildCreateActions.cpp index 075b28cac3..1332c86a31 100644 --- a/src/Ai/Base/Actions/GuildCreateActions.cpp +++ b/src/Ai/Base/Actions/GuildCreateActions.cpp @@ -7,17 +7,18 @@ #include "ArenaTeam.h" #include "BudgetValues.h" +#include "BuyAction.h" +#include "CreateNextAction.h" #include "Event.h" #include "GuildMgr.h" #include "Playerbots.h" #include "RandomPlayerbotFactory.h" #include "ServerFacade.h" -#include "SharedDefines.h" // GOLD +#include "SharedDefines.h" -bool BuyPetitionAction::Execute(Event event) +bool BuyPetitionAction::Execute(Event) { GuidVector vendors = botAI->GetAiObjectContext()->GetValue("nearest npcs")->Get(); - bool vendored = false, result = false; for (GuidVector::iterator i = vendors.begin(); i != vendors.end(); ++i) { ObjectGuid vendorguid = *i; @@ -97,7 +98,6 @@ bool BuyPetitionAction::canBuyPetition(Player* bot) bool PetitionOfferAction::Execute(Event event) { - uint32 petitionEntry = 5863; // GUILD_CHARTER std::vector petitions = AI_VALUE2(std::vector, "inventory items", chat->FormatQItem(5863)); if (petitions.empty()) @@ -152,7 +152,7 @@ bool PetitionOfferAction::Execute(Event event) bool PetitionOfferAction::isUseful() { return !bot->GetGuildId(); } -bool PetitionOfferNearbyAction::Execute(Event event) +bool PetitionOfferNearbyAction::Execute(Event) { uint32 found = 0; @@ -184,11 +184,11 @@ bool PetitionOfferNearbyAction::Execute(Event event) } else { - if (!sPlayerbotAIConfig->randomBotGroupNearby) + if (!sPlayerbotAIConfig.randomBotGroupNearby) return false; } - if (sServerFacade->GetDistance2d(bot, player) > sPlayerbotAIConfig->sightDistance) + if (ServerFacade::instance().GetDistance2d(bot, player) > sPlayerbotAIConfig.sightDistance) continue; // Parse rpg target to quest action. @@ -209,10 +209,9 @@ bool PetitionOfferNearbyAction::isUseful() AI_VALUE(uint8, "petition signs") < sWorld->getIntConfig(CONFIG_MIN_PETITION_SIGNS); } -bool PetitionTurnInAction::Execute(Event event) +bool PetitionTurnInAction::Execute(Event) { GuidVector vendors = botAI->GetAiObjectContext()->GetValue("nearest npcs")->Get(); - bool vendored = false, result = false; std::vector petitions = AI_VALUE2(std::vector, "inventory items", chat->FormatQItem(5863)); if (petitions.empty()) @@ -297,9 +296,9 @@ bool PetitionTurnInAction::isUseful() !context->GetValue("travel target")->Get()->isTraveling(); } -bool BuyTabardAction::Execute(Event event) +bool BuyTabardAction::Execute(Event) { - bool canBuy = botAI->DoSpecificAction("buy", Event("buy tabard", "Hitem:5976:")); + bool canBuy = botAI->DoSpecificAction(CreateNextAction(1.0f).factory, Event("buy tabard", "Hitem:5976:")); if (canBuy && AI_VALUE2(uint32, "item count", chat->FormatQItem(5976))) return true; diff --git a/src/Ai/Base/Actions/GuildManagementActions.cpp b/src/Ai/Base/Actions/GuildManagementActions.cpp index f00a955e7c..7c90486a8e 100644 --- a/src/Ai/Base/Actions/GuildManagementActions.cpp +++ b/src/Ai/Base/Actions/GuildManagementActions.cpp @@ -5,6 +5,7 @@ #include "GuildManagementActions.h" +#include "CreateNextAction.h" #include "GuildMgr.h" #include "GuildPackets.h" #include "Playerbots.h" @@ -128,7 +129,7 @@ bool GuildRemoveAction::PlayerIsValid(Player* member) return member->GetGuildId() == bot->GetGuildId() && GetRankId(bot) < GetRankId(member); }; -bool GuildManageNearbyAction::Execute(Event event) +bool GuildManageNearbyAction::Execute(Event) { uint32 found = 0; @@ -149,14 +150,13 @@ bool GuildManageNearbyAction::Execute(Event event) // Promote or demote nearby members based on chance. if (player->GetGuildId() && player->GetGuildId() == bot->GetGuildId()) { - Guild::Member* member = guild->GetMember(player->GetGUID()); uint32 dCount = AI_VALUE(uint32, "death count"); if (!urand(0, 30) && dCount < 2 && guild->GetRankRights(botMember->GetRankId()) & GR_RIGHT_PROMOTE) { BroadcastHelper::BroadcastGuildMemberPromotion(botAI, bot, player); - botAI->DoSpecificAction("guild promote", Event("guild management", guid), true); + botAI->DoSpecificAction(CreateNextAction(1.0f).factory, Event("guild management", guid), true); continue; } @@ -164,14 +164,14 @@ bool GuildManageNearbyAction::Execute(Event event) { BroadcastHelper::BroadcastGuildMemberDemotion(botAI, bot, player); - botAI->DoSpecificAction("guild demote", Event("guild management", guid), true); + botAI->DoSpecificAction(CreateNextAction(1.0f).factory, Event("guild management", guid), true); continue; } continue; } - if (!sPlayerbotAIConfig->randomBotGuildNearby) + if (!sPlayerbotAIConfig.randomBotGuildNearby) return false; if (guild->GetMemberSize() > 1000) @@ -185,7 +185,7 @@ bool GuildManageNearbyAction::Execute(Event event) PlayerbotAI* botAi = GET_PLAYERBOT_AI(player); - if (!sPlayerbotAIConfig->randomBotInvitePlayer && botAi && botAi->IsRealPlayer()) + if (!sPlayerbotAIConfig.randomBotInvitePlayer && botAi && botAi->IsRealPlayer()) continue; if (botAi) @@ -193,16 +193,16 @@ bool GuildManageNearbyAction::Execute(Event event) if (botAi->GetGuilderType() == GuilderType::SOLO && !botAi->HasRealPlayerMaster()) //Do not invite solo players. continue; - if (botAi->HasActivePlayerMaster() && !sRandomPlayerbotMgr->IsRandomBot(player)) //Do not invite alts of active players. + if (botAi->HasActivePlayerMaster() && !sRandomPlayerbotMgr.IsRandomBot(player)) //Do not invite alts of active players. continue; } bool sameGroup = bot->GetGroup() && bot->GetGroup()->IsMember(player->GetGUID()); - if (!sameGroup && sServerFacade->GetDistance2d(bot, player) > sPlayerbotAIConfig->spellDistance) + if (!sameGroup && ServerFacade::instance().GetDistance2d(bot, player) > sPlayerbotAIConfig.spellDistance) continue; - if (sPlayerbotAIConfig->inviteChat && (sRandomPlayerbotMgr->IsRandomBot(bot) || !botAI->HasActivePlayerMaster())) + if (sPlayerbotAIConfig.inviteChat && (sRandomPlayerbotMgr.IsRandomBot(bot) || !botAI->HasActivePlayerMaster())) { /* std::map placeholders; placeholders["%name"] = player->GetName(); @@ -210,8 +210,8 @@ bool GuildManageNearbyAction::Execute(Event event) placeholders["%guildname"] = guild->GetName(); AreaTableEntry const* current_area = botAI->GetCurrentArea(); AreaTableEntry const* current_zone = botAI->GetCurrentZone(); - placeholders["%area_name"] = current_area ? current_area->area_name[BroadcastHelper::GetLocale()] : BOT_TEXT1("string_unknown_area"); - placeholders["%zone_name"] = current_zone ? current_zone->area_name[BroadcastHelper::GetLocale()] : BOT_TEXT1("string_unknown_area"); + placeholders["%area_name"] = current_area ? current_area->area_name[BroadcastHelper::GetLocale()] : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); + placeholders["%zone_name"] = current_zone ? current_zone->area_name[BroadcastHelper::GetLocale()] : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); std::vector lines; @@ -219,45 +219,45 @@ bool GuildManageNearbyAction::Execute(Event event) switch ((urand(0, 10) * urand(0, 10)) / 10) { case 0: - lines.push_back(BOT_TEXT2("Hey %name do you want to join my guild?", placeholders)); + lines.push_back(PlayerbotTextMgr::instance().GetBotText("Hey %name do you want to join my guild?", placeholders)); break; case 1: - lines.push_back(BOT_TEXT2("Hey man you wanna join my guild %name?", placeholders)); + lines.push_back(PlayerbotTextMgr::instance().GetBotText("Hey man you wanna join my guild %name?", placeholders)); break; case 2: - lines.push_back(BOT_TEXT2("I think you would be a good contribution to %guildname. Would you like to join %name?", placeholders)); + lines.push_back(PlayerbotTextMgr::instance().GetBotText("I think you would be a good contribution to %guildname. Would you like to join %name?", placeholders)); break; case 3: - lines.push_back(BOT_TEXT2("My guild %guildname has %members quality members. Would you like to make it 1 more %name?", placeholders)); + lines.push_back(PlayerbotTextMgr::instance().GetBotText("My guild %guildname has %members quality members. Would you like to make it 1 more %name?", placeholders)); break; case 4: - lines.push_back(BOT_TEXT2("Hey %name do you want to join %guildname? We have %members members and looking to become number 1 of the server.", placeholders)); + lines.push_back(PlayerbotTextMgr::instance().GetBotText("Hey %name do you want to join %guildname? We have %members members and looking to become number 1 of the server.", placeholders)); break; case 5: - lines.push_back(BOT_TEXT2("I'm not really good at smalltalk. Do you wanna join my guild %name/r?", placeholders)); + lines.push_back(PlayerbotTextMgr::instance().GetBotText("I'm not really good at smalltalk. Do you wanna join my guild %name/r?", placeholders)); break; case 6: - lines.push_back(BOT_TEXT2("Welcome to %zone_name.... do you want to join my guild %name?", placeholders)); + lines.push_back(PlayerbotTextMgr::instance().GetBotText("Welcome to %zone_name.... do you want to join my guild %name?", placeholders)); break; case 7: - lines.push_back(BOT_TEXT2("%name, you should join my guild!", placeholders)); + lines.push_back(PlayerbotTextMgr::instance().GetBotText("%name, you should join my guild!", placeholders)); break; case 8: - lines.push_back(BOT_TEXT2("%name, I got this guild....", placeholders)); + lines.push_back(PlayerbotTextMgr::instance().GetBotText("%name, I got this guild....", placeholders)); break; case 9: - lines.push_back(BOT_TEXT2("You are actually going to join my guild %name?", placeholders)); - lines.push_back(BOT_TEXT2("Haha.. you are the man! We are going to raid Molten...", placeholders)); + lines.push_back(PlayerbotTextMgr::instance().GetBotText("You are actually going to join my guild %name?", placeholders)); + lines.push_back(PlayerbotTextMgr::instance().GetBotText("Haha.. you are the man! We are going to raid Molten...", placeholders)); break; case 10: - lines.push_back(BOT_TEXT2("Hey Hey! do you guys wanna join my gild????", placeholders)); - lines.push_back(BOT_TEXT2("We've got a bunch of high levels and we are really super friendly..", placeholders)); - lines.push_back(BOT_TEXT2("..and watch your dog and do your homework...", placeholders)); - lines.push_back(BOT_TEXT2("..and we raid once a week and are working on MC raids...", placeholders)); - lines.push_back(BOT_TEXT2("..and we have more members than just me...", placeholders)); - lines.push_back(BOT_TEXT2("..and please stop I'm lonenly and we can get a ride the whole time...", placeholders)); - lines.push_back(BOT_TEXT2("..and it's really beautifull and I feel like crying...", placeholders)); - lines.push_back(BOT_TEXT2("So what do you guys say are you going to join are you going to join?", placeholders)); + lines.push_back(PlayerbotTextMgr::instance().GetBotText("Hey Hey! do you guys wanna join my gild????", placeholders)); + lines.push_back(PlayerbotTextMgr::instance().GetBotText("We've got a bunch of high levels and we are really super friendly..", placeholders)); + lines.push_back(PlayerbotTextMgr::instance().GetBotText("..and watch your dog and do your homework...", placeholders)); + lines.push_back(PlayerbotTextMgr::instance().GetBotText("..and we raid once a week and are working on MC raids...", placeholders)); + lines.push_back(PlayerbotTextMgr::instance().GetBotText("..and we have more members than just me...", placeholders)); + lines.push_back(PlayerbotTextMgr::instance().GetBotText("..and please stop I'm lonenly and we can get a ride the whole time...", placeholders)); + lines.push_back(PlayerbotTextMgr::instance().GetBotText("..and it's really beautifull and I feel like crying...", placeholders)); + lines.push_back(PlayerbotTextMgr::instance().GetBotText("So what do you guys say are you going to join are you going to join?", placeholders)); break; } @@ -272,9 +272,9 @@ bool GuildManageNearbyAction::Execute(Event event) bot->Say(line, (bot->GetTeamId() == TEAM_ALLIANCE ? LANG_COMMON : LANG_ORCISH));*/ } - if (botAI->DoSpecificAction("guild invite", Event("guild management", guid), true)) + if (botAI->DoSpecificAction(CreateNextAction(1.0f).factory, Event("guild management", guid), true)) { - if (sPlayerbotAIConfig->inviteChat) + if (sPlayerbotAIConfig.inviteChat) return true; found++; } diff --git a/src/Ai/Base/Actions/HelpAction.cpp b/src/Ai/Base/Actions/HelpAction.cpp index 3dbe1d6e4b..afa56fc022 100644 --- a/src/Ai/Base/Actions/HelpAction.cpp +++ b/src/Ai/Base/Actions/HelpAction.cpp @@ -7,13 +7,13 @@ #include "ChatActionContext.h" #include "Event.h" -#include "Playerbots.h" +#include "AiObjectContext.h" HelpAction::HelpAction(PlayerbotAI* botAI) : Action(botAI, "help") { chatContext = new ChatActionContext(); } HelpAction::~HelpAction() { delete chatContext; } -bool HelpAction::Execute(Event event) +bool HelpAction::Execute(Event) { TellChatCommands(); TellStrategies(); diff --git a/src/Ai/Base/Actions/HireAction.cpp b/src/Ai/Base/Actions/HireAction.cpp index f8b3653964..53e399caab 100644 --- a/src/Ai/Base/Actions/HireAction.cpp +++ b/src/Ai/Base/Actions/HireAction.cpp @@ -6,15 +6,16 @@ #include "HireAction.h" #include "Event.h" -#include "Playerbots.h" +#include "RandomPlayerbotMgr.h" +#include "PlayerbotAI.h" -bool HireAction::Execute(Event event) +bool HireAction::Execute(Event) { Player* master = GetMaster(); if (!master) return false; - if (!sRandomPlayerbotMgr->IsRandomBot(bot)) + if (!RandomPlayerbotMgr::instance().IsRandomBot(bot)) return false; uint32 account = master->GetSession()->GetAccountId(); @@ -39,7 +40,7 @@ bool HireAction::Execute(Event event) return false; } - uint32 discount = sRandomPlayerbotMgr->GetTradeDiscount(bot, master); + uint32 discount = RandomPlayerbotMgr::instance().GetTradeDiscount(bot, master); uint32 m = 1 + (bot->GetLevel() / 10); uint32 moneyReq = m * 5000 * bot->GetLevel(); if (discount < moneyReq) @@ -54,7 +55,7 @@ bool HireAction::Execute(Event event) botAI->TellMaster("I will join you at your next relogin"); bot->SetMoney(moneyReq); - sRandomPlayerbotMgr->Remove(bot); + RandomPlayerbotMgr::instance().Remove(bot); CharacterDatabase.Execute("UPDATE characters SET account = {} WHERE guid = {}", account, bot->GetGUID().GetCounter()); diff --git a/src/Ai/Base/Actions/ImbueAction.cpp b/src/Ai/Base/Actions/ImbueAction.cpp index 8c151ef8a6..1f07d21e34 100644 --- a/src/Ai/Base/Actions/ImbueAction.cpp +++ b/src/Ai/Base/Actions/ImbueAction.cpp @@ -10,7 +10,7 @@ ImbueWithPoisonAction::ImbueWithPoisonAction(PlayerbotAI* botAI) : Action(botAI, "apply poison") {} -bool ImbueWithPoisonAction::Execute(Event event) +bool ImbueWithPoisonAction::Execute(Event) { if (bot->IsInCombat()) return false; @@ -103,7 +103,7 @@ bool ImbueWithPoisonAction::Execute(Event event) // Search and apply stone to weapons ImbueWithStoneAction::ImbueWithStoneAction(PlayerbotAI* botAI) : Action(botAI, "apply stone") {} -bool ImbueWithStoneAction::Execute(Event event) +bool ImbueWithStoneAction::Execute(Event) { if (bot->IsInCombat()) return false; @@ -148,7 +148,7 @@ bool ImbueWithStoneAction::Execute(Event event) // Search and apply oil to weapons ImbueWithOilAction::ImbueWithOilAction(PlayerbotAI* botAI) : Action(botAI, "apply oil") {} -bool ImbueWithOilAction::Execute(Event event) +bool ImbueWithOilAction::Execute(Event) { if (bot->IsInCombat()) return false; @@ -201,7 +201,7 @@ static const uint32 uPrioritizedHealingItemIds[19] = { TryEmergencyAction::TryEmergencyAction(PlayerbotAI* botAI) : Action(botAI, "try emergency") {} -bool TryEmergencyAction::Execute(Event event) +bool TryEmergencyAction::Execute(Event) { // Do not use consumable if bot can heal self if ((botAI->IsHeal(bot)) && (bot->GetPowerPct(POWER_MANA) > 20)) diff --git a/src/Ai/Base/Actions/InventoryAction.cpp b/src/Ai/Base/Actions/InventoryAction.cpp index f7b606a91a..c929e1787e 100644 --- a/src/Ai/Base/Actions/InventoryAction.cpp +++ b/src/Ai/Base/Actions/InventoryAction.cpp @@ -373,9 +373,12 @@ ItemIds InventoryAction::FindOutfitItems(std::string const name) std::string const InventoryAction::parseOutfitName(std::string const outfit) { - uint32 pos = outfit.find("="); - if (pos == -1) - return ""; + const uint64_t pos = outfit.find("="); + + if (pos == std::string::npos) + { + return outfit; + } return outfit.substr(0, pos); } @@ -387,9 +390,7 @@ ItemIds InventoryAction::parseOutfitItems(std::string const text) uint8 pos = text.find("=") + 1; while (pos < text.size()) { - uint32 endPos = text.find(',', pos); - if (endPos == -1) - endPos = text.size(); + uint64_t endPos = text.find(',', pos); std::string const idC = text.substr(pos, endPos - pos); uint32 id = atol(idC.c_str()); diff --git a/src/Ai/Base/Actions/InviteToGroupAction.cpp b/src/Ai/Base/Actions/InviteToGroupAction.cpp index bec515fefb..4fa050dcf5 100644 --- a/src/Ai/Base/Actions/InviteToGroupAction.cpp +++ b/src/Ai/Base/Actions/InviteToGroupAction.cpp @@ -5,10 +5,12 @@ #include "InviteToGroupAction.h" +#include "AcceptInvitationAction.h" #include "BroadcastHelper.h" +#include "CreateNextAction.h" #include "Event.h" #include "GuildMgr.h" -#include "Log.h" +#include "LeaveGroupAction.h" #include "PlayerbotOperations.h" #include "Playerbots.h" #include "PlayerbotWorldThreadProcessor.h" @@ -31,7 +33,7 @@ bool InviteToGroupAction::Invite(Player* inviter, Player* player) if (!group->isRaidGroup() && group->GetMembersCount() > 4) { auto convertOp = std::make_unique(inviter->GetGUID()); - sPlayerbotWorldProcessor->QueueOperation(std::move(convertOp)); + PlayerbotWorldThreadProcessor::instance().QueueOperation(std::move(convertOp)); } } @@ -44,7 +46,7 @@ bool InviteToGroupAction::Invite(Player* inviter, Player* player) return true; } -bool InviteNearbyToGroupAction::Execute(Event event) +bool InviteNearbyToGroupAction::Execute(Event) { GuidVector nearGuids = botAI->GetAiObjectContext()->GetValue("nearest friendly players")->Get(); for (auto& i : nearGuids) @@ -62,7 +64,7 @@ bool InviteNearbyToGroupAction::Execute(Event event) if (player->GetGroup()) continue; - if (!sPlayerbotAIConfig->randomBotInvitePlayer && GET_PLAYERBOT_AI(player)->IsRealPlayer()) + if (!PlayerbotAIConfig::instance().randomBotInvitePlayer && GET_PLAYERBOT_AI(player)->IsRealPlayer()) continue; Group* group = bot->GetGroup(); @@ -88,7 +90,7 @@ bool InviteNearbyToGroupAction::Execute(Event event) if (abs(int32(player->GetLevel() - bot->GetLevel())) > 2) continue; - if (sServerFacade->GetDistance2d(bot, player) > sPlayerbotAIConfig->sightDistance) + if (ServerFacade::instance().GetDistance2d(bot, player) > PlayerbotAIConfig::instance().sightDistance) continue; // When inviting the 5th member of the group convert to raid for future invites. @@ -96,19 +98,19 @@ bool InviteNearbyToGroupAction::Execute(Event event) bot->GetGroup()->GetMembersCount() > 3) { auto convertOp = std::make_unique(bot->GetGUID()); - sPlayerbotWorldProcessor->QueueOperation(std::move(convertOp)); + PlayerbotWorldThreadProcessor::instance().QueueOperation(std::move(convertOp)); } - if (sPlayerbotAIConfig->inviteChat && sRandomPlayerbotMgr->IsRandomBot(bot)) + if (PlayerbotAIConfig::instance().inviteChat && RandomPlayerbotMgr::instance().IsRandomBot(bot)) { std::map placeholders; placeholders["%player"] = player->GetName(); if (group && group->isRaidGroup()) - bot->Say(BOT_TEXT2("join_raid", placeholders), + bot->Say(PlayerbotTextMgr::instance().GetBotText("join_raid", placeholders), (bot->GetTeamId() == TEAM_ALLIANCE ? LANG_COMMON : LANG_ORCISH)); else - bot->Say(BOT_TEXT2("join_group", placeholders), + bot->Say(PlayerbotTextMgr::instance().GetBotText("join_group", placeholders), (bot->GetTeamId() == TEAM_ALLIANCE ? LANG_COMMON : LANG_ORCISH)); } @@ -120,7 +122,7 @@ bool InviteNearbyToGroupAction::Execute(Event event) bool InviteNearbyToGroupAction::isUseful() { - if (!sPlayerbotAIConfig->randomBotGroupNearby) + if (!PlayerbotAIConfig::instance().randomBotGroupNearby) return false; if (bot->InBattleground()) @@ -166,11 +168,9 @@ std::vector InviteGuildToGroupAction::getGuildMembers() return worker.GetResult(); } -bool InviteGuildToGroupAction::Execute(Event event) +bool InviteGuildToGroupAction::Execute(Event) { - Guild* guild = sGuildMgr->GetGuildById(bot->GetGuildId()); - - for (auto& member : getGuildMembers()) + for (auto& member : this->getGuildMembers()) { Player* player = member; @@ -186,7 +186,7 @@ bool InviteGuildToGroupAction::Execute(Event event) if (player->isDND()) continue; - if (!sPlayerbotAIConfig->randomBotInvitePlayer && GET_PLAYERBOT_AI(player)->IsRealPlayer()) + if (!PlayerbotAIConfig::instance().randomBotInvitePlayer && GET_PLAYERBOT_AI(player)->IsRealPlayer()) continue; if (player->IsBeingTeleported()) @@ -221,7 +221,7 @@ bool InviteGuildToGroupAction::Execute(Event event) player->GetLevel() + 5) // Do not invite members that too low level or risk dragging them to deadly places. continue; - if (!playerAi && sServerFacade->GetDistance2d(bot, player) > sPlayerbotAIConfig->sightDistance) + if (!playerAi && ServerFacade::instance().GetDistance2d(bot, player) > PlayerbotAIConfig::instance().sightDistance) continue; Group* group = bot->GetGroup(); @@ -230,16 +230,16 @@ bool InviteGuildToGroupAction::Execute(Event event) bot->GetGroup()->GetMembersCount() > 3) { auto convertOp = std::make_unique(bot->GetGUID()); - sPlayerbotWorldProcessor->QueueOperation(std::move(convertOp)); + PlayerbotWorldThreadProcessor::instance().QueueOperation(std::move(convertOp)); } - if (sPlayerbotAIConfig->inviteChat && - (sRandomPlayerbotMgr->IsRandomBot(bot) || !botAI->HasActivePlayerMaster())) + if (PlayerbotAIConfig::instance().inviteChat && + (RandomPlayerbotMgr::instance().IsRandomBot(bot) || !botAI->HasActivePlayerMaster())) { BroadcastHelper::BroadcastGuildGroupOrRaidInvite(botAI, bot, player, group); } - return Invite(bot, player); + return this->Invite(bot, player); } return false; @@ -271,7 +271,7 @@ bool JoinGroupAction::Execute(Event event) if (botAI->HasRealPlayerMaster()) return false; - if (!botAI->DoSpecificAction("leave", event, true)) + if (!botAI->DoSpecificAction(CreateNextAction(1.0f).factory, event, true)) return false; } @@ -373,7 +373,7 @@ bool LfgAction::Execute(Event event) else { auto convertOp = std::make_unique(requester->GetGUID()); - sPlayerbotWorldProcessor->QueueOperation(std::move(convertOp)); + PlayerbotWorldThreadProcessor::instance().QueueOperation(std::move(convertOp)); } } @@ -420,7 +420,7 @@ bool LfgAction::Execute(Event event) if (botAI->HasRealPlayerMaster()) return false; - if (!botAI->DoSpecificAction("leave", event, true)) + if (!botAI->DoSpecificAction(CreateNextAction(1.0f).factory, event, true)) return false; } @@ -429,7 +429,7 @@ bool LfgAction::Execute(Event event) if (invite) { Event acceptEvent("accept invitation", requester ? requester->GetGUID() : ObjectGuid::Empty); - if (!botAI->DoSpecificAction("accept invitation", acceptEvent, true)) + if (!botAI->DoSpecificAction(CreateNextAction(1.0f).factory, acceptEvent, true)) return false; std::map placeholders; @@ -442,17 +442,11 @@ bool LfgAction::Execute(Event event) out << "Joining as " << placeholders["%role"] << ", " << placeholders["%spotsleft"] << " " << placeholders["%role"] << " spots left."; botAI->TellMasterNoFacing(out.str()); - - //botAI->DoSpecificAction("autogear"); - //botAI->DoSpecificAction("maintenance"); } else { out << "Joining as " << placeholders["%role"] << "."; botAI->TellMasterNoFacing(out.str()); - - //botAI->DoSpecificAction("autogear"); - //botAI->DoSpecificAction("maintenance"); } return true; diff --git a/src/Ai/Base/Actions/LeaveGroupAction.cpp b/src/Ai/Base/Actions/LeaveGroupAction.cpp index a279c9426c..47b7724827 100644 --- a/src/Ai/Base/Actions/LeaveGroupAction.cpp +++ b/src/Ai/Base/Actions/LeaveGroupAction.cpp @@ -33,7 +33,7 @@ bool PartyCommandAction::Execute(Event event) Player* master = GetMaster(); if (master && member == master->GetName()) { - if (sRandomPlayerbotMgr->IsRandomBot(bot)) + if (sRandomPlayerbotMgr.IsRandomBot(bot)) { Player* newMaster = botAI->FindNewMaster(); if (newMaster || bot->InBattleground()) @@ -92,7 +92,7 @@ bool LeaveGroupAction::Leave() return true; } -bool LeaveFarAwayAction::Execute(Event event) +bool LeaveFarAwayAction::Execute(Event) { // allow bot to leave party when they want return Leave(); @@ -150,7 +150,7 @@ bool LeaveFarAwayAction::isUseful() if (abs(int32(groupLeader->GetLevel() - bot->GetLevel())) > 4) return true; - if (bot->GetMapId() != groupLeader->GetMapId() || bot->GetDistance2d(groupLeader) >= 2 * sPlayerbotAIConfig->rpgDistance) + if (bot->GetMapId() != groupLeader->GetMapId() || bot->GetDistance2d(groupLeader) >= 2 * sPlayerbotAIConfig.rpgDistance) { return true; } diff --git a/src/Ai/Base/Actions/LfgActions.cpp b/src/Ai/Base/Actions/LfgActions.cpp index 15f8b92f25..1a3a332715 100644 --- a/src/Ai/Base/Actions/LfgActions.cpp +++ b/src/Ai/Base/Actions/LfgActions.cpp @@ -8,19 +8,22 @@ #include "AiFactory.h" #include "ItemVisitors.h" #include "LFGMgr.h" -#include "LFGPackets.h" #include "Opcodes.h" #include "Playerbots.h" #include "World.h" #include "WorldPacket.h" +#include "RandomPlayerbotMgr.h" using namespace lfg; -bool LfgJoinAction::Execute(Event event) { return JoinLFG(); } +bool LfgJoinAction::Execute(Event) +{ + return JoinLFG(); +} -uint32 LfgJoinAction::GetRoles() +uint8_t LfgJoinAction::GetRoles() const { - if (!sRandomPlayerbotMgr->IsRandomBot(bot)) + if (!RandomPlayerbotMgr::instance().IsRandomBot(bot)) { if (botAI->IsTank(bot)) return PLAYER_ROLE_TANK; @@ -30,7 +33,7 @@ uint32 LfgJoinAction::GetRoles() return PLAYER_ROLE_DAMAGE; } - uint8 spec = AiFactory::GetPlayerSpecTab(bot); + const uint8_t spec = AiFactory::GetPlayerSpecTab(bot); switch (bot->getClass()) { case CLASS_DRUID: @@ -101,7 +104,7 @@ bool LfgJoinAction::JoinLFG() LfgDungeonSet list; std::vector selected; - std::vector dungeons = sRandomPlayerbotMgr->LfgDungeons[bot->GetTeamId()]; + std::vector dungeons = RandomPlayerbotMgr::instance().LfgDungeons[bot->GetTeamId()]; if (!dungeons.size()) return false; @@ -115,9 +118,16 @@ bool LfgJoinAction::JoinLFG() auto const& botLevel = bot->GetLevel(); /*LFG_TYPE_RANDOM on classic is 15-58 so bot over level 25 will never queue*/ - if (dungeon->MinLevel && (botLevel < dungeon->MinLevel || botLevel > dungeon->MaxLevel) || - (botLevel > dungeon->MinLevel + 10 && dungeon->TypeID == LFG_TYPE_DUNGEON)) + if ( + ( + dungeon->MinLevel != 0 + && (botLevel < dungeon->MinLevel || botLevel > dungeon->MaxLevel) + ) + || (botLevel > dungeon->MinLevel + 10 && dungeon->TypeID == LFG_TYPE_DUNGEON) + ) + { continue; + } selected.push_back(dungeon->ID); list.insert(dungeon->ID); @@ -170,28 +180,31 @@ bool LfgJoinAction::JoinLFG() return true; } -bool LfgRoleCheckAction::Execute(Event event) +bool LfgRoleCheckAction::Execute(Event) { - if (Group* group = bot->GetGroup()) + const Group* const group = bot->GetGroup(); + + if (group == nullptr) { - uint32 currentRoles = sLFGMgr->GetRoles(bot->GetGUID()); - uint32 newRoles = GetRoles(); - // if (currentRoles == newRoles) - // return false; + return false; + } - WorldPacket* packet = new WorldPacket(CMSG_LFG_SET_ROLES); - *packet << (uint8)newRoles; - bot->GetSession()->QueuePacket(packet); - // sLFGMgr->SetRoles(bot->GetGUID(), newRoles); - // sLFGMgr->UpdateRoleCheck(group->GetGUID(), bot->GetGUID(), newRoles); + const uint8_t newRoles = this->GetRoles(); - LOG_INFO("playerbots", "Bot {} {}:{} <{}>: LFG roles checked", bot->GetGUID().ToString().c_str(), - bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", bot->GetLevel(), bot->GetName().c_str()); + WorldPacket* const packet = new WorldPacket(CMSG_LFG_SET_ROLES); + *packet << newRoles; + bot->GetSession()->QueuePacket(packet); - return true; - } + LOG_INFO( + "playerbots", + "Bot {} {}:{} <{}>: LFG roles checked", + bot->GetGUID().ToString().c_str(), + bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", + bot->GetLevel(), + bot->GetName().c_str() + ); - return false; + return true; } bool LfgAcceptAction::Execute(Event event) @@ -216,9 +229,9 @@ bool LfgAcceptAction::Execute(Event event) *packet << id << true; bot->GetSession()->QueuePacket(packet); - if (sRandomPlayerbotMgr->IsRandomBot(bot) && !bot->GetGroup()) + if (RandomPlayerbotMgr::instance().IsRandomBot(bot) && !bot->GetGroup()) { - sRandomPlayerbotMgr->Refresh(bot); + RandomPlayerbotMgr::instance().Refresh(bot); botAI->ResetStrategies(); } @@ -251,9 +264,9 @@ bool LfgAcceptAction::Execute(Event event) *packet << id << true; bot->GetSession()->QueuePacket(packet); - if (sRandomPlayerbotMgr->IsRandomBot(bot) && !bot->GetGroup()) + if (RandomPlayerbotMgr::instance().IsRandomBot(bot) && !bot->GetGroup()) { - sRandomPlayerbotMgr->Refresh(bot); + RandomPlayerbotMgr::instance().Refresh(bot); botAI->ResetStrategies(); } @@ -265,7 +278,7 @@ bool LfgAcceptAction::Execute(Event event) return false; } -bool LfgLeaveAction::Execute(Event event) +bool LfgLeaveAction::Execute(Event) { // Don't leave if lfg strategy enabled // if (botAI->HasStrategy("lfg", BOT_STATE_NON_COMBAT)) @@ -306,7 +319,7 @@ bool LfgTeleportAction::Execute(Event event) bool LfgJoinAction::isUseful() { - if (!sPlayerbotAIConfig->randomBotJoinLfg) + if (!sPlayerbotAIConfig.randomBotJoinLfg) { // botAI->ChangeStrategy("-lfg", BOT_STATE_NON_COMBAT); return false; @@ -337,7 +350,7 @@ bool LfgJoinAction::isUseful() if (bot->isDead()) return false; - if (!sRandomPlayerbotMgr->IsRandomBot(bot)) + if (!RandomPlayerbotMgr::instance().IsRandomBot(bot)) return false; Map* map = bot->GetMap(); diff --git a/src/Ai/Base/Actions/LfgActions.h b/src/Ai/Base/Actions/LfgActions.h index 8622a42d76..a45ac2c8a9 100644 --- a/src/Ai/Base/Actions/LfgActions.h +++ b/src/Ai/Base/Actions/LfgActions.h @@ -20,7 +20,7 @@ class LfgJoinAction : public InventoryAction protected: bool JoinLFG(); - uint32 GetRoles(); + uint8_t GetRoles() const; }; class LfgAcceptAction : public LfgJoinAction diff --git a/src/Ai/Base/Actions/ListQuestsActions.cpp b/src/Ai/Base/Actions/ListQuestsActions.cpp index 7968417059..0071b113fe 100644 --- a/src/Ai/Base/Actions/ListQuestsActions.cpp +++ b/src/Ai/Base/Actions/ListQuestsActions.cpp @@ -107,14 +107,14 @@ uint32 ListQuestsAction::ListQuests(bool completed, bool silent, QuestTravelDeta if (travelDetail == QUEST_TRAVEL_DETAIL_SUMMARY) { std::vector allDestinations = - sTravelMgr->getQuestTravelDestinations(bot, questId, true, true, -1); + TravelMgr::instance().getQuestTravelDestinations(bot, questId, true, true, -1); std::vector availDestinations = - sTravelMgr->getQuestTravelDestinations(bot, questId, botAI->GetMaster(), false, -1); + TravelMgr::instance().getQuestTravelDestinations(bot, questId, botAI->GetMaster(), false, -1); uint32 desTot = allDestinations.size(); uint32 desAvail = availDestinations.size(); - uint32 desFull = desAvail - sTravelMgr->getQuestTravelDestinations(bot, questId, false, false, -1).size(); - uint32 desRange = desAvail - sTravelMgr->getQuestTravelDestinations(bot, questId, false, false).size(); + uint32 desFull = desAvail - TravelMgr::instance().getQuestTravelDestinations(bot, questId, false, false, -1).size(); + uint32 desRange = desAvail - TravelMgr::instance().getQuestTravelDestinations(bot, questId, false, false).size(); uint32 tpoints = 0; uint32 apoints = 0; @@ -140,7 +140,7 @@ uint32 ListQuestsAction::ListQuests(bool completed, bool silent, QuestTravelDeta { uint32 limit = 0; std::vector allDestinations = - sTravelMgr->getQuestTravelDestinations(bot, questId, true, true, -1); + TravelMgr::instance().getQuestTravelDestinations(bot, questId, true, true, -1); std::sort(allDestinations.begin(), allDestinations.end(), [botPos](TravelDestination* i, TravelDestination* j) { diff --git a/src/Ai/Base/Actions/ListSpellsAction.cpp b/src/Ai/Base/Actions/ListSpellsAction.cpp index 6f67aef1aa..aed7adc6e7 100644 --- a/src/Ai/Base/Actions/ListSpellsAction.cpp +++ b/src/Ai/Base/Actions/ListSpellsAction.cpp @@ -136,7 +136,7 @@ std::vector> ListSpellsAction::GetSpellList(std:: if (spellInfo->IsPassive()) continue; - SkillLineAbilityEntry const* skillLine = sPlayerbotSpellRepository->GetSkillLine(itr->first); + SkillLineAbilityEntry const* skillLine = PlayerbotSpellRepository::Instance().GetSkillLine(itr->first); if (skill != SKILL_NONE && (!skillLine || skillLine->SkillLine != skill)) continue; @@ -175,7 +175,7 @@ std::vector> ListSpellsAction::GetSpellList(std:: FindItemByIdVisitor visitor(itemid); uint32 reagentsInInventory = InventoryAction::GetItemCount(&visitor); - bool buyable = sPlayerbotSpellRepository->IsItemBuyable(itemid); + bool buyable = PlayerbotSpellRepository::Instance().IsItemBuyable(itemid); if (!buyable) { uint32 craftable = reagentsInInventory / reagentsRequired; diff --git a/src/Ai/Base/Actions/LootAction.cpp b/src/Ai/Base/Actions/LootAction.cpp index 2e0656e711..93368f5244 100644 --- a/src/Ai/Base/Actions/LootAction.cpp +++ b/src/Ai/Base/Actions/LootAction.cpp @@ -25,7 +25,7 @@ bool LootAction::Execute(Event /*event*/) LootObject prevLoot = AI_VALUE(LootObject, "loot target"); LootObject const& lootObject = - AI_VALUE(LootObjectStack*, "available loot")->GetLoot(sPlayerbotAIConfig->lootDistance); + AI_VALUE(LootObjectStack*, "available loot")->GetLoot(sPlayerbotAIConfig.lootDistance); if (!prevLoot.IsEmpty() && prevLoot.guid != lootObject.guid) { @@ -37,7 +37,7 @@ bool LootAction::Execute(Event /*event*/) // Provide a system to check if the game object id is disallowed in the user configurable list or not. // Check if the game object id is disallowed in the user configurable list or not. - if (sPlayerbotAIConfig->disallowedGameObjects.find(lootObject.guid.GetEntry()) != sPlayerbotAIConfig->disallowedGameObjects.end()) + if (sPlayerbotAIConfig.disallowedGameObjects.find(lootObject.guid.GetEntry()) != sPlayerbotAIConfig.disallowedGameObjects.end()) { return false; // Game object ID is disallowed, so do not proceed } @@ -50,7 +50,7 @@ bool LootAction::Execute(Event /*event*/) bool LootAction::isUseful() { - return sPlayerbotAIConfig->freeMethodLoot || !bot->GetGroup() || bot->GetGroup()->GetLootMethod() != FREE_FOR_ALL; + return sPlayerbotAIConfig.freeMethodLoot || !bot->GetGroup() || bot->GetGroup()->GetLootMethod() != FREE_FOR_ALL; } enum ProfessionSpells @@ -95,7 +95,7 @@ bool OpenLootAction::DoLoot(LootObject& lootObject) if (bot->IsMounted()) { bot->Dismount(); - botAI->SetNextCheckDelay(sPlayerbotAIConfig->lootDelay); // Small delay to avoid animation issues + botAI->SetNextCheckDelay(sPlayerbotAIConfig.lootDelay); // Small delay to avoid animation issues } if (creature && creature->HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE)) @@ -104,7 +104,7 @@ bool OpenLootAction::DoLoot(LootObject& lootObject) *packet << lootObject.guid; bot->GetSession()->QueuePacket(packet); // bot->GetSession()->HandleLootOpcode(packet); - botAI->SetNextCheckDelay(sPlayerbotAIConfig->lootDelay); + botAI->SetNextCheckDelay(sPlayerbotAIConfig.lootDelay); return true; } @@ -202,7 +202,7 @@ uint32 OpenLootAction::GetOpeningSpell(LootObject& lootObject, GameObject* go) return spellId; } - return sPlayerbotAIConfig->openGoSpell; + return sPlayerbotAIConfig.openGoSpell; } bool OpenLootAction::CanOpenLock(LootObject& /*lootObject*/, SpellInfo const* spellInfo, GameObject* go) @@ -294,7 +294,7 @@ bool StoreLootAction::AuctionItem(uint32 itemId) AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(ahEntry); - uint32 price = oldItem->GetCount() * proto->BuyPrice * sRandomPlayerbotMgr->GetBuyMultiplier(bot); + uint32 price = oldItem->GetCount() * proto->BuyPrice * sRandomPlayerbotMgr.GetBuyMultiplier(bot); uint32 stackCount = urand(1, proto->GetMaxStackSize()); if (!price || !stackCount) @@ -426,28 +426,28 @@ bool StoreLootAction::Execute(Event event) } Player* master = botAI->GetMaster(); - if (sRandomPlayerbotMgr->IsRandomBot(bot) && master) + if (sRandomPlayerbotMgr.IsRandomBot(bot) && master) { - uint32 price = itemcount * proto->BuyPrice * sRandomPlayerbotMgr->GetBuyMultiplier(bot) + gold; + uint32 price = itemcount * proto->BuyPrice * sRandomPlayerbotMgr.GetBuyMultiplier(bot) + gold; if (price) - sRandomPlayerbotMgr->AddTradeDiscount(bot, master, price); + sRandomPlayerbotMgr.AddTradeDiscount(bot, master, price); if (Group* group = bot->GetGroup()) for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) if (ref->GetSource() != bot) - sGuildTaskMgr->CheckItemTask(itemid, itemcount, ref->GetSource(), bot); + GuildTaskMgr::instance().CheckItemTask(itemid, itemcount, ref->GetSource(), bot); } WorldPacket* packet = new WorldPacket(CMSG_AUTOSTORE_LOOT_ITEM, 1); *packet << itemindex; bot->GetSession()->QueuePacket(packet); // bot->GetSession()->HandleAutostoreLootItemOpcode(packet); - botAI->SetNextCheckDelay(sPlayerbotAIConfig->lootDelay); + botAI->SetNextCheckDelay(sPlayerbotAIConfig.lootDelay); - if (proto->Quality > ITEM_QUALITY_NORMAL && !urand(0, 50) && botAI->HasStrategy("emote", BOT_STATE_NON_COMBAT) && sPlayerbotAIConfig->randomBotEmote) + if (proto->Quality > ITEM_QUALITY_NORMAL && !urand(0, 50) && botAI->HasStrategy("emote", BOT_STATE_NON_COMBAT) && sPlayerbotAIConfig.randomBotEmote) botAI->PlayEmote(TEXT_EMOTE_CHEER); - if (proto->Quality >= ITEM_QUALITY_RARE && !urand(0, 1) && botAI->HasStrategy("emote", BOT_STATE_NON_COMBAT) && sPlayerbotAIConfig->randomBotEmote) + if (proto->Quality >= ITEM_QUALITY_RARE && !urand(0, 1) && botAI->HasStrategy("emote", BOT_STATE_NON_COMBAT) && sPlayerbotAIConfig.randomBotEmote) botAI->PlayEmote(TEXT_EMOTE_CHEER); BroadcastHelper::BroadcastLootingItem(botAI, bot, proto); @@ -498,7 +498,7 @@ bool StoreLootAction::IsLootAllowed(uint32 itemid, PlayerbotAI* botAI) { // if (AI_VALUE2(uint32, "item count", proto->Name1) < quest->RequiredItemCount[i]) // { - // if (botAI->GetMaster() && sPlayerbotAIConfig->syncQuestWithPlayer) + // if (botAI->GetMaster() && sPlayerbotAIConfig.syncQuestWithPlayer) // return false; //Quest is autocomplete for the bot so no item needed. // } @@ -514,7 +514,7 @@ bool StoreLootAction::IsLootAllowed(uint32 itemid, PlayerbotAI* botAI) bool canLoot = lootStrategy->CanLoot(proto, context); // if (canLoot && proto->Bonding == BIND_WHEN_PICKED_UP && botAI->HasActivePlayerMaster()) - // canLoot = sPlayerbotAIConfig->IsInRandomAccountList(botAI->GetBot()->GetSession()->GetAccountId()); + // canLoot = sPlayerbotAIConfig.IsInRandomAccountList(botAI->GetBot()->GetSession()->GetAccountId()); return canLoot; } diff --git a/src/Ai/Base/Actions/LootRollAction.cpp b/src/Ai/Base/Actions/LootRollAction.cpp index 912f75fddf..0047522730 100644 --- a/src/Ai/Base/Actions/LootRollAction.cpp +++ b/src/Ai/Base/Actions/LootRollAction.cpp @@ -13,7 +13,7 @@ #include "PlayerbotAIConfig.h" #include "Playerbots.h" -bool LootRollAction::Execute(Event event) +bool LootRollAction::Execute(Event) { Group* group = bot->GetGroup(); if (!group) @@ -27,7 +27,6 @@ bool LootRollAction::Execute(Event event) continue; } ObjectGuid guid = roll->itemGUID; - uint32 slot = roll->itemSlot; uint32 itemId = roll->itemid; int32 randomProperty = 0; if (roll->itemRandomPropId) @@ -84,11 +83,11 @@ bool LootRollAction::Execute(Event event) break; } } - if (sPlayerbotAIConfig->lootRollLevel == 0) + if (sPlayerbotAIConfig.lootRollLevel == 0) { vote = PASS; } - else if (sPlayerbotAIConfig->lootRollLevel == 1) + else if (sPlayerbotAIConfig.lootRollLevel == 1) { if (vote == NEED) { @@ -186,7 +185,6 @@ bool MasterLootRollAction::Execute(Event event) if (!group) return false; - RollVote vote = CalculateRollVote(proto); group->CountRollVote(bot->GetGUID(), creatureGuid, CalculateRollVote(proto)); return true; diff --git a/src/Ai/Base/Actions/LootStrategyAction.cpp b/src/Ai/Base/Actions/LootStrategyAction.cpp index 68f8089c2e..b5f328b041 100644 --- a/src/Ai/Base/Actions/LootStrategyAction.cpp +++ b/src/Ai/Base/Actions/LootStrategyAction.cpp @@ -16,7 +16,6 @@ bool LootStrategyAction::Execute(Event event) { std::string const strategy = event.getParam(); - LootObjectStack* lootItems = AI_VALUE(LootObjectStack*, "available loot"); std::set& alwaysLootItems = AI_VALUE(std::set&, "always loot list"); Value* lootStrategy = context->GetValue("loot strategy"); diff --git a/src/Ai/Base/Actions/MailAction.cpp b/src/Ai/Base/Actions/MailAction.cpp index 4ee2fee6d7..cbbc6eb6c5 100644 --- a/src/Ai/Base/Actions/MailAction.cpp +++ b/src/Ai/Base/Actions/MailAction.cpp @@ -78,7 +78,7 @@ class TellMailProcessor : public MailProcessor class TakeMailProcessor : public MailProcessor { public: - bool Process(uint32 index, Mail* mail, PlayerbotAI* botAI) override + bool Process(uint32_t, Mail* mail, PlayerbotAI* botAI) override { Player* bot = botAI->GetBot(); if (!CheckBagSpace(bot)) @@ -104,8 +104,14 @@ class TakeMailProcessor : public MailProcessor { std::vector guids; for (MailItemInfoVec::iterator i = mail->items.begin(); i != mail->items.end(); ++i) - if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(i->item_template)) + { + const ItemTemplate* const itemTemplate = ObjectMgr::instance()->GetItemTemplate(i->item_template); + + if (itemTemplate != nullptr) + { guids.push_back(i->item_guid); + } + } for (std::vector::iterator i = guids.begin(); i != guids.end(); ++i) { @@ -134,7 +140,7 @@ class TakeMailProcessor : public MailProcessor private: bool CheckBagSpace(Player* bot) { - uint32 totalused = 0, total = 16; + uint32 totalused = 0; for (uint8 slot = INVENTORY_SLOT_ITEM_START; slot < INVENTORY_SLOT_ITEM_END; slot++) if (bot->GetItemByPos(INVENTORY_SLOT_BAG_0, slot)) ++totalused; @@ -157,7 +163,7 @@ class TakeMailProcessor : public MailProcessor class DeleteMailProcessor : public MailProcessor { public: - bool Process(uint32 index, Mail* mail, PlayerbotAI* botAI) override + bool Process(uint32_t, Mail* mail, PlayerbotAI* botAI) override { std::ostringstream out; out << "|cffffffff" << mail->subject << "|cffff0000 deleted"; @@ -172,7 +178,7 @@ class DeleteMailProcessor : public MailProcessor class ReadMailProcessor : public MailProcessor { public: - bool Process(uint32 index, Mail* mail, PlayerbotAI* botAI) override + bool Process(uint32_t, Mail* mail, PlayerbotAI* botAI) override { std::ostringstream out, body; out << "|cffffffff" << mail->subject; diff --git a/src/Ai/Base/Actions/MoveToRpgTargetAction.cpp b/src/Ai/Base/Actions/MoveToRpgTargetAction.cpp index 618af10af1..0fbbf6b7e9 100644 --- a/src/Ai/Base/Actions/MoveToRpgTargetAction.cpp +++ b/src/Ai/Base/Actions/MoveToRpgTargetAction.cpp @@ -11,7 +11,7 @@ #include "LastMovementValue.h" #include "Playerbots.h" -bool MoveToRpgTargetAction::Execute(Event event) +bool MoveToRpgTargetAction::Execute(Event) { GuidPosition guidP = AI_VALUE(GuidPosition, "rpg target"); Unit* unit = botAI->GetUnit(guidP); @@ -24,7 +24,6 @@ bool MoveToRpgTargetAction::Execute(Event event) { return false; } - Player* player = guidP.GetPlayer(); WorldObject* wo = nullptr; if (unit) @@ -61,7 +60,7 @@ bool MoveToRpgTargetAction::Execute(Event event) } if ((unit && unit->isMoving() && !urand(0, 20)) || !ChooseRpgTargetAction::isFollowValid(bot, wo) || - guidP.distance(bot) > sPlayerbotAIConfig->reactDistance * 2 || !urand(0, 50)) + guidP.distance(bot) > sPlayerbotAIConfig.reactDistance * 2 || !urand(0, 50)) { AI_VALUE(GuidSet&, "ignore rpg target").insert(AI_VALUE(GuidPosition, "rpg target")); RESET_AI_VALUE(GuidPosition, "rpg target"); @@ -73,7 +72,7 @@ bool MoveToRpgTargetAction::Execute(Event event) float z = wo->GetPositionZ(); float mapId = wo->GetMapId(); - if (sPlayerbotAIConfig->randombotsWalkingRPG) + if (sPlayerbotAIConfig.randombotsWalkingRPG) if (!bot->IsOutdoors()) bot->m_movementInfo.AddMovementFlag(MOVEMENTFLAG_WALKING); diff --git a/src/Ai/Base/Actions/MoveToTravelTargetAction.cpp b/src/Ai/Base/Actions/MoveToTravelTargetAction.cpp index ed60339b82..1679a824e1 100644 --- a/src/Ai/Base/Actions/MoveToTravelTargetAction.cpp +++ b/src/Ai/Base/Actions/MoveToTravelTargetAction.cpp @@ -7,10 +7,9 @@ #include "ChooseRpgTargetAction.h" #include "LootObjectStack.h" -#include "PathGenerator.h" #include "Playerbots.h" -bool MoveToTravelTargetAction::Execute(Event event) +bool MoveToTravelTargetAction::Execute(Event) { TravelTarget* target = AI_VALUE(TravelTarget*, "travel target"); @@ -43,7 +42,7 @@ bool MoveToTravelTargetAction::Execute(Event event) if (memberDistance < 50.0f) continue; - if (memberDistance > sPlayerbotAIConfig->reactDistance * 20) + if (memberDistance > sPlayerbotAIConfig.reactDistance * 20) continue; // float memberAngle = botLocation.getAngleBetween(targetPos, memberPos); @@ -65,9 +64,9 @@ bool MoveToTravelTargetAction::Execute(Event event) botAI->TellMasterNoFacing(out); } - target->setExpireIn(target->getTimeLeft() + sPlayerbotAIConfig->maxWaitForMove); + target->setExpireIn(target->getTimeLeft() + sPlayerbotAIConfig.maxWaitForMove); - botAI->SetNextCheckDelay(sPlayerbotAIConfig->maxWaitForMove); + botAI->SetNextCheckDelay(sPlayerbotAIConfig.maxWaitForMove); return true; } @@ -80,7 +79,7 @@ bool MoveToTravelTargetAction::Execute(Event event) if (target->getMaxTravelTime() > target->getTimeLeft()) // The bot is late. Speed it up. { - // distance = sPlayerbotAIConfig->fleeDistance; + // distance = sPlayerbotAIConfig.fleeDistance; // angle = bot->GetAngle(location.GetPositionX(), location.GetPositionY()); // location = botLocation.getLocation(); } diff --git a/src/Ai/Base/Actions/MovementActions.cpp b/src/Ai/Base/Actions/MovementActions.cpp index 69e5c278ba..408ec2fb61 100644 --- a/src/Ai/Base/Actions/MovementActions.cpp +++ b/src/Ai/Base/Actions/MovementActions.cpp @@ -11,11 +11,11 @@ #include #include "Corpse.h" +#include "DynamicObject.h" #include "Event.h" #include "FleeManager.h" #include "G3D/Vector3.h" #include "GameObject.h" -#include "Geometry.h" #include "LastMovementValue.h" #include "LootObjectStack.h" #include "Map.h" @@ -36,9 +36,7 @@ #include "SpellAuraEffects.h" #include "SpellInfo.h" #include "Stances.h" -#include "TargetedMovementGenerator.h" #include "Timer.h" -#include "Transport.h" #include "Unit.h" #include "Vehicle.h" #include "WaypointMovementGenerator.h" @@ -51,7 +49,7 @@ MovementAction::MovementAction(PlayerbotAI* botAI, std::string const name) : Act void MovementAction::CreateWp(Player* wpOwner, float x, float y, float z, float o, uint32 entry, bool important) { float dist = wpOwner->GetDistance(x, y, z); - float delay = 1000.0f * dist / wpOwner->GetSpeed(MOVE_RUN) + sPlayerbotAIConfig->reactDelay; + float delay = 1000.0f * dist / wpOwner->GetSpeed(MOVE_RUN) + sPlayerbotAIConfig.reactDelay; // if (!important) // delay *= 0.25; @@ -78,7 +76,6 @@ bool MovementAction::JumpTo(uint32 mapId, float x, float y, float z, MovementPri { return false; } - float botZ = bot->GetPositionZ(); float speed = bot->GetSpeed(MOVE_RUN); MotionMaster& mm = *bot->GetMotionMaster(); mm.Clear(); @@ -100,9 +97,6 @@ bool MovementAction::MoveNear(WorldObject* target, float distance, MovementPrior distance += target->GetCombatReach(); - float x = target->GetPositionX(); - float y = target->GetPositionY(); - float z = target->GetPositionZ(); float followAngle = GetFollowAngle(); for (float angle = followAngle; angle <= followAngle + static_cast(2 * M_PI); @@ -120,7 +114,6 @@ bool MovementAction::MoveNear(WorldObject* target, float distance, MovementPrior return true; } - // botAI->TellError("All paths not in LOS"); return false; } @@ -129,9 +122,6 @@ bool MovementAction::MoveToLOS(WorldObject* target, bool ranged) if (!target) return false; - // std::ostringstream out; out << "Moving to LOS!"; - // bot->Say(out.str(), LANG_UNIVERSAL); - float x = target->GetPositionX(); float y = target->GetPositionY(); float z = target->GetPositionZ(); @@ -176,7 +166,7 @@ bool MovementAction::MoveToLOS(WorldObject* target, bool ranged) return false; } -bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, bool react, bool normal_only, +bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool, bool, bool normal_only, bool exact_waypoint, MovementPriority priority, bool lessDelay, bool backwards) { UpdateMovementState(); @@ -195,8 +185,8 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, bool generatePath = !bot->IsFlying() && !bot->isSwimming(); bool disableMoveSplinePath = - sPlayerbotAIConfig->disableMoveSplinePath >= 2 || - (sPlayerbotAIConfig->disableMoveSplinePath == 1 && bot->InBattleground()); + sPlayerbotAIConfig.disableMoveSplinePath >= 2 || + (sPlayerbotAIConfig.disableMoveSplinePath == 1 && bot->InBattleground()); if (Vehicle* vehicle = bot->GetVehicle()) { VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(bot); @@ -216,7 +206,7 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, delay -= botAI->GetReactDelay(); } delay = std::max(.0f, delay); - delay = std::min((float)sPlayerbotAIConfig->maxWaitForMove, delay); + delay = std::min((float)sPlayerbotAIConfig.maxWaitForMove, delay); AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation(), delay, priority); return true; } @@ -241,7 +231,7 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, delay -= botAI->GetReactDelay(); } delay = std::max(.0f, delay); - delay = std::min((float)sPlayerbotAIConfig->maxWaitForMove, delay); + delay = std::min((float)sPlayerbotAIConfig.maxWaitForMove, delay); AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation(), delay, priority); return true; } @@ -250,7 +240,7 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, { float modifiedZ; Movement::PointsArray path = - SearchForBestPath(x, y, z, modifiedZ, sPlayerbotAIConfig->maxMovementSearchTime, normal_only); + SearchForBestPath(x, y, z, modifiedZ, sPlayerbotAIConfig.maxMovementSearchTime, normal_only); if (modifiedZ == INVALID_HEIGHT) return false; float distance = bot->GetExactDist(x, y, modifiedZ); @@ -264,7 +254,6 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, // bot->CastStop(); // botAI->InterruptSpell(); // } - G3D::Vector3 endP = path.back(); DoMovePoint(bot, x, y, z, generatePath, backwards); float delay = 1000.0f * MoveDelay(distance, backwards); if (lessDelay) @@ -272,7 +261,7 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, delay -= botAI->GetReactDelay(); } delay = std::max(.0f, delay); - delay = std::min((float)sPlayerbotAIConfig->maxWaitForMove, delay); + delay = std::min((float)sPlayerbotAIConfig.maxWaitForMove, delay); AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation(), delay, priority); return true; } @@ -308,8 +297,8 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, // } // } - // float minDist = sPlayerbotAIConfig->targetPosRecalcDistance; //Minium distance a bot should move. - // float maxDist = sPlayerbotAIConfig->reactDistance; //Maxium distance a bot can move in one single + // float minDist = sPlayerbotAIConfig.targetPosRecalcDistance; //Minium distance a bot should move. + // float maxDist = sPlayerbotAIConfig.reactDistance; //Maxium distance a bot can move in one single // action. float originalZ = z; // save original destination height to check // if bot needs to fly up @@ -372,9 +361,9 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, // if (startPosition.getMapId() != endPosition.getMapId() || totalDistance > maxDist) // { - // if (!sTravelNodeMap->getNodes().empty() && !bot->InBattleground()) + // if (!TravelNodeMap::instance().getNodes().empty() && !bot->InBattleground()) // { - // if (sPlayerbotAIConfig->tweakValue) + // if (sPlayerbotAIConfig.tweakValue) // { // if (lastMove.future.valid()) // { @@ -388,12 +377,12 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, // } // } // else - // movePath = sTravelNodeMap->getFullPath(startPosition, endPosition, bot); + // movePath = TravelNodeMap::instance().getFullPath(startPosition, endPosition, bot); // if (movePath.empty()) // { // //We have no path. Beyond 450yd the standard PathGenerator will probably move the wrong way. - // if (sServerFacade->IsDistanceGreaterThan(totalDistance, maxDist * 3)) + // if (ServerFacade::instance().IsDistanceGreaterThan(totalDistance, maxDist * 3)) // { // movePath.clear(); // movePath.addPoint(endPosition); @@ -402,7 +391,7 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, // bot->StopMoving(); // if (botAI->HasStrategy("debug move", BOT_STATE_NON_COMBAT)) // botAI->TellMasterNoFacing("I have no path"); - // LOG_DEBUG("playerbots", "sServerFacade->IsDistanceGreaterThan(totalDistance, maxDist * 3)"); + // LOG_DEBUG("playerbots", "ServerFacade::instance().IsDistanceGreaterThan(totalDistance, maxDist * 3)"); // return false; // } @@ -450,7 +439,7 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, // if (pathType == TravelNodePathType::portal) // && !botAI->isRealPlayer()) // { // //Log bot movement - // if (sPlayerbotAIConfig->hasLog("bot_movement.csv")) + // if (sPlayerbotAIConfig.hasLog("bot_movement.csv")) // { // WorldPosition telePos; // if (entry) @@ -463,7 +452,7 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, // telePos = movePosition; // std::ostringstream out; - // out << sPlayerbotAIConfig->GetTimestampStr() << "+00,"; + // out << sPlayerbotAIConfig.GetTimestampStr() << "+00,"; // out << bot->GetName() << ","; // if (telePos && telePos.GetExactDist(movePosition) > 0.001) // startPosition.printWKT({ startPosition, movePosition, telePos }, out, 1); @@ -475,7 +464,7 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, // out << bot->GetLevel() << ","; // out << (entry ? -1 : entry); - // sPlayerbotAIConfig->log("bot_movement.csv", out.str().c_str()); + // sPlayerbotAIConfig.log("bot_movement.csv", out.str().c_str()); // } // if (entry) @@ -621,10 +610,10 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, // } // //Log bot movement - // if (sPlayerbotAIConfig->hasLog("bot_movement.csv") && lastMove.lastMoveShort.GetExactDist(movePosition) > 0.001) + // if (sPlayerbotAIConfig.hasLog("bot_movement.csv") && lastMove.lastMoveShort.GetExactDist(movePosition) > 0.001) // { // std::ostringstream out; - // out << sPlayerbotAIConfig->GetTimestampStr() << "+00,"; + // out << sPlayerbotAIConfig.GetTimestampStr() << "+00,"; // out << bot->GetName() << ","; // startPosition.printWKT({ startPosition, movePosition }, out, 1); // out << std::to_string(bot->getRace()) << ","; @@ -632,7 +621,7 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, // out << bot->GetLevel(); // out << 0; - // sPlayerbotAIConfig->log("bot_movement.csv", out.str().c_str()); + // sPlayerbotAIConfig.log("bot_movement.csv", out.str().c_str()); // } // // LOG_DEBUG("playerbots", "({}, {}) -> ({}, {})", startPosition.getX(), startPosition.getY(), // movePosition.getX(), movePosition.getY()); if (!react) @@ -694,7 +683,7 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, // if (botAI->GetMaster()) // { // if (botAI->GetMaster()->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_WALKING) && - // sServerFacade->GetDistance2d(bot, botAI->GetMaster()) < 20.0f) + // ServerFacade::instance().GetDistance2d(bot, botAI->GetMaster()) < 20.0f) // masterWalking = true; // } @@ -779,15 +768,13 @@ bool MovementAction::MoveTo(WorldObject* target, float distance, MovementPriorit float by = bot->GetPositionY(); float bz = bot->GetPositionZ(); - float tx = target->GetPositionX(); - float ty = target->GetPositionY(); float tz = target->GetPositionZ(); float distanceToTarget = bot->GetDistance(target); float angle = bot->GetAngle(target); float needToGo = distanceToTarget - distance; - float maxDistance = sPlayerbotAIConfig->spellDistance; + float maxDistance = sPlayerbotAIConfig.spellDistance; if (needToGo > 0 && needToGo > maxDistance) needToGo = maxDistance; else if (needToGo < 0 && needToGo < -maxDistance) @@ -812,10 +799,6 @@ bool MovementAction::ReachCombatTo(Unit* target, float distance) if (!IsMovingAllowed(target)) return false; - float bx = bot->GetPositionX(); - float by = bot->GetPositionY(); - float bz = bot->GetPositionZ(); - float tx = target->GetPositionX(); float ty = target->GetPositionY(); float tz = target->GetPositionZ(); @@ -898,14 +881,14 @@ bool MovementAction::IsMovingAllowed(WorldObject* target) if (bot->GetMapId() != target->GetMapId()) return false; - // float distance = sServerFacade->GetDistance2d(bot, target); - // if (!bot->InBattleground() && distance > sPlayerbotAIConfig->reactDistance) + // float distance = ServerFacade::instance().GetDistance2d(bot, target); + // if (!bot->InBattleground() && distance > sPlayerbotAIConfig.reactDistance) // return false; return IsMovingAllowed(); } -bool MovementAction::IsMovingAllowed(uint32 mapId, float x, float y, float z) +bool MovementAction::IsMovingAllowed(uint32, float, float, float) { // removed sqrt as means distance limit was effectively 22500 (ReactDistance�) // leaving it commented incase we find ReactDistance limit causes problems @@ -918,12 +901,12 @@ bool MovementAction::IsMovingAllowed(uint32 mapId, float x, float y, float z) return IsMovingAllowed(); } -bool MovementAction::IsDuplicateMove(uint32 mapId, float x, float y, float z) +bool MovementAction::IsDuplicateMove(uint32, float x, float y, float z) { LastMovement& lastMove = *context->GetValue("last movement"); // heuristic 5s - if (lastMove.msTime + sPlayerbotAIConfig->maxWaitForMove < getMSTime() || + if (lastMove.msTime + sPlayerbotAIConfig.maxWaitForMove < getMSTime() || lastMove.lastMoveShort.GetExactDist(x, y, z) > 0.01f) return false; @@ -1046,7 +1029,7 @@ void MovementAction::UpdateMovementState() // if (bot->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE && bot->CanNotReachTarget() && // !bot->InBattleground()) // { - // if (Unit* pTarget = sServerFacade->GetChaseTarget(bot)) + // if (Unit* pTarget = ServerFacade::instance().GetChaseTarget(bot)) // { // if (!bot->IsWithinMeleeRange(pTarget) && pTarget->IsCreature()) // { @@ -1080,7 +1063,7 @@ void MovementAction::UpdateMovementState() // bot->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE) && bot->CanNotReachTarget() // && !bot->InBattleground()) // { - // if (Unit* pTarget = sServerFacade->GetChaseTarget(bot)) + // if (Unit* pTarget = ServerFacade::instance().GetChaseTarget(bot)) // { // if (pTarget != botAI->GetGroupLeader()) // return; @@ -1117,8 +1100,8 @@ bool MovementAction::Follow(Unit* target, float distance, float angle) if (!target) return false; - if (!bot->InBattleground() && sServerFacade->IsDistanceLessOrEqualThan(sServerFacade->GetDistance2d(bot, target), - sPlayerbotAIConfig->followDistance)) + if (!bot->InBattleground() && ServerFacade::instance().IsDistanceLessOrEqualThan(ServerFacade::instance().GetDistance2d(bot, target), + sPlayerbotAIConfig.followDistance)) { // botAI->TellError("No need to follow"); return false; @@ -1126,9 +1109,9 @@ bool MovementAction::Follow(Unit* target, float distance, float angle) /* if (!bot->InBattleground() - && sServerFacade->IsDistanceLessOrEqualThan(sServerFacade->GetDistance2d(bot, target->GetPositionX(), - target->GetPositionY()), sPlayerbotAIConfig->sightDistance) - && abs(bot->GetPositionZ() - target->GetPositionZ()) >= sPlayerbotAIConfig->spellDistance && + && ServerFacade::instance().IsDistanceLessOrEqualThan(ServerFacade::instance().GetDistance2d(bot, target->GetPositionX(), + target->GetPositionY()), sPlayerbotAIConfig.sightDistance) + && abs(bot->GetPositionZ() - target->GetPositionZ()) >= sPlayerbotAIConfig.spellDistance && botAI->HasRealPlayerMaster() && (target->GetMapId() && bot->GetMapId() != target->GetMapId())) { @@ -1189,13 +1172,13 @@ bool MovementAction::Follow(Unit* target, float distance, float angle) WorldPosition botPos(bot); WorldPosition cPos(corpse); - if (botPos.fDist(cPos) > sPlayerbotAIConfig->spellDistance) + if (botPos.fDist(cPos) > sPlayerbotAIConfig.spellDistance) return MoveTo(cPos.getMapId(), cPos.getX(), cPos.getY(), cPos.getZ()); } } - if (sServerFacade->IsDistanceGreaterOrEqualThan(sServerFacade->GetDistance2d(bot, target), - sPlayerbotAIConfig->sightDistance)) + if (ServerFacade::instance().IsDistanceGreaterOrEqualThan(ServerFacade::instance().GetDistance2d(bot, target), + sPlayerbotAIConfig.sightDistance)) { if (target->GetGUID().IsPlayer()) { @@ -1238,11 +1221,11 @@ bool MovementAction::Follow(Unit* target, float distance, float angle) } if (!target->HasUnitState(UNIT_STATE_IN_FLIGHT)) - return MoveTo(target, sPlayerbotAIConfig->followDistance); + return MoveTo(target, sPlayerbotAIConfig.followDistance); } - if (sServerFacade->IsDistanceLessOrEqualThan(sServerFacade->GetDistance2d(bot, target), - sPlayerbotAIConfig->followDistance)) + if (ServerFacade::instance().IsDistanceLessOrEqualThan(ServerFacade::instance().GetDistance2d(bot, target), + sPlayerbotAIConfig.followDistance)) { // botAI->TellError("No need to follow"); return false; @@ -1251,8 +1234,8 @@ bool MovementAction::Follow(Unit* target, float distance, float angle) if (target->IsFriendlyTo(bot) && bot->IsMounted() && AI_VALUE(GuidVector, "all targets").empty()) distance += angle; - if (!bot->InBattleground() && sServerFacade->IsDistanceLessOrEqualThan(sServerFacade->GetDistance2d(bot, target), - sPlayerbotAIConfig->followDistance)) + if (!bot->InBattleground() && ServerFacade::instance().IsDistanceLessOrEqualThan(ServerFacade::instance().GetDistance2d(bot, target), + sPlayerbotAIConfig.followDistance)) { // botAI->TellError("No need to follow"); return false; @@ -1274,7 +1257,7 @@ bool MovementAction::Follow(Unit* target, float distance, float angle) if (bot->GetMotionMaster()->GetCurrentMovementGeneratorType() == FOLLOW_MOTION_TYPE) { - Unit* currentTarget = sServerFacade->GetChaseTarget(bot); + Unit* currentTarget = ServerFacade::instance().GetChaseTarget(bot); if (currentTarget && currentTarget->GetGUID() == target->GetGUID()) return false; } @@ -1286,7 +1269,7 @@ bool MovementAction::Follow(Unit* target, float distance, float angle) return true; } -bool MovementAction::ChaseTo(WorldObject* obj, float distance, float angle) +bool MovementAction::ChaseTo(WorldObject* obj, float distance, float) { if (!IsMovingAllowed()) { @@ -1347,13 +1330,13 @@ void MovementAction::WaitForReach(float distance) { float delay = 1000.0f * MoveDelay(distance); - if (delay > sPlayerbotAIConfig->maxWaitForMove) - delay = sPlayerbotAIConfig->maxWaitForMove; + if (delay > sPlayerbotAIConfig.maxWaitForMove) + delay = sPlayerbotAIConfig.maxWaitForMove; Unit* target = *botAI->GetAiObjectContext()->GetValue("current target"); Unit* player = *botAI->GetAiObjectContext()->GetValue("enemy player target"); - if ((player || target) && delay > sPlayerbotAIConfig->globalCoolDown) - delay = sPlayerbotAIConfig->globalCoolDown; + if ((player || target) && delay > sPlayerbotAIConfig.globalCoolDown) + delay = sPlayerbotAIConfig.globalCoolDown; if (delay < 0) delay = 0; @@ -1378,7 +1361,7 @@ bool MovementAction::Flee(Unit* target) if (!target) return false; - if (!sPlayerbotAIConfig->fleeingEnabled) + if (!sPlayerbotAIConfig.fleeingEnabled) return false; if (!IsMovingAllowed()) @@ -1390,7 +1373,7 @@ bool MovementAction::Flee(Unit* target) bool foundFlee = false; time_t lastFlee = AI_VALUE(LastMovement&, "last movement").lastFlee; time_t now = time(0); - uint32 fleeDelay = urand(2, sPlayerbotAIConfig->returnDelay / 1000); + uint32 fleeDelay = urand(2, sPlayerbotAIConfig.returnDelay / 1000); if (lastFlee) { @@ -1406,7 +1389,7 @@ bool MovementAction::Flee(Unit* target) if (Group* group = bot->GetGroup()) { Unit* fleeTarget = nullptr; - float fleeDistance = sPlayerbotAIConfig->sightDistance; + float fleeDistance = sPlayerbotAIConfig.sightDistance; for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next()) { @@ -1416,8 +1399,7 @@ bool MovementAction::Flee(Unit* target) if (botAI->IsTank(player)) { - float distanceToTank = sServerFacade->GetDistance2d(bot, player); - float distanceToTarget = sServerFacade->GetDistance2d(bot, target); + float distanceToTank = ServerFacade::instance().GetDistance2d(bot, player); if (distanceToTank < fleeDistance) { fleeTarget = player; @@ -1438,8 +1420,6 @@ bool MovementAction::Flee(Unit* target) else // bot is not targeted, try to flee dps/healers { bool isHealer = botAI->IsHeal(bot); - bool isDps = !isHealer && !botAI->IsTank(bot); - bool isTank = botAI->IsTank(bot); bool needHealer = !isHealer && AI_VALUE2(uint8, "health", "self target") < 50; bool isRanged = botAI->IsRanged(bot); @@ -1460,10 +1440,10 @@ bool MovementAction::Flee(Unit* target) if ((isHealer && botAI->IsHeal(player)) || needHealer) { - float distanceToHealer = sServerFacade->GetDistance2d(bot, player); - float distanceToTarget = sServerFacade->GetDistance2d(player, target); + float distanceToHealer = ServerFacade::instance().GetDistance2d(bot, player); + float distanceToTarget = ServerFacade::instance().GetDistance2d(player, target); if (distanceToHealer < fleeDistance && - distanceToTarget > (botAI->GetRange("shoot") / 2 + sPlayerbotAIConfig->followDistance) && + distanceToTarget > (botAI->GetRange("shoot") / 2 + sPlayerbotAIConfig.followDistance) && (needHealer || player->IsWithinLOSInMap(target))) { fleeTarget = player; @@ -1473,10 +1453,10 @@ bool MovementAction::Flee(Unit* target) } else if (isRanged && botAI->IsRanged(player)) { - float distanceToRanged = sServerFacade->GetDistance2d(bot, player); - float distanceToTarget = sServerFacade->GetDistance2d(player, target); + float distanceToRanged = ServerFacade::instance().GetDistance2d(bot, player); + float distanceToTarget = ServerFacade::instance().GetDistance2d(player, target); if (distanceToRanged < fleeDistance && - distanceToTarget > (botAI->GetRange("shoot") / 2 + sPlayerbotAIConfig->followDistance) && + distanceToTarget > (botAI->GetRange("shoot") / 2 + sPlayerbotAIConfig.followDistance) && player->IsWithinLOSInMap(target)) { fleeTarget = player; @@ -1485,10 +1465,10 @@ bool MovementAction::Flee(Unit* target) } } // remember any group member in case no one else found - float distanceToFlee = sServerFacade->GetDistance2d(bot, player); - float distanceToTarget = sServerFacade->GetDistance2d(player, target); + float distanceToFlee = ServerFacade::instance().GetDistance2d(bot, player); + float distanceToTarget = ServerFacade::instance().GetDistance2d(player, target); if (distanceToFlee < spareDistance && - distanceToTarget > (botAI->GetRange("shoot") / 2 + sPlayerbotAIConfig->followDistance) && + distanceToTarget > (botAI->GetRange("shoot") / 2 + sPlayerbotAIConfig.followDistance) && player->IsWithinLOSInMap(target)) { spareTarget = player; @@ -1508,8 +1488,8 @@ bool MovementAction::Flee(Unit* target) if ((!fleeTarget || !foundFlee) && master && master->IsAlive() && master->IsWithinLOSInMap(target)) { - float distanceToTarget = sServerFacade->GetDistance2d(master, target); - if (distanceToTarget > (botAI->GetRange("shoot") / 2 + sPlayerbotAIConfig->followDistance)) + float distanceToTarget = ServerFacade::instance().GetDistance2d(master, target); + if (distanceToTarget > (botAI->GetRange("shoot") / 2 + sPlayerbotAIConfig.followDistance)) foundFlee = MoveNear(master); } } @@ -1844,9 +1824,9 @@ void MovementAction::DoMovePoint(Unit* unit, float x, float y, float z, bool gen } } -bool FleeAction::Execute(Event event) +bool FleeAction::Execute(Event) { - return MoveAway(AI_VALUE(Unit*, "current target"), sPlayerbotAIConfig->fleeDistance, true); + return MoveAway(AI_VALUE(Unit*, "current target"), sPlayerbotAIConfig.fleeDistance, true); } bool FleeAction::isUseful() @@ -1862,9 +1842,9 @@ bool FleeAction::isUseful() return true; } -bool FleeWithPetAction::Execute(Event event) +bool FleeWithPetAction::Execute(Event) { - if (Pet* pet = bot->GetPet()) + if (bot->GetPet() != nullptr) { botAI->PetFollow(); } @@ -1874,7 +1854,9 @@ bool FleeWithPetAction::Execute(Event event) bool AvoidAoeAction::isUseful() { - if (getMSTime() - moveInterval < lastMoveTimer) + const int64_t currentMoveTimer = getMSTime() - this->lastMoveTimer; + + if (currentMoveTimer < this->lastMoveTimer) { return false; } @@ -1883,7 +1865,7 @@ bool AvoidAoeAction::isUseful() return AI_VALUE(Aura*, "area debuff") || !traps.empty() || !triggers.empty(); } -bool AvoidAoeAction::Execute(Event event) +bool AvoidAoeAction::Execute(Event) { // Case #1: Aura with dynamic object (e.g. rain of fire) if (AvoidAuraWithDynamicObj()) @@ -1924,8 +1906,8 @@ bool AvoidAoeAction::AvoidAuraWithDynamicObj() { return false; } - if (sPlayerbotAIConfig->aoeAvoidSpellWhitelist.find(spellInfo->Id) != - sPlayerbotAIConfig->aoeAvoidSpellWhitelist.end()) + if (sPlayerbotAIConfig.aoeAvoidSpellWhitelist.find(spellInfo->Id) != + sPlayerbotAIConfig.aoeAvoidSpellWhitelist.end()) return false; DynamicObject* dynOwner = aura->GetDynobjOwner(); @@ -1934,7 +1916,7 @@ bool AvoidAoeAction::AvoidAuraWithDynamicObj() return false; } float radius = dynOwner->GetRadius(); - if (!radius || radius > sPlayerbotAIConfig->maxAoeAvoidRadius) + if (!radius || radius > sPlayerbotAIConfig.maxAoeAvoidRadius) return false; if (bot->GetDistance(dynOwner) > radius) { @@ -1944,7 +1926,7 @@ bool AvoidAoeAction::AvoidAuraWithDynamicObj() name << spellInfo->SpellName[LOCALE_enUS]; // << "] (aura)"; if (FleePosition(dynOwner->GetPosition(), radius)) { - if (sPlayerbotAIConfig->tellWhenAvoidAoe && lastTellTimer < time(NULL) - 10) + if (sPlayerbotAIConfig.tellWhenAvoidAoe && lastTellTimer < time(NULL) - 10) { lastTellTimer = time(NULL); lastMoveTimer = getMSTime(); @@ -1990,8 +1972,8 @@ bool AvoidAoeAction::AvoidGameObjectWithDamage() continue; } - if (sPlayerbotAIConfig->aoeAvoidSpellWhitelist.find(spellId) != - sPlayerbotAIConfig->aoeAvoidSpellWhitelist.end()) + if (sPlayerbotAIConfig.aoeAvoidSpellWhitelist.find(spellId) != + sPlayerbotAIConfig.aoeAvoidSpellWhitelist.end()) continue; const SpellInfo* spellInfo = sSpellMgr->GetSpellInfo(spellId); @@ -2001,7 +1983,7 @@ bool AvoidAoeAction::AvoidGameObjectWithDamage() } float radius = (float)goInfo->trap.diameter / 2 + go->GetCombatReach(); - if (!radius || radius > sPlayerbotAIConfig->maxAoeAvoidRadius) + if (!radius || radius > sPlayerbotAIConfig.maxAoeAvoidRadius) continue; if (bot->GetDistance(go) > radius) @@ -2012,7 +1994,7 @@ bool AvoidAoeAction::AvoidGameObjectWithDamage() name << spellInfo->SpellName[LOCALE_enUS]; // << "] (object)"; if (FleePosition(go->GetPosition(), radius)) { - if (sPlayerbotAIConfig->tellWhenAvoidAoe && lastTellTimer < time(NULL) - 10) + if (sPlayerbotAIConfig.tellWhenAvoidAoe && lastTellTimer < time(NULL) - 10) { lastTellTimer = time(NULL); lastMoveTimer = getMSTime(); @@ -2061,8 +2043,8 @@ bool AvoidAoeAction::AvoidUnitWithDamageAura() sSpellMgr->GetSpellInfo(spellInfo->Effects[aurEff->GetEffIndex()].TriggerSpell); if (!triggerSpellInfo) continue; - if (sPlayerbotAIConfig->aoeAvoidSpellWhitelist.find(triggerSpellInfo->Id) != - sPlayerbotAIConfig->aoeAvoidSpellWhitelist.end()) + if (sPlayerbotAIConfig.aoeAvoidSpellWhitelist.find(triggerSpellInfo->Id) != + sPlayerbotAIConfig.aoeAvoidSpellWhitelist.end()) return false; for (int j = 0; j < MAX_SPELL_EFFECTS; j++) { @@ -2073,13 +2055,13 @@ bool AvoidAoeAction::AvoidUnitWithDamageAura() { break; } - if (!radius || radius > sPlayerbotAIConfig->maxAoeAvoidRadius) + if (!radius || radius > sPlayerbotAIConfig.maxAoeAvoidRadius) continue; std::ostringstream name; name << triggerSpellInfo->SpellName[LOCALE_enUS]; //<< "] (unit)"; if (FleePosition(unit->GetPosition(), radius)) { - if (sPlayerbotAIConfig->tellWhenAvoidAoe && lastTellTimer < time(NULL) - 10) + if (sPlayerbotAIConfig.tellWhenAvoidAoe && lastTellTimer < time(NULL) - 10) { lastTellTimer = time(NULL); lastMoveTimer = getMSTime(); @@ -2134,7 +2116,7 @@ Position MovementAction::BestPositionForMeleeToFlee(Position pos, float radius) continue; } bool strict = checkAngle.strict; - float fleeDis = std::min(radius + 1.0f, sPlayerbotAIConfig->fleeDistance); + float fleeDis = std::min(radius + 1.0f, sPlayerbotAIConfig.fleeDistance); float dx = bot->GetPositionX() + cos(angle) * fleeDis; float dy = bot->GetPositionY() + sin(angle) * fleeDis; float dz = bot->GetPositionZ(); @@ -2146,7 +2128,7 @@ Position MovementAction::BestPositionForMeleeToFlee(Position pos, float radius) Position fleePos{dx, dy, dz}; if (strict && currentTarget && fleePos.GetExactDist(currentTarget) - currentTarget->GetCombatReach() > - sPlayerbotAIConfig->tooCloseDistance && + sPlayerbotAIConfig.tooCloseDistance && bot->IsWithinMeleeRange(currentTarget)) { continue; @@ -2197,7 +2179,7 @@ Position MovementAction::BestPositionForRangedToFlee(Position pos, float radius) continue; } bool strict = checkAngle.strict; - float fleeDis = std::min(radius + 1.0f, sPlayerbotAIConfig->fleeDistance); + float fleeDis = std::min(radius + 1.0f, sPlayerbotAIConfig.fleeDistance); float dx = bot->GetPositionX() + cos(angle) * fleeDis; float dy = bot->GetPositionY() + sin(angle) * fleeDis; float dz = bot->GetPositionZ(); @@ -2208,13 +2190,13 @@ Position MovementAction::BestPositionForRangedToFlee(Position pos, float radius) } Position fleePos{dx, dy, dz}; if (strict && currentTarget && - fleePos.GetExactDist(currentTarget) - currentTarget->GetCombatReach() > sPlayerbotAIConfig->spellDistance) + fleePos.GetExactDist(currentTarget) - currentTarget->GetCombatReach() > sPlayerbotAIConfig.spellDistance) { continue; } if (strict && currentTarget && fleePos.GetExactDist(currentTarget) - currentTarget->GetCombatReach() < - (sPlayerbotAIConfig->tooCloseDistance)) + (sPlayerbotAIConfig.tooCloseDistance)) { continue; } @@ -2306,7 +2288,9 @@ bool MovementAction::CheckLastFlee(float curAngle, std::list& infoList bool CombatFormationMoveAction::isUseful() { - if (getMSTime() - moveInterval < lastMoveTimer) + const int64_t currentMoveTimer = getMSTime() - this->lastMoveTimer; + + if (currentMoveTimer < this->lastMoveTimer) { return false; } @@ -2317,7 +2301,7 @@ bool CombatFormationMoveAction::isUseful() return true; } -bool CombatFormationMoveAction::Execute(Event event) +bool CombatFormationMoveAction::Execute(Event) { float dis = AI_VALUE(float, "disperse distance"); if (dis <= 0.0f || (!bot->IsInCombat() && botAI->HasStrategy("stay", BotState::BOT_STATE_NON_COMBAT)) || @@ -2357,7 +2341,7 @@ Position CombatFormationMoveAction::AverageGroupPos(float dis, bool ranged, bool continue; if (!member->IsAlive() || member->GetMapId() != bot->GetMapId() || member->IsCharmed() || - sServerFacade->GetDistance2d(bot, member) > dis) + ServerFacade::instance().GetDistance2d(bot, member) > dis) continue; averageX += member->GetPositionX(); @@ -2395,7 +2379,7 @@ float CombatFormationMoveAction::AverageGroupAngle(Unit* from, bool ranged, bool continue; if (!member->IsAlive() || member->GetMapId() != bot->GetMapId() || member->IsCharmed() || - sServerFacade->GetDistance2d(bot, member) > sPlayerbotAIConfig->sightDistance) + ServerFacade::instance().GetDistance2d(bot, member) > sPlayerbotAIConfig.sightDistance) continue; cnt++; @@ -2437,7 +2421,7 @@ Player* CombatFormationMoveAction::NearestGroupMember(float dis) { Player* member = ObjectAccessor::FindPlayer(itr->guid); if (!member || !member->IsAlive() || member == bot || member->GetMapId() != bot->GetMapId() || - member->IsCharmed() || sServerFacade->GetDistance2d(bot, member) > dis) + member->IsCharmed() || ServerFacade::instance().GetDistance2d(bot, member) > dis) continue; if (nearestDis > bot->GetExactDist(member)) { @@ -2448,7 +2432,7 @@ Player* CombatFormationMoveAction::NearestGroupMember(float dis) return result; } -bool TankFaceAction::Execute(Event event) +bool TankFaceAction::Execute(Event) { Unit* target = AI_VALUE(Unit*, "current target"); if (!target) @@ -2532,7 +2516,7 @@ bool RearFlankAction::isUseful() return inFront || inRear; } -bool RearFlankAction::Execute(Event event) +bool RearFlankAction::Execute(Event) { Unit* target = AI_VALUE(Unit*, "current target"); if (!target) @@ -2643,29 +2627,29 @@ bool DisperseSetAction::Execute(Event event) return true; } -bool RunAwayAction::Execute(Event event) { return Flee(AI_VALUE(Unit*, "group leader")); } +bool RunAwayAction::Execute(Event) { return Flee(AI_VALUE(Unit*, "group leader")); } -bool MoveToLootAction::Execute(Event event) +bool MoveToLootAction::Execute(Event) { LootObject loot = AI_VALUE(LootObject, "loot target"); if (!loot.IsLootPossible(bot)) return false; - return MoveNear(loot.GetWorldObject(bot), sPlayerbotAIConfig->contactDistance); + return MoveNear(loot.GetWorldObject(bot), sPlayerbotAIConfig.contactDistance); } -bool MoveOutOfEnemyContactAction::Execute(Event event) +bool MoveOutOfEnemyContactAction::Execute(Event) { Unit* target = AI_VALUE(Unit*, "current target"); if (!target) return false; - return MoveTo(target, sPlayerbotAIConfig->contactDistance); + return MoveTo(target, sPlayerbotAIConfig.contactDistance); } bool MoveOutOfEnemyContactAction::isUseful() { return AI_VALUE2(bool, "inside target", "current target"); } -bool SetFacingTargetAction::Execute(Event event) +bool SetFacingTargetAction::Execute(Event) { Unit* target = AI_VALUE(Unit*, "current target"); if (!target) @@ -2674,8 +2658,8 @@ bool SetFacingTargetAction::Execute(Event event) if (bot->HasUnitState(UNIT_STATE_IN_FLIGHT)) return true; - sServerFacade->SetFacingTo(bot, target); - botAI->SetNextCheckDelay(sPlayerbotAIConfig->reactDelay); + ServerFacade::instance().SetFacingTo(bot, target); + botAI->SetNextCheckDelay(sPlayerbotAIConfig.reactDelay); return true; } @@ -2691,7 +2675,7 @@ bool SetFacingTargetAction::isPossible() return true; } -bool SetBehindTargetAction::Execute(Event event) +bool SetBehindTargetAction::Execute(Event) { Unit* target = AI_VALUE(Unit*, "current target"); if (!target) @@ -2751,10 +2735,10 @@ bool SetBehindTargetAction::Execute(Event event) false, true, MovementPriority::MOVEMENT_COMBAT); } -bool MoveOutOfCollisionAction::Execute(Event event) +bool MoveOutOfCollisionAction::Execute(Event) { float angle = M_PI * 2000 / frand(1.f, 1000.f); - float distance = sPlayerbotAIConfig->followDistance; + float distance = sPlayerbotAIConfig.followDistance; return MoveTo(bot->GetMapId(), bot->GetPositionX() + cos(angle) * distance, bot->GetPositionY() + sin(angle) * distance, bot->GetPositionZ()); } @@ -2769,9 +2753,9 @@ bool MoveOutOfCollisionAction::isUseful() botAI->GetAiObjectContext()->GetValue("nearest friendly players")->Get().size() < 15; } -bool MoveRandomAction::Execute(Event event) +bool MoveRandomAction::Execute(Event) { - float distance = sPlayerbotAIConfig->tooCloseDistance + urand(10, 30); + float distance = sPlayerbotAIConfig.tooCloseDistance + urand(10, 30); Map* map = bot->GetMap(); for (int i = 0; i < 3; ++i) @@ -2782,9 +2766,7 @@ bool MoveRandomAction::Execute(Event event) float angle = (float)rand_norm() * static_cast(M_PI); x += urand(0, distance) * cos(angle); y += urand(0, distance) * sin(angle); - float ox = x; - float oy = y; - float oz = z; + if (!bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), x, y, z)) continue; @@ -2801,9 +2783,9 @@ bool MoveRandomAction::Execute(Event event) bool MoveRandomAction::isUseful() { return !AI_VALUE(GuidPosition, "rpg target"); } -bool MoveInsideAction::Execute(Event event) { return MoveInside(bot->GetMapId(), x, y, bot->GetPositionZ(), distance); } +bool MoveInsideAction::Execute(Event) { return MoveInside(bot->GetMapId(), x, y, bot->GetPositionZ(), distance); } -bool RotateAroundTheCenterPointAction::Execute(Event event) +bool RotateAroundTheCenterPointAction::Execute(Event) { uint32 next_point = GetCurrWaypoint(); if (MoveTo(bot->GetMapId(), waypoints[next_point].first, waypoints[next_point].second, bot->GetPositionZ(), false, @@ -2823,10 +2805,9 @@ bool MoveFromGroupAction::Execute(Event event) return MoveFromGroup(distance); } -bool MoveAwayFromCreatureAction::Execute(Event event) +bool MoveAwayFromCreatureAction::Execute(Event) { GuidVector targets = AI_VALUE(GuidVector, "nearest npcs"); - Creature* nearestCreature = bot->FindNearestCreature(creatureId, range, alive); // Find all creatures with the specified Id std::vector creatures; @@ -2904,13 +2885,11 @@ bool MoveAwayFromCreatureAction::Execute(Event event) bool MoveAwayFromCreatureAction::isPossible() { return bot->CanFreeMove(); } -bool MoveAwayFromPlayerWithDebuffAction::Execute(Event event) +bool MoveAwayFromPlayerWithDebuffAction::Execute(Event) { - Player* closestPlayer = nullptr; - float minDistance = 0.0f; + Group* const group = bot->GetGroup(); - Group* group = bot->GetGroup(); - if (!group) + if (group == nullptr) { return false; } diff --git a/src/Ai/Base/Actions/MovementActions.h b/src/Ai/Base/Actions/MovementActions.h index d12bcd555c..046805ccf3 100644 --- a/src/Ai/Base/Actions/MovementActions.h +++ b/src/Ai/Base/Actions/MovementActions.h @@ -29,7 +29,7 @@ class MovementAction : public Action protected: bool JumpTo(uint32 mapId, float x, float y, float z, MovementPriority priority = MovementPriority::MOVEMENT_NORMAL); - bool MoveNear(uint32 mapId, float x, float y, float z, float distance = sPlayerbotAIConfig->contactDistance, + bool MoveNear(uint32 mapId, float x, float y, float z, float distance = sPlayerbotAIConfig.contactDistance, MovementPriority priority = MovementPriority::MOVEMENT_NORMAL); bool MoveToLOS(WorldObject* target, bool ranged = false); bool MoveTo(uint32 mapId, float x, float y, float z, bool idle = false, bool react = false, @@ -38,10 +38,10 @@ class MovementAction : public Action bool backwards = false); bool MoveTo(WorldObject* target, float distance = 0.0f, MovementPriority priority = MovementPriority::MOVEMENT_NORMAL); - bool MoveNear(WorldObject* target, float distance = sPlayerbotAIConfig->contactDistance, + bool MoveNear(WorldObject* target, float distance = sPlayerbotAIConfig.contactDistance, MovementPriority priority = MovementPriority::MOVEMENT_NORMAL); float GetFollowAngle(); - bool Follow(Unit* target, float distance = sPlayerbotAIConfig->followDistance); + bool Follow(Unit* target, float distance = sPlayerbotAIConfig.followDistance); bool Follow(Unit* target, float distance, float angle); bool ChaseTo(WorldObject* obj, float distance = 0.0f, float angle = 0.0f); bool ReachCombatTo(Unit* target, float distance = 0.0f); @@ -56,10 +56,10 @@ class MovementAction : public Action bool Flee(Unit* target); void ClearIdleState(); void UpdateMovementState(); - bool MoveAway(Unit* target, float distance = sPlayerbotAIConfig->fleeDistance, bool backwards = false); + bool MoveAway(Unit* target, float distance = sPlayerbotAIConfig.fleeDistance, bool backwards = false); bool MoveFromGroup(float distance); bool Move(float angle, float distance); - bool MoveInside(uint32 mapId, float x, float y, float z, float distance = sPlayerbotAIConfig->followDistance, + bool MoveInside(uint32 mapId, float x, float y, float z, float distance = sPlayerbotAIConfig.followDistance, MovementPriority priority = MovementPriority::MOVEMENT_NORMAL); void CreateWp(Player* wpOwner, float x, float y, float z, float o, uint32 entry, bool important = false); Position BestPositionForMeleeToFlee(Position pos, float radius); @@ -86,7 +86,7 @@ class MovementAction : public Action class FleeAction : public MovementAction { public: - FleeAction(PlayerbotAI* botAI, float distance = sPlayerbotAIConfig->spellDistance) + FleeAction(PlayerbotAI* botAI, float distance = sPlayerbotAIConfig.spellDistance) : MovementAction(botAI, "flee"), distance(distance) { } @@ -138,8 +138,8 @@ class CombatFormationMoveAction : public MovementAction bool Execute(Event event) override; protected: - Position AverageGroupPos(float dis = sPlayerbotAIConfig->sightDistance, bool ranged = false, bool self = false); - Player* NearestGroupMember(float dis = sPlayerbotAIConfig->sightDistance); + Position AverageGroupPos(float dis = sPlayerbotAIConfig.sightDistance, bool ranged = false, bool self = false); + Player* NearestGroupMember(float dis = sPlayerbotAIConfig.sightDistance); float AverageGroupAngle(Unit* from, bool ranged = false, bool self = false); Position GetNearestPosition(const std::vector& positions); int lastMoveTimer = 0; @@ -266,7 +266,7 @@ class RotateAroundTheCenterPointAction : public MovementAction { public: RotateAroundTheCenterPointAction(PlayerbotAI* ai, std::string name, float center_x, float center_y, - float radius = 40.0f, uint32 intervals = 16, bool clockwise = true, + float radius = 40.0f, uint32_t intervals = 16, bool clockwise = true, float start_angle = 0) : MovementAction(ai, name) { @@ -276,7 +276,8 @@ class RotateAroundTheCenterPointAction : public MovementAction this->intervals = intervals; this->clockwise = clockwise; this->call_counters = 0; - for (int i = 0; i < intervals; i++) + + for (uint32_t i = 0; i < intervals; ++i) { float angle = start_angle + 2 * M_PI * i / intervals; waypoints.push_back(std::make_pair(center_x + cos(angle) * radius, center_y + sin(angle) * radius)); diff --git a/src/Ai/Base/Actions/NonCombatActions.cpp b/src/Ai/Base/Actions/NonCombatActions.cpp index f87aa891dd..22e6cd802e 100644 --- a/src/Ai/Base/Actions/NonCombatActions.cpp +++ b/src/Ai/Base/Actions/NonCombatActions.cpp @@ -8,61 +8,6 @@ #include "Event.h" #include "Playerbots.h" -bool DrinkAction::Execute(Event event) -{ - if (botAI->HasCheat(BotCheatMask::food)) - { - // if (bot->IsNonMeleeSpellCast(true)) - // return false; - - bot->ClearUnitState(UNIT_STATE_CHASE); - bot->ClearUnitState(UNIT_STATE_FOLLOW); - - if (bot->isMoving()) - { - bot->StopMoving(); - // botAI->SetNextCheckDelay(sPlayerbotAIConfig->globalCoolDown); - // return false; - } - bot->SetStandState(UNIT_STAND_STATE_SIT); - botAI->InterruptSpell(); - - // float hp = bot->GetHealthPercent(); - float mp = bot->GetPowerPct(POWER_MANA); - float p = mp; - float delay; - - if (!bot->InBattleground()) - delay = 18000.0f * (100 - p) / 100.0f; - else - delay = 12000.0f * (100 - p) / 100.0f; - - botAI->SetNextCheckDelay(delay); - - bot->AddAura(25990, bot); - return true; - // return botAI->CastSpell(24707, bot); - } - - return UseItemAction::Execute(event); -} - -bool DrinkAction::isUseful() -{ - return UseItemAction::isUseful() && - AI_VALUE2(bool, "has mana", "self target") && - AI_VALUE2(uint8, "mana", "self target") < 100; -} - -bool DrinkAction::isPossible() -{ - return !bot->IsInCombat() && - !bot->IsMounted() && - !botAI->HasAnyAuraOf(GetTarget(), "dire bear form", "bear form", "cat form", "travel form", - "aquatic form","flight form", "swift flight form", nullptr) && - (botAI->HasCheat(BotCheatMask::food) || UseItemAction::isPossible()); -} - bool EatAction::Execute(Event event) { if (botAI->HasCheat(BotCheatMask::food)) @@ -76,7 +21,7 @@ bool EatAction::Execute(Event event) if (bot->isMoving()) { bot->StopMoving(); - // botAI->SetNextCheckDelay(sPlayerbotAIConfig->globalCoolDown); + // botAI->SetNextCheckDelay(sPlayerbotAIConfig.globalCoolDown); // return false; } diff --git a/src/Ai/Base/Actions/NonCombatActions.h b/src/Ai/Base/Actions/NonCombatActions.h index 3156d49921..86b353cf0a 100644 --- a/src/Ai/Base/Actions/NonCombatActions.h +++ b/src/Ai/Base/Actions/NonCombatActions.h @@ -10,16 +10,6 @@ class PlayerbotAI; -class DrinkAction : public UseItemAction -{ -public: - DrinkAction(PlayerbotAI* botAI) : UseItemAction(botAI, "drink") {} - - bool Execute(Event event) override; - bool isUseful() override; - bool isPossible() override; -}; - class EatAction : public UseItemAction { public: diff --git a/src/Ai/Base/Actions/OpenItemAction.cpp b/src/Ai/Base/Actions/OpenItemAction.cpp index d1ebcbaaaf..b298aef855 100644 --- a/src/Ai/Base/Actions/OpenItemAction.cpp +++ b/src/Ai/Base/Actions/OpenItemAction.cpp @@ -7,35 +7,35 @@ #include "LootObjectStack.h" #include "AiObjectContext.h" -bool OpenItemAction::Execute(Event event) +bool OpenItemAction::Execute(Event) { - bool foundOpenable = false; + Item* const item = botAI->FindOpenableItem(); - Item* item = botAI->FindOpenableItem(); - if (item) + if (item == nullptr) { - uint8 bag = item->GetBagSlot(); // Retrieves the bag slot (0 for main inventory) - uint8 slot = item->GetSlot(); // Retrieves the actual slot inside the bag - - OpenItem(item, bag, slot); - foundOpenable = true; + return false; } - return foundOpenable; + uint8_t bag = item->GetBagSlot(); // Retrieves the bag slot (255 for main inventory) + uint8_t slot = item->GetSlot(); // Retrieves the actual slot inside the bag + + this->OpenItem(item, bag, slot); + + return true; } -void OpenItemAction::OpenItem(Item* item, uint8 bag, uint8 slot) +void OpenItemAction::OpenItem(Item* item, uint8_t bag, uint8_t slot) { WorldPacket packet(CMSG_OPEN_ITEM); packet << bag << slot; - bot->GetSession()->HandleOpenItemOpcode(packet); + this->bot->GetSession()->HandleOpenItemOpcode(packet); // Store the item GUID as the loot target LootObject lootObject; lootObject.guid = item->GetGUID(); - botAI->GetAiObjectContext()->GetValue("loot target")->Set(lootObject); + this->botAI->GetAiObjectContext()->GetValue("loot target")->Set(lootObject); std::ostringstream out; out << "Opened item: " << item->GetTemplate()->Name1; - botAI->TellMaster(out.str()); + this->botAI->TellMaster(out.str()); } diff --git a/src/Ai/Base/Actions/PassLeadershipToMasterAction.cpp b/src/Ai/Base/Actions/PassLeadershipToMasterAction.cpp index 87890c1c57..9db5787230 100644 --- a/src/Ai/Base/Actions/PassLeadershipToMasterAction.cpp +++ b/src/Ai/Base/Actions/PassLeadershipToMasterAction.cpp @@ -7,38 +7,47 @@ #include "Event.h" #include "PlayerbotOperations.h" -#include "Playerbots.h" #include "PlayerbotWorldThreadProcessor.h" -bool PassLeadershipToMasterAction::Execute(Event event) +bool PassLeadershipToMasterAction::Execute(Event) { - if (Player* master = GetMaster()) - if (master && master != bot && bot->GetGroup() && bot->GetGroup()->IsMember(master->GetGUID())) - { - auto setLeaderOp = std::make_unique(bot->GetGUID(), master->GetGUID()); - sPlayerbotWorldProcessor->QueueOperation(std::move(setLeaderOp)); + const Player* const master = this->GetMaster(); - if (!message.empty()) - botAI->TellMasterNoFacing(message); + if (master == nullptr || master == this->bot) + { + return false; + } - if (sRandomPlayerbotMgr->IsRandomBot(bot)) - { - botAI->ResetStrategies(); - botAI->Reset(); - } + const Group* const group = this->bot->GetGroup(); - return true; - } + if (group == nullptr || !this->bot->GetGroup()->IsMember(master->GetGUID())) + { + return false; + } - return false; + std::unique_ptr setLeaderOp = std::make_unique(this->bot->GetGUID(), master->GetGUID()); + PlayerbotWorldThreadProcessor::instance().QueueOperation(std::move(setLeaderOp)); + + if (!message.empty()) + { + this->botAI->TellMasterNoFacing(message); + } + + if (RandomPlayerbotMgr::instance().IsRandomBot(this->bot)) + { + this->botAI->ResetStrategies(); + this->botAI->Reset(); + } + + return true; } bool PassLeadershipToMasterAction::isUseful() { - return botAI->IsAlt() && bot->GetGroup() && bot->GetGroup()->IsLeader(bot->GetGUID()); + return this->botAI->IsAlt() && this->bot->GetGroup() && this->bot->GetGroup()->IsLeader(this->bot->GetGUID()); } bool GiveLeaderAction::isUseful() { - return botAI->HasActivePlayerMaster() && bot->GetGroup() && bot->GetGroup()->IsLeader(bot->GetGUID()); + return this->botAI->HasActivePlayerMaster() && this->bot->GetGroup() && this->bot->GetGroup()->IsLeader(this->bot->GetGUID()); } diff --git a/src/Ai/Base/Actions/PassLeadershipToMasterAction.h b/src/Ai/Base/Actions/PassLeadershipToMasterAction.h index afa5663bc8..c93edc7057 100644 --- a/src/Ai/Base/Actions/PassLeadershipToMasterAction.h +++ b/src/Ai/Base/Actions/PassLeadershipToMasterAction.h @@ -33,8 +33,17 @@ class GiveLeaderAction : public PassLeadershipToMasterAction : PassLeadershipToMasterAction(botAI, "give leader", message) { } - bool isUseful() override; }; +class GiveLeaderInDungeonAction : public GiveLeaderAction +{ +public: + GiveLeaderInDungeonAction(PlayerbotAI* botAI, std::string const message = "I don't know this dungeon, lead the way!") + : GiveLeaderAction(botAI, message) + { + } + ~GiveLeaderInDungeonAction() override = default; +}; + #endif diff --git a/src/Ai/Base/Actions/PetAttackAction.h b/src/Ai/Base/Actions/PetAttackAction.h new file mode 100644 index 0000000000..aaa4e9741e --- /dev/null +++ b/src/Ai/Base/Actions/PetAttackAction.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#pragma once + +#include + +#include "Action.h" +#include "PetsAction.h" + +class PlayerbotAI; + +class ChatPetAttackAction : public PetsAction +{ +public: + ChatPetAttackAction(PlayerbotAI* botAI) : PetsAction(botAI, "attack") {} +}; diff --git a/src/Ai/Base/Actions/PetsAction.cpp b/src/Ai/Base/Actions/PetsAction.cpp index cb9dc93957..00ef11e321 100644 --- a/src/Ai/Base/Actions/PetsAction.cpp +++ b/src/Ai/Base/Actions/PetsAction.cpp @@ -11,7 +11,6 @@ #include "Pet.h" #include "Player.h" #include "PlayerbotAI.h" -#include "SharedDefines.h" bool PetsAction::Execute(Event event) { @@ -23,7 +22,7 @@ bool PetsAction::Execute(Event event) if (param.empty()) { // If no parameter is provided, show usage instructions and return. - std::string text = sPlayerbotTextMgr->GetBotTextOrDefault( + std::string text = PlayerbotTextMgr::instance().GetBotTextOrDefault( "pet_usage_error", "Usage: pet ", {}); botAI->TellError(text); return false; @@ -52,7 +51,7 @@ bool PetsAction::Execute(Event event) // If no pets or guardians are found, notify and return. if (targets.empty()) { - std::string text = sPlayerbotTextMgr->GetBotTextOrDefault( + std::string text = PlayerbotTextMgr::instance().GetBotTextOrDefault( "pet_no_pet_error", "You have no pet or guardian pet.", {}); botAI->TellError(text); return false; @@ -65,19 +64,19 @@ bool PetsAction::Execute(Event event) if (param == "aggressive") { react = REACT_AGGRESSIVE; - stanceText = sPlayerbotTextMgr->GetBotTextOrDefault( + stanceText = PlayerbotTextMgr::instance().GetBotTextOrDefault( "pet_stance_aggressive", "aggressive", {}); } else if (param == "defensive") { react = REACT_DEFENSIVE; - stanceText = sPlayerbotTextMgr->GetBotTextOrDefault( + stanceText = PlayerbotTextMgr::instance().GetBotTextOrDefault( "pet_stance_defensive", "defensive", {}); } else if (param == "passive") { react = REACT_PASSIVE; - stanceText = sPlayerbotTextMgr->GetBotTextOrDefault( + stanceText = PlayerbotTextMgr::instance().GetBotTextOrDefault( "pet_stance_passive", "passive", {}); } // The "stance" command simply reports the current stance of each pet/guardian. @@ -86,30 +85,30 @@ bool PetsAction::Execute(Event event) for (Creature* target : targets) { std::string type = target->IsPet() ? - sPlayerbotTextMgr->GetBotTextOrDefault("pet_type_pet", "pet", {}) : - sPlayerbotTextMgr->GetBotTextOrDefault("pet_type_guardian", "guardian", {}); + PlayerbotTextMgr::instance().GetBotTextOrDefault("pet_type_pet", "pet", {}) : + PlayerbotTextMgr::instance().GetBotTextOrDefault("pet_type_guardian", "guardian", {}); std::string name = target->GetName(); std::string stance; switch (target->GetReactState()) { case REACT_AGGRESSIVE: - stance = sPlayerbotTextMgr->GetBotTextOrDefault( + stance = PlayerbotTextMgr::instance().GetBotTextOrDefault( "pet_stance_aggressive", "aggressive", {}); break; case REACT_DEFENSIVE: - stance = sPlayerbotTextMgr->GetBotTextOrDefault( + stance = PlayerbotTextMgr::instance().GetBotTextOrDefault( "pet_stance_defensive", "defensive", {}); break; case REACT_PASSIVE: - stance = sPlayerbotTextMgr->GetBotTextOrDefault( + stance = PlayerbotTextMgr::instance().GetBotTextOrDefault( "pet_stance_passive", "passive", {}); break; default: - stance = sPlayerbotTextMgr->GetBotTextOrDefault( + stance = PlayerbotTextMgr::instance().GetBotTextOrDefault( "pet_stance_unknown", "unknown", {}); break; } - std::string text = sPlayerbotTextMgr->GetBotTextOrDefault( + std::string text = PlayerbotTextMgr::instance().GetBotTextOrDefault( "pet_stance_report", "Current stance of %type \"%name\": %stance.", {{"type", type}, {"name", name}, {"stance", stance}}); botAI->TellMaster(text); @@ -133,30 +132,30 @@ bool PetsAction::Execute(Event event) // If no valid target is selected, show an error and return. if (!targetUnit) { - std::string text = sPlayerbotTextMgr->GetBotTextOrDefault( + std::string text = PlayerbotTextMgr::instance().GetBotTextOrDefault( "pet_no_target_error", "No valid target selected by master.", {}); botAI->TellError(text); return false; } if (!targetUnit->IsAlive()) { - std::string text = sPlayerbotTextMgr->GetBotTextOrDefault( + std::string text = PlayerbotTextMgr::instance().GetBotTextOrDefault( "pet_target_dead_error", "Target is not alive.", {}); botAI->TellError(text); return false; } if (!bot->IsValidAttackTarget(targetUnit)) { - std::string text = sPlayerbotTextMgr->GetBotTextOrDefault( + std::string text = PlayerbotTextMgr::instance().GetBotTextOrDefault( "pet_invalid_target_error", "Target is not a valid attack target for the bot.", {}); botAI->TellError(text); return false; } - if (sPlayerbotAIConfig->IsPvpProhibited(bot->GetZoneId(), bot->GetAreaId()) && + if (sPlayerbotAIConfig.IsPvpProhibited(bot->GetZoneId(), bot->GetAreaId()) && (targetUnit->IsPlayer() || targetUnit->IsPet()) && (!bot->duel || bot->duel->Opponent != targetUnit)) { - std::string text = sPlayerbotTextMgr->GetBotTextOrDefault( + std::string text = PlayerbotTextMgr::instance().GetBotTextOrDefault( "pet_pvp_prohibited_error", "I cannot command my pet to attack players in PvP prohibited areas.", {}); botAI->TellError(text); return false; @@ -208,15 +207,15 @@ bool PetsAction::Execute(Event event) } } // Inform the master if the command succeeded or failed. - if (didAttack && sPlayerbotAIConfig->petChatCommandDebug == 1) + if (didAttack && sPlayerbotAIConfig.petChatCommandDebug == 1) { - std::string text = sPlayerbotTextMgr->GetBotTextOrDefault( + std::string text = PlayerbotTextMgr::instance().GetBotTextOrDefault( "pet_attack_success", "Pet commanded to attack your target.", {}); botAI->TellMaster(text); } else if (!didAttack) { - std::string text = sPlayerbotTextMgr->GetBotTextOrDefault( + std::string text = PlayerbotTextMgr::instance().GetBotTextOrDefault( "pet_attack_failed", "Pet did not attack. (Already attacking or unable to attack target)", {}); botAI->TellError(text); } @@ -226,9 +225,9 @@ bool PetsAction::Execute(Event event) else if (param == "follow") { botAI->PetFollow(); - if (sPlayerbotAIConfig->petChatCommandDebug == 1) + if (sPlayerbotAIConfig.petChatCommandDebug == 1) { - std::string text = sPlayerbotTextMgr->GetBotTextOrDefault( + std::string text = PlayerbotTextMgr::instance().GetBotTextOrDefault( "pet_follow_success", "Pet commanded to follow.", {}); botAI->TellMaster(text); } @@ -267,9 +266,9 @@ bool PetsAction::Execute(Event event) charmInfo->SetForcedTargetGUID(); } } - if (sPlayerbotAIConfig->petChatCommandDebug == 1) + if (sPlayerbotAIConfig.petChatCommandDebug == 1) { - std::string text = sPlayerbotTextMgr->GetBotTextOrDefault( + std::string text = PlayerbotTextMgr::instance().GetBotTextOrDefault( "pet_stay_success", "Pet commanded to stay.", {}); botAI->TellMaster(text); } @@ -278,7 +277,7 @@ bool PetsAction::Execute(Event event) // Unknown command: show usage instructions and return. else { - std::string text = sPlayerbotTextMgr->GetBotTextOrDefault( + std::string text = PlayerbotTextMgr::instance().GetBotTextOrDefault( "pet_unknown_command_error", "Unknown pet command: %param. Use: pet ", {{"param", param}}); botAI->TellError(text); @@ -295,9 +294,9 @@ bool PetsAction::Execute(Event event) } // Inform the master of the new stance if debug is enabled. - if (sPlayerbotAIConfig->petChatCommandDebug == 1) + if (sPlayerbotAIConfig.petChatCommandDebug == 1) { - std::string text = sPlayerbotTextMgr->GetBotTextOrDefault( + std::string text = PlayerbotTextMgr::instance().GetBotTextOrDefault( "pet_stance_set_success", "Pet stance set to %stance.", {{"stance", stanceText}}); botAI->TellMaster(text); diff --git a/src/Ai/Base/Actions/PetsAction.h b/src/Ai/Base/Actions/PetsAction.h index f9334e3194..eaccdcb1a8 100644 --- a/src/Ai/Base/Actions/PetsAction.h +++ b/src/Ai/Base/Actions/PetsAction.h @@ -9,8 +9,6 @@ #include #include "Action.h" -#include "PlayerbotFactory.h" -#include "Unit.h" class PlayerbotAI; @@ -22,7 +20,6 @@ class PetsAction : public Action bool Execute(Event event) override; private: - bool warningEnabled = true; std::string defaultCmd; }; diff --git a/src/Ai/Base/Actions/PositionAction.cpp b/src/Ai/Base/Actions/PositionAction.cpp index 2de27f0414..e7e7f3b5f7 100644 --- a/src/Ai/Base/Actions/PositionAction.cpp +++ b/src/Ai/Base/Actions/PositionAction.cpp @@ -102,7 +102,7 @@ bool PositionAction::Execute(Event event) return false; } -bool MoveToPositionAction::Execute(Event event) +bool MoveToPositionAction::Execute(Event) { PositionInfo pos = context->GetValue("position")->Get()[qualifier]; if (!pos.isSet()) @@ -120,10 +120,10 @@ bool MoveToPositionAction::isUseful() { PositionInfo pos = context->GetValue("position")->Get()[qualifier]; float distance = AI_VALUE2(float, "distance", std::string("position_") + qualifier); - return pos.isSet() && distance > sPlayerbotAIConfig->followDistance && distance < sPlayerbotAIConfig->reactDistance; + return pos.isSet() && distance > sPlayerbotAIConfig.followDistance && distance < sPlayerbotAIConfig.reactDistance; } -bool SetReturnPositionAction::Execute(Event event) +bool SetReturnPositionAction::Execute(Event) { PositionMap& posMap = context->GetValue("position")->Get(); PositionInfo returnPos = posMap["return"]; @@ -131,7 +131,7 @@ bool SetReturnPositionAction::Execute(Event event) if (returnPos.isSet() && !randomPos.isSet()) { float angle = 2 * M_PI * urand(0, 1000) / 100.0f; - float dist = sPlayerbotAIConfig->followDistance * urand(0, 1000) / 1000.0f; + float dist = sPlayerbotAIConfig.followDistance * urand(0, 1000) / 1000.0f; float x = returnPos.x + cos(angle) * dist; float y = returnPos.y + sin(angle) * dist; float z = bot->GetPositionZ(); @@ -157,7 +157,7 @@ bool SetReturnPositionAction::isUseful() bool ReturnAction::isUseful() { PositionInfo pos = context->GetValue("position")->Get()[qualifier]; - return pos.isSet() && AI_VALUE2(float, "distance", "position_random") > sPlayerbotAIConfig->followDistance; + return pos.isSet() && AI_VALUE2(float, "distance", "position_random") > sPlayerbotAIConfig.followDistance; } bool ReturnToStayPositionAction::isPossible() @@ -167,7 +167,7 @@ bool ReturnToStayPositionAction::isPossible() if (stayPosition.isSet()) { const float distance = bot->GetDistance(stayPosition.x, stayPosition.y, stayPosition.z); - if (distance > sPlayerbotAIConfig->reactDistance) + if (distance > sPlayerbotAIConfig.reactDistance) { botAI->TellMaster("The stay position is too far to return. I am going to stay where I am now"); diff --git a/src/Ai/Base/Actions/QueryItemUsageAction.cpp b/src/Ai/Base/Actions/QueryItemUsageAction.cpp index 2fbc75af8f..34e2cc831b 100644 --- a/src/Ai/Base/Actions/QueryItemUsageAction.cpp +++ b/src/Ai/Base/Actions/QueryItemUsageAction.cpp @@ -118,7 +118,7 @@ std::string const QueryItemUsageAction::QueryItemUsage(ItemTemplate const* item) std::string const QueryItemUsageAction::QueryItemPrice(ItemTemplate const* item) { - if (!sRandomPlayerbotMgr->IsRandomBot(bot)) + if (!sRandomPlayerbotMgr.IsRandomBot(bot)) return ""; if (item->Bonding == BIND_WHEN_PICKED_UP) @@ -133,7 +133,7 @@ std::string const QueryItemUsageAction::QueryItemPrice(ItemTemplate const* item) { Item* sell = *i; int32 price = - sell->GetCount() * sell->GetTemplate()->SellPrice * sRandomPlayerbotMgr->GetSellMultiplier(bot); + sell->GetCount() * sell->GetTemplate()->SellPrice * sRandomPlayerbotMgr.GetSellMultiplier(bot); if (!sellPrice || sellPrice > price) sellPrice = price; } @@ -147,7 +147,7 @@ std::string const QueryItemUsageAction::QueryItemPrice(ItemTemplate const* item) if (usage == ITEM_USAGE_NONE) return msg.str(); - int32 buyPrice = item->BuyPrice * sRandomPlayerbotMgr->GetBuyMultiplier(bot); + int32 buyPrice = item->BuyPrice * sRandomPlayerbotMgr.GetBuyMultiplier(bot); if (buyPrice) { if (sellPrice) diff --git a/src/Ai/Base/Actions/QueryQuestAction.cpp b/src/Ai/Base/Actions/QueryQuestAction.cpp index 6ceccad975..337f83a213 100644 --- a/src/Ai/Base/Actions/QueryQuestAction.cpp +++ b/src/Ai/Base/Actions/QueryQuestAction.cpp @@ -7,7 +7,7 @@ #include "ChatHelper.h" #include "Event.h" -#include "Playerbots.h" +#include "PlayerbotAI.h" void QueryQuestAction::TellObjective(std::string const name, uint32 available, uint32 required) { @@ -16,7 +16,6 @@ void QueryQuestAction::TellObjective(std::string const name, uint32 available, u bool QueryQuestAction::Execute(Event event) { - Player* requester = event.getOwner() ? event.getOwner() : GetMaster(); Player* bot = botAI->GetBot(); WorldPosition botPos(bot); WorldPosition* ptr_botpos = &botPos; @@ -73,7 +72,7 @@ bool QueryQuestAction::Execute(Event event) { uint32 limit = 0; std::vector allDestinations = - sTravelMgr->getQuestTravelDestinations(bot, questId, true, true, -1); + TravelMgr::instance().getQuestTravelDestinations(bot, questId, true, true, -1); std::sort(allDestinations.begin(), allDestinations.end(), [ptr_botpos](TravelDestination* i, TravelDestination* j) {return i->distanceTo(ptr_botpos) < j->distanceTo(ptr_botpos); }); for (auto dest : allDestinations) diff --git a/src/Ai/Base/Actions/QuestAction.cpp b/src/Ai/Base/Actions/QuestAction.cpp index b96c539475..e30ff38481 100644 --- a/src/Ai/Base/Actions/QuestAction.cpp +++ b/src/Ai/Base/Actions/QuestAction.cpp @@ -5,6 +5,7 @@ #include "QuestAction.h" #include +#include #include "Chat.h" #include "ChatHelper.h" @@ -116,7 +117,8 @@ bool QuestAction::CompleteQuest(Player* player, uint32 entry) player->CastedCreatureOrGO(creature, ObjectGuid(), spell_id); } }*/ - /*else*/ if (creature > 0) + /*else*/ + if (creature > 0) { if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(creature)) for (uint16 z = 0; z < creaturecount; ++z) @@ -182,7 +184,7 @@ bool QuestAction::ProcessQuests(WorldObject* questGiver) { ObjectGuid guid = questGiver->GetGUID(); - if (bot->GetDistance(questGiver) > INTERACTION_DISTANCE && !sPlayerbotAIConfig->syncQuestWithPlayer) + if (bot->GetDistance(questGiver) > INTERACTION_DISTANCE && !sPlayerbotAIConfig.syncQuestWithPlayer) { //if (botAI->HasStrategy("debug", BotState::BOT_STATE_COMBAT) || botAI->HasStrategy("debug", BotState::BOT_STATE_NON_COMBAT)) @@ -190,7 +192,7 @@ bool QuestAction::ProcessQuests(WorldObject* questGiver) return false; } - if (!bot->HasInArc(CAST_ANGLE_IN_FRONT, questGiver, sPlayerbotAIConfig->sightDistance)) + if (!bot->HasInArc(CAST_ANGLE_IN_FRONT, questGiver, sPlayerbotAIConfig.sightDistance)) bot->SetFacingToObject(questGiver); bot->SetTarget(guid); @@ -238,7 +240,7 @@ bool QuestAction::AcceptQuest(Quest const* quest, ObjectGuid questGiver) p.rpos(0); bot->GetSession()->HandleQuestgiverAcceptQuestOpcode(p); - if (bot->GetQuestStatus(questId) == QUEST_STATUS_NONE && sPlayerbotAIConfig->syncQuestWithPlayer) + if (bot->GetQuestStatus(questId) == QUEST_STATUS_NONE && sPlayerbotAIConfig.syncQuestWithPlayer) { Object* pObject = ObjectAccessor::GetObjectByTypeMask(*bot, questGiver, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT | TYPEMASK_ITEM); @@ -350,7 +352,6 @@ bool QuestUpdateAddItemAction::Execute(Event event) uint32 itemId, count; p >> itemId >> count; - Player* requester = event.getOwner() ? event.getOwner() : GetMaster(); auto const* itemPrototype = sObjectMgr->GetItemTemplate(itemId); if (itemPrototype) { @@ -366,7 +367,7 @@ bool QuestUpdateAddItemAction::Execute(Event event) placeholders["%quest_obj_required"] = std::to_string(requiredItemsCount); if (botAI->HasStrategy("debug quest", BotState::BOT_STATE_COMBAT) || botAI->HasStrategy("debug quest", BotState::BOT_STATE_NON_COMBAT)) { - const auto text = BOT_TEXT2("%quest_link - %item_link %quest_obj_available/%quest_obj_required", placeholders); + const auto text = PlayerbotTextMgr::instance().GetBotText("%quest_link - %item_link %quest_obj_available/%quest_obj_required", placeholders); botAI->Say(text); LOG_INFO("playerbots", "{} => {}", bot->GetName(), text); } @@ -405,15 +406,14 @@ bool QuestItemPushResultAction::Execute(Event event) if (!quest) return false; - const QuestStatusData& q_status = bot->getQuestStatusMap().at(questId); - for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; i++) { uint32 itemId = quest->RequiredItemId[i]; if (!itemId) continue; - int32 previousCount = itemCount - count; + uint32_t previousCount = std::max(itemCount - count, 0); + if (itemId == itemEntry && previousCount < quest->RequiredItemCount[i]) { if (botAI->GetMaster()) @@ -432,7 +432,7 @@ bool QuestItemPushResultAction::Execute(Event event) return false; } -bool QuestUpdateFailedAction::Execute(Event event) +bool QuestUpdateFailedAction::Execute(Event) { //opcode SMSG_QUESTUPDATE_FAILED is never sent...(yet?) return false; @@ -446,15 +446,13 @@ bool QuestUpdateFailedTimerAction::Execute(Event event) uint32 questId; p >> questId; - Player* requester = event.getOwner() ? event.getOwner() : GetMaster(); - Quest const* qInfo = sObjectMgr->GetQuestTemplate(questId); if (qInfo) { std::map placeholders; placeholders["%quest_link"] = botAI->GetChatHelper()->FormatQuest(qInfo); - botAI->TellMaster(BOT_TEXT2("Failed timer for %quest_link, abandoning", placeholders)); + botAI->TellMaster(PlayerbotTextMgr::instance().GetBotText("Failed timer for %quest_link, abandoning", placeholders)); BroadcastHelper::BroadcastQuestUpdateFailedTimer(botAI, bot, qInfo); } else diff --git a/src/Ai/Base/Actions/RandomBotUpdateAction.cpp b/src/Ai/Base/Actions/RandomBotUpdateAction.cpp index 61a8360e59..fdf853bee0 100644 --- a/src/Ai/Base/Actions/RandomBotUpdateAction.cpp +++ b/src/Ai/Base/Actions/RandomBotUpdateAction.cpp @@ -8,9 +8,9 @@ #include "Event.h" #include "Playerbots.h" -bool RandomBotUpdateAction::Execute(Event event) +bool RandomBotUpdateAction::Execute(Event) { - if (!sRandomPlayerbotMgr->IsRandomBot(bot)) + if (!sRandomPlayerbotMgr.IsRandomBot(bot)) return false; if (bot->GetGroup() && botAI->GetGroupLeader()) @@ -20,10 +20,10 @@ bool RandomBotUpdateAction::Execute(Event event) return true; } - if (botAI->HasPlayerNearby(sPlayerbotAIConfig->grindDistance)) + if (botAI->HasPlayerNearby(sPlayerbotAIConfig.grindDistance)) return true; - return sRandomPlayerbotMgr->ProcessBot(bot); + return sRandomPlayerbotMgr.ProcessBot(bot); } bool RandomBotUpdateAction::isUseful() { return AI_VALUE(bool, "random bot update"); } diff --git a/src/Ai/Base/Actions/ReachTargetActions.cpp b/src/Ai/Base/Actions/ReachTargetActions.cpp index 2be0da6beb..80951c31c5 100644 --- a/src/Ai/Base/Actions/ReachTargetActions.cpp +++ b/src/Ai/Base/Actions/ReachTargetActions.cpp @@ -6,11 +6,10 @@ #include "ReachTargetActions.h" #include "Event.h" -#include "PlayerbotAIConfig.h" #include "Playerbots.h" #include "ServerFacade.h" -bool ReachTargetAction::Execute(Event event) { return ReachCombatTo(AI_VALUE(Unit*, GetTargetName()), distance); } +bool ReachTargetAction::Execute(Event) { return ReachCombatTo(AI_VALUE(Unit*, GetTargetName()), distance); } bool ReachTargetAction::isUseful() { @@ -28,24 +27,12 @@ bool ReachTargetAction::isUseful() Unit* target = GetTarget(); // float dis = distance + CONTACT_DISTANCE; return target && - !bot->IsWithinCombatRange(target, distance); // sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, + !bot->IsWithinCombatRange(target, distance); // ServerFacade::instance().IsDistanceGreaterThan(AI_VALUE2(float, // "distance", GetTargetName()), distance); } std::string const ReachTargetAction::GetTargetName() { return "current target"; } -bool CastReachTargetSpellAction::isUseful() -{ - // do not move while staying - if (botAI->HasStrategy("stay", botAI->GetState())) - { - return false; - } - - return sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", "current target"), - (distance + sPlayerbotAIConfig->contactDistance)); -} - ReachSpellAction::ReachSpellAction(PlayerbotAI* botAI) : ReachTargetAction(botAI, "reach spell", botAI->GetRange("spell")) { diff --git a/src/Ai/Base/Actions/ReachTargetActions.h b/src/Ai/Base/Actions/ReachTargetActions.h index 40559753f9..77d8250b00 100644 --- a/src/Ai/Base/Actions/ReachTargetActions.h +++ b/src/Ai/Base/Actions/ReachTargetActions.h @@ -6,7 +6,6 @@ #ifndef _PLAYERBOT_REACHTARGETACTIONS_H #define _PLAYERBOT_REACHTARGETACTIONS_H -#include "GenericSpellActions.h" #include "MovementActions.h" class PlayerbotAI; @@ -27,24 +26,10 @@ class ReachTargetAction : public MovementAction float distance; }; -class CastReachTargetSpellAction : public CastSpellAction -{ -public: - CastReachTargetSpellAction(PlayerbotAI* botAI, std::string const spell, float distance) - : CastSpellAction(botAI, spell), distance(distance) - { - } - - bool isUseful() override; - -protected: - float distance; -}; - class ReachMeleeAction : public ReachTargetAction { public: - ReachMeleeAction(PlayerbotAI* botAI) : ReachTargetAction(botAI, "reach melee", sPlayerbotAIConfig->meleeDistance) {} + ReachMeleeAction(PlayerbotAI* botAI) : ReachTargetAction(botAI, "reach melee", sPlayerbotAIConfig.meleeDistance) {} }; class ReachSpellAction : public ReachTargetAction diff --git a/src/Ai/Base/Actions/ReadyCheckAction.cpp b/src/Ai/Base/Actions/ReadyCheckAction.cpp index 2fc25e6dcc..671fef37dd 100644 --- a/src/Ai/Base/Actions/ReadyCheckAction.cpp +++ b/src/Ai/Base/Actions/ReadyCheckAction.cpp @@ -11,19 +11,32 @@ #include "Event.h" #include "Playerbots.h" -std::string const formatPercent(std::string const name, uint8 value, float percent) +std::string_view getColorForThreshold(const float threshold) +{ + if (threshold > 75.0f) + { + return "|cff00ff00"; + } + + if (threshold > 50.0f) + { + return "|cffffff00"; + } + + return "|cffff0000"; +} + +std::string formatPercent(const std::string& name, const uint32_t value, const float threshold) { std::ostringstream out; - std::string color; - if (percent > 75) - color = "|cff00ff00"; - else if (percent > 50) - color = "|cffffff00"; - else - color = "|cffff0000"; + out << "|cffffffff[" + << name + << "]" + << getColorForThreshold(threshold) + << "x" + << value; - out << "|cffffffff[" << name << "]" << color << "x" << (int)value; return out.str(); } @@ -45,9 +58,9 @@ std::once_flag ReadyChecker::initFlag; class HealthChecker : public ReadyChecker { public: - bool Check(PlayerbotAI* botAI, AiObjectContext* context) override + bool Check(PlayerbotAI*, AiObjectContext* context) override { - return AI_VALUE2(uint8, "health", "self target") > sPlayerbotAIConfig->almostFullHealth; + return AI_VALUE2(uint8, "health", "self target") > sPlayerbotAIConfig.almostFullHealth; } std::string const getName() override { return "HP"; } @@ -56,10 +69,10 @@ class HealthChecker : public ReadyChecker class ManaChecker : public ReadyChecker { public: - bool Check(PlayerbotAI* botAI, AiObjectContext* context) override + bool Check(PlayerbotAI*, AiObjectContext* context) override { return !AI_VALUE2(bool, "has mana", "self target") || - AI_VALUE2(uint8, "mana", "self target") > sPlayerbotAIConfig->mediumHealth; + AI_VALUE2(uint8, "mana", "self target") > sPlayerbotAIConfig.mediumHealth; } std::string const getName() override { return "MP"; } @@ -68,12 +81,12 @@ class ManaChecker : public ReadyChecker class DistanceChecker : public ReadyChecker { public: - bool Check(PlayerbotAI* botAI, AiObjectContext* context) override + bool Check(PlayerbotAI* botAI, AiObjectContext*) override { Player* bot = botAI->GetBot(); if (Player* master = botAI->GetMaster()) { - bool distance = bot->GetDistance(master) <= sPlayerbotAIConfig->sightDistance; + bool distance = bot->GetDistance(master) <= sPlayerbotAIConfig.sightDistance; if (!distance) { return false; @@ -90,7 +103,7 @@ class DistanceChecker : public ReadyChecker class HunterChecker : public ReadyChecker { public: - bool Check(PlayerbotAI* botAI, AiObjectContext* context) override + bool Check(PlayerbotAI* botAI, AiObjectContext*) override { Player* bot = botAI->GetBot(); if (bot->getClass() == CLASS_HUNTER) @@ -126,7 +139,7 @@ class ItemCountChecker : public ReadyChecker public: ItemCountChecker(std::string const item, std::string const name) : item(item), name(name) {} - bool Check(PlayerbotAI* botAI, AiObjectContext* context) override + bool Check(PlayerbotAI*, AiObjectContext* context) override { return AI_VALUE2(uint32, "item count", item) > 0; } @@ -225,4 +238,4 @@ bool ReadyCheckAction::ReadyCheck() return true; } -bool FinishReadyCheckAction::Execute(Event event) { return ReadyCheck(); } +bool FinishReadyCheckAction::Execute(Event) { return ReadyCheck(); } diff --git a/src/Ai/Base/Actions/ReleaseSpiritAction.cpp b/src/Ai/Base/Actions/ReleaseSpiritAction.cpp index 17fcc42a0b..e62192b61a 100644 --- a/src/Ai/Base/Actions/ReleaseSpiritAction.cpp +++ b/src/Ai/Base/Actions/ReleaseSpiritAction.cpp @@ -65,7 +65,7 @@ void ReleaseSpiritAction::IncrementDeathCount() const } } -void ReleaseSpiritAction::LogRelease(const std::string& releaseMsg, bool isAutoRelease) const +void ReleaseSpiritAction::LogRelease(const std::string& releaseMsg, bool) const { const std::string teamPrefix = bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H"; @@ -78,7 +78,7 @@ void ReleaseSpiritAction::LogRelease(const std::string& releaseMsg, bool isAutoR } // AutoReleaseSpiritAction implementation -bool AutoReleaseSpiritAction::Execute(Event event) +bool AutoReleaseSpiritAction::Execute(Event) { IncrementDeathCount(); bot->DurabilityRepairAll(false, 1.0f, false); @@ -183,9 +183,9 @@ bool AutoReleaseSpiritAction::ShouldAutoRelease() const return false; } - return sServerFacade->IsDistanceGreaterThan( + return ServerFacade::instance().IsDistanceGreaterThan( AI_VALUE2(float, "distance", "group leader"), - sPlayerbotAIConfig->sightDistance); + sPlayerbotAIConfig.sightDistance); } bool AutoReleaseSpiritAction::ShouldDelayBattlegroundRelease() const @@ -214,7 +214,7 @@ bool AutoReleaseSpiritAction::ShouldDelayBattlegroundRelease() const return true; } -bool RepopAction::Execute(Event event) +bool RepopAction::Execute(Event) { const GraveyardStruct* graveyard = GetGrave( AI_VALUE(uint32, "death count") > 10 || @@ -250,7 +250,7 @@ void RepopAction::PerformGraveyardTeleport(const GraveyardStruct* graveyard) con } // SelfResurrectAction implementation for Warlock's Soulstone Resurrection/Shaman's Reincarnation -bool SelfResurrectAction::Execute(Event event) +bool SelfResurrectAction::Execute(Event) { if (!bot->IsAlive() && bot->GetUInt32Value(PLAYER_SELF_RES_SPELL)) { diff --git a/src/Ai/Base/Actions/RememberTaxiAction.cpp b/src/Ai/Base/Actions/RememberTaxiAction.cpp index af5a540370..b056f38402 100644 --- a/src/Ai/Base/Actions/RememberTaxiAction.cpp +++ b/src/Ai/Base/Actions/RememberTaxiAction.cpp @@ -7,7 +7,7 @@ #include "Event.h" #include "LastMovementValue.h" -#include "Playerbots.h" +#include "AiObjectContext.h" bool RememberTaxiAction::Execute(Event event) { @@ -28,7 +28,7 @@ bool RememberTaxiAction::Execute(Event event) case CMSG_ACTIVATETAXIEXPRESS: { ObjectGuid guid; - uint32 node_count, totalcost; + uint32 node_count; p >> guid >> node_count; LastMovement& movement = context->GetValue("last taxi")->Get(); diff --git a/src/Ai/Base/Actions/RemoveAuraAction.cpp b/src/Ai/Base/Actions/RemoveAuraAction.cpp index a863a5973b..15a4a1a519 100644 --- a/src/Ai/Base/Actions/RemoveAuraAction.cpp +++ b/src/Ai/Base/Actions/RemoveAuraAction.cpp @@ -6,7 +6,7 @@ #include "RemoveAuraAction.h" #include "Event.h" -#include "Playerbots.h" +#include "PlayerbotAI.h" RemoveAuraAction::RemoveAuraAction(PlayerbotAI* botAI) : Action(botAI, "ra") {} diff --git a/src/Ai/Base/Actions/RepairAllAction.cpp b/src/Ai/Base/Actions/RepairAllAction.cpp index a66ba3a1bb..d62fb1ad12 100644 --- a/src/Ai/Base/Actions/RepairAllAction.cpp +++ b/src/Ai/Base/Actions/RepairAllAction.cpp @@ -9,7 +9,7 @@ #include "Event.h" #include "Playerbots.h" -bool RepairAllAction::Execute(Event event) +bool RepairAllAction::Execute(Event) { GuidVector npcs = AI_VALUE(GuidVector, "nearest npcs"); for (ObjectGuid const guid : npcs) diff --git a/src/Ai/Base/Actions/ResetAiAction.cpp b/src/Ai/Base/Actions/ResetAiAction.cpp index 3df6bbcd2a..19017c9161 100644 --- a/src/Ai/Base/Actions/ResetAiAction.cpp +++ b/src/Ai/Base/Actions/ResetAiAction.cpp @@ -44,7 +44,7 @@ bool ResetAiAction::Execute(Event event) } } } - sPlayerbotRepository->Reset(botAI); + PlayerbotRepository::instance().Reset(botAI); botAI->ResetStrategies(false); botAI->TellMaster("AI was reset to defaults"); return true; diff --git a/src/Ai/Base/Actions/ResetInstancesAction.cpp b/src/Ai/Base/Actions/ResetInstancesAction.cpp index cce5eef1e3..8bf9946d5d 100644 --- a/src/Ai/Base/Actions/ResetInstancesAction.cpp +++ b/src/Ai/Base/Actions/ResetInstancesAction.cpp @@ -5,15 +5,19 @@ #include "ResetInstancesAction.h" -#include "Playerbots.h" +#include "PlayerbotAI.h" -bool ResetInstancesAction::Execute(Event event) +bool ResetInstancesAction::Execute(Event) { WorldPacket packet(CMSG_RESET_INSTANCES, 0); - bot->GetSession()->HandleResetInstancesOpcode(packet); - botAI->TellMaster("Resetting all instances"); + this->bot->GetSession()->HandleResetInstancesOpcode(packet); + this->botAI->TellMaster("Resetting all instances"); + return true; } -bool ResetInstancesAction::isUseful() { return botAI->GetGroupLeader() == bot; }; +bool ResetInstancesAction::isUseful() +{ + return this->botAI->GetGroupLeader() == this->bot; +}; diff --git a/src/Ai/Base/Actions/RevealGatheringItemAction.cpp b/src/Ai/Base/Actions/RevealGatheringItemAction.cpp index 9725dce5ce..7c2a3c85ee 100644 --- a/src/Ai/Base/Actions/RevealGatheringItemAction.cpp +++ b/src/Ai/Base/Actions/RevealGatheringItemAction.cpp @@ -5,31 +5,33 @@ #include "RevealGatheringItemAction.h" -#include "CellImpl.h" #include "ChatHelper.h" #include "Event.h" #include "GridNotifiers.h" -#include "GridNotifiersImpl.h" -#include "Playerbots.h" #include "ServerFacade.h" #include "NearestGameObjects.h" +#include "PlayerbotAI.h" + +// Required due to a poor implementation by AC +#include "CellImpl.h" +#include "GridNotifiersImpl.h" -bool RevealGatheringItemAction::Execute(Event event) +bool RevealGatheringItemAction::Execute(Event) { if (!bot->GetGroup()) return false; std::list targets; - AnyGameObjectInObjectRangeCheck u_check(bot, sPlayerbotAIConfig->grindDistance); + AnyGameObjectInObjectRangeCheck u_check(bot, sPlayerbotAIConfig.grindDistance); Acore::GameObjectListSearcher searcher(bot, targets, u_check); - Cell::VisitObjects(bot, searcher, sPlayerbotAIConfig->reactDistance); + Cell::VisitObjects(bot, searcher, sPlayerbotAIConfig.reactDistance); std::vector result; for (GameObject* go : targets) { if (!go || !go->isSpawned() || - sServerFacade->IsDistanceLessOrEqualThan(sServerFacade->GetDistance2d(bot, go), - sPlayerbotAIConfig->lootDistance)) + ServerFacade::instance().IsDistanceLessOrEqualThan(ServerFacade::instance().GetDistance2d(bot, go), + sPlayerbotAIConfig.lootDistance)) continue; if (LockEntry const* lockInfo = sLockStore.LookupEntry(go->GetGOInfo()->GetLockId())) diff --git a/src/Ai/Base/Actions/ReviveFromCorpseAction.cpp b/src/Ai/Base/Actions/ReviveFromCorpseAction.cpp index ce0b1fa05d..efb179737b 100644 --- a/src/Ai/Base/Actions/ReviveFromCorpseAction.cpp +++ b/src/Ai/Base/Actions/ReviveFromCorpseAction.cpp @@ -5,11 +5,11 @@ #include "ReviveFromCorpseAction.h" +#include "CreateNextAction.h" #include "Event.h" #include "FleeManager.h" #include "GameGraveyard.h" #include "MapMgr.h" -#include "PlayerbotFactory.h" #include "Playerbots.h" #include "RandomPlayerbotMgr.h" #include "ServerFacade.h" @@ -24,8 +24,8 @@ bool ReviveFromCorpseAction::Execute(Event event) WorldPacket& p = event.getPacket(); if (!p.empty() && p.GetOpcode() == CMSG_RECLAIM_CORPSE && groupLeader && !corpse && bot->IsAlive()) { - if (sServerFacade->IsDistanceLessThan(AI_VALUE2(float, "distance", "group leader"), - sPlayerbotAIConfig->farDistance)) + if (ServerFacade::instance().IsDistanceLessThan(AI_VALUE2(float, "distance", "group leader"), + sPlayerbotAIConfig.farDistance)) { if (!botAI->HasStrategy("follow", BOT_STATE_NON_COMBAT)) { @@ -46,8 +46,8 @@ bool ReviveFromCorpseAction::Execute(Event event) if (groupLeader) { if (!GET_PLAYERBOT_AI(groupLeader) && groupLeader->isDead() && groupLeader->GetCorpse() && - sServerFacade->IsDistanceLessThan(AI_VALUE2(float, "distance", "group leader"), - sPlayerbotAIConfig->farDistance)) + ServerFacade::instance().IsDistanceLessThan(AI_VALUE2(float, "distance", "group leader"), + sPlayerbotAIConfig.farDistance)) return false; } @@ -57,7 +57,7 @@ bool ReviveFromCorpseAction::Execute(Event event) if (dCount >= 5) { - return botAI->DoSpecificAction("spirit healer"); + return botAI->DoSpecificAction(CreateNextAction(1.0f).factory); } } @@ -74,7 +74,7 @@ bool ReviveFromCorpseAction::Execute(Event event) return true; } -bool FindCorpseAction::Execute(Event event) +bool FindCorpseAction::Execute(Event) { if (bot->InBattleground()) return false; @@ -87,8 +87,8 @@ bool FindCorpseAction::Execute(Event event) // if (groupLeader) // { // if (!GET_PLAYERBOT_AI(groupLeader) && - // sServerFacade->IsDistanceLessThan(AI_VALUE2(float, "distance", "group leader"), - // sPlayerbotAIConfig->farDistance)) return false; + // ServerFacade::instance().IsDistanceLessThan(AI_VALUE2(float, "distance", "group leader"), + // sPlayerbotAIConfig.farDistance)) return false; // } uint32 dCount = AI_VALUE(uint32, "death count"); @@ -101,8 +101,8 @@ bool FindCorpseAction::Execute(Event event) // bot->GetGUID().ToString().c_str(), bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", bot->GetLevel(), // bot->GetName().c_str()); context->GetValue("death count")->Set(0); - // sRandomPlayerbotMgr->RandomTeleportForLevel(bot); - sRandomPlayerbotMgr->Revive(bot); + // sRandomPlayerbotMgr.RandomTeleportForLevel(bot); + sRandomPlayerbotMgr.Revive(bot); return true; } } @@ -123,7 +123,7 @@ bool FindCorpseAction::Execute(Event event) { if (moveToLeader) // We are near group leader. { - if (botPos.fDist(leaderPos) < sPlayerbotAIConfig->spellDistance) + if (botPos.fDist(leaderPos) < sPlayerbotAIConfig.spellDistance) return false; } else if (deadTime > 8 * MINUTE) // We have walked too long already. @@ -138,7 +138,7 @@ bool FindCorpseAction::Execute(Event event) } // If we are getting close move to a save ressurrection spot instead of just the corpse. - if (corpseDist < sPlayerbotAIConfig->reactDistance) + if (corpseDist < sPlayerbotAIConfig.reactDistance) { if (moveToLeader) moveToPos = leaderPos; @@ -162,7 +162,7 @@ bool FindCorpseAction::Execute(Event event) if (!botAI->AllowActivity(ALL_ACTIVITY)) { - uint32 delay = sServerFacade->GetDistance2d(bot, corpse) / + uint32 delay = ServerFacade::instance().GetDistance2d(bot, corpse) / bot->GetSpeed(MOVE_RUN); // Time a bot would take to travel to it's corpse. delay = std::min(delay, uint32(10 * MINUTE)); // Cap time to get to corpse at 10 minutes. @@ -189,7 +189,7 @@ bool FindCorpseAction::Execute(Event event) if (!moved) { - moved = botAI->DoSpecificAction("spirit healer", Event(), true); + moved = botAI->DoSpecificAction(CreateNextAction(1.0f).factory, Event(), true); } } } @@ -293,7 +293,7 @@ GraveyardStruct const* SpiritHealerAction::GetGrave(bool startZone) return ClosestGrave; } -bool SpiritHealerAction::Execute(Event event) +bool SpiritHealerAction::Execute(Event) { Corpse* corpse = bot->GetCorpse(); if (!corpse) @@ -308,7 +308,7 @@ bool SpiritHealerAction::Execute(Event event) GraveyardStruct const* ClosestGrave = GetGrave(dCount > 10 || deadTime > 15 * MINUTE || AI_VALUE(uint8, "durability") < 10); - if (bot->GetDistance2d(ClosestGrave->x, ClosestGrave->y) < sPlayerbotAIConfig->sightDistance) + if (bot->GetDistance2d(ClosestGrave->x, ClosestGrave->y) < sPlayerbotAIConfig.sightDistance) { GuidVector npcs = AI_VALUE(GuidVector, "nearest npcs"); for (GuidVector::iterator i = npcs.begin(); i != npcs.end(); i++) diff --git a/src/Ai/Base/Actions/RpgAction.cpp b/src/Ai/Base/Actions/RpgAction.cpp index 6002eaf63a..db0f34efa7 100644 --- a/src/Ai/Base/Actions/RpgAction.cpp +++ b/src/Ai/Base/Actions/RpgAction.cpp @@ -7,7 +7,6 @@ #include -#include "BattlegroundMgr.h" #include "ChatHelper.h" #include "EmoteAction.h" #include "Event.h" @@ -16,7 +15,7 @@ #include "ServerFacade.h" #include "RpgSubActions.h" -bool RpgAction::Execute(Event event) +bool RpgAction::Execute(Event) { GuidPosition guidP = AI_VALUE(GuidPosition, "rpg target"); if (!guidP && botAI->GetMaster()) @@ -46,7 +45,7 @@ bool RpgAction::isUseful() { return AI_VALUE(GuidPosition, "rpg target"); } bool RpgAction::SetNextRpgAction() { Strategy* rpgStrategy; - std::vector actions; + std::vector> actions; std::vector relevances; std::vector triggerNodes; @@ -76,7 +75,7 @@ bool RpgAction::SetNextRpgAction() for (NextAction nextAction : nextActions) { - if (nextAction.getRelevance() > 5.0f) + if (nextAction.weight > 5.0f) continue; if (!isChecked && !trigger->IsActive()) @@ -84,12 +83,13 @@ bool RpgAction::SetNextRpgAction() isChecked = true; - Action* action = botAI->GetAiObjectContext()->GetAction(nextAction.getName()); - if (!dynamic_cast(action) || !action->isPossible() || !action->isUseful()) + std::unique_ptr action = nextAction.factory(this->botAI); + + if (!dynamic_cast(action.get()) || !action->isPossible() || !action->isUseful()) continue; - actions.push_back(action); - relevances.push_back((nextAction.getRelevance() - 1) * 500); + actions.push_back(std::move(action)); + relevances.push_back((nextAction.weight - 1) * 500); } } } @@ -108,8 +108,10 @@ bool RpgAction::SetNextRpgAction() { std::vector> sortedActions; - for (int i = 0; i < actions.size(); i++) - sortedActions.push_back(std::make_pair(actions[i], relevances[i])); + for (uint64_t i = 0; i < actions.size(); i++) + { + sortedActions.push_back(std::make_pair(actions[i].get(), relevances[i])); + } std::sort(sortedActions.begin(), sortedActions.end(), [](std::pairi, std::pair j) {return i.second > j.second; }); @@ -118,7 +120,7 @@ bool RpgAction::SetNextRpgAction() bot->Say(ss.str(), LANG_UNIVERSAL); botAI->TellMasterNoFacing(ss.str()); - for (auto action : sortedActions) + for (const std::pair& action : sortedActions) { std::ostringstream out; @@ -130,9 +132,9 @@ bool RpgAction::SetNextRpgAction() std::mt19937 gen(time(0)); - sTravelMgr->weighted_shuffle(actions.begin(), actions.end(), relevances.begin(), relevances.end(), gen); + TravelMgr::instance().weighted_shuffle(actions.begin(), actions.end(), relevances.begin(), relevances.end(), gen); - Action* action = actions.front(); + std::unique_ptr& action = actions.front(); if ((botAI->HasStrategy("debug", BotState::BOT_STATE_NON_COMBAT) || botAI->HasStrategy("debug rpg", BotState::BOT_STATE_NON_COMBAT))) { diff --git a/src/Ai/Base/Actions/RpgSubActions.cpp b/src/Ai/Base/Actions/RpgSubActions.cpp index aa4269fa92..18573cce33 100644 --- a/src/Ai/Base/Actions/RpgSubActions.cpp +++ b/src/Ai/Base/Actions/RpgSubActions.cpp @@ -5,16 +5,30 @@ #include "RpgSubActions.h" +#include "AcceptQuestAction.h" +#include "BattleGroundJoinAction.h" +#include "BuyAction.h" +#include "CastCustomSpellAction.h" #include "ChooseRpgTargetAction.h" +#include "DruidActions.h" #include "EmoteAction.h" #include "Formations.h" #include "GossipDef.h" #include "GuildCreateActions.h" #include "LastMovementValue.h" #include "MovementActions.h" +#include "PaladinActions.h" #include "Playerbots.h" #include "PossibleRpgTargetsValue.h" +#include "PriestActions.h" +#include "RepairAllAction.h" +#include "SellAction.h" +#include "SetHomeAction.h" +#include "ShamanActions.h" #include "SocialMgr.h" +#include "TalkToQuestGiverAction.h" +#include "TradeAction.h" +#include "TrainerAction.h" void RpgHelper::OnExecute(std::string nextAction) { @@ -77,74 +91,101 @@ void RpgHelper::setFacing(GuidPosition guidPosition) void RpgHelper::setDelay(bool waitForGroup) { if (!botAI->HasRealPlayerMaster() || (waitForGroup && botAI->GetGroupLeader() == bot && bot->GetGroup())) - botAI->SetNextCheckDelay(sPlayerbotAIConfig->rpgDelay); + botAI->SetNextCheckDelay(sPlayerbotAIConfig.rpgDelay); else - botAI->SetNextCheckDelay(sPlayerbotAIConfig->rpgDelay / 5); + botAI->SetNextCheckDelay(sPlayerbotAIConfig.rpgDelay / 5); } -bool RpgSubAction::isPossible() { return rpg->guidP() && rpg->guidP().GetWorldObject(); } +bool RpgSubAction::isPossible() +{ + return this->rpg->guidP() && this->rpg->guidP().GetWorldObject(); +} -bool RpgSubAction::isUseful() { return rpg->InRange(); } +bool RpgSubAction::isUseful() +{ + return this->rpg->InRange(); +} bool RpgSubAction::Execute(Event event) { - bool doAction = botAI->DoSpecificAction(ActionName(), ActionEvent(event), true); - rpg->AfterExecute(doAction, true); + bool doAction = botAI->DoSpecificAction(this->getActionFactory(), this->ActionEvent(event), true); + this->rpg->AfterExecute(doAction, true); return doAction; } -std::string const RpgSubAction::ActionName() { return "none"; } +// @TODO: This is a simple fallback. It should never be triggered. +NextAction::Factory RpgSubAction::getActionFactory() const +{ + LOG_ERROR("playerbots.rpg.rpgsubaction", "Bot {} - No action factory defined for RpgSubAction", this->bot->GetName()); -Event RpgSubAction::ActionEvent(Event event) { return event; } + return CreateNextAction(1.0f).factory; +} -bool RpgStayAction::isUseful() { return rpg->InRange() && !botAI->HasRealPlayerMaster(); } +Event RpgSubAction::ActionEvent(Event event) +{ + return event; +} + +bool RpgStayAction::isUseful() +{ + return this->rpg->InRange() && !this->botAI->HasRealPlayerMaster(); +} -bool RpgStayAction::Execute(Event event) +bool RpgStayAction::Execute(Event) { - bot->PlayerTalkClass->SendCloseGossip(); + this->bot->PlayerTalkClass->SendCloseGossip(); + + this->rpg->AfterExecute(); - rpg->AfterExecute(); return true; } -bool RpgWorkAction::isUseful() { return rpg->InRange() && !botAI->HasRealPlayerMaster(); } +bool RpgWorkAction::isUseful() +{ + return this->rpg->InRange() && !this->botAI->HasRealPlayerMaster(); +} -bool RpgWorkAction::Execute(Event event) +bool RpgWorkAction::Execute(Event) { - bot->HandleEmoteCommand(EMOTE_STATE_USE_STANDING); - rpg->AfterExecute(); + this->bot->HandleEmoteCommand(EMOTE_STATE_USE_STANDING); + this->rpg->AfterExecute(); return true; } -bool RpgEmoteAction::isUseful() { return rpg->InRange() && !botAI->HasRealPlayerMaster(); } +bool RpgEmoteAction::isUseful() +{ + return this->rpg->InRange() && !this->botAI->HasRealPlayerMaster(); +} -bool RpgEmoteAction::Execute(Event event) +bool RpgEmoteAction::Execute(Event) { - uint32 type = TalkAction::GetRandomEmote(rpg->guidP().GetUnit()); + uint32 type = TalkAction::GetRandomEmote(this->rpg->guidP().GetUnit()); WorldPacket p1; - p1 << rpg->guid(); - bot->GetSession()->HandleGossipHelloOpcode(p1); + p1 << this->rpg->guid(); - bot->HandleEmoteCommand(type); - - rpg->AfterExecute(); + this->bot->GetSession()->HandleGossipHelloOpcode(p1); + this->bot->HandleEmoteCommand(type); + this->rpg->AfterExecute(); return true; } -bool RpgCancelAction::Execute(Event event) +bool RpgCancelAction::Execute(Event) { RESET_AI_VALUE(GuidPosition, "rpg target"); - rpg->OnExecute(""); + this->rpg->OnExecute(""); return true; } -bool RpgTaxiAction::isUseful() { return rpg->InRange() && !botAI->HasRealPlayerMaster(); } +bool RpgTaxiAction::isUseful() +{ + return this->rpg->InRange() && !this->botAI->HasRealPlayerMaster(); +} -bool RpgTaxiAction::Execute(Event event) +bool RpgTaxiAction::Execute(Event) { - GuidPosition guidP = rpg->guidP(); + GuidPosition guidP = this->rpg->guidP(); WorldPacket emptyPacket; bot->GetSession()->HandleCancelMountAuraOpcode(emptyPacket); @@ -156,7 +197,7 @@ bool RpgTaxiAction::Execute(Event event) for (uint32 i = 0; i < sTaxiPathStore.GetNumRows(); ++i) { TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(i); - if (entry && entry->from == node && (bot->m_taxi.IsTaximaskNodeKnown(entry->to) || bot->isTaxiCheater())) + if (entry && entry->from == node && (this->bot->m_taxi.IsTaximaskNodeKnown(entry->to) || this->bot->isTaxiCheater())) { nodes.push_back(i); } @@ -169,8 +210,8 @@ bool RpgTaxiAction::Execute(Event event) } uint32 path = nodes[urand(0, nodes.size() - 1)]; - uint32 money = bot->GetMoney(); - bot->SetMoney(money + 100000); + uint32 money = this->bot->GetMoney(); + this->bot->SetMoney(money + 100000); TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(path); if (!entry) @@ -182,30 +223,30 @@ bool RpgTaxiAction::Execute(Event event) Creature* flightMaster = bot->GetNPCIfCanInteractWith(guidP, UNIT_NPC_FLAG_FLIGHTMASTER); if (!flightMaster) { - LOG_ERROR("playerbots", "Bot {} cannot talk to flightmaster ({} location available)", bot->GetName(), + LOG_ERROR("playerbots", "Bot {} cannot talk to flightmaster ({} location available)", this->bot->GetName(), nodes.size()); return false; } - if (!bot->ActivateTaxiPathTo({entry->from, entry->to}, flightMaster, 0)) + if (!this->bot->ActivateTaxiPathTo({entry->from, entry->to}, flightMaster, 0)) { - LOG_ERROR("playerbots", "Bot {} cannot fly {} ({} location available)", bot->GetName(), path, nodes.size()); + LOG_ERROR("playerbots", "Bot {} cannot fly {} ({} location available)", this->bot->GetName(), path, nodes.size()); return false; } LOG_INFO("playerbots", "Bot {} <{}> is flying from {} to {} ({} location available)", - bot->GetGUID().ToString().c_str(), bot->GetName(), nodeFrom->name[0], nodeTo->name[0], nodes.size()); + this->bot->GetGUID().ToString().c_str(), this->bot->GetName(), nodeFrom->name[0], nodeTo->name[0], nodes.size()); - bot->SetMoney(money); + this->bot->SetMoney(money); - rpg->AfterExecute(); + this->rpg->AfterExecute(); return true; } -bool RpgDiscoverAction::Execute(Event event) +bool RpgDiscoverAction::Execute(Event) { - GuidPosition guidP = rpg->guidP(); + GuidPosition guidP = this->rpg->guidP(); uint32 node = sObjectMgr->GetNearestTaxiNode(guidP.getX(), guidP.getY(), guidP.getZ(), guidP.getMapId(), bot->GetTeamId()); @@ -213,97 +254,139 @@ bool RpgDiscoverAction::Execute(Event event) if (!node) return false; - Creature* flightMaster = bot->GetNPCIfCanInteractWith(guidP, UNIT_NPC_FLAG_FLIGHTMASTER); + Creature* flightMaster = this->bot->GetNPCIfCanInteractWith(guidP, UNIT_NPC_FLAG_FLIGHTMASTER); if (!flightMaster) return false; - return bot->GetSession()->SendLearnNewTaxiNode(flightMaster); + return this->bot->GetSession()->SendLearnNewTaxiNode(flightMaster); } -std::string const RpgStartQuestAction::ActionName() { return "accept all quests"; } +NextAction::Factory RpgStartQuestAction::getActionFactory() const +{ + return CreateNextAction(1.0f).factory; +} -Event RpgStartQuestAction::ActionEvent(Event event) +Event RpgStartQuestAction::ActionEvent(Event) { WorldPacket p(CMSG_QUESTGIVER_ACCEPT_QUEST); - p << rpg->guid(); + p << this->rpg->guid(); p.rpos(0); + return Event("rpg action", p); } -std::string const RpgEndQuestAction::ActionName() { return "talk to quest giver"; } +NextAction::Factory RpgEndQuestAction::getActionFactory() const +{ + return CreateNextAction(1.0f).factory; +} -Event RpgEndQuestAction::ActionEvent(Event event) +Event RpgEndQuestAction::ActionEvent(Event) { WorldPacket p(CMSG_QUESTGIVER_COMPLETE_QUEST); - p << rpg->guid(); + p << this->rpg->guid(); p.rpos(0); + return Event("rpg action", p); } -std::string const RpgBuyAction::ActionName() { return "buy"; } +NextAction::Factory RpgBuyAction::getActionFactory() const +{ + return CreateNextAction(1.0f).factory; +} -Event RpgBuyAction::ActionEvent(Event event) { return Event("rpg action", "vendor"); } +Event RpgBuyAction::ActionEvent(Event) +{ + return Event("rpg action", "vendor"); +} -std::string const RpgSellAction::ActionName() { return "sell"; } +NextAction::Factory RpgSellAction::getActionFactory() const +{ + return CreateNextAction(1.0f).factory; +} -Event RpgSellAction::ActionEvent(Event event) { return Event("rpg action", "vendor"); } +Event RpgSellAction::ActionEvent(Event) +{ + return Event("rpg action", "vendor"); +} -std::string const RpgRepairAction::ActionName() { return "repair"; } +NextAction::Factory RpgRepairAction::getActionFactory() const +{ + return CreateNextAction(1.0f).factory; +} -std::string const RpgTrainAction::ActionName() { return "trainer"; } +NextAction::Factory RpgTrainAction::getActionFactory() const +{ + return CreateNextAction(1.0f).factory; +} -bool RpgHealAction::Execute(Event event) +bool RpgHealAction::Execute(Event) { bool retVal = false; switch (bot->getClass()) { case CLASS_PRIEST: - retVal = botAI->DoSpecificAction("lesser heal on party", Event(), true); + retVal = botAI->DoSpecificAction(CreateNextAction(1.0f).factory, Event(), true); break; case CLASS_DRUID: - retVal = botAI->DoSpecificAction("healing touch on party", Event(), true); + retVal = botAI->DoSpecificAction(CreateNextAction(1.0f).factory, Event(), true); break; case CLASS_PALADIN: - retVal = botAI->DoSpecificAction("holy light on party", Event(), true); + retVal = botAI->DoSpecificAction(CreateNextAction(1.0f).factory, Event(), true); break; case CLASS_SHAMAN: - retVal = botAI->DoSpecificAction("healing wave on party", Event(), true); + retVal = botAI->DoSpecificAction(CreateNextAction(1.0f).factory, Event(), true); break; } return retVal; } -std::string const RpgHomeBindAction::ActionName() { return "home"; } +NextAction::Factory RpgHomeBindAction::getActionFactory() const +{ + return CreateNextAction(1.0f).factory; +} -std::string const RpgQueueBgAction::ActionName() +NextAction::Factory RpgQueueBgAction::getActionFactory() const { SET_AI_VALUE(uint32, "bg type", (uint32)AI_VALUE(BattlegroundTypeId, "rpg bg type")); - return "free bg join"; + + return CreateNextAction(1.0f).factory; } -std::string const RpgBuyPetitionAction::ActionName() { return "buy petition"; } +NextAction::Factory RpgBuyPetitionAction::getActionFactory() const +{ + return CreateNextAction(1.0f).factory; +} -std::string const RpgUseAction::ActionName() { return "use"; } +NextAction::Factory RpgUseAction::getActionFactory() const +{ + return CreateNextAction(1.0f).factory; +} -Event RpgUseAction::ActionEvent(Event event) +Event RpgUseAction::ActionEvent(Event) { - return Event("rpg action", chat->FormatWorldobject(rpg->guidP().GetWorldObject())); + return Event("rpg action", chat->FormatWorldobject(this->rpg->guidP().GetWorldObject())); } -std::string const RpgSpellAction::ActionName() { return "cast random spell"; } +NextAction::Factory RpgSpellAction::getActionFactory() const +{ + return CreateNextAction(1.0f).factory; +} -Event RpgSpellAction::ActionEvent(Event event) +Event RpgSpellAction::ActionEvent(Event) { - return Event("rpg action", chat->FormatWorldobject(rpg->guidP().GetWorldObject())); + return Event("rpg action", chat->FormatWorldobject(this->rpg->guidP().GetWorldObject())); } -std::string const RpgCraftAction::ActionName() { return "craft random item"; } +NextAction::Factory RpgCraftAction::getActionFactory() const +{ + return CreateNextAction(1.0f).factory; +} -Event RpgCraftAction::ActionEvent(Event event) +Event RpgCraftAction::ActionEvent(Event) { - return Event("rpg action", chat->FormatWorldobject(rpg->guidP().GetWorldObject())); + return Event("rpg action", chat->FormatWorldobject(this->rpg->guidP().GetWorldObject())); } std::vector RpgTradeUsefulAction::CanGiveItems(GuidPosition guidPosition) @@ -341,7 +424,7 @@ std::vector RpgTradeUsefulAction::CanGiveItems(GuidPosition guidPosition) return giveItems; } -bool RpgTradeUsefulAction::Execute(Event event) +bool RpgTradeUsefulAction::Execute(Event) { GuidPosition guidP = AI_VALUE(GuidPosition, "rpg target"); @@ -363,7 +446,7 @@ bool RpgTradeUsefulAction::Execute(Event event) param << " "; param << chat->FormatItem(item->GetTemplate()); - bool hasTraded = botAI->DoSpecificAction("trade", Event("rpg action", param.str().c_str()), true); + bool hasTraded = botAI->DoSpecificAction(CreateNextAction(1.0f).factory, Event("rpg action", param.str().c_str()), true); if (hasTraded || bot->GetTradeData()) { @@ -392,7 +475,7 @@ bool RpgTradeUsefulAction::Execute(Event event) bot->Say("Start trade with" + chat->FormatWorldobject(player), (bot->GetTeamId() == TEAM_ALLIANCE ? LANG_COMMON : LANG_ORCISH)); - botAI->SetNextCheckDelay(sPlayerbotAIConfig->rpgDelay); + botAI->SetNextCheckDelay(sPlayerbotAIConfig.rpgDelay); return true; } @@ -402,7 +485,7 @@ bool RpgTradeUsefulAction::Execute(Event event) bool RpgDuelAction::isUseful() { // do not offer duel in non pvp areas - if (sPlayerbotAIConfig->IsInPvpProhibitedZone(bot->GetZoneId())) + if (sPlayerbotAIConfig.IsInPvpProhibitedZone(bot->GetZoneId())) return false; // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities) @@ -416,7 +499,7 @@ bool RpgDuelAction::isUseful() return true; } -bool RpgDuelAction::Execute(Event event) +bool RpgDuelAction::Execute(Event) { GuidPosition guidP = AI_VALUE(GuidPosition, "rpg target"); @@ -425,7 +508,7 @@ bool RpgDuelAction::Execute(Event event) if (!player) return false; - return botAI->DoSpecificAction("cast custom spell", Event("rpg action", chat->FormatWorldobject(player) + " 7266"), + return botAI->DoSpecificAction(CreateNextAction(1.0f).factory, Event("rpg action", chat->FormatWorldobject(player) + " 7266"), true); } @@ -434,7 +517,7 @@ bool RpgMountAnimAction::isUseful() return AI_VALUE2(bool, "mounted", "self target") && !AI_VALUE2(bool, "moving", "self target"); } -bool RpgMountAnimAction::Execute(Event event) +bool RpgMountAnimAction::Execute(Event) { WorldPacket p; bot->GetSession()->HandleMountSpecialAnimOpcode(p); diff --git a/src/Ai/Base/Actions/RpgSubActions.h b/src/Ai/Base/Actions/RpgSubActions.h index 8d5fbda4c7..7ba9e25d93 100644 --- a/src/Ai/Base/Actions/RpgSubActions.h +++ b/src/Ai/Base/Actions/RpgSubActions.h @@ -8,7 +8,10 @@ #include "Action.h" #include "AiObject.h" +#include "EmoteAction.h" #include "Item.h" +#include "StayActions.h" +#include "TaxiAction.h" class GuidPosition; class ObjectGuid; @@ -55,7 +58,7 @@ class RpgSubAction : public Action, public RpgEnabled bool Execute(Event event) override; protected: - virtual std::string const ActionName(); + virtual NextAction::Factory getActionFactory() const; virtual Event ActionEvent(Event event); }; @@ -117,7 +120,7 @@ class RpgStartQuestAction : public RpgSubAction RpgStartQuestAction(PlayerbotAI* botAI, std::string const name = "rpg start quest") : RpgSubAction(botAI, name) {} private: - std::string const ActionName() override; + NextAction::Factory getActionFactory() const override; Event ActionEvent(Event event) override; }; @@ -127,7 +130,7 @@ class RpgEndQuestAction : public RpgSubAction RpgEndQuestAction(PlayerbotAI* botAI, std::string const name = "rpg end quest") : RpgSubAction(botAI, name) {} private: - std::string const ActionName() override; + NextAction::Factory getActionFactory() const override; Event ActionEvent(Event event) override; }; @@ -137,7 +140,7 @@ class RpgBuyAction : public RpgSubAction RpgBuyAction(PlayerbotAI* botAI, std::string const name = "rpg buy") : RpgSubAction(botAI, name) {} private: - std::string const ActionName() override; + NextAction::Factory getActionFactory() const override; Event ActionEvent(Event event) override; }; @@ -147,7 +150,7 @@ class RpgSellAction : public RpgSubAction RpgSellAction(PlayerbotAI* botAI, std::string const name = "rpg sell") : RpgSubAction(botAI, name) {} private: - std::string const ActionName() override; + NextAction::Factory getActionFactory() const override; Event ActionEvent(Event event) override; }; @@ -157,7 +160,7 @@ class RpgRepairAction : public RpgSubAction RpgRepairAction(PlayerbotAI* botAI, std::string const name = "rpg repair") : RpgSubAction(botAI, name) {} private: - std::string const ActionName() override; + NextAction::Factory getActionFactory() const override; }; class RpgTrainAction : public RpgSubAction @@ -166,7 +169,7 @@ class RpgTrainAction : public RpgSubAction RpgTrainAction(PlayerbotAI* botAI, std::string const name = "rpg train") : RpgSubAction(botAI, name) {} private: - std::string const ActionName() override; + NextAction::Factory getActionFactory() const override; }; class RpgHealAction : public RpgSubAction @@ -183,7 +186,7 @@ class RpgHomeBindAction : public RpgSubAction RpgHomeBindAction(PlayerbotAI* botAI, std::string const name = "rpg home bind") : RpgSubAction(botAI, name) {} private: - std::string const ActionName() override; + NextAction::Factory getActionFactory() const override; }; class RpgQueueBgAction : public RpgSubAction @@ -192,7 +195,7 @@ class RpgQueueBgAction : public RpgSubAction RpgQueueBgAction(PlayerbotAI* botAI, std::string const name = "rpg queue bg") : RpgSubAction(botAI, name) {} private: - std::string const ActionName() override; + NextAction::Factory getActionFactory() const override; }; class RpgBuyPetitionAction : public RpgSubAction @@ -201,7 +204,7 @@ class RpgBuyPetitionAction : public RpgSubAction RpgBuyPetitionAction(PlayerbotAI* botAI, std::string const name = "rpg buy petition") : RpgSubAction(botAI, name) {} private: - std::string const ActionName() override; + NextAction::Factory getActionFactory() const override; }; class RpgUseAction : public RpgSubAction @@ -210,7 +213,7 @@ class RpgUseAction : public RpgSubAction RpgUseAction(PlayerbotAI* botAI, std::string const name = "rpg use") : RpgSubAction(botAI, name) {} private: - std::string const ActionName() override; + NextAction::Factory getActionFactory() const override; Event ActionEvent(Event event) override; }; @@ -220,7 +223,7 @@ class RpgSpellAction : public RpgSubAction RpgSpellAction(PlayerbotAI* botAI, std::string const name = "rpg spell") : RpgSubAction(botAI, name) {} private: - std::string const ActionName() override; + NextAction::Factory getActionFactory() const override; Event ActionEvent(Event event) override; }; @@ -230,7 +233,7 @@ class RpgCraftAction : public RpgSubAction RpgCraftAction(PlayerbotAI* botAI, std::string const name = "rpg craft") : RpgSubAction(botAI, name) {} private: - std::string const ActionName() override; + NextAction::Factory getActionFactory() const override; Event ActionEvent(Event event) override; }; diff --git a/src/Ai/Base/Actions/RtiAction.cpp b/src/Ai/Base/Actions/RtiAction.cpp index b34b3eec3d..84a6aeba56 100644 --- a/src/Ai/Base/Actions/RtiAction.cpp +++ b/src/Ai/Base/Actions/RtiAction.cpp @@ -55,7 +55,7 @@ void RtiAction::AppendRti(std::ostringstream& out, std::string const type) out << " (" << target->GetName() << ")"; } -bool MarkRtiAction::Execute(Event event) +bool MarkRtiAction::Execute(Event) { Group* group = bot->GetGroup(); if (!group) diff --git a/src/Ai/Base/Actions/SayAction.cpp b/src/Ai/Base/Actions/SayAction.cpp index 00fae65293..7c9fd74e08 100644 --- a/src/Ai/Base/Actions/SayAction.cpp +++ b/src/Ai/Base/Actions/SayAction.cpp @@ -9,9 +9,7 @@ #include #include -#include "ChannelMgr.h" #include "Event.h" -#include "GuildMgr.h" #include "PlayerbotTextMgr.h" #include "Playerbots.h" @@ -46,6 +44,7 @@ static const std::unordered_set noReplyMsgs = { "guard", "do accept invitation", "stats", + "manage_inventory", "react ?", "reset strats", "home", @@ -56,7 +55,7 @@ static const std::unordered_set noReplyMsgStarts = {"e ", "accept " SayAction::SayAction(PlayerbotAI* botAI) : Action(botAI, "say"), Qualified() {} -bool SayAction::Execute(Event event) +bool SayAction::Execute(Event) { std::string text = ""; std::map placeholders; @@ -92,7 +91,6 @@ bool SayAction::Execute(Event event) } // set delay before next say - time_t lastSaid = AI_VALUE2(time_t, "last said", qualifier); uint32 nextTime = time(nullptr) + urand(1, 30); botAI->GetAiObjectContext()->GetValue("last said", qualifier)->Set(nextTime); @@ -134,7 +132,7 @@ bool SayAction::Execute(Event event) } // load text based on chance - if (!sPlayerbotTextMgr->GetBotText(qualifier, text, placeholders)) + if (!PlayerbotTextMgr::instance().GetBotText(qualifier, text, placeholders)) return false; if (text.find("/y ") == 0) @@ -157,9 +155,8 @@ bool SayAction::isUseful() return (time(nullptr) - lastSaid) > 30; } -void ChatReplyAction::ChatReplyDo(Player* bot, uint32& type, uint32& guid1, uint32& guid2, std::string& msg, std::string& chanName, std::string& name) +void ChatReplyAction::ChatReplyDo(Player* bot, uint32& type, uint32& guid1, uint32&, std::string& msg, std::string& chanName, std::string& name) { - ChatReplyType replyType = REPLY_NOT_UNDERSTAND; // default not understand std::string respondsText = ""; // if we're just commanding bots around, don't respond... @@ -206,7 +203,7 @@ void ChatReplyAction::ChatReplyDo(Player* bot, uint32& type, uint32& guid1, uint } //toxic links - if (msg.starts_with(sPlayerbotAIConfig->toxicLinksPrefix) + if (msg.starts_with(sPlayerbotAIConfig.toxicLinksPrefix) && (GET_PLAYERBOT_AI(bot)->GetChatHelper()->ExtractAllItemIds(msg).size() > 0 || GET_PLAYERBOT_AI(bot)->GetChatHelper()->ExtractAllQuestIds(msg).size() > 0)) { HandleToxicLinksReply(bot, chatChannelSource, msg, name); @@ -224,13 +221,13 @@ void ChatReplyAction::ChatReplyDo(Player* bot, uint32& type, uint32& guid1, uint SendGeneralResponse(bot, chatChannelSource, messageRepy, name); } -bool ChatReplyAction::HandleThunderfuryReply(Player* bot, ChatChannelSource chatChannelSource, std::string& msg, std::string& name) +bool ChatReplyAction::HandleThunderfuryReply(Player* bot, ChatChannelSource chatChannelSource, std::string&, std::string&) { std::map placeholders; const auto thunderfury = sObjectMgr->GetItemTemplate(19019); placeholders["%thunderfury_link"] = GET_PLAYERBOT_AI(bot)->GetChatHelper()->FormatItem(thunderfury); - std::string responseMessage = BOT_TEXT2("thunderfury_spam", placeholders); + std::string responseMessage = PlayerbotTextMgr::instance().GetBotText("thunderfury_spam", placeholders); switch (chatChannelSource) { @@ -252,7 +249,7 @@ bool ChatReplyAction::HandleThunderfuryReply(Player* bot, ChatChannelSource chat return true; } -bool ChatReplyAction::HandleToxicLinksReply(Player* bot, ChatChannelSource chatChannelSource, std::string& msg, std::string& name) +bool ChatReplyAction::HandleToxicLinksReply(Player* bot, ChatChannelSource chatChannelSource, std::string&, std::string&) { //quests std::vector incompleteQuests; @@ -271,8 +268,8 @@ bool ChatReplyAction::HandleToxicLinksReply(Player* bot, ChatChannelSource chatC std::vector botItems = GET_PLAYERBOT_AI(bot)->GetInventoryAndEquippedItems(); std::map placeholders; - placeholders["%random_inventory_item_link"] = botItems.size() > 0 ? GET_PLAYERBOT_AI(bot)->GetChatHelper()->FormatItem(botItems[rand() % botItems.size()]->GetTemplate()) : BOT_TEXT1("string_empty_link"); - placeholders["%prefix"] = sPlayerbotAIConfig->toxicLinksPrefix; + placeholders["%random_inventory_item_link"] = botItems.size() > 0 ? GET_PLAYERBOT_AI(bot)->GetChatHelper()->FormatItem(botItems[rand() % botItems.size()]->GetTemplate()) : PlayerbotTextMgr::instance().GetBotText("string_empty_link"); + placeholders["%prefix"] = sPlayerbotAIConfig.toxicLinksPrefix; if (incompleteQuests.size() > 0) { @@ -287,8 +284,8 @@ bool ChatReplyAction::HandleToxicLinksReply(Player* bot, ChatChannelSource chatC placeholders["%my_role"] = ChatHelper::FormatClass(bot, AiFactory::GetPlayerSpecTab(bot)); AreaTableEntry const* current_area = GET_PLAYERBOT_AI(bot)->GetCurrentArea(); AreaTableEntry const* current_zone = GET_PLAYERBOT_AI(bot)->GetCurrentZone(); - placeholders["%area_name"] = current_area ? GET_PLAYERBOT_AI(bot)->GetLocalizedAreaName(current_area) : BOT_TEXT1("string_unknown_area"); - placeholders["%zone_name"] = current_zone ? GET_PLAYERBOT_AI(bot)->GetLocalizedAreaName(current_zone) : BOT_TEXT1("string_unknown_area"); + placeholders["%area_name"] = current_area ? GET_PLAYERBOT_AI(bot)->GetLocalizedAreaName(current_area) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); + placeholders["%zone_name"] = current_zone ? GET_PLAYERBOT_AI(bot)->GetLocalizedAreaName(current_zone) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); placeholders["%my_class"] = GET_PLAYERBOT_AI(bot)->GetChatHelper()->FormatClass(bot->getClass()); placeholders["%my_race"] = GET_PLAYERBOT_AI(bot)->GetChatHelper()->FormatRace(bot->getRace()); placeholders["%my_level"] = std::to_string(bot->GetLevel()); @@ -297,17 +294,17 @@ bool ChatReplyAction::HandleToxicLinksReply(Player* bot, ChatChannelSource chatC { case ChatChannelSource::SRC_WORLD: { - GET_PLAYERBOT_AI(bot)->SayToWorld(BOT_TEXT2("suggest_toxic_links", placeholders)); + GET_PLAYERBOT_AI(bot)->SayToWorld(PlayerbotTextMgr::instance().GetBotText("suggest_toxic_links", placeholders)); break; } case ChatChannelSource::SRC_GENERAL: { - GET_PLAYERBOT_AI(bot)->SayToChannel(BOT_TEXT2("suggest_toxic_links", placeholders), ChatChannelId::GENERAL); + GET_PLAYERBOT_AI(bot)->SayToChannel(PlayerbotTextMgr::instance().GetBotText("suggest_toxic_links", placeholders), ChatChannelId::GENERAL); break; } case ChatChannelSource::SRC_GUILD: { - GET_PLAYERBOT_AI(bot)->SayToGuild(BOT_TEXT2("suggest_toxic_links", placeholders)); + GET_PLAYERBOT_AI(bot)->SayToGuild(PlayerbotTextMgr::instance().GetBotText("suggest_toxic_links", placeholders)); break; } default: @@ -343,8 +340,8 @@ bool ChatReplyAction::HandleWTBItemsReply(Player* bot, ChatChannelSource chatCha placeholders["%other_name"] = name; AreaTableEntry const* current_area = GET_PLAYERBOT_AI(bot)->GetCurrentArea(); AreaTableEntry const* current_zone = GET_PLAYERBOT_AI(bot)->GetCurrentZone(); - placeholders["%area_name"] = current_area ? GET_PLAYERBOT_AI(bot)->GetLocalizedAreaName(current_area) : BOT_TEXT1("string_unknown_area"); - placeholders["%zone_name"] = current_zone ? GET_PLAYERBOT_AI(bot)->GetLocalizedAreaName(current_zone) : BOT_TEXT1("string_unknown_area"); + placeholders["%area_name"] = current_area ? GET_PLAYERBOT_AI(bot)->GetLocalizedAreaName(current_area) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); + placeholders["%zone_name"] = current_zone ? GET_PLAYERBOT_AI(bot)->GetLocalizedAreaName(current_zone) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); placeholders["%my_class"] = GET_PLAYERBOT_AI(bot)->GetChatHelper()->FormatClass(bot->getClass()); placeholders["%my_race"] = GET_PLAYERBOT_AI(bot)->GetChatHelper()->FormatRace(bot->getRace()); placeholders["%my_level"] = std::to_string(bot->GetLevel()); @@ -365,12 +362,12 @@ bool ChatReplyAction::HandleWTBItemsReply(Player* bot, ChatChannelSource chatCha //may reply to the same channel or whisper if (urand(0, 1)) { - std::string responseMessage = BOT_TEXT2("response_wtb_items_channel", placeholders); + std::string responseMessage = PlayerbotTextMgr::instance().GetBotText("response_wtb_items_channel", placeholders); GET_PLAYERBOT_AI(bot)->SayToWorld(responseMessage); } else { - std::string responseMessage = BOT_TEXT2("response_wtb_items_whisper", placeholders); + std::string responseMessage = PlayerbotTextMgr::instance().GetBotText("response_wtb_items_whisper", placeholders); GET_PLAYERBOT_AI(bot)->Whisper(responseMessage, name); } break; @@ -380,12 +377,12 @@ bool ChatReplyAction::HandleWTBItemsReply(Player* bot, ChatChannelSource chatCha //may reply to the same channel or whisper if (urand(0, 1)) { - std::string responseMessage = BOT_TEXT2("response_wtb_items_channel", placeholders); + std::string responseMessage = PlayerbotTextMgr::instance().GetBotText("response_wtb_items_channel", placeholders); GET_PLAYERBOT_AI(bot)->SayToChannel(responseMessage, ChatChannelId::GENERAL); } else { - std::string responseMessage = BOT_TEXT2("response_wtb_items_whisper", placeholders); + std::string responseMessage = PlayerbotTextMgr::instance().GetBotText("response_wtb_items_whisper", placeholders); GET_PLAYERBOT_AI(bot)->Whisper(responseMessage, name); } break; @@ -395,12 +392,12 @@ bool ChatReplyAction::HandleWTBItemsReply(Player* bot, ChatChannelSource chatCha //may reply to the same channel or whisper if (urand(0, 1)) { - std::string responseMessage = BOT_TEXT2("response_wtb_items_channel", placeholders); + std::string responseMessage = PlayerbotTextMgr::instance().GetBotText("response_wtb_items_channel", placeholders); GET_PLAYERBOT_AI(bot)->SayToChannel(responseMessage, ChatChannelId::TRADE); } else { - std::string responseMessage = BOT_TEXT2("response_wtb_items_whisper", placeholders); + std::string responseMessage = PlayerbotTextMgr::instance().GetBotText("response_wtb_items_whisper", placeholders); GET_PLAYERBOT_AI(bot)->Whisper(responseMessage, name); } break; @@ -438,8 +435,8 @@ bool ChatReplyAction::HandleLFGQuestsReply(Player* bot, ChatChannelSource chatCh placeholders["%other_name"] = name; AreaTableEntry const* current_area = GET_PLAYERBOT_AI(bot)->GetCurrentArea(); AreaTableEntry const* current_zone = GET_PLAYERBOT_AI(bot)->GetCurrentZone(); - placeholders["%area_name"] = current_area ? GET_PLAYERBOT_AI(bot)->GetLocalizedAreaName(current_area) : BOT_TEXT1("string_unknown_area"); - placeholders["%zone_name"] = current_zone ? GET_PLAYERBOT_AI(bot)->GetLocalizedAreaName(current_zone) : BOT_TEXT1("string_unknown_area"); + placeholders["%area_name"] = current_area ? GET_PLAYERBOT_AI(bot)->GetLocalizedAreaName(current_area) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); + placeholders["%zone_name"] = current_zone ? GET_PLAYERBOT_AI(bot)->GetLocalizedAreaName(current_zone) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); placeholders["%my_class"] = GET_PLAYERBOT_AI(bot)->GetChatHelper()->FormatClass(bot->getClass()); placeholders["%my_race"] = GET_PLAYERBOT_AI(bot)->GetChatHelper()->FormatRace(bot->getRace()); placeholders["%my_level"] = std::to_string(bot->GetLevel()); @@ -458,12 +455,12 @@ bool ChatReplyAction::HandleLFGQuestsReply(Player* bot, ChatChannelSource chatCh //may reply to the same channel or whisper if (urand(0, 1)) { - std::string responseMessage = BOT_TEXT2("response_lfg_quests_channel", placeholders); + std::string responseMessage = PlayerbotTextMgr::instance().GetBotText("response_lfg_quests_channel", placeholders); GET_PLAYERBOT_AI(bot)->SayToWorld(responseMessage); } else { - std::string responseMessage = BOT_TEXT2("response_lfg_quests_whisper", placeholders); + std::string responseMessage = PlayerbotTextMgr::instance().GetBotText("response_lfg_quests_whisper", placeholders); GET_PLAYERBOT_AI(bot)->Whisper(responseMessage, name); } break; @@ -473,12 +470,12 @@ bool ChatReplyAction::HandleLFGQuestsReply(Player* bot, ChatChannelSource chatCh //may reply to the same channel or whisper if (urand(0, 1)) { - std::string responseMessage = BOT_TEXT2("response_lfg_quests_channel", placeholders); + std::string responseMessage = PlayerbotTextMgr::instance().GetBotText("response_lfg_quests_channel", placeholders); GET_PLAYERBOT_AI(bot)->SayToChannel(responseMessage, ChatChannelId::GENERAL); } else { - std::string responseMessage = BOT_TEXT2("response_lfg_quests_whisper", placeholders); + std::string responseMessage = PlayerbotTextMgr::instance().GetBotText("response_lfg_quests_whisper", placeholders); GET_PLAYERBOT_AI(bot)->Whisper(responseMessage, name); } break; @@ -487,7 +484,7 @@ bool ChatReplyAction::HandleLFGQuestsReply(Player* bot, ChatChannelSource chatCh { //do not reply to the chat //may whisper - std::string responseMessage = BOT_TEXT2("response_lfg_quests_whisper", placeholders); + std::string responseMessage = PlayerbotTextMgr::instance().GetBotText("response_lfg_quests_whisper", placeholders); GET_PLAYERBOT_AI(bot)->Whisper(responseMessage, name); break; } @@ -1042,7 +1039,7 @@ std::string ChatReplyAction::GenerateReplyMessage(Player* bot, std::string& inco // load text if needed if (respondsText.empty()) { - respondsText = BOT_TEXT2(replyType, name); + respondsText = PlayerbotTextMgr::instance().GetBotText(replyType, name); } if (respondsText.size() > 255) diff --git a/src/Ai/Base/Actions/SayAction.h b/src/Ai/Base/Actions/SayAction.h index 5bf9a8f044..e8e266a9f9 100644 --- a/src/Ai/Base/Actions/SayAction.h +++ b/src/Ai/Base/Actions/SayAction.h @@ -29,7 +29,7 @@ class ChatReplyAction : public Action { public: ChatReplyAction(PlayerbotAI* ai) : Action(ai, "chat message") {} - virtual bool Execute(Event event) { return true; } + virtual bool Execute(Event) { return true; } bool isUseful() { return true; } static void ChatReplyDo(Player* bot, uint32& type, uint32& guid1, uint32& guid2, std::string& msg, std::string& chanName, std::string& name); @@ -40,4 +40,5 @@ class ChatReplyAction : public Action static bool SendGeneralResponse(Player* bot, ChatChannelSource chatChannelSource, std::string& responseMessage, std::string& name); static std::string GenerateReplyMessage(Player* bot, std::string& incomingMessage, uint32& guid1, std::string& name); }; + #endif diff --git a/src/Ai/Base/Actions/SecurityCheckAction.cpp b/src/Ai/Base/Actions/SecurityCheckAction.cpp index c47a6e52cb..a2c1cdf804 100644 --- a/src/Ai/Base/Actions/SecurityCheckAction.cpp +++ b/src/Ai/Base/Actions/SecurityCheckAction.cpp @@ -10,28 +10,47 @@ bool SecurityCheckAction::isUseful() { - return sRandomPlayerbotMgr->IsRandomBot(bot) && botAI->GetMaster() && - botAI->GetMaster()->GetSession()->GetSecurity() < SEC_GAMEMASTER && !GET_PLAYERBOT_AI(botAI->GetMaster()); -} + if (!RandomPlayerbotMgr::instance().IsRandomBot(this->bot)) + { + return false; + } -bool SecurityCheckAction::Execute(Event event) + Player* const master = this->botAI->GetMaster(); + + return master != nullptr + && master->GetSession()->GetSecurity() < SEC_GAMEMASTER + && !GET_PLAYERBOT_AI(master); +} +bool SecurityCheckAction::Execute(Event) { - if (Group* group = bot->GetGroup()) + const Group* const group = bot->GetGroup(); + + if (group == nullptr) + { + return false; + } + + const LootMethod method = group->GetLootMethod(); + const ItemQualities threshold = group->GetLootThreshold(); + + if (method != MASTER_LOOT && method != FREE_FOR_ALL && threshold <= ITEM_QUALITY_UNCOMMON) + { + return false; + } + + if (botAI->GetGroupLeader()->GetSession()->GetSecurity() != SEC_PLAYER) + { + return true; + } + + uint32_t guildId = this->bot->GetGuildId(); + + if (!guildId || guildId != botAI->GetGroupLeader()->GetGuildId()) { - LootMethod method = group->GetLootMethod(); - ItemQualities threshold = group->GetLootThreshold(); - if (method == MASTER_LOOT || method == FREE_FOR_ALL || threshold > ITEM_QUALITY_UNCOMMON) - { - if ((botAI->GetGroupLeader()->GetSession()->GetSecurity() == SEC_PLAYER) && - (!bot->GetGuildId() || bot->GetGuildId() != botAI->GetGroupLeader()->GetGuildId())) - { - botAI->TellError("I will play with this loot type only if I'm in your guild :/"); - botAI->ChangeStrategy("+passive,+stay", BOT_STATE_NON_COMBAT); - botAI->ChangeStrategy("+passive,+stay", BOT_STATE_COMBAT); - } - return true; - } + this->botAI->TellError("I will play with this loot type only if I'm in your guild :/"); + this->botAI->ChangeStrategy("+passive,+stay", BOT_STATE_NON_COMBAT); + this->botAI->ChangeStrategy("+passive,+stay", BOT_STATE_COMBAT); } - return false; + return true; } diff --git a/src/Ai/Base/Actions/SeeSpellAction.cpp b/src/Ai/Base/Actions/SeeSpellAction.cpp index 88848ca81f..b8d13974bf 100644 --- a/src/Ai/Base/Actions/SeeSpellAction.cpp +++ b/src/Ai/Base/Actions/SeeSpellAction.cpp @@ -7,7 +7,6 @@ #include "Event.h" #include "Formations.h" -#include "PathGenerator.h" #include "Playerbots.h" #include "RTSCValues.h" #include "RtscAction.h" @@ -16,11 +15,11 @@ std::set const FISHING_SPELLS = {7620, 7731, 7732, 18248, 33095, 51294}; -Creature* SeeSpellAction::CreateWps(Player* wpOwner, float x, float y, float z, float o, uint32 entry, Creature* lastWp, +Creature* SeeSpellAction::CreateWps(Player* wpOwner, float x, float y, float z, float o, uint32 entry, Creature*, bool important) { float dist = wpOwner->GetDistance(x, y, z); - float delay = 1000.0f * dist / wpOwner->GetSpeed(MOVE_RUN) + sPlayerbotAIConfig->reactDelay; + float delay = 1000.0f * dist / wpOwner->GetSpeed(MOVE_RUN) + sPlayerbotAIConfig.reactDelay; if (!important) delay *= 0.25; @@ -61,7 +60,7 @@ bool SeeSpellAction::Execute(Event event) if (FISHING_SPELLS.find(spellId) != FISHING_SPELLS.end()) { - if (AI_VALUE(bool, "can fish") && sPlayerbotAIConfig->enableFishingWithMaster) + if (AI_VALUE(bool, "can fish") && sPlayerbotAIConfig.enableFishingWithMaster) { botAI->ChangeStrategy("+master fishing", BOT_STATE_NON_COMBAT); return true; diff --git a/src/Ai/Base/Actions/SendMailAction.cpp b/src/Ai/Base/Actions/SendMailAction.cpp index c6184c4b98..9be9d553ab 100644 --- a/src/Ai/Base/Actions/SendMailAction.cpp +++ b/src/Ai/Base/Actions/SendMailAction.cpp @@ -14,7 +14,7 @@ bool SendMailAction::Execute(Event event) { uint32 account = bot->GetSession()->GetAccountId(); - bool randomBot = sPlayerbotAIConfig->IsInRandomAccountList(account); + bool randomBot = sPlayerbotAIConfig.IsInRandomAccountList(account); GuidVector gos = *context->GetValue("nearest game objects"); bool mailboxFound = false; diff --git a/src/Ai/Base/Actions/SetHomeAction.cpp b/src/Ai/Base/Actions/SetHomeAction.cpp index 44f3c7b49f..b7dff92054 100644 --- a/src/Ai/Base/Actions/SetHomeAction.cpp +++ b/src/Ai/Base/Actions/SetHomeAction.cpp @@ -8,7 +8,7 @@ #include "Event.h" #include "Playerbots.h" -bool SetHomeAction::Execute(Event event) +bool SetHomeAction::Execute(Event) { Player* master = GetMaster(); @@ -26,20 +26,10 @@ bool SetHomeAction::Execute(Event event) if (Unit* unit = botAI->GetUnit(selection)) if (unit->HasNpcFlag(UNIT_NPC_FLAG_INNKEEPER)) { - if (isRpgAction) - { - Creature* creature = botAI->GetCreature(selection); - bot->GetSession()->SendBindPoint(creature); - botAI->TellMaster("This inn is my new home"); - return true; - } - else - { - Creature* creature = botAI->GetCreature(selection); - bot->GetSession()->SendBindPoint(creature); - botAI->TellMaster("This inn is my new home"); - return true; - } + Creature* creature = botAI->GetCreature(selection); + bot->GetSession()->SendBindPoint(creature); + botAI->TellMaster("This inn is my new home"); + return true; } GuidVector npcs = AI_VALUE(GuidVector, "nearest npcs"); diff --git a/src/Ai/Base/Actions/ShareQuestAction.cpp b/src/Ai/Base/Actions/ShareQuestAction.cpp index d4b470b4c1..a778d33fb8 100644 --- a/src/Ai/Base/Actions/ShareQuestAction.cpp +++ b/src/Ai/Base/Actions/ShareQuestAction.cpp @@ -40,9 +40,8 @@ bool ShareQuestAction::Execute(Event event) return false; } -bool AutoShareQuestAction::Execute(Event event) +bool AutoShareQuestAction::Execute(Event) { - Player* requester = event.getOwner() ? event.getOwner() : GetMaster(); bool shared = false; for (uint8 slot = 0; slot < MAX_QUEST_LOG_SIZE; ++slot) @@ -109,4 +108,4 @@ bool AutoShareQuestAction::Execute(Event event) bool AutoShareQuestAction::isUseful() { return bot->GetGroup() && !botAI->HasActivePlayerMaster(); -} \ No newline at end of file +} diff --git a/src/Ai/Base/Actions/StatsAction.cpp b/src/Ai/Base/Actions/StatsAction.cpp index f6872c8468..caf367fb2e 100644 --- a/src/Ai/Base/Actions/StatsAction.cpp +++ b/src/Ai/Base/Actions/StatsAction.cpp @@ -7,9 +7,9 @@ #include "ChatHelper.h" #include "Event.h" -#include "Playerbots.h" +#include "PlayerbotAI.h" -bool StatsAction::Execute(Event event) +bool StatsAction::Execute(Event) { std::ostringstream out; diff --git a/src/Ai/Base/Actions/StayActions.cpp b/src/Ai/Base/Actions/StayActions.cpp index 525ff8d53e..94e4290ac5 100644 --- a/src/Ai/Base/Actions/StayActions.cpp +++ b/src/Ai/Base/Actions/StayActions.cpp @@ -19,7 +19,7 @@ bool StayActionBase::Stay() if (bot->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) return false; - uint32 sitDelay = sPlayerbotAIConfig->sitDelay / 1000; + uint32 sitDelay = sPlayerbotAIConfig.sitDelay / 1000; time_t stayTime = AI_VALUE(time_t, "stay time"); time_t now = time(nullptr); if (!stayTime) @@ -39,7 +39,7 @@ bool StayActionBase::Stay() return true; } -bool StayAction::Execute(Event event) { return Stay(); } +bool StayAction::Execute(Event) { return Stay(); } bool StayAction::isUseful() { @@ -47,8 +47,7 @@ bool StayAction::isUseful() PositionInfo stayPosition = AI_VALUE(PositionMap&, "position")["stay"]; if (stayPosition.isSet()) { - const float distance = bot->GetDistance(stayPosition.x, stayPosition.y, stayPosition.z); - if (sPlayerbotAIConfig->followDistance) + if (sPlayerbotAIConfig.followDistance) { return false; } @@ -64,7 +63,7 @@ bool StayAction::isUseful() return AI_VALUE2(bool, "moving", "self target"); } -bool SitAction::Execute(Event event) +bool SitAction::Execute(Event) { if (bot->isMoving()) return false; diff --git a/src/Ai/Base/Actions/SuggestWhatToDoAction.cpp b/src/Ai/Base/Actions/SuggestWhatToDoAction.cpp index 159bfd4ebb..b3324c3cac 100644 --- a/src/Ai/Base/Actions/SuggestWhatToDoAction.cpp +++ b/src/Ai/Base/Actions/SuggestWhatToDoAction.cpp @@ -7,25 +7,19 @@ #include "SuggestWhatToDoAction.h" #include "ServerFacade.h" -#include "ChannelMgr.h" #include "Event.h" #include "ItemVisitors.h" #include "AiFactory.h" #include "ChatHelper.h" #include "Playerbots.h" -#include "PlayerbotTextMgr.h" -#include "Config.h" #include "BroadcastHelper.h" #include "AiFactory.h" -#include "ChannelMgr.h" #include "ChatHelper.h" -#include "Config.h" #include "Event.h" -#include "GuildMgr.h" #include "ItemVisitors.h" -#include "PlayerbotTextMgr.h" #include "Playerbots.h" #include "ServerFacade.h" +#include "Channel.h" enum eTalkType { @@ -54,7 +48,7 @@ SuggestWhatToDoAction::SuggestWhatToDoAction(PlayerbotAI* botAI, std::string con bool SuggestWhatToDoAction::isUseful() { - if (!sRandomPlayerbotMgr->IsRandomBot(bot) || bot->GetGroup() || bot->GetInstanceId() || bot->GetBattleground()) + if (!sRandomPlayerbotMgr.IsRandomBot(bot) || bot->GetGroup() || bot->GetInstanceId() || bot->GetBattleground()) return false; std::string qualifier = "suggest what to do"; @@ -62,14 +56,13 @@ bool SuggestWhatToDoAction::isUseful() return (time(0) - lastSaid) > 30; } -bool SuggestWhatToDoAction::Execute(Event event) +bool SuggestWhatToDoAction::Execute(Event) { uint32 index = rand() % suggestions.size(); auto fnct_ptr = suggestions[index]; fnct_ptr(); std::string const qualifier = "suggest what to do"; - time_t lastSaid = AI_VALUE2(time_t, "last said", qualifier); botAI->GetAiObjectContext()->GetValue("last said", qualifier)->Set(time(nullptr) + urand(1, 60)); return true; @@ -140,7 +133,7 @@ void SuggestWhatToDoAction::grindMaterials() placeholders["%role"] = chat->formatClass(bot, AiFactory::GetPlayerSpecTab(bot)); placeholders["%category"] = item; - spam(BOT_TEXT2("suggest_trade", placeholders), urand(0, 1) ? 0x3C : 0x18, !urand(0, 2), !urand(0, + spam(PlayerbotTextMgr::instance().GetBotText("suggest_trade", placeholders), urand(0, 1) ? 0x3C : 0x18, !urand(0, 2), !urand(0, 3)); return; } } @@ -227,7 +220,7 @@ void SuggestWhatToDoAction::thunderfury() class FindTradeItemsVisitor : public IterateItemsVisitor { public: - FindTradeItemsVisitor(uint32 quality) : quality(quality), IterateItemsVisitor() {} + FindTradeItemsVisitor(uint32 quality) : IterateItemsVisitor(), quality(quality) {} bool Visit(Item* item) override { @@ -258,11 +251,11 @@ class FindTradeItemsVisitor : public IterateItemsVisitor SuggestDungeonAction::SuggestDungeonAction(PlayerbotAI* botAI) : SuggestWhatToDoAction(botAI, "suggest dungeon") {} -bool SuggestDungeonAction::Execute(Event event) +bool SuggestDungeonAction::Execute(Event) { - // TODO: use sPlayerbotDungeonRepository + // TODO: use PlayerbotDungeonRepository::instance() - if (!sPlayerbotAIConfig->randomBotSuggestDungeons || bot->GetGroup()) + if (!sPlayerbotAIConfig.randomBotSuggestDungeons || bot->GetGroup()) return false; if (instances.empty()) @@ -325,7 +318,7 @@ bool SuggestDungeonAction::Execute(Event event) SuggestTradeAction::SuggestTradeAction(PlayerbotAI* botAI) : SuggestWhatToDoAction(botAI, "suggest trade") {} -bool SuggestTradeAction::Execute(Event event) +bool SuggestTradeAction::Execute(Event) { uint32 quality = urand(0, 100); if (quality > 95) @@ -373,7 +366,7 @@ bool SuggestTradeAction::Execute(Event event) if (!proto) return false; - uint32 price = proto->SellPrice * sRandomPlayerbotMgr->GetSellMultiplier(bot) * count; + uint32 price = proto->SellPrice * sRandomPlayerbotMgr.GetSellMultiplier(bot) * count; if (!price) return false; diff --git a/src/Ai/Base/Actions/TalkToQuestGiverAction.cpp b/src/Ai/Base/Actions/TalkToQuestGiverAction.cpp index 7f791d0d63..35e8584b82 100644 --- a/src/Ai/Base/Actions/TalkToQuestGiverAction.cpp +++ b/src/Ai/Base/Actions/TalkToQuestGiverAction.cpp @@ -24,7 +24,7 @@ bool TalkToQuestGiverAction::ProcessQuest(Quest const* quest, Object* questGiver QuestStatus status = bot->GetQuestStatus(quest->GetQuestId()); Player* master = GetMaster(); - if (sPlayerbotAIConfig->syncQuestForPlayer && master) + if (sPlayerbotAIConfig.syncQuestForPlayer && master) { PlayerbotAI* masterBotAI = GET_PLAYERBOT_AI(master); if (!masterBotAI || masterBotAI->IsRealPlayer()) @@ -35,7 +35,7 @@ bool TalkToQuestGiverAction::ProcessQuest(Quest const* quest, Object* questGiver } } - if (sPlayerbotAIConfig->syncQuestWithPlayer) + if (sPlayerbotAIConfig.syncQuestWithPlayer) { if (master && master->GetQuestStatus(quest->GetQuestId()) == QUEST_STATUS_COMPLETE && (status == QUEST_STATUS_INCOMPLETE || status == QUEST_STATUS_FAILED)) @@ -105,14 +105,14 @@ void TalkToQuestGiverAction::RewardNoItem(Quest const* quest, Object* questGiver if (bot->CanRewardQuest(quest, false)) { - out << BOT_TEXT2("quest_status_completed", args); + out << PlayerbotTextMgr::instance().GetBotText("quest_status_completed", args); BroadcastHelper::BroadcastQuestTurnedIn(botAI, bot, quest); bot->RewardQuest(quest, 0, questGiver, false); } else { - out << BOT_TEXT2("quest_status_unable_to_complete", args); + out << PlayerbotTextMgr::instance().GetBotText("quest_status_unable_to_complete", args); } } @@ -126,13 +126,13 @@ void TalkToQuestGiverAction::RewardSingleItem(Quest const* quest, Object* questG if (bot->CanRewardQuest(quest, index, false)) { - out << BOT_TEXT2("quest_status_complete_single_reward", args); + out << PlayerbotTextMgr::instance().GetBotText("quest_status_complete_single_reward", args); BroadcastHelper::BroadcastQuestTurnedIn(botAI, bot, quest); bot->RewardQuest(quest, index, questGiver, true); } else { - out << BOT_TEXT2("quest_status_unable_to_complete", args); + out << PlayerbotTextMgr::instance().GetBotText("quest_status_unable_to_complete", args); } } @@ -171,7 +171,7 @@ void TalkToQuestGiverAction::RewardMultipleItem(Quest const* quest, Object* ques std::set bestIds; std::ostringstream outid; - if (!botAI->IsAlt() || sPlayerbotAIConfig->autoPickReward == "yes") + if (!botAI->IsAlt() || sPlayerbotAIConfig.autoPickReward == "yes") { bestIds = BestRewards(quest); if (!bestIds.empty()) @@ -198,7 +198,7 @@ void TalkToQuestGiverAction::RewardMultipleItem(Quest const* quest, Object* ques AskToSelectReward(quest, out, true); } } - else if (sPlayerbotAIConfig->autoPickReward == "no") + else if (sPlayerbotAIConfig.autoPickReward == "no") { // Old functionality, list rewards. AskToSelectReward(quest, out, false); @@ -231,7 +231,6 @@ void TalkToQuestGiverAction::AskToSelectReward(Quest const* quest, std::ostrings for (uint8 i = 0; i < quest->GetRewChoiceItemsCount(); ++i) { ItemTemplate const* item = sObjectMgr->GetItemTemplate(quest->RewardChoiceItemId[i]); - ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", quest->RewardChoiceItemId[i]); if (!forEquip || BestRewards(quest).count(i) > 0) { @@ -248,7 +247,6 @@ bool TurnInQueryQuestAction::Execute(Event event) WorldPacket pakcet = event.getPacket(); ObjectGuid guid; uint32 questId; - ObjectGuid unk1; pakcet >> guid >> questId; Object* object = ObjectAccessor::GetObjectByTypeMask(*bot, guid, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT | TYPEMASK_ITEM); @@ -260,7 +258,7 @@ bool TurnInQueryQuestAction::Execute(Event event) QuestStatus status = bot->GetQuestStatus(quest->GetQuestId()); Player* master = GetMaster(); - if (sPlayerbotAIConfig->syncQuestForPlayer && master) + if (sPlayerbotAIConfig.syncQuestForPlayer && master) { PlayerbotAI* masterBotAI = GET_PLAYERBOT_AI(master); if (!masterBotAI || masterBotAI->IsRealPlayer()) @@ -271,7 +269,7 @@ bool TurnInQueryQuestAction::Execute(Event event) } } - if (sPlayerbotAIConfig->syncQuestWithPlayer) + if (sPlayerbotAIConfig.syncQuestWithPlayer) { if (status == QUEST_STATUS_INCOMPLETE || status == QUEST_STATUS_FAILED) { diff --git a/src/Ai/Base/Actions/TameAction.cpp b/src/Ai/Base/Actions/TameAction.cpp index 5b3eda1034..b19626e594 100644 --- a/src/Ai/Base/Actions/TameAction.cpp +++ b/src/Ai/Base/Actions/TameAction.cpp @@ -6,12 +6,10 @@ #include "TameAction.h" #include #include -#include #include #include #include #include "DBCStructure.h" -#include "Log.h" #include "ObjectMgr.h" #include "Pet.h" #include "Player.h" @@ -53,7 +51,6 @@ bool TameAction::Execute(Event event) { std::set normalFamilies; std::set exoticFamilies; - Player* bot = botAI->GetBot(); // Loop over all creature templates and collect tameable families CreatureTemplateContainer const* creatures = sObjectMgr->GetCreatureTemplates(); diff --git a/src/Ai/Base/Actions/TeleportAction.cpp b/src/Ai/Base/Actions/TeleportAction.cpp index 65aa24e09f..65a76b12d7 100644 --- a/src/Ai/Base/Actions/TeleportAction.cpp +++ b/src/Ai/Base/Actions/TeleportAction.cpp @@ -7,9 +7,12 @@ #include "Event.h" #include "LastMovementValue.h" -#include "Playerbots.h" +#include "AiObjectContext.h" +#include "PlayerbotAI.h" +#include "SpellMgr.h" +#include "Spell.h" -bool TeleportAction::Execute(Event event) +bool TeleportAction::Execute(Event) { /* // List of allowed portal entries (you can populate this dynamically) @@ -74,7 +77,7 @@ bool TeleportAction::Execute(Event event) continue; uint32 spellId = goInfo->spellcaster.spellId; - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); + SpellInfo const* spellInfo = SpellMgr::instance()->GetSpellInfo(spellId); if (!spellInfo || !spellInfo->HasEffect(SPELL_EFFECT_TELEPORT_UNITS)) continue; diff --git a/src/Ai/Base/Actions/TellLosAction.cpp b/src/Ai/Base/Actions/TellLosAction.cpp index 9cd12b02e3..a839f03240 100644 --- a/src/Ai/Base/Actions/TellLosAction.cpp +++ b/src/Ai/Base/Actions/TellLosAction.cpp @@ -4,11 +4,10 @@ */ #include "TellLosAction.h" -#include #include #include "ChatHelper.h" -#include "DBCStores.h" +#include "DynamicObject.h" #include "Event.h" #include "ItemTemplate.h" #include "ObjectMgr.h" @@ -77,7 +76,7 @@ void TellLosAction::ListGameObjects(std::string const title, GuidVector gos) } } -bool TellAuraAction::Execute(Event event) +bool TellAuraAction::Execute(Event) { botAI->TellMaster("--- Auras ---"); sLog->outMessage("playerbot", LOG_LEVEL_DEBUG, "--- Auras ---"); @@ -97,7 +96,6 @@ bool TellAuraAction::Execute(Event event) std::string caster_name = caster ? caster->GetName() : "unknown"; bool is_area = aura->IsArea(); int32 duration = aura->GetDuration(); - const SpellInfo* spellInfo = aura->GetSpellInfo(); int32 spellId = aura->GetSpellInfo()->Id; bool isPositive = aura->GetSpellInfo()->IsPositive(); sLog->outMessage("playerbot", LOG_LEVEL_DEBUG, @@ -130,7 +128,7 @@ bool TellAuraAction::Execute(Event event) return true; } -bool TellEstimatedDpsAction::Execute(Event event) +bool TellEstimatedDpsAction::Execute(Event) { float dps = AI_VALUE(float, "estimated group dps"); botAI->TellMaster("Estimated Group DPS: " + std::to_string(dps)); diff --git a/src/Ai/Base/Actions/TellMasterAction.cpp b/src/Ai/Base/Actions/TellMasterAction.cpp index 4b8d96d561..1da66554db 100644 --- a/src/Ai/Base/Actions/TellMasterAction.cpp +++ b/src/Ai/Base/Actions/TellMasterAction.cpp @@ -8,13 +8,13 @@ #include "Event.h" #include "Playerbots.h" -bool TellMasterAction::Execute(Event event) +bool TellMasterAction::Execute(Event) { botAI->TellMaster(text); return true; } -bool OutOfReactRangeAction::Execute(Event event) +bool OutOfReactRangeAction::Execute(Event) { botAI->TellMaster("Wait for me!"); return true; diff --git a/src/Ai/Base/Actions/TellMasterAction.h b/src/Ai/Base/Actions/TellMasterAction.h index 5a8821206a..380174cd9f 100644 --- a/src/Ai/Base/Actions/TellMasterAction.h +++ b/src/Ai/Base/Actions/TellMasterAction.h @@ -30,4 +30,18 @@ class OutOfReactRangeAction : public MovementAction bool isUseful() override; }; +class TellMasterNotEnoughMoneyAction : public TellMasterAction +{ +public: + TellMasterNotEnoughMoneyAction(PlayerbotAI* botAI) : TellMasterAction(botAI, "Not enough money") {} + ~TellMasterNotEnoughMoneyAction() override = default; +}; + +class TellMasterNotEnoughReputationAction : public TellMasterAction +{ +public: + TellMasterNotEnoughReputationAction(PlayerbotAI* botAI) : TellMasterAction(botAI, "Not enough reputation") {} + ~TellMasterNotEnoughReputationAction() override = default; +}; + #endif diff --git a/src/Ai/Base/Actions/TellPvpStatsAction.h b/src/Ai/Base/Actions/TellPvpStatsAction.h new file mode 100644 index 0000000000..8c9e21e8ae --- /dev/null +++ b/src/Ai/Base/Actions/TellPvpStatsAction.h @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#pragma once + +#include "ArenaTeam.h" +#include "ArenaTeamMgr.h" + +#include "Action.h" +#include "PlayerbotAI.h" + +class TellPvpStatsAction : public Action +{ +public: + TellPvpStatsAction(PlayerbotAI* botAI) : Action(botAI, "tell pvp stats") {} + + bool Execute(Event event) override + { + if (this->bot == nullptr) + { + return false; + } + + Player* requester = this->GetMaster(); + Unit* const eventOwner = event.getOwner(); + + if (eventOwner != nullptr) + { + requester = eventOwner->ToPlayer(); + } + + if (requester == nullptr) + { + return false; + } + + // PVP currencies + std::map currencyPlaceholders; + + currencyPlaceholders["%arena_points"] = std::to_string(this->bot->GetArenaPoints()); + currencyPlaceholders["%honor_points"] = std::to_string(this->bot->GetHonorPoints()); + + const std::string currencyText = PlayerbotTextMgr::instance().GetBotTextOrDefault( + "pvp_currency", + "[PVP] Arena points: %arena_points | Honor Points: %honor_points", + currencyPlaceholders); + + this->bot->Whisper(currencyText, LANG_UNIVERSAL, requester); + + // Arena Teams by slot + bool hasArenaTeam = false; + + for (uint8_t slot = 0; slot < MAX_ARENA_SLOT; ++slot) + { + const uint32_t teamId = this->bot->GetArenaTeamId(slot); + + if (teamId == 0) + { + continue; + } + + const ArenaTeam* const team = ArenaTeamMgr::instance()->GetArenaTeamById(teamId); + + if (team == nullptr) + { + continue; + } + + hasArenaTeam = true; + + std::map placeholders; + + placeholders["%bracket"] = this->MapBracketToString(slot); + placeholders["%team_name"] = team->GetName(); + placeholders["%team_rating"] = std::to_string(team->GetRating()); + + const std::string teamText = PlayerbotTextMgr::instance().GetBotTextOrDefault( + "pvp_arena_team", + "[PVP] %bracket: <%team_name> (rating %team_rating)", + placeholders + ); + + this->bot->Whisper(teamText, LANG_UNIVERSAL, requester); + } + + if (!hasArenaTeam) + { + const std::string noTeamText = PlayerbotTextMgr::instance().GetBotTextOrDefault( + "pvp_no_arena_team", + "[PVP] I have no Arena Team.", + std::map() + ); + + this->bot->Whisper(noTeamText, LANG_UNIVERSAL, requester); + } + + return true; + } + +private: + static std::string_view MapBracketToString(const uint8_t slot) noexcept + { + switch (slot) + { + case ARENA_SLOT_2v2: + return "2v2"; + case ARENA_SLOT_3v3: + return "3v3"; + case ARENA_SLOT_5v5: + return "5v5"; + default: + return ""; + } + } +}; diff --git a/src/Ai/Base/Actions/TellReputationAction.cpp b/src/Ai/Base/Actions/TellReputationAction.cpp index e08a38d840..050a2457a5 100644 --- a/src/Ai/Base/Actions/TellReputationAction.cpp +++ b/src/Ai/Base/Actions/TellReputationAction.cpp @@ -6,10 +6,10 @@ #include "TellReputationAction.h" #include "Event.h" -#include "Playerbots.h" #include "ReputationMgr.h" +#include "PlayerbotAI.h" -bool TellReputationAction::Execute(Event event) +bool TellReputationAction::Execute(Event) { Player* master = GetMaster(); if (!master) diff --git a/src/Ai/Base/Actions/TellTargetAction.cpp b/src/Ai/Base/Actions/TellTargetAction.cpp index 7ecd8efb5a..8830618996 100644 --- a/src/Ai/Base/Actions/TellTargetAction.cpp +++ b/src/Ai/Base/Actions/TellTargetAction.cpp @@ -6,10 +6,11 @@ #include "TellTargetAction.h" #include "Event.h" -#include "Playerbots.h" #include "ThreatMgr.h" +#include "AiObjectContext.h" +#include "PlayerbotAI.h" -bool TellTargetAction::Execute(Event event) +bool TellTargetAction::Execute(Event) { Unit* target = context->GetValue("current target")->Get(); if (target) @@ -24,7 +25,7 @@ bool TellTargetAction::Execute(Event event) return true; } -bool TellAttackersAction::Execute(Event event) +bool TellAttackersAction::Execute(Event) { botAI->TellMaster("--- Attackers ---"); diff --git a/src/Ai/Base/Actions/TradeAction.cpp b/src/Ai/Base/Actions/TradeAction.cpp index ad81d9f93b..84faae89f4 100644 --- a/src/Ai/Base/Actions/TradeAction.cpp +++ b/src/Ai/Base/Actions/TradeAction.cpp @@ -8,14 +8,14 @@ #include "Event.h" #include "ItemCountValue.h" #include "ItemVisitors.h" -#include "Playerbots.h" +#include "PlayerbotAI.h" bool TradeAction::Execute(Event event) { std::string const text = event.getParam(); // If text starts with any excluded prefix, don't process it further. - for (auto const& prefix : sPlayerbotAIConfig->tradeActionExcludedPrefixes) + for (auto const& prefix : sPlayerbotAIConfig.tradeActionExcludedPrefixes) { if (text.find(prefix) == 0) return false; @@ -56,7 +56,18 @@ bool TradeAction::Execute(Event event) } size_t pos = text.rfind(" "); - int count = pos != std::string::npos ? atoi(text.substr(pos + 1).c_str()) : 1; + + uint32_t count = 1; + + if (pos != std::string::npos) + { + const int32_t possibleValue = atoi(text.substr(pos + 1).c_str()); + + if (possibleValue > 0) + { + count = possibleValue; + } + } std::vector found = parseItems(text); if (found.empty()) diff --git a/src/Ai/Base/Actions/TradeStatusAction.cpp b/src/Ai/Base/Actions/TradeStatusAction.cpp index 16ad2ca79d..72ddb87109 100644 --- a/src/Ai/Base/Actions/TradeStatusAction.cpp +++ b/src/Ai/Base/Actions/TradeStatusAction.cpp @@ -32,7 +32,7 @@ bool TradeStatusAction::Execute(Event event) return false; } - if (sPlayerbotAIConfig->enableRandomBotTrading == 0 && (sRandomPlayerbotMgr->IsRandomBot(bot)|| sRandomPlayerbotMgr->IsAddclassBot(bot))) + if (sPlayerbotAIConfig.enableRandomBotTrading == 0 && (sRandomPlayerbotMgr.IsRandomBot(bot)|| sRandomPlayerbotMgr.IsAddclassBot(bot))) { bot->Whisper("Trading is disabled", LANG_UNIVERSAL, trader); return false; @@ -61,11 +61,9 @@ bool TradeStatusAction::Execute(Event event) uint32 status = 0; p << status; - uint32 discount = sRandomPlayerbotMgr->GetTradeDiscount(bot, trader); + uint32 discount = sRandomPlayerbotMgr.GetTradeDiscount(bot, trader); if (CheckTrade()) { - int32 botMoney = CalculateCost(bot, true); - std::map givenItemIds, takenItemIds; for (uint32 slot = 0; slot < TRADE_SLOT_TRADED_COUNT; ++slot) { @@ -81,7 +79,7 @@ bool TradeStatusAction::Execute(Event event) bot->GetSession()->HandleAcceptTradeOpcode(p); if (bot->GetTradeData()) { - sRandomPlayerbotMgr->SetTradeDiscount(bot, trader, discount); + sRandomPlayerbotMgr.SetTradeDiscount(bot, trader, discount); return false; } @@ -96,7 +94,7 @@ bool TradeStatusAction::Execute(Event event) craftData.AddObtained(itemId, count); } - sGuildTaskMgr->CheckItemTask(itemId, count, trader, bot); + GuildTaskMgr::instance().CheckItemTask(itemId, count, trader, bot); } for (std::map::iterator i = takenItemIds.begin(); i != takenItemIds.end(); ++i) @@ -116,7 +114,7 @@ bool TradeStatusAction::Execute(Event event) } else if (status == TRADE_STATUS_BEGIN_TRADE) { - if (!bot->HasInArc(CAST_ANGLE_IN_FRONT, trader, sPlayerbotAIConfig->sightDistance)) + if (!bot->HasInArc(CAST_ANGLE_IN_FRONT, trader, sPlayerbotAIConfig.sightDistance)) bot->SetFacingToObject(trader); BeginTrade(); @@ -141,9 +139,9 @@ void TradeStatusAction::BeginTrade() botAI->TellMaster("=== Inventory ==="); TellItems(visitor.items, visitor.soulbound); - if (sRandomPlayerbotMgr->IsRandomBot(bot)) + if (sRandomPlayerbotMgr.IsRandomBot(bot)) { - uint32 discount = sRandomPlayerbotMgr->GetTradeDiscount(bot, botAI->GetMaster()); + uint32 discount = sRandomPlayerbotMgr.GetTradeDiscount(bot, botAI->GetMaster()); if (discount) { std::ostringstream out; @@ -161,13 +159,11 @@ bool TradeStatusAction::CheckTrade() if (!botAI->HasActivePlayerMaster() && GET_PLAYERBOT_AI(bot->GetTrader())) { - bool isGivingItem = false; for (uint32 slot = 0; slot < TRADE_SLOT_TRADED_COUNT; ++slot) { Item* item = bot->GetTradeData()->GetItem((TradeSlots)slot); if (item) { - isGivingItem = true; break; } } @@ -198,7 +194,7 @@ bool TradeStatusAction::CheckTrade() return false; } uint32 accountId = bot->GetSession()->GetAccountId(); - if (!sPlayerbotAIConfig->IsInRandomAccountList(accountId)) + if (!sPlayerbotAIConfig.IsInRandomAccountList(accountId)) { int32 botItemsMoney = CalculateCost(bot, true); int32 botMoney = bot->GetTradeData()->GetMoney() + botItemsMoney; @@ -214,12 +210,12 @@ bool TradeStatusAction::CheckTrade() int32 botMoney = bot->GetTradeData()->GetMoney() + botItemsMoney; int32 playerItemsMoney = CalculateCost(trader, false); int32 playerMoney = trader->GetTradeData()->GetMoney() + playerItemsMoney; - if (botItemsMoney > 0 && sPlayerbotAIConfig->enableRandomBotTrading == 2 && (sRandomPlayerbotMgr->IsRandomBot(bot)|| sRandomPlayerbotMgr->IsAddclassBot(bot))) + if (botItemsMoney > 0 && sPlayerbotAIConfig.enableRandomBotTrading == 2 && (sRandomPlayerbotMgr.IsRandomBot(bot)|| sRandomPlayerbotMgr.IsAddclassBot(bot))) { bot->Whisper("Selling is disabled.", LANG_UNIVERSAL, trader); return false; } - if (playerItemsMoney && sPlayerbotAIConfig->enableRandomBotTrading == 3 && (sRandomPlayerbotMgr->IsRandomBot(bot)|| sRandomPlayerbotMgr->IsAddclassBot(bot))) + if (playerItemsMoney && sPlayerbotAIConfig.enableRandomBotTrading == 3 && (sRandomPlayerbotMgr.IsRandomBot(bot)|| sRandomPlayerbotMgr.IsAddclassBot(bot))) { bot->Whisper("Buying is disabled.", LANG_UNIVERSAL, trader); return false; @@ -262,7 +258,7 @@ bool TradeStatusAction::CheckTrade() return false; } - int32 discount = (int32)sRandomPlayerbotMgr->GetTradeDiscount(bot, trader); + int32 discount = (int32)sRandomPlayerbotMgr.GetTradeDiscount(bot, trader); int32 delta = playerMoney - botMoney; int32 moneyDelta = (int32)trader->GetTradeData()->GetMoney() - (int32)bot->GetTradeData()->GetMoney(); bool success = false; @@ -287,7 +283,7 @@ bool TradeStatusAction::CheckTrade() if (success) { - sRandomPlayerbotMgr->AddTradeDiscount(bot, trader, delta); + sRandomPlayerbotMgr.AddTradeDiscount(bot, trader, delta); switch (urand(0, 4)) { case 0: @@ -353,11 +349,11 @@ int32 TradeStatusAction::CalculateCost(Player* player, bool sell) if (sell) { - sum += item->GetCount() * proto->SellPrice * sRandomPlayerbotMgr->GetSellMultiplier(bot); + sum += item->GetCount() * proto->SellPrice * sRandomPlayerbotMgr.GetSellMultiplier(bot); } else { - sum += item->GetCount() * proto->BuyPrice * sRandomPlayerbotMgr->GetBuyMultiplier(bot); + sum += item->GetCount() * proto->BuyPrice * sRandomPlayerbotMgr.GetBuyMultiplier(bot); } } diff --git a/src/Ai/Base/Actions/TradeStatusExtendedAction.cpp b/src/Ai/Base/Actions/TradeStatusExtendedAction.cpp index ada779e36d..88a53b2ac1 100644 --- a/src/Ai/Base/Actions/TradeStatusExtendedAction.cpp +++ b/src/Ai/Base/Actions/TradeStatusExtendedAction.cpp @@ -1,7 +1,9 @@ #include "TradeStatusExtendedAction.h" +#include "CreateNextAction.h" #include "Event.h" #include "Player.h" #include "PlayerbotAI.h" +#include "UnlockTradedItemAction.h" #include "WorldPacket.h" #include "TradeData.h" @@ -70,7 +72,7 @@ bool TradeStatusExtendedAction::Execute(Event event) if (bot->getClass() == CLASS_ROGUE && bot->HasSpell(1804) && lockbox->IsLocked()) // Pick Lock spell { // botAI->CastSpell(1804, bot, lockbox); // Attempt to cast Pick Lock on the lockbox - botAI->DoSpecificAction("unlock traded item"); + botAI->DoSpecificAction(CreateNextAction(1.0f).factory); botAI->SetNextCheckDelay(4000); // Delay before accepting trade } else diff --git a/src/Ai/Base/Actions/TrainerAction.cpp b/src/Ai/Base/Actions/TrainerAction.cpp index bca7406012..0155da5789 100644 --- a/src/Ai/Base/Actions/TrainerAction.cpp +++ b/src/Ai/Base/Actions/TrainerAction.cpp @@ -12,7 +12,7 @@ void TrainerAction::Learn(uint32 cost, const Trainer::Spell tSpell, std::ostringstream& msg) { - if (sPlayerbotAIConfig->autoTrainSpells != "free" && !botAI->HasCheat(BotCheatMask::gold)) + if (sPlayerbotAIConfig.autoTrainSpells != "free" && !botAI->HasCheat(BotCheatMask::gold)) { if (AI_VALUE2(uint32, "free money for", (uint32)NeedMoneyFor::spells) < cost) { @@ -126,8 +126,8 @@ bool TrainerAction::Execute(Event event) if (spell) spells.insert(spell); - if (text.find("learn") != std::string::npos || sRandomPlayerbotMgr->IsRandomBot(bot) || - (sPlayerbotAIConfig->autoTrainSpells != "no" && + if (text.find("learn") != std::string::npos || sRandomPlayerbotMgr.IsRandomBot(bot) || + (sPlayerbotAIConfig.autoTrainSpells != "no" && (trainer->GetTrainerType() != Trainer::Type::Tradeskill || !botAI->HasActivePlayerMaster()))) // Todo rewrite to only exclude start primary profession skills and make // config dependent. @@ -155,9 +155,9 @@ void TrainerAction::TellFooter(uint32 totalCost) } } -bool MaintenanceAction::Execute(Event event) +bool MaintenanceAction::Execute(Event) { - if (!sPlayerbotAIConfig->maintenanceCommand) + if (!sPlayerbotAIConfig.maintenanceCommand) { botAI->TellError("maintenance command is not allowed, please check the configuration."); return false; @@ -186,66 +186,66 @@ bool MaintenanceAction::Execute(Event event) factory.InitMounts(); factory.InitGlyphs(false); factory.InitKeyring(); - if (bot->GetLevel() >= sPlayerbotAIConfig->minEnchantingBotLevel) + if (bot->GetLevel() >= sPlayerbotAIConfig.minEnchantingBotLevel) factory.ApplyEnchantAndGemsNew(); } else { - if (sPlayerbotAIConfig->altMaintenanceAttunementQs) + if (sPlayerbotAIConfig.altMaintenanceAttunementQs) factory.InitAttunementQuests(); - if (sPlayerbotAIConfig->altMaintenanceBags) + if (sPlayerbotAIConfig.altMaintenanceBags) factory.InitBags(false); - if (sPlayerbotAIConfig->altMaintenanceAmmo) + if (sPlayerbotAIConfig.altMaintenanceAmmo) factory.InitAmmo(); - if (sPlayerbotAIConfig->altMaintenanceFood) + if (sPlayerbotAIConfig.altMaintenanceFood) factory.InitFood(); - if (sPlayerbotAIConfig->altMaintenanceReagents) + if (sPlayerbotAIConfig.altMaintenanceReagents) factory.InitReagents(); - if (sPlayerbotAIConfig->altMaintenanceConsumables) + if (sPlayerbotAIConfig.altMaintenanceConsumables) factory.InitConsumables(); - if (sPlayerbotAIConfig->altMaintenancePotions) + if (sPlayerbotAIConfig.altMaintenancePotions) factory.InitPotions(); - if (sPlayerbotAIConfig->altMaintenanceTalentTree) + if (sPlayerbotAIConfig.altMaintenanceTalentTree) factory.InitTalentsTree(true); - if (sPlayerbotAIConfig->altMaintenancePet) + if (sPlayerbotAIConfig.altMaintenancePet) factory.InitPet(); - if (sPlayerbotAIConfig->altMaintenancePetTalents) + if (sPlayerbotAIConfig.altMaintenancePetTalents) factory.InitPetTalents(); - if (sPlayerbotAIConfig->altMaintenanceSkills) + if (sPlayerbotAIConfig.altMaintenanceSkills) factory.InitSkills(); - if (sPlayerbotAIConfig->altMaintenanceClassSpells) + if (sPlayerbotAIConfig.altMaintenanceClassSpells) factory.InitClassSpells(); - if (sPlayerbotAIConfig->altMaintenanceAvailableSpells) + if (sPlayerbotAIConfig.altMaintenanceAvailableSpells) factory.InitAvailableSpells(); - if (sPlayerbotAIConfig->altMaintenanceReputation) + if (sPlayerbotAIConfig.altMaintenanceReputation) factory.InitReputation(); - if (sPlayerbotAIConfig->altMaintenanceSpecialSpells) + if (sPlayerbotAIConfig.altMaintenanceSpecialSpells) factory.InitSpecialSpells(); - if (sPlayerbotAIConfig->altMaintenanceMounts) + if (sPlayerbotAIConfig.altMaintenanceMounts) factory.InitMounts(); - if (sPlayerbotAIConfig->altMaintenanceGlyphs) + if (sPlayerbotAIConfig.altMaintenanceGlyphs) factory.InitGlyphs(false); - if (sPlayerbotAIConfig->altMaintenanceKeyring) + if (sPlayerbotAIConfig.altMaintenanceKeyring) factory.InitKeyring(); - if (sPlayerbotAIConfig->altMaintenanceGemsEnchants && bot->GetLevel() >= sPlayerbotAIConfig->minEnchantingBotLevel) + if (sPlayerbotAIConfig.altMaintenanceGemsEnchants && bot->GetLevel() >= sPlayerbotAIConfig.minEnchantingBotLevel) factory.ApplyEnchantAndGemsNew(); } @@ -255,7 +255,7 @@ bool MaintenanceAction::Execute(Event event) return true; } -bool RemoveGlyphAction::Execute(Event event) +bool RemoveGlyphAction::Execute(Event) { for (uint32 slotIndex = 0; slotIndex < MAX_GLYPH_SLOT_INDEX; ++slotIndex) { @@ -265,30 +265,30 @@ bool RemoveGlyphAction::Execute(Event event) return true; } -bool AutoGearAction::Execute(Event event) +bool AutoGearAction::Execute(Event) { - if (!sPlayerbotAIConfig->autoGearCommand) + if (!sPlayerbotAIConfig.autoGearCommand) { botAI->TellError("autogear command is not allowed, please check the configuration."); return false; } - if (!sPlayerbotAIConfig->autoGearCommandAltBots && - !sPlayerbotAIConfig->IsInRandomAccountList(bot->GetSession()->GetAccountId())) + if (!sPlayerbotAIConfig.autoGearCommandAltBots && + !sPlayerbotAIConfig.IsInRandomAccountList(bot->GetSession()->GetAccountId())) { botAI->TellError("You cannot use autogear on alt bots."); return false; } botAI->TellMaster("I'm auto gearing"); - uint32 gs = sPlayerbotAIConfig->autoGearScoreLimit == 0 + uint32 gs = sPlayerbotAIConfig.autoGearScoreLimit == 0 ? 0 - : PlayerbotFactory::CalcMixedGearScore(sPlayerbotAIConfig->autoGearScoreLimit, - sPlayerbotAIConfig->autoGearQualityLimit); - PlayerbotFactory factory(bot, bot->GetLevel(), sPlayerbotAIConfig->autoGearQualityLimit, gs); + : PlayerbotFactory::CalcMixedGearScore(sPlayerbotAIConfig.autoGearScoreLimit, + sPlayerbotAIConfig.autoGearQualityLimit); + PlayerbotFactory factory(bot, bot->GetLevel(), sPlayerbotAIConfig.autoGearQualityLimit, gs); factory.InitEquipment(true); factory.InitAmmo(); - if (bot->GetLevel() >= sPlayerbotAIConfig->minEnchantingBotLevel) + if (bot->GetLevel() >= sPlayerbotAIConfig.minEnchantingBotLevel) { factory.ApplyEnchantAndGemsNew(); } diff --git a/src/Ai/Base/Actions/TravelAction.cpp b/src/Ai/Base/Actions/TravelAction.cpp index a290605718..5c5dfa27b5 100644 --- a/src/Ai/Base/Actions/TravelAction.cpp +++ b/src/Ai/Base/Actions/TravelAction.cpp @@ -5,12 +5,15 @@ #include "TravelAction.h" -#include "CellImpl.h" +#include "AreaTriggerAction.h" +#include "CreateNextAction.h" #include "GridNotifiers.h" -#include "GridNotifiersImpl.h" #include "Playerbots.h" +// Required due to a poor implementation by AC +#include "CellImpl.h" +#include "GridNotifiersImpl.h" -bool TravelAction::Execute(Event event) +bool TravelAction::Execute(Event) { TravelTarget* target = AI_VALUE(TravelTarget*, "travel target"); @@ -21,9 +24,9 @@ bool TravelAction::Execute(Event event) Unit* newTarget = nullptr; std::list targets; - Acore::AnyUnitInObjectRangeCheck u_check(bot, sPlayerbotAIConfig->sightDistance * 2); + Acore::AnyUnitInObjectRangeCheck u_check(bot, sPlayerbotAIConfig.sightDistance * 2); Acore::UnitListSearcher searcher(bot, targets, u_check); - Cell::VisitObjects(bot, searcher, sPlayerbotAIConfig->sightDistance); + Cell::VisitObjects(bot, searcher, sPlayerbotAIConfig.sightDistance); for (Unit* unit : targets) { @@ -37,7 +40,9 @@ bool TravelAction::Execute(Event event) if (!newTarget->IsAlive()) continue; - if (newTarget->GetEntry() == target->getDestination()->getEntry()) + const int64_t newTargetEntry = newTarget->GetEntry(); + + if (newTargetEntry == target->getDestination()->getEntry()) continue; if (newTarget->IsInCombat()) @@ -60,7 +65,7 @@ bool TravelAction::isUseful() (!AI_VALUE(GuidPosition, "rpg target") || !AI_VALUE(ObjectGuid, "pull target")); } -bool MoveToDarkPortalAction::Execute(Event event) +bool MoveToDarkPortalAction::Execute(Event) { if (bot->GetGroup()) if (bot->GetGroup()->GetLeaderGUID() != bot->GetGUID() && @@ -77,7 +82,7 @@ bool MoveToDarkPortalAction::Execute(Event event) if (bot->GetTeamId() == TEAM_ALLIANCE) { Quest const* quest = sObjectMgr->GetQuestTemplate(10119); - CreatureData const* creatureData = sRandomPlayerbotMgr->GetCreatureDataByEntry(16841); + CreatureData const* creatureData = sRandomPlayerbotMgr.GetCreatureDataByEntry(16841); if (quest && creatureData) { auto creatureBounds = @@ -89,7 +94,7 @@ bool MoveToDarkPortalAction::Execute(Event event) else { Quest const* quest = sObjectMgr->GetQuestTemplate(9407); - CreatureData const* creatureData = sRandomPlayerbotMgr->GetCreatureDataByEntry(19254); + CreatureData const* creatureData = sRandomPlayerbotMgr.GetCreatureDataByEntry(19254); if (quest && creatureData) { auto creatureBounds = @@ -111,14 +116,14 @@ bool MoveToDarkPortalAction::Execute(Event event) bool MoveToDarkPortalAction::isUseful() { return bot->GetLevel() > 54; } -bool DarkPortalAzerothAction::Execute(Event event) +bool DarkPortalAzerothAction::Execute(Event) { if (bot->GetLevel() > 57) { WorldPacket packet(CMSG_AREATRIGGER); packet << 4354; - return GET_PLAYERBOT_AI(bot)->DoSpecificAction("reach area trigger", Event("travel action", packet)); + return this->botAI->DoSpecificAction(CreateNextAction(1.0f).factory, Event("travel action", packet)); } return false; @@ -126,14 +131,14 @@ bool DarkPortalAzerothAction::Execute(Event event) bool DarkPortalAzerothAction::isUseful() { return bot->GetLevel() > 57; } -bool MoveFromDarkPortalAction::Execute(Event event) +bool MoveFromDarkPortalAction::Execute(Event) { RESET_AI_VALUE(GuidPosition, "rpg target"); if (bot->GetTeamId() == TEAM_ALLIANCE) + { return MoveTo(530, -319.261f, 1027.213, 54.172638f, false, true); - else - return MoveTo(530, -180.444f, 1027.947, 54.181538f, false, true); + } - return false; + return MoveTo(530, -180.444f, 1027.947, 54.181538f, false, true); } diff --git a/src/Ai/Base/Actions/UnlockItemAction.cpp b/src/Ai/Base/Actions/UnlockItemAction.cpp index 367a4fcbfb..0e869e72c6 100644 --- a/src/Ai/Base/Actions/UnlockItemAction.cpp +++ b/src/Ai/Base/Actions/UnlockItemAction.cpp @@ -1,38 +1,39 @@ #include "UnlockItemAction.h" #include "PlayerbotAI.h" #include "ItemTemplate.h" -#include "WorldPacket.h" #include "Player.h" #include "ObjectMgr.h" #include "SpellInfo.h" -#define PICK_LOCK_SPELL_ID 1804 +inline constexpr uint32_t PICK_LOCK_SPELL_ID = 1804; -bool UnlockItemAction::Execute(Event event) +bool UnlockItemAction::Execute(Event) { - bool foundLockedItem = false; + Item* const item = botAI->FindLockedItem(); - Item* item = botAI->FindLockedItem(); - if (item) + if (item == nullptr) { - UnlockItem(item); - foundLockedItem = true; + return false; } - return foundLockedItem; + this->UnlockItem(item); + + return true; } void UnlockItemAction::UnlockItem(Item* item) { // Use CastSpell to unlock the item - if (botAI->CastSpell(PICK_LOCK_SPELL_ID, bot, item)) + const bool unlocked = this->botAI->CastSpell(PICK_LOCK_SPELL_ID, bot, item); + + if (unlocked) { std::ostringstream out; out << "Used Pick Lock on: " << item->GetTemplate()->Name1; - botAI->TellMaster(out.str()); - } - else - { - botAI->TellError("Failed to cast Pick Lock."); + this->botAI->TellMaster(out.str()); + + return; } + + this->botAI->TellError("Failed to cast Pick Lock."); } diff --git a/src/Ai/Base/Actions/UnlockTradedItemAction.cpp b/src/Ai/Base/Actions/UnlockTradedItemAction.cpp index 047cd2e201..fbc527c7a5 100644 --- a/src/Ai/Base/Actions/UnlockTradedItemAction.cpp +++ b/src/Ai/Base/Actions/UnlockTradedItemAction.cpp @@ -1,11 +1,11 @@ #include "UnlockTradedItemAction.h" -#include "Playerbots.h" +#include "PlayerbotAI.h" #include "TradeData.h" #include "SpellInfo.h" -#define PICK_LOCK_SPELL_ID 1804 +inline constexpr uint32_t PICK_LOCK_SPELL_ID = 1804; -bool UnlockTradedItemAction::Execute(Event event) +bool UnlockTradedItemAction::Execute(Event) { Player* trader = bot->GetTrader(); if (!trader) diff --git a/src/Ai/Base/Actions/UseItemAction.cpp b/src/Ai/Base/Actions/UseItemAction.cpp index bfb86ef0bd..a0052c1272 100644 --- a/src/Ai/Base/Actions/UseItemAction.cpp +++ b/src/Ai/Base/Actions/UseItemAction.cpp @@ -69,7 +69,6 @@ bool UseItemAction::UseItem(Item* item, ObjectGuid goGuid, Item* itemTarget, Uni uint8 bagIndex = item->GetBagSlot(); uint8 slot = item->GetSlot(); - uint8 spell_index = 0; uint8 cast_count = 1; ObjectGuid item_guid = item->GetGUID(); uint32 glyphIndex = 0; @@ -187,7 +186,7 @@ bool UseItemAction::UseItem(Item* item, ObjectGuid goGuid, Item* itemTarget, Uni if (bot->isMoving()) { bot->StopMoving(); - botAI->SetNextCheckDelay(sPlayerbotAIConfig->globalCoolDown); + botAI->SetNextCheckDelay(sPlayerbotAIConfig.globalCoolDown); return false; } @@ -229,7 +228,7 @@ bool UseItemAction::UseItem(Item* item, ObjectGuid goGuid, Item* itemTarget, Uni out << " on " << chat->FormatItem(itemForSpell->GetTemplate()); } uint32 castTime = spellInfo->CalcCastTime(); - botAI->SetNextCheckDelay(castTime + sPlayerbotAIConfig->reactDelay); + botAI->SetNextCheckDelay(castTime + sPlayerbotAIConfig.reactDelay); } break; @@ -307,7 +306,7 @@ bool UseItemAction::UseItem(Item* item, ObjectGuid goGuid, Item* itemTarget, Uni if (!spellId) return false; - // botAI->SetNextCheckDelay(sPlayerbotAIConfig->globalCoolDown); + // botAI->SetNextCheckDelay(sPlayerbotAIConfig.globalCoolDown); botAI->TellMasterNoFacing(out.str()); bot->GetSession()->HandleUseItemOpcode(packet); return true; @@ -392,6 +391,8 @@ bool UseSpellItemAction::isUseful() { return AI_VALUE2(bool, "spell cast useful" bool UseHealingPotion::isUseful() { return AI_VALUE2(bool, "combat", "self target"); } +bool UseHealthstone::isUseful() { return AI_VALUE2(bool, "combat", "self target"); } + bool UseManaPotion::isUseful() { return AI_VALUE2(bool, "combat", "self target"); } bool UseHearthStone::Execute(Event event) @@ -423,7 +424,7 @@ bool UseRandomRecipe::isUseful() bool UseRandomRecipe::isPossible() { return AI_VALUE2(uint32, "item count", "recipe") > 0; } -bool UseRandomRecipe::Execute(Event event) +bool UseRandomRecipe::Execute(Event) { std::vector recipes = AI_VALUE2(std::vector, "inventory items", "recipe"); @@ -452,7 +453,7 @@ bool UseRandomQuestItem::isUseful() bool UseRandomQuestItem::isPossible() { return AI_VALUE2(uint32, "item count", "quest") > 0; } -bool UseRandomQuestItem::Execute(Event event) +bool UseRandomQuestItem::Execute(Event) { Unit* unitTarget = nullptr; ObjectGuid goTarget; @@ -486,7 +487,7 @@ bool UseRandomQuestItem::Execute(Event event) bool used = UseItem(item, goTarget, nullptr, unitTarget); if (used) - botAI->SetNextCheckDelay(sPlayerbotAIConfig->globalCoolDown); + botAI->SetNextCheckDelay(sPlayerbotAIConfig.globalCoolDown); return used; } diff --git a/src/Ai/Base/Actions/UseItemAction.h b/src/Ai/Base/Actions/UseItemAction.h index 2b0c7e1911..83e23fb3f6 100644 --- a/src/Ai/Base/Actions/UseItemAction.h +++ b/src/Ai/Base/Actions/UseItemAction.h @@ -56,6 +56,14 @@ class UseHealingPotion : public UseItemAction bool isUseful() override; }; +class UseHealthstone : public UseItemAction +{ +public: + UseHealthstone(PlayerbotAI* botAI) : UseItemAction(botAI, "healthstone") {} + + bool isUseful() override; +}; + class UseManaPotion : public UseItemAction { public: diff --git a/src/Ai/Base/Actions/UseMeetingStoneAction.cpp b/src/Ai/Base/Actions/UseMeetingStoneAction.cpp index 323d9d5859..a676b0cf28 100644 --- a/src/Ai/Base/Actions/UseMeetingStoneAction.cpp +++ b/src/Ai/Base/Actions/UseMeetingStoneAction.cpp @@ -5,14 +5,15 @@ #include "UseMeetingStoneAction.h" -#include "CellImpl.h" #include "Event.h" #include "GridNotifiers.h" -#include "GridNotifiersImpl.h" #include "NearestGameObjects.h" #include "PlayerbotAIConfig.h" #include "Playerbots.h" #include "PositionValue.h" +// Required because of a poor implementation by AC +#include "GridNotifiersImpl.h" +#include "CellImpl.h" bool UseMeetingStoneAction::Execute(Event event) { @@ -55,13 +56,13 @@ bool UseMeetingStoneAction::Execute(Event event) return Teleport(master, bot, false); } -bool SummonAction::Execute(Event event) +bool SummonAction::Execute(Event) { Player* master = GetMaster(); if (!master) return false; - if (Pet* pet = bot->GetPet()) + if (bot->GetPet() != nullptr) { botAI->PetFollow(); } @@ -91,9 +92,9 @@ bool SummonAction::Execute(Event event) bool SummonAction::SummonUsingGos(Player* summoner, Player* player, bool preserveAuras) { std::list targets; - AnyGameObjectInObjectRangeCheck u_check(summoner, sPlayerbotAIConfig->sightDistance); + AnyGameObjectInObjectRangeCheck u_check(summoner, sPlayerbotAIConfig.sightDistance); Acore::GameObjectListSearcher searcher(summoner, targets, u_check); - Cell::VisitObjects(summoner, searcher, sPlayerbotAIConfig->sightDistance); + Cell::VisitObjects(summoner, searcher, sPlayerbotAIConfig.sightDistance); for (GameObject* go : targets) { @@ -107,13 +108,13 @@ bool SummonAction::SummonUsingGos(Player* summoner, Player* player, bool preserv bool SummonAction::SummonUsingNpcs(Player* summoner, Player* player, bool preserveAuras) { - if (!sPlayerbotAIConfig->summonAtInnkeepersEnabled) + if (!sPlayerbotAIConfig.summonAtInnkeepersEnabled) return false; std::list targets; - Acore::AnyUnitInObjectRangeCheck u_check(summoner, sPlayerbotAIConfig->sightDistance); + Acore::AnyUnitInObjectRangeCheck u_check(summoner, sPlayerbotAIConfig.sightDistance); Acore::UnitListSearcher searcher(summoner, targets, u_check); - Cell::VisitObjects(summoner, searcher, sPlayerbotAIConfig->sightDistance); + Cell::VisitObjects(summoner, searcher, sPlayerbotAIConfig.sightDistance); for (Unit* unit : targets) { @@ -150,7 +151,7 @@ bool SummonAction::SummonUsingNpcs(Player* summoner, Player* player, bool preser bool SummonAction::Teleport(Player* summoner, Player* player, bool preserveAuras) { // Player* master = GetMaster(); - if (!summoner) + if (!summoner || summoner == player) return false; if (player->GetVehicle()) @@ -165,38 +166,37 @@ bool SummonAction::Teleport(Player* summoner, Player* player, bool preserveAuras for (float angle = followAngle - M_PI; angle <= followAngle + M_PI; angle += M_PI / 4) { uint32 mapId = summoner->GetMapId(); - float x = summoner->GetPositionX() + cos(angle) * sPlayerbotAIConfig->followDistance; - float y = summoner->GetPositionY() + sin(angle) * sPlayerbotAIConfig->followDistance; + float x = summoner->GetPositionX() + cos(angle) * sPlayerbotAIConfig.followDistance; + float y = summoner->GetPositionY() + sin(angle) * sPlayerbotAIConfig.followDistance; float z = summoner->GetPositionZ(); if (summoner->IsWithinLOS(x, y, z)) { - if (sPlayerbotAIConfig - ->botRepairWhenSummon) // .conf option to repair bot gear when summoned 0 = off, 1 = on + if (sPlayerbotAIConfig.botRepairWhenSummon) // .conf option to repair bot gear when summoned 0 = off, 1 = on bot->DurabilityRepairAll(false, 1.0f, false); - if (summoner->IsInCombat() && !sPlayerbotAIConfig->allowSummonInCombat) + if (summoner->IsInCombat() && !sPlayerbotAIConfig.allowSummonInCombat) { botAI->TellError("You cannot summon me while you're in combat"); return false; } - if (!summoner->IsAlive() && !sPlayerbotAIConfig->allowSummonWhenMasterIsDead) + if (!summoner->IsAlive() && !sPlayerbotAIConfig.allowSummonWhenMasterIsDead) { botAI->TellError("You cannot summon me while you're dead"); return false; } if (bot->isDead() && !bot->HasPlayerFlag(PLAYER_FLAGS_GHOST) && - !sPlayerbotAIConfig->allowSummonWhenBotIsDead) + !sPlayerbotAIConfig.allowSummonWhenBotIsDead) { botAI->TellError("You cannot summon me while I'm dead, you need to release my spirit first"); return false; } bool revive = - sPlayerbotAIConfig->reviveBotWhenSummoned == 2 || - (sPlayerbotAIConfig->reviveBotWhenSummoned == 1 && !summoner->IsInCombat() && summoner->IsAlive()); + sPlayerbotAIConfig.reviveBotWhenSummoned == 2 || + (sPlayerbotAIConfig.reviveBotWhenSummoned == 1 && !summoner->IsInCombat() && summoner->IsAlive()); if (bot->isDead() && revive) { @@ -212,9 +212,11 @@ bool SummonAction::Teleport(Player* summoner, Player* player, bool preserveAuras if (!preserveAuras) player->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TELEPORTED | AURA_INTERRUPT_FLAG_CHANGE_MAP); - player->TeleportTo(mapId, x, y, z, 0); - + if (player->GetPet()) + player->GetPet()->NearTeleportTo(x, y, z, player->GetOrientation()); + if (player->GetGuardianPet()) + player->GetGuardianPet()->NearTeleportTo(x, y, z, player->GetOrientation()); if (botAI->HasStrategy("stay", botAI->GetState())) { PositionMap& posMap = AI_VALUE(PositionMap&, "position"); diff --git a/src/Ai/Base/Actions/VehicleActions.cpp b/src/Ai/Base/Actions/VehicleActions.cpp index ee1c6e2dd8..f5a43f899c 100644 --- a/src/Ai/Base/Actions/VehicleActions.cpp +++ b/src/Ai/Base/Actions/VehicleActions.cpp @@ -74,7 +74,7 @@ bool EnterVehicleAction::Execute(Event event) bool EnterVehicleAction::EnterVehicle(Unit* vehicleBase, bool moveIfFar) { - float dist = sServerFacade->GetDistance2d(bot, vehicleBase); + float dist = ServerFacade::instance().GetDistance2d(bot, vehicleBase); if (dist > 40.0f) return false; @@ -95,7 +95,7 @@ bool EnterVehicleAction::EnterVehicle(Unit* vehicleBase, bool moveIfFar) return true; } -bool LeaveVehicleAction::Execute(Event event) +bool LeaveVehicleAction::Execute(Event) { Vehicle* myVehicle = bot->GetVehicle(); if (!myVehicle) diff --git a/src/Ai/Base/Actions/WhoAction.cpp b/src/Ai/Base/Actions/WhoAction.cpp index edafdfcb27..1cc325038f 100644 --- a/src/Ai/Base/Actions/WhoAction.cpp +++ b/src/Ai/Base/Actions/WhoAction.cpp @@ -33,7 +33,7 @@ bool WhoAction::Execute(Event event) { out << QuerySkill(text); - if (sRandomPlayerbotMgr->IsRandomBot(bot)) + if (sRandomPlayerbotMgr.IsRandomBot(bot)) out << QueryTrade(text); } else @@ -74,7 +74,7 @@ std::string const WhoAction::QueryTrade(std::string const text) for (Item* sell : items) { int32 sellPrice = - sell->GetTemplate()->SellPrice * sRandomPlayerbotMgr->GetSellMultiplier(bot) * sell->GetCount(); + sell->GetTemplate()->SellPrice * sRandomPlayerbotMgr.GetSellMultiplier(bot) * sell->GetCount(); if (!sellPrice) continue; @@ -108,7 +108,7 @@ std::string const WhoAction::QuerySkill(std::string const text) return out.str(); } -std::string const WhoAction::QuerySpec(std::string const text) +std::string const WhoAction::QuerySpec(std::string) { std::ostringstream out; diff --git a/src/Ai/Base/Actions/WipeAction.cpp b/src/Ai/Base/Actions/WipeAction.cpp index bbd1997d6c..7101b9f2c0 100644 --- a/src/Ai/Base/Actions/WipeAction.cpp +++ b/src/Ai/Base/Actions/WipeAction.cpp @@ -8,11 +8,15 @@ bool WipeAction::Execute(Event event) { - Player* master = event.getOwner(); + const Player* const owner = event.getOwner(); + const Player* const master = this->botAI->GetMaster(); - if (botAI->GetMaster()->GetGUID() != event.getOwner()->GetGUID()) + if (owner != nullptr && master != nullptr && master->GetGUID() != owner->GetGUID()) + { return false; + } + + this->bot->Kill(this->bot, this->bot); - bot->Kill(bot, bot); return true; } diff --git a/src/Ai/Base/Actions/WorldBuffAction.cpp b/src/Ai/Base/Actions/WorldBuffAction.cpp index 3cd770e4d0..b2bf4e096f 100644 --- a/src/Ai/Base/Actions/WorldBuffAction.cpp +++ b/src/Ai/Base/Actions/WorldBuffAction.cpp @@ -25,7 +25,7 @@ std::vector WorldBuffAction::NeedWorldBuffs(Unit* unit) { std::vector retVec; - if (sPlayerbotAIConfig->worldBuffs.empty()) + if (sPlayerbotAIConfig.worldBuffs.empty()) return retVec; FactionTemplateEntry const* humanFaction = sFactionTemplateStore.LookupEntry(1); @@ -70,7 +70,7 @@ std::vector WorldBuffAction::NeedWorldBuffs(Unit* unit) // If tank, effectiveSpec remains unchanged } - for (auto const& wb : sPlayerbotAIConfig->worldBuffs) + for (auto const& wb : sPlayerbotAIConfig.worldBuffs) { // Faction check if (wb.factionId != 0 && wb.factionId != factionId) diff --git a/src/Ai/Base/Actions/WtsAction.cpp b/src/Ai/Base/Actions/WtsAction.cpp index a3c77c27f9..950ab7d05f 100644 --- a/src/Ai/Base/Actions/WtsAction.cpp +++ b/src/Ai/Base/Actions/WtsAction.cpp @@ -20,7 +20,7 @@ bool WtsAction::Execute(Event event) std::ostringstream out; std::string const text = event.getParam(); - if (!sRandomPlayerbotMgr->IsRandomBot(bot)) + if (!sRandomPlayerbotMgr.IsRandomBot(bot)) return false; std::string const link = event.getParam(); @@ -42,7 +42,7 @@ bool WtsAction::Execute(Event event) if (usage == ITEM_USAGE_NONE) continue; - int32 buyPrice = proto->BuyPrice * sRandomPlayerbotMgr->GetBuyMultiplier(bot); + int32 buyPrice = proto->BuyPrice * sRandomPlayerbotMgr.GetBuyMultiplier(bot); if (!buyPrice) continue; diff --git a/src/Ai/Base/Actions/XpGainAction.cpp b/src/Ai/Base/Actions/XpGainAction.cpp index 4048ce3af8..fba57180f2 100644 --- a/src/Ai/Base/Actions/XpGainAction.cpp +++ b/src/Ai/Base/Actions/XpGainAction.cpp @@ -40,14 +40,14 @@ bool XpGainAction::Execute(Event event) } // randomBotXPRate is now implemented in OnPlayerGiveXP script - // if (!sRandomPlayerbotMgr->IsRandomBot(bot) || sPlayerbotAIConfig->randomBotXPRate == 1) + // if (!sRandomPlayerbotMgr.IsRandomBot(bot) || sPlayerbotAIConfig.randomBotXPRate == 1) // return true; // Unit* victim = nullptr; // if (guid) // victim = botAI->GetUnit(guid); - // xpgain = xpgain * (sPlayerbotAIConfig->randomBotXPRate - 1); + // xpgain = xpgain * (sPlayerbotAIConfig.randomBotXPRate - 1); // GiveXP(xpgain, victim); return true; diff --git a/src/Ai/Base/Actions/combat/UniversalTauntAction.h b/src/Ai/Base/Actions/combat/UniversalTauntAction.h new file mode 100644 index 0000000000..21c35e565f --- /dev/null +++ b/src/Ai/Base/Actions/combat/UniversalTauntAction.h @@ -0,0 +1,71 @@ +#pragma once + +#include "CreateNextAction.h" +#include "GenericSpellActions.h" +#include "AiFactory.h" +#include "DKActions.h" +#include "PaladinActions.h" +#include "WarriorActions.h" +#include "DruidBearActions.h" + +class UniversalTauntAction : public Action +{ +public: + UniversalTauntAction(PlayerbotAI* botAI) : Action(botAI) {} + + bool isPossible() override + { + const uint8_t tab = AiFactory::GetPlayerSpecTab(this->bot); + + switch (this->bot->getClass()) + { + case CLASS_DEATH_KNIGHT: + return tab == DEATH_KNIGHT_TAB_BLOOD; + case CLASS_PALADIN: + return tab == PALADIN_TAB_PROTECTION; + case CLASS_DRUID: + return tab == DRUID_TAB_FERAL; + case CLASS_WARRIOR: + return tab == WARRIOR_TAB_PROTECTION; + } + + return false; + } + + bool isUseful() override + { + const Unit* const target = this->GetTarget(); + + if (target == nullptr) + { + return false; + } + + const ObjectGuid targetTargetGUID = target->GetTarget(); + + if (targetTargetGUID == this->bot->GetGUID()) + { + return false; + } + + return true; + } + + bool Execute(Event) override + { + switch (this->bot->getClass()) + { + case CLASS_DEATH_KNIGHT: + return this->botAI->DoSpecificAction(CreateNextAction(ACTION_EMERGENCY).factory); + case CLASS_PALADIN: + return this->botAI->DoSpecificAction(CreateNextAction(ACTION_EMERGENCY).factory); + case CLASS_DRUID: + return this->botAI->DoSpecificAction(CreateNextAction(ACTION_EMERGENCY).factory); + case CLASS_WARRIOR: + return this->botAI->DoSpecificAction(CreateNextAction(ACTION_EMERGENCY).factory); + } + + return false; + } + +}; diff --git a/src/Ai/Base/ChatActionContext.h b/src/Ai/Base/ChatActionContext.h index 4873f52005..de29e7dd20 100644 --- a/src/Ai/Base/ChatActionContext.h +++ b/src/Ai/Base/ChatActionContext.h @@ -38,6 +38,7 @@ #include "LootStrategyAction.h" #include "LootRollAction.h" #include "MailAction.h" +#include "ManageInventoryAction.h" #include "NamedObjectContext.h" #include "NewRpgAction.h" #include "PassLeadershipToMasterAction.h" @@ -67,6 +68,7 @@ #include "TellItemCountAction.h" #include "TellLosAction.h" #include "TellReputationAction.h" +#include "TellPvpStatsAction.h" #include "TellTargetAction.h" #include "TradeAction.h" #include "TrainerAction.h" @@ -94,9 +96,13 @@ class ChatActionContext : public NamedObjectContext creators["unlock traded item"] = &ChatActionContext::unlock_traded_item; creators["range"] = &ChatActionContext::range; creators["stats"] = &ChatActionContext::stats; + + creators["manage inventory"] = &ChatActionContext::manage_inventory; + creators["quests"] = &ChatActionContext::quests; creators["leave"] = &ChatActionContext::leave; creators["reputation"] = &ChatActionContext::reputation; + creators["tell pvp stats"] = &ChatActionContext::tell_pvp_stats; creators["log"] = &ChatActionContext::log; creators["los"] = &ChatActionContext::los; creators["rpg status"] = &ChatActionContext::rpg_status; @@ -276,9 +282,13 @@ class ChatActionContext : public NamedObjectContext static Action* clean_quest_log(PlayerbotAI* botAI) { return new CleanQuestLogAction(botAI); } static Action* share(PlayerbotAI* botAI) { return new ShareQuestAction(botAI); } static Action* stats(PlayerbotAI* botAI) { return new StatsAction(botAI); } + + static Action* manage_inventory(PlayerbotAI* botAI) { return new ManageInventoryAction(botAI); } + static Action* quests(PlayerbotAI* botAI) { return new ListQuestsAction(botAI); } static Action* leave(PlayerbotAI* botAI) { return new LeaveGroupAction(botAI); } static Action* reputation(PlayerbotAI* botAI) { return new TellReputationAction(botAI); } + static Action* tell_pvp_stats(PlayerbotAI* botAI) { return new TellPvpStatsAction(botAI); } static Action* log(PlayerbotAI* botAI) { return new LogLevelAction(botAI); } static Action* los(PlayerbotAI* botAI) { return new TellLosAction(botAI); } static Action* rpg_status(PlayerbotAI* botAI) { return new TellRpgStatusAction(botAI); } diff --git a/src/Ai/Base/ChatTriggerContext.h b/src/Ai/Base/ChatTriggerContext.h index b3498ce301..aaaca896d5 100644 --- a/src/Ai/Base/ChatTriggerContext.h +++ b/src/Ai/Base/ChatTriggerContext.h @@ -24,6 +24,7 @@ class ChatTriggerContext : public NamedObjectContext creators["leave"] = &ChatTriggerContext::leave; creators["rep"] = &ChatTriggerContext::reputation; creators["reputation"] = &ChatTriggerContext::reputation; + creators["pvp stats"] = &ChatTriggerContext::pvp_stats; creators["log"] = &ChatTriggerContext::log; creators["los"] = &ChatTriggerContext::los; creators["rpg status"] = &ChatTriggerContext::rpg_status; @@ -138,6 +139,7 @@ class ChatTriggerContext : public NamedObjectContext creators["pet"] = &ChatTriggerContext::pet; creators["pet attack"] = &ChatTriggerContext::pet_attack; creators["roll"] = &ChatTriggerContext::roll_action; + creators["manage inventory"] = &ChatTriggerContext::manage_inventory; } private: @@ -224,6 +226,7 @@ class ChatTriggerContext : public NamedObjectContext static Trigger* stats(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "stats"); } static Trigger* leave(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "leave"); } static Trigger* reputation(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "reputation"); } + static Trigger* pvp_stats(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "pvp stats"); } static Trigger* log(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "log"); } static Trigger* los(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "los"); } static Trigger* rpg_status(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "rpg status"); } @@ -255,6 +258,7 @@ class ChatTriggerContext : public NamedObjectContext static Trigger* pet(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "pet"); } static Trigger* pet_attack(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "pet attack"); } static Trigger* roll_action(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "roll"); } + static Trigger* manage_inventory(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "manage inventory"); } }; #endif diff --git a/src/Ai/Base/CreateAction.h b/src/Ai/Base/CreateAction.h new file mode 100644 index 0000000000..be7f10e87e --- /dev/null +++ b/src/Ai/Base/CreateAction.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include + +#include "Action.h" +#include "ActionFactoryRegistry.h" +#include "RegisterActionFactoryOnce.h" + +template +std::unique_ptr CreateAction(PlayerbotAI* botAI) +{ + static_assert(std::is_base_of::value == true, "TAction must derive from Action."); + + RegisterActionFactoryOnce(botAI); + + return std::unique_ptr(new TAction(botAI)); +} diff --git a/src/Ai/Base/CreateNextAction.h b/src/Ai/Base/CreateNextAction.h new file mode 100644 index 0000000000..3b71eeaac5 --- /dev/null +++ b/src/Ai/Base/CreateNextAction.h @@ -0,0 +1,10 @@ +#pragma once + +#include "NextAction.h" +#include "CreateAction.h" + +template +NextAction CreateNextAction(float weight) +{ + return NextAction{ weight, &CreateAction }; +} diff --git a/src/Ai/Base/RegisterActionFactoryOnce.h b/src/Ai/Base/RegisterActionFactoryOnce.h new file mode 100644 index 0000000000..b3472c3183 --- /dev/null +++ b/src/Ai/Base/RegisterActionFactoryOnce.h @@ -0,0 +1,41 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "Action.h" +#include "ActionFactoryRegistry.h" + +class Action; +class PlayerbotAI; + +template +std::unique_ptr CreateAction(PlayerbotAI* const botAI); + +template +void RegisterActionFactoryOnce(PlayerbotAI* const botAI) +{ + static_assert(std::is_base_of::value == true); + + static std::once_flag flag; + + std::call_once( + flag, + [botAI]() + { + assert(botAI != nullptr); + + ActionFactoryRegistry::RegisterByType(std::type_index(typeid(TAction)), &CreateAction); + + std::unique_ptr probe = std::unique_ptr(new TAction(botAI)); + + const std::string& name = probe->getName(); + + ActionFactoryRegistry::RegisterByName(name, &CreateAction); + } + ); +} diff --git a/src/Ai/Base/SharedValueContext.h b/src/Ai/Base/SharedValueContext.h index 23b8266bdd..0ac35ab1b2 100644 --- a/src/Ai/Base/SharedValueContext.h +++ b/src/Ai/Base/SharedValueContext.h @@ -8,43 +8,18 @@ #include "LootValues.h" #include "NamedObjectContext.h" -#include "Playerbots.h" +#include "PlayerbotAI.h" #include "PvpValues.h" #include "QuestValues.h" -class PlayerbotAI; - class SharedValueContext : public NamedObjectContext { public: - SharedValueContext() : NamedObjectContext(true) - { - creators["bg masters"] = &SharedValueContext::bg_masters; - creators["drop map"] = &SharedValueContext::drop_map; - creators["item drop list"] = &SharedValueContext::item_drop_list; - creators["entry loot list"] = &SharedValueContext::entry_loot_list; - - creators["entry quest relation"] = &SharedValueContext::entry_quest_relation; - creators["quest guidp map"] = &SharedValueContext::quest_guidp_map; - creators["quest givers"] = &SharedValueContext::quest_givers; - } - -private: - static UntypedValue* bg_masters(PlayerbotAI* botAI) { return new BgMastersValue(botAI); } - static UntypedValue* drop_map(PlayerbotAI* botAI) { return new DropMapValue(botAI); } - static UntypedValue* item_drop_list(PlayerbotAI* botAI) { return new ItemDropListValue(botAI); } - static UntypedValue* entry_loot_list(PlayerbotAI* botAI) { return new EntryLootListValue(botAI); } - - static UntypedValue* entry_quest_relation(PlayerbotAI* botAI) { return new EntryQuestRelationMapValue(botAI); } - static UntypedValue* quest_guidp_map(PlayerbotAI* botAI) { return new QuestGuidpMapValue(botAI); } - static UntypedValue* quest_givers(PlayerbotAI* botAI) { return new QuestGiversValue(botAI); } - - // Global acess functions -public: - static SharedValueContext* instance() + static SharedValueContext& instance() { static SharedValueContext instance; - return &instance; + + return instance; } template @@ -74,6 +49,36 @@ class SharedValueContext : public NamedObjectContext out << param; return getGlobalValue(name, out.str()); } + +private: + SharedValueContext() : NamedObjectContext(true) + { + creators["bg masters"] = &SharedValueContext::bg_masters; + creators["drop map"] = &SharedValueContext::drop_map; + creators["item drop list"] = &SharedValueContext::item_drop_list; + creators["entry loot list"] = &SharedValueContext::entry_loot_list; + + creators["entry quest relation"] = &SharedValueContext::entry_quest_relation; + creators["quest guidp map"] = &SharedValueContext::quest_guidp_map; + creators["quest givers"] = &SharedValueContext::quest_givers; + } + ~SharedValueContext() = default; + + SharedValueContext(const SharedValueContext&) = delete; + SharedValueContext& operator=(const SharedValueContext&) = delete; + + SharedValueContext(SharedValueContext&&) = delete; + SharedValueContext& operator=(SharedValueContext&&) = delete; + + static UntypedValue* bg_masters(PlayerbotAI* botAI) { return new BgMastersValue(botAI); } + static UntypedValue* drop_map(PlayerbotAI* botAI) { return new DropMapValue(botAI); } + static UntypedValue* item_drop_list(PlayerbotAI* botAI) { return new ItemDropListValue(botAI); } + static UntypedValue* entry_loot_list(PlayerbotAI* botAI) { return new EntryLootListValue(botAI); } + + static UntypedValue* entry_quest_relation(PlayerbotAI* botAI) { return new EntryQuestRelationMapValue(botAI); } + static UntypedValue* quest_guidp_map(PlayerbotAI* botAI) { return new QuestGuidpMapValue(botAI); } + static UntypedValue* quest_givers(PlayerbotAI* botAI) { return new QuestGiversValue(botAI); } + }; #define sSharedValueContext SharedValueContext::instance() diff --git a/src/Ai/Base/Strategy/AttackEnemyPlayersStrategy.cpp b/src/Ai/Base/Strategy/AttackEnemyPlayersStrategy.cpp index a43269976d..108f89c145 100644 --- a/src/Ai/Base/Strategy/AttackEnemyPlayersStrategy.cpp +++ b/src/Ai/Base/Strategy/AttackEnemyPlayersStrategy.cpp @@ -5,10 +5,17 @@ #include "AttackEnemyPlayersStrategy.h" -#include "Playerbots.h" +#include "ChooseTargetActions.h" +#include "CreateNextAction.h" void AttackEnemyPlayersStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("enemy player near", - { NextAction("attack enemy player", 55.0f) })); + triggers.push_back( + new TriggerNode( + "enemy player near", + { + CreateNextAction(55.0f) + } + ) + ); } diff --git a/src/Ai/Base/Strategy/BattlegroundStrategy.cpp b/src/Ai/Base/Strategy/BattlegroundStrategy.cpp index 41c726cc2b..e561eb9622 100644 --- a/src/Ai/Base/Strategy/BattlegroundStrategy.cpp +++ b/src/Ai/Base/Strategy/BattlegroundStrategy.cpp @@ -5,83 +5,386 @@ #include "BattlegroundStrategy.h" -#include "Playerbots.h" +#include "BattleGroundJoinAction.h" +#include "CreateNextAction.h" +#include "BattlegroundTacticsMoveToStart.h" +#include "BattlegroundTacticsMoveToObjective.h" +#include "BattlegroundTacticsCheckObjective.h" +#include "BattlegroundTacticsResetObjectiveForce.h" +#include "BattlegroundTacticsCheckFlag.h" +#include "ChooseTargetActions.h" +#include "BattlegroundTacticsProtectFC.h" +#include "BattlegroundTacticsUseBuff.h" +#include "VehicleActions.h" +#include "GenericSpellActions.h" void BGStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("often", { NextAction("bg join", relevance)})); - triggers.push_back(new TriggerNode("bg invite active", { NextAction("bg status check", relevance)})); - triggers.push_back(new TriggerNode("timer", { NextAction("bg strategy check", relevance)})); + triggers.push_back( + new TriggerNode( + "often", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "bg invite active", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "timer", + { + CreateNextAction(relevance) + } + ) + ); } BGStrategy::BGStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI) {} void BattlegroundStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("bg waiting", { NextAction("bg move to start", ACTION_BG)})); - triggers.push_back(new TriggerNode("bg active", { NextAction("bg move to objective", ACTION_BG)})); - triggers.push_back(new TriggerNode("often", { NextAction("bg check objective", ACTION_BG + 1)})); - triggers.push_back(new TriggerNode("dead", { NextAction("bg reset objective force", ACTION_EMERGENCY)})); + triggers.push_back( + new TriggerNode( + "bg waiting", + { + CreateNextAction(ACTION_BG) + } + ) + ); + triggers.push_back( + new TriggerNode( + "bg active", + { + CreateNextAction(ACTION_BG) + } + ) + ); + triggers.push_back( + new TriggerNode( + "often", + { + CreateNextAction(ACTION_BG + 1.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "dead", + { + CreateNextAction(ACTION_EMERGENCY) + } + ) + ); } void WarsongStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("bg active", { NextAction("bg check flag", ACTION_EMERGENCY )})); - triggers.push_back(new TriggerNode("enemy flagcarrier near", { NextAction("attack enemy flag carrier", ACTION_RAID + 1.0f)})); - triggers.push_back(new TriggerNode("team flagcarrier near", { NextAction("bg protect fc", ACTION_RAID)})); - triggers.push_back(new TriggerNode("often", { NextAction("bg use buff", ACTION_BG)})); - triggers.push_back(new TriggerNode("low health", { NextAction("bg use buff", ACTION_MOVE)})); - triggers.push_back(new TriggerNode("low mana", { NextAction("bg use buff", ACTION_MOVE)})); - triggers.push_back(new TriggerNode("player has flag", { NextAction("bg move to objective", ACTION_EMERGENCY)})); - triggers.push_back(new TriggerNode("timer bg", { NextAction("bg reset objective force", ACTION_EMERGENCY)})); + triggers.push_back( + new TriggerNode( + "bg active", + { + CreateNextAction(ACTION_EMERGENCY ) + } + ) + ); + triggers.push_back( + new TriggerNode( + "enemy flagcarrier near", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "team flagcarrier near", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + triggers.push_back( + new TriggerNode( + "often", + { + CreateNextAction(ACTION_BG) + } + ) + ); + triggers.push_back( + new TriggerNode( + "low health", + { + CreateNextAction(ACTION_MOVE) + } + ) + ); + triggers.push_back( + new TriggerNode( + "low mana", + { + CreateNextAction(ACTION_MOVE) + } + ) + ); + triggers.push_back( + new TriggerNode( + "player has flag", + { + CreateNextAction(ACTION_EMERGENCY) + } + ) + ); + triggers.push_back( + new TriggerNode( + "timer bg", + { + CreateNextAction(ACTION_EMERGENCY) + } + ) + ); } void AlteracStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("alliance no snowfall gy", { NextAction("bg move to objective", ACTION_EMERGENCY)})); - triggers.push_back(new TriggerNode("timer bg", { NextAction("bg reset objective force", ACTION_EMERGENCY)})); + triggers.push_back( + new TriggerNode( + "alliance no snowfall gy", + { + CreateNextAction(ACTION_EMERGENCY) + } + ) + ); + triggers.push_back( + new TriggerNode( + "timer bg", + { + CreateNextAction(ACTION_EMERGENCY) + } + ) + ); } void ArathiStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("bg active", { NextAction("bg check flag", ACTION_EMERGENCY)})); - triggers.push_back(new TriggerNode("often", { NextAction("bg use buff", ACTION_BG)})); - triggers.push_back(new TriggerNode("low health", { NextAction("bg use buff", ACTION_MOVE)})); - triggers.push_back(new TriggerNode("low mana", { NextAction("bg use buff", ACTION_MOVE)})); + triggers.push_back( + new TriggerNode( + "bg active", + { + CreateNextAction(ACTION_EMERGENCY) + } + ) + ); + triggers.push_back( + new TriggerNode( + "often", + { + CreateNextAction(ACTION_BG) + } + ) + ); + triggers.push_back( + new TriggerNode( + "low health", + { + CreateNextAction(ACTION_MOVE) + } + ) + ); + triggers.push_back( + new TriggerNode( + "low mana", + { + CreateNextAction(ACTION_MOVE) + } + ) + ); } void EyeStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("bg active", { NextAction("bg check flag", ACTION_EMERGENCY)})); - triggers.push_back(new TriggerNode("often", { NextAction("bg use buff", ACTION_BG)})); - triggers.push_back(new TriggerNode("low health", { NextAction("bg use buff", ACTION_MOVE)})); - triggers.push_back(new TriggerNode("low mana", { NextAction("bg use buff", ACTION_MOVE)})); - triggers.push_back(new TriggerNode("enemy flagcarrier near", { NextAction("attack enemy flag carrier", ACTION_RAID)})); - triggers.push_back(new TriggerNode("player has flag",{ NextAction("bg move to objective", ACTION_EMERGENCY)})); + triggers.push_back( + new TriggerNode( + "bg active", + { + CreateNextAction(ACTION_EMERGENCY) + } + ) + ); + triggers.push_back( + new TriggerNode( + "often", + { + CreateNextAction(ACTION_BG) + } + ) + ); + triggers.push_back( + new TriggerNode( + "low health", + { + CreateNextAction(ACTION_MOVE) + } + ) + ); + triggers.push_back( + new TriggerNode( + "low mana", + { + CreateNextAction(ACTION_MOVE) + } + ) + ); + triggers.push_back( + new TriggerNode( + "enemy flagcarrier near", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + triggers.push_back( + new TriggerNode( + "player has flag", + { + CreateNextAction(ACTION_EMERGENCY) + } + ) + ); } //TODO: Do Priorities void IsleStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("bg active", { NextAction("bg check flag", ACTION_MOVE)})); - triggers.push_back(new TriggerNode("timer", { NextAction("enter vehicle", ACTION_MOVE + 8.0f)})); - triggers.push_back(new TriggerNode("random", { NextAction("leave vehicle", ACTION_MOVE + 7.0f)})); - triggers.push_back(new TriggerNode("in vehicle", { NextAction("hurl boulder", ACTION_MOVE + 9.0f)})); - triggers.push_back(new TriggerNode("in vehicle", { NextAction("fire cannon", ACTION_MOVE + 9.0f)})); - triggers.push_back(new TriggerNode("in vehicle", { NextAction("napalm", ACTION_MOVE + 9.0f)})); - triggers.push_back(new TriggerNode("enemy is close", { NextAction("steam blast", ACTION_MOVE + 9.0f)})); - triggers.push_back(new TriggerNode("in vehicle", { NextAction("ram", ACTION_MOVE + 9.0f)})); - triggers.push_back(new TriggerNode("enemy is close", { NextAction("ram", ACTION_MOVE + 9.1f)})); - triggers.push_back(new TriggerNode("enemy out of melee", { NextAction("steam rush", ACTION_MOVE + 9.2f)})); - triggers.push_back(new TriggerNode("in vehicle", { NextAction("incendiary rocket", ACTION_MOVE + 9.0f)})); - triggers.push_back(new TriggerNode("in vehicle", { NextAction("rocket blast", ACTION_MOVE + 9.0f)})); + triggers.push_back( + new TriggerNode( + "bg active", + { + CreateNextAction(ACTION_MOVE) + } + ) + ); + triggers.push_back( + new TriggerNode( + "timer", + { + CreateNextAction(ACTION_MOVE + 8.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "random", + { + CreateNextAction(ACTION_MOVE + 7.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "in vehicle", + { + CreateNextAction(ACTION_MOVE + 9.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "in vehicle", + { + CreateNextAction(ACTION_MOVE + 9.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "in vehicle", + { + CreateNextAction(ACTION_MOVE + 9.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "enemy is close", + { + CreateNextAction(ACTION_MOVE + 9.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "in vehicle", + { + CreateNextAction(ACTION_MOVE + 9.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "enemy is close", + { + CreateNextAction(ACTION_MOVE + 9.1f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "enemy out of melee", + { + CreateNextAction(ACTION_MOVE + 9.2f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "in vehicle", + { + CreateNextAction(ACTION_MOVE + 9.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "in vehicle", + { + CreateNextAction(ACTION_MOVE + 9.0f) + } + ) + ); // this is bugged: it doesn't work, and stops glaive throw working (which is needed to take down gate) - // triggers.push_back(new TriggerNode("in vehicle", { NextAction("blade salvo", ACTION_MOVE + 9.0f)})); - triggers.push_back(new TriggerNode("in vehicle", { NextAction("glaive throw", ACTION_MOVE + 9.0f)})); + // triggers.push_back( + // new TriggerNode( + // "in vehicle", + // { + // CreateNextAction("blade salvo", ACTION_MOVE + 9.0f) + // } + // ) + // ); + triggers.push_back( + new TriggerNode( + "in vehicle", + { + CreateNextAction(ACTION_MOVE + 9.0f) + } + ) + ); } void ArenaStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("no possible targets", { NextAction("arena tactics", ACTION_BG)})); + new TriggerNode("no possible targets", + { + CreateNextAction(ACTION_BG) + } + ) + ); } diff --git a/src/Ai/Base/Strategy/CastTimeStrategy.cpp b/src/Ai/Base/Strategy/CastTimeStrategy.cpp index 042d1c9e41..badecbaea1 100644 --- a/src/Ai/Base/Strategy/CastTimeStrategy.cpp +++ b/src/Ai/Base/Strategy/CastTimeStrategy.cpp @@ -8,58 +8,49 @@ #include "GenericSpellActions.h" #include "Playerbots.h" -float CastTimeMultiplier::GetValue(Action* action) +float CastTimeMultiplier::GetValue(Action& action) { - if (action == nullptr) + if (!action.GetTarget() || action.GetTarget() != this->context->GetValue("current target")->Get()) return 1.0f; - if (!action->GetTarget() || action->GetTarget() != AI_VALUE(Unit*, "current target")) - return 1.0f; + CastSpellAction* spellAction = dynamic_cast(&action); - if (/*targetHealth < sPlayerbotAIConfig->criticalHealth && */ dynamic_cast(action)) + if (spellAction == nullptr) { - CastSpellAction* spellAction = dynamic_cast(action); - uint32 spellId = AI_VALUE2(uint32, "spell id", spellAction->getSpell()); - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - if (!spellInfo) - return 1.0f; + return 1.0f; + } - if ((spellInfo->Targets & TARGET_FLAG_DEST_LOCATION) != 0 || - (spellInfo->Targets & TARGET_FLAG_SOURCE_LOCATION) != 0) - return 1.0f; + uint32 spellId = AI_VALUE2(uint32, "spell id", spellAction->getSpell()); + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - uint32 castTime = spellInfo->CalcCastTime(bot); + if (!spellInfo) + return 1.0f; - if (spellInfo->IsChanneled()) - { - int32 duration = spellInfo->GetDuration(); - // bot->ApplySpellMod(spellInfo->Id, SPELLMOD_DURATION, duration); - duration = std::min(duration, 3000); - if (duration > 0) - castTime += duration; - } + if ((spellInfo->Targets & TARGET_FLAG_DEST_LOCATION) != 0 || + (spellInfo->Targets & TARGET_FLAG_SOURCE_LOCATION) != 0) + return 1.0f; - Unit* target = action->GetTarget(); - if (!target || !target->IsAlive() || !target->IsInWorld()) - { - return 1.0f; - } + uint32 castTime = spellInfo->CalcCastTime(bot); - if (castTime > (1000 * target->GetHealth() / AI_VALUE(float, "estimated group dps"))) - { - return 0.1f; - } + if (spellInfo->IsChanneled()) + { + int32 duration = spellInfo->GetDuration(); + // bot->ApplySpellMod(spellInfo->Id, SPELLMOD_DURATION, duration); + duration = std::min(duration, 3000); + if (duration > 0) + castTime += duration; } - // if (castTime >= 3000) - // return 0.0f; - // if (castTime >= 1500) - // return 0.5f; - - // if (castTime >= 1000) - // return 0.25f; - // // } + Unit* target = action.GetTarget(); + if (!target || !target->IsAlive() || !target->IsInWorld()) + { + return 1.0f; + } + if (castTime > (1000 * target->GetHealth() / this->context->GetValue("estimated group dps")->Get())) + { + return 0.1f; + } return 1.0f; } diff --git a/src/Ai/Base/Strategy/CastTimeStrategy.h b/src/Ai/Base/Strategy/CastTimeStrategy.h index f5eddc1ca2..e4bfb4245b 100644 --- a/src/Ai/Base/Strategy/CastTimeStrategy.h +++ b/src/Ai/Base/Strategy/CastTimeStrategy.h @@ -15,7 +15,7 @@ class CastTimeMultiplier : public Multiplier public: CastTimeMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "cast time") {} - float GetValue(Action* action) override; + float GetValue(Action& action) override; }; class CastTimeStrategy : public Strategy diff --git a/src/Ai/Base/Strategy/ChatCommandHandlerStrategy.cpp b/src/Ai/Base/Strategy/ChatCommandHandlerStrategy.cpp index 0a81686a9d..8d4eb8ff04 100644 --- a/src/Ai/Base/Strategy/ChatCommandHandlerStrategy.cpp +++ b/src/Ai/Base/Strategy/ChatCommandHandlerStrategy.cpp @@ -5,7 +5,45 @@ #include "ChatCommandHandlerStrategy.h" -#include "Playerbots.h" +#include "ActionNode.h" +#include "CreateNextAction.h" +#include "CastCustomSpellAction.h" +#include "AttackAction.h" +#include "TellReputationAction.h" +#include "QueryQuestAction.h" +#include "QueryItemUsageAction.h" +#include "AddLootAction.h" +#include "LootAction.h" +#include "UseItemAction.h" +#include "TellItemCountAction.h" +#include "EquipAction.h" +#include "UnequipAction.h" +#include "TradeAction.h" +#include "SellAction.h" +#include "BuyAction.h" +#include "RewardAction.h" +#include "AcceptQuestAction.h" +#include "ChatShortcutActions.h" +#include "GossipHelloAction.h" +#include "TalkToQuestGiverAction.h" +#include "VehicleActions.h" +#include "ReviveFromCorpseAction.h" +#include "TellTargetAction.h" +#include "ReadyCheckAction.h" +#include "MovementActions.h" +#include "TellLosAction.h" +#include "OpenItemAction.h" +#include "QueryItemUsageAction.h" +#include "UnlockItemAction.h" +#include "UnlockTradedItemAction.h" +#include "WipeAction.h" +#include "TameAction.h" +#include "TellGlyphsAction.h" +#include "EquipGlyphsAction.h" +#include "PetsAction.h" +#include "PetAttackAction.h" +#include "LootRollAction.h" +#include "ManageInventoryAction.h" class ChatCommandActionNodeFactoryInternal : public NamedObjectFactory { @@ -13,12 +51,13 @@ class ChatCommandActionNodeFactoryInternal : public NamedObjectFactory(100.0f) } + ); } }; @@ -26,168 +65,496 @@ void ChatCommandHandlerStrategy::InitTriggers(std::vector& trigger { PassTroughStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("rep", { NextAction("reputation", relevance) })); - triggers.push_back(new TriggerNode("q", { NextAction("query quest", relevance), - NextAction("query item usage", relevance) })); - triggers.push_back(new TriggerNode("add all loot", { NextAction("add all loot", relevance), - NextAction("loot", relevance) })); - triggers.push_back(new TriggerNode("u", { NextAction("use", relevance) })); - triggers.push_back(new TriggerNode("c", { NextAction("item count", relevance) })); triggers.push_back( - new TriggerNode("items", { NextAction("item count", relevance) })); - triggers.push_back(new TriggerNode("inv", { NextAction("item count", relevance) })); - triggers.push_back(new TriggerNode("e", { NextAction("equip", relevance) })); - triggers.push_back(new TriggerNode("ue", { NextAction("unequip", relevance) })); - triggers.push_back(new TriggerNode("t", { NextAction("trade", relevance) })); - triggers.push_back(new TriggerNode("nt", { NextAction("trade", relevance) })); - triggers.push_back(new TriggerNode("s", { NextAction("sell", relevance) })); - triggers.push_back(new TriggerNode("b", { NextAction("buy", relevance) })); - triggers.push_back(new TriggerNode("r", { NextAction("reward", relevance) })); + new TriggerNode( + "pvp stats", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("attack", { NextAction("attack my target", relevance) })); + new TriggerNode( + "rep", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("accept", { NextAction("accept quest", relevance) })); + new TriggerNode( + "q", + { + CreateNextAction(relevance), + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("follow", { NextAction("follow chat shortcut", relevance) })); + new TriggerNode( + "add all loot", + { + CreateNextAction(relevance), + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("stay", { NextAction("stay chat shortcut", relevance) })); + new TriggerNode( + "u", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("move from group", { NextAction("move from group chat shortcut", relevance) })); + new TriggerNode( + "c", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("flee", { NextAction("flee chat shortcut", relevance) })); - triggers.push_back(new TriggerNode( - "tank attack", { NextAction("tank attack chat shortcut", relevance) })); + new TriggerNode( + "items", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("grind", { NextAction("grind chat shortcut", relevance) })); + new TriggerNode( + "inv", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("talk", { NextAction("gossip hello", relevance), - NextAction("talk to quest giver", relevance) })); + new TriggerNode( + "e", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("enter vehicle", { NextAction("enter vehicle", relevance) })); + new TriggerNode( + "ue", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("leave vehicle", { NextAction("leave vehicle", relevance) })); + new TriggerNode( + "t", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("cast", { NextAction("cast custom spell", relevance) })); + new TriggerNode( + "nt", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("castnc", { NextAction("cast custom nc spell", relevance) })); + new TriggerNode( + "s", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("revive", { NextAction("spirit healer", relevance) })); + new TriggerNode( + "b", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("runaway", { NextAction("runaway chat shortcut", relevance) })); + new TriggerNode( + "r", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("warning", { NextAction("runaway chat shortcut", relevance) })); + new TriggerNode( + "attack", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("max dps", { NextAction("max dps chat shortcut", relevance) })); + new TriggerNode( + "accept", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("attackers", { NextAction("tell attackers", relevance) })); + new TriggerNode( + "follow", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("target", { NextAction("tell target", relevance) })); + new TriggerNode( + "stay", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("ready", { NextAction("ready check", relevance) })); + new TriggerNode( + "move from group", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("bwl", { NextAction("bwl chat shortcut", relevance) })); + new TriggerNode( + "flee", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("dps", { NextAction("tell estimated dps", relevance) })); + new TriggerNode( + "tank attack", + { + CreateNextAction(relevance) + } + ) +); triggers.push_back( - new TriggerNode("disperse", { NextAction("disperse set", relevance) })); + new TriggerNode( + "grind", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("open items", { NextAction("open items", relevance) })); + new TriggerNode( + "talk", + { + CreateNextAction(relevance), + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("qi", { NextAction("query item usage", relevance) })); + new TriggerNode( + "enter vehicle", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("unlock items", { NextAction("unlock items", relevance) })); + new TriggerNode( + "leave vehicle", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("unlock traded item", { NextAction("unlock traded item", relevance) })); + new TriggerNode( + "cast", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("wipe", { NextAction("wipe", relevance) })); - triggers.push_back(new TriggerNode("tame", { NextAction("tame", relevance) })); - triggers.push_back(new TriggerNode("glyphs", { NextAction("glyphs", relevance) })); // Added for custom Glyphs - triggers.push_back(new TriggerNode("glyph equip", { NextAction("glyph equip", relevance) })); // Added for custom Glyphs - triggers.push_back(new TriggerNode("pet", { NextAction("pet", relevance) })); - triggers.push_back(new TriggerNode("pet attack", { NextAction("pet attack", relevance) })); - triggers.push_back(new TriggerNode("roll", { NextAction("roll", relevance) })); + new TriggerNode( + "castnc", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "revive", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "runaway", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "warning", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "max dps", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "attackers", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "target", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "ready", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "bwl", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "dps", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "disperse", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "open items", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "qi", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "unlock items", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "unlock traded item", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "wipe", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "tame", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "glyphs", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "glyph equip", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "pet", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "pet attack", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "roll", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "manage inventory", + { + CreateNextAction(relevance) + } + ) + ); } ChatCommandHandlerStrategy::ChatCommandHandlerStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI) { actionNodeFactories.Add(new ChatCommandActionNodeFactoryInternal()); - supported.push_back("quests"); - supported.push_back("stats"); - supported.push_back("leave"); - supported.push_back("reputation"); - supported.push_back("log"); - supported.push_back("los"); - supported.push_back("rpg status"); - supported.push_back("rpg do quest"); - supported.push_back("aura"); - supported.push_back("drop"); - supported.push_back("share"); - supported.push_back("ll"); - supported.push_back("ss"); - supported.push_back("release"); - supported.push_back("teleport"); - supported.push_back("taxi"); - supported.push_back("repair"); - supported.push_back("talents"); - supported.push_back("spells"); - supported.push_back("co"); - supported.push_back("nc"); - supported.push_back("de"); - supported.push_back("trainer"); - supported.push_back("maintenance"); - supported.push_back("remove glyph"); - supported.push_back("autogear"); - supported.push_back("equip upgrade"); - supported.push_back("chat"); - supported.push_back("home"); - supported.push_back("destroy"); - supported.push_back("reset botAI"); - supported.push_back("emote"); - supported.push_back("buff"); - supported.push_back("help"); - supported.push_back("gb"); - supported.push_back("bank"); - supported.push_back("invite"); - supported.push_back("lfg"); - supported.push_back("spell"); - supported.push_back("rti"); - supported.push_back("position"); - supported.push_back("summon"); - supported.push_back("who"); - supported.push_back("save mana"); - supported.push_back("formation"); - supported.push_back("stance"); - supported.push_back("sendmail"); - supported.push_back("mail"); - supported.push_back("outfit"); - supported.push_back("go"); - supported.push_back("debug"); - supported.push_back("cdebug"); - supported.push_back("cs"); - supported.push_back("wts"); - supported.push_back("hire"); - supported.push_back("craft"); - supported.push_back("flag"); - supported.push_back("range"); - supported.push_back("ra"); - supported.push_back("give leader"); - supported.push_back("cheat"); - supported.push_back("ginvite"); - supported.push_back("guild promote"); - supported.push_back("guild demote"); - supported.push_back("guild remove"); - supported.push_back("guild leave"); - supported.push_back("rtsc"); - supported.push_back("drink"); - supported.push_back("calc"); - supported.push_back("open items"); - supported.push_back("qi"); - supported.push_back("unlock items"); - supported.push_back("unlock traded item"); - supported.push_back("tame"); - supported.push_back("glyphs"); // Added for custom Glyphs - supported.push_back("glyph equip"); // Added for custom Glyphs - supported.push_back("pet"); - supported.push_back("pet attack"); + this->supported.push_back({ "tell pvp stats", CreateNextAction(relevance).factory }); + this->supported.push_back({ "quests", CreateNextAction(relevance).factory }); + this->supported.push_back({ "stats", CreateNextAction(relevance).factory }); + this->supported.push_back({ "manage inventory", CreateNextAction(relevance).factory }); + this->supported.push_back({ "leave", CreateNextAction(relevance).factory }); + this->supported.push_back({ "reputation", CreateNextAction(relevance).factory }); + this->supported.push_back({ "log", CreateNextAction(relevance).factory }); + this->supported.push_back({ "los", CreateNextAction(relevance).factory }); + this->supported.push_back({ "rpg status", CreateNextAction(relevance).factory }); + this->supported.push_back({ "rpg do quest", CreateNextAction(relevance).factory }); + this->supported.push_back({ "aura", CreateNextAction(relevance).factory }); + this->supported.push_back({ "drop", CreateNextAction(relevance).factory }); + this->supported.push_back({ "share", CreateNextAction(relevance).factory }); + this->supported.push_back({ "ll", CreateNextAction(relevance).factory }); + this->supported.push_back({ "ss", CreateNextAction(relevance).factory }); + this->supported.push_back({ "release", CreateNextAction(relevance).factory }); + this->supported.push_back({ "teleport", CreateNextAction(relevance).factory }); + this->supported.push_back({ "taxi", CreateNextAction(relevance).factory }); + this->supported.push_back({ "repair", CreateNextAction(relevance).factory }); + this->supported.push_back({ "talents", CreateNextAction(relevance).factory }); + this->supported.push_back({ "spells", CreateNextAction(relevance).factory }); + this->supported.push_back({ "co", CreateNextAction(relevance).factory }); + this->supported.push_back({ "nc", CreateNextAction(relevance).factory }); + this->supported.push_back({ "de", CreateNextAction(relevance).factory }); + this->supported.push_back({ "trainer", CreateNextAction(relevance).factory }); + this->supported.push_back({ "maintenance", CreateNextAction(relevance).factory }); + this->supported.push_back({ "remove glyph", CreateNextAction(relevance).factory }); + this->supported.push_back({ "autogear", CreateNextAction(relevance).factory }); + this->supported.push_back({ "equip upgrade", CreateNextAction(relevance).factory }); + this->supported.push_back({ "chat", CreateNextAction(relevance).factory }); + this->supported.push_back({ "home", CreateNextAction(relevance).factory }); + this->supported.push_back({ "destroy", CreateNextAction(relevance).factory }); + this->supported.push_back({ "reset botAI", CreateNextAction(relevance).factory }); + this->supported.push_back({ "emote", CreateNextAction(relevance).factory }); + this->supported.push_back({ "buff", CreateNextAction(relevance).factory }); + this->supported.push_back({ "help", CreateNextAction(relevance).factory }); + this->supported.push_back({ "gb", CreateNextAction(relevance).factory }); + this->supported.push_back({ "bank", CreateNextAction(relevance).factory }); + this->supported.push_back({ "invite", CreateNextAction(relevance).factory }); + this->supported.push_back({ "lfg", CreateNextAction(relevance).factory }); + this->supported.push_back({ "spell", CreateNextAction(relevance).factory }); + this->supported.push_back({ "rti", CreateNextAction(relevance).factory }); + this->supported.push_back({ "position", CreateNextAction(relevance).factory }); + this->supported.push_back({ "summon", CreateNextAction(relevance).factory }); + this->supported.push_back({ "who", CreateNextAction(relevance).factory }); + this->supported.push_back({ "save mana", CreateNextAction(relevance).factory }); + this->supported.push_back({ "formation", CreateNextAction(relevance).factory }); + this->supported.push_back({ "stance", CreateNextAction(relevance).factory }); + this->supported.push_back({ "sendmail", CreateNextAction(relevance).factory }); + this->supported.push_back({ "mail", CreateNextAction(relevance).factory }); + // It seems "outfit" command is not implemente); + // this->supported.push_back({ "outfit" }); + this->supported.push_back({ "go", CreateNextAction(relevance).factory }); + this->supported.push_back({ "debug", CreateNextAction(relevance).factory }); + this->supported.push_back({ "cdebug", CreateNextAction(relevance).factory }); + this->supported.push_back({ "cs", CreateNextAction(relevance).factory }); + this->supported.push_back({ "wts", CreateNextAction(relevance).factory }); + this->supported.push_back({ "hire", CreateNextAction(relevance).factory }); + this->supported.push_back({ "craft", CreateNextAction(relevance).factory }); + this->supported.push_back({ "flag", CreateNextAction(relevance).factory }); + this->supported.push_back({ "range", CreateNextAction(relevance).factory }); + // It seems "ra" command is not implemente); + // this->supported.push_back({ "ra" }); + this->supported.push_back({ "give leader", CreateNextAction(relevance).factory }); + this->supported.push_back({ "cheat", CreateNextAction(relevance).factory }); + this->supported.push_back({ "ginvite", CreateNextAction(relevance).factory }); + this->supported.push_back({ "guild promote", CreateNextAction(relevance).factory }); + this->supported.push_back({ "guild demote", CreateNextAction(relevance).factory }); + this->supported.push_back({ "guild remove", CreateNextAction(relevance).factory }); + this->supported.push_back({ "guild leave", CreateNextAction(relevance).factory }); + this->supported.push_back({ "rtsc", CreateNextAction(relevance).factory }); + this->supported.push_back({ "drink", CreateNextAction(relevance).factory }); + this->supported.push_back({ "calc", CreateNextAction(relevance).factory }); + this->supported.push_back({ "open items", CreateNextAction(relevance).factory }); + // It seems "qi" command is not implemente); + // this->supported.push_back({ "qi" }); + this->supported.push_back({ "unlock items", CreateNextAction(relevance).factory }); + this->supported.push_back({ "unlock traded item", CreateNextAction(relevance).factory }); + this->supported.push_back({ "tame", CreateNextAction(relevance).factory }); + this->supported.push_back({ "glyphs", CreateNextAction(relevance).factory }); // Added for custom Glyph + this->supported.push_back({ "glyph equip", CreateNextAction(relevance).factory }); // Added for custom Glyph + this->supported.push_back({ "pet", CreateNextAction(relevance).factory }); + this->supported.push_back({ "pet attack", CreateNextAction(relevance).factory }); } diff --git a/src/Ai/Base/Strategy/ChatCommandHandlerStrategy.h b/src/Ai/Base/Strategy/ChatCommandHandlerStrategy.h index 87eab747d6..b04fe77279 100644 --- a/src/Ai/Base/Strategy/ChatCommandHandlerStrategy.h +++ b/src/Ai/Base/Strategy/ChatCommandHandlerStrategy.h @@ -6,7 +6,52 @@ #ifndef _PLAYERBOT_CHATCOMMANDHANDLERSTRATEGY_H #define _PLAYERBOT_CHATCOMMANDHANDLERSTRATEGY_H +#include "BuffAction.h" +#include "ChangeChatAction.h" +#include "ChangeStrategyAction.h" +#include "ChangeTalentsAction.h" +#include "ChatActionContext.h" +#include "DebugAction.h" +#include "DestroyItemAction.h" +#include "DrinkAction.h" +#include "EmoteAction.h" +#include "EquipAction.h" +#include "FlagAction.h" +#include "Formations.h" +#include "GoAction.h" +#include "HelpAction.h" +#include "HireAction.h" +#include "InviteToGroupAction.h" +#include "LeaveGroupAction.h" +#include "ListQuestsActions.h" +#include "ListSpellsAction.h" +#include "LogLevelAction.h" +#include "MailAction.h" +#include "PassLeadershipToMasterAction.h" #include "PassTroughStrategy.h" +#include "PetAttackAction.h" +#include "PositionAction.h" +#include "RangeAction.h" +#include "ReleaseSpiritAction.h" +#include "RepairAllAction.h" +#include "ResetAiAction.h" +#include "RtiAction.h" +#include "SaveManaAction.h" +#include "SendMailAction.h" +#include "SetCraftAction.h" +#include "SetHomeAction.h" +#include "SkipSpellsListAction.h" +#include "Stances.h" +#include "StatsAction.h" +#include "TaxiAction.h" +#include "TeleportAction.h" +#include "TellCastFailedAction.h" +#include "TellLosAction.h" +#include "TellReputationAction.h" +#include "TrainerAction.h" +#include "UseMeetingStoneAction.h" +#include "WhoAction.h" +#include "WtsAction.h" class PlayerbotAI; diff --git a/src/Ai/Base/Strategy/CombatStrategy.cpp b/src/Ai/Base/Strategy/CombatStrategy.cpp index 75700e9a6d..85409ac4e5 100644 --- a/src/Ai/Base/Strategy/CombatStrategy.cpp +++ b/src/Ai/Base/Strategy/CombatStrategy.cpp @@ -5,8 +5,12 @@ #include "CombatStrategy.h" -#include "Playerbots.h" #include "Strategy.h" +#include "CreateNextAction.h" +#include "ReachTargetActions.h" +#include "ChooseTargetActions.h" +#include "CheckMountStateAction.h" +#include "MovementActions.h" void CombatStrategy::InitTriggers(std::vector& triggers) { @@ -14,16 +18,15 @@ void CombatStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "enemy out of spell", { - NextAction("reach spell", ACTION_HIGH) + CreateNextAction(ACTION_HIGH) } ) ); - // drop target relevance 99 (lower than Worldpacket triggers) triggers.push_back( new TriggerNode( "invalid target", { - NextAction("drop target", 99) + CreateNextAction(99.0f) } ) ); @@ -31,23 +34,24 @@ void CombatStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "mounted", { - NextAction("check mount state", 54) - } - ) - ); - triggers.push_back( - new TriggerNode( - "combat stuck", - { - NextAction("reset", 1.0f) + CreateNextAction(54.0f) } ) ); + // "reset" is seemingly not linked to any creator + // triggers.push_back( + // new TriggerNode( + // "combat stuck", + // { + // CreateNextAction("reset", 1.0f) + // } + // ) + // ); triggers.push_back( new TriggerNode( "not facing target", { - NextAction("set facing", ACTION_MOVE + 7) + CreateNextAction(ACTION_MOVE + 7.0f) } ) ); @@ -61,15 +65,15 @@ AvoidAoeStrategy::AvoidAoeStrategy(PlayerbotAI* botAI) : Strategy(botAI) {} std::vector AvoidAoeStrategy::getDefaultActions() { return { - NextAction("avoid aoe", ACTION_EMERGENCY) + CreateNextAction(ACTION_EMERGENCY) }; } -void AvoidAoeStrategy::InitTriggers(std::vector& triggers) +void AvoidAoeStrategy::InitTriggers(std::vector&) { } -void AvoidAoeStrategy::InitMultipliers(std::vector& multipliers) +void AvoidAoeStrategy::InitMultipliers(std::vector&) { } @@ -78,17 +82,17 @@ TankFaceStrategy::TankFaceStrategy(PlayerbotAI* botAI) : Strategy(botAI) {} std::vector TankFaceStrategy::getDefaultActions() { return { - NextAction("tank face", ACTION_MOVE) + CreateNextAction(ACTION_MOVE) }; } -void TankFaceStrategy::InitTriggers(std::vector& triggers) +void TankFaceStrategy::InitTriggers(std::vector&) { } std::vector CombatFormationStrategy::getDefaultActions() { return { - NextAction("combat formation move", ACTION_NORMAL) + CreateNextAction(ACTION_NORMAL) }; } diff --git a/src/Ai/Base/Strategy/ConserveManaStrategy.cpp b/src/Ai/Base/Strategy/ConserveManaStrategy.cpp index adc3cec884..793bb752e1 100644 --- a/src/Ai/Base/Strategy/ConserveManaStrategy.cpp +++ b/src/Ai/Base/Strategy/ConserveManaStrategy.cpp @@ -8,123 +8,44 @@ #include "GenericSpellActions.h" #include "LastSpellCastValue.h" #include "PlayerbotAIConfig.h" -#include "Playerbots.h" -// float ConserveManaMultiplier::GetValue(Action* action) -// { -// if (!action) -// return 1.0f; - -// uint8 health = AI_VALUE2(uint8, "health", "self target"); -// uint8 targetHealth = AI_VALUE2(uint8, "health", "current target"); -// uint8 mana = AI_VALUE2(uint8, "mana", "self target"); -// bool hasMana = AI_VALUE2(bool, "has mana", "self target"); -// bool mediumMana = hasMana && mana < sPlayerbotAIConfig->mediumMana; - -// if (health < sPlayerbotAIConfig->lowHealth) -// return 1.0f; - -// Unit* target = AI_VALUE(Unit*, "current target"); -// if (action->GetTarget() != target) -// return 1.0f; - -// CastSpellAction* spellAction = dynamic_cast(action); -// if (!spellAction) -// return 1.0f; - -// std::string const spell = spellAction->getName(); -// uint32 spellId = AI_VALUE2(uint32, "spell id", spell); -// SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); -// if (!spellInfo || spellInfo->PowerType != POWER_MANA) -// return 1.0f; - -// if (mediumMana && dynamic_cast(action)) -// return 0.0f; - -// if (target && ((int)target->GetLevel() - (int)bot->GetLevel()) >= 0) -// return 1.0f; - -// return 1.0f; -// } - -// float SaveManaMultiplier::GetValue(Action* action) -// { -// if (!action) -// return 1.0f; - -// if (action->GetTarget() != AI_VALUE(Unit*, "current target")) -// return 1.0f; - -// double saveLevel = AI_VALUE(double, "mana save level"); -// if (saveLevel <= 1.0) -// return 1.0f; - -// CastSpellAction* spellAction = dynamic_cast(action); -// if (!spellAction) -// return 1.0f; - -// std::string const spell = spellAction->getName(); -// uint32 spellId = AI_VALUE2(uint32, "spell id", spell); -// SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); -// if (!spellInfo || spellInfo->PowerType != POWER_MANA) -// return 1.0f; - -// int32 cost = spellInfo->ManaCost; -// if (!cost) -// return 1.0f; - -// time_t lastCastTime = AI_VALUE2(time_t, "last spell cast time", spell); -// if (!lastCastTime) -// return 1.0f; - -// time_t elapsed = time(nullptr) - lastCastTime; -// if ((double)elapsed < 10 * saveLevel) -// return 0.0f; - -// return 1.0f; -// } - -// void ConserveManaStrategy::InitMultipliers(std::vector& multipliers) -// { -// multipliers.push_back(new ConserveManaMultiplier(botAI)); -// } - -float HealerAutoSaveManaMultiplier::GetValue(Action* action) +float HealerAutoSaveManaMultiplier::GetValue(Action& action) { uint8 mana = bot->GetPowerPct(Powers::POWER_MANA); - if (mana > sPlayerbotAIConfig->saveManaThreshold) + if (mana > sPlayerbotAIConfig.saveManaThreshold) return 1.0f; - CastHealingSpellAction* healingAction = dynamic_cast(action); + CastHealingSpellAction* healingAction = dynamic_cast(&action); - if (!healingAction) + if (healingAction == nullptr) return 1.0f; Unit* target = healingAction->GetTarget(); - if (!target) + if (target == nullptr) return 1.0f; bool isTank = target->ToPlayer() ? botAI->IsTank(target->ToPlayer()) : false; uint8 health = target->GetHealthPct(); HealingManaEfficiency manaEfficiency = healingAction->manaEfficiency; uint8 estAmount = healingAction->estAmount; uint8 lossAmount = 100 - health; + if (isTank) { estAmount /= 1.5; // tanks have more health - if (health >= sPlayerbotAIConfig->mediumHealth && + if (health >= sPlayerbotAIConfig.mediumHealth && (lossAmount < estAmount || manaEfficiency <= HealingManaEfficiency::MEDIUM)) return 0.0f; - if (health >= sPlayerbotAIConfig->lowHealth && + if (health >= sPlayerbotAIConfig.lowHealth && (lossAmount < estAmount || manaEfficiency <= HealingManaEfficiency::LOW)) return 0.0f; + + return 1.0f; } - else - { - if (health >= sPlayerbotAIConfig->mediumHealth && - (lossAmount < estAmount || manaEfficiency <= HealingManaEfficiency::MEDIUM)) - return 0.0f; - if (lossAmount < estAmount || manaEfficiency <= HealingManaEfficiency::LOW) - return 0.0f; - } + if (health >= sPlayerbotAIConfig.mediumHealth && + (lossAmount < estAmount || manaEfficiency <= HealingManaEfficiency::MEDIUM)) + return 0.0f; + if (lossAmount < estAmount || manaEfficiency <= HealingManaEfficiency::LOW) + return 0.0f; + return 1.0f; } diff --git a/src/Ai/Base/Strategy/ConserveManaStrategy.h b/src/Ai/Base/Strategy/ConserveManaStrategy.h index 000399f19f..d639d99a91 100644 --- a/src/Ai/Base/Strategy/ConserveManaStrategy.h +++ b/src/Ai/Base/Strategy/ConserveManaStrategy.h @@ -15,7 +15,7 @@ class HealerAutoSaveManaMultiplier : public Multiplier public: HealerAutoSaveManaMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "save mana") {} - float GetValue(Action* action) override; + float GetValue(Action& action) override; }; class HealerAutoSaveManaStrategy : public Strategy diff --git a/src/Ai/Base/Strategy/DeadStrategy.cpp b/src/Ai/Base/Strategy/DeadStrategy.cpp index 61399fa10e..9aeb510a3e 100644 --- a/src/Ai/Base/Strategy/DeadStrategy.cpp +++ b/src/Ai/Base/Strategy/DeadStrategy.cpp @@ -5,28 +5,79 @@ #include "DeadStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "ReleaseSpiritAction.h" +#include "ReviveFromCorpseAction.h" +#include "AcceptResurrectAction.h" void DeadStrategy::InitTriggers(std::vector& triggers) { PassTroughStrategy::InitTriggers(triggers); triggers.push_back( - new TriggerNode("often", { NextAction("auto release", relevance) })); + new TriggerNode( + "often", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("bg active", { NextAction("auto release", relevance) })); + new TriggerNode( + "bg active", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("dead", { NextAction("find corpse", relevance) })); - triggers.push_back(new TriggerNode( - "corpse near", { NextAction("revive from corpse", relevance - 1.0f) })); - triggers.push_back(new TriggerNode("resurrect request", - { NextAction("accept resurrect", relevance) })); + new TriggerNode( + "dead", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("falling far", { NextAction("repop", relevance + 1.f) })); + new TriggerNode( + "corpse near", + { + CreateNextAction(relevance - 1.0f) + } + ) + ); triggers.push_back( - new TriggerNode("location stuck", { NextAction("repop", relevance + 1) })); - triggers.push_back(new TriggerNode( - "can self resurrect", { NextAction("self resurrect", relevance + 2.0f) })); + new TriggerNode( + "resurrect request", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "falling far", + { + CreateNextAction(relevance + 1.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "location stuck", + { + CreateNextAction(relevance + 1.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "can self resurrect", + { + CreateNextAction(relevance + 2.0f) + } + ) + ); } DeadStrategy::DeadStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI) {} diff --git a/src/Ai/Base/Strategy/DebugStrategy.cpp b/src/Ai/Base/Strategy/DebugStrategy.cpp deleted file mode 100644 index bae6b419d8..0000000000 --- a/src/Ai/Base/Strategy/DebugStrategy.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it - * and/or modify it under version 3 of the License, or (at your option), any later version. - */ - -#include "DebugStrategy.h" - -#include "Playerbots.h" diff --git a/src/Ai/Base/Strategy/DpsAssistStrategy.cpp b/src/Ai/Base/Strategy/DpsAssistStrategy.cpp index 8ead279bd4..050b4793fc 100644 --- a/src/Ai/Base/Strategy/DpsAssistStrategy.cpp +++ b/src/Ai/Base/Strategy/DpsAssistStrategy.cpp @@ -5,16 +5,29 @@ #include "DpsAssistStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "ChooseTargetActions.h" void DpsAssistStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("not dps target active", { NextAction("dps assist", 50.0f) })); + new TriggerNode( + "not dps target active", + { + CreateNextAction(50.0f) + } + ) + ); } void DpsAoeStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("not dps aoe target active", { NextAction("dps aoe", 50.0f) })); + new TriggerNode( + "not dps aoe target active", + { + CreateNextAction(50.0f) + } + ) + ); } diff --git a/src/Ai/Base/Strategy/DuelStrategy.cpp b/src/Ai/Base/Strategy/DuelStrategy.cpp index 4c08397e6b..9618b4ec82 100644 --- a/src/Ai/Base/Strategy/DuelStrategy.cpp +++ b/src/Ai/Base/Strategy/DuelStrategy.cpp @@ -5,20 +5,34 @@ #include "DuelStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "AcceptDuelAction.h" +#include "AttackAction.h" void DuelStrategy::InitTriggers(std::vector& triggers) { PassTroughStrategy::InitTriggers(triggers); triggers.push_back( - new TriggerNode("duel requested", { NextAction("accept duel", relevance) })); + new TriggerNode( + "duel requested", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("no attackers", { NextAction("attack duel opponent", 70.0f) })); + new TriggerNode( + "no attackers", + { + CreateNextAction(70.0f) + } + ) + ); } DuelStrategy::DuelStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI) {} -void StartDuelStrategy::InitTriggers(std::vector& triggers) {} +void StartDuelStrategy::InitTriggers(std::vector&) {} StartDuelStrategy::StartDuelStrategy(PlayerbotAI* botAI) : Strategy(botAI) {} diff --git a/src/Ai/Base/Strategy/EmoteStrategy.cpp b/src/Ai/Base/Strategy/EmoteStrategy.cpp index 9419e0c386..e4addf90f3 100644 --- a/src/Ai/Base/Strategy/EmoteStrategy.cpp +++ b/src/Ai/Base/Strategy/EmoteStrategy.cpp @@ -5,31 +5,83 @@ #include "EmoteStrategy.h" -#include "Playerbots.h" +#include "PlayerbotAIConfig.h" +#include "CreateNextAction.h" +#include "EmoteAction.h" +#include "SuggestWhatToDoAction.h" +#include "GreetAction.h" +#include "RpgSubActions.h" void EmoteStrategy::InitTriggers(std::vector& triggers) { - if (sPlayerbotAIConfig->randomBotEmote) + if (PlayerbotAIConfig::instance().randomBotEmote) { - triggers.push_back(new TriggerNode("often", { NextAction("talk", 1.0f) })); - triggers.push_back(new TriggerNode("seldom", { NextAction("emote", 1.0f) })); triggers.push_back( - new TriggerNode("receive text emote", { NextAction("emote", 10.0f) })); + new TriggerNode( + "often", + { + CreateNextAction(1.0f) + } + ) + ); triggers.push_back( - new TriggerNode("receive emote", { NextAction("emote", 10.0f) })); + new TriggerNode( + "seldom", + { + CreateNextAction(1.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "receive text emote", + { + CreateNextAction(10.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "receive emote", + { + CreateNextAction(10.0f) + } + ) + ); } - if (sPlayerbotAIConfig->randomBotTalk) + if (PlayerbotAIConfig::instance().randomBotTalk) { - triggers.push_back(new TriggerNode( - "often", - { NextAction("suggest what to do", 10.0f), NextAction("suggest dungeon", 3.0f), - NextAction("suggest trade", 3.0f) })); + triggers.push_back( + new TriggerNode( + "often", + { + CreateNextAction(10.0f), + CreateNextAction(3.0f), + CreateNextAction(3.0f) + } + ) + ); } - if (sPlayerbotAIConfig->enableGreet) + if (PlayerbotAIConfig::instance().enableGreet) + { triggers.push_back( - new TriggerNode("new player nearby", { NextAction("greet", 1.0f) })); + new TriggerNode( + "new player nearby", + { + CreateNextAction(1.0f) + } + ) + ); + } - triggers.push_back(new TriggerNode("often", { NextAction("rpg mount anim", 1.0f) })); + triggers.push_back( + new TriggerNode( + "often", + { + CreateNextAction(1.0f) + } + ) + ); } diff --git a/src/Ai/Base/Strategy/FleeStrategy.cpp b/src/Ai/Base/Strategy/FleeStrategy.cpp index 663738306b..8ec617ebbc 100644 --- a/src/Ai/Base/Strategy/FleeStrategy.cpp +++ b/src/Ai/Base/Strategy/FleeStrategy.cpp @@ -5,20 +5,45 @@ #include "FleeStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "MovementActions.h" void FleeStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("panic", { NextAction("flee", ACTION_EMERGENCY + 9) })); + new TriggerNode( + "panic", + { + CreateNextAction(ACTION_EMERGENCY + 9.0f) + } + ) + ); triggers.push_back( - new TriggerNode("outnumbered", { NextAction("flee", ACTION_EMERGENCY + 9) })); + new TriggerNode( + "outnumbered", + { + CreateNextAction(ACTION_EMERGENCY + 9.0f) + } + ) + ); triggers.push_back( - new TriggerNode("critical health", { NextAction("flee", ACTION_MEDIUM_HEAL) })); + new TriggerNode( + "critical health", + { + CreateNextAction(ACTION_MEDIUM_HEAL) + } + ) + ); } void FleeFromAddsStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("has nearest adds", { NextAction("runaway", 50.0f) })); + new TriggerNode( + "has nearest adds", + { + CreateNextAction(50.0f) + } + ) + ); } diff --git a/src/Ai/Base/Strategy/FollowMasterStrategy.cpp b/src/Ai/Base/Strategy/FollowMasterStrategy.cpp index 0308b113f9..21bb140c90 100644 --- a/src/Ai/Base/Strategy/FollowMasterStrategy.cpp +++ b/src/Ai/Base/Strategy/FollowMasterStrategy.cpp @@ -5,15 +5,16 @@ #include "FollowMasterStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "FollowActions.h" std::vector FollowMasterStrategy::getDefaultActions() { return { - NextAction("follow", 1.0f) + CreateNextAction(1.0f) }; } -void FollowMasterStrategy::InitTriggers(std::vector& triggers) +void FollowMasterStrategy::InitTriggers(std::vector&) { } diff --git a/src/Ai/Base/Strategy/GrindingStrategy.cpp b/src/Ai/Base/Strategy/GrindingStrategy.cpp index 2db8cd87d6..9f03ccc5ba 100644 --- a/src/Ai/Base/Strategy/GrindingStrategy.cpp +++ b/src/Ai/Base/Strategy/GrindingStrategy.cpp @@ -5,24 +5,27 @@ #include "GrindingStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "DrinkAction.h" +#include "NonCombatActions.h" +#include "ChooseTargetActions.h" +#include "MovementActions.h" std::vector GrindingStrategy::getDefaultActions() { return { - NextAction("drink", 4.2f), - NextAction("food", 4.1f), + CreateNextAction(4.2f), + CreateNextAction(4.1f), }; } void GrindingStrategy::InitTriggers(std::vector& triggers) { - // reduce lower than loot triggers.push_back( new TriggerNode( "no target", { - NextAction("attack anything", 4.0f) + CreateNextAction(4.0f) } ) ); @@ -34,7 +37,7 @@ void MoveRandomStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "often", { - NextAction("move random", 1.5f) + CreateNextAction(1.5f) } ) ); diff --git a/src/Ai/Base/Strategy/GroupStrategy.cpp b/src/Ai/Base/Strategy/GroupStrategy.cpp index 1b81faa9ff..ddf6c732d3 100644 --- a/src/Ai/Base/Strategy/GroupStrategy.cpp +++ b/src/Ai/Base/Strategy/GroupStrategy.cpp @@ -5,12 +5,43 @@ #include "GroupStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "InviteToGroupAction.h" +#include "LeaveGroupAction.h" +#include "ResetInstancesAction.h" void GroupStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("often", { NextAction("invite nearby", 4.0f) })); - triggers.push_back(new TriggerNode("random", { NextAction("invite guild", 4.0f) })); - triggers.push_back(new TriggerNode("random", { NextAction("leave far away", 4.0f) })); - triggers.push_back(new TriggerNode("seldom", { NextAction("reset instances", 1.0f) })); + triggers.push_back( + new TriggerNode( + "often", + { + CreateNextAction(4.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "random", + { + CreateNextAction(4.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "random", + { + CreateNextAction(4.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "seldom", + { + CreateNextAction(1.0f) + } + ) + ); } diff --git a/src/Ai/Base/Strategy/GuardStrategy.cpp b/src/Ai/Base/Strategy/GuardStrategy.cpp index 9a396ac57f..d82c04582a 100644 --- a/src/Ai/Base/Strategy/GuardStrategy.cpp +++ b/src/Ai/Base/Strategy/GuardStrategy.cpp @@ -5,13 +5,14 @@ #include "GuardStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "PositionAction.h" std::vector GuardStrategy::getDefaultActions() { return { - NextAction("guard", 4.0f) + CreateNextAction(4.0f) }; } -void GuardStrategy::InitTriggers(std::vector& triggers) {} +void GuardStrategy::InitTriggers(std::vector&) {} diff --git a/src/Ai/Base/Strategy/GuildStrategy.cpp b/src/Ai/Base/Strategy/GuildStrategy.cpp index d2594504d5..f1aecd76c3 100644 --- a/src/Ai/Base/Strategy/GuildStrategy.cpp +++ b/src/Ai/Base/Strategy/GuildStrategy.cpp @@ -5,18 +5,50 @@ #include "GuildStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "GuildCreateActions.h" +#include "GuildManagementActions.h" void GuildStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("often", { NextAction("offer petition nearby", 4.0f) })); + new TriggerNode( + "often", + { + CreateNextAction(4.0f) + } + ) + ); triggers.push_back( - new TriggerNode("often", { NextAction("guild manage nearby", 4.0f) })); + new TriggerNode( + "often", + { + CreateNextAction(4.0f) + } + ) + ); triggers.push_back( - new TriggerNode("petition signed", { NextAction("turn in petition", 10.0f) })); + new TriggerNode( + "petition signed", + { + CreateNextAction(10.0f) + } + ) + ); triggers.push_back( - new TriggerNode("buy tabard", { NextAction("buy tabard", 10.0f) })); + new TriggerNode( + "buy tabard", + { + CreateNextAction(10.0f) + } + ) + ); triggers.push_back( - new TriggerNode("leave large guild", { NextAction("guild leave", 4.0f) })); + new TriggerNode( + "leave large guild", + { + CreateNextAction(4.0f) + } + ) + ); } diff --git a/src/Ai/Base/Strategy/KiteStrategy.cpp b/src/Ai/Base/Strategy/KiteStrategy.cpp index 2d4964460e..dfc3346617 100644 --- a/src/Ai/Base/Strategy/KiteStrategy.cpp +++ b/src/Ai/Base/Strategy/KiteStrategy.cpp @@ -5,11 +5,19 @@ #include "KiteStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "MovementActions.h" KiteStrategy::KiteStrategy(PlayerbotAI* botAI) : Strategy(botAI) {} void KiteStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("has aggro", { NextAction("runaway", 51.0f) })); + triggers.push_back( + new TriggerNode( + "has aggro", + { + CreateNextAction(51.0f) + } + ) + ); } diff --git a/src/Ai/Base/Strategy/LfgStrategy.cpp b/src/Ai/Base/Strategy/LfgStrategy.cpp index b6057881ca..8ac1ff2d06 100644 --- a/src/Ai/Base/Strategy/LfgStrategy.cpp +++ b/src/Ai/Base/Strategy/LfgStrategy.cpp @@ -5,15 +5,36 @@ #include "LfgStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "LfgActions.h" +#include "PassLeadershipToMasterAction.h" void LfgStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("random", { NextAction("lfg join", relevance) })); triggers.push_back( - new TriggerNode("seldom", { NextAction("lfg leave", relevance) })); - triggers.push_back(new TriggerNode( - "unknown dungeon", { NextAction("give leader in dungeon", relevance) })); + new TriggerNode( + "random", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "seldom", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "unknown dungeon", + { + CreateNextAction(relevance) + } + ) + ); } LfgStrategy::LfgStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI) {} diff --git a/src/Ai/Base/Strategy/LootNonCombatStrategy.cpp b/src/Ai/Base/Strategy/LootNonCombatStrategy.cpp index 5ecbb6959f..3a0399755b 100644 --- a/src/Ai/Base/Strategy/LootNonCombatStrategy.cpp +++ b/src/Ai/Base/Strategy/LootNonCombatStrategy.cpp @@ -5,33 +5,89 @@ #include "LootNonCombatStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "LootAction.h" +#include "MovementActions.h" +#include "AddLootAction.h" +#include "RevealGatheringItemAction.h" +#include "FishingAction.h" void LootNonCombatStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("loot available", { NextAction("loot", 6.0f) })); triggers.push_back( - new TriggerNode("far from loot target", { NextAction("move to loot", 7.0f) })); - triggers.push_back(new TriggerNode("can loot", { NextAction("open loot", 8.0f) })); - triggers.push_back(new TriggerNode("often", { NextAction("add all loot", 5.0f) })); + new TriggerNode( + "loot available", + { + CreateNextAction(6.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "far from loot target", + { + CreateNextAction(7.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "can loot", + { + CreateNextAction(8.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "often", + { + CreateNextAction(5.0f) + } + ) + ); } void GatherStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("timer", { NextAction("add gathering loot", 5.0f) })); + new TriggerNode( + "timer", + { + CreateNextAction(5.0f) + } + ) + ); } void RevealStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("often", { NextAction("reveal gathering item", 50.0f) })); + new TriggerNode( + "often", + { + CreateNextAction(50.0f) + } + ) + ); } void UseBobberStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("can use fishing bobber", { NextAction("use fishing bobber", 20.0f) })); + new TriggerNode( + "can use fishing bobber", + { + CreateNextAction(20.0f) + } + ) + ); triggers.push_back( - new TriggerNode("random", { NextAction("remove bobber strategy", 20.0f) })); + new TriggerNode( + "random", + { + CreateNextAction(20.0f) + } + ) + ); } diff --git a/src/Ai/Base/Strategy/MaintenanceStrategy.cpp b/src/Ai/Base/Strategy/MaintenanceStrategy.cpp index 855555edda..0e0c282e2d 100644 --- a/src/Ai/Base/Strategy/MaintenanceStrategy.cpp +++ b/src/Ai/Base/Strategy/MaintenanceStrategy.cpp @@ -5,7 +5,12 @@ #include "MaintenanceStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "DropQuestAction.h" +#include "UseItemAction.h" +#include "CastCustomSpellAction.h" +#include "DestroyItemAction.h" +#include "ShareQuestAction.h" std::vector MaintenanceStrategy::getDefaultActions() { return {}; } @@ -15,7 +20,7 @@ void MaintenanceStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "random", { - NextAction("clean quest log", 6.0f) + CreateNextAction(6.0f) } ) ); @@ -23,7 +28,7 @@ void MaintenanceStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "random", { - NextAction("use random recipe", 1.0f) + CreateNextAction(1.0f) } ) ); @@ -31,7 +36,7 @@ void MaintenanceStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "random", { - NextAction("disenchant random item", 1.0f) + CreateNextAction(1.0f) } ) ); @@ -39,7 +44,7 @@ void MaintenanceStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "random", { - NextAction("enchant random item", 1.0f) + CreateNextAction(1.0f) } ) ); @@ -47,23 +52,24 @@ void MaintenanceStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "random", { - NextAction("smart destroy item", 1.0f) - } - ) - ); - triggers.push_back( - new TriggerNode( - "move stuck", - { - NextAction("reset", 1.0f) + CreateNextAction(1.0f) } ) ); + // It seems "reset" has no attached creator + // triggers.push_back( + // new TriggerNode( + // "move stuck", + // { + // CreateNextAction("reset", 1.0f) + // } + // ) + // ); triggers.push_back( new TriggerNode( "random", { - NextAction("use random quest item", 0.9f) + CreateNextAction(0.9f) } ) ); @@ -71,7 +77,7 @@ void MaintenanceStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "random", { - NextAction("auto share quest", 0.9f) + CreateNextAction(0.9f) } ) ); diff --git a/src/Ai/Base/Strategy/MarkRtiStrategy.cpp b/src/Ai/Base/Strategy/MarkRtiStrategy.cpp index 8d49c9a8a0..70ff8784bd 100644 --- a/src/Ai/Base/Strategy/MarkRtiStrategy.cpp +++ b/src/Ai/Base/Strategy/MarkRtiStrategy.cpp @@ -5,10 +5,17 @@ #include "MarkRtiStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "RtiAction.h" void MarkRtiStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("no rti target", { NextAction("mark rti", ACTION_NORMAL) })); + new TriggerNode( + "no rti target", + { + CreateNextAction(ACTION_NORMAL) + } + ) + ); } diff --git a/src/Ai/Base/Strategy/MeleeCombatStrategy.cpp b/src/Ai/Base/Strategy/MeleeCombatStrategy.cpp index bc2d189134..e727ed9980 100644 --- a/src/Ai/Base/Strategy/MeleeCombatStrategy.cpp +++ b/src/Ai/Base/Strategy/MeleeCombatStrategy.cpp @@ -5,20 +5,34 @@ #include "MeleeCombatStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "ReachTargetActions.h" +#include "MovementActions.h" void MeleeCombatStrategy::InitTriggers(std::vector& triggers) { CombatStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode( - "enemy out of melee", { NextAction("reach melee", ACTION_HIGH + 1) })); + triggers.push_back( + new TriggerNode( + "enemy out of melee", + { + CreateNextAction(ACTION_HIGH + 1.0f) + } + ) + ); } void SetBehindCombatStrategy::InitTriggers(std::vector& triggers) { CombatStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("not behind target", - { NextAction("set behind", ACTION_MOVE + 7) })); + triggers.push_back( + new TriggerNode( + "not behind target", + { + CreateNextAction(ACTION_MOVE + 7.0f) + } + ) + ); } diff --git a/src/Ai/Base/Strategy/MoveFromGroupStrategy.cpp b/src/Ai/Base/Strategy/MoveFromGroupStrategy.cpp index 247abc88ec..5997df2930 100644 --- a/src/Ai/Base/Strategy/MoveFromGroupStrategy.cpp +++ b/src/Ai/Base/Strategy/MoveFromGroupStrategy.cpp @@ -5,12 +5,13 @@ #include "MoveFromGroupStrategy.h" #include "PassiveMultiplier.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "MovementActions.h" std::vector MoveFromGroupStrategy::getDefaultActions() { return { - NextAction("move from group", 1.0f) + CreateNextAction(1.0f) }; } diff --git a/src/Ai/Base/Strategy/NonCombatStrategy.cpp b/src/Ai/Base/Strategy/NonCombatStrategy.cpp index 6b8f76ac95..2f1cd63fe0 100644 --- a/src/Ai/Base/Strategy/NonCombatStrategy.cpp +++ b/src/Ai/Base/Strategy/NonCombatStrategy.cpp @@ -5,21 +5,56 @@ #include "NonCombatStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "DropQuestAction.h" +#include "CheckMountStateAction.h" +#include "MovementActions.h" +#include "WorldBuffAction.h" +#include "FishingAction.h" +#include "EquipAction.h" +#include "ManageInventoryAction.h" void NonCombatStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("random", { NextAction("clean quest log", 1.0f) })); - triggers.push_back(new TriggerNode("timer", { NextAction("check mount state", 1.0f) })); + triggers.push_back( + new TriggerNode( + "random", + { + CreateNextAction(1.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "seldom", + { + CreateNextAction(1.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "timer", + { + CreateNextAction(1.0f) + } + ) + ); } void CollisionStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("collision", { NextAction("move out of collision", 2.0f) })); + new TriggerNode( + "collision", + { + CreateNextAction(2.0f) + } + ) + ); } -void MountStrategy::InitTriggers(std::vector& triggers) +void MountStrategy::InitTriggers(std::vector&) { } @@ -29,7 +64,7 @@ void WorldBuffStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "need world buff", { - NextAction("world buff", 1.0f) + CreateNextAction(1.0f) } ) ); @@ -41,7 +76,7 @@ void MasterFishingStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "very often", { - NextAction("move near water" , 10.0f) + CreateNextAction(10.0f) } ) ); @@ -49,7 +84,7 @@ void MasterFishingStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "very often", { - NextAction("go fishing" , 10.0f) + CreateNextAction(10.0f) } ) ); @@ -57,8 +92,8 @@ void MasterFishingStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "random", { - NextAction("end master fishing", 12.0f), - NextAction("equip upgrades", 6.0f) + CreateNextAction(12.0f), + CreateNextAction(6.0f) } ) ); diff --git a/src/Ai/Base/Strategy/PassTroughStrategy.cpp b/src/Ai/Base/Strategy/PassTroughStrategy.cpp index 228106df44..984f861a8c 100644 --- a/src/Ai/Base/Strategy/PassTroughStrategy.cpp +++ b/src/Ai/Base/Strategy/PassTroughStrategy.cpp @@ -4,12 +4,22 @@ */ #include "PassTroughStrategy.h" - -#include "Playerbots.h" +#include "NextAction.h" void PassTroughStrategy::InitTriggers(std::vector& triggers) { - for (std::vector::iterator i = supported.begin(); i != supported.end(); i++) + for (std::vector::iterator i = this->supported.begin(); i != this->supported.end(); i++) + { triggers.push_back( - new TriggerNode(i->c_str(), { NextAction(i->c_str(), relevance) })); + new TriggerNode( + i->name, + { + NextAction{ + .weight = relevance, + .factory = i->factory + }, + } + ) + ); + } } diff --git a/src/Ai/Base/Strategy/PassTroughStrategy.h b/src/Ai/Base/Strategy/PassTroughStrategy.h index b3f897e2c3..bdd90b0a17 100644 --- a/src/Ai/Base/Strategy/PassTroughStrategy.h +++ b/src/Ai/Base/Strategy/PassTroughStrategy.h @@ -6,6 +6,7 @@ #ifndef _PLAYERBOT_PASSTHROUGHSTRATEGY_H #define _PLAYERBOT_PASSTHROUGHSTRATEGY_H +#include "PassTroughStrategy/definition/struct/passthrough-strategy-supported-actions.struct.h" #include "Strategy.h" class PlayerbotAI; @@ -18,7 +19,7 @@ class PassTroughStrategy : public Strategy void InitTriggers(std::vector& triggers) override; protected: - std::vector supported; + std::vector supported; float relevance; }; diff --git a/src/Ai/Base/Strategy/PassTroughStrategy/definition/struct/passthrough-strategy-supported-actions.struct.h b/src/Ai/Base/Strategy/PassTroughStrategy/definition/struct/passthrough-strategy-supported-actions.struct.h new file mode 100644 index 0000000000..dff924b745 --- /dev/null +++ b/src/Ai/Base/Strategy/PassTroughStrategy/definition/struct/passthrough-strategy-supported-actions.struct.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +#include "NextAction.h" + +struct PassthroughStrategySupportedActionsStruct +{ + std::string name; + NextAction::Factory factory; +}; diff --git a/src/Ai/Base/Strategy/PassiveStrategy.cpp b/src/Ai/Base/Strategy/PassiveStrategy.cpp index 700b9e6770..2dbedf8a2d 100644 --- a/src/Ai/Base/Strategy/PassiveStrategy.cpp +++ b/src/Ai/Base/Strategy/PassiveStrategy.cpp @@ -6,7 +6,6 @@ #include "PassiveStrategy.h" #include "PassiveMultiplier.h" -#include "Playerbots.h" void PassiveStrategy::InitMultipliers(std::vector& multipliers) { diff --git a/src/Ai/Base/Strategy/PullStrategy.cpp b/src/Ai/Base/Strategy/PullStrategy.cpp index d0c7c9eacb..f4b0a5e068 100644 --- a/src/Ai/Base/Strategy/PullStrategy.cpp +++ b/src/Ai/Base/Strategy/PullStrategy.cpp @@ -6,25 +6,26 @@ #include "PullStrategy.h" #include "PassiveMultiplier.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "FollowActions.h" +#include "ChangeStrategyAction.h" +#include "MovementActions.h" class MagePullMultiplier : public PassiveMultiplier { public: MagePullMultiplier(PlayerbotAI* botAI, std::string const action) : PassiveMultiplier(botAI), actionName(action) {} - float GetValue(Action* action) override; + float GetValue(Action& action) override; private: std::string const actionName; }; -float MagePullMultiplier::GetValue(Action* action) +float MagePullMultiplier::GetValue(Action& action) { - if (!action) - return 1.0f; + std::string const name = action.getName(); - std::string const name = action->getName(); if (actionName == name || name == "reach spell" || name == "change strategy") return 1.0f; @@ -33,10 +34,20 @@ float MagePullMultiplier::GetValue(Action* action) std::vector PullStrategy::getDefaultActions() { + NextAction::Factory actionFactory = ActionFactoryRegistry::GetFactoryByName(action); + + if (actionFactory == nullptr) + { + return Strategy::getDefaultActions(); + } + return { - NextAction(action, 105.0f), - NextAction("follow", 104.0f), - NextAction("end pull", 103.0f), + { + .weight = 105.0f, + .factory = actionFactory, + }, + CreateNextAction(104.0f), + CreateNextAction(103.0f), }; } @@ -56,7 +67,7 @@ void PossibleAddsStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "possible adds", { - NextAction("flee with pet", 60) + CreateNextAction(60.0f) } ) ); diff --git a/src/Ai/Base/Strategy/QuestStrategies.cpp b/src/Ai/Base/Strategy/QuestStrategies.cpp index adcc4b22b5..50988ebc94 100644 --- a/src/Ai/Base/Strategy/QuestStrategies.cpp +++ b/src/Ai/Base/Strategy/QuestStrategies.cpp @@ -5,28 +5,52 @@ #include "QuestStrategies.h" -#include "Playerbots.h" - -QuestStrategy::QuestStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI) { supported.push_back("accept quest"); } +#include "CreateNextAction.h" +#include "AcceptQuestAction.h" +#include "TalkToQuestGiverAction.h" void QuestStrategy::InitTriggers(std::vector& triggers) { PassTroughStrategy::InitTriggers(triggers); triggers.push_back( - new TriggerNode("quest share", { NextAction("accept quest share", relevance) })); + new TriggerNode( + "quest share", + { + CreateNextAction(relevance) + } + ) + ); } void DefaultQuestStrategy::InitTriggers(std::vector& triggers) { QuestStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode( - "use game object", { NextAction("talk to quest giver", relevance) })); - triggers.push_back(new TriggerNode( - "gossip hello", { NextAction("talk to quest giver", relevance) })); - triggers.push_back(new TriggerNode( - "complete quest", { NextAction("talk to quest giver", relevance) })); + triggers.push_back( + new TriggerNode( + "use game object", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "gossip hello", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "complete quest", + { + CreateNextAction(relevance) + } + ) + ); } DefaultQuestStrategy::DefaultQuestStrategy(PlayerbotAI* botAI) : QuestStrategy(botAI) {} @@ -36,14 +60,29 @@ void AcceptAllQuestsStrategy::InitTriggers(std::vector& triggers) QuestStrategy::InitTriggers(triggers); triggers.push_back( - new TriggerNode("use game object", { NextAction("talk to quest giver", relevance), - NextAction("accept all quests", relevance) })); + new TriggerNode("use game object", + { + CreateNextAction(relevance), + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("gossip hello", { NextAction("talk to quest giver", relevance), - NextAction("accept all quests", relevance) })); + new TriggerNode("gossip hello", + { + CreateNextAction(relevance), + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("complete quest", { NextAction("talk to quest giver", relevance), - NextAction("accept all quests", relevance) })); + new TriggerNode("complete quest", + { + CreateNextAction(relevance), + CreateNextAction(relevance) + } + ) + ); } AcceptAllQuestsStrategy::AcceptAllQuestsStrategy(PlayerbotAI* botAI) : QuestStrategy(botAI) {} diff --git a/src/Ai/Base/Strategy/QuestStrategies.h b/src/Ai/Base/Strategy/QuestStrategies.h index 232d19428b..44d35e482a 100644 --- a/src/Ai/Base/Strategy/QuestStrategies.h +++ b/src/Ai/Base/Strategy/QuestStrategies.h @@ -6,6 +6,8 @@ #ifndef _PLAYERBOT_QUESTSTRATEGIES_H #define _PLAYERBOT_QUESTSTRATEGIES_H +#include "AcceptQuestAction.h" +#include "CreateAction.h" #include "PassTroughStrategy.h" class PlayerbotAI; @@ -13,7 +15,15 @@ class PlayerbotAI; class QuestStrategy : public PassTroughStrategy { public: - QuestStrategy(PlayerbotAI* botAI); + QuestStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI) + { + this->supported.push_back( + { + .name = "accept quest", + .factory = &CreateAction + } + ); + }; void InitTriggers(std::vector& triggers) override; }; diff --git a/src/Ai/Base/Strategy/RTSCStrategy.cpp b/src/Ai/Base/Strategy/RTSCStrategy.cpp index 2c64092e3c..daf8bfc579 100644 --- a/src/Ai/Base/Strategy/RTSCStrategy.cpp +++ b/src/Ai/Base/Strategy/RTSCStrategy.cpp @@ -5,8 +5,6 @@ #include "RTSCStrategy.h" -#include "Playerbots.h" - RTSCStrategy::RTSCStrategy(PlayerbotAI* botAI) : Strategy(botAI) {} -void RTSCStrategy::InitTriggers(std::vector& triggers) {} +void RTSCStrategy::InitTriggers(std::vector&) {} diff --git a/src/Ai/Base/Strategy/RacialsStrategy.cpp b/src/Ai/Base/Strategy/RacialsStrategy.cpp index f4f270b1b0..0ee00b35eb 100644 --- a/src/Ai/Base/Strategy/RacialsStrategy.cpp +++ b/src/Ai/Base/Strategy/RacialsStrategy.cpp @@ -5,36 +5,65 @@ #include "RacialsStrategy.h" -#include "Playerbots.h" +#include "ActionNode.h" +#include "CreateNextAction.h" +#include "GenericSpellActions.h" class RacialsStrategyActionNodeFactory : public NamedObjectFactory { public: - RacialsStrategyActionNodeFactory() { creators["lifeblood"] = &lifeblood; } + RacialsStrategyActionNodeFactory() + { + creators["lifeblood"] = &lifeblood; + } private: - static ActionNode* lifeblood(PlayerbotAI* botAI) + static ActionNode* lifeblood(PlayerbotAI*) { - return new ActionNode("lifeblood", - /*P*/ {}, - /*A*/ { NextAction("gift of the naaru") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } }; void RacialsStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("low health", { NextAction("lifeblood", ACTION_NORMAL + 5) })); + new TriggerNode( + "low health", + { + CreateNextAction(ACTION_NORMAL + 5.0f) + } + ) + ); triggers.push_back( - new TriggerNode("medium aoe", { NextAction("war stomp", ACTION_NORMAL + 5) })); - triggers.push_back(new TriggerNode( - "low mana", { NextAction("arcane torrent", ACTION_NORMAL + 5) })); - - triggers.push_back(new TriggerNode( - "generic boost", { NextAction("blood fury", ACTION_NORMAL + 5), - NextAction("berserking", ACTION_NORMAL + 5), - NextAction("use trinket", ACTION_NORMAL + 4) })); + new TriggerNode( + "medium aoe", + { + CreateNextAction(ACTION_NORMAL + 5.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "low mana", + { + CreateNextAction(ACTION_NORMAL + 5.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "generic boost", + { + CreateNextAction(ACTION_NORMAL + 5.0f), + CreateNextAction(ACTION_NORMAL + 5.0f), + CreateNextAction(ACTION_NORMAL + 4.0f) + } + ) + ); } diff --git a/src/Ai/Base/Strategy/RangedCombatStrategy.cpp b/src/Ai/Base/Strategy/RangedCombatStrategy.cpp index 73f26423a2..f948594aae 100644 --- a/src/Ai/Base/Strategy/RangedCombatStrategy.cpp +++ b/src/Ai/Base/Strategy/RangedCombatStrategy.cpp @@ -6,11 +6,19 @@ #include "RangedCombatStrategy.h" #include "Playerbots.h" +#include "CreateNextAction.h" +#include "MovementActions.h" void RangedCombatStrategy::InitTriggers(std::vector& triggers) { CombatStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("enemy too close for spell", - { NextAction("flee", ACTION_MOVE + 4) })); + triggers.push_back( + new TriggerNode( + "enemy too close for spell", + { + CreateNextAction(ACTION_MOVE + 4.0f) + } + ) + ); } diff --git a/src/Ai/Base/Strategy/ReturnStrategy.cpp b/src/Ai/Base/Strategy/ReturnStrategy.cpp index 2c88e64fdc..230fb61fe9 100644 --- a/src/Ai/Base/Strategy/ReturnStrategy.cpp +++ b/src/Ai/Base/Strategy/ReturnStrategy.cpp @@ -6,9 +6,18 @@ #include "ReturnStrategy.h" #include "Playerbots.h" +#include "CreateNextAction.h" +#include "PositionAction.h" void ReturnStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("return", { NextAction("set return position", 1.5f), - NextAction("return", 1.0f), })); + triggers.push_back( + new TriggerNode( + "return", + { + CreateNextAction(1.5f), + CreateNextAction(1.0f), + } + ) + ); } diff --git a/src/Ai/Base/Strategy/RpgStrategy.cpp b/src/Ai/Base/Strategy/RpgStrategy.cpp index 2c0b3544ef..1b92559197 100644 --- a/src/Ai/Base/Strategy/RpgStrategy.cpp +++ b/src/Ai/Base/Strategy/RpgStrategy.cpp @@ -5,29 +5,18 @@ #include "RpgStrategy.h" -#include "Playerbots.h" +#include "ChooseRpgTargetAction.h" +#include "CreateNextAction.h" +#include "MoveToRpgTargetAction.h" #include "RpgSubActions.h" - -float RpgActionMultiplier::GetValue(Action* action) -{ - if (action == nullptr) - return 1.0f; - - std::string const nextAction = AI_VALUE(std::string, "next rpg action"); - std::string const name = action->getName(); - - if (!nextAction.empty() && dynamic_cast(action) && name != nextAction) - return 0.0f; - - return 1.0f; -} +#include "RpgAction.h" RpgStrategy::RpgStrategy(PlayerbotAI* botAI) : Strategy(botAI) {} std::vector RpgStrategy::getDefaultActions() { return { - NextAction("rpg", 1.0f) + CreateNextAction(1.0f) }; } @@ -37,7 +26,7 @@ void RpgStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "no rpg target", { - NextAction("choose rpg target", 5.0f) + CreateNextAction(5.0f) } ) ); @@ -45,7 +34,7 @@ void RpgStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "often", { - NextAction("move random", 1.10f) + CreateNextAction(1.10f) } ) ); @@ -53,7 +42,7 @@ void RpgStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "far from rpg target", { - NextAction("move to rpg target", 5.0f) + CreateNextAction(5.0f) } ) ); @@ -63,7 +52,7 @@ void RpgStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "rpg", { - NextAction("rpg stay", 1.101f) + CreateNextAction(1.101f) } ) ); @@ -71,7 +60,7 @@ void RpgStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "rpg", { - NextAction("rpg work", 1.101f) + CreateNextAction(1.101f) } ) ); @@ -79,7 +68,7 @@ void RpgStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "rpg", { - NextAction("rpg emote", 1.101f) + CreateNextAction(1.101f) } ) ); @@ -87,7 +76,7 @@ void RpgStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "has rpg target", { - NextAction("rpg cancel", 1.101f) + CreateNextAction(1.101f) } ) ); @@ -95,7 +84,7 @@ void RpgStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "rpg discover", { - NextAction("rpg discover", 1.210f) + CreateNextAction(1.210f) } ) ); @@ -103,7 +92,7 @@ void RpgStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "rpg start quest", { - NextAction("rpg start quest", 1.180f) + CreateNextAction(1.180f) } ) ); @@ -111,7 +100,7 @@ void RpgStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "rpg end quest", { - NextAction("rpg end quest", 1.190f) + CreateNextAction(1.190f) } ) ); @@ -119,7 +108,7 @@ void RpgStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "rpg buy", { - NextAction("rpg buy", 1.130f) + CreateNextAction(1.130f) } ) ); @@ -127,7 +116,7 @@ void RpgStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "rpg repair", { - NextAction("rpg repair", 1.195f) + CreateNextAction(1.195f) } ) ); @@ -135,7 +124,7 @@ void RpgStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "rpg heal", { - NextAction("rpg heal", 1.125f) + CreateNextAction(1.125f) } ) ); @@ -143,7 +132,7 @@ void RpgStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "rpg home bind", { - NextAction("rpg home bind", 1.160f) + CreateNextAction(1.160f) } ) ); @@ -151,7 +140,7 @@ void RpgStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "rpg buy petition", { - NextAction("rpg buy petition", 1.140f) + CreateNextAction(1.140f) } ) ); @@ -159,7 +148,7 @@ void RpgStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "rpg use", { - NextAction("rpg use", 1.102f) + CreateNextAction(1.102f) } ) ); diff --git a/src/Ai/Base/Strategy/RpgStrategy.h b/src/Ai/Base/Strategy/RpgStrategy.h index cb1db70421..2799218f7c 100644 --- a/src/Ai/Base/Strategy/RpgStrategy.h +++ b/src/Ai/Base/Strategy/RpgStrategy.h @@ -6,6 +6,8 @@ #ifndef _PLAYERBOT_RPGSTRATEGY_H #define _PLAYERBOT_RPGSTRATEGY_H +#include "AiObjectContext.h" +#include "RpgSubActions.h" #include "Strategy.h" class PlayerbotAI; @@ -15,7 +17,18 @@ class RpgActionMultiplier : public Multiplier public: RpgActionMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "rpg action") {} - float GetValue(Action* action) override; + float GetValue(Action& action) override + { + const std::string nextAction = this->context->GetValue("next rpg action")->Get(); + const std::string name = action.getName(); + + if (!nextAction.empty() && dynamic_cast(&action) && name != nextAction) + { + return 0.0f; + } + + return 1.0f; + }; }; class RpgStrategy : public Strategy diff --git a/src/Ai/Base/Strategy/RunawayStrategy.cpp b/src/Ai/Base/Strategy/RunawayStrategy.cpp index 28868a48e8..f368ad6e8b 100644 --- a/src/Ai/Base/Strategy/RunawayStrategy.cpp +++ b/src/Ai/Base/Strategy/RunawayStrategy.cpp @@ -5,10 +5,17 @@ #include "RunawayStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "MovementActions.h" void RunawayStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("enemy too close for spell", { NextAction("runaway", 50.0f) })); + new TriggerNode( + "enemy too close for spell", + { + CreateNextAction(50.0f) + } + ) + ); } diff --git a/src/Ai/Base/Strategy/SayStrategy.cpp b/src/Ai/Base/Strategy/SayStrategy.cpp deleted file mode 100644 index 71a72b79f8..0000000000 --- a/src/Ai/Base/Strategy/SayStrategy.cpp +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it - * and/or modify it under version 3 of the License, or (at your option), any later version. - */ - -#include "SayStrategy.h" - -#include "Playerbots.h" - -void SayStrategy::InitTriggers(std::vector& triggers) -{ - triggers.push_back(new TriggerNode("critical health", - { NextAction("say::critical health", 99.0f) })); - triggers.push_back( - new TriggerNode("low health", { NextAction("say::low health", 99.0f) })); - triggers.push_back( - new TriggerNode("low mana", { NextAction("say::low mana", 99.0f) })); - triggers.push_back(new TriggerNode("tank aoe", { NextAction("say::taunt", 99.0f) })); - triggers.push_back(new TriggerNode("medium aoe", { NextAction("say::aoe", 99.0f) })); -} diff --git a/src/Ai/Base/Strategy/SayStrategy.h b/src/Ai/Base/Strategy/SayStrategy.h deleted file mode 100644 index f83ece59c4..0000000000 --- a/src/Ai/Base/Strategy/SayStrategy.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it - * and/or modify it under version 3 of the License, or (at your option), any later version. - */ - -#ifndef _PLAYERBOT_SAYSTRATEGY_H -#define _PLAYERBOT_SAYSTRATEGY_H - -#include "Strategy.h" - -class PlayerbotAI; - -class SayStrategy : public Strategy -{ -public: - SayStrategy(PlayerbotAI* botAI) : Strategy(botAI) {} - - void InitTriggers(std::vector& triggers) override; - std::string const getName() override { return "say"; } -}; - -#endif diff --git a/src/Ai/Base/Strategy/StayStrategy.cpp b/src/Ai/Base/Strategy/StayStrategy.cpp index a59f9461a5..2b95457d6b 100644 --- a/src/Ai/Base/Strategy/StayStrategy.cpp +++ b/src/Ai/Base/Strategy/StayStrategy.cpp @@ -6,6 +6,9 @@ #include "StayStrategy.h" #include "Playerbots.h" +#include "CreateNextAction.h" +#include "PositionAction.h" +#include "StayActions.h" void StayStrategy::InitTriggers(std::vector& triggers) { @@ -13,7 +16,7 @@ void StayStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "return to stay position", { - NextAction("return to stay position", ACTION_MOVE) + CreateNextAction(ACTION_MOVE) } ) ); @@ -22,7 +25,7 @@ void StayStrategy::InitTriggers(std::vector& triggers) std::vector StayStrategy::getDefaultActions() { return { - NextAction("stay", 1.0f) + CreateNextAction(1.0f) }; } @@ -32,7 +35,7 @@ void SitStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "sit", { - NextAction("sit", 1.5f) + CreateNextAction(1.5f) } ) ); diff --git a/src/Ai/Base/Strategy/TankAssistStrategy.cpp b/src/Ai/Base/Strategy/TankAssistStrategy.cpp index 4d4aae1a81..99ceba640c 100644 --- a/src/Ai/Base/Strategy/TankAssistStrategy.cpp +++ b/src/Ai/Base/Strategy/TankAssistStrategy.cpp @@ -5,10 +5,17 @@ #include "TankAssistStrategy.h" -#include "Playerbots.h" +#include "ChooseTargetActions.h" +#include "CreateNextAction.h" void TankAssistStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("tank assist", { NextAction("tank assist", 50.0f) })); + new TriggerNode( + "tank assist", + { + CreateNextAction(50.0f) + } + ) + ); } diff --git a/src/Ai/Base/Strategy/TellTargetStrategy.cpp b/src/Ai/Base/Strategy/TellTargetStrategy.cpp index c4c387f4fd..d93744090e 100644 --- a/src/Ai/Base/Strategy/TellTargetStrategy.cpp +++ b/src/Ai/Base/Strategy/TellTargetStrategy.cpp @@ -6,9 +6,17 @@ #include "TellTargetStrategy.h" #include "Playerbots.h" +#include "CreateNextAction.h" +#include "TellTargetAction.h" void TellTargetStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("target changed", { NextAction("tell target", 51.0f) })); + new TriggerNode( + "target changed", + { + CreateNextAction(51.0f) + } + ) + ); } diff --git a/src/Ai/Base/Strategy/ThreatStrategy.cpp b/src/Ai/Base/Strategy/ThreatStrategy.cpp index 4509eaa0b5..17df997d28 100644 --- a/src/Ai/Base/Strategy/ThreatStrategy.cpp +++ b/src/Ai/Base/Strategy/ThreatStrategy.cpp @@ -6,23 +6,22 @@ #include "ThreatStrategy.h" #include "GenericSpellActions.h" -#include "Map.h" #include "Playerbots.h" -float ThreatMultiplier::GetValue(Action* action) +float ThreatMultiplier::GetValue(Action& action) { if (AI_VALUE(bool, "neglect threat")) { return 1.0f; } - if (!action || action->getThreatType() == Action::ActionThreatType::None) + if (action.getThreatType() == Action::ActionThreatType::None) return 1.0f; if (!AI_VALUE(bool, "group")) return 1.0f; - if (action->getThreatType() == Action::ActionThreatType::Aoe) + if (action.getThreatType() == Action::ActionThreatType::Aoe) { uint8 threat = AI_VALUE2(uint8, "threat", "aoe"); if (threat >= 50) @@ -41,17 +40,14 @@ void ThreatStrategy::InitMultipliers(std::vector& multipliers) multipliers.push_back(new ThreatMultiplier(botAI)); } -float FocusMultiplier::GetValue(Action* action) +float FocusMultiplier::GetValue(Action& action) { - if (!action) - { - return 1.0f; - } - if (action->getThreatType() == Action::ActionThreatType::Aoe && !dynamic_cast(action)) + if (action.getThreatType() == Action::ActionThreatType::Aoe && !dynamic_cast(&action)) { return 0.0f; } - if (dynamic_cast(action)) + + if (dynamic_cast(&action)) { return 0.0f; } diff --git a/src/Ai/Base/Strategy/ThreatStrategy.h b/src/Ai/Base/Strategy/ThreatStrategy.h index d1815e8165..5b4cc673a7 100644 --- a/src/Ai/Base/Strategy/ThreatStrategy.h +++ b/src/Ai/Base/Strategy/ThreatStrategy.h @@ -15,7 +15,7 @@ class ThreatMultiplier : public Multiplier public: ThreatMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "threat") {} - float GetValue(Action* action) override; + float GetValue(Action& action) override; }; class ThreatStrategy : public Strategy @@ -32,7 +32,7 @@ class FocusMultiplier : public Multiplier public: FocusMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "focus") {} - float GetValue(Action* action) override; + float GetValue(Action& action) override; }; class FocusStrategy : public Strategy diff --git a/src/Ai/Base/Strategy/TravelStrategy.cpp b/src/Ai/Base/Strategy/TravelStrategy.cpp index 3b5c77ff3c..027dce166e 100644 --- a/src/Ai/Base/Strategy/TravelStrategy.cpp +++ b/src/Ai/Base/Strategy/TravelStrategy.cpp @@ -6,13 +6,17 @@ #include "TravelStrategy.h" #include "Playerbots.h" +#include "CreateNextAction.h" +#include "TravelAction.h" +#include "ChooseTravelTargetAction.h" +#include "MoveToTravelTargetAction.h" TravelStrategy::TravelStrategy(PlayerbotAI* botAI) : Strategy(botAI) {} std::vector TravelStrategy::getDefaultActions() { return { - NextAction("travel", 1.0f) + CreateNextAction(1.0f) }; } @@ -22,7 +26,7 @@ void TravelStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "no travel target", { - NextAction("choose travel target", 6.f) + CreateNextAction(6.0f) } ) ); @@ -30,7 +34,7 @@ void TravelStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "far from travel target", { - NextAction("move to travel target", 1) + CreateNextAction(1.0f) } ) ); diff --git a/src/Ai/Base/Strategy/UseFoodStrategy.cpp b/src/Ai/Base/Strategy/UseFoodStrategy.cpp index 939d655ff3..7ab4c05313 100644 --- a/src/Ai/Base/Strategy/UseFoodStrategy.cpp +++ b/src/Ai/Base/Strategy/UseFoodStrategy.cpp @@ -5,20 +5,50 @@ #include "UseFoodStrategy.h" +#include "DrinkAction.h" #include "PlayerbotAIConfig.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "NonCombatActions.h" void UseFoodStrategy::InitTriggers(std::vector& triggers) { Strategy::InitTriggers(triggers); if (botAI->HasCheat(BotCheatMask::food)) { - triggers.push_back(new TriggerNode("medium health", { NextAction("food", 3.0f) })); - triggers.push_back(new TriggerNode("high mana", { NextAction("drink", 3.0f) })); + triggers.push_back( + new TriggerNode( + "medium health", + { + CreateNextAction(3.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "high mana", + { + CreateNextAction(3.0f) + } + ) + ); } else { - triggers.push_back(new TriggerNode("low health", { NextAction("food", 3.0f) })); - triggers.push_back(new TriggerNode("low mana", { NextAction("drink", 3.0f) })); + triggers.push_back( + new TriggerNode( + "low health", + { + CreateNextAction(3.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "low mana", + { + CreateNextAction(3.0f) + } + ) + ); } } diff --git a/src/Ai/Base/Strategy/UsePotionsStrategy.cpp b/src/Ai/Base/Strategy/UsePotionsStrategy.cpp index b0e0049269..8a3b0f95df 100644 --- a/src/Ai/Base/Strategy/UsePotionsStrategy.cpp +++ b/src/Ai/Base/Strategy/UsePotionsStrategy.cpp @@ -5,20 +5,26 @@ #include "UsePotionsStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "UseItemAction.h" +#include "ActionNode.h" class UsePotionsStrategyActionNodeFactory : public NamedObjectFactory { public: - UsePotionsStrategyActionNodeFactory() { creators["healthstone"] = &healthstone; } + UsePotionsStrategyActionNodeFactory() + { + creators["healthstone"] = &healthstone; + } private: - static ActionNode* healthstone(PlayerbotAI* botAI) + static ActionNode* healthstone(PlayerbotAI*) { - return new ActionNode("healthstone", - /*P*/ {}, - /*A*/ { NextAction("healing potion") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } }; @@ -31,8 +37,20 @@ void UsePotionsStrategy::InitTriggers(std::vector& triggers) { Strategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode( - "critical health", { NextAction("healthstone", ACTION_MEDIUM_HEAL + 1) })); triggers.push_back( - new TriggerNode("low mana", { NextAction("mana potion", ACTION_EMERGENCY) })); + new TriggerNode( + "critical health", + { + CreateNextAction(ACTION_MEDIUM_HEAL + 1.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "low mana", + { + CreateNextAction(ACTION_EMERGENCY) + } + ) + ); } diff --git a/src/Ai/Base/Strategy/WorldPacketHandlerStrategy.cpp b/src/Ai/Base/Strategy/WorldPacketHandlerStrategy.cpp index cb37d27179..a64a2b8979 100644 --- a/src/Ai/Base/Strategy/WorldPacketHandlerStrategy.cpp +++ b/src/Ai/Base/Strategy/WorldPacketHandlerStrategy.cpp @@ -4,96 +4,339 @@ */ #include "WorldPacketHandlerStrategy.h" +#include "AddLootAction.h" +#include "AreaTriggerAction.h" +#include "ArenaTeamActions.h" +#include "AutoMaintenanceOnLevelupAction.h" +#include "BattleGroundJoinAction.h" +#include "CreateNextAction.h" +#include "AcceptInvitationAction.h" +#include "EquipAction.h" +#include "GuildAcceptAction.h" +#include "InventoryChangeFailureAction.h" +#include "LeaveGroupAction.h" +#include "LfgActions.h" +#include "LootAction.h" +#include "LootRollAction.h" +#include "OpenItemAction.h" +#include "PassLeadershipToMasterAction.h" +#include "PetitionSignAction.h" +#include "QuestAction.h" +#include "ReadyCheckAction.h" +#include "ReleaseSpiritAction.h" +#include "RememberTaxiAction.h" +#include "ResetAiAction.h" +#include "SeeSpellAction.h" +#include "TalkToQuestGiverAction.h" +#include "TaxiAction.h" +#include "TellMasterAction.h" +#include "TradeStatusAction.h" +#include "TradeStatusExtendedAction.h" +#include "TrainerAction.h" +#include "UnlockItemAction.h" +#include "XpGainAction.h" void WorldPacketHandlerStrategy::InitTriggers(std::vector& triggers) { PassTroughStrategy::InitTriggers(triggers); triggers.push_back( - new TriggerNode("group invite", { NextAction("accept invitation", relevance) })); + new TriggerNode( + "group invite", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("uninvite", { NextAction("uninvite", relevance) })); + new TriggerNode( + "uninvite", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("uninvite guid", { NextAction("uninvite", relevance) })); + new TriggerNode( + "uninvite guid", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("group set leader", { /*NextAction("leader", relevance),*/ })); - triggers.push_back(new TriggerNode( - "not enough money", { NextAction("tell not enough money", relevance) })); + new TriggerNode( + "group set leader", + { + CreateNextAction(relevance), + } + ) + ); triggers.push_back( - new TriggerNode("not enough reputation", - { NextAction("tell not enough reputation", relevance) })); + new TriggerNode( + "not enough money", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("cannot equip", { NextAction("tell cannot equip", relevance) })); + new TriggerNode( + "not enough reputation", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("use game object", { NextAction("add loot", relevance), - NextAction("use meeting stone", relevance) })); + new TriggerNode( + "cannot equip", + { + CreateNextAction(relevance) + } + ) + ); triggers.push_back( - new TriggerNode("gossip hello", { NextAction("trainer", relevance) })); - triggers.push_back(new TriggerNode("activate taxi", { NextAction("remember taxi", relevance), - NextAction("taxi", relevance) })); - triggers.push_back(new TriggerNode("taxi done", { NextAction("taxi", relevance) })); - triggers.push_back(new TriggerNode("trade status", { NextAction("accept trade", relevance), NextAction("equip upgrades", relevance) })); - triggers.push_back(new TriggerNode("trade status extended", { NextAction("trade status extended", relevance) })); - triggers.push_back(new TriggerNode("area trigger", { NextAction("reach area trigger", relevance) })); - triggers.push_back(new TriggerNode("within area trigger", { NextAction("area trigger", relevance) })); - triggers.push_back(new TriggerNode("loot response", { NextAction("store loot", relevance) })); - triggers.push_back(new TriggerNode("item push result", { NextAction("unlock items", relevance), - NextAction("open items", relevance), - NextAction("query item usage", relevance), - NextAction("equip upgrades", relevance) })); - triggers.push_back(new TriggerNode("item push result", { NextAction("quest item push result", relevance) })); - triggers.push_back(new TriggerNode("ready check finished", { NextAction("finish ready check", relevance) })); + new TriggerNode( + "use game object", + { + CreateNextAction(relevance), + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "gossip hello", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "activate taxi", + { + CreateNextAction(relevance), + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "taxi done", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "trade status", + { + CreateNextAction(relevance), + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "trade status extended", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "area trigger", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "within area trigger", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "loot response", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "item push result", + { + CreateNextAction(relevance), + CreateNextAction(relevance), + CreateNextAction(relevance), + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "item push result", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "ready check finished", + { + CreateNextAction(relevance) + } + ) + ); // triggers.push_back(new TriggerNode("often", { NextAction("security check", relevance), NextAction("check mail", relevance) })); - triggers.push_back(new TriggerNode("guild invite", { NextAction("guild accept", relevance) })); - triggers.push_back(new TriggerNode("petition offer", { NextAction("petition sign", relevance) })); - triggers.push_back(new TriggerNode("lfg proposal", { NextAction("lfg accept", relevance) })); - triggers.push_back(new TriggerNode("lfg proposal active", { NextAction("lfg accept", relevance) })); - triggers.push_back(new TriggerNode("arena team invite", { NextAction("arena team accept", relevance) })); + triggers.push_back( + new TriggerNode( + "guild invite", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "petition offer", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "lfg proposal", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "lfg proposal active", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "arena team invite", + { + CreateNextAction(relevance) + } + ) + ); //triggers.push_back(new TriggerNode("no non bot players around", { NextAction("delay", relevance) })); - triggers.push_back(new TriggerNode("bg status", { NextAction("bg status", relevance) })); - triggers.push_back(new TriggerNode("xpgain", { NextAction("xp gain", relevance) })); triggers.push_back( - new TriggerNode("levelup", { NextAction("auto maintenance on levelup", relevance + 3) })); + new TriggerNode( + "bg status", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "xpgain", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "levelup", + { + CreateNextAction(relevance + 3.0f) + } + ) + ); // triggers.push_back(new TriggerNode("group destroyed", { NextAction("reset botAI", // relevance) })); - triggers.push_back(new TriggerNode("group list", { NextAction("reset botAI", relevance) })); - triggers.push_back(new TriggerNode("see spell", { NextAction("see spell", relevance) })); - triggers.push_back(new TriggerNode("release spirit", { NextAction("release", relevance) })); - triggers.push_back(new TriggerNode("revive from corpse", { NextAction("revive from corpse", relevance) })); - triggers.push_back(new TriggerNode("master loot roll", { NextAction("master loot roll", relevance) })); + triggers.push_back( + new TriggerNode( + "group list", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "see spell", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "release spirit", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "revive from corpse", + { + CreateNextAction(relevance) + } + ) + ); + triggers.push_back( + new TriggerNode( + "master loot roll", + { + CreateNextAction(relevance) + } + ) + ); // quest ? //triggers.push_back(new TriggerNode("quest confirm", { NextAction("quest confirm", relevance) })); - triggers.push_back(new TriggerNode("questgiver quest details", { NextAction("turn in query quest", relevance) })); + triggers.push_back( + new TriggerNode( + "questgiver quest details", + { + CreateNextAction(relevance) + } + ) + ); // loot roll - triggers.push_back(new TriggerNode("very often", { NextAction("loot roll", relevance) })); -} - -WorldPacketHandlerStrategy::WorldPacketHandlerStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI) -{ - supported.push_back("loot roll"); - supported.push_back("check mount state"); - supported.push_back("party command"); - supported.push_back("ready check"); - supported.push_back("uninvite"); - supported.push_back("lfg role check"); - supported.push_back("lfg teleport"); - supported.push_back("random bot update"); - supported.push_back("inventory change failure"); - supported.push_back("bg status"); - - // quests - supported.push_back("quest update add kill"); - // supported.push_back("quest update add item"); - supported.push_back("quest update failed"); - supported.push_back("quest update failed timer"); - supported.push_back("quest update complete"); - supported.push_back("confirm quest"); + triggers.push_back( + new TriggerNode( + "very often", + { + CreateNextAction(relevance) + } + ) + ); } void ReadyCheckStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("timer", { NextAction("ready check", relevance) })); + new TriggerNode( + "timer", + { + CreateNextAction(relevance) + } + ) + ); } diff --git a/src/Ai/Base/Strategy/WorldPacketHandlerStrategy.h b/src/Ai/Base/Strategy/WorldPacketHandlerStrategy.h index 52b6e83e37..f57e551dd8 100644 --- a/src/Ai/Base/Strategy/WorldPacketHandlerStrategy.h +++ b/src/Ai/Base/Strategy/WorldPacketHandlerStrategy.h @@ -6,14 +6,49 @@ #ifndef _PLAYERBOT_WORLDPACKETHANDLERSTRATEGY_H #define _PLAYERBOT_WORLDPACKETHANDLERSTRATEGY_H +#include "AcceptQuestAction.h" +#include "BattleGroundJoinAction.h" +#include "CheckMountStateAction.h" +#include "CreateNextAction.h" +#include "GuildAcceptAction.h" +#include "InventoryChangeFailureAction.h" +#include "LeaveGroupAction.h" +#include "LfgActions.h" +#include "LootRollAction.h" #include "PassTroughStrategy.h" +#include "QuestAction.h" +#include "RandomBotUpdateAction.h" +#include "ReadyCheckAction.h" +#include "SecurityCheckAction.h" class PlayerbotAI; class WorldPacketHandlerStrategy : public PassTroughStrategy { public: - WorldPacketHandlerStrategy(PlayerbotAI* botAI); + WorldPacketHandlerStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI) + { + this->supported.push_back({ "loot roll", CreateNextAction(relevance).factory }); + this->supported.push_back({ "check mount state", CreateNextAction(relevance).factory }); + this->supported.push_back({ "party command", CreateNextAction(relevance).factory }); + this->supported.push_back({ "ready check", CreateNextAction(relevance).factory }); + this->supported.push_back({ "uninvite", CreateNextAction(relevance).factory }); + this->supported.push_back({ "lfg role check", CreateNextAction(relevance).factory }); + this->supported.push_back({ "lfg teleport", CreateNextAction(relevance).factory }); + this->supported.push_back({ "random bot update", CreateNextAction(relevance).factory }); + this->supported.push_back({ "inventory change failure", CreateNextAction(relevance).factory }); + this->supported.push_back({ "guild accept", CreateNextAction(relevance).factory }); + this->supported.push_back({ "security check", CreateNextAction(relevance).factory }); + this->supported.push_back({ "bg status", CreateNextAction(relevance).factory}); + + // quests + this->supported.push_back({ "quest update add kill", CreateNextAction(relevance).factory}); + this->supported.push_back({ "quest update add item", CreateNextAction(relevance).factory}); + this->supported.push_back({ "quest update failed", CreateNextAction(relevance).factory}); + this->supported.push_back({ "quest update failed timer", CreateNextAction(relevance).factory}); + this->supported.push_back({ "quest update complete", CreateNextAction(relevance).factory}); + this->supported.push_back({ "confirm quest", CreateNextAction(relevance).factory}); + } void InitTriggers(std::vector& triggers) override; std::string const getName() override { return "default"; } diff --git a/src/Ai/Base/Trigger/ChatCommandTrigger.cpp b/src/Ai/Base/Trigger/ChatCommandTrigger.cpp index 3fd6d7325a..2321fac406 100644 --- a/src/Ai/Base/Trigger/ChatCommandTrigger.cpp +++ b/src/Ai/Base/Trigger/ChatCommandTrigger.cpp @@ -4,8 +4,7 @@ */ #include "ChatCommandTrigger.h" - -#include "Playerbots.h" +#include "Player.h" ChatCommandTrigger::ChatCommandTrigger(PlayerbotAI* botAI, std::string const command) : Trigger(botAI, command), triggered(false), owner(nullptr) diff --git a/src/Ai/Base/Trigger/GenericTriggers.cpp b/src/Ai/Base/Trigger/GenericTriggers.cpp index 988413b2f3..35041970cd 100644 --- a/src/Ai/Base/Trigger/GenericTriggers.cpp +++ b/src/Ai/Base/Trigger/GenericTriggers.cpp @@ -7,9 +7,7 @@ #include -#include "BattlegroundWS.h" #include "CreatureAI.h" -#include "GameTime.h" #include "ItemVisitors.h" #include "LastSpellCastValue.h" #include "ObjectGuid.h" @@ -22,17 +20,18 @@ #include "Timer.h" #include "PlayerbotAI.h" #include "Player.h" +#include "Corpse.h" bool LowManaTrigger::IsActive() { return AI_VALUE2(bool, "has mana", "self target") && - AI_VALUE2(uint8, "mana", "self target") < sPlayerbotAIConfig->lowMana; + AI_VALUE2(uint8, "mana", "self target") < sPlayerbotAIConfig.lowMana; } bool MediumManaTrigger::IsActive() { return AI_VALUE2(bool, "has mana", "self target") && - AI_VALUE2(uint8, "mana", "self target") < sPlayerbotAIConfig->mediumMana; + AI_VALUE2(uint8, "mana", "self target") < sPlayerbotAIConfig.mediumMana; } bool NoPetTrigger::IsActive() @@ -72,7 +71,7 @@ bool PetAttackTrigger::IsActive() bool HighManaTrigger::IsActive() { - return AI_VALUE2(bool, "has mana", "self target") && AI_VALUE2(uint8, "mana", "self target") < sPlayerbotAIConfig->highMana; + return AI_VALUE2(bool, "has mana", "self target") && AI_VALUE2(uint8, "mana", "self target") < sPlayerbotAIConfig.highMana; } bool AlmostFullManaTrigger::IsActive() @@ -82,7 +81,7 @@ bool AlmostFullManaTrigger::IsActive() bool EnoughManaTrigger::IsActive() { - return AI_VALUE2(bool, "has mana", "self target") && AI_VALUE2(uint8, "mana", "self target") > sPlayerbotAIConfig->highMana; + return AI_VALUE2(bool, "has mana", "self target") && AI_VALUE2(uint8, "mana", "self target") > sPlayerbotAIConfig.highMana; } bool RageAvailable::IsActive() { return AI_VALUE2(uint8, "rage", "self target") >= amount; } @@ -110,9 +109,9 @@ bool HasAggroTrigger::IsActive() { return AI_VALUE2(bool, "has aggro", "current bool PanicTrigger::IsActive() { - return AI_VALUE2(uint8, "health", "self target") < sPlayerbotAIConfig->criticalHealth && + return AI_VALUE2(uint8, "health", "self target") < sPlayerbotAIConfig.criticalHealth && (!AI_VALUE2(bool, "has mana", "self target") || - AI_VALUE2(uint8, "mana", "self target") < sPlayerbotAIConfig->lowMana); + AI_VALUE2(uint8, "mana", "self target") < sPlayerbotAIConfig.lowMana); } bool OutNumberedTrigger::IsActive() @@ -165,7 +164,10 @@ bool BuffTrigger::IsActive() Aura* aura = botAI->GetAura(spell, target, checkIsOwner, checkDuration); if (!aura) return true; - if (beforeDuration && aura->GetDuration() < beforeDuration) + + const int64_t signedBeforeDuration = this->beforeDuration; + + if (beforeDuration && aura->GetDuration() < signedBeforeDuration) return true; return false; } @@ -248,7 +250,7 @@ bool AoeTrigger::IsActive() bool NoFoodTrigger::IsActive() { - bool isRandomBot = sRandomPlayerbotMgr->IsRandomBot(bot); + bool isRandomBot = sRandomPlayerbotMgr.IsRandomBot(bot); if (isRandomBot && botAI->HasCheat(BotCheatMask::food)) return false; @@ -257,7 +259,7 @@ bool NoFoodTrigger::IsActive() bool NoDrinkTrigger::IsActive() { - bool isRandomBot = sRandomPlayerbotMgr->IsRandomBot(bot); + bool isRandomBot = sRandomPlayerbotMgr.IsRandomBot(bot); if (isRandomBot && botAI->HasCheat(BotCheatMask::food)) return false; @@ -319,11 +321,11 @@ RandomTrigger::RandomTrigger(PlayerbotAI* botAI, std::string const name, int32 p bool RandomTrigger::IsActive() { - if (getMSTime() - lastCheck < sPlayerbotAIConfig->repeatDelay) + if (getMSTime() - lastCheck < sPlayerbotAIConfig.repeatDelay) return false; lastCheck = getMSTime(); - int32 k = (int32)(probability / sPlayerbotAIConfig->randomChangeMultiplier); + int32 k = (int32)(probability / sPlayerbotAIConfig.randomChangeMultiplier); if (k < 1) k = 1; return (rand() % k) == 0; @@ -381,10 +383,10 @@ bool GenericBoostTrigger::IsActive() bool HealerShouldAttackTrigger::IsActive() { // nobody can help me - if (botAI->GetNearGroupMemberCount(sPlayerbotAIConfig->sightDistance) <= 1) + if (botAI->GetNearGroupMemberCount(sPlayerbotAIConfig.sightDistance) <= 1) return true; - if (AI_VALUE2(uint8, "health", "party member to heal") < sPlayerbotAIConfig->almostFullHealth) + if (AI_VALUE2(uint8, "health", "party member to heal") < sPlayerbotAIConfig.almostFullHealth) return false; // special check for resto druid (dont remove tree of life frequently) @@ -401,9 +403,9 @@ bool HealerShouldAttackTrigger::IsActive() if (balance <= 50) manaThreshold = 85; else if (balance <= 100) - manaThreshold = sPlayerbotAIConfig->highMana; + manaThreshold = sPlayerbotAIConfig.highMana; else - manaThreshold = sPlayerbotAIConfig->mediumMana; + manaThreshold = sPlayerbotAIConfig.mediumMana; if (AI_VALUE2(bool, "has mana", "self target") && AI_VALUE2(uint8, "mana", "self target") < manaThreshold) return false; @@ -411,7 +413,12 @@ bool HealerShouldAttackTrigger::IsActive() return true; } -bool ItemCountTrigger::IsActive() { return AI_VALUE2(uint32, "item count", item) < count; } +bool ItemCountTrigger::IsActive() +{ + const int64_t aiValue = this->context->GetValue("item count", item)->Get(); + + return aiValue < this->count; +} bool InterruptSpellTrigger::IsActive() { @@ -632,7 +639,7 @@ bool ReturnToStayPositionTrigger::IsActive() if (stayPosition.isSet()) { const float distance = bot->GetDistance(stayPosition.x, stayPosition.y, stayPosition.z); - return distance > sPlayerbotAIConfig->followDistance; + return distance > sPlayerbotAIConfig.followDistance; } return false; diff --git a/src/Ai/Base/Trigger/GenericTriggers.h b/src/Ai/Base/Trigger/GenericTriggers.h index 943e80b742..7b884fbf08 100644 --- a/src/Ai/Base/Trigger/GenericTriggers.h +++ b/src/Ai/Base/Trigger/GenericTriggers.h @@ -216,7 +216,7 @@ class DeflectSpellTrigger : public SpellTrigger class AttackerCountTrigger : public Trigger { public: - AttackerCountTrigger(PlayerbotAI* botAI, int32 amount, float distance = sPlayerbotAIConfig->sightDistance) + AttackerCountTrigger(PlayerbotAI* botAI, int32 amount, float distance = sPlayerbotAIConfig.sightDistance) : Trigger(botAI), amount(amount), distance(distance) { } @@ -836,7 +836,7 @@ class StayTimeTrigger : public Trigger class SitTrigger : public StayTimeTrigger { public: - SitTrigger(PlayerbotAI* botAI) : StayTimeTrigger(botAI, sPlayerbotAIConfig->sitDelay, "sit") {} + SitTrigger(PlayerbotAI* botAI) : StayTimeTrigger(botAI, sPlayerbotAIConfig.sitDelay, "sit") {} }; class ReturnToStayPositionTrigger : public Trigger @@ -850,7 +850,7 @@ class ReturnToStayPositionTrigger : public Trigger class ReturnTrigger : public StayTimeTrigger { public: - ReturnTrigger(PlayerbotAI* botAI) : StayTimeTrigger(botAI, sPlayerbotAIConfig->returnDelay, "return") {} + ReturnTrigger(PlayerbotAI* botAI) : StayTimeTrigger(botAI, sPlayerbotAIConfig.returnDelay, "return") {} }; class GiveItemTrigger : public Trigger diff --git a/src/Ai/Base/Trigger/HealthTriggers.h b/src/Ai/Base/Trigger/HealthTriggers.h index d8149bffdb..0fbd403d72 100644 --- a/src/Ai/Base/Trigger/HealthTriggers.h +++ b/src/Ai/Base/Trigger/HealthTriggers.h @@ -48,7 +48,7 @@ class LowHealthTrigger : public HealthInRangeTrigger { public: LowHealthTrigger(PlayerbotAI* botAI, std::string const name = "low health", - float value = sPlayerbotAIConfig->lowHealth, float minValue = 0) + float value = sPlayerbotAIConfig.lowHealth, float minValue = 0) : HealthInRangeTrigger(botAI, name, value, minValue) { } @@ -60,7 +60,7 @@ class CriticalHealthTrigger : public LowHealthTrigger { public: CriticalHealthTrigger(PlayerbotAI* botAI) - : LowHealthTrigger(botAI, "critical health", sPlayerbotAIConfig->criticalHealth, 0) + : LowHealthTrigger(botAI, "critical health", sPlayerbotAIConfig.criticalHealth, 0) { } }; @@ -69,7 +69,7 @@ class MediumHealthTrigger : public LowHealthTrigger { public: MediumHealthTrigger(PlayerbotAI* botAI) - : LowHealthTrigger(botAI, "medium health", sPlayerbotAIConfig->mediumHealth, 0) + : LowHealthTrigger(botAI, "medium health", sPlayerbotAIConfig.mediumHealth, 0) { } }; @@ -78,8 +78,8 @@ class AlmostFullHealthTrigger : public LowHealthTrigger { public: AlmostFullHealthTrigger(PlayerbotAI* botAI) - : LowHealthTrigger(botAI, "almost full health", sPlayerbotAIConfig->almostFullHealth, - sPlayerbotAIConfig->mediumHealth) + : LowHealthTrigger(botAI, "almost full health", sPlayerbotAIConfig.almostFullHealth, + sPlayerbotAIConfig.mediumHealth) { } }; @@ -88,7 +88,7 @@ class PartyMemberLowHealthTrigger : public HealthInRangeTrigger { public: PartyMemberLowHealthTrigger(PlayerbotAI* botAI, std::string const name = "party member low health", - float value = sPlayerbotAIConfig->lowHealth, + float value = sPlayerbotAIConfig.lowHealth, float minValue = 0) : HealthInRangeTrigger(botAI, name, value, minValue) { @@ -101,7 +101,7 @@ class PartyMemberCriticalHealthTrigger : public PartyMemberLowHealthTrigger { public: PartyMemberCriticalHealthTrigger(PlayerbotAI* botAI) - : PartyMemberLowHealthTrigger(botAI, "party member critical health", sPlayerbotAIConfig->criticalHealth, 0) + : PartyMemberLowHealthTrigger(botAI, "party member critical health", sPlayerbotAIConfig.criticalHealth, 0) { } }; @@ -110,7 +110,7 @@ class PartyMemberMediumHealthTrigger : public PartyMemberLowHealthTrigger { public: PartyMemberMediumHealthTrigger(PlayerbotAI* botAI) - : PartyMemberLowHealthTrigger(botAI, "party member medium health", sPlayerbotAIConfig->mediumHealth, + : PartyMemberLowHealthTrigger(botAI, "party member medium health", sPlayerbotAIConfig.mediumHealth, 0) { } @@ -120,7 +120,7 @@ class PartyMemberAlmostFullHealthTrigger : public PartyMemberLowHealthTrigger { public: PartyMemberAlmostFullHealthTrigger(PlayerbotAI* botAI) - : PartyMemberLowHealthTrigger(botAI, "party member almost full health", sPlayerbotAIConfig->almostFullHealth, + : PartyMemberLowHealthTrigger(botAI, "party member almost full health", sPlayerbotAIConfig.almostFullHealth, 0) { } diff --git a/src/Ai/Base/Trigger/LootTriggers.cpp b/src/Ai/Base/Trigger/LootTriggers.cpp index f422f386ee..0a4b7e4117 100644 --- a/src/Ai/Base/Trigger/LootTriggers.cpp +++ b/src/Ai/Base/Trigger/LootTriggers.cpp @@ -15,11 +15,11 @@ bool LootAvailableTrigger::IsActive() if (botAI->HasStrategy("stay", BOT_STATE_NON_COMBAT)) { distanceCheck = - sServerFacade->IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", "loot target"), CONTACT_DISTANCE); + ServerFacade::instance().IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", "loot target"), CONTACT_DISTANCE); } else { - distanceCheck = sServerFacade->IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", "loot target"), + distanceCheck = ServerFacade::instance().IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", "loot target"), INTERACTION_DISTANCE - 2.0f); } diff --git a/src/Ai/Base/Trigger/PvpTriggers.cpp b/src/Ai/Base/Trigger/PvpTriggers.cpp index c837d8b16c..31fcd0357e 100644 --- a/src/Ai/Base/Trigger/PvpTriggers.cpp +++ b/src/Ai/Base/Trigger/PvpTriggers.cpp @@ -247,7 +247,7 @@ bool EnemyFlagCarrierNear::IsActive() { Unit* carrier = AI_VALUE(Unit*, "enemy flag carrier"); - if (!carrier || !sServerFacade->IsDistanceLessOrEqualThan(sServerFacade->GetDistance2d(bot, carrier), 100.f)) + if (!carrier || !ServerFacade::instance().IsDistanceLessOrEqualThan(ServerFacade::instance().GetDistance2d(bot, carrier), 100.f)) return false; // Check if there is another enemy player target closer than the FC @@ -255,8 +255,8 @@ bool EnemyFlagCarrierNear::IsActive() if (nearbyEnemy) { - float distToFC = sServerFacade->GetDistance2d(bot, carrier); - float distToEnemy = sServerFacade->GetDistance2d(bot, nearbyEnemy); + float distToFC = ServerFacade::instance().GetDistance2d(bot, carrier); + float distToEnemy = ServerFacade::instance().GetDistance2d(bot, nearbyEnemy); // If the other enemy is significantly closer, don't pursue FC if (distToEnemy + 15.0f < distToFC) // Add small buffer @@ -283,7 +283,7 @@ bool TeamFlagCarrierNear::IsActive() } Unit* carrier = AI_VALUE(Unit*, "team flag carrier"); - return carrier && sServerFacade->IsDistanceLessOrEqualThan(sServerFacade->GetDistance2d(bot, carrier), 200.f); + return carrier && ServerFacade::instance().IsDistanceLessOrEqualThan(ServerFacade::instance().GetDistance2d(bot, carrier), 200.f); } bool PlayerWantsInBattlegroundTrigger::IsActive() diff --git a/src/Ai/Base/Trigger/RangeTriggers.cpp b/src/Ai/Base/Trigger/RangeTriggers.cpp index af29f984d1..d0d86d0148 100644 --- a/src/Ai/Base/Trigger/RangeTriggers.cpp +++ b/src/Ai/Base/Trigger/RangeTriggers.cpp @@ -11,10 +11,10 @@ #include "ServerFacade.h" #include "SharedDefines.h" -static float GetSpeedInMotion(Unit* target) -{ - return target->GetSpeed(Movement::SelectSpeedType(target->GetUnitMovementFlags())); -} +// static float GetSpeedInMotion(Unit* target) +// { +// return target->GetSpeed(Movement::SelectSpeedType(target->GetUnitMovementFlags())); +// } bool EnemyTooCloseForSpellTrigger::IsActive() { @@ -34,7 +34,7 @@ bool EnemyTooCloseForSpellTrigger::IsActive() // bool isBoss = false; // bool isRaid = false; // float combatReach = bot->GetCombatReach() + target->GetCombatReach(); - // float targetDistance = sServerFacade->GetDistance2d(bot, target) + combatReach; + // float targetDistance = ServerFacade::instance().GetDistance2d(bot, target) + combatReach; // if (target->IsCreature()) // { // Creature* creature = botAI->GetCreature(target->GetGUID()); @@ -48,10 +48,10 @@ bool EnemyTooCloseForSpellTrigger::IsActive() // isRaid = true; // // if (isBoss || isRaid) - // // return sServerFacade->IsDistanceLessThan(targetDistance, (sPlayerbotAIConfig->tooCloseDistance + + // // return ServerFacade::instance().IsDistanceLessThan(targetDistance, (sPlayerbotAIConfig.tooCloseDistance + // combatReach) / 2); - // return sServerFacade->IsDistanceLessOrEqualThan(targetDistance, (sPlayerbotAIConfig->tooCloseDistance + + // return ServerFacade::instance().IsDistanceLessOrEqualThan(targetDistance, (sPlayerbotAIConfig.tooCloseDistance + // combatReach / 2)); } @@ -80,7 +80,7 @@ bool EnemyTooCloseForAutoShotTrigger::IsActive() // bool isBoss = false; // bool isRaid = false; // float combatReach = bot->GetCombatReach() + target->GetCombatReach(); - // float targetDistance = sServerFacade->GetDistance2d(bot, target) + combatReach; + // float targetDistance = ServerFacade::instance().GetDistance2d(bot, target) + combatReach; // if (target->IsCreature()) // { // Creature* creature = botAI->GetCreature(target->GetGUID()); @@ -93,7 +93,7 @@ bool EnemyTooCloseForAutoShotTrigger::IsActive() // if (bot->GetMap() && bot->GetMap()->IsRaid()) // isRaid = true; - // return sServerFacade->IsDistanceLessOrEqualThan(targetDistance, 5.0f); + // return ServerFacade::instance().IsDistanceLessOrEqualThan(targetDistance, 5.0f); } bool EnemyTooCloseForShootTrigger::IsActive() @@ -115,7 +115,7 @@ bool EnemyTooCloseForShootTrigger::IsActive() // bool isBoss = false; // bool isRaid = false; // float combatReach = bot->GetCombatReach() + target->GetCombatReach(); - // float targetDistance = sServerFacade->GetDistance2d(bot, target) + combatReach; + // float targetDistance = ServerFacade::instance().GetDistance2d(bot, target) + combatReach; // if (target->IsCreature()) // { // Creature* creature = botAI->GetCreature(target->GetGUID()); @@ -129,9 +129,9 @@ bool EnemyTooCloseForShootTrigger::IsActive() // isRaid = true; // // if (isBoss || isRaid) - // // return sServerFacade->IsDistanceLessThan(targetDistance, botAI->GetRange("shoot") + combatReach); + // // return ServerFacade::instance().IsDistanceLessThan(targetDistance, botAI->GetRange("shoot") + combatReach); - // return sServerFacade->IsDistanceLessOrEqualThan(targetDistance, (botAI->GetRange("shoot") + combatReach / + // return ServerFacade::instance().IsDistanceLessOrEqualThan(targetDistance, (botAI->GetRange("shoot") + combatReach / // 2)); } @@ -147,8 +147,8 @@ bool EnemyTooCloseForMeleeTrigger::IsActive() bool EnemyIsCloseTrigger::IsActive() { Unit* target = AI_VALUE(Unit*, "current target"); - return target && sServerFacade->IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", "current target"), - sPlayerbotAIConfig->tooCloseDistance); + return target && ServerFacade::instance().IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", "current target"), + sPlayerbotAIConfig.tooCloseDistance); } bool EnemyWithinMeleeTrigger::IsActive() @@ -165,7 +165,7 @@ bool OutOfRangeTrigger::IsActive() return target && !bot->IsWithinCombatRange( target, - dis); // sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", GetTargetName()), distance); + dis); // ServerFacade::instance().IsDistanceGreaterThan(AI_VALUE2(float, "distance", GetTargetName()), distance); } EnemyOutOfSpellRangeTrigger::EnemyOutOfSpellRangeTrigger(PlayerbotAI* botAI) @@ -180,8 +180,8 @@ EnemyOutOfSpellRangeTrigger::EnemyOutOfSpellRangeTrigger(PlayerbotAI* botAI) // return false; // float combatReach = bot->GetCombatReach() + target->GetCombatReach(); -// return target && (sServerFacade->GetDistance2d(bot, target) > (distance + combatReach + -// sPlayerbotAIConfig->contactDistance) || !bot->IsWithinLOSInMap(target)); +// return target && (ServerFacade::instance().GetDistance2d(bot, target) > (distance + combatReach + +// sPlayerbotAIConfig.contactDistance) || !bot->IsWithinLOSInMap(target)); // } // bool EnemyOutOfMeleeTrigger::IsActive() @@ -190,7 +190,7 @@ EnemyOutOfSpellRangeTrigger::EnemyOutOfSpellRangeTrigger(PlayerbotAI* botAI) // if (!target) // return false; -// float targetDistance = sServerFacade->GetDistance2d(bot, target); +// float targetDistance = ServerFacade::instance().GetDistance2d(bot, target); // return target && (targetDistance > std::max(5.0f, bot->GetCombatReach() + target->GetCombatReach()) || // (!bot->IsWithinLOSInMap(target) && targetDistance > 5.0f)); // } @@ -201,8 +201,7 @@ bool PartyMemberToHealOutOfSpellRangeTrigger::IsActive() if (!target) return false; - float combatReach = bot->GetCombatReach() + target->GetCombatReach(); - return target && (sServerFacade->GetDistance2d(bot, target) > (distance + sPlayerbotAIConfig->contactDistance) || + return target && (ServerFacade::instance().GetDistance2d(bot, target) > (distance + sPlayerbotAIConfig.contactDistance) || !bot->IsWithinLOSInMap(target)); } @@ -213,7 +212,7 @@ PartyMemberToHealOutOfSpellRangeTrigger::PartyMemberToHealOutOfSpellRangeTrigger bool FarFromMasterTrigger::IsActive() { - return sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", "group leader"), distance); + return ServerFacade::instance().IsDistanceGreaterThan(AI_VALUE2(float, "distance", "group leader"), distance); } bool TooCloseToCreatureTrigger::TooCloseToCreature(uint32 creatureId, float range, bool alive) diff --git a/src/Ai/Base/Trigger/RangeTriggers.h b/src/Ai/Base/Trigger/RangeTriggers.h index cc320ad027..62e1ae6e03 100644 --- a/src/Ai/Base/Trigger/RangeTriggers.h +++ b/src/Ai/Base/Trigger/RangeTriggers.h @@ -78,7 +78,7 @@ class EnemyOutOfMeleeTrigger : public OutOfRangeTrigger { public: EnemyOutOfMeleeTrigger(PlayerbotAI* botAI) - : OutOfRangeTrigger(botAI, "enemy out of melee range", sPlayerbotAIConfig->meleeDistance) + : OutOfRangeTrigger(botAI, "enemy out of melee range", sPlayerbotAIConfig.meleeDistance) { } diff --git a/src/Ai/Base/Trigger/RpgTriggers.cpp b/src/Ai/Base/Trigger/RpgTriggers.cpp index f390359be3..ed528d2b72 100644 --- a/src/Ai/Base/Trigger/RpgTriggers.cpp +++ b/src/Ai/Base/Trigger/RpgTriggers.cpp @@ -31,9 +31,16 @@ bool RpgTrigger::IsActive() { return true; } Event RpgTrigger::Check() { - if (!NoRpgTargetTrigger::IsActive() && (AI_VALUE(std::string, "next rpg action") == "choose rpg target") || - !FarFromRpgTargetTrigger::IsActive()) + if ( + ( + !NoRpgTargetTrigger::IsActive() + && (AI_VALUE(std::string, "next rpg action") == "choose rpg target") + ) + || !FarFromRpgTargetTrigger::IsActive() + ) + { return Trigger::Check(); + } return Event(); } diff --git a/src/Ai/Base/Trigger/TravelTriggers.cpp b/src/Ai/Base/Trigger/TravelTriggers.cpp index 88dfbb2b4b..ce036027c1 100644 --- a/src/Ai/Base/Trigger/TravelTriggers.cpp +++ b/src/Ai/Base/Trigger/TravelTriggers.cpp @@ -21,7 +21,7 @@ bool AtDarkPortalAzerothTrigger::IsActive() { if (bot->GetAreaId() == 72) { - if (sServerFacade->GetDistance2d(bot, -11906.9f, -3208.53f) < 20.0f) + if (ServerFacade::instance().GetDistance2d(bot, -11906.9f, -3208.53f) < 20.0f) { return true; } @@ -34,7 +34,7 @@ bool AtDarkPortalOutlandTrigger::IsActive() { if (bot->GetAreaId() == 3539) { - if (sServerFacade->GetDistance2d(bot, -248.1939f, 921.919f) < 10.0f) + if (ServerFacade::instance().GetDistance2d(bot, -248.1939f, 921.919f) < 10.0f) { return true; } diff --git a/src/Ai/Base/Value/AoeHealValues.cpp b/src/Ai/Base/Value/AoeHealValues.cpp index 06f0002056..2c56986678 100644 --- a/src/Ai/Base/Value/AoeHealValues.cpp +++ b/src/Ai/Base/Value/AoeHealValues.cpp @@ -16,13 +16,13 @@ uint8 AoeHealValue::Calculate() float range = 0; if (qualifier == "low") - range = sPlayerbotAIConfig->lowHealth; + range = sPlayerbotAIConfig.lowHealth; else if (qualifier == "medium") - range = sPlayerbotAIConfig->mediumHealth; + range = sPlayerbotAIConfig.mediumHealth; else if (qualifier == "critical") - range = sPlayerbotAIConfig->criticalHealth; + range = sPlayerbotAIConfig.criticalHealth; else if (qualifier == "almost full") - range = sPlayerbotAIConfig->almostFullHealth; + range = sPlayerbotAIConfig.almostFullHealth; uint8 count = 0; Group::MemberSlotList const& groupSlot = group->GetMemberSlots(); @@ -32,7 +32,7 @@ uint8 AoeHealValue::Calculate() if (!player || !player->IsAlive()) continue; - if (player->GetDistance(bot) >= sPlayerbotAIConfig->sightDistance) + if (player->GetDistance(bot) >= sPlayerbotAIConfig.sightDistance) continue; float percent = (static_cast(player->GetHealth()) / player->GetMaxHealth()) * 100; diff --git a/src/Ai/Base/Value/AoeValues.cpp b/src/Ai/Base/Value/AoeValues.cpp index d46dcb816f..d1b60b590b 100644 --- a/src/Ai/Base/Value/AoeValues.cpp +++ b/src/Ai/Base/Value/AoeValues.cpp @@ -29,8 +29,8 @@ GuidVector FindMaxDensity(Player* bot) if (!other) continue; - float d = sServerFacade->GetDistance2d(unit, other); - if (sServerFacade->IsDistanceLessOrEqualThan(d, sPlayerbotAIConfig->aoeRadius * 2)) + float d = ServerFacade::instance().GetDistance2d(unit, other); + if (ServerFacade::instance().IsDistanceLessOrEqualThan(d, sPlayerbotAIConfig.aoeRadius * 2)) groups[*i].push_back(*j); } diff --git a/src/Ai/Base/Value/Arrow.cpp b/src/Ai/Base/Value/Arrow.cpp index 15fc2e2959..25e3a03947 100644 --- a/src/Ai/Base/Value/Arrow.cpp +++ b/src/Ai/Base/Value/Arrow.cpp @@ -6,7 +6,8 @@ #include "Arrow.h" #include "Map.h" -#include "Playerbots.h" +#include "PlayerbotAI.h" +#include "Group.h" WorldLocation ArrowFormation::GetLocationInternal() { @@ -18,7 +19,6 @@ WorldLocation ArrowFormation::GetLocationInternal() uint32 tankLines = 1 + tanks.Size() / 6; uint32 meleeLines = 1 + melee.Size() / 6; uint32 rangedLines = 1 + ranged.Size() / 6; - uint32 healerLines = 1 + healers.Size() / 6; float offset = 0.f; Player* master = botAI->GetMaster(); @@ -31,15 +31,15 @@ WorldLocation ArrowFormation::GetLocationInternal() tanks.PlaceUnits(&placer); tanks.Move(-cos(orientation) * offset, -sin(orientation) * offset); - offset += tankLines * sPlayerbotAIConfig->followDistance + sPlayerbotAIConfig->tooCloseDistance / 2; + offset += tankLines * sPlayerbotAIConfig.followDistance + sPlayerbotAIConfig.tooCloseDistance / 2; melee.PlaceUnits(&placer); melee.Move(-cos(orientation) * offset, -sin(orientation) * offset); - offset += meleeLines * sPlayerbotAIConfig->followDistance + sPlayerbotAIConfig->tooCloseDistance / 2; + offset += meleeLines * sPlayerbotAIConfig.followDistance + sPlayerbotAIConfig.tooCloseDistance / 2; ranged.PlaceUnits(&placer); ranged.Move(-cos(orientation) * offset, -sin(orientation) * offset); - offset += rangedLines * sPlayerbotAIConfig->followDistance; + offset += rangedLines * sPlayerbotAIConfig.followDistance; healers.PlaceUnits(&placer); healers.Move(-cos(orientation) * offset, -sin(orientation) * offset); @@ -143,16 +143,14 @@ UnitPosition MultiLineUnitPlacer::Place(FormationUnit* unit, uint32 index, uint3 uint32 lineNo = index / 6; uint32 indexInLine = index % 6; uint32 lineSize = std::max(count - lineNo * 6, uint32(6)); - float x = cos(orientation) * sPlayerbotAIConfig->followDistance * lineNo; - float y = sin(orientation) * sPlayerbotAIConfig->followDistance * lineNo; return placer.Place(unit, indexInLine, lineSize); } -UnitPosition SingleLineUnitPlacer::Place(FormationUnit* unit, uint32 index, uint32 count) +UnitPosition SingleLineUnitPlacer::Place(FormationUnit*, uint32 index, uint32 count) { float angle = orientation - M_PI / 2.0f; - float x = cos(angle) * sPlayerbotAIConfig->followDistance * ((float)index - (float)count / 2); - float y = sin(angle) * sPlayerbotAIConfig->followDistance * ((float)index - (float)count / 2); + float x = cos(angle) * sPlayerbotAIConfig.followDistance * ((float)index - (float)count / 2); + float y = sin(angle) * sPlayerbotAIConfig.followDistance * ((float)index - (float)count / 2); return UnitPosition(x, y); } diff --git a/src/Ai/Base/Value/Arrow.h b/src/Ai/Base/Value/Arrow.h index 3e5a76b8fb..220cb370bd 100644 --- a/src/Ai/Base/Value/Arrow.h +++ b/src/Ai/Base/Value/Arrow.h @@ -16,11 +16,13 @@ class UnitPosition { public: UnitPosition(float x, float y) : x(x), y(y) {} - UnitPosition(UnitPosition const& other) - { - x = other.x; - y = other.y; - } + ~UnitPosition() = default; + + UnitPosition(UnitPosition const& other) = default; + UnitPosition& operator=(UnitPosition const& other) = default; + + UnitPosition(UnitPosition&&) = default; + UnitPosition& operator=(UnitPosition&&) = default; float x, y; }; @@ -102,7 +104,7 @@ class ArrowFormation : public MoveAheadFormation { public: ArrowFormation(PlayerbotAI* botAI) - : MoveAheadFormation(botAI, "arrow"), built(false), masterUnit(nullptr), botUnit(nullptr) + : MoveAheadFormation(botAI, "arrow"), masterUnit(nullptr), botUnit(nullptr), built(false) { } diff --git a/src/Ai/Base/Value/AttackerCountValues.cpp b/src/Ai/Base/Value/AttackerCountValues.cpp index 637fd72864..88c3cd1fb6 100644 --- a/src/Ai/Base/Value/AttackerCountValues.cpp +++ b/src/Ai/Base/Value/AttackerCountValues.cpp @@ -34,7 +34,7 @@ bool HasAggroValue::Calculate() uint8 AttackerCountValue::Calculate() { uint32 count = 0; - float range = sPlayerbotAIConfig->sightDistance; + float range = sPlayerbotAIConfig.sightDistance; GuidVector attackers = context->GetValue("attackers")->Get(); for (ObjectGuid const guid : attackers) diff --git a/src/Ai/Base/Value/AttackersValue.cpp b/src/Ai/Base/Value/AttackersValue.cpp index f6da0aa7a6..dbde7ab8df 100644 --- a/src/Ai/Base/Value/AttackersValue.cpp +++ b/src/Ai/Base/Value/AttackersValue.cpp @@ -71,7 +71,7 @@ void AttackersValue::AddAttackersOf(Group* group, std::unordered_set& tar { Player* member = ObjectAccessor::FindPlayer(itr->guid); if (!member || !member->IsAlive() || member == bot || member->GetMapId() != bot->GetMapId() || - sServerFacade->GetDistance2d(bot, member) > sPlayerbotAIConfig->sightDistance) + ServerFacade::instance().GetDistance2d(bot, member) > sPlayerbotAIConfig.sightDistance) continue; AddAttackersOf(member, targets); @@ -103,7 +103,7 @@ void AttackersValue::AddAttackersOf(Player* player, std::unordered_set& t Unit* attacker = threatMgr->GetOwner(); if (player->IsValidAttackTarget(attacker) && - player->GetDistance2d(attacker) < sPlayerbotAIConfig->sightDistance) + player->GetDistance2d(attacker) < sPlayerbotAIConfig.sightDistance) targets.insert(attacker); ref = ref->next(); @@ -176,8 +176,8 @@ bool AttackersValue::IsPossibleTarget(Unit* attacker, Player* bot, float /*range // PvP prohibition checks (skip for duels) if ((attacker->GetGUID().IsPlayer() || attacker->GetGUID().IsPet()) && (!bot->duel || bot->duel->Opponent != attacker) && - (sPlayerbotAIConfig->IsPvpProhibited(attacker->GetZoneId(), attacker->GetAreaId()) || - sPlayerbotAIConfig->IsPvpProhibited(bot->GetZoneId(), bot->GetAreaId()))) + (sPlayerbotAIConfig.IsPvpProhibited(attacker->GetZoneId(), attacker->GetAreaId()) || + sPlayerbotAIConfig.IsPvpProhibited(bot->GetZoneId(), bot->GetAreaId()))) { // This will stop aggresive pets from starting an attack. // This will stop currently attacking pets from continuing their attack. @@ -269,11 +269,11 @@ bool PossibleAddsValue::Calculate() if (!attacker) continue; - float dist = sServerFacade->GetDistance2d(attacker, add); - if (sServerFacade->IsDistanceLessOrEqualThan(dist, sPlayerbotAIConfig->aoeRadius * 1.5f)) + float dist = ServerFacade::instance().GetDistance2d(attacker, add); + if (ServerFacade::instance().IsDistanceLessOrEqualThan(dist, sPlayerbotAIConfig.aoeRadius * 1.5f)) continue; - if (sServerFacade->IsDistanceLessOrEqualThan(dist, sPlayerbotAIConfig->aggroDistance)) + if (ServerFacade::instance().IsDistanceLessOrEqualThan(dist, sPlayerbotAIConfig.aggroDistance)) return true; } } diff --git a/src/Ai/Base/Value/AttackersValue.h b/src/Ai/Base/Value/AttackersValue.h index 906db92a88..7e9397c86c 100644 --- a/src/Ai/Base/Value/AttackersValue.h +++ b/src/Ai/Base/Value/AttackersValue.h @@ -20,7 +20,7 @@ class AttackersValue : public ObjectGuidListCalculatedValue AttackersValue(PlayerbotAI* botAI) : ObjectGuidListCalculatedValue(botAI, "attackers", 1 * 1000) {} GuidVector Calculate(); - static bool IsPossibleTarget(Unit* attacker, Player* bot, float range = sPlayerbotAIConfig->sightDistance); + static bool IsPossibleTarget(Unit* attacker, Player* bot, float range = sPlayerbotAIConfig.sightDistance); static bool IsValidTarget(Unit* attacker, Player* bot); private: diff --git a/src/Ai/Base/Value/AvailableLootValue.cpp b/src/Ai/Base/Value/AvailableLootValue.cpp index 7f945d7e1e..75b4b599a4 100644 --- a/src/Ai/Base/Value/AvailableLootValue.cpp +++ b/src/Ai/Base/Value/AvailableLootValue.cpp @@ -26,5 +26,5 @@ bool CanLootValue::Calculate() { LootObject loot = AI_VALUE(LootObject, "loot target"); return !loot.IsEmpty() && loot.GetWorldObject(bot) && loot.IsLootPossible(bot) && - sServerFacade->IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", "loot target"), INTERACTION_DISTANCE - 2); + ServerFacade::instance().IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", "loot target"), INTERACTION_DISTANCE - 2); } diff --git a/src/Ai/Base/Value/BudgetValues.cpp b/src/Ai/Base/Value/BudgetValues.cpp index daa7aca863..06b2e1d576 100644 --- a/src/Ai/Base/Value/BudgetValues.cpp +++ b/src/Ai/Base/Value/BudgetValues.cpp @@ -10,7 +10,7 @@ uint32 MaxGearRepairCostValue::Calculate() { uint32 TotalCost = 0; - for (int i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; ++i) + for (uint32_t i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; ++i) { uint16 pos = ((INVENTORY_SLOT_BAG_0 << 8) | i); Item* item = bot->GetItemByPos(pos); diff --git a/src/Ai/Base/Value/CcTargetValue.cpp b/src/Ai/Base/Value/CcTargetValue.cpp index c47151ddfd..e84f4f4b70 100644 --- a/src/Ai/Base/Value/CcTargetValue.cpp +++ b/src/Ai/Base/Value/CcTargetValue.cpp @@ -6,7 +6,9 @@ #include "CcTargetValue.h" #include "Action.h" -#include "Playerbots.h" +#include "AiObjectContext.h" +#include "Group.h" +#include "PlayerbotAI.h" #include "ServerFacade.h" class FindTargetForCcStrategy : public FindTargetStrategy @@ -18,7 +20,7 @@ class FindTargetForCcStrategy : public FindTargetStrategy } public: - void CheckAttacker(Unit* creature, ThreatMgr* threatMgr) override + void CheckAttacker(Unit* creature, ThreatMgr*) override { Player* bot = botAI->GetBot(); if (!botAI->CanCastSpell(spell, creature)) @@ -34,7 +36,7 @@ class FindTargetForCcStrategy : public FindTargetStrategy return; uint8 health = static_cast(creature->GetHealthPct()); - if (health < sPlayerbotAIConfig->mediumHealth) + if (health < sPlayerbotAIConfig.mediumHealth) return; float minDistance = botAI->GetRange("spell"); @@ -45,9 +47,9 @@ class FindTargetForCcStrategy : public FindTargetStrategy if (*botAI->GetAiObjectContext()->GetValue("aoe count") > 2) { WorldLocation aoe = *botAI->GetAiObjectContext()->GetValue("aoe position"); - if (sServerFacade->IsDistanceLessOrEqualThan( - sServerFacade->GetDistance2d(creature, aoe.GetPositionX(), aoe.GetPositionY()), - sPlayerbotAIConfig->aoeRadius)) + if (ServerFacade::instance().IsDistanceLessOrEqualThan( + ServerFacade::instance().GetDistance2d(creature, aoe.GetPositionX(), aoe.GetPositionY()), + sPlayerbotAIConfig.aoeRadius)) return; } @@ -70,7 +72,7 @@ class FindTargetForCcStrategy : public FindTargetStrategy if (!botAI->IsTank(member)) continue; - float distance = sServerFacade->GetDistance2d(member, creature); + float distance = ServerFacade::instance().GetDistance2d(member, creature); if (distance < minDistance) minDistance = distance; } diff --git a/src/Ai/Base/Value/CollisionValue.cpp b/src/Ai/Base/Value/CollisionValue.cpp index 7657742590..172a909b17 100644 --- a/src/Ai/Base/Value/CollisionValue.cpp +++ b/src/Ai/Base/Value/CollisionValue.cpp @@ -18,7 +18,7 @@ bool CollisionValue::Calculate() return false; std::list targets; - float range = sPlayerbotAIConfig->contactDistance; + float range = sPlayerbotAIConfig.contactDistance; Acore::AnyUnitInObjectRangeCheck u_check(bot, range); Acore::UnitListSearcher searcher(bot, targets, u_check); Cell::VisitObjects(bot, searcher, range); @@ -28,8 +28,8 @@ bool CollisionValue::Calculate() if (bot == target) continue; - float dist = sServerFacade->GetDistance2d(bot, target->GetPositionX(), target->GetPositionY()); - if (sServerFacade->IsDistanceLessThan(dist, target->GetCombatReach())) + float dist = ServerFacade::instance().GetDistance2d(bot, target->GetPositionX(), target->GetPositionY()); + if (ServerFacade::instance().IsDistanceLessThan(dist, target->GetCombatReach())) return true; } diff --git a/src/Ai/Base/Value/CraftValue.h b/src/Ai/Base/Value/CraftValue.h index d3311e6c8a..def3352b9c 100644 --- a/src/Ai/Base/Value/CraftValue.h +++ b/src/Ai/Base/Value/CraftValue.h @@ -16,11 +16,13 @@ class CraftData { public: CraftData() : itemId(0) {} - CraftData(CraftData const& other) : itemId(other.itemId) - { - required.insert(other.required.begin(), other.required.end()); - obtained.insert(other.obtained.begin(), other.obtained.end()); - } + ~CraftData() = default; + + CraftData(CraftData const& other) = default; + CraftData& operator=(CraftData const& other) = default; + + CraftData(CraftData&&) = default; + CraftData& operator=(CraftData&&) = default; uint32 itemId; std::map required, obtained; diff --git a/src/Ai/Base/Value/CurrentCcTargetValue.cpp b/src/Ai/Base/Value/CurrentCcTargetValue.cpp index 27b8100264..7739dd81b9 100644 --- a/src/Ai/Base/Value/CurrentCcTargetValue.cpp +++ b/src/Ai/Base/Value/CurrentCcTargetValue.cpp @@ -4,8 +4,7 @@ */ #include "CurrentCcTargetValue.h" - -#include "Playerbots.h" +#include "PlayerbotAI.h" class FindCurrentCcTargetStrategy : public FindTargetStrategy { @@ -14,7 +13,7 @@ class FindCurrentCcTargetStrategy : public FindTargetStrategy { } - void CheckAttacker(Unit* attacker, ThreatMgr* threatMgr) override + void CheckAttacker(Unit* attacker, ThreatMgr*) override { if (botAI->HasAura(spell, attacker)) result = attacker; diff --git a/src/Ai/Base/Value/DistanceValue.cpp b/src/Ai/Base/Value/DistanceValue.cpp index 2c1e818b54..a5c6fe857a 100644 --- a/src/Ai/Base/Value/DistanceValue.cpp +++ b/src/Ai/Base/Value/DistanceValue.cpp @@ -24,7 +24,7 @@ float DistanceValue::Calculate() if (!obj || !obj->IsInWorld()) return 0.0f; - return sServerFacade->GetDistance2d(botAI->GetBot(), obj); + return ServerFacade::instance().GetDistance2d(botAI->GetBot(), obj); } if (qualifier.find("position_") == 0) @@ -37,7 +37,7 @@ float DistanceValue::Calculate() if (botAI->GetBot()->GetMapId() != pos.mapId) return 0.0f; - return sServerFacade->GetDistance2d(botAI->GetBot(), pos.x, pos.y); + return ServerFacade::instance().GetDistance2d(botAI->GetBot(), pos.x, pos.y); } Unit* target = nullptr; @@ -76,7 +76,7 @@ float DistanceValue::Calculate() { Formation* formation = AI_VALUE(Formation*, "formation"); WorldLocation loc = formation->GetLocation(); - return sServerFacade->GetDistance2d(botAI->GetBot(), loc.GetPositionX(), loc.GetPositionY()); + return ServerFacade::instance().GetDistance2d(botAI->GetBot(), loc.GetPositionX(), loc.GetPositionY()); } } @@ -86,7 +86,7 @@ float DistanceValue::Calculate() if (target == botAI->GetBot()) return 0.0f; - return sServerFacade->GetDistance2d(botAI->GetBot(), target); + return ServerFacade::instance().GetDistance2d(botAI->GetBot(), target); } bool InsideTargetValue::Calculate() @@ -95,6 +95,6 @@ bool InsideTargetValue::Calculate() if (!target || !target->IsInWorld() || target == botAI->GetBot()) return false; - float dist = sServerFacade->GetDistance2d(botAI->GetBot(), target->GetPositionX(), target->GetPositionY()); - return sServerFacade->IsDistanceLessThan(dist, target->GetCombatReach()); + float dist = ServerFacade::instance().GetDistance2d(botAI->GetBot(), target->GetPositionX(), target->GetPositionY()); + return ServerFacade::instance().IsDistanceLessThan(dist, target->GetCombatReach()); } diff --git a/src/Ai/Base/Value/DpsTargetValue.cpp b/src/Ai/Base/Value/DpsTargetValue.cpp index 55b47d7c01..d1bad8c17d 100644 --- a/src/Ai/Base/Value/DpsTargetValue.cpp +++ b/src/Ai/Base/Value/DpsTargetValue.cpp @@ -29,7 +29,6 @@ class FindMaxThreatGapTargetStrategy : public FindTargetStrategy foundHighPriority = true; return; } - Unit* victim = attacker->GetVictim(); if (!result || CalcThreatGap(attacker, threatMgr) > CalcThreatGap(result, &result->GetThreatMgr())) result = attacker; } @@ -53,7 +52,7 @@ class CasterFindTargetSmartStrategy : public FindTargetStrategy result = nullptr; } - void CheckAttacker(Unit* attacker, ThreatMgr* threatMgr) override + void CheckAttacker(Unit* attacker, ThreatMgr*) override { if (Group* group = botAI->GetBot()->GetGroup()) { @@ -116,7 +115,7 @@ class CasterFindTargetSmartStrategy : public FindTargetStrategy float time = unit->GetHealth() / dps_; float dis = unit->GetDistance(botAI->GetBot()); float attackRange = - botAI->IsRanged(botAI->GetBot()) ? sPlayerbotAIConfig->spellDistance : sPlayerbotAIConfig->meleeDistance; + botAI->IsRanged(botAI->GetBot()) ? sPlayerbotAIConfig.spellDistance : sPlayerbotAIConfig.meleeDistance; attackRange += 5.0f; int level = dis < attackRange ? 10 : 0; if (time >= 5 && time <= 30) @@ -144,7 +143,7 @@ class GeneralFindTargetSmartStrategy : public FindTargetStrategy { } - void CheckAttacker(Unit* attacker, ThreatMgr* threatMgr) override + void CheckAttacker(Unit* attacker, ThreatMgr*) override { if (Group* group = botAI->GetBot()->GetGroup()) { @@ -195,10 +194,9 @@ class GeneralFindTargetSmartStrategy : public FindTargetStrategy } int32_t GetIntervalLevel(Unit* unit) { - float time = unit->GetHealth() / dps_; float dis = unit->GetDistance(botAI->GetBot()); float attackRange = - botAI->IsRanged(botAI->GetBot()) ? sPlayerbotAIConfig->spellDistance : sPlayerbotAIConfig->meleeDistance; + botAI->IsRanged(botAI->GetBot()) ? sPlayerbotAIConfig.spellDistance : sPlayerbotAIConfig.meleeDistance; attackRange += 5.0f; int level = dis < attackRange ? 10 : 0; return level; @@ -218,7 +216,7 @@ class ComboFindTargetSmartStrategy : public FindTargetStrategy { } - void CheckAttacker(Unit* attacker, ThreatMgr* threatMgr) override + void CheckAttacker(Unit* attacker, ThreatMgr*) override { if (Group* group = botAI->GetBot()->GetGroup()) { @@ -276,10 +274,9 @@ class ComboFindTargetSmartStrategy : public FindTargetStrategy } int32_t GetIntervalLevel(Unit* unit) { - float time = unit->GetHealth() / dps_; float dis = unit->GetDistance(botAI->GetBot()); float attackRange = - botAI->IsRanged(botAI->GetBot()) ? sPlayerbotAIConfig->spellDistance : sPlayerbotAIConfig->meleeDistance; + botAI->IsRanged(botAI->GetBot()) ? sPlayerbotAIConfig.spellDistance : sPlayerbotAIConfig.meleeDistance; attackRange += 5.0f; int level = dis < attackRange ? 10 : 0; return level; @@ -322,7 +319,7 @@ class FindMaxHpTargetStrategy : public FindTargetStrategy public: FindMaxHpTargetStrategy(PlayerbotAI* botAI) : FindTargetStrategy(botAI), maxHealth(0) {} - void CheckAttacker(Unit* attacker, ThreatMgr* threatMgr) override + void CheckAttacker(Unit* attacker, ThreatMgr*) override { if (Group* group = botAI->GetBot()->GetGroup()) { diff --git a/src/Ai/Base/Value/EnemyHealerTargetValue.cpp b/src/Ai/Base/Value/EnemyHealerTargetValue.cpp index 6040c4fcb5..85559f7827 100644 --- a/src/Ai/Base/Value/EnemyHealerTargetValue.cpp +++ b/src/Ai/Base/Value/EnemyHealerTargetValue.cpp @@ -20,7 +20,7 @@ Unit* EnemyHealerTargetValue::Calculate() if (!unit || unit == target) continue; - if (sServerFacade->GetDistance2d(bot, unit) > botAI->GetRange("spell")) + if (ServerFacade::instance().GetDistance2d(bot, unit) > botAI->GetRange("spell")) continue; if (!botAI->IsInterruptableSpellCasting(unit, spell)) diff --git a/src/Ai/Base/Value/EnemyPlayerValue.cpp b/src/Ai/Base/Value/EnemyPlayerValue.cpp index 2325c9c09b..7de0cd670a 100644 --- a/src/Ai/Base/Value/EnemyPlayerValue.cpp +++ b/src/Ai/Base/Value/EnemyPlayerValue.cpp @@ -14,7 +14,7 @@ bool NearestEnemyPlayersValue::AcceptUnit(Unit* unit) bool inCannon = botAI->IsInVehicle(false, true); Player* enemy = dynamic_cast(unit); if (enemy && botAI->IsOpposing(enemy) && enemy->IsPvP() && - !sPlayerbotAIConfig->IsPvpProhibited(enemy->GetZoneId(), enemy->GetAreaId()) && + !sPlayerbotAIConfig.IsPvpProhibited(enemy->GetZoneId(), enemy->GetAreaId()) && !enemy->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NON_ATTACKABLE_2) && ((inCannon || !enemy->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))) && /*!enemy->HasStealthAura() && !enemy->HasInvisibilityAura()*/ enemy->CanSeeOrDetect(bot) && @@ -131,7 +131,7 @@ Unit* EnemyPlayerValue::Calculate() if (pMember == bot) continue; - if (sServerFacade->GetDistance2d(bot, pMember) > 30.0f) + if (ServerFacade::instance().GetDistance2d(bot, pMember) > 30.0f) continue; if (Unit* pAttacker = pMember->getAttackerForHelper()) diff --git a/src/Ai/Base/Value/EnemyPlayerValue.h b/src/Ai/Base/Value/EnemyPlayerValue.h index f94f20265f..2ff56f4eb2 100644 --- a/src/Ai/Base/Value/EnemyPlayerValue.h +++ b/src/Ai/Base/Value/EnemyPlayerValue.h @@ -16,7 +16,7 @@ class Unit; class NearestEnemyPlayersValue : public PossibleTargetsValue { public: - NearestEnemyPlayersValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig->grindDistance) + NearestEnemyPlayersValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig.grindDistance) : PossibleTargetsValue(botAI, "nearest enemy players", range) { } diff --git a/src/Ai/Base/Value/EstimatedLifetimeValue.cpp b/src/Ai/Base/Value/EstimatedLifetimeValue.cpp index dd79207130..ee43a8c6c1 100644 --- a/src/Ai/Base/Value/EstimatedLifetimeValue.cpp +++ b/src/Ai/Base/Value/EstimatedLifetimeValue.cpp @@ -46,7 +46,7 @@ float EstimatedGroupDpsValue::Calculate() if (member->GetMapId() != bot->GetMapId()) continue; - if (member->GetExactDist(bot) > sPlayerbotAIConfig->sightDistance) + if (member->GetExactDist(bot) > sPlayerbotAIConfig.sightDistance) continue; groupPlayer.push_back(member); diff --git a/src/Ai/Base/Value/Formations.cpp b/src/Ai/Base/Value/Formations.cpp index 69869889d7..1394b9fbe0 100644 --- a/src/Ai/Base/Value/Formations.cpp +++ b/src/Ai/Base/Value/Formations.cpp @@ -64,8 +64,8 @@ WorldLocation MoveAheadFormation::GetLocation() // if (master->isMoving()) // { // float ori = master->GetOrientation(); - // float x1 = x + sPlayerbotAIConfig->tooCloseDistance * cos(ori); - // float y1 = y + sPlayerbotAIConfig->tooCloseDistance * sin(ori); + // float x1 = x + sPlayerbotAIConfig.tooCloseDistance * cos(ori); + // float y1 = y + sPlayerbotAIConfig.tooCloseDistance * sin(ori); // float ground = map->GetHeight(x1, y1, z); // if (ground > INVALID_HEIGHT) // { @@ -111,7 +111,7 @@ class NearFormation : public MoveAheadFormation if (!ValidateTargetContext(master, bot, map)) return Formation::NullLocation; - float range = sPlayerbotAIConfig->followDistance; + float range = sPlayerbotAIConfig.followDistance; float angle = GetFollowAngle(); float x = master->GetPositionX() + cos(angle) * range; float y = master->GetPositionY() + sin(angle) * range; @@ -127,7 +127,7 @@ class NearFormation : public MoveAheadFormation return WorldLocation(master->GetMapId(), x, y, z); } - float GetMaxDistance() override { return sPlayerbotAIConfig->followDistance; } + float GetMaxDistance() override { return sPlayerbotAIConfig.followDistance; } }; class ChaosFormation : public MoveAheadFormation @@ -142,7 +142,7 @@ class ChaosFormation : public MoveAheadFormation if (!ValidateTargetContext(master, bot, map)) return Formation::NullLocation; - float range = sPlayerbotAIConfig->followDistance; + float range = sPlayerbotAIConfig.followDistance; float angle = GetFollowAngle(); time_t now = time(nullptr); @@ -150,8 +150,8 @@ class ChaosFormation : public MoveAheadFormation { lastChangeTime = now; - dx = (urand(0, 10) / 10.0f - 0.5f) * sPlayerbotAIConfig->tooCloseDistance; - dy = (urand(0, 10) / 10.0f - 0.5f) * sPlayerbotAIConfig->tooCloseDistance; + dx = (urand(0, 10) / 10.0f - 0.5f) * sPlayerbotAIConfig.tooCloseDistance; + dy = (urand(0, 10) / 10.0f - 0.5f) * sPlayerbotAIConfig.tooCloseDistance; dr = std::sqrt(dx * dx + dy * dy); } @@ -173,7 +173,7 @@ class ChaosFormation : public MoveAheadFormation return WorldLocation(master->GetMapId(), x, y, z); } - float GetMaxDistance() override { return sPlayerbotAIConfig->followDistance + dr; } + float GetMaxDistance() override { return sPlayerbotAIConfig.followDistance + dr; } private: time_t lastChangeTime; @@ -287,7 +287,7 @@ class ShieldFormation : public MoveFormation if (!group) return Formation::NullLocation; - float range = sPlayerbotAIConfig->followDistance; + float range = sPlayerbotAIConfig.followDistance; Player* master = GetMaster(); if (!master) @@ -326,14 +326,14 @@ class ShieldFormation : public MoveFormation if (botAI->IsTank(bot) && !botAI->IsTank(master)) { - float diff = (tanks.size() % 2 == 0) ? -sPlayerbotAIConfig->tooCloseDistance / 2.0f : 0.0f; + float diff = (tanks.size() % 2 == 0) ? -sPlayerbotAIConfig.tooCloseDistance / 2.0f : 0.0f; return MoveLine(tanks, diff, x + cos(orientation) * range, y + sin(orientation) * range, z, orientation, range); } if (!botAI->IsTank(bot) && botAI->IsTank(master)) { - float diff = (dps.size() % 2 == 0) ? -sPlayerbotAIConfig->tooCloseDistance / 2.0f : 0.0f; + float diff = (dps.size() % 2 == 0) ? -sPlayerbotAIConfig.tooCloseDistance / 2.0f : 0.0f; return MoveLine(dps, diff, x - cos(orientation) * range, y - sin(orientation) * range, z, orientation, range); } @@ -354,10 +354,10 @@ class FarFormation : public FollowFormation if (!ValidateTargetContext(master, bot, map)) return Formation::NullLocation; - float range = sPlayerbotAIConfig->farDistance; - float followRange = sPlayerbotAIConfig->followDistance; + float range = sPlayerbotAIConfig.farDistance; + float followRange = sPlayerbotAIConfig.followDistance; - if (sServerFacade->GetDistance2d(bot, master) <= range) + if (ServerFacade::instance().GetDistance2d(bot, master) <= range) return Formation::NullLocation; float angleToBot = master->GetAngle(bot); @@ -378,7 +378,7 @@ class FarFormation : public FollowFormation float tx = master->GetPositionX() + cos(a) * range + cos(followAngle) * followRange; float ty = master->GetPositionY() + sin(a) * range + sin(followAngle) * followRange; - float dist = sServerFacade->GetDistance2d(bot, tx, ty); + float dist = ServerFacade::instance().GetDistance2d(bot, tx, ty); float tg = master->GetMapHeight(tx, ty, z + 30.0f); if (tg > INVALID_HEIGHT && (!minDist || dist < minDist)) diff --git a/src/Ai/Base/Value/Formations.h b/src/Ai/Base/Value/Formations.h index c44e1d0f42..3e5decf7f1 100644 --- a/src/Ai/Base/Value/Formations.h +++ b/src/Ai/Base/Value/Formations.h @@ -21,7 +21,7 @@ class Formation : public AiNamedObject virtual ~Formation() = default; virtual std::string const GetTargetName() { return ""; } virtual WorldLocation GetLocation() { return NullLocation; } - virtual float GetMaxDistance() { return sPlayerbotAIConfig->followDistance; } + virtual float GetMaxDistance() { return sPlayerbotAIConfig.followDistance; } static WorldLocation NullLocation; static bool IsNullLocation(WorldLocation const& loc); diff --git a/src/Ai/Base/Value/GrindTargetValue.cpp b/src/Ai/Base/Value/GrindTargetValue.cpp index 7e6168c776..d0c5095b8a 100644 --- a/src/Ai/Base/Value/GrindTargetValue.cpp +++ b/src/Ai/Base/Value/GrindTargetValue.cpp @@ -30,7 +30,6 @@ Unit* GrindTargetValue::Calculate() Unit* GrindTargetValue::FindTargetForGrinding(uint32 assistCount) { - uint32 memberCount = 1; Group* group = bot->GetGroup(); Player* master = GetMaster(); @@ -65,7 +64,6 @@ Unit* GrindTargetValue::FindTargetForGrinding(uint32 assistCount) if (!unit->IsInWorld() || unit->IsDuringRemoveFromWorld()) continue; - auto& rep = bot->ToPlayer()->GetReputationMgr(); if (unit->ToCreature() && !unit->ToCreature()->GetCreatureTemplate()->lootid && bot->GetReactionTo(unit) >= REP_NEUTRAL) continue; @@ -82,12 +80,12 @@ Unit* GrindTargetValue::FindTargetForGrinding(uint32 assistCount) if (!bot->InBattleground() && GetTargetingPlayerCount(unit) > assistCount) continue; - // if (!bot->InBattleground() && master && master->GetDistance(unit) >= sPlayerbotAIConfig->grindDistance && - // !sRandomPlayerbotMgr->IsRandomBot(bot)) continue; + // if (!bot->InBattleground() && master && master->GetDistance(unit) >= sPlayerbotAIConfig.grindDistance && + // !sRandomPlayerbotMgr.IsRandomBot(bot)) continue; // Bots in bot-groups no have a more limited range to look for grind target if (!bot->InBattleground() && master && botAI->HasStrategy("follow", BotState::BOT_STATE_NON_COMBAT) && - sServerFacade->GetDistance2d(master, unit) > sPlayerbotAIConfig->lootDistance) + ServerFacade::instance().GetDistance2d(master, unit) > sPlayerbotAIConfig.lootDistance) { if (botAI->HasStrategy("debug grind", BotState::BOT_STATE_NON_COMBAT)) botAI->TellMaster(chat->FormatWorldobject(unit) + " ignored (far from master)."); @@ -184,7 +182,9 @@ bool GrindTargetValue::needForQuest(Unit* target) int required = questTemplate->RequiredNpcOrGoCount[j]; int available = questStatus->CreatureOrGOCount[j]; - if (required && available < required && target->GetEntry() == entry) + const int64_t targetEntry = target->GetEntry(); + + if (required && available < required && targetEntry == entry) return true; } } diff --git a/src/Ai/Base/Value/GroupValues.cpp b/src/Ai/Base/Value/GroupValues.cpp index 01049a7969..460b9f334d 100644 --- a/src/Ai/Base/Value/GroupValues.cpp +++ b/src/Ai/Base/Value/GroupValues.cpp @@ -47,7 +47,7 @@ bool IsNearLeaderValue::Calculate() if (groupLeader == bot) return true; - return sServerFacade->GetDistance2d(bot, botAI->GetGroupLeader()) < sPlayerbotAIConfig->sightDistance; + return ServerFacade::instance().GetDistance2d(bot, botAI->GetGroupLeader()) < sPlayerbotAIConfig.sightDistance; } bool BoolANDValue::Calculate() @@ -155,10 +155,10 @@ bool GroupReadyValue::Calculate() // We only wait for members that are in range otherwise we might be waiting for bots stuck in dead loops // forever. if (botAI->GetGroupLeader() && - sServerFacade->GetDistance2d(member, botAI->GetGroupLeader()) > sPlayerbotAIConfig->sightDistance) + ServerFacade::instance().GetDistance2d(member, botAI->GetGroupLeader()) > sPlayerbotAIConfig.sightDistance) continue; - if (member->GetHealthPct() < sPlayerbotAIConfig->almostFullHealth) + if (member->GetHealthPct() < sPlayerbotAIConfig.almostFullHealth) return false; if (!member->GetPower(POWER_MANA)) @@ -166,7 +166,7 @@ bool GroupReadyValue::Calculate() float mana = (static_cast(member->GetPower(POWER_MANA)) / member->GetMaxPower(POWER_MANA)) * 100; - if (mana < sPlayerbotAIConfig->mediumMana) + if (mana < sPlayerbotAIConfig.mediumMana) return false; } diff --git a/src/Ai/Base/Value/HasAvailableLootValue.cpp b/src/Ai/Base/Value/HasAvailableLootValue.cpp index d687e1fc41..532e06afcd 100644 --- a/src/Ai/Base/Value/HasAvailableLootValue.cpp +++ b/src/Ai/Base/Value/HasAvailableLootValue.cpp @@ -11,5 +11,5 @@ bool HasAvailableLootValue::Calculate() { return !AI_VALUE(bool, "can loot") && - AI_VALUE(LootObjectStack*, "available loot")->CanLoot(sPlayerbotAIConfig->lootDistance); + AI_VALUE(LootObjectStack*, "available loot")->CanLoot(sPlayerbotAIConfig.lootDistance); } diff --git a/src/Ai/Base/Value/ItemCountValue.cpp b/src/Ai/Base/Value/ItemCountValue.cpp index 2c719d8f4d..9d4cb729f9 100644 --- a/src/Ai/Base/Value/ItemCountValue.cpp +++ b/src/Ai/Base/Value/ItemCountValue.cpp @@ -5,26 +5,12 @@ #include "ItemCountValue.h" -#include "Playerbots.h" - -std::vector InventoryItemValueBase::Find(std::string const qualifier) +uint32_t ItemCountValue::Calculate() { - std::vector result; - - Player* bot = InventoryAction::botAI->GetBot(); - + uint32_t count = 0; std::vector items = InventoryAction::parseItems(qualifier); - for (Item* item : items) - result.push_back(item); - - return result; -} -uint32 ItemCountValue::Calculate() -{ - uint32 count = 0; - std::vector items = Find(qualifier); - for (Item* item : items) + for (const Item* const item : items) { count += item->GetCount(); } @@ -32,4 +18,7 @@ uint32 ItemCountValue::Calculate() return count; } -std::vector InventoryItemValue::Calculate() { return Find(qualifier); } +std::vector InventoryItemValue::Calculate() +{ + return InventoryAction::parseItems(qualifier); +} diff --git a/src/Ai/Base/Value/ItemCountValue.h b/src/Ai/Base/Value/ItemCountValue.h index 6f7c593b23..41ac9a62f4 100644 --- a/src/Ai/Base/Value/ItemCountValue.h +++ b/src/Ai/Base/Value/ItemCountValue.h @@ -17,10 +17,7 @@ class InventoryItemValueBase : public InventoryAction public: InventoryItemValueBase(PlayerbotAI* botAI) : InventoryAction(botAI, "empty") {} - bool Execute(Event event) override { return false; } - -protected: - std::vector Find(std::string const qualifier); + bool Execute(Event) override { return false; } }; class ItemCountValue : public Uint32CalculatedValue, public Qualified, InventoryItemValueBase diff --git a/src/Ai/Base/Value/ItemUsageValue.cpp b/src/Ai/Base/Value/ItemUsageValue.cpp index 25866c8059..b0dcddb706 100644 --- a/src/Ai/Base/Value/ItemUsageValue.cpp +++ b/src/Ai/Base/Value/ItemUsageValue.cpp @@ -56,7 +56,7 @@ ItemUsage ItemUsageValue::Calculate() if (proto->Class == ITEM_CLASS_TRADE_GOODS || proto->Class == ITEM_CLASS_MISC || proto->Class == ITEM_CLASS_REAGENT) - needItem = IsItemNeededForUsefullSpell(proto, lowBagSpace); + needItem = IsItemNeededForUsefullSpell(*proto, lowBagSpace); else if (proto->Class == ITEM_CLASS_RECIPE) { if (bot->HasSpell(proto->Spells[2].SpellId)) @@ -79,8 +79,10 @@ ItemUsage ItemUsageValue::Calculate() if (proto->Class == ITEM_CLASS_KEY) return ITEM_USAGE_USE; + const uint32_t maxCount = proto->MaxCount; + if (proto->Class == ITEM_CLASS_CONSUMABLE && - (proto->MaxCount == 0 || bot->GetItemCount(itemId, false) < proto->MaxCount)) + (maxCount == 0 || bot->GetItemCount(itemId, false) < maxCount)) { std::string const foodType = GetConsumableType(proto, bot->GetPower(POWER_MANA)); @@ -99,7 +101,7 @@ ItemUsage ItemUsageValue::Calculate() } } - if (bot->GetGuildId() && sGuildTaskMgr->IsGuildTaskItem(itemId, bot->GetGuildId())) + if (bot->GetGuildId() && GuildTaskMgr::instance().IsGuildTaskItem(itemId, bot->GetGuildId())) return ITEM_USAGE_GUILD_TASK; ItemUsage equip = QueryItemUsageForEquip(proto, randomPropertyId); @@ -129,7 +131,7 @@ ItemUsage ItemUsageValue::Calculate() Player* master = botAI->GetMaster(); bool isSelfBot = (master == bot); bool botNeedsItemForQuest = IsItemUsefulForQuest(bot, proto); - bool masterNeedsItemForQuest = master && sPlayerbotAIConfig->syncQuestWithPlayer && IsItemUsefulForQuest(master, proto); + bool masterNeedsItemForQuest = master && sPlayerbotAIConfig.syncQuestWithPlayer && IsItemUsefulForQuest(master, proto); // Identify the source of loot LootObject lootObject = AI_VALUE(LootObject, "loot target"); @@ -304,7 +306,7 @@ ItemUsage ItemUsageValue::QueryItemUsageForEquip(ItemTemplate const* itemProto, } bool shouldEquip = false; - // uint32 statWeight = sRandomItemMgr->GetLiveStatWeight(bot, itemProto->ItemId); + // uint32 statWeight = sRandomItemMgr.GetLiveStatWeight(bot, itemProto->ItemId); StatsWeightCalculator calculator(bot); calculator.SetItemSetBonus(false); calculator.SetOverflowPenalty(false); @@ -314,10 +316,10 @@ ItemUsage ItemUsageValue::QueryItemUsageForEquip(ItemTemplate const* itemProto, if (itemScore) shouldEquip = true; - if (itemProto->Class == ITEM_CLASS_WEAPON && !sRandomItemMgr->CanEquipWeapon(bot->getClass(), itemProto)) + if (itemProto->Class == ITEM_CLASS_WEAPON && !sRandomItemMgr.CanEquipWeapon(bot->getClass(), itemProto)) shouldEquip = false; if (itemProto->Class == ITEM_CLASS_ARMOR && - !sRandomItemMgr->CanEquipArmor(bot->getClass(), bot->GetLevel(), itemProto)) + !sRandomItemMgr.CanEquipArmor(bot->getClass(), bot->GetLevel(), itemProto)) shouldEquip = false; uint8 possibleSlots = 1; @@ -396,10 +398,10 @@ ItemUsage ItemUsageValue::QueryItemUsageForEquip(ItemTemplate const* itemProto, float oldScore = calculator.CalculateItem(oldItemProto->ItemId, oldItem->GetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID)); if (oldItem) { - // uint32 oldStatWeight = sRandomItemMgr->GetLiveStatWeight(bot, oldItemProto->ItemId); + // uint32 oldStatWeight = sRandomItemMgr.GetLiveStatWeight(bot, oldItemProto->ItemId); if (itemScore || oldScore) { - shouldEquipInSlot = itemScore > oldScore * sPlayerbotAIConfig->equipUpgradeThreshold; + shouldEquipInSlot = itemScore > oldScore * sPlayerbotAIConfig.equipUpgradeThreshold; } } @@ -417,15 +419,15 @@ ItemUsage ItemUsageValue::QueryItemUsageForEquip(ItemTemplate const* itemProto, } bool existingShouldEquip = true; - if (oldItemProto->Class == ITEM_CLASS_WEAPON && !sRandomItemMgr->CanEquipWeapon(bot->getClass(), oldItemProto)) + if (oldItemProto->Class == ITEM_CLASS_WEAPON && !sRandomItemMgr.CanEquipWeapon(bot->getClass(), oldItemProto)) existingShouldEquip = false; if (oldItemProto->Class == ITEM_CLASS_ARMOR && - !sRandomItemMgr->CanEquipArmor(bot->getClass(), bot->GetLevel(), oldItemProto)) + !sRandomItemMgr.CanEquipArmor(bot->getClass(), bot->GetLevel(), oldItemProto)) existingShouldEquip = false; - // uint32 oldItemPower = sRandomItemMgr->GetLiveStatWeight(bot, oldItemProto->ItemId); - // uint32 newItemPower = sRandomItemMgr->GetLiveStatWeight(bot, itemProto->ItemId); + // uint32 oldItemPower = sRandomItemMgr.GetLiveStatWeight(bot, oldItemProto->ItemId); + // uint32 newItemPower = sRandomItemMgr.GetLiveStatWeight(bot, itemProto->ItemId); // Compare items based on item level, quality or itemId. bool isBetter = false; @@ -695,57 +697,86 @@ bool ItemUsageValue::IsItemUsefulForSkill(ItemTemplate const* proto) return false; } -bool ItemUsageValue::IsItemNeededForUsefullSpell(ItemTemplate const* proto, bool checkAllReagents) +bool ItemUsageValue::IsItemNeededForUsefullSpell(const ItemTemplate& itemTemplate, bool checkAllReagents) const { - for (auto spellId : SpellsUsingItem(proto->ItemId, bot)) + for (uint32_t spellId : SpellsUsingItem(itemTemplate.ItemId, bot)) { - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - if (!spellInfo) + const SpellInfo* const spellInfo = SpellMgr::instance()->GetSpellInfo(spellId); + + if (spellInfo == nullptr) + { continue; + } - if (checkAllReagents && !HasItemsNeededForSpell(spellId, proto)) + if (checkAllReagents && !this->HasItemsNeededForSpell(spellId, itemTemplate)) + { continue; + } - if (SpellGivesSkillUp(spellId, bot)) + if (this->SpellGivesSkillUp(spellId, bot)) + { return true; + } - uint32 newItemId = spellInfo->Effects[EFFECT_0].ItemType; - if (newItemId && newItemId != proto->ItemId) + const uint32_t newItemId = spellInfo->Effects[EFFECT_0].ItemType; + + if (newItemId == 0 || newItemId == itemTemplate.ItemId) { - ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", newItemId); + continue; + } - if (usage != ITEM_USAGE_REPLACE && usage != ITEM_USAGE_EQUIP && usage != ITEM_USAGE_AMMO && - usage != ITEM_USAGE_QUEST && usage != ITEM_USAGE_SKILL && usage != ITEM_USAGE_USE) - continue; + const ItemUsage usage = this->context->GetValue("item usage", newItemId)->Get(); - return true; + if (usage != ITEM_USAGE_REPLACE + && usage != ITEM_USAGE_EQUIP + && usage != ITEM_USAGE_AMMO + && usage != ITEM_USAGE_QUEST + && usage != ITEM_USAGE_SKILL + && usage != ITEM_USAGE_USE + ) + { + continue; } + + return true; } return false; } -bool ItemUsageValue::HasItemsNeededForSpell(uint32 spellId, ItemTemplate const* proto) +bool ItemUsageValue::HasItemsNeededForSpell(uint32_t spellId, const ItemTemplate& itemTemplate) const { - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - if (!spellInfo) + const SpellInfo* const spellInfo = SpellMgr::instance()->GetSpellInfo(spellId); + + if (spellInfo == nullptr) + { return false; + } - for (uint8 i = 0; i < MAX_SPELL_REAGENTS; i++) - if (spellInfo->ReagentCount[i] > 0 && spellInfo->Reagent[i]) + for (uint8_t i = 0; i < MAX_SPELL_REAGENTS; i++) + { + if (spellInfo->ReagentCount[i] < 1 || spellInfo->Reagent[i] == 0) { - if (proto && proto->ItemId == spellInfo->Reagent[i] && - spellInfo->ReagentCount[i] == 1) // If we only need 1 item then current item does not need to be - // checked since we are looting/buying or already have it. - continue; + continue; + } + + const int64_t itemTemplateId = itemTemplate.ItemId; - ItemTemplate const* reqProto = sObjectMgr->GetItemTemplate(spellInfo->Reagent[i]); + // If we only need 1 item then current item does not need to be + // checked since we are looting/buying or already have it. + if (itemTemplateId == spellInfo->Reagent[i] && spellInfo->ReagentCount[i] == 1) + { + continue; + } - uint32 count = AI_VALUE2(uint32, "item count", reqProto->Name1); + const ItemTemplate* const requiredItemTemplate = ObjectMgr::instance()->GetItemTemplate(spellInfo->Reagent[i]); + const uint32_t count = this->context->GetValue("item count", requiredItemTemplate->Name1)->Get(); - if (count < spellInfo->ReagentCount[i]) - return false; + if (count < spellInfo->ReagentCount[i]) + { + return false; } + } return true; } @@ -809,7 +840,7 @@ float ItemUsageValue::BetterStacks(ItemTemplate const* proto, std::string const return stacks; } -std::vector ItemUsageValue::SpellsUsingItem(uint32 itemId, Player* bot) +std::vector ItemUsageValue::SpellsUsingItem(int64_t itemId, Player* bot) { std::vector retSpells; @@ -854,23 +885,27 @@ inline int32 SkillGainChance(uint32 SkillValue, uint32 GrayLevel, uint32 GreenLe return sWorld->getIntConfig(CONFIG_SKILL_CHANCE_ORANGE) * 10; } -bool ItemUsageValue::SpellGivesSkillUp(uint32 spellId, Player* bot) +bool ItemUsageValue::SpellGivesSkillUp(const uint32_t spellId, const Player* const bot) { - SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(spellId); + const SkillLineAbilityMapBounds bounds = SpellMgr::instance()->GetSkillLineAbilityMapBounds(spellId); - for (SkillLineAbilityMap::const_iterator _spell_idx = bounds.first; _spell_idx != bounds.second; ++_spell_idx) + for (SkillLineAbilityMap::const_iterator spellIterator = bounds.first; spellIterator != bounds.second; ++spellIterator) { - SkillLineAbilityEntry const* skill = _spell_idx->second; - if (skill->SkillLine) + const SkillLineAbilityEntry* const skill = spellIterator->second; + + if (skill->SkillLine == 0) { - uint32 SkillValue = bot->GetPureSkillValue(skill->SkillLine); + continue; + } - uint32 craft_skill_gain = sWorld->getIntConfig(CONFIG_SKILL_GAIN_CRAFTING); + const uint32_t SkillValue = bot->GetPureSkillValue(skill->SkillLine); - if (SkillGainChance(SkillValue, skill->TrivialSkillLineRankHigh, - (skill->TrivialSkillLineRankHigh + skill->TrivialSkillLineRankLow) / 2, - skill->TrivialSkillLineRankLow) > 0) - return true; + if (SkillGainChance(SkillValue, skill->TrivialSkillLineRankHigh, + (skill->TrivialSkillLineRankHigh + skill->TrivialSkillLineRankLow) / 2, + skill->TrivialSkillLineRankLow) > 0 + ) + { + return true; } } diff --git a/src/Ai/Base/Value/ItemUsageValue.h b/src/Ai/Base/Value/ItemUsageValue.h index d50ea1b060..27cc724b72 100644 --- a/src/Ai/Base/Value/ItemUsageValue.h +++ b/src/Ai/Base/Value/ItemUsageValue.h @@ -48,15 +48,15 @@ class ItemUsageValue : public CalculatedValue, public Qualified bool IsItemUsefulForQuest(Player* player, ItemTemplate const* proto); bool IsItemNeededForSkill(ItemTemplate const* proto); bool IsItemUsefulForSkill(ItemTemplate const* proto); - bool IsItemNeededForUsefullSpell(ItemTemplate const* proto, bool checkAllReagents = false); - bool HasItemsNeededForSpell(uint32 spellId, ItemTemplate const* proto); + bool IsItemNeededForUsefullSpell(const ItemTemplate& proto, bool checkAllReagents = false) const; + bool HasItemsNeededForSpell(uint32_t spellId, const ItemTemplate& proto) const; Item* CurrentItem(ItemTemplate const* proto); float CurrentStacks(ItemTemplate const* proto); float BetterStacks(ItemTemplate const* proto, std::string const usageType = ""); public: - static std::vector SpellsUsingItem(uint32 itemId, Player* bot); - static bool SpellGivesSkillUp(uint32 spellId, Player* bot); + static std::vector SpellsUsingItem(int64_t itemId, Player* bot); + static bool SpellGivesSkillUp(const uint32_t spellId, const Player* const bot); static std::string const GetConsumableType(ItemTemplate const* proto, bool hasMana); }; diff --git a/src/Ai/Base/Value/LastMovementValue.cpp b/src/Ai/Base/Value/LastMovementValue.cpp index ba54020e39..34f554616a 100644 --- a/src/Ai/Base/Value/LastMovementValue.cpp +++ b/src/Ai/Base/Value/LastMovementValue.cpp @@ -5,7 +5,6 @@ #include "LastMovementValue.h" -#include "Playerbots.h" #include "Timer.h" LastMovement::LastMovement() { clear(); } @@ -15,11 +14,11 @@ LastMovement::LastMovement(LastMovement& other) taxiMaster(other.taxiMaster), lastFollow(other.lastFollow), lastAreaTrigger(other.lastAreaTrigger), + lastFlee(other.lastFlee), lastMoveToX(other.lastMoveToX), lastMoveToY(other.lastMoveToY), lastMoveToZ(other.lastMoveToZ), - lastMoveToOri(other.lastMoveToOri), - lastFlee(other.lastFlee) + lastMoveToOri(other.lastMoveToOri) { lastMoveShort = other.lastMoveShort; nextTeleport = other.nextTeleport; diff --git a/src/Ai/Base/Value/LeastHpTargetValue.cpp b/src/Ai/Base/Value/LeastHpTargetValue.cpp index 8b9f1a55fc..04b3fcefff 100644 --- a/src/Ai/Base/Value/LeastHpTargetValue.cpp +++ b/src/Ai/Base/Value/LeastHpTargetValue.cpp @@ -6,16 +6,14 @@ #include "LeastHpTargetValue.h" #include "AttackersValue.h" -#include "Playerbots.h" class FindLeastHpTargetStrategy : public FindNonCcTargetStrategy { public: FindLeastHpTargetStrategy(PlayerbotAI* botAI) : FindNonCcTargetStrategy(botAI), minHealth(0) {} - void CheckAttacker(Unit* attacker, ThreatMgr* threatMgr) override + void CheckAttacker(Unit* attacker, ThreatMgr*) override { - Player* bot = botAI->GetBot(); if (IsCcTarget(attacker)) return; @@ -30,5 +28,6 @@ class FindLeastHpTargetStrategy : public FindNonCcTargetStrategy Unit* LeastHpTargetValue::Calculate() { FindLeastHpTargetStrategy strategy(botAI); + return FindTarget(&strategy); } diff --git a/src/Ai/Base/Value/LogLevelValue.h b/src/Ai/Base/Value/LogLevelValue.h index 18fdbddcee..f8515b13b2 100644 --- a/src/Ai/Base/Value/LogLevelValue.h +++ b/src/Ai/Base/Value/LogLevelValue.h @@ -6,6 +6,7 @@ #ifndef _PLAYERBOT_LOGLEVELVALUE_H #define _PLAYERBOT_LOGLEVELVALUE_H +#include "LogCommon.h" #include "Value.h" class PlayerbotAI; diff --git a/src/Ai/Base/Value/LootStrategyValue.cpp b/src/Ai/Base/Value/LootStrategyValue.cpp index 6a4f9b9b48..0ff6f7e98b 100644 --- a/src/Ai/Base/Value/LootStrategyValue.cpp +++ b/src/Ai/Base/Value/LootStrategyValue.cpp @@ -60,7 +60,7 @@ class DisenchantLootStrategy : public NormalLootStrategy class AllLootStrategy : public LootStrategy { public: - bool CanLoot(ItemTemplate const* proto, AiObjectContext* context) override { return true; } + bool CanLoot(ItemTemplate const*, AiObjectContext*) override { return true; } std::string const GetName() override { return "all"; } }; diff --git a/src/Ai/Base/Value/NearestAdsValue.h b/src/Ai/Base/Value/NearestAdsValue.h index 312d5596eb..b9e3fbe316 100644 --- a/src/Ai/Base/Value/NearestAdsValue.h +++ b/src/Ai/Base/Value/NearestAdsValue.h @@ -14,7 +14,7 @@ class PlayerbotAI; class NearestAddsValue : public PossibleTargetsValue { public: - NearestAddsValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig->tooCloseDistance) + NearestAddsValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig.tooCloseDistance) : PossibleTargetsValue(botAI, "nearest adds", range, true) { } diff --git a/src/Ai/Base/Value/NearestCorpsesValue.cpp b/src/Ai/Base/Value/NearestCorpsesValue.cpp index fec1aed21f..3e049ea24d 100644 --- a/src/Ai/Base/Value/NearestCorpsesValue.cpp +++ b/src/Ai/Base/Value/NearestCorpsesValue.cpp @@ -5,28 +5,30 @@ #include "NearestCorpsesValue.h" -#include "CellImpl.h" #include "GridNotifiers.h" +// Required due to +#include "CellImpl.h" #include "GridNotifiersImpl.h" -#include "Playerbots.h" class AnyDeadUnitInObjectRangeCheck { public: - AnyDeadUnitInObjectRangeCheck(WorldObject const* obj, float range) : i_obj(obj), i_range(range) {} + AnyDeadUnitInObjectRangeCheck(WorldObject const* obj) : i_obj(obj) {} WorldObject const& GetFocusObject() const { return *i_obj; } bool operator()(Unit* u) { return !u->IsAlive(); } private: WorldObject const* i_obj; - float i_range; }; void NearestCorpsesValue::FindUnits(std::list& targets) { - AnyDeadUnitInObjectRangeCheck u_check(bot, range); + AnyDeadUnitInObjectRangeCheck u_check(bot); Acore::UnitListSearcher searcher(bot, targets, u_check); Cell::VisitObjects(bot, searcher, range); } -bool NearestCorpsesValue::AcceptUnit(Unit* unit) { return true; } +bool NearestCorpsesValue::AcceptUnit(Unit*) +{ + return true; +} diff --git a/src/Ai/Base/Value/NearestCorpsesValue.h b/src/Ai/Base/Value/NearestCorpsesValue.h index 4c0716e299..f6a067c3fe 100644 --- a/src/Ai/Base/Value/NearestCorpsesValue.h +++ b/src/Ai/Base/Value/NearestCorpsesValue.h @@ -14,7 +14,7 @@ class PlayerbotAI; class NearestCorpsesValue : public NearestUnitsValue { public: - NearestCorpsesValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig->sightDistance) + NearestCorpsesValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig.sightDistance) : NearestUnitsValue(botAI, "nearest corpses", range, true) { } diff --git a/src/Ai/Base/Value/NearestFriendlyPlayersValue.h b/src/Ai/Base/Value/NearestFriendlyPlayersValue.h index 9876316929..2588409044 100644 --- a/src/Ai/Base/Value/NearestFriendlyPlayersValue.h +++ b/src/Ai/Base/Value/NearestFriendlyPlayersValue.h @@ -14,7 +14,7 @@ class PlayerbotAI; class NearestFriendlyPlayersValue : public NearestUnitsValue { public: - NearestFriendlyPlayersValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig->sightDistance) + NearestFriendlyPlayersValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig.sightDistance) : NearestUnitsValue(botAI, "nearest friendly players", range) { } diff --git a/src/Ai/Base/Value/NearestGameObjects.h b/src/Ai/Base/Value/NearestGameObjects.h index 2018e93eb1..9d1153aade 100644 --- a/src/Ai/Base/Value/NearestGameObjects.h +++ b/src/Ai/Base/Value/NearestGameObjects.h @@ -33,7 +33,7 @@ class AnyGameObjectInObjectRangeCheck class NearestGameObjects : public ObjectGuidListCalculatedValue { public: - NearestGameObjects(PlayerbotAI* botAI, float range = sPlayerbotAIConfig->sightDistance, bool ignoreLos = false, + NearestGameObjects(PlayerbotAI* botAI, float range = sPlayerbotAIConfig.sightDistance, bool ignoreLos = false, std::string const name = "nearest game objects") : ObjectGuidListCalculatedValue(botAI, name, 1 * 1000), range(range), ignoreLos(ignoreLos) { diff --git a/src/Ai/Base/Value/NearestNonBotPlayersValue.h b/src/Ai/Base/Value/NearestNonBotPlayersValue.h index 73d522c5fb..1980bcf2ba 100644 --- a/src/Ai/Base/Value/NearestNonBotPlayersValue.h +++ b/src/Ai/Base/Value/NearestNonBotPlayersValue.h @@ -14,7 +14,7 @@ class PlayerbotAI; class NearestNonBotPlayersValue : public NearestUnitsValue { public: - NearestNonBotPlayersValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig->grindDistance) + NearestNonBotPlayersValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig.grindDistance) : NearestUnitsValue(botAI, "nearest non bot players", range, true) { } diff --git a/src/Ai/Base/Value/NearestNpcsValue.h b/src/Ai/Base/Value/NearestNpcsValue.h index 6935026147..71e1d9de45 100644 --- a/src/Ai/Base/Value/NearestNpcsValue.h +++ b/src/Ai/Base/Value/NearestNpcsValue.h @@ -14,7 +14,7 @@ class PlayerbotAI; class NearestNpcsValue : public NearestUnitsValue { public: - NearestNpcsValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig->sightDistance) + NearestNpcsValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig.sightDistance) : NearestUnitsValue(botAI, "nearest npcs", range) { } @@ -27,7 +27,7 @@ class NearestNpcsValue : public NearestUnitsValue class NearestHostileNpcsValue : public NearestUnitsValue { public: - NearestHostileNpcsValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig->sightDistance) + NearestHostileNpcsValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig.sightDistance) : NearestUnitsValue(botAI, "nearest hostile npcs", range) { } @@ -40,7 +40,7 @@ class NearestHostileNpcsValue : public NearestUnitsValue class NearestVehiclesValue : public NearestUnitsValue { public: - NearestVehiclesValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig->sightDistance) + NearestVehiclesValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig.sightDistance) : NearestUnitsValue(botAI, "nearest vehicles", range) { } @@ -53,7 +53,7 @@ class NearestVehiclesValue : public NearestUnitsValue class NearestTriggersValue : public NearestUnitsValue { public: - NearestTriggersValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig->sightDistance) + NearestTriggersValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig.sightDistance) : NearestUnitsValue(botAI, "nearest triggers", range) { } diff --git a/src/Ai/Base/Value/NearestUnitsValue.h b/src/Ai/Base/Value/NearestUnitsValue.h index 527925a0d7..5e00cb6d09 100644 --- a/src/Ai/Base/Value/NearestUnitsValue.h +++ b/src/Ai/Base/Value/NearestUnitsValue.h @@ -16,7 +16,7 @@ class NearestUnitsValue : public ObjectGuidListCalculatedValue { public: NearestUnitsValue(PlayerbotAI* botAI, std::string const name = "nearest units", - float range = sPlayerbotAIConfig->sightDistance, bool ignoreLos = false, uint32 checkInterval = 1) + float range = sPlayerbotAIConfig.sightDistance, bool ignoreLos = false, uint32 checkInterval = 1) : ObjectGuidListCalculatedValue(botAI, name, checkInterval), range(range), ignoreLos(ignoreLos) { } diff --git a/src/Ai/Base/Value/PartyMemberToDispel.cpp b/src/Ai/Base/Value/PartyMemberToDispel.cpp index 91b1955b27..d578052c10 100644 --- a/src/Ai/Base/Value/PartyMemberToDispel.cpp +++ b/src/Ai/Base/Value/PartyMemberToDispel.cpp @@ -4,14 +4,14 @@ */ #include "PartyMemberToDispel.h" +#include "PlayerbotAI.h" -#include "Playerbots.h" class PartyMemberToDispelPredicate : public FindPlayerPredicate, public PlayerbotAIAware { public: PartyMemberToDispelPredicate(PlayerbotAI* botAI, uint32 dispelType) - : PlayerbotAIAware(botAI), FindPlayerPredicate(), dispelType(dispelType) + : FindPlayerPredicate(), PlayerbotAIAware(botAI), dispelType(dispelType) { } diff --git a/src/Ai/Base/Value/PartyMemberToHeal.cpp b/src/Ai/Base/Value/PartyMemberToHeal.cpp index 47554c7c2b..b49c1cd419 100644 --- a/src/Ai/Base/Value/PartyMemberToHeal.cpp +++ b/src/Ai/Base/Value/PartyMemberToHeal.cpp @@ -46,10 +46,10 @@ Unit* PartyMemberToHeal::Calculate() if (player && player->IsAlive()) { uint8 health = player->GetHealthPct(); - if (isRaid || health < sPlayerbotAIConfig->mediumHealth || !IsTargetOfSpellCast(player, predicate)) + if (isRaid || health < sPlayerbotAIConfig.mediumHealth || !IsTargetOfSpellCast(player, predicate)) { uint32 probeValue = 100; - if (player->GetDistance2d(bot) > sPlayerbotAIConfig->healDistance) + if (player->GetDistance2d(bot) > sPlayerbotAIConfig.healDistance) { probeValue = health + 30; } @@ -70,7 +70,7 @@ Unit* PartyMemberToHeal::Calculate() { uint8 health = ((Unit*)pet)->GetHealthPct(); uint32 probeValue = 100; - if (isRaid || health < sPlayerbotAIConfig->mediumHealth) + if (isRaid || health < sPlayerbotAIConfig.mediumHealth) probeValue = health + 30; // delay Check pet to here for better performance if (probeValue < calc.minValue && Check(pet)) @@ -84,7 +84,7 @@ Unit* PartyMemberToHeal::Calculate() { uint8 health = charm->GetHealthPct(); uint32 probeValue = 100; - if (isRaid || health < sPlayerbotAIConfig->mediumHealth) + if (isRaid || health < sPlayerbotAIConfig.mediumHealth) probeValue = health + 30; // delay Check charm to here for better performance if (probeValue < calc.minValue && Check(charm)) @@ -99,10 +99,10 @@ Unit* PartyMemberToHeal::Calculate() bool PartyMemberToHeal::Check(Unit* player) { // return player && player != bot && player->GetMapId() == bot->GetMapId() && player->IsInWorld() && - // sServerFacade->GetDistance2d(bot, player) < (player->IsPlayer() && botAI->IsTank((Player*)player) ? 50.0f + // ServerFacade::instance().GetDistance2d(bot, player) < (player->IsPlayer() && botAI->IsTank((Player*)player) ? 50.0f // : 40.0f); return player->GetMapId() == bot->GetMapId() && !player->IsCharmed() && - bot->GetDistance2d(player) < sPlayerbotAIConfig->healDistance * 2 && bot->IsWithinLOSInMap(player); + bot->GetDistance2d(player) < sPlayerbotAIConfig.healDistance * 2 && bot->IsWithinLOSInMap(player); } Unit* PartyMemberToProtect::Calculate() @@ -129,7 +129,7 @@ Unit* PartyMemberToProtect::Calculate() continue; float attackDistance = 30.0f; - if (sServerFacade->GetDistance2d(pVictim, unit) > attackDistance) + if (ServerFacade::instance().GetDistance2d(pVictim, unit) > attackDistance) continue; if (botAI->IsTank((Player*)pVictim) && pVictim->GetHealthPct() > 10) diff --git a/src/Ai/Base/Value/PartyMemberValue.cpp b/src/Ai/Base/Value/PartyMemberValue.cpp index 4ae9be08ad..37602c02d1 100644 --- a/src/Ai/Base/Value/PartyMemberValue.cpp +++ b/src/Ai/Base/Value/PartyMemberValue.cpp @@ -4,9 +4,13 @@ */ #include "PartyMemberValue.h" +#include "Corpse.h" -#include "Playerbots.h" +#include "Group.h" +#include "PlayerbotAI.h" #include "ServerFacade.h" +#include "Pet.h" +#include "Spell.h" Unit* PartyMemberValue::FindPartyMember(std::vector* party, FindPlayerPredicate& predicate) { @@ -23,7 +27,7 @@ Unit* PartyMemberValue::FindPartyMember(std::vector* party, FindPlayerP return nullptr; } -Unit* PartyMemberValue::FindPartyMember(FindPlayerPredicate& predicate, bool ignoreOutOfGroup) +Unit* PartyMemberValue::FindPartyMember(FindPlayerPredicate& predicate, bool) { Player* master = GetMaster(); // GuidVector nearestPlayers; @@ -102,10 +106,10 @@ Unit* PartyMemberValue::FindPartyMember(FindPlayerPredicate& predicate, bool ign bool PartyMemberValue::Check(Unit* player) { // return player && player != bot && player->GetMapId() == bot->GetMapId() && bot->IsWithinDistInMap(player, - // sPlayerbotAIConfig->sightDistance, false); + // sPlayerbotAIConfig.sightDistance, false); bool isGM = player->ToPlayer() && player->ToPlayer()->IsGameMaster(); return player && player->GetMapId() == bot->GetMapId() && !isGM && - bot->GetDistance(player) < sPlayerbotAIConfig->spellDistance * 2 && + bot->GetDistance(player) < sPlayerbotAIConfig.spellDistance * 2 && bot->IsWithinLOS(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ()); } diff --git a/src/Ai/Base/Value/PartyMemberWithoutAuraValue.cpp b/src/Ai/Base/Value/PartyMemberWithoutAuraValue.cpp index f195a899bd..e9b181d791 100644 --- a/src/Ai/Base/Value/PartyMemberWithoutAuraValue.cpp +++ b/src/Ai/Base/Value/PartyMemberWithoutAuraValue.cpp @@ -13,7 +13,7 @@ class PlayerWithoutAuraPredicate : public FindPlayerPredicate, public PlayerbotA { public: PlayerWithoutAuraPredicate(PlayerbotAI* botAI, std::string const aura) - : PlayerbotAIAware(botAI), FindPlayerPredicate(), auras(split(aura, ',')) + : FindPlayerPredicate(), PlayerbotAIAware(botAI), auras(split(aura, ',')) { } diff --git a/src/Ai/Base/Value/PartyMemberWithoutAuraValue.h b/src/Ai/Base/Value/PartyMemberWithoutAuraValue.h index 57bb958c76..6d95a31313 100644 --- a/src/Ai/Base/Value/PartyMemberWithoutAuraValue.h +++ b/src/Ai/Base/Value/PartyMemberWithoutAuraValue.h @@ -8,7 +8,6 @@ #include "NamedObjectContext.h" #include "PartyMemberValue.h" -#include "PlayerbotAIConfig.h" class PlayerbotAI; class Unit; @@ -16,8 +15,7 @@ class Unit; class PartyMemberWithoutAuraValue : public PartyMemberValue, public Qualified { public: - PartyMemberWithoutAuraValue(PlayerbotAI* botAI, std::string const name = "party member without aura", - float range = sPlayerbotAIConfig->sightDistance) + PartyMemberWithoutAuraValue(PlayerbotAI* botAI, std::string const name = "party member without aura") : PartyMemberValue(botAI, name) { } diff --git a/src/Ai/Base/Value/PartyMemberWithoutItemValue.cpp b/src/Ai/Base/Value/PartyMemberWithoutItemValue.cpp index c9136c61a5..fe8032a459 100644 --- a/src/Ai/Base/Value/PartyMemberWithoutItemValue.cpp +++ b/src/Ai/Base/Value/PartyMemberWithoutItemValue.cpp @@ -11,7 +11,7 @@ class PlayerWithoutItemPredicate : public FindPlayerPredicate, public PlayerbotA { public: PlayerWithoutItemPredicate(PlayerbotAI* botAI, std::string const item) - : PlayerbotAIAware(botAI), FindPlayerPredicate(), item(item) + : FindPlayerPredicate(), PlayerbotAIAware(botAI), item(item) { } diff --git a/src/Ai/Base/Value/PartyMemberWithoutItemValue.h b/src/Ai/Base/Value/PartyMemberWithoutItemValue.h index 9ca128ff8d..379835543e 100644 --- a/src/Ai/Base/Value/PartyMemberWithoutItemValue.h +++ b/src/Ai/Base/Value/PartyMemberWithoutItemValue.h @@ -8,7 +8,6 @@ #include "NamedObjectContext.h" #include "PartyMemberValue.h" -#include "PlayerbotAIConfig.h" class PlayerbotAI; class Unit; @@ -16,8 +15,7 @@ class Unit; class PartyMemberWithoutItemValue : public PartyMemberValue, public Qualified { public: - PartyMemberWithoutItemValue(PlayerbotAI* botAI, std::string const name = "party member without item", - float range = sPlayerbotAIConfig->farDistance) + PartyMemberWithoutItemValue(PlayerbotAI* botAI, std::string const name = "party member without item") : PartyMemberValue(botAI, name) { } diff --git a/src/Ai/Base/Value/PositionValue.h b/src/Ai/Base/Value/PositionValue.h index 69e8e35943..9e613e1398 100644 --- a/src/Ai/Base/Value/PositionValue.h +++ b/src/Ai/Base/Value/PositionValue.h @@ -20,10 +20,12 @@ class PositionInfo : x(x), y(y), z(z), mapId(mapId), valueSet(valueSet) { } - PositionInfo(PositionInfo const& other) - : x(other.x), y(other.y), z(other.z), mapId(other.mapId), valueSet(other.valueSet) - { - } + + PositionInfo(PositionInfo const& other) = default; + PositionInfo& operator=(PositionInfo const& other) = default; + + PositionInfo(PositionInfo&& other) = default; + PositionInfo& operator=(PositionInfo&& other) = default; void Set(float newX, float newY, float newZ, uint32 newMapId) { @@ -71,7 +73,7 @@ class CurrentPositionValue : public LogCalculatedValue bool EqualToLast(WorldPosition value) override { - return value.fDist(lastValue) < sPlayerbotAIConfig->tooCloseDistance; + return value.fDist(lastValue) < sPlayerbotAIConfig.tooCloseDistance; } WorldPosition Calculate() override; diff --git a/src/Ai/Base/Value/PossibleRpgTargetsValue.cpp b/src/Ai/Base/Value/PossibleRpgTargetsValue.cpp index e9b79debf8..e0695e825d 100644 --- a/src/Ai/Base/Value/PossibleRpgTargetsValue.cpp +++ b/src/Ai/Base/Value/PossibleRpgTargetsValue.cpp @@ -5,14 +5,16 @@ #include "PossibleRpgTargetsValue.h" -#include "CellImpl.h" -#include "GridNotifiers.h" -#include "GridNotifiersImpl.h" +#include "AiObjectContext.h" #include "ObjectGuid.h" -#include "Playerbots.h" #include "ServerFacade.h" #include "SharedDefines.h" #include "NearestGameObjects.h" +#include "GridNotifiers.h" +// Required due to a poor implementation by AC +#include "GridNotifiersImpl.h" +#include "CellImpl.h" +#include "TravelMgr.h" std::vector PossibleRpgTargetsValue::allowedNpcFlags; @@ -60,7 +62,7 @@ bool PossibleRpgTargetsValue::AcceptUnit(Unit* unit) if (unit->IsHostileTo(bot) || unit->IsPlayer()) return false; - if (sServerFacade->GetDistance2d(bot, unit) <= sPlayerbotAIConfig->tooCloseDistance) + if (ServerFacade::instance().GetDistance2d(bot, unit) <= sPlayerbotAIConfig.tooCloseDistance) return false; if (unit->HasNpcFlag(UNIT_NPC_FLAG_SPIRITHEALER)) @@ -73,9 +75,16 @@ bool PossibleRpgTargetsValue::AcceptUnit(Unit* unit) } TravelTarget* travelTarget = context->GetValue("travel target")->Get(); - if (travelTarget && travelTarget->getDestination() && - travelTarget->getDestination()->getEntry() == unit->GetEntry()) + + + if ( + travelTarget != nullptr + && travelTarget->getDestination() + && (uint32_t)travelTarget->getDestination()->getEntry() == unit->GetEntry() + ) + { return true; + } if (urand(1, 100) < 25 && unit->IsFriendlyTo(bot)) return true; diff --git a/src/Ai/Base/Value/PossibleTargetsValue.h b/src/Ai/Base/Value/PossibleTargetsValue.h index 13023b3bcb..c710c2676b 100644 --- a/src/Ai/Base/Value/PossibleTargetsValue.h +++ b/src/Ai/Base/Value/PossibleTargetsValue.h @@ -15,7 +15,7 @@ class PossibleTargetsValue : public NearestUnitsValue { public: PossibleTargetsValue(PlayerbotAI* botAI, std::string const name = "possible targets", - float range = sPlayerbotAIConfig->sightDistance, bool ignoreLos = false) + float range = sPlayerbotAIConfig.sightDistance, bool ignoreLos = false) : NearestUnitsValue(botAI, name, range, ignoreLos) { } @@ -28,7 +28,7 @@ class PossibleTargetsValue : public NearestUnitsValue class AllTargetsValue : public PossibleTargetsValue { public: - AllTargetsValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig->sightDistance) + AllTargetsValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig.sightDistance) : PossibleTargetsValue(botAI, "all targets", range, true) { } diff --git a/src/Ai/Base/Value/PvpValues.cpp b/src/Ai/Base/Value/PvpValues.cpp index e01b56ef2c..c89b4b9f37 100644 --- a/src/Ai/Base/Value/PvpValues.cpp +++ b/src/Ai/Base/Value/PvpValues.cpp @@ -5,77 +5,57 @@ #include "PvpValues.h" -#include "BattlegroundEY.h" #include "BattlegroundMgr.h" -#include "BattlegroundWS.h" +#include "AreaDefines.h" #include "Playerbots.h" #include "ServerFacade.h" -Unit* FlagCarrierValue::Calculate() +Player* FlagCarrierValue::GetBattlegroundFlagCarrier(Battleground& battleground) const { - Unit* carrier = nullptr; + const uint32_t mapId = battleground.GetMapId(); - if (botAI->GetBot()->InBattleground()) + if (mapId != MAP_WARSONG_GULCH && mapId != MAP_EYE_OF_THE_STORM) { - if (botAI->GetBot()->GetBattlegroundTypeId() == BattlegroundTypeId::BATTLEGROUND_WS) - { - BattlegroundWS* bg = (BattlegroundWS*)botAI->GetBot()->GetBattleground(); + return nullptr; + } - if (!bg) - return nullptr; - - if ((!sameTeam && bot->GetTeamId() == TEAM_HORDE || (sameTeam && bot->GetTeamId() == TEAM_ALLIANCE)) && - !bg->GetFlagPickerGUID(TEAM_HORDE).IsEmpty()) - carrier = ObjectAccessor::GetPlayer(bg->GetBgMap(), bg->GetFlagPickerGUID(TEAM_HORDE)); - - if ((!sameTeam && bot->GetTeamId() == TEAM_ALLIANCE || (sameTeam && bot->GetTeamId() == TEAM_HORDE)) && - !bg->GetFlagPickerGUID(TEAM_ALLIANCE).IsEmpty()) - carrier = ObjectAccessor::GetPlayer(bg->GetBgMap(), bg->GetFlagPickerGUID(TEAM_ALLIANCE)); - - if (carrier) - { - if (ignoreRange || bot->IsWithinDistInMap(carrier, sPlayerbotAIConfig->sightDistance)) - { - return carrier; - } - else - return nullptr; - } - } + const TeamId botTeamId = this->bot->GetTeamId(); + const TeamId opposedTeamId = botTeamId == TEAM_ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE; - if (botAI->GetBot()->GetBattlegroundTypeId() == BATTLEGROUND_EY) - { - BattlegroundEY* bg = (BattlegroundEY*)botAI->GetBot()->GetBattleground(); + TeamId flagCarrierTeamIdLookup = TEAM_NEUTRAL; - if (!bg) - return nullptr; - - if (bg->GetFlagPickerGUID().IsEmpty()) - return nullptr; - - Player* fc = ObjectAccessor::GetPlayer(bg->GetBgMap(), bg->GetFlagPickerGUID()); - if (!fc) - return nullptr; - - if (!sameTeam && (fc->GetTeamId() != bot->GetTeamId())) - carrier = fc; - - if (sameTeam && (fc->GetTeamId() == bot->GetTeamId())) - carrier = fc; - - if (carrier) - { - if (ignoreRange || bot->IsWithinDistInMap(carrier, sPlayerbotAIConfig->sightDistance)) - { - return carrier; - } - else - return nullptr; - } - } + if (mapId == MAP_WARSONG_GULCH) + { + flagCarrierTeamIdLookup = this->sameTeam ? botTeamId : opposedTeamId; + } + + const ObjectGuid& flagCarrierGUID = battleground.GetFlagPickerGUID(flagCarrierTeamIdLookup); + + if (flagCarrierGUID.IsEmpty()) + { + return nullptr; + } + + Player* const flagCarrier = ObjectAccessor::GetPlayer(battleground.GetBgMap(), flagCarrierGUID); + + if (flagCarrier == nullptr) + { + return nullptr; + } + + return flagCarrier; +} + +Unit* FlagCarrierValue::Calculate() +{ + Battleground* const battleground = this->bot->GetBattleground(); + + if (battleground == nullptr) + { + return nullptr; } - return carrier; + return this->GetBattlegroundFlagCarrier(*battleground); } std::vector BgMastersValue::Calculate() @@ -84,7 +64,7 @@ std::vector BgMastersValue::Calculate() std::vector entries; std::map>> battleMastersCache = - sRandomPlayerbotMgr->getBattleMastersCache(); + sRandomPlayerbotMgr.getBattleMastersCache(); entries.insert(entries.end(), battleMastersCache[TEAM_NEUTRAL][bgTypeId].begin(), battleMastersCache[TEAM_NEUTRAL][bgTypeId].end()); entries.insert(entries.end(), battleMastersCache[TEAM_ALLIANCE][bgTypeId].begin(), @@ -199,7 +179,7 @@ BattlegroundTypeId RpgBgTypeValue::Calculate() continue; std::map>> battleMastersCache = - sRandomPlayerbotMgr->getBattleMastersCache(); + sRandomPlayerbotMgr.getBattleMastersCache(); for (auto& entry : battleMastersCache[TEAM_NEUTRAL][bgTypeId]) if (entry == guidPosition.GetEntry()) diff --git a/src/Ai/Base/Value/PvpValues.h b/src/Ai/Base/Value/PvpValues.h index bad46b951b..734567c411 100644 --- a/src/Ai/Base/Value/PvpValues.h +++ b/src/Ai/Base/Value/PvpValues.h @@ -59,13 +59,20 @@ class RpgBgTypeValue : public CalculatedValue class FlagCarrierValue : public UnitCalculatedValue { public: - FlagCarrierValue(PlayerbotAI* botAI, bool sameTeam = false, bool ignoreRange = false) + FlagCarrierValue( + PlayerbotAI* botAI, + bool sameTeam = false, + bool ignoreRange = false + ) : UnitCalculatedValue(botAI), sameTeam(sameTeam), ignoreRange(ignoreRange) { } Unit* Calculate() override; +protected: + Player* GetBattlegroundFlagCarrier(Battleground& battleground) const; + private: bool sameTeam; bool ignoreRange; diff --git a/src/Ai/Base/Value/RtiTargetValue.cpp b/src/Ai/Base/Value/RtiTargetValue.cpp index 205bcc3db0..4240e91c76 100644 --- a/src/Ai/Base/Value/RtiTargetValue.cpp +++ b/src/Ai/Base/Value/RtiTargetValue.cpp @@ -60,8 +60,8 @@ Unit* RtiTargetValue::Calculate() Unit* unit = botAI->GetUnit(guid); if (!unit || unit->isDead() || !bot->IsWithinLOSInMap(unit) || !AttackersValue::IsValidTarget(unit, bot) || - sServerFacade->IsDistanceGreaterThan(sServerFacade->GetDistance2d(bot, unit), - sPlayerbotAIConfig->sightDistance)) + ServerFacade::instance().IsDistanceGreaterThan(ServerFacade::instance().GetDistance2d(bot, unit), + sPlayerbotAIConfig.sightDistance)) return nullptr; // Also prevent chasing raid icon targets that are too far away from the master, @@ -69,8 +69,8 @@ Unit* RtiTargetValue::Calculate() if (Player* master = botAI->GetMaster()) { if (master->IsInWorld() && master->GetMapId() == unit->GetMapId() && - sServerFacade->IsDistanceGreaterThan(sServerFacade->GetDistance2d(master, unit), - sPlayerbotAIConfig->sightDistance)) + ServerFacade::instance().IsDistanceGreaterThan(ServerFacade::instance().GetDistance2d(master, unit), + sPlayerbotAIConfig.sightDistance)) return nullptr; } diff --git a/src/Ai/Base/Value/SnareTargetValue.cpp b/src/Ai/Base/Value/SnareTargetValue.cpp index 96e958c2d8..76be6c35de 100644 --- a/src/Ai/Base/Value/SnareTargetValue.cpp +++ b/src/Ai/Base/Value/SnareTargetValue.cpp @@ -5,15 +5,15 @@ #include "SnareTargetValue.h" -#include "Playerbots.h" +#include "AiObjectContext.h" +#include "PlayerbotAI.h" #include "ServerFacade.h" Unit* SnareTargetValue::Calculate() { std::string const spell = qualifier; - GuidVector attackers = botAI->GetAiObjectContext()->GetValue("attackers")->Get(); - Unit* target = botAI->GetAiObjectContext()->GetValue("current target")->Get(); + GuidVector attackers = this->botAI->GetAiObjectContext()->GetValue("attackers")->Get(); for (ObjectGuid const guid : attackers) { Unit* unit = botAI->GetUnit(guid); @@ -30,7 +30,7 @@ Unit* SnareTargetValue::Calculate() return unit; case CHASE_MOTION_TYPE: { - chaseTarget = sServerFacade->GetChaseTarget(unit); + chaseTarget = ServerFacade::instance().GetChaseTarget(unit); if (!chaseTarget) continue; Player* chaseTargetPlayer = ObjectAccessor::FindPlayer(chaseTarget->GetGUID()); diff --git a/src/Ai/Base/Value/SpellIdValue.cpp b/src/Ai/Base/Value/SpellIdValue.cpp index 682c0b3ffd..909a3a3075 100644 --- a/src/Ai/Base/Value/SpellIdValue.cpp +++ b/src/Ai/Base/Value/SpellIdValue.cpp @@ -8,7 +8,6 @@ #include "ChatHelper.h" #include "Playerbots.h" #include "Vehicle.h" -#include "World.h" SpellIdValue::SpellIdValue(PlayerbotAI* botAI) : CalculatedValue(botAI, "spell id", 20 * 1000) {} @@ -31,7 +30,7 @@ uint32 SpellIdValue::Calculate() wstrToLower(wnamepart); char firstSymbol = tolower(namepart[0]); - int spellLength = wnamepart.length(); + size_t spellLength = wnamepart.length(); LocaleConstant loc = LOCALE_enUS; @@ -98,7 +97,7 @@ uint32 SpellIdValue::Calculate() return 0; int32 saveMana = (int32)round(AI_VALUE(double, "mana save level")); - uint32 rank = 1; + int32 rank = 1; uint32 highestRank = 0; uint32 highestSpellId = 0; uint32 lowestRank = 0; @@ -128,21 +127,23 @@ uint32 SpellIdValue::Calculate() // convert the remaining text to an integer int id = atoi(spellName.c_str()); - if (!id) + if (id < 1) { highestSpellId = spellId; continue; } - if (!highestRank || id > highestRank) + const uint32_t unsignedId = id; + + if (!highestRank || unsignedId > highestRank) { - highestRank = id; + highestRank = unsignedId; highestSpellId = spellId; } - if (!lowestRank || (lowestRank && id < lowestRank)) + if (!lowestRank || (lowestRank && unsignedId < lowestRank)) { - lowestRank = id; + lowestRank = unsignedId; lowestSpellId = spellId; } } @@ -193,7 +194,7 @@ uint32 VehicleSpellIdValue::Calculate() wstrToLower(wnamepart); char firstSymbol = tolower(namepart[0]); - int spellLength = wnamepart.length(); + size_t spellLength = wnamepart.length(); const int loc = LocaleConstant::LOCALE_enUS; diff --git a/src/Ai/Base/Value/Stances.cpp b/src/Ai/Base/Value/Stances.cpp index 2e7a18d2b9..81d9b285c5 100644 --- a/src/Ai/Base/Value/Stances.cpp +++ b/src/Ai/Base/Value/Stances.cpp @@ -48,7 +48,7 @@ WorldLocation Stance::GetNearLocation(float angle, float distance) WorldLocation MoveStance::GetLocationInternal() { Unit* target = GetTarget(); - float distance = std::max(sPlayerbotAIConfig->meleeDistance, target->GetCombatReach()); + float distance = std::max(sPlayerbotAIConfig.meleeDistance, target->GetCombatReach()); float angle = GetAngle(); return GetNearLocation(angle, distance); @@ -56,7 +56,7 @@ WorldLocation MoveStance::GetLocationInternal() std::string const Stance::GetTargetName() { return "current target"; } -float Stance::GetMaxDistance() { return sPlayerbotAIConfig->contactDistance; } +float Stance::GetMaxDistance() { return sPlayerbotAIConfig.contactDistance; } StanceValue::~StanceValue() { diff --git a/src/Ai/Base/Value/StatsValues.cpp b/src/Ai/Base/Value/StatsValues.cpp index dc3499c683..941750d3b4 100644 --- a/src/Ai/Base/Value/StatsValues.cpp +++ b/src/Ai/Base/Value/StatsValues.cpp @@ -4,8 +4,12 @@ */ #include "StatsValues.h" -#include "Playerbots.h" +#include "AiObjectContext.h" +#include "Group.h" +#include "Pet.h" +#include "PlayerbotAIConfig.h" #include "ServerFacade.h" +#include "Player.h" Unit* HealthValue::GetTarget() { @@ -183,8 +187,8 @@ bool IsInCombatValue::Calculate() continue; if (member->IsInCombat() && - sServerFacade->IsDistanceLessOrEqualThan(sServerFacade->GetDistance2d(member, bot), - sPlayerbotAIConfig->reactDistance)) + ServerFacade::instance().IsDistanceLessOrEqualThan(ServerFacade::instance().GetDistance2d(member, bot), + PlayerbotAIConfig::instance().reactDistance)) return true; } } @@ -204,7 +208,6 @@ uint8 BagSpaceValue::Calculate() ++totalused; } - uint32 totalfree = 16 - totalused; for (uint8 bag = INVENTORY_SLOT_BAG_START; bag < INVENTORY_SLOT_BAG_END; ++bag) { const Bag* const pBag = (Bag*)bot->GetItemByPos(INVENTORY_SLOT_BAG_0, bag); @@ -214,7 +217,6 @@ uint8 BagSpaceValue::Calculate() if (pBagProto->Class == ITEM_CLASS_CONTAINER && pBagProto->SubClass == ITEM_SUBCLASS_CONTAINER) { total += pBag->GetBagSize(); - totalfree += pBag->GetFreeSlots(); totalused += pBag->GetBagSize() - pBag->GetFreeSlots(); } } diff --git a/src/Ai/Base/Value/TankTargetValue.cpp b/src/Ai/Base/Value/TankTargetValue.cpp index ef2d1e959c..0bda67eae5 100644 --- a/src/Ai/Base/Value/TankTargetValue.cpp +++ b/src/Ai/Base/Value/TankTargetValue.cpp @@ -5,9 +5,10 @@ #include "TankTargetValue.h" +#include "AiObjectContext.h" #include "AttackersValue.h" -#include "PlayerbotAIConfig.h" -#include "Playerbots.h" +#include "Group.h" +#include "PlayerbotAI.h" class FindTargetForTankStrategy : public FindNonCcTargetStrategy { @@ -53,7 +54,7 @@ class FindTankTargetSmartStrategy : public FindTargetStrategy public: FindTankTargetSmartStrategy(PlayerbotAI* botAI) : FindTargetStrategy(botAI) {} - void CheckAttacker(Unit* attacker, ThreatMgr* threatMgr) override + void CheckAttacker(Unit* attacker, ThreatMgr*) override { if (Group* group = botAI->GetBot()->GetGroup()) { diff --git a/src/Ai/Base/Value/TargetValue.cpp b/src/Ai/Base/Value/TargetValue.cpp index 598b78441b..26e153ceba 100644 --- a/src/Ai/Base/Value/TargetValue.cpp +++ b/src/Ai/Base/Value/TargetValue.cpp @@ -161,7 +161,7 @@ Unit* FindTargetValue::Calculate() return nullptr; } -void FindBossTargetStrategy::CheckAttacker(Unit* attacker, ThreatMgr* threatManager) +void FindBossTargetStrategy::CheckAttacker(Unit* attacker, ThreatMgr*) { UnitAI* unitAI = attacker->GetAI(); BossAI* bossAI = dynamic_cast(unitAI); diff --git a/src/Ai/Base/ValueContext.h b/src/Ai/Base/ValueContext.h index 7349e9d614..82ef819ce2 100644 --- a/src/Ai/Base/ValueContext.h +++ b/src/Ai/Base/ValueContext.h @@ -51,6 +51,7 @@ #include "LineTargetValue.h" #include "LogLevelValue.h" #include "LootStrategyValue.h" +#include "LootValues.h" #include "MaintenanceValues.h" #include "ManaSaveLevelValue.h" #include "NearestAdsValue.h" @@ -396,7 +397,7 @@ class ValueContext : public NamedObjectContext static UntypedValue* nearest_game_objects(PlayerbotAI* botAI) { return new NearestGameObjects(botAI); } static UntypedValue* nearest_game_objects_no_los(PlayerbotAI* botAI) { - return new NearestGameObjects(botAI, sPlayerbotAIConfig->sightDistance, true); + return new NearestGameObjects(botAI, sPlayerbotAIConfig.sightDistance, true); } static UntypedValue* closest_game_objects(PlayerbotAI* botAI) { @@ -422,7 +423,7 @@ class ValueContext : public NamedObjectContext static UntypedValue* possible_triggers(PlayerbotAI* botAI) { return new PossibleTriggersValue(botAI); } static UntypedValue* possible_targets_no_los(PlayerbotAI* botAI) { - return new PossibleTargetsValue(botAI, "possible targets", sPlayerbotAIConfig->sightDistance, true); + return new PossibleTargetsValue(botAI, "possible targets", sPlayerbotAIConfig.sightDistance, true); } static UntypedValue* possible_adds(PlayerbotAI* botAI) { return new PossibleAddsValue(botAI); } static UntypedValue* prioritized_targets(PlayerbotAI* botAI) { return new PrioritizedTargetsValue(botAI); } diff --git a/src/Ai/Base/WorldPacketActionContext.h b/src/Ai/Base/WorldPacketActionContext.h deleted file mode 100644 index 59c0550368..0000000000 --- a/src/Ai/Base/WorldPacketActionContext.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it - * and/or modify it under version 3 of the License, or (at your option), any later version. - */ - -#ifndef _PLAYERBOT_WORLDPACKETACTIONCONTEXT_H -#define _PLAYERBOT_WORLDPACKETACTIONCONTEXT_H - -#include "AcceptBattlegroundInvitationAction.h" -#include "AcceptDuelAction.h" -#include "AcceptInvitationAction.h" -#include "AcceptQuestAction.h" -#include "AcceptResurrectAction.h" -#include "AreaTriggerAction.h" -#include "ArenaTeamActions.h" -#include "BattleGroundTactics.h" -#include "CheckMountStateAction.h" -#include "GuildAcceptAction.h" -#include "GuildCreateActions.h" -#include "InventoryChangeFailureAction.h" -#include "LeaveGroupAction.h" -#include "LfgActions.h" -#include "LootAction.h" -#include "LootRollAction.h" -#include "NamedObjectContext.h" -#include "PassLeadershipToMasterAction.h" -#include "PetitionSignAction.h" -#include "QuestAction.h" -#include "QuestConfirmAcceptAction.h" -#include "ReadyCheckAction.h" -#include "RememberTaxiAction.h" -#include "ReviveFromCorpseAction.h" -#include "RewardAction.h" -#include "SecurityCheckAction.h" -#include "SeeSpellAction.h" -#include "TalkToQuestGiverAction.h" -#include "TellCastFailedAction.h" -#include "TellMasterAction.h" -#include "TradeStatusAction.h" -#include "TradeStatusExtendedAction.h" -#include "UseMeetingStoneAction.h" -#include "NamedObjectContext.h" -#include "ReleaseSpiritAction.h" -#include "PetsAction.h" - -class PlayerbotAI; - -class WorldPacketActionContext : public NamedObjectContext -{ -public: - WorldPacketActionContext() - { - creators["accept invitation"] = &WorldPacketActionContext::accept_invitation; - creators["give leader in dungeon"] = &WorldPacketActionContext::give_leader_in_dungeon; - creators["leader"] = &WorldPacketActionContext::pass_leadership_to_master; - creators["tell not enough money"] = &WorldPacketActionContext::tell_not_enough_money; - creators["tell not enough reputation"] = &WorldPacketActionContext::tell_not_enough_reputation; - creators["tell cannot equip"] = &WorldPacketActionContext::tell_cannot_equip; - creators["loot roll"] = &WorldPacketActionContext::loot_roll; - creators["master loot roll"] = &WorldPacketActionContext::master_loot_roll; - creators["revive from corpse"] = &WorldPacketActionContext::revive_from_corpse; - creators["find corpse"] = &WorldPacketActionContext::find_corpse; - creators["auto release"] = &WorldPacketActionContext::auto_release; - creators["accept resurrect"] = &WorldPacketActionContext::accept_resurrect; - creators["use meeting stone"] = &WorldPacketActionContext::use_meeting_stone; - creators["area trigger"] = &WorldPacketActionContext::area_trigger; - creators["reach area trigger"] = &WorldPacketActionContext::reach_area_trigger; - creators["check mount state"] = &WorldPacketActionContext::check_mount_state; - creators["remember taxi"] = &WorldPacketActionContext::remember_taxi; - creators["accept trade"] = &WorldPacketActionContext::accept_trade; - creators["trade status extended"] = &WorldPacketActionContext::trade_status_extended; - creators["store loot"] = &WorldPacketActionContext::store_loot; - creators["self resurrect"] = &WorldPacketActionContext::self_resurrect; - creators["pet"] = &WorldPacketActionContext::pet; - - // quest - creators["talk to quest giver"] = &WorldPacketActionContext::turn_in_quest; - creators["accept quest"] = &WorldPacketActionContext::accept_quest; - creators["confirm quest"] = &WorldPacketActionContext::confirm_quest; - creators["accept all quests"] = &WorldPacketActionContext::accept_all_quests; - creators["accept quest share"] = &WorldPacketActionContext::accept_quest_share; - creators["quest update add kill"] = &WorldPacketActionContext::quest_update_add_kill; - creators["quest update add item"] = &WorldPacketActionContext::quest_update_add_item; - creators["quest update failed"] = &WorldPacketActionContext::quest_update_failed; - creators["quest update failed timer"] = &WorldPacketActionContext::quest_update_failed_timer; - creators["quest update complete"] = &WorldPacketActionContext::quest_update_complete; - creators["turn in query quest"] = &WorldPacketActionContext::turn_in_query_quest; - creators["quest item push result"] = &WorldPacketActionContext::quest_item_push_result; - - creators["party command"] = &WorldPacketActionContext::party_command; - creators["tell cast failed"] = &WorldPacketActionContext::tell_cast_failed; - creators["accept duel"] = &WorldPacketActionContext::accept_duel; - creators["ready check"] = &WorldPacketActionContext::ready_check; - creators["ready check finished"] = &WorldPacketActionContext::ready_check_finished; - creators["uninvite"] = &WorldPacketActionContext::uninvite; - creators["security check"] = &WorldPacketActionContext::security_check; - creators["guild accept"] = &WorldPacketActionContext::guild_accept; - creators["inventory change failure"] = &WorldPacketActionContext::inventory_change_failure; - creators["bg status check"] = &WorldPacketActionContext::bg_status_check; - creators["bg strategy check"] = &WorldPacketActionContext::bg_strategy_check; - creators["bg status"] = &WorldPacketActionContext::bg_status; - creators["bg join"] = &WorldPacketActionContext::bg_join; - creators["bg leave"] = &WorldPacketActionContext::bg_leave; - creators["arena tactics"] = &WorldPacketActionContext::arena_tactics; - creators["petition sign"] = &WorldPacketActionContext::petition_sign; - creators["lfg join"] = &WorldPacketActionContext::lfg_join; - creators["lfg accept"] = &WorldPacketActionContext::lfg_accept; - creators["lfg role check"] = &WorldPacketActionContext::lfg_role_check; - creators["lfg leave"] = &WorldPacketActionContext::lfg_leave; - creators["lfg teleport"] = &WorldPacketActionContext::lfg_teleport; - creators["see spell"] = &WorldPacketActionContext::see_spell; - creators["arena team accept"] = &WorldPacketActionContext::arena_team_accept; - } - -private: - static Action* inventory_change_failure(PlayerbotAI* botAI) { return new InventoryChangeFailureAction(botAI); } - static Action* guild_accept(PlayerbotAI* botAI) { return new GuildAcceptAction(botAI); } - static Action* security_check(PlayerbotAI* botAI) { return new SecurityCheckAction(botAI); } - static Action* uninvite(PlayerbotAI* botAI) { return new UninviteAction(botAI); } - static Action* ready_check_finished(PlayerbotAI* botAI) { return new FinishReadyCheckAction(botAI); } - static Action* ready_check(PlayerbotAI* botAI) { return new ReadyCheckAction(botAI); } - static Action* accept_duel(PlayerbotAI* botAI) { return new AcceptDuelAction(botAI); } - static Action* tell_cast_failed(PlayerbotAI* botAI) { return new TellCastFailedAction(botAI); } - static Action* party_command(PlayerbotAI* botAI) { return new PartyCommandAction(botAI); } - static Action* store_loot(PlayerbotAI* botAI) { return new StoreLootAction(botAI); } - static Action* accept_trade(PlayerbotAI* botAI) { return new TradeStatusAction(botAI); } - static Action* trade_status_extended(PlayerbotAI* botAI) { return new TradeStatusExtendedAction(botAI); } - static Action* remember_taxi(PlayerbotAI* botAI) { return new RememberTaxiAction(botAI); } - static Action* check_mount_state(PlayerbotAI* botAI) { return new CheckMountStateAction(botAI); } - static Action* area_trigger(PlayerbotAI* botAI) { return new AreaTriggerAction(botAI); } - static Action* reach_area_trigger(PlayerbotAI* botAI) { return new ReachAreaTriggerAction(botAI); } - static Action* use_meeting_stone(PlayerbotAI* botAI) { return new UseMeetingStoneAction(botAI); } - static Action* accept_resurrect(PlayerbotAI* botAI) { return new AcceptResurrectAction(botAI); } - static Action* find_corpse(PlayerbotAI* botAI) { return new FindCorpseAction(botAI); } - static Action* auto_release(PlayerbotAI* botAI) { return new AutoReleaseSpiritAction(botAI); } - static Action* revive_from_corpse(PlayerbotAI* botAI) { return new ReviveFromCorpseAction(botAI); } - static Action* accept_invitation(PlayerbotAI* botAI) { return new AcceptInvitationAction(botAI); } - static Action* give_leader_in_dungeon(PlayerbotAI* botAI) { return new GiveLeaderAction(botAI, "I don't know this dungeon, lead the way!"); } - static Action* pass_leadership_to_master(PlayerbotAI* botAI) { return new PassLeadershipToMasterAction(botAI); } - static Action* tell_not_enough_money(PlayerbotAI* botAI) { return new TellMasterAction(botAI, "Not enough money"); } - static Action* tell_not_enough_reputation(PlayerbotAI* botAI) { return new TellMasterAction(botAI, "Not enough reputation"); } - static Action* tell_cannot_equip(PlayerbotAI* botAI) { return new InventoryChangeFailureAction(botAI); } - static Action* self_resurrect(PlayerbotAI* botAI) { return new SelfResurrectAction(botAI); } - static Action* pet(PlayerbotAI* botAI) { return new PetsAction(botAI); } - - // quest - static Action* quest_update_add_kill(PlayerbotAI* ai) { return new QuestUpdateAddKillAction(ai); } - static Action* quest_update_add_item(PlayerbotAI* ai) { return new QuestUpdateAddItemAction(ai); } - static Action* quest_update_failed(PlayerbotAI* ai) { return new QuestUpdateFailedAction(ai); } - static Action* quest_update_failed_timer(PlayerbotAI* ai) { return new QuestUpdateFailedTimerAction(ai); } - static Action* quest_update_complete(PlayerbotAI* botAI) { return new QuestUpdateCompleteAction(botAI); } - static Action* quest_item_push_result(PlayerbotAI* ai) { return new QuestItemPushResultAction(ai); } - - static Action* turn_in_quest(PlayerbotAI* botAI) { return new TalkToQuestGiverAction(botAI); } - static Action* accept_quest(PlayerbotAI* botAI) { return new AcceptQuestAction(botAI); } - static Action* confirm_quest(PlayerbotAI* ai) { return new ConfirmQuestAction(ai); } - static Action* accept_all_quests(PlayerbotAI* botAI) { return new AcceptAllQuestsAction(botAI); } - static Action* accept_quest_share(PlayerbotAI* botAI) { return new AcceptQuestShareAction(botAI); } - static Action* turn_in_query_quest(PlayerbotAI* botAI) { return new TurnInQueryQuestAction(botAI); } - //static Action* quest_confirm_accept(PlayerbotAI* botAI) { return new QuestConfirmAcceptAction(botAI); } - - static Action* loot_roll(PlayerbotAI* botAI) { return new LootRollAction(botAI); } - static Action* master_loot_roll(PlayerbotAI* botAI) { return new MasterLootRollAction(botAI); } - static Action* bg_join(PlayerbotAI* botAI) { return new BGJoinAction(botAI); } - static Action* bg_leave(PlayerbotAI* botAI) { return new BGLeaveAction(botAI); } - static Action* bg_status(PlayerbotAI* botAI) { return new BGStatusAction(botAI); } - static Action* bg_status_check(PlayerbotAI* botAI) { return new BGStatusCheckAction(botAI); } - static Action* bg_strategy_check(PlayerbotAI* botAI) { return new BGStrategyCheckAction(botAI); } - static Action* arena_tactics(PlayerbotAI* botAI) { return new ArenaTactics(botAI); } - static Action* petition_sign(PlayerbotAI* botAI) { return new PetitionSignAction(botAI); } - static Action* lfg_teleport(PlayerbotAI* botAI) { return new LfgTeleportAction(botAI); } - static Action* lfg_leave(PlayerbotAI* botAI) { return new LfgLeaveAction(botAI); } - static Action* lfg_accept(PlayerbotAI* botAI) { return new LfgAcceptAction(botAI); } - static Action* lfg_role_check(PlayerbotAI* botAI) { return new LfgRoleCheckAction(botAI); } - static Action* lfg_join(PlayerbotAI* botAI) { return new LfgJoinAction(botAI); } - static Action* see_spell(PlayerbotAI* botAI) { return new SeeSpellAction(botAI); } - static Action* arena_team_accept(PlayerbotAI* botAI) { return new ArenaTeamAcceptAction(botAI); } -}; - -#endif diff --git a/src/Ai/Base/WorldPacketTriggerContext.h b/src/Ai/Base/WorldPacketTriggerContext.h index 1e73095244..61422c833b 100644 --- a/src/Ai/Base/WorldPacketTriggerContext.h +++ b/src/Ai/Base/WorldPacketTriggerContext.h @@ -7,6 +7,7 @@ #define _PLAYERBOT_WORLDPACKETTRIGGERCONTEXT_H #include "NamedObjectContext.h" +#include "RangeTriggers.h" #include "WithinAreaTrigger.h" #include "WorldPacketTrigger.h" diff --git a/src/Ai/Class/Dk/Action/DKActions.cpp b/src/Ai/Class/Dk/Action/DKActions.cpp index 7788e48190..2dbe5e041d 100644 --- a/src/Ai/Class/Dk/Action/DKActions.cpp +++ b/src/Ai/Class/Dk/Action/DKActions.cpp @@ -5,34 +5,39 @@ #include "DKActions.h" -#include "Duration.h" +#include "CreateNextAction.h" #include "GenericSpellActions.h" #include "Playerbots.h" #include "SpellInfo.h" #include "SpellMgr.h" +#include "DKActions.h" std::vector CastDeathchillAction::getPrerequisites() { - return NextAction::merge({ NextAction("frost presence") }, - CastSpellAction::getPrerequisites()); + return { + CreateNextAction(1.0f) + }; } std::vector CastUnholyMeleeSpellAction::getPrerequisites() { - return NextAction::merge({ NextAction("unholy presence") }, - CastMeleeSpellAction::getPrerequisites()); + return { + CreateNextAction(1.0f) + }; } std::vector CastFrostMeleeSpellAction::getPrerequisites() { - return NextAction::merge({ NextAction("frost presence") }, - CastMeleeSpellAction::getPrerequisites()); + return { + CreateNextAction(1.0f) + }; } std::vector CastBloodMeleeSpellAction::getPrerequisites() { - return NextAction::merge({ NextAction("blood presence") }, - CastMeleeSpellAction::getPrerequisites()); + return { + CreateNextAction(1.0f) + }; } bool CastRaiseDeadAction::Execute(Event event) diff --git a/src/Ai/Class/Dk/DKAiObjectContext.cpp b/src/Ai/Class/Dk/DKAiObjectContext.cpp index ac80c7dc46..fefdccfd27 100644 --- a/src/Ai/Class/Dk/DKAiObjectContext.cpp +++ b/src/Ai/Class/Dk/DKAiObjectContext.cpp @@ -11,7 +11,6 @@ #include "FrostDKStrategy.h" #include "GenericDKNonCombatStrategy.h" #include "GenericTriggers.h" -#include "Playerbots.h" #include "PullStrategy.h" #include "UnholyDKStrategy.h" @@ -154,140 +153,19 @@ class DeathKnightTriggerFactoryInternal : public NamedObjectContext static Trigger* army_of_the_dead(PlayerbotAI* botAI) { return new ArmyOfTheDeadTrigger(botAI); } }; -class DeathKnightAiObjectContextInternal : public NamedObjectContext -{ -public: - DeathKnightAiObjectContextInternal() - { - // Unholy - creators["bone shield"] = &DeathKnightAiObjectContextInternal::bone_shield; - creators["plague strike"] = &DeathKnightAiObjectContextInternal::plague_strike; - creators["plague strike on attacker"] = &DeathKnightAiObjectContextInternal::plague_strike_on_attacker; - creators["death grip"] = &DeathKnightAiObjectContextInternal::death_grip; - creators["death coil"] = &DeathKnightAiObjectContextInternal::death_coil; - creators["death strike"] = &DeathKnightAiObjectContextInternal::death_strike; - creators["unholy blight"] = &DeathKnightAiObjectContextInternal::unholy_blight; - creators["scourge strike"] = &DeathKnightAiObjectContextInternal::scourge_strike; - creators["death and decay"] = &DeathKnightAiObjectContextInternal::death_and_decay; - creators["unholy presence"] = &DeathKnightAiObjectContextInternal::unholy_presence; - creators["raise dead"] = &DeathKnightAiObjectContextInternal::raise_dead; - creators["army of the dead"] = &DeathKnightAiObjectContextInternal::army_of_the_dead; - creators["summon gargoyle"] = &DeathKnightAiObjectContextInternal::summon_gargoyle; - creators["anti magic shell"] = &DeathKnightAiObjectContextInternal::anti_magic_shell; - creators["anti magic zone"] = &DeathKnightAiObjectContextInternal::anti_magic_zone; - creators["ghoul frenzy"] = &DeathKnightAiObjectContextInternal::ghoul_frenzy; - creators["corpse explosion"] = &DeathKnightAiObjectContextInternal::corpse_explosion; - // Frost - creators["icy touch"] = &DeathKnightAiObjectContextInternal::icy_touch; - creators["icy touch on attacker"] = &DeathKnightAiObjectContextInternal::icy_touch_on_attacker; - creators["obliterate"] = &DeathKnightAiObjectContextInternal::obliterate; - creators["howling blast"] = &DeathKnightAiObjectContextInternal::howling_blast; - creators["frost strike"] = &DeathKnightAiObjectContextInternal::frost_strike; - creators["chains of ice"] = &DeathKnightAiObjectContextInternal::chains_of_ice; - creators["rune strike"] = &DeathKnightAiObjectContextInternal::rune_strike; - // creators["icy clutch"] = &DeathKnightAiObjectContextInternal::icy_clutch; - creators["horn of winter"] = &DeathKnightAiObjectContextInternal::horn_of_winter; - creators["killing machine"] = &DeathKnightAiObjectContextInternal::killing_machine; - creators["frost presence"] = &DeathKnightAiObjectContextInternal::frost_presence; - creators["deathchill"] = &DeathKnightAiObjectContextInternal::deathchill; - creators["icebound fortitude"] = &DeathKnightAiObjectContextInternal::icebound_fortitude; - creators["mind freeze"] = &DeathKnightAiObjectContextInternal::mind_freeze; - creators["empower rune weapon"] = &DeathKnightAiObjectContextInternal::empower_rune_weapon; - creators["hungering cold"] = &DeathKnightAiObjectContextInternal::hungering_cold; - creators["unbreakable armor"] = &DeathKnightAiObjectContextInternal::unbreakable_armor; - creators["improved icy talons"] = &DeathKnightAiObjectContextInternal::improved_icy_talons; - // blood - creators["blood strike"] = &DeathKnightAiObjectContextInternal::blood_strike; - creators["blood tap"] = &DeathKnightAiObjectContextInternal::blood_tap; - creators["pestilence"] = &DeathKnightAiObjectContextInternal::pestilence; - creators["strangulate"] = &DeathKnightAiObjectContextInternal::strangulate; - creators["blood boil"] = &DeathKnightAiObjectContextInternal::blood_boil; - creators["heart strike"] = &DeathKnightAiObjectContextInternal::heart_strike; - creators["mark of_blood"] = &DeathKnightAiObjectContextInternal::mark_of_blood; - creators["blood presence"] = &DeathKnightAiObjectContextInternal::blood_presence; - creators["rune tap"] = &DeathKnightAiObjectContextInternal::rune_tap; - creators["vampiric blood"] = &DeathKnightAiObjectContextInternal::vampiric_blood; - creators["death pact"] = &DeathKnightAiObjectContextInternal::death_pact; - creators["death rune_mastery"] = &DeathKnightAiObjectContextInternal::death_rune_mastery; - // creators["hysteria"] = &DeathKnightAiObjectContextInternal::hysteria; - creators["dancing rune weapon"] = &DeathKnightAiObjectContextInternal::dancing_rune_weapon; - creators["dark command"] = &DeathKnightAiObjectContextInternal::dark_command; - } - -private: - // Unholy - static Action* bone_shield(PlayerbotAI* botAI) { return new CastBoneShieldAction(botAI); } - static Action* plague_strike(PlayerbotAI* botAI) { return new CastPlagueStrikeAction(botAI); } - static Action* plague_strike_on_attacker(PlayerbotAI* botAI) { return new CastPlagueStrikeOnAttackerAction(botAI); } - static Action* death_grip(PlayerbotAI* botAI) { return new CastDeathGripAction(botAI); } - static Action* death_coil(PlayerbotAI* botAI) { return new CastDeathCoilAction(botAI); } - static Action* death_strike(PlayerbotAI* botAI) { return new CastDeathStrikeAction(botAI); } - static Action* unholy_blight(PlayerbotAI* botAI) { return new CastUnholyBlightAction(botAI); } - static Action* scourge_strike(PlayerbotAI* botAI) { return new CastScourgeStrikeAction(botAI); } - static Action* death_and_decay(PlayerbotAI* botAI) { return new CastDeathAndDecayAction(botAI); } - static Action* unholy_presence(PlayerbotAI* botAI) { return new CastUnholyPresenceAction(botAI); } - static Action* raise_dead(PlayerbotAI* botAI) { return new CastRaiseDeadAction(botAI); } - static Action* army_of_the_dead(PlayerbotAI* botAI) { return new CastArmyOfTheDeadAction(botAI); } - static Action* summon_gargoyle(PlayerbotAI* botAI) { return new CastSummonGargoyleAction(botAI); } - static Action* anti_magic_shell(PlayerbotAI* botAI) { return new CastAntiMagicShellAction(botAI); } - static Action* anti_magic_zone(PlayerbotAI* botAI) { return new CastAntiMagicZoneAction(botAI); } - static Action* ghoul_frenzy(PlayerbotAI* botAI) { return new CastGhoulFrenzyAction(botAI); } - static Action* corpse_explosion(PlayerbotAI* botAI) { return new CastCorpseExplosionAction(botAI); } - // Frost - static Action* icy_touch(PlayerbotAI* botAI) { return new CastIcyTouchAction(botAI); } - static Action* icy_touch_on_attacker(PlayerbotAI* botAI) { return new CastIcyTouchOnAttackerAction(botAI); } - static Action* obliterate(PlayerbotAI* botAI) { return new CastObliterateAction(botAI); } - static Action* howling_blast(PlayerbotAI* botAI) { return new CastHowlingBlastAction(botAI); } - static Action* frost_strike(PlayerbotAI* botAI) { return new CastFrostStrikeAction(botAI); } - static Action* chains_of_ice(PlayerbotAI* botAI) { return new CastChainsOfIceAction(botAI); } - static Action* rune_strike(PlayerbotAI* botAI) { return new CastRuneStrikeAction(botAI); } - // static Action* icy_clutch(PlayerbotAI* botAI) { return new CastIcyClutchAction(botAI); } - static Action* horn_of_winter(PlayerbotAI* botAI) { return new CastHornOfWinterAction(botAI); } - static Action* killing_machine(PlayerbotAI* botAI) { return new CastKillingMachineAction(botAI); } - static Action* frost_presence(PlayerbotAI* botAI) { return new CastFrostPresenceAction(botAI); } - static Action* deathchill(PlayerbotAI* botAI) { return new CastDeathchillAction(botAI); } - static Action* icebound_fortitude(PlayerbotAI* botAI) { return new CastIceboundFortitudeAction(botAI); } - static Action* mind_freeze(PlayerbotAI* botAI) { return new CastMindFreezeAction(botAI); } - static Action* empower_rune_weapon(PlayerbotAI* botAI) { return new CastEmpowerRuneWeaponAction(botAI); } - static Action* hungering_cold(PlayerbotAI* botAI) { return new CastHungeringColdAction(botAI); } - static Action* unbreakable_armor(PlayerbotAI* botAI) { return new CastUnbreakableArmorAction(botAI); } - static Action* improved_icy_talons(PlayerbotAI* botAI) { return new CastImprovedIcyTalonsAction(botAI); } - // blood - static Action* blood_strike(PlayerbotAI* botAI) { return new CastBloodStrikeAction(botAI); } - static Action* blood_tap(PlayerbotAI* botAI) { return new CastBloodTapAction(botAI); } - static Action* pestilence(PlayerbotAI* botAI) { return new CastPestilenceAction(botAI); } - static Action* strangulate(PlayerbotAI* botAI) { return new CastStrangulateAction(botAI); } - static Action* blood_boil(PlayerbotAI* botAI) { return new CastBloodBoilAction(botAI); } - static Action* heart_strike(PlayerbotAI* botAI) { return new CastHeartStrikeAction(botAI); } - static Action* mark_of_blood(PlayerbotAI* botAI) { return new CastMarkOfBloodAction(botAI); } - static Action* blood_presence(PlayerbotAI* botAI) { return new CastBloodPresenceAction(botAI); } - static Action* rune_tap(PlayerbotAI* botAI) { return new CastRuneTapAction(botAI); } - static Action* vampiric_blood(PlayerbotAI* botAI) { return new CastVampiricBloodAction(botAI); } - static Action* death_pact(PlayerbotAI* botAI) { return new CastDeathPactAction(botAI); } - static Action* death_rune_mastery(PlayerbotAI* botAI) { return new CastDeathRuneMasteryAction(botAI); } - // static Action* hysteria(PlayerbotAI* botAI) { return new CastHysteriaAction(botAI); } - static Action* dancing_rune_weapon(PlayerbotAI* botAI) { return new CastDancingRuneWeaponAction(botAI); } - static Action* dark_command(PlayerbotAI* botAI) { return new CastDarkCommandAction(botAI); } - static Action* mind_freeze_on_enemy_healer(PlayerbotAI* botAI) - { - return new CastMindFreezeOnEnemyHealerAction(botAI); - } -}; - SharedNamedObjectContextList DKAiObjectContext::sharedStrategyContexts; -SharedNamedObjectContextList DKAiObjectContext::sharedActionContexts; SharedNamedObjectContextList DKAiObjectContext::sharedTriggerContexts; SharedNamedObjectContextList DKAiObjectContext::sharedValueContexts; DKAiObjectContext::DKAiObjectContext(PlayerbotAI* botAI) - : AiObjectContext(botAI, sharedStrategyContexts, sharedActionContexts, sharedTriggerContexts, sharedValueContexts) + : AiObjectContext(botAI, sharedStrategyContexts, sharedTriggerContexts, sharedValueContexts) { } void DKAiObjectContext::BuildSharedContexts() { BuildSharedStrategyContexts(sharedStrategyContexts); - BuildSharedActionContexts(sharedActionContexts); + // BuildSharedActionContexts(sharedActionContexts); BuildSharedTriggerContexts(sharedTriggerContexts); BuildSharedValueContexts(sharedValueContexts); } @@ -300,12 +178,6 @@ void DKAiObjectContext::BuildSharedStrategyContexts(SharedNamedObjectContextList strategyContexts.Add(new DeathKnightDKBuffStrategyFactoryInternal()); } -void DKAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts) -{ - AiObjectContext::BuildSharedActionContexts(actionContexts); - actionContexts.Add(new DeathKnightAiObjectContextInternal()); -} - void DKAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts) { AiObjectContext::BuildSharedTriggerContexts(triggerContexts); diff --git a/src/Ai/Class/Dk/DKAiObjectContext.h b/src/Ai/Class/Dk/DKAiObjectContext.h index 8921df718a..bfa8e7e457 100644 --- a/src/Ai/Class/Dk/DKAiObjectContext.h +++ b/src/Ai/Class/Dk/DKAiObjectContext.h @@ -17,12 +17,10 @@ class DKAiObjectContext : public AiObjectContext static void BuildSharedContexts(); static void BuildSharedStrategyContexts(SharedNamedObjectContextList& strategyContexts); - static void BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts); static void BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts); static void BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts); static SharedNamedObjectContextList sharedStrategyContexts; - static SharedNamedObjectContextList sharedActionContexts; static SharedNamedObjectContextList sharedTriggerContexts; static SharedNamedObjectContextList sharedValueContexts; }; diff --git a/src/Ai/Class/Dk/Strategy/BloodDKStrategy.cpp b/src/Ai/Class/Dk/Strategy/BloodDKStrategy.cpp index 344b3dc095..ba7071a266 100644 --- a/src/Ai/Class/Dk/Strategy/BloodDKStrategy.cpp +++ b/src/Ai/Class/Dk/Strategy/BloodDKStrategy.cpp @@ -5,7 +5,10 @@ #include "BloodDKStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "DKActions.h" +#include "ActionNode.h" +#include "GenericActions.h" class BloodDKStrategyActionNodeFactory : public NamedObjectFactory { @@ -24,9 +27,8 @@ class BloodDKStrategyActionNodeFactory : public NamedObjectFactory static ActionNode* rune_strike([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "rune strike", { - NextAction("frost presence") + CreateNextAction(1.0f) }, /*A*/ {}, /*C*/ {} @@ -35,9 +37,8 @@ class BloodDKStrategyActionNodeFactory : public NamedObjectFactory static ActionNode* icy_touch([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "icy touch", { - NextAction("frost presence") + CreateNextAction(1.0f) }, /*A*/ {}, /*C*/ {} @@ -46,9 +47,8 @@ class BloodDKStrategyActionNodeFactory : public NamedObjectFactory static ActionNode* heart_strike([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "heart strike", { - NextAction("frost presence") + CreateNextAction(1.0f) }, /*A*/ {}, /*C*/ {} @@ -58,9 +58,8 @@ class BloodDKStrategyActionNodeFactory : public NamedObjectFactory static ActionNode* death_strike([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "death strike", { - NextAction("frost presence") + CreateNextAction(1.0f) }, /*A*/ {}, /*C*/ {} @@ -69,12 +68,11 @@ class BloodDKStrategyActionNodeFactory : public NamedObjectFactory static ActionNode* dark_command([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "dark command", { - NextAction("frost presence") + CreateNextAction(1.0f) }, /*A*/ { - NextAction("death grip") + CreateNextAction(1.0f) }, /*C*/ {} ); @@ -89,15 +87,15 @@ BloodDKStrategy::BloodDKStrategy(PlayerbotAI* botAI) : GenericDKStrategy(botAI) std::vector BloodDKStrategy::getDefaultActions() { return { - NextAction("rune strike", ACTION_DEFAULT + 0.8f), - NextAction("icy touch", ACTION_DEFAULT + 0.7f), - NextAction("heart strike", ACTION_DEFAULT + 0.6f), - NextAction("blood strike", ACTION_DEFAULT + 0.5f), - NextAction("dancing rune weapon", ACTION_DEFAULT + 0.4f), - NextAction("death coil", ACTION_DEFAULT + 0.3f), - NextAction("plague strike", ACTION_DEFAULT + 0.2f), - NextAction("horn of winter", ACTION_DEFAULT + 0.1f), - NextAction("melee", ACTION_DEFAULT) + CreateNextAction(ACTION_DEFAULT + 0.8f), + CreateNextAction(ACTION_DEFAULT + 0.7f), + CreateNextAction(ACTION_DEFAULT + 0.6f), + CreateNextAction(ACTION_DEFAULT + 0.5f), + CreateNextAction(ACTION_DEFAULT + 0.4f), + CreateNextAction(ACTION_DEFAULT + 0.3f), + CreateNextAction(ACTION_DEFAULT + 0.2f), + CreateNextAction(ACTION_DEFAULT + 0.1f), + CreateNextAction(ACTION_DEFAULT) }; } @@ -109,7 +107,7 @@ void BloodDKStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "rune strike", { - NextAction("rune strike", ACTION_NORMAL + 3) + CreateNextAction(ACTION_NORMAL + 3.0f) } ) ); @@ -117,7 +115,7 @@ void BloodDKStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "blood tap", { - NextAction("blood tap", ACTION_HIGH + 5) + CreateNextAction(ACTION_HIGH + 5.0f) } ) ); @@ -125,7 +123,7 @@ void BloodDKStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "lose aggro", { - NextAction("dark command", ACTION_HIGH + 3) + CreateNextAction(ACTION_HIGH + 3.0f) } ) ); @@ -133,8 +131,8 @@ void BloodDKStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "low health", { - NextAction("army of the dead", ACTION_HIGH + 4), - NextAction("death strike", ACTION_HIGH + 3) + CreateNextAction(ACTION_HIGH + 4.0f), + CreateNextAction(ACTION_HIGH + 3.0f) } ) ); @@ -142,7 +140,7 @@ void BloodDKStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "critical health", { - NextAction("vampiric blood", ACTION_HIGH + 5) + CreateNextAction(ACTION_HIGH + 5.0f) } ) ); @@ -150,7 +148,7 @@ void BloodDKStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "icy touch", { - NextAction("icy touch", ACTION_HIGH + 2) + CreateNextAction(ACTION_HIGH + 2.0f) } ) ); @@ -158,7 +156,7 @@ void BloodDKStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "plague strike", { - NextAction("plague strike", ACTION_HIGH + 2) + CreateNextAction(ACTION_HIGH + 2.0f) } ) ); diff --git a/src/Ai/Class/Dk/Strategy/FrostDKStrategy.cpp b/src/Ai/Class/Dk/Strategy/FrostDKStrategy.cpp index d0b0ee2037..63284373c0 100644 --- a/src/Ai/Class/Dk/Strategy/FrostDKStrategy.cpp +++ b/src/Ai/Class/Dk/Strategy/FrostDKStrategy.cpp @@ -5,7 +5,9 @@ #include "FrostDKStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "DKActions.h" +#include "GenericActions.h" class FrostDKStrategyActionNodeFactory : public NamedObjectFactory { @@ -24,8 +26,7 @@ class FrostDKStrategyActionNodeFactory : public NamedObjectFactory static ActionNode* icy_touch([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "icy touch", - /*P*/ { NextAction("blood presence") }, + /*P*/ { CreateNextAction(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -34,8 +35,7 @@ class FrostDKStrategyActionNodeFactory : public NamedObjectFactory static ActionNode* obliterate([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "obliterate", - /*P*/ { NextAction("blood presence") }, + /*P*/ { CreateNextAction(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -44,9 +44,8 @@ class FrostDKStrategyActionNodeFactory : public NamedObjectFactory static ActionNode* rune_strike([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "rune strike", - /*P*/ { NextAction("blood presence") }, - /*A*/ { NextAction("melee") }, + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } @@ -54,8 +53,7 @@ class FrostDKStrategyActionNodeFactory : public NamedObjectFactory static ActionNode* frost_strike([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "frost strike", - /*P*/ { NextAction("blood presence") }, + /*P*/ { CreateNextAction(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -64,8 +62,7 @@ class FrostDKStrategyActionNodeFactory : public NamedObjectFactory static ActionNode* howling_blast([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "howling blast", - /*P*/ { NextAction("blood presence") }, + /*P*/ { CreateNextAction(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -73,8 +70,7 @@ class FrostDKStrategyActionNodeFactory : public NamedObjectFactory static ActionNode* unbreakable_armor([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "unbreakable armor", - /*P*/ { NextAction("blood tap") }, + /*P*/ { CreateNextAction(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -89,11 +85,11 @@ FrostDKStrategy::FrostDKStrategy(PlayerbotAI* botAI) : GenericDKStrategy(botAI) std::vector FrostDKStrategy::getDefaultActions() { return { - NextAction("obliterate", ACTION_DEFAULT + 0.7f), - NextAction("frost strike", ACTION_DEFAULT + 0.4f), - NextAction("empower rune weapon", ACTION_DEFAULT + 0.3f), - NextAction("horn of winter", ACTION_DEFAULT + 0.1f), - NextAction("melee", ACTION_DEFAULT) + CreateNextAction(ACTION_DEFAULT + 0.7f), + CreateNextAction(ACTION_DEFAULT + 0.4f), + CreateNextAction(ACTION_DEFAULT + 0.3f), + CreateNextAction(ACTION_DEFAULT + 0.1f), + CreateNextAction(ACTION_DEFAULT) }; } @@ -105,7 +101,7 @@ void FrostDKStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "unbreakable armor", { - NextAction("unbreakable armor", ACTION_DEFAULT + 0.6f) + CreateNextAction(ACTION_DEFAULT + 0.6f) } ) ); @@ -114,7 +110,7 @@ void FrostDKStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "freezing fog", { - NextAction("howling blast", ACTION_DEFAULT + 0.5f) + CreateNextAction(ACTION_DEFAULT + 0.5f) } ) ); @@ -123,7 +119,7 @@ void FrostDKStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "high blood rune", { - NextAction("blood strike", ACTION_DEFAULT + 0.2f) + CreateNextAction(ACTION_DEFAULT + 0.2f) } ) ); @@ -132,7 +128,7 @@ void FrostDKStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "army of the dead", { - NextAction("army of the dead", ACTION_HIGH + 6) + CreateNextAction(ACTION_HIGH + 6.0f) } ) ); @@ -141,7 +137,7 @@ void FrostDKStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "icy touch", { - NextAction("icy touch", ACTION_HIGH + 2) + CreateNextAction(ACTION_HIGH + 2.0f) } ) ); @@ -149,7 +145,7 @@ void FrostDKStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "plague strike", { - NextAction("plague strike", ACTION_HIGH + 2) + CreateNextAction(ACTION_HIGH + 2.0f) } ) ); @@ -162,7 +158,7 @@ void FrostDKAoeStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "medium aoe", { - NextAction("howling blast", ACTION_HIGH + 4) + CreateNextAction(ACTION_HIGH + 4) } ) ); diff --git a/src/Ai/Class/Dk/Strategy/GenericDKNonCombatStrategy.cpp b/src/Ai/Class/Dk/Strategy/GenericDKNonCombatStrategy.cpp index edead06755..26db2e2991 100644 --- a/src/Ai/Class/Dk/Strategy/GenericDKNonCombatStrategy.cpp +++ b/src/Ai/Class/Dk/Strategy/GenericDKNonCombatStrategy.cpp @@ -4,8 +4,9 @@ */ #include "GenericDKNonCombatStrategy.h" - -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "DKActions.h" +#include "GenericActions.h" class GenericDKNonCombatStrategyActionNodeFactory : public NamedObjectFactory { @@ -19,18 +20,20 @@ class GenericDKNonCombatStrategyActionNodeFactory : public NamedObjectFactory& trigger NonCombatStrategy::InitTriggers(triggers); triggers.push_back( - new TriggerNode("no pet", { NextAction("raise dead", ACTION_NORMAL + 1) })); + new TriggerNode( + "no pet", + { + CreateNextAction(ACTION_NORMAL + 1.0f) + } + ) + ); triggers.push_back( - new TriggerNode("horn of winter", { NextAction("horn of winter", 21.0f) })); + new TriggerNode( + "horn of winter", + { + CreateNextAction(21.0f) + } + ) + ); triggers.push_back( - new TriggerNode("bone shield", { NextAction("bone shield", 21.0f) })); + new TriggerNode( + "bone shield", + { + CreateNextAction(21.0f) + } + ) + ); triggers.push_back( - new TriggerNode("has pet", { NextAction("toggle pet spell", 60.0f) })); + new TriggerNode( + "has pet", + { + CreateNextAction(60.0f) + } + ) + ); triggers.push_back( - new TriggerNode("new pet", { NextAction("set pet stance", 60.0f) })); + new TriggerNode( + "new pet", + { + CreateNextAction(60.0f) + } + ) + ); } -void DKBuffDpsStrategy::InitTriggers(std::vector& triggers) +void DKBuffDpsStrategy::InitTriggers(std::vector&) { } diff --git a/src/Ai/Class/Dk/Strategy/GenericDKStrategy.cpp b/src/Ai/Class/Dk/Strategy/GenericDKStrategy.cpp index 61ff8c7489..c1a274151c 100644 --- a/src/Ai/Class/Dk/Strategy/GenericDKStrategy.cpp +++ b/src/Ai/Class/Dk/Strategy/GenericDKStrategy.cpp @@ -1,3 +1,6 @@ +#include "CreateNextAction.h" +#include "DKActions.h" +#include "GenericActions.h" #/* * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it and/or modify it under version 3 of the License, or (at your option), any later version. */ @@ -5,7 +8,6 @@ #include "GenericDKStrategy.h" #include "DKAiObjectContext.h" -#include "Playerbots.h" class GenericDKStrategyActionNodeFactory : public NamedObjectFactory { @@ -53,106 +55,119 @@ class GenericDKStrategyActionNodeFactory : public NamedObjectFactory private: static ActionNode* death_coil([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("death coil", - /*P*/ {}, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* death_grip([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("death grip", - /*P*/ {}, - /*A*/ { NextAction("icy touch") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* plague_strike([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("plague strike", - /*P*/ {}, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* icy_touch([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("icy touch", - /*P*/ {}, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* heart_strike([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("heart strike", - /*P*/ {}, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* pestilence([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("pestilence", - /*P*/ {}, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* horn_of_winter([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("horn of winter", - /*P*/ {}, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* bone_shield([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("bone shield", - /*P*/ {}, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* killing_machine([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("killing machine", - /*P*/ {}, - /*A*/ { NextAction("improved icy talons") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* corpse_explosion([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("corpse explosion", - /*P*/ {}, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* death_and_decay([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("death and decay", - /*P*/ {}, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* anti_magic_zone([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("anti magic zone", - /*P*/ {}, - /*A*/ { NextAction("anti magic shell") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* icebound_fortitude([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("icebound fortitude", - /*P*/ {}, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ {}, + /*C*/ {} + ); } }; @@ -166,28 +181,86 @@ void GenericDKStrategy::InitTriggers(std::vector& triggers) MeleeCombatStrategy::InitTriggers(triggers); triggers.push_back( - new TriggerNode("no pet", { NextAction("raise dead", ACTION_NORMAL + 5) })); + new TriggerNode( + "no pet", + { + CreateNextAction(ACTION_NORMAL + 5.0f) + } + ) + ); triggers.push_back( - new TriggerNode("has pet", { NextAction("toggle pet spell", 60.0f) })); + new TriggerNode( + "has pet", + { + CreateNextAction(60.0f) + } + ) + ); triggers.push_back( - new TriggerNode("new pet", { NextAction("set pet stance", 60.0f) })); + new TriggerNode( + "new pet", + { + CreateNextAction(60.0f) + } + ) + ); triggers.push_back( - new TriggerNode("mind freeze", { NextAction("mind freeze", ACTION_HIGH + 1) })); + new TriggerNode( + "mind freeze", + { + CreateNextAction(ACTION_HIGH + 1.0f) + } + ) + ); triggers.push_back( - new TriggerNode("mind freeze on enemy healer", - { NextAction("mind freeze on enemy healer", ACTION_HIGH + 1) })); - triggers.push_back(new TriggerNode( - "horn of winter", { NextAction("horn of winter", ACTION_NORMAL + 1) })); - triggers.push_back(new TriggerNode("critical health", - { NextAction("death pact", ACTION_HIGH + 5) })); - + new TriggerNode( + "mind freeze on enemy healer", + { + CreateNextAction(ACTION_HIGH + 1.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "horn of winter", + { + CreateNextAction(ACTION_NORMAL + 1.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "critical health", + { + CreateNextAction(ACTION_HIGH + 5.0f) + } + ) + ); triggers.push_back( - new TriggerNode("low health", { NextAction("icebound fortitude", ACTION_HIGH + 5), - NextAction("rune tap", ACTION_HIGH + 4) })); + new TriggerNode( + "low health", + { + CreateNextAction(ACTION_HIGH + 5.0f), + CreateNextAction(ACTION_HIGH + 4.0f) + } + ) + ); triggers.push_back( - new TriggerNode("medium aoe", { NextAction("death and decay", ACTION_HIGH + 9), - NextAction("pestilence", ACTION_NORMAL + 4), - NextAction("blood boil", ACTION_NORMAL + 3) })); + new TriggerNode( + "medium aoe", + { + CreateNextAction(ACTION_HIGH + 9.0f), + CreateNextAction(ACTION_NORMAL + 4.0f), + CreateNextAction(ACTION_NORMAL + 3.0f) + } + ) + ); triggers.push_back( - new TriggerNode("pestilence glyph", { NextAction("pestilence", ACTION_HIGH + 9) })); + new TriggerNode( + "pestilence glyph", + { + CreateNextAction(ACTION_HIGH + 9.0f) + } + ) + ); } diff --git a/src/Ai/Class/Dk/Strategy/UnholyDKStrategy.cpp b/src/Ai/Class/Dk/Strategy/UnholyDKStrategy.cpp index d94a94ec31..78c981b3d1 100644 --- a/src/Ai/Class/Dk/Strategy/UnholyDKStrategy.cpp +++ b/src/Ai/Class/Dk/Strategy/UnholyDKStrategy.cpp @@ -3,8 +3,9 @@ */ #include "UnholyDKStrategy.h" - -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "DKActions.h" +#include "GenericActions.h" class UnholyDKStrategyActionNodeFactory : public NamedObjectFactory { @@ -22,8 +23,7 @@ class UnholyDKStrategyActionNodeFactory : public NamedObjectFactory static ActionNode* death_strike([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "death strike", - /*P*/ { NextAction("blood presence") }, + /*P*/ { CreateNextAction(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -31,8 +31,7 @@ class UnholyDKStrategyActionNodeFactory : public NamedObjectFactory static ActionNode* ghoul_frenzy([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "ghoul frenzy", - /*P*/ { NextAction("blood presence") }, + /*P*/ { CreateNextAction(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -40,8 +39,7 @@ class UnholyDKStrategyActionNodeFactory : public NamedObjectFactory static ActionNode* corpse_explosion([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "corpse explosion", - /*P*/ { NextAction("blood presence") }, + /*P*/ { CreateNextAction(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -50,8 +48,7 @@ class UnholyDKStrategyActionNodeFactory : public NamedObjectFactory static ActionNode* scourge_strike([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "scourge strike", - /*P*/ { NextAction("blood presence") }, + /*P*/ { CreateNextAction(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -59,8 +56,7 @@ class UnholyDKStrategyActionNodeFactory : public NamedObjectFactory static ActionNode* icy_touch([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "icy touch", - /*P*/ { NextAction("blood presence") }, + /*P*/ { CreateNextAction(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -75,11 +71,11 @@ UnholyDKStrategy::UnholyDKStrategy(PlayerbotAI* botAI) : GenericDKStrategy(botAI std::vector UnholyDKStrategy::getDefaultActions() { return { - NextAction("death and decay", ACTION_HIGH + 5), - NextAction("summon gargoyle", ACTION_DEFAULT + 0.4f), - NextAction("horn of winter", ACTION_DEFAULT + 0.2f), - NextAction("death coil", ACTION_DEFAULT + 0.1f), - NextAction("melee", ACTION_DEFAULT) + CreateNextAction(ACTION_HIGH + 5.0f), + CreateNextAction(ACTION_DEFAULT + 0.4f), + CreateNextAction(ACTION_DEFAULT + 0.2f), + CreateNextAction(ACTION_DEFAULT + 0.1f), + CreateNextAction(ACTION_DEFAULT) }; } @@ -91,11 +87,11 @@ void UnholyDKStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "death and decay cooldown", { - NextAction("ghoul frenzy", ACTION_DEFAULT + 0.9f), - NextAction("scourge strike", ACTION_DEFAULT + 0.8f), - NextAction("icy touch", ACTION_DEFAULT + 0.7f), - NextAction("blood strike", ACTION_DEFAULT + 0.6f), - NextAction("plague strike", ACTION_DEFAULT + 0.5f), + CreateNextAction(ACTION_DEFAULT + 0.9f), + CreateNextAction(ACTION_DEFAULT + 0.8f), + CreateNextAction(ACTION_DEFAULT + 0.7f), + CreateNextAction(ACTION_DEFAULT + 0.6f), + CreateNextAction(ACTION_DEFAULT + 0.5f), } ) ); @@ -104,7 +100,7 @@ void UnholyDKStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "dd cd and no desolation", { - NextAction("blood strike", ACTION_DEFAULT + 0.75f) + CreateNextAction(ACTION_DEFAULT + 0.75f) } ) ); @@ -112,7 +108,7 @@ void UnholyDKStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "high frost rune", { - NextAction("icy touch", ACTION_NORMAL + 3) + CreateNextAction(ACTION_NORMAL + 3.0f) } ) ); @@ -120,7 +116,7 @@ void UnholyDKStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "high blood rune", { - NextAction("blood strike", ACTION_NORMAL + 2) + CreateNextAction(ACTION_NORMAL + 2.0f) } ) ); @@ -128,28 +124,31 @@ void UnholyDKStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "high unholy rune", { - NextAction("plague strike", ACTION_NORMAL + 1) + CreateNextAction(ACTION_NORMAL + 1.0f) } ) ); triggers.push_back( - new TriggerNode("dd cd and plague strike 3s", + new TriggerNode( + "dd cd and plague strike 3s", { - NextAction("plague strike", ACTION_HIGH + 1) + CreateNextAction(ACTION_HIGH + 1.0f) } ) ); triggers.push_back( - new TriggerNode("dd cd and icy touch 3s", + new TriggerNode( + "dd cd and icy touch 3s", { - NextAction("icy touch", ACTION_HIGH + 2) + CreateNextAction(ACTION_HIGH + 2.0f) } ) ); triggers.push_back( - new TriggerNode("no rune", + new TriggerNode( + "no rune", { - NextAction("empower rune weapon", ACTION_HIGH + 1) + CreateNextAction(ACTION_HIGH + 1.0f) } ) ); @@ -157,14 +156,15 @@ void UnholyDKStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "army of the dead", { - NextAction("army of the dead", ACTION_HIGH + 6) + CreateNextAction(ACTION_HIGH + 6.0f) } ) ); triggers.push_back( - new TriggerNode("bone shield", + new TriggerNode( + "bone shield", { - NextAction("bone shield", ACTION_HIGH + 3) + CreateNextAction(ACTION_HIGH + 3.0f) } ) ); @@ -176,7 +176,7 @@ void UnholyDKAoeStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "loot available", { - NextAction("corpse explosion", ACTION_NORMAL + 1) + CreateNextAction(ACTION_NORMAL + 1.0f) } ) ); @@ -184,8 +184,8 @@ void UnholyDKAoeStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "medium aoe", { - NextAction("death and decay", ACTION_NORMAL + 3), - NextAction("corpse explosion", ACTION_NORMAL + 3) + CreateNextAction(ACTION_NORMAL + 3.0f), + CreateNextAction(ACTION_NORMAL + 3.0f) } ) ); diff --git a/src/Ai/Class/Dk/Trigger/DKTriggers.cpp b/src/Ai/Class/Dk/Trigger/DKTriggers.cpp index 90c1620953..983661bc46 100644 --- a/src/Ai/Class/Dk/Trigger/DKTriggers.cpp +++ b/src/Ai/Class/Dk/Trigger/DKTriggers.cpp @@ -9,7 +9,6 @@ #include "GenericTriggers.h" #include "Playerbots.h" -#include "SharedDefines.h" bool DKPresenceTrigger::IsActive() { diff --git a/src/Ai/Class/Druid/Action/DruidActions.cpp b/src/Ai/Class/Druid/Action/DruidActions.cpp index 13336a674a..1bc53e8ca7 100644 --- a/src/Ai/Class/Druid/Action/DruidActions.cpp +++ b/src/Ai/Class/Druid/Action/DruidActions.cpp @@ -5,22 +5,28 @@ #include "DruidActions.h" +#include "DruidShapeshiftActions.h" #include "Event.h" #include "Playerbots.h" #include "ServerFacade.h" -#include "AoeValues.h" #include "TargetValue.h" std::vector CastAbolishPoisonAction::getAlternatives() { - return NextAction::merge({ NextAction("cure poison") }, - CastSpellAction::getPrerequisites()); + std::vector alternatives = CastSpellAction::getAlternatives(); + + alternatives.push_back(CreateNextAction(1.0f)); + + return alternatives; } std::vector CastAbolishPoisonOnPartyAction::getAlternatives() { - return NextAction::merge({ NextAction("cure poison on party") }, - CastSpellAction::getPrerequisites()); + std::vector alternatives = CastSpellAction::getAlternatives(); + + alternatives.push_back(CreateNextAction(1.0f)); + + return alternatives; } Value* CastEntanglingRootsCcAction::GetTargetValue() @@ -28,11 +34,11 @@ Value* CastEntanglingRootsCcAction::GetTargetValue() return context->GetValue("cc target", "entangling roots"); } -bool CastEntanglingRootsCcAction::Execute(Event event) { return botAI->CastSpell("entangling roots", GetTarget()); } +bool CastEntanglingRootsCcAction::Execute(Event) { return botAI->CastSpell("entangling roots", GetTarget()); } Value* CastHibernateCcAction::GetTargetValue() { return context->GetValue("cc target", "hibernate"); } -bool CastHibernateCcAction::Execute(Event event) { return botAI->CastSpell("hibernate", GetTarget()); } +bool CastHibernateCcAction::Execute(Event) { return botAI->CastSpell("hibernate", GetTarget()); } bool CastStarfallAction::isUseful() { if (!CastSpellAction::isUseful()) @@ -43,8 +49,8 @@ bool CastStarfallAction::isUseful() Unit* ccTarget = context->GetValue("current cc target")->Get(); if (ccTarget && ccTarget->IsAlive()) { - float dist2d = sServerFacade->GetDistance2d(ccTarget, aoePos.GetPositionX(), aoePos.GetPositionY()); - if (sServerFacade->IsDistanceLessOrEqualThan(dist2d, sPlayerbotAIConfig->aoeRadius)) + float dist2d = ServerFacade::instance().GetDistance2d(ccTarget, aoePos.GetPositionX(), aoePos.GetPositionY()); + if (ServerFacade::instance().IsDistanceLessOrEqualThan(dist2d, sPlayerbotAIConfig.aoeRadius)) return false; } @@ -62,20 +68,26 @@ bool CastStarfallAction::isUseful() std::vector CastReviveAction::getPrerequisites() { - return NextAction::merge({ NextAction("caster form") }, - ResurrectPartyMemberAction::getPrerequisites()); + std::vector prerequisites = ResurrectPartyMemberAction::getPrerequisites(); + + prerequisites.push_back(CreateNextAction(1.0f)); + + return prerequisites; } std::vector CastRebirthAction::getPrerequisites() { - return NextAction::merge({ NextAction("caster form") }, - ResurrectPartyMemberAction::getPrerequisites()); + std::vector prerequisites = ResurrectPartyMemberAction::getPrerequisites(); + + prerequisites.push_back(CreateNextAction(1.0f)); + + return prerequisites; } bool CastRebirthAction::isUseful() { return CastSpellAction::isUseful() && - AI_VALUE2(float, "distance", GetTargetName()) <= sPlayerbotAIConfig->spellDistance; + AI_VALUE2(float, "distance", GetTargetName()) <= sPlayerbotAIConfig.spellDistance; } Unit* CastRejuvenationOnNotFullAction::GetTarget() @@ -91,7 +103,7 @@ Unit* CastRejuvenationOnNotFullAction::GetTarget() { continue; } - if (player->GetDistance2d(bot) > sPlayerbotAIConfig->spellDistance) + if (player->GetDistance2d(bot) > sPlayerbotAIConfig.spellDistance) { continue; } @@ -107,4 +119,4 @@ Unit* CastRejuvenationOnNotFullAction::GetTarget() bool CastRejuvenationOnNotFullAction::isUseful() { return GetTarget(); -} \ No newline at end of file +} diff --git a/src/Ai/Class/Druid/Action/DruidShapeshiftActions.cpp b/src/Ai/Class/Druid/Action/DruidShapeshiftActions.cpp index 4f4a4e5968..230df23c6c 100644 --- a/src/Ai/Class/Druid/Action/DruidShapeshiftActions.cpp +++ b/src/Ai/Class/Druid/Action/DruidShapeshiftActions.cpp @@ -19,8 +19,11 @@ bool CastBearFormAction::isUseful() std::vector CastDireBearFormAction::getAlternatives() { - return NextAction::merge({ NextAction("bear form") }, - CastSpellAction::getAlternatives()); + std::vector alternatives; + + alternatives.push_back(CreateNextAction(1.0f)); + + return alternatives; } bool CastTravelFormAction::isUseful() @@ -36,10 +39,10 @@ bool CastCasterFormAction::isUseful() { return botAI->HasAnyAuraOf(GetTarget(), "dire bear form", "bear form", "cat form", "travel form", "aquatic form", "flight form", "swift flight form", "moonkin form", nullptr) && - AI_VALUE2(uint8, "mana", "self target") > sPlayerbotAIConfig->mediumHealth; + AI_VALUE2(uint8, "mana", "self target") > sPlayerbotAIConfig.mediumHealth; } -bool CastCasterFormAction::Execute(Event event) +bool CastCasterFormAction::Execute(Event) { botAI->RemoveShapeshift(); return true; @@ -50,7 +53,7 @@ bool CastCancelTreeFormAction::isUseful() return botAI->HasAura(33891, bot); } -bool CastCancelTreeFormAction::Execute(Event event) +bool CastCancelTreeFormAction::Execute(Event) { botAI->RemoveAura("tree of life"); return true; diff --git a/src/Ai/Class/Druid/DruidAiObjectContext.cpp b/src/Ai/Class/Druid/DruidAiObjectContext.cpp index 29d9d4fdc0..689b72964c 100644 --- a/src/Ai/Class/Druid/DruidAiObjectContext.cpp +++ b/src/Ai/Class/Druid/DruidAiObjectContext.cpp @@ -18,7 +18,6 @@ #include "HealDruidStrategy.h" #include "MeleeDruidStrategy.h" #include "OffhealDruidCatStrategy.h" -#include "Playerbots.h" class DruidStrategyFactoryInternal : public NamedObjectContext { @@ -151,195 +150,18 @@ class DruidTriggerFactoryInternal : public NamedObjectContext static Trigger* hurricane_channel_check(PlayerbotAI* ai) { return new HurricaneChannelCheckTrigger(ai); } }; -class DruidAiObjectContextInternal : public NamedObjectContext -{ -public: - DruidAiObjectContextInternal() - { - creators["feral charge - bear"] = &DruidAiObjectContextInternal::feral_charge_bear; - creators["feral charge - cat"] = &DruidAiObjectContextInternal::feral_charge_cat; - creators["swipe (bear)"] = &DruidAiObjectContextInternal::swipe_bear; - creators["faerie fire (feral)"] = &DruidAiObjectContextInternal::faerie_fire_feral; - creators["faerie fire"] = &DruidAiObjectContextInternal::faerie_fire; - creators["bear form"] = &DruidAiObjectContextInternal::bear_form; - creators["dire bear form"] = &DruidAiObjectContextInternal::dire_bear_form; - creators["moonkin form"] = &DruidAiObjectContextInternal::moonkin_form; - creators["cat form"] = &DruidAiObjectContextInternal::cat_form; - creators["tree form"] = &DruidAiObjectContextInternal::tree_form; - creators["travel form"] = &DruidAiObjectContextInternal::travel_form; - creators["aquatic form"] = &DruidAiObjectContextInternal::aquatic_form; - creators["caster form"] = &DruidAiObjectContextInternal::caster_form; - creators["cancel tree form"] = &DruidAiObjectContextInternal::cancel_tree_form; - creators["mangle (bear)"] = &DruidAiObjectContextInternal::mangle_bear; - creators["maul"] = &DruidAiObjectContextInternal::maul; - creators["bash"] = &DruidAiObjectContextInternal::bash; - creators["swipe"] = &DruidAiObjectContextInternal::swipe; - creators["growl"] = &DruidAiObjectContextInternal::growl; - creators["demoralizing roar"] = &DruidAiObjectContextInternal::demoralizing_roar; - creators["hibernate"] = &DruidAiObjectContextInternal::hibernate; - creators["entangling roots"] = &DruidAiObjectContextInternal::entangling_roots; - creators["entangling roots on cc"] = &DruidAiObjectContextInternal::entangling_roots_on_cc; - creators["hibernate"] = &DruidAiObjectContextInternal::hibernate; - creators["hibernate on cc"] = &DruidAiObjectContextInternal::hibernate_on_cc; - creators["wrath"] = &DruidAiObjectContextInternal::wrath; - creators["starfall"] = &DruidAiObjectContextInternal::starfall; - creators["insect swarm"] = &DruidAiObjectContextInternal::insect_swarm; - creators["moonfire"] = &DruidAiObjectContextInternal::moonfire; - creators["starfire"] = &DruidAiObjectContextInternal::starfire; - creators["nature's grasp"] = &DruidAiObjectContextInternal::natures_grasp; - creators["claw"] = &DruidAiObjectContextInternal::claw; - creators["mangle (cat)"] = &DruidAiObjectContextInternal::mangle_cat; - creators["swipe (cat)"] = &DruidAiObjectContextInternal::swipe_cat; - creators["rake"] = &DruidAiObjectContextInternal::rake; - creators["rake on attacker"] = &DruidAiObjectContextInternal::rake_on_attacker; - creators["ferocious bite"] = &DruidAiObjectContextInternal::ferocious_bite; - creators["rip"] = &DruidAiObjectContextInternal::rip; - creators["cower"] = &DruidAiObjectContextInternal::cower; - creators["survival instincts"] = &DruidAiObjectContextInternal::survival_instincts; - creators["frenzied regeneration"] = &DruidAiObjectContextInternal::frenzied_regeneration; - creators["thorns"] = &DruidAiObjectContextInternal::thorns; - creators["thorns on party"] = &DruidAiObjectContextInternal::thorns_on_party; - creators["thorns on main tank"] = &DruidAiObjectContextInternal::thorns_on_main_tank; - creators["cure poison"] = &DruidAiObjectContextInternal::cure_poison; - creators["cure poison on party"] = &DruidAiObjectContextInternal::cure_poison_on_party; - creators["abolish poison"] = &DruidAiObjectContextInternal::abolish_poison; - creators["abolish poison on party"] = &DruidAiObjectContextInternal::abolish_poison_on_party; - creators["berserk"] = &DruidAiObjectContextInternal::berserk; - creators["tiger's fury"] = &DruidAiObjectContextInternal::tigers_fury; - creators["savage roar"] = &DruidAiObjectContextInternal::savage_roar; - creators["mark of the wild"] = &DruidAiObjectContextInternal::mark_of_the_wild; - creators["mark of the wild on party"] = &DruidAiObjectContextInternal::mark_of_the_wild_on_party; - creators["regrowth"] = &DruidAiObjectContextInternal::regrowth; - creators["rejuvenation"] = &DruidAiObjectContextInternal::rejuvenation; - creators["healing touch"] = &DruidAiObjectContextInternal::healing_touch; - creators["regrowth on party"] = &DruidAiObjectContextInternal::regrowth_on_party; - creators["rejuvenation on party"] = &DruidAiObjectContextInternal::rejuvenation_on_party; - creators["rejuvenation on not full"] = &DruidAiObjectContextInternal::rejuvenation_on_not_full; - creators["healing touch on party"] = &DruidAiObjectContextInternal::healing_touch_on_party; - creators["rebirth"] = &DruidAiObjectContextInternal::rebirth; - creators["revive"] = &DruidAiObjectContextInternal::revive; - creators["barkskin"] = &DruidAiObjectContextInternal::barkskin; - creators["lacerate"] = &DruidAiObjectContextInternal::lacerate; - creators["hurricane"] = &DruidAiObjectContextInternal::hurricane; - creators["innervate"] = &DruidAiObjectContextInternal::innervate; - creators["tranquility"] = &DruidAiObjectContextInternal::tranquility; - creators["bash on enemy healer"] = &DruidAiObjectContextInternal::bash_on_enemy_healer; - creators["omen of clarity"] = &DruidAiObjectContextInternal::omen_of_clarity; - creators["nature's swiftness"] = &DruidAiObjectContextInternal::natures_swiftness; - creators["prowl"] = &DruidAiObjectContextInternal::prowl; - creators["dash"] = &DruidAiObjectContextInternal::dash; - creators["shred"] = &DruidAiObjectContextInternal::shred; - creators["ravage"] = &DruidAiObjectContextInternal::ravage; - creators["pounce"] = &DruidAiObjectContextInternal::pounce; - creators["wild growth on party"] = &DruidAiObjectContextInternal::wild_growth_on_party; - creators["swiftmend on party"] = &DruidAiObjectContextInternal::swiftmend_on_party; - creators["nourish on party"] = &DruidAiObjectContextInternal::nourish_on_party; - creators["remove curse on party"] = &DruidAiObjectContextInternal::remove_curse_on_party; - creators["insect swarm on attacker"] = &DruidAiObjectContextInternal::insect_swarm_on_attacker; - creators["moonfire on attacker"] = &DruidAiObjectContextInternal::moonfire_on_attacker; - creators["enrage"] = &DruidAiObjectContextInternal::enrage; - creators["force of nature"] = &DruidAiObjectContextInternal::force_of_nature; - } - -private: - static Action* natures_swiftness(PlayerbotAI* botAI) { return new CastNaturesSwiftnessAction(botAI); } - static Action* omen_of_clarity(PlayerbotAI* botAI) { return new CastOmenOfClarityAction(botAI); } - static Action* tranquility(PlayerbotAI* botAI) { return new CastTranquilityAction(botAI); } - static Action* feral_charge_bear(PlayerbotAI* botAI) { return new CastFeralChargeBearAction(botAI); } - static Action* feral_charge_cat(PlayerbotAI* botAI) { return new CastFeralChargeCatAction(botAI); } - static Action* swipe_bear(PlayerbotAI* botAI) { return new CastSwipeBearAction(botAI); } - static Action* faerie_fire_feral(PlayerbotAI* botAI) { return new CastFaerieFireFeralAction(botAI); } - static Action* faerie_fire(PlayerbotAI* botAI) { return new CastFaerieFireAction(botAI); } - static Action* bear_form(PlayerbotAI* botAI) { return new CastBearFormAction(botAI); } - static Action* dire_bear_form(PlayerbotAI* botAI) { return new CastDireBearFormAction(botAI); } - static Action* cat_form(PlayerbotAI* botAI) { return new CastCatFormAction(botAI); } - static Action* tree_form(PlayerbotAI* botAI) { return new CastTreeFormAction(botAI); } - static Action* travel_form(PlayerbotAI* botAI) { return new CastTravelFormAction(botAI); } - static Action* aquatic_form(PlayerbotAI* botAI) { return new CastAquaticFormAction(botAI); } - static Action* caster_form(PlayerbotAI* botAI) { return new CastCasterFormAction(botAI); } - static Action* cancel_tree_form(PlayerbotAI* botAI) { return new CastCancelTreeFormAction(botAI); } - static Action* mangle_bear(PlayerbotAI* botAI) { return new CastMangleBearAction(botAI); } - static Action* maul(PlayerbotAI* botAI) { return new CastMaulAction(botAI); } - static Action* bash(PlayerbotAI* botAI) { return new CastBashAction(botAI); } - static Action* swipe(PlayerbotAI* botAI) { return new CastSwipeAction(botAI); } - static Action* growl(PlayerbotAI* botAI) { return new CastGrowlAction(botAI); } - static Action* demoralizing_roar(PlayerbotAI* botAI) { return new CastDemoralizingRoarAction(botAI); } - static Action* moonkin_form(PlayerbotAI* botAI) { return new CastMoonkinFormAction(botAI); } - static Action* hibernate(PlayerbotAI* botAI) { return new CastHibernateAction(botAI); } - static Action* entangling_roots(PlayerbotAI* botAI) { return new CastEntanglingRootsAction(botAI); } - static Action* hibernate_on_cc(PlayerbotAI* botAI) { return new CastHibernateCcAction(botAI); } - static Action* entangling_roots_on_cc(PlayerbotAI* botAI) { return new CastEntanglingRootsCcAction(botAI); } - static Action* wrath(PlayerbotAI* botAI) { return new CastWrathAction(botAI); } - static Action* starfall(PlayerbotAI* botAI) { return new CastStarfallAction(botAI); } - static Action* insect_swarm(PlayerbotAI* botAI) { return new CastInsectSwarmAction(botAI); } - static Action* moonfire(PlayerbotAI* botAI) { return new CastMoonfireAction(botAI); } - static Action* starfire(PlayerbotAI* botAI) { return new CastStarfireAction(botAI); } - static Action* natures_grasp(PlayerbotAI* botAI) { return new CastNaturesGraspAction(botAI); } - static Action* claw(PlayerbotAI* botAI) { return new CastClawAction(botAI); } - static Action* mangle_cat(PlayerbotAI* botAI) { return new CastMangleCatAction(botAI); } - static Action* swipe_cat(PlayerbotAI* botAI) { return new CastSwipeCatAction(botAI); } - static Action* rake(PlayerbotAI* botAI) { return new CastRakeAction(botAI); } - static Action* rake_on_attacker(PlayerbotAI* botAI) { return new CastRakeOnMeleeAttackersAction(botAI); } - static Action* ferocious_bite(PlayerbotAI* botAI) { return new CastFerociousBiteAction(botAI); } - static Action* rip(PlayerbotAI* botAI) { return new CastRipAction(botAI); } - static Action* cower(PlayerbotAI* botAI) { return new CastCowerAction(botAI); } - static Action* survival_instincts(PlayerbotAI* botAI) { return new CastSurvivalInstinctsAction(botAI); } - static Action* frenzied_regeneration(PlayerbotAI* botAI) { return new CastFrenziedRegenerationAction(botAI); } - static Action* thorns(PlayerbotAI* botAI) { return new CastThornsAction(botAI); } - static Action* thorns_on_party(PlayerbotAI* botAI) { return new CastThornsOnPartyAction(botAI); } - static Action* thorns_on_main_tank(PlayerbotAI* botAI) { return new CastThornsOnMainTankAction(botAI); } - static Action* cure_poison(PlayerbotAI* botAI) { return new CastCurePoisonAction(botAI); } - static Action* cure_poison_on_party(PlayerbotAI* botAI) { return new CastCurePoisonOnPartyAction(botAI); } - static Action* abolish_poison(PlayerbotAI* botAI) { return new CastAbolishPoisonAction(botAI); } - static Action* abolish_poison_on_party(PlayerbotAI* botAI) { return new CastAbolishPoisonOnPartyAction(botAI); } - static Action* berserk(PlayerbotAI* botAI) { return new CastBerserkAction(botAI); } - static Action* tigers_fury(PlayerbotAI* botAI) { return new CastTigersFuryAction(botAI); } - static Action* savage_roar(PlayerbotAI* botAI) { return new CastSavageRoarAction(botAI); } - static Action* mark_of_the_wild(PlayerbotAI* botAI) { return new CastMarkOfTheWildAction(botAI); } - static Action* mark_of_the_wild_on_party(PlayerbotAI* botAI) { return new CastMarkOfTheWildOnPartyAction(botAI); } - static Action* regrowth(PlayerbotAI* botAI) { return new CastRegrowthAction(botAI); } - static Action* rejuvenation(PlayerbotAI* botAI) { return new CastRejuvenationAction(botAI); } - static Action* healing_touch(PlayerbotAI* botAI) { return new CastHealingTouchAction(botAI); } - static Action* regrowth_on_party(PlayerbotAI* botAI) { return new CastRegrowthOnPartyAction(botAI); } - static Action* rejuvenation_on_party(PlayerbotAI* botAI) { return new CastRejuvenationOnPartyAction(botAI); } - static Action* rejuvenation_on_not_full(PlayerbotAI* botAI) { return new CastRejuvenationOnNotFullAction(botAI); } - static Action* healing_touch_on_party(PlayerbotAI* botAI) { return new CastHealingTouchOnPartyAction(botAI); } - static Action* rebirth(PlayerbotAI* botAI) { return new CastRebirthAction(botAI); } - static Action* revive(PlayerbotAI* botAI) { return new CastReviveAction(botAI); } - static Action* barkskin(PlayerbotAI* botAI) { return new CastBarkskinAction(botAI); } - static Action* lacerate(PlayerbotAI* botAI) { return new CastLacerateAction(botAI); } - static Action* hurricane(PlayerbotAI* botAI) { return new CastHurricaneAction(botAI); } - static Action* innervate(PlayerbotAI* botAI) { return new CastInnervateAction(botAI); } - static Action* bash_on_enemy_healer(PlayerbotAI* botAI) { return new CastBashOnEnemyHealerAction(botAI); } - static Action* ravage(PlayerbotAI* botAI) { return new CastRavageAction(botAI); } - static Action* pounce(PlayerbotAI* botAI) { return new CastPounceAction(botAI); } - static Action* prowl(PlayerbotAI* botAI) { return new CastProwlAction(botAI); } - static Action* dash(PlayerbotAI* botAI) { return new CastDashAction(botAI); } - static Action* shred(PlayerbotAI* botAI) { return new CastShredAction(botAI); } - static Action* wild_growth_on_party(PlayerbotAI* ai) { return new CastWildGrowthOnPartyAction(ai); } - static Action* swiftmend_on_party(PlayerbotAI* ai) { return new CastPartySwiftmendAction(ai); } - static Action* nourish_on_party(PlayerbotAI* ai) { return new CastPartyNourishAction(ai); } - static Action* remove_curse_on_party(PlayerbotAI* ai) { return new CastDruidRemoveCurseOnPartyAction(ai); } - static Action* insect_swarm_on_attacker(PlayerbotAI* ai) { return new CastInsectSwarmOnAttackerAction(ai); } - static Action* moonfire_on_attacker(PlayerbotAI* ai) { return new CastMoonfireOnAttackerAction(ai); } - static Action* enrage(PlayerbotAI* ai) { return new CastEnrageAction(ai); } - static Action* force_of_nature(PlayerbotAI* ai) { return new CastForceOfNatureAction(ai); } -}; - SharedNamedObjectContextList DruidAiObjectContext::sharedStrategyContexts; -SharedNamedObjectContextList DruidAiObjectContext::sharedActionContexts; SharedNamedObjectContextList DruidAiObjectContext::sharedTriggerContexts; SharedNamedObjectContextList DruidAiObjectContext::sharedValueContexts; DruidAiObjectContext::DruidAiObjectContext(PlayerbotAI* botAI) - : AiObjectContext(botAI, sharedStrategyContexts, sharedActionContexts, sharedTriggerContexts, sharedValueContexts) + : AiObjectContext(botAI, sharedStrategyContexts, sharedTriggerContexts, sharedValueContexts) { } void DruidAiObjectContext::BuildSharedContexts() { BuildSharedStrategyContexts(sharedStrategyContexts); - BuildSharedActionContexts(sharedActionContexts); BuildSharedTriggerContexts(sharedTriggerContexts); BuildSharedValueContexts(sharedValueContexts); } @@ -351,12 +173,6 @@ void DruidAiObjectContext::BuildSharedStrategyContexts(SharedNamedObjectContextL strategyContexts.Add(new DruidDruidStrategyFactoryInternal()); } -void DruidAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts) -{ - AiObjectContext::BuildSharedActionContexts(actionContexts); - actionContexts.Add(new DruidAiObjectContextInternal()); -} - void DruidAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts) { AiObjectContext::BuildSharedTriggerContexts(triggerContexts); diff --git a/src/Ai/Class/Druid/DruidAiObjectContext.h b/src/Ai/Class/Druid/DruidAiObjectContext.h index ee309e79c7..cee64c7662 100644 --- a/src/Ai/Class/Druid/DruidAiObjectContext.h +++ b/src/Ai/Class/Druid/DruidAiObjectContext.h @@ -17,12 +17,10 @@ class DruidAiObjectContext : public AiObjectContext static void BuildSharedContexts(); static void BuildSharedStrategyContexts(SharedNamedObjectContextList& strategyContexts); - static void BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts); static void BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts); static void BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts); static SharedNamedObjectContextList sharedStrategyContexts; - static SharedNamedObjectContextList sharedActionContexts; static SharedNamedObjectContextList sharedTriggerContexts; static SharedNamedObjectContextList sharedValueContexts; }; diff --git a/src/Ai/Class/Druid/Strategy/BearTankDruidStrategy.cpp b/src/Ai/Class/Druid/Strategy/BearTankDruidStrategy.cpp index 4a60fbd3ea..9a8e127fc4 100644 --- a/src/Ai/Class/Druid/Strategy/BearTankDruidStrategy.cpp +++ b/src/Ai/Class/Druid/Strategy/BearTankDruidStrategy.cpp @@ -5,7 +5,13 @@ #include "BearTankDruidStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "ActionNode.h" +#include "GenericActions.h" +#include "ReachTargetActions.h" +#include "DruidActions.h" +#include "DruidShapeshiftActions.h" +#include "DruidBearActions.h" class BearTankDruidStrategyActionNodeFactory : public NamedObjectFactory { @@ -31,8 +37,7 @@ class BearTankDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -41,9 +46,8 @@ class BearTankDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -51,7 +55,6 @@ class BearTankDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -71,7 +73,6 @@ class BearTankDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } @@ -91,7 +91,6 @@ class BearTankDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -111,9 +109,8 @@ class BearTankDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -121,9 +118,8 @@ class BearTankDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -131,9 +127,8 @@ class BearTankDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -141,7 +136,6 @@ class BearTankDruidStrategyActionNodeFactory : public NamedObjectFactory BearTankDruidStrategy::getDefaultActions() { return { - NextAction("mangle (bear)", ACTION_DEFAULT + 0.5f), - NextAction("faerie fire (feral)", ACTION_DEFAULT + 0.4f), - NextAction("lacerate", ACTION_DEFAULT + 0.3f), - NextAction("maul", ACTION_DEFAULT + 0.2f), - NextAction("enrage", ACTION_DEFAULT + 0.1f), - NextAction("melee", ACTION_DEFAULT) + CreateNextAction(ACTION_DEFAULT + 0.5f), + CreateNextAction(ACTION_DEFAULT + 0.4f), + CreateNextAction(ACTION_DEFAULT + 0.3f), + CreateNextAction(ACTION_DEFAULT + 0.2f), + CreateNextAction(ACTION_DEFAULT + 0.1f), + CreateNextAction(ACTION_DEFAULT) }; } @@ -184,7 +177,7 @@ void BearTankDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "enemy out of melee", { - NextAction("feral charge - bear", ACTION_NORMAL + 8) + CreateNextAction(ACTION_NORMAL + 8.0f) } ) ); @@ -192,7 +185,7 @@ void BearTankDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "bear form", { - NextAction("dire bear form", ACTION_HIGH + 8) + CreateNextAction(ACTION_HIGH + 8.0f) } ) ); @@ -200,7 +193,7 @@ void BearTankDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "low health", { - NextAction("frenzied regeneration", ACTION_HIGH + 7) + CreateNextAction(ACTION_HIGH + 7.0f) } ) ); @@ -208,7 +201,7 @@ void BearTankDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "faerie fire (feral)", { - NextAction("faerie fire (feral)", ACTION_HIGH + 7) + CreateNextAction(ACTION_HIGH + 7.0f) } ) ); @@ -216,7 +209,7 @@ void BearTankDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "lose aggro", { - NextAction("growl", ACTION_HIGH + 8) + CreateNextAction(ACTION_HIGH + 8.0f) } ) ); @@ -224,8 +217,8 @@ void BearTankDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "medium aoe", { - NextAction("demoralizing roar", ACTION_HIGH + 6), - NextAction("swipe (bear)", ACTION_HIGH + 6) + CreateNextAction(ACTION_HIGH + 6.0f), + CreateNextAction(ACTION_HIGH + 6.0f) } ) ); @@ -233,7 +226,7 @@ void BearTankDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "light aoe", { - NextAction("swipe (bear)", ACTION_HIGH + 5) + CreateNextAction(ACTION_HIGH + 5.0f) } ) ); @@ -241,7 +234,7 @@ void BearTankDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "bash", { - NextAction("bash", ACTION_INTERRUPT + 2) + CreateNextAction(ACTION_INTERRUPT + 2.0f) } ) ); @@ -249,7 +242,7 @@ void BearTankDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "bash on enemy healer", { - NextAction("bash on enemy healer", ACTION_INTERRUPT + 1) + CreateNextAction(ACTION_INTERRUPT + 1.0f) } ) ); diff --git a/src/Ai/Class/Druid/Strategy/CasterDruidStrategy.cpp b/src/Ai/Class/Druid/Strategy/CasterDruidStrategy.cpp index a91f3b5409..21f993dd31 100644 --- a/src/Ai/Class/Druid/Strategy/CasterDruidStrategy.cpp +++ b/src/Ai/Class/Druid/Strategy/CasterDruidStrategy.cpp @@ -5,7 +5,13 @@ #include "CasterDruidStrategy.h" +#include "ActionNode.h" +#include "CreateNextAction.h" #include "AiObjectContext.h" +#include "MovementActions.h" +#include "CancelChannelAction.h" +#include "DruidActions.h" +#include "DruidShapeshiftActions.h" #include "FeralDruidStrategy.h" class CasterDruidStrategyActionNodeFactory : public NamedObjectFactory @@ -29,8 +35,7 @@ class CasterDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -39,9 +44,8 @@ class CasterDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } @@ -49,8 +53,7 @@ class CasterDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -59,8 +62,7 @@ class CasterDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -69,8 +71,7 @@ class CasterDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -79,8 +80,7 @@ class CasterDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -89,8 +89,7 @@ class CasterDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -99,8 +98,7 @@ class CasterDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -109,8 +107,7 @@ class CasterDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -119,8 +116,7 @@ class CasterDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -136,9 +132,9 @@ CasterDruidStrategy::CasterDruidStrategy(PlayerbotAI* botAI) : GenericDruidStrat std::vector CasterDruidStrategy::getDefaultActions() { return { - NextAction("starfall", ACTION_HIGH + 1.0f), - NextAction("force of nature", ACTION_DEFAULT + 1.0f), - NextAction("wrath", ACTION_DEFAULT + 0.1f), + CreateNextAction(ACTION_HIGH + 1.0f), + CreateNextAction(ACTION_DEFAULT + 1.0f), + CreateNextAction(ACTION_DEFAULT + 0.1f), }; } @@ -150,7 +146,7 @@ void CasterDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "eclipse (lunar) cooldown", { - NextAction("starfire", ACTION_DEFAULT + 0.2f) + CreateNextAction(ACTION_DEFAULT + 0.2f) } ) ); @@ -158,7 +154,7 @@ void CasterDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "eclipse (solar) cooldown", { - NextAction("wrath", ACTION_DEFAULT + 0.2f) + CreateNextAction(ACTION_DEFAULT + 0.2f) } ) ); @@ -166,7 +162,7 @@ void CasterDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "insect swarm", { - NextAction("insect swarm", ACTION_NORMAL + 5) + CreateNextAction(ACTION_NORMAL + 5.0f) } ) ); @@ -174,7 +170,7 @@ void CasterDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "moonfire", { - NextAction("moonfire", ACTION_NORMAL + 4) + CreateNextAction(ACTION_NORMAL + 4.0f) } ) ); @@ -182,7 +178,7 @@ void CasterDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "eclipse (solar)", { - NextAction("wrath", ACTION_NORMAL + 6) + CreateNextAction(ACTION_NORMAL + 6.0f) } ) ); @@ -190,7 +186,7 @@ void CasterDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "eclipse (lunar)", { - NextAction("starfire", ACTION_NORMAL + 6) + CreateNextAction(ACTION_NORMAL + 6.0f) } ) ); @@ -198,7 +194,7 @@ void CasterDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "medium mana", { - NextAction("innervate", ACTION_HIGH + 9) + CreateNextAction(ACTION_HIGH + 9.0f) } ) ); @@ -206,7 +202,7 @@ void CasterDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "enemy too close for spell", { - NextAction("flee", ACTION_MOVE + 9) + CreateNextAction(ACTION_MOVE + 9.0f) } ) ); @@ -218,7 +214,7 @@ void CasterDruidAoeStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "hurricane channel check", { - NextAction("cancel channel", ACTION_HIGH + 2) + CreateNextAction(ACTION_HIGH + 2.0f) } ) ); @@ -226,7 +222,7 @@ void CasterDruidAoeStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "medium aoe", { - NextAction("hurricane", ACTION_HIGH + 1) + CreateNextAction(ACTION_HIGH + 1.0f) } ) ); @@ -234,8 +230,8 @@ void CasterDruidAoeStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "light aoe", { - NextAction("insect swarm on attacker", ACTION_NORMAL + 3), - NextAction("moonfire on attacker", ACTION_NORMAL + 3) + CreateNextAction(ACTION_NORMAL + 3.0f), + CreateNextAction(ACTION_NORMAL + 3.0f) } ) ); @@ -247,7 +243,7 @@ void CasterDruidDebuffStrategy::InitTriggers(std::vector& triggers new TriggerNode( "faerie fire", { - NextAction("faerie fire", ACTION_HIGH) + CreateNextAction(ACTION_HIGH) } ) ); diff --git a/src/Ai/Class/Druid/Strategy/CatDpsDruidStrategy.cpp b/src/Ai/Class/Druid/Strategy/CatDpsDruidStrategy.cpp index fda1b5f94f..bbbb02c02f 100644 --- a/src/Ai/Class/Druid/Strategy/CatDpsDruidStrategy.cpp +++ b/src/Ai/Class/Druid/Strategy/CatDpsDruidStrategy.cpp @@ -6,6 +6,13 @@ #include "CatDpsDruidStrategy.h" #include "AiObjectContext.h" +#include "ActionNode.h" +#include "CreateNextAction.h" +#include "DruidActions.h" +#include "DruidShapeshiftActions.h" +#include "DruidCatActions.h" +#include "GenericActions.h" +#include "MovementActions.h" class CatDpsDruidStrategyActionNodeFactory : public NamedObjectFactory { @@ -29,7 +36,6 @@ class CatDpsDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -49,9 +54,8 @@ class CatDpsDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -59,9 +63,8 @@ class CatDpsDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } @@ -69,9 +72,8 @@ class CatDpsDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -79,7 +81,6 @@ class CatDpsDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -109,7 +108,6 @@ class CatDpsDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -129,9 +126,8 @@ class CatDpsDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -145,7 +141,7 @@ CatDpsDruidStrategy::CatDpsDruidStrategy(PlayerbotAI* botAI) : FeralDruidStrateg std::vector CatDpsDruidStrategy::getDefaultActions() { return { - NextAction("tiger's fury", ACTION_DEFAULT + 0.1f) + CreateNextAction(ACTION_DEFAULT + 0.1f) }; } @@ -158,7 +154,7 @@ void CatDpsDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "almost full energy available", { - NextAction("shred", ACTION_DEFAULT + 0.4f) + CreateNextAction(ACTION_DEFAULT + 0.4f) } ) ); @@ -166,7 +162,7 @@ void CatDpsDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "combo points not full", { - NextAction("shred", ACTION_DEFAULT + 0.4f) + CreateNextAction(ACTION_DEFAULT + 0.4f) } ) ); @@ -174,7 +170,7 @@ void CatDpsDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "almost full energy available", { - NextAction("mangle (cat)", ACTION_DEFAULT + 0.3f) + CreateNextAction(ACTION_DEFAULT + 0.3f) } ) ); @@ -182,7 +178,7 @@ void CatDpsDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "combo points not full and high energy", { - NextAction("mangle (cat)", ACTION_DEFAULT + 0.3f) + CreateNextAction(ACTION_DEFAULT + 0.3f) } ) ); @@ -190,7 +186,7 @@ void CatDpsDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "almost full energy available", { - NextAction("claw", ACTION_DEFAULT + 0.2f) + CreateNextAction(ACTION_DEFAULT + 0.2f) } ) ); @@ -198,7 +194,7 @@ void CatDpsDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "combo points not full and high energy", { - NextAction("claw", ACTION_DEFAULT + 0.2f) + CreateNextAction(ACTION_DEFAULT + 0.2f) } ) ); @@ -206,7 +202,7 @@ void CatDpsDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "faerie fire (feral)", { - NextAction("faerie fire (feral)", ACTION_DEFAULT + 0.0f) + CreateNextAction(ACTION_DEFAULT) } ) ); @@ -215,14 +211,14 @@ void CatDpsDruidStrategy::InitTriggers(std::vector& triggers) triggers.push_back( new TriggerNode( "cat form", { - NextAction("cat form", ACTION_HIGH + 8) + CreateNextAction(ACTION_HIGH + 8.0f) } ) ); triggers.push_back( new TriggerNode( "savage roar", { - NextAction("savage roar", ACTION_HIGH + 7) + CreateNextAction(ACTION_HIGH + 7.0f) } ) ); @@ -230,7 +226,7 @@ void CatDpsDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "combo points available", { - NextAction("rip", ACTION_HIGH + 6) + CreateNextAction(ACTION_HIGH + 6.0f) } ) ); @@ -238,7 +234,7 @@ void CatDpsDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "ferocious bite time", { - NextAction("ferocious bite", ACTION_HIGH + 5) + CreateNextAction(ACTION_HIGH + 5.0f) } ) ); @@ -246,7 +242,7 @@ void CatDpsDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "target with combo points almost dead", { - NextAction("ferocious bite", ACTION_HIGH + 4) + CreateNextAction(ACTION_HIGH + 4.0f) } ) ); @@ -254,7 +250,7 @@ void CatDpsDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "mangle (cat)", { - NextAction("mangle (cat)", ACTION_HIGH + 3) + CreateNextAction(ACTION_HIGH + 3.0f) } ) ); @@ -262,7 +258,7 @@ void CatDpsDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "rake", { - NextAction("rake", ACTION_HIGH + 2) + CreateNextAction(ACTION_HIGH + 2.0f) } ) ); @@ -270,7 +266,7 @@ void CatDpsDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "medium threat", { - NextAction("cower", ACTION_HIGH + 1) + CreateNextAction(ACTION_HIGH + 1.0f) } ) ); @@ -280,7 +276,7 @@ void CatDpsDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "medium aoe", { - NextAction("swipe (cat)", ACTION_HIGH + 3) + CreateNextAction(ACTION_HIGH + 3.0f) } ) ); @@ -288,7 +284,7 @@ void CatDpsDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "light aoe", { - NextAction("rake on attacker", ACTION_HIGH + 2) + CreateNextAction(ACTION_HIGH + 2.0f) } ) ); @@ -297,7 +293,7 @@ void CatDpsDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "enemy out of melee", { - NextAction("feral charge - cat", ACTION_HIGH + 9) + CreateNextAction(ACTION_HIGH + 9.0f) } ) ); @@ -305,10 +301,10 @@ void CatDpsDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "enemy out of melee", { - NextAction("dash", ACTION_HIGH + 8) + CreateNextAction(ACTION_HIGH + 8.0f) } ) ); } -void CatAoeDruidStrategy::InitTriggers(std::vector& triggers) {} +void CatAoeDruidStrategy::InitTriggers(std::vector&) {} diff --git a/src/Ai/Class/Druid/Strategy/FeralDruidStrategy.cpp b/src/Ai/Class/Druid/Strategy/FeralDruidStrategy.cpp index 894c05bff6..2c89a1d3a7 100644 --- a/src/Ai/Class/Druid/Strategy/FeralDruidStrategy.cpp +++ b/src/Ai/Class/Druid/Strategy/FeralDruidStrategy.cpp @@ -4,8 +4,11 @@ */ #include "FeralDruidStrategy.h" - -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "DruidActions.h" +#include "DruidCatActions.h" +#include "DruidShapeshiftActions.h" +#include "ReachTargetActions.h" class FeralDruidStrategyActionNodeFactory : public NamedObjectFactory { @@ -25,66 +28,74 @@ class FeralDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, + /*C*/ {} + ); } static ActionNode* thorns([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("thorns", - /*P*/ { NextAction("caster form") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* omen_of_clarity([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("omen of clarity", - /*P*/ { NextAction("caster form") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* cure_poison([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("cure poison", - /*P*/ { NextAction("caster form") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* cure_poison_on_party([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("cure poison on party", - /*P*/ { NextAction("caster form") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* abolish_poison([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("abolish poison", - /*P*/ { NextAction("caster form") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* abolish_poison_on_party([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("abolish poison on party", - /*P*/ { NextAction("caster form") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* prowl([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("prowl", - /*P*/ { NextAction("cat form") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } }; @@ -98,16 +109,52 @@ void FeralDruidStrategy::InitTriggers(std::vector& triggers) { GenericDruidStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode( - "enemy out of melee", { NextAction("reach melee", ACTION_HIGH + 1) })); - triggers.push_back(new TriggerNode( - "critical health", { NextAction("survival instincts", ACTION_EMERGENCY + 1) })); - triggers.push_back(new TriggerNode( - "omen of clarity", { NextAction("omen of clarity", ACTION_HIGH + 9) })); - triggers.push_back(new TriggerNode("player has flag", - { NextAction("dash", ACTION_EMERGENCY + 2) })); - triggers.push_back(new TriggerNode("enemy flagcarrier near", - { NextAction("dash", ACTION_EMERGENCY + 2) })); triggers.push_back( - new TriggerNode("berserk", { NextAction("berserk", ACTION_HIGH + 6) })); + new TriggerNode( + "enemy out of melee", + { + CreateNextAction(ACTION_HIGH + 1.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "critical health", + { + CreateNextAction(ACTION_EMERGENCY + 1.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "omen of clarity", + { + CreateNextAction(ACTION_HIGH + 9.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "player has flag", + { + CreateNextAction(ACTION_EMERGENCY + 2.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "enemy flagcarrier near", + { + CreateNextAction(ACTION_EMERGENCY + 2.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "berserk", + { + CreateNextAction(ACTION_HIGH + 6.0f) + } + ) + ); } diff --git a/src/Ai/Class/Druid/Strategy/FeralDruidStrategy.h b/src/Ai/Class/Druid/Strategy/FeralDruidStrategy.h index abf01c694c..f7dc6b89be 100644 --- a/src/Ai/Class/Druid/Strategy/FeralDruidStrategy.h +++ b/src/Ai/Class/Druid/Strategy/FeralDruidStrategy.h @@ -6,6 +6,9 @@ #ifndef _PLAYERBOT_FERALRUIDSTRATEGY_H #define _PLAYERBOT_FERALRUIDSTRATEGY_H +#include "DruidActions.h" +#include "DruidShapeshiftActions.h" +#include "GenericActions.h" #include "GenericDruidStrategy.h" class PlayerbotAI; @@ -26,50 +29,56 @@ class ShapeshiftDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ { CreateNextAction(10.0f) } + ); } static ActionNode* rejuvenation([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("rejuvenation", - /*P*/ { NextAction("caster form") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* healing_touch([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("healing touch", - /*P*/ { NextAction("caster form") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* regrowth_on_party([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("regrowth on party", - /*P*/ { NextAction("caster form") }, - /*A*/ { NextAction("healing touch on party") }, - /*C*/ { NextAction("melee", 10.0f) }); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ { CreateNextAction(10.0f) } + ); } static ActionNode* rejuvenation_on_party([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("rejuvenation on party", - /*P*/ { NextAction("caster form") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* healing_touch_on_party([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("healing touch on party", - /*P*/ { NextAction("caster form") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } }; diff --git a/src/Ai/Class/Druid/Strategy/GenericDruidNonCombatStrategy.cpp b/src/Ai/Class/Druid/Strategy/GenericDruidNonCombatStrategy.cpp index 7d1a5f7ca1..4e943b325e 100644 --- a/src/Ai/Class/Druid/Strategy/GenericDruidNonCombatStrategy.cpp +++ b/src/Ai/Class/Druid/Strategy/GenericDruidNonCombatStrategy.cpp @@ -5,8 +5,12 @@ #include "GenericDruidNonCombatStrategy.h" -#include "Playerbots.h" #include "AiFactory.h" +#include "CreateNextAction.h" +#include "DruidActions.h" +#include "DruidShapeshiftActions.h" +#include "GenericActions.h" +#include "ImbueAction.h" class GenericDruidNonCombatStrategyActionNodeFactory : public NamedObjectFactory { @@ -28,69 +32,78 @@ class GenericDruidNonCombatStrategyActionNodeFactory : public NamedObjectFactory private: static ActionNode* thorns([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("thorns", - /*P*/ { NextAction("caster form") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* thorns_on_party([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("thorns on party", - /*P*/ { NextAction("caster form") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* mark_of_the_wild([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("mark of the wild", - /*P*/ { NextAction("caster form") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* mark_of_the_wild_on_party([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("mark of the wild on party", - /*P*/ { NextAction("caster form") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* regrowth_on_party([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("regrowth on party", - /*P*/ { NextAction("caster form") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* rejuvenation_on_party([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("rejuvenation on party", - /*P*/ { NextAction("caster form") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* remove_curse_on_party([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("remove curse on party", - /*P*/ { NextAction("caster form") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* abolish_poison_on_party([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("abolish poison on party", - /*P*/ { NextAction("caster form") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* revive([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("revive", - /*P*/ { NextAction("caster form") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } }; @@ -103,73 +116,146 @@ void GenericDruidNonCombatStrategy::InitTriggers(std::vector& trig { NonCombatStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("mark of the wild", { NextAction("mark of the wild", 14.0f) })); - triggers.push_back(new TriggerNode("party member cure poison", { NextAction("abolish poison on party", 20.0f) })); - triggers.push_back(new TriggerNode("party member dead", { NextAction("revive", ACTION_CRITICAL_HEAL + 10) })); - - triggers.push_back(new TriggerNode("often", { NextAction("apply oil", 1.0f) })); - triggers.push_back( - new TriggerNode("party member critical health", - { - NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 7), - NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 6), - NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 5), - })); - + new TriggerNode( + "mark of the wild", + { + CreateNextAction(14.0f) + } + ) + ); triggers.push_back( - new TriggerNode("party member low health", - { - NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 5), - NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 4), - NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 3), - })); - + new TriggerNode( + "party member cure poison", + { + CreateNextAction(20.0f) + } + ) + ); triggers.push_back( - new TriggerNode("party member medium health", - { NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 3), - NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 2), - NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 1), - })); - + new TriggerNode( + "party member dead", + { + CreateNextAction(ACTION_CRITICAL_HEAL + 10.0f) + } + ) + ); triggers.push_back( - new TriggerNode("party member almost full health", - { NextAction("wild growth on party", ACTION_LIGHT_HEAL + 3), NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 2) })); - + new TriggerNode( + "often", + { + CreateNextAction(1.0f) + } + ) + ); triggers.push_back( - new TriggerNode("party member remove curse", - { NextAction("remove curse on party", ACTION_DISPEL + 7) })); + new TriggerNode( + "party member critical health", + { + CreateNextAction(ACTION_MEDIUM_HEAL + 7.0f), + CreateNextAction(ACTION_MEDIUM_HEAL + 6.0f), + CreateNextAction(ACTION_MEDIUM_HEAL + 5.0f), + } + ) + ); triggers.push_back( - new TriggerNode("new pet", { NextAction("set pet stance", 60.0f) })); - - triggers.push_back(new TriggerNode("party member critical health", { - NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 7), - NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 6), - NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 5), - })); - triggers.push_back(new TriggerNode("party member low health", { - NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 5), - NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 4), - NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 3), - })); - triggers.push_back(new TriggerNode("party member medium health", { - NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 3), - NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 2), - NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 1), - })); - triggers.push_back(new TriggerNode("party member almost full health", { - NextAction("wild growth on party", ACTION_LIGHT_HEAL + 3), - NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 2), - })); - triggers.push_back(new TriggerNode("party member remove curse", { - NextAction("remove curse on party", ACTION_DISPEL + 7), - })); + new TriggerNode( + "party member low health", + { + CreateNextAction(ACTION_MEDIUM_HEAL + 5.0f), + CreateNextAction(ACTION_MEDIUM_HEAL + 4.0f), + CreateNextAction(ACTION_MEDIUM_HEAL + 3.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member medium health", + { + CreateNextAction(ACTION_MEDIUM_HEAL + 3.0f), + CreateNextAction(ACTION_MEDIUM_HEAL + 2.0f), + CreateNextAction(ACTION_MEDIUM_HEAL + 1.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member almost full health", + { + CreateNextAction(ACTION_LIGHT_HEAL + 3.0f), + CreateNextAction(ACTION_LIGHT_HEAL + 2.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member remove curse", + { + CreateNextAction(ACTION_DISPEL + 7.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "new pet", + { + CreateNextAction(60.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member critical health", + { + CreateNextAction(ACTION_MEDIUM_HEAL + 7.0f), + CreateNextAction(ACTION_MEDIUM_HEAL + 6.0f), + CreateNextAction(ACTION_MEDIUM_HEAL + 5.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member low health", + { + CreateNextAction(ACTION_MEDIUM_HEAL + 5.0f), + CreateNextAction(ACTION_MEDIUM_HEAL + 4.0f), + CreateNextAction(ACTION_MEDIUM_HEAL + 3.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member medium health", + { + CreateNextAction(ACTION_MEDIUM_HEAL + 3.0f), + CreateNextAction(ACTION_MEDIUM_HEAL + 2.0f), + CreateNextAction(ACTION_MEDIUM_HEAL + 1.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member almost full health", + { + CreateNextAction(ACTION_LIGHT_HEAL + 3.0f), + CreateNextAction(ACTION_LIGHT_HEAL + 2.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member remove curse", + { + CreateNextAction(ACTION_DISPEL + 7.0f), + } + ) + ); int specTab = AiFactory::GetPlayerSpecTab(botAI->GetBot()); if (specTab == 0 || specTab == 2) // Balance or Restoration - triggers.push_back(new TriggerNode("often", { NextAction("apply oil", 1.0f) })); + triggers.push_back(new TriggerNode("often", { CreateNextAction(1.0f) })); if (specTab == 1) // Feral - triggers.push_back(new TriggerNode("often", { NextAction("apply stone", 1.0f) })); + triggers.push_back(new TriggerNode("often", { CreateNextAction(1.0f) })); } @@ -182,13 +268,28 @@ void GenericDruidBuffStrategy::InitTriggers(std::vector& triggers) { NonCombatStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("mark of the wild on party", { - NextAction("mark of the wild on party", 13.0f), - })); - triggers.push_back(new TriggerNode("thorns on main tank", { - NextAction("thorns on main tank", 11.0f), - })); - triggers.push_back(new TriggerNode("thorns", { - NextAction("thorns", 10.0f), - })); + triggers.push_back( + new TriggerNode( + "mark of the wild on party", + { + CreateNextAction(13.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "thorns on main tank", + { + CreateNextAction(11.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "thorns", + { + CreateNextAction(10.0f), + } + ) + ); } diff --git a/src/Ai/Class/Druid/Strategy/GenericDruidStrategy.cpp b/src/Ai/Class/Druid/Strategy/GenericDruidStrategy.cpp index d5ac8fcea5..8e66df2daf 100644 --- a/src/Ai/Class/Druid/Strategy/GenericDruidStrategy.cpp +++ b/src/Ai/Class/Druid/Strategy/GenericDruidStrategy.cpp @@ -5,7 +5,10 @@ #include "GenericDruidStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "DruidActions.h" +#include "DruidShapeshiftActions.h" +#include "GenericActions.h" class GenericDruidStrategyActionNodeFactory : public NamedObjectFactory { @@ -26,74 +29,83 @@ class GenericDruidStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* innervate([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("innervate", - /*P*/ {}, - /*A*/ { NextAction("mana potion") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } }; @@ -107,52 +119,110 @@ void GenericDruidStrategy::InitTriggers(std::vector& triggers) CombatStrategy::InitTriggers(triggers); triggers.push_back( - new TriggerNode("low health", { NextAction("barkskin", ACTION_HIGH + 7) })); - - triggers.push_back(new TriggerNode("combat party member dead", - { NextAction("rebirth", ACTION_HIGH + 9) })); - triggers.push_back(new TriggerNode("being attacked", - { NextAction("nature's grasp", ACTION_HIGH + 1) })); - triggers.push_back(new TriggerNode("new pet", { NextAction("set pet stance", 60.0f) })); + new TriggerNode( + "low health", + { + CreateNextAction(ACTION_HIGH + 7.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "combat party member dead", + { + CreateNextAction(ACTION_HIGH + 9.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "being attacked", + { + CreateNextAction(ACTION_HIGH + 1.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "new pet", + { + CreateNextAction(60.0f) + } + ) + ); } void DruidCureStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("party member cure poison", - { NextAction("abolish poison on party", ACTION_DISPEL + 1) })); - + new TriggerNode( + "party member cure poison", + { + CreateNextAction(ACTION_DISPEL + 1.0f) + } + ) + ); triggers.push_back( - new TriggerNode("party member remove curse", - { NextAction("remove curse on party", ACTION_DISPEL + 7) })); - + new TriggerNode( + "party member remove curse", + { + CreateNextAction(ACTION_DISPEL + 7.0f) + } + ) + ); } void DruidBoostStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode( - "nature's swiftness", { NextAction("nature's swiftness", ACTION_HIGH + 9) })); + triggers.push_back( + new TriggerNode( + "nature's swiftness", + { + CreateNextAction(ACTION_HIGH + 9.0f) + } + ) + ); } void DruidCcStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode( - "entangling roots", { NextAction("entangling roots on cc", ACTION_HIGH + 2) })); - triggers.push_back(new TriggerNode( - "entangling roots kite", { NextAction("entangling roots", ACTION_HIGH + 2) })); - triggers.push_back(new TriggerNode( - "hibernate", { NextAction("hibernate on cc", ACTION_HIGH + 3) })); + triggers.push_back( + new TriggerNode( + "entangling roots", + { + CreateNextAction(ACTION_HIGH + 2.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "entangling roots kite", + { + CreateNextAction(ACTION_HIGH + 2.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "hibernate", + { + CreateNextAction(ACTION_HIGH + 3.0f) + } + ) + ); } void DruidHealerDpsStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("healer should attack", - { - NextAction("cancel tree form", ACTION_DEFAULT + 0.3f), - NextAction("moonfire", ACTION_DEFAULT + 0.2f), - NextAction("wrath", ACTION_DEFAULT + 0.1f), - NextAction("starfire", ACTION_DEFAULT), -})); - + new TriggerNode( + "healer should attack", + { + CreateNextAction(ACTION_DEFAULT + 0.3f), + CreateNextAction(ACTION_DEFAULT + 0.2f), + CreateNextAction(ACTION_DEFAULT + 0.1f), + CreateNextAction(ACTION_DEFAULT), + } + ) + ); } diff --git a/src/Ai/Class/Druid/Strategy/HealDruidStrategy.cpp b/src/Ai/Class/Druid/Strategy/HealDruidStrategy.cpp index 5d2c4ce34c..5789af68b1 100644 --- a/src/Ai/Class/Druid/Strategy/HealDruidStrategy.cpp +++ b/src/Ai/Class/Druid/Strategy/HealDruidStrategy.cpp @@ -4,8 +4,10 @@ */ #include "HealDruidStrategy.h" - -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "DruidActions.h" +#include "DruidShapeshiftActions.h" +#include "MovementActions.h" class HealDruidStrategyActionNodeFactory : public NamedObjectFactory { @@ -17,10 +19,11 @@ class HealDruidStrategyActionNodeFactory : public NamedObjectFactory private: static ActionNode* nourtish_on_party([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("nourish on party", - /*P*/ {}, - /*A*/ { NextAction("healing touch on party") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } }; @@ -33,69 +36,111 @@ void HealDruidStrategy::InitTriggers(std::vector& triggers) { GenericDruidStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode( - "party member to heal out of spell range", - { NextAction("reach party member to heal", ACTION_CRITICAL_HEAL + 9) })); + triggers.push_back( + new TriggerNode( + "party member to heal out of spell range", + { + CreateNextAction(ACTION_CRITICAL_HEAL + 9.0f) + } + ) + ); // CRITICAL triggers.push_back( - new TriggerNode("party member critical health", - { - NextAction("tree form", ACTION_CRITICAL_HEAL + 4.1f), - NextAction("swiftmend on party", ACTION_CRITICAL_HEAL + 4), - NextAction("regrowth on party", ACTION_CRITICAL_HEAL + 3), - NextAction("wild growth on party", ACTION_CRITICAL_HEAL + 2), - NextAction("nourish on party", ACTION_CRITICAL_HEAL + 1), - })); - + new TriggerNode( + "party member critical health", + { + CreateNextAction(ACTION_CRITICAL_HEAL + 4.1f), + CreateNextAction(ACTION_CRITICAL_HEAL + 4.0f), + CreateNextAction(ACTION_CRITICAL_HEAL + 3.0f), + CreateNextAction(ACTION_CRITICAL_HEAL + 2.0f), + CreateNextAction(ACTION_CRITICAL_HEAL + 1.0f), + } + ) + ); triggers.push_back( - new TriggerNode("party member critical health", - { NextAction("nature's swiftness", ACTION_CRITICAL_HEAL + 4) })); - - triggers.push_back(new TriggerNode( - "group heal setting", - { - NextAction("tree form", ACTION_MEDIUM_HEAL + 2.3f), - NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 2.2f), - NextAction("rejuvenation on not full", ACTION_MEDIUM_HEAL + 2.1f), - })); - + new TriggerNode( + "party member critical health", + { + CreateNextAction(ACTION_CRITICAL_HEAL + 4.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "group heal setting", + { + CreateNextAction(ACTION_MEDIUM_HEAL + 2.3f), + CreateNextAction(ACTION_MEDIUM_HEAL + 2.2f), + CreateNextAction(ACTION_MEDIUM_HEAL + 2.1f), + } + ) + ); triggers.push_back( - new TriggerNode("medium group heal setting", - { - NextAction("tree form", ACTION_CRITICAL_HEAL + 0.6f), - NextAction("tranquility", ACTION_CRITICAL_HEAL + 0.5f) })); + new TriggerNode( + "medium group heal setting", + { + CreateNextAction(ACTION_CRITICAL_HEAL + 0.6f), + CreateNextAction(ACTION_CRITICAL_HEAL + 0.5f) + } + ) + ); // LOW triggers.push_back( - new TriggerNode("party member low health", - { NextAction("tree form", ACTION_MEDIUM_HEAL + 1.5f), - NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 1.4f), - NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 1.3f), - NextAction("swiftmend on party", ACTION_MEDIUM_HEAL + 1.2), - NextAction("nourish on party", ACTION_MEDIUM_HEAL + 1.1f), - })); + new TriggerNode( + "party member low health", + { + CreateNextAction(ACTION_MEDIUM_HEAL + 1.5f), + CreateNextAction(ACTION_MEDIUM_HEAL + 1.4f), + CreateNextAction(ACTION_MEDIUM_HEAL + 1.3f), + CreateNextAction(ACTION_MEDIUM_HEAL + 1.2f), + CreateNextAction(ACTION_MEDIUM_HEAL + 1.1f), + } + ) + ); // MEDIUM triggers.push_back( - new TriggerNode("party member medium health", - { - NextAction("tree form", ACTION_MEDIUM_HEAL + 0.5f), - NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 0.4f), - NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 0.3f), - NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 0.2f), - NextAction("nourish on party", ACTION_MEDIUM_HEAL + 0.1f) })); + new TriggerNode( + "party member medium health", + { + CreateNextAction(ACTION_MEDIUM_HEAL + 0.5f), + CreateNextAction(ACTION_MEDIUM_HEAL + 0.4f), + CreateNextAction(ACTION_MEDIUM_HEAL + 0.3f), + CreateNextAction(ACTION_MEDIUM_HEAL + 0.2f), + CreateNextAction(ACTION_MEDIUM_HEAL + 0.1f) + } + ) + ); // almost full triggers.push_back( - new TriggerNode("party member almost full health", - { NextAction("wild growth on party", ACTION_LIGHT_HEAL + 0.3f), - NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 0.2f), - NextAction("regrowth on party", ACTION_LIGHT_HEAL + 0.1f) })); + new TriggerNode( + "party member almost full health", + { + CreateNextAction(ACTION_LIGHT_HEAL + 0.3f), + CreateNextAction(ACTION_LIGHT_HEAL + 0.2f), + CreateNextAction(ACTION_LIGHT_HEAL + 0.1f) + } + ) + ); triggers.push_back( - new TriggerNode("medium mana", { NextAction("innervate", ACTION_HIGH + 5) })); + new TriggerNode( + "medium mana", + { + CreateNextAction(ACTION_HIGH + 5.0f) + } + ) + ); - triggers.push_back(new TriggerNode("enemy too close for spell", - { NextAction("flee", ACTION_MOVE + 9) })); + triggers.push_back( + new TriggerNode( + "enemy too close for spell", + { + CreateNextAction(ACTION_MOVE + 9.0f) + } + ) + ); } diff --git a/src/Ai/Class/Druid/Strategy/MeleeDruidStrategy.cpp b/src/Ai/Class/Druid/Strategy/MeleeDruidStrategy.cpp index 5dc0f85d91..6470ad0649 100644 --- a/src/Ai/Class/Druid/Strategy/MeleeDruidStrategy.cpp +++ b/src/Ai/Class/Druid/Strategy/MeleeDruidStrategy.cpp @@ -4,16 +4,17 @@ */ #include "MeleeDruidStrategy.h" - -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "DruidActions.h" +#include "GenericActions.h" MeleeDruidStrategy::MeleeDruidStrategy(PlayerbotAI* botAI) : CombatStrategy(botAI) {} std::vector MeleeDruidStrategy::getDefaultActions() { return { - NextAction("faerie fire", ACTION_DEFAULT + 0.1f), - NextAction("melee", ACTION_DEFAULT) + CreateNextAction(ACTION_DEFAULT + 0.1f), + CreateNextAction(ACTION_DEFAULT) }; } @@ -23,7 +24,7 @@ void MeleeDruidStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "omen of clarity", { - NextAction("omen of clarity", ACTION_HIGH + 9) + CreateNextAction(ACTION_HIGH + 9) } ) ); diff --git a/src/Ai/Class/Druid/Strategy/OffhealDruidCatStrategy.cpp b/src/Ai/Class/Druid/Strategy/OffhealDruidCatStrategy.cpp index c472ce8d86..fc2789dcfb 100644 --- a/src/Ai/Class/Druid/Strategy/OffhealDruidCatStrategy.cpp +++ b/src/Ai/Class/Druid/Strategy/OffhealDruidCatStrategy.cpp @@ -5,7 +5,11 @@ #include "OffhealDruidCatStrategy.h" - #include "Playerbots.h" +#include "CreateNextAction.h" +#include "DruidActions.h" +#include "DruidCatActions.h" +#include "DruidShapeshiftActions.h" +#include "GenericActions.h" #include "Strategy.h" class OffhealDruidCatStrategyActionNodeFactory : public NamedObjectFactory @@ -30,7 +34,6 @@ static ActionNode* cat_form([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "cat form", /*P*/ {}, /*A*/ {}, /*C*/ {} @@ -40,7 +43,6 @@ static ActionNode* mangle_cat([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "mangle (cat)", /*P*/ {}, /*A*/ {}, /*C*/ {} @@ -50,9 +52,8 @@ static ActionNode* shred([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "shred", /*P*/ {}, - /*A*/ { NextAction("claw") }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } @@ -60,7 +61,6 @@ static ActionNode* rake([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "rake", /*P*/ {}, /*A*/ {}, /*C*/ {} @@ -70,7 +70,6 @@ static ActionNode* rip([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "rip", /*P*/ {}, /*A*/ {}, /*C*/ {} @@ -80,9 +79,8 @@ static ActionNode* ferocious_bite([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "ferocious bite", /*P*/ {}, - /*A*/ { NextAction("rip") }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } @@ -90,7 +88,6 @@ static ActionNode* savage_roar([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "savage roar", /*P*/ {}, /*A*/ {}, /*C*/ {} @@ -100,7 +97,6 @@ static ActionNode* faerie_fire_feral([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "faerie fire (feral)", /*P*/ {}, /*A*/ {}, /*C*/ {} @@ -110,30 +106,27 @@ static ActionNode* healing_touch_on_party([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "healing touch on party", - /*P*/ { NextAction("caster form") }, + /*P*/ { CreateNextAction(1.0f) }, /*A*/ {}, - /*C*/ { NextAction("cat form") } + /*C*/ { CreateNextAction(1.0f) } ); } static ActionNode* regrowth_on_party([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "regrowth on party", - /*P*/ { NextAction("caster form") }, + /*P*/ { CreateNextAction(1.0f) }, /*A*/ {}, - /*C*/ { NextAction("cat form") } + /*C*/ { CreateNextAction(1.0f) } ); } static ActionNode* rejuvenation_on_party([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "rejuvenation on party", - /*P*/ { NextAction("caster form") }, + /*P*/ { CreateNextAction(1.0f) }, /*A*/ {}, - /*C*/ { NextAction("cat form") } + /*C*/ { CreateNextAction(1.0f) } ); } }; @@ -146,11 +139,11 @@ OffhealDruidCatStrategy::OffhealDruidCatStrategy(PlayerbotAI* botAI) : FeralDrui std::vector OffhealDruidCatStrategy::getDefaultActions() { return { - NextAction("mangle (cat)", ACTION_DEFAULT + 0.5f), - NextAction("shred", ACTION_DEFAULT + 0.4f), - NextAction("rake", ACTION_DEFAULT + 0.3f), - NextAction("melee", ACTION_DEFAULT), - NextAction("cat form", ACTION_DEFAULT - 0.1f) + CreateNextAction(ACTION_DEFAULT + 0.5f), + CreateNextAction(ACTION_DEFAULT + 0.4f), + CreateNextAction(ACTION_DEFAULT + 0.3f), + CreateNextAction(ACTION_DEFAULT), + CreateNextAction(ACTION_DEFAULT - 0.1f) }; } @@ -162,7 +155,7 @@ void OffhealDruidCatStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "cat form", { - NextAction("cat form", ACTION_HIGH + 8) + CreateNextAction(ACTION_HIGH + 8.0f) } ) ); @@ -170,7 +163,7 @@ void OffhealDruidCatStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "savage roar", { - NextAction("savage roar", ACTION_HIGH + 7) + CreateNextAction(ACTION_HIGH + 7.0f) } ) ); @@ -178,7 +171,7 @@ void OffhealDruidCatStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "combo points available", { - NextAction("rip", ACTION_HIGH + 6) + CreateNextAction(ACTION_HIGH + 6.0f) } ) ); @@ -186,7 +179,7 @@ void OffhealDruidCatStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "ferocious bite time", { - NextAction("ferocious bite", ACTION_HIGH + 5) + CreateNextAction(ACTION_HIGH + 5.0f) } ) ); @@ -194,7 +187,7 @@ void OffhealDruidCatStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "target with combo points almost dead", { - NextAction("ferocious bite", ACTION_HIGH + 4) + CreateNextAction(ACTION_HIGH + 4.0f) } ) ); @@ -202,7 +195,7 @@ void OffhealDruidCatStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "mangle (cat)", { - NextAction("mangle (cat)", ACTION_HIGH + 3) + CreateNextAction(ACTION_HIGH + 3.0f) } ) ); @@ -210,7 +203,7 @@ void OffhealDruidCatStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "rake", { - NextAction("rake", ACTION_HIGH + 2) + CreateNextAction(ACTION_HIGH + 2.0f) } ) ); @@ -218,7 +211,7 @@ void OffhealDruidCatStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "almost full energy available", { - NextAction("shred", ACTION_DEFAULT + 0.4f) + CreateNextAction(ACTION_DEFAULT + 0.4f) } ) ); @@ -226,7 +219,7 @@ void OffhealDruidCatStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "combo points not full", { - NextAction("shred", ACTION_DEFAULT + 0.4f) + CreateNextAction(ACTION_DEFAULT + 0.4f) } ) ); @@ -234,7 +227,7 @@ void OffhealDruidCatStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "faerie fire (feral)", { - NextAction("faerie fire (feral)", ACTION_NORMAL) + CreateNextAction(ACTION_NORMAL) } ) ); @@ -242,8 +235,8 @@ void OffhealDruidCatStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "enemy out of melee", { - NextAction("feral charge - cat", ACTION_HIGH + 9), - NextAction("dash", ACTION_HIGH + 8) + CreateNextAction(ACTION_HIGH + 9.0f), + CreateNextAction(ACTION_HIGH + 8) } ) ); @@ -251,7 +244,7 @@ void OffhealDruidCatStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "medium aoe", { - NextAction("swipe (cat)", ACTION_HIGH + 3) + CreateNextAction(ACTION_HIGH + 3.0f) } ) ); @@ -259,7 +252,7 @@ void OffhealDruidCatStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "low energy", { - NextAction("tiger's fury", ACTION_NORMAL + 1) + CreateNextAction(ACTION_NORMAL + 1.0f) } ) ); @@ -267,8 +260,8 @@ void OffhealDruidCatStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "party member critical health", { - NextAction("regrowth on party", ACTION_CRITICAL_HEAL + 6), - NextAction("healing touch on party", ACTION_CRITICAL_HEAL + 5) + CreateNextAction(ACTION_CRITICAL_HEAL + 6.0f), + CreateNextAction(ACTION_CRITICAL_HEAL + 5.0f) } ) ); @@ -276,7 +269,7 @@ void OffhealDruidCatStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "party member low health", { - NextAction("healing touch on party", ACTION_MEDIUM_HEAL + 5) + CreateNextAction(ACTION_MEDIUM_HEAL + 5.0f) } ) ); @@ -284,7 +277,7 @@ void OffhealDruidCatStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "party member medium health", { - NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 8) + CreateNextAction(ACTION_LIGHT_HEAL + 8.0f) } ) ); @@ -292,7 +285,7 @@ void OffhealDruidCatStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "party member to heal out of spell range", { - NextAction("reach party member to heal", ACTION_EMERGENCY + 3) + CreateNextAction(ACTION_EMERGENCY + 3.0f) } ) ); @@ -300,7 +293,7 @@ void OffhealDruidCatStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "low mana", { - NextAction("innervate", ACTION_HIGH + 4) + CreateNextAction(ACTION_HIGH + 4.0f) } ) ); diff --git a/src/Ai/Class/Hunter/Action/HunterActions.cpp b/src/Ai/Class/Hunter/Action/HunterActions.cpp index a1588f8537..4cf55629a9 100644 --- a/src/Ai/Class/Hunter/Action/HunterActions.cpp +++ b/src/Ai/Class/Hunter/Action/HunterActions.cpp @@ -59,7 +59,7 @@ bool CastImmolationTrapAction::isUseful() Value* CastFreezingTrap::GetTargetValue() { return context->GetValue("cc target", "freezing trap"); } -bool FeedPetAction::Execute(Event event) +bool FeedPetAction::Execute(Event) { if (Pet* pet = bot->GetPet()) if (pet->getPetType() == HUNTER_PET && pet->GetHappinessState() != HAPPY) @@ -99,7 +99,7 @@ bool CastDisengageAction::isUseful() Value* CastScareBeastCcAction::GetTargetValue() { return context->GetValue("cc target", "scare beast"); } -bool CastScareBeastCcAction::Execute(Event event) { return botAI->CastSpell("scare beast", GetTarget()); } +bool CastScareBeastCcAction::Execute(Event) { return botAI->CastSpell("scare beast", GetTarget()); } bool CastWingClipAction::isUseful() { return CastSpellAction::isUseful() && !botAI->HasAura(spell, GetTarget()); } diff --git a/src/Ai/Class/Hunter/Action/HunterActions.h b/src/Ai/Class/Hunter/Action/HunterActions.h index 8e21135254..d094bb96e0 100644 --- a/src/Ai/Class/Hunter/Action/HunterActions.h +++ b/src/Ai/Class/Hunter/Action/HunterActions.h @@ -9,6 +9,7 @@ #include "AiObject.h" #include "Event.h" #include "GenericSpellActions.h" +#include "SayAction.h" #include "Unit.h" class PlayerbotAI; @@ -352,7 +353,7 @@ class CastExplosiveShotRank4Action : public CastDebuffSpellAction public: CastExplosiveShotRank4Action(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "explosive shot", true, 0.0f) {} - bool Execute(Event event) override { return botAI->CastSpell(60053, GetTarget()); } + bool Execute(Event) override { return botAI->CastSpell(60053, GetTarget()); } bool isUseful() override { Unit* target = GetTarget(); @@ -368,7 +369,7 @@ class CastExplosiveShotRank3Action : public CastDebuffSpellAction public: CastExplosiveShotRank3Action(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "explosive shot", true, 0.0f) {} - bool Execute(Event event) override { return botAI->CastSpell(60052, GetTarget()); } + bool Execute(Event) override { return botAI->CastSpell(60052, GetTarget()); } bool isUseful() override { Unit* target = GetTarget(); @@ -384,7 +385,7 @@ class CastExplosiveShotRank2Action : public CastDebuffSpellAction public: CastExplosiveShotRank2Action(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "explosive shot", true, 0.0f) {} - bool Execute(Event event) override { return botAI->CastSpell(60051, GetTarget()); } + bool Execute(Event) override { return botAI->CastSpell(60051, GetTarget()); } bool isUseful() override { Unit* target = GetTarget(); @@ -400,7 +401,7 @@ class CastExplosiveShotRank1Action : public CastDebuffSpellAction public: CastExplosiveShotRank1Action(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "explosive shot", true, 0.0f) {} - bool Execute(Event event) override { return botAI->CastSpell(53301, GetTarget()); } + bool Execute(Event) override { return botAI->CastSpell(53301, GetTarget()); } bool isUseful() override { Unit* target = GetTarget(); @@ -448,4 +449,19 @@ class CastVolleyAction : public CastSpellAction ActionThreatType getThreatType() override { return ActionThreatType::Aoe; } }; +class SayLowAmmoAction : public SayAction +{ +public: + SayLowAmmoAction(PlayerbotAI* botAI) : SayAction(botAI) + { + this->qualifier = "low ammo"; + } +}; + +class CastTrackHumanoidsAction : public CastBuffSpellAction +{ +public: + CastTrackHumanoidsAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "track humanoids") {}; +}; + #endif diff --git a/src/Ai/Class/Hunter/HunterAiObjectContext.cpp b/src/Ai/Class/Hunter/HunterAiObjectContext.cpp index def1e46939..09f24df2d5 100644 --- a/src/Ai/Class/Hunter/HunterAiObjectContext.cpp +++ b/src/Ai/Class/Hunter/HunterAiObjectContext.cpp @@ -13,7 +13,6 @@ #include "HunterTriggers.h" #include "MarksmanshipHunterStrategy.h" #include "NamedObjectContext.h" -#include "Playerbots.h" #include "SurvivalHunterStrategy.h" class HunterStrategyFactoryInternal : public NamedObjectContext @@ -145,139 +144,19 @@ class HunterTriggerFactoryInternal : public NamedObjectContext static Trigger* volley_channel_check(PlayerbotAI* botAI) { return new VolleyChannelCheckTrigger(botAI); } }; -class HunterAiObjectContextInternal : public NamedObjectContext -{ -public: - HunterAiObjectContextInternal() - { - creators["auto shot"] = &HunterAiObjectContextInternal::auto_shot; - creators["aimed shot"] = &HunterAiObjectContextInternal::aimed_shot; - creators["chimera shot"] = &HunterAiObjectContextInternal::chimera_shot; - creators["explosive shot"] = &HunterAiObjectContextInternal::explosive_shot; - creators["arcane shot"] = &HunterAiObjectContextInternal::arcane_shot; - creators["concussive shot"] = &HunterAiObjectContextInternal::concussive_shot; - creators["distracting shot"] = &HunterAiObjectContextInternal::distracting_shot; - creators["multi-shot"] = &HunterAiObjectContextInternal::multi_shot; - creators["volley"] = &HunterAiObjectContextInternal::volley; - creators["serpent sting"] = &HunterAiObjectContextInternal::serpent_sting; - creators["serpent sting on attacker"] = &HunterAiObjectContextInternal::serpent_sting_on_attacker; - creators["wyvern sting"] = &HunterAiObjectContextInternal::wyvern_sting; - creators["viper sting"] = &HunterAiObjectContextInternal::viper_sting; - creators["scorpid sting"] = &HunterAiObjectContextInternal::scorpid_sting; - creators["hunter's mark"] = &HunterAiObjectContextInternal::hunters_mark; - creators["mend pet"] = &HunterAiObjectContextInternal::mend_pet; - creators["kill command"] = &HunterAiObjectContextInternal::kill_command; - creators["revive pet"] = &HunterAiObjectContextInternal::revive_pet; - creators["call pet"] = &HunterAiObjectContextInternal::call_pet; - creators["black arrow"] = &HunterAiObjectContextInternal::black_arrow; - creators["freezing trap"] = &HunterAiObjectContextInternal::freezing_trap; - creators["rapid fire"] = &HunterAiObjectContextInternal::rapid_fire; - creators["boost"] = &HunterAiObjectContextInternal::rapid_fire; - creators["deterrence"] = &HunterAiObjectContextInternal::deterrence; - creators["readiness"] = &HunterAiObjectContextInternal::readiness; - creators["aspect of the hawk"] = &HunterAiObjectContextInternal::aspect_of_the_hawk; - creators["aspect of the monkey"] = &HunterAiObjectContextInternal::aspect_of_the_monkey; - creators["aspect of the wild"] = &HunterAiObjectContextInternal::aspect_of_the_wild; - creators["aspect of the viper"] = &HunterAiObjectContextInternal::aspect_of_the_viper; - creators["aspect of the pack"] = &HunterAiObjectContextInternal::aspect_of_the_pack; - creators["aspect of the cheetah"] = &HunterAiObjectContextInternal::aspect_of_the_cheetah; - creators["trueshot aura"] = &HunterAiObjectContextInternal::trueshot_aura; - creators["track humanoids"] = &HunterAiObjectContextInternal::track_humanoids; - creators["feign death"] = &HunterAiObjectContextInternal::feign_death; - creators["wing clip"] = &HunterAiObjectContextInternal::wing_clip; - creators["raptor strike"] = &HunterAiObjectContextInternal::raptor_strike; - creators["mongoose bite"] = &HunterAiObjectContextInternal::mongoose_bite; - creators["feed pet"] = &HunterAiObjectContextInternal::feed_pet; - creators["bestial wrath"] = &HunterAiObjectContextInternal::bestial_wrath; - creators["scare beast"] = &HunterAiObjectContextInternal::scare_beast; - creators["scare beast on cc"] = &HunterAiObjectContextInternal::scare_beast_on_cc; - creators["aspect of the dragonhawk"] = &HunterAiObjectContextInternal::aspect_of_the_dragonhawk; - creators["tranquilizing shot"] = &HunterAiObjectContextInternal::tranquilizing_shot; - creators["steady shot"] = &HunterAiObjectContextInternal::steady_shot; - creators["kill shot"] = &HunterAiObjectContextInternal::kill_shot; - creators["misdirection on main tank"] = &HunterAiObjectContextInternal::misdirection_on_main_tank; - creators["silencing shot"] = &HunterAiObjectContextInternal::silencing_shot; - creators["disengage"] = &HunterAiObjectContextInternal::disengage; - creators["immolation trap"] = &HunterAiObjectContextInternal::immolation_trap; - creators["explosive trap"] = &HunterAiObjectContextInternal::explosive_trap; - creators["explosive shot rank 4"] = &HunterAiObjectContextInternal::explosive_shot_rank_4; - creators["explosive shot rank 3"] = &HunterAiObjectContextInternal::explosive_shot_rank_3; - creators["explosive shot rank 2"] = &HunterAiObjectContextInternal::explosive_shot_rank_2; - creators["explosive shot rank 1"] = &HunterAiObjectContextInternal::explosive_shot_rank_1; - creators["intimidation"] = &HunterAiObjectContextInternal::intimidation; - } - -private: - static Action* scare_beast(PlayerbotAI* botAI) { return new CastScareBeastAction(botAI); } - static Action* scare_beast_on_cc(PlayerbotAI* botAI) { return new CastScareBeastCcAction(botAI); } - static Action* bestial_wrath(PlayerbotAI* botAI) { return new CastBestialWrathAction(botAI); } - static Action* feed_pet(PlayerbotAI* botAI) { return new FeedPetAction(botAI); } - static Action* feign_death(PlayerbotAI* botAI) { return new CastFeignDeathAction(botAI); } - static Action* trueshot_aura(PlayerbotAI* botAI) { return new CastTrueshotAuraAction(botAI); } - static Action* track_humanoids(PlayerbotAI* botAI) { return new CastBuffSpellAction(botAI, "track humanoids"); } - static Action* auto_shot(PlayerbotAI* botAI) { return new CastAutoShotAction(botAI); } - static Action* aimed_shot(PlayerbotAI* botAI) { return new CastAimedShotAction(botAI); } - static Action* chimera_shot(PlayerbotAI* botAI) { return new CastChimeraShotAction(botAI); } - static Action* explosive_shot(PlayerbotAI* botAI) { return new CastExplosiveShotAction(botAI); } - static Action* arcane_shot(PlayerbotAI* botAI) { return new CastArcaneShotAction(botAI); } - static Action* concussive_shot(PlayerbotAI* botAI) { return new CastConcussiveShotAction(botAI); } - static Action* distracting_shot(PlayerbotAI* botAI) { return new CastDistractingShotAction(botAI); } - static Action* multi_shot(PlayerbotAI* botAI) { return new CastMultiShotAction(botAI); } - static Action* volley(PlayerbotAI* botAI) { return new CastVolleyAction(botAI); } - static Action* serpent_sting(PlayerbotAI* botAI) { return new CastSerpentStingAction(botAI); } - static Action* serpent_sting_on_attacker(PlayerbotAI* botAI) { return new CastSerpentStingOnAttackerAction(botAI); } - static Action* wyvern_sting(PlayerbotAI* botAI) { return new CastWyvernStingAction(botAI); } - static Action* viper_sting(PlayerbotAI* botAI) { return new CastViperStingAction(botAI); } - static Action* scorpid_sting(PlayerbotAI* botAI) { return new CastScorpidStingAction(botAI); } - static Action* hunters_mark(PlayerbotAI* botAI) { return new CastHuntersMarkAction(botAI); } - static Action* mend_pet(PlayerbotAI* botAI) { return new CastMendPetAction(botAI); } - static Action* kill_command(PlayerbotAI* botAI) { return new CastKillCommandAction(botAI); } - static Action* revive_pet(PlayerbotAI* botAI) { return new CastRevivePetAction(botAI); } - static Action* call_pet(PlayerbotAI* botAI) { return new CastCallPetAction(botAI); } - static Action* black_arrow(PlayerbotAI* botAI) { return new CastBlackArrow(botAI); } - static Action* freezing_trap(PlayerbotAI* botAI) { return new CastFreezingTrap(botAI); } - static Action* rapid_fire(PlayerbotAI* botAI) { return new CastRapidFireAction(botAI); } - static Action* deterrence(PlayerbotAI* botAI) { return new CastDeterrenceAction(botAI); } - static Action* readiness(PlayerbotAI* botAI) { return new CastReadinessAction(botAI); } - static Action* aspect_of_the_hawk(PlayerbotAI* botAI) { return new CastAspectOfTheHawkAction(botAI); } - static Action* aspect_of_the_monkey(PlayerbotAI* botAI) { return new CastAspectOfTheMonkeyAction(botAI); } - static Action* aspect_of_the_wild(PlayerbotAI* botAI) { return new CastAspectOfTheWildAction(botAI); } - static Action* aspect_of_the_viper(PlayerbotAI* botAI) { return new CastAspectOfTheViperAction(botAI); } - static Action* aspect_of_the_pack(PlayerbotAI* botAI) { return new CastAspectOfThePackAction(botAI); } - static Action* aspect_of_the_cheetah(PlayerbotAI* botAI) { return new CastAspectOfTheCheetahAction(botAI); } - static Action* wing_clip(PlayerbotAI* botAI) { return new CastWingClipAction(botAI); } - static Action* raptor_strike(PlayerbotAI* botAI) { return new CastRaptorStrikeAction(botAI); } - static Action* mongoose_bite(PlayerbotAI* botAI) { return new CastMongooseBiteAction(botAI); } - static Action* aspect_of_the_dragonhawk(PlayerbotAI* ai) { return new CastAspectOfTheDragonhawkAction(ai); } - static Action* tranquilizing_shot(PlayerbotAI* ai) { return new CastTranquilizingShotAction(ai); } - static Action* steady_shot(PlayerbotAI* ai) { return new CastSteadyShotAction(ai); } - static Action* kill_shot(PlayerbotAI* ai) { return new CastKillShotAction(ai); } - static Action* misdirection_on_main_tank(PlayerbotAI* ai) { return new CastMisdirectionOnMainTankAction(ai); } - static Action* silencing_shot(PlayerbotAI* ai) { return new CastSilencingShotAction(ai); } - static Action* disengage(PlayerbotAI* ai) { return new CastDisengageAction(ai); } - static Action* immolation_trap(PlayerbotAI* ai) { return new CastImmolationTrapAction(ai); } - static Action* explosive_trap(PlayerbotAI* ai) { return new CastExplosiveTrapAction(ai); } - static Action* explosive_shot_rank_4(PlayerbotAI* ai) { return new CastExplosiveShotRank4Action(ai); } - static Action* explosive_shot_rank_3(PlayerbotAI* ai) { return new CastExplosiveShotRank3Action(ai); } - static Action* explosive_shot_rank_2(PlayerbotAI* ai) { return new CastExplosiveShotRank2Action(ai); } - static Action* explosive_shot_rank_1(PlayerbotAI* ai) { return new CastExplosiveShotRank1Action(ai); } - static Action* intimidation(PlayerbotAI* ai) { return new CastIntimidationAction(ai); } -}; SharedNamedObjectContextList HunterAiObjectContext::sharedStrategyContexts; -SharedNamedObjectContextList HunterAiObjectContext::sharedActionContexts; SharedNamedObjectContextList HunterAiObjectContext::sharedTriggerContexts; SharedNamedObjectContextList HunterAiObjectContext::sharedValueContexts; HunterAiObjectContext::HunterAiObjectContext(PlayerbotAI* botAI) - : AiObjectContext(botAI, sharedStrategyContexts, sharedActionContexts, sharedTriggerContexts, sharedValueContexts) + : AiObjectContext(botAI, sharedStrategyContexts, sharedTriggerContexts, sharedValueContexts) { } void HunterAiObjectContext::BuildSharedContexts() { BuildSharedStrategyContexts(sharedStrategyContexts); - BuildSharedActionContexts(sharedActionContexts); BuildSharedTriggerContexts(sharedTriggerContexts); BuildSharedValueContexts(sharedValueContexts); } @@ -289,12 +168,6 @@ void HunterAiObjectContext::BuildSharedStrategyContexts(SharedNamedObjectContext strategyContexts.Add(new HunterBuffStrategyFactoryInternal()); } -void HunterAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts) -{ - AiObjectContext::BuildSharedActionContexts(actionContexts); - actionContexts.Add(new HunterAiObjectContextInternal()); -} - void HunterAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts) { AiObjectContext::BuildSharedTriggerContexts(triggerContexts); diff --git a/src/Ai/Class/Hunter/HunterAiObjectContext.h b/src/Ai/Class/Hunter/HunterAiObjectContext.h index 27178104a5..2bafae95b3 100644 --- a/src/Ai/Class/Hunter/HunterAiObjectContext.h +++ b/src/Ai/Class/Hunter/HunterAiObjectContext.h @@ -17,12 +17,10 @@ class HunterAiObjectContext : public AiObjectContext static void BuildSharedContexts(); static void BuildSharedStrategyContexts(SharedNamedObjectContextList& strategyContexts); - static void BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts); static void BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts); static void BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts); static SharedNamedObjectContextList sharedStrategyContexts; - static SharedNamedObjectContextList sharedActionContexts; static SharedNamedObjectContextList sharedTriggerContexts; static SharedNamedObjectContextList sharedValueContexts; }; diff --git a/src/Ai/Class/Hunter/Strategy/BeastMasteryHunterStrategy.cpp b/src/Ai/Class/Hunter/Strategy/BeastMasteryHunterStrategy.cpp index a2c302d379..d2704f58ab 100644 --- a/src/Ai/Class/Hunter/Strategy/BeastMasteryHunterStrategy.cpp +++ b/src/Ai/Class/Hunter/Strategy/BeastMasteryHunterStrategy.cpp @@ -4,7 +4,8 @@ */ #include "BeastMasteryHunterStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "HunterActions.h" // ===== Action Node Factory ===== class BeastMasteryHunterStrategyActionNodeFactory : public NamedObjectFactory @@ -25,16 +26,96 @@ class BeastMasteryHunterStrategyActionNodeFactory : public NamedObjectFactory BeastMasteryHunterStrategy::getDefaultActions() { return { - NextAction("bestial wrath", 19.0f), - NextAction("kill command", 5.7f), - NextAction("kill shot", 5.6f), - NextAction("serpent sting", 5.5f), - NextAction("aimed shot", 5.4f), - NextAction("arcane shot", 5.3f), - NextAction("steady shot", 5.2f), - NextAction("auto shot", 5.1f) + CreateNextAction(19.0f), + CreateNextAction(5.7f), + CreateNextAction(5.6f), + CreateNextAction(5.5f), + CreateNextAction(5.4f), + CreateNextAction(5.3f), + CreateNextAction(5.2f), + CreateNextAction(5.1f) }; } @@ -66,7 +147,7 @@ void BeastMasteryHunterStrategy::InitTriggers(std::vector& trigger new TriggerNode( "intimidation", { - NextAction("intimidation", 40.0f) + CreateNextAction(40.0f) } ) ); @@ -74,7 +155,7 @@ void BeastMasteryHunterStrategy::InitTriggers(std::vector& trigger new TriggerNode( "kill command", { - NextAction("kill command", 18.5f) + CreateNextAction(18.5f) } ) ); @@ -82,7 +163,7 @@ void BeastMasteryHunterStrategy::InitTriggers(std::vector& trigger new TriggerNode( "target critical health", { - NextAction("kill shot", 18.0f) + CreateNextAction(18.0f) } ) ); @@ -90,7 +171,7 @@ void BeastMasteryHunterStrategy::InitTriggers(std::vector& trigger new TriggerNode( "low mana", { - NextAction("viper sting", 17.5f) + CreateNextAction(17.5f) } ) ); @@ -98,7 +179,7 @@ void BeastMasteryHunterStrategy::InitTriggers(std::vector& trigger new TriggerNode( "no stings", { - NextAction("serpent sting", 17.0f) + CreateNextAction(17.0f) } ) ); @@ -106,7 +187,7 @@ void BeastMasteryHunterStrategy::InitTriggers(std::vector& trigger new TriggerNode( "serpent sting on attacker", { - NextAction("serpent sting on attacker", 16.5f) + CreateNextAction(16.5f) } ) ); diff --git a/src/Ai/Class/Hunter/Strategy/GenericHunterNonCombatStrategy.cpp b/src/Ai/Class/Hunter/Strategy/GenericHunterNonCombatStrategy.cpp index 151feadf16..90371d2a9b 100644 --- a/src/Ai/Class/Hunter/Strategy/GenericHunterNonCombatStrategy.cpp +++ b/src/Ai/Class/Hunter/Strategy/GenericHunterNonCombatStrategy.cpp @@ -4,8 +4,11 @@ */ #include "GenericHunterNonCombatStrategy.h" - -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "EquipAction.h" +#include "GenericActions.h" +#include "HunterActions.h" +#include "ImbueAction.h" class GenericHunterNonCombatStrategyActionNodeFactory : public NamedObjectFactory { @@ -20,18 +23,20 @@ class GenericHunterNonCombatStrategyActionNodeFactory : public NamedObjectFactor private: static ActionNode* rapid_fire([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("rapid fire", - /*P*/ {}, - /*A*/ { NextAction("readiness")}, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* aspect_of_the_pack([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("aspect of the pack", - /*P*/ {}, - /*A*/ { NextAction("aspect of the cheetah")}, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } }; @@ -44,22 +49,97 @@ void GenericHunterNonCombatStrategy::InitTriggers(std::vector& tri { NonCombatStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("trueshot aura", { NextAction("trueshot aura", 2.0f)})); - triggers.push_back(new TriggerNode("often", { - NextAction("apply stone", 1.0f), - NextAction("apply oil", 1.0f), - })); - triggers.push_back(new TriggerNode("low ammo", { NextAction("say::low ammo", ACTION_NORMAL)})); - triggers.push_back(new TriggerNode("no track", { NextAction("track humanoids", ACTION_NORMAL)})); - triggers.push_back(new TriggerNode("no ammo", { NextAction("equip upgrades", ACTION_HIGH + 1)})); + triggers.push_back( + new TriggerNode( + "trueshot aura", + { + CreateNextAction(2.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "often", + { + CreateNextAction(1.0f), + CreateNextAction(1.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "low ammo", + { + CreateNextAction(ACTION_NORMAL) + } + ) + ); + triggers.push_back( + new TriggerNode( + "no track", + { + CreateNextAction(ACTION_NORMAL) + } + ) + ); + triggers.push_back( + new TriggerNode( + "no ammo", + { + CreateNextAction(ACTION_HIGH + 1.0f) + } + ) + ); } void HunterPetStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("no pet", { NextAction("call pet", 60.0f)})); - triggers.push_back(new TriggerNode("has pet", { NextAction("toggle pet spell", 60.0f)})); - triggers.push_back(new TriggerNode("new pet", { NextAction("set pet stance", 60.0f)})); - triggers.push_back(new TriggerNode("pet not happy", { NextAction("feed pet", 60.0f)})); - triggers.push_back(new TriggerNode("hunters pet medium health", { NextAction("mend pet", 60.0f)})); - triggers.push_back(new TriggerNode("hunters pet dead", { NextAction("revive pet", 60.0f)})); + triggers.push_back( + new TriggerNode( + "no pet", + { + CreateNextAction(60.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "has pet", + { + CreateNextAction(60.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "new pet", + { + CreateNextAction(60.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "pet not happy", + { + CreateNextAction(60.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "hunters pet medium health", + { + CreateNextAction(60.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "hunters pet dead", + { + CreateNextAction(60.0f) + } + ) + ); } diff --git a/src/Ai/Class/Hunter/Strategy/GenericHunterStrategy.cpp b/src/Ai/Class/Hunter/Strategy/GenericHunterStrategy.cpp index 04afc6f766..481c112f6a 100644 --- a/src/Ai/Class/Hunter/Strategy/GenericHunterStrategy.cpp +++ b/src/Ai/Class/Hunter/Strategy/GenericHunterStrategy.cpp @@ -4,9 +4,11 @@ */ #include "GenericHunterStrategy.h" - -#include "Playerbots.h" -#include "Strategy.h" +#include "CancelChannelAction.h" +#include "CreateNextAction.h" +#include "EquipAction.h" +#include "GenericActions.h" +#include "HunterActions.h" class GenericHunterStrategyActionNodeFactory : public NamedObjectFactory { @@ -27,67 +29,74 @@ class GenericHunterStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, + /*C*/ {} + ); } static ActionNode* aspect_of_the_pack([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("aspect of the pack", - /*P*/ {}, - /*A*/ { NextAction("aspect of the cheetah") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* aspect_of_the_dragonhawk([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("aspect of the dragonhawk", - /*P*/ {}, - /*A*/ { NextAction("aspect of the hawk") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* feign_death([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("feign death", - /*P*/ {}, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* wing_clip([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("wing clip", - /*P*/ {}, - // /*A*/ { NextAction("mongoose bite") }, - {}, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + {}, + /*C*/ {} + ); } static ActionNode* mongoose_bite([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("mongoose bite", - /*P*/ {}, - /*A*/ { NextAction("raptor strike") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* raptor_strike([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("raptor strike", - /*P*/ { NextAction("melee") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* explosive_trap([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("explosive trap", - /*P*/ {}, - /*A*/ { NextAction("immolation trap") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } }; @@ -101,34 +110,144 @@ void GenericHunterStrategy::InitTriggers(std::vector& triggers) CombatStrategy::InitTriggers(triggers); // Mark/Ammo/Mana Triggers - triggers.push_back(new TriggerNode("no ammo", { NextAction("equip upgrades", 30.0f) })); - triggers.push_back(new TriggerNode("hunter's mark", { NextAction("hunter's mark", 29.5f) })); - triggers.push_back(new TriggerNode("rapid fire", { NextAction("rapid fire", 29.0f) })); - triggers.push_back(new TriggerNode("aspect of the viper", { NextAction("aspect of the viper", 28.0f) })); - triggers.push_back(new TriggerNode("aspect of the hawk", { NextAction("aspect of the dragonhawk", 27.5f) })); + triggers.push_back( + new TriggerNode( + "no ammo", + { + CreateNextAction(30.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "hunter's mark", + { + CreateNextAction(29.5f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "rapid fire", + { + CreateNextAction(29.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "aspect of the viper", + { + CreateNextAction(28.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "aspect of the hawk", + { + CreateNextAction(27.5f) + } + ) + ); // Aggro/Threat/Defensive Triggers - triggers.push_back(new TriggerNode("has aggro", { NextAction("concussive shot", 20.0f) })); - triggers.push_back(new TriggerNode("low tank threat", { NextAction("misdirection on main tank", 27.0f) })); - triggers.push_back(new TriggerNode("low health", { NextAction("deterrence", 35.0f) })); - triggers.push_back(new TriggerNode("concussive shot on snare target", { NextAction("concussive shot", 20.0f) })); - triggers.push_back(new TriggerNode("medium threat", { NextAction("feign death", 35.0f) })); - triggers.push_back(new TriggerNode("hunters pet medium health", { NextAction("mend pet", 22.0f) })); - triggers.push_back(new TriggerNode("hunters pet low health", { NextAction("mend pet", 21.0f) })); + triggers.push_back( + new TriggerNode( + "has aggro", + { + CreateNextAction(20.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "low tank threat", + { + CreateNextAction(27.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "low health", + { + CreateNextAction(35.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "concussive shot on snare target", + { + CreateNextAction(20.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "medium threat", + { + CreateNextAction(35.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "hunters pet medium health", + { + CreateNextAction(22.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "hunters pet low health", + { + CreateNextAction(21.0f) + } + ) + ); // Dispel Triggers - triggers.push_back(new TriggerNode("tranquilizing shot enrage", { NextAction("tranquilizing shot", 61.0f) })); - triggers.push_back(new TriggerNode("tranquilizing shot magic", { NextAction("tranquilizing shot", 61.0f) })); + triggers.push_back( + new TriggerNode( + "tranquilizing shot enrage", + { + CreateNextAction(61.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "tranquilizing shot magic", + { + CreateNextAction(61.0f) + } + ) + ); // Ranged-based Triggers - triggers.push_back(new TriggerNode("enemy within melee", { - NextAction("explosive trap", 37.0f), - NextAction("mongoose bite", 22.0f), - NextAction("wing clip", 21.0f) })); - - triggers.push_back(new TriggerNode("enemy too close for auto shot", { - NextAction("disengage", 35.0f), - NextAction("flee", 34.0f) })); + triggers.push_back( + new TriggerNode( + "enemy within melee", + { + CreateNextAction(37.0f), + CreateNextAction(22.0f), + CreateNextAction(21.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "enemy too close for auto shot", + { + CreateNextAction(35.0f), + CreateNextAction(34.0f) + } + ) + ); } // ===== AoE Strategy, 2/3+ enemies ===== @@ -136,22 +255,65 @@ AoEHunterStrategy::AoEHunterStrategy(PlayerbotAI* botAI) : CombatStrategy(botAI) void AoEHunterStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("volley channel check", { NextAction("cancel channel", 23.0f) })); - triggers.push_back(new TriggerNode("medium aoe", { NextAction("volley", 22.0f) })); - triggers.push_back(new TriggerNode("light aoe", { NextAction("multi-shot", 21.0f) })); + triggers.push_back( + new TriggerNode( + "volley channel check", + { + CreateNextAction(23.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "medium aoe", + { + CreateNextAction(22.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "light aoe", + { + CreateNextAction(21.0f) + } + ) + ); } -void HunterBoostStrategy::InitTriggers(std::vector& triggers) +void HunterBoostStrategy::InitTriggers(std::vector&) { } void HunterCcStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("scare beast", { NextAction("scare beast on cc", 23.0f) })); - triggers.push_back(new TriggerNode("freezing trap", { NextAction("freezing trap on cc", 23.0f) })); + triggers.push_back( + new TriggerNode( + "scare beast", + { + CreateNextAction(23.0f) + } + ) + ); + // @TODO: This has always been broken because there is no such action. + // triggers.push_back( + // new TriggerNode( + // "freezing trap", + // { + // CreateNextAction("freezing trap on cc", 23.0f) + // } + // ) + // ); } void HunterTrapWeaveStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("immolation trap no cd", { NextAction("reach melee", 23.0f) })); + triggers.push_back( + new TriggerNode( + "immolation trap no cd", + { + CreateNextAction(23.0f) + } + ) + ); } diff --git a/src/Ai/Class/Hunter/Strategy/HunterBuffStrategies.cpp b/src/Ai/Class/Hunter/Strategy/HunterBuffStrategies.cpp index 3601d77119..2b521a274e 100644 --- a/src/Ai/Class/Hunter/Strategy/HunterBuffStrategies.cpp +++ b/src/Ai/Class/Hunter/Strategy/HunterBuffStrategies.cpp @@ -4,21 +4,25 @@ */ #include "HunterBuffStrategies.h" - -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "HunterActions.h" class BuffHunterStrategyActionNodeFactory : public NamedObjectFactory { public: - BuffHunterStrategyActionNodeFactory() { creators["aspect of the hawk"] = &aspect_of_the_hawk; } + BuffHunterStrategyActionNodeFactory() + { + creators["aspect of the hawk"] = &aspect_of_the_hawk; + } private: static ActionNode* aspect_of_the_hawk([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("aspect of the hawk", - /*P*/ {}, - /*A*/ { NextAction("aspect of the monkey") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } }; @@ -30,24 +34,48 @@ HunterBuffDpsStrategy::HunterBuffDpsStrategy(PlayerbotAI* botAI) : NonCombatStra void HunterBuffDpsStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("aspect of the hawk", { NextAction("aspect of the dragonhawk", 20.1f), - NextAction("aspect of the hawk", 20.0f) })); + new TriggerNode( + "aspect of the hawk", + { + CreateNextAction(20.1f), + CreateNextAction(20.0f) + } + ) + ); } void HunterNatureResistanceStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("aspect of the wild", - { NextAction("aspect of the wild", 20.0f) })); + triggers.push_back( + new TriggerNode( + "aspect of the wild", + { + CreateNextAction(20.0f) + } + ) + ); } void HunterBuffSpeedStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("aspect of the pack", - { NextAction("aspect of the pack", 20.0f) })); + triggers.push_back( + new TriggerNode( + "aspect of the pack", + { + CreateNextAction(20.0f) + } + ) + ); } void HunterBuffManaStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("aspect of the viper", - { NextAction("aspect of the viper", 20.0f) })); + triggers.push_back( + new TriggerNode( + "aspect of the viper", + { + CreateNextAction(20.0f) + } + ) + ); } diff --git a/src/Ai/Class/Hunter/Strategy/MarksmanshipHunterStrategy.cpp b/src/Ai/Class/Hunter/Strategy/MarksmanshipHunterStrategy.cpp index e4e8a9a4f4..d7d5bd29b2 100644 --- a/src/Ai/Class/Hunter/Strategy/MarksmanshipHunterStrategy.cpp +++ b/src/Ai/Class/Hunter/Strategy/MarksmanshipHunterStrategy.cpp @@ -4,7 +4,8 @@ */ #include "MarksmanshipHunterStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "HunterActions.h" // ===== Action Node Factory ===== class MarksmanshipHunterStrategyActionNodeFactory : public NamedObjectFactory @@ -27,18 +28,113 @@ class MarksmanshipHunterStrategyActionNodeFactory : public NamedObjectFactory MarksmanshipHunterStrategy::getDefaultActions() { return { - NextAction("kill command", 5.8f), - NextAction("kill shot", 5.7f), - NextAction("serpent sting", 5.6f), - NextAction("chimera shot", 5.5f), - NextAction("aimed shot", 5.4f), - NextAction("arcane shot", 5.3f), - NextAction("steady shot", 5.2f), - NextAction("auto shot", 5.1f) + CreateNextAction(5.8f), + CreateNextAction(5.7f), + CreateNextAction(5.6f), + CreateNextAction(5.5f), + CreateNextAction(5.4f), + CreateNextAction(5.3f), + CreateNextAction(5.2f), + CreateNextAction(5.1f) }; } @@ -71,7 +167,7 @@ void MarksmanshipHunterStrategy::InitTriggers(std::vector& trigger new TriggerNode( "silencing shot", { - NextAction("silencing shot", 40.0f) + CreateNextAction(40.0f) } ) ); @@ -79,7 +175,7 @@ void MarksmanshipHunterStrategy::InitTriggers(std::vector& trigger new TriggerNode( "kill command", { - NextAction("kill command", 18.5f) + CreateNextAction(18.5f) } ) ); @@ -87,7 +183,7 @@ void MarksmanshipHunterStrategy::InitTriggers(std::vector& trigger new TriggerNode( "target critical health", { - NextAction("kill shot", 18.0f) + CreateNextAction(18.0f) } ) ); @@ -95,7 +191,7 @@ void MarksmanshipHunterStrategy::InitTriggers(std::vector& trigger new TriggerNode( "low mana", { - NextAction("viper sting", 17.5f) + CreateNextAction(17.5f) } ) ); @@ -103,7 +199,7 @@ void MarksmanshipHunterStrategy::InitTriggers(std::vector& trigger new TriggerNode( "no stings", { - NextAction("serpent sting", 17.0f) + CreateNextAction(17.0f) } ) ); @@ -111,7 +207,7 @@ void MarksmanshipHunterStrategy::InitTriggers(std::vector& trigger new TriggerNode( "serpent sting on attacker", { - NextAction("serpent sting on attacker", 16.5f) + CreateNextAction(16.5f) } ) ); diff --git a/src/Ai/Class/Hunter/Strategy/SurvivalHunterStrategy.cpp b/src/Ai/Class/Hunter/Strategy/SurvivalHunterStrategy.cpp index 796891a9b0..f7208bbaa7 100644 --- a/src/Ai/Class/Hunter/Strategy/SurvivalHunterStrategy.cpp +++ b/src/Ai/Class/Hunter/Strategy/SurvivalHunterStrategy.cpp @@ -4,7 +4,8 @@ */ #include "SurvivalHunterStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "HunterActions.h" // ===== Action Node Factory ===== class SurvivalHunterStrategyActionNodeFactory : public NamedObjectFactory @@ -27,18 +28,114 @@ class SurvivalHunterStrategyActionNodeFactory : public NamedObjectFactory SurvivalHunterStrategy::getDefaultActions() { return { - NextAction("kill command", 5.9f), - NextAction("kill shot", 5.8f), - NextAction("explosive shot", 5.7f), - NextAction("black arrow", 5.6f), - NextAction("serpent sting", 5.5f), - NextAction("aimed shot", 5.4f), - NextAction("arcane shot", 5.3f), - NextAction("steady shot", 5.2f), - NextAction("auto shot", 5.1f) + CreateNextAction(5.9f), + CreateNextAction(5.8f), + CreateNextAction(5.7f), + CreateNextAction(5.6f), + CreateNextAction(5.5f), + CreateNextAction(5.4f), + CreateNextAction(5.3f), + CreateNextAction(5.2f), + CreateNextAction(5.1f) }; } @@ -72,7 +169,7 @@ void SurvivalHunterStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "lock and load", { - NextAction("explosive shot rank 4", 28.0f) + CreateNextAction(28.0f) } ) ); @@ -80,7 +177,7 @@ void SurvivalHunterStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "lock and load", { - NextAction("explosive shot rank 3", 27.5f) + CreateNextAction(27.5f) } ) ); @@ -88,7 +185,7 @@ void SurvivalHunterStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "lock and load", { - NextAction("explosive shot rank 2", 27.0f) + CreateNextAction(27.0f) } ) ); @@ -96,7 +193,7 @@ void SurvivalHunterStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "lock and load", { - NextAction("explosive shot rank 1", 26.5f) + CreateNextAction(26.5f) } ) ); @@ -104,7 +201,7 @@ void SurvivalHunterStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "kill command", { - NextAction("kill command", 18.5f) + CreateNextAction(18.5f) } ) ); @@ -112,7 +209,7 @@ void SurvivalHunterStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "target critical health", { - NextAction("kill shot", 18.0f) + CreateNextAction(18.0f) } ) ); @@ -120,7 +217,7 @@ void SurvivalHunterStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "explosive shot", { - NextAction("explosive shot", 17.5f) + CreateNextAction(17.5f) } ) ); @@ -128,7 +225,7 @@ void SurvivalHunterStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "black arrow", { - NextAction("black arrow", 16.5f) + CreateNextAction(16.5f) } ) ); @@ -136,7 +233,7 @@ void SurvivalHunterStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "low mana", { - NextAction("viper sting", 16.0f) + CreateNextAction(16.0f) } ) ); @@ -144,7 +241,7 @@ void SurvivalHunterStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "no stings", { - NextAction("serpent sting", 15.5f) + CreateNextAction(15.5f) } ) ); @@ -152,7 +249,7 @@ void SurvivalHunterStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "serpent sting on attacker", { - NextAction("serpent sting on attacker", 15.0f) + CreateNextAction(15.0f) } ) ); diff --git a/src/Ai/Class/Hunter/Trigger/HunterTriggers.cpp b/src/Ai/Class/Hunter/Trigger/HunterTriggers.cpp index 091b8d5f72..84ece04b76 100644 --- a/src/Ai/Class/Hunter/Trigger/HunterTriggers.cpp +++ b/src/Ai/Class/Hunter/Trigger/HunterTriggers.cpp @@ -62,7 +62,7 @@ bool HuntersPetLowHealthTrigger::IsActive() bool HuntersPetMediumHealthTrigger::IsActive() { Unit* pet = AI_VALUE(Unit*, "pet target"); - return pet && AI_VALUE2(uint8, "health", "pet target") < sPlayerbotAIConfig->mediumHealth && + return pet && AI_VALUE2(uint8, "health", "pet target") < sPlayerbotAIConfig.mediumHealth && !AI_VALUE2(bool, "dead", "pet target") && !AI_VALUE2(bool, "mounted", "self target"); } @@ -74,7 +74,7 @@ bool HunterPetNotHappy::IsActive() bool HunterAspectOfTheViperTrigger::IsActive() { return SpellTrigger::IsActive() && !botAI->HasAura(spell, GetTarget()) && - AI_VALUE2(uint8, "mana", "self target") < (sPlayerbotAIConfig->lowMana / 2); + AI_VALUE2(uint8, "mana", "self target") < (sPlayerbotAIConfig.lowMana / 2); ; } @@ -96,7 +96,7 @@ bool SwitchToRangedTrigger::IsActive() Unit* target = AI_VALUE(Unit*, "current target"); return botAI->HasStrategy("close", BOT_STATE_COMBAT) && target && (target->GetVictim() != bot && - sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", "current target"), 8.0f)); + ServerFacade::instance().IsDistanceGreaterThan(AI_VALUE2(float, "distance", "current target"), 8.0f)); } bool SwitchToMeleeTrigger::IsActive() @@ -104,7 +104,7 @@ bool SwitchToMeleeTrigger::IsActive() Unit* target = AI_VALUE(Unit*, "current target"); return botAI->HasStrategy("ranged", BOT_STATE_COMBAT) && target && (target->GetVictim() == bot && - sServerFacade->IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", "current target"), 8.0f)); + ServerFacade::instance().IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", "current target"), 8.0f)); } bool NoTrackTrigger::IsActive() diff --git a/src/Ai/Class/Mage/Action/MageActions.cpp b/src/Ai/Class/Mage/Action/MageActions.cpp index 67587e3213..5eb63ea866 100644 --- a/src/Ai/Class/Mage/Action/MageActions.cpp +++ b/src/Ai/Class/Mage/Action/MageActions.cpp @@ -61,13 +61,13 @@ bool CastFrostNovaAction::isUseful() if (target->isFrozen()) return false; - return sServerFacade->IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", GetTargetName()), 10.f); + return ServerFacade::instance().IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", GetTargetName()), 10.f); } bool CastConeOfColdAction::isUseful() { bool facingTarget = AI_VALUE2(bool, "facing", "current target"); - bool targetClose = sServerFacade->IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", GetTargetName()), 10.f); + bool targetClose = ServerFacade::instance().IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", GetTargetName()), 10.f); return facingTarget && targetClose; } @@ -105,7 +105,7 @@ Unit* CastFocusMagicOnPartyAction::GetTarget() if (!member || member == bot || !member->IsAlive()) continue; - if (member->GetMap() != bot->GetMap() || bot->GetDistance(member) > sPlayerbotAIConfig->spellDistance) + if (member->GetMap() != bot->GetMap() || bot->GetDistance(member) > sPlayerbotAIConfig.spellDistance) continue; if (member->HasAura(54646)) diff --git a/src/Ai/Class/Mage/Action/MageActions.h b/src/Ai/Class/Mage/Action/MageActions.h index 39d1531a70..88d4fcf795 100644 --- a/src/Ai/Class/Mage/Action/MageActions.h +++ b/src/Ai/Class/Mage/Action/MageActions.h @@ -404,4 +404,10 @@ class CastBlastWaveAction : public CastSpellAction bool isUseful() override; }; +class CastArcaneExplosionAction : public CastSpellAction +{ +public: + CastArcaneExplosionAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "arcane explosion") {} +}; + #endif diff --git a/src/Ai/Class/Mage/MageAiObjectContext.cpp b/src/Ai/Class/Mage/MageAiObjectContext.cpp index 477c0e075d..b573332926 100644 --- a/src/Ai/Class/Mage/MageAiObjectContext.cpp +++ b/src/Ai/Class/Mage/MageAiObjectContext.cpp @@ -12,7 +12,6 @@ #include "MageActions.h" #include "MageTriggers.h" #include "NamedObjectContext.h" -#include "Playerbots.h" #include "PullStrategy.h" class MageStrategyFactoryInternal : public NamedObjectContext @@ -175,146 +174,18 @@ class MageTriggerFactoryInternal : public NamedObjectContext static Trigger* enemy_too_close_for_spell_and_no_firestarter_strategy(PlayerbotAI* botAI) { return new EnemyTooCloseForSpellAndNoFirestarterStrategyTrigger(botAI); } }; -class MageAiObjectContextInternal : public NamedObjectContext -{ -public: - MageAiObjectContextInternal() - { - creators["arcane power"] = &MageAiObjectContextInternal::arcane_power; - creators["presence of mind"] = &MageAiObjectContextInternal::presence_of_mind; - creators["frostbolt"] = &MageAiObjectContextInternal::frostbolt; - creators["frostfire bolt"] = &MageAiObjectContextInternal::frostfire_bolt; - creators["ice lance"] = &MageAiObjectContextInternal::ice_lance; - creators["deep freeze"] = &MageAiObjectContextInternal::deep_freeze; - creators["blizzard"] = &MageAiObjectContextInternal::blizzard; - creators["cone of cold"] = &MageAiObjectContextInternal::cone_of_cold; - creators["frost nova"] = &MageAiObjectContextInternal::frost_nova; - creators["arcane intellect"] = &MageAiObjectContextInternal::arcane_intellect; - creators["arcane intellect on party"] = &MageAiObjectContextInternal::arcane_intellect_on_party; - creators["conjure water"] = &MageAiObjectContextInternal::conjure_water; - creators["conjure food"] = &MageAiObjectContextInternal::conjure_food; - creators["conjure mana gem"] = &MageAiObjectContextInternal::conjure_mana_gem; - creators["molten armor"] = &MageAiObjectContextInternal::molten_armor; - creators["mage armor"] = &MageAiObjectContextInternal::mage_armor; - creators["ice armor"] = &MageAiObjectContextInternal::ice_armor; - creators["frost armor"] = &MageAiObjectContextInternal::frost_armor; - creators["fireball"] = &MageAiObjectContextInternal::fireball; - creators["pyroblast"] = &MageAiObjectContextInternal::pyroblast; - creators["flamestrike"] = &MageAiObjectContextInternal::flamestrike; - creators["fire blast"] = &MageAiObjectContextInternal::fire_blast; - creators["scorch"] = &MageAiObjectContextInternal::scorch; - creators["counterspell"] = &MageAiObjectContextInternal::counterspell; - creators["remove curse"] = &MageAiObjectContextInternal::remove_curse; - creators["remove curse on party"] = &MageAiObjectContextInternal::remove_curse_on_party; - creators["remove lesser curse"] = &MageAiObjectContextInternal::remove_lesser_curse; - creators["remove lesser curse on party"] = &MageAiObjectContextInternal::remove_lesser_curse_on_party; - creators["icy veins"] = &MageAiObjectContextInternal::icy_veins; - creators["cold snap"] = &MageAiObjectContextInternal::cold_snap; - creators["ice barrier"] = &MageAiObjectContextInternal::ice_barrier; - creators["summon water elemental"] = &MageAiObjectContextInternal::summon_water_elemental; - creators["combustion"] = &MageAiObjectContextInternal::combustion; - creators["ice block"] = &MageAiObjectContextInternal::ice_block; - creators["polymorph"] = &MageAiObjectContextInternal::polymorph; - creators["spellsteal"] = &MageAiObjectContextInternal::spellsteal; - creators["living bomb"] = &MageAiObjectContextInternal::living_bomb; - creators["living bomb on attackers"] = &MageAiObjectContextInternal::living_bomb_on_attackers; - creators["dragon's breath"] = &MageAiObjectContextInternal::dragons_breath; - creators["blast wave"] = &MageAiObjectContextInternal::blast_wave; - creators["invisibility"] = &MageAiObjectContextInternal::invisibility; - creators["evocation"] = &MageAiObjectContextInternal::evocation; - creators["arcane blast"] = &MageAiObjectContextInternal::arcane_blast; - creators["arcane barrage"] = &MageAiObjectContextInternal::arcane_barrage; - creators["arcane missiles"] = &MageAiObjectContextInternal::arcane_missiles; - creators["counterspell on enemy healer"] = &MageAiObjectContextInternal::counterspell_on_enemy_healer; - creators["fire ward"] = &MageAiObjectContextInternal::fire_ward; - creators["frost ward"] = &MageAiObjectContextInternal::frost_ward; - creators["mirror image"] = &MageAiObjectContextInternal::mirror_image; - creators["focus magic on party"] = &MageAiObjectContextInternal::focus_magic_on_party; - creators["blink back"] = &MageAiObjectContextInternal::blink_back; - creators["use mana sapphire"] = &MageAiObjectContextInternal::use_mana_sapphire; - creators["use mana emerald"] = &MageAiObjectContextInternal::use_mana_emerald; - creators["use mana ruby"] = &MageAiObjectContextInternal::use_mana_ruby; - creators["use mana citrine"] = &MageAiObjectContextInternal::use_mana_citrine; - creators["use mana jade"] = &MageAiObjectContextInternal::use_mana_jade; - creators["use mana agate"] = &MageAiObjectContextInternal::use_mana_agate; - creators["mana shield"] = &MageAiObjectContextInternal::mana_shield; - } - -private: - static Action* presence_of_mind(PlayerbotAI* botAI) { return new CastPresenceOfMindAction(botAI); } - static Action* frost_ward(PlayerbotAI* botAI) { return new CastFrostWardAction(botAI); } - static Action* fire_ward(PlayerbotAI* botAI) { return new CastFireWardAction(botAI); } - static Action* arcane_power(PlayerbotAI* botAI) { return new CastArcanePowerAction(botAI); } - static Action* arcane_missiles(PlayerbotAI* botAI) { return new CastArcaneMissilesAction(botAI); } - static Action* arcane_barrage(PlayerbotAI* botAI) { return new CastArcaneBarrageAction(botAI); } - static Action* arcane_blast(PlayerbotAI* botAI) { return new CastArcaneBlastAction(botAI); } - static Action* frostbolt(PlayerbotAI* botAI) { return new CastFrostboltAction(botAI); } - static Action* frostfire_bolt(PlayerbotAI* botAI) { return new CastFrostfireBoltAction(botAI); } - static Action* ice_lance(PlayerbotAI* botAI) { return new CastIceLanceAction(botAI); } - static Action* deep_freeze(PlayerbotAI* botAI) { return new CastDeepFreezeAction(botAI); } - static Action* blizzard(PlayerbotAI* botAI) { return new CastBlizzardAction(botAI); } - static Action* cone_of_cold(PlayerbotAI* botAI) { return new CastConeOfColdAction(botAI); } - static Action* frost_nova(PlayerbotAI* botAI) { return new CastFrostNovaAction(botAI); } - static Action* arcane_intellect(PlayerbotAI* botAI) { return new CastArcaneIntellectAction(botAI); } - static Action* arcane_intellect_on_party(PlayerbotAI* botAI) { return new CastArcaneIntellectOnPartyAction(botAI); } - static Action* conjure_water(PlayerbotAI* botAI) { return new CastConjureWaterAction(botAI); } - static Action* conjure_food(PlayerbotAI* botAI) { return new CastConjureFoodAction(botAI); } - static Action* conjure_mana_gem(PlayerbotAI* botAI) { return new CastConjureManaGemAction(botAI); } - static Action* molten_armor(PlayerbotAI* botAI) { return new CastMoltenArmorAction(botAI); } - static Action* mage_armor(PlayerbotAI* botAI) { return new CastMageArmorAction(botAI); } - static Action* ice_armor(PlayerbotAI* botAI) { return new CastIceArmorAction(botAI); } - static Action* frost_armor(PlayerbotAI* botAI) { return new CastFrostArmorAction(botAI); } - static Action* fireball(PlayerbotAI* botAI) { return new CastFireballAction(botAI); } - static Action* pyroblast(PlayerbotAI* botAI) { return new CastPyroblastAction(botAI); } - static Action* flamestrike(PlayerbotAI* botAI) { return new CastFlamestrikeAction(botAI); } - static Action* fire_blast(PlayerbotAI* botAI) { return new CastFireBlastAction(botAI); } - static Action* scorch(PlayerbotAI* botAI) { return new CastScorchAction(botAI); } - static Action* counterspell(PlayerbotAI* botAI) { return new CastCounterspellAction(botAI); } - static Action* remove_curse(PlayerbotAI* botAI) { return new CastRemoveCurseAction(botAI); } - static Action* remove_curse_on_party(PlayerbotAI* botAI) { return new CastRemoveCurseOnPartyAction(botAI); } - static Action* remove_lesser_curse(PlayerbotAI* botAI) { return new CastRemoveLesserCurseAction(botAI); } - static Action* remove_lesser_curse_on_party(PlayerbotAI* botAI) { return new CastRemoveLesserCurseOnPartyAction(botAI); } - static Action* icy_veins(PlayerbotAI* botAI) { return new CastIcyVeinsAction(botAI); } - static Action* cold_snap(PlayerbotAI* botAI) { return new CastColdSnapAction(botAI); } - static Action* ice_barrier(PlayerbotAI* botAI) { return new CastIceBarrierAction(botAI); } - static Action* summon_water_elemental(PlayerbotAI* botAI) { return new CastSummonWaterElementalAction(botAI); } - static Action* combustion(PlayerbotAI* botAI) { return new CastCombustionAction(botAI); } - static Action* ice_block(PlayerbotAI* botAI) { return new CastIceBlockAction(botAI); } - static Action* polymorph(PlayerbotAI* botAI) { return new CastPolymorphAction(botAI); } - static Action* spellsteal(PlayerbotAI* botAI) { return new CastSpellstealAction(botAI); } - static Action* living_bomb(PlayerbotAI* botAI) { return new CastLivingBombAction(botAI); } - static Action* living_bomb_on_attackers(PlayerbotAI* botAI) { return new CastLivingBombOnAttackersAction(botAI); } - static Action* dragons_breath(PlayerbotAI* botAI) { return new CastDragonsBreathAction(botAI); } - static Action* blast_wave(PlayerbotAI* botAI) { return new CastBlastWaveAction(botAI); } - static Action* invisibility(PlayerbotAI* botAI) { return new CastInvisibilityAction(botAI); } - static Action* evocation(PlayerbotAI* botAI) { return new CastEvocationAction(botAI); } - static Action* counterspell_on_enemy_healer(PlayerbotAI* botAI) { return new CastCounterspellOnEnemyHealerAction(botAI); } - static Action* mirror_image(PlayerbotAI* botAI) { return new CastMirrorImageAction(botAI); } - static Action* focus_magic_on_party(PlayerbotAI* botAI) { return new CastFocusMagicOnPartyAction(botAI); } - static Action* blink_back(PlayerbotAI* botAI) { return new CastBlinkBackAction(botAI); } - static Action* use_mana_sapphire(PlayerbotAI* botAI) { return new UseManaSapphireAction(botAI); } - static Action* use_mana_emerald(PlayerbotAI* botAI) { return new UseManaEmeraldAction(botAI); } - static Action* use_mana_ruby(PlayerbotAI* botAI) { return new UseManaRubyAction(botAI); } - static Action* use_mana_citrine(PlayerbotAI* botAI) { return new UseManaCitrineAction(botAI); } - static Action* use_mana_jade(PlayerbotAI* botAI) { return new UseManaJadeAction(botAI); } - static Action* use_mana_agate(PlayerbotAI* botAI) { return new UseManaAgateAction(botAI); } - static Action* mana_shield(PlayerbotAI* botAI) { return new CastManaShieldAction(botAI); } -}; - SharedNamedObjectContextList MageAiObjectContext::sharedStrategyContexts; -SharedNamedObjectContextList MageAiObjectContext::sharedActionContexts; SharedNamedObjectContextList MageAiObjectContext::sharedTriggerContexts; SharedNamedObjectContextList MageAiObjectContext::sharedValueContexts; MageAiObjectContext::MageAiObjectContext(PlayerbotAI* botAI) - : AiObjectContext(botAI, sharedStrategyContexts, sharedActionContexts, sharedTriggerContexts, sharedValueContexts) + : AiObjectContext(botAI, sharedStrategyContexts, sharedTriggerContexts, sharedValueContexts) { } void MageAiObjectContext::BuildSharedContexts() { BuildSharedStrategyContexts(sharedStrategyContexts); - BuildSharedActionContexts(sharedActionContexts); BuildSharedTriggerContexts(sharedTriggerContexts); BuildSharedValueContexts(sharedValueContexts); } @@ -327,12 +198,6 @@ void MageAiObjectContext::BuildSharedStrategyContexts(SharedNamedObjectContextLi strategyContexts.Add(new MageBuffStrategyFactoryInternal()); } -void MageAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts) -{ - AiObjectContext::BuildSharedActionContexts(actionContexts); - actionContexts.Add(new MageAiObjectContextInternal()); -} - void MageAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts) { AiObjectContext::BuildSharedTriggerContexts(triggerContexts); diff --git a/src/Ai/Class/Mage/MageAiObjectContext.h b/src/Ai/Class/Mage/MageAiObjectContext.h index c2cd2f5e70..142322248b 100644 --- a/src/Ai/Class/Mage/MageAiObjectContext.h +++ b/src/Ai/Class/Mage/MageAiObjectContext.h @@ -17,12 +17,10 @@ class MageAiObjectContext : public AiObjectContext static void BuildSharedContexts(); static void BuildSharedStrategyContexts(SharedNamedObjectContextList& strategyContexts); - static void BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts); static void BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts); static void BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts); static SharedNamedObjectContextList sharedStrategyContexts; - static SharedNamedObjectContextList sharedActionContexts; static SharedNamedObjectContextList sharedTriggerContexts; static SharedNamedObjectContextList sharedValueContexts; }; diff --git a/src/Ai/Class/Mage/Strategy/ArcaneMageStrategy.cpp b/src/Ai/Class/Mage/Strategy/ArcaneMageStrategy.cpp index 4707231db1..a1074b181a 100644 --- a/src/Ai/Class/Mage/Strategy/ArcaneMageStrategy.cpp +++ b/src/Ai/Class/Mage/Strategy/ArcaneMageStrategy.cpp @@ -4,7 +4,8 @@ */ #include "ArcaneMageStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "MageActions.h" // ===== Action Node Factory ===== class ArcaneMageStrategyActionNodeFactory : public NamedObjectFactory @@ -22,13 +23,69 @@ class ArcaneMageStrategyActionNodeFactory : public NamedObjectFactory ArcaneMageStrategy::getDefaultActions() { return { - NextAction("arcane blast", 5.6f), - NextAction("arcane missiles", 5.5f), - NextAction("arcane barrage", 5.4f), // cast while moving - NextAction("fire blast", 5.3f), // cast while moving if arcane barrage isn't available/learned - NextAction("frostbolt", 5.2f), // for arcane immune targets - NextAction("shoot", 5.1f) + CreateNextAction(5.6f), + CreateNextAction(5.5f), + CreateNextAction(5.4f), // cast while moving + CreateNextAction(5.3f), // cast while moving if arcane barrage isn't available/learned + CreateNextAction(5.2f), // for arcane immune targets + CreateNextAction(5.1f) }; } @@ -60,7 +117,7 @@ void ArcaneMageStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "arcane blast 4 stacks and missile barrage", { - NextAction("arcane missiles", 15.0f) + CreateNextAction(15.0f) } ) ); diff --git a/src/Ai/Class/Mage/Strategy/FireMageStrategy.cpp b/src/Ai/Class/Mage/Strategy/FireMageStrategy.cpp index 4914c72df6..df9483a1dc 100644 --- a/src/Ai/Class/Mage/Strategy/FireMageStrategy.cpp +++ b/src/Ai/Class/Mage/Strategy/FireMageStrategy.cpp @@ -4,8 +4,9 @@ */ #include "FireMageStrategy.h" -#include "Playerbots.h" -#include "Strategy.h" +#include "CreateNextAction.h" +#include "MageActions.h" +#include "ReachTargetActions.h" // ===== Action Node Factory ===== class FireMageStrategyActionNodeFactory : public NamedObjectFactory @@ -23,13 +24,69 @@ class FireMageStrategyActionNodeFactory : public NamedObjectFactory } private: - static ActionNode* fireball(PlayerbotAI*) { return new ActionNode("fireball", {}, {}, {}); } - static ActionNode* frostbolt(PlayerbotAI*) { return new ActionNode("frostbolt", {}, {}, {}); } - static ActionNode* fire_blast(PlayerbotAI*) { return new ActionNode("fire blast", {}, {}, {}); } - static ActionNode* pyroblast(PlayerbotAI*) { return new ActionNode("pyroblast", {}, {}, {}); } - static ActionNode* scorch(PlayerbotAI*) { return new ActionNode("scorch", {}, {}, {}); } - static ActionNode* living_bomb(PlayerbotAI*) { return new ActionNode("living bomb", {}, {}, {}); } - static ActionNode* combustion(PlayerbotAI*) { return new ActionNode("combustion", {}, {}, {}); } + static ActionNode* fireball(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + + static ActionNode* frostbolt(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + + static ActionNode* fire_blast(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + + static ActionNode* pyroblast(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + + static ActionNode* scorch(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + + static ActionNode* living_bomb(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + + static ActionNode* combustion(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + }; // ===== Single Target Strategy ===== @@ -42,10 +99,10 @@ FireMageStrategy::FireMageStrategy(PlayerbotAI* botAI) : GenericMageStrategy(bot std::vector FireMageStrategy::getDefaultActions() { return { - NextAction("fireball", 5.3f), - NextAction("frostbolt", 5.2f), // fire immune target - NextAction("fire blast", 5.1f), // cast during movement - NextAction("shoot", 5.0f) + CreateNextAction(5.3f), + CreateNextAction(5.2f), // fire immune target + CreateNextAction(5.1f), // cast during movement + CreateNextAction(5.0f) }; } @@ -59,7 +116,7 @@ void FireMageStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "improved scorch", { - NextAction("scorch", 19.0f) + CreateNextAction(19.0f) } ) ); @@ -67,7 +124,7 @@ void FireMageStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "living bomb", { - NextAction("living bomb", 18.5f) + CreateNextAction(18.5f) } ) ); @@ -77,7 +134,7 @@ void FireMageStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "hot streak", { - NextAction("pyroblast", 25.0f) + CreateNextAction(25.0f) } ) ); @@ -95,7 +152,7 @@ void FirestarterStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "blast wave off cd and medium aoe", { - NextAction("reach melee", 25.5f) + CreateNextAction(25.5f) } ) ); diff --git a/src/Ai/Class/Mage/Strategy/FrostFireMageStrategy.cpp b/src/Ai/Class/Mage/Strategy/FrostFireMageStrategy.cpp index 4448a43493..f87378bfcb 100644 --- a/src/Ai/Class/Mage/Strategy/FrostFireMageStrategy.cpp +++ b/src/Ai/Class/Mage/Strategy/FrostFireMageStrategy.cpp @@ -4,7 +4,8 @@ */ #include "FrostFireMageStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "MageActions.h" // ===== Action Node Factory ===== class FrostFireMageStrategyActionNodeFactory : public NamedObjectFactory @@ -22,13 +23,69 @@ class FrostFireMageStrategyActionNodeFactory : public NamedObjectFactory FrostFireMageStrategy::getDefaultActions() { return { - NextAction("frostfire bolt", 5.2f), - NextAction("fire blast", 5.1f), // cast during movement - NextAction("shoot", 5.0f) + CreateNextAction(5.2f), + CreateNextAction(5.1f), // cast during movement + CreateNextAction(5.0f) }; } @@ -57,7 +114,7 @@ void FrostFireMageStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "improved scorch", { - NextAction("scorch", 19.0f) + CreateNextAction(19.0f) } ) ); @@ -65,7 +122,7 @@ void FrostFireMageStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "living bomb", { - NextAction("living bomb", 18.5f) + CreateNextAction(18.5f) } ) ); @@ -75,7 +132,7 @@ void FrostFireMageStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "hot streak", { - NextAction("pyroblast", 25.0f) + CreateNextAction(25.0f) } ) ); diff --git a/src/Ai/Class/Mage/Strategy/FrostMageStrategy.cpp b/src/Ai/Class/Mage/Strategy/FrostMageStrategy.cpp index 34ed81dba1..ca9e0bfa66 100644 --- a/src/Ai/Class/Mage/Strategy/FrostMageStrategy.cpp +++ b/src/Ai/Class/Mage/Strategy/FrostMageStrategy.cpp @@ -5,7 +5,9 @@ #include "FrostMageStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "GenericActions.h" +#include "MageActions.h" // ===== Action Node Factory ===== class FrostMageStrategyActionNodeFactory : public NamedObjectFactory @@ -26,16 +28,86 @@ class FrostMageStrategyActionNodeFactory : public NamedObjectFactory } private: - static ActionNode* cold_snap(PlayerbotAI*) { return new ActionNode("cold snap", {}, {}, {}); } - static ActionNode* ice_barrier(PlayerbotAI*) { return new ActionNode("ice barrier", {}, {}, {}); } - static ActionNode* summon_water_elemental(PlayerbotAI*) { return new ActionNode("summon water elemental", {}, {}, {}); } - static ActionNode* deep_freeze(PlayerbotAI*) { return new ActionNode("deep freeze", {}, {}, {}); } - static ActionNode* icy_veins(PlayerbotAI*) { return new ActionNode("icy veins", {}, {}, {}); } - static ActionNode* frostbolt(PlayerbotAI*) { return new ActionNode("frostbolt", {}, {}, {}); } - static ActionNode* ice_lance(PlayerbotAI*) { return new ActionNode("ice lance", {}, {}, {}); } - static ActionNode* fire_blast(PlayerbotAI*) { return new ActionNode("fire blast", {}, {}, {}); } - static ActionNode* fireball(PlayerbotAI*) { return new ActionNode("fireball", {}, {}, {}); } - static ActionNode* frostfire_bolt(PlayerbotAI*) { return new ActionNode("frostfire bolt", {}, {}, {}); } + static ActionNode* cold_snap(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* ice_barrier(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* summon_water_elemental(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* deep_freeze(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* icy_veins(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* frostbolt(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* ice_lance(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* fire_blast(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* fireball(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* frostfire_bolt(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } }; // ===== Single Target Strategy ===== @@ -48,11 +120,11 @@ FrostMageStrategy::FrostMageStrategy(PlayerbotAI* botAI) : GenericMageStrategy(b std::vector FrostMageStrategy::getDefaultActions() { return { - NextAction("frostbolt", 5.4f), - NextAction("ice lance", 5.3f), // cast during movement - NextAction("fire blast", 5.2f), // cast during movement if ice lance is not learned - NextAction("shoot", 5.1f), - NextAction("fireball", 5.0f) + CreateNextAction(5.4f), + CreateNextAction(5.3f), // cast during movement + CreateNextAction(5.2f), // cast during movement if ice lance is not learned + CreateNextAction(5.1f), + CreateNextAction(5.0f) }; } @@ -66,7 +138,7 @@ void FrostMageStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "no pet", { - NextAction("summon water elemental", 30.0f) + CreateNextAction(30.0f) } ) ); @@ -74,7 +146,7 @@ void FrostMageStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "has pet", { - NextAction("toggle pet spell", 60.0f) + CreateNextAction(60.0f) } ) ); @@ -82,7 +154,7 @@ void FrostMageStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "new pet", { - NextAction("set pet stance", 60.0f) + CreateNextAction(60.0f) } ) ); @@ -90,7 +162,7 @@ void FrostMageStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "medium health", { - NextAction("ice barrier", 29.0f) + CreateNextAction(29.0f) } ) ); @@ -98,7 +170,7 @@ void FrostMageStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "being attacked", { - NextAction("ice barrier", 29.0f) + CreateNextAction(29.0f) } ) ); @@ -108,7 +180,7 @@ void FrostMageStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "brain freeze", { - NextAction("frostfire bolt", 19.5f) + CreateNextAction(19.5f) } ) ); @@ -116,8 +188,8 @@ void FrostMageStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "fingers of frost", { - NextAction("deep freeze", 19.0f), - NextAction("frostbolt", 18.0f) + CreateNextAction(19.0f), + CreateNextAction(18.0f) } ) ); @@ -125,8 +197,8 @@ void FrostMageStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "frostbite on target", { - NextAction("deep freeze", 19.0f), - NextAction("frostbolt", 18.0f) + CreateNextAction(19.0f), + CreateNextAction(18.0f) } ) ); @@ -134,8 +206,8 @@ void FrostMageStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "frost nova on target", { - NextAction("deep freeze", 19.0f), - NextAction("frostbolt", 18.0f) + CreateNextAction(19.0f), + CreateNextAction(18.0f) } ) ); diff --git a/src/Ai/Class/Mage/Strategy/GenericMageNonCombatStrategy.cpp b/src/Ai/Class/Mage/Strategy/GenericMageNonCombatStrategy.cpp index eab98ea5a2..ec51d23d8c 100644 --- a/src/Ai/Class/Mage/Strategy/GenericMageNonCombatStrategy.cpp +++ b/src/Ai/Class/Mage/Strategy/GenericMageNonCombatStrategy.cpp @@ -5,7 +5,9 @@ #include "GenericMageNonCombatStrategy.h" #include "AiFactory.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "ImbueAction.h" +#include "MageActions.h" class GenericMageNonCombatStrategyActionNodeFactory : public NamedObjectFactory { @@ -20,26 +22,29 @@ class GenericMageNonCombatStrategyActionNodeFactory : public NamedObjectFactory< private: static ActionNode* molten_armor([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("molten armor", - /*P*/ {}, - /*A*/ { NextAction("mage armor") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* mage_armor([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("mage armor", - /*P*/ {}, - /*A*/ { NextAction("ice armor") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* ice_armor([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("ice armor", - /*P*/ {}, - /*A*/ { NextAction("frost armor") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } }; @@ -52,23 +57,72 @@ void GenericMageNonCombatStrategy::InitTriggers(std::vector& trigg { NonCombatStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("arcane intellect", { NextAction("arcane intellect", 21.0f) })); - triggers.push_back(new TriggerNode("no focus magic", { NextAction("focus magic on party", 19.0f) })); - triggers.push_back(new TriggerNode("often", { NextAction("apply oil", 1.0f) })); - triggers.push_back(new TriggerNode("no mana gem", { NextAction("conjure mana gem", 20.0f) })); + triggers.push_back( + new TriggerNode( + "arcane intellect", + { + CreateNextAction(21.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "no focus magic", + { + CreateNextAction(19.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "often", + { + CreateNextAction(1.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "no mana gem", + { + CreateNextAction(20.0f) + } + ) + ); } void MageBuffManaStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("mage armor", { NextAction("mage armor", 19.0f) })); + triggers.push_back( + new TriggerNode( + "mage armor", + { + CreateNextAction(19.0f) + } + ) + ); } void MageBuffDpsStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("mage armor", { NextAction("molten armor", 19.0f) })); + triggers.push_back( + new TriggerNode( + "mage armor", + { + CreateNextAction(19.0f) + } + ) + ); } void MageBuffStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("arcane intellect on party", { NextAction("arcane intellect on party", 20.0f) })); + triggers.push_back( + new TriggerNode( + "arcane intellect on party", + { + CreateNextAction(20.0f) + } + ) + ); } diff --git a/src/Ai/Class/Mage/Strategy/GenericMageStrategy.cpp b/src/Ai/Class/Mage/Strategy/GenericMageStrategy.cpp index 75a63efa47..f9fe0a5896 100644 --- a/src/Ai/Class/Mage/Strategy/GenericMageStrategy.cpp +++ b/src/Ai/Class/Mage/Strategy/GenericMageStrategy.cpp @@ -5,7 +5,10 @@ #include "GenericMageStrategy.h" #include "AiFactory.h" -#include "Playerbots.h" +#include "CancelChannelAction.h" +#include "CreateNextAction.h" +#include "GenericSpellActions.h" +#include "MageActions.h" #include "RangedCombatStrategy.h" class GenericMageStrategyActionNodeFactory : public NamedObjectFactory @@ -33,121 +36,136 @@ class GenericMageStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, + /*C*/ {} + ); } static ActionNode* frostfire_bolt([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("frostfire bolt", - /*P*/ {}, - /*A*/ { NextAction("fireball") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* ice_lance([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("ice lance", - /*P*/ {}, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* fire_blast([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("fire blast", - /*P*/ {}, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* scorch([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("scorch", - /*P*/ {}, - /*A*/ { NextAction("shoot") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* frost_nova([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("frost nova", - /*P*/ {}, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* cone_of_cold([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("cone of cold", - /*P*/ {}, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* icy_veins([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("icy veins", - /*P*/ {}, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* combustion([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("combustion", - /*P*/ {}, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* evocation([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("evocation", - /*P*/ {}, - /*A*/ { NextAction("mana potion") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* dragons_breath([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("dragon's breath", - /*P*/ {}, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* blast_wave([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("blast wave", - /*P*/ {}, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* remove_curse([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("remove curse", - /*P*/ {}, - /*A*/ { NextAction("remove lesser curse") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* remove_curse_on_party([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("remove curse on party", - /*P*/ {}, - /*A*/ { NextAction("remove lesser curse on party") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* fireball([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("fireball", - /*P*/ {}, - /*A*/ { NextAction("shoot") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } }; @@ -161,44 +179,182 @@ void GenericMageStrategy::InitTriggers(std::vector& triggers) RangedCombatStrategy::InitTriggers(triggers); // Threat Triggers - triggers.push_back(new TriggerNode("high threat", { NextAction("mirror image", 60.0f) })); - triggers.push_back(new TriggerNode("medium threat", { NextAction("invisibility", 30.0f) })); + triggers.push_back( + new TriggerNode( + "high threat", + { + CreateNextAction(60.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "medium threat", + { + CreateNextAction(30.0f) + } + ) + ); // Defensive Triggers - triggers.push_back(new TriggerNode("critical health", { NextAction("ice block", 90.0f) })); - triggers.push_back(new TriggerNode("low health", { NextAction("mana shield", 85.0f) })); - triggers.push_back(new TriggerNode("fire ward", { NextAction("fire ward", 90.0f) })); - triggers.push_back(new TriggerNode("frost ward", { NextAction("frost ward", 90.0f) })); - triggers.push_back(new TriggerNode("enemy is close and no firestarter strategy", { NextAction("frost nova", 50.0f) })); - triggers.push_back(new TriggerNode("enemy too close for spell and no firestarter strategy", { NextAction("blink back", 35.0f) })); + triggers.push_back( + new TriggerNode( + "critical health", + { + CreateNextAction(90.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "low health", + { + CreateNextAction(85.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "fire ward", + { + CreateNextAction(90.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "frost ward", + { + CreateNextAction(90.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "enemy is close and no firestarter strategy", + { + CreateNextAction(50.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "enemy too close for spell and no firestarter strategy", + { + CreateNextAction(35.0f) + } + ) + ); // Mana Threshold Triggers Player* bot = botAI->GetBot(); if (bot->HasSpell(42985)) // Mana Sapphire - triggers.push_back(new TriggerNode("high mana", { NextAction("use mana sapphire", 90.0f) })); + triggers.push_back( + new TriggerNode( + "high mana", + { + CreateNextAction(90.0f) + } + ) + ); else if (bot->HasSpell(27101)) // Mana Emerald - triggers.push_back(new TriggerNode("high mana", { NextAction("use mana emerald", 90.0f) })); + triggers.push_back( + new TriggerNode( + "high mana", + { + CreateNextAction(90.0f) + } + ) + ); else if (bot->HasSpell(10054)) // Mana Ruby - triggers.push_back(new TriggerNode("high mana", { NextAction("use mana ruby", 90.0f) })); + triggers.push_back( + new TriggerNode( + "high mana", + { + CreateNextAction(90.0f) + } + ) + ); else if (bot->HasSpell(10053)) // Mana Citrine - triggers.push_back(new TriggerNode("high mana", { NextAction("use mana citrine", 90.0f) })); + triggers.push_back( + new TriggerNode( + "high mana", + { + CreateNextAction(90.0f) + } + ) + ); else if (bot->HasSpell(3552)) // Mana Jade - triggers.push_back(new TriggerNode("high mana", { NextAction("use mana jade", 90.0f) })); + triggers.push_back( + new TriggerNode( + "high mana", + { + CreateNextAction(90.0f) + } + ) + ); else if (bot->HasSpell(759)) // Mana Agate - triggers.push_back(new TriggerNode("high mana", { NextAction("use mana agate", 90.0f) })); + triggers.push_back( + new TriggerNode( + "high mana", + { + CreateNextAction(90.0f) + } + ) + ); - triggers.push_back(new TriggerNode("medium mana", { NextAction("mana potion", 90.0f) })); - triggers.push_back(new TriggerNode("low mana", { NextAction("evocation", 90.0f) })); + triggers.push_back( + new TriggerNode( + "medium mana", { CreateNextAction(90.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "low mana", + { + CreateNextAction(90.0f) + } + ) + ); // Counterspell / Spellsteal Triggers - triggers.push_back(new TriggerNode("spellsteal", { NextAction("spellsteal", 40.0f) })); - triggers.push_back(new TriggerNode("counterspell on enemy healer", { NextAction("counterspell on enemy healer", 40.0f) })); + triggers.push_back( + new TriggerNode( + "spellsteal", + { + CreateNextAction(40.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "counterspell on enemy healer", + { + CreateNextAction(40.0f) + } + ) + ); } void MageCureStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("remove curse", { NextAction("remove curse", 41.0f) })); - triggers.push_back(new TriggerNode("remove curse on party", { NextAction("remove curse on party", 40.0f) })); + triggers.push_back( + new TriggerNode( + "remove curse", + { + CreateNextAction(41.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "remove curse on party", + { + CreateNextAction(40.0f) + } + ) + ); } void MageBoostStrategy::InitTriggers(std::vector& triggers) @@ -208,71 +364,233 @@ void MageBoostStrategy::InitTriggers(std::vector& triggers) if (tab == 0) // Arcane { - triggers.push_back(new TriggerNode("arcane power", { NextAction("arcane power", 29.0f) })); - triggers.push_back(new TriggerNode("icy veins", { NextAction("icy veins", 28.5f) })); - triggers.push_back(new TriggerNode("mirror image", { NextAction("mirror image", 28.0f) })); + triggers.push_back( + new TriggerNode( + "arcane power", + { + CreateNextAction(29.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "icy veins", + { + CreateNextAction(28.5f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "mirror image", + { + CreateNextAction(28.0f) + } + ) + ); } else if (tab == 1) { if (bot->HasSpell(44614) /*Frostfire Bolt*/ && bot->HasAura(15047) /*Ice Shards*/) { // Frostfire - triggers.push_back(new TriggerNode("combustion", { NextAction("combustion", 18.0f) })); - triggers.push_back(new TriggerNode("icy veins", { NextAction("icy veins", 17.5f) })); - triggers.push_back(new TriggerNode("mirror image", { NextAction("mirror image", 17.0f) })); + triggers.push_back( + new TriggerNode( + "combustion", + { + CreateNextAction(18.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "icy veins", + { + CreateNextAction(17.5f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "mirror image", + { + CreateNextAction(17.0f) + } + ) + ); } else { // Fire - triggers.push_back(new TriggerNode("combustion", { NextAction("combustion", 18.0f) })); - triggers.push_back(new TriggerNode("mirror image", { NextAction("mirror image", 17.5f) })); + triggers.push_back( + new TriggerNode( + "combustion", + { + CreateNextAction(18.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "mirror image", + { + CreateNextAction(17.5f) + } + ) + ); } } else if (tab == 2) // Frost { - triggers.push_back(new TriggerNode("cold snap", { NextAction("cold snap", 28.0f) })); - triggers.push_back(new TriggerNode("icy veins", { NextAction("icy veins", 27.5f) })); - triggers.push_back(new TriggerNode("mirror image", { NextAction("mirror image", 26.0f) })); + triggers.push_back( + new TriggerNode( + "cold snap", + { + CreateNextAction(28.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "icy veins", + { + CreateNextAction(27.5f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "mirror image", + { + CreateNextAction(26.0f) + } + ) + ); } } void MageCcStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("polymorph", { NextAction("polymorph", 30.0f) })); + triggers.push_back( + new TriggerNode( + "polymorph", + { + CreateNextAction(30.0f) + } + ) + ); } void MageAoeStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("blizzard channel check", { NextAction("cancel channel", 26.0f) })); + triggers.push_back( + new TriggerNode( + "blizzard channel check", + { + CreateNextAction(26.0f) + } + ) + ); Player* bot = botAI->GetBot(); - int tab = AiFactory::GetPlayerSpecTab(bot); + const uint8_t tab = AiFactory::GetPlayerSpecTab(bot); - if (tab == 0) // Arcane + // Arcane + if (tab == MAGE_TAB_ARCANE) { - triggers.push_back(new TriggerNode("flamestrike active and medium aoe", { NextAction("blizzard", 24.0f) })); - triggers.push_back(new TriggerNode("medium aoe", { - NextAction("flamestrike", 23.0f), - NextAction("blizzard", 22.0f) })); - triggers.push_back(new TriggerNode("light aoe", { NextAction("arcane explosion", 21.0f) })); + triggers.push_back( + new TriggerNode( + "flamestrike active and medium aoe", + { + CreateNextAction(24.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "medium aoe", + { + CreateNextAction(23.0f), + CreateNextAction(22.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "light aoe", + { + CreateNextAction(21.0f) + } + ) + ); } - else if (tab == 1) // Fire and Frostfire + + // Fire and Frostfire + if (tab == MAGE_TAB_FIRE) { triggers.push_back( - new TriggerNode("medium aoe", { - NextAction("dragon's breath", 39.0f), - NextAction("blast wave", 38.0f), - NextAction("flamestrike", 23.0f), - NextAction("blizzard", 22.0f) })); - - triggers.push_back(new TriggerNode("flamestrike active and medium aoe", { NextAction("blizzard", 24.0f) })); - triggers.push_back(new TriggerNode("firestarter", { NextAction("flamestrike", 40.0f) })); - triggers.push_back(new TriggerNode("living bomb on attackers", { NextAction("living bomb on attackers", 21.0f) })); + new TriggerNode( + "medium aoe", + { + CreateNextAction(39.0f), + CreateNextAction(38.0f), + CreateNextAction(23.0f), + CreateNextAction(22.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "flamestrike active and medium aoe", + { + CreateNextAction(24.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "firestarter", + { + CreateNextAction(40.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "living bomb on attackers", + { + CreateNextAction(21.0f) + } + ) + ); } - else if (tab == 2) // Frost + + // Frost + if (tab == MAGE_TAB_FROST) { - triggers.push_back(new TriggerNode("flamestrike active and medium aoe", { NextAction("blizzard", 24.0f) })); - triggers.push_back(new TriggerNode("medium aoe", { - NextAction("flamestrike", 23.0f), - NextAction("blizzard", 22.0f) })); - triggers.push_back(new TriggerNode("light aoe", { NextAction("cone of cold", 21.0f) })); + triggers.push_back( + new TriggerNode( + "flamestrike active and medium aoe", + { + CreateNextAction(24.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "medium aoe", + { + CreateNextAction(23.0f), + CreateNextAction(22.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "light aoe", + { + CreateNextAction(21.0f) + } + ) + ); } } diff --git a/src/Ai/Class/Paladin/Action/PaladinActions.cpp b/src/Ai/Class/Paladin/Action/PaladinActions.cpp index 190ecb264a..9b09f8b4dd 100644 --- a/src/Ai/Class/Paladin/Action/PaladinActions.cpp +++ b/src/Ai/Class/Paladin/Action/PaladinActions.cpp @@ -8,18 +8,14 @@ #include "AiFactory.h" #include "Event.h" #include "PlayerbotAI.h" -#include "PlayerbotAIConfig.h" -#include "PlayerbotFactory.h" #include "Playerbots.h" #include "SharedDefines.h" #include "../../../../../src/server/scripts/Spells/spell_generic.cpp" #include "GenericBuffUtils.h" -#include "Config.h" #include "Group.h" #include "ObjectAccessor.h" using ai::buff::MakeAuraQualifierForBuff; -using ai::buff::UpgradeToGroupIfAppropriate; // Helper : detect tank role on the target (player bot or not) return true if spec is tank or if the bot have tank strategies (bear/tank/tank face). static inline bool IsTankRole(Player* p) @@ -56,11 +52,6 @@ static inline bool IsOnlyPaladinInGroup(Player* bot) return pals == 1u; } -static inline bool GroupHasTankOfClass(Group* g, uint8 classId) -{ - return GroupHasTankOfClass(g, static_cast(classId)); -} - inline std::string const GetActualBlessingOfMight(Unit* target) { if (!target->ToPlayer()) @@ -167,7 +158,7 @@ Value* CastBlessingOnPartyAction::GetTargetValue() return context->GetValue("party member without aura", MakeAuraQualifierForBuff(spell)); } -bool CastBlessingOfMightAction::Execute(Event event) +bool CastBlessingOfMightAction::Execute(Event) { Unit* target = GetTarget(); if (!target) @@ -188,7 +179,7 @@ Value* CastBlessingOfMightOnPartyAction::GetTargetValue() ); } -bool CastBlessingOfMightOnPartyAction::Execute(Event event) +bool CastBlessingOfMightOnPartyAction::Execute(Event) { Unit* target = GetTarget(); if (!target) @@ -201,7 +192,7 @@ bool CastBlessingOfMightOnPartyAction::Execute(Event event) return botAI->CastSpell(castName, target); } -bool CastBlessingOfWisdomAction::Execute(Event event) +bool CastBlessingOfWisdomAction::Execute(Event) { Unit* target = GetTarget(); if (!target) @@ -222,7 +213,7 @@ Value* CastBlessingOfWisdomOnPartyAction::GetTargetValue() ); } -bool CastBlessingOfWisdomOnPartyAction::Execute(Event event) +bool CastBlessingOfWisdomOnPartyAction::Execute(Event) { Unit* target = GetTarget(); if (!target) @@ -258,7 +249,7 @@ Value* CastBlessingOfSanctuaryOnPartyAction::GetTargetValue() ); } -bool CastBlessingOfSanctuaryOnPartyAction::Execute(Event event) +bool CastBlessingOfSanctuaryOnPartyAction::Execute(Event) { if (!bot->HasSpell(SPELL_BLESSING_OF_SANCTUARY)) return false; @@ -382,7 +373,7 @@ Value* CastBlessingOfKingsOnPartyAction::GetTargetValue() ); } -bool CastBlessingOfKingsOnPartyAction::Execute(Event event) +bool CastBlessingOfKingsOnPartyAction::Execute(Event) { Unit* target = GetTarget(); if (!target) @@ -493,7 +484,7 @@ bool CastDivineSacrificeAction::isUseful() !botAI->HasAura("divine guardian", GetTarget(), false, false, -1, true); } -bool CastCancelDivineSacrificeAction::Execute(Event event) +bool CastCancelDivineSacrificeAction::Execute(Event) { botAI->RemoveAura("divine sacrifice"); return true; diff --git a/src/Ai/Class/Paladin/PaladinAiObjectContext.cpp b/src/Ai/Class/Paladin/PaladinAiObjectContext.cpp index 4929eb9df0..c8861884f0 100644 --- a/src/Ai/Class/Paladin/PaladinAiObjectContext.cpp +++ b/src/Ai/Class/Paladin/PaladinAiObjectContext.cpp @@ -13,7 +13,6 @@ #include "PaladinActions.h" #include "PaladinBuffStrategies.h" #include "PaladinTriggers.h" -#include "Playerbots.h" #include "TankPaladinStrategy.h" class PaladinStrategyFactoryInternal : public NamedObjectContext @@ -220,212 +219,18 @@ class PaladinTriggerFactoryInternal : public NamedObjectContext static Trigger* avenging_wrath(PlayerbotAI* botAI) { return new AvengingWrathTrigger(botAI); } }; -class PaladinAiObjectContextInternal : public NamedObjectContext -{ -public: - PaladinAiObjectContextInternal() - { - creators["seal of command"] = &PaladinAiObjectContextInternal::seal_of_command; - creators["seal of vengeance"] = &PaladinAiObjectContextInternal::seal_of_vengeance; - creators["seal of corruption"] = &PaladinAiObjectContextInternal::seal_of_corruption; - creators["blessing of might"] = &PaladinAiObjectContextInternal::blessing_of_might; - creators["blessing of wisdom"] = &PaladinAiObjectContextInternal::blessing_of_wisdom; - creators["blessing of kings"] = &PaladinAiObjectContextInternal::blessing_of_kings; - creators["blessing of sanctuary"] = &PaladinAiObjectContextInternal::blessing_of_sanctuary; - creators["divine storm"] = &PaladinAiObjectContextInternal::divine_storm; - creators["blessing of kings on party"] = &PaladinAiObjectContextInternal::blessing_of_kings_on_party; - creators["blessing of might on party"] = &PaladinAiObjectContextInternal::blessing_of_might_on_party; - creators["blessing of wisdom on party"] = &PaladinAiObjectContextInternal::blessing_of_wisdom_on_party; - creators["blessing of sanctuary on party"] = &PaladinAiObjectContextInternal::blessing_of_sanctuary_on_party; - creators["redemption"] = &PaladinAiObjectContextInternal::redemption; - creators["crusader strike"] = &PaladinAiObjectContextInternal::crusader_strike; - creators["crusader aura"] = &PaladinAiObjectContextInternal::crusader_aura; - creators["seal of light"] = &PaladinAiObjectContextInternal::seal_of_light; - creators["devotion aura"] = &PaladinAiObjectContextInternal::devotion_aura; - creators["concentration aura"] = &PaladinAiObjectContextInternal::concentration_aura; - creators["holy wrath"] = &PaladinAiObjectContextInternal::holy_wrath; - creators["consecration"] = &PaladinAiObjectContextInternal::consecration; - creators["cleanse disease"] = &PaladinAiObjectContextInternal::cleanse_disease; - creators["cleanse poison"] = &PaladinAiObjectContextInternal::cleanse_poison; - creators["cleanse magic"] = &PaladinAiObjectContextInternal::cleanse_magic; - creators["purify disease"] = &PaladinAiObjectContextInternal::purify_disease; - creators["purify poison"] = &PaladinAiObjectContextInternal::purify_poison; - creators["cleanse poison on party"] = &PaladinAiObjectContextInternal::cleanse_poison_on_party; - creators["cleanse disease on party"] = &PaladinAiObjectContextInternal::cleanse_disease_on_party; - creators["cleanse magic on party"] = &PaladinAiObjectContextInternal::cleanse_magic_on_party; - creators["purify poison on party"] = &PaladinAiObjectContextInternal::purify_poison_on_party; - creators["purify disease on party"] = &PaladinAiObjectContextInternal::purify_disease_on_party; - creators["seal of wisdom"] = &PaladinAiObjectContextInternal::seal_of_wisdom; - creators["seal of justice"] = &PaladinAiObjectContextInternal::seal_of_justice; - creators["seal of righteousness"] = &PaladinAiObjectContextInternal::seal_of_righteousness; - creators["flash of light"] = &PaladinAiObjectContextInternal::flash_of_light; - creators["hand of reckoning"] = &PaladinAiObjectContextInternal::hand_of_reckoning; - creators["avenger's shield"] = &PaladinAiObjectContextInternal::avengers_shield; - creators["exorcism"] = &PaladinAiObjectContextInternal::exorcism; - creators["judgement"] = &PaladinAiObjectContextInternal::judgement; - creators["judgement of light"] = &PaladinAiObjectContextInternal::judgement_of_light; - creators["judgement of wisdom"] = &PaladinAiObjectContextInternal::judgement_of_wisdom; - creators["divine shield"] = &PaladinAiObjectContextInternal::divine_shield; - creators["divine protection"] = &PaladinAiObjectContextInternal::divine_protection; - creators["divine protection on party"] = &PaladinAiObjectContextInternal::divine_protection_on_party; - creators["hammer of justice"] = &PaladinAiObjectContextInternal::hammer_of_justice; - creators["flash of light on party"] = &PaladinAiObjectContextInternal::flash_of_light_on_party; - creators["holy light"] = &PaladinAiObjectContextInternal::holy_light; - creators["holy light on party"] = &PaladinAiObjectContextInternal::holy_light_on_party; - creators["lay on hands"] = &PaladinAiObjectContextInternal::lay_on_hands; - creators["lay on hands on party"] = &PaladinAiObjectContextInternal::lay_on_hands_on_party; - creators["judgement of justice"] = &PaladinAiObjectContextInternal::judgement_of_justice; - creators["hammer of wrath"] = &PaladinAiObjectContextInternal::hammer_of_wrath; - creators["holy shield"] = &PaladinAiObjectContextInternal::holy_shield; - creators["hammer of the righteous"] = &PaladinAiObjectContextInternal::hammer_of_the_righteous; - creators["retribution aura"] = &PaladinAiObjectContextInternal::retribution_aura; - creators["shadow resistance aura"] = &PaladinAiObjectContextInternal::shadow_resistance_aura; - creators["frost resistance aura"] = &PaladinAiObjectContextInternal::frost_resistance_aura; - creators["fire resistance aura"] = &PaladinAiObjectContextInternal::fire_resistance_aura; - creators["righteous fury"] = &PaladinAiObjectContextInternal::righteous_fury; - creators["hammer of justice on enemy healer"] = - &PaladinAiObjectContextInternal::hammer_of_justice_on_enemy_healer; - creators["hammer of justice on snare target"] = - &PaladinAiObjectContextInternal::hammer_of_justice_on_snare_target; - creators["divine favor"] = &PaladinAiObjectContextInternal::divine_favor; - creators["turn undead"] = &PaladinAiObjectContextInternal::turn_undead; - creators["blessing of protection on party"] = &PaladinAiObjectContextInternal::blessing_of_protection_on_party; - creators["righteous defense"] = &PaladinAiObjectContextInternal::righteous_defense; - creators["repentance"] = &PaladinAiObjectContextInternal::repentance; - creators["repentance on snare target"] = &PaladinAiObjectContextInternal::repentance_on_snare_target; - creators["repentance on enemy healer"] = &PaladinAiObjectContextInternal::repentance_on_enemy_healer; - creators["sanctity aura"] = &PaladinAiObjectContextInternal::sanctity_aura; - creators["holy shock"] = &PaladinAiObjectContextInternal::holy_shock; - creators["holy shock on party"] = &PaladinAiObjectContextInternal::holy_shock_on_party; - creators["divine plea"] = &PaladinAiObjectContextInternal::divine_plea; - creators["shield of righteousness"] = &PaladinAiObjectContextInternal::shield_of_righteousness; - creators["beacon of light on main tank"] = &PaladinAiObjectContextInternal::beacon_of_light_on_main_tank; - creators["sacred shield on main tank"] = &PaladinAiObjectContextInternal::sacred_shield_on_main_tank; - creators["avenging wrath"] = &PaladinAiObjectContextInternal::avenging_wrath; - creators["divine illumination"] = &PaladinAiObjectContextInternal::divine_illumination; - creators["divine sacrifice"] = &PaladinAiObjectContextInternal::divine_sacrifice; - creators["cancel divine sacrifice"] = &PaladinAiObjectContextInternal::cancel_divine_sacrifice; - } - -private: - static Action* blessing_of_protection_on_party(PlayerbotAI* botAI) - { - return new CastBlessingOfProtectionProtectAction(botAI); - } - static Action* turn_undead(PlayerbotAI* botAI) { return new CastTurnUndeadAction(botAI); } - static Action* divine_favor(PlayerbotAI* botAI) { return new CastDivineFavorAction(botAI); } - static Action* righteous_fury(PlayerbotAI* botAI) { return new CastRighteousFuryAction(botAI); } - static Action* seal_of_command(PlayerbotAI* botAI) { return new CastSealOfCommandAction(botAI); } - static Action* seal_of_vengeance(PlayerbotAI* botAI) { return new CastSealOfVengeanceAction(botAI); } - static Action* seal_of_corruption(PlayerbotAI* botAI) { return new CastSealOfCorruptionAction(botAI); } - static Action* blessing_of_sanctuary(PlayerbotAI* botAI) { return new CastBlessingOfSanctuaryAction(botAI); } - static Action* blessing_of_might(PlayerbotAI* botAI) { return new CastBlessingOfMightAction(botAI); } - static Action* blessing_of_wisdom(PlayerbotAI* botAI) { return new CastBlessingOfWisdomAction(botAI); } - static Action* blessing_of_kings(PlayerbotAI* botAI) { return new CastBlessingOfKingsAction(botAI); } - static Action* divine_storm(PlayerbotAI* botAI) { return new CastDivineStormAction(botAI); } - static Action* blessing_of_kings_on_party(PlayerbotAI* botAI) - { - return new CastBlessingOfKingsOnPartyAction(botAI); - } - static Action* blessing_of_might_on_party(PlayerbotAI* botAI) - { - return new CastBlessingOfMightOnPartyAction(botAI); - } - static Action* blessing_of_wisdom_on_party(PlayerbotAI* botAI) - { - return new CastBlessingOfWisdomOnPartyAction(botAI); - } - static Action* blessing_of_sanctuary_on_party(PlayerbotAI* botAI) - { - return new CastBlessingOfSanctuaryOnPartyAction(botAI); - } - static Action* redemption(PlayerbotAI* botAI) { return new CastRedemptionAction(botAI); } - static Action* crusader_strike(PlayerbotAI* botAI) { return new CastCrusaderStrikeAction(botAI); } - static Action* crusader_aura(PlayerbotAI* botAI) { return new CastCrusaderAuraAction(botAI); } - static Action* seal_of_light(PlayerbotAI* botAI) { return new CastSealOfLightAction(botAI); } - static Action* devotion_aura(PlayerbotAI* botAI) { return new CastDevotionAuraAction(botAI); } - static Action* concentration_aura(PlayerbotAI* botAI) { return new CastConcentrationAuraAction(botAI); } - static Action* holy_wrath(PlayerbotAI* botAI) { return new CastHolyWrathAction(botAI); } - static Action* consecration(PlayerbotAI* botAI) { return new CastConsecrationAction(botAI); } - static Action* cleanse_poison(PlayerbotAI* botAI) { return new CastCleansePoisonAction(botAI); } - static Action* cleanse_disease(PlayerbotAI* botAI) { return new CastCleanseDiseaseAction(botAI); } - static Action* cleanse_magic(PlayerbotAI* botAI) { return new CastCleanseMagicAction(botAI); } - static Action* purify_poison(PlayerbotAI* botAI) { return new CastPurifyPoisonAction(botAI); } - static Action* purify_disease(PlayerbotAI* botAI) { return new CastPurifyDiseaseAction(botAI); } - static Action* cleanse_poison_on_party(PlayerbotAI* botAI) { return new CastCleansePoisonOnPartyAction(botAI); } - static Action* cleanse_disease_on_party(PlayerbotAI* botAI) { return new CastCleanseDiseaseOnPartyAction(botAI); } - static Action* cleanse_magic_on_party(PlayerbotAI* botAI) { return new CastCleanseMagicOnPartyAction(botAI); } - static Action* purify_poison_on_party(PlayerbotAI* botAI) { return new CastPurifyPoisonOnPartyAction(botAI); } - static Action* purify_disease_on_party(PlayerbotAI* botAI) { return new CastPurifyDiseaseOnPartyAction(botAI); } - static Action* seal_of_wisdom(PlayerbotAI* botAI) { return new CastSealOfWisdomAction(botAI); } - static Action* seal_of_justice(PlayerbotAI* botAI) { return new CastSealOfJusticeAction(botAI); } - static Action* seal_of_righteousness(PlayerbotAI* botAI) { return new CastSealOfRighteousnessAction(botAI); } - static Action* flash_of_light(PlayerbotAI* botAI) { return new CastFlashOfLightAction(botAI); } - static Action* hand_of_reckoning(PlayerbotAI* botAI) { return new CastHandOfReckoningAction(botAI); } - static Action* avengers_shield(PlayerbotAI* botAI) { return new CastAvengersShieldAction(botAI); } - static Action* exorcism(PlayerbotAI* botAI) { return new CastExorcismAction(botAI); } - static Action* judgement(PlayerbotAI* botAI) { return new CastJudgementAction(botAI); } - static Action* judgement_of_light(PlayerbotAI* botAI) { return new CastJudgementOfLightAction(botAI); } - static Action* judgement_of_wisdom(PlayerbotAI* botAI) { return new CastJudgementOfWisdomAction(botAI); } - static Action* divine_shield(PlayerbotAI* botAI) { return new CastDivineShieldAction(botAI); } - static Action* divine_protection(PlayerbotAI* botAI) { return new CastDivineProtectionAction(botAI); } - static Action* divine_protection_on_party(PlayerbotAI* botAI) - { - return new CastDivineProtectionOnPartyAction(botAI); - } - static Action* hammer_of_justice(PlayerbotAI* botAI) { return new CastHammerOfJusticeAction(botAI); } - static Action* flash_of_light_on_party(PlayerbotAI* botAI) { return new CastFlashOfLightOnPartyAction(botAI); } - static Action* holy_light(PlayerbotAI* botAI) { return new CastHolyLightAction(botAI); } - static Action* holy_light_on_party(PlayerbotAI* botAI) { return new CastHolyLightOnPartyAction(botAI); } - static Action* lay_on_hands(PlayerbotAI* botAI) { return new CastLayOnHandsAction(botAI); } - static Action* lay_on_hands_on_party(PlayerbotAI* botAI) { return new CastLayOnHandsOnPartyAction(botAI); } - static Action* judgement_of_justice(PlayerbotAI* botAI) { return new CastJudgementOfJusticeAction(botAI); } - static Action* hammer_of_wrath(PlayerbotAI* botAI) { return new CastHammerOfWrathAction(botAI); } - static Action* holy_shield(PlayerbotAI* botAI) { return new CastHolyShieldAction(botAI); } - static Action* hammer_of_the_righteous(PlayerbotAI* botAI) { return new CastHammerOfTheRighteousAction(botAI); } - static Action* retribution_aura(PlayerbotAI* botAI) { return new CastRetributionAuraAction(botAI); } - static Action* shadow_resistance_aura(PlayerbotAI* botAI) { return new CastShadowResistanceAuraAction(botAI); } - static Action* frost_resistance_aura(PlayerbotAI* botAI) { return new CastFrostResistanceAuraAction(botAI); } - static Action* fire_resistance_aura(PlayerbotAI* botAI) { return new CastFireResistanceAuraAction(botAI); } - static Action* hammer_of_justice_on_enemy_healer(PlayerbotAI* botAI) - { - return new CastHammerOfJusticeOnEnemyHealerAction(botAI); - } - static Action* hammer_of_justice_on_snare_target(PlayerbotAI* botAI) - { - return new CastHammerOfJusticeSnareAction(botAI); - } - static Action* righteous_defense(PlayerbotAI* botAI) { return new CastRighteousDefenseAction(botAI); } - static Action* repentance(PlayerbotAI* botAI) { return new CastRepentanceAction(botAI); } - static Action* repentance_on_snare_target(PlayerbotAI* botAI) { return new CastRepentanceSnareAction(botAI); } - static Action* repentance_on_enemy_healer(PlayerbotAI* botAI) { return new CastRepentanceOnHealerAction(botAI); } - static Action* sanctity_aura(PlayerbotAI* botAI) { return new CastSanctityAuraAction(botAI); } - static Action* holy_shock(PlayerbotAI* botAI) { return new CastHolyShockAction(botAI); } - static Action* holy_shock_on_party(PlayerbotAI* botAI) { return new CastHolyShockOnPartyAction(botAI); } - static Action* divine_plea(PlayerbotAI* ai) { return new CastDivinePleaAction(ai); } - static Action* shield_of_righteousness(PlayerbotAI* ai) { return new ShieldOfRighteousnessAction(ai); } - static Action* beacon_of_light_on_main_tank(PlayerbotAI* ai) { return new CastBeaconOfLightOnMainTankAction(ai); } - static Action* sacred_shield_on_main_tank(PlayerbotAI* ai) { return new CastSacredShieldOnMainTankAction(ai); } - static Action* avenging_wrath(PlayerbotAI* ai) { return new CastAvengingWrathAction(ai); } - static Action* divine_illumination(PlayerbotAI* ai) { return new CastDivineIlluminationAction(ai); } - static Action* divine_sacrifice(PlayerbotAI* ai) { return new CastDivineSacrificeAction(ai); } - static Action* cancel_divine_sacrifice(PlayerbotAI* ai) { return new CastCancelDivineSacrificeAction(ai); } -}; - SharedNamedObjectContextList PaladinAiObjectContext::sharedStrategyContexts; -SharedNamedObjectContextList PaladinAiObjectContext::sharedActionContexts; SharedNamedObjectContextList PaladinAiObjectContext::sharedTriggerContexts; SharedNamedObjectContextList PaladinAiObjectContext::sharedValueContexts; PaladinAiObjectContext::PaladinAiObjectContext(PlayerbotAI* botAI) - : AiObjectContext(botAI, sharedStrategyContexts, sharedActionContexts, sharedTriggerContexts, sharedValueContexts) + : AiObjectContext(botAI, sharedStrategyContexts, sharedTriggerContexts, sharedValueContexts) { } void PaladinAiObjectContext::BuildSharedContexts() { BuildSharedStrategyContexts(sharedStrategyContexts); - BuildSharedActionContexts(sharedActionContexts); BuildSharedTriggerContexts(sharedTriggerContexts); BuildSharedValueContexts(sharedValueContexts); } @@ -439,12 +244,6 @@ void PaladinAiObjectContext::BuildSharedStrategyContexts(SharedNamedObjectContex strategyContexts.Add(new PaladinResistanceStrategyFactoryInternal()); } -void PaladinAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts) -{ - AiObjectContext::BuildSharedActionContexts(actionContexts); - actionContexts.Add(new PaladinAiObjectContextInternal()); -} - void PaladinAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts) { AiObjectContext::BuildSharedTriggerContexts(triggerContexts); diff --git a/src/Ai/Class/Paladin/PaladinAiObjectContext.h b/src/Ai/Class/Paladin/PaladinAiObjectContext.h index 4ca5f94beb..7b96a5e7cd 100644 --- a/src/Ai/Class/Paladin/PaladinAiObjectContext.h +++ b/src/Ai/Class/Paladin/PaladinAiObjectContext.h @@ -17,12 +17,10 @@ class PaladinAiObjectContext : public AiObjectContext static void BuildSharedContexts(); static void BuildSharedStrategyContexts(SharedNamedObjectContextList& strategyContexts); - static void BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts); static void BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts); static void BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts); static SharedNamedObjectContextList sharedStrategyContexts; - static SharedNamedObjectContextList sharedActionContexts; static SharedNamedObjectContextList sharedTriggerContexts; static SharedNamedObjectContextList sharedValueContexts; }; diff --git a/src/Ai/Class/Paladin/Strategy/DpsPaladinStrategy.cpp b/src/Ai/Class/Paladin/Strategy/DpsPaladinStrategy.cpp index 185fb72d76..da7b5a2762 100644 --- a/src/Ai/Class/Paladin/Strategy/DpsPaladinStrategy.cpp +++ b/src/Ai/Class/Paladin/Strategy/DpsPaladinStrategy.cpp @@ -4,9 +4,10 @@ */ #include "DpsPaladinStrategy.h" - -#include "Playerbots.h" -#include "Strategy.h" +#include "CreateNextAction.h" +#include "GenericActions.h" +#include "PaladinActions.h" +#include "ReachTargetActions.h" class DpsPaladinStrategyActionNodeFactory : public NamedObjectFactory { @@ -30,9 +31,8 @@ class DpsPaladinStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -40,9 +40,8 @@ class DpsPaladinStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -50,9 +49,8 @@ class DpsPaladinStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -60,9 +58,8 @@ class DpsPaladinStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -70,7 +67,6 @@ class DpsPaladinStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -90,9 +85,8 @@ class DpsPaladinStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -100,9 +94,8 @@ class DpsPaladinStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -110,9 +103,8 @@ class DpsPaladinStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -120,9 +112,8 @@ class DpsPaladinStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -130,9 +121,8 @@ class DpsPaladinStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -146,12 +136,12 @@ DpsPaladinStrategy::DpsPaladinStrategy(PlayerbotAI* botAI) : GenericPaladinStrat std::vector DpsPaladinStrategy::getDefaultActions() { return { - NextAction("hammer of wrath", ACTION_DEFAULT + 0.6f), - NextAction("judgement of wisdom", ACTION_DEFAULT + 0.5f), - NextAction("crusader strike", ACTION_DEFAULT + 0.4f), - NextAction("divine storm", ACTION_DEFAULT + 0.3f), - NextAction("consecration", ACTION_DEFAULT + 0.1f), - NextAction("melee", ACTION_DEFAULT) + CreateNextAction(ACTION_DEFAULT + 0.6f), + CreateNextAction(ACTION_DEFAULT + 0.5f), + CreateNextAction(ACTION_DEFAULT + 0.4f), + CreateNextAction(ACTION_DEFAULT + 0.3f), + CreateNextAction(ACTION_DEFAULT + 0.1f), + CreateNextAction(ACTION_DEFAULT) }; } @@ -163,7 +153,7 @@ void DpsPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "art of war", { - NextAction("exorcism", ACTION_DEFAULT + 0.2f) + CreateNextAction(ACTION_DEFAULT + 0.2f) } ) ); @@ -171,7 +161,7 @@ void DpsPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "seal", { - NextAction("seal of corruption", ACTION_HIGH) + CreateNextAction(ACTION_HIGH) } ) ); @@ -179,7 +169,7 @@ void DpsPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "low mana", { - NextAction("seal of wisdom", ACTION_HIGH + 5) + CreateNextAction(ACTION_HIGH + 5.0f) } ) ); @@ -188,7 +178,7 @@ void DpsPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "avenging wrath", { - NextAction("avenging wrath", ACTION_HIGH + 2) + CreateNextAction(ACTION_HIGH + 2.0f) } ) ); @@ -196,8 +186,8 @@ void DpsPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "medium aoe", { - NextAction("divine storm", ACTION_HIGH + 4), - NextAction("consecration", ACTION_HIGH + 3) + CreateNextAction(ACTION_HIGH + 4.0f), + CreateNextAction(ACTION_HIGH + 3.0f) } ) ); @@ -205,7 +195,7 @@ void DpsPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "enemy out of melee", { - NextAction("reach melee", ACTION_HIGH + 1) + CreateNextAction(ACTION_HIGH + 1.0f) } ) ); diff --git a/src/Ai/Class/Paladin/Strategy/GenericPaladinNonCombatStrategy.cpp b/src/Ai/Class/Paladin/Strategy/GenericPaladinNonCombatStrategy.cpp index 7f9919e06b..90a649f8a1 100644 --- a/src/Ai/Class/Paladin/Strategy/GenericPaladinNonCombatStrategy.cpp +++ b/src/Ai/Class/Paladin/Strategy/GenericPaladinNonCombatStrategy.cpp @@ -5,9 +5,11 @@ #include "GenericPaladinNonCombatStrategy.h" +#include "CreateNextAction.h" #include "GenericPaladinStrategyActionNodeFactory.h" -#include "Playerbots.h" #include "AiFactory.h" +#include "ImbueAction.h" +#include "PaladinActions.h" GenericPaladinNonCombatStrategy::GenericPaladinNonCombatStrategy(PlayerbotAI* botAI) : NonCombatStrategy(botAI) { @@ -18,15 +20,72 @@ void GenericPaladinNonCombatStrategy::InitTriggers(std::vector& tr { NonCombatStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("party member dead", { NextAction("redemption", ACTION_CRITICAL_HEAL + 10) })); - triggers.push_back(new TriggerNode("party member almost full health", { NextAction("flash of light on party", 25.0f) })); - triggers.push_back(new TriggerNode("party member medium health", { NextAction("flash of light on party", 26.0f) })); - triggers.push_back(new TriggerNode("party member low health", { NextAction("holy light on party", 27.0f) })); - triggers.push_back(new TriggerNode("party member critical health", { NextAction("holy light on party", 28.0f) })); - - int specTab = AiFactory::GetPlayerSpecTab(botAI->GetBot()); - if (specTab == 0 || specTab == 1) // Holy or Protection - triggers.push_back(new TriggerNode("often", { NextAction("apply oil", 1.0f) })); - if (specTab == 2) // Retribution - triggers.push_back(new TriggerNode("often", { NextAction("apply stone", 1.0f) })); + triggers.push_back( + new TriggerNode( + "party member dead", + { + CreateNextAction(ACTION_CRITICAL_HEAL + 10.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member almost full health", + { + CreateNextAction(25.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member medium health", + { + CreateNextAction(26.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member low health", + { + CreateNextAction(27.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member critical health", + { + CreateNextAction(28.0f) + } + ) + ); + + const uint8_t specTab = AiFactory::GetPlayerSpecTab(botAI->GetBot()); + + // Holy or Protection + if (specTab == PALADIN_TAB_HOLY || specTab == PALADIN_TAB_PROTECTION) + { + triggers.push_back( + new TriggerNode( + "often", + { + CreateNextAction(1.0f) + } + ) + ); + } + + // Retribution + if (specTab == PALADIN_TAB_RETRIBUTION) + { + triggers.push_back( + new TriggerNode( + "often", + { + CreateNextAction(1.0f) + } + ) + ); + } } diff --git a/src/Ai/Class/Paladin/Strategy/GenericPaladinStrategy.cpp b/src/Ai/Class/Paladin/Strategy/GenericPaladinStrategy.cpp index 62d7dfb10b..0d1aa746a1 100644 --- a/src/Ai/Class/Paladin/Strategy/GenericPaladinStrategy.cpp +++ b/src/Ai/Class/Paladin/Strategy/GenericPaladinStrategy.cpp @@ -5,8 +5,9 @@ #include "GenericPaladinStrategy.h" +#include "CreateNextAction.h" #include "GenericPaladinStrategyActionNodeFactory.h" -#include "Playerbots.h" +#include "PaladinActions.h" GenericPaladinStrategy::GenericPaladinStrategy(PlayerbotAI* botAI) : CombatStrategy(botAI) { @@ -17,71 +18,154 @@ void GenericPaladinStrategy::InitTriggers(std::vector& triggers) { CombatStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("critical health", { NextAction("divine shield", - ACTION_HIGH + 5) })); - triggers.push_back( - new TriggerNode("hammer of justice interrupt", - { NextAction("hammer of justice", ACTION_INTERRUPT) })); - triggers.push_back(new TriggerNode( - "hammer of justice on enemy healer", - { NextAction("hammer of justice on enemy healer", ACTION_INTERRUPT) })); - triggers.push_back(new TriggerNode( - "hammer of justice on snare target", - { NextAction("hammer of justice on snare target", ACTION_INTERRUPT) })); - triggers.push_back(new TriggerNode( - "critical health", { NextAction("lay on hands", ACTION_EMERGENCY) })); - triggers.push_back( - new TriggerNode("party member critical health", - { NextAction("lay on hands on party", ACTION_EMERGENCY + 1) })); - triggers.push_back(new TriggerNode( - "protect party member", - { NextAction("blessing of protection on party", ACTION_EMERGENCY + 2) })); - triggers.push_back( - new TriggerNode("high mana", { NextAction("divine plea", ACTION_HIGH) })); + triggers.push_back( + new TriggerNode( + "critical health", + { + CreateNextAction(ACTION_HIGH + 5.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "hammer of justice interrupt", + { + CreateNextAction(ACTION_INTERRUPT) + } + ) + ); + triggers.push_back( + new TriggerNode( + "hammer of justice on enemy healer", + { + CreateNextAction(ACTION_INTERRUPT) + } + ) + ); + triggers.push_back( + new TriggerNode( + "hammer of justice on snare target", + { + CreateNextAction(ACTION_INTERRUPT) + } + ) + ); + triggers.push_back( + new TriggerNode( + "critical health", + { + CreateNextAction(ACTION_EMERGENCY) + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member critical health", + { + CreateNextAction(ACTION_EMERGENCY + 1.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "protect party member", + { + CreateNextAction(ACTION_EMERGENCY + 2.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "high mana", + { + CreateNextAction(ACTION_HIGH) + } + ) + ); } void PaladinCureStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode( - "cleanse cure disease", { NextAction("cleanse disease", ACTION_DISPEL + 2) })); triggers.push_back( - new TriggerNode("cleanse party member cure disease", - { NextAction("cleanse disease on party", ACTION_DISPEL + 1) })); - triggers.push_back(new TriggerNode( - "cleanse cure poison", { NextAction("cleanse poison", ACTION_DISPEL + 2) })); + new TriggerNode( + "cleanse cure disease", + { + CreateNextAction(ACTION_DISPEL + 2.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "cleanse party member cure disease", + { + CreateNextAction(ACTION_DISPEL + 1.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "cleanse cure poison", + { + CreateNextAction(ACTION_DISPEL + 2.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "cleanse party member cure poison", + { + CreateNextAction(ACTION_DISPEL + 1.0f) + } + ) + ); triggers.push_back( - new TriggerNode("cleanse party member cure poison", - { NextAction("cleanse poison on party", ACTION_DISPEL + 1) })); - triggers.push_back(new TriggerNode( - "cleanse cure magic", { NextAction("cleanse magic", ACTION_DISPEL + 2) })); + new TriggerNode( + "cleanse cure magic", + { + CreateNextAction(ACTION_DISPEL + 2.0f) + } + ) + ); triggers.push_back( - new TriggerNode("cleanse party member cure magic", - { NextAction("cleanse magic on party", ACTION_DISPEL + 1) })); + new TriggerNode( + "cleanse party member cure magic", + { + CreateNextAction(ACTION_DISPEL + 1.0f) + } + ) + ); } -void PaladinBoostStrategy::InitTriggers(std::vector& triggers) +void PaladinBoostStrategy::InitTriggers(std::vector&) { - // triggers.push_back(new TriggerNode("divine favor", { NextAction("divine favor", - // ACTION_HIGH + 1) })); } void PaladinCcStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("turn undead", { NextAction("turn undead", ACTION_HIGH + 1) })); + new TriggerNode( + "turn undead", + { + CreateNextAction(ACTION_HIGH + 1.0f) + } + ) + ); } void PaladinHealerDpsStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("healer should attack", - { - NextAction("hammer of wrath", ACTION_DEFAULT + 0.6f), - NextAction("holy shock", ACTION_DEFAULT + 0.5f), - NextAction("shield of righteousness", ACTION_DEFAULT + 0.4f), - NextAction("judgement of light", ACTION_DEFAULT + 0.3f), - NextAction("consecration", ACTION_DEFAULT + 0.2f), - NextAction("exorcism", ACTION_DEFAULT+ 0.1f), - })); + new TriggerNode( + "healer should attack", + { + CreateNextAction(ACTION_DEFAULT + 0.6f), + CreateNextAction(ACTION_DEFAULT + 0.5f), + CreateNextAction(ACTION_DEFAULT + 0.4f), + CreateNextAction(ACTION_DEFAULT + 0.3f), + CreateNextAction(ACTION_DEFAULT + 0.2f), + CreateNextAction(ACTION_DEFAULT + 0.1f), + } + ) + ); } diff --git a/src/Ai/Class/Paladin/Strategy/GenericPaladinStrategyActionNodeFactory.h b/src/Ai/Class/Paladin/Strategy/GenericPaladinStrategyActionNodeFactory.h index f1d0d342e3..0eeaa8d799 100644 --- a/src/Ai/Class/Paladin/Strategy/GenericPaladinStrategyActionNodeFactory.h +++ b/src/Ai/Class/Paladin/Strategy/GenericPaladinStrategyActionNodeFactory.h @@ -7,7 +7,10 @@ #define _PLAYERBOT_GENERICPALADINSTRATEGYACTIONNODEFACTORY_H #include "Action.h" +#include "ActionNode.h" +#include "CreateNextAction.h" #include "NamedObjectContext.h" +#include "PaladinActions.h" class PlayerbotAI; @@ -51,207 +54,227 @@ class GenericPaladinStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, + /*C*/ {} + ); } static ActionNode* lay_on_hands(PlayerbotAI* /* ai */) { - return new ActionNode("lay on hands", - /*P*/ {}, - /*A*/ {}, // { NextAction("divine shield"), new - // NextAction("flash of light"), NULL), - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* lay_on_hands_on_party(PlayerbotAI* /* ai */) { - return new ActionNode("lay on hands on party", - /*P*/ {}, - /*A*/ {}, // { NextAction("flash of light"), NULL), - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ {}, + /*C*/ {} + ); } - // static ActionNode* seal_of_light(PlayerbotAI* /* ai */) - // { - // return new ActionNode ("seal of light", - // /*P*/ NULL, - // /*A*/ { NextAction("seal of justice"), NULL), - // /*C*/ NULL); - // } static ActionNode* cleanse_poison(PlayerbotAI* /* ai */) { - return new ActionNode("cleanse poison", - /*P*/ {}, - /*A*/ { NextAction("purify poison") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* cleanse_magic(PlayerbotAI* /* ai */) { - return new ActionNode("cleanse magic", - /*P*/ {}, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* cleanse_disease(PlayerbotAI* /* ai */) { - return new ActionNode("cleanse disease", - /*P*/ {}, - /*A*/ { NextAction("purify disease") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* cleanse_poison_on_party(PlayerbotAI* /* ai */) { - return new ActionNode("cleanse poison on party", - /*P*/ {}, - /*A*/ { NextAction("purify poison on party") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* cleanse_disease_on_party(PlayerbotAI* /* ai */) { - return new ActionNode("cleanse disease on party", - /*P*/ {}, - /*A*/ { NextAction("purify disease on party") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* seal_of_wisdom(PlayerbotAI* /* ai */) { - return new ActionNode ("seal of wisdom", + return new ActionNode( /*P*/ {}, - /*A*/ { NextAction("seal of righteousness") }, - /*C*/ {}); + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* seal_of_justice(PlayerbotAI* /* ai */) { - return new ActionNode("seal of justice", - /*P*/ {}, - /*A*/ { NextAction("seal of righteousness") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* hand_of_reckoning(PlayerbotAI* /* ai */) { - return new ActionNode("hand of reckoning", - /*P*/ {}, - /*A*/ { NextAction("righteous defense") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* righteous_defense(PlayerbotAI* /* ai */) { - return new ActionNode("righteous defense", - /*P*/ {}, - /*A*/ { NextAction("avenger's shield") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* avengers_shield(PlayerbotAI* /* ai */) { - return new ActionNode("avenger's shield", - /*P*/ {}, - /*A*/ { NextAction("judgement of wisdom") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* divine_sacrifice(PlayerbotAI* /* ai */) { - return new ActionNode("divine sacrifice", - /*P*/ {}, - /*A*/ {}, - /*C*/ { NextAction("cancel divine sacrifice") }); + return new ActionNode( + /*P*/ {}, + /*A*/ {}, + /*C*/ { CreateNextAction(1.0f) } + ); } static ActionNode* judgement_of_wisdom(PlayerbotAI* /* ai */) { - return new ActionNode("judgement of wisdom", - /*P*/ {}, - /*A*/ { NextAction("judgement of light") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* judgement(PlayerbotAI* /* ai */) { - return new ActionNode("judgement", - /*P*/ {}, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* divine_shield(PlayerbotAI* /* ai */) { - return new ActionNode("divine shield", - /*P*/ {}, - /*A*/ { NextAction("divine protection") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* flash_of_light(PlayerbotAI* /* ai */) { - return new ActionNode("flash of light", - /*P*/ {}, - /*A*/ { NextAction("holy light") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* flash_of_light_on_party(PlayerbotAI* /* ai */) { - return new ActionNode("flash of light on party", - /*P*/ {}, - /*A*/ { NextAction("holy light on party") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* holy_wrath(PlayerbotAI* /* ai */) { - return new ActionNode("holy wrath", - /*P*/ {}, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* hammer_of_wrath(PlayerbotAI* /* ai */) { - return new ActionNode("hammer of wrath", - /*P*/ {}, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* seal_of_command(PlayerbotAI* /* ai */) { - return new ActionNode("seal of command", - /*P*/ {}, - /*A*/ { NextAction("seal of righteousness") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } }; diff --git a/src/Ai/Class/Paladin/Strategy/HealPaladinStrategy.cpp b/src/Ai/Class/Paladin/Strategy/HealPaladinStrategy.cpp index 5eb1a3acc1..671b0f96ee 100644 --- a/src/Ai/Class/Paladin/Strategy/HealPaladinStrategy.cpp +++ b/src/Ai/Class/Paladin/Strategy/HealPaladinStrategy.cpp @@ -4,9 +4,9 @@ */ #include "HealPaladinStrategy.h" - -#include "Playerbots.h" -#include "Strategy.h" +#include "CreateNextAction.h" +#include "PaladinActions.h" +#include "ReachTargetActions.h" class HealPaladinStrategyActionNodeFactory : public NamedObjectFactory { @@ -19,7 +19,9 @@ HealPaladinStrategy::HealPaladinStrategy(PlayerbotAI* botAI) : GenericPaladinStr std::vector HealPaladinStrategy::getDefaultActions() { - return { NextAction("judgement of light", ACTION_DEFAULT) }; + return { + CreateNextAction(ACTION_DEFAULT) + }; } void HealPaladinStrategy::InitTriggers(std::vector& triggers) @@ -30,7 +32,7 @@ void HealPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "seal", { - NextAction("seal of wisdom", ACTION_HIGH) + CreateNextAction(ACTION_HIGH) } ) ); @@ -38,7 +40,7 @@ void HealPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "medium mana", { - NextAction("divine illumination", ACTION_HIGH + 2) + CreateNextAction(ACTION_HIGH + 2.0f) } ) ); @@ -46,7 +48,7 @@ void HealPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "low mana", { - NextAction("divine favor", ACTION_HIGH + 1) + CreateNextAction(ACTION_HIGH + 1.0f) } ) ); @@ -54,7 +56,7 @@ void HealPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "party member to heal out of spell range", { - NextAction("reach party member to heal", ACTION_EMERGENCY + 3) + CreateNextAction(ACTION_EMERGENCY + 3.0f) } ) ); @@ -62,8 +64,8 @@ void HealPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "medium group heal setting", { - NextAction("divine sacrifice", ACTION_CRITICAL_HEAL + 5), - NextAction("avenging wrath", ACTION_HIGH + 4), + CreateNextAction(ACTION_CRITICAL_HEAL + 5.0f), + CreateNextAction(ACTION_HIGH + 4), } ) ); @@ -71,9 +73,9 @@ void HealPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "party member critical health", { - NextAction("holy shock on party", ACTION_CRITICAL_HEAL + 6), - NextAction("divine sacrifice", ACTION_CRITICAL_HEAL + 5), - NextAction("holy light on party", ACTION_CRITICAL_HEAL + 4) + CreateNextAction(ACTION_CRITICAL_HEAL + 6.0f), + CreateNextAction(ACTION_CRITICAL_HEAL + 5.0f), + CreateNextAction(ACTION_CRITICAL_HEAL + 4.0f) } ) ); @@ -81,7 +83,7 @@ void HealPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "party member low health", { - NextAction("holy light on party", ACTION_MEDIUM_HEAL + 5) + CreateNextAction(ACTION_MEDIUM_HEAL + 5.0f) } ) ); @@ -89,36 +91,34 @@ void HealPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "party member medium health", { - NextAction("holy light on party", ACTION_LIGHT_HEAL + 9), - NextAction("flash of light on party", ACTION_LIGHT_HEAL + 8) + CreateNextAction(ACTION_LIGHT_HEAL + 9.0f), + CreateNextAction(ACTION_LIGHT_HEAL + 8.0f) } ) ); triggers.push_back( new TriggerNode( - "party member almost full health", - { - NextAction("flash of light on party", ACTION_LIGHT_HEAL + 3) - } - ) -); - + "party member almost full health", + { + CreateNextAction(ACTION_LIGHT_HEAL + 3.0f) + } + ) + ); triggers.push_back( new TriggerNode( - "beacon of light on main tank", - { - NextAction("beacon of light on main tank", ACTION_CRITICAL_HEAL + 7) - } - ) -); - + "beacon of light on main tank", + { + CreateNextAction(ACTION_CRITICAL_HEAL + 7.0f) + } + ) + ); triggers.push_back( new TriggerNode( - "sacred shield on main tank", - { - NextAction("sacred shield on main tank", ACTION_CRITICAL_HEAL + 6) - } - ) + "sacred shield on main tank", + { + CreateNextAction(ACTION_CRITICAL_HEAL + 6.0f) + } + ) ); } diff --git a/src/Ai/Class/Paladin/Strategy/OffhealRetPaladinStrategy.cpp b/src/Ai/Class/Paladin/Strategy/OffhealRetPaladinStrategy.cpp index b25fc36b35..ae4d1c828f 100644 --- a/src/Ai/Class/Paladin/Strategy/OffhealRetPaladinStrategy.cpp +++ b/src/Ai/Class/Paladin/Strategy/OffhealRetPaladinStrategy.cpp @@ -4,9 +4,10 @@ */ #include "OffhealRetPaladinStrategy.h" - -#include "Playerbots.h" -#include "Strategy.h" +#include "CreateNextAction.h" +#include "GenericActions.h" +#include "PaladinActions.h" +#include "ReachTargetActions.h" class OffhealRetPaladinStrategyActionNodeFactory : public NamedObjectFactory { @@ -26,9 +27,8 @@ class OffhealRetPaladinStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -36,9 +36,8 @@ class OffhealRetPaladinStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -46,9 +45,8 @@ class OffhealRetPaladinStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -56,9 +54,8 @@ class OffhealRetPaladinStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -66,9 +63,8 @@ class OffhealRetPaladinStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -76,7 +72,6 @@ class OffhealRetPaladinStrategyActionNodeFactory : public NamedObjectFactory OffhealRetPaladinStrategy::getDefaultActions() { return { - NextAction("hammer of wrath", ACTION_DEFAULT + 0.6f), - NextAction("judgement of wisdom", ACTION_DEFAULT + 0.5f), - NextAction("crusader strike", ACTION_DEFAULT + 0.4f), - NextAction("divine storm", ACTION_DEFAULT + 0.3f), - NextAction("melee", ACTION_DEFAULT) + CreateNextAction(ACTION_DEFAULT + 0.6f), + CreateNextAction(ACTION_DEFAULT + 0.5f), + CreateNextAction(ACTION_DEFAULT + 0.4f), + CreateNextAction(ACTION_DEFAULT + 0.3f), + CreateNextAction(ACTION_DEFAULT) }; } @@ -119,7 +113,7 @@ void OffhealRetPaladinStrategy::InitTriggers(std::vector& triggers new TriggerNode( "seal", { - NextAction("seal of corruption", ACTION_HIGH) + CreateNextAction(ACTION_HIGH) } ) ); @@ -127,8 +121,8 @@ void OffhealRetPaladinStrategy::InitTriggers(std::vector& triggers new TriggerNode( "low mana", { - NextAction("seal of wisdom", ACTION_HIGH + 5), - NextAction("divine plea", ACTION_HIGH + 4) + CreateNextAction(ACTION_HIGH + 5.0f), + CreateNextAction(ACTION_HIGH + 4.0f) } ) ); @@ -136,7 +130,7 @@ void OffhealRetPaladinStrategy::InitTriggers(std::vector& triggers new TriggerNode( "art of war", { - NextAction("exorcism", ACTION_HIGH + 1) + CreateNextAction(ACTION_HIGH + 1.0f) } ) ); @@ -144,7 +138,7 @@ void OffhealRetPaladinStrategy::InitTriggers(std::vector& triggers new TriggerNode( "avenging wrath", { - NextAction("avenging wrath", ACTION_HIGH + 2) + CreateNextAction(ACTION_HIGH + 2.0f) } ) ); @@ -152,8 +146,8 @@ void OffhealRetPaladinStrategy::InitTriggers(std::vector& triggers new TriggerNode( "medium aoe", { - NextAction("divine storm", ACTION_HIGH + 4), - NextAction("consecration", ACTION_HIGH + 3) + CreateNextAction(ACTION_HIGH + 4.0f), + CreateNextAction(ACTION_HIGH + 3.0f) } ) ); @@ -161,7 +155,7 @@ void OffhealRetPaladinStrategy::InitTriggers(std::vector& triggers new TriggerNode( "enemy out of melee", { - NextAction("reach melee", ACTION_HIGH + 1) + CreateNextAction(ACTION_HIGH + 1.0f) } ) ); @@ -169,7 +163,7 @@ void OffhealRetPaladinStrategy::InitTriggers(std::vector& triggers new TriggerNode( "retribution aura", { - NextAction("retribution aura", ACTION_NORMAL) + CreateNextAction(ACTION_NORMAL) } ) ); @@ -177,7 +171,7 @@ void OffhealRetPaladinStrategy::InitTriggers(std::vector& triggers new TriggerNode( "blessing of might", { - NextAction("blessing of might", ACTION_NORMAL + 1) + CreateNextAction(ACTION_NORMAL + 1.0f) } ) ); @@ -185,7 +179,7 @@ void OffhealRetPaladinStrategy::InitTriggers(std::vector& triggers new TriggerNode( "low health", { - NextAction("holy light", ACTION_CRITICAL_HEAL + 2) + CreateNextAction(ACTION_CRITICAL_HEAL + 2.0f) } ) ); @@ -195,8 +189,8 @@ void OffhealRetPaladinStrategy::InitTriggers(std::vector& triggers new TriggerNode( "party member critical health", { - NextAction("holy shock on party", ACTION_CRITICAL_HEAL + 6), - NextAction("holy light on party", ACTION_CRITICAL_HEAL + 4) + CreateNextAction(ACTION_CRITICAL_HEAL + 6.0f), + CreateNextAction(ACTION_CRITICAL_HEAL + 4.0f) } ) ); @@ -204,7 +198,7 @@ void OffhealRetPaladinStrategy::InitTriggers(std::vector& triggers new TriggerNode( "party member low health", { - NextAction("holy light on party", ACTION_MEDIUM_HEAL + 5) + CreateNextAction(ACTION_MEDIUM_HEAL + 5.0f) } ) ); @@ -212,7 +206,7 @@ void OffhealRetPaladinStrategy::InitTriggers(std::vector& triggers new TriggerNode( "party member medium health", { - NextAction("flash of light on party", ACTION_LIGHT_HEAL + 8) + CreateNextAction(ACTION_LIGHT_HEAL + 8.0f) } ) ); @@ -220,7 +214,7 @@ void OffhealRetPaladinStrategy::InitTriggers(std::vector& triggers new TriggerNode( "party member almost full health", { - NextAction("flash of light on party", ACTION_LIGHT_HEAL + 3) + CreateNextAction(ACTION_LIGHT_HEAL + 3.0f) } ) ); @@ -228,7 +222,7 @@ void OffhealRetPaladinStrategy::InitTriggers(std::vector& triggers new TriggerNode( "party member to heal out of spell range", { - NextAction("reach party member to heal", ACTION_EMERGENCY + 3) + CreateNextAction(ACTION_EMERGENCY + 3.0f) } ) ); @@ -236,7 +230,7 @@ void OffhealRetPaladinStrategy::InitTriggers(std::vector& triggers new TriggerNode( "beacon of light on main tank", { - NextAction("beacon of light on main tank", ACTION_CRITICAL_HEAL + 7) + CreateNextAction(ACTION_CRITICAL_HEAL + 7.0f) } ) ); diff --git a/src/Ai/Class/Paladin/Strategy/PaladinBuffStrategies.cpp b/src/Ai/Class/Paladin/Strategy/PaladinBuffStrategies.cpp index 884c2f2779..517db29120 100644 --- a/src/Ai/Class/Paladin/Strategy/PaladinBuffStrategies.cpp +++ b/src/Ai/Class/Paladin/Strategy/PaladinBuffStrategies.cpp @@ -4,91 +4,168 @@ */ #include "PaladinBuffStrategies.h" - -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "PaladinActions.h" void PaladinBuffManaStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("blessing of wisdom on party", - { NextAction("blessing of wisdom on party", 11.0f) })); - - triggers.push_back(new TriggerNode("blessing of kings on party", - { NextAction("blessing of kings on party", 10.5f) })); + triggers.push_back( + new TriggerNode( + "blessing of wisdom on party", + { + CreateNextAction(11.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "blessing of kings on party", + { + CreateNextAction(10.5f) + } + ) + ); } void PaladinBuffHealthStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("blessing of sanctuary on party", - { NextAction("blessing of sanctuary on party", 11.0f) })); + new TriggerNode( + "blessing of sanctuary on party", + { + CreateNextAction(11.0f) + } + ) + ); } void PaladinBuffDpsStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("blessing of might on party", - { NextAction("blessing of might on party", 11.0f) })); + new TriggerNode( + "blessing of might on party", + { + CreateNextAction(11.0f) + } + ) + ); } void PaladinShadowResistanceStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("shadow resistance aura", - { NextAction("shadow resistance aura", ACTION_NORMAL) })); + new TriggerNode( + "shadow resistance aura", + { + CreateNextAction(ACTION_NORMAL) + } + ) + ); } void PaladinFrostResistanceStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("frost resistance aura", - { NextAction("frost resistance aura", ACTION_NORMAL) })); + new TriggerNode( + "frost resistance aura", + { + CreateNextAction(ACTION_NORMAL) + } + ) + ); } void PaladinFireResistanceStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode( - "fire resistance aura", { NextAction("fire resistance aura", ACTION_NORMAL) })); + triggers.push_back( + new TriggerNode( + "fire resistance aura", + { + CreateNextAction(ACTION_NORMAL) + } + ) + ); } void PaladinBuffArmorStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("devotion aura", - { NextAction("devotion aura", ACTION_NORMAL) })); + triggers.push_back( + new TriggerNode( + "devotion aura", + { + CreateNextAction(ACTION_NORMAL) + } + ) + ); } void PaladinBuffAoeStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode( - "retribution aura", { NextAction("retribution aura", ACTION_NORMAL) })); + triggers.push_back( + new TriggerNode( + "retribution aura", + { + CreateNextAction(ACTION_NORMAL) + } + ) + ); } void PaladinBuffCastStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode( - "concentration aura", { NextAction("concentration aura", ACTION_NORMAL) })); + triggers.push_back( + new TriggerNode( + "concentration aura", + { + CreateNextAction(ACTION_NORMAL) + } + ) + ); } void PaladinBuffSpeedStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode( - "crusader aura", { NextAction("crusader aura", ACTION_NORMAL) })); + triggers.push_back( + new TriggerNode( + "crusader aura", + { + CreateNextAction(ACTION_NORMAL) + } + ) + ); } void PaladinBuffThreatStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode( - "righteous fury", { NextAction("righteous fury", ACTION_HIGH + 8) })); + triggers.push_back( + new TriggerNode( + "righteous fury", + { + CreateNextAction(ACTION_HIGH + 8.0f) + } + ) + ); } void PaladinBuffStatsStrategy::InitTriggers(std::vector& triggers) { // First Sanctuary (prio > Kings) triggers.push_back( - new TriggerNode("blessing of sanctuary on party", - { NextAction("blessing of sanctuary on party", 12.0f) })); + new TriggerNode( + "blessing of sanctuary on party", + { + CreateNextAction(12.0f) + } + ) + ); // After Kings triggers.push_back( - new TriggerNode("blessing of kings on party", - { NextAction("blessing of kings on party", 11.0f) })); + new TriggerNode( + "blessing of kings on party", + { + CreateNextAction(11.0f) + } + ) + ); } diff --git a/src/Ai/Class/Paladin/Strategy/TankPaladinStrategy.cpp b/src/Ai/Class/Paladin/Strategy/TankPaladinStrategy.cpp index b76116e043..5c15fe1c5f 100644 --- a/src/Ai/Class/Paladin/Strategy/TankPaladinStrategy.cpp +++ b/src/Ai/Class/Paladin/Strategy/TankPaladinStrategy.cpp @@ -4,8 +4,10 @@ */ #include "TankPaladinStrategy.h" - -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "GenericActions.h" +#include "PaladinActions.h" +#include "ReachTargetActions.h" class TankPaladinStrategyActionNodeFactory : public NamedObjectFactory { @@ -23,18 +25,16 @@ class TankPaladinStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } static ActionNode* seal_of_corruption([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "seal of corruption", /*P*/ {}, - /*A*/ { NextAction("seal of vengeance") }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } @@ -42,9 +42,8 @@ class TankPaladinStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -52,9 +51,8 @@ class TankPaladinStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -68,10 +66,10 @@ TankPaladinStrategy::TankPaladinStrategy(PlayerbotAI* botAI) : GenericPaladinStr std::vector TankPaladinStrategy::getDefaultActions() { return { - NextAction("shield of righteousness", ACTION_DEFAULT + 0.6f), - NextAction("hammer of the righteous", ACTION_DEFAULT + 0.5f), - NextAction("judgement of wisdom", ACTION_DEFAULT + 0.4f), - NextAction("melee", ACTION_DEFAULT) + CreateNextAction(ACTION_DEFAULT + 0.6f), + CreateNextAction(ACTION_DEFAULT + 0.5f), + CreateNextAction(ACTION_DEFAULT + 0.4f), + CreateNextAction(ACTION_DEFAULT) }; } @@ -83,7 +81,7 @@ void TankPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "seal", { - NextAction("seal of corruption", ACTION_HIGH) + CreateNextAction(ACTION_HIGH) } ) ); @@ -91,14 +89,14 @@ void TankPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "low mana", { - NextAction("seal of wisdom", ACTION_HIGH + 9) + CreateNextAction(ACTION_HIGH + 9.0f) } ) ); triggers.push_back(new TriggerNode( "light aoe", { - NextAction("avenger's shield", ACTION_HIGH + 5) + CreateNextAction(ACTION_HIGH + 5.0f) } ) ); @@ -106,8 +104,8 @@ void TankPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "medium aoe", { - NextAction("consecration", ACTION_HIGH + 7), - NextAction("avenger's shield", ACTION_HIGH + 6) + CreateNextAction(ACTION_HIGH + 7.0f), + CreateNextAction(ACTION_HIGH + 6.0f) } ) ); @@ -115,14 +113,14 @@ void TankPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "lose aggro", { - NextAction("hand of reckoning", ACTION_HIGH + 7) + CreateNextAction(ACTION_HIGH + 7.0f) } ) ); triggers.push_back( new TriggerNode( "medium health", - { NextAction("holy shield", ACTION_HIGH + 4) + { CreateNextAction(ACTION_HIGH + 4.0f) } ) ); @@ -130,7 +128,7 @@ void TankPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "low health", { - NextAction("holy shield", ACTION_HIGH + 4) + CreateNextAction(ACTION_HIGH + 4.0f) } ) ); @@ -138,7 +136,7 @@ void TankPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "critical health", { - NextAction("holy shield", ACTION_HIGH + 4) + CreateNextAction(ACTION_HIGH + 4.0f) } ) ); @@ -146,7 +144,7 @@ void TankPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "avenging wrath", { - NextAction("avenging wrath", ACTION_HIGH + 2) + CreateNextAction(ACTION_HIGH + 2.0f) } ) ); @@ -154,7 +152,7 @@ void TankPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "target critical health", { - NextAction("hammer of wrath", ACTION_CRITICAL_HEAL) + CreateNextAction(ACTION_CRITICAL_HEAL) } ) ); @@ -162,7 +160,7 @@ void TankPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "righteous fury", { - NextAction("righteous fury", ACTION_HIGH + 8) + CreateNextAction(ACTION_HIGH + 8.0f) } ) ); @@ -170,7 +168,7 @@ void TankPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "medium group heal setting", { - NextAction("divine sacrifice", ACTION_HIGH + 5) + CreateNextAction(ACTION_HIGH + 5.0f) } ) ); @@ -178,7 +176,7 @@ void TankPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "enough mana", { - NextAction("consecration", ACTION_HIGH + 4) + CreateNextAction(ACTION_HIGH + 4.0f) } ) ); @@ -186,7 +184,7 @@ void TankPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "not facing target", { - NextAction("set facing", ACTION_NORMAL + 7) + CreateNextAction(ACTION_NORMAL + 7.0f) } ) ); @@ -194,7 +192,7 @@ void TankPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "enemy out of melee", { - NextAction("reach melee", ACTION_HIGH + 1) + CreateNextAction(ACTION_HIGH + 1.0f) } ) ); diff --git a/src/Ai/Class/Priest/Action/PriestActions.cpp b/src/Ai/Class/Priest/Action/PriestActions.cpp index e1c61033a1..0dbbd74cc5 100644 --- a/src/Ai/Class/Priest/Action/PriestActions.cpp +++ b/src/Ai/Class/Priest/Action/PriestActions.cpp @@ -12,7 +12,7 @@ bool CastRemoveShadowformAction::isUseful() { return botAI->HasAura("shadowform" bool CastRemoveShadowformAction::isPossible() { return true; } -bool CastRemoveShadowformAction::Execute(Event event) +bool CastRemoveShadowformAction::Execute(Event) { botAI->RemoveAura("shadowform"); return true; @@ -30,11 +30,11 @@ Unit* CastPowerWordShieldOnAlmostFullHealthBelowAction::GetTarget() { continue; } - if (player->GetHealthPct() > sPlayerbotAIConfig->almostFullHealth) + if (player->GetHealthPct() > sPlayerbotAIConfig.almostFullHealth) { continue; } - if (player->GetDistance2d(bot) > sPlayerbotAIConfig->spellDistance) + if (player->GetDistance2d(bot) > sPlayerbotAIConfig.spellDistance) { continue; } @@ -59,11 +59,11 @@ bool CastPowerWordShieldOnAlmostFullHealthBelowAction::isUseful() { continue; } - if (player->GetHealthPct() > sPlayerbotAIConfig->almostFullHealth) + if (player->GetHealthPct() > sPlayerbotAIConfig.almostFullHealth) { continue; } - if (player->GetDistance2d(bot) > sPlayerbotAIConfig->spellDistance) + if (player->GetDistance2d(bot) > sPlayerbotAIConfig.spellDistance) { continue; } @@ -89,7 +89,7 @@ Unit* CastPowerWordShieldOnNotFullAction::GetTarget() { continue; } - if (player->GetDistance2d(bot) > sPlayerbotAIConfig->spellDistance) + if (player->GetDistance2d(bot) > sPlayerbotAIConfig.spellDistance) { continue; } diff --git a/src/Ai/Class/Priest/PriestAiObjectContext.cpp b/src/Ai/Class/Priest/PriestAiObjectContext.cpp index 7ffac96cca..4e0eb66eae 100644 --- a/src/Ai/Class/Priest/PriestAiObjectContext.cpp +++ b/src/Ai/Class/Priest/PriestAiObjectContext.cpp @@ -8,7 +8,6 @@ #include "GenericPriestStrategy.h" #include "HolyPriestStrategy.h" #include "NamedObjectContext.h" -#include "Playerbots.h" #include "PriestActions.h" #include "PriestNonCombatStrategy.h" #include "PriestTriggers.h" @@ -152,218 +151,18 @@ class PriestTriggerFactoryInternal : public NamedObjectContext static Trigger* mind_sear_channel_check(PlayerbotAI* botAI) { return new MindSearChannelCheckTrigger(botAI); } }; -class PriestAiObjectContextInternal : public NamedObjectContext -{ -public: - PriestAiObjectContextInternal() - { - creators["power infusion"] = &PriestAiObjectContextInternal::power_infusion; - creators["inner focus"] = &PriestAiObjectContextInternal::inner_focus; - creators["shadow word: pain"] = &PriestAiObjectContextInternal::shadow_word_pain; - creators["shadow word: pain on attacker"] = &PriestAiObjectContextInternal::shadow_word_pain_on_attacker; - creators["devouring plague"] = &PriestAiObjectContextInternal::devouring_plague; - creators["mind flay"] = &PriestAiObjectContextInternal::mind_flay; - creators["holy fire"] = &PriestAiObjectContextInternal::holy_fire; - creators["smite"] = &PriestAiObjectContextInternal::smite; - creators["mind blast"] = &PriestAiObjectContextInternal::mind_blast; - creators["shadowform"] = &PriestAiObjectContextInternal::shadowform; - creators["remove shadowform"] = &PriestAiObjectContextInternal::remove_shadowform; - creators["holy nova"] = &PriestAiObjectContextInternal::holy_nova; - creators["power word: fortitude"] = &PriestAiObjectContextInternal::power_word_fortitude; - creators["power word: fortitude on party"] = &PriestAiObjectContextInternal::power_word_fortitude_on_party; - creators["divine spirit"] = &PriestAiObjectContextInternal::divine_spirit; - creators["divine spirit on party"] = &PriestAiObjectContextInternal::divine_spirit_on_party; - creators["power word: shield"] = &PriestAiObjectContextInternal::power_word_shield; - creators["power word: shield on party"] = &PriestAiObjectContextInternal::power_word_shield_on_party; - creators["power word: shield on almost full health below"] = - &PriestAiObjectContextInternal::power_word_shield_on_almost_full_health_below; - creators["power word: shield on not full"] = &PriestAiObjectContextInternal::power_word_shield_on_not_full; - creators["renew"] = &PriestAiObjectContextInternal::renew; - creators["renew on party"] = &PriestAiObjectContextInternal::renew_on_party; - creators["greater heal"] = &PriestAiObjectContextInternal::greater_heal; - creators["greater heal on party"] = &PriestAiObjectContextInternal::greater_heal_on_party; - creators["heal"] = &PriestAiObjectContextInternal::heal; - creators["heal on party"] = &PriestAiObjectContextInternal::heal_on_party; - creators["lesser heal"] = &PriestAiObjectContextInternal::lesser_heal; - creators["lesser heal on party"] = &PriestAiObjectContextInternal::lesser_heal_on_party; - creators["flash heal"] = &PriestAiObjectContextInternal::flash_heal; - creators["flash heal on party"] = &PriestAiObjectContextInternal::flash_heal_on_party; - creators["dispel magic"] = &PriestAiObjectContextInternal::dispel_magic; - creators["dispel magic on party"] = &PriestAiObjectContextInternal::dispel_magic_on_party; - creators["dispel magic on target"] = &PriestAiObjectContextInternal::dispel_magic_on_target; - creators["cure disease"] = &PriestAiObjectContextInternal::cure_disease; - creators["cure disease on party"] = &PriestAiObjectContextInternal::cure_disease_on_party; - creators["abolish disease"] = &PriestAiObjectContextInternal::abolish_disease; - creators["abolish disease on party"] = &PriestAiObjectContextInternal::abolish_disease_on_party; - creators["fade"] = &PriestAiObjectContextInternal::fade; - creators["inner fire"] = &PriestAiObjectContextInternal::inner_fire; - creators["resurrection"] = &PriestAiObjectContextInternal::resurrection; - creators["circle of healing on party"] = &PriestAiObjectContextInternal::circle_of_healing; - creators["psychic scream"] = &PriestAiObjectContextInternal::psychic_scream; - creators["vampiric touch"] = &PriestAiObjectContextInternal::vampiric_touch; - creators["vampiric touch on attacker"] = &PriestAiObjectContextInternal::vampiric_touch_on_attacker; - creators["vampiric embrace"] = &PriestAiObjectContextInternal::vampiric_embrace; - creators["dispersion"] = &PriestAiObjectContextInternal::dispersion; - creators["shadow protection"] = &PriestAiObjectContextInternal::shadow_protection; - creators["shadow protection on party"] = &PriestAiObjectContextInternal::shadow_protection_on_party; - creators["shackle undead"] = &PriestAiObjectContextInternal::shackle_undead; - creators["prayer of fortitude on party"] = &PriestAiObjectContextInternal::prayer_of_fortitude_on_party; - creators["prayer of spirit on party"] = &PriestAiObjectContextInternal::prayer_of_spirit_on_party; - creators["power infusion on party"] = &PriestAiObjectContextInternal::power_infusion_on_party; - creators["silence"] = &PriestAiObjectContextInternal::silence; - creators["silence on enemy healer"] = &PriestAiObjectContextInternal::silence_on_enemy_healer; - creators["mana burn"] = &PriestAiObjectContextInternal::mana_burn; - creators["levitate"] = &PriestAiObjectContextInternal::levitate; - creators["prayer of healing on party"] = &PriestAiObjectContextInternal::prayer_of_healing; - creators["lightwell"] = &PriestAiObjectContextInternal::lightwell; - creators["mind soothe"] = &PriestAiObjectContextInternal::mind_soothe; - creators["touch of weakness"] = &PriestAiObjectContextInternal::touch_of_weakness; - creators["hex of weakness"] = &PriestAiObjectContextInternal::hex_of_weakness; - creators["shadowguard"] = &PriestAiObjectContextInternal::shadowguard; - creators["desperate prayer"] = &PriestAiObjectContextInternal::desperate_prayer; - creators["fear ward"] = &PriestAiObjectContextInternal::fear_ward; - creators["fear ward on party"] = &PriestAiObjectContextInternal::fear_ward_on_party; - creators["starshards"] = &PriestAiObjectContextInternal::starshards; - creators["elune's grace"] = &PriestAiObjectContextInternal::elunes_grace; - creators["feedback"] = &PriestAiObjectContextInternal::feedback; - creators["symbol of hope"] = &PriestAiObjectContextInternal::symbol_of_hope; - creators["consume magic"] = &PriestAiObjectContextInternal::consume_magic; - creators["chastise"] = &PriestAiObjectContextInternal::chastise; - creators["shadow word: death"] = &PriestAiObjectContextInternal::shadow_word_death; - creators["shadowfiend"] = &PriestAiObjectContextInternal::shadowfiend; - creators["mass dispel"] = &PriestAiObjectContextInternal::mass_dispel; - creators["pain suppression"] = &PriestAiObjectContextInternal::pain_suppression; - creators["pain suppression on party"] = &PriestAiObjectContextInternal::pain_suppression_on_party; - creators["prayer of mending on party"] = &PriestAiObjectContextInternal::prayer_of_mending; - creators["binding heal"] = &PriestAiObjectContextInternal::binding_heal; - creators["penance on party"] = &PriestAiObjectContextInternal::penance_on_party; - creators["hymn of hope"] = &PriestAiObjectContextInternal::hymn_of_hope; - creators["divine hymn"] = &PriestAiObjectContextInternal::divine_hymn; - creators["mind sear"] = &PriestAiObjectContextInternal::mind_sear; - creators["guardian spirit on party"] = &PriestAiObjectContextInternal::guardian_spirit_on_party; - } - -private: - static Action* shadow_protection_on_party(PlayerbotAI* botAI) - { - return new CastShadowProtectionOnPartyAction(botAI); - } - static Action* shadow_protection(PlayerbotAI* botAI) { return new CastShadowProtectionAction(botAI); } - static Action* power_infusion(PlayerbotAI* botAI) { return new CastPowerInfusionAction(botAI); } - static Action* inner_focus(PlayerbotAI* botAI) { return new CastInnerFocusAction(botAI); } - static Action* dispersion(PlayerbotAI* botAI) { return new CastDispersionAction(botAI); } - static Action* vampiric_embrace(PlayerbotAI* botAI) { return new CastVampiricEmbraceAction(botAI); } - static Action* vampiric_touch(PlayerbotAI* botAI) { return new CastVampiricTouchAction(botAI); } - static Action* vampiric_touch_on_attacker(PlayerbotAI* botAI) - { - return new CastVampiricTouchOnAttackerAction(botAI); - } - static Action* psychic_scream(PlayerbotAI* botAI) { return new CastPsychicScreamAction(botAI); } - static Action* circle_of_healing(PlayerbotAI* botAI) { return new CastCircleOfHealingAction(botAI); } - static Action* resurrection(PlayerbotAI* botAI) { return new CastResurrectionAction(botAI); } - static Action* shadow_word_pain(PlayerbotAI* botAI) { return new CastPowerWordPainAction(botAI); } - static Action* shadow_word_pain_on_attacker(PlayerbotAI* botAI) - { - return new CastPowerWordPainOnAttackerAction(botAI); - } - static Action* devouring_plague(PlayerbotAI* botAI) { return new CastDevouringPlagueAction(botAI); } - static Action* mind_flay(PlayerbotAI* botAI) { return new CastMindFlayAction(botAI); } - static Action* holy_fire(PlayerbotAI* botAI) { return new CastHolyFireAction(botAI); } - static Action* smite(PlayerbotAI* botAI) { return new CastSmiteAction(botAI); } - static Action* mind_blast(PlayerbotAI* botAI) { return new CastMindBlastAction(botAI); } - static Action* shadowform(PlayerbotAI* botAI) { return new CastShadowformAction(botAI); } - static Action* remove_shadowform(PlayerbotAI* botAI) { return new CastRemoveShadowformAction(botAI); } - static Action* holy_nova(PlayerbotAI* botAI) { return new CastHolyNovaAction(botAI); } - static Action* power_word_fortitude(PlayerbotAI* botAI) { return new CastPowerWordFortitudeAction(botAI); } - static Action* power_word_fortitude_on_party(PlayerbotAI* botAI) - { - return new CastPowerWordFortitudeOnPartyAction(botAI); - } - static Action* divine_spirit(PlayerbotAI* botAI) { return new CastDivineSpiritAction(botAI); } - static Action* divine_spirit_on_party(PlayerbotAI* botAI) { return new CastDivineSpiritOnPartyAction(botAI); } - static Action* power_word_shield(PlayerbotAI* botAI) { return new CastPowerWordShieldAction(botAI); } - static Action* power_word_shield_on_party(PlayerbotAI* botAI) - { - return new CastPowerWordShieldOnPartyAction(botAI); - } - static Action* power_word_shield_on_almost_full_health_below(PlayerbotAI* ai) - { - return new CastPowerWordShieldOnAlmostFullHealthBelowAction(ai); - } - static Action* power_word_shield_on_not_full(PlayerbotAI* ai) { return new CastPowerWordShieldOnNotFullAction(ai); } - static Action* renew(PlayerbotAI* botAI) { return new CastRenewAction(botAI); } - static Action* renew_on_party(PlayerbotAI* botAI) { return new CastRenewOnPartyAction(botAI); } - static Action* greater_heal(PlayerbotAI* botAI) { return new CastGreaterHealAction(botAI); } - static Action* greater_heal_on_party(PlayerbotAI* botAI) { return new CastGreaterHealOnPartyAction(botAI); } - static Action* heal(PlayerbotAI* botAI) { return new CastHealAction(botAI); } - static Action* heal_on_party(PlayerbotAI* botAI) { return new CastHealOnPartyAction(botAI); } - static Action* lesser_heal(PlayerbotAI* botAI) { return new CastLesserHealAction(botAI); } - static Action* lesser_heal_on_party(PlayerbotAI* botAI) { return new CastLesserHealOnPartyAction(botAI); } - static Action* flash_heal(PlayerbotAI* botAI) { return new CastFlashHealAction(botAI); } - static Action* flash_heal_on_party(PlayerbotAI* botAI) { return new CastFlashHealOnPartyAction(botAI); } - static Action* dispel_magic(PlayerbotAI* botAI) { return new CastDispelMagicAction(botAI); } - static Action* dispel_magic_on_party(PlayerbotAI* botAI) { return new CastDispelMagicOnPartyAction(botAI); } - static Action* dispel_magic_on_target(PlayerbotAI* botAI) { return new CastDispelMagicOnTargetAction(botAI); } - static Action* cure_disease(PlayerbotAI* botAI) { return new CastCureDiseaseAction(botAI); } - static Action* cure_disease_on_party(PlayerbotAI* botAI) { return new CastCureDiseaseOnPartyAction(botAI); } - static Action* abolish_disease(PlayerbotAI* botAI) { return new CastAbolishDiseaseAction(botAI); } - static Action* abolish_disease_on_party(PlayerbotAI* botAI) { return new CastAbolishDiseaseOnPartyAction(botAI); } - static Action* fade(PlayerbotAI* botAI) { return new CastFadeAction(botAI); } - static Action* inner_fire(PlayerbotAI* botAI) { return new CastInnerFireAction(botAI); } - static Action* shackle_undead(PlayerbotAI* botAI) { return new CastShackleUndeadAction(botAI); } - static Action* prayer_of_spirit_on_party(PlayerbotAI* botAI) { return new CastPrayerOfSpiritOnPartyAction(botAI); } - static Action* prayer_of_fortitude_on_party(PlayerbotAI* botAI) - { - return new CastPrayerOfFortitudeOnPartyAction(botAI); - } - static Action* feedback(PlayerbotAI* botAI) { return new CastFeedbackAction(botAI); } - static Action* elunes_grace(PlayerbotAI* botAI) { return new CastElunesGraceAction(botAI); } - static Action* starshards(PlayerbotAI* botAI) { return new CastStarshardsAction(botAI); } - static Action* fear_ward_on_party(PlayerbotAI* botAI) { return new CastFearWardOnPartyAction(botAI); } - static Action* fear_ward(PlayerbotAI* botAI) { return new CastFearWardAction(botAI); } - static Action* desperate_prayer(PlayerbotAI* botAI) { return new CastDesperatePrayerAction(botAI); } - static Action* shadowguard(PlayerbotAI* botAI) { return new CastShadowguardAction(botAI); } - static Action* hex_of_weakness(PlayerbotAI* botAI) { return new CastHexOfWeaknessAction(botAI); } - static Action* touch_of_weakness(PlayerbotAI* botAI) { return new CastTouchOfWeaknessAction(botAI); } - static Action* mind_soothe(PlayerbotAI* botAI) { return new CastMindSootheAction(botAI); } - static Action* lightwell(PlayerbotAI* botAI) { return new CastLightwellAction(botAI); } - static Action* prayer_of_healing(PlayerbotAI* botAI) { return new CastPrayerOfHealingAction(botAI); } - static Action* levitate(PlayerbotAI* botAI) { return new CastLevitateAction(botAI); } - static Action* mana_burn(PlayerbotAI* botAI) { return new CastManaBurnAction(botAI); } - static Action* silence_on_enemy_healer(PlayerbotAI* botAI) { return new CastSilenceOnEnemyHealerAction(botAI); } - static Action* silence(PlayerbotAI* botAI) { return new CastSilenceAction(botAI); } - static Action* power_infusion_on_party(PlayerbotAI* botAI) { return new CastPowerInfusionOnPartyAction(botAI); } - static Action* binding_heal(PlayerbotAI* botAI) { return new CastBindingHealAction(botAI); } - static Action* prayer_of_mending(PlayerbotAI* botAI) { return new CastPrayerOfMendingAction(botAI); } - static Action* pain_suppression_on_party(PlayerbotAI* botAI) { return new CastPainSuppressionProtectAction(botAI); } - static Action* pain_suppression(PlayerbotAI* botAI) { return new CastPainSuppressionAction(botAI); } - static Action* mass_dispel(PlayerbotAI* botAI) { return new CastMassDispelAction(botAI); } - static Action* shadowfiend(PlayerbotAI* botAI) { return new CastShadowfiendAction(botAI); } - static Action* shadow_word_death(PlayerbotAI* botAI) { return new CastShadowWordDeathAction(botAI); } - static Action* chastise(PlayerbotAI* botAI) { return new CastChastiseAction(botAI); } - static Action* consume_magic(PlayerbotAI* botAI) { return new CastConsumeMagicAction(botAI); } - static Action* symbol_of_hope(PlayerbotAI* botAI) { return new CastSymbolOfHopeAction(botAI); } - static Action* penance_on_party(PlayerbotAI* ai) { return new CastPenanceOnPartyAction(ai); } - static Action* hymn_of_hope(PlayerbotAI* ai) { return new CastHymnOfHopeAction(ai); } - static Action* divine_hymn(PlayerbotAI* ai) { return new CastDivineHymnAction(ai); } - static Action* mind_sear(PlayerbotAI* ai) { return new CastMindSearAction(ai); } - static Action* guardian_spirit_on_party(PlayerbotAI* ai) { return new CastGuardianSpiritOnPartyAction(ai); } -}; - SharedNamedObjectContextList PriestAiObjectContext::sharedStrategyContexts; -SharedNamedObjectContextList PriestAiObjectContext::sharedActionContexts; SharedNamedObjectContextList PriestAiObjectContext::sharedTriggerContexts; SharedNamedObjectContextList PriestAiObjectContext::sharedValueContexts; PriestAiObjectContext::PriestAiObjectContext(PlayerbotAI* botAI) - : AiObjectContext(botAI, sharedStrategyContexts, sharedActionContexts, sharedTriggerContexts, sharedValueContexts) + : AiObjectContext(botAI, sharedStrategyContexts, sharedTriggerContexts, sharedValueContexts) { } void PriestAiObjectContext::BuildSharedContexts() { BuildSharedStrategyContexts(sharedStrategyContexts); - BuildSharedActionContexts(sharedActionContexts); BuildSharedTriggerContexts(sharedTriggerContexts); BuildSharedValueContexts(sharedValueContexts); } @@ -375,12 +174,6 @@ void PriestAiObjectContext::BuildSharedStrategyContexts(SharedNamedObjectContext strategyContexts.Add(new PriestCombatStrategyFactoryInternal()); } -void PriestAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts) -{ - AiObjectContext::BuildSharedActionContexts(actionContexts); - actionContexts.Add(new PriestAiObjectContextInternal()); -} - void PriestAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts) { AiObjectContext::BuildSharedTriggerContexts(triggerContexts); diff --git a/src/Ai/Class/Priest/PriestAiObjectContext.h b/src/Ai/Class/Priest/PriestAiObjectContext.h index 83e3449cb3..a565b93e02 100644 --- a/src/Ai/Class/Priest/PriestAiObjectContext.h +++ b/src/Ai/Class/Priest/PriestAiObjectContext.h @@ -17,12 +17,10 @@ class PriestAiObjectContext : public AiObjectContext static void BuildSharedContexts(); static void BuildSharedStrategyContexts(SharedNamedObjectContextList& strategyContexts); - static void BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts); static void BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts); static void BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts); static SharedNamedObjectContextList sharedStrategyContexts; - static SharedNamedObjectContextList sharedActionContexts; static SharedNamedObjectContextList sharedTriggerContexts; static SharedNamedObjectContextList sharedValueContexts; }; diff --git a/src/Ai/Class/Priest/Strategy/GenericPriestStrategy.cpp b/src/Ai/Class/Priest/Strategy/GenericPriestStrategy.cpp index 60da134330..72732560ec 100644 --- a/src/Ai/Class/Priest/Strategy/GenericPriestStrategy.cpp +++ b/src/Ai/Class/Priest/Strategy/GenericPriestStrategy.cpp @@ -5,9 +5,13 @@ #include "GenericPriestStrategy.h" +#include "CreateNextAction.h" +#include "GenericActions.h" #include "GenericPriestStrategyActionNodeFactory.h" #include "HealPriestStrategy.h" -#include "Playerbots.h" +#include "ImbueAction.h" +#include "MovementActions.h" +#include "PriestActions.h" GenericPriestStrategy::GenericPriestStrategy(PlayerbotAI* botAI) : RangedCombatStrategy(botAI) { @@ -18,30 +22,91 @@ void GenericPriestStrategy::InitTriggers(std::vector& triggers) { CombatStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("medium threat", { NextAction("fade", 55.0f) })); - triggers.push_back(new TriggerNode("critical health", { NextAction("desperate prayer", - ACTION_HIGH + 5) })); - triggers.push_back(new TriggerNode( - "critical health", { NextAction("power word: shield", ACTION_NORMAL) })); + triggers.push_back( + new TriggerNode( + "medium threat", + { + CreateNextAction(55.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "critical health", + { + CreateNextAction(ACTION_HIGH + 5.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "critical health", + { + CreateNextAction(ACTION_NORMAL) + } + ) + ); triggers.push_back( - new TriggerNode("low health", { NextAction("power word: shield", ACTION_HIGH) })); + new TriggerNode( + "low health", + { + CreateNextAction(ACTION_HIGH) + } + ) + ); triggers.push_back( - new TriggerNode("medium mana", + new TriggerNode( + "medium mana", { - NextAction("shadowfiend", ACTION_HIGH + 2), - NextAction("inner focus", ACTION_HIGH + 1) })); + CreateNextAction(ACTION_HIGH + 2), + CreateNextAction(ACTION_HIGH + 1.0f) + } + ) + ); triggers.push_back( - new TriggerNode("low mana", { NextAction("hymn of hope", ACTION_HIGH) })); + new TriggerNode( + "low mana", + { + CreateNextAction(ACTION_HIGH) + } + ) + ); - triggers.push_back(new TriggerNode("enemy too close for spell", - { NextAction("flee", ACTION_MOVE + 9) })); - triggers.push_back(new TriggerNode("often", { NextAction("apply oil", 1.0f) })); - triggers.push_back(new TriggerNode("being attacked", - { NextAction("power word: shield", ACTION_HIGH + 1) })); - triggers.push_back(new TriggerNode("new pet", { NextAction("set pet stance", 60.0f) })); + triggers.push_back( + new TriggerNode( + "enemy too close for spell", + { + CreateNextAction(ACTION_MOVE + 9.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "often", + { + CreateNextAction(1.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "being attacked", + { + CreateNextAction(ACTION_HIGH + 1.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "new pet", + { + CreateNextAction(60.0f) + } + ) + ); } PriestCureStrategy::PriestCureStrategy(PlayerbotAI* botAI) : Strategy(botAI) @@ -52,41 +117,92 @@ PriestCureStrategy::PriestCureStrategy(PlayerbotAI* botAI) : Strategy(botAI) void PriestCureStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("dispel magic", { NextAction("dispel magic", 41.0f) })); - triggers.push_back(new TriggerNode("dispel magic on party", - { NextAction("dispel magic on party", 40.0f) })); + new TriggerNode( + "dispel magic", + { + CreateNextAction(41.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "dispel magic on party", + { + CreateNextAction(40.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "cure disease", + { + CreateNextAction(31.0f) + } + ) + ); triggers.push_back( - new TriggerNode("cure disease", { NextAction("abolish disease", 31.0f) })); - triggers.push_back(new TriggerNode( - "party member cure disease", { NextAction("abolish disease on party", 30.0f) })); + new TriggerNode( + "party member cure disease", + { + CreateNextAction(30.0f) + } + ) +); } void PriestBoostStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("power infusion", { NextAction("power infusion", 41.0f) })); - triggers.push_back(new TriggerNode("boost", { NextAction("shadowfiend", 20.0f) })); + new TriggerNode( + "power infusion", + { + CreateNextAction(41.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "boost", + { + CreateNextAction(20.0f) + } + ) + ); } void PriestCcStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("shackle undead", { NextAction("shackle undead", 31.0f) })); + new TriggerNode( + "shackle undead", + { + CreateNextAction(31.0f) + } + ) + ); } void PriestHealerDpsStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("healer should attack", - { - NextAction("shadow word: pain", ACTION_DEFAULT + 0.5f), - NextAction("holy fire", ACTION_DEFAULT + 0.4f), - NextAction("smite", ACTION_DEFAULT + 0.3f), - NextAction("mind blast", ACTION_DEFAULT + 0.2f), - NextAction("shoot", ACTION_DEFAULT) })); + new TriggerNode( + "healer should attack", + { + CreateNextAction(ACTION_DEFAULT + 0.5f), + CreateNextAction(ACTION_DEFAULT + 0.4f), + CreateNextAction(ACTION_DEFAULT + 0.3f), + CreateNextAction(ACTION_DEFAULT + 0.2f), + CreateNextAction(ACTION_DEFAULT) + } + ) + ); triggers.push_back( - new TriggerNode("medium aoe and healer should attack", - { - NextAction("mind sear", ACTION_DEFAULT + 0.5f) })); + new TriggerNode( + "medium aoe and healer should attack", + { + CreateNextAction(ACTION_DEFAULT + 0.5f) + } + ) + ); } diff --git a/src/Ai/Class/Priest/Strategy/GenericPriestStrategyActionNodeFactory.h b/src/Ai/Class/Priest/Strategy/GenericPriestStrategyActionNodeFactory.h index ab6a0c2ba4..49faf3b9ac 100644 --- a/src/Ai/Class/Priest/Strategy/GenericPriestStrategyActionNodeFactory.h +++ b/src/Ai/Class/Priest/Strategy/GenericPriestStrategyActionNodeFactory.h @@ -7,7 +7,10 @@ #define _PLAYERBOT_GENERICPRIESTSTRATEGYACTIONNODEFACTORY_H #include "Action.h" +#include "ActionNode.h" +#include "CreateNextAction.h" #include "NamedObjectContext.h" +#include "PriestActions.h" class GenericPriestStrategyActionNodeFactory : public NamedObjectFactory { @@ -41,8 +44,7 @@ class GenericPriestStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -50,8 +52,7 @@ class GenericPriestStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -59,8 +60,7 @@ class GenericPriestStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -68,8 +68,7 @@ class GenericPriestStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -77,8 +76,7 @@ class GenericPriestStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -86,8 +84,7 @@ class GenericPriestStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -95,9 +92,8 @@ class GenericPriestStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, + // /*A*/ { CreateNextAction("renew", 50.0f) }, /*A*/ {}, /*C*/ {} ); @@ -105,8 +101,7 @@ class GenericPriestStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -114,8 +109,7 @@ class GenericPriestStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -123,8 +117,7 @@ class GenericPriestStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -132,44 +125,39 @@ class GenericPriestStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } static ActionNode* greater_heal_on_party([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "greater heal on party", - /*P*/ { NextAction("remove shadowform") }, - /*A*/ { NextAction("heal on party") }, + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } static ActionNode* heal([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "heal", - /*P*/ { NextAction("remove shadowform") }, - /*A*/ { NextAction("lesser heal") }, + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } static ActionNode* heal_on_party([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "heal on party", - /*P*/ { NextAction("remove shadowform") }, - /*A*/ { NextAction("lesser heal on party") }, + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } static ActionNode* lesser_heal([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "lesser heal", - /*P*/ { NextAction("remove shadowform") }, + /*P*/ { CreateNextAction(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -177,8 +165,7 @@ class GenericPriestStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -186,27 +173,24 @@ class GenericPriestStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } static ActionNode* flash_heal_on_party([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "flash heal on party", - /*P*/ { NextAction("remove shadowform") }, - /*A*/ { NextAction("greater heal on party") }, + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } static ActionNode* psychic_scream([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "psychic scream", /*P*/ {}, - /*A*/ { NextAction("fade") }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } @@ -214,7 +198,6 @@ class GenericPriestStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -246,9 +228,8 @@ class CurePriestStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } diff --git a/src/Ai/Class/Priest/Strategy/HealPriestStrategy.cpp b/src/Ai/Class/Priest/Strategy/HealPriestStrategy.cpp index 35f764e4df..b6b98b53bd 100644 --- a/src/Ai/Class/Priest/Strategy/HealPriestStrategy.cpp +++ b/src/Ai/Class/Priest/Strategy/HealPriestStrategy.cpp @@ -5,8 +5,11 @@ #include "HealPriestStrategy.h" +#include "CreateNextAction.h" #include "GenericPriestStrategyActionNodeFactory.h" -#include "Playerbots.h" +#include "GenericSpellActions.h" +#include "PriestActions.h" +#include "ReachTargetActions.h" HealPriestStrategy::HealPriestStrategy(PlayerbotAI* botAI) : GenericPriestStrategy(botAI) { @@ -16,7 +19,7 @@ HealPriestStrategy::HealPriestStrategy(PlayerbotAI* botAI) : GenericPriestStrate std::vector HealPriestStrategy::getDefaultActions() { return { - NextAction("shoot", ACTION_DEFAULT) + CreateNextAction(ACTION_DEFAULT) }; } @@ -28,83 +31,77 @@ void HealPriestStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "group heal setting", { - NextAction("prayer of mending on party", ACTION_MEDIUM_HEAL + 8), - NextAction("power word: shield on not full", ACTION_MEDIUM_HEAL + 7) + CreateNextAction(ACTION_MEDIUM_HEAL + 8.0f), + CreateNextAction(ACTION_MEDIUM_HEAL + 7.0f) } ) ); - triggers.push_back( new TriggerNode( "medium group heal setting", { - NextAction("divine hymn", ACTION_CRITICAL_HEAL + 7), - NextAction("prayer of mending on party", ACTION_CRITICAL_HEAL + 6), - NextAction("power word: shield on not full", ACTION_CRITICAL_HEAL + 5), - NextAction("prayer of healing on party", ACTION_CRITICAL_HEAL + 4) + CreateNextAction(ACTION_CRITICAL_HEAL + 7.0f), + CreateNextAction(ACTION_CRITICAL_HEAL + 6.0f), + CreateNextAction(ACTION_CRITICAL_HEAL + 5.0f), + CreateNextAction(ACTION_CRITICAL_HEAL + 4.0f) } ) ); - triggers.push_back( new TriggerNode( "party member critical health", { - NextAction("power word: shield on party", ACTION_CRITICAL_HEAL + 5), - NextAction("penance on party", ACTION_CRITICAL_HEAL + 4), - NextAction("prayer of mending on party", ACTION_CRITICAL_HEAL + 3), - NextAction("flash heal on party", ACTION_CRITICAL_HEAL + 2) + CreateNextAction(ACTION_CRITICAL_HEAL + 5.0f), + CreateNextAction(ACTION_CRITICAL_HEAL + 4.0f), + CreateNextAction(ACTION_CRITICAL_HEAL + 3.0f), + CreateNextAction(ACTION_CRITICAL_HEAL + 2.0f) } ) ); - triggers.push_back( new TriggerNode( "party member low health", { - NextAction("power word: shield on party", ACTION_MEDIUM_HEAL + 4), - NextAction("prayer of mending on party", ACTION_MEDIUM_HEAL + 3), - NextAction("penance on party", ACTION_MEDIUM_HEAL + 2), - NextAction("flash heal on party", ACTION_MEDIUM_HEAL + 0) + CreateNextAction(ACTION_MEDIUM_HEAL + 4.0f), + CreateNextAction(ACTION_MEDIUM_HEAL + 3.0f), + CreateNextAction(ACTION_MEDIUM_HEAL + 2.0f), + CreateNextAction(ACTION_MEDIUM_HEAL + 0.0f) } ) ); - triggers.push_back( new TriggerNode( "party member medium health", { - NextAction("power word: shield on party", ACTION_LIGHT_HEAL + 9), - NextAction("prayer of mending on party", ACTION_LIGHT_HEAL + 7), - NextAction("penance on party", ACTION_LIGHT_HEAL + 6), - NextAction("flash heal on party", ACTION_LIGHT_HEAL + 5) + CreateNextAction(ACTION_LIGHT_HEAL + 9.0f), + CreateNextAction(ACTION_LIGHT_HEAL + 7.0f), + CreateNextAction(ACTION_LIGHT_HEAL + 6.0f), + CreateNextAction(ACTION_LIGHT_HEAL + 5.0f) } ) ); - triggers.push_back( new TriggerNode( "party member almost full health", { - NextAction("prayer of mending on party", ACTION_LIGHT_HEAL + 2), - NextAction("renew on party", ACTION_LIGHT_HEAL + 1) + CreateNextAction(ACTION_LIGHT_HEAL + 2.0f), + CreateNextAction(ACTION_LIGHT_HEAL + 1.0f) } ) ); - triggers.push_back( new TriggerNode( "party member to heal out of spell range", { - NextAction("reach party member to heal", ACTION_CRITICAL_HEAL + 10) + CreateNextAction(ACTION_CRITICAL_HEAL + 10.0f) } ) ); - triggers.push_back( new TriggerNode( - "critical health", { - NextAction("pain suppression", ACTION_EMERGENCY + 1) + "critical health", + { + CreateNextAction(ACTION_EMERGENCY + 1.0f) } ) ); @@ -112,7 +109,7 @@ void HealPriestStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "protect party member", { - NextAction("pain suppression on party", ACTION_EMERGENCY) + CreateNextAction(ACTION_EMERGENCY) } ) ); diff --git a/src/Ai/Class/Priest/Strategy/HolyPriestStrategy.cpp b/src/Ai/Class/Priest/Strategy/HolyPriestStrategy.cpp index 399f21c615..9c4f2cf6f8 100644 --- a/src/Ai/Class/Priest/Strategy/HolyPriestStrategy.cpp +++ b/src/Ai/Class/Priest/Strategy/HolyPriestStrategy.cpp @@ -4,8 +4,11 @@ */ #include "HolyPriestStrategy.h" - -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "GenericPriestStrategyActionNodeFactory.h" +#include "GenericSpellActions.h" +#include "PriestActions.h" +#include "ReachTargetActions.h" class HolyPriestStrategyActionNodeFactory : public NamedObjectFactory { @@ -16,9 +19,8 @@ class HolyPriestStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -32,9 +34,9 @@ HolyPriestStrategy::HolyPriestStrategy(PlayerbotAI* botAI) : HealPriestStrategy( std::vector HolyPriestStrategy::getDefaultActions() { return { - NextAction("smite", ACTION_DEFAULT + 0.2f), - NextAction("mana burn", ACTION_DEFAULT + 0.1f), - NextAction("starshards", ACTION_DEFAULT) + CreateNextAction(ACTION_DEFAULT + 0.2f), + CreateNextAction(ACTION_DEFAULT + 0.1f), + CreateNextAction(ACTION_DEFAULT) }; } @@ -46,7 +48,7 @@ void HolyPriestStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "holy fire", { - NextAction("holy fire", ACTION_NORMAL + 9) + CreateNextAction(ACTION_NORMAL + 9.0f) } ) ); @@ -54,7 +56,7 @@ void HolyPriestStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "shadowfiend", { - NextAction("shadowfiend", ACTION_HIGH) + CreateNextAction(ACTION_HIGH) } ) ); @@ -62,7 +64,7 @@ void HolyPriestStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "medium mana", { - NextAction("shadowfiend", ACTION_HIGH) + CreateNextAction(ACTION_HIGH) } ) ); @@ -70,7 +72,7 @@ void HolyPriestStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "low mana", { - NextAction("mana burn", ACTION_HIGH) + CreateNextAction(ACTION_HIGH) } ) ); @@ -83,7 +85,7 @@ HolyHealPriestStrategy::HolyHealPriestStrategy(PlayerbotAI* botAI) : GenericPrie std::vector HolyHealPriestStrategy::getDefaultActions() { - return { NextAction("shoot", ACTION_DEFAULT) }; + return { CreateNextAction(ACTION_DEFAULT) }; } void HolyHealPriestStrategy::InitTriggers(std::vector& triggers) @@ -94,8 +96,8 @@ void HolyHealPriestStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "group heal setting", { - NextAction("prayer of mending on party", ACTION_MEDIUM_HEAL + 9), - NextAction("circle of healing on party", ACTION_MEDIUM_HEAL + 8) + CreateNextAction(ACTION_MEDIUM_HEAL + 9.0f), + CreateNextAction(ACTION_MEDIUM_HEAL + 8.0f) } ) ); @@ -104,10 +106,10 @@ void HolyHealPriestStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "medium group heal setting", { - NextAction("divine hymn", ACTION_CRITICAL_HEAL + 7), - NextAction("prayer of mending on party", ACTION_CRITICAL_HEAL + 6), - NextAction("circle of healing on party", ACTION_CRITICAL_HEAL + 5), - NextAction("prayer of healing on party", ACTION_CRITICAL_HEAL + 4) + CreateNextAction(ACTION_CRITICAL_HEAL + 7.0f), + CreateNextAction(ACTION_CRITICAL_HEAL + 6.0f), + CreateNextAction(ACTION_CRITICAL_HEAL + 5.0f), + CreateNextAction(ACTION_CRITICAL_HEAL + 4.0f) } ) ); @@ -116,11 +118,11 @@ void HolyHealPriestStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "party member critical health", { - NextAction("guardian spirit on party", ACTION_CRITICAL_HEAL + 6), - NextAction("power word: shield on party", ACTION_CRITICAL_HEAL + 5), - NextAction("prayer of mending on party", ACTION_CRITICAL_HEAL + 3), - NextAction("greater heal on party", ACTION_MEDIUM_HEAL + 2), - NextAction("flash heal on party", ACTION_CRITICAL_HEAL + 1), + CreateNextAction(ACTION_CRITICAL_HEAL + 6.0f), + CreateNextAction(ACTION_CRITICAL_HEAL + 5.0f), + CreateNextAction(ACTION_CRITICAL_HEAL + 3.0f), + CreateNextAction(ACTION_MEDIUM_HEAL + 2.0f), + CreateNextAction(ACTION_CRITICAL_HEAL + 1.0f), } ) ); @@ -129,10 +131,10 @@ void HolyHealPriestStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "party member low health", { - NextAction("circle of healing on party", ACTION_MEDIUM_HEAL + 4), - NextAction("prayer of mending on party", ACTION_MEDIUM_HEAL + 3), - NextAction("greater heal on party", ACTION_MEDIUM_HEAL + 2), - NextAction("flash heal on party", ACTION_MEDIUM_HEAL + 1) + CreateNextAction(ACTION_MEDIUM_HEAL + 4.0f), + CreateNextAction(ACTION_MEDIUM_HEAL + 3.0f), + CreateNextAction(ACTION_MEDIUM_HEAL + 2.0f), + CreateNextAction(ACTION_MEDIUM_HEAL + 1.0f) } ) ); @@ -141,10 +143,10 @@ void HolyHealPriestStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "party member medium health", { - NextAction("circle of healing on party", ACTION_LIGHT_HEAL + 7), - NextAction("prayer of mending on party", ACTION_LIGHT_HEAL + 6), - NextAction("greater heal on party", ACTION_MEDIUM_HEAL + 5), - NextAction("flash heal on party", ACTION_LIGHT_HEAL + 4), + CreateNextAction(ACTION_LIGHT_HEAL + 7.0f), + CreateNextAction(ACTION_LIGHT_HEAL + 6.0f), + CreateNextAction(ACTION_MEDIUM_HEAL + 5.0f), + CreateNextAction(ACTION_LIGHT_HEAL + 4.0f), } ) ); @@ -153,8 +155,8 @@ void HolyHealPriestStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "party member almost full health", { - NextAction("renew on party", ACTION_LIGHT_HEAL + 2), - NextAction("prayer of mending on party", ACTION_LIGHT_HEAL + 1), + CreateNextAction(ACTION_LIGHT_HEAL + 2.0f), + CreateNextAction(ACTION_LIGHT_HEAL + 1.0f), } ) ); @@ -163,7 +165,7 @@ void HolyHealPriestStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "party member to heal out of spell range", { - NextAction("reach party member to heal", ACTION_CRITICAL_HEAL + 10) + CreateNextAction(ACTION_CRITICAL_HEAL + 10.0f) } ) ); diff --git a/src/Ai/Class/Priest/Strategy/HolyPriestStrategy.h b/src/Ai/Class/Priest/Strategy/HolyPriestStrategy.h index 5ae94c383b..9bed76944c 100644 --- a/src/Ai/Class/Priest/Strategy/HolyPriestStrategy.h +++ b/src/Ai/Class/Priest/Strategy/HolyPriestStrategy.h @@ -6,7 +6,6 @@ #ifndef _PLAYERBOT_HOLYPRIESTSTRATEGY_H #define _PLAYERBOT_HOLYPRIESTSTRATEGY_H -#include "GenericPriestStrategyActionNodeFactory.h" #include "HealPriestStrategy.h" class PlayerbotAI; diff --git a/src/Ai/Class/Priest/Strategy/PriestNonCombatStrategy.cpp b/src/Ai/Class/Priest/Strategy/PriestNonCombatStrategy.cpp index 6447d45197..be51c5e7dc 100644 --- a/src/Ai/Class/Priest/Strategy/PriestNonCombatStrategy.cpp +++ b/src/Ai/Class/Priest/Strategy/PriestNonCombatStrategy.cpp @@ -5,7 +5,10 @@ #include "PriestNonCombatStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "GenericActions.h" +#include "ImbueAction.h" +#include "PriestActions.h" #include "PriestNonCombatStrategyActionNodeFactory.h" PriestNonCombatStrategy::PriestNonCombatStrategy(PlayerbotAI* botAI) : NonCombatStrategy(botAI) @@ -18,36 +21,87 @@ void PriestNonCombatStrategy::InitTriggers(std::vector& triggers) NonCombatStrategy::InitTriggers(triggers); triggers.push_back( - new TriggerNode("inner fire",{ NextAction("inner fire", 10.0f) })); - triggers.push_back(new TriggerNode( - "party member dead",{ NextAction("remove shadowform", ACTION_CRITICAL_HEAL + 11), - NextAction("resurrection", ACTION_CRITICAL_HEAL + 10) })); - triggers.push_back(new TriggerNode("often",{ NextAction("apply oil", 1.0f) })); + new TriggerNode( + "inner fire", + { + CreateNextAction(10.0f) + } + ) + ); triggers.push_back( - new TriggerNode("party member critical health", - { NextAction("renew on party", ACTION_CRITICAL_HEAL + 3), - NextAction("penance on party", ACTION_CRITICAL_HEAL + 2), - NextAction("greater heal on party", ACTION_CRITICAL_HEAL + 1) })); + new TriggerNode( + "party member dead", + { + CreateNextAction(ACTION_CRITICAL_HEAL + 11.0f), + CreateNextAction(ACTION_CRITICAL_HEAL + 10.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "often", + { + CreateNextAction(1.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member critical health", + { + CreateNextAction(ACTION_CRITICAL_HEAL + 3.0f), + CreateNextAction(ACTION_CRITICAL_HEAL + 2.0f), + CreateNextAction(ACTION_CRITICAL_HEAL + 1.0f) + } + ) + ); triggers.push_back( - new TriggerNode("party member low health", - { NextAction("renew on party", ACTION_MEDIUM_HEAL + 3), - NextAction("penance on party", ACTION_MEDIUM_HEAL + 2), - NextAction("greater heal on party", ACTION_MEDIUM_HEAL + 1) })); + new TriggerNode( + "party member low health", + { + CreateNextAction(ACTION_MEDIUM_HEAL + 3.0f), + CreateNextAction(ACTION_MEDIUM_HEAL + 2.0f), + CreateNextAction(ACTION_MEDIUM_HEAL + 1.0f) + } + ) + ); triggers.push_back( - new TriggerNode("party member medium health", - { NextAction("renew on party", ACTION_LIGHT_HEAL + 9), - NextAction("penance on party", ACTION_LIGHT_HEAL + 8) })); + new TriggerNode( + "party member medium health", + { + CreateNextAction(ACTION_LIGHT_HEAL + 9.0f), + CreateNextAction(ACTION_LIGHT_HEAL + 8.0f) + } + ) + ); triggers.push_back( - new TriggerNode("party member almost full health", - { NextAction("renew on party", ACTION_LIGHT_HEAL + 3) })); + new TriggerNode( + "party member almost full health", + { + CreateNextAction(ACTION_LIGHT_HEAL + 3.0f) + } + ) + ); triggers.push_back( - new TriggerNode("group heal setting",{ NextAction("circle of healing on party", 27.0f) })); - triggers.push_back(new TriggerNode("new pet", - { NextAction("set pet stance", 10.0f) })); + new TriggerNode( + "group heal setting", + { + CreateNextAction(27.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "new pet", + { + CreateNextAction(10.0f) + } + ) + ); } void PriestBuffStrategy::InitTriggers(std::vector& triggers) @@ -55,25 +109,57 @@ void PriestBuffStrategy::InitTriggers(std::vector& triggers) NonCombatStrategy::InitTriggers(triggers); triggers.push_back( - new TriggerNode("prayer of fortitude on party", - { NextAction("prayer of fortitude on party", 12.0f) })); + new TriggerNode( + "prayer of fortitude on party", + { + CreateNextAction(12.0f) + } + ) + ); triggers.push_back( - new TriggerNode("prayer of spirit on party", - { NextAction("prayer of spirit on party", 14.0f) })); + new TriggerNode( + "prayer of spirit on party", + { + CreateNextAction(14.0f) + } + ) + ); triggers.push_back( - new TriggerNode("power word: fortitude on party", - { NextAction("power word: fortitude on party", 11.0f) })); - triggers.push_back(new TriggerNode("divine spirit on party", - { NextAction("divine spirit on party", 13.0f) })); + new TriggerNode( + "power word: fortitude on party", + { + CreateNextAction(11.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "divine spirit on party", + { + CreateNextAction(13.0f) + } + ) + ); } void PriestShadowResistanceStrategy::InitTriggers(std::vector& triggers) { NonCombatStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("shadow protection", - { NextAction("shadow protection", 12.0f) })); triggers.push_back( - new TriggerNode("shadow protection on party", - { NextAction("shadow protection on party", 11.0f) })); + new TriggerNode( + "shadow protection", + { + CreateNextAction(12.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "shadow protection on party", + { + CreateNextAction(11.0f) + } + ) + ); } diff --git a/src/Ai/Class/Priest/Strategy/PriestNonCombatStrategyActionNodeFactory.h b/src/Ai/Class/Priest/Strategy/PriestNonCombatStrategyActionNodeFactory.h index c7d4aba82b..59e377265b 100644 --- a/src/Ai/Class/Priest/Strategy/PriestNonCombatStrategyActionNodeFactory.h +++ b/src/Ai/Class/Priest/Strategy/PriestNonCombatStrategyActionNodeFactory.h @@ -7,7 +7,10 @@ #define _PLAYERBOT_PRIESTNONCOMBATSTRATEGYACTIONNODEFACTORY_H #include "Action.h" +#include "ActionNode.h" +#include "CreateNextAction.h" #include "NamedObjectContext.h" +#include "PriestActions.h" class PlayerbotAI; @@ -37,116 +40,131 @@ class PriestNonCombatStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* power_word_shield([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("power word: shield", - /*P*/ {}, - /*A*/ { NextAction("renew", 50.0f) }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(50.0f) }, + /*C*/ {} + ); } static ActionNode* power_word_shield_on_party([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("power word: shield on party", - /*P*/ {}, - /*A*/ { NextAction("renew on party", 50.0f) }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(50.0f) }, + /*C*/ {} + ); } static ActionNode* renew([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("renew", - /*P*/ { NextAction("remove shadowform") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* renew_on_party([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("renew on party", - /*P*/ { NextAction("remove shadowform") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* greater_heal([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("greater heal", - /*P*/ { NextAction("remove shadowform") }, - /*A*/ { NextAction("heal") }, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* greater_heal_on_party([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("greater heal on party", - /*P*/ {}, - /*A*/ { NextAction("heal on party") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* heal([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("heal", - /*P*/ { NextAction("remove shadowform") }, - /*A*/ { NextAction("lesser heal") }, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* heal_on_party([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("heal on party", - /*P*/ { NextAction("remove shadowform") }, - /*A*/ { NextAction("lesser heal on party") }, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* lesser_heal([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("lesser heal", - /*P*/ { NextAction("remove shadowform") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* lesser_heal_on_party([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("lesser heal on party", - /*P*/ { NextAction("remove shadowform") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* flash_heal([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("flash heal", - /*P*/ { NextAction("remove shadowform") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* flash_heal_on_party([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("flash heal on party", - /*P*/ { NextAction("remove shadowform") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* circle_of_healing([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("circle of healing on party", - /*P*/ { NextAction("remove shadowform") }, - // /*A*/ { NextAction("flash heal on party") }, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ {}, + /*C*/ {} + ); } static ActionNode* prayer_of_fortitude_on_party([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("prayer of fortitude on party", - /*P*/ { NextAction("remove shadowform") }, - /*A*/ { NextAction("power word: fortitude on party") }, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* prayer_of_spirit_on_party([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("prayer of spirit on party", - /*P*/ { NextAction("remove shadowform") }, - /*A*/ { NextAction("divine spirit on party") }, - /*C*/ {}); + return new ActionNode( + /*P*/ { CreateNextAction(1.0f) }, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } }; diff --git a/src/Ai/Class/Priest/Strategy/ShadowPriestStrategy.cpp b/src/Ai/Class/Priest/Strategy/ShadowPriestStrategy.cpp index 1308f7225d..92afda98a6 100644 --- a/src/Ai/Class/Priest/Strategy/ShadowPriestStrategy.cpp +++ b/src/Ai/Class/Priest/Strategy/ShadowPriestStrategy.cpp @@ -5,7 +5,9 @@ #include "ShadowPriestStrategy.h" -#include "Playerbots.h" +#include "CancelChannelAction.h" +#include "CreateNextAction.h" +#include "PriestActions.h" #include "ShadowPriestStrategyActionNodeFactory.h" ShadowPriestStrategy::ShadowPriestStrategy(PlayerbotAI* botAI) : GenericPriestStrategy(botAI) @@ -16,10 +18,10 @@ ShadowPriestStrategy::ShadowPriestStrategy(PlayerbotAI* botAI) : GenericPriestSt std::vector ShadowPriestStrategy::getDefaultActions() { return { - NextAction("mind blast", ACTION_DEFAULT + 0.3f), - NextAction("mind flay", ACTION_DEFAULT + 0.2f), - NextAction("shadow word: death", ACTION_DEFAULT + 0.1f), // cast during movement - NextAction("shoot", ACTION_DEFAULT) + CreateNextAction(ACTION_DEFAULT + 0.3f), + CreateNextAction(ACTION_DEFAULT + 0.2f), + CreateNextAction(ACTION_DEFAULT + 0.1f), // cast during movement + CreateNextAction(ACTION_DEFAULT) }; } @@ -31,7 +33,7 @@ void ShadowPriestStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "shadowform", { - NextAction("shadowform", ACTION_HIGH) + CreateNextAction(ACTION_HIGH) } ) ); @@ -39,7 +41,7 @@ void ShadowPriestStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "low mana", { - NextAction("dispersion", ACTION_HIGH + 5) + CreateNextAction(ACTION_HIGH + 5.0f) } ) ); @@ -47,7 +49,7 @@ void ShadowPriestStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "critical health", { - NextAction("dispersion", ACTION_HIGH + 5) + CreateNextAction(ACTION_HIGH + 5.0f) } ) ); @@ -55,7 +57,7 @@ void ShadowPriestStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "vampiric embrace", { - NextAction("vampiric embrace", 16.0f) + CreateNextAction(16.0f) } ) ); @@ -63,7 +65,7 @@ void ShadowPriestStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "silence", { - NextAction("silence", ACTION_INTERRUPT + 1) + CreateNextAction(ACTION_INTERRUPT + 1.0f) } ) ); @@ -71,7 +73,7 @@ void ShadowPriestStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "silence on enemy healer", { - NextAction("silence on enemy healer", ACTION_INTERRUPT) + CreateNextAction(ACTION_INTERRUPT) } ) ); @@ -83,7 +85,7 @@ void ShadowPriestAoeStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "shadow word: pain on attacker", { - NextAction("shadow word: pain on attacker", ACTION_NORMAL + 5) + CreateNextAction(ACTION_NORMAL + 5.0f) } ) ); @@ -91,7 +93,7 @@ void ShadowPriestAoeStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "vampiric touch on attacker", { - NextAction("vampiric touch on attacker", ACTION_NORMAL + 4) + CreateNextAction(ACTION_NORMAL + 4.0f) } ) ); @@ -99,7 +101,7 @@ void ShadowPriestAoeStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "mind sear channel check", { - NextAction("cancel channel", ACTION_HIGH + 5) + CreateNextAction(ACTION_HIGH + 5.0f) } ) ); @@ -107,7 +109,7 @@ void ShadowPriestAoeStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "medium aoe", { - NextAction("mind sear", ACTION_HIGH + 4) + CreateNextAction(ACTION_HIGH + 4.0f) } ) ); @@ -119,7 +121,7 @@ void ShadowPriestDebuffStrategy::InitTriggers(std::vector& trigger new TriggerNode( "vampiric touch", { - NextAction("vampiric touch", ACTION_HIGH + 3) + CreateNextAction(ACTION_HIGH + 3.0f) } ) ); @@ -127,7 +129,7 @@ void ShadowPriestDebuffStrategy::InitTriggers(std::vector& trigger new TriggerNode( "devouring plague", { - NextAction("devouring plague", ACTION_HIGH + 2) + CreateNextAction(ACTION_HIGH + 2.0f) } ) ); @@ -135,7 +137,7 @@ void ShadowPriestDebuffStrategy::InitTriggers(std::vector& trigger new TriggerNode( "shadow word: pain", { - NextAction("shadow word: pain", ACTION_HIGH + 1) + CreateNextAction(ACTION_HIGH + 1.0f) } ) ); diff --git a/src/Ai/Class/Priest/Strategy/ShadowPriestStrategyActionNodeFactory.h b/src/Ai/Class/Priest/Strategy/ShadowPriestStrategyActionNodeFactory.h index 4efcc6f6a3..042d2ec3de 100644 --- a/src/Ai/Class/Priest/Strategy/ShadowPriestStrategyActionNodeFactory.h +++ b/src/Ai/Class/Priest/Strategy/ShadowPriestStrategyActionNodeFactory.h @@ -7,7 +7,10 @@ #define _PLAYERBOT_SHADOWPRIESTSTRATEGYACTIONNODEFACTORY_H #include "Action.h" +#include "ActionNode.h" +#include "CreateNextAction.h" #include "NamedObjectContext.h" +#include "PriestActions.h" class PlayerbotAI; @@ -25,34 +28,38 @@ class ShadowPriestStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, + /*C*/ {} + ); } static ActionNode* mind_flay([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("mind flay", - /*P*/ {}, - /*A*/ { NextAction("smite") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* smite([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("smite", - /*P*/ {}, - /*A*/ { NextAction("shoot") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* dispersion([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("dispersion", - /*P*/ {}, - /*A*/ { NextAction("mana potion") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } }; diff --git a/src/Ai/Class/Priest/Trigger/PriestTriggers.cpp b/src/Ai/Class/Priest/Trigger/PriestTriggers.cpp index 894780ad45..7f61ba6eec 100644 --- a/src/Ai/Class/Priest/Trigger/PriestTriggers.cpp +++ b/src/Ai/Class/Priest/Trigger/PriestTriggers.cpp @@ -68,14 +68,14 @@ bool ShadowformTrigger::IsActive() { return !botAI->HasAura("shadowform", bot); bool ShadowfiendTrigger::IsActive() { return BoostTrigger::IsActive() && !bot->HasSpellCooldown(34433); } BindingHealTrigger::BindingHealTrigger(PlayerbotAI* botAI) - : PartyMemberLowHealthTrigger(botAI, "binding heal", sPlayerbotAIConfig->lowHealth, 0) + : PartyMemberLowHealthTrigger(botAI, "binding heal", sPlayerbotAIConfig.lowHealth, 0) { } bool BindingHealTrigger::IsActive() { return PartyMemberLowHealthTrigger::IsActive() && - AI_VALUE2(uint8, "health", "self target") < sPlayerbotAIConfig->mediumHealth; + AI_VALUE2(uint8, "health", "self target") < sPlayerbotAIConfig.mediumHealth; } const std::set MindSearChannelCheckTrigger::MIND_SEAR_SPELL_IDS = { diff --git a/src/Ai/Class/Rogue/Action/RogueActions.cpp b/src/Ai/Class/Rogue/Action/RogueActions.cpp index 3019e0ec86..32759d6d63 100644 --- a/src/Ai/Class/Rogue/Action/RogueActions.cpp +++ b/src/Ai/Class/Rogue/Action/RogueActions.cpp @@ -14,7 +14,7 @@ bool CastStealthAction::isUseful() { Unit* target = AI_VALUE(Unit*, "current target"); - if (target && bot->GetDistance(target) >= sPlayerbotAIConfig->spellDistance) + if (target && bot->GetDistance(target) >= sPlayerbotAIConfig.spellDistance) return false; return true; } @@ -25,7 +25,7 @@ bool CastStealthAction::isPossible() return !botAI->HasAura(23333, bot) && !botAI->HasAura(23335, bot) && !botAI->HasAura(34976, bot); } -bool UnstealthAction::Execute(Event event) +bool UnstealthAction::Execute(Event) { botAI->RemoveAura("stealth"); // botAI->ChangeStrategy("+dps,-stealthed", BOT_STATE_COMBAT); @@ -33,7 +33,7 @@ bool UnstealthAction::Execute(Event event) return true; } -bool CheckStealthAction::Execute(Event event) +bool CheckStealthAction::Execute(Event) { if (botAI->HasAura("stealth", bot)) { @@ -69,7 +69,7 @@ bool CastTricksOfTheTradeOnMainTankAction::isUseful() return CastSpellAction::isUseful() && AI_VALUE2(float, "distance", GetTargetName()) < 20.0f; } -bool UseDeadlyPoisonAction::Execute(Event event) +bool UseDeadlyPoisonAction::Execute(Event) { std::vector poison_suffixs = {" IX", " VIII", " VII", " VI", " V", " IV", " III", " II", ""}; std::vector items; @@ -109,7 +109,7 @@ bool UseDeadlyPoisonAction::isPossible() return !items.empty(); } -bool UseInstantPoisonAction::Execute(Event event) +bool UseInstantPoisonAction::Execute(Event) { std::vector poison_suffixs = {" IX", " VIII", " VII", " VI", " V", " IV", " III", " II", ""}; std::vector items; @@ -148,7 +148,7 @@ bool UseInstantPoisonAction::isPossible() return !items.empty(); } -bool UseInstantPoisonOffHandAction::Execute(Event event) +bool UseInstantPoisonOffHandAction::Execute(Event) { std::vector poison_suffixs = {" IX", " VIII", " VII", " VI", " V", " IV", " III", " II", ""}; std::vector items; diff --git a/src/Ai/Class/Rogue/RogueAiObjectContext.cpp b/src/Ai/Class/Rogue/RogueAiObjectContext.cpp index 9875f23dec..1b7d29e2e3 100644 --- a/src/Ai/Class/Rogue/RogueAiObjectContext.cpp +++ b/src/Ai/Class/Rogue/RogueAiObjectContext.cpp @@ -10,7 +10,6 @@ #include "DpsRogueStrategy.h" #include "GenericRogueNonCombatStrategy.h" #include "NamedObjectContext.h" -#include "Playerbots.h" #include "PullStrategy.h" #include "RogueActions.h" #include "RogueComboActions.h" @@ -103,96 +102,12 @@ class RogueTriggerFactoryInternal : public NamedObjectContext } }; -class RogueAiObjectContextInternal : public NamedObjectContext -{ -public: - RogueAiObjectContextInternal() - { - creators["riposte"] = &RogueAiObjectContextInternal::riposte; - creators["mutilate"] = &RogueAiObjectContextInternal::mutilate; - creators["sinister strike"] = &RogueAiObjectContextInternal::sinister_strike; - creators["gouge"] = &RogueAiObjectContextInternal::gouge; - creators["kidney shot"] = &RogueAiObjectContextInternal::kidney_shot; - creators["rupture"] = &RogueAiObjectContextInternal::rupture; - creators["slice and dice"] = &RogueAiObjectContextInternal::slice_and_dice; - creators["hunger for blood"] = &RogueAiObjectContextInternal::hunger_for_blood; - creators["eviscerate"] = &RogueAiObjectContextInternal::eviscerate; - creators["vanish"] = &RogueAiObjectContextInternal::vanish; - creators["evasion"] = &RogueAiObjectContextInternal::evasion; - creators["cloak of shadows"] = &RogueAiObjectContextInternal::cloak_of_shadows; - creators["kick"] = &RogueAiObjectContextInternal::kick; - creators["feint"] = &RogueAiObjectContextInternal::feint; - creators["backstab"] = &RogueAiObjectContextInternal::backstab; - creators["expose armor"] = &RogueAiObjectContextInternal::expose_armor; - creators["kick on enemy healer"] = &RogueAiObjectContextInternal::kick_on_enemy_healer; - creators["blade flurry"] = &RogueAiObjectContextInternal::blade_flurry; - creators["adrenaline rush"] = &RogueAiObjectContextInternal::adrenaline_rush; - creators["ambush"] = &RogueAiObjectContextInternal::ambush; - creators["stealth"] = &RogueAiObjectContextInternal::stealth; - creators["sprint"] = &RogueAiObjectContextInternal::sprint; - creators["garrote"] = &RogueAiObjectContextInternal::garrote; - creators["cheap shot"] = &RogueAiObjectContextInternal::cheap_shot; - creators["blind"] = &RogueAiObjectContextInternal::blind; - creators["unstealth"] = &RogueAiObjectContextInternal::unstealth; - creators["sap"] = &RogueAiObjectContextInternal::sap; - creators["check stealth"] = &RogueAiObjectContextInternal::check_stealth; - creators["envenom"] = &RogueAiObjectContextInternal::envenom; - creators["tricks of the trade on main tank"] = &RogueAiObjectContextInternal::tricks_of_the_trade_on_main_tank; - creators["use instant poison on main hand"] = &RogueAiObjectContextInternal::use_instant_poison; - creators["use deadly poison on off hand"] = &RogueAiObjectContextInternal::use_deadly_poison; - creators["use instant poison on off hand"] = &RogueAiObjectContextInternal::use_instant_poison_off_hand; - creators["fan of knives"] = &RogueAiObjectContextInternal::fan_of_knives; - creators["killing spree"] = &RogueAiObjectContextInternal::killing_spree; - } - -private: - static Action* adrenaline_rush(PlayerbotAI* botAI) { return new CastAdrenalineRushAction(botAI); } - static Action* blade_flurry(PlayerbotAI* botAI) { return new CastBladeFlurryAction(botAI); } - static Action* riposte(PlayerbotAI* botAI) { return new CastRiposteAction(botAI); } - static Action* mutilate(PlayerbotAI* botAI) { return new CastMutilateAction(botAI); } - static Action* sinister_strike(PlayerbotAI* botAI) { return new CastSinisterStrikeAction(botAI); } - static Action* gouge(PlayerbotAI* botAI) { return new CastGougeAction(botAI); } - static Action* kidney_shot(PlayerbotAI* botAI) { return new CastKidneyShotAction(botAI); } - static Action* rupture(PlayerbotAI* botAI) { return new CastRuptureAction(botAI); } - static Action* slice_and_dice(PlayerbotAI* botAI) { return new CastSliceAndDiceAction(botAI); } - static Action* hunger_for_blood(PlayerbotAI* botAI) { return new CastHungerForBloodAction(botAI); } - static Action* eviscerate(PlayerbotAI* botAI) { return new CastEviscerateAction(botAI); } - static Action* vanish(PlayerbotAI* botAI) { return new CastVanishAction(botAI); } - static Action* evasion(PlayerbotAI* botAI) { return new CastEvasionAction(botAI); } - static Action* cloak_of_shadows(PlayerbotAI* botAI) { return new CastCloakOfShadowsAction(botAI); } - static Action* kick(PlayerbotAI* botAI) { return new CastKickAction(botAI); } - static Action* feint(PlayerbotAI* botAI) { return new CastFeintAction(botAI); } - static Action* backstab(PlayerbotAI* botAI) { return new CastBackstabAction(botAI); } - static Action* expose_armor(PlayerbotAI* botAI) { return new CastExposeArmorAction(botAI); } - static Action* kick_on_enemy_healer(PlayerbotAI* botAI) { return new CastKickOnEnemyHealerAction(botAI); } - static Action* ambush(PlayerbotAI* botAI) { return new CastAmbushAction(botAI); } - static Action* stealth(PlayerbotAI* botAI) { return new CastStealthAction(botAI); } - static Action* sprint(PlayerbotAI* botAI) { return new CastSprintAction(botAI); } - static Action* garrote(PlayerbotAI* botAI) { return new CastGarroteAction(botAI); } - static Action* cheap_shot(PlayerbotAI* botAI) { return new CastCheapShotAction(botAI); } - static Action* blind(PlayerbotAI* botAI) { return new CastBlindAction(botAI); } - static Action* check_stealth(PlayerbotAI* botAI) { return new CheckStealthAction(botAI); } - static Action* sap(PlayerbotAI* botAI) { return new CastSapAction(botAI); } - static Action* unstealth(PlayerbotAI* botAI) { return new UnstealthAction(botAI); } - static Action* envenom(PlayerbotAI* ai) { return new CastEnvenomAction(ai); } - static Action* tricks_of_the_trade_on_main_tank(PlayerbotAI* ai) - { - return new CastTricksOfTheTradeOnMainTankAction(ai); - } - static Action* use_instant_poison(PlayerbotAI* ai) { return new UseInstantPoisonAction(ai); } - static Action* use_deadly_poison(PlayerbotAI* ai) { return new UseDeadlyPoisonAction(ai); } - static Action* use_instant_poison_off_hand(PlayerbotAI* ai) { return new UseInstantPoisonOffHandAction(ai); } - static Action* fan_of_knives(PlayerbotAI* ai) { return new FanOfKnivesAction(ai); } - static Action* killing_spree(PlayerbotAI* ai) { return new CastKillingSpreeAction(ai); } -}; - SharedNamedObjectContextList RogueAiObjectContext::sharedStrategyContexts; -SharedNamedObjectContextList RogueAiObjectContext::sharedActionContexts; SharedNamedObjectContextList RogueAiObjectContext::sharedTriggerContexts; SharedNamedObjectContextList RogueAiObjectContext::sharedValueContexts; RogueAiObjectContext::RogueAiObjectContext(PlayerbotAI* botAI) - : AiObjectContext(botAI, sharedStrategyContexts, sharedActionContexts, + : AiObjectContext(botAI, sharedStrategyContexts, sharedTriggerContexts, sharedValueContexts) { } @@ -200,7 +115,6 @@ RogueAiObjectContext::RogueAiObjectContext(PlayerbotAI* botAI) void RogueAiObjectContext::BuildSharedContexts() { BuildSharedStrategyContexts(sharedStrategyContexts); - BuildSharedActionContexts(sharedActionContexts); BuildSharedTriggerContexts(sharedTriggerContexts); BuildSharedValueContexts(sharedValueContexts); } @@ -212,12 +126,6 @@ void RogueAiObjectContext::BuildSharedStrategyContexts(SharedNamedObjectContextL strategyContexts.Add(new RogueCombatStrategyFactoryInternal()); } -void RogueAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts) -{ - AiObjectContext::BuildSharedActionContexts(actionContexts); - actionContexts.Add(new RogueAiObjectContextInternal()); -} - void RogueAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts) { AiObjectContext::BuildSharedTriggerContexts(triggerContexts); diff --git a/src/Ai/Class/Rogue/RogueAiObjectContext.h b/src/Ai/Class/Rogue/RogueAiObjectContext.h index 3628f8737d..3153182f59 100644 --- a/src/Ai/Class/Rogue/RogueAiObjectContext.h +++ b/src/Ai/Class/Rogue/RogueAiObjectContext.h @@ -18,12 +18,10 @@ class RogueAiObjectContext : public AiObjectContext static void BuildSharedContexts(); static void BuildSharedStrategyContexts(SharedNamedObjectContextList& strategyContexts); - static void BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts); static void BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts); static void BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts); static SharedNamedObjectContextList sharedStrategyContexts; - static SharedNamedObjectContextList sharedActionContexts; static SharedNamedObjectContextList sharedTriggerContexts; static SharedNamedObjectContextList sharedValueContexts; }; diff --git a/src/Ai/Class/Rogue/Strategy/AssassinationRogueStrategy.cpp b/src/Ai/Class/Rogue/Strategy/AssassinationRogueStrategy.cpp index b8563893ce..cc0c61521e 100644 --- a/src/Ai/Class/Rogue/Strategy/AssassinationRogueStrategy.cpp +++ b/src/Ai/Class/Rogue/Strategy/AssassinationRogueStrategy.cpp @@ -1,7 +1,12 @@ #include "AssassinationRogueStrategy.h" - -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "GenericActions.h" +#include "ReachTargetActions.h" +#include "RogueActions.h" +#include "RogueComboActions.h" +#include "RogueFinishingActions.h" +#include "RogueOpeningActions.h" class AssassinationRogueStrategyActionNodeFactory : public NamedObjectFactory { @@ -18,36 +23,32 @@ class AssassinationRogueStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } static ActionNode* envenom([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "envenom", /*P*/ {}, - /*A*/ { NextAction("rupture") }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } static ActionNode* backstab([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "backstab", /*P*/ {}, - /*A*/ { NextAction("sinister strike") }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } static ActionNode* rupture([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "rupture", /*P*/ {}, - /*A*/ { NextAction("eviscerate") }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } @@ -61,7 +62,7 @@ AssassinationRogueStrategy::AssassinationRogueStrategy(PlayerbotAI* ai) : MeleeC std::vector AssassinationRogueStrategy::getDefaultActions() { return { - NextAction("melee", ACTION_DEFAULT) + CreateNextAction(ACTION_DEFAULT) }; } @@ -73,8 +74,8 @@ void AssassinationRogueStrategy::InitTriggers(std::vector& trigger new TriggerNode( "high energy available", { - NextAction("garrote", ACTION_HIGH + 7), - NextAction("ambush", ACTION_HIGH + 6) + CreateNextAction(ACTION_HIGH + 7.0f), + CreateNextAction(ACTION_HIGH + 6.0f) } ) ); @@ -83,7 +84,7 @@ void AssassinationRogueStrategy::InitTriggers(std::vector& trigger new TriggerNode( "high energy available", { - NextAction("mutilate", ACTION_NORMAL + 3) + CreateNextAction(ACTION_NORMAL + 3.0f) } ) ); @@ -92,7 +93,7 @@ void AssassinationRogueStrategy::InitTriggers(std::vector& trigger new TriggerNode( "hunger for blood", { - NextAction("hunger for blood", ACTION_HIGH + 6), + CreateNextAction(ACTION_HIGH + 6.0f), } ) ); @@ -101,7 +102,7 @@ void AssassinationRogueStrategy::InitTriggers(std::vector& trigger new TriggerNode( "slice and dice", { - NextAction("slice and dice", ACTION_HIGH + 5), + CreateNextAction(ACTION_HIGH + 5.0f), } ) ); @@ -110,8 +111,8 @@ void AssassinationRogueStrategy::InitTriggers(std::vector& trigger new TriggerNode( "combo points 3 available", { - NextAction("envenom", ACTION_HIGH + 5), - NextAction("eviscerate", ACTION_HIGH + 3) + CreateNextAction(ACTION_HIGH + 5.0f), + CreateNextAction(ACTION_HIGH + 3.0f) } ) ); @@ -120,8 +121,8 @@ void AssassinationRogueStrategy::InitTriggers(std::vector& trigger new TriggerNode( "target with combo points almost dead", { - NextAction("envenom", ACTION_HIGH + 4), - NextAction("eviscerate", ACTION_HIGH + 2) + CreateNextAction(ACTION_HIGH + 4.0f), + CreateNextAction(ACTION_HIGH + 2) } ) ); @@ -130,7 +131,7 @@ void AssassinationRogueStrategy::InitTriggers(std::vector& trigger new TriggerNode( "expose armor", { - NextAction("expose armor", ACTION_HIGH + 3), + CreateNextAction(ACTION_HIGH + 3.0f), } ) ); @@ -139,7 +140,7 @@ void AssassinationRogueStrategy::InitTriggers(std::vector& trigger new TriggerNode( "medium threat", { - NextAction("vanish", ACTION_HIGH), + CreateNextAction(ACTION_HIGH), } ) ); @@ -148,8 +149,8 @@ void AssassinationRogueStrategy::InitTriggers(std::vector& trigger new TriggerNode( "low health", { - NextAction("evasion", ACTION_HIGH + 9), - NextAction("feint", ACTION_HIGH + 8) + CreateNextAction(ACTION_HIGH + 9.0f), + CreateNextAction(ACTION_HIGH + 8.0f) } ) ); @@ -158,7 +159,7 @@ void AssassinationRogueStrategy::InitTriggers(std::vector& trigger new TriggerNode( "critical health", { - NextAction("cloak of shadows", ACTION_HIGH + 7) + CreateNextAction(ACTION_HIGH + 7.0f) } ) ); @@ -167,7 +168,7 @@ void AssassinationRogueStrategy::InitTriggers(std::vector& trigger new TriggerNode( "kick", { - NextAction("kick", ACTION_INTERRUPT + 2), + CreateNextAction(ACTION_INTERRUPT + 2.0f), } ) ); @@ -176,7 +177,7 @@ void AssassinationRogueStrategy::InitTriggers(std::vector& trigger new TriggerNode( "kick on enemy healer", { - NextAction("kick on enemy healer", ACTION_INTERRUPT + 1), + CreateNextAction(ACTION_INTERRUPT + 1.0f), } ) ); @@ -185,7 +186,7 @@ void AssassinationRogueStrategy::InitTriggers(std::vector& trigger new TriggerNode( "medium aoe", { - NextAction("fan of knives", ACTION_NORMAL + 5), + CreateNextAction(ACTION_NORMAL + 5.0f), } ) ); @@ -194,7 +195,7 @@ void AssassinationRogueStrategy::InitTriggers(std::vector& trigger new TriggerNode( "low tank threat", { - NextAction("tricks of the trade on main tank", ACTION_HIGH + 7), + CreateNextAction(ACTION_HIGH + 7.0f), } ) ); @@ -203,9 +204,9 @@ void AssassinationRogueStrategy::InitTriggers(std::vector& trigger new TriggerNode( "enemy out of melee", { - NextAction("stealth", ACTION_HIGH + 3), - NextAction("sprint", ACTION_HIGH + 2), - NextAction("reach melee", ACTION_HIGH + 1), + CreateNextAction(ACTION_HIGH + 3.0f), + CreateNextAction(ACTION_HIGH + 2.0f), + CreateNextAction(ACTION_HIGH + 1.0f), } ) ); diff --git a/src/Ai/Class/Rogue/Strategy/DpsRogueStrategy.cpp b/src/Ai/Class/Rogue/Strategy/DpsRogueStrategy.cpp index 22c6a6f836..43b8ab8efd 100644 --- a/src/Ai/Class/Rogue/Strategy/DpsRogueStrategy.cpp +++ b/src/Ai/Class/Rogue/Strategy/DpsRogueStrategy.cpp @@ -4,8 +4,13 @@ */ #include "DpsRogueStrategy.h" - -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "GenericActions.h" +#include "ReachTargetActions.h" +#include "RogueActions.h" +#include "RogueComboActions.h" +#include "RogueFinishingActions.h" +#include "RogueOpeningActions.h" class DpsRogueStrategyActionNodeFactory : public NamedObjectFactory { @@ -25,47 +30,38 @@ class DpsRogueStrategyActionNodeFactory : public NamedObjectFactory static ActionNode* melee([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "melee", /*P*/ {}, - /*A*/ { - NextAction("mutilate") }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } static ActionNode* mutilate([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "mutilate", /*P*/ {}, - /*A*/ { - NextAction("sinister strike") }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } static ActionNode* sinister_strike([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "sinister strike", /*P*/ {}, - /*A*/ { - NextAction("melee") }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } static ActionNode* kick([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "kick", /*P*/ {}, - /*A*/ { - NextAction("kidney shot") }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } static ActionNode* kidney_shot([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "kidney shot", /*P*/ {}, /*A*/ {}, /*C*/ {} @@ -74,20 +70,16 @@ class DpsRogueStrategyActionNodeFactory : public NamedObjectFactory static ActionNode* backstab([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "backstab", /*P*/ {}, - /*A*/ { - NextAction("mutilate") }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } static ActionNode* rupture([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "rupture", /*P*/ {}, - /*A*/ { - NextAction("eviscerate") }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } @@ -101,8 +93,8 @@ DpsRogueStrategy::DpsRogueStrategy(PlayerbotAI* botAI) : MeleeCombatStrategy(bot std::vector DpsRogueStrategy::getDefaultActions() { return { - NextAction("killing spree", ACTION_DEFAULT + 0.1f), - NextAction("melee", ACTION_DEFAULT) + CreateNextAction(ACTION_DEFAULT + 0.1f), + CreateNextAction(ACTION_DEFAULT) }; } @@ -114,8 +106,8 @@ void DpsRogueStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "high energy available", { - NextAction("garrote", ACTION_HIGH + 7), - NextAction("ambush", ACTION_HIGH + 6) + CreateNextAction(ACTION_HIGH + 7.0f), + CreateNextAction(ACTION_HIGH + 6.0f) } ) ); @@ -124,7 +116,7 @@ void DpsRogueStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "high energy available", { - NextAction("sinister strike", ACTION_NORMAL + 3) + CreateNextAction(ACTION_NORMAL + 3.0f) } ) ); @@ -133,7 +125,7 @@ void DpsRogueStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "slice and dice", { - NextAction("slice and dice", ACTION_HIGH + 2) + CreateNextAction(ACTION_HIGH + 2.0f) } ) ); @@ -142,8 +134,8 @@ void DpsRogueStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "combo points available", { - NextAction("rupture", ACTION_HIGH + 1), - NextAction("eviscerate", ACTION_HIGH) + CreateNextAction(ACTION_HIGH + 1.0f), + CreateNextAction(ACTION_HIGH) } ) ); @@ -152,7 +144,7 @@ void DpsRogueStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "target with combo points almost dead", { - NextAction("eviscerate", ACTION_HIGH + 2) + CreateNextAction(ACTION_HIGH + 0.2f) } ) ); @@ -161,7 +153,7 @@ void DpsRogueStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "medium threat", { - NextAction("vanish", ACTION_HIGH) + CreateNextAction(ACTION_HIGH) } ) ); @@ -170,8 +162,8 @@ void DpsRogueStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "low health", { - NextAction("evasion", ACTION_HIGH + 9), - NextAction("feint", ACTION_HIGH + 8) + CreateNextAction(ACTION_HIGH + 9.0f), + CreateNextAction(ACTION_HIGH + 8.0f) } ) ); @@ -180,7 +172,7 @@ void DpsRogueStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "critical health", { - NextAction("cloak of shadows", ACTION_HIGH + 7) + CreateNextAction(ACTION_HIGH + 7.0f) } ) ); @@ -189,7 +181,7 @@ void DpsRogueStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "kick", { - NextAction("kick", ACTION_INTERRUPT + 2) + CreateNextAction(ACTION_INTERRUPT + 2.0f) } ) ); @@ -198,7 +190,7 @@ void DpsRogueStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "kick on enemy healer", { - NextAction("kick on enemy healer", ACTION_INTERRUPT + 1) + CreateNextAction(ACTION_INTERRUPT + 1.0f) } ) ); @@ -207,7 +199,7 @@ void DpsRogueStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "light aoe", { - NextAction("blade flurry", ACTION_HIGH + 3) + CreateNextAction(ACTION_HIGH + 3.0f) } ) ); @@ -216,7 +208,7 @@ void DpsRogueStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "blade flurry", { - NextAction("blade flurry", ACTION_HIGH + 2) + CreateNextAction(ACTION_HIGH + 2.0f) } ) ); @@ -225,9 +217,9 @@ void DpsRogueStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "enemy out of melee", { - NextAction("stealth", ACTION_HIGH + 3), - NextAction("sprint", ACTION_HIGH + 2), - NextAction("reach melee", ACTION_HIGH + 1) + CreateNextAction(ACTION_HIGH + 3.0f), + CreateNextAction(ACTION_HIGH + 2.0f), + CreateNextAction(ACTION_HIGH + 1.0f) } ) ); @@ -236,7 +228,7 @@ void DpsRogueStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "expose armor", { - NextAction("expose armor", ACTION_HIGH + 3) + CreateNextAction(ACTION_HIGH + 3.0f) } ) ); @@ -245,7 +237,7 @@ void DpsRogueStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "low tank threat", { - NextAction("tricks of the trade on main tank", ACTION_HIGH + 7) + CreateNextAction(ACTION_HIGH + 7.0f) } ) ); @@ -267,9 +259,8 @@ class StealthedRogueStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -277,7 +268,6 @@ class StealthedRogueStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } @@ -323,11 +310,11 @@ StealthedRogueStrategy::StealthedRogueStrategy(PlayerbotAI* botAI) : Strategy(bo std::vector StealthedRogueStrategy::getDefaultActions() { return { - NextAction("ambush", ACTION_NORMAL + 4), - NextAction("backstab", ACTION_NORMAL + 3), - NextAction("cheap shot", ACTION_NORMAL + 2), - NextAction("sinister strike", ACTION_NORMAL + 1), - NextAction("melee", ACTION_NORMAL) + CreateNextAction(ACTION_NORMAL + 4), + CreateNextAction(ACTION_NORMAL + 3), + CreateNextAction(ACTION_NORMAL + 2), + CreateNextAction(ACTION_NORMAL + 1), + CreateNextAction(ACTION_NORMAL) }; } @@ -337,7 +324,7 @@ void StealthedRogueStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "combo points available", { - NextAction("eviscerate", ACTION_HIGH) + CreateNextAction(ACTION_HIGH) } ) ); @@ -345,7 +332,7 @@ void StealthedRogueStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "kick", { - NextAction("cheap shot", ACTION_INTERRUPT) + CreateNextAction(ACTION_INTERRUPT) } ) ); @@ -353,7 +340,7 @@ void StealthedRogueStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "kick on enemy healer", { - NextAction("cheap shot", ACTION_INTERRUPT) + CreateNextAction(ACTION_INTERRUPT) } ) ); @@ -361,7 +348,7 @@ void StealthedRogueStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "behind target", { - NextAction("ambush", ACTION_HIGH) + CreateNextAction(ACTION_HIGH) } ) ); @@ -369,7 +356,7 @@ void StealthedRogueStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "not behind target", { - NextAction("cheap shot", ACTION_HIGH) + CreateNextAction(ACTION_HIGH) } ) ); @@ -377,7 +364,7 @@ void StealthedRogueStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "enemy flagcarrier near", { - NextAction("sprint", ACTION_EMERGENCY + 1) + CreateNextAction(ACTION_EMERGENCY + 1.0f) } ) ); @@ -385,7 +372,7 @@ void StealthedRogueStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "unstealth", { - NextAction("unstealth", ACTION_NORMAL) + CreateNextAction(ACTION_NORMAL) } ) ); @@ -394,7 +381,7 @@ void StealthedRogueStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "no stealth", { - NextAction("check stealth", ACTION_EMERGENCY) + CreateNextAction(ACTION_EMERGENCY) } ) ); @@ -402,7 +389,7 @@ void StealthedRogueStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "sprint", { - NextAction("sprint", ACTION_INTERRUPT) + CreateNextAction(ACTION_INTERRUPT) } ) ); @@ -414,7 +401,7 @@ void StealthStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "stealth", { - NextAction("stealth", ACTION_INTERRUPT) + CreateNextAction(ACTION_INTERRUPT) } ) ); @@ -426,7 +413,7 @@ void RogueAoeStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "light aoe", { - NextAction("blade flurry", ACTION_HIGH) + CreateNextAction(ACTION_HIGH) } ) ); @@ -434,7 +421,7 @@ void RogueAoeStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "medium aoe", { - NextAction("fan of knives", ACTION_NORMAL + 5) + CreateNextAction(ACTION_NORMAL + 5.0f) } ) ); @@ -446,7 +433,7 @@ void RogueBoostStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "adrenaline rush", { - NextAction("adrenaline rush", ACTION_HIGH + 2) + CreateNextAction(ACTION_HIGH + 2.0f) } ) ); @@ -458,8 +445,8 @@ void RogueCcStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "sap", { - NextAction("stealth", ACTION_INTERRUPT), - NextAction("sap", ACTION_INTERRUPT) + CreateNextAction(ACTION_INTERRUPT), + CreateNextAction(ACTION_INTERRUPT) } ) ); diff --git a/src/Ai/Class/Rogue/Strategy/GenericRogueNonCombatStrategy.cpp b/src/Ai/Class/Rogue/Strategy/GenericRogueNonCombatStrategy.cpp index 88838f2dd3..9c42c9bbcd 100644 --- a/src/Ai/Class/Rogue/Strategy/GenericRogueNonCombatStrategy.cpp +++ b/src/Ai/Class/Rogue/Strategy/GenericRogueNonCombatStrategy.cpp @@ -4,8 +4,8 @@ */ #include "GenericRogueNonCombatStrategy.h" - -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "RogueActions.h" class GenericRogueNonCombatStrategyActionNodeFactory : public NamedObjectFactory { @@ -18,10 +18,11 @@ class GenericRogueNonCombatStrategyActionNodeFactory : public NamedObjectFactory private: static ActionNode* use_deadly_poison_on_off_hand([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("use deadly poison on off hand", - /*P*/ {}, - /*A*/ { NextAction("use instant poison on off hand") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } }; @@ -34,17 +35,46 @@ void GenericRogueNonCombatStrategy::InitTriggers(std::vector& trig { NonCombatStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("player has flag", - { NextAction("sprint", ACTION_EMERGENCY + 1) })); - triggers.push_back(new TriggerNode("enemy flagcarrier near", - { NextAction("sprint", ACTION_EMERGENCY + 2) })); triggers.push_back( - new TriggerNode("main hand weapon no enchant", - { NextAction("use instant poison on main hand", 20.0f) })); + new TriggerNode( + "player has flag", + { + CreateNextAction(ACTION_EMERGENCY + 1.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "enemy flagcarrier near", + { + CreateNextAction(ACTION_EMERGENCY + 2.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "main hand weapon no enchant", + { + CreateNextAction(20.0f) + } + ) + ); triggers.push_back( - new TriggerNode("off hand weapon no enchant", - { NextAction("use deadly poison on off hand", 19.0f) })); + new TriggerNode( + "off hand weapon no enchant", + { + CreateNextAction(19.0f) + } + ) + ); - triggers.push_back(new TriggerNode("often", { NextAction("unstealth", 30.0f) })); + triggers.push_back( + new TriggerNode( + "often", + { + CreateNextAction(30.0f) + } + ) + ); } diff --git a/src/Ai/Class/Rogue/Trigger/RogueTriggers.cpp b/src/Ai/Class/Rogue/Trigger/RogueTriggers.cpp index fd9901552e..c33dbb7fe4 100644 --- a/src/Ai/Class/Rogue/Trigger/RogueTriggers.cpp +++ b/src/Ai/Class/Rogue/Trigger/RogueTriggers.cpp @@ -22,7 +22,7 @@ bool UnstealthTrigger::IsActive() return botAI->HasAura("stealth", bot) && !AI_VALUE(uint8, "attacker count") && (AI_VALUE2(bool, "moving", "self target") && ((botAI->GetMaster() && - sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", "group leader"), 10.0f) && + ServerFacade::instance().IsDistanceGreaterThan(AI_VALUE2(float, "distance", "group leader"), 10.0f) && AI_VALUE2(bool, "moving", "group leader")) || !AI_VALUE(uint8, "attacker count"))); } @@ -60,7 +60,7 @@ bool StealthTrigger::IsActive() if (bot->InArena()) distance += 15; - return target && sServerFacade->GetDistance2d(bot, target) < distance; + return target && ServerFacade::instance().GetDistance2d(bot, target) < distance; } bool SapTrigger::IsPossible() { return bot->GetLevel() > 10 && bot->HasSpell(6770) && !bot->IsInCombat(); } @@ -99,8 +99,8 @@ bool SprintTrigger::IsActive() return AI_VALUE2(bool, "moving", "self target") && (AI_VALUE2(bool, "moving", "dps target") || AI_VALUE2(bool, "moving", "enemy player target")) && targeted && - (sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", "dps target"), distance) || - sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", "enemy player target"), distance)); + (ServerFacade::instance().IsDistanceGreaterThan(AI_VALUE2(float, "distance", "dps target"), distance) || + ServerFacade::instance().IsDistanceGreaterThan(AI_VALUE2(float, "distance", "enemy player target"), distance)); } bool ExposeArmorTrigger::IsActive() diff --git a/src/Ai/Class/Shaman/Action/ShamanActions.cpp b/src/Ai/Class/Shaman/Action/ShamanActions.cpp index e8ed1234bf..943c10298e 100644 --- a/src/Ai/Class/Shaman/Action/ShamanActions.cpp +++ b/src/Ai/Class/Shaman/Action/ShamanActions.cpp @@ -6,7 +6,6 @@ #include "ShamanActions.h" #include "TotemsShamanStrategy.h" #include "Playerbots.h" -#include "Totem.h" #include "PlayerbotAI.h" #include "Action.h" @@ -71,7 +70,7 @@ bool CastLavaBurstAction::isUseful() // Logic for making a guardian (spirit wolf) use a spell (spirit walk) // There is no existing code for guardians casting spells in the AC/Playerbots repo. -bool CastSpiritWalkAction::Execute(Event event) +bool CastSpiritWalkAction::Execute(Event) { constexpr uint32 SPIRIT_WOLF = 29264; constexpr uint32 SPIRIT_WALK_SPELL = 58875; @@ -93,7 +92,7 @@ bool CastSpiritWalkAction::Execute(Event event) // Set Strategy Assigned Totems (Actions) - First, it checks // the highest-rank spell the bot knows for each totem type, // then adds it to the Call of the Elements bar. -bool SetTotemAction::Execute(Event event) +bool SetTotemAction::Execute(Event) { uint32 totemSpell = 0; for (size_t i = 0; i < totemSpellIdsCount; ++i) diff --git a/src/Ai/Class/Shaman/ShamanAiObjectContext.cpp b/src/Ai/Class/Shaman/ShamanAiObjectContext.cpp index 08ee3638d9..786afbe771 100644 --- a/src/Ai/Class/Shaman/ShamanAiObjectContext.cpp +++ b/src/Ai/Class/Shaman/ShamanAiObjectContext.cpp @@ -10,7 +10,6 @@ #include "RestoShamanStrategy.h" #include "EnhancementShamanStrategy.h" #include "NamedObjectContext.h" -#include "Playerbots.h" #include "ShamanActions.h" #include "ShamanNonCombatStrategy.h" #include "ShamanTriggers.h" @@ -263,206 +262,18 @@ class ShamanATriggerFactoryInternal : public NamedObjectContext static Trigger* set_grounding_totem(PlayerbotAI* ai) { return new SetGroundingTotemTrigger(ai); } }; -class ShamanAiObjectContextInternal : public NamedObjectContext -{ -public: - ShamanAiObjectContextInternal() - { - creators["water shield"] = &ShamanAiObjectContextInternal::water_shield; - creators["lightning shield"] = &ShamanAiObjectContextInternal::lightning_shield; - creators["wind shear"] = &ShamanAiObjectContextInternal::wind_shear; - creators["wind shear on enemy healer"] = &ShamanAiObjectContextInternal::wind_shear_on_enemy_healer; - creators["rockbiter weapon"] = &ShamanAiObjectContextInternal::rockbiter_weapon; - creators["flametongue weapon"] = &ShamanAiObjectContextInternal::flametongue_weapon; - creators["frostbrand weapon"] = &ShamanAiObjectContextInternal::frostbrand_weapon; - creators["windfury weapon"] = &ShamanAiObjectContextInternal::windfury_weapon; - creators["earthliving weapon"] = &ShamanAiObjectContextInternal::earthliving_weapon; - creators["purge"] = &ShamanAiObjectContextInternal::purge; - creators["healing wave"] = &ShamanAiObjectContextInternal::healing_wave; - creators["lesser healing wave"] = &ShamanAiObjectContextInternal::lesser_healing_wave; - creators["healing wave on party"] = &ShamanAiObjectContextInternal::healing_wave_on_party; - creators["lesser healing wave on party"] = &ShamanAiObjectContextInternal::lesser_healing_wave_on_party; - creators["earth shield"] = &ShamanAiObjectContextInternal::earth_shield; - creators["earth shield on party"] = &ShamanAiObjectContextInternal::earth_shield_on_party; - creators["chain heal on party"] = &ShamanAiObjectContextInternal::chain_heal; - creators["riptide"] = &ShamanAiObjectContextInternal::riptide; - creators["riptide on party"] = &ShamanAiObjectContextInternal::riptide_on_party; - creators["stormstrike"] = &ShamanAiObjectContextInternal::stormstrike; - creators["lava lash"] = &ShamanAiObjectContextInternal::lava_lash; - creators["fire nova"] = &ShamanAiObjectContextInternal::fire_nova; - creators["ancestral spirit"] = &ShamanAiObjectContextInternal::ancestral_spirit; - creators["water walking"] = &ShamanAiObjectContextInternal::water_walking; - creators["water breathing"] = &ShamanAiObjectContextInternal::water_breathing; - creators["water walking on party"] = &ShamanAiObjectContextInternal::water_walking_on_party; - creators["water breathing on party"] = &ShamanAiObjectContextInternal::water_breathing_on_party; - creators["cleanse spirit"] = &ShamanAiObjectContextInternal::cleanse_spirit; - creators["cleanse spirit poison on party"] = &ShamanAiObjectContextInternal::cleanse_spirit_poison_on_party; - creators["cleanse spirit disease on party"] = &ShamanAiObjectContextInternal::cleanse_spirit_disease_on_party; - creators["cleanse spirit curse on party"] = &ShamanAiObjectContextInternal::cleanse_spirit_curse_on_party; - creators["flame shock"] = &ShamanAiObjectContextInternal::flame_shock; - creators["earth shock"] = &ShamanAiObjectContextInternal::earth_shock; - creators["frost shock"] = &ShamanAiObjectContextInternal::frost_shock; - creators["chain lightning"] = &ShamanAiObjectContextInternal::chain_lightning; - creators["lightning bolt"] = &ShamanAiObjectContextInternal::lightning_bolt; - creators["thunderstorm"] = &ShamanAiObjectContextInternal::thunderstorm; - creators["heroism"] = &ShamanAiObjectContextInternal::heroism; - creators["bloodlust"] = &ShamanAiObjectContextInternal::bloodlust; - creators["elemental mastery"] = &ShamanAiObjectContextInternal::elemental_mastery; - creators["cure disease"] = &ShamanAiObjectContextInternal::cure_disease; - creators["cure disease on party"] = &ShamanAiObjectContextInternal::cure_disease_on_party; - creators["cure poison"] = &ShamanAiObjectContextInternal::cure_poison; - creators["cure poison on party"] = &ShamanAiObjectContextInternal::cure_poison_on_party; - creators["lava burst"] = &ShamanAiObjectContextInternal::lava_burst; - creators["earth shield on main tank"] = &ShamanAiObjectContextInternal::earth_shield_on_main_tank; - creators["shamanistic rage"] = &ShamanAiObjectContextInternal::shamanistic_rage; - creators["feral spirit"] = &ShamanAiObjectContextInternal::feral_spirit; - creators["spirit walk"] = &ShamanAiObjectContextInternal::spirit_walk; - creators["call of the elements"] = &ShamanAiObjectContextInternal::call_of_the_elements; - creators["totemic recall"] = &ShamanAiObjectContextInternal::totemic_recall; - creators["strength of earth totem"] = &ShamanAiObjectContextInternal::strength_of_earth_totem; - creators["stoneskin totem"] = &ShamanAiObjectContextInternal::stoneskin_totem; - creators["tremor totem"] = &ShamanAiObjectContextInternal::tremor_totem; - creators["earthbind totem"] = &ShamanAiObjectContextInternal::earthbind_totem; - creators["stoneclaw totem"] = &ShamanAiObjectContextInternal::stoneclaw_totem; - creators["searing totem"] = &ShamanAiObjectContextInternal::searing_totem; - creators["magma totem"] = &ShamanAiObjectContextInternal::magma_totem; - creators["flametongue totem"] = &ShamanAiObjectContextInternal::flametongue_totem; - creators["totem of wrath"] = &ShamanAiObjectContextInternal::totem_of_wrath; - creators["frost resistance totem"] = &ShamanAiObjectContextInternal::frost_resistance_totem; - creators["fire elemental totem"] = &ShamanAiObjectContextInternal::fire_elemental_totem; - creators["fire elemental totem melee"] = &ShamanAiObjectContextInternal::fire_elemental_totem_melee; - creators["healing stream totem"] = &ShamanAiObjectContextInternal::healing_stream_totem; - creators["mana spring totem"] = &ShamanAiObjectContextInternal::mana_spring_totem; - creators["cleansing totem"] = &ShamanAiObjectContextInternal::cleansing_totem; - creators["mana tide totem"] = &ShamanAiObjectContextInternal::mana_tide_totem; - creators["fire resistance totem"] = &ShamanAiObjectContextInternal::fire_resistance_totem; - creators["wrath of air totem"] = &ShamanAiObjectContextInternal::wrath_of_air_totem; - creators["windfury totem"] = &ShamanAiObjectContextInternal::windfury_totem; - creators["nature resistance totem"] = &ShamanAiObjectContextInternal::nature_resistance_totem; - creators["set strength of earth totem"] = &ShamanAiObjectContextInternal::set_strength_of_earth_totem; - creators["set stoneskin totem"] = &ShamanAiObjectContextInternal::set_stoneskin_totem; - creators["set tremor totem"] = &ShamanAiObjectContextInternal::set_tremor_totem; - creators["set earthbind totem"] = &ShamanAiObjectContextInternal::set_earthbind_totem; - creators["set searing totem"] = &ShamanAiObjectContextInternal::set_searing_totem; - creators["set magma totem"] = &ShamanAiObjectContextInternal::set_magma_totem; - creators["set flametongue totem"] = &ShamanAiObjectContextInternal::set_flametongue_totem; - creators["set totem of wrath"] = &ShamanAiObjectContextInternal::set_totem_of_wrath; - creators["set frost resistance totem"] = &ShamanAiObjectContextInternal::set_frost_resistance_totem; - creators["set healing stream totem"] = &ShamanAiObjectContextInternal::set_healing_stream_totem; - creators["set mana spring totem"] = &ShamanAiObjectContextInternal::set_mana_spring_totem; - creators["set cleansing totem"] = &ShamanAiObjectContextInternal::set_cleansing_totem; - creators["set fire resistance totem"] = &ShamanAiObjectContextInternal::set_fire_resistance_totem; - creators["set wrath of air totem"] = &ShamanAiObjectContextInternal::set_wrath_of_air_totem; - creators["set windfury totem"] = &ShamanAiObjectContextInternal::set_windfury_totem; - creators["set nature resistance totem"] = &ShamanAiObjectContextInternal::set_nature_resistance_totem; - creators["set grounding totem"] = &ShamanAiObjectContextInternal::set_grounding_totem; - } - -private: - static Action* heroism(PlayerbotAI* botAI) { return new CastHeroismAction(botAI); } - static Action* bloodlust(PlayerbotAI* botAI) { return new CastBloodlustAction(botAI); } - static Action* elemental_mastery(PlayerbotAI* botAI) { return new CastElementalMasteryAction(botAI); } - static Action* thunderstorm(PlayerbotAI* botAI) { return new CastThunderstormAction(botAI); } - static Action* lightning_bolt(PlayerbotAI* botAI) { return new CastLightningBoltAction(botAI); } - static Action* chain_lightning(PlayerbotAI* botAI) { return new CastChainLightningAction(botAI); } - static Action* frost_shock(PlayerbotAI* botAI) { return new CastFrostShockAction(botAI); } - static Action* earth_shock(PlayerbotAI* botAI) { return new CastEarthShockAction(botAI); } - static Action* flame_shock(PlayerbotAI* botAI) { return new CastFlameShockAction(botAI); } - static Action* cleanse_spirit_poison_on_party(PlayerbotAI* botAI) { return new CastCleanseSpiritPoisonOnPartyAction(botAI); } - static Action* cleanse_spirit_disease_on_party(PlayerbotAI* botAI) { return new CastCleanseSpiritDiseaseOnPartyAction(botAI); } - static Action* cleanse_spirit_curse_on_party(PlayerbotAI* botAI) { return new CastCleanseSpiritCurseOnPartyAction(botAI); } - static Action* cleanse_spirit(PlayerbotAI* botAI) { return new CastCleanseSpiritAction(botAI); } - static Action* water_walking(PlayerbotAI* botAI) { return new CastWaterWalkingAction(botAI); } - static Action* water_breathing(PlayerbotAI* botAI) { return new CastWaterBreathingAction(botAI); } - static Action* water_walking_on_party(PlayerbotAI* botAI) { return new CastWaterWalkingOnPartyAction(botAI); } - static Action* water_breathing_on_party(PlayerbotAI* botAI) { return new CastWaterBreathingOnPartyAction(botAI); } - static Action* water_shield(PlayerbotAI* botAI) { return new CastWaterShieldAction(botAI); } - static Action* lightning_shield(PlayerbotAI* botAI) { return new CastLightningShieldAction(botAI); } - static Action* fire_nova(PlayerbotAI* botAI) { return new CastFireNovaAction(botAI); } - static Action* wind_shear(PlayerbotAI* botAI) { return new CastWindShearAction(botAI); } - static Action* rockbiter_weapon(PlayerbotAI* botAI) { return new CastRockbiterWeaponAction(botAI); } - static Action* flametongue_weapon(PlayerbotAI* botAI) { return new CastFlametongueWeaponAction(botAI); } - static Action* frostbrand_weapon(PlayerbotAI* botAI) { return new CastFrostbrandWeaponAction(botAI); } - static Action* windfury_weapon(PlayerbotAI* botAI) { return new CastWindfuryWeaponAction(botAI); } - static Action* earthliving_weapon(PlayerbotAI* botAI) { return new CastEarthlivingWeaponAction(botAI); } - static Action* purge(PlayerbotAI* botAI) { return new CastPurgeAction(botAI); } - static Action* healing_wave(PlayerbotAI* botAI) { return new CastHealingWaveAction(botAI); } - static Action* lesser_healing_wave(PlayerbotAI* botAI) { return new CastLesserHealingWaveAction(botAI); } - static Action* healing_wave_on_party(PlayerbotAI* botAI) { return new CastHealingWaveOnPartyAction(botAI); } - static Action* lesser_healing_wave_on_party(PlayerbotAI* botAI) { return new CastLesserHealingWaveOnPartyAction(botAI); } - static Action* earth_shield(PlayerbotAI* botAI) { return new CastEarthShieldAction(botAI); } - static Action* earth_shield_on_party(PlayerbotAI* botAI) { return new CastEarthShieldOnPartyAction(botAI); } - static Action* chain_heal(PlayerbotAI* botAI) { return new CastChainHealAction(botAI); } - static Action* riptide(PlayerbotAI* botAI) { return new CastRiptideAction(botAI); } - static Action* riptide_on_party(PlayerbotAI* botAI) { return new CastRiptideOnPartyAction(botAI); } - static Action* stormstrike(PlayerbotAI* botAI) { return new CastStormstrikeAction(botAI); } - static Action* lava_lash(PlayerbotAI* botAI) { return new CastLavaLashAction(botAI); } - static Action* ancestral_spirit(PlayerbotAI* botAI) { return new CastAncestralSpiritAction(botAI); } - static Action* wind_shear_on_enemy_healer(PlayerbotAI* botAI) { return new CastWindShearOnEnemyHealerAction(botAI); } - static Action* cure_poison(PlayerbotAI* botAI) { return new CastCurePoisonActionSham(botAI); } - static Action* cure_poison_on_party(PlayerbotAI* botAI) { return new CastCurePoisonOnPartyActionSham(botAI); } - static Action* cure_disease(PlayerbotAI* botAI) { return new CastCureDiseaseActionSham(botAI); } - static Action* cure_disease_on_party(PlayerbotAI* botAI) { return new CastCureDiseaseOnPartyActionSham(botAI); } - static Action* lava_burst(PlayerbotAI* ai) { return new CastLavaBurstAction(ai); } - static Action* earth_shield_on_main_tank(PlayerbotAI* ai) { return new CastEarthShieldOnMainTankAction(ai); } - static Action* shamanistic_rage(PlayerbotAI* ai) { return new CastShamanisticRageAction(ai); } - static Action* feral_spirit(PlayerbotAI* ai) { return new CastFeralSpiritAction(ai); } - static Action* spirit_walk(PlayerbotAI* ai) { return new CastSpiritWalkAction(ai); } - static Action* call_of_the_elements(PlayerbotAI* ai) { return new CastCallOfTheElementsAction(ai); } - static Action* totemic_recall(PlayerbotAI* ai) { return new CastTotemicRecallAction(ai); } - static Action* strength_of_earth_totem(PlayerbotAI* ai) { return new CastStrengthOfEarthTotemAction(ai); } - static Action* stoneskin_totem(PlayerbotAI* ai) { return new CastStoneskinTotemAction(ai); } - static Action* tremor_totem(PlayerbotAI* ai) { return new CastTremorTotemAction(ai); } - static Action* earthbind_totem(PlayerbotAI* ai) { return new CastEarthbindTotemAction(ai); } - static Action* stoneclaw_totem(PlayerbotAI* ai) { return new CastStoneclawTotemAction(ai); } - static Action* searing_totem(PlayerbotAI* ai) { return new CastSearingTotemAction(ai); } - static Action* magma_totem(PlayerbotAI* ai) { return new CastMagmaTotemAction(ai); } - static Action* flametongue_totem(PlayerbotAI* ai) { return new CastFlametongueTotemAction(ai); } - static Action* totem_of_wrath(PlayerbotAI* ai) { return new CastTotemOfWrathAction(ai); } - static Action* frost_resistance_totem(PlayerbotAI* ai) { return new CastFrostResistanceTotemAction(ai); } - static Action* fire_elemental_totem(PlayerbotAI* ai) { return new CastFireElementalTotemAction(ai); } - static Action* fire_elemental_totem_melee(PlayerbotAI* ai) { return new CastFireElementalTotemMeleeAction(ai); } - static Action* healing_stream_totem(PlayerbotAI* ai) { return new CastHealingStreamTotemAction(ai); } - static Action* mana_spring_totem(PlayerbotAI* ai) { return new CastManaSpringTotemAction(ai); } - static Action* cleansing_totem(PlayerbotAI* ai) { return new CastCleansingTotemAction(ai); } - static Action* mana_tide_totem(PlayerbotAI* ai) { return new CastManaTideTotemAction(ai); } - static Action* fire_resistance_totem(PlayerbotAI* ai) { return new CastFireResistanceTotemAction(ai); } - static Action* wrath_of_air_totem(PlayerbotAI* ai) { return new CastWrathOfAirTotemAction(ai); } - static Action* windfury_totem(PlayerbotAI* ai) { return new CastWindfuryTotemAction(ai); } - static Action* nature_resistance_totem(PlayerbotAI* ai) { return new CastNatureResistanceTotemAction(ai); } - static Action* set_strength_of_earth_totem(PlayerbotAI* ai) { return new SetStrengthOfEarthTotemAction(ai); } - static Action* set_stoneskin_totem(PlayerbotAI* ai) { return new SetStoneskinTotemAction(ai); } - static Action* set_tremor_totem(PlayerbotAI* ai) { return new SetTremorTotemAction(ai); } - static Action* set_earthbind_totem(PlayerbotAI* ai) { return new SetEarthbindTotemAction(ai); } - static Action* set_searing_totem(PlayerbotAI* ai) { return new SetSearingTotemAction(ai); } - static Action* set_magma_totem(PlayerbotAI* ai) { return new SetMagmaTotemAction(ai); } - static Action* set_flametongue_totem(PlayerbotAI* ai) { return new SetFlametongueTotemAction(ai); } - static Action* set_totem_of_wrath(PlayerbotAI* ai) { return new SetTotemOfWrathAction(ai); } - static Action* set_frost_resistance_totem(PlayerbotAI* ai) { return new SetFrostResistanceTotemAction(ai); } - static Action* set_healing_stream_totem(PlayerbotAI* ai) { return new SetHealingStreamTotemAction(ai); } - static Action* set_mana_spring_totem(PlayerbotAI* ai) { return new SetManaSpringTotemAction(ai); } - static Action* set_cleansing_totem(PlayerbotAI* ai) { return new SetCleansingTotemAction(ai); } - static Action* set_fire_resistance_totem(PlayerbotAI* ai) { return new SetFireResistanceTotemAction(ai); } - static Action* set_wrath_of_air_totem(PlayerbotAI* ai) { return new SetWrathOfAirTotemAction(ai); } - static Action* set_windfury_totem(PlayerbotAI* ai) { return new SetWindfuryTotemAction(ai); } - static Action* set_nature_resistance_totem(PlayerbotAI* ai) { return new SetNatureResistanceTotemAction(ai); } - static Action* set_grounding_totem(PlayerbotAI* ai) { return new SetGroundingTotemAction(ai); } -}; - SharedNamedObjectContextList ShamanAiObjectContext::sharedStrategyContexts; -SharedNamedObjectContextList ShamanAiObjectContext::sharedActionContexts; SharedNamedObjectContextList ShamanAiObjectContext::sharedTriggerContexts; SharedNamedObjectContextList ShamanAiObjectContext::sharedValueContexts; ShamanAiObjectContext::ShamanAiObjectContext(PlayerbotAI* botAI) - : AiObjectContext(botAI, sharedStrategyContexts, sharedActionContexts, sharedTriggerContexts, sharedValueContexts) + : AiObjectContext(botAI, sharedStrategyContexts, sharedTriggerContexts, sharedValueContexts) { } void ShamanAiObjectContext::BuildSharedContexts() { BuildSharedStrategyContexts(sharedStrategyContexts); - BuildSharedActionContexts(sharedActionContexts); BuildSharedTriggerContexts(sharedTriggerContexts); BuildSharedValueContexts(sharedValueContexts); } @@ -478,12 +289,6 @@ void ShamanAiObjectContext::BuildSharedStrategyContexts(SharedNamedObjectContext strategyContexts.Add(new ShamanAirTotemStrategyFactoryInternal()); } -void ShamanAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts) -{ - AiObjectContext::BuildSharedActionContexts(actionContexts); - actionContexts.Add(new ShamanAiObjectContextInternal()); -} - void ShamanAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts) { AiObjectContext::BuildSharedTriggerContexts(triggerContexts); diff --git a/src/Ai/Class/Shaman/ShamanAiObjectContext.h b/src/Ai/Class/Shaman/ShamanAiObjectContext.h index cb07ba6e64..c4bb0341d6 100644 --- a/src/Ai/Class/Shaman/ShamanAiObjectContext.h +++ b/src/Ai/Class/Shaman/ShamanAiObjectContext.h @@ -17,12 +17,10 @@ class ShamanAiObjectContext : public AiObjectContext static void BuildSharedContexts(); static void BuildSharedStrategyContexts(SharedNamedObjectContextList& strategyContexts); - static void BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts); static void BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts); static void BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts); static SharedNamedObjectContextList sharedStrategyContexts; - static SharedNamedObjectContextList sharedActionContexts; static SharedNamedObjectContextList sharedTriggerContexts; static SharedNamedObjectContextList sharedValueContexts; }; diff --git a/src/Ai/Class/Shaman/Strategy/ElementalShamanStrategy.cpp b/src/Ai/Class/Shaman/Strategy/ElementalShamanStrategy.cpp index c1295687cd..f800bdefb8 100644 --- a/src/Ai/Class/Shaman/Strategy/ElementalShamanStrategy.cpp +++ b/src/Ai/Class/Shaman/Strategy/ElementalShamanStrategy.cpp @@ -4,8 +4,8 @@ */ #include "ElementalShamanStrategy.h" - -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "ShamanActions.h" // ===== Action Node Factory ===== class ElementalShamanStrategyActionNodeFactory : public NamedObjectFactory @@ -25,15 +25,78 @@ class ElementalShamanStrategyActionNodeFactory : public NamedObjectFactory ElementalShamanStrategy::getDefaultActions() { return { - NextAction("lava burst", 5.2f), - NextAction("lightning bolt", 5.0f) + CreateNextAction(5.2f), + CreateNextAction(5.0f) }; } @@ -61,7 +124,7 @@ void ElementalShamanStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "call of the elements", { - NextAction("call of the elements", 60.0f) + CreateNextAction(60.0f) } ) ); @@ -69,7 +132,7 @@ void ElementalShamanStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "low health", { - NextAction("stoneclaw totem", 40.0f) + CreateNextAction(40.0f) } ) ); @@ -79,7 +142,7 @@ void ElementalShamanStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "elemental mastery", { - NextAction("elemental mastery", 29.0f) + CreateNextAction(29.0f) } ) ); @@ -89,7 +152,7 @@ void ElementalShamanStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "earth shock execute", { - NextAction("earth shock", 5.5f) + CreateNextAction(5.5f) } ) ); @@ -97,7 +160,7 @@ void ElementalShamanStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "flame shock", { - NextAction("flame shock", 5.3f) + CreateNextAction(5.3f) } ) ); @@ -107,7 +170,7 @@ void ElementalShamanStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "water shield", { - NextAction("water shield", 19.5f) + CreateNextAction(19.5f) } ) ); @@ -115,7 +178,7 @@ void ElementalShamanStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "high mana", { - NextAction("thunderstorm", 19.0f) + CreateNextAction(19.0f) } ) ); @@ -125,7 +188,7 @@ void ElementalShamanStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "enemy is close", { - NextAction("thunderstorm", 19.0f) + CreateNextAction(19.0f) } ) ); diff --git a/src/Ai/Class/Shaman/Strategy/EnhancementShamanStrategy.cpp b/src/Ai/Class/Shaman/Strategy/EnhancementShamanStrategy.cpp index 4b7fb7159e..bd740e579e 100644 --- a/src/Ai/Class/Shaman/Strategy/EnhancementShamanStrategy.cpp +++ b/src/Ai/Class/Shaman/Strategy/EnhancementShamanStrategy.cpp @@ -4,8 +4,10 @@ */ #include "EnhancementShamanStrategy.h" - -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "GenericActions.h" +#include "ReachTargetActions.h" +#include "ShamanActions.h" // ===== Action Node Factory ===== class EnhancementShamanStrategyActionNodeFactory : public NamedObjectFactory @@ -25,23 +27,78 @@ class EnhancementShamanStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } - static ActionNode* feral_spirit(PlayerbotAI*) { return new ActionNode("feral spirit", {}, {}, {}); } - static ActionNode* lightning_bolt(PlayerbotAI*) { return new ActionNode("lightning bolt", {}, {}, {}); } - static ActionNode* earth_shock(PlayerbotAI*) { return new ActionNode("earth shock", {}, {}, {}); } - static ActionNode* flame_shock(PlayerbotAI*) { return new ActionNode("flame shock", {}, {}, {}); } - static ActionNode* shamanistic_rage(PlayerbotAI*) { return new ActionNode("shamanistic rage", {}, {}, {}); } - static ActionNode* call_of_the_elements(PlayerbotAI*) { return new ActionNode("call of the elements", {}, {}, {}); } - static ActionNode* lightning_shield(PlayerbotAI*) { return new ActionNode("lightning shield", {}, {}, {}); } + static ActionNode* feral_spirit(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* lightning_bolt(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* earth_shock(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* flame_shock(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* shamanistic_rage(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* call_of_the_elements(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* lightning_shield(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } }; // ===== Single Target Strategy ===== @@ -54,11 +111,11 @@ EnhancementShamanStrategy::EnhancementShamanStrategy(PlayerbotAI* botAI) : Gener std::vector EnhancementShamanStrategy::getDefaultActions() { return { - NextAction("stormstrike", 5.5f), - NextAction("feral spirit", 5.4f), - NextAction("earth shock", 5.3f), - NextAction("lava lash", 5.2f), - NextAction("melee", 5.0f) + CreateNextAction(5.5f), + CreateNextAction(5.4f), + CreateNextAction(5.3f), + CreateNextAction(5.2f), + CreateNextAction(5.0f) }; } @@ -72,7 +129,7 @@ void EnhancementShamanStrategy::InitTriggers(std::vector& triggers new TriggerNode( "call of the elements and enemy within melee", { - NextAction("call of the elements", 60.0f) + CreateNextAction(60.0f) } ) ); @@ -82,7 +139,7 @@ void EnhancementShamanStrategy::InitTriggers(std::vector& triggers new TriggerNode( "spirit walk ready", { - NextAction("spirit walk", 50.0f) + CreateNextAction(50.0f) } ) ); @@ -92,7 +149,7 @@ void EnhancementShamanStrategy::InitTriggers(std::vector& triggers new TriggerNode( "enemy out of melee", { - NextAction("reach melee", 40.0f) + CreateNextAction(40.0f) } ) ); @@ -100,7 +157,7 @@ void EnhancementShamanStrategy::InitTriggers(std::vector& triggers new TriggerNode( "maelstrom weapon 5", { - NextAction("lightning bolt", 20.0f) + CreateNextAction(20.0f) } ) ); @@ -108,7 +165,7 @@ void EnhancementShamanStrategy::InitTriggers(std::vector& triggers new TriggerNode( "maelstrom weapon 4", { - NextAction("lightning bolt", 19.5f) + CreateNextAction(19.5f) } ) ); @@ -116,7 +173,7 @@ void EnhancementShamanStrategy::InitTriggers(std::vector& triggers new TriggerNode( "flame shock", { - NextAction("flame shock", 19.0f) + CreateNextAction(19.0f) } ) ); @@ -124,7 +181,7 @@ void EnhancementShamanStrategy::InitTriggers(std::vector& triggers new TriggerNode( "lightning shield", { - NextAction("lightning shield", 18.5f) + CreateNextAction(18.5f) } ) ); @@ -134,7 +191,7 @@ void EnhancementShamanStrategy::InitTriggers(std::vector& triggers new TriggerNode( "medium mana", { - NextAction("shamanistic rage", 23.0f) + CreateNextAction(23.0f) } ) ); @@ -142,7 +199,7 @@ void EnhancementShamanStrategy::InitTriggers(std::vector& triggers new TriggerNode( "low health", { - NextAction("shamanistic rage", 23.0f) + CreateNextAction(23.0f) } ) ); diff --git a/src/Ai/Class/Shaman/Strategy/GenericShamanStrategy.cpp b/src/Ai/Class/Shaman/Strategy/GenericShamanStrategy.cpp index fd47d023d4..98264b0818 100644 --- a/src/Ai/Class/Shaman/Strategy/GenericShamanStrategy.cpp +++ b/src/Ai/Class/Shaman/Strategy/GenericShamanStrategy.cpp @@ -4,9 +4,10 @@ */ #include "GenericShamanStrategy.h" -#include "Playerbots.h" -#include "Strategy.h" #include "AiFactory.h" +#include "CreateNextAction.h" +#include "GenericActions.h" +#include "ShamanActions.h" class GenericShamanStrategyActionNodeFactory : public NamedObjectFactory { @@ -39,60 +40,116 @@ class GenericShamanStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, + /*C*/ {} + ); } static ActionNode* flametongue_totem([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("flametongue totem", - /*P*/ {}, - /*A*/ { NextAction("searing totem") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* magma_totem([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("magma totem", - /*P*/ {}, - /*A*/ { NextAction("searing totem") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); + } + static ActionNode* searing_totem(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); } - static ActionNode* searing_totem(PlayerbotAI*) { return new ActionNode("searing totem", {}, {}, {}); } static ActionNode* strength_of_earth_totem([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("strength of earth totem", - /*P*/ {}, - /*A*/ { NextAction("stoneskin totem") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); + } + static ActionNode* stoneskin_totem(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); } - static ActionNode* stoneskin_totem(PlayerbotAI*) { return new ActionNode("stoneskin totem", {}, {}, {}); } static ActionNode* cleansing_totem([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("cleansing totem", - /*P*/ {}, - /*A*/ { NextAction("mana spring totem") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); + } + static ActionNode* mana_spring_totem(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* healing_stream_totem(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); } - static ActionNode* mana_spring_totem(PlayerbotAI*) { return new ActionNode("mana spring totem", {}, {}, {}); } - static ActionNode* healing_stream_totem(PlayerbotAI*) { return new ActionNode("healing stream totem", {}, {}, {}); } static ActionNode* wrath_of_air_totem([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("wrath of air totem", - /*P*/ {}, - /*A*/ { NextAction("windfury totem") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* windfury_totem([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("windfury totem", - /*P*/ {}, - /*A*/ { NextAction("grounding totem") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); + } + static ActionNode* grounding_totem(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* wind_shear(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* purge(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); } - static ActionNode* grounding_totem(PlayerbotAI*) { return new ActionNode("grounding totem", {}, {}, {}); } - static ActionNode* wind_shear(PlayerbotAI*) { return new ActionNode("wind shear", {}, {}, {}); } - static ActionNode* purge(PlayerbotAI*) { return new ActionNode("purge", {}, {}, {}); } }; GenericShamanStrategy::GenericShamanStrategy(PlayerbotAI* botAI) : CombatStrategy(botAI) @@ -104,42 +161,175 @@ void GenericShamanStrategy::InitTriggers(std::vector& triggers) { CombatStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("wind shear", { NextAction("wind shear", 23.0f), })); - triggers.push_back(new TriggerNode("wind shear on enemy healer", { NextAction("wind shear on enemy healer", 23.0f), })); - triggers.push_back(new TriggerNode("purge", { NextAction("purge", ACTION_DISPEL), })); - triggers.push_back(new TriggerNode("medium mana", { NextAction("mana potion", ACTION_DISPEL), })); - triggers.push_back(new TriggerNode("new pet", { NextAction("set pet stance", 65.0f), })); + triggers.push_back( + new TriggerNode( + "wind shear", + { + CreateNextAction(23.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "wind shear on enemy healer", + { + CreateNextAction(23.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "purge", + { + CreateNextAction(ACTION_DISPEL), + } + ) + ); + triggers.push_back( + new TriggerNode( + "medium mana", + { + CreateNextAction(ACTION_DISPEL), + } + ) + ); + triggers.push_back( + new TriggerNode( + "new pet", + { + CreateNextAction(65.0f), + } + ) + ); } void ShamanCureStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("cure poison", { NextAction("cure poison", 21.0f), })); - triggers.push_back(new TriggerNode("party member cure poison", { NextAction("cure poison on party", 21.0f), })); - triggers.push_back(new TriggerNode("cleanse spirit poison", { NextAction("cleanse spirit", 24.0f), })); - triggers.push_back(new TriggerNode("party member cleanse spirit poison", { NextAction("cleanse spirit poison on party", 23.0f), })); - triggers.push_back(new TriggerNode("cure disease", { NextAction("cure disease", 31.0f), })); - triggers.push_back(new TriggerNode("party member cure disease", { NextAction("cure disease on party", 30.0f), })); - triggers.push_back(new TriggerNode("cleanse spirit disease", { NextAction("cleanse spirit", 24.0f), })); - triggers.push_back(new TriggerNode("party member cleanse spirit disease", { NextAction("cleanse spirit disease on party", 23.0f), })); - triggers.push_back(new TriggerNode("cleanse spirit curse", { NextAction("cleanse spirit", 24.0f), })); - triggers.push_back(new TriggerNode("party member cleanse spirit curse", { NextAction("cleanse spirit curse on party", 23.0f), })); + triggers.push_back( + new TriggerNode( + "cure poison", + { + CreateNextAction(21.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member cure poison", + { + CreateNextAction(21.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "cleanse spirit poison", + { + CreateNextAction(24.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member cleanse spirit poison", + { + CreateNextAction(23.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "cure disease", + { + CreateNextAction(31.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member cure disease", + { + CreateNextAction(30.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "cleanse spirit disease", + { + CreateNextAction(24.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member cleanse spirit disease", + { + CreateNextAction(23.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "cleanse spirit curse", + { + CreateNextAction(24.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member cleanse spirit curse", + { + CreateNextAction(23.0f), + } + ) + ); } void ShamanBoostStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("heroism", { NextAction("heroism", 30.0f), })); - triggers.push_back(new TriggerNode("bloodlust", { NextAction("bloodlust", 30.0f), })); + triggers.push_back( + new TriggerNode( + "heroism", + { + CreateNextAction(30.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "bloodlust", + { + CreateNextAction(30.0f), + } + ) + ); Player* bot = botAI->GetBot(); int tab = AiFactory::GetPlayerSpecTab(bot); if (tab == 0) // Elemental { - triggers.push_back(new TriggerNode("fire elemental totem", { NextAction("fire elemental totem", 23.0f), })); + triggers.push_back( + new TriggerNode( + "fire elemental totem", + { + CreateNextAction(23.0f), + } + ) + ); } else if (tab == 1) // Enhancement { - triggers.push_back(new TriggerNode("fire elemental totem", { NextAction("fire elemental totem melee", 24.0f), })); + triggers.push_back( + new TriggerNode( + "fire elemental totem", + { + CreateNextAction(24.0f), + } + ) + ); } } @@ -147,24 +337,65 @@ void ShamanAoeStrategy::InitTriggers(std::vector& triggers) { Player* bot = botAI->GetBot(); - int tab = AiFactory::GetPlayerSpecTab(bot); + const uint8_t tab = AiFactory::GetPlayerSpecTab(bot); - if (tab == 0) // Elemental + // Elemental + if (tab == SHAMAN_TAB_ELEMENTAL) { - triggers.push_back(new TriggerNode("medium aoe",{ NextAction("fire nova", 23.0f), })); - triggers.push_back(new TriggerNode("chain lightning no cd", { NextAction("chain lightning", 5.6f), })); + triggers.push_back( + new TriggerNode( + "medium aoe",{ CreateNextAction(23.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "chain lightning no cd", + { + CreateNextAction(5.6f), + } + ) + ); } - else if (tab == 1) // Enhancement + // Enhancement + if (tab == SHAMAN_TAB_ENHANCEMENT) { - triggers.push_back(new TriggerNode("medium aoe",{ - NextAction("magma totem", 24.0f), - NextAction("fire nova", 23.0f), })); + triggers.push_back( + new TriggerNode( + "medium aoe", + { + CreateNextAction(24.0f), + CreateNextAction(23.0f), + } + ) + ); - triggers.push_back(new TriggerNode("maelstrom weapon 5 and medium aoe", { NextAction("chain lightning", 22.0f), })); - triggers.push_back(new TriggerNode("maelstrom weapon 4 and medium aoe", { NextAction("chain lightning", 21.0f), })); - triggers.push_back(new TriggerNode("enemy within melee", { NextAction("fire nova", 5.1f), })); + triggers.push_back( + new TriggerNode( + "maelstrom weapon 5 and medium aoe", + { + CreateNextAction(22.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "maelstrom weapon 4 and medium aoe", + { + CreateNextAction(21.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "enemy within melee", + { + CreateNextAction(5.1f), + } + ) + ); } - else if (tab == 2) // Restoration + if (tab == SHAMAN_TAB_RESTORATION) { // Handled by "Healer DPS" Strategy } diff --git a/src/Ai/Class/Shaman/Strategy/RestoShamanStrategy.cpp b/src/Ai/Class/Shaman/Strategy/RestoShamanStrategy.cpp index 698531a858..cb1905b2e8 100644 --- a/src/Ai/Class/Shaman/Strategy/RestoShamanStrategy.cpp +++ b/src/Ai/Class/Shaman/Strategy/RestoShamanStrategy.cpp @@ -4,8 +4,11 @@ */ #include "RestoShamanStrategy.h" - -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "MovementActions.h" +#include "ReachTargetActions.h" +#include "ShamanActions.h" +#include "UseItemAction.h" // ===== Action Node Factory ===== class RestoShamanStrategyActionNodeFactory : public NamedObjectFactory @@ -35,27 +38,140 @@ class RestoShamanStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, + /*C*/ {} + ); + } + static ActionNode* call_of_the_elements(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* stoneclaw_totem(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* riptide_on_party(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* chain_heal_on_party(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* healing_wave_on_party(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* lesser_healing_wave_on_party(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* earth_shield_on_main_tank(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* cleanse_spirit_poison_on_party(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* cleanse_spirit_disease_on_party(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* cleanse_spirit_curse_on_party(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* cleansing_totem(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* water_shield(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* flame_shock(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* lava_burst(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* lightning_bolt(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* chain_lightning(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } }; // ===== Single Target Strategy ===== @@ -70,55 +186,166 @@ void RestoShamanStrategy::InitTriggers(std::vector& triggers) GenericShamanStrategy::InitTriggers(triggers); // Totem Triggers - triggers.push_back(new TriggerNode("call of the elements", { NextAction("call of the elements", 60.0f) })); - triggers.push_back(new TriggerNode("low health", { NextAction("stoneclaw totem", 40.0f) })); - triggers.push_back(new TriggerNode("medium mana", { NextAction("mana tide totem", ACTION_HIGH + 5) })); + triggers.push_back( + new TriggerNode( + "call of the elements", + { + CreateNextAction(60.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "low health", + { + CreateNextAction(40.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "medium mana", + { + CreateNextAction(ACTION_HIGH + 5.0f) + } + ) + ); // Healing Triggers - triggers.push_back(new TriggerNode("group heal setting", { - NextAction("riptide on party", 27.0f), - NextAction("chain heal on party", 26.0f) })); + triggers.push_back( + new TriggerNode( + "group heal setting", + { + CreateNextAction(27.0f), + CreateNextAction(26.0f) + } + ) + ); - triggers.push_back(new TriggerNode("party member critical health", { - NextAction("riptide on party", 25.0f), - NextAction("healing wave on party", 24.0f), - NextAction("lesser healing wave on party", 23.0f) })); + triggers.push_back( + new TriggerNode( + "party member critical health", + { + CreateNextAction(25.0f), + CreateNextAction(24.0f), + CreateNextAction(23.0f) + } + ) + ); - triggers.push_back(new TriggerNode("party member low health", { - NextAction("riptide on party", 19.0f), - NextAction("healing wave on party", 18.0f), - NextAction("lesser healing wave on party", 17.0f) })); + triggers.push_back( + new TriggerNode( + "party member low health", + { + CreateNextAction(19.0f), + CreateNextAction(18.0f), + CreateNextAction(17.0f) + } + ) + ); - triggers.push_back(new TriggerNode("party member medium health", { - NextAction("riptide on party", 16.0f), - NextAction("healing wave on party", 15.0f), - NextAction("lesser healing wave on party", 14.0f) })); + triggers.push_back( + new TriggerNode( + "party member medium health", + { + CreateNextAction(16.0f), + CreateNextAction(15.0f), + CreateNextAction(14.0f) + } + ) + ); - triggers.push_back(new TriggerNode("party member almost full health", { - NextAction("riptide on party", 12.0f), - NextAction("lesser healing wave on party", 11.0f) })); + triggers.push_back( + new TriggerNode( + "party member almost full health", + { + CreateNextAction(12.0f), + CreateNextAction(11.0f) + } + ) + ); - triggers.push_back(new TriggerNode("earth shield on main tank", { NextAction("earth shield on main tank", ACTION_HIGH + 7) })); + triggers.push_back( + new TriggerNode( + "earth shield on main tank", + { + CreateNextAction(ACTION_HIGH + 7.0f) + } + ) + ); // Dispel Triggers - triggers.push_back(new TriggerNode("party member cleanse spirit poison", { NextAction("cleanse spirit poison on party", ACTION_DISPEL + 2) })); - triggers.push_back(new TriggerNode("party member cleanse spirit disease", { NextAction("cleanse spirit disease on party", ACTION_DISPEL + 2) })); - triggers.push_back(new TriggerNode("party member cleanse spirit curse",{ NextAction("cleanse spirit curse on party", ACTION_DISPEL + 2) })); + triggers.push_back( + new TriggerNode( + "party member cleanse spirit poison", + { + CreateNextAction(ACTION_DISPEL + 2.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member cleanse spirit disease", + { + CreateNextAction(ACTION_DISPEL + 2.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member cleanse spirit curse", + { + CreateNextAction(ACTION_DISPEL + 2.0f) + } + ) + ); // Range/Mana Triggers - triggers.push_back(new TriggerNode("enemy too close for spell", { NextAction("flee", ACTION_MOVE + 9) })); - triggers.push_back(new TriggerNode("party member to heal out of spell range", { NextAction("reach party member to heal", ACTION_CRITICAL_HEAL + 1) })); - triggers.push_back(new TriggerNode("water shield", { NextAction("water shield", 19.5f) })); + triggers.push_back( + new TriggerNode( + "enemy too close for spell", + { + CreateNextAction(ACTION_MOVE + 9.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member to heal out of spell range", + { + CreateNextAction(ACTION_CRITICAL_HEAL + 1.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "water shield", + { + CreateNextAction(19.5f) + } + ) + ); } void ShamanHealerDpsStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("healer should attack", - { NextAction("flame shock", ACTION_DEFAULT + 0.2f), - NextAction("lava burst", ACTION_DEFAULT + 0.1f), - NextAction("lightning bolt", ACTION_DEFAULT) })); + triggers.push_back( + new TriggerNode( + "healer should attack", + { + CreateNextAction(ACTION_DEFAULT + 0.2f), + CreateNextAction(ACTION_DEFAULT + 0.1f), + CreateNextAction(ACTION_DEFAULT) + } + ) + ); triggers.push_back( - new TriggerNode("medium aoe and healer should attack", - { NextAction("chain lightning", ACTION_DEFAULT + 0.3f) })); + new TriggerNode( + "medium aoe and healer should attack", + { + CreateNextAction(ACTION_DEFAULT + 0.3f) + } + ) + ); } diff --git a/src/Ai/Class/Shaman/Strategy/ShamanNonCombatStrategy.cpp b/src/Ai/Class/Shaman/Strategy/ShamanNonCombatStrategy.cpp index c72000539c..4bca8f6fba 100644 --- a/src/Ai/Class/Shaman/Strategy/ShamanNonCombatStrategy.cpp +++ b/src/Ai/Class/Shaman/Strategy/ShamanNonCombatStrategy.cpp @@ -5,8 +5,9 @@ #include "ShamanNonCombatStrategy.h" #include "AiFactory.h" -#include "Strategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "GenericActions.h" +#include "ShamanActions.h" class ShamanNonCombatStrategyActionNodeFactory : public NamedObjectFactory { @@ -24,34 +25,52 @@ class ShamanNonCombatStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, + /*C*/ {} + ); } static ActionNode* frostbrand_weapon([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("frostbrand weapon", - /*P*/ {}, - /*A*/ { NextAction("flametongue weapon") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* windfury_weapon([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("windfury weapon", - /*P*/ {}, - /*A*/ { NextAction("flametongue weapon") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* earthliving_weapon([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("earthliving weapon", - /*P*/ {}, - /*A*/ { NextAction("flametongue weapon") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); + } + static ActionNode* wind_shear(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); + } + static ActionNode* purge(PlayerbotAI*) + { + return new ActionNode( + {}, + {}, + {} + ); } - static ActionNode* wind_shear(PlayerbotAI*) { return new ActionNode("wind shear", {}, {}, {}); } - static ActionNode* purge(PlayerbotAI*) { return new ActionNode("purge", {}, {}, {}); } }; ShamanNonCombatStrategy::ShamanNonCombatStrategy(PlayerbotAI* botAI) : NonCombatStrategy(botAI) @@ -64,29 +83,102 @@ void ShamanNonCombatStrategy::InitTriggers(std::vector& triggers) NonCombatStrategy::InitTriggers(triggers); // Totemic Recall - triggers.push_back(new TriggerNode("totemic recall", { NextAction("totemic recall", 60.0f), })); + triggers.push_back( + new TriggerNode( + "totemic recall", + { + CreateNextAction(60.0f), + } + ) + ); // Healing/Resurrect Triggers - triggers.push_back(new TriggerNode("party member dead", { NextAction("ancestral spirit", ACTION_CRITICAL_HEAL + 10), })); - triggers.push_back(new TriggerNode("party member critical health", { - NextAction("riptide on party", 31.0f), - NextAction("healing wave on party", 30.0f) })); - triggers.push_back(new TriggerNode("party member low health",{ - NextAction("riptide on party", 29.0f), - NextAction("healing wave on party", 28.0f) })); - triggers.push_back(new TriggerNode("party member medium health",{ - NextAction("riptide on party", 27.0f), - NextAction("healing wave on party", 26.0f) })); - triggers.push_back(new TriggerNode("party member almost full health",{ - NextAction("riptide on party", 25.0f), - NextAction("lesser healing wave on party", 24.0f) })); - triggers.push_back(new TriggerNode("group heal setting",{ NextAction("chain heal on party", 27.0f) })); + triggers.push_back( + new TriggerNode( + "party member dead", + { + CreateNextAction(ACTION_CRITICAL_HEAL + 10.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member critical health", + { + CreateNextAction(31.0f), + CreateNextAction(30.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member low health", + { + CreateNextAction(29.0f), + CreateNextAction(28.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member medium health", + { + CreateNextAction(27.0f), + CreateNextAction(26.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member almost full health", + { + CreateNextAction(25.0f), + CreateNextAction(24.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "group heal setting", + { + CreateNextAction(27.0f) + } + ) + ); // Cure Triggers - triggers.push_back(new TriggerNode("cure poison", { NextAction("cure poison", 21.0f), })); - triggers.push_back(new TriggerNode("party member cure poison", { NextAction("cure poison on party", 21.0f), })); - triggers.push_back(new TriggerNode("cure disease", { NextAction("cure disease", 31.0f), })); - triggers.push_back(new TriggerNode("party member cure disease", { NextAction("cure disease on party", 30.0f), })); + triggers.push_back( + new TriggerNode( + "cure poison", + { + CreateNextAction(21.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member cure poison", + { + CreateNextAction(21.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "cure disease", + { + CreateNextAction(31.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "party member cure disease", + { + CreateNextAction(30.0f), + } + ) + ); // Out of Combat Buff Triggers Player* bot = botAI->GetBot(); @@ -94,30 +186,121 @@ void ShamanNonCombatStrategy::InitTriggers(std::vector& triggers) if (tab == 0) // Elemental { - triggers.push_back(new TriggerNode("main hand weapon no imbue", { NextAction("flametongue weapon", 22.0f), })); - triggers.push_back(new TriggerNode("water shield", { NextAction("water shield", 21.0f), })); + triggers.push_back( + new TriggerNode( + "main hand weapon no imbue", + { + CreateNextAction(22.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "water shield", + { + CreateNextAction(21.0f), + } + ) + ); } else if (tab == 1) // Enhancement { - triggers.push_back(new TriggerNode("main hand weapon no imbue", { NextAction("windfury weapon", 22.0f), })); - triggers.push_back(new TriggerNode("off hand weapon no imbue", { NextAction("flametongue weapon", 21.0f), })); - triggers.push_back(new TriggerNode("lightning shield", { NextAction("lightning shield", 20.0f), })); + triggers.push_back( + new TriggerNode( + "main hand weapon no imbue", + { + CreateNextAction(22.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "off hand weapon no imbue", + { + CreateNextAction(21.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "lightning shield", + { + CreateNextAction(20.0f), + } + ) + ); } else if (tab == 2) // Restoration { - triggers.push_back(new TriggerNode("main hand weapon no imbue",{ NextAction("earthliving weapon", 22.0f), })); - triggers.push_back(new TriggerNode("water shield", { NextAction("water shield", 20.0f), })); + triggers.push_back( + new TriggerNode( + "main hand weapon no imbue", + { + CreateNextAction(22.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "water shield", + { + CreateNextAction(20.0f), + } + ) + ); } // Buff Triggers while swimming - triggers.push_back(new TriggerNode("water breathing", { NextAction("water breathing", 12.0f), })); - triggers.push_back(new TriggerNode("water walking", { NextAction("water walking", 12.0f), })); - triggers.push_back(new TriggerNode("water breathing on party", { NextAction("water breathing on party", 11.0f), })); - triggers.push_back(new TriggerNode("water walking on party", { NextAction("water walking on party", 11.0f), })); + triggers.push_back( + new TriggerNode( + "water breathing", + { + CreateNextAction(12.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "water walking", + { + CreateNextAction(12.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "water breathing on party", + { + CreateNextAction(11.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "water walking on party", + { + CreateNextAction(11.0f), + } + ) + ); // Pet Triggers - triggers.push_back(new TriggerNode("has pet", { NextAction("toggle pet spell", 60.0f), })); - triggers.push_back(new TriggerNode("new pet", { NextAction("set pet stance", 65.0f), })); + triggers.push_back( + new TriggerNode( + "has pet", + { + CreateNextAction(60.0f), + } + ) + ); + triggers.push_back( + new TriggerNode( + "new pet", + { + CreateNextAction(65.0f), + } + ) + ); } void ShamanNonCombatStrategy::InitMultipliers(std::vector& multipliers) diff --git a/src/Ai/Class/Shaman/Strategy/TotemsShamanStrategy.cpp b/src/Ai/Class/Shaman/Strategy/TotemsShamanStrategy.cpp index d00cc5e6cb..34917f9583 100644 --- a/src/Ai/Class/Shaman/Strategy/TotemsShamanStrategy.cpp +++ b/src/Ai/Class/Shaman/Strategy/TotemsShamanStrategy.cpp @@ -4,7 +4,8 @@ */ #include "TotemsShamanStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "ShamanActions.h" // These combat strategies are used to set the corresponding totems on the bar, and cast the totem when it's missing. // There are special cases for Totem of Wrath, Windfury Totem, Wrath of Air totem, and Cleansing totem - these totems @@ -15,32 +16,88 @@ StrengthOfEarthTotemStrategy::StrengthOfEarthTotemStrategy(PlayerbotAI* botAI) : void StrengthOfEarthTotemStrategy::InitTriggers(std::vector& triggers) { GenericShamanStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("set strength of earth totem", { NextAction("set strength of earth totem", 60.0f) })); - triggers.push_back(new TriggerNode("no earth totem", { NextAction("strength of earth totem", 55.0f) })); + triggers.push_back( + new TriggerNode( + "set strength of earth totem", + { + CreateNextAction(60.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "no earth totem", + { + CreateNextAction(55.0f) + } + ) + ); } StoneclawTotemStrategy::StoneclawTotemStrategy(PlayerbotAI* botAI) : GenericShamanStrategy(botAI) {} void StoneclawTotemStrategy::InitTriggers(std::vector& triggers) { GenericShamanStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("set stoneskin totem", { NextAction("set stoneskin totem", 60.0f) })); - triggers.push_back(new TriggerNode("no earth totem", { NextAction("stoneskin totem", 55.0f) })); + triggers.push_back( + new TriggerNode( + "set stoneskin totem", + { + CreateNextAction(60.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "no earth totem", + { + CreateNextAction(55.0f) + } + ) + ); } EarthTotemStrategy::EarthTotemStrategy(PlayerbotAI* botAI) : GenericShamanStrategy(botAI) {} void EarthTotemStrategy::InitTriggers(std::vector& triggers) { GenericShamanStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("set tremor totem", { NextAction("set tremor totem", 60.0f) })); - triggers.push_back(new TriggerNode("no earth totem", { NextAction("tremor totem", 55.0f) })); + triggers.push_back( + new TriggerNode( + "set tremor totem", + { + CreateNextAction(60.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "no earth totem", + { + CreateNextAction(55.0f) + } + ) + ); } EarthbindTotemStrategy::EarthbindTotemStrategy(PlayerbotAI* botAI) : GenericShamanStrategy(botAI) {} void EarthbindTotemStrategy::InitTriggers(std::vector& triggers) { GenericShamanStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("set earthbind totem", { NextAction("set earthbind totem", 60.0f) })); - triggers.push_back(new TriggerNode("no earth totem", { NextAction("earthbind totem", 55.0f) })); + triggers.push_back( + new TriggerNode( + "set earthbind totem", + { + CreateNextAction(60.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "no earth totem", + { + CreateNextAction(55.0f) + } + ) + ); } // Fire Totems @@ -48,24 +105,66 @@ SearingTotemStrategy::SearingTotemStrategy(PlayerbotAI* botAI) : GenericShamanSt void SearingTotemStrategy::InitTriggers(std::vector& triggers) { GenericShamanStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("set searing totem", { NextAction("set searing totem", 60.0f) })); - triggers.push_back(new TriggerNode("no fire totem", { NextAction("searing totem", 55.0f) })); + triggers.push_back( + new TriggerNode( + "set searing totem", + { + CreateNextAction(60.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "no fire totem", + { + CreateNextAction(55.0f) + } + ) + ); } MagmaTotemStrategy::MagmaTotemStrategy(PlayerbotAI* botAI) : GenericShamanStrategy(botAI) {} void MagmaTotemStrategy::InitTriggers(std::vector& triggers) { GenericShamanStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("set magma totem", { NextAction("set magma totem", 60.0f) })); - triggers.push_back(new TriggerNode("no fire totem", { NextAction("magma totem", 55.0f) })); + triggers.push_back( + new TriggerNode( + "set magma totem", + { + CreateNextAction(60.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "no fire totem", + { + CreateNextAction(55.0f) + } + ) + ); } FlametongueTotemStrategy::FlametongueTotemStrategy(PlayerbotAI* botAI) : GenericShamanStrategy(botAI) {} void FlametongueTotemStrategy::InitTriggers(std::vector& triggers) { GenericShamanStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("set flametongue totem", { NextAction("set flametongue totem", 60.0f) })); - triggers.push_back(new TriggerNode("no fire totem", { NextAction("flametongue totem", 55.0f) })); + triggers.push_back( + new TriggerNode( + "set flametongue totem", + { + CreateNextAction(60.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "no fire totem", + { + CreateNextAction(55.0f) + } + ) + ); } TotemOfWrathStrategy::TotemOfWrathStrategy(PlayerbotAI* botAI) : GenericShamanStrategy(botAI) {} @@ -76,21 +175,56 @@ void TotemOfWrathStrategy::InitTriggers(std::vector& triggers) Player* bot = botAI->GetBot(); if (bot->HasSpell(30706)) { - triggers.push_back(new TriggerNode("set totem of wrath", { NextAction("set totem of wrath", 60.0f) })); + triggers.push_back( + new TriggerNode( + "set totem of wrath", + { + CreateNextAction(60.0f) + } + ) + ); } else if (bot->HasSpell(8227)) { - triggers.push_back(new TriggerNode("set flametongue totem", { NextAction("set flametongue totem", 60.0f) })); + triggers.push_back( + new TriggerNode( + "set flametongue totem", + { + CreateNextAction(60.0f) + } + ) + ); } - triggers.push_back(new TriggerNode("no fire totem", { NextAction("totem of wrath", 55.0f) })); + triggers.push_back( + new TriggerNode( + "no fire totem", + { + CreateNextAction(55.0f) + } + ) + ); } FrostResistanceTotemStrategy::FrostResistanceTotemStrategy(PlayerbotAI* botAI) : GenericShamanStrategy(botAI) {} void FrostResistanceTotemStrategy::InitTriggers(std::vector& triggers) { GenericShamanStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("set frost resistance totem", { NextAction("set frost resistance totem", 60.0f) })); - triggers.push_back(new TriggerNode("no fire totem", { NextAction("frost resistance totem", 55.0f) })); + triggers.push_back( + new TriggerNode( + "set frost resistance totem", + { + CreateNextAction(60.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "no fire totem", + { + CreateNextAction(55.0f) + } + ) + ); } // Water Totems @@ -98,16 +232,44 @@ HealingStreamTotemStrategy::HealingStreamTotemStrategy(PlayerbotAI* botAI) : Gen void HealingStreamTotemStrategy::InitTriggers(std::vector& triggers) { GenericShamanStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("set healing stream totem", { NextAction("set healing stream totem", 60.0f) })); - triggers.push_back(new TriggerNode("no water totem", { NextAction("healing stream totem", 55.0f) })); + triggers.push_back( + new TriggerNode( + "set healing stream totem", + { + CreateNextAction(60.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "no water totem", + { + CreateNextAction(55.0f) + } + ) + ); } ManaSpringTotemStrategy::ManaSpringTotemStrategy(PlayerbotAI* botAI) : GenericShamanStrategy(botAI) {} void ManaSpringTotemStrategy::InitTriggers(std::vector& triggers) { GenericShamanStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("set mana spring totem", { NextAction("set mana spring totem", 60.0f) })); - triggers.push_back(new TriggerNode("no water totem", { NextAction("mana spring totem", 55.0f) })); + triggers.push_back( + new TriggerNode( + "set mana spring totem", + { + CreateNextAction(60.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "no water totem", + { + CreateNextAction(55.0f) + } + ) + ); } CleansingTotemStrategy::CleansingTotemStrategy(PlayerbotAI* botAI) : GenericShamanStrategy(botAI) {} @@ -118,21 +280,56 @@ void CleansingTotemStrategy::InitTriggers(std::vector& triggers) Player* bot = botAI->GetBot(); if (bot->HasSpell(8170)) { - triggers.push_back(new TriggerNode("set cleansing totem", { NextAction("set cleansing totem", 60.0f) })); + triggers.push_back( + new TriggerNode( + "set cleansing totem", + { + CreateNextAction(60.0f) + } + ) + ); } else if (bot->HasSpell(5675)) { - triggers.push_back(new TriggerNode("set mana spring totem", { NextAction("set mana spring totem", 60.0f) })); + triggers.push_back( + new TriggerNode( + "set mana spring totem", + { + CreateNextAction(60.0f) + } + ) + ); } - triggers.push_back(new TriggerNode("no water totem", { NextAction("cleansing totem", 55.0f) })); + triggers.push_back( + new TriggerNode( + "no water totem", + { + CreateNextAction(55.0f) + } + ) + ); } FireResistanceTotemStrategy::FireResistanceTotemStrategy(PlayerbotAI* botAI) : GenericShamanStrategy(botAI) {} void FireResistanceTotemStrategy::InitTriggers(std::vector& triggers) { GenericShamanStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("set fire resistance totem", { NextAction("set fire resistance totem", 60.0f) })); - triggers.push_back(new TriggerNode("no water totem", { NextAction("fire resistance totem", 55.0f) })); + triggers.push_back( + new TriggerNode( + "set fire resistance totem", + { + CreateNextAction(60.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "no water totem", + { + CreateNextAction(55.0f) + } + ) + ); } // Air Totems @@ -144,14 +341,34 @@ void WrathOfAirTotemStrategy::InitTriggers(std::vector& triggers) Player* bot = botAI->GetBot(); if (bot->HasSpell(3738)) { - triggers.push_back(new TriggerNode("set wrath of air totem", { NextAction("set wrath of air totem", 60.0f) })); + triggers.push_back( + new TriggerNode( + "set wrath of air totem", + { + CreateNextAction(60.0f) + } + ) + ); } else if (bot->HasSpell(8177)) { - triggers.push_back(new TriggerNode("set grounding totem", { NextAction("set grounding totem", 60.0f) })); + triggers.push_back( + new TriggerNode( + "set grounding totem", + { + CreateNextAction(60.0f) + } + ) + ); } triggers.push_back( - new TriggerNode("no air totem", { NextAction("wrath of air totem", 55.0f) })); + new TriggerNode( + "no air totem", + { + CreateNextAction(55.0f) + } + ) + ); } WindfuryTotemStrategy::WindfuryTotemStrategy(PlayerbotAI* botAI) : GenericShamanStrategy(botAI) {} @@ -162,27 +379,76 @@ void WindfuryTotemStrategy::InitTriggers(std::vector& triggers) Player* bot = botAI->GetBot(); if (bot->HasSpell(8512)) { - triggers.push_back(new TriggerNode("set windfury totem", { NextAction("set windfury totem", 60.0f) })); + triggers.push_back( + new TriggerNode( + "set windfury totem", + { + CreateNextAction(60.0f) + } + ) + ); } else if (bot->HasSpell(8177)) { - triggers.push_back(new TriggerNode("set grounding totem", { NextAction("set grounding totem", 60.0f) })); + triggers.push_back( + new TriggerNode( + "set grounding totem", + { + CreateNextAction(60.0f) + } + ) + ); } - triggers.push_back(new TriggerNode("no air totem", { NextAction("windfury totem", 55.0f) })); + triggers.push_back( + new TriggerNode( + "no air totem", + { + CreateNextAction(55.0f) + } + ) + ); } NatureResistanceTotemStrategy::NatureResistanceTotemStrategy(PlayerbotAI* botAI) : GenericShamanStrategy(botAI) {} void NatureResistanceTotemStrategy::InitTriggers(std::vector& triggers) { GenericShamanStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("set nature resistance totem", { NextAction("set nature resistance totem", 60.0f) })); - triggers.push_back(new TriggerNode("no air totem", { NextAction("nature resistance totem", 55.0f) })); + triggers.push_back( + new TriggerNode( + "set nature resistance totem", + { + CreateNextAction(60.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "no air totem", + { + CreateNextAction(55.0f) + } + ) + ); } GroundingTotemStrategy::GroundingTotemStrategy(PlayerbotAI* botAI) : GenericShamanStrategy(botAI) {} void GroundingTotemStrategy::InitTriggers(std::vector& triggers) { GenericShamanStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("set grounding totem", { NextAction("set grounding totem", 60.0f) })); - triggers.push_back(new TriggerNode("no air totem", { NextAction("grounding totem", 55.0f) })); + triggers.push_back( + new TriggerNode( + "set grounding totem", + { + CreateNextAction(60.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "no air totem", + { + CreateNextAction(55.0f) + } + ) + ); } diff --git a/src/Ai/Class/Shaman/Strategy/TotemsShamanStrategy.h b/src/Ai/Class/Shaman/Strategy/TotemsShamanStrategy.h index 6d36f4a271..60488740c6 100644 --- a/src/Ai/Class/Shaman/Strategy/TotemsShamanStrategy.h +++ b/src/Ai/Class/Shaman/Strategy/TotemsShamanStrategy.h @@ -7,7 +7,6 @@ #define _PLAYERBOT_TOTEMSSHAMANSTRATEGY_H #include "GenericShamanStrategy.h" -#include #include #include diff --git a/src/Ai/Class/Shaman/Trigger/ShamanTriggers.cpp b/src/Ai/Class/Shaman/Trigger/ShamanTriggers.cpp index 753edb83fd..c8b36135a9 100644 --- a/src/Ai/Class/Shaman/Trigger/ShamanTriggers.cpp +++ b/src/Ai/Class/Shaman/Trigger/ShamanTriggers.cpp @@ -283,20 +283,6 @@ static uint32 GetRequiredTotemSpellId(PlayerbotAI* ai, const char* strategies[], return 0; // No relevant strategy active, or bot doesn't know any rank } -// Get the spellId of the currently summoned totem in the slot -static uint32 GetSummonedTotemSpellId(Player* bot, uint8 slot) -{ - ObjectGuid guid = bot->m_SummonSlot[slot]; - if (guid.IsEmpty()) - return 0; - - Creature* totem = bot->GetMap()->GetCreature(guid); - if (!totem) - return 0; - - return totem->GetUInt32Value(UNIT_CREATED_BY_SPELL); -} - bool NoEarthTotemTrigger::IsActive() { // Check if the bot has Stoneskin Totem (required level 4) and prevents the trigger firing if it doesn't diff --git a/src/Ai/Class/Shaman/Trigger/ShamanTriggers.h b/src/Ai/Class/Shaman/Trigger/ShamanTriggers.h index abf4ed566c..9e1a86aace 100644 --- a/src/Ai/Class/Shaman/Trigger/ShamanTriggers.h +++ b/src/Ai/Class/Shaman/Trigger/ShamanTriggers.h @@ -10,9 +10,7 @@ #include "GenericTriggers.h" #include "SharedDefines.h" #include "Trigger.h" -#include #include "TotemsShamanStrategy.h" -#include "Player.h" #include "PlayerbotAI.h" #include @@ -361,10 +359,8 @@ class SetTotemTrigger : public Trigger public: // Template constructor: infers N (size of the id array) at compile time template - SetTotemTrigger(PlayerbotAI* ai, std::string const& spellName, uint32 requiredSpellId, - const uint32 (&ids)[N], int actionButtonId) + SetTotemTrigger(PlayerbotAI* ai, std::string const& spellName, const uint32 (&ids)[N], int actionButtonId) : Trigger(ai, "set " + spellName) - , requiredSpellId(requiredSpellId) , totemSpellIds(ids) , totemSpellIdsCount(N) , actionButtonId(actionButtonId) @@ -372,7 +368,6 @@ class SetTotemTrigger : public Trigger bool IsActive() override; private: - uint32 requiredSpellId; uint32 const* totemSpellIds; size_t totemSpellIdsCount; int actionButtonId; @@ -382,119 +377,119 @@ class SetStrengthOfEarthTotemTrigger : public SetTotemTrigger { public: SetStrengthOfEarthTotemTrigger(PlayerbotAI* ai) - : SetTotemTrigger(ai, "strength of earth totem", SPELL_STRENGTH_OF_EARTH_TOTEM_RANK_1, STRENGTH_OF_EARTH_TOTEM, TOTEM_BAR_SLOT_EARTH) {} + : SetTotemTrigger(ai, "strength of earth totem", STRENGTH_OF_EARTH_TOTEM, TOTEM_BAR_SLOT_EARTH) {} }; class SetStoneskinTotemTrigger : public SetTotemTrigger { public: SetStoneskinTotemTrigger(PlayerbotAI* ai) - : SetTotemTrigger(ai, "stoneskin totem", SPELL_STONESKIN_TOTEM_RANK_1, STONESKIN_TOTEM, TOTEM_BAR_SLOT_EARTH) {} + : SetTotemTrigger(ai, "stoneskin totem", STONESKIN_TOTEM, TOTEM_BAR_SLOT_EARTH) {} }; class SetTremorTotemTrigger : public SetTotemTrigger { public: SetTremorTotemTrigger(PlayerbotAI* ai) - : SetTotemTrigger(ai, "tremor totem", SPELL_TREMOR_TOTEM_RANK_1, TREMOR_TOTEM, TOTEM_BAR_SLOT_EARTH) {} + : SetTotemTrigger(ai, "tremor totem", TREMOR_TOTEM, TOTEM_BAR_SLOT_EARTH) {} }; class SetEarthbindTotemTrigger : public SetTotemTrigger { public: SetEarthbindTotemTrigger(PlayerbotAI* ai) - : SetTotemTrigger(ai, "earthbind totem", SPELL_EARTHBIND_TOTEM_RANK_1, EARTHBIND_TOTEM, TOTEM_BAR_SLOT_EARTH) {} + : SetTotemTrigger(ai, "earthbind totem", EARTHBIND_TOTEM, TOTEM_BAR_SLOT_EARTH) {} }; class SetSearingTotemTrigger : public SetTotemTrigger { public: SetSearingTotemTrigger(PlayerbotAI* ai) - : SetTotemTrigger(ai, "searing totem", SPELL_SEARING_TOTEM_RANK_1, SEARING_TOTEM, TOTEM_BAR_SLOT_FIRE) {} + : SetTotemTrigger(ai, "searing totem", SEARING_TOTEM, TOTEM_BAR_SLOT_FIRE) {} }; class SetMagmaTotemTrigger : public SetTotemTrigger { public: SetMagmaTotemTrigger(PlayerbotAI* ai) - : SetTotemTrigger(ai, "magma totem", SPELL_MAGMA_TOTEM_RANK_1, MAGMA_TOTEM, TOTEM_BAR_SLOT_FIRE) {} + : SetTotemTrigger(ai, "magma totem", MAGMA_TOTEM, TOTEM_BAR_SLOT_FIRE) {} }; class SetFlametongueTotemTrigger : public SetTotemTrigger { public: SetFlametongueTotemTrigger(PlayerbotAI* ai) - : SetTotemTrigger(ai, "flametongue totem", SPELL_FLAMETONGUE_TOTEM_RANK_1, FLAMETONGUE_TOTEM, TOTEM_BAR_SLOT_FIRE) {} + : SetTotemTrigger(ai, "flametongue totem", FLAMETONGUE_TOTEM, TOTEM_BAR_SLOT_FIRE) {} }; class SetTotemOfWrathTrigger : public SetTotemTrigger { public: SetTotemOfWrathTrigger(PlayerbotAI* ai) - : SetTotemTrigger(ai, "totem of wrath", SPELL_TOTEM_OF_WRATH_RANK_1, TOTEM_OF_WRATH, TOTEM_BAR_SLOT_FIRE) {} + : SetTotemTrigger(ai, "totem of wrath", TOTEM_OF_WRATH, TOTEM_BAR_SLOT_FIRE) {} }; class SetFrostResistanceTotemTrigger : public SetTotemTrigger { public: SetFrostResistanceTotemTrigger(PlayerbotAI* ai) - : SetTotemTrigger(ai, "frost resistance totem", SPELL_FROST_RESISTANCE_TOTEM_RANK_1, FROST_RESISTANCE_TOTEM, TOTEM_BAR_SLOT_FIRE) {} + : SetTotemTrigger(ai, "frost resistance totem", FROST_RESISTANCE_TOTEM, TOTEM_BAR_SLOT_FIRE) {} }; class SetHealingStreamTotemTrigger : public SetTotemTrigger { public: SetHealingStreamTotemTrigger(PlayerbotAI* ai) - : SetTotemTrigger(ai, "healing stream totem", SPELL_HEALING_STREAM_TOTEM_RANK_1, HEALING_STREAM_TOTEM, TOTEM_BAR_SLOT_WATER) {} + : SetTotemTrigger(ai, "healing stream totem", HEALING_STREAM_TOTEM, TOTEM_BAR_SLOT_WATER) {} }; class SetManaSpringTotemTrigger : public SetTotemTrigger { public: SetManaSpringTotemTrigger(PlayerbotAI* ai) - : SetTotemTrigger(ai, "mana spring totem", SPELL_MANA_SPRING_TOTEM_RANK_1, MANA_SPRING_TOTEM, TOTEM_BAR_SLOT_WATER) {} + : SetTotemTrigger(ai, "mana spring totem", MANA_SPRING_TOTEM, TOTEM_BAR_SLOT_WATER) {} }; class SetCleansingTotemTrigger : public SetTotemTrigger { public: SetCleansingTotemTrigger(PlayerbotAI* ai) - : SetTotemTrigger(ai, "cleansing totem", SPELL_CLEANSING_TOTEM_RANK_1, CLEANSING_TOTEM, TOTEM_BAR_SLOT_WATER) {} + : SetTotemTrigger(ai, "cleansing totem", CLEANSING_TOTEM, TOTEM_BAR_SLOT_WATER) {} }; class SetFireResistanceTotemTrigger : public SetTotemTrigger { public: SetFireResistanceTotemTrigger(PlayerbotAI* ai) - : SetTotemTrigger(ai, "fire resistance totem", SPELL_FIRE_RESISTANCE_TOTEM_RANK_1, FIRE_RESISTANCE_TOTEM, TOTEM_BAR_SLOT_WATER) {} + : SetTotemTrigger(ai, "fire resistance totem", FIRE_RESISTANCE_TOTEM, TOTEM_BAR_SLOT_WATER) {} }; class SetWrathOfAirTotemTrigger : public SetTotemTrigger { public: SetWrathOfAirTotemTrigger(PlayerbotAI* ai) - : SetTotemTrigger(ai, "wrath of air totem", SPELL_WRATH_OF_AIR_TOTEM_RANK_1, WRATH_OF_AIR_TOTEM, TOTEM_BAR_SLOT_AIR) {} + : SetTotemTrigger(ai, "wrath of air totem", WRATH_OF_AIR_TOTEM, TOTEM_BAR_SLOT_AIR) {} }; class SetWindfuryTotemTrigger : public SetTotemTrigger { public: SetWindfuryTotemTrigger(PlayerbotAI* ai) - : SetTotemTrigger(ai, "windfury totem", SPELL_WINDFURY_TOTEM_RANK_1, WINDFURY_TOTEM, TOTEM_BAR_SLOT_AIR) {} + : SetTotemTrigger(ai, "windfury totem", WINDFURY_TOTEM, TOTEM_BAR_SLOT_AIR) {} }; class SetNatureResistanceTotemTrigger : public SetTotemTrigger { public: SetNatureResistanceTotemTrigger(PlayerbotAI* ai) - : SetTotemTrigger(ai, "nature resistance totem", SPELL_NATURE_RESISTANCE_TOTEM_RANK_1, NATURE_RESISTANCE_TOTEM, TOTEM_BAR_SLOT_AIR) {} + : SetTotemTrigger(ai, "nature resistance totem", NATURE_RESISTANCE_TOTEM, TOTEM_BAR_SLOT_AIR) {} }; class SetGroundingTotemTrigger : public SetTotemTrigger { public: SetGroundingTotemTrigger(PlayerbotAI* ai) - : SetTotemTrigger(ai, "grounding totem", SPELL_GROUNDING_TOTEM_RANK_1, GROUNDING_TOTEM, TOTEM_BAR_SLOT_AIR) {} + : SetTotemTrigger(ai, "grounding totem", GROUNDING_TOTEM, TOTEM_BAR_SLOT_AIR) {} }; #endif diff --git a/src/Ai/Class/Warlock/Action/WarlockActions.cpp b/src/Ai/Class/Warlock/Action/WarlockActions.cpp index e899c7a2f6..a1163894fc 100644 --- a/src/Ai/Class/Warlock/Action/WarlockActions.cpp +++ b/src/Ai/Class/Warlock/Action/WarlockActions.cpp @@ -25,7 +25,7 @@ const int ITEM_SOUL_SHARD = 6265; bool CastDrainSoulAction::isUseful() { return AI_VALUE2(uint32, "item count", "soul shard") < 26; } // Checks if the bot's health is above a certain threshold, and if so, allows casting Life Tap -bool CastLifeTapAction::isUseful() { return AI_VALUE2(uint8, "health", "self target") > sPlayerbotAIConfig->lowHealth; } +bool CastLifeTapAction::isUseful() { return AI_VALUE2(uint8, "health", "self target") > sPlayerbotAIConfig.lowHealth; } // Checks if the target marked with the moon icon can be banished bool CastBanishOnCcAction::isPossible() @@ -116,7 +116,7 @@ bool CastSoulshatterAction::isUseful() } // Checks if the bot has enough bag space to create a soul shard, then does so -bool CreateSoulShardAction::Execute(Event event) +bool CreateSoulShardAction::Execute(Event) { Player* bot = botAI->GetBot(); if (!bot) @@ -188,7 +188,7 @@ bool CastCreateSoulstoneAction::isUseful() return hasSpace; } -bool DestroySoulShardAction::Execute(Event event) +bool DestroySoulShardAction::Execute(Event) { // Look for the first soul shard in any bag and destroy it for (int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) @@ -234,7 +234,7 @@ static bool HasSoulstoneAura(Unit* unit) } // Use the soulstone item on the bot itself with nc strategy "ss self" -bool UseSoulstoneSelfAction::Execute(Event event) +bool UseSoulstoneSelfAction::Execute(Event) { std::vector items = AI_VALUE2(std::vector, "inventory items", "soulstone"); if (items.empty()) @@ -266,7 +266,7 @@ void CleanupSoulstoneReservations() } // Use the soulstone item on the bot's master with nc strategy "ss master" -bool UseSoulstoneMasterAction::Execute(Event event) +bool UseSoulstoneMasterAction::Execute(Event) { CleanupSoulstoneReservations(); @@ -288,7 +288,7 @@ bool UseSoulstoneMasterAction::Execute(Event event) soulstoneReservations[master->GetGUID()] = now + 2500; // Reserve for 2.5 seconds } - float distance = sServerFacade->GetDistance2d(bot, master); + float distance = ServerFacade::instance().GetDistance2d(bot, master); if (distance >= 30.0f) return false; @@ -300,7 +300,7 @@ bool UseSoulstoneMasterAction::Execute(Event event) } // Use the soulstone item on a tank in the group with nc strategy "ss tank" -bool UseSoulstoneTankAction::Execute(Event event) +bool UseSoulstoneTankAction::Execute(Event) { CleanupSoulstoneReservations(); @@ -325,7 +325,7 @@ bool UseSoulstoneTankAction::Execute(Event event) if (soulstoneReservations.count(member->GetGUID()) && soulstoneReservations[member->GetGUID()] > now) continue; // Already being soulstoned - float distance = sServerFacade->GetDistance2d(bot, member); + float distance = ServerFacade::instance().GetDistance2d(bot, member); if (distance < 30.0f && bot->IsWithinLOSInMap(member)) { chosenTank = member; @@ -348,7 +348,7 @@ bool UseSoulstoneTankAction::Execute(Event event) soulstoneReservations[member->GetGUID()] > now) continue; // Already being soulstoned - float distance = sServerFacade->GetDistance2d(bot, member); + float distance = ServerFacade::instance().GetDistance2d(bot, member); if (distance < 30.0f && bot->IsWithinLOSInMap(member)) { chosenTank = member; @@ -368,7 +368,7 @@ bool UseSoulstoneTankAction::Execute(Event event) } // Use the soulstone item on a healer in the group with nc strategy "ss healer" -bool UseSoulstoneHealerAction::Execute(Event event) +bool UseSoulstoneHealerAction::Execute(Event) { CleanupSoulstoneReservations(); @@ -392,7 +392,7 @@ bool UseSoulstoneHealerAction::Execute(Event event) soulstoneReservations[member->GetGUID()] > now) continue; // Already being soulstoned - float distance = sServerFacade->GetDistance2d(bot, member); + float distance = ServerFacade::instance().GetDistance2d(bot, member); if (distance < 30.0f && bot->IsWithinLOSInMap(member)) { healer = member; @@ -425,7 +425,7 @@ CastCreateFirestoneAction::CastCreateFirestoneAction(PlayerbotAI* botAI) { } -bool CastCreateFirestoneAction::Execute(Event event) +bool CastCreateFirestoneAction::Execute(Event) { for (uint32 spellId : firestoneSpellIds) { diff --git a/src/Ai/Class/Warlock/Action/WarlockActions.h b/src/Ai/Class/Warlock/Action/WarlockActions.h index 787b518d69..38964a80de 100644 --- a/src/Ai/Class/Warlock/Action/WarlockActions.h +++ b/src/Ai/Class/Warlock/Action/WarlockActions.h @@ -80,6 +80,18 @@ class CastCreateSpellstoneAction : public CastBuffSpellAction CastCreateSpellstoneAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "create spellstone") {} }; +class UseSpellstoneAction : public UseSpellItemAction +{ +public: + UseSpellstoneAction(PlayerbotAI* botAI) : UseSpellItemAction(botAI, "spellstone", true) {} +}; + +class UseFirestoneAction : public UseSpellItemAction +{ +public: + UseFirestoneAction(PlayerbotAI* botAI) : UseSpellItemAction(botAI, "firestone", true) {} +}; + class CastCreateSoulstoneAction : public CastBuffSpellAction { public: diff --git a/src/Ai/Class/Warlock/Strategy/AfflictionWarlockStrategy.cpp b/src/Ai/Class/Warlock/Strategy/AfflictionWarlockStrategy.cpp index 78da04d99e..c349bc3e81 100644 --- a/src/Ai/Class/Warlock/Strategy/AfflictionWarlockStrategy.cpp +++ b/src/Ai/Class/Warlock/Strategy/AfflictionWarlockStrategy.cpp @@ -4,7 +4,9 @@ */ #include "AfflictionWarlockStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "MovementActions.h" +#include "WarlockActions.h" // ===== Action Node Factory ===== class AfflictionWarlockStrategyActionNodeFactory : public NamedObjectFactory @@ -27,18 +29,114 @@ class AfflictionWarlockStrategyActionNodeFactory : public NamedObjectFactory AfflictionWarlockStrategy::getDefaultActions() { return { - NextAction("corruption", 5.5f), - NextAction("unstable affliction", 5.4f), - NextAction("haunt", 5.3f), - NextAction("shadow bolt", 5.2f), - NextAction("shoot", 5.0f) + CreateNextAction(5.5f), + CreateNextAction(5.4f), + CreateNextAction(5.3f), + CreateNextAction(5.2f), + CreateNextAction(5.0f) }; } @@ -69,7 +167,7 @@ void AfflictionWarlockStrategy::InitTriggers(std::vector& triggers new TriggerNode( "corruption on attacker", { - NextAction("corruption on attacker", 19.5f) + CreateNextAction(19.5f) } ) ); @@ -77,7 +175,7 @@ void AfflictionWarlockStrategy::InitTriggers(std::vector& triggers new TriggerNode( "unstable affliction on attacker", { - NextAction("unstable affliction on attacker", 19.0f) + CreateNextAction(19.0f) } ) ); @@ -85,7 +183,7 @@ void AfflictionWarlockStrategy::InitTriggers(std::vector& triggers new TriggerNode( "corruption", { - NextAction("corruption", 18.0f) + CreateNextAction(18.0f) } ) ); @@ -93,7 +191,7 @@ void AfflictionWarlockStrategy::InitTriggers(std::vector& triggers new TriggerNode( "unstable affliction", { - NextAction("unstable affliction", 17.5f) + CreateNextAction(17.5f) } ) ); @@ -101,7 +199,7 @@ void AfflictionWarlockStrategy::InitTriggers(std::vector& triggers new TriggerNode( "haunt", { - NextAction("haunt", 16.5f) + CreateNextAction(16.5f) } ) ); @@ -111,7 +209,7 @@ void AfflictionWarlockStrategy::InitTriggers(std::vector& triggers new TriggerNode( "shadow trance", { - NextAction("shadow bolt", 16.0f) + CreateNextAction(16.0f) } ) ); @@ -119,7 +217,7 @@ void AfflictionWarlockStrategy::InitTriggers(std::vector& triggers new TriggerNode( "target critical health", { - NextAction("drain soul", 15.5f) + CreateNextAction(15.5f) } ) ); @@ -129,7 +227,7 @@ void AfflictionWarlockStrategy::InitTriggers(std::vector& triggers new TriggerNode( "life tap glyph buff", { - NextAction("life tap", 29.5f) + CreateNextAction(29.5f) } ) ); @@ -137,7 +235,7 @@ void AfflictionWarlockStrategy::InitTriggers(std::vector& triggers new TriggerNode( "life tap", { - NextAction("life tap", 5.1f) + CreateNextAction(5.1f) } ) ); @@ -146,7 +244,7 @@ void AfflictionWarlockStrategy::InitTriggers(std::vector& triggers new TriggerNode( "enemy too close for spell", { - NextAction("flee", 39.0f) + CreateNextAction(39.0f) } ) ); diff --git a/src/Ai/Class/Warlock/Strategy/DemonologyWarlockStrategy.cpp b/src/Ai/Class/Warlock/Strategy/DemonologyWarlockStrategy.cpp index 6bb4e9de59..5cc4d2eadd 100644 --- a/src/Ai/Class/Warlock/Strategy/DemonologyWarlockStrategy.cpp +++ b/src/Ai/Class/Warlock/Strategy/DemonologyWarlockStrategy.cpp @@ -4,7 +4,10 @@ */ #include "DemonologyWarlockStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "MovementActions.h" +#include "ReachTargetActions.h" +#include "WarlockActions.h" // ===== Action Node Factory ===== class DemonologyWarlockStrategyActionNodeFactory : public NamedObjectFactory @@ -31,22 +34,150 @@ class DemonologyWarlockStrategyActionNodeFactory : public NamedObjectFactory DemonologyWarlockStrategy::getDefaultActions() { return { - NextAction("corruption", 5.5f), - NextAction("immolate", 5.4f), - NextAction("shadow bolt", 5.3f), - NextAction("incinerate", 5.2f), - NextAction("shoot", 5.0f) }; + CreateNextAction(5.5f), + CreateNextAction(5.4f), + CreateNextAction(5.3f), + CreateNextAction(5.2f), + CreateNextAction(5.0f) }; } // ===== Trigger Initialization === @@ -76,7 +207,7 @@ void DemonologyWarlockStrategy::InitTriggers(std::vector& triggers new TriggerNode( "metamorphosis", { - NextAction("metamorphosis", 28.5f) + CreateNextAction(28.5f) } ) ); @@ -84,7 +215,7 @@ void DemonologyWarlockStrategy::InitTriggers(std::vector& triggers new TriggerNode( "demonic empowerment", { - NextAction("demonic empowerment", 28.0f) + CreateNextAction(28.0f) } ) ); @@ -94,7 +225,7 @@ void DemonologyWarlockStrategy::InitTriggers(std::vector& triggers new TriggerNode( "corruption on attacker", { - NextAction("corruption on attacker", 19.5f) + CreateNextAction(19.5f) } ) ); @@ -102,7 +233,7 @@ void DemonologyWarlockStrategy::InitTriggers(std::vector& triggers new TriggerNode( "immolate on attacker", { - NextAction("immolate on attacker", 19.0f) + CreateNextAction(19.0f) } ) ); @@ -110,7 +241,7 @@ void DemonologyWarlockStrategy::InitTriggers(std::vector& triggers new TriggerNode( "corruption", { - NextAction("corruption", 18.0f) + CreateNextAction(18.0f) } ) ); @@ -118,7 +249,7 @@ void DemonologyWarlockStrategy::InitTriggers(std::vector& triggers new TriggerNode( "immolate", { - NextAction("immolate", 17.5f) + CreateNextAction(17.5f) } ) ); @@ -128,7 +259,7 @@ void DemonologyWarlockStrategy::InitTriggers(std::vector& triggers new TriggerNode( "decimation", { - NextAction("soul fire", 17.0f) + CreateNextAction(17.0f) } ) ); @@ -136,7 +267,7 @@ void DemonologyWarlockStrategy::InitTriggers(std::vector& triggers new TriggerNode( "molten core", { - NextAction("incinerate", 16.5f) + CreateNextAction(16.5f) } ) ); @@ -146,7 +277,7 @@ void DemonologyWarlockStrategy::InitTriggers(std::vector& triggers new TriggerNode( "life tap glyph buff", { - NextAction("life tap", 29.5f) + CreateNextAction(29.5f) } ) ); @@ -154,7 +285,7 @@ void DemonologyWarlockStrategy::InitTriggers(std::vector& triggers new TriggerNode( "life tap", { - NextAction("life tap", 5.1f) + CreateNextAction(5.1f) } ) ); @@ -163,7 +294,7 @@ void DemonologyWarlockStrategy::InitTriggers(std::vector& triggers new TriggerNode( "meta melee flee check", { - NextAction("flee", 39.0f) + CreateNextAction(39.0f) } ) ); @@ -181,8 +312,8 @@ void MetaMeleeAoeStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "immolation aura active", { - NextAction("reach melee", 25.5f), - NextAction("demon charge", 25.0f) + CreateNextAction(25.5f), + CreateNextAction(25.0f) } ) ); diff --git a/src/Ai/Class/Warlock/Strategy/DestructionWarlockStrategy.cpp b/src/Ai/Class/Warlock/Strategy/DestructionWarlockStrategy.cpp index af44de01c5..3a5ec5e232 100644 --- a/src/Ai/Class/Warlock/Strategy/DestructionWarlockStrategy.cpp +++ b/src/Ai/Class/Warlock/Strategy/DestructionWarlockStrategy.cpp @@ -4,7 +4,9 @@ */ #include "DestructionWarlockStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "MovementActions.h" +#include "WarlockActions.h" // ===== Action Node Factory ===== class DestructionWarlockStrategyActionNodeFactory : public NamedObjectFactory @@ -29,20 +31,132 @@ class DestructionWarlockStrategyActionNodeFactory : public NamedObjectFactory DestructionWarlockStrategy::getDefaultActions() { return { - NextAction("immolate", 5.9f), - NextAction("conflagrate", 5.8f), - NextAction("chaos bolt", 5.7f), - NextAction("incinerate", 5.6f), - NextAction("corruption", 5.3f), // Note: Corruption and Shadow Bolt won't be used after the character learns Incinerate at level 64 - NextAction("shadow bolt", 5.2f), - NextAction("shoot", 5.0f) + CreateNextAction(5.9f), + CreateNextAction(5.8f), + CreateNextAction(5.7f), + CreateNextAction(5.6f), + CreateNextAction(5.3f), // Note: Corruption and Shadow Bolt won't be used after the character learns Incinerate at level 64 + CreateNextAction(5.2f), + CreateNextAction(5.0f) }; } @@ -75,7 +189,7 @@ void DestructionWarlockStrategy::InitTriggers(std::vector& trigger new TriggerNode( "immolate", { - NextAction("immolate", 20.0f) + CreateNextAction(20.0f) } ) ); @@ -83,7 +197,7 @@ void DestructionWarlockStrategy::InitTriggers(std::vector& trigger new TriggerNode( "conflagrate", { - NextAction("conflagrate", 19.5f) + CreateNextAction(19.5f) } ) ); @@ -91,7 +205,7 @@ void DestructionWarlockStrategy::InitTriggers(std::vector& trigger new TriggerNode( "chaos bolt", { - NextAction("chaos bolt", 19.0f) + CreateNextAction(19.0f) } ) ); @@ -101,7 +215,7 @@ void DestructionWarlockStrategy::InitTriggers(std::vector& trigger new TriggerNode( "corruption on attacker", { - NextAction("corruption on attacker", 5.5f) + CreateNextAction(5.5f) } ) ); @@ -109,7 +223,7 @@ void DestructionWarlockStrategy::InitTriggers(std::vector& trigger new TriggerNode( "corruption", { - NextAction("corruption", 5.4f) + CreateNextAction(5.4f) } ) ); @@ -119,7 +233,7 @@ void DestructionWarlockStrategy::InitTriggers(std::vector& trigger new TriggerNode( "target critical health", { - NextAction("shadowburn", 18.0f) + CreateNextAction(18.0f) } ) ); @@ -129,7 +243,7 @@ void DestructionWarlockStrategy::InitTriggers(std::vector& trigger new TriggerNode( "life tap glyph buff", { - NextAction("life tap", 29.5f) + CreateNextAction(29.5f) } ) ); @@ -137,7 +251,7 @@ void DestructionWarlockStrategy::InitTriggers(std::vector& trigger new TriggerNode( "life tap", { - NextAction("life tap", 5.1f) + CreateNextAction(5.1f) } ) ); @@ -146,7 +260,7 @@ void DestructionWarlockStrategy::InitTriggers(std::vector& trigger new TriggerNode( "enemy too close for spell", { - NextAction("flee", 39.0f) + CreateNextAction(39.0f) } ) ); diff --git a/src/Ai/Class/Warlock/Strategy/GenericWarlockNonCombatStrategy.cpp b/src/Ai/Class/Warlock/Strategy/GenericWarlockNonCombatStrategy.cpp index a78ff0a988..6bea81ebfe 100644 --- a/src/Ai/Class/Warlock/Strategy/GenericWarlockNonCombatStrategy.cpp +++ b/src/Ai/Class/Warlock/Strategy/GenericWarlockNonCombatStrategy.cpp @@ -5,7 +5,9 @@ #include "GenericWarlockNonCombatStrategy.h" #include "AiFactory.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "GenericActions.h" +#include "WarlockActions.h" class GenericWarlockNonCombatStrategyActionNodeFactory : public NamedObjectFactory { @@ -27,46 +29,52 @@ class GenericWarlockNonCombatStrategyActionNodeFactory : public NamedObjectFacto private: static ActionNode* fel_armor([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("fel armor", - /*P*/ {}, - /*A*/ { NextAction("demon armor") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* demon_armor([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("demon armor", - /*P*/ {}, - /*A*/ { NextAction("demon skin") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* summon_voidwalker([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("summon voidwalker", - /*P*/ {}, - /*A*/ { NextAction("summon imp") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* summon_succubus([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("summon succubus", - /*P*/ {}, - /*A*/ { NextAction("summon voidwalker") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* summon_felhunter([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("summon felhunter", - /*P*/ {}, - /*A*/ { NextAction("summon succubus") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } static ActionNode* summon_felguard([[maybe_unused]] PlayerbotAI* botAI) { - return new ActionNode("summon felguard", - /*P*/ {}, - /*A*/ { NextAction("summon felhunter") }, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ { CreateNextAction(1.0f) }, + /*C*/ {} + ); } }; @@ -78,16 +86,86 @@ GenericWarlockNonCombatStrategy::GenericWarlockNonCombatStrategy(PlayerbotAI* bo void GenericWarlockNonCombatStrategy::InitTriggers(std::vector& triggers) { NonCombatStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("has pet", { NextAction("toggle pet spell", 60.0f) })); - triggers.push_back(new TriggerNode("new pet", { NextAction("set pet stance", 60.0f) })); - triggers.push_back(new TriggerNode("no pet", { NextAction("fel domination", 30.0f) })); - triggers.push_back(new TriggerNode("no soul shard", { NextAction("create soul shard", 60.0f) })); - triggers.push_back(new TriggerNode("too many soul shards", { NextAction("destroy soul shard", 60.0f) })); - triggers.push_back(new TriggerNode("soul link", { NextAction("soul link", 28.0f) })); - triggers.push_back(new TriggerNode("demon armor", { NextAction("fel armor", 27.0f) })); - triggers.push_back(new TriggerNode("no healthstone", { NextAction("create healthstone", 26.0f) })); - triggers.push_back(new TriggerNode("no soulstone", { NextAction("create soulstone", 25.0f) })); - triggers.push_back(new TriggerNode("life tap", { NextAction("life tap", 23.0f) })); + triggers.push_back( + new TriggerNode( + "has pet", + { + CreateNextAction(60.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "new pet", + { + CreateNextAction(60.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "no pet", + { + CreateNextAction(30.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "no soul shard", + { + CreateNextAction(60.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "too many soul shards", + { + CreateNextAction(60.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "soul link", + { + CreateNextAction(28.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "demon armor", + { + CreateNextAction(27.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "no healthstone", + { + CreateNextAction(26.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "no soulstone", + { + CreateNextAction(25.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "life tap", + { + CreateNextAction(23.0f) + } + ) + ); } // Non-combat strategy for summoning a Imp @@ -98,8 +176,22 @@ SummonImpStrategy::SummonImpStrategy(PlayerbotAI* ai) : NonCombatStrategy(ai) {} void SummonImpStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("no pet", { NextAction("summon imp", 29.0f) })); - triggers.push_back(new TriggerNode("wrong pet", { NextAction("summon imp", 29.0f) })); + triggers.push_back( + new TriggerNode( + "no pet", + { + CreateNextAction(29.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "wrong pet", + { + CreateNextAction(29.0f) + } + ) + ); } // Non-combat strategy for summoning a Voidwalker @@ -110,8 +202,22 @@ SummonVoidwalkerStrategy::SummonVoidwalkerStrategy(PlayerbotAI* ai) : NonCombatS void SummonVoidwalkerStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("no pet", { NextAction("summon voidwalker", 29.0f) })); - triggers.push_back(new TriggerNode("wrong pet", { NextAction("summon voidwalker", 29.0f) })); + triggers.push_back( + new TriggerNode( + "no pet", + { + CreateNextAction(29.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "wrong pet", + { + CreateNextAction(29.0f) + } + ) + ); } // Non-combat strategy for summoning a Succubus @@ -122,8 +228,22 @@ SummonSuccubusStrategy::SummonSuccubusStrategy(PlayerbotAI* ai) : NonCombatStrat void SummonSuccubusStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("no pet", { NextAction("summon succubus", 29.0f) })); - triggers.push_back(new TriggerNode("wrong pet", { NextAction("summon succubus", 29.0f) })); + triggers.push_back( + new TriggerNode( + "no pet", + { + CreateNextAction(29.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "wrong pet", + { + CreateNextAction(29.0f) + } + ) + ); } // Non-combat strategy for summoning a Felhunter @@ -134,8 +254,22 @@ SummonFelhunterStrategy::SummonFelhunterStrategy(PlayerbotAI* ai) : NonCombatStr void SummonFelhunterStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("no pet", { NextAction("summon felhunter", 29.0f) })); - triggers.push_back(new TriggerNode("wrong pet", { NextAction("summon felhunter", 29.0f) })); + triggers.push_back( + new TriggerNode( + "no pet", + { + CreateNextAction(29.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "wrong pet", + { + CreateNextAction(29.0f) + } + ) + ); } // Non-combat strategy for summoning a Felguard @@ -146,8 +280,22 @@ SummonFelguardStrategy::SummonFelguardStrategy(PlayerbotAI* ai) : NonCombatStrat void SummonFelguardStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("no pet", { NextAction("summon felguard", 29.0f) })); - triggers.push_back(new TriggerNode("wrong pet", { NextAction("summon felguard", 29.0f) })); + triggers.push_back( + new TriggerNode( + "no pet", + { + CreateNextAction(29.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "wrong pet", + { + CreateNextAction(29.0f) + } + ) + ); } // Non-combat strategy for selecting themselves to receive soulstone @@ -158,7 +306,14 @@ SoulstoneSelfStrategy::SoulstoneSelfStrategy(PlayerbotAI* ai) : NonCombatStrateg void SoulstoneSelfStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("soulstone", { NextAction("soulstone self", 24.0f) })); + triggers.push_back( + new TriggerNode( + "soulstone", + { + CreateNextAction(24.0f) + } + ) + ); } // Non-combat strategy for selecting the master to receive soulstone @@ -169,7 +324,14 @@ SoulstoneMasterStrategy::SoulstoneMasterStrategy(PlayerbotAI* ai) : NonCombatStr void SoulstoneMasterStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("soulstone", { NextAction("soulstone master", 24.0f) })); + triggers.push_back( + new TriggerNode( + "soulstone", + { + CreateNextAction(24.0f) + } + ) + ); } // Non-combat strategy for selecting tanks to receive soulstone @@ -180,7 +342,14 @@ SoulstoneTankStrategy::SoulstoneTankStrategy(PlayerbotAI* ai) : NonCombatStrateg void SoulstoneTankStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("soulstone", { NextAction("soulstone tank", 24.0f) })); + triggers.push_back( + new TriggerNode( + "soulstone", + { + CreateNextAction(24.0f) + } + ) + ); } // Non-combat strategy for selecting healers to receive soulstone @@ -191,7 +360,14 @@ SoulstoneHealerStrategy::SoulstoneHealerStrategy(PlayerbotAI* ai) : NonCombatStr void SoulstoneHealerStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("soulstone", { NextAction("soulstone healer", 24.0f) })); + triggers.push_back( + new TriggerNode( + "soulstone", + { + CreateNextAction(24.0f) + } + ) + ); } // Non-combat strategy for using Spellstone @@ -202,8 +378,22 @@ UseSpellstoneStrategy::UseSpellstoneStrategy(PlayerbotAI* ai) : NonCombatStrateg void UseSpellstoneStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("no spellstone", { NextAction("create spellstone", 24.0f) })); - triggers.push_back(new TriggerNode("spellstone", { NextAction("spellstone", 24.0f) })); + triggers.push_back( + new TriggerNode( + "no spellstone", + { + CreateNextAction(24.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "spellstone", + { + CreateNextAction(24.0f) + } + ) + ); } // Non-combat strategy for using Firestone @@ -214,6 +404,20 @@ UseFirestoneStrategy::UseFirestoneStrategy(PlayerbotAI* ai) : NonCombatStrategy( void UseFirestoneStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("no firestone", { NextAction("create firestone", 24.0f) })); - triggers.push_back(new TriggerNode("firestone", { NextAction("firestone", 24.0f) })); + triggers.push_back( + new TriggerNode( + "no firestone", + { + CreateNextAction(24.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "firestone", + { + CreateNextAction(24.0f) + } + ) + ); } diff --git a/src/Ai/Class/Warlock/Strategy/GenericWarlockStrategy.cpp b/src/Ai/Class/Warlock/Strategy/GenericWarlockStrategy.cpp index 1759776580..f74736e3aa 100644 --- a/src/Ai/Class/Warlock/Strategy/GenericWarlockStrategy.cpp +++ b/src/Ai/Class/Warlock/Strategy/GenericWarlockStrategy.cpp @@ -4,8 +4,8 @@ */ #include "GenericWarlockStrategy.h" -#include "Strategy.h" -#include "Playerbots.h" +#include "CancelChannelAction.h" +#include "WarlockActions.h" class GenericWarlockStrategyActionNodeFactory : public NamedObjectFactory { @@ -20,11 +20,51 @@ class GenericWarlockStrategyActionNodeFactory : public NamedObjectFactory& triggers) new TriggerNode( "low mana", { - NextAction("life tap", 95.0f) + CreateNextAction(95.0f) } ) ); @@ -53,7 +93,7 @@ void GenericWarlockStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "medium threat", { - NextAction("soulshatter", 55.0f) + CreateNextAction(55.0f) } ) ); @@ -61,7 +101,7 @@ void GenericWarlockStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "spell lock", { - NextAction("spell lock", 40.0f) + CreateNextAction(40.0f) } ) ); @@ -69,7 +109,7 @@ void GenericWarlockStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "no soul shard", { - NextAction("create soul shard", 60.0f) + CreateNextAction(60.0f) } ) ); @@ -77,7 +117,7 @@ void GenericWarlockStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "too many soul shards", { - NextAction("destroy soul shard", 60.0f) + CreateNextAction(60.0f) } ) ); @@ -85,7 +125,7 @@ void GenericWarlockStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "devour magic purge", { - NextAction("devour magic purge", 50.0f) + CreateNextAction(50.0f) } ) ); @@ -93,7 +133,7 @@ void GenericWarlockStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "devour magic cleanse", { - NextAction("devour magic cleanse", 50.0f) + CreateNextAction(50.0f) } ) ); @@ -107,12 +147,12 @@ void AoEWarlockStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "medium aoe", { - NextAction("immolation aura", 26.0f), - NextAction("shadowfury", 23.0f), - NextAction("shadowflame", 22.5f), - NextAction("seed of corruption on attacker", 22.0f), - NextAction("seed of corruption", 21.5f), - NextAction("rain of fire", 21.0f) + CreateNextAction(26.0f), + CreateNextAction(23.0f), + CreateNextAction(22.5f), + CreateNextAction(22.0f), + CreateNextAction(21.5f), + CreateNextAction(21.0f) } ) ); @@ -120,18 +160,18 @@ void AoEWarlockStrategy::InitTriggers(std::vector& triggers) triggers.push_back( new TriggerNode("rain of fire channel check", { - NextAction("cancel channel", 21.5f) + CreateNextAction(21.5f) } ) ); } -void WarlockBoostStrategy::InitTriggers(std::vector& triggers) +void WarlockBoostStrategy::InitTriggers(std::vector&) { // Placeholder for future boost triggers } -void WarlockPetStrategy::InitTriggers(std::vector& triggers) +void WarlockPetStrategy::InitTriggers(std::vector&) { // Placeholder for future pet triggers } @@ -142,7 +182,7 @@ void WarlockCcStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "banish", { - NextAction("banish on cc", 33.0f) + CreateNextAction(33.0f) } ) ); @@ -150,7 +190,7 @@ void WarlockCcStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "fear", { - NextAction("fear on cc", 32.0f) + CreateNextAction(32.0f) } ) ); @@ -166,7 +206,7 @@ void WarlockCurseOfAgonyStrategy::InitTriggers(std::vector& trigge new TriggerNode( "curse of agony on attacker", { - NextAction("curse of agony on attacker", 18.5f) + CreateNextAction(18.5f) } ) ); @@ -174,7 +214,7 @@ void WarlockCurseOfAgonyStrategy::InitTriggers(std::vector& trigge new TriggerNode( "curse of agony", { - NextAction("curse of agony", 17.0f) + CreateNextAction(17.0f) } ) ); @@ -190,7 +230,7 @@ void WarlockCurseOfTheElementsStrategy::InitTriggers(std::vector& new TriggerNode( "curse of the elements", { - NextAction("curse of the elements", 29.0f) + CreateNextAction(29.0f) } ) ); @@ -206,7 +246,7 @@ void WarlockCurseOfDoomStrategy::InitTriggers(std::vector& trigger new TriggerNode( "curse of doom", { - NextAction("curse of doom", 29.0f) + CreateNextAction(29.0f) } ) ); @@ -222,7 +262,7 @@ void WarlockCurseOfExhaustionStrategy::InitTriggers(std::vector& t new TriggerNode( "curse of exhaustion", { - NextAction("curse of exhaustion", 29.0f) + CreateNextAction(29.0f) } ) ); @@ -238,7 +278,7 @@ void WarlockCurseOfTonguesStrategy::InitTriggers(std::vector& trig new TriggerNode( "curse of tongues", { - NextAction("curse of tongues", 29.0f) + CreateNextAction(29.0f) } ) ); @@ -254,7 +294,7 @@ void WarlockCurseOfWeaknessStrategy::InitTriggers(std::vector& tri new TriggerNode( "curse of weakness", { - NextAction("curse of weakness", 29.0f) + CreateNextAction(29.0f) } ) ); diff --git a/src/Ai/Class/Warlock/Strategy/TankWarlockStrategy.cpp b/src/Ai/Class/Warlock/Strategy/TankWarlockStrategy.cpp index c54fd59684..b84974c286 100644 --- a/src/Ai/Class/Warlock/Strategy/TankWarlockStrategy.cpp +++ b/src/Ai/Class/Warlock/Strategy/TankWarlockStrategy.cpp @@ -4,7 +4,8 @@ */ #include "TankWarlockStrategy.h" -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "WarlockActions.h" // Combat strategy for a Warlock Tank, for certain bosses like Twin Emperors // Priority is set to spam Searing Pain and use Shadow Ward on CD @@ -23,8 +24,23 @@ class TankWarlockStrategyActionNodeFactory : public NamedObjectFactory TankWarlockStrategy::getDefaultActions() { // Shadow Ward is the highest priority, Searing Pain next. return { - NextAction("shadow ward", 27.5f), - NextAction("searing pain", 27.0f) + CreateNextAction(27.5f), + CreateNextAction(27.0f) }; } -void TankWarlockStrategy::InitTriggers(std::vector& triggers) +void TankWarlockStrategy::InitTriggers(std::vector&) { } diff --git a/src/Ai/Class/Warlock/Trigger/WarlockTriggers.cpp b/src/Ai/Class/Warlock/Trigger/WarlockTriggers.cpp index 04592c9b41..53e77669b2 100644 --- a/src/Ai/Class/Warlock/Trigger/WarlockTriggers.cpp +++ b/src/Ai/Class/Warlock/Trigger/WarlockTriggers.cpp @@ -96,7 +96,7 @@ bool DecimationTrigger::IsActive() // Checks if the bot's mana is below 85% and health is above a low health threshold bool LifeTapTrigger::IsActive() { - if (AI_VALUE2(uint8, "health", "self target") <= sPlayerbotAIConfig->lowHealth) + if (AI_VALUE2(uint8, "health", "self target") <= sPlayerbotAIConfig.lowHealth) return false; if (!AI_VALUE2(bool, "has mana", "self target")) diff --git a/src/Ai/Class/Warlock/WarlockAiObjectContext.cpp b/src/Ai/Class/Warlock/WarlockAiObjectContext.cpp index a70327b6c6..be28f4d8b5 100644 --- a/src/Ai/Class/Warlock/WarlockAiObjectContext.cpp +++ b/src/Ai/Class/Warlock/WarlockAiObjectContext.cpp @@ -11,7 +11,6 @@ #include "GenericTriggers.h" #include "GenericWarlockNonCombatStrategy.h" #include "NamedObjectContext.h" -#include "Playerbots.h" #include "PullStrategy.h" #include "Strategy.h" #include "TankWarlockStrategy.h" @@ -231,161 +230,18 @@ class WarlockTriggerFactoryInternal : public NamedObjectContext static Trigger* rain_of_fire_channel_check(PlayerbotAI* ai) { return new RainOfFireChannelCheckTrigger(ai); } }; -class WarlockAiObjectContextInternal : public NamedObjectContext -{ -public: - WarlockAiObjectContextInternal() - { - creators["fel armor"] = &WarlockAiObjectContextInternal::fel_armor; - creators["demon armor"] = &WarlockAiObjectContextInternal::demon_armor; - creators["demon skin"] = &WarlockAiObjectContextInternal::demon_skin; - creators["soul link"] = &WarlockAiObjectContextInternal::soul_link; - creators["create soul shard"] = &WarlockAiObjectContextInternal::create_soul_shard; - creators["destroy soul shard"] = &WarlockAiObjectContextInternal::destroy_soul_shard; - creators["create healthstone"] = &WarlockAiObjectContextInternal::create_healthstone; - creators["create firestone"] = &WarlockAiObjectContextInternal::create_firestone; - creators["create spellstone"] = &WarlockAiObjectContextInternal::create_spellstone; - creators["create soulstone"] = &WarlockAiObjectContextInternal::create_soulstone; - creators["firestone"] = &WarlockAiObjectContextInternal::firestone; - creators["spellstone"] = &WarlockAiObjectContextInternal::spellstone; - creators["soulstone self"] = &WarlockAiObjectContextInternal::soulstone_self; - creators["soulstone master"] = &WarlockAiObjectContextInternal::soulstone_master; - creators["soulstone tank"] = &WarlockAiObjectContextInternal::soulstone_tank; - creators["soulstone healer"] = &WarlockAiObjectContextInternal::soulstone_healer; - creators["summon voidwalker"] = &WarlockAiObjectContextInternal::summon_voidwalker; - creators["summon felguard"] = &WarlockAiObjectContextInternal::summon_felguard; - creators["summon felhunter"] = &WarlockAiObjectContextInternal::summon_felhunter; - creators["summon succubus"] = &WarlockAiObjectContextInternal::summon_succubus; - creators["summon imp"] = &WarlockAiObjectContextInternal::summon_imp; - creators["fel domination"] = &WarlockAiObjectContextInternal::fel_domination; - creators["immolate"] = &WarlockAiObjectContextInternal::immolate; - creators["immolate on attacker"] = &WarlockAiObjectContextInternal::immolate_on_attacker; - creators["corruption"] = &WarlockAiObjectContextInternal::corruption; - creators["corruption on attacker"] = &WarlockAiObjectContextInternal::corruption_on_attacker; - creators["shadow bolt"] = &WarlockAiObjectContextInternal::shadow_bolt; - creators["drain soul"] = &WarlockAiObjectContextInternal::drain_soul; - creators["drain mana"] = &WarlockAiObjectContextInternal::drain_mana; - creators["drain life"] = &WarlockAiObjectContextInternal::drain_life; - creators["banish on cc"] = &WarlockAiObjectContextInternal::banish_on_cc; - creators["fear on cc"] = &WarlockAiObjectContextInternal::fear_on_cc; - creators["spell lock"] = &WarlockAiObjectContextInternal::spell_lock; - creators["devour magic purge"] = &WarlockAiObjectContextInternal::devour_magic_purge; - creators["devour magic cleanse"] = &WarlockAiObjectContextInternal::devour_magic_cleanse; - creators["seed of corruption"] = &WarlockAiObjectContextInternal::seed_of_corruption; - creators["seed of corruption on attacker"] = &WarlockAiObjectContextInternal::seed_of_corruption_on_attacker; - creators["rain of fire"] = &WarlockAiObjectContextInternal::rain_of_fire; - creators["hellfire"] = &WarlockAiObjectContextInternal::hellfire; - creators["shadowfury"] = &WarlockAiObjectContextInternal::shadowfury; - creators["life tap"] = &WarlockAiObjectContextInternal::life_tap; - creators["incinerate"] = &WarlockAiObjectContextInternal::incinerate; - creators["conflagrate"] = &WarlockAiObjectContextInternal::conflagrate; - creators["unstable affliction"] = &WarlockAiObjectContextInternal::unstable_affliction; - creators["unstable affliction on attacker"] = &WarlockAiObjectContextInternal::unstable_affliction_on_attacker; - creators["haunt"] = &WarlockAiObjectContextInternal::haunt; - creators["demonic empowerment"] = &WarlockAiObjectContextInternal::demonic_empowerment; - creators["metamorphosis"] = &WarlockAiObjectContextInternal::metamorphosis; - creators["soul fire"] = &WarlockAiObjectContextInternal::soul_fire; - creators["incinerate"] = &WarlockAiObjectContextInternal::incinerate; - creators["demon charge"] = &WarlockAiObjectContextInternal::demon_charge; - creators["shadow cleave"] = &WarlockAiObjectContextInternal::shadow_cleave; - creators["shadowburn"] = &WarlockAiObjectContextInternal::shadowburn; - creators["shadowflame"] = &WarlockAiObjectContextInternal::shadowflame; - creators["immolation aura"] = &WarlockAiObjectContextInternal::immolation_aura; - creators["chaos bolt"] = &WarlockAiObjectContextInternal::chaos_bolt; - creators["soulshatter"] = &WarlockAiObjectContextInternal::soulshatter; - creators["searing pain"] = WarlockAiObjectContextInternal::searing_pain; - creators["shadow ward"] = &WarlockAiObjectContextInternal::shadow_ward; - creators["curse of agony"] = &WarlockAiObjectContextInternal::curse_of_agony; - creators["curse of agony on attacker"] = &WarlockAiObjectContextInternal::curse_of_agony_on_attacker; - creators["curse of the elements"] = &WarlockAiObjectContextInternal::curse_of_the_elements; - creators["curse of doom"] = &WarlockAiObjectContextInternal::curse_of_doom; - creators["curse of exhaustion"] = &WarlockAiObjectContextInternal::curse_of_exhaustion; - creators["curse of tongues"] = &WarlockAiObjectContextInternal::curse_of_tongues; - creators["curse of weakness"] = &WarlockAiObjectContextInternal::curse_of_weakness; - } - -private: - static Action* conflagrate(PlayerbotAI* botAI) { return new CastConflagrateAction(botAI); } - static Action* incinerate(PlayerbotAI* botAI) { return new CastIncinerateAction(botAI); } - static Action* immolate(PlayerbotAI* botAI) { return new CastImmolateAction(botAI); } - static Action* immolate_on_attacker(PlayerbotAI* botAI) { return new CastImmolateOnAttackerAction(botAI); } - static Action* fel_armor(PlayerbotAI* botAI) { return new CastFelArmorAction(botAI); } - static Action* demon_armor(PlayerbotAI* botAI) { return new CastDemonArmorAction(botAI); } - static Action* demon_skin(PlayerbotAI* botAI) { return new CastDemonSkinAction(botAI); } - static Action* soul_link(PlayerbotAI* botAI) { return new CastSoulLinkAction(botAI); } - static Action* create_soul_shard(PlayerbotAI* botAI) { return new CreateSoulShardAction(botAI); } - static Action* destroy_soul_shard(PlayerbotAI* botAI) { return new DestroySoulShardAction(botAI); } - static Action* create_healthstone(PlayerbotAI* botAI) { return new CastCreateHealthstoneAction(botAI); } - static Action* create_firestone(PlayerbotAI* botAI) { return new CastCreateFirestoneAction(botAI); } - static Action* create_spellstone(PlayerbotAI* botAI) { return new CastCreateSpellstoneAction(botAI); } - static Action* create_soulstone(PlayerbotAI* botAI) { return new CastCreateSoulstoneAction(botAI); } - static Action* firestone(PlayerbotAI* botAI) { return new UseSpellItemAction(botAI, "firestone", true); } - static Action* spellstone(PlayerbotAI* botAI) { return new UseSpellItemAction(botAI, "spellstone", true); } - static Action* soulstone_self(PlayerbotAI* botAI) { return new UseSoulstoneSelfAction(botAI); } - static Action* soulstone_master(PlayerbotAI* botAI) { return new UseSoulstoneMasterAction(botAI); } - static Action* soulstone_tank(PlayerbotAI* botAI) { return new UseSoulstoneTankAction(botAI); } - static Action* soulstone_healer(PlayerbotAI* botAI) { return new UseSoulstoneHealerAction(botAI); } - static Action* summon_voidwalker(PlayerbotAI* botAI) { return new CastSummonVoidwalkerAction(botAI); } - static Action* summon_felguard(PlayerbotAI* botAI) { return new CastSummonFelguardAction(botAI); } - static Action* summon_felhunter(PlayerbotAI* botAI) { return new CastSummonFelhunterAction(botAI); } - static Action* summon_imp(PlayerbotAI* botAI) { return new CastSummonImpAction(botAI); } - static Action* summon_succubus(PlayerbotAI* botAI) { return new CastSummonSuccubusAction(botAI); } - static Action* fel_domination(PlayerbotAI* botAI) { return new CastFelDominationAction(botAI); } - static Action* corruption(PlayerbotAI* botAI) { return new CastCorruptionAction(botAI); } - static Action* corruption_on_attacker(PlayerbotAI* botAI) { return new CastCorruptionOnAttackerAction(botAI); } - static Action* shadow_bolt(PlayerbotAI* botAI) { return new CastShadowBoltAction(botAI); } - static Action* drain_soul(PlayerbotAI* botAI) { return new CastDrainSoulAction(botAI); } - static Action* drain_mana(PlayerbotAI* botAI) { return new CastDrainManaAction(botAI); } - static Action* drain_life(PlayerbotAI* botAI) { return new CastDrainLifeAction(botAI); } - static Action* banish_on_cc(PlayerbotAI* botAI) { return new CastBanishOnCcAction(botAI); } - static Action* fear_on_cc(PlayerbotAI* botAI) { return new CastFearOnCcAction(botAI); } - static Action* spell_lock(PlayerbotAI* botAI) { return new CastSpellLockAction(botAI); } - static Action* devour_magic_purge(PlayerbotAI* botAI) { return new CastDevourMagicPurgeAction(botAI); } - static Action* devour_magic_cleanse(PlayerbotAI* botAI) { return new CastDevourMagicCleanseAction(botAI); } - static Action* seed_of_corruption(PlayerbotAI* botAI) { return new CastSeedOfCorruptionAction(botAI); } - static Action* seed_of_corruption_on_attacker(PlayerbotAI* botAI) { return new CastSeedOfCorruptionOnAttackerAction(botAI); } - static Action* rain_of_fire(PlayerbotAI* botAI) { return new CastRainOfFireAction(botAI); } - static Action* hellfire(PlayerbotAI* botAI) { return new CastHellfireAction(botAI); } - static Action* shadowfury(PlayerbotAI* botAI) { return new CastShadowfuryAction(botAI); } - static Action* life_tap(PlayerbotAI* botAI) { return new CastLifeTapAction(botAI); } - static Action* unstable_affliction(PlayerbotAI* ai) { return new CastUnstableAfflictionAction(ai); } - static Action* unstable_affliction_on_attacker(PlayerbotAI* ai) { return new CastUnstableAfflictionOnAttackerAction(ai); } - static Action* haunt(PlayerbotAI* ai) { return new CastHauntAction(ai); } - static Action* demonic_empowerment(PlayerbotAI* ai) { return new CastDemonicEmpowermentAction(ai); } - static Action* metamorphosis(PlayerbotAI* ai) { return new CastMetamorphosisAction(ai); } - static Action* soul_fire(PlayerbotAI* ai) { return new CastSoulFireAction(ai); } - static Action* demon_charge(PlayerbotAI* ai) { return new DemonChargeAction(ai); } - static Action* shadow_cleave(PlayerbotAI* ai) { return new ShadowCleaveAction(ai); } - static Action* shadowburn(PlayerbotAI* ai) { return new CastShadowburnAction(ai); } - static Action* shadowflame(PlayerbotAI* botAI) { return new CastShadowflameAction(botAI); } - static Action* immolation_aura(PlayerbotAI* botAI) { return new CastImmolationAuraAction(botAI); } - static Action* chaos_bolt(PlayerbotAI* botAI) { return new CastChaosBoltAction(botAI); } - static Action* soulshatter(PlayerbotAI* botAI) { return new CastSoulshatterAction(botAI); } - static Action* searing_pain(PlayerbotAI* botAI) { return new CastSearingPainAction(botAI); } - static Action* shadow_ward(PlayerbotAI* botAI) { return new CastShadowWardAction(botAI); } - static Action* curse_of_agony(PlayerbotAI* botAI) { return new CastCurseOfAgonyAction(botAI); } - static Action* curse_of_agony_on_attacker(PlayerbotAI* botAI) { return new CastCurseOfAgonyOnAttackerAction(botAI); } - static Action* curse_of_the_elements(PlayerbotAI* ai) { return new CastCurseOfTheElementsAction(ai); } - static Action* curse_of_doom(PlayerbotAI* ai) { return new CastCurseOfDoomAction(ai); } - static Action* curse_of_exhaustion(PlayerbotAI* ai) { return new CastCurseOfExhaustionAction(ai); } - static Action* curse_of_tongues(PlayerbotAI* ai) { return new CastCurseOfTonguesAction(ai); } - static Action* curse_of_weakness(PlayerbotAI* ai) { return new CastCurseOfWeaknessAction(ai); } -}; - SharedNamedObjectContextList WarlockAiObjectContext::sharedStrategyContexts; -SharedNamedObjectContextList WarlockAiObjectContext::sharedActionContexts; SharedNamedObjectContextList WarlockAiObjectContext::sharedTriggerContexts; SharedNamedObjectContextList WarlockAiObjectContext::sharedValueContexts; WarlockAiObjectContext::WarlockAiObjectContext(PlayerbotAI* botAI) - : AiObjectContext(botAI, sharedStrategyContexts, sharedActionContexts, sharedTriggerContexts, sharedValueContexts) + : AiObjectContext(botAI, sharedStrategyContexts, sharedTriggerContexts, sharedValueContexts) { } void WarlockAiObjectContext::BuildSharedContexts() { BuildSharedStrategyContexts(sharedStrategyContexts); - BuildSharedActionContexts(sharedActionContexts); BuildSharedTriggerContexts(sharedTriggerContexts); BuildSharedValueContexts(sharedValueContexts); } @@ -401,12 +257,6 @@ void WarlockAiObjectContext::BuildSharedStrategyContexts(SharedNamedObjectContex strategyContexts.Add(new WarlockWeaponStoneStrategyFactoryInternal()); } -void WarlockAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts) -{ - AiObjectContext::BuildSharedActionContexts(actionContexts); - actionContexts.Add(new WarlockAiObjectContextInternal()); -} - void WarlockAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts) { AiObjectContext::BuildSharedTriggerContexts(triggerContexts); diff --git a/src/Ai/Class/Warlock/WarlockAiObjectContext.h b/src/Ai/Class/Warlock/WarlockAiObjectContext.h index 29b3792d94..60d94e107b 100644 --- a/src/Ai/Class/Warlock/WarlockAiObjectContext.h +++ b/src/Ai/Class/Warlock/WarlockAiObjectContext.h @@ -17,12 +17,10 @@ class WarlockAiObjectContext : public AiObjectContext static void BuildSharedContexts(); static void BuildSharedStrategyContexts(SharedNamedObjectContextList& strategyContexts); - static void BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts); static void BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts); static void BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts); static SharedNamedObjectContextList sharedStrategyContexts; - static SharedNamedObjectContextList sharedActionContexts; static SharedNamedObjectContextList sharedTriggerContexts; static SharedNamedObjectContextList sharedValueContexts; }; diff --git a/src/Ai/Class/Warrior/Action/WarriorActions.cpp b/src/Ai/Class/Warrior/Action/WarriorActions.cpp index 9733226a95..f31dd1d9a1 100644 --- a/src/Ai/Class/Warrior/Action/WarriorActions.cpp +++ b/src/Ai/Class/Warrior/Action/WarriorActions.cpp @@ -93,7 +93,7 @@ Unit* CastVigilanceAction::GetTarget() return nullptr; } -bool CastVigilanceAction::Execute(Event event) +bool CastVigilanceAction::Execute(Event) { Unit* target = GetTarget(); if (!target || target == bot) @@ -234,7 +234,7 @@ bool CastShatteringThrowAction::isPossible() return true; } -bool CastShatteringThrowAction::Execute(Event event) +bool CastShatteringThrowAction::Execute(Event) { Unit* target = GetTarget(); if (!target) diff --git a/src/Ai/Class/Warrior/Strategy/ArmsWarriorStrategy.cpp b/src/Ai/Class/Warrior/Strategy/ArmsWarriorStrategy.cpp index eba5677e7f..fa3527c216 100644 --- a/src/Ai/Class/Warrior/Strategy/ArmsWarriorStrategy.cpp +++ b/src/Ai/Class/Warrior/Strategy/ArmsWarriorStrategy.cpp @@ -4,8 +4,10 @@ */ #include "ArmsWarriorStrategy.h" - -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "GenericActions.h" +#include "ReachTargetActions.h" +#include "WarriorActions.h" class ArmsWarriorStrategyActionNodeFactory : public NamedObjectFactory { @@ -23,80 +25,72 @@ class ArmsWarriorStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } - static ActionNode* death_wish(PlayerbotAI* botAI) + static ActionNode* death_wish(PlayerbotAI*) { return new ActionNode( - "death wish", /*P*/ {}, - /*A*/ { NextAction("bloodrage") }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } - static ActionNode* piercing_howl(PlayerbotAI* botAI) + static ActionNode* piercing_howl(PlayerbotAI*) { return new ActionNode( - "piercing howl", /*P*/ {}, - /*A*/ { NextAction("mocking blow") }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } - static ActionNode* mocking_blow(PlayerbotAI* botAI) + static ActionNode* mocking_blow(PlayerbotAI*) { return new ActionNode( - "mocking blow", /*P*/ {}, - /*A*/ { NextAction("hamstring") }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } - static ActionNode* heroic_strike(PlayerbotAI* botAI) + static ActionNode* heroic_strike(PlayerbotAI*) { return new ActionNode( - "heroic strike", /*P*/ {}, - /*A*/ { NextAction("melee") }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } - static ActionNode* enraged_regeneration(PlayerbotAI* botAI) + static ActionNode* enraged_regeneration(PlayerbotAI*) { return new ActionNode( - "enraged regeneration", /*P*/ {}, /*A*/ {}, /*C*/ {} ); } - static ActionNode* retaliation(PlayerbotAI* botAI) + static ActionNode* retaliation(PlayerbotAI*) { return new ActionNode( - "retaliation", /*P*/ {}, /*A*/ {}, /*C*/ {} ); } - static ActionNode* shattering_throw(PlayerbotAI* botAI) + static ActionNode* shattering_throw(PlayerbotAI*) { return new ActionNode( - "shattering throw", /*P*/ {}, /*A*/ {}, /*C*/ {} @@ -112,9 +106,9 @@ ArmsWarriorStrategy::ArmsWarriorStrategy(PlayerbotAI* botAI) : GenericWarriorStr std::vector ArmsWarriorStrategy::getDefaultActions() { return { - NextAction("bladestorm", ACTION_DEFAULT + 0.2f), - NextAction("mortal strike", ACTION_DEFAULT + 0.1f), - NextAction("melee", ACTION_DEFAULT) + CreateNextAction(ACTION_DEFAULT + 0.2f), + CreateNextAction(ACTION_DEFAULT + 0.1f), + CreateNextAction(ACTION_DEFAULT) }; } void ArmsWarriorStrategy::InitTriggers(std::vector& triggers) @@ -125,7 +119,7 @@ void ArmsWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "enemy out of melee", { - NextAction("charge", ACTION_MOVE + 10) + CreateNextAction(ACTION_MOVE + 10.0f) } ) ); @@ -134,7 +128,7 @@ void ArmsWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "battle stance", { - NextAction("battle stance", ACTION_HIGH + 10) + CreateNextAction(ACTION_HIGH + 10) } ) ); @@ -143,7 +137,7 @@ void ArmsWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "battle shout", { - NextAction("battle shout", ACTION_HIGH + 9) + CreateNextAction(ACTION_HIGH + 9.0f) } ) ); @@ -152,7 +146,7 @@ void ArmsWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "rend", { - NextAction("rend", ACTION_HIGH + 8) + CreateNextAction(ACTION_HIGH + 8.0f) } ) ); @@ -161,7 +155,7 @@ void ArmsWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "rend on attacker", { - NextAction("rend on attacker", ACTION_HIGH + 8) + CreateNextAction(ACTION_HIGH + 8.0f) } ) ); @@ -170,7 +164,7 @@ void ArmsWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "mortal strike", { - NextAction("mortal strike", ACTION_HIGH + 3) + CreateNextAction(ACTION_HIGH + 3.0f) } ) ); @@ -179,7 +173,7 @@ void ArmsWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "target critical health", { - NextAction("execute", ACTION_HIGH + 5) + CreateNextAction(ACTION_HIGH + 5.0f) } ) ); @@ -188,7 +182,7 @@ void ArmsWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "sudden death", { - NextAction("execute", ACTION_HIGH + 5) + CreateNextAction(ACTION_HIGH + 5.0f) } ) ); @@ -197,7 +191,7 @@ void ArmsWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "hamstring", { - NextAction("piercing howl", ACTION_HIGH) + CreateNextAction(ACTION_HIGH) } ) ); @@ -206,7 +200,7 @@ void ArmsWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "overpower", { - NextAction("overpower", ACTION_HIGH + 4) + CreateNextAction(ACTION_HIGH + 4.0f) } ) ); @@ -215,7 +209,7 @@ void ArmsWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "taste for blood", { - NextAction("overpower", ACTION_HIGH + 4) + CreateNextAction(ACTION_HIGH + 4.0f) } ) ); @@ -224,7 +218,7 @@ void ArmsWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "victory rush", { - NextAction("victory rush", ACTION_INTERRUPT) + CreateNextAction(ACTION_INTERRUPT) } ) ); @@ -233,8 +227,8 @@ void ArmsWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "high rage available", { - NextAction("heroic strike", ACTION_HIGH), - NextAction("slam", ACTION_HIGH + 1) + CreateNextAction(ACTION_HIGH), + CreateNextAction(ACTION_HIGH + 1.0f) } ) ); @@ -242,7 +236,7 @@ void ArmsWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "bloodrage", { - NextAction("bloodrage", ACTION_HIGH + 2) + CreateNextAction(ACTION_HIGH + 2.0f) } ) ); @@ -251,7 +245,7 @@ void ArmsWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "death wish", { - NextAction("death wish", ACTION_HIGH + 2) + CreateNextAction(ACTION_HIGH + 2.0f) } ) ); @@ -260,7 +254,7 @@ void ArmsWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "critical health", { - NextAction("intimidating shout", ACTION_EMERGENCY) + CreateNextAction(ACTION_EMERGENCY) } ) ); @@ -269,7 +263,7 @@ void ArmsWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "medium health", { - NextAction("enraged regeneration", ACTION_EMERGENCY) + CreateNextAction(ACTION_EMERGENCY) } ) ); @@ -278,7 +272,7 @@ void ArmsWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "almost full health", { - NextAction("retaliation", ACTION_EMERGENCY + 1) + CreateNextAction(ACTION_EMERGENCY + 1.0f) } ) ); @@ -287,7 +281,7 @@ void ArmsWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "shattering throw trigger", { - NextAction("shattering throw", ACTION_INTERRUPT + 1) + CreateNextAction(ACTION_INTERRUPT + 1.0f) } ) ); diff --git a/src/Ai/Class/Warrior/Strategy/FuryWarriorStrategy.cpp b/src/Ai/Class/Warrior/Strategy/FuryWarriorStrategy.cpp index 6400ee4a8e..7104946140 100644 --- a/src/Ai/Class/Warrior/Strategy/FuryWarriorStrategy.cpp +++ b/src/Ai/Class/Warrior/Strategy/FuryWarriorStrategy.cpp @@ -4,8 +4,9 @@ */ #include "FuryWarriorStrategy.h" - -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "GenericActions.h" +#include "WarriorActions.h" class FuryWarriorStrategyActionNodeFactory : public NamedObjectFactory { @@ -20,50 +21,45 @@ class FuryWarriorStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } - static ActionNode* intercept(PlayerbotAI* botAI) + static ActionNode* intercept(PlayerbotAI*) { return new ActionNode( - "intercept", /*P*/ {}, - /*A*/ { NextAction("reach melee" )}, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } - static ActionNode* piercing_howl(PlayerbotAI* botAI) + static ActionNode* piercing_howl(PlayerbotAI*) { return new ActionNode( - "piercing howl", /*P*/ {}, - /*A*/ { NextAction("hamstring" )}, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } - static ActionNode* pummel(PlayerbotAI* botAI) + static ActionNode* pummel(PlayerbotAI*) { return new ActionNode( - "pummel", /*P*/ {}, - /*A*/ { NextAction("intercept" )}, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } - static ActionNode* enraged_regeneration(PlayerbotAI* botAI) + static ActionNode* enraged_regeneration(PlayerbotAI*) { return new ActionNode( - "enraged regeneration", /*P*/ {}, /*A*/ {}, /*C*/ {} @@ -79,11 +75,11 @@ FuryWarriorStrategy::FuryWarriorStrategy(PlayerbotAI* botAI) : GenericWarriorStr std::vector FuryWarriorStrategy::getDefaultActions() { return { - NextAction("bloodthirst", ACTION_DEFAULT + 0.5f), - NextAction("whirlwind", ACTION_DEFAULT + 0.4f), - NextAction("sunder armor", ACTION_DEFAULT + 0.3f), - NextAction("execute", ACTION_DEFAULT + 0.2f), - NextAction("melee", ACTION_DEFAULT) + CreateNextAction(ACTION_DEFAULT + 0.5f), + CreateNextAction(ACTION_DEFAULT + 0.4f), + CreateNextAction(ACTION_DEFAULT + 0.3f), + CreateNextAction(ACTION_DEFAULT + 0.2f), + CreateNextAction(ACTION_DEFAULT) }; } @@ -95,14 +91,14 @@ void FuryWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "enemy out of melee", { - NextAction("charge", ACTION_MOVE + 9) + CreateNextAction(ACTION_MOVE + 9.0f) } ) ); triggers.push_back( new TriggerNode( "berserker stance", { - NextAction("berserker stance", ACTION_HIGH + 9) + CreateNextAction(ACTION_HIGH + 9) } ) ); @@ -110,7 +106,7 @@ void FuryWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "battle shout", { - NextAction("battle shout", ACTION_HIGH + 8) + CreateNextAction(ACTION_HIGH + 8.0f) } ) ); @@ -118,7 +114,7 @@ void FuryWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "pummel on enemy healer", { - NextAction("pummel on enemy healer", ACTION_INTERRUPT) + CreateNextAction(ACTION_INTERRUPT) } ) ); @@ -126,7 +122,7 @@ void FuryWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "pummel", { - NextAction("pummel", ACTION_INTERRUPT) + CreateNextAction(ACTION_INTERRUPT) } ) ); @@ -134,7 +130,7 @@ void FuryWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "victory rush", { - NextAction("victory rush", ACTION_INTERRUPT) + CreateNextAction(ACTION_INTERRUPT) } ) ); @@ -142,7 +138,7 @@ void FuryWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "bloodthirst", { - NextAction("bloodthirst", ACTION_HIGH + 7) + CreateNextAction(ACTION_HIGH + 7.0f) } ) ); @@ -150,7 +146,7 @@ void FuryWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "whirlwind", { - NextAction("whirlwind", ACTION_HIGH + 6) + CreateNextAction(ACTION_HIGH + 6.0f) } ) ); @@ -158,7 +154,7 @@ void FuryWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "instant slam", { - NextAction("slam", ACTION_HIGH + 5) + CreateNextAction(ACTION_HIGH + 5.0f) } ) ); @@ -166,7 +162,7 @@ void FuryWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "bloodrage", { - NextAction("bloodrage", ACTION_HIGH + 2) + CreateNextAction(ACTION_HIGH + 2.0f) } ) ); @@ -174,7 +170,7 @@ void FuryWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "medium rage available", { - NextAction("heroic strike", ACTION_DEFAULT + 0.1f) + CreateNextAction(ACTION_DEFAULT + 0.1f) } ) ); @@ -183,7 +179,7 @@ void FuryWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "death wish", { - NextAction("death wish", ACTION_HIGH) + CreateNextAction(ACTION_HIGH) } ) ); @@ -191,7 +187,7 @@ void FuryWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "recklessness", { - NextAction("recklessness", ACTION_HIGH) + CreateNextAction(ACTION_HIGH) } ) ); @@ -199,7 +195,7 @@ void FuryWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "critical health", { - NextAction("enraged regeneration", ACTION_EMERGENCY) + CreateNextAction(ACTION_EMERGENCY) } ) ); diff --git a/src/Ai/Class/Warrior/Strategy/GenericWarriorNonCombatStrategy.cpp b/src/Ai/Class/Warrior/Strategy/GenericWarriorNonCombatStrategy.cpp index 091aed2b84..c00325e216 100644 --- a/src/Ai/Class/Warrior/Strategy/GenericWarriorNonCombatStrategy.cpp +++ b/src/Ai/Class/Warrior/Strategy/GenericWarriorNonCombatStrategy.cpp @@ -4,12 +4,19 @@ */ #include "GenericWarriorNonCombatStrategy.h" - -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "ImbueAction.h" void GenericWarriorNonCombatStrategy::InitTriggers(std::vector& triggers) { NonCombatStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("often", { NextAction("apply stone", 1.0f) })); + triggers.push_back( + new TriggerNode( + "often", + { + CreateNextAction(1.0f) + } + ) + ); } diff --git a/src/Ai/Class/Warrior/Strategy/GenericWarriorStrategy.cpp b/src/Ai/Class/Warrior/Strategy/GenericWarriorStrategy.cpp index 178984de9c..55b1584d43 100644 --- a/src/Ai/Class/Warrior/Strategy/GenericWarriorStrategy.cpp +++ b/src/Ai/Class/Warrior/Strategy/GenericWarriorStrategy.cpp @@ -4,8 +4,9 @@ */ #include "GenericWarriorStrategy.h" - -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "ReachTargetActions.h" +#include "WarriorActions.h" GenericWarriorStrategy::GenericWarriorStrategy(PlayerbotAI* botAI) : CombatStrategy(botAI) { @@ -15,8 +16,14 @@ GenericWarriorStrategy::GenericWarriorStrategy(PlayerbotAI* botAI) : CombatStrat void GenericWarriorStrategy::InitTriggers(std::vector& triggers) { CombatStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode( - "enemy out of melee", { NextAction("reach melee", ACTION_HIGH + 1) })); + triggers.push_back( + new TriggerNode( + "enemy out of melee", + { + CreateNextAction(ACTION_HIGH + 1.0f) + } + ) + ); } class WarrirorAoeStrategyActionNodeFactory : public NamedObjectFactory @@ -38,15 +45,25 @@ WarrirorAoeStrategy::WarrirorAoeStrategy(PlayerbotAI* botAI) : CombatStrategy(bo void WarrirorAoeStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode( - "light aoe", { NextAction("sweeping strikes", ACTION_HIGH + 7), - NextAction("bladestorm", ACTION_HIGH + 6), - NextAction("thunder clap", ACTION_HIGH + 5), - NextAction("shockwave", ACTION_HIGH + 4), - NextAction("demoralizing shout without life time check", ACTION_HIGH + 1), - NextAction("cleave", ACTION_HIGH) })); triggers.push_back( - new TriggerNode("shockwave on snare target", - { NextAction("shockwave on snare target", ACTION_HIGH + 5) })); - + new TriggerNode( + "light aoe", + { + CreateNextAction(ACTION_HIGH + 7.0f), + CreateNextAction(ACTION_HIGH + 6.0f), + CreateNextAction(ACTION_HIGH + 5.0f), + CreateNextAction(ACTION_HIGH + 4.0f), + CreateNextAction(ACTION_HIGH + 1.0f), + CreateNextAction(ACTION_HIGH) + } + ) + ); + triggers.push_back( + new TriggerNode( + "shockwave on snare target", + { + CreateNextAction(ACTION_HIGH + 5.0f) + } + ) + ); } diff --git a/src/Ai/Class/Warrior/Strategy/GenericWarriorStrategy.h b/src/Ai/Class/Warrior/Strategy/GenericWarriorStrategy.h index 5a336be203..6d067064d5 100644 --- a/src/Ai/Class/Warrior/Strategy/GenericWarriorStrategy.h +++ b/src/Ai/Class/Warrior/Strategy/GenericWarriorStrategy.h @@ -7,6 +7,8 @@ #define _PLAYERBOT_GENERICWARRIORSTRATEGY_H #include "CombatStrategy.h" +#include "CreateNextAction.h" +#include "WarriorActions.h" class PlayerbotAI; @@ -47,8 +49,7 @@ class WarriorStanceRequirementActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -57,8 +58,7 @@ class WarriorStanceRequirementActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -67,8 +67,7 @@ class WarriorStanceRequirementActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -77,8 +76,7 @@ class WarriorStanceRequirementActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -87,8 +85,7 @@ class WarriorStanceRequirementActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -97,8 +94,7 @@ class WarriorStanceRequirementActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -107,8 +103,7 @@ class WarriorStanceRequirementActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -117,8 +112,7 @@ class WarriorStanceRequirementActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -127,8 +121,7 @@ class WarriorStanceRequirementActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -137,8 +130,7 @@ class WarriorStanceRequirementActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -147,8 +139,7 @@ class WarriorStanceRequirementActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -157,8 +148,7 @@ class WarriorStanceRequirementActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -167,8 +157,7 @@ class WarriorStanceRequirementActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -177,8 +166,7 @@ class WarriorStanceRequirementActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -187,8 +175,7 @@ class WarriorStanceRequirementActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -197,8 +184,7 @@ class WarriorStanceRequirementActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); @@ -207,8 +193,7 @@ class WarriorStanceRequirementActionNodeFactory : public NamedObjectFactory(1.0f) }, /*A*/ {}, /*C*/ {} ); diff --git a/src/Ai/Class/Warrior/Strategy/TankWarriorStrategy.cpp b/src/Ai/Class/Warrior/Strategy/TankWarriorStrategy.cpp index 05f732c30c..c8e2123e62 100644 --- a/src/Ai/Class/Warrior/Strategy/TankWarriorStrategy.cpp +++ b/src/Ai/Class/Warrior/Strategy/TankWarriorStrategy.cpp @@ -4,8 +4,7 @@ */ #include "TankWarriorStrategy.h" - -#include "Playerbots.h" +#include "GenericActions.h" class TankWarriorStrategyActionNodeFactory : public NamedObjectFactory { @@ -26,100 +25,93 @@ class TankWarriorStrategyActionNodeFactory : public NamedObjectFactory(1.0f) }, /*C*/ {} ); } - static ActionNode* heroic_throw_on_snare_target(PlayerbotAI* botAI) + static ActionNode* heroic_throw_on_snare_target(PlayerbotAI*) { return new ActionNode( - "heroic throw on snare target", /*P*/ {}, - /*A*/ { NextAction("taunt on snare target") }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } - static ActionNode* last_stand(PlayerbotAI* botAI) + static ActionNode* last_stand(PlayerbotAI*) { return new ActionNode( - "last stand", /*P*/ {}, - /*A*/ { NextAction("intimidating shout") }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } - static ActionNode* devastate(PlayerbotAI* botAI) + static ActionNode* devastate(PlayerbotAI*) { return new ActionNode( - "devastate", /*P*/ {}, - /*A*/ { NextAction("sunder armor") }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } - static ActionNode* commanding_shout(PlayerbotAI* botAI) + static ActionNode* commanding_shout(PlayerbotAI*) { return new ActionNode( - "commanding shout", /*P*/ {}, - /*A*/ { NextAction("battle shout") }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } - static ActionNode* sunder_armor(PlayerbotAI* botAI) + static ActionNode* sunder_armor(PlayerbotAI*) { return new ActionNode( - "sunder armor", /*P*/ {}, - /*A*/ { NextAction("melee") }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } - static ActionNode* charge(PlayerbotAI* botAI) + static ActionNode* charge(PlayerbotAI*) { return new ActionNode( - "charge", /*P*/ {}, - /*A*/ { NextAction("reach melee") }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } - static ActionNode* taunt(PlayerbotAI* botAI) + static ActionNode* taunt(PlayerbotAI*) { return new ActionNode( - "taunt", /*P*/ {}, - /*A*/ { NextAction("heroic throw taunt") }, + /*A*/ { + CreateNextAction(1.0f), + CreateNextAction(1.0f), + }, /*C*/ {} ); } - static ActionNode* vigilance(PlayerbotAI* botAI) + static ActionNode* vigilance(PlayerbotAI*) { return new ActionNode( - "vigilance", /*P*/ {}, /*A*/ {}, /*C*/ {} ); } - static ActionNode* enraged_regeneration(PlayerbotAI* botAI) + static ActionNode* enraged_regeneration(PlayerbotAI*) { return new ActionNode( - "enraged regeneration", /*P*/ {}, /*A*/ {}, /*C*/ {} @@ -135,10 +127,10 @@ TankWarriorStrategy::TankWarriorStrategy(PlayerbotAI* botAI) : GenericWarriorStr std::vector TankWarriorStrategy::getDefaultActions() { return { - NextAction("devastate", ACTION_DEFAULT + 0.3f), - NextAction("revenge", ACTION_DEFAULT + 0.2f), - NextAction("demoralizing shout", ACTION_DEFAULT + 0.1f), - NextAction("melee", ACTION_DEFAULT) + CreateNextAction(ACTION_DEFAULT + 0.3f), + CreateNextAction(ACTION_DEFAULT + 0.2f), + CreateNextAction(ACTION_DEFAULT + 0.1f), + CreateNextAction(ACTION_DEFAULT) }; } @@ -150,7 +142,7 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "vigilance", { - NextAction("vigilance", ACTION_HIGH + 7) + CreateNextAction(ACTION_HIGH + 7.0f) } ) ); @@ -158,8 +150,8 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "enemy out of melee", { - NextAction("heroic throw", ACTION_MOVE + 11), - NextAction("charge", ACTION_MOVE + 10) + CreateNextAction(ACTION_MOVE + 11.0f), + CreateNextAction(ACTION_MOVE + 10.0f) } ) ); @@ -168,7 +160,7 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "thunder clap and rage", { - NextAction("thunder clap", ACTION_MOVE + 11) + CreateNextAction(ACTION_MOVE + 11.0f) } ) ); @@ -176,7 +168,7 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "defensive stance", { - NextAction("defensive stance", ACTION_HIGH + 9) + CreateNextAction(ACTION_HIGH + 9.0f) } ) ); @@ -184,7 +176,7 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "commanding shout", { - NextAction("commanding shout", ACTION_HIGH + 8) + CreateNextAction(ACTION_HIGH + 8.0f) } ) ); @@ -192,7 +184,7 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "bloodrage", { - NextAction("bloodrage", ACTION_HIGH + 2) + CreateNextAction(ACTION_HIGH + 2.0f) } ) ); @@ -200,7 +192,7 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "sunder armor", { - NextAction("devastate", ACTION_HIGH + 2) + CreateNextAction(ACTION_HIGH + 2.0f) } ) ); @@ -208,8 +200,8 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "medium rage available", { - NextAction("shield slam", ACTION_HIGH + 2), - NextAction("devastate", ACTION_HIGH + 1) + CreateNextAction(ACTION_HIGH + 2.0f), + CreateNextAction(ACTION_HIGH + 1.0f) } ) ); @@ -217,7 +209,7 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "shield block", { - NextAction("shield block", ACTION_INTERRUPT + 1) + CreateNextAction(ACTION_INTERRUPT + 1.0f) } ) ); @@ -225,7 +217,7 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "revenge", { - NextAction("revenge", ACTION_HIGH + 2) + CreateNextAction(ACTION_HIGH + 2.0f) } ) ); @@ -233,7 +225,7 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "disarm", { - NextAction("disarm", ACTION_HIGH + 1) + CreateNextAction(ACTION_HIGH + 1.0f) } ) ); @@ -241,7 +233,7 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "lose aggro", { - NextAction("taunt", ACTION_INTERRUPT + 1) + CreateNextAction(ACTION_INTERRUPT + 1.0f) } ) ); @@ -249,7 +241,7 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "taunt on snare target", { - NextAction("heroic throw on snare target", ACTION_INTERRUPT) + CreateNextAction(ACTION_INTERRUPT) } ) ); @@ -257,7 +249,7 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "low health", { - NextAction("shield wall", ACTION_MEDIUM_HEAL) + CreateNextAction(ACTION_MEDIUM_HEAL) } ) ); @@ -265,8 +257,8 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "critical health", { - NextAction("last stand", ACTION_EMERGENCY + 3), - NextAction("enraged regeneration", ACTION_EMERGENCY + 2) + CreateNextAction(ACTION_EMERGENCY + 3.0f), + CreateNextAction(ACTION_EMERGENCY + 2.0f) } ) ); @@ -274,7 +266,7 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "high aoe", { - NextAction("challenging shout", ACTION_HIGH + 3) + CreateNextAction(ACTION_HIGH + 3.0f) } ) ); @@ -282,7 +274,7 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "concussion blow", { - NextAction("concussion blow", ACTION_INTERRUPT) + CreateNextAction(ACTION_INTERRUPT) } ) ); @@ -290,7 +282,7 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "shield bash", { - NextAction("shield bash", ACTION_INTERRUPT) + CreateNextAction(ACTION_INTERRUPT) } ) ); @@ -298,7 +290,7 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "shield bash on enemy healer", { - NextAction("shield bash on enemy healer", ACTION_INTERRUPT) + CreateNextAction(ACTION_INTERRUPT) } ) ); @@ -306,7 +298,7 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "spell reflection", { - NextAction("spell reflection", ACTION_INTERRUPT + 1) + CreateNextAction(ACTION_INTERRUPT + 1.0f) } ) ); @@ -314,7 +306,7 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "victory rush", { - NextAction("victory rush", ACTION_INTERRUPT) + CreateNextAction(ACTION_INTERRUPT) } ) ); @@ -322,7 +314,7 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "sword and board", { - NextAction("shield slam", ACTION_INTERRUPT) + CreateNextAction(ACTION_INTERRUPT) } ) ); @@ -330,7 +322,7 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "rend", { - NextAction("rend", ACTION_NORMAL + 1) + CreateNextAction(ACTION_NORMAL + 1.0f) } ) ); @@ -338,7 +330,7 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "rend on attacker", { - NextAction("rend on attacker", ACTION_NORMAL + 1) + CreateNextAction(ACTION_NORMAL + 1.0f) } ) ); @@ -346,7 +338,7 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "protect party member", { - NextAction("intervene", ACTION_EMERGENCY) + CreateNextAction(ACTION_EMERGENCY) } ) ); @@ -354,7 +346,7 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "high rage available", { - NextAction("heroic strike", ACTION_HIGH) + CreateNextAction(ACTION_HIGH) } ) ); @@ -362,7 +354,7 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "medium rage available", { - NextAction("thunder clap", ACTION_HIGH + 1) + CreateNextAction(ACTION_HIGH + 1.0f) } ) ); diff --git a/src/Ai/Class/Warrior/Strategy/TankWarriorStrategy.h b/src/Ai/Class/Warrior/Strategy/TankWarriorStrategy.h index b528242979..885d0fb1f1 100644 --- a/src/Ai/Class/Warrior/Strategy/TankWarriorStrategy.h +++ b/src/Ai/Class/Warrior/Strategy/TankWarriorStrategy.h @@ -7,7 +7,6 @@ #define _PLAYERBOT_TANKWARRIORSTRATEGY_H #include "GenericWarriorStrategy.h" -#include "WarriorTriggers.h" class PlayerbotAI; diff --git a/src/Ai/Class/Warrior/Trigger/WarriorTriggers.cpp b/src/Ai/Class/Warrior/Trigger/WarriorTriggers.cpp index b561c4815d..5aa419c927 100644 --- a/src/Ai/Class/Warrior/Trigger/WarriorTriggers.cpp +++ b/src/Ai/Class/Warrior/Trigger/WarriorTriggers.cpp @@ -9,7 +9,7 @@ bool BloodrageBuffTrigger::IsActive() { - return AI_VALUE2(uint8, "health", "self target") >= sPlayerbotAIConfig->mediumHealth && + return AI_VALUE2(uint8, "health", "self target") >= sPlayerbotAIConfig.mediumHealth && AI_VALUE2(uint8, "rage", "self target") < 20; } diff --git a/src/Ai/Class/Warrior/WarriorAiObjectContext.cpp b/src/Ai/Class/Warrior/WarriorAiObjectContext.cpp index 3a9af55172..7792eb272b 100644 --- a/src/Ai/Class/Warrior/WarriorAiObjectContext.cpp +++ b/src/Ai/Class/Warrior/WarriorAiObjectContext.cpp @@ -9,10 +9,8 @@ #include "FuryWarriorStrategy.h" #include "GenericWarriorNonCombatStrategy.h" #include "NamedObjectContext.h" -#include "Playerbots.h" #include "PullStrategy.h" #include "TankWarriorStrategy.h" -#include "WarriorActions.h" #include "WarriorTriggers.h" class WarriorStrategyFactoryInternal : public NamedObjectContext @@ -176,162 +174,18 @@ class WarriorTriggerFactoryInternal : public NamedObjectContext static Trigger* shattering_throw_trigger(PlayerbotAI* botAI) { return new ShatteringThrowTrigger(botAI); } }; -class WarriorAiObjectContextInternal : public NamedObjectContext -{ -public: - WarriorAiObjectContextInternal() - { - creators["devastate"] = &WarriorAiObjectContextInternal::devastate; - creators["overpower"] = &WarriorAiObjectContextInternal::overpower; - creators["charge"] = &WarriorAiObjectContextInternal::charge; - creators["bloodthirst"] = &WarriorAiObjectContextInternal::bloodthirst; - creators["rend"] = &WarriorAiObjectContextInternal::rend; - creators["rend on attacker"] = &WarriorAiObjectContextInternal::rend_on_attacker; - creators["mocking blow"] = &WarriorAiObjectContextInternal::mocking_blow; - creators["death wish"] = &WarriorAiObjectContextInternal::death_wish; - creators["recklessness"] = &WarriorAiObjectContextInternal::recklessness; - creators["berserker rage"] = &WarriorAiObjectContextInternal::berserker_rage; - creators["victory rush"] = &WarriorAiObjectContextInternal::victory_rush; - creators["execute"] = &WarriorAiObjectContextInternal::execute; - creators["defensive stance"] = &WarriorAiObjectContextInternal::defensive_stance; - creators["hamstring"] = &WarriorAiObjectContextInternal::hamstring; - creators["shield bash"] = &WarriorAiObjectContextInternal::shield_bash; - creators["shield block"] = &WarriorAiObjectContextInternal::shield_block; - creators["bloodrage"] = &WarriorAiObjectContextInternal::bloodrage; - creators["battle stance"] = &WarriorAiObjectContextInternal::battle_stance; - creators["heroic strike"] = &WarriorAiObjectContextInternal::heroic_strike; - creators["intimidating shout"] = &WarriorAiObjectContextInternal::intimidating_shout; - creators["demoralizing shout"] = &WarriorAiObjectContextInternal::demoralizing_shout; - creators["demoralizing shout without life time check"] = - &WarriorAiObjectContextInternal::demoralizing_shout_without_life_time_check; - creators["challenging shout"] = &WarriorAiObjectContextInternal::challenging_shout; - creators["shield wall"] = &WarriorAiObjectContextInternal::shield_wall; - creators["battle shout"] = &WarriorAiObjectContextInternal::battle_shout; - creators["battle shout taunt"] = &WarriorAiObjectContextInternal::battle_shout_taunt; - creators["thunder clap"] = &WarriorAiObjectContextInternal::thunder_clap; - creators["taunt"] = &WarriorAiObjectContextInternal::taunt; - creators["revenge"] = &WarriorAiObjectContextInternal::revenge; - creators["slam"] = &WarriorAiObjectContextInternal::slam; - creators["shield slam"] = &WarriorAiObjectContextInternal::shield_slam; - creators["disarm"] = &WarriorAiObjectContextInternal::disarm; - creators["sunder armor"] = &WarriorAiObjectContextInternal::sunder_armor; - creators["last stand"] = &WarriorAiObjectContextInternal::last_stand; - creators["shockwave on snare target"] = &WarriorAiObjectContextInternal::shockwave_on_snare_target; - creators["shockwave"] = &WarriorAiObjectContextInternal::shockwave; - creators["cleave"] = &WarriorAiObjectContextInternal::cleave; - creators["concussion blow"] = &WarriorAiObjectContextInternal::concussion_blow; - creators["shield bash on enemy healer"] = &WarriorAiObjectContextInternal::shield_bash_on_enemy_healer; - creators["berserker stance"] = &WarriorAiObjectContextInternal::berserker_stance; - creators["commanding shout"] = &WarriorAiObjectContextInternal::commanding_shout; - creators["retaliation"] = &WarriorAiObjectContextInternal::retaliation; - creators["mortal strike"] = &WarriorAiObjectContextInternal::mortal_strike; - creators["sweeping strikes"] = &WarriorAiObjectContextInternal::sweeping_strikes; - creators["intercept"] = &WarriorAiObjectContextInternal::intercept; - creators["whirlwind"] = &WarriorAiObjectContextInternal::whirlwind; - creators["pummel"] = &WarriorAiObjectContextInternal::pummel; - creators["pummel on enemy healer"] = &WarriorAiObjectContextInternal::pummel_on_enemy_healer; - creators["recklessness"] = &WarriorAiObjectContextInternal::recklessness; - creators["piercing howl"] = &WarriorAiObjectContextInternal::piercing_howl; - creators["rampage"] = &WarriorAiObjectContextInternal::rampage; - creators["intervene"] = &WarriorAiObjectContextInternal::intervene; - creators["spell reflection"] = &WarriorAiObjectContextInternal::spell_reflection; - creators["thunder clap on snare target"] = &WarriorAiObjectContextInternal::thunder_clap_on_snare_target; - creators["taunt on snare target"] = &WarriorAiObjectContextInternal::taunt_on_snare_target; - creators["intercept on enemy healer"] = &WarriorAiObjectContextInternal::intercept_on_enemy_healer; - creators["intercept on snare target"] = &WarriorAiObjectContextInternal::intercept_on_snare_target; - creators["bladestorm"] = &WarriorAiObjectContextInternal::bladestorm; - creators["heroic throw"] = &WarriorAiObjectContextInternal::heroic_throw; - creators["heroic throw on snare target"] = &WarriorAiObjectContextInternal::heroic_throw_on_snare_target; - creators["shattering throw"] = &WarriorAiObjectContextInternal::shattering_throw; - creators["vigilance"] = &WarriorAiObjectContextInternal::vigilance; - creators["enraged regeneration"] = &WarriorAiObjectContextInternal::enraged_regeneration; - } - -private: - static Action* devastate(PlayerbotAI* botAI) { return new CastDevastateAction(botAI); } - static Action* last_stand(PlayerbotAI* botAI) { return new CastLastStandAction(botAI); } - static Action* shockwave(PlayerbotAI* botAI) { return new CastShockwaveAction(botAI); } - static Action* shockwave_on_snare_target(PlayerbotAI* botAI) { return new CastShockwaveSnareAction(botAI); } - static Action* cleave(PlayerbotAI* botAI) { return new CastCleaveAction(botAI); } - static Action* concussion_blow(PlayerbotAI* botAI) { return new CastConcussionBlowAction(botAI); } - static Action* taunt(PlayerbotAI* botAI) { return new CastTauntAction(botAI); } - static Action* revenge(PlayerbotAI* botAI) { return new CastRevengeAction(botAI); } - static Action* slam(PlayerbotAI* botAI) { return new CastSlamAction(botAI); } - static Action* shield_slam(PlayerbotAI* botAI) { return new CastShieldSlamAction(botAI); } - static Action* disarm(PlayerbotAI* botAI) { return new CastDisarmAction(botAI); } - static Action* sunder_armor(PlayerbotAI* botAI) { return new CastSunderArmorAction(botAI); } - static Action* overpower(PlayerbotAI* botAI) { return new CastOverpowerAction(botAI); } - static Action* charge(PlayerbotAI* botAI) { return new CastChargeAction(botAI); } - static Action* bloodthirst(PlayerbotAI* botAI) { return new CastBloodthirstAction(botAI); } - static Action* rend(PlayerbotAI* botAI) { return new CastRendAction(botAI); } - static Action* rend_on_attacker(PlayerbotAI* botAI) { return new CastRendOnAttackerAction(botAI); } - static Action* mocking_blow(PlayerbotAI* botAI) { return new CastMockingBlowAction(botAI); } - static Action* death_wish(PlayerbotAI* botAI) { return new CastDeathWishAction(botAI); } - static Action* recklessness(PlayerbotAI* botAI) { return new CastRecklessnessAction(botAI); } - static Action* berserker_rage(PlayerbotAI* botAI) { return new CastBerserkerRageAction(botAI); } - static Action* victory_rush(PlayerbotAI* botAI) { return new CastVictoryRushAction(botAI); } - static Action* execute(PlayerbotAI* botAI) { return new CastExecuteAction(botAI); } - static Action* defensive_stance(PlayerbotAI* botAI) { return new CastDefensiveStanceAction(botAI); } - static Action* hamstring(PlayerbotAI* botAI) { return new CastHamstringAction(botAI); } - static Action* shield_bash(PlayerbotAI* botAI) { return new CastShieldBashAction(botAI); } - static Action* shield_block(PlayerbotAI* botAI) { return new CastShieldBlockAction(botAI); } - static Action* bloodrage(PlayerbotAI* botAI) { return new CastBloodrageAction(botAI); } - static Action* battle_stance(PlayerbotAI* botAI) { return new CastBattleStanceAction(botAI); } - static Action* heroic_strike(PlayerbotAI* botAI) { return new CastHeroicStrikeAction(botAI); } - static Action* intimidating_shout(PlayerbotAI* botAI) { return new CastIntimidatingShoutAction(botAI); } - static Action* demoralizing_shout(PlayerbotAI* botAI) { return new CastDemoralizingShoutAction(botAI); } - static Action* demoralizing_shout_without_life_time_check(PlayerbotAI* botAI) - { - return new CastDemoralizingShoutWithoutLifeTimeCheckAction(botAI); - } - static Action* challenging_shout(PlayerbotAI* botAI) { return new CastChallengingShoutAction(botAI); } - static Action* shield_wall(PlayerbotAI* botAI) { return new CastShieldWallAction(botAI); } - static Action* battle_shout(PlayerbotAI* botAI) { return new CastBattleShoutAction(botAI); } - static Action* battle_shout_taunt(PlayerbotAI* botAI) { return new CastBattleShoutTauntAction(botAI); } - static Action* thunder_clap(PlayerbotAI* botAI) { return new CastThunderClapAction(botAI); } - static Action* shield_bash_on_enemy_healer(PlayerbotAI* botAI) - { - return new CastShieldBashOnEnemyHealerAction(botAI); - } - static Action* intercept_on_snare_target(PlayerbotAI* botAI) { return new CastInterceptOnSnareTargetAction(botAI); } - static Action* intercept_on_enemy_healer(PlayerbotAI* botAI) { return new CastInterceptOnEnemyHealerAction(botAI); } - static Action* taunt_on_snare_target(PlayerbotAI* botAI) { return new CastTauntOnSnareTargetAction(botAI); } - static Action* thunder_clap_on_snare_target(PlayerbotAI* botAI) { return new CastThunderClapSnareAction(botAI); } - static Action* berserker_stance(PlayerbotAI* botAI) { return new CastBerserkerStanceAction(botAI); } - static Action* commanding_shout(PlayerbotAI* botAI) { return new CastCommandingShoutAction(botAI); } - static Action* retaliation(PlayerbotAI* botAI) { return new CastRetaliationAction(botAI); } - static Action* mortal_strike(PlayerbotAI* botAI) { return new CastMortalStrikeAction(botAI); } - static Action* sweeping_strikes(PlayerbotAI* botAI) { return new CastSweepingStrikesAction(botAI); } - static Action* intercept(PlayerbotAI* botAI) { return new CastInterceptAction(botAI); } - static Action* whirlwind(PlayerbotAI* botAI) { return new CastWhirlwindAction(botAI); } - static Action* pummel(PlayerbotAI* botAI) { return new CastPummelAction(botAI); } - static Action* pummel_on_enemy_healer(PlayerbotAI* botAI) { return new CastPummelOnEnemyHealerAction(botAI); } - static Action* piercing_howl(PlayerbotAI* botAI) { return new CastPiercingHowlAction(botAI); } - static Action* rampage(PlayerbotAI* botAI) { return new CastRampageAction(botAI); } - static Action* intervene(PlayerbotAI* botAI) { return new CastInterveneAction(botAI); } - static Action* spell_reflection(PlayerbotAI* botAI) { return new CastSpellReflectionAction(botAI); } - static Action* shattering_throw(PlayerbotAI* botAI) { return new CastShatteringThrowAction(botAI); } - static Action* heroic_throw_on_snare_target(PlayerbotAI* botAI) { return new CastHeroicThrowSnareAction(botAI); } - static Action* heroic_throw(PlayerbotAI* botAI) { return new CastHeroicThrowAction(botAI); } - static Action* bladestorm(PlayerbotAI* botAI) { return new CastBladestormAction(botAI); } - static Action* vigilance(PlayerbotAI* botAI) { return new CastVigilanceAction(botAI); } - static Action* enraged_regeneration(PlayerbotAI* botAI) { return new CastEnragedRegenerationAction(botAI); } -}; - SharedNamedObjectContextList WarriorAiObjectContext::sharedStrategyContexts; -SharedNamedObjectContextList WarriorAiObjectContext::sharedActionContexts; SharedNamedObjectContextList WarriorAiObjectContext::sharedTriggerContexts; SharedNamedObjectContextList WarriorAiObjectContext::sharedValueContexts; WarriorAiObjectContext::WarriorAiObjectContext(PlayerbotAI* botAI) - : AiObjectContext(botAI, sharedStrategyContexts, sharedActionContexts, sharedTriggerContexts, sharedValueContexts) + : AiObjectContext(botAI, sharedStrategyContexts, sharedTriggerContexts, sharedValueContexts) { } void WarriorAiObjectContext::BuildSharedContexts() { BuildSharedStrategyContexts(sharedStrategyContexts); - BuildSharedActionContexts(sharedActionContexts); BuildSharedTriggerContexts(sharedTriggerContexts); BuildSharedValueContexts(sharedValueContexts); } @@ -343,12 +197,6 @@ void WarriorAiObjectContext::BuildSharedStrategyContexts(SharedNamedObjectContex strategyContexts.Add(new WarriorCombatStrategyFactoryInternal()); } -void WarriorAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts) -{ - AiObjectContext::BuildSharedActionContexts(actionContexts); - actionContexts.Add(new WarriorAiObjectContextInternal()); -} - void WarriorAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts) { AiObjectContext::BuildSharedTriggerContexts(triggerContexts); diff --git a/src/Ai/Class/Warrior/WarriorAiObjectContext.h b/src/Ai/Class/Warrior/WarriorAiObjectContext.h index b4f3449b7a..098d4ee8c3 100644 --- a/src/Ai/Class/Warrior/WarriorAiObjectContext.h +++ b/src/Ai/Class/Warrior/WarriorAiObjectContext.h @@ -17,12 +17,10 @@ class WarriorAiObjectContext : public AiObjectContext static void BuildSharedContexts(); static void BuildSharedStrategyContexts(SharedNamedObjectContextList& strategyContexts); - static void BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts); static void BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts); static void BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts); static SharedNamedObjectContextList sharedStrategyContexts; - static SharedNamedObjectContextList sharedActionContexts; static SharedNamedObjectContextList sharedTriggerContexts; static SharedNamedObjectContextList sharedValueContexts; }; diff --git a/src/Ai/Dungeon/AzjolNerub/Action/AzjolNerubActions.cpp b/src/Ai/Dungeon/AzjolNerub/Action/AzjolNerubActions.cpp index e31ffd00f5..885210b4e6 100644 --- a/src/Ai/Dungeon/AzjolNerub/Action/AzjolNerubActions.cpp +++ b/src/Ai/Dungeon/AzjolNerub/Action/AzjolNerubActions.cpp @@ -1,9 +1,9 @@ +#include "AzjolNerubTriggers.h" #include "Playerbots.h" #include "AzjolNerubActions.h" -#include "AzjolNerubStrategy.h" bool AttackWebWrapAction::isUseful() { return !botAI->IsHeal(bot); } -bool AttackWebWrapAction::Execute(Event event) +bool AttackWebWrapAction::Execute(Event) { Unit* webWrap = nullptr; @@ -29,7 +29,7 @@ bool AttackWebWrapAction::Execute(Event event) } bool WatchersTargetAction::isUseful() { return !botAI->IsHeal(bot); } -bool WatchersTargetAction::Execute(Event event) +bool WatchersTargetAction::Execute(Event) { // Always prioritise web wraps Unit* currTarget = AI_VALUE(Unit*, "current target"); @@ -95,7 +95,7 @@ bool WatchersTargetAction::Execute(Event event) } bool AnubarakDodgePoundAction::isUseful() { return !AI_VALUE2(bool, "behind", "current target"); } -bool AnubarakDodgePoundAction::Execute(Event event) +bool AnubarakDodgePoundAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "anub'arak"); if (!boss) { return false; } diff --git a/src/Ai/Dungeon/AzjolNerub/Action/AzjolNerubActions.h b/src/Ai/Dungeon/AzjolNerub/Action/AzjolNerubActions.h index ef388cbdb2..7add1b61e0 100644 --- a/src/Ai/Dungeon/AzjolNerub/Action/AzjolNerubActions.h +++ b/src/Ai/Dungeon/AzjolNerub/Action/AzjolNerubActions.h @@ -4,8 +4,6 @@ #include "Action.h" #include "AttackAction.h" #include "PlayerbotAI.h" -#include "Playerbots.h" -#include "AzjolNerubTriggers.h" class AttackWebWrapAction : public AttackAction { diff --git a/src/Ai/Dungeon/AzjolNerub/AzjolNerubActionContext.h b/src/Ai/Dungeon/AzjolNerub/AzjolNerubActionContext.h deleted file mode 100644 index 6306643bab..0000000000 --- a/src/Ai/Dungeon/AzjolNerub/AzjolNerubActionContext.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _PLAYERBOT_WOTLKDUNGEONANACTIONCONTEXT_H -#define _PLAYERBOT_WOTLKDUNGEONANACTIONCONTEXT_H - -#include "Action.h" -#include "NamedObjectContext.h" -#include "AzjolNerubActions.h" - -class WotlkDungeonANActionContext : public NamedObjectContext -{ - public: - WotlkDungeonANActionContext() { - creators["attack web wrap"] = &WotlkDungeonANActionContext::attack_web_wrap; - creators["krik'thir priority"] = &WotlkDungeonANActionContext::krikthir_priority; - creators["dodge pound"] = &WotlkDungeonANActionContext::dodge_pound; - } - private: - static Action* attack_web_wrap(PlayerbotAI* ai) { return new AttackWebWrapAction(ai); } - static Action* krikthir_priority(PlayerbotAI* ai) { return new WatchersTargetAction(ai); } - static Action* dodge_pound(PlayerbotAI* ai) { return new AnubarakDodgePoundAction(ai); } -}; - -#endif diff --git a/src/Ai/Dungeon/AzjolNerub/Multiplier/AzjolNerubMultipliers.cpp b/src/Ai/Dungeon/AzjolNerub/Multiplier/AzjolNerubMultipliers.cpp index 6cd6673dc5..00f26ca0c2 100644 --- a/src/Ai/Dungeon/AzjolNerub/Multiplier/AzjolNerubMultipliers.cpp +++ b/src/Ai/Dungeon/AzjolNerub/Multiplier/AzjolNerubMultipliers.cpp @@ -1,14 +1,20 @@ +#include "ObjectGuid.h" + #include "AzjolNerubMultipliers.h" -#include "AzjolNerubActions.h" +#include "ObjectGuid.h" #include "GenericSpellActions.h" #include "ChooseTargetActions.h" #include "MovementActions.h" -#include "AzjolNerubTriggers.h" #include "Action.h" +#include "Playerbots.h" +#include "AzjolNerubTriggers.h" -float KrikthirMultiplier::GetValue(Action* action) +float KrikthirMultiplier::GetValue(Action& action) { - if (!botAI->IsDps(bot)) { return 1.0f; } + if (!botAI->IsDps(bot)) + { + return 1.0f; + } // Target is not findable from threat table using AI_VALUE2(), // therefore need to search manually for the unit name @@ -40,12 +46,12 @@ float KrikthirMultiplier::GetValue(Action* action) if (boss && watcher) { // Do not target swap - if (dynamic_cast(action)) + if (dynamic_cast(&action)) { return 0.0f; } - if (action->getThreatType() == Action::ActionThreatType::Aoe) + if (action.getThreatType() == Action::ActionThreatType::Aoe) { return 0.0f; } diff --git a/src/Ai/Dungeon/AzjolNerub/Multiplier/AzjolNerubMultipliers.h b/src/Ai/Dungeon/AzjolNerub/Multiplier/AzjolNerubMultipliers.h index bb01115e22..e0d900d272 100644 --- a/src/Ai/Dungeon/AzjolNerub/Multiplier/AzjolNerubMultipliers.h +++ b/src/Ai/Dungeon/AzjolNerub/Multiplier/AzjolNerubMultipliers.h @@ -9,7 +9,7 @@ class KrikthirMultiplier : public Multiplier KrikthirMultiplier(PlayerbotAI* ai) : Multiplier(ai, "krik'thir the gatewatcher") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; #endif diff --git a/src/Ai/Dungeon/AzjolNerub/Strategy/AzjolNerubStrategy.cpp b/src/Ai/Dungeon/AzjolNerub/Strategy/AzjolNerubStrategy.cpp index dbbb8f5bf5..03676cd0bc 100644 --- a/src/Ai/Dungeon/AzjolNerub/Strategy/AzjolNerubStrategy.cpp +++ b/src/Ai/Dungeon/AzjolNerub/Strategy/AzjolNerubStrategy.cpp @@ -1,15 +1,29 @@ #include "AzjolNerubStrategy.h" +#include "AzjolNerubActions.h" #include "AzjolNerubMultipliers.h" +#include "CreateNextAction.h" void WotlkDungeonANStrategy::InitTriggers(std::vector &triggers) { // Krik'thir the Gatewatcher // TODO: Add CC trigger while web wraps are casting? // TODO: Bring healer closer than ranged dps to avoid fixates? - triggers.push_back(new TriggerNode("krik'thir web wrap", - { NextAction("attack web wrap", ACTION_RAID + 5) })); - triggers.push_back(new TriggerNode("krik'thir watchers", - { NextAction("krik'thir priority", ACTION_RAID + 4) })); + triggers.push_back( + new TriggerNode( + "krik'thir web wrap", + { + CreateNextAction(ACTION_RAID + 5.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "krik'thir watchers", + { + CreateNextAction(ACTION_RAID + 4.0f) + } + ) + ); // Hadronox // The core AC triggers are very buggy with this boss, but default strat seems to play correctly @@ -18,10 +32,18 @@ void WotlkDungeonANStrategy::InitTriggers(std::vector &triggers) // TODO: No clear way to track these spikes. They don't seem to appear as gameobjects or triggers, // and cast time is instant so no way to check currently casting location. // May need to hook boss AI.. might be able to just heal through it for now. - // triggers.push_back(new TriggerNode("anub'arak impale", + // triggers.push_back( + // new TriggerNode( + // "anub'arak impale", // { NextAction("TODO", ACTION_MOVE + 5) })); - triggers.push_back(new TriggerNode("anub'arak pound", - { NextAction("dodge pound", ACTION_MOVE + 5) })); + triggers.push_back( + new TriggerNode( + "anub'arak pound", + { + CreateNextAction(ACTION_MOVE + 5.0f) + } + ) + ); } void WotlkDungeonANStrategy::InitMultipliers(std::vector &multipliers) diff --git a/src/Ai/Dungeon/AzjolNerub/Trigger/AzjolNerubTriggers.cpp b/src/Ai/Dungeon/AzjolNerub/Trigger/AzjolNerubTriggers.cpp index f9ef4ff953..c91c514d2a 100644 --- a/src/Ai/Dungeon/AzjolNerub/Trigger/AzjolNerubTriggers.cpp +++ b/src/Ai/Dungeon/AzjolNerub/Trigger/AzjolNerubTriggers.cpp @@ -2,6 +2,8 @@ #include "AzjolNerubTriggers.h" #include "AiObject.h" #include "AiObjectContext.h" +// Required due to excessive macro usage @TODO: Remove all macros. +#include "DungeonStrategyUtils.h" bool KrikthirWebWrapTrigger::IsActive() { diff --git a/src/Ai/Dungeon/AzjolNerub/Trigger/AzjolNerubTriggers.h b/src/Ai/Dungeon/AzjolNerub/Trigger/AzjolNerubTriggers.h index 5d12b59602..125d113e81 100644 --- a/src/Ai/Dungeon/AzjolNerub/Trigger/AzjolNerubTriggers.h +++ b/src/Ai/Dungeon/AzjolNerub/Trigger/AzjolNerubTriggers.h @@ -2,9 +2,7 @@ #define _PLAYERBOT_WOTLKDUNGEONANTRIGGERS_H #include "Trigger.h" -#include "PlayerbotAIConfig.h" #include "GenericTriggers.h" -#include "DungeonStrategyUtils.h" enum AzjolNerubIDs { @@ -44,13 +42,6 @@ class KrikthirWatchersTrigger : public Trigger bool IsActive() override; }; -// class AnubarakImpaleTrigger : public Trigger -// { -// public: -// AnubarakImpaleTrigger(PlayerbotAI* ai) : Trigger(ai, "anub'arak impale") {} -// bool IsActive() override; -// }; - class AnubarakPoundTrigger : public Trigger { public: diff --git a/src/Ai/Dungeon/CullingOfStratholme/Action/CullingOfStratholmeActions.cpp b/src/Ai/Dungeon/CullingOfStratholme/Action/CullingOfStratholmeActions.cpp index 15121f4a2e..97f27eefff 100644 --- a/src/Ai/Dungeon/CullingOfStratholme/Action/CullingOfStratholmeActions.cpp +++ b/src/Ai/Dungeon/CullingOfStratholme/Action/CullingOfStratholmeActions.cpp @@ -1,8 +1,7 @@ #include "Playerbots.h" #include "CullingOfStratholmeActions.h" -#include "CullingOfStratholmeStrategy.h" -bool ExplodeGhoulSpreadAction::Execute(Event event) +bool ExplodeGhoulSpreadAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "salramm the fleshcrafter"); if (!boss) { return false; } @@ -38,7 +37,7 @@ bool EpochStackAction::isUseful() // else return !(bot->getClass() == CLASS_HUNTER) && AI_VALUE2(float, "distance", "current target") > 5.0f; } -bool EpochStackAction::Execute(Event event) +bool EpochStackAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "chrono-lord epoch"); if (!boss) { return false; } diff --git a/src/Ai/Dungeon/CullingOfStratholme/CullingOfStratholmeActionContext.h b/src/Ai/Dungeon/CullingOfStratholme/CullingOfStratholmeActionContext.h deleted file mode 100644 index 0e12c908c8..0000000000 --- a/src/Ai/Dungeon/CullingOfStratholme/CullingOfStratholmeActionContext.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef _PLAYERBOT_WOTLKDUNGEONCOSACTIONCONTEXT_H -#define _PLAYERBOT_WOTLKDUNGEONCOSACTIONCONTEXT_H - -#include "Action.h" -#include "NamedObjectContext.h" -#include "CullingOfStratholmeActions.h" - -class WotlkDungeonCoSActionContext : public NamedObjectContext -{ - public: - WotlkDungeonCoSActionContext() { - creators["explode ghoul spread"] = &WotlkDungeonCoSActionContext::explode_ghoul_spread; - creators["epoch stack"] = &WotlkDungeonCoSActionContext::epoch_stack; - } - private: - static Action* explode_ghoul_spread(PlayerbotAI* ai) { return new ExplodeGhoulSpreadAction(ai); } - static Action* epoch_stack(PlayerbotAI* ai) { return new EpochStackAction(ai); } -}; - -#endif diff --git a/src/Ai/Dungeon/CullingOfStratholme/Multiplier/CullingOfStratholmeMultipliers.cpp b/src/Ai/Dungeon/CullingOfStratholme/Multiplier/CullingOfStratholmeMultipliers.cpp index 1fbbc6b3e8..4bb38aed5c 100644 --- a/src/Ai/Dungeon/CullingOfStratholme/Multiplier/CullingOfStratholmeMultipliers.cpp +++ b/src/Ai/Dungeon/CullingOfStratholme/Multiplier/CullingOfStratholmeMultipliers.cpp @@ -1,19 +1,27 @@ #include "CullingOfStratholmeMultipliers.h" -#include "CullingOfStratholmeActions.h" #include "GenericSpellActions.h" -#include "ChooseTargetActions.h" #include "MovementActions.h" -#include "CullingOfStratholmeTriggers.h" #include "Action.h" +#include "Playerbots.h" -float EpochMultiplier::GetValue(Action* action) +float EpochMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "chrono-lord epoch"); - if (!boss) { return 1.0f; } - if (bot->getClass() == CLASS_HUNTER) { return 1.0f; } + if (boss == nullptr) + { + return 1.0f; + } - if (dynamic_cast(action)) { return 0.0f; } + if (bot->getClass() == CLASS_HUNTER) + { + return 1.0f; + } + + if (dynamic_cast(&action)) + { + return 0.0f; + } return 1.0f; } diff --git a/src/Ai/Dungeon/CullingOfStratholme/Multiplier/CullingOfStratholmeMultipliers.h b/src/Ai/Dungeon/CullingOfStratholme/Multiplier/CullingOfStratholmeMultipliers.h index 587b0f7048..4234b0431a 100644 --- a/src/Ai/Dungeon/CullingOfStratholme/Multiplier/CullingOfStratholmeMultipliers.h +++ b/src/Ai/Dungeon/CullingOfStratholme/Multiplier/CullingOfStratholmeMultipliers.h @@ -9,7 +9,7 @@ class EpochMultiplier : public Multiplier EpochMultiplier(PlayerbotAI* ai) : Multiplier(ai, "chrono-lord epoch") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; #endif diff --git a/src/Ai/Dungeon/CullingOfStratholme/Strategy/CullingOfStratholmeStrategy.cpp b/src/Ai/Dungeon/CullingOfStratholme/Strategy/CullingOfStratholmeStrategy.cpp index 90765bded4..7c5ee7037c 100644 --- a/src/Ai/Dungeon/CullingOfStratholme/Strategy/CullingOfStratholmeStrategy.cpp +++ b/src/Ai/Dungeon/CullingOfStratholme/Strategy/CullingOfStratholmeStrategy.cpp @@ -1,4 +1,6 @@ #include "CullingOfStratholmeStrategy.h" +#include "CreateNextAction.h" +#include "CullingOfStratholmeActions.h" #include "CullingOfStratholmeMultipliers.h" void WotlkDungeonCoSStrategy::InitTriggers(std::vector &triggers) @@ -7,13 +9,25 @@ void WotlkDungeonCoSStrategy::InitTriggers(std::vector &triggers) // Can tank this in a fixed position to allow healer to LoS the stun, probably not necessary // Salramm the Fleshcrafter - triggers.push_back(new TriggerNode("explode ghoul", - { NextAction("explode ghoul spread", ACTION_MOVE + 5) })); + triggers.push_back( + new TriggerNode( + "explode ghoul", + { + CreateNextAction(ACTION_MOVE + 5.0f) + } + ) + ); // Chrono-Lord Epoch // Not sure if this actually works, I think I've seen him charge melee characters..? - triggers.push_back(new TriggerNode("epoch ranged", - { NextAction("epoch stack", ACTION_MOVE + 5) })); + triggers.push_back( + new TriggerNode( + "epoch ranged", + { + CreateNextAction(ACTION_MOVE + 5.0f) + } + ) + ); // Mal'Ganis diff --git a/src/Ai/Dungeon/DraktharonKeep/Action/DrakTharonKeepActions.cpp b/src/Ai/Dungeon/DraktharonKeep/Action/DrakTharonKeepActions.cpp index 8cbbe49c2a..59d0091c4a 100644 --- a/src/Ai/Dungeon/DraktharonKeep/Action/DrakTharonKeepActions.cpp +++ b/src/Ai/Dungeon/DraktharonKeep/Action/DrakTharonKeepActions.cpp @@ -1,8 +1,7 @@ #include "Playerbots.h" #include "DrakTharonKeepActions.h" -#include "DrakTharonKeepStrategy.h" -bool CorpseExplodeSpreadAction::Execute(Event event) +bool CorpseExplodeSpreadAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "trollgore"); if (!boss) { return false; } @@ -25,7 +24,7 @@ bool CorpseExplodeSpreadAction::Execute(Event event) return false; } -bool AvoidArcaneFieldAction::Execute(Event event) +bool AvoidArcaneFieldAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "novos the summoner"); if (!boss) { return false; } @@ -44,7 +43,7 @@ bool NovosDefaultPositionAction::isUseful() float threshold = 15.0f; return bot->GetDistance(NOVOS_PARTY_POSITION) > threshold; } -bool NovosDefaultPositionAction::Execute(Event event) +bool NovosDefaultPositionAction::Execute(Event) { float clusterDistance = 4.0f; // Only reposition if we're not killing anything @@ -59,7 +58,7 @@ bool NovosDefaultPositionAction::Execute(Event event) return false; } -bool NovosTargetPriorityAction::Execute(Event event) +bool NovosTargetPriorityAction::Execute(Event) { // TODO: This can be improved, some parts are still buggy. // But it works for now and this fight is very easy diff --git a/src/Ai/Dungeon/DraktharonKeep/DrakTharonKeepActionContext.h b/src/Ai/Dungeon/DraktharonKeep/DrakTharonKeepActionContext.h deleted file mode 100644 index 1435eedbe2..0000000000 --- a/src/Ai/Dungeon/DraktharonKeep/DrakTharonKeepActionContext.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef _PLAYERBOT_WOTLKDUNGEONDTKACTIONCONTEXT_H -#define _PLAYERBOT_WOTLKDUNGEONDTKACTIONCONTEXT_H - -#include "Action.h" -#include "NamedObjectContext.h" -#include "DrakTharonKeepActions.h" - -class WotlkDungeonDTKActionContext : public NamedObjectContext -{ - public: - WotlkDungeonDTKActionContext() { - creators["corpse explode spread"] = &WotlkDungeonDTKActionContext::corpse_explode_spread; - creators["avoid arcane field"] = &WotlkDungeonDTKActionContext::avoid_arcane_field; - creators["novos positioning"] = &WotlkDungeonDTKActionContext::novos_positioning; - creators["novos target priority"] = &WotlkDungeonDTKActionContext::novos_target_priority; - creators["slaying strike"] = &WotlkDungeonDTKActionContext::slaying_strike; - creators["tharonja taunt"] = &WotlkDungeonDTKActionContext::taunt; - creators["bone armor"] = &WotlkDungeonDTKActionContext::bone_armor; - creators["touch of life"] = &WotlkDungeonDTKActionContext::touch_of_life; - } - private: - static Action* corpse_explode_spread(PlayerbotAI* ai) { return new CorpseExplodeSpreadAction(ai); } - static Action* avoid_arcane_field(PlayerbotAI* ai) { return new AvoidArcaneFieldAction(ai); } - static Action* novos_positioning(PlayerbotAI* ai) { return new NovosDefaultPositionAction(ai); } - static Action* novos_target_priority(PlayerbotAI* ai) { return new NovosTargetPriorityAction(ai); } - static Action* slaying_strike(PlayerbotAI* ai) { return new CastSlayingStrikeAction(ai); } - static Action* taunt(PlayerbotAI* ai) { return new CastTauntAction(ai); } - static Action* bone_armor(PlayerbotAI* ai) { return new CastBoneArmorAction(ai); } - static Action* touch_of_life(PlayerbotAI* ai) { return new CastTouchOfLifeAction(ai); } -}; - -#endif diff --git a/src/Ai/Dungeon/DraktharonKeep/Multiplier/DrakTharonKeepMultipliers.cpp b/src/Ai/Dungeon/DraktharonKeep/Multiplier/DrakTharonKeepMultipliers.cpp index 8fd119dc4e..1085d9be83 100644 --- a/src/Ai/Dungeon/DraktharonKeep/Multiplier/DrakTharonKeepMultipliers.cpp +++ b/src/Ai/Dungeon/DraktharonKeep/Multiplier/DrakTharonKeepMultipliers.cpp @@ -6,15 +6,15 @@ #include "DrakTharonKeepTriggers.h" #include "Action.h" -float NovosMultiplier::GetValue(Action* action) +float NovosMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "novos the summoner"); if (!boss) { return 1.0f; } if (boss->FindCurrentSpellBySpellId(SPELL_ARCANE_FIELD) && bot->GetTarget()) { - if (dynamic_cast(action) - || dynamic_cast(action)) + if (dynamic_cast(&action) + || dynamic_cast(&action)) { return 0.0f; } @@ -22,22 +22,22 @@ float NovosMultiplier::GetValue(Action* action) return 1.0f; } -float TharonjaMultiplier::GetValue(Action* action) +float TharonjaMultiplier::GetValue(Action& action) { if (!bot->HasAura(SPELL_GIFT_OF_THARONJA)) { return 1.0f; } // Suppress all skills that are not enabled in skeleton form. // Still allow non-ability actions such as movement - if (dynamic_cast(action) - && !dynamic_cast(action) - && !dynamic_cast(action) - && !dynamic_cast(action) - && !dynamic_cast(action)) + if (dynamic_cast(&action) + && !dynamic_cast(&action) + && !dynamic_cast(&action) + && !dynamic_cast(&action) + && !dynamic_cast(&action)) { return 0.0f; } // Also suppress FleeAction to prevent ranged characters from avoiding melee range - if (dynamic_cast(action)) + if (dynamic_cast(&action)) { return 0.0f; } @@ -45,7 +45,7 @@ float TharonjaMultiplier::GetValue(Action* action) // Tanks should only taunt, no slaying strike if (botAI->IsTank(bot)) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) { return 0.0f; } @@ -53,7 +53,7 @@ float TharonjaMultiplier::GetValue(Action* action) // Dps & healer should not taunt else { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) { return 0.0f; } diff --git a/src/Ai/Dungeon/DraktharonKeep/Multiplier/DrakTharonKeepMultipliers.h b/src/Ai/Dungeon/DraktharonKeep/Multiplier/DrakTharonKeepMultipliers.h index c8f3c81350..bfe99be38a 100644 --- a/src/Ai/Dungeon/DraktharonKeep/Multiplier/DrakTharonKeepMultipliers.h +++ b/src/Ai/Dungeon/DraktharonKeep/Multiplier/DrakTharonKeepMultipliers.h @@ -9,7 +9,7 @@ class NovosMultiplier : public Multiplier NovosMultiplier(PlayerbotAI* ai) : Multiplier(ai, "novos the summoner") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class TharonjaMultiplier : public Multiplier @@ -18,7 +18,7 @@ class TharonjaMultiplier : public Multiplier TharonjaMultiplier(PlayerbotAI* ai) : Multiplier(ai, "the prophet tharon'ja") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; #endif diff --git a/src/Ai/Dungeon/DraktharonKeep/Strategy/DrakTharonKeepStrategy.cpp b/src/Ai/Dungeon/DraktharonKeep/Strategy/DrakTharonKeepStrategy.cpp index 791a0ea71e..309744bfc7 100644 --- a/src/Ai/Dungeon/DraktharonKeep/Strategy/DrakTharonKeepStrategy.cpp +++ b/src/Ai/Dungeon/DraktharonKeep/Strategy/DrakTharonKeepStrategy.cpp @@ -1,36 +1,93 @@ #include "DrakTharonKeepStrategy.h" +#include "CreateNextAction.h" +#include "DrakTharonKeepActions.h" #include "DrakTharonKeepMultipliers.h" +#include "ReachTargetActions.h" void WotlkDungeonDTKStrategy::InitTriggers(std::vector &triggers) { // Trollgore - triggers.push_back(new TriggerNode("corpse explode", - { NextAction("corpse explode spread", ACTION_MOVE + 5) })); + triggers.push_back( + new TriggerNode( + "corpse explode", + { + CreateNextAction(ACTION_MOVE + 5.0f) + } + ) + ); // Novos the Summoner // TODO: Can be improved - it's a pretty easy fight but complex to program, revisit if needed - triggers.push_back(new TriggerNode("arcane field", - { NextAction("avoid arcane field", ACTION_MOVE + 5) })); - triggers.push_back(new TriggerNode("arcane field", - { NextAction("novos positioning", ACTION_MOVE + 4) })); - triggers.push_back(new TriggerNode("arcane field", - { NextAction("novos target priority", ACTION_NORMAL + 1) })); + triggers.push_back( + new TriggerNode( + "arcane field", + { + CreateNextAction(ACTION_MOVE + 5.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "arcane field", + { + CreateNextAction(ACTION_MOVE + 4.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "arcane field", + { + CreateNextAction(ACTION_NORMAL + 1.0f) + } + ) + ); // King Dred // TODO: Fear ward / tremor totem, or general anti-fear strat development //The Prophet Tharon'ja - triggers.push_back(new TriggerNode("gift of tharon'ja", - { NextAction("touch of life", ACTION_NORMAL + 5) })); - triggers.push_back(new TriggerNode("gift of tharon'ja", - { NextAction("bone armor", ACTION_NORMAL + 4) })); + triggers.push_back( + new TriggerNode( + "gift of tharon'ja", + { + CreateNextAction(ACTION_NORMAL + 5.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "gift of tharon'ja", + { + CreateNextAction(ACTION_NORMAL + 4.0f) + } + ) + ); // Run ranged chars (who would normally stand at range) into melee, to dps in skeleton form - triggers.push_back(new TriggerNode("tharon'ja out of melee", - { NextAction("reach melee", ACTION_NORMAL + 3) })); - triggers.push_back(new TriggerNode("gift of tharon'ja", - { NextAction("taunt", ACTION_NORMAL + 2) })); - triggers.push_back(new TriggerNode("gift of tharon'ja", - { NextAction("slaying strike", ACTION_NORMAL + 2) })); + triggers.push_back( + new TriggerNode( + "tharon'ja out of melee", + { + CreateNextAction(ACTION_NORMAL + 3.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "gift of tharon'ja", + { + CreateNextAction(ACTION_NORMAL + 2.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "gift of tharon'ja", + { + CreateNextAction(ACTION_NORMAL + 2.0f) + } + ) + ); } void WotlkDungeonDTKStrategy::InitMultipliers(std::vector &multipliers) diff --git a/src/Ai/Dungeon/DungeonStrategyUtils.h b/src/Ai/Dungeon/DungeonStrategyUtils.h index 3f67f4b4d4..0d871eb5bd 100644 --- a/src/Ai/Dungeon/DungeonStrategyUtils.h +++ b/src/Ai/Dungeon/DungeonStrategyUtils.h @@ -1,6 +1,8 @@ #ifndef _PLAYERBOT_DUNGEONUTILS_H #define _PLAYERBOT_DUNGEONUTILS_H +#include "Player.h" + template inline const T& DUNGEON_MODE(Player* bot, const T& normal5, const T& heroic10) { diff --git a/src/Ai/Dungeon/ForgeOfSouls/Action/ForgeOfSoulsActions.cpp b/src/Ai/Dungeon/ForgeOfSouls/Action/ForgeOfSoulsActions.cpp index e72fe98d5f..a22e5403db 100644 --- a/src/Ai/Dungeon/ForgeOfSouls/Action/ForgeOfSoulsActions.cpp +++ b/src/Ai/Dungeon/ForgeOfSouls/Action/ForgeOfSoulsActions.cpp @@ -1,9 +1,7 @@ #include "Playerbots.h" #include "ForgeOfSoulsActions.h" -#include "ForgeOfSoulsStrategy.h" -#include "SharedDefines.h" -bool MoveFromBronjahmAction::Execute(Event event) +bool MoveFromBronjahmAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "bronjahm"); if (!boss) @@ -17,13 +15,11 @@ bool MoveFromBronjahmAction::Execute(Event event) return false; } -bool AttackCorruptedSoulFragmentAction::Execute(Event event) +bool AttackCorruptedSoulFragmentAction::Execute(Event) { - Unit* currentTarget = AI_VALUE(Unit*, "current target"); GuidVector targets = AI_VALUE(GuidVector, "possible targets"); // If no valid skull target, search for corrupted soul fragment - Unit* empoweredPrince = nullptr; for (auto i = targets.begin(); i != targets.end(); ++i) { Unit* unit = botAI->GetUnit(*i); @@ -32,8 +28,6 @@ bool AttackCorruptedSoulFragmentAction::Execute(Event event) if (unit->GetEntry() == NPC_CORRUPTED_SOUL_FRAGMENT) { - empoweredPrince = unit; - // Mark corrupted soul fragment with skull if in group and not already marked if (Group* group = bot->GetGroup()) { @@ -51,7 +45,7 @@ bool AttackCorruptedSoulFragmentAction::Execute(Event event) return false; } -bool BronjahmGroupPositionAction::Execute(Event event) +bool BronjahmGroupPositionAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "bronjahm"); if (!boss) @@ -141,7 +135,7 @@ bool BronjahmGroupPositionAction::Execute(Event event) bool BronjahmGroupPositionAction::isUseful() { return true; } -bool DevourerOfSoulsAction::Execute(Event event) +bool DevourerOfSoulsAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "devourer of souls"); if (!boss) diff --git a/src/Ai/Dungeon/ForgeOfSouls/ForgeOfSoulsActionContext.h b/src/Ai/Dungeon/ForgeOfSouls/ForgeOfSoulsActionContext.h deleted file mode 100644 index 4797b69c13..0000000000 --- a/src/Ai/Dungeon/ForgeOfSouls/ForgeOfSoulsActionContext.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef _PLAYERBOT_WOTLKDUNGEONFOSACTIONCONTEXT_H -#define _PLAYERBOT_WOTLKDUNGEONFOSACTIONCONTEXT_H - -#include "Action.h" -#include "NamedObjectContext.h" -#include "ForgeOfSoulsActions.h" - -class WotlkDungeonFoSActionContext : public NamedObjectContext -{ - public: - WotlkDungeonFoSActionContext() - { - creators["move from bronjahm"] = &WotlkDungeonFoSActionContext::move_from_bronjahm; - creators["attack corrupted soul fragment"] = &WotlkDungeonFoSActionContext::attack_corrupted_soul_fragment; - creators["bronjahm group position"] = &WotlkDungeonFoSActionContext::bronjahm_group_position; - creators["devourer of souls"] = &WotlkDungeonFoSActionContext::devourer_of_souls; - } - private: - static Action* move_from_bronjahm(PlayerbotAI* ai) { return new MoveFromBronjahmAction(ai); } - static Action* attack_corrupted_soul_fragment(PlayerbotAI* ai) { return new AttackCorruptedSoulFragmentAction(ai); } - static Action* bronjahm_group_position(PlayerbotAI* ai) { return new BronjahmGroupPositionAction(ai); } - static Action* devourer_of_souls(PlayerbotAI* ai) { return new DevourerOfSoulsAction(ai); } -}; - -#endif diff --git a/src/Ai/Dungeon/ForgeOfSouls/Multiplier/ForgeOfSoulsMultipliers.cpp b/src/Ai/Dungeon/ForgeOfSouls/Multiplier/ForgeOfSoulsMultipliers.cpp index 7873e7c1d1..a8cd83f8f4 100644 --- a/src/Ai/Dungeon/ForgeOfSouls/Multiplier/ForgeOfSoulsMultipliers.cpp +++ b/src/Ai/Dungeon/ForgeOfSouls/Multiplier/ForgeOfSoulsMultipliers.cpp @@ -6,17 +6,17 @@ #include "ForgeOfSoulsTriggers.h" #include "ForgeOfSoulsActions.h" -float BronjahmMultiplier::GetValue(Action* action) { +float BronjahmMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit *, "find target", "bronjahm"); if (!boss) return 1.0f; - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 0.0f; if (bot->HasAura(SPELL_CORRUPT_SOUL)) { - if (dynamic_cast(action) && !dynamic_cast(action)) + if (dynamic_cast(&action) && !dynamic_cast(&action)) { return 0.0f; } @@ -24,7 +24,7 @@ float BronjahmMultiplier::GetValue(Action* action) { return 1.0f; } -float AttackFragmentMultiplier::GetValue(Action* action) +float AttackFragmentMultiplier::GetValue(Action& action) { Unit* fragment = nullptr; @@ -41,7 +41,7 @@ float AttackFragmentMultiplier::GetValue(Action* action) } } - if (fragment && botAI->IsDps(bot) && dynamic_cast(action)) + if (fragment && botAI->IsDps(bot) && dynamic_cast(&action)) return 0.0f; return 1.0f; diff --git a/src/Ai/Dungeon/ForgeOfSouls/Multiplier/ForgeOfSoulsMultipliers.h b/src/Ai/Dungeon/ForgeOfSouls/Multiplier/ForgeOfSoulsMultipliers.h index 1c89bb096b..3da8403db5 100644 --- a/src/Ai/Dungeon/ForgeOfSouls/Multiplier/ForgeOfSoulsMultipliers.h +++ b/src/Ai/Dungeon/ForgeOfSouls/Multiplier/ForgeOfSoulsMultipliers.h @@ -9,7 +9,7 @@ class BronjahmMultiplier : public Multiplier BronjahmMultiplier(PlayerbotAI* ai) : Multiplier(ai, "bronjahm") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class AttackFragmentMultiplier : public Multiplier @@ -17,7 +17,7 @@ class AttackFragmentMultiplier : public Multiplier public: AttackFragmentMultiplier(PlayerbotAI* ai) : Multiplier(ai, "attack fragment") { } - float GetValue(Action* action) override; + float GetValue(Action& action) override; }; #endif diff --git a/src/Ai/Dungeon/ForgeOfSouls/Strategy/ForgeOfSoulsStrategy.cpp b/src/Ai/Dungeon/ForgeOfSouls/Strategy/ForgeOfSoulsStrategy.cpp index 9ff3219829..bb307ad011 100644 --- a/src/Ai/Dungeon/ForgeOfSouls/Strategy/ForgeOfSoulsStrategy.cpp +++ b/src/Ai/Dungeon/ForgeOfSouls/Strategy/ForgeOfSoulsStrategy.cpp @@ -1,16 +1,42 @@ #include "ForgeOfSoulsStrategy.h" +#include "CreateNextAction.h" +#include "ForgeOfSoulsActions.h" #include "ForgeOfSoulsMultipliers.h" void WotlkDungeonFoSStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("move from bronjahm", - { NextAction("move from bronjahm", ACTION_MOVE + 5) })); - triggers.push_back(new TriggerNode("switch to soul fragment", - { NextAction("attack corrupted soul fragment", ACTION_RAID + 2) })); - triggers.push_back(new TriggerNode("bronjahm position", - { NextAction("bronjahm group position", ACTION_RAID + 1) })); - triggers.push_back(new TriggerNode("devourer of souls", - { NextAction("devourer of souls", ACTION_RAID + 1) })); + triggers.push_back( + new TriggerNode( + "move from bronjahm", + { + CreateNextAction(ACTION_MOVE + 5.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "switch to soul fragment", + { + CreateNextAction(ACTION_RAID + 2.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "bronjahm position", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "devourer of souls", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); } void WotlkDungeonFoSStrategy::InitMultipliers(std::vector& multipliers) diff --git a/src/Ai/Dungeon/Gundrak/Action/GundrakActions.cpp b/src/Ai/Dungeon/Gundrak/Action/GundrakActions.cpp index 4e9910993d..e9ff00ef68 100644 --- a/src/Ai/Dungeon/Gundrak/Action/GundrakActions.cpp +++ b/src/Ai/Dungeon/Gundrak/Action/GundrakActions.cpp @@ -1,8 +1,7 @@ #include "Playerbots.h" #include "GundrakActions.h" -#include "GundrakStrategy.h" -bool AvoidPoisonNovaAction::Execute(Event event) +bool AvoidPoisonNovaAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "slad'ran"); if (!boss) { return false; } @@ -19,12 +18,11 @@ bool AvoidPoisonNovaAction::Execute(Event event) return false; } -bool AttackSnakeWrapAction::Execute(Event event) +bool AttackSnakeWrapAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "slad'ran"); if (!boss) { return false; } - Unit* snakeWrap = nullptr; // Target is not findable from threat table using AI_VALUE2(), // therefore need to search manually for the unit name GuidVector targets = AI_VALUE(GuidVector, "possible targets no los"); @@ -45,7 +43,7 @@ bool AttackSnakeWrapAction::Execute(Event event) return false; } -bool AvoidWhirlingSlashAction::Execute(Event event) +bool AvoidWhirlingSlashAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "gal'darah"); if (!boss) { return false; } diff --git a/src/Ai/Dungeon/Gundrak/GundrakActionContext.h b/src/Ai/Dungeon/Gundrak/GundrakActionContext.h deleted file mode 100644 index 746fed3946..0000000000 --- a/src/Ai/Dungeon/Gundrak/GundrakActionContext.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _PLAYERBOT_WOTLKDUNGEONGDACTIONCONTEXT_H -#define _PLAYERBOT_WOTLKDUNGEONGDACTIONCONTEXT_H - -#include "Action.h" -#include "NamedObjectContext.h" -#include "GundrakActions.h" - -class WotlkDungeonGDActionContext : public NamedObjectContext -{ - public: - WotlkDungeonGDActionContext() { - creators["avoid poison nova"] = &WotlkDungeonGDActionContext::avoid_poison_nova; - creators["attack snake wrap"] = &WotlkDungeonGDActionContext::attack_snake_wrap; - creators["avoid whirling slash"] = &WotlkDungeonGDActionContext::avoid_whirling_slash; - } - private: - static Action* avoid_poison_nova(PlayerbotAI* ai) { return new AvoidPoisonNovaAction(ai); } - static Action* attack_snake_wrap(PlayerbotAI* ai) { return new AttackSnakeWrapAction(ai); } - static Action* avoid_whirling_slash(PlayerbotAI* ai) { return new AvoidWhirlingSlashAction(ai); } -}; - -#endif diff --git a/src/Ai/Dungeon/Gundrak/Multiplier/GundrakMultipliers.cpp b/src/Ai/Dungeon/Gundrak/Multiplier/GundrakMultipliers.cpp index 2d44042551..80f204eaf9 100644 --- a/src/Ai/Dungeon/Gundrak/Multiplier/GundrakMultipliers.cpp +++ b/src/Ai/Dungeon/Gundrak/Multiplier/GundrakMultipliers.cpp @@ -5,15 +5,17 @@ #include "MovementActions.h" #include "GundrakTriggers.h" #include "Action.h" +// Required due to excessive use of macros +#include "DungeonStrategyUtils.h" -float SladranMultiplier::GetValue(Action* action) +float SladranMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "slad'ran"); if (!boss) { return 1.0f; } if (boss->FindCurrentSpellBySpellId(SPELL_POISON_NOVA)) { - if (dynamic_cast(action) && !dynamic_cast(action)) + if (dynamic_cast(&action) && !dynamic_cast(&action)) { return 0.0f; } @@ -21,7 +23,7 @@ float SladranMultiplier::GetValue(Action* action) if (!botAI->IsDps(bot)) { return 1.0f; } - if (action->getThreatType() == Action::ActionThreatType::Aoe) + if (action.getThreatType() == Action::ActionThreatType::Aoe) { return 0.0f; } @@ -38,7 +40,7 @@ float SladranMultiplier::GetValue(Action* action) } } // Prevent auto-target acquisition during snake wraps - if (snakeWrap && dynamic_cast(action)) + if (snakeWrap && dynamic_cast(&action)) { return 0.0f; } @@ -46,14 +48,14 @@ float SladranMultiplier::GetValue(Action* action) return 1.0f; } -float GaldarahMultiplier::GetValue(Action* action) +float GaldarahMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "gal'darah"); if (!boss) { return 1.0f; } if (boss->HasAura(SPELL_WHIRLING_SLASH)) { - if (dynamic_cast(action) && !dynamic_cast(action)) + if (dynamic_cast(&action) && !dynamic_cast(&action)) { return 0.0f; } diff --git a/src/Ai/Dungeon/Gundrak/Multiplier/GundrakMultipliers.h b/src/Ai/Dungeon/Gundrak/Multiplier/GundrakMultipliers.h index e1ceb0b629..5874ae5824 100644 --- a/src/Ai/Dungeon/Gundrak/Multiplier/GundrakMultipliers.h +++ b/src/Ai/Dungeon/Gundrak/Multiplier/GundrakMultipliers.h @@ -9,7 +9,7 @@ class SladranMultiplier : public Multiplier SladranMultiplier(PlayerbotAI* ai) : Multiplier(ai, "slad'ran") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class GaldarahMultiplier : public Multiplier @@ -18,7 +18,7 @@ class GaldarahMultiplier : public Multiplier GaldarahMultiplier(PlayerbotAI* ai) : Multiplier(ai, "gal'darah") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; #endif diff --git a/src/Ai/Dungeon/Gundrak/Strategy/GundrakStrategy.cpp b/src/Ai/Dungeon/Gundrak/Strategy/GundrakStrategy.cpp index c8244e2ca9..3a8e6455ea 100644 --- a/src/Ai/Dungeon/Gundrak/Strategy/GundrakStrategy.cpp +++ b/src/Ai/Dungeon/Gundrak/Strategy/GundrakStrategy.cpp @@ -1,4 +1,6 @@ #include "GundrakStrategy.h" +#include "CreateNextAction.h" +#include "GundrakActions.h" #include "GundrakMultipliers.h" void WotlkDungeonGDStrategy::InitTriggers(std::vector &triggers) @@ -10,14 +12,32 @@ void WotlkDungeonGDStrategy::InitTriggers(std::vector &triggers) // Slad'ran // TODO: Might need to add target priority for heroic on the snakes or to burn down boss. // Will re-test in heroic, decent dps groups should be able to blast him down with no funky strats. - triggers.push_back(new TriggerNode("poison nova", - { NextAction("avoid poison nova", ACTION_RAID + 5) })); - triggers.push_back(new TriggerNode("snake wrap", - { NextAction("attack snake wrap", ACTION_RAID + 4) })); + triggers.push_back( + new TriggerNode( + "poison nova", + { + CreateNextAction(ACTION_RAID + 5.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "snake wrap", + { + CreateNextAction(ACTION_RAID + 4.0f) + } + ) + ); // Gal'darah - triggers.push_back(new TriggerNode("whirling slash", - { NextAction("avoid whirling slash", ACTION_RAID + 5) })); + triggers.push_back( + new TriggerNode( + "whirling slash", + { + CreateNextAction(ACTION_RAID + 5.0f) + } + ) + ); // Eck the Ferocious (Heroic only) } diff --git a/src/Ai/Dungeon/Gundrak/Trigger/GundrakTriggers.cpp b/src/Ai/Dungeon/Gundrak/Trigger/GundrakTriggers.cpp index b3e98cfdb6..55327b95a0 100644 --- a/src/Ai/Dungeon/Gundrak/Trigger/GundrakTriggers.cpp +++ b/src/Ai/Dungeon/Gundrak/Trigger/GundrakTriggers.cpp @@ -2,6 +2,8 @@ #include "GundrakTriggers.h" #include "AiObject.h" #include "AiObjectContext.h" +// Required due to excessive use of macros +#include "DungeonStrategyUtils.h" bool SladranPoisonNovaTrigger::IsActive() { diff --git a/src/Ai/Dungeon/Gundrak/Trigger/GundrakTriggers.h b/src/Ai/Dungeon/Gundrak/Trigger/GundrakTriggers.h index e8a5c25f15..fd2847bb34 100644 --- a/src/Ai/Dungeon/Gundrak/Trigger/GundrakTriggers.h +++ b/src/Ai/Dungeon/Gundrak/Trigger/GundrakTriggers.h @@ -2,9 +2,7 @@ #define _PLAYERBOT_WOTLKDUNGEONGDTRIGGERS_H #include "Trigger.h" -#include "PlayerbotAIConfig.h" #include "GenericTriggers.h" -#include "DungeonStrategyUtils.h" enum GundrakIDs { diff --git a/src/Ai/Dungeon/HallsOfLightning/Action/HallsOfLightningActions.cpp b/src/Ai/Dungeon/HallsOfLightning/Action/HallsOfLightningActions.cpp index 047e0aee13..4613492ae8 100644 --- a/src/Ai/Dungeon/HallsOfLightning/Action/HallsOfLightningActions.cpp +++ b/src/Ai/Dungeon/HallsOfLightning/Action/HallsOfLightningActions.cpp @@ -1,8 +1,7 @@ #include "Playerbots.h" #include "HallsOfLightningActions.h" -#include "HallsOfLightningStrategy.h" -bool BjarngrimTargetAction::Execute(Event event) +bool BjarngrimTargetAction::Execute(Event) { Unit* target = nullptr; @@ -35,7 +34,7 @@ bool BjarngrimTargetAction::Execute(Event event) return Attack(target); } -bool AvoidWhirlwindAction::Execute(Event event) +bool AvoidWhirlwindAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "general bjarngrim"); if (!boss) { return false; } @@ -52,7 +51,7 @@ bool AvoidWhirlwindAction::Execute(Event event) return false; } -bool VolkhanTargetAction::Execute(Event event) +bool VolkhanTargetAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "volkhan"); if (!boss || AI_VALUE(Unit*, "current target") == boss) @@ -63,7 +62,7 @@ bool VolkhanTargetAction::Execute(Event event) return Attack(boss); } -bool StaticOverloadSpreadAction::Execute(Event event) +bool StaticOverloadSpreadAction::Execute(Event) { float radius = 8.0f; float distanceExtra = 2.0f; @@ -86,7 +85,7 @@ bool StaticOverloadSpreadAction::Execute(Event event) return false; } -bool BallLightningSpreadAction::Execute(Event event) +bool BallLightningSpreadAction::Execute(Event) { float radius = 6.0f; float distanceExtra = 1.0f; @@ -108,14 +107,14 @@ bool BallLightningSpreadAction::Execute(Event event) } bool IonarTankPositionAction::isUseful() { return bot->GetExactDist2d(IONAR_TANK_POSITION) > 10.0f; } -bool IonarTankPositionAction::Execute(Event event) +bool IonarTankPositionAction::Execute(Event) { return MoveTo(bot->GetMapId(), IONAR_TANK_POSITION.GetPositionX(), IONAR_TANK_POSITION.GetPositionY(), IONAR_TANK_POSITION.GetPositionZ(), false, false, false, true, MovementPriority::MOVEMENT_COMBAT); } bool DispersePositionAction::isUseful() { return bot->GetExactDist2d(DISPERSE_POSITION) > 8.0f; } -bool DispersePositionAction::Execute(Event event) +bool DispersePositionAction::Execute(Event) { return MoveTo(bot->GetMapId(), DISPERSE_POSITION.GetPositionX(), DISPERSE_POSITION.GetPositionY(), DISPERSE_POSITION.GetPositionZ(), false, false, false, true, MovementPriority::MOVEMENT_COMBAT); @@ -133,7 +132,7 @@ bool LokenStackAction::isUseful() // else return AI_VALUE2(float, "distance", "current target") > 2.0f; } -bool LokenStackAction::Execute(Event event) +bool LokenStackAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "loken"); if (!boss) { return false; } @@ -152,7 +151,7 @@ bool LokenStackAction::Execute(Event event) return false; } -bool AvoidLightningNovaAction::Execute(Event event) +bool AvoidLightningNovaAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "loken"); if (!boss) { return false; } diff --git a/src/Ai/Dungeon/HallsOfLightning/HallsOfLightningActionContext.h b/src/Ai/Dungeon/HallsOfLightning/HallsOfLightningActionContext.h deleted file mode 100644 index c3073d4922..0000000000 --- a/src/Ai/Dungeon/HallsOfLightning/HallsOfLightningActionContext.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef _PLAYERBOT_WOTLKDUNGEONHOLACTIONCONTEXT_H -#define _PLAYERBOT_WOTLKDUNGEONHOLACTIONCONTEXT_H - -#include "Action.h" -#include "NamedObjectContext.h" -#include "HallsOfLightningActions.h" - -class WotlkDungeonHoLActionContext : public NamedObjectContext -{ - public: - WotlkDungeonHoLActionContext() { - creators["bjarngrim target"] = &WotlkDungeonHoLActionContext::bjarngrim_target; - creators["avoid whirlwind"] = &WotlkDungeonHoLActionContext::avoid_whirlwind; - creators["volkhan target"] = &WotlkDungeonHoLActionContext::volkhan_target; - creators["static overload spread"] = &WotlkDungeonHoLActionContext::static_overload_spread; - creators["ball lightning spread"] = &WotlkDungeonHoLActionContext::ball_lightning_spread; - creators["ionar tank position"] = &WotlkDungeonHoLActionContext::ionar_tank_position; - creators["disperse position"] = &WotlkDungeonHoLActionContext::disperse_position; - creators["loken stack"] = &WotlkDungeonHoLActionContext::loken_stack; - creators["avoid lightning nova"] = &WotlkDungeonHoLActionContext::avoid_lightning_nova; - } - private: - static Action* bjarngrim_target(PlayerbotAI* ai) { return new BjarngrimTargetAction(ai); } - static Action* avoid_whirlwind(PlayerbotAI* ai) { return new AvoidWhirlwindAction(ai); } - static Action* volkhan_target(PlayerbotAI* ai) { return new VolkhanTargetAction(ai); } - static Action* static_overload_spread(PlayerbotAI* ai) { return new StaticOverloadSpreadAction(ai); } - static Action* ball_lightning_spread(PlayerbotAI* ai) { return new BallLightningSpreadAction(ai); } - static Action* ionar_tank_position(PlayerbotAI* ai) { return new IonarTankPositionAction(ai); } - static Action* disperse_position(PlayerbotAI* ai) { return new DispersePositionAction(ai); } - static Action* loken_stack(PlayerbotAI* ai) { return new LokenStackAction(ai); } - static Action* avoid_lightning_nova(PlayerbotAI* ai) { return new AvoidLightningNovaAction(ai); } -}; - -#endif diff --git a/src/Ai/Dungeon/HallsOfLightning/Multiplier/HallsOfLightningMultipliers.cpp b/src/Ai/Dungeon/HallsOfLightning/Multiplier/HallsOfLightningMultipliers.cpp index 3bf9fcfd63..a81441035c 100644 --- a/src/Ai/Dungeon/HallsOfLightning/Multiplier/HallsOfLightningMultipliers.cpp +++ b/src/Ai/Dungeon/HallsOfLightning/Multiplier/HallsOfLightningMultipliers.cpp @@ -8,14 +8,14 @@ #include "WarriorActions.h" -float BjarngrimMultiplier::GetValue(Action* action) +float BjarngrimMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "general bjarngrim"); if (!boss || botAI->IsHeal(bot)) { return 1.0f; } if (boss->HasUnitState(UNIT_STATE_CASTING) && boss->FindCurrentSpellBySpellId(SPELL_WHIRLWIND_BJARNGRIM)) { - if (dynamic_cast(action) && !dynamic_cast(action)) + if (dynamic_cast(&action) && !dynamic_cast(&action)) { return 0.0f; } @@ -39,12 +39,12 @@ float BjarngrimMultiplier::GetValue(Action* action) if (!boss_add || botAI->IsTank(bot)) { return 1.0f; } - if (dynamic_cast(action)) + if (dynamic_cast(&action)) { return 0.0f; } - if (action->getThreatType() == Action::ActionThreatType::Aoe) + if (action.getThreatType() == Action::ActionThreatType::Aoe) { return 0.0f; } @@ -52,17 +52,17 @@ float BjarngrimMultiplier::GetValue(Action* action) return 1.0f; } -float VolkhanMultiplier::GetValue(Action* action) +float VolkhanMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "volkhan"); if (!boss || botAI->IsTank(bot) || botAI->IsHeal(bot)) { return 1.0f; } - if (dynamic_cast(action)) + if (dynamic_cast(&action)) { return 0.0f; } - if (action->getThreatType() == Action::ActionThreatType::Aoe) + if (action.getThreatType() == Action::ActionThreatType::Aoe) { return 0.0f; } @@ -70,7 +70,7 @@ float VolkhanMultiplier::GetValue(Action* action) return 1.0f; } -float IonarMultiplier::GetValue(Action* action) +float IonarMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "ionar"); if (!boss) { return 1.0f; } @@ -79,9 +79,9 @@ float IonarMultiplier::GetValue(Action* action) if (!bot->CanSeeOrDetect(boss)) { // Block MovementActions except for specific exceptions. - if (dynamic_cast(action) - && !dynamic_cast(action) - && !dynamic_cast(action)) + if (dynamic_cast(&action) + && !dynamic_cast(&action) + && !dynamic_cast(&action)) { return 0.0f; } @@ -90,32 +90,32 @@ float IonarMultiplier::GetValue(Action* action) if (boss->FindCurrentSpellBySpellId(SPELL_DISPERSE)) { // Explicitly block the CastChargeAction during dispersal. - if (dynamic_cast(action)) + if (dynamic_cast(&action)) { return 0.0f; } } return 1.0f; } -float LokenMultiplier::GetValue(Action* action) +float LokenMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "loken"); if (!boss) { return 1.0f; } // Prevent FleeAction from being executed. - if (dynamic_cast(action)) { return 0.0f; } + if (dynamic_cast(&action)) { return 0.0f; } // Prevent MovementActions during Lightning Nova unless it's AvoidLightningNovaAction. if (boss->FindCurrentSpellBySpellId(SPELL_LIGHTNING_NOVA)) { - if (dynamic_cast(action) - && !dynamic_cast(action)) + if (dynamic_cast(&action) + && !dynamic_cast(&action)) { return 0.0f; } // Specifically prevent Charge during Lightning Nova. - if (dynamic_cast(action)) + if (dynamic_cast(&action)) { return 0.0f; } diff --git a/src/Ai/Dungeon/HallsOfLightning/Multiplier/HallsOfLightningMultipliers.h b/src/Ai/Dungeon/HallsOfLightning/Multiplier/HallsOfLightningMultipliers.h index 8cc439677e..49d40317c7 100644 --- a/src/Ai/Dungeon/HallsOfLightning/Multiplier/HallsOfLightningMultipliers.h +++ b/src/Ai/Dungeon/HallsOfLightning/Multiplier/HallsOfLightningMultipliers.h @@ -9,7 +9,7 @@ class BjarngrimMultiplier : public Multiplier BjarngrimMultiplier(PlayerbotAI* ai) : Multiplier(ai, "general bjarngrim") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class VolkhanMultiplier : public Multiplier @@ -18,7 +18,7 @@ class VolkhanMultiplier : public Multiplier VolkhanMultiplier(PlayerbotAI* ai) : Multiplier(ai, "volkhan") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class IonarMultiplier : public Multiplier @@ -27,7 +27,7 @@ class IonarMultiplier : public Multiplier IonarMultiplier(PlayerbotAI* ai) : Multiplier(ai, "ionar") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class LokenMultiplier : public Multiplier @@ -36,7 +36,7 @@ class LokenMultiplier : public Multiplier LokenMultiplier(PlayerbotAI* ai) : Multiplier(ai, "loken") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; #endif diff --git a/src/Ai/Dungeon/HallsOfLightning/Strategy/HallsOfLightningStrategy.cpp b/src/Ai/Dungeon/HallsOfLightning/Strategy/HallsOfLightningStrategy.cpp index 1266fb0b9c..d284eb1dc0 100644 --- a/src/Ai/Dungeon/HallsOfLightning/Strategy/HallsOfLightningStrategy.cpp +++ b/src/Ai/Dungeon/HallsOfLightning/Strategy/HallsOfLightningStrategy.cpp @@ -1,34 +1,90 @@ #include "HallsOfLightningStrategy.h" +#include "CreateNextAction.h" +#include "HallsOfLightningActions.h" #include "HallsOfLightningMultipliers.h" void WotlkDungeonHoLStrategy::InitTriggers(std::vector &triggers) { // General Bjarngrim - triggers.push_back(new TriggerNode("stormforged lieutenant", - { NextAction("bjarngrim target", ACTION_RAID + 5) })); - triggers.push_back(new TriggerNode("whirlwind", - { NextAction("avoid whirlwind", ACTION_RAID + 4) })); + triggers.push_back( + new TriggerNode( + "stormforged lieutenant", + { + CreateNextAction(ACTION_RAID + 5.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "whirlwind", + { + CreateNextAction(ACTION_RAID + 4.0f) + } + ) + ); // Volkhan - triggers.push_back(new TriggerNode("volkhan", - { NextAction("volkhan target", ACTION_RAID + 5) })); + triggers.push_back( + new TriggerNode( + "volkhan", + { + CreateNextAction(ACTION_RAID + 5.0f) + } + ) + ); // Ionar - triggers.push_back(new TriggerNode("ionar disperse", - { NextAction("disperse position", ACTION_MOVE + 5) })); - triggers.push_back(new TriggerNode("ionar tank aggro", - { NextAction("ionar tank position", ACTION_MOVE + 4) })); - triggers.push_back(new TriggerNode("static overload", - { NextAction("static overload spread", ACTION_MOVE + 3) })); + triggers.push_back( + new TriggerNode( + "ionar disperse", + { + CreateNextAction(ACTION_MOVE + 5.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "ionar tank aggro", + { + CreateNextAction(ACTION_MOVE + 4.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "static overload", + { + CreateNextAction(ACTION_MOVE + 3.0f) + } + ) + ); // TODO: Targeted player can dodge the ball, but a single player soaking it isn't too bad to heal - triggers.push_back(new TriggerNode("ball lightning", - { NextAction("ball lightning spread", ACTION_MOVE + 2) })); + triggers.push_back( + new TriggerNode( + "ball lightning", + { + CreateNextAction(ACTION_MOVE + 2.0f) + } + ) + ); // Loken - triggers.push_back(new TriggerNode("lightning nova", - { NextAction("avoid lightning nova", ACTION_MOVE + 5) })); - triggers.push_back(new TriggerNode("loken ranged", - { NextAction("loken stack", ACTION_MOVE + 4) })); + triggers.push_back( + new TriggerNode( + "lightning nova", + { + CreateNextAction(ACTION_MOVE + 5.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "loken ranged", + { + CreateNextAction(ACTION_MOVE + 4.0f) + } + ) + ); } void WotlkDungeonHoLStrategy::InitMultipliers(std::vector &multipliers) diff --git a/src/Ai/Dungeon/HallsOfReflection/TODO b/src/Ai/Dungeon/HallsOfReflection/.gitkeep similarity index 100% rename from src/Ai/Dungeon/HallsOfReflection/TODO rename to src/Ai/Dungeon/HallsOfReflection/.gitkeep diff --git a/src/Ai/Dungeon/HallsOfStone/Action/HallsOfStoneActions.cpp b/src/Ai/Dungeon/HallsOfStone/Action/HallsOfStoneActions.cpp index 30562f090d..c43e23b66e 100644 --- a/src/Ai/Dungeon/HallsOfStone/Action/HallsOfStoneActions.cpp +++ b/src/Ai/Dungeon/HallsOfStone/Action/HallsOfStoneActions.cpp @@ -1,8 +1,7 @@ #include "Playerbots.h" #include "HallsOfStoneActions.h" -#include "HallsOfStoneStrategy.h" -bool ShatterSpreadAction::Execute(Event event) +bool ShatterSpreadAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "krystallus"); if (!boss) { return false; } @@ -35,7 +34,7 @@ bool ShatterSpreadAction::Execute(Event event) return false; } -bool AvoidLightningRingAction::Execute(Event event) +bool AvoidLightningRingAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "sjonnir the ironshaper"); if (!boss) { return false; } diff --git a/src/Ai/Dungeon/HallsOfStone/HallsOfStoneActionContext.h b/src/Ai/Dungeon/HallsOfStone/HallsOfStoneActionContext.h deleted file mode 100644 index 40b469b40f..0000000000 --- a/src/Ai/Dungeon/HallsOfStone/HallsOfStoneActionContext.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef _PLAYERBOT_WOTLKDUNGEONHOSACTIONCONTEXT_H -#define _PLAYERBOT_WOTLKDUNGEONHOSACTIONCONTEXT_H - -#include "Action.h" -#include "NamedObjectContext.h" -#include "HallsOfStoneActions.h" - -class WotlkDungeonHoSActionContext : public NamedObjectContext -{ - public: - WotlkDungeonHoSActionContext() { - creators["shatter spread"] = &WotlkDungeonHoSActionContext::shatter_spread; - creators["avoid lightning ring"] = &WotlkDungeonHoSActionContext::avoid_lightning_ring; - } - private: - static Action* shatter_spread(PlayerbotAI* ai) { return new ShatterSpreadAction(ai); } - static Action* avoid_lightning_ring(PlayerbotAI* ai) { return new AvoidLightningRingAction(ai); } -}; - -#endif diff --git a/src/Ai/Dungeon/HallsOfStone/Multiplier/HallsOfStoneMultipliers.cpp b/src/Ai/Dungeon/HallsOfStone/Multiplier/HallsOfStoneMultipliers.cpp index 443905bbbb..487409d0d5 100644 --- a/src/Ai/Dungeon/HallsOfStone/Multiplier/HallsOfStoneMultipliers.cpp +++ b/src/Ai/Dungeon/HallsOfStone/Multiplier/HallsOfStoneMultipliers.cpp @@ -1,12 +1,12 @@ #include "HallsOfStoneMultipliers.h" -#include "HallsOfStoneActions.h" #include "GenericSpellActions.h" -#include "ChooseTargetActions.h" +#include "HallsOfStoneActions.h" #include "MovementActions.h" #include "HallsOfStoneTriggers.h" #include "Action.h" +#include "Playerbots.h" -float KrystallusMultiplier::GetValue(Action* action) +float KrystallusMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "krystallus"); if (!boss) { return 1.0f; } @@ -15,7 +15,7 @@ float KrystallusMultiplier::GetValue(Action* action) // Neither is active for the full duration so we need to trigger off both if (bot->HasAura(SPELL_GROUND_SLAM) || bot->HasAura(DEBUFF_GROUND_SLAM)) { - if (dynamic_cast(action) && !dynamic_cast(action)) + if (dynamic_cast(&action) && !dynamic_cast(&action)) { return 0.0f; } @@ -23,19 +23,20 @@ float KrystallusMultiplier::GetValue(Action* action) return 1.0f; } -float SjonnirMultiplier::GetValue(Action* action) +float SjonnirMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "sjonnir the ironshaper"); if (!boss) { return 1.0f; } if (boss->HasUnitState(UNIT_STATE_CASTING) && boss->FindCurrentSpellBySpellId(SPELL_LIGHTNING_RING)) + { + // Problematic since there's a lot of movement on this boss, will prevent players from positioning + // well to deal with adds etc. during the channel period. Takes a bit of work to improve this though + if (dynamic_cast(&action) && !dynamic_cast(&action)) { - // Problematic since there's a lot of movement on this boss, will prevent players from positioning - // well to deal with adds etc. during the channel period. Takes a bit of work to improve this though - if (dynamic_cast(action) && !dynamic_cast(action)) - { - return 0.0f; - } + return 0.0f; } + } + return 1.0f; } diff --git a/src/Ai/Dungeon/HallsOfStone/Multiplier/HallsOfStoneMultipliers.h b/src/Ai/Dungeon/HallsOfStone/Multiplier/HallsOfStoneMultipliers.h index 543d389a8b..f149a86df4 100644 --- a/src/Ai/Dungeon/HallsOfStone/Multiplier/HallsOfStoneMultipliers.h +++ b/src/Ai/Dungeon/HallsOfStone/Multiplier/HallsOfStoneMultipliers.h @@ -9,7 +9,7 @@ class KrystallusMultiplier : public Multiplier KrystallusMultiplier(PlayerbotAI* ai) : Multiplier(ai, "krystallus") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class SjonnirMultiplier : public Multiplier @@ -18,7 +18,7 @@ class SjonnirMultiplier : public Multiplier SjonnirMultiplier(PlayerbotAI* ai) : Multiplier(ai, "sjonnir the ironshaper") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; #endif diff --git a/src/Ai/Dungeon/HallsOfStone/Strategy/HallsOfStoneStrategy.cpp b/src/Ai/Dungeon/HallsOfStone/Strategy/HallsOfStoneStrategy.cpp index 47006a9e44..fd43fab054 100644 --- a/src/Ai/Dungeon/HallsOfStone/Strategy/HallsOfStoneStrategy.cpp +++ b/src/Ai/Dungeon/HallsOfStone/Strategy/HallsOfStoneStrategy.cpp @@ -1,4 +1,6 @@ #include "HallsOfStoneStrategy.h" +#include "CreateNextAction.h" +#include "HallsOfStoneActions.h" #include "HallsOfStoneMultipliers.h" void WotlkDungeonHoSStrategy::InitTriggers(std::vector &triggers) @@ -8,8 +10,14 @@ void WotlkDungeonHoSStrategy::InitTriggers(std::vector &triggers) // Krystallus // TODO: I think bots need to dismiss pets on this, or they nuke players they are standing close to - triggers.push_back(new TriggerNode("ground slam", - { NextAction("shatter spread", ACTION_RAID + 5) })); + triggers.push_back( + new TriggerNode( + "ground slam", + { + CreateNextAction(ACTION_RAID + 5.0f) + } + ) + ); // Tribunal of Ages // Seems fine, maybe add focus targeting strat if needed on heroic. @@ -18,8 +26,14 @@ void WotlkDungeonHoSStrategy::InitTriggers(std::vector &triggers) // Sjonnir The Ironshaper // Possibly tank in place in the middle of the room, assign a dps to adds? - triggers.push_back(new TriggerNode("lightning ring", - { NextAction("avoid lightning ring", ACTION_RAID + 5) })); + triggers.push_back( + new TriggerNode( + "lightning ring", + { + CreateNextAction(ACTION_RAID + 5.0f) + } + ) + ); } void WotlkDungeonHoSStrategy::InitMultipliers(std::vector &multipliers) diff --git a/src/Ai/Dungeon/HallsOfStone/Trigger/HallsOfStoneTriggers.h b/src/Ai/Dungeon/HallsOfStone/Trigger/HallsOfStoneTriggers.h index 53a15b6f24..e9232db67e 100644 --- a/src/Ai/Dungeon/HallsOfStone/Trigger/HallsOfStoneTriggers.h +++ b/src/Ai/Dungeon/HallsOfStone/Trigger/HallsOfStoneTriggers.h @@ -2,8 +2,8 @@ #define _PLAYERBOT_WOTLKDUNGEONHOSTRIGGERS_H #include "Trigger.h" -#include "PlayerbotAIConfig.h" #include "GenericTriggers.h" +// Required due to excessive use of macros #include "DungeonStrategyUtils.h" enum HallsOfStoneIDs diff --git a/src/Ai/Dungeon/Nexus/Action/NexusActions.cpp b/src/Ai/Dungeon/Nexus/Action/NexusActions.cpp index f61a95aef4..7f106e33de 100644 --- a/src/Ai/Dungeon/Nexus/Action/NexusActions.cpp +++ b/src/Ai/Dungeon/Nexus/Action/NexusActions.cpp @@ -1,8 +1,8 @@ +#include "NexusTriggers.h" #include "Playerbots.h" #include "NexusActions.h" -#include "NexusStrategy.h" -bool MoveFromWhirlwindAction::Execute(Event event) +bool MoveFromWhirlwindAction::Execute(Event) { Unit* boss = nullptr; uint8 faction = bot->GetTeamId(); @@ -52,7 +52,7 @@ bool MoveFromWhirlwindAction::Execute(Event event) return MoveAway(boss, targetDist - bossDistance); } -bool FirebombSpreadAction::Execute(Event event) +bool FirebombSpreadAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "grand magus telestra"); float radius = 5.0f; @@ -74,7 +74,7 @@ bool FirebombSpreadAction::Execute(Event event) } bool TelestraSplitTargetAction::isUseful() { return !botAI->IsHeal(bot); } -bool TelestraSplitTargetAction::Execute(Event event) +bool TelestraSplitTargetAction::Execute(Event) { GuidVector attackers = AI_VALUE(GuidVector, "attackers"); Unit* splitTargets[3] = {nullptr, nullptr, nullptr}; @@ -121,7 +121,7 @@ bool TelestraSplitTargetAction::Execute(Event event) } bool ChaoticRiftTargetAction::isUseful() { return !botAI->IsHeal(bot); } -bool ChaoticRiftTargetAction::Execute(Event event) +bool ChaoticRiftTargetAction::Execute(Event) { Unit* chaoticRift = nullptr; @@ -152,7 +152,7 @@ bool DodgeSpikesAction::isUseful() return bot->GetExactDist2d(boss) > 0.5f; } -bool DodgeSpikesAction::Execute(Event event) +bool DodgeSpikesAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "ormorok the tree-shaper"); if (!boss) { return false; } @@ -160,7 +160,7 @@ bool DodgeSpikesAction::Execute(Event event) return Move(bot->GetAngle(boss), bot->GetExactDist2d(boss) - 0.3f); } -bool IntenseColdJumpAction::Execute(Event event) +bool IntenseColdJumpAction::Execute(Event) { // This needs improving but maybe it should be done in the playerbot core. // Jump doesn't seem to support zero offset (eg. jump on the spot) so need to add a tiny delta. diff --git a/src/Ai/Dungeon/Nexus/Action/NexusActions.h b/src/Ai/Dungeon/Nexus/Action/NexusActions.h index 96790c367c..3a2ed1423b 100644 --- a/src/Ai/Dungeon/Nexus/Action/NexusActions.h +++ b/src/Ai/Dungeon/Nexus/Action/NexusActions.h @@ -4,8 +4,6 @@ #include "Action.h" #include "AttackAction.h" #include "PlayerbotAI.h" -#include "Playerbots.h" -#include "NexusTriggers.h" class MoveFromWhirlwindAction : public MovementAction { diff --git a/src/Ai/Dungeon/Nexus/Multiplier/NexusMultipliers.cpp b/src/Ai/Dungeon/Nexus/Multiplier/NexusMultipliers.cpp index 7adc79b455..ac5974fd35 100644 --- a/src/Ai/Dungeon/Nexus/Multiplier/NexusMultipliers.cpp +++ b/src/Ai/Dungeon/Nexus/Multiplier/NexusMultipliers.cpp @@ -1,11 +1,12 @@ #include "NexusMultipliers.h" -#include "NexusActions.h" -#include "GenericSpellActions.h" #include "ChooseTargetActions.h" +#include "GenericSpellActions.h" +#include "NexusActions.h" +#include "Playerbots.h" #include "MovementActions.h" #include "NexusTriggers.h" -float FactionCommanderMultiplier::GetValue(Action* action) +float FactionCommanderMultiplier::GetValue(Action& action) { Unit* boss = nullptr; uint8 faction = bot->GetTeamId(); @@ -39,7 +40,7 @@ float FactionCommanderMultiplier::GetValue(Action* action) boss->FindCurrentSpellBySpellId(SPELL_WHIRLWIND)) { // Prevent movement actions other than flee during a whirlwind, to prevent running back in early. - if (dynamic_cast(action) && !dynamic_cast(action)) + if (dynamic_cast(&action) && !dynamic_cast(&action)) { return 0.0f; } @@ -47,13 +48,13 @@ float FactionCommanderMultiplier::GetValue(Action* action) return 1.0f; } -float TelestraMultiplier::GetValue(Action* action) +float TelestraMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "grand magus telestra"); if (boss && boss->GetEntry() != NPC_TELESTRA) { // boss is split into clones, do not auto acquire target - if (dynamic_cast(action)) + if (dynamic_cast(&action)) { return 0.0f; } @@ -61,12 +62,12 @@ float TelestraMultiplier::GetValue(Action* action) return 1.0f; } -float AnomalusMultiplier::GetValue(Action* action) +float AnomalusMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "anomalus"); if (boss && boss->HasAura(BUFF_RIFT_SHIELD)) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) { return 0.0f; } @@ -74,19 +75,19 @@ float AnomalusMultiplier::GetValue(Action* action) return 1.0f; } -float OrmorokMultiplier::GetValue(Action* action) +float OrmorokMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "ormorok the tree-shaper"); if (!boss) { return 1.0f; } // These are used for auto ranged repositioning, need to suppress so ranged dps don't ping-pong - if (dynamic_cast(action)) + if (dynamic_cast(&action)) { return 0.0f; } // This boss is annoying and shuffles around a lot. Don't let tank move once fight has started. // Extra checks are to allow the tank to close distance and engage the boss initially - if (dynamic_cast(action) && !dynamic_cast(action) + if (dynamic_cast(&action) && !dynamic_cast(&action) && botAI->IsTank(bot) && bot->IsWithinMeleeRange(boss) && AI_VALUE2(bool, "facing", "current target")) { diff --git a/src/Ai/Dungeon/Nexus/Multiplier/NexusMultipliers.h b/src/Ai/Dungeon/Nexus/Multiplier/NexusMultipliers.h index 00373ebd93..a588b6a33d 100644 --- a/src/Ai/Dungeon/Nexus/Multiplier/NexusMultipliers.h +++ b/src/Ai/Dungeon/Nexus/Multiplier/NexusMultipliers.h @@ -9,7 +9,7 @@ class FactionCommanderMultiplier : public Multiplier FactionCommanderMultiplier(PlayerbotAI* ai) : Multiplier(ai, "faction commander") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class TelestraMultiplier : public Multiplier @@ -18,7 +18,7 @@ class TelestraMultiplier : public Multiplier TelestraMultiplier(PlayerbotAI* ai) : Multiplier(ai, "grand magus telestra") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class AnomalusMultiplier : public Multiplier @@ -27,7 +27,7 @@ class AnomalusMultiplier : public Multiplier AnomalusMultiplier(PlayerbotAI* ai) : Multiplier(ai, "anomalus") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class OrmorokMultiplier : public Multiplier @@ -36,7 +36,7 @@ class OrmorokMultiplier : public Multiplier OrmorokMultiplier(PlayerbotAI* ai) : Multiplier(ai, "ormorok the tree-shaper") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; #endif diff --git a/src/Ai/Dungeon/Nexus/NexusActionContext.h b/src/Ai/Dungeon/Nexus/NexusActionContext.h deleted file mode 100644 index c024226258..0000000000 --- a/src/Ai/Dungeon/Nexus/NexusActionContext.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _PLAYERBOT_WOTLKDUNGEONNEXACTIONCONTEXT_H -#define _PLAYERBOT_WOTLKDUNGEONNEXACTIONCONTEXT_H - -#include "Action.h" -#include "NamedObjectContext.h" -#include "NexusActions.h" - -class WotlkDungeonNexActionContext : public NamedObjectContext -{ - public: - WotlkDungeonNexActionContext() { - creators["move from whirlwind"] = &WotlkDungeonNexActionContext::move_from_whirlwind; - creators["firebomb spread"] = &WotlkDungeonNexActionContext::firebomb_spread; - creators["telestra split target"] = &WotlkDungeonNexActionContext::telestra_split_target; - creators["chaotic rift target"] = &WotlkDungeonNexActionContext::chaotic_rift_target; - creators["dodge spikes"] = &WotlkDungeonNexActionContext::dodge_spikes; - creators["intense cold jump"] = &WotlkDungeonNexActionContext::intense_cold_jump; - } - private: - static Action* move_from_whirlwind(PlayerbotAI* ai) { return new MoveFromWhirlwindAction(ai); } - static Action* firebomb_spread(PlayerbotAI* ai) { return new FirebombSpreadAction(ai); } - static Action* telestra_split_target(PlayerbotAI* ai) { return new TelestraSplitTargetAction(ai); } - static Action* chaotic_rift_target(PlayerbotAI* ai) { return new ChaoticRiftTargetAction(ai); } - static Action* dodge_spikes(PlayerbotAI* ai) { return new DodgeSpikesAction(ai); } - static Action* intense_cold_jump(PlayerbotAI* ai) { return new IntenseColdJumpAction(ai); } -}; - -#endif diff --git a/src/Ai/Dungeon/Nexus/Strategy/NexusStrategy.cpp b/src/Ai/Dungeon/Nexus/Strategy/NexusStrategy.cpp index e633ba9822..5f09e031ab 100644 --- a/src/Ai/Dungeon/Nexus/Strategy/NexusStrategy.cpp +++ b/src/Ai/Dungeon/Nexus/Strategy/NexusStrategy.cpp @@ -1,4 +1,6 @@ #include "NexusStrategy.h" +#include "CreateNextAction.h" +#include "NexusActions.h" #include "NexusMultipliers.h" void WotlkDungeonNexStrategy::InitTriggers(std::vector &triggers) @@ -6,40 +8,88 @@ void WotlkDungeonNexStrategy::InitTriggers(std::vector &triggers) // Horde Commander (Alliance N)/Commander Kolurg (Alliance H) // or // Alliance Commander (Horde N)/Commander Stoutbeard (Horde H) - triggers.push_back(new TriggerNode("faction commander whirlwind", - { NextAction("move from whirlwind", ACTION_MOVE + 5) })); + triggers.push_back( + new TriggerNode( + "faction commander whirlwind", + { + CreateNextAction(ACTION_MOVE + 5.0f) + } + ) + ); // TODO: Handle fear? (tremor totems, fear ward etc.) // Grand Magus Telestra - triggers.push_back(new TriggerNode("telestra firebomb", - { NextAction("firebomb spread", ACTION_MOVE + 5) })); - triggers.push_back(new TriggerNode("telestra split phase", - { NextAction("telestra split target", ACTION_RAID + 1) })); + triggers.push_back( + new TriggerNode( + "telestra firebomb", + { + CreateNextAction(ACTION_MOVE + 5.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "telestra split phase", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); // TODO: Add priority interrupt on the frost split's Blizzard casts // Anomalus - triggers.push_back(new TriggerNode("chaotic rift", - { NextAction("chaotic rift target", ACTION_RAID + 1) })); + triggers.push_back( + new TriggerNode( + "chaotic rift", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); // Ormorok the Tree-Shaper // Tank trigger to stack inside boss. Can also add return action to prevent boss repositioning // if it becomes too much of a problem. He usually dies before he's up against a wall though - triggers.push_back(new TriggerNode("ormorok spikes", - { NextAction("dodge spikes", ACTION_MOVE + 5) })); + triggers.push_back( + new TriggerNode( + "ormorok spikes", + { + CreateNextAction(ACTION_MOVE + 5.0f) + } + ) + ); // Non-tank trigger to stack. Avoiding the spikes at range is.. harder than it seems. // TODO: This turns hunters into melee marshmallows, have not come up with a better solution yet - triggers.push_back(new TriggerNode("ormorok stack", - { NextAction("dodge spikes", ACTION_MOVE + 5) })); + triggers.push_back( + new TriggerNode( + "ormorok stack", + { + CreateNextAction(ACTION_MOVE + 5.0f) + } + ) + ); // TODO: Add handling for spell reflect... best to spam low level/weak spells but don't want // to hardcode spells per class, might be difficult to dynamically generate this. // Will revisit if I find my altbots killing themselves in heroic, just heal through it for now // Keristrasza - triggers.push_back(new TriggerNode("intense cold", - { NextAction("intense cold jump", ACTION_MOVE + 5) })); + triggers.push_back( + new TriggerNode( + "intense cold", + { + CreateNextAction(ACTION_MOVE + 5.0f) + } + ) + ); // Flank dragon positioning - triggers.push_back(new TriggerNode("keristrasza positioning", - { NextAction("rear flank", ACTION_MOVE + 4) })); + triggers.push_back( + new TriggerNode( + "keristrasza positioning", + { + CreateNextAction(ACTION_MOVE + 4.0f) + } + ) + ); // TODO: Add frost resist aura for paladins? } diff --git a/src/Ai/Dungeon/Oculus/Action/OculusActions.cpp b/src/Ai/Dungeon/Oculus/Action/OculusActions.cpp index 414acc4bc9..1ea8f87618 100644 --- a/src/Ai/Dungeon/Oculus/Action/OculusActions.cpp +++ b/src/Ai/Dungeon/Oculus/Action/OculusActions.cpp @@ -1,9 +1,9 @@ +#include "OculusTriggers.h" #include "Playerbots.h" #include "OculusActions.h" -#include "OculusStrategy.h" #include "LastSpellCastValue.h" -bool AvoidUnstableSphereAction::Execute(Event event) +bool AvoidUnstableSphereAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "drakos the interrogator"); if (!boss) { return false; } @@ -34,7 +34,7 @@ bool AvoidUnstableSphereAction::Execute(Event event) } bool MountDrakeAction::isPossible() { return bot->GetMapId() == OCULUS_MAP_ID; } -bool MountDrakeAction::Execute(Event event) +bool MountDrakeAction::Execute(Event) { std::map drakeAssignments; // Composition can be adjusted - both 3/1/1 and 2/2/1 are good default comps @@ -88,7 +88,7 @@ bool MountDrakeAction::Execute(Event event) } // Correct/update the drake items in inventories incase assignments have changed - for (uint32 itemId : DRAKE_ITEMS) + for (int64_t itemId : DRAKE_ITEMS) { Item* item = bot->GetItemByEntry(itemId); if (!item) { continue; } @@ -109,7 +109,7 @@ bool MountDrakeAction::Execute(Event event) return false; } -bool DismountDrakeAction::Execute(Event event) +bool DismountDrakeAction::Execute(Event) { if (bot->GetVehicle()) { @@ -119,7 +119,7 @@ bool DismountDrakeAction::Execute(Event event) return false; } -bool OccFlyDrakeAction::Execute(Event event) +bool OccFlyDrakeAction::Execute(Event) { Player* master = botAI->GetMaster(); if (!master) { return false; } @@ -160,7 +160,7 @@ bool OccFlyDrakeAction::Execute(Event event) return false; } -bool OccDrakeAttackAction::Execute(Event event) +bool OccDrakeAttackAction::Execute(Event) { vehicleBase = bot->GetVehicleBase(); if (!vehicleBase) { return false; } @@ -319,7 +319,7 @@ bool OccDrakeAttackAction::RubyDrakeAction(Unit* target) return CastDrakeSpellAction(target, SPELL_SEARING_WRATH, 0); } -bool AvoidArcaneExplosionAction::Execute(Event event) +bool AvoidArcaneExplosionAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "mage-lord urom"); if (!boss) { return false; } @@ -339,7 +339,7 @@ bool AvoidArcaneExplosionAction::Execute(Event event) return MoveNear(bot->GetMapId(), closestPos->GetPositionX(), closestPos->GetPositionY(), closestPos->GetPositionZ(), 2.0f, MovementPriority::MOVEMENT_COMBAT); } -bool TimeBombSpreadAction::Execute(Event event) +bool TimeBombSpreadAction::Execute(Event) { float radius = 10.0f; float distanceExtra = 2.0f; diff --git a/src/Ai/Dungeon/Oculus/Action/OculusActions.h b/src/Ai/Dungeon/Oculus/Action/OculusActions.h index 6b26b9ddbc..6616ce884b 100644 --- a/src/Ai/Dungeon/Oculus/Action/OculusActions.h +++ b/src/Ai/Dungeon/Oculus/Action/OculusActions.h @@ -4,8 +4,6 @@ #include "Action.h" #include "AttackAction.h" #include "PlayerbotAI.h" -#include "Playerbots.h" -#include "OculusTriggers.h" #include "UseItemAction.h" #include "GenericSpellActions.h" diff --git a/src/Ai/Dungeon/Oculus/Multiplier/OculusMultipliers.cpp b/src/Ai/Dungeon/Oculus/Multiplier/OculusMultipliers.cpp index 7be543ee70..7b34b55a5b 100644 --- a/src/Ai/Dungeon/Oculus/Multiplier/OculusMultipliers.cpp +++ b/src/Ai/Dungeon/Oculus/Multiplier/OculusMultipliers.cpp @@ -6,8 +6,9 @@ #include "OculusTriggers.h" #include "FollowActions.h" #include "ReachTargetActions.h" +#include "Playerbots.h" -float MountingDrakeMultiplier::GetValue(Action* action) +float MountingDrakeMultiplier::GetValue(Action& action) { // P.I.T.A bug where the bots will somehow interrupt their item spell use, // even though the 0.5 sec cast goes off, it puts the drake essence on 15 sec cd @@ -19,30 +20,30 @@ float MountingDrakeMultiplier::GetValue(Action* action) if (bot->GetMapId() != OCULUS_MAP_ID || !master->GetVehicleBase() || bot->GetVehicleBase()) { return 1.0f; } - if (!dynamic_cast(action)) + if (!dynamic_cast(&action)) { return 0.0f; } return 1.0f; } -float OccFlyingMultiplier::GetValue(Action* action) +float OccFlyingMultiplier::GetValue(Action& action) { if (bot->GetMapId() != OCULUS_MAP_ID || !bot->GetVehicleBase()) { return 1.0f; } // Suppresses FollowAction as well as some attack-based movements - if (dynamic_cast(action) && !dynamic_cast(action)) + if (dynamic_cast(&action) && !dynamic_cast(&action)) { return 0.0f; } return 1.0f; } -float UromMultiplier::GetValue(Action* action) +float UromMultiplier::GetValue(Action& action) { if (GetPhaseByCurrentPosition(bot) < 3) { - Unit* target = action->GetTarget(); + Unit* target = action.GetTarget(); if (target && target->GetEntry() == NPC_MAGE_LORD_UROM) { return 0.0f; @@ -56,7 +57,7 @@ float UromMultiplier::GetValue(Action* action) if (boss->HasUnitState(UNIT_STATE_CASTING) && boss->FindCurrentSpellBySpellId(SPELL_EMPOWERED_ARCANE_EXPLOSION)) { - if (dynamic_cast(action) && !dynamic_cast(action)) + if (dynamic_cast(&action) && !dynamic_cast(&action)) { return 0.0f; } @@ -65,7 +66,7 @@ float UromMultiplier::GetValue(Action* action) // Don't bother avoiding Frostbomb for melee if (botAI->IsMelee(bot)) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) { return 0.0f; } @@ -73,7 +74,7 @@ float UromMultiplier::GetValue(Action* action) if (bot->HasAura(SPELL_TIME_BOMB)) { - if (dynamic_cast(action) && !dynamic_cast(action)) + if (dynamic_cast(&action) && !dynamic_cast(&action)) { return 0.0f; } @@ -98,14 +99,19 @@ uint8 UromMultiplier::GetPhaseByCurrentPosition(Unit* unit) return 3; } -float EregosMultiplier::GetValue(Action* action) +float EregosMultiplier::GetValue(Action& action) { - Unit* boss = AI_VALUE2(Unit*, "find target", "ley-guardian eregos"); - if (!boss) { return 1.0f; } + const Unit* const boss = this->context->GetValue("find target", "ley-guardian eregos")->Get(); - if (boss->HasAura(SPELL_PLANAR_SHIFT && dynamic_cast(action))) + if (boss == nullptr) + { + return 1.0f; + } + + if (boss->HasAura(SPELL_PLANAR_SHIFT) && action.getName() == "occ drake attack") { return 0.0f; } + return 1.0f; } diff --git a/src/Ai/Dungeon/Oculus/Multiplier/OculusMultipliers.h b/src/Ai/Dungeon/Oculus/Multiplier/OculusMultipliers.h index 423364b099..58c7727f5e 100644 --- a/src/Ai/Dungeon/Oculus/Multiplier/OculusMultipliers.h +++ b/src/Ai/Dungeon/Oculus/Multiplier/OculusMultipliers.h @@ -18,7 +18,7 @@ class MountingDrakeMultiplier : public Multiplier MountingDrakeMultiplier(PlayerbotAI* ai) : Multiplier(ai, "mounting drake") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class OccFlyingMultiplier : public Multiplier @@ -27,7 +27,7 @@ class OccFlyingMultiplier : public Multiplier OccFlyingMultiplier(PlayerbotAI* ai) : Multiplier(ai, "occ flying drake") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class UromMultiplier : public Multiplier @@ -36,7 +36,7 @@ class UromMultiplier : public Multiplier UromMultiplier(PlayerbotAI* ai) : Multiplier(ai, "mage-lord urom") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); protected: uint8 GetPhaseByCurrentPosition(Unit* boss); }; @@ -47,7 +47,7 @@ class EregosMultiplier : public Multiplier EregosMultiplier(PlayerbotAI* ai) : Multiplier(ai, "ley-guardian eregos") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; #endif diff --git a/src/Ai/Dungeon/Oculus/OculusActionContext.h b/src/Ai/Dungeon/Oculus/OculusActionContext.h deleted file mode 100644 index fa5036e545..0000000000 --- a/src/Ai/Dungeon/Oculus/OculusActionContext.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef _PLAYERBOT_WOTLKDUNGEONOCCACTIONCONTEXT_H -#define _PLAYERBOT_WOTLKDUNGEONOCCACTIONCONTEXT_H - -#include "Action.h" -#include "NamedObjectContext.h" -#include "OculusActions.h" - -class WotlkDungeonOccActionContext : public NamedObjectContext -{ - public: - WotlkDungeonOccActionContext() { - creators["avoid unstable sphere"] = &WotlkDungeonOccActionContext::avoid_unstable_sphere; - creators["mount drake"] = &WotlkDungeonOccActionContext::mount_drake; - creators["dismount drake"] = &WotlkDungeonOccActionContext::dismount_drake; - creators["occ fly drake"] = &WotlkDungeonOccActionContext::occ_fly_drake; - creators["occ drake attack"] = &WotlkDungeonOccActionContext::occ_drake_attack; - creators["avoid arcane explosion"] = &WotlkDungeonOccActionContext::avoid_arcane_explosion; - creators["time bomb spread"] = &WotlkDungeonOccActionContext::time_bomb_spread; - } - private: - static Action* avoid_unstable_sphere(PlayerbotAI* ai) { return new AvoidUnstableSphereAction(ai); } - static Action* mount_drake(PlayerbotAI* ai) { return new MountDrakeAction(ai); } - static Action* dismount_drake(PlayerbotAI* ai) { return new DismountDrakeAction(ai); } - static Action* occ_fly_drake(PlayerbotAI* ai) { return new OccFlyDrakeAction(ai); } - static Action* occ_drake_attack(PlayerbotAI* ai) { return new OccDrakeAttackAction(ai); } - static Action* avoid_arcane_explosion(PlayerbotAI* ai) { return new AvoidArcaneExplosionAction(ai); } - static Action* time_bomb_spread(PlayerbotAI* ai) { return new TimeBombSpreadAction(ai); } -}; - -#endif diff --git a/src/Ai/Dungeon/Oculus/Strategy/OculusStrategy.cpp b/src/Ai/Dungeon/Oculus/Strategy/OculusStrategy.cpp index 4c558469ee..b3b100dd58 100644 --- a/src/Ai/Dungeon/Oculus/Strategy/OculusStrategy.cpp +++ b/src/Ai/Dungeon/Oculus/Strategy/OculusStrategy.cpp @@ -1,33 +1,82 @@ #include "OculusStrategy.h" +#include "OculusActions.h" #include "OculusMultipliers.h" void WotlkDungeonOccStrategy::InitTriggers(std::vector &triggers) { // Drakos the Interrogator // TODO: May need work, TBA. - triggers.push_back(new TriggerNode("unstable sphere", - { NextAction("avoid unstable sphere", ACTION_MOVE + 5) })); + triggers.push_back( + new TriggerNode( + "unstable sphere", + { + CreateNextAction(ACTION_MOVE + 5.0f) + } + ) + ); // DRAKES - triggers.push_back(new TriggerNode("drake mount", - { NextAction("mount drake", ACTION_RAID + 5) })); - triggers.push_back(new TriggerNode("drake dismount", - { NextAction("dismount drake", ACTION_RAID + 5) })); - triggers.push_back(new TriggerNode("group flying", - { NextAction("occ fly drake", ACTION_NORMAL + 1) })); - triggers.push_back(new TriggerNode("drake combat", - { NextAction("occ drake attack", ACTION_NORMAL + 5) })); + triggers.push_back( + new TriggerNode( + "drake mount", + { + CreateNextAction(ACTION_RAID + 5.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "drake dismount", + { + CreateNextAction(ACTION_RAID + 5.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "group flying", + { + CreateNextAction(ACTION_NORMAL + 1.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "drake combat", + { + CreateNextAction(ACTION_NORMAL + 5.0f) + } + ) + ); // Varos Cloudstrider // Seems to be no way to identify the marked cores, may need to hook boss AI.. - // triggers.push_back(new TriggerNode("varos cloudstrider", - // { NextAction("avoid energize cores", ACTION_RAID + 5) })); + // triggers.push_back( + // new TriggerNode( + // "varos cloudstrider", + // + // { CreateNextAction(ACTION_RAID + 5) + // } + // ) + // ); // Mage-Lord Urom - triggers.push_back(new TriggerNode("arcane explosion", - { NextAction("avoid arcane explosion", ACTION_MOVE + 5) })); - triggers.push_back(new TriggerNode("time bomb", - { NextAction("time bomb spread", ACTION_MOVE + 4) })); + triggers.push_back( + new TriggerNode( + "arcane explosion", + { + CreateNextAction(ACTION_MOVE + 5.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "time bomb", + { + CreateNextAction(ACTION_MOVE + 4.0f) + } + ) + ); // Ley-Guardian Eregos } diff --git a/src/Ai/Dungeon/OldKingdom/Action/OldKingdomActions.cpp b/src/Ai/Dungeon/OldKingdom/Action/OldKingdomActions.cpp index 916bf29200..7755617758 100644 --- a/src/Ai/Dungeon/OldKingdom/Action/OldKingdomActions.cpp +++ b/src/Ai/Dungeon/OldKingdom/Action/OldKingdomActions.cpp @@ -1,8 +1,7 @@ #include "Playerbots.h" #include "OldKingdomActions.h" -#include "OldKingdomStrategy.h" -bool AttackNadoxGuardianAction::Execute(Event event) +bool AttackNadoxGuardianAction::Execute(Event) { Unit* target = AI_VALUE2(Unit*, "find target", "ahn'kahar guardian"); if (!target || AI_VALUE(Unit*, "current target") == target) @@ -12,7 +11,7 @@ bool AttackNadoxGuardianAction::Execute(Event event) return Attack(target); } -bool AttackJedogaVolunteerAction::Execute(Event event) +bool AttackJedogaVolunteerAction::Execute(Event) { Unit* target = nullptr; // Target is not findable from threat table using AI_VALUE2(), @@ -40,7 +39,7 @@ bool AttackJedogaVolunteerAction::Execute(Event event) return Attack(target); } -bool AvoidShadowCrashAction::Execute(Event event) +bool AvoidShadowCrashAction::Execute(Event) { // Could check all enemy units in range as it's possible to pull multiple of these mobs. // They should really be killed 1 by 1, multipulls are messy so we just handle singles for now diff --git a/src/Ai/Dungeon/OldKingdom/Multiplier/OldKingdomMultipliers.cpp b/src/Ai/Dungeon/OldKingdom/Multiplier/OldKingdomMultipliers.cpp index dbca523160..75feff563e 100644 --- a/src/Ai/Dungeon/OldKingdom/Multiplier/OldKingdomMultipliers.cpp +++ b/src/Ai/Dungeon/OldKingdom/Multiplier/OldKingdomMultipliers.cpp @@ -1,12 +1,12 @@ #include "OldKingdomMultipliers.h" -#include "OldKingdomActions.h" -#include "GenericSpellActions.h" #include "ChooseTargetActions.h" +#include "Playerbots.h" +#include "GenericSpellActions.h" #include "MovementActions.h" #include "OldKingdomTriggers.h" #include "Action.h" -float ElderNadoxMultiplier::GetValue(Action* action) +float ElderNadoxMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "elder nadox"); if (!boss) { return 1.0f; } @@ -14,7 +14,7 @@ float ElderNadoxMultiplier::GetValue(Action* action) Unit* guardian = AI_VALUE2(Unit*, "find target", "ahn'kahar guardian"); if (guardian) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) { return 0.0f; } @@ -22,7 +22,7 @@ float ElderNadoxMultiplier::GetValue(Action* action) return 1.0f; } -float JedogaShadowseekerMultiplier::GetValue(Action* action) +float JedogaShadowseekerMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "jedoga shadowseeker"); if (!boss) { return 1.0f; } @@ -44,7 +44,7 @@ float JedogaShadowseekerMultiplier::GetValue(Action* action) if (volunteer) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) { return 0.0f; } @@ -52,14 +52,14 @@ float JedogaShadowseekerMultiplier::GetValue(Action* action) return 1.0f; } -float ForgottenOneMultiplier::GetValue(Action* action) +float ForgottenOneMultiplier::GetValue(Action& action) { Unit* unit = AI_VALUE2(Unit*, "find target", "forgotten one"); if (!unit) { return 1.0f; } if (bot->isMoving()) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) { return 0.0f; } diff --git a/src/Ai/Dungeon/OldKingdom/Multiplier/OldKingdomMultipliers.h b/src/Ai/Dungeon/OldKingdom/Multiplier/OldKingdomMultipliers.h index 88ae2fa511..d36f5c4b6a 100644 --- a/src/Ai/Dungeon/OldKingdom/Multiplier/OldKingdomMultipliers.h +++ b/src/Ai/Dungeon/OldKingdom/Multiplier/OldKingdomMultipliers.h @@ -9,7 +9,7 @@ class ElderNadoxMultiplier : public Multiplier ElderNadoxMultiplier(PlayerbotAI* ai) : Multiplier(ai, "elder nadox") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class JedogaShadowseekerMultiplier : public Multiplier @@ -18,7 +18,7 @@ class JedogaShadowseekerMultiplier : public Multiplier JedogaShadowseekerMultiplier(PlayerbotAI* ai) : Multiplier(ai, "jedoga shadowseeker") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class ForgottenOneMultiplier : public Multiplier @@ -27,7 +27,7 @@ class ForgottenOneMultiplier : public Multiplier ForgottenOneMultiplier(PlayerbotAI* ai) : Multiplier(ai, "forgotten one") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; #endif diff --git a/src/Ai/Dungeon/OldKingdom/OldKingdomActionContext.h b/src/Ai/Dungeon/OldKingdom/OldKingdomActionContext.h deleted file mode 100644 index 19426c5794..0000000000 --- a/src/Ai/Dungeon/OldKingdom/OldKingdomActionContext.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _PLAYERBOT_WOTLKDUNGEONOKACTIONCONTEXT_H -#define _PLAYERBOT_WOTLKDUNGEONOKACTIONCONTEXT_H - -#include "Action.h" -#include "NamedObjectContext.h" -#include "OldKingdomActions.h" - -class WotlkDungeonOKActionContext : public NamedObjectContext -{ - public: - WotlkDungeonOKActionContext() { - creators["attack nadox guardian"] = &WotlkDungeonOKActionContext::attack_nadox_guardian; - creators["attack jedoga volunteer"] = &WotlkDungeonOKActionContext::attack_jedoga_volunteer; - creators["avoid shadow crash"] = &WotlkDungeonOKActionContext::avoid_shadow_crash; - } - private: - static Action* attack_nadox_guardian(PlayerbotAI* ai) { return new AttackNadoxGuardianAction(ai); } - static Action* attack_jedoga_volunteer(PlayerbotAI* ai) { return new AttackJedogaVolunteerAction(ai); } - static Action* avoid_shadow_crash(PlayerbotAI* ai) { return new AvoidShadowCrashAction(ai); } -}; - -#endif diff --git a/src/Ai/Dungeon/OldKingdom/Strategy/OldKingdomStrategy.cpp b/src/Ai/Dungeon/OldKingdom/Strategy/OldKingdomStrategy.cpp index 484ea6ac48..ccabd457ca 100644 --- a/src/Ai/Dungeon/OldKingdom/Strategy/OldKingdomStrategy.cpp +++ b/src/Ai/Dungeon/OldKingdom/Strategy/OldKingdomStrategy.cpp @@ -1,11 +1,19 @@ #include "OldKingdomStrategy.h" +#include "CreateNextAction.h" +#include "OldKingdomActions.h" #include "OldKingdomMultipliers.h" void WotlkDungeonOKStrategy::InitTriggers(std::vector &triggers) { // Elder Nadox - triggers.push_back(new TriggerNode("nadox guardian", - { NextAction("attack nadox guardian", ACTION_RAID + 5) })); + triggers.push_back( + new TriggerNode( + "nadox guardian", + { + CreateNextAction(ACTION_RAID + 5.0f) + } + ) + ); // Prince Taldaram // Flame Orb spawns in melee, doesn't have a clear direction until it starts moving. @@ -13,14 +21,26 @@ void WotlkDungeonOKStrategy::InitTriggers(std::vector &triggers) // players anywhere near melee when it spawns // Jedoga Shadowseeker - triggers.push_back(new TriggerNode("jedoga volunteer", - { NextAction("attack jedoga volunteer", ACTION_RAID + 5) })); + triggers.push_back( + new TriggerNode( + "jedoga volunteer", + { + CreateNextAction(ACTION_RAID + 5.0f) + } + ) + ); // Herald Volazj // Trash mobs before him have a big telegraphed shadow crash spell, // this can be avoided and is intended to be dodged - triggers.push_back(new TriggerNode("shadow crash", - { NextAction("avoid shadow crash", ACTION_MOVE + 5) })); + triggers.push_back( + new TriggerNode( + "shadow crash", + { + CreateNextAction(ACTION_MOVE + 5.0f) + } + ) + ); // Volazj is not implemented properly in AC, insanity phase does nothing. // Amanitar (Heroic Only) diff --git a/src/Ai/Dungeon/OldKingdom/Trigger/OldKingdomTriggers.h b/src/Ai/Dungeon/OldKingdom/Trigger/OldKingdomTriggers.h index 2aa77986ee..cbb19ae742 100644 --- a/src/Ai/Dungeon/OldKingdom/Trigger/OldKingdomTriggers.h +++ b/src/Ai/Dungeon/OldKingdom/Trigger/OldKingdomTriggers.h @@ -2,9 +2,7 @@ #define _PLAYERBOT_WOTLKDUNGEONOKTRIGGERS_H #include "Trigger.h" -#include "PlayerbotAIConfig.h" #include "GenericTriggers.h" -#include "DungeonStrategyUtils.h" enum OldKingdomIDs { @@ -19,8 +17,6 @@ enum OldKingdomIDs SPELL_SHADOW_CRASH_H = 60848, }; -#define SPELL_SHADOW_CRASH DUNGEON_MODE(bot, SPELL_SHADOW_CRASH_N, SPELL_SHADOW_CRASH_H) - class NadoxGuardianTrigger : public Trigger { public: diff --git a/src/Ai/Dungeon/PitOfSaron/Action/PitOfSaronActions.cpp b/src/Ai/Dungeon/PitOfSaron/Action/PitOfSaronActions.cpp index f34b98462e..7053fc5b0d 100644 --- a/src/Ai/Dungeon/PitOfSaron/Action/PitOfSaronActions.cpp +++ b/src/Ai/Dungeon/PitOfSaron/Action/PitOfSaronActions.cpp @@ -1,9 +1,7 @@ #include "Playerbots.h" #include "PitOfSaronActions.h" -#include "PitOfSaronStrategy.h" -#include "SharedDefines.h" -bool IckAndKrickAction::Execute(Event event) +bool IckAndKrickAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "Ick"); if (!boss) @@ -26,7 +24,14 @@ bool IckAndKrickAction::Execute(Event event) bool pursuit = bot->HasAura(SPELL_PURSUIT) || (!botAI->IsTank(bot) && boss->HasUnitState(UNIT_STATE_CASTING) && boss->FindCurrentSpellBySpellId(SPELL_PURSUIT)); bool poisonNova = boss->HasUnitState(UNIT_STATE_CASTING) && (boss->FindCurrentSpellBySpellId(SPELL_POISON_NOVA_POS) || boss->FindCurrentSpellBySpellId(SPELL_POISON_NOVA_POS_HC)); - bool explosiveBarrage = orb || boss->HasUnitState(UNIT_STATE_CASTING) && (boss->FindCurrentSpellBySpellId(SPELL_EXPLOSIVE_BARRAGE_ICK) || boss->FindCurrentSpellBySpellId(SPELL_EXPLOSIVE_BARRAGE_KRICK)); + bool explosiveBarrage = orb + || ( + boss->HasUnitState(UNIT_STATE_CASTING) + && ( + boss->FindCurrentSpellBySpellId(SPELL_EXPLOSIVE_BARRAGE_ICK) + || boss->FindCurrentSpellBySpellId(SPELL_EXPLOSIVE_BARRAGE_KRICK) + ) + ); bool isTank = botAI->IsTank(bot); if (pursuit && Pursuit(pursuit, boss)) @@ -136,7 +141,7 @@ bool IckAndKrickAction::PoisonNova(bool poisonNova, Unit* boss) return false; } -bool IckAndKrickAction::ExplosiveBarrage(bool explosiveBarrage, Unit* boss) +bool IckAndKrickAction::ExplosiveBarrage(bool, Unit* boss) { std::vector orbs; Unit* closestOrb = nullptr; @@ -269,7 +274,7 @@ bool IckAndKrickAction::ExplosiveBarrage(bool explosiveBarrage, Unit* boss) return false; } -bool TyrannusAction::Execute(Event event) +bool TyrannusAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "scourgelord tyrannus"); if (!boss) diff --git a/src/Ai/Dungeon/PitOfSaron/Multiplier/PitOfSaronMultipliers.cpp b/src/Ai/Dungeon/PitOfSaron/Multiplier/PitOfSaronMultipliers.cpp index be36e480f2..f069787dbb 100644 --- a/src/Ai/Dungeon/PitOfSaron/Multiplier/PitOfSaronMultipliers.cpp +++ b/src/Ai/Dungeon/PitOfSaron/Multiplier/PitOfSaronMultipliers.cpp @@ -5,14 +5,14 @@ #include "MovementActions.h" #include "PitOfSaronTriggers.h" -float IckAndKrickMultiplier::GetValue(Action* action) +float IckAndKrickMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "ick"); if (!boss) return 1.0f; // Allow the IckAndKrickAction to run - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 1.0f; if (boss->HasUnitState(UNIT_STATE_CASTING) && (boss->FindCurrentSpellBySpellId(SPELL_POISON_NOVA_POS) || boss->FindCurrentSpellBySpellId(SPELL_POISON_NOVA_POS_HC)) && bot->GetExactDist2d(boss) < 20.0f) @@ -27,7 +27,7 @@ float IckAndKrickMultiplier::GetValue(Action* action) return 1.0f; } -float GarfrostMultiplier::GetValue(Action* action) +float GarfrostMultiplier::GetValue(Action&) { Unit* boss = AI_VALUE2(Unit*, "find target", "garfrost"); if (!boss) diff --git a/src/Ai/Dungeon/PitOfSaron/Multiplier/PitOfSaronMultipliers.h b/src/Ai/Dungeon/PitOfSaron/Multiplier/PitOfSaronMultipliers.h index bcafc01a43..52cc44413e 100644 --- a/src/Ai/Dungeon/PitOfSaron/Multiplier/PitOfSaronMultipliers.h +++ b/src/Ai/Dungeon/PitOfSaron/Multiplier/PitOfSaronMultipliers.h @@ -9,7 +9,7 @@ class IckAndKrickMultiplier : public Multiplier IckAndKrickMultiplier(PlayerbotAI* ai) : Multiplier(ai, "ick and krick") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class GarfrostMultiplier : public Multiplier @@ -17,7 +17,7 @@ class GarfrostMultiplier : public Multiplier public: GarfrostMultiplier(PlayerbotAI* ai) : Multiplier(ai, "garfrost") { } - float GetValue(Action* action) override; + float GetValue(Action& action) override; }; #endif diff --git a/src/Ai/Dungeon/PitOfSaron/PitOfSaronActionContext.h b/src/Ai/Dungeon/PitOfSaron/PitOfSaronActionContext.h deleted file mode 100644 index 816202a8a5..0000000000 --- a/src/Ai/Dungeon/PitOfSaron/PitOfSaronActionContext.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _PLAYERBOT_WOTLKDUNGEONPOSACTIONCONTEXT_H -#define _PLAYERBOT_WOTLKDUNGEONPOSACTIONCONTEXT_H - -#include "Action.h" -#include "NamedObjectContext.h" -#include "PitOfSaronActions.h" - -class WotlkDungeonPoSActionContext : public NamedObjectContext -{ - public: - WotlkDungeonPoSActionContext() - { - creators["ick and krick"] = &WotlkDungeonPoSActionContext::ick_and_krick; - creators["tyrannus"] = &WotlkDungeonPoSActionContext::tyrannus; - } - private: - static Action* ick_and_krick(PlayerbotAI* ai) { return new IckAndKrickAction(ai); } - static Action* tyrannus(PlayerbotAI* ai) { return new TyrannusAction(ai); } -}; - -#endif diff --git a/src/Ai/Dungeon/PitOfSaron/Strategy/PitOfSaronStrategy.cpp b/src/Ai/Dungeon/PitOfSaron/Strategy/PitOfSaronStrategy.cpp index 641af0a6d4..a42e0e9925 100644 --- a/src/Ai/Dungeon/PitOfSaron/Strategy/PitOfSaronStrategy.cpp +++ b/src/Ai/Dungeon/PitOfSaron/Strategy/PitOfSaronStrategy.cpp @@ -1,13 +1,27 @@ #include "PitOfSaronStrategy.h" +#include "CreateNextAction.h" +#include "PitOfSaronActions.h" #include "PitOfSaronMultipliers.h" void WotlkDungeonPoSStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("ick and krick", - { NextAction("ick and krick", ACTION_RAID + 5) })); + triggers.push_back( + new TriggerNode( + "ick and krick", + { + CreateNextAction(ACTION_RAID + 5.0f) + } + ) + ); - triggers.push_back(new TriggerNode("tyrannus", - { NextAction("tyrannus", ACTION_RAID + 5) })); + triggers.push_back( + new TriggerNode( + "tyrannus", + { + CreateNextAction(ACTION_RAID + 5.0f) + } + ) + ); } void WotlkDungeonPoSStrategy::InitMultipliers(std::vector& multipliers) diff --git a/src/Ai/Dungeon/TrialOfTheChampion/Action/TrialOfTheChampionActions.cpp b/src/Ai/Dungeon/TrialOfTheChampion/Action/TrialOfTheChampionActions.cpp index 92b687b292..5cdfb4f21a 100644 --- a/src/Ai/Dungeon/TrialOfTheChampion/Action/TrialOfTheChampionActions.cpp +++ b/src/Ai/Dungeon/TrialOfTheChampion/Action/TrialOfTheChampionActions.cpp @@ -1,15 +1,12 @@ #include "Playerbots.h" #include "TrialOfTheChampionActions.h" -#include "TrialOfTheChampionStrategy.h" #include "NearestNpcsValue.h" #include "ObjectAccessor.h" -#include "Timer.h" #include "Vehicle.h" #include "GenericSpellActions.h" #include "GenericActions.h" -#include -bool ToCLanceAction::Execute(Event event) +bool ToCLanceAction::Execute(Event) { // If already has lance equipped, do nothing if (bot->HasItemOrGemWithIdEquipped(ITEM_LANCE, 1)) @@ -58,10 +55,6 @@ bool ToCLanceAction::Execute(Event event) // If we found the lance, equip it if (lanceItem) { - // Store the lance's current position - uint8 srcBag = lanceItem->GetBagSlot(); - uint8 srcSlot = lanceItem->GetSlot(); - // First unequip current weapon if it exists if (oldWeapon) { @@ -105,7 +98,7 @@ bool ToCUELanceAction::Execute(Event event) return false; } -bool ToCMountedAction::Execute(Event event) +bool ToCMountedAction::Execute(Event) { Unit* vehicleBase = bot->GetVehicleBase(); Vehicle* vehicle = bot->GetVehicle(); @@ -179,7 +172,7 @@ bool ToCMountedAction::Execute(Event event) return false; } -bool ToCMountAction::Execute(Event event) +bool ToCMountAction::Execute(Event) { // do not switch vehicles yet if (bot->GetVehicle()) @@ -244,7 +237,7 @@ bool ToCMountAction::EnterVehicle(Unit* vehicleBase, bool moveIfFar) return true; } -bool ToCEadricAction::Execute(Event event) +bool ToCEadricAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "eadric the pure"); if (!boss) diff --git a/src/Ai/Dungeon/TrialOfTheChampion/Strategy/TrialOfTheChampionStrategy.cpp b/src/Ai/Dungeon/TrialOfTheChampion/Strategy/TrialOfTheChampionStrategy.cpp index bbccca71f3..df07cb7b27 100644 --- a/src/Ai/Dungeon/TrialOfTheChampion/Strategy/TrialOfTheChampionStrategy.cpp +++ b/src/Ai/Dungeon/TrialOfTheChampion/Strategy/TrialOfTheChampionStrategy.cpp @@ -1,21 +1,52 @@ #include "TrialOfTheChampionStrategy.h" -#include "TrialOfTheChampionMultipliers.h" +#include "CreateNextAction.h" +#include "TrialOfTheChampionActions.h" void WotlkDungeonToCStrategy::InitTriggers(std::vector &triggers) { - triggers.push_back(new TriggerNode("toc lance", - { NextAction("toc lance", ACTION_RAID + 5) })); - triggers.push_back(new TriggerNode("toc ue lance", - { NextAction("toc ue lance", ACTION_RAID + 2) })); - triggers.push_back(new TriggerNode("toc mount near", - { NextAction("toc mount", ACTION_RAID + 4) })); - triggers.push_back(new TriggerNode("toc mounted", - { NextAction("toc mounted", ACTION_RAID + 6) })); - triggers.push_back(new TriggerNode("toc eadric", - { NextAction("toc eadric", ACTION_RAID + 3) })); + triggers.push_back( + new TriggerNode( + "toc lance", + { + CreateNextAction(ACTION_RAID + 5.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "toc ue lance", + { + CreateNextAction(ACTION_RAID + 2.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "toc mount near", + { + CreateNextAction(ACTION_RAID + 4.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "toc mounted", + { + CreateNextAction(ACTION_RAID + 6.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "toc eadric", + { + CreateNextAction(ACTION_RAID + 3.0f) + } + ) + ); } -void WotlkDungeonToCStrategy::InitMultipliers(std::vector &multipliers) +void WotlkDungeonToCStrategy::InitMultipliers(std::vector&) { } diff --git a/src/Ai/Dungeon/TrialOfTheChampion/TrialOfTheChampionActionContext.h b/src/Ai/Dungeon/TrialOfTheChampion/TrialOfTheChampionActionContext.h deleted file mode 100644 index 21f877f241..0000000000 --- a/src/Ai/Dungeon/TrialOfTheChampion/TrialOfTheChampionActionContext.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef _PLAYERBOT_WOTLKDUNGEONTOCACTIONCONTEXT_H -#define _PLAYERBOT_WOTLKDUNGEONTOCACTIONCONTEXT_H - -#include "Action.h" -#include "NamedObjectContext.h" -#include "TrialOfTheChampionActions.h" - -class WotlkDungeonToCActionContext : public NamedObjectContext -{ - public: - WotlkDungeonToCActionContext() { - creators["toc lance"] = &WotlkDungeonToCActionContext::toc_lance; - creators["toc ue lance"] = &WotlkDungeonToCActionContext::toc_ue_lance; - creators["toc mount"] = &WotlkDungeonToCActionContext::toc_mount; - creators["toc mounted"] = &WotlkDungeonToCActionContext::toc_mounted; - creators["toc eadric"] = &WotlkDungeonToCActionContext::toc_eadric; - } - private: - static Action* toc_lance(PlayerbotAI* ai) { return new ToCLanceAction(ai); } - static Action* toc_ue_lance(PlayerbotAI* ai) { return new ToCUELanceAction(ai); } - static Action* toc_mount(PlayerbotAI* ai) { return new ToCMountAction(ai); } - static Action* toc_mounted(PlayerbotAI* ai) { return new ToCMountedAction(ai); } - static Action* toc_eadric(PlayerbotAI* ai) { return new ToCEadricAction(ai); } -}; - -#endif diff --git a/src/Ai/Dungeon/UtgardeKeep/Action/UtgardeKeepActions.cpp b/src/Ai/Dungeon/UtgardeKeep/Action/UtgardeKeepActions.cpp index 20a5f27b49..81865c750e 100644 --- a/src/Ai/Dungeon/UtgardeKeep/Action/UtgardeKeepActions.cpp +++ b/src/Ai/Dungeon/UtgardeKeep/Action/UtgardeKeepActions.cpp @@ -1,9 +1,8 @@ #include "Playerbots.h" #include "UtgardeKeepActions.h" -#include "UtgardeKeepStrategy.h" bool AttackFrostTombAction::isUseful() { return !botAI->IsHeal(bot); } -bool AttackFrostTombAction::Execute(Event event) +bool AttackFrostTombAction::Execute(Event) { Unit* frostTomb = nullptr; @@ -28,7 +27,7 @@ bool AttackFrostTombAction::Execute(Event event) } // TODO: Possibly add player stacking behaviour close to tank, to prevent Skarvald charging ranged -bool AttackDalronnAction::Execute(Event event) +bool AttackDalronnAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "dalronn the controller"); if (!boss) { return false; } @@ -40,7 +39,7 @@ bool AttackDalronnAction::Execute(Event event) return Attack(boss); } -bool IngvarStopCastingAction::Execute(Event event) +bool IngvarStopCastingAction::Execute(Event) { // Doesn't work, this action gets queued behind the current spell instead of interrupting it Unit* boss = AI_VALUE2(Unit*, "find target", "ingvar the plunderer"); @@ -64,7 +63,7 @@ bool IngvarStopCastingAction::Execute(Event event) } bool IngvarDodgeSmashAction::isUseful() { return !AI_VALUE2(bool, "behind", "current target"); } -bool IngvarDodgeSmashAction::Execute(Event event) +bool IngvarDodgeSmashAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "ingvar the plunderer"); if (!boss) { return false; } @@ -78,7 +77,7 @@ bool IngvarDodgeSmashAction::Execute(Event event) } bool IngvarSmashReturnAction::isUseful() { return AI_VALUE2(bool, "behind", "current target"); } -bool IngvarSmashReturnAction::Execute(Event event) +bool IngvarSmashReturnAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "ingvar the plunderer"); if (!boss) { return false; } diff --git a/src/Ai/Dungeon/UtgardeKeep/Multiplier/UtgardeKeepMultipliers.cpp b/src/Ai/Dungeon/UtgardeKeep/Multiplier/UtgardeKeepMultipliers.cpp index e9a411dac8..d7ffa8e3ea 100644 --- a/src/Ai/Dungeon/UtgardeKeep/Multiplier/UtgardeKeepMultipliers.cpp +++ b/src/Ai/Dungeon/UtgardeKeep/Multiplier/UtgardeKeepMultipliers.cpp @@ -4,13 +4,13 @@ #include "ChooseTargetActions.h" #include "UtgardeKeepTriggers.h" -float PrinceKelesethMultiplier::GetValue(Action* action) +float PrinceKelesethMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "prince keleseth"); if (!boss) { return 1.0f; } // Suppress auto-targeting behaviour only when a tomb is up - if (dynamic_cast(action)) + if (dynamic_cast(&action)) { GuidVector members = AI_VALUE(GuidVector, "group members"); for (auto& member : members) @@ -25,28 +25,28 @@ float PrinceKelesethMultiplier::GetValue(Action* action) return 1.0f; } -float SkarvaldAndDalronnMultiplier::GetValue(Action* action) +float SkarvaldAndDalronnMultiplier::GetValue(Action& action) { // Only need to deal with Dalronn here. If he's dead, just fall back to normal dps strat Unit* dalronn = AI_VALUE2(Unit*, "find target", "dalronn the controller"); if (!dalronn) { return 1.0f; } // Only suppress DpsAssistAction if Dalronn is alive - if (dalronn->isTargetableForAttack() && dynamic_cast(action)) + if (dalronn->isTargetableForAttack() && dynamic_cast(&action)) { return 0.0f; } return 1.0f; } -float IngvarThePlundererMultiplier::GetValue(Action* action) +float IngvarThePlundererMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "ingvar the plunderer"); bool isTank = botAI->IsTank(bot); if (!boss) { return 1.0f; } // Prevent movement actions overriding current movement, we're probably dodging a slam - if (isTank && bot->isMoving() && dynamic_cast(action)) + if (isTank && bot->isMoving() && dynamic_cast(&action)) { return 0.0f; } @@ -57,9 +57,9 @@ float IngvarThePlundererMultiplier::GetValue(Action* action) if (boss->FindCurrentSpellBySpellId(SPELL_STAGGERING_ROAR) || boss->FindCurrentSpellBySpellId(SPELL_DREADFUL_ROAR)) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) { - uint32 spellId = AI_VALUE2(uint32, "spell id", action->getName()); + uint32 spellId = AI_VALUE2(uint32, "spell id", action.getName()); SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); if (!spellInfo) { return 1.0f; } @@ -79,7 +79,7 @@ float IngvarThePlundererMultiplier::GetValue(Action* action) { // Prevent movement actions during smash which can mess up boss position. // Allow through IngvarDodgeSmashAction only, as well as any non-movement actions. - if (dynamic_cast(action) && !dynamic_cast(action)) + if (dynamic_cast(&action) && !dynamic_cast(&action)) { return 0.0f; } diff --git a/src/Ai/Dungeon/UtgardeKeep/Multiplier/UtgardeKeepMultipliers.h b/src/Ai/Dungeon/UtgardeKeep/Multiplier/UtgardeKeepMultipliers.h index e0b8e7af0c..d0cf0e06d7 100644 --- a/src/Ai/Dungeon/UtgardeKeep/Multiplier/UtgardeKeepMultipliers.h +++ b/src/Ai/Dungeon/UtgardeKeep/Multiplier/UtgardeKeepMultipliers.h @@ -9,7 +9,7 @@ class PrinceKelesethMultiplier : public Multiplier PrinceKelesethMultiplier(PlayerbotAI* ai) : Multiplier(ai, "prince keleseth") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class SkarvaldAndDalronnMultiplier : public Multiplier @@ -18,7 +18,7 @@ class SkarvaldAndDalronnMultiplier : public Multiplier SkarvaldAndDalronnMultiplier(PlayerbotAI* ai) : Multiplier(ai, "skarvald and dalronn") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class IngvarThePlundererMultiplier : public Multiplier @@ -27,7 +27,7 @@ class IngvarThePlundererMultiplier : public Multiplier IngvarThePlundererMultiplier(PlayerbotAI* ai) : Multiplier(ai, "ingvar the plunderer") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; #endif diff --git a/src/Ai/Dungeon/UtgardeKeep/Strategy/UtgardeKeepStrategy.cpp b/src/Ai/Dungeon/UtgardeKeep/Strategy/UtgardeKeepStrategy.cpp index 562cb8ec5f..70a2e39763 100644 --- a/src/Ai/Dungeon/UtgardeKeep/Strategy/UtgardeKeepStrategy.cpp +++ b/src/Ai/Dungeon/UtgardeKeep/Strategy/UtgardeKeepStrategy.cpp @@ -1,36 +1,80 @@ #include "UtgardeKeepStrategy.h" +#include "CreateNextAction.h" +#include "UtgardeKeepActions.h" #include "UtgardeKeepMultipliers.h" void WotlkDungeonUKStrategy::InitTriggers(std::vector &triggers) { // Prince Keleseth - triggers.push_back(new TriggerNode("keleseth frost tomb", - { NextAction("attack frost tomb", ACTION_RAID + 1) })); + triggers.push_back( + new TriggerNode( + "keleseth frost tomb", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); // Skarvald the Constructor & Dalronn the Controller - triggers.push_back(new TriggerNode("dalronn priority", - { NextAction("attack dalronn", ACTION_RAID + 1) })); + triggers.push_back( + new TriggerNode( + "dalronn priority", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); // Ingvar the Plunderer // Doesn't work yet, this action doesn't get processed until the existing cast finishes - // triggers.push_back(new TriggerNode("ingvar staggering roar", - // { NextAction("ingvar stop casting", ACTION_RAID + 1) })); + // triggers.push_back( + // new TriggerNode( + // "ingvar staggering roar", + // { + // CreateNextAction("ingvar stop casting", ACTION_RAID + 1) + // } + // ) + // ); // No easy way to check LoS here, the pillars do not seem to count as gameobjects. // Not implemented for now, unsure if this is needed as a good group can probably burst through the boss // and just eat the debuff. - // triggers.push_back(new TriggerNode("ingvar dreadful roar", - // { NextAction("ingvar hide los", ACTION_RAID + 1) })); - triggers.push_back(new TriggerNode("ingvar smash tank", - { NextAction("ingvar dodge smash", ACTION_MOVE + 5) })); - triggers.push_back(new TriggerNode("ingvar smash tank return", - { NextAction("ingvar smash return", ACTION_MOVE + 5) })); + // triggers.push_back( + // new TriggerNode( + // "ingvar dreadful roar", + // { + // CreateNextAction("ingvar hide los", ACTION_RAID + 1) + // } + // ) + // ); + triggers.push_back( + new TriggerNode( + "ingvar smash tank", + { + CreateNextAction(ACTION_MOVE + 5.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "ingvar smash tank return", + { + CreateNextAction(ACTION_MOVE + 5.0f) + } + ) + ); // Buggy... if not behind target, ai can get stuck running towards and away from target. // I think for ranged chars, a custom action should be added that doesn't attempt to run into melee. // This is a bandaid for now, needs to be improved. - triggers.push_back(new TriggerNode("not behind ingvar", - { NextAction("set behind", ACTION_MOVE + 1) })); + triggers.push_back( + new TriggerNode( + "not behind ingvar", + { + CreateNextAction(ACTION_MOVE + 1.0f) + } + ) + ); } diff --git a/src/Ai/Dungeon/UtgardeKeep/UtgardeKeepActionContext.h b/src/Ai/Dungeon/UtgardeKeep/UtgardeKeepActionContext.h deleted file mode 100644 index 0e51e56b40..0000000000 --- a/src/Ai/Dungeon/UtgardeKeep/UtgardeKeepActionContext.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef _PLAYERBOT_WOTLKDUNGEONUKACTIONCONTEXT_H -#define _PLAYERBOT_WOTLKDUNGEONUKACTIONCONTEXT_H - -#include "Action.h" -#include "NamedObjectContext.h" -#include "UtgardeKeepActions.h" - -class WotlkDungeonUKActionContext : public NamedObjectContext -{ - public: - WotlkDungeonUKActionContext() { - creators["attack frost tomb"] = &WotlkDungeonUKActionContext::attack_frost_tomb; - creators["attack dalronn"] = &WotlkDungeonUKActionContext::attack_dalronn; - creators["ingvar stop casting"] = &WotlkDungeonUKActionContext::ingvar_stop_casting; - creators["ingvar get behind"] = &WotlkDungeonUKActionContext::ingvar_get_behind; - // creators["ingvar hide los"] = &WotlkDungeonUKActionContext::ingvar_hide_los; - creators["ingvar dodge smash"] = &WotlkDungeonUKActionContext::ingvar_dodge_smash; - creators["ingvar smash return"] = &WotlkDungeonUKActionContext::ingvar_smash_return; - } - private: - static Action* attack_frost_tomb(PlayerbotAI* ai) { return new AttackFrostTombAction(ai); } - static Action* attack_dalronn(PlayerbotAI* ai) { return new AttackDalronnAction(ai); } - static Action* ingvar_stop_casting(PlayerbotAI* ai) { return new IngvarStopCastingAction(ai); } - static Action* ingvar_get_behind(PlayerbotAI* ai) { return new SetBehindTargetAction(ai); } - // static Action* ingvar_hide_los(PlayerbotAI* ai) { return new TellLosAction(ai); } - static Action* ingvar_dodge_smash(PlayerbotAI* ai) { return new IngvarDodgeSmashAction(ai); } - static Action* ingvar_smash_return(PlayerbotAI* ai) { return new IngvarSmashReturnAction(ai); } -}; - -#endif diff --git a/src/Ai/Dungeon/UtgardePinnacle/Action/UtgardePinnacleActions.cpp b/src/Ai/Dungeon/UtgardePinnacle/Action/UtgardePinnacleActions.cpp index f084ca15b6..0b09459e71 100644 --- a/src/Ai/Dungeon/UtgardePinnacle/Action/UtgardePinnacleActions.cpp +++ b/src/Ai/Dungeon/UtgardePinnacle/Action/UtgardePinnacleActions.cpp @@ -1,8 +1,7 @@ #include "Playerbots.h" #include "UtgardePinnacleActions.h" -#include "UtgardePinnacleStrategy.h" -bool AvoidFreezingCloudAction::Execute(Event event) +bool AvoidFreezingCloudAction::Execute(Event) { Unit* closestTrigger = nullptr; GuidVector objects = AI_VALUE(GuidVector, "nearest hostile npcs"); @@ -36,7 +35,7 @@ bool AvoidFreezingCloudAction::Execute(Event event) return false; } -bool AvoidSkadiWhirlwindAction::Execute(Event event) +bool AvoidSkadiWhirlwindAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "skadi the ruthless"); if (!boss) { return false; } diff --git a/src/Ai/Dungeon/UtgardePinnacle/Multiplier/UtgardePinnacleMultipliers.cpp b/src/Ai/Dungeon/UtgardePinnacle/Multiplier/UtgardePinnacleMultipliers.cpp index 9a950933e5..4c3401040a 100644 --- a/src/Ai/Dungeon/UtgardePinnacle/Multiplier/UtgardePinnacleMultipliers.cpp +++ b/src/Ai/Dungeon/UtgardePinnacle/Multiplier/UtgardePinnacleMultipliers.cpp @@ -1,12 +1,11 @@ #include "UtgardePinnacleMultipliers.h" #include "UtgardePinnacleActions.h" #include "GenericSpellActions.h" -#include "ChooseTargetActions.h" #include "MovementActions.h" #include "UtgardePinnacleTriggers.h" #include "Action.h" -float SkadiMultiplier::GetValue(Action* action) +float SkadiMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "skadi the ruthless"); if (!boss) { return 1.0f; } @@ -18,7 +17,7 @@ float SkadiMultiplier::GetValue(Action* action) { if (boss->HasAura(SPELL_SKADI_WHIRLWIND)) { - if (dynamic_cast(action) && !dynamic_cast(action)) + if (dynamic_cast(&action) && !dynamic_cast(&action)) { return 0.0f; } @@ -27,8 +26,8 @@ float SkadiMultiplier::GetValue(Action* action) else { // Bots tend to get stuck trying to attack the boss in the sky, not the adds on the ground - if (dynamic_cast(action) - && (action->GetTarget() == boss || action->GetTarget() == bossMount)) + if (dynamic_cast(&action) + && (action.GetTarget() == boss || action.GetTarget() == bossMount)) { return 0.0f; } @@ -73,7 +72,7 @@ float SkadiMultiplier::GetValue(Action* action) // if (cloudActive) // { - // if (dynamic_cast(action) && !dynamic_cast(action)) + // if (dynamic_cast(&action) && !dynamic_cast(&action)) // { // return 0.0f; // } @@ -83,14 +82,14 @@ float SkadiMultiplier::GetValue(Action* action) return 1.0f; } -float YmironMultiplier::GetValue(Action* action) +float YmironMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "king ymiron"); if (!boss) { return 1.0f; } if (boss->FindCurrentSpellBySpellId(SPELL_BANE) || boss->HasAura(SPELL_BANE)) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) { return 0.0f; } diff --git a/src/Ai/Dungeon/UtgardePinnacle/Multiplier/UtgardePinnacleMultipliers.h b/src/Ai/Dungeon/UtgardePinnacle/Multiplier/UtgardePinnacleMultipliers.h index 06cb857838..67175a27fd 100644 --- a/src/Ai/Dungeon/UtgardePinnacle/Multiplier/UtgardePinnacleMultipliers.h +++ b/src/Ai/Dungeon/UtgardePinnacle/Multiplier/UtgardePinnacleMultipliers.h @@ -9,7 +9,7 @@ class SkadiMultiplier : public Multiplier SkadiMultiplier(PlayerbotAI* ai) : Multiplier(ai, "skadi the ruthless") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class YmironMultiplier : public Multiplier @@ -18,7 +18,7 @@ class YmironMultiplier : public Multiplier YmironMultiplier(PlayerbotAI* ai) : Multiplier(ai, "king ymiron") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; #endif diff --git a/src/Ai/Dungeon/UtgardePinnacle/Strategy/UtgardePinnacleStrategy.cpp b/src/Ai/Dungeon/UtgardePinnacle/Strategy/UtgardePinnacleStrategy.cpp index fe104f34fb..29ea8f2807 100644 --- a/src/Ai/Dungeon/UtgardePinnacle/Strategy/UtgardePinnacleStrategy.cpp +++ b/src/Ai/Dungeon/UtgardePinnacle/Strategy/UtgardePinnacleStrategy.cpp @@ -1,4 +1,7 @@ #include "UtgardePinnacleStrategy.h" +#include "ChooseTargetActions.h" +#include "CreateNextAction.h" +#include "UtgardePinnacleActions.h" #include "UtgardePinnacleMultipliers.h" void WotlkDungeonUPStrategy::InitTriggers(std::vector &triggers) @@ -9,15 +12,33 @@ void WotlkDungeonUPStrategy::InitTriggers(std::vector &triggers) // Skadi the Ruthless // TODO: Harpoons launchable via GameObject. For now players should do them - triggers.push_back(new TriggerNode("freezing cloud", - { NextAction("avoid freezing cloud", ACTION_RAID + 5) })); - triggers.push_back(new TriggerNode("skadi whirlwind", - { NextAction("avoid skadi whirlwind", ACTION_RAID + 4) })); + triggers.push_back( + new TriggerNode( + "freezing cloud", + { + CreateNextAction(ACTION_RAID + 5.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "skadi whirlwind", + { + CreateNextAction(ACTION_RAID + 4.0f) + } + ) + ); // King Ymiron // May need to avoid orb.. unclear if the generic avoid AoE does this well - triggers.push_back(new TriggerNode("ymiron bane", - { NextAction("stop attack", ACTION_RAID + 5) })); + triggers.push_back( + new TriggerNode( + "ymiron bane", + { + CreateNextAction(ACTION_RAID + 5.0f) + } + ) + ); } void WotlkDungeonUPStrategy::InitMultipliers(std::vector &multipliers) diff --git a/src/Ai/Dungeon/UtgardePinnacle/UtgardePinnacleActionContext.h b/src/Ai/Dungeon/UtgardePinnacle/UtgardePinnacleActionContext.h deleted file mode 100644 index 9e7532b9ae..0000000000 --- a/src/Ai/Dungeon/UtgardePinnacle/UtgardePinnacleActionContext.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _PLAYERBOT_WOTLKDUNGEONUPACTIONCONTEXT_H -#define _PLAYERBOT_WOTLKDUNGEONUPACTIONCONTEXT_H - -#include "Action.h" -#include "NamedObjectContext.h" -#include "UtgardePinnacleActions.h" - -class WotlkDungeonUPActionContext : public NamedObjectContext -{ - public: - WotlkDungeonUPActionContext() { - creators["avoid freezing cloud"] = &WotlkDungeonUPActionContext::avoid_freezing_cloud; - creators["avoid skadi whirlwind"] = &WotlkDungeonUPActionContext::avoid_whirlwind; - creators["stop attack"] = &WotlkDungeonUPActionContext::stop_attack; - } - private: - static Action* avoid_freezing_cloud(PlayerbotAI* ai) { return new AvoidFreezingCloudAction(ai); } - static Action* avoid_whirlwind(PlayerbotAI* ai) { return new AvoidSkadiWhirlwindAction(ai); } - static Action* stop_attack(PlayerbotAI* ai) { return new DropTargetAction(ai); } -}; - -#endif diff --git a/src/Ai/Dungeon/VioletHold/Action/VioletHoldActions.cpp b/src/Ai/Dungeon/VioletHold/Action/VioletHoldActions.cpp index b590642d8b..157e24b2de 100644 --- a/src/Ai/Dungeon/VioletHold/Action/VioletHoldActions.cpp +++ b/src/Ai/Dungeon/VioletHold/Action/VioletHoldActions.cpp @@ -1,8 +1,7 @@ #include "Playerbots.h" #include "VioletHoldActions.h" -#include "VioletHoldStrategy.h" -bool AttackErekemAction::Execute(Event event) +bool AttackErekemAction::Execute(Event) { // Focus boss first, adds after Unit* boss = AI_VALUE2(Unit*, "find target", "erekem"); @@ -15,7 +14,7 @@ bool AttackErekemAction::Execute(Event event) return false; } -bool AttackIchorGlobuleAction::Execute(Event event) +bool AttackIchorGlobuleAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "ichoron"); if (!boss) { return false; } @@ -60,7 +59,7 @@ bool AttackIchorGlobuleAction::Execute(Event event) return false; } -bool AttackVoidSentryAction::Execute(Event event) +bool AttackVoidSentryAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "zuramat the obliterator"); if (!boss) { return false; } @@ -96,7 +95,7 @@ bool AttackVoidSentryAction::Execute(Event event) return false; } -bool StopAttackAction::Execute(Event event) +bool StopAttackAction::Execute(Event) { return bot->AttackStop(); } diff --git a/src/Ai/Dungeon/VioletHold/Multiplier/VioletHoldMultipliers.cpp b/src/Ai/Dungeon/VioletHold/Multiplier/VioletHoldMultipliers.cpp index 3d3a13cd0f..ca721a4219 100644 --- a/src/Ai/Dungeon/VioletHold/Multiplier/VioletHoldMultipliers.cpp +++ b/src/Ai/Dungeon/VioletHold/Multiplier/VioletHoldMultipliers.cpp @@ -1,55 +1,55 @@ #include "VioletHoldMultipliers.h" -#include "VioletHoldActions.h" #include "GenericSpellActions.h" #include "ChooseTargetActions.h" #include "MovementActions.h" #include "VioletHoldTriggers.h" #include "Action.h" +#include "Playerbots.h" -float ErekemMultiplier::GetValue(Action* action) +float ErekemMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "erekem"); if (!boss || !botAI->IsDps(bot)) { return 1.0f; } - if (dynamic_cast(action)) + if (dynamic_cast(&action)) { return 0.0f; } - if (action->getThreatType() == Action::ActionThreatType::Aoe) + if (action.getThreatType() == Action::ActionThreatType::Aoe) { return 0.0f; } return 1.0f; } -float IchoronMultiplier::GetValue(Action* action) +float IchoronMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "ichoron"); if (!boss) { return 1.0f; } - if (dynamic_cast(action) - || dynamic_cast(action) - || dynamic_cast(action)) + if (dynamic_cast(&action) + || dynamic_cast(&action) + || dynamic_cast(&action)) { return 0.0f; } return 1.0f; } -float ZuramatMultiplier::GetValue(Action* action) +float ZuramatMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "zuramat the obliterator"); if (!boss) { return 1.0f; } if (bot->HasAura(SPELL_VOID_SHIFTED)) { - if (dynamic_cast(action) || dynamic_cast(action)) + if (dynamic_cast(&action) || dynamic_cast(&action)) { return 0.0f; } } - if (boss->HasAura(SPELL_SHROUD_OF_DARKNESS) && dynamic_cast(action)) + if (boss->HasAura(SPELL_SHROUD_OF_DARKNESS) && dynamic_cast(&action)) { return 0.0f; } diff --git a/src/Ai/Dungeon/VioletHold/Multiplier/VioletHoldMultipliers.h b/src/Ai/Dungeon/VioletHold/Multiplier/VioletHoldMultipliers.h index 67952a16b3..5d4ba0ab2d 100644 --- a/src/Ai/Dungeon/VioletHold/Multiplier/VioletHoldMultipliers.h +++ b/src/Ai/Dungeon/VioletHold/Multiplier/VioletHoldMultipliers.h @@ -9,7 +9,7 @@ class ErekemMultiplier : public Multiplier ErekemMultiplier(PlayerbotAI* ai) : Multiplier(ai, "erekem") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class IchoronMultiplier : public Multiplier @@ -18,7 +18,7 @@ class IchoronMultiplier : public Multiplier IchoronMultiplier(PlayerbotAI* ai) : Multiplier(ai, "ichoron") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class ZuramatMultiplier : public Multiplier @@ -27,7 +27,7 @@ class ZuramatMultiplier : public Multiplier ZuramatMultiplier(PlayerbotAI* ai) : Multiplier(ai, "zuramat the obliterator") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; #endif diff --git a/src/Ai/Dungeon/VioletHold/Strategy/VioletHoldStrategy.cpp b/src/Ai/Dungeon/VioletHold/Strategy/VioletHoldStrategy.cpp index ffc00e3063..d10263a349 100644 --- a/src/Ai/Dungeon/VioletHold/Strategy/VioletHoldStrategy.cpp +++ b/src/Ai/Dungeon/VioletHold/Strategy/VioletHoldStrategy.cpp @@ -1,19 +1,32 @@ #include "VioletHoldStrategy.h" +#include "VioletHoldActions.h" #include "VioletHoldMultipliers.h" void WotlkDungeonVHStrategy::InitTriggers(std::vector &triggers) { // Erekem // This boss has many purgable buffs, purging/dispels could be merged into generic strats though - triggers.push_back(new TriggerNode("erekem target", - { NextAction("attack erekem", ACTION_RAID + 1) })); + triggers.push_back( + new TriggerNode( + "erekem target", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); // Moragg // TODO: This guy has Optic Link which may require moving, add if needed // Ichoron - triggers.push_back(new TriggerNode("ichoron target", - { NextAction("attack ichor globule", ACTION_RAID + 1) })); + triggers.push_back( + new TriggerNode( + "ichoron target", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); // Xevozz // TODO: Revisit in heroics, waypoints back and forth on stairs. Need to test with double beacon spawn @@ -22,14 +35,32 @@ void WotlkDungeonVHStrategy::InitTriggers(std::vector &triggers) // Tank & spank // Zuramat the Obliterator - triggers.push_back(new TriggerNode("shroud of darkness", - { NextAction("stop attack", ACTION_HIGH + 5) })); - triggers.push_back(new TriggerNode("void shift", - { NextAction("attack void sentry", ACTION_RAID + 1) })); + triggers.push_back( + new TriggerNode( + "shroud of darkness", + { + CreateNextAction(ACTION_HIGH + 5.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "void shift", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); // Cyanigosa - triggers.push_back(new TriggerNode("cyanigosa positioning", - { NextAction("rear flank", ACTION_MOVE + 5) })); + triggers.push_back( + new TriggerNode( + "cyanigosa positioning", + { + CreateNextAction(ACTION_MOVE + 5.0f) + } + ) + ); } void WotlkDungeonVHStrategy::InitMultipliers(std::vector &multipliers) diff --git a/src/Ai/Dungeon/VioletHold/VioletHoldActionContext.h b/src/Ai/Dungeon/VioletHold/VioletHoldActionContext.h deleted file mode 100644 index 902332f158..0000000000 --- a/src/Ai/Dungeon/VioletHold/VioletHoldActionContext.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef _PLAYERBOT_WOTLKDUNGEONVHACTIONCONTEXT_H -#define _PLAYERBOT_WOTLKDUNGEONVHACTIONCONTEXT_H - -#include "Action.h" -#include "NamedObjectContext.h" -#include "VioletHoldActions.h" - -class WotlkDungeonVHActionContext : public NamedObjectContext -{ - public: - WotlkDungeonVHActionContext() { - creators["attack erekem"] = &WotlkDungeonVHActionContext::attack_erekem; - creators["attack ichor globule"] = &WotlkDungeonVHActionContext::attack_ichor_globule; - creators["attack void sentry"] = &WotlkDungeonVHActionContext::attack_void_sentry; - creators["stop attack"] = &WotlkDungeonVHActionContext::stop_attack; - } - private: - static Action* attack_erekem(PlayerbotAI* ai) { return new AttackErekemAction(ai); } - static Action* attack_ichor_globule(PlayerbotAI* ai) { return new AttackIchorGlobuleAction(ai); } - static Action* attack_void_sentry(PlayerbotAI* ai) { return new AttackVoidSentryAction(ai); } - static Action* stop_attack(PlayerbotAI* ai) { return new StopAttackAction(ai); } -}; - -#endif diff --git a/src/Ai/Raid/Aq20/Action/RaidAq20Actions.cpp b/src/Ai/Raid/Aq20/Action/RaidAq20Actions.cpp index 1bf33147f8..01ae38aa54 100644 --- a/src/Ai/Raid/Aq20/Action/RaidAq20Actions.cpp +++ b/src/Ai/Raid/Aq20/Action/RaidAq20Actions.cpp @@ -1,48 +1,63 @@ #include "RaidAq20Actions.h" -#include "Playerbots.h" #include "RaidAq20Utils.h" -bool Aq20UseCrystalAction::Execute(Event event) +bool Aq20UseCrystalAction::Execute(Event) { - if (Unit* boss = AI_VALUE2(Unit*, "find target", "ossirian the unscarred")) + Unit* const boss = context->GetValue("find target", "ossirian the unscarred")->Get(); + + if (boss == nullptr) + { + return false; + } + + const GameObject* const crystal = RaidAq20Utils::GetNearestCrystal(*boss); + + if (crystal == nullptr) { - if (GameObject* crystal = RaidAq20Utils::GetNearestCrystal(boss)) - { - float botDist = bot->GetDistance(crystal); - if (botDist > INTERACTION_DISTANCE) - return MoveTo(bot->GetMapId(), - crystal->GetPositionX() + frand(-3.5f, 3.5f), - crystal->GetPositionY() + frand(-3.5f, 3.5f), - crystal->GetPositionZ()); - - // if we're already in range just wait here until it's time to activate crystal - SetNextMovementDelay(500); - - // don't activate crystal if boss too far or its already been activated - if (boss->GetDistance(crystal) > 25.0f || - crystal->HasGameObjectFlag(GO_FLAG_IN_USE)) - return false; - - // don't activate crystal if boss doesn't have buff yet AND isn't going to have it soon - // (though ideally bot should activate it ~5 seconds early due to time it takes for - // crystal to activate and remove buff) - if (!RaidAq20Utils::IsOssirianBuffActive(boss) && - RaidAq20Utils::GetOssirianDebuffTimeRemaining(boss) > 5000) - return false; - - // this makes crystal do its animation (then disappear after) - WorldPacket data1(CMSG_GAMEOBJ_USE); - data1 << crystal->GetGUID(); - bot->GetSession()->HandleGameObjectUseOpcode(data1); - - // this makes crystal actually remove the buff and put on debuff (took a while to figure that out) - WorldPacket data2(CMSG_GAMEOBJ_USE); - data2 << crystal->GetGUID(); - bot->GetSession()->HandleGameobjectReportUse(data2); - - return true; - } + return false; } - return false; + + float botDist = this->bot->GetDistance(crystal); + + if (botDist > INTERACTION_DISTANCE) + { + return MoveTo( + this->bot->GetMapId(), + crystal->GetPositionX() + frand(-3.5f, 3.5f), + crystal->GetPositionY() + frand(-3.5f, 3.5f), + crystal->GetPositionZ() + ); + } + + // if we're already in range just wait here until it's time to activate crystal + this->SetNextMovementDelay(500); + + // don't activate crystal if boss too far or its already been activated + if (boss->GetDistance(crystal) > 25.0f + || crystal->HasGameObjectFlag(GO_FLAG_IN_USE)) + { + return false; + } + + // don't activate crystal if boss doesn't have buff yet AND isn't going to have it soon + // (though ideally bot should activate it ~5 seconds early due to time it takes for + // crystal to activate and remove buff) + if (!RaidAq20Utils::IsOssirianBuffActive(*boss) && + RaidAq20Utils::GetOssirianDebuffTimeRemaining(*boss) > 5000) + { + return false; + } + + // this makes crystal do its animation (then disappear after) + WorldPacket data1(CMSG_GAMEOBJ_USE); + data1 << crystal->GetGUID(); + bot->GetSession()->HandleGameObjectUseOpcode(data1); + + // this makes crystal actually remove the buff and put on debuff (took a while to figure that out) + WorldPacket data2(CMSG_GAMEOBJ_USE); + data2 << crystal->GetGUID(); + bot->GetSession()->HandleGameobjectReportUse(data2); + + return true; } diff --git a/src/Ai/Raid/Aq20/RaidAq20ActionContext.h b/src/Ai/Raid/Aq20/RaidAq20ActionContext.h deleted file mode 100644 index ea3afcf410..0000000000 --- a/src/Ai/Raid/Aq20/RaidAq20ActionContext.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef _PLAYERBOT_RAIDAQ20ACTIONCONTEXT_H -#define _PLAYERBOT_RAIDAQ20ACTIONCONTEXT_H - -#include "Action.h" -#include "NamedObjectContext.h" -#include "RaidAq20Actions.h" - -class RaidAq20ActionContext : public NamedObjectContext -{ -public: - RaidAq20ActionContext() - { - creators["aq20 use crystal"] = &RaidAq20ActionContext::use_crystal; - } - -private: - static Action* use_crystal(PlayerbotAI* ai) { return new Aq20UseCrystalAction(ai); } -}; - -#endif diff --git a/src/Ai/Raid/Aq20/Strategy/RaidAq20Strategy.cpp b/src/Ai/Raid/Aq20/Strategy/RaidAq20Strategy.cpp index 93e0462caf..1d05dfd95e 100644 --- a/src/Ai/Raid/Aq20/Strategy/RaidAq20Strategy.cpp +++ b/src/Ai/Raid/Aq20/Strategy/RaidAq20Strategy.cpp @@ -1,11 +1,17 @@ #include "RaidAq20Strategy.h" +#include "CreateNextAction.h" +#include "RaidAq20Actions.h" #include "Strategy.h" void RaidAq20Strategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("aq20 move to crystal", - { NextAction("aq20 use crystal", ACTION_RAID) })); - + new TriggerNode( + "aq20 move to crystal", + { + CreateNextAction(ACTION_RAID) + } + ) + ); } diff --git a/src/Ai/Raid/Aq20/Trigger/RaidAq20Triggers.cpp b/src/Ai/Raid/Aq20/Trigger/RaidAq20Triggers.cpp index 1a580d6bd3..40f95c9369 100644 --- a/src/Ai/Raid/Aq20/Trigger/RaidAq20Triggers.cpp +++ b/src/Ai/Raid/Aq20/Trigger/RaidAq20Triggers.cpp @@ -1,36 +1,52 @@ #include "RaidAq20Triggers.h" -#include "SharedDefines.h" #include "RaidAq20Utils.h" bool Aq20MoveToCrystalTrigger::IsActive() { - if (Unit* boss = AI_VALUE2(Unit*, "find target", "ossirian the unscarred")) + Unit* const boss = context->GetValue("find target", "ossirian the unscarred")->Get(); + + if (boss == nullptr) { - if (boss->IsInCombat()) + return false; + } + + if (!boss->IsInCombat()) + { + return false; + } + + // if buff is active move to crystal + if (RaidAq20Utils::IsOssirianBuffActive(*boss)) + { + return true; + } + + // if buff is not active a debuff will be, buff becomes active once debuff expires + // so move to crystal when debuff almost done, or based debuff time left and + // distance bot is from crystal (ie: start moving early enough to make it) + int32_t debuffTimeRemaining = RaidAq20Utils::GetOssirianDebuffTimeRemaining(*boss); + + if (debuffTimeRemaining < 5000) + { + return true; + } + + if (debuffTimeRemaining < 30000) + { + const GameObject* const crystal = RaidAq20Utils::GetNearestCrystal(*boss); + + if (crystal == nullptr) { - // if buff is active move to crystal - if (RaidAq20Utils::IsOssirianBuffActive(boss)) - return true; - - // if buff is not active a debuff will be, buff becomes active once debuff expires - // so move to crystal when debuff almost done, or based debuff time left and - // distance bot is from crystal (ie: start moving early enough to make it) - int32 debuffTimeRemaining = RaidAq20Utils::GetOssirianDebuffTimeRemaining(boss); - if (debuffTimeRemaining < 5000) - return true; - if (debuffTimeRemaining < 30000) - { - if (GameObject* crystal = RaidAq20Utils::GetNearestCrystal(boss)) - { - float botDist = bot->GetDistance(crystal); - float timeToReach = botDist / bot->GetSpeed(MOVE_RUN); - // bot should ideally activate crystal a ~5 seconds early (due to time it takes for crystal - // to activate) so aim to get there in time to do so - return debuffTimeRemaining - 5000 < timeToReach * 1000.0f; - } - } + return false; } + + float botDist = this->bot->GetDistance(crystal); + float timeToReach = botDist / this->bot->GetSpeed(MOVE_RUN); + // bot should ideally activate crystal a ~5 seconds early (due to time it takes for crystal + // to activate) so aim to get there in time to do so + return debuffTimeRemaining - 5000 < timeToReach * 1000.0f; } + return false; } diff --git a/src/Ai/Raid/Aq20/Util/RaidAq20Utils.cpp b/src/Ai/Raid/Aq20/Util/RaidAq20Utils.cpp index 41637af7b4..fe005820a5 100644 --- a/src/Ai/Raid/Aq20/Util/RaidAq20Utils.cpp +++ b/src/Ai/Raid/Aq20/Util/RaidAq20Utils.cpp @@ -6,33 +6,43 @@ uint32 const OSSIRIAN_BUFF = 25176; uint32 const OSSIRIAN_DEBUFFS[] = {25177, 25178, 25180, 25181, 25183}; uint32 const OSSIRIAN_CRYSTAL_GO_ENTRY = 180619; -bool RaidAq20Utils::IsOssirianBuffActive(Unit* ossirian) +bool RaidAq20Utils::IsOssirianBuffActive(Unit& ossirian) { - return ossirian && ossirian->HasAura(OSSIRIAN_BUFF); + return ossirian.HasAura(OSSIRIAN_BUFF); } -int32 RaidAq20Utils::GetOssirianDebuffTimeRemaining(Unit* ossirian) +int32_t RaidAq20Utils::GetOssirianDebuffTimeRemaining(Unit& ossirian) { - int32 retVal = 0xffffff; - if (ossirian) + int32_t retVal = 0xffffff; + + for (uint32_t debuff : OSSIRIAN_DEBUFFS) { - for (uint32 debuff : OSSIRIAN_DEBUFFS) + const AuraApplication* const auraApplication = ossirian.GetAuraApplication(debuff); + + if (auraApplication == nullptr) + { + continue; + } + + const Aura* const aura = auraApplication->GetBase(); + + if (aura == nullptr) { - if (AuraApplication* auraApplication = ossirian->GetAuraApplication(debuff)) - { - if (Aura* aura = auraApplication->GetBase()) - { - int32 duration = aura->GetDuration(); - if (retVal > duration) - retVal = duration; - } - } + continue; + } + + int32_t duration = aura->GetDuration(); + + if (retVal > duration) + { + retVal = duration; } } + return retVal; } -GameObject* RaidAq20Utils::GetNearestCrystal(Unit* ossirian) +GameObject* RaidAq20Utils::GetNearestCrystal(Unit& ossirian) { - return ossirian ? ossirian->FindNearestGameObject(OSSIRIAN_CRYSTAL_GO_ENTRY, 200.0f) : nullptr; + return ossirian.FindNearestGameObject(OSSIRIAN_CRYSTAL_GO_ENTRY, 200.0f); } diff --git a/src/Ai/Raid/Aq20/Util/RaidAq20Utils.h b/src/Ai/Raid/Aq20/Util/RaidAq20Utils.h index b78340d0e1..bfa6e43c48 100644 --- a/src/Ai/Raid/Aq20/Util/RaidAq20Utils.h +++ b/src/Ai/Raid/Aq20/Util/RaidAq20Utils.h @@ -7,9 +7,9 @@ class RaidAq20Utils { public: - static bool IsOssirianBuffActive(Unit* ossirian); - static int32 GetOssirianDebuffTimeRemaining(Unit* ossirian); - static GameObject* GetNearestCrystal(Unit* ossirian); + static bool IsOssirianBuffActive(Unit& ossirian); + static int32 GetOssirianDebuffTimeRemaining(Unit& ossirian); + static GameObject* GetNearestCrystal(Unit& ossirian); }; #endif diff --git a/src/Ai/Raid/BlackwingLair/Action/RaidBwlActions.cpp b/src/Ai/Raid/BlackwingLair/Action/RaidBwlActions.cpp index 54b21791e8..795f6c9e89 100644 --- a/src/Ai/Raid/BlackwingLair/Action/RaidBwlActions.cpp +++ b/src/Ai/Raid/BlackwingLair/Action/RaidBwlActions.cpp @@ -2,7 +2,7 @@ #include "Playerbots.h" -bool BwlOnyxiaScaleCloakAuraCheckAction::Execute(Event event) +bool BwlOnyxiaScaleCloakAuraCheckAction::Execute(Event) { bot->AddAura(22683, bot); return true; @@ -10,7 +10,7 @@ bool BwlOnyxiaScaleCloakAuraCheckAction::Execute(Event event) bool BwlOnyxiaScaleCloakAuraCheckAction::isUseful() { return !bot->HasAura(22683); } -bool BwlTurnOffSuppressionDeviceAction::Execute(Event event) +bool BwlTurnOffSuppressionDeviceAction::Execute(Event) { GuidVector gos = AI_VALUE(GuidVector, "nearest game objects"); for (GuidVector::iterator i = gos.begin(); i != gos.end(); i++) @@ -29,4 +29,4 @@ bool BwlTurnOffSuppressionDeviceAction::Execute(Event event) return true; } -bool BwlUseHourglassSandAction::Execute(Event event) { return botAI->CastSpell(23645, bot); } +bool BwlUseHourglassSandAction::Execute(Event) { return botAI->CastSpell(23645, bot); } diff --git a/src/Ai/Raid/BlackwingLair/RaidBwlActionContext.h b/src/Ai/Raid/BlackwingLair/RaidBwlActionContext.h deleted file mode 100644 index 7b73f410ff..0000000000 --- a/src/Ai/Raid/BlackwingLair/RaidBwlActionContext.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef _PLAYERBOT_RAIDBWLACTIONCONTEXT_H -#define _PLAYERBOT_RAIDBWLACTIONCONTEXT_H - -#include "Action.h" -#include "NamedObjectContext.h" -#include "RaidBwlActions.h" - -class RaidBwlActionContext : public NamedObjectContext -{ -public: - RaidBwlActionContext() - { - creators["bwl check onyxia scale cloak"] = &RaidBwlActionContext::bwl_check_onyxia_scale_cloak; - creators["bwl turn off suppression device"] = &RaidBwlActionContext::bwl_turn_off_suppression_device; - creators["bwl use hourglass sand"] = &RaidBwlActionContext::bwl_use_hourglass_sand; - } - -private: - static Action* bwl_check_onyxia_scale_cloak(PlayerbotAI* botAI) { return new BwlOnyxiaScaleCloakAuraCheckAction(botAI); } - static Action* bwl_turn_off_suppression_device(PlayerbotAI* botAI) { return new BwlTurnOffSuppressionDeviceAction(botAI); } - static Action* bwl_use_hourglass_sand(PlayerbotAI* botAI) { return new BwlUseHourglassSandAction(botAI); } -}; - -#endif diff --git a/src/Ai/Raid/BlackwingLair/Strategy/RaidBwlStrategy.cpp b/src/Ai/Raid/BlackwingLair/Strategy/RaidBwlStrategy.cpp index c65a80ecba..e864916826 100644 --- a/src/Ai/Raid/BlackwingLair/Strategy/RaidBwlStrategy.cpp +++ b/src/Ai/Raid/BlackwingLair/Strategy/RaidBwlStrategy.cpp @@ -1,15 +1,35 @@ #include "RaidBwlStrategy.h" +#include "CreateNextAction.h" +#include "RaidBwlActions.h" #include "Strategy.h" void RaidBwlStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("often", - { NextAction("bwl check onyxia scale cloak", ACTION_RAID) })); + triggers.push_back( + new TriggerNode( + "often", + { + CreateNextAction(ACTION_RAID) + } + ) + ); - triggers.push_back(new TriggerNode("bwl suppression device", - { NextAction("bwl turn off suppression device", ACTION_RAID) })); + triggers.push_back( + new TriggerNode( + "bwl suppression device", + { + CreateNextAction(ACTION_RAID) + } + ) + ); - triggers.push_back(new TriggerNode("bwl affliction bronze", - { NextAction("bwl use hourglass sand", ACTION_RAID) })); + triggers.push_back( + new TriggerNode( + "bwl affliction bronze", + { + CreateNextAction(ACTION_RAID) + } + ) + ); } diff --git a/src/Ai/Raid/EyeOfEternity/Action/RaidEoEActions.cpp b/src/Ai/Raid/EyeOfEternity/Action/RaidEoEActions.cpp index 3547388426..0f47adda71 100644 --- a/src/Ai/Raid/EyeOfEternity/Action/RaidEoEActions.cpp +++ b/src/Ai/Raid/EyeOfEternity/Action/RaidEoEActions.cpp @@ -2,7 +2,7 @@ #include "RaidEoEActions.h" #include "RaidEoETriggers.h" -bool MalygosPositionAction::Execute(Event event) +bool MalygosPositionAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "malygos"); if (!boss) { return false; } @@ -65,7 +65,7 @@ bool MalygosPositionAction::Execute(Event event) return false; } -bool MalygosTargetAction::Execute(Event event) +bool MalygosTargetAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "malygos"); if (!boss) { return false; } @@ -229,7 +229,7 @@ bool EoEFlyDrakeAction::isPossible() Unit* vehicleBase = bot->GetVehicleBase(); return (vehicleBase && vehicleBase->GetEntry() == NPC_WYRMREST_SKYTALON); } -bool EoEFlyDrakeAction::Execute(Event event) +bool EoEFlyDrakeAction::Execute(Event) { Player* master = botAI->GetMaster(); if (!master) { return false; } @@ -279,7 +279,7 @@ bool EoEDrakeAttackAction::isPossible() return (vehicleBase && vehicleBase->GetEntry() == NPC_WYRMREST_SKYTALON); } -bool EoEDrakeAttackAction::Execute(Event event) +bool EoEDrakeAttackAction::Execute(Event) { vehicleBase = bot->GetVehicleBase(); if (!vehicleBase) @@ -367,8 +367,6 @@ bool EoEDrakeAttackAction::DrakeDpsAction(Unit* target) Unit* vehicleBase = bot->GetVehicleBase(); if (!vehicleBase) { return false; } - Vehicle* veh = bot->GetVehicle(); - uint8 comboPoints = vehicleBase->GetComboPoints(target); if (comboPoints >= 2) { diff --git a/src/Ai/Raid/EyeOfEternity/Multiplier/RaidEoEMultipliers.cpp b/src/Ai/Raid/EyeOfEternity/Multiplier/RaidEoEMultipliers.cpp index a2d8a3f1df..5946ac296d 100644 --- a/src/Ai/Raid/EyeOfEternity/Multiplier/RaidEoEMultipliers.cpp +++ b/src/Ai/Raid/EyeOfEternity/Multiplier/RaidEoEMultipliers.cpp @@ -1,21 +1,15 @@ #include "RaidEoEMultipliers.h" #include "ChooseTargetActions.h" -#include "DKActions.h" #include "DruidActions.h" -#include "DruidBearActions.h" #include "FollowActions.h" -#include "GenericActions.h" #include "GenericSpellActions.h" #include "MovementActions.h" #include "PaladinActions.h" #include "RaidEoEActions.h" #include "RaidEoETriggers.h" -#include "ReachTargetActions.h" -#include "ScriptedCreature.h" -#include "WarriorActions.h" -float MalygosMultiplier::GetValue(Action* action) +float MalygosMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "malygos"); @@ -24,46 +18,47 @@ float MalygosMultiplier::GetValue(Action* action) if (phase == 1) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) { return 0.0f; } - if (botAI->IsDps(bot) && dynamic_cast(action)) + if (botAI->IsDps(bot) && dynamic_cast(&action)) { return 0.0f; } - if (botAI->IsRangedDps(bot) && dynamic_cast(action)) + if (botAI->IsRangedDps(bot) && dynamic_cast(&action)) { return 0.0f; } - if (!botAI->IsMainTank(bot) && dynamic_cast(action)) + if (!botAI->IsMainTank(bot) && dynamic_cast(&action)) { return 0.0f; } - // if (dynamic_cast(action) && !dynamic_cast(action)) + // if (dynamic_cast(&action) && !dynamic_cast(&action)) // { // return 0.0f; // } } else if (phase == 2) { - if (botAI->IsDps(bot) && dynamic_cast(action)) + + if (botAI->IsDps(bot) && dynamic_cast(&action)) { return 0.0f; } - if (dynamic_cast(action)) + if (dynamic_cast(&action)) { return 0.0f; } - if (dynamic_cast(action)) + if (dynamic_cast(&action)) { - Unit* target = action->GetTarget(); + Unit* target = action.GetTarget(); if (target && target->GetEntry() == NPC_SCION_OF_ETERNITY) return 0.0f; } @@ -71,7 +66,7 @@ float MalygosMultiplier::GetValue(Action* action) else if (phase == 3) { // Suppresses FollowAction as well as some attack-based movements - if (dynamic_cast(action) && !dynamic_cast(action)) + if (dynamic_cast(&action) && !dynamic_cast(&action)) { return 0.0f; } diff --git a/src/Ai/Raid/EyeOfEternity/Multiplier/RaidEoEMultipliers.h b/src/Ai/Raid/EyeOfEternity/Multiplier/RaidEoEMultipliers.h index 05db5ee9e8..e1876dc708 100644 --- a/src/Ai/Raid/EyeOfEternity/Multiplier/RaidEoEMultipliers.h +++ b/src/Ai/Raid/EyeOfEternity/Multiplier/RaidEoEMultipliers.h @@ -10,7 +10,7 @@ class MalygosMultiplier : public Multiplier MalygosMultiplier(PlayerbotAI* ai) : Multiplier(ai, "malygos") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; #endif diff --git a/src/Ai/Raid/EyeOfEternity/RaidEoEActionContext.h b/src/Ai/Raid/EyeOfEternity/RaidEoEActionContext.h deleted file mode 100644 index 620610e91d..0000000000 --- a/src/Ai/Raid/EyeOfEternity/RaidEoEActionContext.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef _PLAYERBOT_RAIDEOEACTIONCONTEXT_H -#define _PLAYERBOT_RAIDEOEACTIONCONTEXT_H - -#include "Action.h" -#include "NamedObjectContext.h" -#include "RaidEoEActions.h" - -class RaidEoEActionContext : public NamedObjectContext -{ -public: - RaidEoEActionContext() - { - creators["malygos position"] = &RaidEoEActionContext::position; - creators["malygos target"] = &RaidEoEActionContext::target; - // creators["pull power spark"] = &RaidEoEActionContext::pull_power_spark; - // creators["kill power spark"] = &RaidEoEActionContext::kill_power_spark; - creators["eoe fly drake"] = &RaidEoEActionContext::eoe_fly_drake; - creators["eoe drake attack"] = &RaidEoEActionContext::eoe_drake_attack; - } - -private: - static Action* position(PlayerbotAI* ai) { return new MalygosPositionAction(ai); } - static Action* target(PlayerbotAI* ai) { return new MalygosTargetAction(ai); } - // static Action* pull_power_spark(PlayerbotAI* ai) { return new PullPowerSparkAction(ai); } - // static Action* kill_power_spark(PlayerbotAI* ai) { return new KillPowerSparkAction(ai); } - static Action* eoe_fly_drake(PlayerbotAI* ai) { return new EoEFlyDrakeAction(ai); } - static Action* eoe_drake_attack(PlayerbotAI* ai) { return new EoEDrakeAttackAction(ai); } -}; - -#endif diff --git a/src/Ai/Raid/EyeOfEternity/Strategy/RaidEoEStrategy.cpp b/src/Ai/Raid/EyeOfEternity/Strategy/RaidEoEStrategy.cpp index 3c0ff7ffd8..ae319cdddc 100644 --- a/src/Ai/Raid/EyeOfEternity/Strategy/RaidEoEStrategy.cpp +++ b/src/Ai/Raid/EyeOfEternity/Strategy/RaidEoEStrategy.cpp @@ -1,18 +1,42 @@ #include "RaidEoEStrategy.h" +#include "RaidEoEActions.h" #include "RaidEoEMultipliers.h" #include "Strategy.h" void RaidEoEStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("malygos", - { NextAction("malygos position", ACTION_MOVE) })); - triggers.push_back(new TriggerNode("malygos", - { NextAction("malygos target", ACTION_RAID + 1) })); - - triggers.push_back(new TriggerNode("group flying", - { NextAction("eoe fly drake", ACTION_NORMAL + 1) })); - triggers.push_back(new TriggerNode("drake combat", - { NextAction("eoe drake attack", ACTION_NORMAL + 5) })); + triggers.push_back( + new TriggerNode( + "malygos", + { + CreateNextAction(ACTION_MOVE) + } + ) + ); + triggers.push_back( + new TriggerNode( + "malygos", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "group flying", + { + CreateNextAction(ACTION_NORMAL + 1.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "drake combat", + { + CreateNextAction(ACTION_NORMAL + 5.0f) + } + ) + ); } void RaidEoEStrategy::InitMultipliers(std::vector &multipliers) diff --git a/src/Ai/Raid/GruulsLair/Action/RaidGruulsLairActions.cpp b/src/Ai/Raid/GruulsLair/Action/RaidGruulsLairActions.cpp index 1a98135cac..b4ffd799df 100644 --- a/src/Ai/Raid/GruulsLair/Action/RaidGruulsLairActions.cpp +++ b/src/Ai/Raid/GruulsLair/Action/RaidGruulsLairActions.cpp @@ -9,7 +9,7 @@ using namespace GruulsLairHelpers; // High King Maulgar Actions // Main tank on Maulgar -bool HighKingMaulgarMainTankAttackMaulgarAction::Execute(Event event) +bool HighKingMaulgarMainTankAttackMaulgarAction::Execute(Event) { Unit* maulgar = AI_VALUE2(Unit*, "find target", "high king maulgar"); @@ -52,7 +52,7 @@ bool HighKingMaulgarMainTankAttackMaulgarAction::Execute(Event event) } // First offtank on Olm -bool HighKingMaulgarFirstAssistTankAttackOlmAction::Execute(Event event) +bool HighKingMaulgarFirstAssistTankAttackOlmAction::Execute(Event) { Unit* olm = AI_VALUE2(Unit*, "find target", "olm the summoner"); @@ -92,7 +92,7 @@ bool HighKingMaulgarFirstAssistTankAttackOlmAction::Execute(Event event) } // Second offtank on Blindeye -bool HighKingMaulgarSecondAssistTankAttackBlindeyeAction::Execute(Event event) +bool HighKingMaulgarSecondAssistTankAttackBlindeyeAction::Execute(Event) { Unit* blindeye = AI_VALUE2(Unit*, "find target", "blindeye the seer"); @@ -135,7 +135,7 @@ bool HighKingMaulgarSecondAssistTankAttackBlindeyeAction::Execute(Event event) } // Mage with highest max HP on Krosh -bool HighKingMaulgarMageTankAttackKroshAction::Execute(Event event) +bool HighKingMaulgarMageTankAttackKroshAction::Execute(Event) { Unit* krosh = AI_VALUE2(Unit*, "find target", "krosh firehand"); @@ -189,7 +189,7 @@ bool HighKingMaulgarMageTankAttackKroshAction::Execute(Event event) } // Moonkin with highest max HP on Kiggler -bool HighKingMaulgarMoonkinTankAttackKigglerAction::Execute(Event event) +bool HighKingMaulgarMoonkinTankAttackKigglerAction::Execute(Event) { Unit* kiggler = AI_VALUE2(Unit*, "find target", "kiggler the crazed"); @@ -212,7 +212,7 @@ bool HighKingMaulgarMoonkinTankAttackKigglerAction::Execute(Event event) return false; } -bool HighKingMaulgarAssignDPSPriorityAction::Execute(Event event) +bool HighKingMaulgarAssignDPSPriorityAction::Execute(Event) { // Target priority 1: Blindeye Unit* blindeye = AI_VALUE2(Unit*, "find target", "blindeye the seer"); @@ -336,7 +336,7 @@ bool HighKingMaulgarAssignDPSPriorityAction::Execute(Event event) } // Avoid Whirlwind and Blast Wave and generally try to stay near the center of the room -bool HighKingMaulgarHealerFindSafePositionAction::Execute(Event event) +bool HighKingMaulgarHealerFindSafePositionAction::Execute(Event) { const Location& fightCenter = GruulsLairLocations::MaulgarRoomCenter; const float maxDistanceFromFight = 50.0f; @@ -370,7 +370,7 @@ bool HighKingMaulgarHealerFindSafePositionAction::Execute(Event event) } // Run away from Maulgar during Whirlwind (logic for after all other ogres are dead) -bool HighKingMaulgarRunAwayFromWhirlwindAction::Execute(Event event) +bool HighKingMaulgarRunAwayFromWhirlwindAction::Execute(Event) { Unit* maulgar = AI_VALUE2(Unit*, "find target", "high king maulgar"); @@ -403,7 +403,7 @@ bool HighKingMaulgarRunAwayFromWhirlwindAction::Execute(Event event) return false; } -bool HighKingMaulgarBanishFelstalkerAction::Execute(Event event) +bool HighKingMaulgarBanishFelstalkerAction::Execute(Event) { Group* group = bot->GetGroup(); if (!group) @@ -436,7 +436,9 @@ bool HighKingMaulgarBanishFelstalkerAction::Execute(Event event) } } - if (warlockIndex >= 0 && warlockIndex < felStalkers.size()) + const int64_t felStalkersSize = felStalkers.size(); + + if (warlockIndex >= 0 && warlockIndex < felStalkersSize) { Unit* assignedFelStalker = felStalkers[warlockIndex]; if (!assignedFelStalker->HasAura(SPELL_BANISH) && botAI->CanCastSpell(SPELL_BANISH, assignedFelStalker, true)) @@ -448,7 +450,7 @@ bool HighKingMaulgarBanishFelstalkerAction::Execute(Event event) // Hunter 1: Misdirect Olm to first offtank and have pet attack Blindeye // Hunter 2: Misdirect Blindeye to second offtank -bool HighKingMaulgarMisdirectOlmAndBlindeyeAction::Execute(Event event) +bool HighKingMaulgarMisdirectOlmAndBlindeyeAction::Execute(Event) { Group* group = bot->GetGroup(); if (!group) @@ -528,7 +530,7 @@ bool HighKingMaulgarMisdirectOlmAndBlindeyeAction::Execute(Event event) // Gruul the Dragonkiller Actions // Position in center of the room -bool GruulTheDragonkillerMainTankPositionBossAction::Execute(Event event) +bool GruulTheDragonkillerMainTankPositionBossAction::Execute(Event) { Unit* gruul = AI_VALUE2(Unit*, "find target", "gruul the dragonkiller"); @@ -546,7 +548,6 @@ bool GruulTheDragonkillerMainTankPositionBossAction::Execute(Event event) if (distanceToTankPosition > maxDistance) { - float step = std::min(maxDistance, distanceToTankPosition); float moveX = bot->GetPositionX() + (dX / distanceToTankPosition) * maxDistance; float moveY = bot->GetPositionY() + (dY / distanceToTankPosition) * maxDistance; const float moveZ = tankPosition.z; @@ -569,7 +570,7 @@ bool GruulTheDragonkillerMainTankPositionBossAction::Execute(Event event) // Ranged will take initial positions around the middle of the room, 25-40 yards from center // Ranged should spread out 10 yards from each other -bool GruulTheDragonkillerSpreadRangedAction::Execute(Event event) +bool GruulTheDragonkillerSpreadRangedAction::Execute(Event) { Group* group = bot->GetGroup(); if (!group) @@ -662,7 +663,7 @@ bool GruulTheDragonkillerSpreadRangedAction::Execute(Event event) } // Try to get away from other group members when Ground Slam is cast -bool GruulTheDragonkillerShatterSpreadAction::Execute(Event event) +bool GruulTheDragonkillerShatterSpreadAction::Execute(Event) { Group* group = bot->GetGroup(); if (!group) diff --git a/src/Ai/Raid/GruulsLair/Multiplier/RaidGruulsLairMultipliers.cpp b/src/Ai/Raid/GruulsLair/Multiplier/RaidGruulsLairMultipliers.cpp index 5ca2de9327..4a1939b6f9 100644 --- a/src/Ai/Raid/GruulsLair/Multiplier/RaidGruulsLairMultipliers.cpp +++ b/src/Ai/Raid/GruulsLair/Multiplier/RaidGruulsLairMultipliers.cpp @@ -12,24 +12,24 @@ using namespace GruulsLairHelpers; -static bool IsChargeAction(Action* action) +static bool IsChargeAction(Action& action) { - return dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action); + return dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action); } -float HighKingMaulgarDisableTankAssistMultiplier::GetValue(Action* action) +float HighKingMaulgarDisableTankAssistMultiplier::GetValue(Action& action) { - if (IsAnyOgreBossAlive(botAI) && dynamic_cast(action)) + if (IsAnyOgreBossAlive(botAI) && dynamic_cast(&action)) return 0.0f; return 1.0f; } // Don't run back in during Whirlwind -float HighKingMaulgarAvoidWhirlwindMultiplier::GetValue(Action* action) +float HighKingMaulgarAvoidWhirlwindMultiplier::GetValue(Action& action) { Unit* maulgar = AI_VALUE2(Unit*, "find target", "high king maulgar"); Unit* kiggler = AI_VALUE2(Unit*, "find target", "kiggler the crazed"); @@ -43,8 +43,8 @@ float HighKingMaulgarAvoidWhirlwindMultiplier::GetValue(Action* action) (!olm || !olm->IsAlive()) && (!blindeye || !blindeye->IsAlive())) { - if (IsChargeAction(action) || (dynamic_cast(action) && - !dynamic_cast(action))) + if (IsChargeAction(action) || (dynamic_cast(&action) && + !dynamic_cast(&action))) return 0.0f; } @@ -52,29 +52,29 @@ float HighKingMaulgarAvoidWhirlwindMultiplier::GetValue(Action* action) } // Arcane Shot will remove Spell Shield, which the mage tank needs to survive -float HighKingMaulgarDisableArcaneShotOnKroshMultiplier::GetValue(Action* action) +float HighKingMaulgarDisableArcaneShotOnKroshMultiplier::GetValue(Action& action) { Unit* krosh = AI_VALUE2(Unit*, "find target", "krosh firehand"); Unit* target = AI_VALUE(Unit*, "current target"); - if (krosh && target && target->GetGUID() == krosh->GetGUID() && dynamic_cast(action)) + if (krosh && target && target->GetGUID() == krosh->GetGUID() && dynamic_cast(&action)) return 0.0f; return 1.0f; } -float HighKingMaulgarDisableMageTankAOEMultiplier::GetValue(Action* action) +float HighKingMaulgarDisableMageTankAOEMultiplier::GetValue(Action& action) { if (IsKroshMageTank(botAI, bot) && - (dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action))) + (dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action))) return 0.0f; return 1.0f; } -float GruulTheDragonkillerMainTankMovementMultiplier::GetValue(Action* action) +float GruulTheDragonkillerMainTankMovementMultiplier::GetValue(Action& action) { Unit* gruul = AI_VALUE2(Unit*, "find target", "gruul the dragonkiller"); if (!gruul) @@ -82,17 +82,17 @@ float GruulTheDragonkillerMainTankMovementMultiplier::GetValue(Action* action) if (botAI->IsMainTank(bot)) { - if (gruul->GetVictim() == bot && dynamic_cast(action)) + if (gruul->GetVictim() == bot && dynamic_cast(&action)) return 0.0f; - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 0.0f; } return 1.0f; } -float GruulTheDragonkillerGroundSlamMultiplier::GetValue(Action* action) +float GruulTheDragonkillerGroundSlamMultiplier::GetValue(Action& action) { Unit* gruul = AI_VALUE2(Unit*, "find target", "gruul the dragonkiller"); if (!gruul) @@ -101,7 +101,7 @@ float GruulTheDragonkillerGroundSlamMultiplier::GetValue(Action* action) if (bot->HasAura(SPELL_GROUND_SLAM_1) || bot->HasAura(SPELL_GROUND_SLAM_2)) { - if ((dynamic_cast(action) && !dynamic_cast(action)) || + if ((dynamic_cast(&action) && !dynamic_cast(&action)) || IsChargeAction(action)) return 0.0f; } diff --git a/src/Ai/Raid/GruulsLair/Multiplier/RaidGruulsLairMultipliers.h b/src/Ai/Raid/GruulsLair/Multiplier/RaidGruulsLairMultipliers.h index d67e8523e7..b45ae8dbba 100644 --- a/src/Ai/Raid/GruulsLair/Multiplier/RaidGruulsLairMultipliers.h +++ b/src/Ai/Raid/GruulsLair/Multiplier/RaidGruulsLairMultipliers.h @@ -7,42 +7,42 @@ class HighKingMaulgarDisableTankAssistMultiplier : public Multiplier { public: HighKingMaulgarDisableTankAssistMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "high king maulgar disable tank assist multiplier") {} - float GetValue(Action* action) override; + float GetValue(Action& action) override; }; class HighKingMaulgarAvoidWhirlwindMultiplier : public Multiplier { public: HighKingMaulgarAvoidWhirlwindMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "high king maulgar avoid whirlwind multiplier") {} - float GetValue(Action* action) override; + float GetValue(Action& action) override; }; class HighKingMaulgarDisableArcaneShotOnKroshMultiplier : public Multiplier { public: HighKingMaulgarDisableArcaneShotOnKroshMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "high king maulgar disable arcane shot on krosh multiplier") {} - float GetValue(Action* action) override; + float GetValue(Action& action) override; }; class HighKingMaulgarDisableMageTankAOEMultiplier : public Multiplier { public: HighKingMaulgarDisableMageTankAOEMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "high king maulgar disable mage tank aoe multiplier") {} - float GetValue(Action* action) override; + float GetValue(Action& action) override; }; class GruulTheDragonkillerMainTankMovementMultiplier : public Multiplier { public: GruulTheDragonkillerMainTankMovementMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "gruul the dragonkiller main tank movement multiplier") {} - float GetValue(Action* action) override; + float GetValue(Action& action) override; }; class GruulTheDragonkillerGroundSlamMultiplier : public Multiplier { public: GruulTheDragonkillerGroundSlamMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "gruul the dragonkiller ground slam multiplier") {} - float GetValue(Action* action) override; + float GetValue(Action& action) override; }; #endif diff --git a/src/Ai/Raid/GruulsLair/RaidGruulsLairActionContext.h b/src/Ai/Raid/GruulsLair/RaidGruulsLairActionContext.h deleted file mode 100644 index 809fadf034..0000000000 --- a/src/Ai/Raid/GruulsLair/RaidGruulsLairActionContext.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef _PLAYERBOT_RAIDGRUULSLAIRACTIONCONTEXT_H -#define _PLAYERBOT_RAIDGRUULSLAIRACTIONCONTEXT_H - -#include "RaidGruulsLairActions.h" -#include "NamedObjectContext.h" - -class RaidGruulsLairActionContext : public NamedObjectContext -{ -public: - RaidGruulsLairActionContext() - { - // High King Maulgar - creators["high king maulgar main tank attack maulgar"] = &RaidGruulsLairActionContext::high_king_maulgar_main_tank_attack_maulgar; - creators["high king maulgar first assist tank attack olm"] = &RaidGruulsLairActionContext::high_king_maulgar_first_assist_tank_attack_olm; - creators["high king maulgar second assist tank attack blindeye"] = &RaidGruulsLairActionContext::high_king_maulgar_second_assist_tank_attack_blindeye; - creators["high king maulgar mage tank attack krosh"] = &RaidGruulsLairActionContext::high_king_maulgar_mage_tank_attack_krosh; - creators["high king maulgar moonkin tank attack kiggler"] = &RaidGruulsLairActionContext::high_king_maulgar_moonkin_tank_attack_kiggler; - creators["high king maulgar assign dps priority"] = &RaidGruulsLairActionContext::high_king_maulgar_assign_dps_priority; - creators["high king maulgar healer find safe position"] = &RaidGruulsLairActionContext::high_king_maulgar_healer_find_safe_position; - creators["high king maulgar run away from whirlwind"] = &RaidGruulsLairActionContext::high_king_maulgar_run_away_from_whirlwind; - creators["high king maulgar banish felstalker"] = &RaidGruulsLairActionContext::high_king_maulgar_banish_felstalker; - creators["high king maulgar misdirect olm and blindeye"] = &RaidGruulsLairActionContext::high_king_maulgar_misdirect_olm_and_blindeye; - - // Gruul the Dragonkiller - creators["gruul the dragonkiller main tank position boss"] = &RaidGruulsLairActionContext::gruul_the_dragonkiller_main_tank_position_boss; - creators["gruul the dragonkiller spread ranged"] = &RaidGruulsLairActionContext::gruul_the_dragonkiller_spread_ranged; - creators["gruul the dragonkiller shatter spread"] = &RaidGruulsLairActionContext::gruul_the_dragonkiller_shatter_spread; - } - -private: - // High King Maulgar - static Action* high_king_maulgar_main_tank_attack_maulgar(PlayerbotAI* botAI) { return new HighKingMaulgarMainTankAttackMaulgarAction(botAI); } - static Action* high_king_maulgar_first_assist_tank_attack_olm(PlayerbotAI* botAI) { return new HighKingMaulgarFirstAssistTankAttackOlmAction(botAI); } - static Action* high_king_maulgar_second_assist_tank_attack_blindeye(PlayerbotAI* botAI) { return new HighKingMaulgarSecondAssistTankAttackBlindeyeAction(botAI); } - static Action* high_king_maulgar_mage_tank_attack_krosh(PlayerbotAI* botAI) { return new HighKingMaulgarMageTankAttackKroshAction(botAI); } - static Action* high_king_maulgar_moonkin_tank_attack_kiggler(PlayerbotAI* botAI) { return new HighKingMaulgarMoonkinTankAttackKigglerAction(botAI); } - static Action* high_king_maulgar_assign_dps_priority(PlayerbotAI* botAI) { return new HighKingMaulgarAssignDPSPriorityAction(botAI); } - static Action* high_king_maulgar_healer_find_safe_position(PlayerbotAI* botAI) { return new HighKingMaulgarHealerFindSafePositionAction(botAI); } - static Action* high_king_maulgar_run_away_from_whirlwind(PlayerbotAI* botAI) { return new HighKingMaulgarRunAwayFromWhirlwindAction(botAI); } - static Action* high_king_maulgar_banish_felstalker(PlayerbotAI* botAI) { return new HighKingMaulgarBanishFelstalkerAction(botAI); } - static Action* high_king_maulgar_misdirect_olm_and_blindeye(PlayerbotAI* botAI) { return new HighKingMaulgarMisdirectOlmAndBlindeyeAction(botAI); } - - // Gruul the Dragonkiller - static Action* gruul_the_dragonkiller_main_tank_position_boss(PlayerbotAI* botAI) { return new GruulTheDragonkillerMainTankPositionBossAction(botAI); } - static Action* gruul_the_dragonkiller_spread_ranged(PlayerbotAI* botAI) { return new GruulTheDragonkillerSpreadRangedAction(botAI); } - static Action* gruul_the_dragonkiller_shatter_spread(PlayerbotAI* botAI) { return new GruulTheDragonkillerShatterSpreadAction(botAI); } -}; - -#endif diff --git a/src/Ai/Raid/GruulsLair/Strategy/RaidGruulsLairStrategy.cpp b/src/Ai/Raid/GruulsLair/Strategy/RaidGruulsLairStrategy.cpp index 9ec264ea00..5b8ab3ed0d 100644 --- a/src/Ai/Raid/GruulsLair/Strategy/RaidGruulsLairStrategy.cpp +++ b/src/Ai/Raid/GruulsLair/Strategy/RaidGruulsLairStrategy.cpp @@ -1,48 +1,128 @@ #include "RaidGruulsLairStrategy.h" #include "RaidGruulsLairMultipliers.h" +#include "CreateNextAction.h" +#include "RaidGruulsLairActions.h" void RaidGruulsLairStrategy::InitTriggers(std::vector& triggers) { // High King Maulgar - triggers.push_back(new TriggerNode("high king maulgar is main tank", { - NextAction("high king maulgar main tank attack maulgar", ACTION_RAID + 1) })); + triggers.push_back( + new TriggerNode( + "high king maulgar is main tank", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); - triggers.push_back(new TriggerNode("high king maulgar is first assist tank", { - NextAction("high king maulgar first assist tank attack olm", ACTION_RAID + 1) })); + triggers.push_back( + new TriggerNode( + "high king maulgar is first assist tank", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); - triggers.push_back(new TriggerNode("high king maulgar is second assist tank", { - NextAction("high king maulgar second assist tank attack blindeye", ACTION_RAID + 1) })); + triggers.push_back( + new TriggerNode( + "high king maulgar is second assist tank", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); - triggers.push_back(new TriggerNode("high king maulgar is mage tank", { - NextAction("high king maulgar mage tank attack krosh", ACTION_RAID + 1) })); + triggers.push_back( + new TriggerNode( + "high king maulgar is mage tank", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); - triggers.push_back(new TriggerNode("high king maulgar is moonkin tank", { - NextAction("high king maulgar moonkin tank attack kiggler", ACTION_RAID + 1) })); + triggers.push_back( + new TriggerNode( + "high king maulgar is moonkin tank", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); - triggers.push_back(new TriggerNode("high king maulgar determining kill order", { - NextAction("high king maulgar assign dps priority", ACTION_RAID + 1) })); + triggers.push_back( + new TriggerNode( + "high king maulgar determining kill order", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); - triggers.push_back(new TriggerNode("high king maulgar healer in danger", { - NextAction("high king maulgar healer find safe position", ACTION_RAID + 1) })); + triggers.push_back( + new TriggerNode( + "high king maulgar healer in danger", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); - triggers.push_back(new TriggerNode("high king maulgar boss channeling whirlwind", { - NextAction("high king maulgar run away from whirlwind", ACTION_EMERGENCY + 6) })); + triggers.push_back( + new TriggerNode( + "high king maulgar boss channeling whirlwind", + { + CreateNextAction(ACTION_EMERGENCY + 6.0f) + } + ) + ); - triggers.push_back(new TriggerNode("high king maulgar wild felstalker spawned", { - NextAction("high king maulgar banish felstalker", ACTION_RAID + 2) })); + triggers.push_back( + new TriggerNode( + "high king maulgar wild felstalker spawned", + { + CreateNextAction(ACTION_RAID + 2.0f) + } + ) + ); - triggers.push_back(new TriggerNode("high king maulgar pulling olm and blindeye", { - NextAction("high king maulgar misdirect olm and blindeye", ACTION_RAID + 2) })); + triggers.push_back( + new TriggerNode( + "high king maulgar pulling olm and blindeye", + { + CreateNextAction(ACTION_RAID + 2.0f) + } + ) + ); // Gruul the Dragonkiller - triggers.push_back(new TriggerNode("gruul the dragonkiller boss engaged by main tank", { - NextAction("gruul the dragonkiller main tank position boss", ACTION_RAID + 1) })); + triggers.push_back( + new TriggerNode( + "gruul the dragonkiller boss engaged by main tank", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); - triggers.push_back(new TriggerNode("gruul the dragonkiller boss engaged by range", { - NextAction("gruul the dragonkiller spread ranged", ACTION_RAID + 1) })); + triggers.push_back( + new TriggerNode( + "gruul the dragonkiller boss engaged by range", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); - triggers.push_back(new TriggerNode("gruul the dragonkiller incoming shatter", { - NextAction("gruul the dragonkiller shatter spread", ACTION_EMERGENCY + 6) })); + triggers.push_back( + new TriggerNode( + "gruul the dragonkiller incoming shatter", + { + CreateNextAction(ACTION_EMERGENCY + 6.0f) + } + ) + ); } void RaidGruulsLairStrategy::InitMultipliers(std::vector& multipliers) diff --git a/src/Ai/Raid/GruulsLair/Util/RaidGruulsLairHelpers.cpp b/src/Ai/Raid/GruulsLair/Util/RaidGruulsLairHelpers.cpp index 0c8a23a19c..d10c1c1209 100644 --- a/src/Ai/Raid/GruulsLair/Util/RaidGruulsLairHelpers.cpp +++ b/src/Ai/Raid/GruulsLair/Util/RaidGruulsLairHelpers.cpp @@ -95,7 +95,7 @@ namespace GruulsLairHelpers } } - bool IsKroshMageTank(PlayerbotAI* botAI, Player* bot) + bool IsKroshMageTank(PlayerbotAI*, Player* bot) { Group* group = bot->GetGroup(); if (!group) @@ -123,7 +123,7 @@ namespace GruulsLairHelpers return highestHpMage == bot; } - bool IsKigglerMoonkinTank(PlayerbotAI* botAI, Player* bot) + bool IsKigglerMoonkinTank(PlayerbotAI*, Player* bot) { Group* group = bot->GetGroup(); if (!group) diff --git a/src/Ai/Raid/Icecrown/Action/RaidIccActions.cpp b/src/Ai/Raid/Icecrown/Action/RaidIccActions.cpp index 14c8ada9ac..7876187a63 100644 --- a/src/Ai/Raid/Icecrown/Action/RaidIccActions.cpp +++ b/src/Ai/Raid/Icecrown/Action/RaidIccActions.cpp @@ -1,19 +1,16 @@ #include "RaidIccActions.h" #include "NearestNpcsValue.h" #include "ObjectAccessor.h" -#include "RaidIccStrategy.h" #include "Playerbots.h" -#include "Timer.h" #include "Vehicle.h" #include "RtiValue.h" #include "GenericSpellActions.h" #include "GenericActions.h" -#include #include "RaidIccTriggers.h" #include "Multiplier.h" // Lord Marrowgwar -bool IccLmTankPositionAction::Execute(Event event) +bool IccLmTankPositionAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "lord marrowgar"); if (!boss) @@ -73,7 +70,7 @@ bool IccLmTankPositionAction::MoveTowardPosition(const Position& position, float MovementPriority::MOVEMENT_COMBAT); } -bool IccSpikeAction::Execute(Event event) +bool IccSpikeAction::Execute(Event) { // If we're impaled, we can't do anything if (botAI->GetAura("Impaled", bot)) @@ -183,7 +180,7 @@ void IccSpikeAction::UpdateRaidTargetIcon(Unit* target) } // Lady Deathwhisper -bool IccDarkReckoningAction::Execute(Event event) +bool IccDarkReckoningAction::Execute(Event) { constexpr float SAFE_DISTANCE_THRESHOLD = 2.0f; @@ -201,7 +198,7 @@ bool IccDarkReckoningAction::Execute(Event event) return false; } -bool IccRangedPositionLadyDeathwhisperAction::Execute(Event event) +bool IccRangedPositionLadyDeathwhisperAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "lady deathwhisper"); if (!boss) @@ -301,7 +298,7 @@ bool IccRangedPositionLadyDeathwhisperAction::MaintainRangedSpacing() return false; // Everyone is properly spaced } -bool IccAddsLadyDeathwhisperAction::Execute(Event event) +bool IccAddsLadyDeathwhisperAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "lady deathwhisper"); if (!boss) @@ -419,7 +416,7 @@ void IccAddsLadyDeathwhisperAction::UpdateRaidTargetIcon(Unit* target) } } -bool IccShadeLadyDeathwhisperAction::Execute(Event event) +bool IccShadeLadyDeathwhisperAction::Execute(Event) { static constexpr uint32 VENGEFUL_SHADE_ID = NPC_SHADE; static constexpr float SAFE_DISTANCE = 12.0f; @@ -473,7 +470,7 @@ bool IccShadeLadyDeathwhisperAction::Execute(Event event) return false; } -bool IccRottingFrostGiantTankPositionAction::Execute(Event event) +bool IccRottingFrostGiantTankPositionAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "rotting frost giant"); if (!boss) @@ -696,7 +693,7 @@ bool IccRottingFrostGiantTankPositionAction::Execute(Event event) } //Gunship -bool IccCannonFireAction::Execute(Event event) +bool IccCannonFireAction::Execute(Event) { Unit* vehicleBase = bot->GetVehicleBase(); Vehicle* vehicle = bot->GetVehicle(); @@ -755,7 +752,7 @@ bool IccCannonFireAction::TryCastCannonSpell(uint32 spellId, Unit* target, Unit* return false; } -bool IccGunshipEnterCannonAction::Execute(Event event) +bool IccGunshipEnterCannonAction::Execute(Event) { // Do not switch vehicles if already in one if (bot->GetVehicle()) @@ -855,7 +852,7 @@ bool IccGunshipEnterCannonAction::EnterVehicle(Unit* vehicleBase, bool moveIfFar return true; } -bool IccGunshipTeleportAllyAction::Execute(Event event) +bool IccGunshipTeleportAllyAction::Execute(Event) { static constexpr float MAX_WAITING_DISTANCE = 45.0f; static constexpr float MAX_ATTACK_DISTANCE = 15.0f; @@ -922,7 +919,7 @@ void IccGunshipTeleportAllyAction::UpdateBossSkullIcon(Unit* boss, uint8_t SKULL } } -bool IccGunshipTeleportHordeAction::Execute(Event event) +bool IccGunshipTeleportHordeAction::Execute(Event) { static constexpr float MAX_WAITING_DISTANCE = 45.0f; static constexpr float MAX_ATTACK_DISTANCE = 15.0f; @@ -990,7 +987,7 @@ void IccGunshipTeleportHordeAction::UpdateBossSkullIcon(Unit* boss, uint8_t SKUL } //DBS -bool IccDbsTankPositionAction::Execute(Event event) +bool IccDbsTankPositionAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "deathbringer saurfang"); if (!boss) @@ -1037,8 +1034,6 @@ bool IccDbsTankPositionAction::CrowdControlBloodBeasts() NPC_BLOOD_BEAST4}; const GuidVector npcs = AI_VALUE(GuidVector, "nearest hostile npcs"); - bool appliedCC = false; - for (auto const& npc : npcs) { Unit* unit = botAI->GetUnit(npc); @@ -1059,70 +1054,60 @@ bool IccDbsTankPositionAction::CrowdControlBloodBeasts() if (!botAI->HasAura("Frost Nova", unit)) { botAI->CastSpell("Frost Nova", unit); - appliedCC = true; } break; case CLASS_DRUID: if (!botAI->HasAura("Entangling Roots", unit)) { botAI->CastSpell("Entangling Roots", unit); - appliedCC = true; } break; case CLASS_PALADIN: if (!botAI->HasAura("Hammer of Justice", unit)) { botAI->CastSpell("Hammer of Justice", unit); - appliedCC = true; } break; case CLASS_WARRIOR: if (!botAI->HasAura("Hamstring", unit)) { botAI->CastSpell("Hamstring", unit); - appliedCC = true; } break; case CLASS_HUNTER: if (!botAI->HasAura("Concussive Shot", unit)) { botAI->CastSpell("Concussive Shot", unit); - appliedCC = true; } break; case CLASS_ROGUE: if (!botAI->HasAura("Kidney Shot", unit)) { botAI->CastSpell("Kidney Shot", unit); - appliedCC = true; } break; case CLASS_SHAMAN: if (!botAI->HasAura("Frost Shock", unit)) { botAI->CastSpell("Frost Shock", unit); - appliedCC = true; } break; case CLASS_DEATH_KNIGHT: if (!botAI->HasAura("Chains of Ice", unit)) { botAI->CastSpell("Chains of Ice", unit); - appliedCC = true; } break; case CLASS_PRIEST: if (!botAI->HasAura("Psychic Scream", unit)) { botAI->CastSpell("Psychic Scream", unit); - appliedCC = true; } break; case CLASS_WARLOCK: if (!botAI->HasAura("Fear", unit)) { botAI->CastSpell("Fear", unit); - appliedCC = true; } break; default: @@ -1231,7 +1216,7 @@ bool IccDbsTankPositionAction::PositionInRangedFormation() return false; } -bool IccAddsDbsAction::Execute(Event event) +bool IccAddsDbsAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "deathbringer saurfang"); if (!boss) @@ -1295,7 +1280,7 @@ void IccAddsDbsAction::UpdateSkullMarker(Unit* priorityTarget) } // Festergut -bool IccFestergutGroupPositionAction::Execute(Event event) +bool IccFestergutGroupPositionAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "festergut"); if (!boss) @@ -1467,7 +1452,6 @@ int IccFestergutGroupPositionAction::CalculatePositionIndex(Group* group) else { // Fill remaining spots in second row - int spotsInFirstRow = 6; int spotsInSecondRow = healerSpotsUsed - 6; int remainingInSecondRow = 6 - spotsInSecondRow; @@ -1511,10 +1495,9 @@ int IccFestergutGroupPositionAction::CalculatePositionIndex(Group* group) return -1; } -bool IccFestergutSporeAction::Execute(Event event) +bool IccFestergutSporeAction::Execute(Event) { constexpr float POSITION_TOLERANCE = 4.0f; - constexpr float SPREAD_RADIUS = 2.0f; // Check if bot has spore bool hasSpore = bot->HasAura(SPELL_GAS_SPORE); // gas spore @@ -1624,7 +1607,7 @@ bool IccFestergutSporeAction::CheckMainTankSpore() } // Rotface -bool IccRotfaceTankPositionAction::Execute(Event event) +bool IccRotfaceTankPositionAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "rotface"); if (!boss) @@ -1662,7 +1645,7 @@ bool IccRotfaceTankPositionAction::PositionMainTankAndMelee(Unit* boss) { bool isBossCasting = false; if (boss && boss->HasUnitState(UNIT_STATE_CASTING) && boss->GetCurrentSpell(SPELL_SLIME_SPRAY)) - bool isBossCasting = true; + isBossCasting = true; if (bot->GetExactDist2d(ICC_ROTFACE_CENTER_POSITION) > 7.0f && botAI->HasAggro(boss) && botAI->IsMainTank(bot)) MoveTo(bot->GetMapId(), ICC_ROTFACE_CENTER_POSITION.GetPositionX(), @@ -1700,7 +1683,7 @@ bool IccRotfaceTankPositionAction::HandleAssistTankPositioning(Unit* boss) return HandleBigOozePositioning(boss); } -bool IccRotfaceTankPositionAction::HandleBigOozePositioning(Unit* boss) +bool IccRotfaceTankPositionAction::HandleBigOozePositioning(Unit*) { // Find all big oozes GuidVector bigOozes = AI_VALUE(GuidVector, "nearest hostile npcs"); @@ -1824,28 +1807,21 @@ bool IccRotfaceTankPositionAction::HandleBigOozePositioning(Unit* boss) return false; } -bool IccRotfaceGroupPositionAction::Execute(Event event) +bool IccRotfaceGroupPositionAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "rotface"); if (!boss) return false; const GuidVector npcs = AI_VALUE(GuidVector, "nearest hostile npcs"); - bool floodPresent = false; for (auto const& npc : npcs) { Unit* unit = botAI->GetUnit(npc); if (!unit || !botAI->HasAura("Ooze Flood", unit)) continue; - - float puddleDistance = bot->GetExactDist2d(unit); - - if (puddleDistance < 30.0f) - floodPresent = true; } - Unit* bigOoze = AI_VALUE2(Unit*, "find target", "big ooze"); bool hasOozeFlood = botAI->HasAura("Ooze Flood", bot); Unit* smallOoze = AI_VALUE2(Unit*, "find target", "little ooze"); bool hasMutatedInfection = botAI->HasAura("Mutated Infection", bot); @@ -1891,7 +1867,7 @@ bool IccRotfaceGroupPositionAction::HandlePuddleAvoidance(Unit* boss) return false; } -bool IccRotfaceGroupPositionAction::MoveAwayFromPuddle(Unit* boss, Unit* puddle, float puddleDistance) +bool IccRotfaceGroupPositionAction::MoveAwayFromPuddle(Unit* boss, Unit* puddle, float) { if (!boss || !puddle) return false; @@ -2017,7 +1993,7 @@ bool IccRotfaceGroupPositionAction::PositionRangedAndHealers(Unit* boss,Unit *sm Difficulty diff = bot->GetRaidDifficulty(); bool isBossCasting = false; if (boss && boss->HasUnitState(UNIT_STATE_CASTING) && boss->GetCurrentSpell(SPELL_SLIME_SPRAY)) - bool isBossCasting = true; + isBossCasting = true; bool isHeroic = (diff == RAID_DIFFICULTY_10MAN_HEROIC || diff == RAID_DIFFICULTY_25MAN_HEROIC); @@ -2052,7 +2028,7 @@ bool IccRotfaceGroupPositionAction::PositionRangedAndHealers(Unit* boss,Unit *sm return FindAndMoveFromClosestMember(boss, smallOoze); } -bool IccRotfaceGroupPositionAction::FindAndMoveFromClosestMember(Unit* boss, Unit* smallOoze) +bool IccRotfaceGroupPositionAction::FindAndMoveFromClosestMember(Unit*, Unit* smallOoze) { const GuidVector npcs = AI_VALUE(GuidVector, "nearest hostile npcs"); @@ -2073,7 +2049,6 @@ bool IccRotfaceGroupPositionAction::FindAndMoveFromClosestMember(Unit* boss, Uni const float maxMoveDistance = 12.0f; // Limit maximum movement distance const float puddleSafeDistance = 30.0f; // Minimum distance to stay away from puddle const float minCenterDistance = 20.0f; // Minimum distance from center position - const bool isRanged = botAI->IsRanged(bot) || botAI->IsHeal(bot); // Ranged: spread from other members const GuidVector members = AI_VALUE(GuidVector, "group members"); @@ -2175,7 +2150,7 @@ bool IccRotfaceGroupPositionAction::FindAndMoveFromClosestMember(Unit* boss, Uni return false; // Everyone is properly spaced } -bool IccRotfaceMoveAwayFromExplosionAction::Execute(Event event) +bool IccRotfaceMoveAwayFromExplosionAction::Execute(Event) { // Skip if main tank or ooze flood if (botAI->IsMainTank(bot)) @@ -2238,7 +2213,6 @@ bool IccRotfaceMoveAwayFromExplosionAction::MoveToRandomSafeLocation() // Move in increments of 5.0f towards the calculated position float currentX = bot->GetPositionX(); float currentY = bot->GetPositionY(); - float currentZ = bot->GetPositionZ(); float directionX = moveX - currentX; float directionY = moveY - currentY; @@ -2258,7 +2232,7 @@ bool IccRotfaceMoveAwayFromExplosionAction::MoveToRandomSafeLocation() } // Proffesor Putricide -bool IccPutricideGrowingOozePuddleAction::Execute(Event event) +bool IccPutricideGrowingOozePuddleAction::Execute(Event) { Unit* closestPuddle = FindClosestThreateningPuddle(); if (!closestPuddle) @@ -2281,7 +2255,6 @@ Unit* IccPutricideGrowingOozePuddleAction::FindClosestThreateningPuddle() Unit* closestPuddle = nullptr; float closestDistance = FLT_MAX; - float closestSafeDistance = BASE_RADIUS; for (auto const& npc : npcs) { @@ -2298,7 +2271,6 @@ Unit* IccPutricideGrowingOozePuddleAction::FindClosestThreateningPuddle() if (currentDistance < safeDistance && currentDistance < closestDistance) { closestDistance = currentDistance; - closestSafeDistance = safeDistance; closestPuddle = unit; } } @@ -2416,7 +2388,7 @@ bool IccPutricideGrowingOozePuddleAction::IsPositionTooCloseToOtherPuddles(float return false; } -bool IccPutricideVolatileOozeAction::Execute(Event event) +bool IccPutricideVolatileOozeAction::Execute(Event) { static const float STACK_DISTANCE = 7.0f; @@ -2529,7 +2501,7 @@ Unit* IccPutricideVolatileOozeAction::FindAuraTarget() return nullptr; } -bool IccPutricideGasCloudAction::Execute(Event event) +bool IccPutricideGasCloudAction::Execute(Event) { Unit* gasCloud = AI_VALUE2(Unit*, "find target", "gas cloud"); if (!gasCloud) @@ -2806,7 +2778,6 @@ Position IccPutricideGasCloudAction::CalculateEmergencyPosition(const Position& Position bestPos = Position(botPos.GetPositionX() + dx * 15.0f, botPos.GetPositionY() + dy * 15.0f, botPos.GetPositionZ()); float bestFreedom = 0.0f; - static const float MOVEMENT_INCREMENT = 5.0f; // Fixed movement increment // Try fewer directions for emergency but still avoid corners for (int i = 0; i < 8; i++) @@ -2942,7 +2913,7 @@ bool IccPutricideGasCloudAction::GroupHasGaseousBloat(Group* group) return false; } -bool IccPutricideAvoidMalleableGooAction::Execute(Event event) +bool IccPutricideAvoidMalleableGooAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "professor putricide"); if (!boss) @@ -2964,7 +2935,7 @@ bool IccPutricideAvoidMalleableGooAction::Execute(Event event) return HandleBossPositioning(boss); } -bool IccPutricideAvoidMalleableGooAction::HandleTankPositioning(Unit* boss) +bool IccPutricideAvoidMalleableGooAction::HandleTankPositioning(Unit*) { if (!botAI->IsTank(bot)) return false; @@ -3229,7 +3200,7 @@ Position IccPutricideAvoidMalleableGooAction::CalculateIncrementalMove(const Pos } // BPC -bool IccBpcKelesethTankAction::Execute(Event event) +bool IccBpcKelesethTankAction::Execute(Event) { if (!botAI->IsAssistTank(bot)) return false; @@ -3310,7 +3281,7 @@ bool IccBpcKelesethTankAction::Execute(Event event) return false; } -bool IccBpcMainTankAction::Execute(Event event) +bool IccBpcMainTankAction::Execute(Event) { // Main tank specific behavior (higher priority) if (botAI->IsMainTank(bot)) @@ -3427,7 +3398,7 @@ void IccBpcMainTankAction::MarkEmpoweredPrince() } } -bool IccBpcEmpoweredVortexAction::Execute(Event event) +bool IccBpcEmpoweredVortexAction::Execute(Event) { Unit* valanar = AI_VALUE2(Unit*, "find target", "prince valanar"); if (!valanar) @@ -3612,7 +3583,7 @@ bool IccBpcEmpoweredVortexAction::HandleEmpoweredVortexSpread() return false; // Everyone is properly spaced } -bool IccBpcKineticBombAction::Execute(Event event) +bool IccBpcKineticBombAction::Execute(Event) { // Early exit if not ranged DPS if (!botAI->IsRangedDps(bot)) @@ -3657,7 +3628,6 @@ bool IccBpcKineticBombAction::Execute(Event event) Unit* IccBpcKineticBombAction::FindOptimalKineticBomb() { - static constexpr float MAX_HEIGHT_DIFF = 20.0f; static constexpr std::array KINETIC_BOMB_ENTRIES = {NPC_KINETIC_BOMB1, NPC_KINETIC_BOMB2, NPC_KINETIC_BOMB3, NPC_KINETIC_BOMB4}; @@ -3758,7 +3728,7 @@ bool IccBpcKineticBombAction::IsBombAlreadyHandled(Unit* bomb, Group* group) return false; } -bool IccBpcBallOfFlameAction::Execute(Event event) +bool IccBpcBallOfFlameAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "prince taldaram"); if (!boss) @@ -3839,7 +3809,7 @@ bool IccBpcBallOfFlameAction::Execute(Event event) } // Blood Queen Lana'thel -bool IccBqlGroupPositionAction::Execute(Event event) +bool IccBqlGroupPositionAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "blood-queen lana'thel"); if (!boss) @@ -3920,7 +3890,8 @@ bool IccBqlGroupPositionAction::HandleShadowsMovement() GuidVector npcs = AI_VALUE(GuidVector, "nearest hostile npcs"); Unit* shadows[100]{}; // Reasonable max estimate int shadowCount = 0; - for (int i = 0; i < npcs.size() && shadowCount < 100; i++) + + for (uint64_t i = 0; i < npcs.size() && shadowCount < 100; i++) { Unit* unit = botAI->GetUnit(npcs[i]); if (unit && unit->IsAlive() && unit->GetEntry() == NPC_SWARMING_SHADOWS) @@ -4021,7 +3992,6 @@ bool IccBqlGroupPositionAction::HandleShadowsMovement() // Find closest safe point by searching in both directions from closest point Position safeMoveTarget = closestPoint; - float safeMoveTargetDist = FLT_MAX; bool foundSafe = closestIsSafe; // Only search for safe spots if the closest point isn't already safe @@ -4092,7 +4062,6 @@ bool IccBqlGroupPositionAction::HandleShadowsMovement() if (foundSafe) { // If we found a safe point, penalize based on travel distance along the curve to reach it - float stepsToCurve = minDist / 2.0f; // Approximate steps to reach the curve float safeDist = bot->GetExactDist2d(safeMoveTarget); // Add distance penalty based on how far we need to move along the curve @@ -4373,7 +4342,6 @@ bool IccBqlGroupPositionAction::HandleGroupPosition(Unit* boss, Aura* frenzyAura rangedBots.erase(std::remove(rangedBots.begin(), rangedBots.end(), h), rangedBots.end()); // Distribute remaining ranged evenly - size_t totalRanged = leftSide.size() + rightSide.size() + rangedBots.size(); size_t leftCount = leftSide.size(); size_t rightCount = rightSide.size(); for (Player* p : rangedBots) @@ -4532,14 +4500,14 @@ bool IccBqlGroupPositionAction::HandleGroupPosition(Unit* boss, Aura* frenzyAura // Find all swarming shadows GuidVector npcs = AI_VALUE(GuidVector, "nearest hostile npcs"); std::vector swarmingShadows; - for (int i = 0; i < npcs.size(); ++i) + for (uint64_t i = 0; i < npcs.size(); ++i) { Unit* unit = botAI->GetUnit(npcs[i]); if (unit && unit->IsAlive() && unit->GetEntry() == NPC_SWARMING_SHADOWS) swarmingShadows.push_back(unit); } - for (int i = 0; i < members.size(); i++) + for (uint64_t i = 0; i < members.size(); i++) { Unit* member = botAI->GetUnit(members[i]); if (!member || !member->IsAlive() || member == bot || botAI->GetAura("Frenzied Bloodthirst", member) || @@ -4601,7 +4569,7 @@ bool IccBqlGroupPositionAction::HandleGroupPosition(Unit* boss, Aura* frenzyAura return false; } -bool IccBqlPactOfDarkfallenAction::Execute(Event event) +bool IccBqlPactOfDarkfallenAction::Execute(Event) { // Check if bot has Pact of the Darkfallen if (!botAI->GetAura("Pact of the Darkfallen", bot)) @@ -4720,7 +4688,7 @@ bool IccBqlPactOfDarkfallenAction::MoveToTargetPosition(const Position& targetPo return false; } -bool IccBqlVampiricBiteAction::Execute(Event event) +bool IccBqlVampiricBiteAction::Execute(Event) { // Only act when bot has Frenzied Bloodthirst if (!botAI->GetAura("Frenzied Bloodthirst", bot)) @@ -4857,7 +4825,7 @@ bool IccBqlVampiricBiteAction::CastVampiricBite(Player* target) } // Sister Svalna -bool IccValkyreSpearAction::Execute(Event event) +bool IccValkyreSpearAction::Execute(Event) { // Find the nearest spear Creature* spear = bot->FindNearestCreature(NPC_SPEAR, 100.0f); @@ -4883,7 +4851,7 @@ bool IccValkyreSpearAction::Execute(Event event) return false; } -bool IccSisterSvalnaAction::Execute(Event event) +bool IccSisterSvalnaAction::Execute(Event) { Unit* svalna = AI_VALUE2(Unit*, "find target", "sister svalna"); if (!svalna || !svalna->HasAura(SPELL_AETHER_SHIELD)) // Check for Aether Shield aura @@ -4908,7 +4876,7 @@ bool IccSisterSvalnaAction::Execute(Event event) } // VDW -bool IccValithriaGroupAction::Execute(Event event) +bool IccValithriaGroupAction::Execute(Event) { // Helper lambda to find nearest creature of given entries auto findNearestCreature = [this](std::initializer_list entries, float range) -> Creature* @@ -5318,7 +5286,7 @@ bool IccValithriaGroupAction::Handle10ManGroupLogic() return false; } -bool IccValithriaPortalAction::Execute(Event event) +bool IccValithriaPortalAction::Execute(Event) { // Only healers should take portals, and not if already inside if (!botAI->IsHeal(bot) || bot->HasAura(SPELL_DREAM_STATE)) @@ -5451,7 +5419,7 @@ bool IccValithriaPortalAction::Execute(Event event) return false; } -bool IccValithriaHealAction::Execute(Event event) +bool IccValithriaHealAction::Execute(Event) { // Early validation checks if (!botAI->IsHeal(bot) || bot->GetHealthPct() < 50.0f) @@ -5541,7 +5509,7 @@ bool IccValithriaHealAction::Execute(Event event) return false; } -bool IccValithriaDreamCloudAction::Execute(Event event) +bool IccValithriaDreamCloudAction::Execute(Event) { // Only execute if we're in dream state if (!bot->HasAura(SPELL_DREAM_STATE)) @@ -5572,7 +5540,6 @@ bool IccValithriaDreamCloudAction::Execute(Event event) auto it = std::find(dreamBots.begin(), dreamBots.end(), bot); if (it == dreamBots.end()) return false; - size_t myIndex = std::distance(dreamBots.begin(), it); // Check if all dream bots are stacked within 3f of the current leader (lowest guid) constexpr float STACK_RADIUS = 2.0f; @@ -5612,7 +5579,7 @@ bool IccValithriaDreamCloudAction::Execute(Event event) std::vector dreamClouds; std::vector nightmareClouds; - for (int i = 0; i < npcs.size(); ++i) + for (uint64_t i = 0; i < npcs.size(); ++i) { Unit* unit = botAI->GetUnit(npcs[i]); if (unit && unit->IsAlive()) @@ -5824,7 +5791,7 @@ bool IccValithriaDreamCloudAction::Execute(Event event) } // Sindragosa -bool IccSindragosaGroupPositionAction::Execute(Event event) +bool IccSindragosaGroupPositionAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "sindragosa"); if (!boss || boss->HasUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY)) @@ -6083,7 +6050,7 @@ bool IccSindragosaGroupPositionAction::MoveIncrementallyToPosition(const Positio MovementPriority::MOVEMENT_COMBAT); } -bool IccSindragosaTankSwapPositionAction::Execute(Event event) +bool IccSindragosaTankSwapPositionAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "sindragosa"); if (!boss) @@ -6107,7 +6074,7 @@ bool IccSindragosaTankSwapPositionAction::Execute(Event event) return false; } -bool IccSindragosaFrostBeaconAction::Execute(Event event) +bool IccSindragosaFrostBeaconAction::Execute(Event) { const Unit* boss = AI_VALUE2(Unit*, "find target", "sindragosa"); if (!boss) @@ -6341,7 +6308,7 @@ bool IccSindragosaFrostBeaconAction::IsBossFlying(const Unit* boss) ICC_SINDRAGOSA_FLYING_POSITION.GetPositionY()) < 30.0f; } -bool IccSindragosaBlisteringColdAction::Execute(Event event) +bool IccSindragosaBlisteringColdAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "sindragosa"); if (!boss) @@ -6389,7 +6356,7 @@ bool IccSindragosaBlisteringColdAction::Execute(Event event) return false; } -bool IccSindragosaUnchainedMagicAction::Execute(Event event) +bool IccSindragosaUnchainedMagicAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "sindragosa"); if (!boss) @@ -6411,7 +6378,7 @@ bool IccSindragosaUnchainedMagicAction::Execute(Event event) return false; } -bool IccSindragosaChilledToTheBoneAction::Execute(Event event) +bool IccSindragosaChilledToTheBoneAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "sindragosa"); if (!boss) @@ -6434,7 +6401,7 @@ bool IccSindragosaChilledToTheBoneAction::Execute(Event event) return false; } -bool IccSindragosaMysticBuffetAction::Execute(Event event) +bool IccSindragosaMysticBuffetAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "sindragosa"); if (!boss || !bot || !bot->IsAlive()) @@ -6517,7 +6484,7 @@ bool IccSindragosaMysticBuffetAction::Execute(Event event) return false; } -bool IccSindragosaFrostBombAction::Execute(Event event) +bool IccSindragosaFrostBombAction::Execute(Event) { if (!bot || !bot->IsAlive() || bot->HasAura(SPELL_ICE_TOMB)) // Skip if dead or in Ice Tomb return false; @@ -6709,7 +6676,6 @@ bool IccSindragosaFrostBombAction::Execute(Event event) } } Unit* losTomb = myTombs[bestIdx]; - ObjectGuid losTombGuid = myTombGuids[bestIdx]; // Calculate position for LOS (stand at least 6.5f behind the tomb from the bomb) float angle = marker->GetAngle(losTomb); @@ -6792,7 +6758,6 @@ bool IccSindragosaFrostBombAction::Execute(Event event) // Clear the marker for our group's icon group->SetTargetIcon(iconIndex, bot->GetGUID(), ObjectGuid::Empty); } - Unit* boss = AI_VALUE2(Unit*, "find target", "sindragosa"); bot->AttackStop(); return true; } @@ -6802,7 +6767,7 @@ bool IccSindragosaFrostBombAction::Execute(Event event) } // The Lich King -bool IccLichKingShadowTrapAction::Execute(Event event) +bool IccLichKingShadowTrapAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "the lich king"); if (!boss || !botAI->IsTank(bot)) @@ -6810,7 +6775,7 @@ bool IccLichKingShadowTrapAction::Execute(Event event) Difficulty diff = bot->GetRaidDifficulty(); - if (sPlayerbotAIConfig->EnableICCBuffs && diff && (diff == RAID_DIFFICULTY_10MAN_HEROIC || diff == RAID_DIFFICULTY_25MAN_HEROIC)) + if (sPlayerbotAIConfig.EnableICCBuffs && diff && (diff == RAID_DIFFICULTY_10MAN_HEROIC || diff == RAID_DIFFICULTY_25MAN_HEROIC)) { //-------CHEAT------- if (!bot->HasAura(SPELL_EXPERIENCED)) @@ -6929,7 +6894,7 @@ bool IccLichKingShadowTrapAction::Execute(Event event) return false; } -bool IccLichKingNecroticPlagueAction::Execute(Event event) +bool IccLichKingNecroticPlagueAction::Execute(Event) { bool hasPlague = botAI->HasAura("Necrotic Plague", bot); // Only execute if we have the plague @@ -6981,7 +6946,7 @@ bool IccLichKingNecroticPlagueAction::Execute(Event event) return false; } -bool IccLichKingWinterAction::Execute(Event event) +bool IccLichKingWinterAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "the lich king"); if (!boss) @@ -7006,7 +6971,7 @@ bool IccLichKingWinterAction::Execute(Event event) Difficulty diff = bot->GetRaidDifficulty(); - if (sPlayerbotAIConfig->EnableICCBuffs && diff && (diff == RAID_DIFFICULTY_10MAN_HEROIC || diff == RAID_DIFFICULTY_25MAN_HEROIC)) + if (sPlayerbotAIConfig.EnableICCBuffs && diff && (diff == RAID_DIFFICULTY_10MAN_HEROIC || diff == RAID_DIFFICULTY_25MAN_HEROIC)) { //------CHEAT------- if (!bot->HasAura(SPELL_EXPERIENCED)) @@ -7032,7 +6997,6 @@ bool IccLichKingWinterAction::Execute(Event event) const ObjectGuid currentSkullTarget = group->GetTargetIcon(7); if (!currentSkullTarget.IsEmpty()) { - Unit* skullTarget = ObjectAccessor::GetUnit(*bot, currentSkullTarget); group->SetTargetIcon(7, bot->GetGUID(), ObjectGuid::Empty); } } @@ -7196,7 +7160,7 @@ const Position* IccLichKingWinterAction::GetMainTankRangedPosition() return &ICC_LK_FROSTR3_POSITION; } -bool IccLichKingWinterAction::IsPositionSafeFromDefile(float x, float y, float z, float minSafeDistance) +bool IccLichKingWinterAction::IsPositionSafeFromDefile(float x, float y, float, float minSafeDistance) { Unit* boss = AI_VALUE2(Unit*, "find target", "the lich king"); if (!boss) @@ -7556,7 +7520,7 @@ void IccLichKingWinterAction::HandleRangedPositioning() } } -void IccLichKingWinterAction::HandleMainTankAddManagement(Unit* boss, const Position* tankPos) +void IccLichKingWinterAction::HandleMainTankAddManagement(Unit*, const Position* tankPos) { if (!botAI->IsMainTank(bot)) return; @@ -7679,7 +7643,7 @@ void IccLichKingWinterAction::HandleMainTankAddManagement(Unit* boss, const Posi } } -void IccLichKingWinterAction::HandleAssistTankAddManagement(Unit* boss, const Position* tankPos) +void IccLichKingWinterAction::HandleAssistTankAddManagement(Unit*, const Position* tankPos) { if (!botAI->IsAssistTank(bot)) return; @@ -7783,7 +7747,7 @@ void IccLichKingWinterAction::HandleAssistTankAddManagement(Unit* boss, const Po } } -bool IccLichKingAddsAction::Execute(Event event) +bool IccLichKingAddsAction::Execute(Event) { if (bot->HasAura(SPELL_HARVEST_SOUL_VALKYR)) // Don't process actions if bot is picked up by Val'kyr return false; @@ -7792,7 +7756,7 @@ bool IccLichKingAddsAction::Execute(Event event) Difficulty diff = bot->GetRaidDifficulty(); - if (sPlayerbotAIConfig->EnableICCBuffs && diff && (diff == RAID_DIFFICULTY_10MAN_HEROIC || diff == RAID_DIFFICULTY_25MAN_HEROIC)) + if (sPlayerbotAIConfig.EnableICCBuffs && diff && (diff == RAID_DIFFICULTY_10MAN_HEROIC || diff == RAID_DIFFICULTY_25MAN_HEROIC)) { //------CHEAT------- if (!bot->HasAura(SPELL_EXPERIENCED)) @@ -7812,7 +7776,6 @@ bool IccLichKingAddsAction::Execute(Event event) //------CHEAT------- } - Unit* spiritWarden = AI_VALUE2(Unit*, "find target", "spirit warden"); bool hasPlague = botAI->HasAura("Necrotic Plague", bot); Unit* terenasMenethilHC = bot->FindNearestCreature(NPC_TERENAS_MENETHIL_HC, 55.0f); @@ -8324,7 +8287,7 @@ bool IccLichKingAddsAction::HandleQuakeMechanics(Unit* boss) return false; } -void IccLichKingAddsAction::HandleShamblingHorrors(Unit* boss, bool hasPlague) +void IccLichKingAddsAction::HandleShamblingHorrors(Unit*, bool) { // Find closest shambling horror GuidVector npcs2 = AI_VALUE(GuidVector, "nearest hostile npcs"); @@ -8485,8 +8448,6 @@ bool IccLichKingAddsAction::HandleAssistTankAddManagement(Unit* boss, Difficulty // In heroic mode, stay at melee position if (diff && (diff == RAID_DIFFICULTY_10MAN_HEROIC || diff == RAID_DIFFICULTY_25MAN_HEROIC)) { - Unit* mainTank = AI_VALUE(Unit*, "main tank"); - if (bot->GetExactDist2d(ICC_LICH_KING_ASSISTHC_POSITION.GetPositionX(), ICC_LICH_KING_ASSISTHC_POSITION.GetPositionY()) > 2.0f) { @@ -8723,7 +8684,6 @@ void IccLichKingAddsAction::HandleDefileMechanics(Unit* boss, Difficulty diff) // Gather all defile units std::vector defiles; - Unit* closestDefile = nullptr; float closestDistance = std::numeric_limits::max(); GuidVector npcs = AI_VALUE(GuidVector, "nearest hostile npcs"); @@ -8737,7 +8697,6 @@ void IccLichKingAddsAction::HandleDefileMechanics(Unit* boss, Difficulty diff) if (dist < closestDistance) { closestDistance = dist; - closestDefile = unit; } } } @@ -9078,7 +9037,6 @@ void IccLichKingAddsAction::HandleValkyrMarking(const std::vector& grabbi std::sort(sortedValkyrs.begin(), sortedValkyrs.end(), [](Unit* a, Unit* b) { return a->GetGUID() < b->GetGUID(); }); static constexpr uint8_t ICON_INDICES[] = {7, 6, 0}; // Skull, Cross, Star - static constexpr const char* ICON_NAMES[] = {"skull", "cross", "star"}; // In heroic mode, clean up invalid markers for all possible icons if (diff && (diff == RAID_DIFFICULTY_10MAN_HEROIC || diff == RAID_DIFFICULTY_25MAN_HEROIC)) @@ -9192,7 +9150,7 @@ void IccLichKingAddsAction::HandleValkyrAssignment(const std::vector& gra bot->SetFacingToObject(myValkyr); Difficulty diff = bot->GetRaidDifficulty(); - if (sPlayerbotAIConfig->EnableICCBuffs && diff && (diff == RAID_DIFFICULTY_10MAN_HEROIC || diff == RAID_DIFFICULTY_25MAN_HEROIC)) + if (sPlayerbotAIConfig.EnableICCBuffs && diff && (diff == RAID_DIFFICULTY_10MAN_HEROIC || diff == RAID_DIFFICULTY_25MAN_HEROIC)) { //---------CHEAT--------- if (!myValkyr->HasAura(SPELL_HAMMER_OF_JUSTICE)) diff --git a/src/Ai/Raid/Icecrown/Action/RaidIccActions.h b/src/Ai/Raid/Icecrown/Action/RaidIccActions.h index 9ac2a48a04..b692fcfbfe 100644 --- a/src/Ai/Raid/Icecrown/Action/RaidIccActions.h +++ b/src/Ai/Raid/Icecrown/Action/RaidIccActions.h @@ -4,14 +4,9 @@ #include "Action.h" #include "MovementActions.h" #include "PlayerbotAI.h" -#include "Playerbots.h" #include "AttackAction.h" #include "LastMovementValue.h" #include "ObjectGuid.h" -#include "PlayerbotAIConfig.h" -#include "RaidIccStrategy.h" -#include "ScriptedCreature.h" -#include "SharedDefines.h" #include "Trigger.h" #include "CellImpl.h" #include "GridNotifiers.h" diff --git a/src/Ai/Raid/Icecrown/Multiplier/RaidIccMultipliers.cpp b/src/Ai/Raid/Icecrown/Multiplier/RaidIccMultipliers.cpp index fc02d56bea..fe6a097035 100644 --- a/src/Ai/Raid/Icecrown/Multiplier/RaidIccMultipliers.cpp +++ b/src/Ai/Raid/Icecrown/Multiplier/RaidIccMultipliers.cpp @@ -15,7 +15,6 @@ #include "RaidIccActions.h" #include "ReachTargetActions.h" #include "RogueActions.h" -#include "ScriptedCreature.h" #include "ShamanActions.h" #include "UseMeetingStoneAction.h" #include "WarriorActions.h" @@ -25,21 +24,19 @@ // LK global variables namespace { -uint32 g_lastPlagueTime = 0; -bool g_plagueAllowedToCure = false; std::map g_plagueTimes; std::map g_allowCure; std::mutex g_plagueMutex; // Lock before accessing shared variables } // Lady Deathwhisper -float IccLadyDeathwhisperMultiplier::GetValue(Action* action) +float IccLadyDeathwhisperMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "lady deathwhisper"); if (!boss) return 1.0f; - if (dynamic_cast(action) || dynamic_cast(action) || dynamic_cast(action)) + if (dynamic_cast(&action) || dynamic_cast(&action) || dynamic_cast(&action)) return 0.0f; static constexpr uint32 VENGEFUL_SHADE_ID = NPC_SHADE; @@ -48,7 +45,7 @@ float IccLadyDeathwhisperMultiplier::GetValue(Action* action) const GuidVector npcs = AI_VALUE(GuidVector, "nearest hostile npcs"); // Allow the IccShadeLadyDeathwhisperAction to run - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 1.0f; for (auto const& npcGuid : npcs) @@ -68,22 +65,22 @@ float IccLadyDeathwhisperMultiplier::GetValue(Action* action) } // dbs -float IccAddsDbsMultiplier::GetValue(Action* action) +float IccAddsDbsMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "deathbringer saurfang"); if (!boss) return 1.0f; - if (dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action)) + if (dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action)) return 0.0f; if (botAI->IsRanged(bot)) - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 0.0f; if (botAI->IsMainTank(bot)) @@ -91,7 +88,7 @@ float IccAddsDbsMultiplier::GetValue(Action* action) Aura* aura = botAI->GetAura("rune of blood", bot); if (aura) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 1.0f; else return 0.0f; @@ -102,7 +99,7 @@ float IccAddsDbsMultiplier::GetValue(Action* action) } // dogs -float IccDogsMultiplier::GetValue(Action* action) +float IccDogsMultiplier::GetValue(Action& action) { bool bossPresent = false; if (AI_VALUE2(Unit*, "find target", "stinky") || AI_VALUE2(Unit*, "find target", "precious")) @@ -116,7 +113,7 @@ float IccDogsMultiplier::GetValue(Action* action) Aura* aura = botAI->GetAura("mortal wound", bot, false, true); if (aura && aura->GetStackAmount() >= 8) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 1.0f; else return 0.0f; @@ -126,16 +123,16 @@ float IccDogsMultiplier::GetValue(Action* action) } // Festergut -float IccFestergutMultiplier::GetValue(Action* action) +float IccFestergutMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "festergut"); if (!boss) return 1.0f; - if (dynamic_cast(action) || dynamic_cast(action)) + if (dynamic_cast(&action) || dynamic_cast(&action)) return 0.0f; - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 0.0f; if (botAI->IsMainTank(bot)) @@ -143,14 +140,14 @@ float IccFestergutMultiplier::GetValue(Action* action) Aura* aura = botAI->GetAura("gastric bloat", bot, false, true); if (aura && aura->GetStackAmount() >= 6) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 1.0f; else return 0.0f; } } - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 1.0f; if (bot->HasAura(SPELL_GAS_SPORE)) @@ -160,22 +157,22 @@ float IccFestergutMultiplier::GetValue(Action* action) } // Rotface -float IccRotfaceMultiplier::GetValue(Action* action) +float IccRotfaceMultiplier::GetValue(Action& action) { Unit* boss1 = AI_VALUE2(Unit*, "find target", "rotface"); if (!boss1) return 1.0f; - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 0.0f; - if (dynamic_cast(action) && !(bot->getClass() == CLASS_HUNTER)) + if (dynamic_cast(&action) && !(bot->getClass() == CLASS_HUNTER)) return 0.0f; - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 0.0f; - if (botAI->IsAssistTank(bot) && (dynamic_cast(action) || dynamic_cast(action))) + if (botAI->IsAssistTank(bot) && (dynamic_cast(&action) || dynamic_cast(&action))) return 0.0f; Unit* boss = AI_VALUE2(Unit*, "find target", "big ooze"); @@ -211,8 +208,8 @@ float IccRotfaceMultiplier::GetValue(Action* action) // If 9 seconds have passed since cast start and we haven't moved yet if (lastExplosionTimes[botGuid] > 0 && !hasMoved[botGuid] && time(nullptr) - lastExplosionTimes[botGuid] >= 9) { - if (dynamic_cast(action) - && !dynamic_cast(action)) + if (dynamic_cast(&action) + && !dynamic_cast(&action)) { return 0.0f; // Block other movement actions } @@ -221,15 +218,15 @@ float IccRotfaceMultiplier::GetValue(Action* action) // Continue blocking other movements for 7 seconds after moving if (hasMoved[botGuid] && time(nullptr) - lastExplosionTimes[botGuid] < 16 // 9 seconds wait + 7 seconds stay - && dynamic_cast(action) - && !dynamic_cast(action)) + && dynamic_cast(&action) + && !dynamic_cast(&action)) return 0.0f; return 1.0f; } // pp -float IccAddsPutricideMultiplier::GetValue(Action* action) +float IccAddsPutricideMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "professor putricide"); if (!boss) @@ -238,16 +235,16 @@ float IccAddsPutricideMultiplier::GetValue(Action* action) bool hasGaseousBloat = botAI->HasAura("Gaseous Bloat", bot); bool hasUnboundPlague = botAI->HasAura("Unbound Plague", bot); - if (!(bot->getClass() == CLASS_HUNTER) && dynamic_cast(action)) + if (!(bot->getClass() == CLASS_HUNTER) && dynamic_cast(&action)) return 0.0f; - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 0.0f; - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 0.0f; - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 0.0f; if (botAI->IsMainTank(bot)) @@ -255,7 +252,7 @@ float IccAddsPutricideMultiplier::GetValue(Action* action) Aura* aura = botAI->GetAura("mutated plague", bot, false, true); if (aura && aura->GetStackAmount() >= 4) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 1.0f; else return 0.0f; @@ -264,10 +261,10 @@ float IccAddsPutricideMultiplier::GetValue(Action* action) if (hasGaseousBloat) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 1.0f; - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 1.0f; if (botAI->IsHeal(bot)) @@ -278,17 +275,17 @@ float IccAddsPutricideMultiplier::GetValue(Action* action) if (hasUnboundPlague && boss && !boss->HealthBelowPct(35)) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 1.0f; else return 0.0f; // Cancel all other actions when we need to handle Unbound Plague } - if (dynamic_cast(action)) + if (dynamic_cast(&action)) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 0.0f; - if (dynamic_cast(action) && !botAI->IsMainTank(bot)) + if (dynamic_cast(&action) && !botAI->IsMainTank(bot)) return 0.0f; //if (dynamic_cast(action) && !hasGaseousBloat) //return 0.0f; @@ -298,17 +295,17 @@ float IccAddsPutricideMultiplier::GetValue(Action* action) } // bpc -float IccBpcAssistMultiplier::GetValue(Action* action) +float IccBpcAssistMultiplier::GetValue(Action& action) { Unit* keleseth = AI_VALUE2(Unit*, "find target", "prince keleseth"); if (!keleseth) return 1.0f; - if (dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action)) + if (dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action)) return 0.0f; Aura* aura = botAI->GetAura("Shadow Prison", bot, false, true); @@ -316,13 +313,13 @@ float IccBpcAssistMultiplier::GetValue(Action* action) { if (aura->GetStackAmount() > 18 && botAI->IsTank(bot)) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 0.0f; } if (aura->GetStackAmount() > 12 && !botAI->IsTank(bot)) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 0.0f; } } @@ -337,7 +334,7 @@ float IccBpcAssistMultiplier::GetValue(Action* action) valanar->FindCurrentSpellBySpellId(SPELL_EMPOWERED_SHOCK_VORTEX3) || valanar->FindCurrentSpellBySpellId(SPELL_EMPOWERED_SHOCK_VORTEX4))) { - if (dynamic_cast(action) || dynamic_cast(action)) + if (dynamic_cast(&action) || dynamic_cast(&action)) return 1.0f; else return 0.0f; // Cancel all other actions when we need to handle Empowered Vortex @@ -350,17 +347,17 @@ float IccBpcAssistMultiplier::GetValue(Action* action) if (flame2) { - if (dynamic_cast(action) || dynamic_cast(action)) + if (dynamic_cast(&action) || dynamic_cast(&action)) return 0.0f; - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 1.0f; } if (ballOfFlame || infernoFlame) { // If bot is tank, do nothing special - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 1.0f; else return 0.0f; // Cancel all other actions when we need to handle Ball of Flame @@ -396,11 +393,11 @@ float IccBpcAssistMultiplier::GetValue(Action* action) if (bombFound && !(aura && aura->GetStackAmount() > 12) && !botAI->IsTank(bot)) { // If kinetic bomb action is active, disable these actions - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 1.0f; - if (dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action)) + if (dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action)) return 0.0f; } @@ -408,14 +405,14 @@ float IccBpcAssistMultiplier::GetValue(Action* action) if (botAI->IsAssistTank(bot) && !(aura && aura->GetStackAmount() > 18)) { // Allow BPC-specific actions - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 1.0f; // Disable normal assist behavior - if (dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action)) + if (dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action)) return 0.0f; } @@ -424,7 +421,7 @@ float IccBpcAssistMultiplier::GetValue(Action* action) } //BQL -float IccBqlMultiplier::GetValue(Action* action) +float IccBqlMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "blood-queen lana'thel"); if (!boss) @@ -434,14 +431,14 @@ float IccBqlMultiplier::GetValue(Action* action) Aura* aura = botAI->GetAura("Frenzied Bloodthirst", bot); if (botAI->IsRanged(bot)) - if (dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action)) + if (dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action)) return 0.0f; // If bot has Pact of Darkfallen aura, return 0 for all other actions if (bot->HasAura(SPELL_PACT_OF_THE_DARKFALLEN)) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 1.0f; // Allow Pact of Darkfallen action else return 0.0f; // Cancel all other actions when we need to handle Pact of Darkfallen @@ -449,7 +446,7 @@ float IccBqlMultiplier::GetValue(Action* action) if (botAI->IsMelee(bot) && ((boss->GetPositionZ() - ICC_BQL_CENTER_POSITION.GetPositionZ()) > 5.0f) && !aura) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 1.0f; else return 0.0f; @@ -458,7 +455,7 @@ float IccBqlMultiplier::GetValue(Action* action) // If bot has frenzied bloodthirst, allow highest priority for bite action if (aura) // If bot has frenzied bloodthirst { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 1.0f; else return 0.0f; @@ -466,7 +463,7 @@ float IccBqlMultiplier::GetValue(Action* action) if (aura2 && !aura) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 1.0f; else return 0.0f; // Cancel all other actions when we need to handle Swarming Shadows @@ -475,7 +472,7 @@ float IccBqlMultiplier::GetValue(Action* action) if ((boss->GetExactDist2d(ICC_BQL_TANK_POSITION.GetPositionX(), ICC_BQL_TANK_POSITION.GetPositionY()) > 10.0f) && botAI->IsRanged(bot) && !((boss->GetPositionZ() - bot->GetPositionZ()) > 5.0f)) { - if (dynamic_cast(action) || dynamic_cast(action)) + if (dynamic_cast(&action) || dynamic_cast(&action)) return 0.0f; } @@ -483,7 +480,7 @@ float IccBqlMultiplier::GetValue(Action* action) } //VDW -float IccValithriaDreamCloudMultiplier::GetValue(Action* action) +float IccValithriaDreamCloudMultiplier::GetValue(Action& action) { Unit* boss = bot->FindNearestCreature(NPC_VALITHRIA_DREAMWALKER, 100.0f); @@ -493,22 +490,22 @@ float IccValithriaDreamCloudMultiplier::GetValue(Action* action) if (!boss && !bot->HasAura(SPELL_DREAM_STATE)) return 1.0f; - if (dynamic_cast(action) || dynamic_cast(action)) + if (dynamic_cast(&action) || dynamic_cast(&action)) return 0.0f; if (botAI->IsTank(bot)) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 0.0f; } if (botAI->IsHeal(bot) && (twistedNightmares || emeraldVigor)) - if (dynamic_cast(action) || dynamic_cast(action)) + if (dynamic_cast(&action) || dynamic_cast(&action)) return 0.0f; if (bot->HasAura(SPELL_DREAM_STATE) && !bot->HealthBelowPct(50)) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 1.0f; // Allow Dream Cloud action else return 0.0f; // Cancel all other actions when we need to handle Dream Cloud @@ -520,7 +517,7 @@ float IccValithriaDreamCloudMultiplier::GetValue(Action* action) //SINDRAGOSA -float IccSindragosaMultiplier::GetValue(Action* action) +float IccSindragosaMultiplier::GetValue(Action& action) { Unit* boss = bot->FindNearestCreature(NPC_SINDRAGOSA, 200.0f); if (!boss) @@ -531,15 +528,15 @@ float IccSindragosaMultiplier::GetValue(Action* action) if (boss->HealthBelowPct(95)) { - if (dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action)) + if (dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action)) return 0.0f; } if (aura && (diff == RAID_DIFFICULTY_10MAN_HEROIC || diff == RAID_DIFFICULTY_25MAN_HEROIC) && - !dynamic_cast(action)) + !dynamic_cast(&action)) { - if (dynamic_cast(action) || dynamic_cast(action)) + if (dynamic_cast(&action) || dynamic_cast(&action)) return 1.0f; else return 0.0f; @@ -551,10 +548,10 @@ float IccSindragosaMultiplier::GetValue(Action* action) boss->FindCurrentSpellBySpellId(71048) || boss->FindCurrentSpellBySpellId(71049))) { // If this is the blistering cold action, give it highest priority - if (dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action)) + if (dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action)) return 1.0f; // Disable all other actions while blistering cold is casting @@ -564,7 +561,7 @@ float IccSindragosaMultiplier::GetValue(Action* action) // Highest priority if we have beacon if (bot->HasAura(SPELL_FROST_BEACON)) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 1.0f; else return 0.0f; @@ -592,7 +589,7 @@ float IccSindragosaMultiplier::GetValue(Action* action) ICC_SINDRAGOSA_FLYING_POSITION.GetPositionY()) < 30.0f && !boss->HealthBelowPct(25) && !boss->HealthAbovePct(99)) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 1.0f; else return 0.0f; @@ -600,7 +597,7 @@ float IccSindragosaMultiplier::GetValue(Action* action) if (anyoneHasFrostBeacon && !botAI->IsMainTank(bot)) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 0.0f; } @@ -609,7 +606,7 @@ float IccSindragosaMultiplier::GetValue(Action* action) Aura* aura = botAI->GetAura("mystic buffet", bot, false, true); if (aura && aura->GetStackAmount() >= 6) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 1.0f; else return 0.0f; @@ -618,7 +615,7 @@ float IccSindragosaMultiplier::GetValue(Action* action) if (!botAI->IsTank(bot) && boss && boss->HealthBelowPct(35)) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 0.0f; } @@ -626,8 +623,8 @@ float IccSindragosaMultiplier::GetValue(Action* action) { if (boss->HealthBelowPct(35)) { - if (dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action)) + if (dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action)) return 1.0f; else return 0.0f; @@ -636,33 +633,33 @@ float IccSindragosaMultiplier::GetValue(Action* action) if (boss && boss->GetExactDist2d(ICC_SINDRAGOSA_FLYING_POSITION.GetPositionX(), ICC_SINDRAGOSA_FLYING_POSITION.GetPositionY()) < 30.0f && !boss->HealthBelowPct(25) && !boss->HealthAbovePct(99)) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 1.0f; - if (dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action)) + if (dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action)) return 0.0f; } return 1.0f; } -float IccLichKingAddsMultiplier::GetValue(Action* action) +float IccLichKingAddsMultiplier::GetValue(Action& action) { Unit* terenasMenethilHC = bot->FindNearestCreature(NPC_TERENAS_MENETHIL_HC, 55.0f); if (!terenasMenethilHC) - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 0.0f; if (terenasMenethilHC) @@ -671,23 +668,23 @@ float IccLichKingAddsMultiplier::GetValue(Action* action) if (!botAI->IsMainTank(bot) && mainTank && bot->GetExactDist2d(mainTank->GetPositionX(), mainTank->GetPositionY()) < 2.0f) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 0.0f; } if (botAI->IsMelee(bot) || (bot->getClass() == CLASS_WARLOCK)) { - if (dynamic_cast(action) || dynamic_cast(action)) + if (dynamic_cast(&action) || dynamic_cast(&action)) return 1.0f; else return 0.0f; } - if (dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action)) + if (dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action)) return 0.0f; } @@ -696,9 +693,9 @@ float IccLichKingAddsMultiplier::GetValue(Action* action) return 1.0f; // Handle cure actions - if (dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action)) + if (dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action)) { Group* group = bot->GetGroup(); if (!group) @@ -759,25 +756,25 @@ float IccLichKingAddsMultiplier::GetValue(Action* action) return 0.0f; } - if (dynamic_cast(action) && (bot->getClass() != CLASS_HUNTER)) + if (dynamic_cast(&action) && (bot->getClass() != CLASS_HUNTER)) return 0.0f; - if (dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action)) + if (dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action)) return 0.0f; if (boss && !boss->HealthBelowPct(71)) { if (!botAI->IsTank(bot)) - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 0.0f; - if (dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action)) + if (dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action)) return 0.0f; } @@ -810,29 +807,29 @@ float IccLichKingAddsMultiplier::GetValue(Action* action) if (hasWinterAura || hasWinter2Aura || (isCasting && isWinter)) { - if (dynamic_cast(action) || dynamic_cast(action)) + if (dynamic_cast(&action) || dynamic_cast(&action)) return 1.0f; - if (botAI->IsAssistTank(bot) && dynamic_cast(action)) + if (botAI->IsAssistTank(bot) && dynamic_cast(&action)) return 0.0f; - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 0.0f; if (currentTarget && boss && bot->GetDistance2d(boss->GetPositionX(), boss->GetPositionY()) > 50.0f && currentTarget == boss) { - if (dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action)) + if (dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action)) return 0.0f; } if (currentTarget && (currentTarget->GetEntry() == NPC_ICE_SPHERE1 || currentTarget->GetEntry() == NPC_ICE_SPHERE2 || currentTarget->GetEntry() == NPC_ICE_SPHERE3 || currentTarget->GetEntry() == NPC_ICE_SPHERE4)) { - if (dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action)) + if (dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action)) return 0.0f; } @@ -855,11 +852,11 @@ float IccLichKingAddsMultiplier::GetValue(Action* action) // Only disable movement if defile is present if (defilePresent && ( - dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action))) + dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action))) { return 0.0f; } @@ -867,7 +864,7 @@ float IccLichKingAddsMultiplier::GetValue(Action* action) if (botAI->IsAssistTank(bot) && boss && !boss->HealthBelowPct(71) && currentTarget == boss) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 0.0f; } diff --git a/src/Ai/Raid/Icecrown/Multiplier/RaidIccMultipliers.h b/src/Ai/Raid/Icecrown/Multiplier/RaidIccMultipliers.h index 69d1ac51ba..7f814a3f17 100644 --- a/src/Ai/Raid/Icecrown/Multiplier/RaidIccMultipliers.h +++ b/src/Ai/Raid/Icecrown/Multiplier/RaidIccMultipliers.h @@ -8,7 +8,7 @@ class IccLadyDeathwhisperMultiplier : public Multiplier { public: IccLadyDeathwhisperMultiplier(PlayerbotAI* ai) : Multiplier(ai, "icc lady deathwhisper") {} - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; //DBS @@ -16,7 +16,7 @@ class IccAddsDbsMultiplier : public Multiplier { public: IccAddsDbsMultiplier(PlayerbotAI* ai) : Multiplier(ai, "icc adds dbs") {} - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; //DOGS @@ -25,7 +25,7 @@ class IccDogsMultiplier : public Multiplier { public: IccDogsMultiplier(PlayerbotAI* ai) : Multiplier(ai, "icc dogs") {} - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; //FESTERGUT @@ -33,7 +33,7 @@ class IccFestergutMultiplier : public Multiplier { public: IccFestergutMultiplier(PlayerbotAI* ai) : Multiplier(ai, "icc festergut") {} - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; //ROTFACE @@ -41,14 +41,14 @@ class IccRotfaceMultiplier : public Multiplier { public: IccRotfaceMultiplier(PlayerbotAI* ai) : Multiplier(ai, "icc rotface") {} - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; /*class IccRotfaceGroupPositionMultiplier : public Multiplier { public: IccRotfaceGroupPositionMultiplier(PlayerbotAI* ai) : Multiplier(ai, "icc rotface group position") {} - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); };*/ //PP @@ -56,7 +56,7 @@ class IccAddsPutricideMultiplier : public Multiplier { public: IccAddsPutricideMultiplier(PlayerbotAI* ai) : Multiplier(ai, "icc adds putricide") {} - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; //BPC @@ -64,7 +64,7 @@ class IccBpcAssistMultiplier : public Multiplier { public: IccBpcAssistMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "icc bpc assist") {} - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; //BQL @@ -72,7 +72,7 @@ class IccBqlMultiplier : public Multiplier { public: IccBqlMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "icc bql multiplier") {} - virtual float GetValue(Action* action) override; + virtual float GetValue(Action& action) override; }; //VDW @@ -80,7 +80,7 @@ class IccValithriaDreamCloudMultiplier : public Multiplier { public: IccValithriaDreamCloudMultiplier(PlayerbotAI* ai) : Multiplier(ai, "icc valithria dream cloud") {} - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; //SINDRAGOSA @@ -88,7 +88,7 @@ class IccSindragosaMultiplier : public Multiplier { public: IccSindragosaMultiplier(PlayerbotAI* ai) : Multiplier(ai, "icc sindragosa") {} - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; //LK @@ -96,7 +96,7 @@ class IccLichKingAddsMultiplier : public Multiplier { public: IccLichKingAddsMultiplier(PlayerbotAI* ai) : Multiplier(ai, "icc lich king adds") {} - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; #endif diff --git a/src/Ai/Raid/Icecrown/RaidIccActionContext.h b/src/Ai/Raid/Icecrown/RaidIccActionContext.h deleted file mode 100644 index e648b09b73..0000000000 --- a/src/Ai/Raid/Icecrown/RaidIccActionContext.h +++ /dev/null @@ -1,139 +0,0 @@ -#ifndef _PLAYERBOT_RAIDICCACTIONCONTEXT_H -#define _PLAYERBOT_RAIDICCACTIONCONTEXT_H - -#include "Action.h" -#include "NamedObjectContext.h" -#include "RaidIccActions.h" - -class RaidIccActionContext : public NamedObjectContext -{ -public: - RaidIccActionContext() - { - creators["icc lm tank position"] = &RaidIccActionContext::icc_lm_tank_position; - creators["icc spike"] = &RaidIccActionContext::icc_spike; - - creators["icc dark reckoning"] = &RaidIccActionContext::icc_dark_reckoning; - creators["icc ranged position lady deathwhisper"] = &RaidIccActionContext::icc_ranged_position_lady_deathwhisper; - creators["icc adds lady deathwhisper"] = &RaidIccActionContext::icc_adds_lady_deathwhisper; - creators["icc shade lady deathwhisper"] = &RaidIccActionContext::icc_shade_lady_deathwhisper; - - creators["icc rotting frost giant tank position"] = &RaidIccActionContext::icc_rotting_frost_giant_tank_position; - creators["icc cannon fire"] = &RaidIccActionContext::icc_cannon_fire; - creators["icc gunship enter cannon"] = &RaidIccActionContext::icc_gunship_enter_cannon; - creators["icc gunship teleport ally"] = &RaidIccActionContext::icc_gunship_teleport_ally; - creators["icc gunship teleport horde"] = &RaidIccActionContext::icc_gunship_teleport_horde; - - creators["icc dbs tank position"] = &RaidIccActionContext::icc_dbs_tank_position; - creators["icc adds dbs"] = &RaidIccActionContext::icc_adds_dbs; - - creators["icc festergut group position"] = &RaidIccActionContext::icc_festergut_group_position; - creators["icc festergut spore"] = &RaidIccActionContext::icc_festergut_spore; - - creators["icc rotface tank position"] = &RaidIccActionContext::icc_rotface_tank_position; - creators["icc rotface group position"] = &RaidIccActionContext::icc_rotface_group_position; - creators["icc rotface move away from explosion"] = &RaidIccActionContext::icc_rotface_move_away_from_explosion; - - creators["icc putricide volatile ooze"] = &RaidIccActionContext::icc_putricide_volatile_ooze; - creators["icc putricide gas cloud"] = &RaidIccActionContext::icc_putricide_gas_cloud; - creators["icc putricide growing ooze puddle"] = &RaidIccActionContext::icc_putricide_growing_ooze_puddle; - creators["icc putricide avoid malleable goo"] = &RaidIccActionContext::icc_putricide_avoid_malleable_goo; - - creators["icc bpc keleseth tank"] = &RaidIccActionContext::icc_bpc_keleseth_tank; - creators["icc bpc main tank"] = &RaidIccActionContext::icc_bpc_main_tank; - creators["icc bpc empowered vortex"] = &RaidIccActionContext::icc_bpc_empowered_vortex; - creators["icc bpc kinetic bomb"] = &RaidIccActionContext::icc_bpc_kinetic_bomb; - creators["icc bpc ball of flame"] = &RaidIccActionContext::icc_bpc_ball_of_flame; - - creators["icc bql group position"] = &RaidIccActionContext::icc_bql_group_position; - creators["icc bql pact of darkfallen"] = &RaidIccActionContext::icc_bql_pact_of_darkfallen; - creators["icc bql vampiric bite"] = &RaidIccActionContext::icc_bql_vampiric_bite; - - creators["icc valkyre spear"] = &RaidIccActionContext::icc_valkyre_spear; - creators["icc sister svalna"] = &RaidIccActionContext::icc_sister_svalna; - - creators["icc valithria group"] = &RaidIccActionContext::icc_valithria_group; - creators["icc valithria portal"] = &RaidIccActionContext::icc_valithria_portal; - creators["icc valithria heal"] = &RaidIccActionContext::icc_valithria_heal; - creators["icc valithria dream cloud"] = &RaidIccActionContext::icc_valithria_dream_cloud; - - creators["icc sindragosa group position"] = &RaidIccActionContext::icc_sindragosa_group_position; - creators["icc sindragosa frost beacon"] = &RaidIccActionContext::icc_sindragosa_frost_beacon; - creators["icc sindragosa blistering cold"] = &RaidIccActionContext::icc_sindragosa_blistering_cold; - creators["icc sindragosa unchained magic"] = &RaidIccActionContext::icc_sindragosa_unchained_magic; - creators["icc sindragosa chilled to the bone"] = &RaidIccActionContext::icc_sindragosa_chilled_to_the_bone; - creators["icc sindragosa mystic buffet"] = &RaidIccActionContext::icc_sindragosa_mystic_buffet; - creators["icc sindragosa frost bomb"] = &RaidIccActionContext::icc_sindragosa_frost_bomb; - creators["icc sindragosa tank swap position"] = &RaidIccActionContext::icc_sindragosa_tank_swap_position; - - creators["icc lich king shadow trap"] = &RaidIccActionContext::icc_lich_king_shadow_trap; - creators["icc lich king necrotic plague"] = &RaidIccActionContext::icc_lich_king_necrotic_plague; - creators["icc lich king winter"] = &RaidIccActionContext::icc_lich_king_winter; - creators["icc lich king adds"] = &RaidIccActionContext::icc_lich_king_adds; - } - -private: - static Action* icc_lm_tank_position(PlayerbotAI* ai) { return new IccLmTankPositionAction(ai); } - static Action* icc_spike(PlayerbotAI* ai) { return new IccSpikeAction(ai); } - - static Action* icc_dark_reckoning(PlayerbotAI* ai) { return new IccDarkReckoningAction(ai); } - static Action* icc_ranged_position_lady_deathwhisper(PlayerbotAI* ai) { return new IccRangedPositionLadyDeathwhisperAction(ai); } - static Action* icc_adds_lady_deathwhisper(PlayerbotAI* ai) { return new IccAddsLadyDeathwhisperAction(ai); } - static Action* icc_shade_lady_deathwhisper(PlayerbotAI* ai) { return new IccShadeLadyDeathwhisperAction(ai); } - - static Action* icc_rotting_frost_giant_tank_position(PlayerbotAI* ai) { return new IccRottingFrostGiantTankPositionAction(ai); } - static Action* icc_cannon_fire(PlayerbotAI* ai) { return new IccCannonFireAction(ai); } - static Action* icc_gunship_enter_cannon(PlayerbotAI* ai) { return new IccGunshipEnterCannonAction(ai); } - static Action* icc_gunship_teleport_ally(PlayerbotAI* ai) { return new IccGunshipTeleportAllyAction(ai); } - static Action* icc_gunship_teleport_horde(PlayerbotAI* ai) { return new IccGunshipTeleportHordeAction(ai); } - - static Action* icc_dbs_tank_position(PlayerbotAI* ai) { return new IccDbsTankPositionAction(ai); } - static Action* icc_adds_dbs(PlayerbotAI* ai) { return new IccAddsDbsAction(ai); } - - static Action* icc_festergut_group_position(PlayerbotAI* ai) { return new IccFestergutGroupPositionAction(ai); } - static Action* icc_festergut_spore(PlayerbotAI* ai) { return new IccFestergutSporeAction(ai); } - - static Action* icc_rotface_tank_position(PlayerbotAI* ai) { return new IccRotfaceTankPositionAction(ai); } - static Action* icc_rotface_group_position(PlayerbotAI* ai) { return new IccRotfaceGroupPositionAction(ai); } - static Action* icc_rotface_move_away_from_explosion(PlayerbotAI* ai) { return new IccRotfaceMoveAwayFromExplosionAction(ai); } - - static Action* icc_putricide_volatile_ooze(PlayerbotAI* ai) { return new IccPutricideVolatileOozeAction(ai); } - static Action* icc_putricide_gas_cloud(PlayerbotAI* ai) { return new IccPutricideGasCloudAction(ai); } - static Action* icc_putricide_growing_ooze_puddle(PlayerbotAI* ai) { return new IccPutricideGrowingOozePuddleAction(ai); } - static Action* icc_putricide_avoid_malleable_goo(PlayerbotAI* ai) { return new IccPutricideAvoidMalleableGooAction(ai); } - - static Action* icc_bpc_keleseth_tank(PlayerbotAI* ai) { return new IccBpcKelesethTankAction(ai); } - static Action* icc_bpc_main_tank(PlayerbotAI* ai) { return new IccBpcMainTankAction(ai); } - static Action* icc_bpc_empowered_vortex(PlayerbotAI* ai) { return new IccBpcEmpoweredVortexAction(ai); } - static Action* icc_bpc_kinetic_bomb(PlayerbotAI* ai) { return new IccBpcKineticBombAction(ai); } - static Action* icc_bpc_ball_of_flame(PlayerbotAI* ai) { return new IccBpcBallOfFlameAction(ai); } - - static Action* icc_bql_group_position(PlayerbotAI* ai) { return new IccBqlGroupPositionAction(ai); } - static Action* icc_bql_pact_of_darkfallen(PlayerbotAI* ai) { return new IccBqlPactOfDarkfallenAction(ai); } - static Action* icc_bql_vampiric_bite(PlayerbotAI* ai) { return new IccBqlVampiricBiteAction(ai); } - - static Action* icc_valkyre_spear(PlayerbotAI* ai) { return new IccValkyreSpearAction(ai); } - static Action* icc_sister_svalna(PlayerbotAI* ai) { return new IccSisterSvalnaAction(ai); } - - static Action* icc_valithria_group(PlayerbotAI* ai) { return new IccValithriaGroupAction(ai); } - static Action* icc_valithria_portal(PlayerbotAI* ai) { return new IccValithriaPortalAction(ai); } - static Action* icc_valithria_heal(PlayerbotAI* ai) { return new IccValithriaHealAction(ai); } - static Action* icc_valithria_dream_cloud(PlayerbotAI* ai) { return new IccValithriaDreamCloudAction(ai); } - - static Action* icc_sindragosa_group_position(PlayerbotAI* ai) { return new IccSindragosaGroupPositionAction(ai); } - static Action* icc_sindragosa_frost_beacon(PlayerbotAI* ai) { return new IccSindragosaFrostBeaconAction(ai); } - static Action* icc_sindragosa_blistering_cold(PlayerbotAI* ai) { return new IccSindragosaBlisteringColdAction(ai); } - static Action* icc_sindragosa_unchained_magic(PlayerbotAI* ai) { return new IccSindragosaUnchainedMagicAction(ai); } - static Action* icc_sindragosa_chilled_to_the_bone(PlayerbotAI* ai) { return new IccSindragosaChilledToTheBoneAction(ai); } - static Action* icc_sindragosa_mystic_buffet(PlayerbotAI* ai) { return new IccSindragosaMysticBuffetAction(ai); } - static Action* icc_sindragosa_frost_bomb(PlayerbotAI* ai) { return new IccSindragosaFrostBombAction(ai); } - static Action* icc_sindragosa_tank_swap_position(PlayerbotAI* ai) { return new IccSindragosaTankSwapPositionAction(ai); } - - static Action* icc_lich_king_shadow_trap(PlayerbotAI* ai) { return new IccLichKingShadowTrapAction(ai); } - static Action* icc_lich_king_necrotic_plague(PlayerbotAI* ai) { return new IccLichKingNecroticPlagueAction(ai); } - static Action* icc_lich_king_winter(PlayerbotAI* ai) { return new IccLichKingWinterAction(ai); } - static Action* icc_lich_king_adds(PlayerbotAI* ai) { return new IccLichKingAddsAction(ai); } - -}; - -#endif diff --git a/src/Ai/Raid/Icecrown/Strategy/RaidIccStrategy.cpp b/src/Ai/Raid/Icecrown/Strategy/RaidIccStrategy.cpp index e0dbe82306..f78602fcb5 100644 --- a/src/Ai/Raid/Icecrown/Strategy/RaidIccStrategy.cpp +++ b/src/Ai/Raid/Icecrown/Strategy/RaidIccStrategy.cpp @@ -1,173 +1,471 @@ #include "RaidIccStrategy.h" +#include "CreateNextAction.h" #include "RaidIccMultipliers.h" +#include "RaidIccActions.h" +#include "combat/UniversalTauntAction.h" void RaidIccStrategy::InitTriggers(std::vector& triggers) { //Lord Marrogwar - triggers.push_back(new TriggerNode("icc lm", - { NextAction("icc lm tank position", ACTION_RAID + 5), - NextAction("icc spike", ACTION_RAID + 3) })); + triggers.push_back( + new TriggerNode( + "icc lm", + { + CreateNextAction(ACTION_RAID + 5.0f), + CreateNextAction(ACTION_RAID + 3.0f) + } + ) + ); //Lady Deathwhisper - triggers.push_back(new TriggerNode("icc dark reckoning", - { NextAction("icc dark reckoning", ACTION_MOVE + 5) })); - - triggers.push_back(new TriggerNode("icc lady deathwhisper", - { NextAction("icc ranged position lady deathwhisper", ACTION_MOVE + 2), - NextAction("icc adds lady deathwhisper", ACTION_RAID + 3), - NextAction("icc shade lady deathwhisper", ACTION_RAID + 4) })); + triggers.push_back( + new TriggerNode( + "icc dark reckoning", + { + CreateNextAction(ACTION_MOVE + 5.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc lady deathwhisper", + { + CreateNextAction(ACTION_MOVE + 2.0f), + CreateNextAction(ACTION_RAID + 3.0f), + CreateNextAction(ACTION_RAID + 4.0f) + } + ) + ); //Gunship Battle - triggers.push_back(new TriggerNode("icc rotting frost giant tank position", - { NextAction("icc rotting frost giant tank position", ACTION_RAID + 5) })); - - triggers.push_back(new TriggerNode("icc gunship cannon near", - { NextAction("icc gunship enter cannon", ACTION_RAID + 6) })); - - triggers.push_back( new TriggerNode("icc in cannon", - { NextAction("icc cannon fire", ACTION_RAID+5) })); - - triggers.push_back(new TriggerNode("icc gunship teleport ally", - { NextAction("icc gunship teleport ally", ACTION_RAID + 4) })); - - triggers.push_back(new TriggerNode("icc gunship teleport horde", - { NextAction("icc gunship teleport horde", ACTION_RAID + 4) })); + triggers.push_back( + new TriggerNode( + "icc rotting frost giant tank position", + { + CreateNextAction(ACTION_RAID + 5.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc gunship cannon near", + { + CreateNextAction(ACTION_RAID + 6.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc in cannon", + { + CreateNextAction(ACTION_RAID + 5.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc gunship teleport ally", + { + CreateNextAction(ACTION_RAID + 4.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc gunship teleport horde", + { + CreateNextAction(ACTION_RAID + 4.0f) + } + ) + ); //DBS - triggers.push_back(new TriggerNode("icc dbs", - { NextAction("icc dbs tank position", ACTION_RAID + 3), - NextAction("icc adds dbs", ACTION_RAID + 5) })); - - triggers.push_back(new TriggerNode("icc dbs main tank rune of blood", - { NextAction("taunt spell", ACTION_EMERGENCY + 4) })); + triggers.push_back( + new TriggerNode( + "icc dbs", + { + CreateNextAction(ACTION_RAID + 3.0f), + CreateNextAction(ACTION_RAID + 5.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc dbs main tank rune of blood", + { + // This requires a specific action to be created + CreateNextAction(ACTION_EMERGENCY + 4.0f) + } + ) + ); //DOGS - triggers.push_back(new TriggerNode("icc stinky precious main tank mortal wound", - { NextAction("taunt spell", ACTION_EMERGENCY + 4) })); + triggers.push_back( + new TriggerNode( + "icc stinky precious main tank mortal wound", + { + CreateNextAction(ACTION_EMERGENCY + 4.0f) + } + ) + ); //FESTERGUT - triggers.push_back(new TriggerNode("icc festergut group position", - { NextAction("icc festergut group position", ACTION_MOVE + 4) })); - - triggers.push_back(new TriggerNode("icc festergut main tank gastric bloat", - { NextAction("taunt spell", ACTION_EMERGENCY + 6) })); - - triggers.push_back(new TriggerNode("icc festergut spore", - { NextAction("icc festergut spore", ACTION_MOVE + 5) })); + triggers.push_back( + new TriggerNode( + "icc festergut group position", + { + CreateNextAction(ACTION_MOVE + 4.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc festergut main tank gastric bloat", + { + CreateNextAction(ACTION_EMERGENCY + 6.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc festergut spore", + { + CreateNextAction(ACTION_MOVE + 5.0f) + } + ) + ); //ROTFACE - triggers.push_back(new TriggerNode("icc rotface tank position", - { NextAction("icc rotface tank position", ACTION_RAID + 5) })); - - triggers.push_back(new TriggerNode("icc rotface group position", - { NextAction("icc rotface group position", ACTION_RAID + 6) })); - - triggers.push_back(new TriggerNode("icc rotface move away from explosion", - { NextAction("icc rotface move away from explosion", ACTION_RAID +7) })); + triggers.push_back( + new TriggerNode( + "icc rotface tank position", + { + CreateNextAction(ACTION_RAID + 5.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc rotface group position", + { + CreateNextAction(ACTION_RAID + 6.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc rotface move away from explosion", + { + CreateNextAction(ACTION_RAID + 7.0f) + } + ) + ); //PP - triggers.push_back(new TriggerNode("icc putricide volatile ooze", - { NextAction("icc putricide volatile ooze", ACTION_RAID + 4) })); - - triggers.push_back(new TriggerNode("icc putricide gas cloud", - { NextAction("icc putricide gas cloud", ACTION_RAID + 5) })); - - triggers.push_back(new TriggerNode("icc putricide growing ooze puddle", - { NextAction("icc putricide growing ooze puddle", ACTION_RAID + 3) })); - - triggers.push_back(new TriggerNode("icc putricide main tank mutated plague", - { NextAction("taunt spell", ACTION_RAID + 10) })); - - triggers.push_back(new TriggerNode("icc putricide malleable goo", - { NextAction("icc putricide avoid malleable goo", ACTION_RAID + 2) })); + triggers.push_back( + new TriggerNode( + "icc putricide volatile ooze", + { + CreateNextAction(ACTION_RAID + 4.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc putricide gas cloud", + { + CreateNextAction(ACTION_RAID + 5.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc putricide growing ooze puddle", + { + CreateNextAction(ACTION_RAID + 3.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc putricide main tank mutated plague", + { + CreateNextAction(ACTION_RAID + 10.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc putricide malleable goo", + { + CreateNextAction(ACTION_RAID + 2.0f) + } + ) + ); //BPC - triggers.push_back(new TriggerNode("icc bpc keleseth tank", - { NextAction("icc bpc keleseth tank", ACTION_RAID + 1) })); - - triggers.push_back(new TriggerNode("icc bpc main tank", - { NextAction("icc bpc main tank", ACTION_RAID + 3) })); - - triggers.push_back(new TriggerNode("icc bpc empowered vortex", - { NextAction("icc bpc empowered vortex", ACTION_RAID + 4) })); - - triggers.push_back(new TriggerNode("icc bpc kinetic bomb", - { NextAction("icc bpc kinetic bomb", ACTION_RAID + 6) })); - - triggers.push_back(new TriggerNode("icc bpc ball of flame", - { NextAction("icc bpc ball of flame", ACTION_RAID + 7) })); + triggers.push_back( + new TriggerNode( + "icc bpc keleseth tank", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc bpc main tank", + { + CreateNextAction(ACTION_RAID + 3.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc bpc empowered vortex", + { + CreateNextAction(ACTION_RAID + 4.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc bpc kinetic bomb", + { + CreateNextAction(ACTION_RAID + 6.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc bpc ball of flame", + { + CreateNextAction(ACTION_RAID + 7.0f) + } + ) + ); //BQL - triggers.push_back(new TriggerNode("icc bql group position", - { NextAction("icc bql group position", ACTION_RAID) })); - - triggers.push_back(new TriggerNode("icc bql pact of darkfallen", - { NextAction("icc bql pact of darkfallen", ACTION_RAID +1) })); - - triggers.push_back(new TriggerNode("icc bql vampiric bite", - { NextAction("icc bql vampiric bite", ACTION_EMERGENCY + 5) })); + triggers.push_back( + new TriggerNode( + "icc bql group position", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc bql pact of darkfallen", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc bql vampiric bite", + { + CreateNextAction(ACTION_EMERGENCY + 5.0f) + } + ) + ); //Sister Svalna - triggers.push_back(new TriggerNode("icc valkyre spear", - { NextAction("icc valkyre spear", ACTION_EMERGENCY + 5) })); - - triggers.push_back(new TriggerNode("icc sister svalna", - { NextAction("icc sister svalna", ACTION_RAID + 5) })); + triggers.push_back( + new TriggerNode( + "icc valkyre spear", + { + CreateNextAction(ACTION_EMERGENCY + 5.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc sister svalna", + { + CreateNextAction(ACTION_RAID + 5.0f) + } + ) + ); //VDW - triggers.push_back(new TriggerNode("icc valithria group", - { NextAction("icc valithria group", ACTION_RAID + 1) })); - - triggers.push_back(new TriggerNode("icc valithria portal", - { NextAction("icc valithria portal", ACTION_RAID + 5) })); - - triggers.push_back(new TriggerNode("icc valithria heal", - { NextAction("icc valithria heal", ACTION_RAID+2) })); - - triggers.push_back(new TriggerNode("icc valithria dream cloud", - { NextAction("icc valithria dream cloud", ACTION_RAID + 4) })); + triggers.push_back( + new TriggerNode( + "icc valithria group", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc valithria portal", + { + CreateNextAction(ACTION_RAID + 5.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc valithria heal", + { + CreateNextAction(ACTION_RAID + 2.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc valithria dream cloud", + { + CreateNextAction(ACTION_RAID + 4.0f) + } + ) + ); //SINDRAGOSA - triggers.push_back(new TriggerNode("icc sindragosa group position", - { NextAction("icc sindragosa group position", ACTION_RAID + 1) })); - - triggers.push_back(new TriggerNode("icc sindragosa frost beacon", - { NextAction("icc sindragosa frost beacon", ACTION_RAID + 5) })); - - triggers.push_back(new TriggerNode("icc sindragosa blistering cold", - { NextAction("icc sindragosa blistering cold", ACTION_EMERGENCY + 4) })); - - triggers.push_back(new TriggerNode("icc sindragosa unchained magic", - { NextAction("icc sindragosa unchained magic", ACTION_RAID + 2) })); - - triggers.push_back(new TriggerNode("icc sindragosa chilled to the bone", - { NextAction("icc sindragosa chilled to the bone", ACTION_RAID + 2) })); - - triggers.push_back(new TriggerNode("icc sindragosa mystic buffet", - { NextAction("icc sindragosa mystic buffet", ACTION_RAID + 3) })); - - triggers.push_back(new TriggerNode("icc sindragosa main tank mystic buffet", - { NextAction("taunt spell", ACTION_EMERGENCY + 3) })); - - triggers.push_back(new TriggerNode("icc sindragosa frost bomb", - { NextAction("icc sindragosa frost bomb", ACTION_RAID + 7) })); - - triggers.push_back(new TriggerNode("icc sindragosa tank swap position", - { NextAction("icc sindragosa tank swap position", ACTION_EMERGENCY + 2) })); + triggers.push_back( + new TriggerNode( + "icc sindragosa group position", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc sindragosa frost beacon", + { + CreateNextAction(ACTION_RAID + 5.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc sindragosa blistering cold", + { + CreateNextAction(ACTION_EMERGENCY + 4.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc sindragosa unchained magic", + { + CreateNextAction(ACTION_RAID + 2.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc sindragosa chilled to the bone", + { + CreateNextAction(ACTION_RAID + 2.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc sindragosa mystic buffet", + { + CreateNextAction(ACTION_RAID + 3.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc sindragosa main tank mystic buffet", + { + CreateNextAction(ACTION_EMERGENCY + 3.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc sindragosa frost bomb", + { + CreateNextAction(ACTION_RAID + 7.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc sindragosa tank swap position", + { + CreateNextAction(ACTION_EMERGENCY + 2.0f) + } + ) + ); //LICH KING - triggers.push_back(new TriggerNode("icc lich king shadow trap", - { NextAction("icc lich king shadow trap", ACTION_RAID + 6) })); - - triggers.push_back(new TriggerNode("icc lich king necrotic plague", - { NextAction("icc lich king necrotic plague", ACTION_RAID + 3) })); - - triggers.push_back(new TriggerNode("icc lich king winter", - { NextAction("icc lich king winter", ACTION_RAID +5) })); - - triggers.push_back(new TriggerNode("icc lich king adds", - { NextAction("icc lich king adds", ACTION_RAID +2) })); + triggers.push_back( + new TriggerNode( + "icc lich king shadow trap", + { + CreateNextAction(ACTION_RAID + 6.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc lich king necrotic plague", + { + CreateNextAction(ACTION_RAID + 3.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc lich king winter", + { + CreateNextAction(ACTION_RAID + 5.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "icc lich king adds", + { + CreateNextAction(ACTION_RAID + 2.0f) + } + ) + ); } void RaidIccStrategy::InitMultipliers(std::vector& multipliers) diff --git a/src/Ai/Raid/Icecrown/Strategy/RaidIccStrategy.h b/src/Ai/Raid/Icecrown/Strategy/RaidIccStrategy.h index 53967c3344..e3ec8824d0 100644 --- a/src/Ai/Raid/Icecrown/Strategy/RaidIccStrategy.h +++ b/src/Ai/Raid/Icecrown/Strategy/RaidIccStrategy.h @@ -4,7 +4,6 @@ #include "AiObjectContext.h" #include "Multiplier.h" #include "Strategy.h" -#include "RaidIccMultipliers.h" class RaidIccStrategy : public Strategy { diff --git a/src/Ai/Raid/Icecrown/Trigger/RaidIccTriggers.cpp b/src/Ai/Raid/Icecrown/Trigger/RaidIccTriggers.cpp index b9ebb8ca8d..8fdef577ec 100644 --- a/src/Ai/Raid/Icecrown/Trigger/RaidIccTriggers.cpp +++ b/src/Ai/Raid/Icecrown/Trigger/RaidIccTriggers.cpp @@ -4,14 +4,9 @@ #include "PlayerbotAIConfig.h" #include "ObjectAccessor.h" #include "GenericTriggers.h" -#include "DungeonStrategyUtils.h" -#include "EventMap.h" #include "Playerbots.h" -#include "ScriptedCreature.h" #include "Trigger.h" -#include "CellImpl.h" #include "GridNotifiers.h" -#include "GridNotifiersImpl.h" #include "Vehicle.h" //Lord Marrogwar @@ -287,7 +282,7 @@ bool IccPutricideGrowingOozePuddleTrigger::IsActive() Difficulty diff = bot->GetRaidDifficulty(); - if (sPlayerbotAIConfig->EnableICCBuffs && diff && (diff == RAID_DIFFICULTY_10MAN_HEROIC || diff == RAID_DIFFICULTY_25MAN_HEROIC)) + if (sPlayerbotAIConfig.EnableICCBuffs && diff && (diff == RAID_DIFFICULTY_10MAN_HEROIC || diff == RAID_DIFFICULTY_25MAN_HEROIC)) { //-------CHEAT------- if (!bot->HasAura(SPELL_EXPERIENCED)) @@ -564,10 +559,7 @@ bool IccBqlVampiricBiteTrigger::IsActive() bool IccValkyreSpearTrigger::IsActive() { // Check if there's a spear nearby - if (Creature* spear = bot->FindNearestCreature(NPC_SPEAR, 100.0f)) - return true; - - return false; + return bot->FindNearestCreature(NPC_SPEAR, 100.0f) != nullptr; } bool IccSisterSvalnaTrigger::IsActive() @@ -834,7 +826,7 @@ bool IccSindragosaGroupPositionTrigger::IsActive() Difficulty diff = bot->GetRaidDifficulty(); - if (sPlayerbotAIConfig->EnableICCBuffs && diff && (diff == RAID_DIFFICULTY_10MAN_HEROIC || diff == RAID_DIFFICULTY_25MAN_HEROIC)) + if (sPlayerbotAIConfig.EnableICCBuffs && diff && (diff == RAID_DIFFICULTY_10MAN_HEROIC || diff == RAID_DIFFICULTY_25MAN_HEROIC)) { //-------CHEAT------- if (!bot->HasAura(SPELL_EXPERIENCED)) @@ -1107,7 +1099,6 @@ bool IccLichKingShadowTrapTrigger::IsActive() // search for all nearby traps GuidVector npcs = AI_VALUE(GuidVector, "nearest hostile npcs"); std::vector nearbyTraps; - bool needToMove = false; for (auto& npc : npcs) { @@ -1151,15 +1142,21 @@ bool IccLichKingWinterTrigger::IsActive() isCasting = true; bool isWinter = false; - if (boss && boss->FindCurrentSpellBySpellId(SPELL_REMORSELESS_WINTER1) || - boss->FindCurrentSpellBySpellId(SPELL_REMORSELESS_WINTER2) || - boss->FindCurrentSpellBySpellId(SPELL_REMORSELESS_WINTER5) || - boss->FindCurrentSpellBySpellId(SPELL_REMORSELESS_WINTER6) || - boss->FindCurrentSpellBySpellId(SPELL_REMORSELESS_WINTER3) || - boss->FindCurrentSpellBySpellId(SPELL_REMORSELESS_WINTER4) || - boss->FindCurrentSpellBySpellId(SPELL_REMORSELESS_WINTER7) || - boss->FindCurrentSpellBySpellId(SPELL_REMORSELESS_WINTER8)) + if (boss + && ( + boss->FindCurrentSpellBySpellId(SPELL_REMORSELESS_WINTER1) + || boss->FindCurrentSpellBySpellId(SPELL_REMORSELESS_WINTER2) + || boss->FindCurrentSpellBySpellId(SPELL_REMORSELESS_WINTER5) + || boss->FindCurrentSpellBySpellId(SPELL_REMORSELESS_WINTER6) + || boss->FindCurrentSpellBySpellId(SPELL_REMORSELESS_WINTER3) + || boss->FindCurrentSpellBySpellId(SPELL_REMORSELESS_WINTER4) + || boss->FindCurrentSpellBySpellId(SPELL_REMORSELESS_WINTER7) + || boss->FindCurrentSpellBySpellId(SPELL_REMORSELESS_WINTER8) + ) + ) + { isWinter = true; + } if (hasWinterAura || hasWinter2Aura) return true; diff --git a/src/Ai/Raid/Karazhan/Action/RaidKarazhanActions.cpp b/src/Ai/Raid/Karazhan/Action/RaidKarazhanActions.cpp index 2e5d7abcfd..b9f85b1cfd 100644 --- a/src/Ai/Raid/Karazhan/Action/RaidKarazhanActions.cpp +++ b/src/Ai/Raid/Karazhan/Action/RaidKarazhanActions.cpp @@ -9,7 +9,7 @@ using namespace KarazhanHelpers; // Mana Warps blow up when they die for massive raid damage // But they cannot cast the ability if they are stunned -bool ManaWarpStunCreatureBeforeWarpBreachAction::Execute(Event event) +bool ManaWarpStunCreatureBeforeWarpBreachAction::Execute(Event) { Unit* manaWarp = GetFirstAliveUnitByEntry(botAI, NPC_MANA_WARP); if (!manaWarp) @@ -39,7 +39,7 @@ bool ManaWarpStunCreatureBeforeWarpBreachAction::Execute(Event event) // Attumen the Huntsman // Prioritize Midnight until Attumen is mounted -bool AttumenTheHuntsmanMarkTargetAction::Execute(Event event) +bool AttumenTheHuntsmanMarkTargetAction::Execute(Event) { Unit* attumenMounted = GetFirstAliveUnitByEntry(botAI, NPC_ATTUMEN_THE_HUNTSMAN_MOUNTED); if (attumenMounted) @@ -76,7 +76,7 @@ bool AttumenTheHuntsmanMarkTargetAction::Execute(Event event) } // Off tank should move Attumen out of the way so he doesn't cleave bots -bool AttumenTheHuntsmanSplitBossesAction::Execute(Event event) +bool AttumenTheHuntsmanSplitBossesAction::Execute(Event) { Unit* midnight = AI_VALUE2(Unit*, "find target", "midnight"); if (!midnight) @@ -104,7 +104,7 @@ bool AttumenTheHuntsmanSplitBossesAction::Execute(Event event) } // Stack behind mounted Attumen (inside minimum range of Berserker Charge) -bool AttumenTheHuntsmanStackBehindAction::Execute(Event event) +bool AttumenTheHuntsmanStackBehindAction::Execute(Event) { Unit* attumenMounted = GetFirstAliveUnitByEntry(botAI, NPC_ATTUMEN_THE_HUNTSMAN_MOUNTED); if (!attumenMounted) @@ -125,7 +125,7 @@ bool AttumenTheHuntsmanStackBehindAction::Execute(Event event) } // Reset timer for bots to pause DPS when Attumen mounts Midnight -bool AttumenTheHuntsmanManageDpsTimerAction::Execute(Event event) +bool AttumenTheHuntsmanManageDpsTimerAction::Execute(Event) { Unit* midnight = AI_VALUE2(Unit*, "find target", "midnight"); if (!midnight) @@ -152,7 +152,7 @@ bool AttumenTheHuntsmanManageDpsTimerAction::Execute(Event event) // Moroes -bool MoroesMainTankAttackBossAction::Execute(Event event) +bool MoroesMainTankAttackBossAction::Execute(Event) { Unit* moroes = AI_VALUE2(Unit*, "find target", "moroes"); if (!moroes) @@ -168,7 +168,7 @@ bool MoroesMainTankAttackBossAction::Execute(Event event) } // Mark targets with skull in the recommended kill order -bool MoroesMarkTargetAction::Execute(Event event) +bool MoroesMarkTargetAction::Execute(Event) { Unit* dorothea = AI_VALUE2(Unit*, "find target", "baroness dorothea millstipe"); Unit* catriona = AI_VALUE2(Unit*, "find target", "lady catriona von'indi"); @@ -193,7 +193,7 @@ bool MoroesMarkTargetAction::Execute(Event event) // Tank the boss in the center of the room // Move to healers after Repentenace to break the stun -bool MaidenOfVirtueMoveBossToHealerAction::Execute(Event event) +bool MaidenOfVirtueMoveBossToHealerAction::Execute(Event) { Unit* maiden = AI_VALUE2(Unit*, "find target", "maiden of virtue"); if (!maiden) @@ -247,7 +247,7 @@ bool MaidenOfVirtueMoveBossToHealerAction::Execute(Event event) } // Spread out ranged DPS between the pillars -bool MaidenOfVirtuePositionRangedAction::Execute(Event event) +bool MaidenOfVirtuePositionRangedAction::Execute(Event) { const uint8 maxIndex = 7; uint8 index = 0; @@ -287,7 +287,7 @@ bool MaidenOfVirtuePositionRangedAction::Execute(Event event) // The Big Bad Wolf // Tank the boss at the front left corner of the stage -bool BigBadWolfPositionBossAction::Execute(Event event) +bool BigBadWolfPositionBossAction::Execute(Event) { Unit* wolf = AI_VALUE2(Unit*, "find target", "the big bad wolf"); if (!wolf) @@ -318,7 +318,7 @@ bool BigBadWolfPositionBossAction::Execute(Event event) } // Run away, little girl, run away -bool BigBadWolfRunAwayFromBossAction::Execute(Event event) +bool BigBadWolfRunAwayFromBossAction::Execute(Event) { const ObjectGuid botGuid = bot->GetGUID(); uint8 index = bigBadWolfRunIndex.count(botGuid) ? bigBadWolfRunIndex[botGuid] : 0; @@ -341,7 +341,7 @@ bool BigBadWolfRunAwayFromBossAction::Execute(Event event) // Romulo and Julianne // Keep the couple within 10% HP of each other -bool RomuloAndJulianneMarkTargetAction::Execute(Event event) +bool RomuloAndJulianneMarkTargetAction::Execute(Event) { Unit* romulo = AI_VALUE2(Unit*, "find target", "romulo"); if (!romulo) @@ -370,7 +370,7 @@ bool RomuloAndJulianneMarkTargetAction::Execute(Event event) // The Wizard of Oz // Mark targets with skull in the recommended kill order -bool WizardOfOzMarkTargetAction::Execute(Event event) +bool WizardOfOzMarkTargetAction::Execute(Event) { Unit* dorothee = AI_VALUE2(Unit*, "find target", "dorothee"); Unit* tito = AI_VALUE2(Unit*, "find target", "tito"); @@ -387,7 +387,7 @@ bool WizardOfOzMarkTargetAction::Execute(Event event) } // Mages spam Scorch on Strawman to disorient him -bool WizardOfOzScorchStrawmanAction::Execute(Event event) +bool WizardOfOzScorchStrawmanAction::Execute(Event) { Unit* strawman = AI_VALUE2(Unit*, "find target", "strawman"); if (strawman && botAI->CanCastSpell("scorch", strawman)) @@ -399,7 +399,7 @@ bool WizardOfOzScorchStrawmanAction::Execute(Event event) // The Curator // Prioritize destroying Astral Flares -bool TheCuratorMarkAstralFlareAction::Execute(Event event) +bool TheCuratorMarkAstralFlareAction::Execute(Event) { Unit* flare = AI_VALUE2(Unit*, "find target", "astral flare"); if (!flare) @@ -415,7 +415,7 @@ bool TheCuratorMarkAstralFlareAction::Execute(Event event) // Tank the boss in the center of the hallway near the Guardian's Library // Main tank and off tank will attack the boss; others will focus on Astral Flares -bool TheCuratorPositionBossAction::Execute(Event event) +bool TheCuratorPositionBossAction::Execute(Event) { Unit* curator = AI_VALUE2(Unit*, "find target", "the curator"); if (!curator) @@ -449,7 +449,7 @@ bool TheCuratorPositionBossAction::Execute(Event event) } // Spread out ranged DPS to avoid Arcing Sear damage -bool TheCuratorSpreadRangedAction::Execute(Event event) +bool TheCuratorSpreadRangedAction::Execute(Event) { const float minDistance = 5.0f; Unit* nearestPlayer = GetNearestPlayerInRadius(bot, minDistance); @@ -467,7 +467,7 @@ bool TheCuratorSpreadRangedAction::Execute(Event event) // Terestian Illhoof // Prioritize (1) Demon Chains, (2) Kil'rek, (3) Illhoof -bool TerestianIllhoofMarkTargetAction::Execute(Event event) +bool TerestianIllhoofMarkTargetAction::Execute(Event) { Unit* demonChains = AI_VALUE2(Unit*, "find target", "demon chains"); Unit* kilrek = AI_VALUE2(Unit*, "find target", "kil'rek"); @@ -483,7 +483,7 @@ bool TerestianIllhoofMarkTargetAction::Execute(Event event) // Shade of Aran // Run to the edge of the room to avoid Arcane Explosion -bool ShadeOfAranRunAwayFromArcaneExplosionAction::Execute(Event event) +bool ShadeOfAranRunAwayFromArcaneExplosionAction::Execute(Event) { Unit* aran = AI_VALUE2(Unit*, "find target", "shade of aran"); if (!aran) @@ -502,7 +502,7 @@ bool ShadeOfAranRunAwayFromArcaneExplosionAction::Execute(Event event) } // I will not move when Flame Wreath is cast or the raid blows up -bool ShadeOfAranStopMovingDuringFlameWreathAction::Execute(Event event) +bool ShadeOfAranStopMovingDuringFlameWreathAction::Execute(Event) { AI_VALUE(LastMovement&, "last movement").Set(nullptr); @@ -517,7 +517,7 @@ bool ShadeOfAranStopMovingDuringFlameWreathAction::Execute(Event event) } // Mark Conjured Elementals with skull so DPS can burn them down -bool ShadeOfAranMarkConjuredElementalAction::Execute(Event event) +bool ShadeOfAranMarkConjuredElementalAction::Execute(Event) { Unit* elemental = GetFirstAliveUnitByEntry(botAI, NPC_CONJURED_ELEMENTAL); @@ -529,7 +529,7 @@ bool ShadeOfAranMarkConjuredElementalAction::Execute(Event event) // Don't get closer than 11 yards to Aran to avoid counterspell // Don't get farther than 15 yards from Aran to avoid getting stuck in alcoves -bool ShadeOfAranRangedMaintainDistanceAction::Execute(Event event) +bool ShadeOfAranRangedMaintainDistanceAction::Execute(Event) { Unit* aran = AI_VALUE2(Unit*, "find target", "shade of aran"); if (!aran) @@ -593,7 +593,7 @@ bool ShadeOfAranRangedMaintainDistanceAction::Execute(Event event) // One tank bot per phase will dance in and out of the red beam (5 seconds in, 5 seconds out) // Tank bots will ignore void zones--their positioning is too important to risk losing beam control -bool NetherspiteBlockRedBeamAction::Execute(Event event) +bool NetherspiteBlockRedBeamAction::Execute(Event) { Unit* netherspite = AI_VALUE2(Unit*, "find target", "netherspite"); if (!netherspite) @@ -617,7 +617,7 @@ bool NetherspiteBlockRedBeamAction::Execute(Event event) if (!wasBlocking) { std::map placeholders{{"%player", bot->GetName()}}; - std::string text = sPlayerbotTextMgr->GetBotTextOrDefault( + std::string text = PlayerbotTextMgr::instance().GetBotTextOrDefault( "netherspite_beam_blocking_red", "%player is moving to block the red beam!", placeholders); bot->Yell(text, LANG_UNIVERSAL); } @@ -680,7 +680,7 @@ Position NetherspiteBlockRedBeamAction::GetPositionOnBeam(Unit* netherspite, Uni // Two non-Rogue/Warrior DPS bots will block the blue beam for each phase (swap at 25 debuff stacks) // When avoiding void zones, blocking bots will move along the beam to continue blocking -bool NetherspiteBlockBlueBeamAction::Execute(Event event) +bool NetherspiteBlockBlueBeamAction::Execute(Event) { Unit* netherspite = AI_VALUE2(Unit*, "find target", "netherspite"); if (!netherspite) @@ -700,7 +700,7 @@ bool NetherspiteBlockBlueBeamAction::Execute(Event event) if (wasBlocking && !isBlockingNow) { std::map placeholders{{"%player", bot->GetName()}}; - std::string text = sPlayerbotTextMgr->GetBotTextOrDefault( + std::string text = PlayerbotTextMgr::instance().GetBotTextOrDefault( "netherspite_beam_leaving_blue", "%player is leaving the blue beam--next blocker up!", placeholders); bot->Yell(text, LANG_UNIVERSAL); _wasBlockingBlueBeam[botGuid] = false; @@ -711,7 +711,7 @@ bool NetherspiteBlockBlueBeamAction::Execute(Event event) if (!wasBlocking) { std::map placeholders{{"%player", bot->GetName()}}; - std::string text = sPlayerbotTextMgr->GetBotTextOrDefault( + std::string text = PlayerbotTextMgr::instance().GetBotTextOrDefault( "netherspite_beam_blocking_blue", "%player is moving to block the blue beam!", placeholders); bot->Yell(text, LANG_UNIVERSAL); } @@ -773,7 +773,7 @@ bool NetherspiteBlockBlueBeamAction::Execute(Event event) // Two healer bots will block the green beam for each phase (swap at 25 debuff stacks) // OR one rogue or DPS warrior bot will block the green beam for an entire phase (if they begin the phase as the blocker) // When avoiding void zones, blocking bots will move along the beam to continue blocking -bool NetherspiteBlockGreenBeamAction::Execute(Event event) +bool NetherspiteBlockGreenBeamAction::Execute(Event) { Unit* netherspite = AI_VALUE2(Unit*, "find target", "netherspite"); if (!netherspite) @@ -793,7 +793,7 @@ bool NetherspiteBlockGreenBeamAction::Execute(Event event) if (wasBlocking && !isBlockingNow) { std::map placeholders{{"%player", bot->GetName()}}; - std::string text = sPlayerbotTextMgr->GetBotTextOrDefault( + std::string text = PlayerbotTextMgr::instance().GetBotTextOrDefault( "netherspite_beam_leaving_green", "%player is leaving the green beam--next blocker up!", placeholders); bot->Yell(text, LANG_UNIVERSAL); _wasBlockingGreenBeam[botGuid] = false; @@ -804,7 +804,7 @@ bool NetherspiteBlockGreenBeamAction::Execute(Event event) if (!wasBlocking) { std::map placeholders{{"%player", bot->GetName()}}; - std::string text = sPlayerbotTextMgr->GetBotTextOrDefault( + std::string text = PlayerbotTextMgr::instance().GetBotTextOrDefault( "netherspite_beam_blocking_green", "%player is moving to block the green beam!", placeholders); bot->Yell(text, LANG_UNIVERSAL); } @@ -863,13 +863,12 @@ bool NetherspiteBlockGreenBeamAction::Execute(Event event) } // All bots not currently blocking a beam will avoid beams and void zones -bool NetherspiteAvoidBeamAndVoidZoneAction::Execute(Event event) +bool NetherspiteAvoidBeamAndVoidZoneAction::Execute(Event) { Unit* netherspite = AI_VALUE2(Unit*, "find target", "netherspite"); if (!netherspite) return false; - auto [redBlocker, greenBlocker, blueBlocker] = GetCurrentBeamBlockers(botAI, bot); std::vector voidZones = GetAllVoidZones(botAI, bot); bool nearVoidZone = !IsSafePosition(bot->GetPositionX(), bot->GetPositionY(), @@ -979,7 +978,7 @@ bool NetherspiteAvoidBeamAndVoidZoneAction::IsAwayFromBeams( return true; } -bool NetherspiteBanishPhaseAvoidVoidZoneAction::Execute(Event event) +bool NetherspiteBanishPhaseAvoidVoidZoneAction::Execute(Event) { std::vector voidZones = GetAllVoidZones(botAI, bot); @@ -992,7 +991,7 @@ bool NetherspiteBanishPhaseAvoidVoidZoneAction::Execute(Event event) return false; } -bool NetherspiteManageTimersAndTrackersAction::Execute(Event event) +bool NetherspiteManageTimersAndTrackersAction::Execute(Event) { Unit* netherspite = AI_VALUE2(Unit*, "find target", "netherspite"); if (!netherspite) @@ -1044,7 +1043,7 @@ bool NetherspiteManageTimersAndTrackersAction::Execute(Event event) // Move away from the boss to avoid Shadow Nova when Enfeebled // Do not cross within Infernal Hellfire radius while doing so -bool PrinceMalchezaarEnfeebledAvoidHazardAction::Execute(Event event) +bool PrinceMalchezaarEnfeebledAvoidHazardAction::Execute(Event) { Unit* malchezaar = AI_VALUE2(Unit*, "find target", "prince malchezaar"); if (!malchezaar) @@ -1056,7 +1055,6 @@ bool PrinceMalchezaarEnfeebledAvoidHazardAction::Execute(Event event) const float minSafeBossDistanceSq = minSafeBossDistance * minSafeBossDistance; const float maxSafeBossDistance = 60.0f; const float safeInfernalDistance = 23.0f; - const float safeInfernalDistanceSq = safeInfernalDistance * safeInfernalDistance; const float distIncrement = 0.5f; const uint8 numAngles = 64; @@ -1121,7 +1119,7 @@ bool PrinceMalchezaarEnfeebledAvoidHazardAction::Execute(Event event) // Move away from infernals while staying within range of the boss // Prioritize finding a safe path to the new location, but will fallback to just finding a safe location if needed -bool PrinceMalchezaarNonTankAvoidInfernalAction::Execute(Event event) +bool PrinceMalchezaarNonTankAvoidInfernalAction::Execute(Event) { Unit* malchezaar = AI_VALUE2(Unit*, "find target", "prince malchezaar"); if (!malchezaar) @@ -1188,7 +1186,7 @@ bool PrinceMalchezaarNonTankAvoidInfernalAction::Execute(Event event) // This is similar to the non-tank avoid infernal action, but the movement is based on the bot's location // And the safe distance from infernals is larger to give melee more room to maneuver -bool PrinceMalchezaarMainTankMovementAction::Execute(Event event) +bool PrinceMalchezaarMainTankMovementAction::Execute(Event) { Unit* malchezaar = AI_VALUE2(Unit*, "find target", "prince malchezaar"); if (!malchezaar) @@ -1254,7 +1252,7 @@ bool PrinceMalchezaarMainTankMovementAction::Execute(Event event) // The tank position is near the Southeastern area of the Master's Terrace // The tank moves Nightbane into position in two steps to try to get Nightbane to face sideways to the raid -bool NightbaneGroundPhasePositionBossAction::Execute(Event event) +bool NightbaneGroundPhasePositionBossAction::Execute(Event) { Unit* nightbane = AI_VALUE2(Unit*, "find target", "nightbane"); if (!nightbane) @@ -1300,7 +1298,7 @@ bool NightbaneGroundPhasePositionBossAction::Execute(Event event) // Ranged bots rotate between 3 positions to avoid standing in Charred Earth, which lasts for // 30s and has a minimum cooldown of 18s (so there can be 2 active at once) // Ranged positions are near the Northeastern door to the tower -bool NightbaneGroundPhaseRotateRangedPositionsAction::Execute(Event event) +bool NightbaneGroundPhaseRotateRangedPositionsAction::Execute(Event) { const ObjectGuid botGuid = bot->GetGUID(); uint8 index = nightbaneRangedStep.count(botGuid) ? nightbaneRangedStep[botGuid] : 0; @@ -1344,7 +1342,7 @@ bool NightbaneGroundPhaseRotateRangedPositionsAction::Execute(Event event) } // For countering Bellowing Roars during the ground phase -bool NightbaneCastFearWardOnMainTankAction::Execute(Event event) +bool NightbaneCastFearWardOnMainTankAction::Execute(Event) { Player* mainTank = nullptr; if (Group* group = bot->GetGroup()) @@ -1367,7 +1365,7 @@ bool NightbaneCastFearWardOnMainTankAction::Execute(Event event) } // Put pets on passive during the flight phase so they don't try to chase Nightbane off the map -bool NightbaneControlPetAggressionAction::Execute(Event event) +bool NightbaneControlPetAggressionAction::Execute(Event) { Unit* nightbane = AI_VALUE2(Unit*, "find target", "nightbane"); if (!nightbane) @@ -1393,7 +1391,7 @@ bool NightbaneControlPetAggressionAction::Execute(Event event) // 2. Once Rain of Bones hits, the whole party moves to a new stack position // This action lasts for the first 35 seconds of the flight phase, after which Nightbane gets // ready to land, and the player will need to lead the bots over near the ground phase position -bool NightbaneFlightPhaseMovementAction::Execute(Event event) +bool NightbaneFlightPhaseMovementAction::Execute(Event) { Unit* nightbane = AI_VALUE2(Unit*, "find target", "nightbane"); if (!nightbane || nightbane->GetPositionZ() <= NIGHTBANE_FLIGHT_Z) @@ -1439,7 +1437,7 @@ bool NightbaneFlightPhaseMovementAction::Execute(Event event) return false; } -bool NightbaneManageTimersAndTrackersAction::Execute(Event event) +bool NightbaneManageTimersAndTrackersAction::Execute(Event) { Unit* nightbane = AI_VALUE2(Unit*, "find target", "nightbane"); if (!nightbane) diff --git a/src/Ai/Raid/Karazhan/Multiplier/RaidKarazhanMultipliers.cpp b/src/Ai/Raid/Karazhan/Multiplier/RaidKarazhanMultipliers.cpp index 117a17f38a..63007862cb 100644 --- a/src/Ai/Raid/Karazhan/Multiplier/RaidKarazhanMultipliers.cpp +++ b/src/Ai/Raid/Karazhan/Multiplier/RaidKarazhanMultipliers.cpp @@ -17,7 +17,7 @@ using namespace KarazhanHelpers; // Keep tanks from jumping back and forth between Attumen and Midnight -float AttumenTheHuntsmanDisableTankAssistMultiplier::GetValue(Action* action) +float AttumenTheHuntsmanDisableTankAssistMultiplier::GetValue(Action& action) { Unit* midnight = AI_VALUE2(Unit*, "find target", "midnight"); if (!midnight) @@ -27,14 +27,14 @@ float AttumenTheHuntsmanDisableTankAssistMultiplier::GetValue(Action* action) if (!attumen) return 1.0f; - if (bot->GetVictim() != nullptr && dynamic_cast(action)) + if (bot->GetVictim() != nullptr && dynamic_cast(&action)) return 0.0f; return 1.0f; } // Try to get rid of jittering when bots are stacked behind Attumen -float AttumenTheHuntsmanStayStackedMultiplier::GetValue(Action* action) +float AttumenTheHuntsmanStayStackedMultiplier::GetValue(Action& action) { Unit* attumenMounted = GetFirstAliveUnitByEntry(botAI, NPC_ATTUMEN_THE_HUNTSMAN_MOUNTED); if (!attumenMounted) @@ -42,11 +42,11 @@ float AttumenTheHuntsmanStayStackedMultiplier::GetValue(Action* action) if (!botAI->IsMainTank(bot) && attumenMounted->GetVictim() != bot) { - if (dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action)) + if (dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action)) return 0.0f; } @@ -55,7 +55,7 @@ float AttumenTheHuntsmanStayStackedMultiplier::GetValue(Action* action) // Give the main tank 8 seconds to grab aggro when Attumen mounts Midnight // In reality it's shorter because it takes Attumen a few seconds to aggro after mounting -float AttumenTheHuntsmanWaitForDpsMultiplier::GetValue(Action* action) +float AttumenTheHuntsmanWaitForDpsMultiplier::GetValue(Action& action) { Unit* attumenMounted = GetFirstAliveUnitByEntry(botAI, NPC_ATTUMEN_THE_HUNTSMAN_MOUNTED); if (!attumenMounted) @@ -70,8 +70,8 @@ float AttumenTheHuntsmanWaitForDpsMultiplier::GetValue(Action* action) { if (!botAI->IsMainTank(bot)) { - if (dynamic_cast(action) || (dynamic_cast(action) && - !dynamic_cast(action))) + if (dynamic_cast(&action) || (dynamic_cast(&action) && + !dynamic_cast(&action))) return 0.0f; } } @@ -80,20 +80,20 @@ float AttumenTheHuntsmanWaitForDpsMultiplier::GetValue(Action* action) } // The assist tank should stay on the boss to be 2nd on aggro and tank Hateful Bolts -float TheCuratorDisableTankAssistMultiplier::GetValue(Action* action) +float TheCuratorDisableTankAssistMultiplier::GetValue(Action& action) { Unit* curator = AI_VALUE2(Unit*, "find target", "the curator"); if (!curator) return 1.0f; - if (bot->GetVictim() != nullptr && dynamic_cast(action)) + if (bot->GetVictim() != nullptr && dynamic_cast(&action)) return 0.0f; return 1.0f; } // Save Bloodlust/Heroism for Evocation (100% increased damage) -float TheCuratorDelayBloodlustAndHeroismMultiplier::GetValue(Action* action) +float TheCuratorDelayBloodlustAndHeroismMultiplier::GetValue(Action& action) { Unit* curator = AI_VALUE2(Unit*, "find target", "the curator"); if (!curator) @@ -101,8 +101,8 @@ float TheCuratorDelayBloodlustAndHeroismMultiplier::GetValue(Action* action) if (!curator->HasAura(SPELL_CURATOR_EVOCATION)) { - if (dynamic_cast(action) || - dynamic_cast(action)) + if (dynamic_cast(&action) || + dynamic_cast(&action)) return 0.0f; } @@ -110,7 +110,7 @@ float TheCuratorDelayBloodlustAndHeroismMultiplier::GetValue(Action* action) } // Don't charge back in when running from Arcane Explosion -float ShadeOfAranArcaneExplosionDisableChargeMultiplier::GetValue(Action* action) +float ShadeOfAranArcaneExplosionDisableChargeMultiplier::GetValue(Action& action) { Unit* aran = AI_VALUE2(Unit*, "find target", "shade of aran"); if (!aran) @@ -119,16 +119,16 @@ float ShadeOfAranArcaneExplosionDisableChargeMultiplier::GetValue(Action* action if (aran->HasUnitState(UNIT_STATE_CASTING) && aran->FindCurrentSpellBySpellId(SPELL_ARCANE_EXPLOSION)) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 0.0f; if (bot->GetDistance2d(aran) >= 20.0f) { - if (dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action)) + if (dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action)) return 0.0f; } } @@ -137,7 +137,7 @@ float ShadeOfAranArcaneExplosionDisableChargeMultiplier::GetValue(Action* action } // I will not move when Flame Wreath is cast or the raid blows up -float ShadeOfAranFlameWreathDisableMovementMultiplier::GetValue(Action* action) +float ShadeOfAranFlameWreathDisableMovementMultiplier::GetValue(Action& action) { Unit* aran = AI_VALUE2(Unit*, "find target", "shade of aran"); if (!aran) @@ -145,15 +145,15 @@ float ShadeOfAranFlameWreathDisableMovementMultiplier::GetValue(Action* action) if (IsFlameWreathActive(botAI, bot)) { - if (dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action)) + if (dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action)) return 0.0f; } @@ -161,7 +161,7 @@ float ShadeOfAranFlameWreathDisableMovementMultiplier::GetValue(Action* action) } // Try to rid of the jittering when blocking beams -float NetherspiteKeepBlockingBeamMultiplier::GetValue(Action* action) +float NetherspiteKeepBlockingBeamMultiplier::GetValue(Action& action) { Unit* netherspite = AI_VALUE2(Unit*, "find target", "netherspite"); if (!netherspite || netherspite->HasAura(SPELL_NETHERSPITE_BANISHED)) @@ -171,24 +171,24 @@ float NetherspiteKeepBlockingBeamMultiplier::GetValue(Action* action) if (bot == redBlocker) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 0.0f; } if (bot == blueBlocker) { - if (dynamic_cast(action) || - dynamic_cast(action)) + if (dynamic_cast(&action) || + dynamic_cast(&action)) return 0.0f; } if (bot == greenBlocker) { - if (dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action)) + if (dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action)) return 0.0f; } @@ -196,7 +196,7 @@ float NetherspiteKeepBlockingBeamMultiplier::GetValue(Action* action) } // Give tanks 5 seconds to get aggro during phase transitions -float NetherspiteWaitForDpsMultiplier::GetValue(Action* action) +float NetherspiteWaitForDpsMultiplier::GetValue(Action& action) { Unit* netherspite = AI_VALUE2(Unit*, "find target", "netherspite"); if (!netherspite || netherspite->HasAura(SPELL_NETHERSPITE_BANISHED)) @@ -211,8 +211,8 @@ float NetherspiteWaitForDpsMultiplier::GetValue(Action* action) { if (!botAI->IsTank(bot)) { - if (dynamic_cast(action) || (dynamic_cast(action) && - !dynamic_cast(action))) + if (dynamic_cast(&action) || (dynamic_cast(&action) && + !dynamic_cast(&action))) return 0.0f; } } @@ -221,20 +221,20 @@ float NetherspiteWaitForDpsMultiplier::GetValue(Action* action) } // Disable standard "avoid aoe" strategy, which may interfere with scripted avoidance -float PrinceMalchezaarDisableAvoidAoeMultiplier::GetValue(Action* action) +float PrinceMalchezaarDisableAvoidAoeMultiplier::GetValue(Action& action) { Unit* malchezaar = AI_VALUE2(Unit*, "find target", "prince malchezaar"); if (!malchezaar) return 1.0f; - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 0.0f; return 1.0f; } // Don't run back into Shadow Nova when Enfeebled -float PrinceMalchezaarEnfeebleKeepDistanceMultiplier::GetValue(Action* action) +float PrinceMalchezaarEnfeebleKeepDistanceMultiplier::GetValue(Action& action) { Unit* malchezaar = AI_VALUE2(Unit*, "find target", "prince malchezaar"); if (!malchezaar) @@ -242,8 +242,8 @@ float PrinceMalchezaarEnfeebleKeepDistanceMultiplier::GetValue(Action* action) if (bot->HasAura(SPELL_ENFEEBLE)) { - if (dynamic_cast(action) && - !dynamic_cast(action)) + if (dynamic_cast(&action) && + !dynamic_cast(&action)) return 0.0f; } @@ -251,7 +251,7 @@ float PrinceMalchezaarEnfeebleKeepDistanceMultiplier::GetValue(Action* action) } // Wait until Phase 3 to use Bloodlust/Heroism -float PrinceMalchezaarDelayBloodlustAndHeroismMultiplier::GetValue(Action* action) +float PrinceMalchezaarDelayBloodlustAndHeroismMultiplier::GetValue(Action& action) { Unit* malchezaar = AI_VALUE2(Unit*, "find target", "prince malchezaar"); if (!malchezaar) @@ -259,8 +259,8 @@ float PrinceMalchezaarDelayBloodlustAndHeroismMultiplier::GetValue(Action* actio if (malchezaar->GetHealthPct() > 30.0f) { - if (dynamic_cast(action) || - dynamic_cast(action)) + if (dynamic_cast(&action) || + dynamic_cast(&action)) return 0.0f; } @@ -271,23 +271,23 @@ float PrinceMalchezaarDelayBloodlustAndHeroismMultiplier::GetValue(Action* actio // Pets also tend to pull adds from inside of the tower through the floor // This multiplier DOES NOT impact Hunter and Warlock pets // Hunter and Warlock pets are addressed in ControlPetAggressionAction -float NightbaneDisablePetsMultiplier::GetValue(Action* action) +float NightbaneDisablePetsMultiplier::GetValue(Action& action) { Unit* nightbane = AI_VALUE2(Unit*, "find target", "nightbane"); if (!nightbane) return 1.0f; - if (dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action)) + if (dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action)) return 0.0f; if (nightbane->GetPositionZ() > NIGHTBANE_FLIGHT_Z) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 0.0f; } @@ -295,7 +295,7 @@ float NightbaneDisablePetsMultiplier::GetValue(Action* action) } // Give the main tank 8 seconds to get aggro during phase transitions -float NightbaneWaitForDpsMultiplier::GetValue(Action* action) +float NightbaneWaitForDpsMultiplier::GetValue(Action& action) { Unit* nightbane = AI_VALUE2(Unit*, "find target", "nightbane"); if (!nightbane || nightbane->GetPositionZ() > NIGHTBANE_FLIGHT_Z) @@ -310,8 +310,8 @@ float NightbaneWaitForDpsMultiplier::GetValue(Action* action) { if (!botAI->IsMainTank(bot)) { - if (dynamic_cast(action) || (dynamic_cast(action) && - !dynamic_cast(action))) + if (dynamic_cast(&action) || (dynamic_cast(&action) && + !dynamic_cast(&action))) return 0.0f; } } @@ -322,7 +322,7 @@ float NightbaneWaitForDpsMultiplier::GetValue(Action* action) // The "avoid aoe" strategy must be disabled for the main tank // Otherwise, the main tank will spin Nightbane to avoid Charred Earth and wipe the raid // It is also disabled for all bots during the flight phase -float NightbaneDisableAvoidAoeMultiplier::GetValue(Action* action) +float NightbaneDisableAvoidAoeMultiplier::GetValue(Action& action) { Unit* nightbane = AI_VALUE2(Unit*, "find target", "nightbane"); if (!nightbane) @@ -330,7 +330,7 @@ float NightbaneDisableAvoidAoeMultiplier::GetValue(Action* action) if (nightbane->GetPositionZ() > NIGHTBANE_FLIGHT_Z || botAI->IsMainTank(bot)) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 0.0f; } @@ -338,15 +338,15 @@ float NightbaneDisableAvoidAoeMultiplier::GetValue(Action* action) } // Disable some movement actions that conflict with the strategies -float NightbaneDisableMovementMultiplier::GetValue(Action* action) +float NightbaneDisableMovementMultiplier::GetValue(Action& action) { Unit* nightbane = AI_VALUE2(Unit*, "find target", "nightbane"); if (!nightbane) return 1.0f; - if (dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action)) + if (dynamic_cast(&action) || + dynamic_cast(&action) || + dynamic_cast(&action)) return 0.0f; // Disable CombatFormationMoveAction for all bots except: @@ -355,7 +355,7 @@ float NightbaneDisableMovementMultiplier::GetValue(Action* action) (botAI->IsMelee(bot) && !botAI->IsMainTank(bot) && nightbane->GetPositionZ() > NIGHTBANE_FLIGHT_Z)) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 0.0f; } diff --git a/src/Ai/Raid/Karazhan/Multiplier/RaidKarazhanMultipliers.h b/src/Ai/Raid/Karazhan/Multiplier/RaidKarazhanMultipliers.h index 8ad5a1d4ec..430d170c5b 100644 --- a/src/Ai/Raid/Karazhan/Multiplier/RaidKarazhanMultipliers.h +++ b/src/Ai/Raid/Karazhan/Multiplier/RaidKarazhanMultipliers.h @@ -8,7 +8,7 @@ class AttumenTheHuntsmanDisableTankAssistMultiplier : public Multiplier public: AttumenTheHuntsmanDisableTankAssistMultiplier( PlayerbotAI* botAI) : Multiplier(botAI, "attumen the huntsman disable tank assist multiplier") {} - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class AttumenTheHuntsmanStayStackedMultiplier : public Multiplier @@ -16,7 +16,7 @@ class AttumenTheHuntsmanStayStackedMultiplier : public Multiplier public: AttumenTheHuntsmanStayStackedMultiplier( PlayerbotAI* botAI) : Multiplier(botAI, "attumen the huntsman stay stacked multiplier") {} - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class AttumenTheHuntsmanWaitForDpsMultiplier : public Multiplier @@ -24,7 +24,7 @@ class AttumenTheHuntsmanWaitForDpsMultiplier : public Multiplier public: AttumenTheHuntsmanWaitForDpsMultiplier( PlayerbotAI* botAI) : Multiplier(botAI, "attumen the huntsman wait for dps multiplier") {} - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class TheCuratorDisableTankAssistMultiplier : public Multiplier @@ -32,7 +32,7 @@ class TheCuratorDisableTankAssistMultiplier : public Multiplier public: TheCuratorDisableTankAssistMultiplier( PlayerbotAI* botAI) : Multiplier(botAI, "the curator disable tank assist multiplier") {} - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class TheCuratorDelayBloodlustAndHeroismMultiplier : public Multiplier @@ -40,7 +40,7 @@ class TheCuratorDelayBloodlustAndHeroismMultiplier : public Multiplier public: TheCuratorDelayBloodlustAndHeroismMultiplier( PlayerbotAI* botAI) : Multiplier(botAI, "the curator delay bloodlust and heroism multiplier") {} - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class ShadeOfAranArcaneExplosionDisableChargeMultiplier : public Multiplier @@ -48,7 +48,7 @@ class ShadeOfAranArcaneExplosionDisableChargeMultiplier : public Multiplier public: ShadeOfAranArcaneExplosionDisableChargeMultiplier( PlayerbotAI* botAI) : Multiplier(botAI, "shade of aran arcane explosion disable charge multiplier") {} - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class ShadeOfAranFlameWreathDisableMovementMultiplier : public Multiplier @@ -56,7 +56,7 @@ class ShadeOfAranFlameWreathDisableMovementMultiplier : public Multiplier public: ShadeOfAranFlameWreathDisableMovementMultiplier( PlayerbotAI* botAI) : Multiplier(botAI, "shade of aran flame wreath disable movement multiplier") {} - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class NetherspiteKeepBlockingBeamMultiplier : public Multiplier @@ -64,7 +64,7 @@ class NetherspiteKeepBlockingBeamMultiplier : public Multiplier public: NetherspiteKeepBlockingBeamMultiplier( PlayerbotAI* botAI) : Multiplier(botAI, "netherspite keep blocking beam multiplier") {} - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class NetherspiteWaitForDpsMultiplier : public Multiplier @@ -72,7 +72,7 @@ class NetherspiteWaitForDpsMultiplier : public Multiplier public: NetherspiteWaitForDpsMultiplier( PlayerbotAI* botAI) : Multiplier(botAI, "netherspite wait for dps multiplier") {} - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class PrinceMalchezaarDisableAvoidAoeMultiplier : public Multiplier @@ -80,7 +80,7 @@ class PrinceMalchezaarDisableAvoidAoeMultiplier : public Multiplier public: PrinceMalchezaarDisableAvoidAoeMultiplier( PlayerbotAI* botAI) : Multiplier(botAI, "prince malchezaar disable avoid aoe multiplier") {} - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class PrinceMalchezaarEnfeebleKeepDistanceMultiplier : public Multiplier @@ -88,7 +88,7 @@ class PrinceMalchezaarEnfeebleKeepDistanceMultiplier : public Multiplier public: PrinceMalchezaarEnfeebleKeepDistanceMultiplier( PlayerbotAI* botAI) : Multiplier(botAI, "prince malchezaar enfeeble keep distance multiplier") {} - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class PrinceMalchezaarDelayBloodlustAndHeroismMultiplier : public Multiplier @@ -96,7 +96,7 @@ class PrinceMalchezaarDelayBloodlustAndHeroismMultiplier : public Multiplier public: PrinceMalchezaarDelayBloodlustAndHeroismMultiplier( PlayerbotAI* botAI) : Multiplier(botAI, "prince malchezaar delay bloodlust and heroism multiplier") {} - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class NightbaneDisablePetsMultiplier : public Multiplier @@ -104,7 +104,7 @@ class NightbaneDisablePetsMultiplier : public Multiplier public: NightbaneDisablePetsMultiplier( PlayerbotAI* botAI) : Multiplier(botAI, "nightbane disable pets multiplier") {} - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class NightbaneWaitForDpsMultiplier : public Multiplier @@ -112,7 +112,7 @@ class NightbaneWaitForDpsMultiplier : public Multiplier public: NightbaneWaitForDpsMultiplier( PlayerbotAI* botAI) : Multiplier(botAI, "nightbane wait for dps multiplier") {} - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class NightbaneDisableAvoidAoeMultiplier : public Multiplier @@ -120,7 +120,7 @@ class NightbaneDisableAvoidAoeMultiplier : public Multiplier public: NightbaneDisableAvoidAoeMultiplier( PlayerbotAI* botAI) : Multiplier(botAI, "nightbane disable avoid aoe multiplier") {} - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; class NightbaneDisableMovementMultiplier : public Multiplier @@ -128,7 +128,7 @@ class NightbaneDisableMovementMultiplier : public Multiplier public: NightbaneDisableMovementMultiplier( PlayerbotAI* botAI) : Multiplier(botAI, "nightbane disable movement multiplier") {} - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; #endif diff --git a/src/Ai/Raid/Karazhan/RaidKarazhanActionContext.h b/src/Ai/Raid/Karazhan/RaidKarazhanActionContext.h deleted file mode 100644 index e555cd14d0..0000000000 --- a/src/Ai/Raid/Karazhan/RaidKarazhanActionContext.h +++ /dev/null @@ -1,263 +0,0 @@ -#ifndef _PLAYERBOT_RAIDKARAZHANACTIONCONTEXT_H -#define _PLAYERBOT_RAIDKARAZHANACTIONCONTEXT_H - -#include "RaidKarazhanActions.h" -#include "NamedObjectContext.h" - -class RaidKarazhanActionContext : public NamedObjectContext -{ -public: - RaidKarazhanActionContext() - { - // Trash - creators["mana warp stun creature before warp breach"] = - &RaidKarazhanActionContext::mana_warp_stun_creature_before_warp_breach; - - // Attumen the Huntsman - creators["attumen the huntsman mark target"] = - &RaidKarazhanActionContext::attumen_the_huntsman_mark_target; - - creators["attumen the huntsman split bosses"] = - &RaidKarazhanActionContext::attumen_the_huntsman_split_bosses; - - creators["attumen the huntsman stack behind"] = - &RaidKarazhanActionContext::attumen_the_huntsman_stack_behind; - - creators["attumen the huntsman manage dps timer"] = - &RaidKarazhanActionContext::attumen_the_huntsman_manage_dps_timer; - - // Moroes - creators["moroes main tank attack boss"] = - &RaidKarazhanActionContext::moroes_main_tank_attack_boss; - - creators["moroes mark target"] = - &RaidKarazhanActionContext::moroes_mark_target; - - // Maiden of Virtue - creators["maiden of virtue move boss to healer"] = - &RaidKarazhanActionContext::maiden_of_virtue_move_boss_to_healer; - - creators["maiden of virtue position ranged"] = - &RaidKarazhanActionContext::maiden_of_virtue_position_ranged; - - // The Big Bad Wolf - creators["big bad wolf position boss"] = - &RaidKarazhanActionContext::big_bad_wolf_position_boss; - - creators["big bad wolf run away from boss"] = - &RaidKarazhanActionContext::big_bad_wolf_run_away_from_boss; - - // Romulo and Julianne - creators["romulo and julianne mark target"] = - &RaidKarazhanActionContext::romulo_and_julianne_mark_target; - - // The Wizard of Oz - creators["wizard of oz mark target"] = - &RaidKarazhanActionContext::wizard_of_oz_mark_target; - - creators["wizard of oz scorch strawman"] = - &RaidKarazhanActionContext::wizard_of_oz_scorch_strawman; - - // The Curator - creators["the curator mark astral flare"] = - &RaidKarazhanActionContext::the_curator_mark_astral_flare; - - creators["the curator position boss"] = - &RaidKarazhanActionContext::the_curator_position_boss; - - creators["the curator spread ranged"] = - &RaidKarazhanActionContext::the_curator_spread_ranged; - - // Terestian Illhoof - creators["terestian illhoof mark target"] = - &RaidKarazhanActionContext::terestian_illhoof_mark_target; - - // Shade of Aran - creators["shade of aran run away from arcane explosion"] = - &RaidKarazhanActionContext::shade_of_aran_run_away_from_arcane_explosion; - - creators["shade of aran stop moving during flame wreath"] = - &RaidKarazhanActionContext::shade_of_aran_stop_moving_during_flame_wreath; - - creators["shade of aran mark conjured elemental"] = - &RaidKarazhanActionContext::shade_of_aran_mark_conjured_elemental; - - creators["shade of aran ranged maintain distance"] = - &RaidKarazhanActionContext::shade_of_aran_ranged_maintain_distance; - - // Netherspite - creators["netherspite block red beam"] = - &RaidKarazhanActionContext::netherspite_block_red_beam; - - creators["netherspite block blue beam"] = - &RaidKarazhanActionContext::netherspite_block_blue_beam; - - creators["netherspite block green beam"] = - &RaidKarazhanActionContext::netherspite_block_green_beam; - - creators["netherspite avoid beam and void zone"] = - &RaidKarazhanActionContext::netherspite_avoid_beam_and_void_zone; - - creators["netherspite banish phase avoid void zone"] = - &RaidKarazhanActionContext::netherspite_banish_phase_avoid_void_zone; - - creators["netherspite manage timers and trackers"] = - &RaidKarazhanActionContext::netherspite_manage_timers_and_trackers; - - // Prince Malchezaar - creators["prince malchezaar enfeebled avoid hazard"] = - &RaidKarazhanActionContext::prince_malchezaar_enfeebled_avoid_hazard; - - creators["prince malchezaar non tank avoid infernal"] = - &RaidKarazhanActionContext::prince_malchezaar_non_tank_avoid_infernal; - - creators["prince malchezaar main tank movement"] = - &RaidKarazhanActionContext::prince_malchezaar_main_tank_movement; - - // Nightbane - creators["nightbane ground phase position boss"] = - &RaidKarazhanActionContext::nightbane_ground_phase_position_boss; - - creators["nightbane ground phase rotate ranged positions"] = - &RaidKarazhanActionContext::nightbane_ground_phase_rotate_ranged_positions; - - creators["nightbane cast fear ward on main tank"] = - &RaidKarazhanActionContext::nightbane_cast_fear_ward_on_main_tank; - - creators["nightbane control pet aggression"] = - &RaidKarazhanActionContext::nightbane_control_pet_aggression; - - creators["nightbane flight phase movement"] = - &RaidKarazhanActionContext::nightbane_flight_phase_movement; - - creators["nightbane manage timers and trackers"] = - &RaidKarazhanActionContext::nightbane_manage_timers_and_trackers; - } - -private: - // Trash - static Action* mana_warp_stun_creature_before_warp_breach( - PlayerbotAI* botAI) { return new ManaWarpStunCreatureBeforeWarpBreachAction(botAI); } - - // Attumen the Huntsman - static Action* attumen_the_huntsman_mark_target( - PlayerbotAI* botAI) { return new AttumenTheHuntsmanMarkTargetAction(botAI); } - - static Action* attumen_the_huntsman_split_bosses( - PlayerbotAI* botAI) { return new AttumenTheHuntsmanSplitBossesAction(botAI); } - - static Action* attumen_the_huntsman_stack_behind( - PlayerbotAI* botAI) { return new AttumenTheHuntsmanStackBehindAction(botAI); } - - static Action* attumen_the_huntsman_manage_dps_timer( - PlayerbotAI* botAI) { return new AttumenTheHuntsmanManageDpsTimerAction(botAI); } - - // Moroes - static Action* moroes_main_tank_attack_boss( - PlayerbotAI* botAI) { return new MoroesMainTankAttackBossAction(botAI); } - - static Action* moroes_mark_target( - PlayerbotAI* botAI) { return new MoroesMarkTargetAction(botAI); } - - // Maiden of Virtue - static Action* maiden_of_virtue_move_boss_to_healer( - PlayerbotAI* botAI) { return new MaidenOfVirtueMoveBossToHealerAction(botAI); } - - static Action* maiden_of_virtue_position_ranged( - PlayerbotAI* botAI) { return new MaidenOfVirtuePositionRangedAction(botAI); } - - // The Big Bad Wolf - static Action* big_bad_wolf_position_boss( - PlayerbotAI* botAI) { return new BigBadWolfPositionBossAction(botAI); } - - static Action* big_bad_wolf_run_away_from_boss( - PlayerbotAI* botAI) { return new BigBadWolfRunAwayFromBossAction(botAI); } - - // Romulo and Julianne - static Action* romulo_and_julianne_mark_target( - PlayerbotAI* botAI) { return new RomuloAndJulianneMarkTargetAction(botAI); } - - // The Wizard of Oz - static Action* wizard_of_oz_mark_target( - PlayerbotAI* botAI) { return new WizardOfOzMarkTargetAction(botAI); } - - static Action* wizard_of_oz_scorch_strawman( - PlayerbotAI* botAI) { return new WizardOfOzScorchStrawmanAction(botAI); } - - // The Curator - static Action* the_curator_mark_astral_flare( - PlayerbotAI* botAI) { return new TheCuratorMarkAstralFlareAction(botAI); } - - static Action* the_curator_position_boss( - PlayerbotAI* botAI) { return new TheCuratorPositionBossAction(botAI); } - - static Action* the_curator_spread_ranged( - PlayerbotAI* botAI) { return new TheCuratorSpreadRangedAction(botAI); } - - // Terestian Illhoof - static Action* terestian_illhoof_mark_target( - PlayerbotAI* botAI) { return new TerestianIllhoofMarkTargetAction(botAI); } - - // Shade of Aran - static Action* shade_of_aran_run_away_from_arcane_explosion( - PlayerbotAI* botAI) { return new ShadeOfAranRunAwayFromArcaneExplosionAction(botAI); } - - static Action* shade_of_aran_stop_moving_during_flame_wreath( - PlayerbotAI* botAI) { return new ShadeOfAranStopMovingDuringFlameWreathAction(botAI); } - - static Action* shade_of_aran_mark_conjured_elemental( - PlayerbotAI* botAI) { return new ShadeOfAranMarkConjuredElementalAction(botAI); } - - static Action* shade_of_aran_ranged_maintain_distance( - PlayerbotAI* botAI) { return new ShadeOfAranRangedMaintainDistanceAction(botAI); } - - // Netherspite - static Action* netherspite_block_red_beam( - PlayerbotAI* botAI) { return new NetherspiteBlockRedBeamAction(botAI); } - - static Action* netherspite_block_blue_beam( - PlayerbotAI* botAI) { return new NetherspiteBlockBlueBeamAction(botAI); } - - static Action* netherspite_block_green_beam( - PlayerbotAI* botAI) { return new NetherspiteBlockGreenBeamAction(botAI); } - - static Action* netherspite_avoid_beam_and_void_zone( - PlayerbotAI* botAI) { return new NetherspiteAvoidBeamAndVoidZoneAction(botAI); } - - static Action* netherspite_banish_phase_avoid_void_zone( - PlayerbotAI* botAI) { return new NetherspiteBanishPhaseAvoidVoidZoneAction(botAI); } - - static Action* netherspite_manage_timers_and_trackers( - PlayerbotAI* botAI) { return new NetherspiteManageTimersAndTrackersAction(botAI); } - - // Prince Malchezaar - static Action* prince_malchezaar_enfeebled_avoid_hazard( - PlayerbotAI* botAI) { return new PrinceMalchezaarEnfeebledAvoidHazardAction(botAI); } - - static Action* prince_malchezaar_non_tank_avoid_infernal( - PlayerbotAI* botAI) { return new PrinceMalchezaarNonTankAvoidInfernalAction(botAI); } - - static Action* prince_malchezaar_main_tank_movement( - PlayerbotAI* botAI) { return new PrinceMalchezaarMainTankMovementAction(botAI); } - - // Nightbane - static Action* nightbane_ground_phase_position_boss( - PlayerbotAI* botAI) { return new NightbaneGroundPhasePositionBossAction(botAI); } - - static Action* nightbane_ground_phase_rotate_ranged_positions( - PlayerbotAI* botAI) { return new NightbaneGroundPhaseRotateRangedPositionsAction(botAI); } - - static Action* nightbane_cast_fear_ward_on_main_tank( - PlayerbotAI* botAI) { return new NightbaneCastFearWardOnMainTankAction(botAI); } - - static Action* nightbane_control_pet_aggression( - PlayerbotAI* botAI) { return new NightbaneControlPetAggressionAction(botAI); } - - static Action* nightbane_flight_phase_movement( - PlayerbotAI* botAI) { return new NightbaneFlightPhaseMovementAction(botAI); } - - static Action* nightbane_manage_timers_and_trackers( - PlayerbotAI* botAI) { return new NightbaneManageTimersAndTrackersAction(botAI); } -}; - -#endif diff --git a/src/Ai/Raid/Karazhan/Strategy/RaidKarazhanStrategy.cpp b/src/Ai/Raid/Karazhan/Strategy/RaidKarazhanStrategy.cpp index 04578f0839..6f4b9ce37c 100644 --- a/src/Ai/Raid/Karazhan/Strategy/RaidKarazhanStrategy.cpp +++ b/src/Ai/Raid/Karazhan/Strategy/RaidKarazhanStrategy.cpp @@ -1,143 +1,293 @@ #include "RaidKarazhanStrategy.h" +#include "CreateNextAction.h" #include "RaidKarazhanMultipliers.h" +#include "RaidKarazhanActions.h" void RaidKarazhanStrategy::InitTriggers(std::vector& triggers) { // Trash - triggers.push_back(new TriggerNode("mana warp is about to explode", - { NextAction("mana warp stun creature before warp breach", ACTION_EMERGENCY + 6) } + triggers.push_back( + new TriggerNode( + "mana warp is about to explode", + { + CreateNextAction(ACTION_EMERGENCY + 6.0f) + } )); // Attumen the Huntsman - triggers.push_back(new TriggerNode("attumen the huntsman need target priority", - { NextAction("attumen the huntsman mark target", ACTION_RAID + 1) } - )); - triggers.push_back(new TriggerNode("attumen the huntsman attumen spawned", - { NextAction("attumen the huntsman split bosses", ACTION_RAID + 2) } - )); - triggers.push_back(new TriggerNode("attumen the huntsman attumen is mounted", - { NextAction("attumen the huntsman stack behind", ACTION_RAID + 1) } - )); - triggers.push_back(new TriggerNode("attumen the huntsman boss wipes aggro when mounting", - { NextAction("attumen the huntsman manage dps timer", ACTION_RAID + 2) } + triggers.push_back( + new TriggerNode( + "attumen the huntsman need target priority", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + )); + triggers.push_back( + new TriggerNode( + "attumen the huntsman attumen spawned", + { + CreateNextAction(ACTION_RAID + 2.0f) + } + )); + triggers.push_back( + new TriggerNode( + "attumen the huntsman attumen is mounted", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + )); + triggers.push_back( + new TriggerNode( + "attumen the huntsman boss wipes aggro when mounting", + { + CreateNextAction(ACTION_RAID + 2.0f) + } )); // Moroes - triggers.push_back(new TriggerNode("moroes boss engaged by main tank", - { NextAction("moroes main tank attack boss", ACTION_RAID + 1) } - )); - triggers.push_back(new TriggerNode("moroes need target priority", - { NextAction("moroes mark target", ACTION_RAID + 1) } + triggers.push_back( + new TriggerNode( + "moroes boss engaged by main tank", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + )); + triggers.push_back( + new TriggerNode( + "moroes need target priority", + { + CreateNextAction(ACTION_RAID + 1.0f) + } )); // Maiden of Virtue - triggers.push_back(new TriggerNode("maiden of virtue healers are stunned by repentance", - { NextAction("maiden of virtue move boss to healer", ACTION_RAID + 1) } - )); - triggers.push_back(new TriggerNode("maiden of virtue holy wrath deals chain damage", - { NextAction("maiden of virtue position ranged", ACTION_RAID + 1) } + triggers.push_back( + new TriggerNode( + "maiden of virtue healers are stunned by repentance", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + )); + triggers.push_back( + new TriggerNode( + "maiden of virtue holy wrath deals chain damage", + { + CreateNextAction(ACTION_RAID + 1.0f) + } )); // The Big Bad Wolf - triggers.push_back(new TriggerNode("big bad wolf boss is chasing little red riding hood", - { NextAction("big bad wolf run away from boss", ACTION_EMERGENCY + 6) } - )); - triggers.push_back(new TriggerNode("big bad wolf boss engaged by tank", - { NextAction("big bad wolf position boss", ACTION_RAID + 1) } + triggers.push_back( + new TriggerNode( + "big bad wolf boss is chasing little red riding hood", + { + CreateNextAction(ACTION_EMERGENCY + 6.0f) + } + )); + triggers.push_back( + new TriggerNode( + "big bad wolf boss engaged by tank", + { + CreateNextAction(ACTION_RAID + 1.0f) + } )); // Romulo and Julianne - triggers.push_back(new TriggerNode("romulo and julianne both bosses revived", - { NextAction("romulo and julianne mark target", ACTION_RAID + 1) } + triggers.push_back( + new TriggerNode( + "romulo and julianne both bosses revived", + { + CreateNextAction(ACTION_RAID + 1.0f) + } )); // The Wizard of Oz - triggers.push_back(new TriggerNode("wizard of oz need target priority", - { NextAction("wizard of oz mark target", ACTION_RAID + 1) } - )); - triggers.push_back(new TriggerNode("wizard of oz strawman is vulnerable to fire", - { NextAction("wizard of oz scorch strawman", ACTION_RAID + 2) } + triggers.push_back( + new TriggerNode( + "wizard of oz need target priority", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + )); + triggers.push_back( + new TriggerNode( + "wizard of oz strawman is vulnerable to fire", + { + CreateNextAction(ACTION_RAID + 2.0f) + } )); // The Curator - triggers.push_back(new TriggerNode("the curator astral flare spawned", - { NextAction("the curator mark astral flare", ACTION_RAID + 1) } - )); - triggers.push_back(new TriggerNode("the curator boss engaged by tanks", - { NextAction("the curator position boss", ACTION_RAID + 2) } - )); - triggers.push_back(new TriggerNode("the curator astral flares cast arcing sear", - { NextAction("the curator spread ranged", ACTION_RAID + 2) } + triggers.push_back( + new TriggerNode( + "the curator astral flare spawned", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + )); + triggers.push_back( + new TriggerNode( + "the curator boss engaged by tanks", + { + CreateNextAction(ACTION_RAID + 2.0f) + } + )); + triggers.push_back( + new TriggerNode( + "the curator astral flares cast arcing sear", + { + CreateNextAction(ACTION_RAID + 2.0f) + } )); // Terestian Illhoof - triggers.push_back(new TriggerNode("terestian illhoof need target priority", - { NextAction("terestian illhoof mark target", ACTION_RAID + 1) } + triggers.push_back( + new TriggerNode( + "terestian illhoof need target priority", + { + CreateNextAction(ACTION_RAID + 1.0f) + } )); // Shade of Aran - triggers.push_back(new TriggerNode("shade of aran arcane explosion is casting", - { NextAction("shade of aran run away from arcane explosion", ACTION_EMERGENCY + 6) } - )); - triggers.push_back(new TriggerNode("shade of aran flame wreath is active", - { NextAction("shade of aran stop moving during flame wreath", ACTION_EMERGENCY + 7) } - )); - triggers.push_back(new TriggerNode("shade of aran conjured elementals summoned", - { NextAction("shade of aran mark conjured elemental", ACTION_RAID + 1) } - )); - triggers.push_back(new TriggerNode("shade of aran boss uses counterspell and blizzard", - { NextAction("shade of aran ranged maintain distance", ACTION_RAID + 2) } + triggers.push_back( + new TriggerNode( + "shade of aran arcane explosion is casting", + { + CreateNextAction(ACTION_EMERGENCY + 6.0f) + } + )); + triggers.push_back( + new TriggerNode( + "shade of aran flame wreath is active", + { + CreateNextAction(ACTION_EMERGENCY + 7.0f) + } + )); + triggers.push_back( + new TriggerNode( + "shade of aran conjured elementals summoned", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + )); + triggers.push_back( + new TriggerNode( + "shade of aran boss uses counterspell and blizzard", + { + CreateNextAction(ACTION_RAID + 2.0f) + } )); // Netherspite - triggers.push_back(new TriggerNode("netherspite red beam is active", - { NextAction("netherspite block red beam", ACTION_EMERGENCY + 8) } - )); - triggers.push_back(new TriggerNode("netherspite blue beam is active", - { NextAction("netherspite block blue beam", ACTION_EMERGENCY + 8) } - )); - triggers.push_back(new TriggerNode("netherspite green beam is active", - { NextAction("netherspite block green beam", ACTION_EMERGENCY + 8) } - )); - triggers.push_back(new TriggerNode("netherspite bot is not beam blocker", - { NextAction("netherspite avoid beam and void zone", ACTION_EMERGENCY + 7) } - )); - triggers.push_back(new TriggerNode("netherspite boss is banished", - { NextAction("netherspite banish phase avoid void zone", ACTION_RAID + 1) } - )); - triggers.push_back(new TriggerNode("netherspite need to manage timers and trackers", - { NextAction("netherspite manage timers and trackers", ACTION_EMERGENCY + 10) } + triggers.push_back( + new TriggerNode( + "netherspite red beam is active", + { + CreateNextAction(ACTION_EMERGENCY + 8.0f) + } + )); + triggers.push_back( + new TriggerNode( + "netherspite blue beam is active", + { + CreateNextAction(ACTION_EMERGENCY + 8.0f) + } + )); + triggers.push_back( + new TriggerNode( + "netherspite green beam is active", + { + CreateNextAction(ACTION_EMERGENCY + 8.0f) + } + )); + triggers.push_back( + new TriggerNode( + "netherspite bot is not beam blocker", + { + CreateNextAction(ACTION_EMERGENCY + 7.0f) + } + )); + triggers.push_back( + new TriggerNode( + "netherspite boss is banished", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + )); + triggers.push_back( + new TriggerNode( + "netherspite need to manage timers and trackers", + { + CreateNextAction(ACTION_EMERGENCY + 10.0f) + } )); // Prince Malchezaar - triggers.push_back(new TriggerNode("prince malchezaar bot is enfeebled", - { NextAction("prince malchezaar enfeebled avoid hazard", ACTION_EMERGENCY + 6) } - )); - triggers.push_back(new TriggerNode("prince malchezaar infernals are spawned", - { NextAction("prince malchezaar non tank avoid infernal", ACTION_EMERGENCY + 1) } - )); - triggers.push_back(new TriggerNode("prince malchezaar boss engaged by main tank", - { NextAction("prince malchezaar main tank movement", ACTION_EMERGENCY + 6) } + triggers.push_back( + new TriggerNode( + "prince malchezaar bot is enfeebled", + { + CreateNextAction(ACTION_EMERGENCY + 6.0f) + } + )); + triggers.push_back( + new TriggerNode( + "prince malchezaar infernals are spawned", + { + CreateNextAction(ACTION_EMERGENCY + 1.0f) + } + )); + triggers.push_back( + new TriggerNode( + "prince malchezaar boss engaged by main tank", + { + CreateNextAction(ACTION_EMERGENCY + 6.0f) + } )); // Nightbane - triggers.push_back(new TriggerNode("nightbane boss engaged by main tank", - { NextAction("nightbane ground phase position boss", ACTION_RAID + 1) } - )); - triggers.push_back(new TriggerNode("nightbane ranged bots are in charred earth", - { NextAction("nightbane ground phase rotate ranged positions", ACTION_EMERGENCY + 1) } - )); - triggers.push_back(new TriggerNode("nightbane main tank is susceptible to fear", - { NextAction("nightbane cast fear ward on main tank", ACTION_RAID + 2) } - )); - triggers.push_back(new TriggerNode("nightbane pets ignore collision to chase flying boss", - { NextAction("nightbane control pet aggression", ACTION_RAID + 2) } - )); - triggers.push_back(new TriggerNode("nightbane boss is flying", - { NextAction("nightbane flight phase movement", ACTION_RAID + 1) } - )); - triggers.push_back(new TriggerNode("nightbane need to manage timers and trackers", - { NextAction("nightbane manage timers and trackers", ACTION_EMERGENCY + 10) } + triggers.push_back( + new TriggerNode( + "nightbane boss engaged by main tank", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + )); + triggers.push_back( + new TriggerNode( + "nightbane ranged bots are in charred earth", + { + CreateNextAction(ACTION_EMERGENCY + 1.0f) + } + )); + triggers.push_back( + new TriggerNode( + "nightbane main tank is susceptible to fear", + { + CreateNextAction(ACTION_RAID + 2.0f) + } + )); + triggers.push_back( + new TriggerNode( + "nightbane pets ignore collision to chase flying boss", + { + CreateNextAction(ACTION_RAID + 2.0f) + } + )); + triggers.push_back( + new TriggerNode( + "nightbane boss is flying", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + )); + triggers.push_back( + new TriggerNode( + "nightbane need to manage timers and trackers", + { + CreateNextAction(ACTION_EMERGENCY + 10.0f) + } )); } diff --git a/src/Ai/Raid/Karazhan/Util/RaidKarazhanHelpers.cpp b/src/Ai/Raid/Karazhan/Util/RaidKarazhanHelpers.cpp index 821cc67019..037bf2e9e6 100644 --- a/src/Ai/Raid/Karazhan/Util/RaidKarazhanHelpers.cpp +++ b/src/Ai/Raid/Karazhan/Util/RaidKarazhanHelpers.cpp @@ -1,5 +1,4 @@ #include "RaidKarazhanHelpers.h" -#include "RaidKarazhanActions.h" #include "Playerbots.h" #include "RtiTargetValue.h" @@ -381,7 +380,7 @@ namespace KarazhanHelpers return voidZones; } - bool IsSafePosition(float x, float y, float z, const std::vector& hazards, float hazardRadius) + bool IsSafePosition(float x, float y, float, const std::vector& hazards, float hazardRadius) { for (Unit* hazard : hazards) { @@ -412,10 +411,8 @@ namespace KarazhanHelpers { float sx = start.GetPositionX(); float sy = start.GetPositionY(); - float sz = start.GetPositionZ(); float tx = target.GetPositionX(); float ty = target.GetPositionY(); - float tz = target.GetPositionZ(); const float totalDist = start.GetExactDist2d(target.GetPositionX(), target.GetPositionY()); if (totalDist == 0.0f) @@ -426,7 +423,6 @@ namespace KarazhanHelpers float t = checkDist / totalDist; float checkX = sx + (tx - sx) * t; float checkY = sy + (ty - sy) * t; - float checkZ = sz + (tz - sz) * t; for (Unit* hazard : hazards) { const float hx = checkX - hazard->GetPositionX(); diff --git a/src/Ai/Raid/Magtheridon/Action/RaidMagtheridonActions.cpp b/src/Ai/Raid/Magtheridon/Action/RaidMagtheridonActions.cpp index 69fc862442..5ad70ca292 100644 --- a/src/Ai/Raid/Magtheridon/Action/RaidMagtheridonActions.cpp +++ b/src/Ai/Raid/Magtheridon/Action/RaidMagtheridonActions.cpp @@ -7,7 +7,7 @@ using namespace MagtheridonHelpers; -bool MagtheridonMainTankAttackFirstThreeChannelersAction::Execute(Event event) +bool MagtheridonMainTankAttackFirstThreeChannelersAction::Execute(Event) { Unit* magtheridon = AI_VALUE2(Unit*, "find target", "magtheridon"); if (!magtheridon) @@ -67,7 +67,7 @@ bool MagtheridonMainTankAttackFirstThreeChannelersAction::Execute(Event event) return false; } -bool MagtheridonFirstAssistTankAttackNWChannelerAction::Execute(Event event) +bool MagtheridonFirstAssistTankAttackNWChannelerAction::Execute(Event) { Creature* channelerDiamond = GetChanneler(bot, NORTHWEST_CHANNELER); if (!channelerDiamond || !channelerDiamond->IsAlive()) @@ -100,7 +100,7 @@ bool MagtheridonFirstAssistTankAttackNWChannelerAction::Execute(Event event) return false; } -bool MagtheridonSecondAssistTankAttackNEChannelerAction::Execute(Event event) +bool MagtheridonSecondAssistTankAttackNEChannelerAction::Execute(Event) { Creature* channelerTriangle = GetChanneler(bot, NORTHEAST_CHANNELER); if (!channelerTriangle || !channelerTriangle->IsAlive()) @@ -134,7 +134,7 @@ bool MagtheridonSecondAssistTankAttackNEChannelerAction::Execute(Event event) } // Misdirect West & East Channelers to Main Tank -bool MagtheridonMisdirectHellfireChannelers::Execute(Event event) +bool MagtheridonMisdirectHellfireChannelers::Execute(Event) { Group* group = bot->GetGroup(); if (!group) @@ -211,7 +211,7 @@ bool MagtheridonMisdirectHellfireChannelers::Execute(Event event) return false; } -bool MagtheridonAssignDPSPriorityAction::Execute(Event event) +bool MagtheridonAssignDPSPriorityAction::Execute(Event) { // Listed in order of priority Creature* channelerSquare = GetChanneler(bot, SOUTH_CHANNELER); @@ -306,7 +306,7 @@ bool MagtheridonAssignDPSPriorityAction::Execute(Event event) // Assign Burning Abyssals to Warlocks to Banish // Burning Abyssals in excess of Warlocks in party will be Feared -bool MagtheridonWarlockCCBurningAbyssalAction::Execute(Event event) +bool MagtheridonWarlockCCBurningAbyssalAction::Execute(Event) { Group* group = bot->GetGroup(); if (!group) @@ -340,7 +340,9 @@ bool MagtheridonWarlockCCBurningAbyssalAction::Execute(Event event) } } - if (warlockIndex >= 0 && warlockIndex < abyssals.size()) + const int64_t abyssalSize = abyssals.size(); + + if (warlockIndex >= 0 && warlockIndex < abyssalSize) { Unit* assignedAbyssal = abyssals[warlockIndex]; if (!assignedAbyssal->HasAura(SPELL_BANISH) && botAI->CanCastSpell(SPELL_BANISH, assignedAbyssal, true)) @@ -359,7 +361,7 @@ bool MagtheridonWarlockCCBurningAbyssalAction::Execute(Event event) } // Main tank will back up to the Northern point of the room -bool MagtheridonMainTankPositionBossAction::Execute(Event event) +bool MagtheridonMainTankPositionBossAction::Execute(Event) { Unit* magtheridon = AI_VALUE2(Unit*, "find target", "magtheridon"); if (!magtheridon) @@ -399,7 +401,7 @@ bool MagtheridonMainTankPositionBossAction::Execute(Event event) std::unordered_map MagtheridonSpreadRangedAction::initialPositions; std::unordered_map MagtheridonSpreadRangedAction::hasReachedInitialPosition; -bool MagtheridonSpreadRangedAction::Execute(Event event) +bool MagtheridonSpreadRangedAction::Execute(Event) { Unit* magtheridon = AI_VALUE2(Unit*, "find target", "magtheridon"); if (!magtheridon) @@ -456,7 +458,7 @@ bool MagtheridonSpreadRangedAction::Execute(Event event) uint8 count = members.size(); float angle = 2 * M_PI * botIndex / count; - float radius = static_cast(rand()) / RAND_MAX * maxSpreadRadius; + float radius = static_cast(rand()) / static_cast(RAND_MAX) * maxSpreadRadius; float targetX = centerX + radius * cos(angle); float targetY = centerY + radius * sin(angle); @@ -489,8 +491,8 @@ bool MagtheridonSpreadRangedAction::Execute(Event event) if (distToCenter > maxSpreadRadius + radiusBuffer) { - float angle = static_cast(rand()) / RAND_MAX * 2.0f * M_PI; - float radius = static_cast(rand()) / RAND_MAX * maxSpreadRadius; + float angle = static_cast(rand()) / static_cast(RAND_MAX) * 2.0f * M_PI; + float radius = static_cast(rand()) / static_cast(RAND_MAX) * maxSpreadRadius; float targetX = centerX + radius * cos(angle); float targetY = centerY + radius * sin(angle); @@ -509,7 +511,7 @@ bool MagtheridonSpreadRangedAction::Execute(Event event) // For bots that are assigned to click cubes // Magtheridon casts Blast Nova every 54.35 to 55.40s, with a 2s cast time -bool MagtheridonUseManticronCubeAction::Execute(Event event) +bool MagtheridonUseManticronCubeAction::Execute(Event) { Unit* magtheridon = AI_VALUE2(Unit*, "find target", "magtheridon"); if (!magtheridon) @@ -543,7 +545,7 @@ bool MagtheridonUseManticronCubeAction::Execute(Event event) return false; } -bool MagtheridonUseManticronCubeAction::HandleCubeRelease(Unit* magtheridon, GameObject* cube) +bool MagtheridonUseManticronCubeAction::HandleCubeRelease(Unit* magtheridon, GameObject*) { if (bot->HasAura(SPELL_SHADOW_GRASP) && !(magtheridon->HasUnitState(UNIT_STATE_CASTING) && @@ -598,7 +600,7 @@ bool MagtheridonUseManticronCubeAction::HandleWaitingPhase(const CubeInfo& cubeI } } - float angle = static_cast(rand()) / RAND_MAX * 2.0f * M_PI; + float angle = static_cast(rand()) / static_cast(RAND_MAX) * 2.0f * M_PI; float fallbackX = cubeInfo.x + cos(angle) * safeWaitDistance; float fallbackY = cubeInfo.y + sin(angle) * safeWaitDistance; float fallbackZ = bot->GetPositionZ(); @@ -650,7 +652,7 @@ bool MagtheridonUseManticronCubeAction::HandleCubeInteraction(const CubeInfo& cu // is not interrupted or takes too long to interrupt, the timer will be thrown off for the rest of the encounter. // Correcting this issue is complicated and probably would need some rewriting--I have not done so and // and view the current solution as sufficient since in TBC a missed Blast Nova would be a guaranteed wipe anyway. -bool MagtheridonManageTimersAndAssignmentsAction::Execute(Event event) +bool MagtheridonManageTimersAndAssignmentsAction::Execute(Event) { Unit* magtheridon = AI_VALUE2(Unit*, "find target", "magtheridon"); if (!magtheridon) diff --git a/src/Ai/Raid/Magtheridon/Multiplier/RaidMagtheridonMultipliers.cpp b/src/Ai/Raid/Magtheridon/Multiplier/RaidMagtheridonMultipliers.cpp index 9580fd923a..0284099e02 100644 --- a/src/Ai/Raid/Magtheridon/Multiplier/RaidMagtheridonMultipliers.cpp +++ b/src/Ai/Raid/Magtheridon/Multiplier/RaidMagtheridonMultipliers.cpp @@ -2,9 +2,9 @@ #include #include "RaidMagtheridonMultipliers.h" +#include "ChooseTargetActions.h" #include "RaidMagtheridonActions.h" #include "RaidMagtheridonHelpers.h" -#include "ChooseTargetActions.h" #include "GenericSpellActions.h" #include "Playerbots.h" #include "WarlockActions.h" @@ -12,7 +12,7 @@ using namespace MagtheridonHelpers; // Don't do anything other than clicking cubes when Magtheridon is casting Blast Nova -float MagtheridonUseManticronCubeMultiplier::GetValue(Action* action) +float MagtheridonUseManticronCubeMultiplier::GetValue(Action& action) { Unit* magtheridon = AI_VALUE2(Unit*, "find target", "magtheridon"); if (!magtheridon) @@ -24,7 +24,7 @@ float MagtheridonUseManticronCubeMultiplier::GetValue(Action* action) auto it = botToCubeAssignment.find(bot->GetGUID()); if (it != botToCubeAssignment.end()) { - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 1.0f; return 0.0f; @@ -35,7 +35,7 @@ float MagtheridonUseManticronCubeMultiplier::GetValue(Action* action) } // Bots will wait for 6 seconds after Magtheridon becomes attackable before engaging -float MagtheridonWaitToAttackMultiplier::GetValue(Action* action) +float MagtheridonWaitToAttackMultiplier::GetValue(Action& action) { Unit* magtheridon = AI_VALUE2(Unit*, "find target", "magtheridon"); if (!magtheridon || magtheridon->HasAura(SPELL_SHADOW_CAGE)) @@ -46,8 +46,8 @@ float MagtheridonWaitToAttackMultiplier::GetValue(Action* action) if (it == dpsWaitTimer.end() || (time(nullptr) - it->second) < dpsWaitSeconds) { - if (!botAI->IsMainTank(bot) && (dynamic_cast(action) || - (!botAI->IsHeal(bot) && dynamic_cast(action)))) + if (!botAI->IsMainTank(bot) && (dynamic_cast(&action) || + (!botAI->IsHeal(bot) && dynamic_cast(&action)))) return 0.0f; } @@ -56,15 +56,14 @@ float MagtheridonWaitToAttackMultiplier::GetValue(Action* action) // No tank assist for offtanks during the channeler phase // So they don't try to pull channelers from each other or the main tank -float MagtheridonDisableOffTankAssistMultiplier::GetValue(Action* action) +float MagtheridonDisableOffTankAssistMultiplier::GetValue(Action& action) { Unit* magtheridon = AI_VALUE2(Unit*, "find target", "magtheridon"); - Unit* channeler = AI_VALUE2(Unit*, "find target", "hellfire channeler"); if (!magtheridon) return 1.0f; if ((botAI->IsAssistTankOfIndex(bot, 0) || botAI->IsAssistTankOfIndex(bot, 1)) && - dynamic_cast(action)) + dynamic_cast(&action)) return 0.0f; return 1.0f; diff --git a/src/Ai/Raid/Magtheridon/Multiplier/RaidMagtheridonMultipliers.h b/src/Ai/Raid/Magtheridon/Multiplier/RaidMagtheridonMultipliers.h index 2cce516b6f..94d738a94b 100644 --- a/src/Ai/Raid/Magtheridon/Multiplier/RaidMagtheridonMultipliers.h +++ b/src/Ai/Raid/Magtheridon/Multiplier/RaidMagtheridonMultipliers.h @@ -7,21 +7,21 @@ class MagtheridonUseManticronCubeMultiplier : public Multiplier { public: MagtheridonUseManticronCubeMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "magtheridon use manticron cube multiplier") {} - float GetValue(Action* action) override; + float GetValue(Action& action) override; }; class MagtheridonWaitToAttackMultiplier : public Multiplier { public: MagtheridonWaitToAttackMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "magtheridon wait to attack multiplier") {} - float GetValue(Action* action) override; + float GetValue(Action& action) override; }; class MagtheridonDisableOffTankAssistMultiplier : public Multiplier { public: MagtheridonDisableOffTankAssistMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "magtheridon disable off tank assist multiplier") {} - float GetValue(Action* action) override; + float GetValue(Action& action) override; }; #endif diff --git a/src/Ai/Raid/Magtheridon/RaidMagtheridonActionContext.h b/src/Ai/Raid/Magtheridon/RaidMagtheridonActionContext.h deleted file mode 100644 index 48e8cfd351..0000000000 --- a/src/Ai/Raid/Magtheridon/RaidMagtheridonActionContext.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef _PLAYERBOT_RAIDMAGTHERIDONACTIONCONTEXT_H -#define _PLAYERBOT_RAIDMAGTHERIDONACTIONCONTEXT_H - -#include "RaidMagtheridonActions.h" -#include "NamedObjectContext.h" - -class RaidMagtheridonActionContext : public NamedObjectContext -{ -public: - RaidMagtheridonActionContext() - { - creators["magtheridon main tank attack first three channelers"] = &RaidMagtheridonActionContext::magtheridon_main_tank_attack_first_three_channelers; - creators["magtheridon first assist tank attack nw channeler"] = &RaidMagtheridonActionContext::magtheridon_first_assist_tank_attack_nw_channeler; - creators["magtheridon second assist tank attack ne channeler"] = &RaidMagtheridonActionContext::magtheridon_second_assist_tank_attack_ne_channeler; - creators["magtheridon misdirect hellfire channelers"] = &RaidMagtheridonActionContext::magtheridon_misdirect_hellfire_channelers; - creators["magtheridon assign dps priority"] = &RaidMagtheridonActionContext::magtheridon_assign_dps_priority; - creators["magtheridon warlock cc burning abyssal"] = &RaidMagtheridonActionContext::magtheridon_warlock_cc_burning_abyssal; - creators["magtheridon main tank position boss"] = &RaidMagtheridonActionContext::magtheridon_main_tank_position_boss; - creators["magtheridon spread ranged"] = &RaidMagtheridonActionContext::magtheridon_spread_ranged; - creators["magtheridon use manticron cube"] = &RaidMagtheridonActionContext::magtheridon_use_manticron_cube; - creators["magtheridon manage timers and assignments"] = &RaidMagtheridonActionContext::magtheridon_manage_timers_and_assignments; - } - -private: - static Action* magtheridon_main_tank_attack_first_three_channelers(PlayerbotAI* botAI) { return new MagtheridonMainTankAttackFirstThreeChannelersAction(botAI); } - static Action* magtheridon_first_assist_tank_attack_nw_channeler(PlayerbotAI* botAI) { return new MagtheridonFirstAssistTankAttackNWChannelerAction(botAI); } - static Action* magtheridon_second_assist_tank_attack_ne_channeler(PlayerbotAI* botAI) { return new MagtheridonSecondAssistTankAttackNEChannelerAction(botAI); } - static Action* magtheridon_misdirect_hellfire_channelers(PlayerbotAI* botAI) { return new MagtheridonMisdirectHellfireChannelers(botAI); } - static Action* magtheridon_assign_dps_priority(PlayerbotAI* botAI) { return new MagtheridonAssignDPSPriorityAction(botAI); } - static Action* magtheridon_warlock_cc_burning_abyssal(PlayerbotAI* botAI) { return new MagtheridonWarlockCCBurningAbyssalAction(botAI); } - static Action* magtheridon_main_tank_position_boss(PlayerbotAI* botAI) { return new MagtheridonMainTankPositionBossAction(botAI); } - static Action* magtheridon_spread_ranged(PlayerbotAI* botAI) { return new MagtheridonSpreadRangedAction(botAI); } - static Action* magtheridon_use_manticron_cube(PlayerbotAI* botAI) { return new MagtheridonUseManticronCubeAction(botAI); } - static Action* magtheridon_manage_timers_and_assignments(PlayerbotAI* botAI) { return new MagtheridonManageTimersAndAssignmentsAction(botAI); } -}; - -#endif diff --git a/src/Ai/Raid/Magtheridon/Strategy/RaidMagtheridonStrategy.cpp b/src/Ai/Raid/Magtheridon/Strategy/RaidMagtheridonStrategy.cpp index 73d240825f..96b2286a9a 100644 --- a/src/Ai/Raid/Magtheridon/Strategy/RaidMagtheridonStrategy.cpp +++ b/src/Ai/Raid/Magtheridon/Strategy/RaidMagtheridonStrategy.cpp @@ -1,37 +1,100 @@ #include "RaidMagtheridonStrategy.h" +#include "CreateNextAction.h" #include "RaidMagtheridonMultipliers.h" +#include "RaidMagtheridonActions.h" + void RaidMagtheridonStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("magtheridon incoming blast nova", { - NextAction("magtheridon use manticron cube", ACTION_EMERGENCY + 10) })); + triggers.push_back( + new TriggerNode( + "magtheridon incoming blast nova", + { + CreateNextAction(ACTION_EMERGENCY + 10.0f) + } + ) + ); - triggers.push_back(new TriggerNode("magtheridon need to manage timers and assignments", { - NextAction("magtheridon manage timers and assignments", ACTION_EMERGENCY + 1) })); + triggers.push_back( + new TriggerNode( + "magtheridon need to manage timers and assignments", + { + CreateNextAction(ACTION_EMERGENCY + 1.0f) + } + ) + ); - triggers.push_back(new TriggerNode("magtheridon burning abyssal spawned", { - NextAction("magtheridon warlock cc burning abyssal", ACTION_RAID + 3) })); + triggers.push_back( + new TriggerNode( + "magtheridon burning abyssal spawned", + { + CreateNextAction(ACTION_RAID + 3.0f) + } + ) + ); - triggers.push_back(new TriggerNode("magtheridon boss engaged by ranged", { - NextAction("magtheridon spread ranged", ACTION_RAID + 2) })); + triggers.push_back( + new TriggerNode( + "magtheridon boss engaged by ranged", + { + CreateNextAction(ACTION_RAID + 2.0f) + } + ) + ); - triggers.push_back(new TriggerNode("magtheridon pulling west and east channelers", { - NextAction("magtheridon misdirect hellfire channelers", ACTION_RAID + 2) })); + triggers.push_back( + new TriggerNode( + "magtheridon pulling west and east channelers", + { + CreateNextAction(ACTION_RAID + 2.0f) + } + ) + ); - triggers.push_back(new TriggerNode("magtheridon boss engaged by main tank", { - NextAction("magtheridon main tank position boss", ACTION_RAID + 2) })); + triggers.push_back( + new TriggerNode( + "magtheridon boss engaged by main tank", + { + CreateNextAction(ACTION_RAID + 2.0f) + } + ) + ); - triggers.push_back(new TriggerNode("magtheridon first three channelers engaged by main tank", { - NextAction("magtheridon main tank attack first three channelers", ACTION_RAID + 1) })); + triggers.push_back( + new TriggerNode( + "magtheridon first three channelers engaged by main tank", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); - triggers.push_back(new TriggerNode("magtheridon nw channeler engaged by first assist tank", { - NextAction("magtheridon first assist tank attack nw channeler", ACTION_RAID + 1) })); + triggers.push_back( + new TriggerNode( + "magtheridon nw channeler engaged by first assist tank", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); - triggers.push_back(new TriggerNode("magtheridon ne channeler engaged by second assist tank", { - NextAction("magtheridon second assist tank attack ne channeler", ACTION_RAID + 1) })); + triggers.push_back( + new TriggerNode( + "magtheridon ne channeler engaged by second assist tank", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); - triggers.push_back(new TriggerNode("magtheridon determining kill order", { - NextAction("magtheridon assign dps priority", ACTION_RAID + 1) })); + triggers.push_back( + new TriggerNode( + "magtheridon determining kill order", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); } void RaidMagtheridonStrategy::InitMultipliers(std::vector& multipliers) diff --git a/src/Ai/Raid/Magtheridon/Util/RaidMagtheridonHelpers.cpp b/src/Ai/Raid/Magtheridon/Util/RaidMagtheridonHelpers.cpp index dc88d2a192..d7113e9b6b 100644 --- a/src/Ai/Raid/Magtheridon/Util/RaidMagtheridonHelpers.cpp +++ b/src/Ai/Raid/Magtheridon/Util/RaidMagtheridonHelpers.cpp @@ -174,7 +174,7 @@ namespace MagtheridonHelpers std::unordered_map spreadWaitTimer; std::unordered_map dpsWaitTimer; - bool IsSafeFromMagtheridonHazards(PlayerbotAI* botAI, Player* bot, float x, float y, float z) + bool IsSafeFromMagtheridonHazards(PlayerbotAI* botAI, Player*, float x, float y, float) { // Debris std::vector debrisHazards; diff --git a/src/Ai/Raid/MoltenCore/Action/RaidMcActions.cpp b/src/Ai/Raid/MoltenCore/Action/RaidMcActions.cpp index b18c8b8534..496e424555 100644 --- a/src/Ai/Raid/MoltenCore/Action/RaidMcActions.cpp +++ b/src/Ai/Raid/MoltenCore/Action/RaidMcActions.cpp @@ -2,8 +2,8 @@ #include "Playerbots.h" #include "RtiTargetValue.h" -#include "RaidMcTriggers.h" #include "RaidMcHelpers.h" +#include "UniversalTauntAction.h" static constexpr float LIVING_BOMB_DISTANCE = 20.0f; static constexpr float INFERNO_DISTANCE = 20.0f; @@ -20,12 +20,12 @@ static constexpr float CORE_RAGER_STEP_DISTANCE = 5.0f; using namespace MoltenCoreHelpers; -bool McMoveFromGroupAction::Execute(Event event) +bool McMoveFromGroupAction::Execute(Event) { return MoveFromGroup(LIVING_BOMB_DISTANCE); } -bool McMoveFromBaronGeddonAction::Execute(Event event) +bool McMoveFromBaronGeddonAction::Execute(Event) { if (Unit* boss = AI_VALUE2(Unit*, "find target", "baron geddon")) { @@ -42,7 +42,7 @@ bool McMoveFromBaronGeddonAction::Execute(Event event) return false; } -bool McShazzrahMoveAwayAction::Execute(Event event) +bool McShazzrahMoveAwayAction::Execute(Event) { if (Unit* boss = AI_VALUE2(Unit*, "find target", "shazzrah")) { @@ -53,7 +53,7 @@ bool McShazzrahMoveAwayAction::Execute(Event event) return false; } -bool McGolemaggMarkBossAction::Execute(Event event) +bool McGolemaggMarkBossAction::Execute(Event) { if (Unit* boss = AI_VALUE2(Unit*, "find target", "golemagg the incinerator")) { @@ -90,7 +90,7 @@ bool McGolemaggTankAction::MoveUnitToPosition(Unit* target, const Position& tank true); } } - else if (botAI->DoSpecificAction("taunt spell", Event(), true)) + else if (botAI->DoSpecificAction(CreateNextAction(1.0f).factory, Event(), true)) return true; return false; } @@ -115,7 +115,7 @@ bool McGolemaggTankAction::FindCoreRagers(Unit*& coreRager1, Unit*& coreRager2) return coreRager1 != nullptr && coreRager2 != nullptr; } -bool McGolemaggMainTankAttackGolemaggAction::Execute(Event event) +bool McGolemaggMainTankAttackGolemaggAction::Execute(Event) { // At this point, we know we are not the last living tank in the group. if (Unit* boss = AI_VALUE2(Unit*, "find target", "golemagg the incinerator")) @@ -170,7 +170,7 @@ bool McGolemaggAssistTankAttackCoreRagerAction::Execute(Event event) // Step 3.1: My Core Rager isn't attacking me. Attack until it does. if (bot->GetVictim() != myCoreRager) return Attack(myCoreRager); - return botAI->DoSpecificAction("taunt spell", event, true); + return botAI->DoSpecificAction(CreateNextAction(1.0f).factory, event, true); } Unit* otherCoreRagerVictim = otherCoreRager->GetVictim(); @@ -185,7 +185,7 @@ bool McGolemaggAssistTankAttackCoreRagerAction::Execute(Event event) // Assume we are the only assist tank or the other assist tank is dead => pick up other Core Rager! if (bot->GetVictim() != otherCoreRager) return Attack(otherCoreRager); - return botAI->DoSpecificAction("taunt spell", event, true); + return botAI->DoSpecificAction(CreateNextAction(1.0f).factory, event, true); } } diff --git a/src/Ai/Raid/MoltenCore/Action/RaidMcActions.h b/src/Ai/Raid/MoltenCore/Action/RaidMcActions.h index 680b311d3c..596b3e2d0a 100644 --- a/src/Ai/Raid/MoltenCore/Action/RaidMcActions.h +++ b/src/Ai/Raid/MoltenCore/Action/RaidMcActions.h @@ -2,9 +2,90 @@ #define _PLAYERBOT_RAIDMCACTIONS_H #include "AttackAction.h" +#include "BossAuraActions.h" #include "MovementActions.h" #include "PlayerbotAI.h" -#include "Playerbots.h" + +class LucifronShadowResistanceAction : public BossShadowResistanceAction +{ +public: + LucifronShadowResistanceAction(PlayerbotAI* botAI) + : BossShadowResistanceAction(botAI, "lucifron") + { + } +}; + +class MagmadarFireResistanceAction : public BossFireResistanceAction +{ +public: + MagmadarFireResistanceAction(PlayerbotAI* botAI) + : BossFireResistanceAction(botAI, "magmadar") + { + } +}; + +class GehennasShadowResistanceAction : public BossShadowResistanceAction +{ +public: + GehennasShadowResistanceAction(PlayerbotAI* botAI) + : BossShadowResistanceAction(botAI, "gehennas") + { + } +}; + +class GarrFireResistanceAction : public BossFireResistanceAction +{ +public: + GarrFireResistanceAction(PlayerbotAI* botAI) + : BossFireResistanceAction(botAI, "garr") + { + } +}; + +class BaronGeddonFireResistanceAction : public BossFireResistanceAction +{ +public: + BaronGeddonFireResistanceAction(PlayerbotAI* botAI) + : BossFireResistanceAction(botAI, "baron geddon") + { + } +}; + +class SulfuronHarbingerFireResistanceAction : public BossFireResistanceAction +{ +public: + SulfuronHarbingerFireResistanceAction(PlayerbotAI* botAI) + : BossFireResistanceAction(botAI, "sulfuron harbinger") + { + } +}; + +class GolemaggTheIncineratorFireResistanceAction : public BossFireResistanceAction +{ +public: + GolemaggTheIncineratorFireResistanceAction(PlayerbotAI* botAI) + : BossFireResistanceAction(botAI, "golemagg the incinerator") + { + } +}; + +class MajordomoExecutusShadowResistanceAction : public BossShadowResistanceAction +{ +public: + MajordomoExecutusShadowResistanceAction(PlayerbotAI* botAI) + : BossShadowResistanceAction(botAI, "majordomo executus") + { + } +}; + +class RagnarosFireResistanceAction : public BossFireResistanceAction +{ +public: + RagnarosFireResistanceAction(PlayerbotAI* botAI) + : BossFireResistanceAction(botAI, "ragnaros") + { + } +}; class McMoveFromGroupAction : public MovementAction { diff --git a/src/Ai/Raid/MoltenCore/Multiplier/RaidMcMultipliers.cpp b/src/Ai/Raid/MoltenCore/Multiplier/RaidMcMultipliers.cpp index d1ee936b0d..8e45b6700a 100644 --- a/src/Ai/Raid/MoltenCore/Multiplier/RaidMcMultipliers.cpp +++ b/src/Ai/Raid/MoltenCore/Multiplier/RaidMcMultipliers.cpp @@ -14,17 +14,17 @@ using namespace MoltenCoreHelpers; -static bool IsDpsBotWithAoeAction(Player* bot, Action* action) +static bool IsDpsBotWithAoeAction(Player* bot, Action& action) { if (PlayerbotAI::IsDps(bot)) { - if (dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action)) + if (dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action)) return true; - if (auto castSpellAction = dynamic_cast(action)) + if (auto castSpellAction = dynamic_cast(&action)) { if (castSpellAction->getThreatType() == Action::ActionThreatType::Aoe) return true; @@ -33,7 +33,7 @@ static bool IsDpsBotWithAoeAction(Player* bot, Action* action) return false; } -float GarrDisableDpsAoeMultiplier::GetValue(Action* action) +float GarrDisableDpsAoeMultiplier::GetValue(Action& action) { if (AI_VALUE2(Unit*, "find target", "garr")) { @@ -43,20 +43,20 @@ float GarrDisableDpsAoeMultiplier::GetValue(Action* action) return 1.0f; } -static bool IsAllowedGeddonMovementAction(Action* action) +static bool IsAllowedGeddonMovementAction(Action& action) { - if (dynamic_cast(action) && - !dynamic_cast(action) && - !dynamic_cast(action)) + if (dynamic_cast(&action) && + !dynamic_cast(&action) && + !dynamic_cast(&action)) return false; - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return false; return true; } -float BaronGeddonAbilityMultiplier::GetValue(Action* action) +float BaronGeddonAbilityMultiplier::GetValue(Action& action) { if (Unit* boss = AI_VALUE2(Unit*, "find target", "baron geddon")) { @@ -93,21 +93,21 @@ static bool IsSingleLivingTankInGroup(Player* bot) return true; } -float GolemaggMultiplier::GetValue(Action* action) +float GolemaggMultiplier::GetValue(Action& action) { if (AI_VALUE2(Unit*, "find target", "golemagg the incinerator")) { if (PlayerbotAI::IsTank(bot) && IsSingleLivingTankInGroup(bot)) { // Only one tank => Pick up Golemagg and the two Core Ragers - if (dynamic_cast(action) || - dynamic_cast(action)) + if (dynamic_cast(&action) || + dynamic_cast(&action)) return 0.0f; } if (PlayerbotAI::IsAssistTank(bot)) { // The first two assist tanks manage the Core Ragers. The remaining assist tanks attack the boss. - if (dynamic_cast(action)) + if (dynamic_cast(&action)) return 0.0f; } if (IsDpsBotWithAoeAction(bot, action)) diff --git a/src/Ai/Raid/MoltenCore/Multiplier/RaidMcMultipliers.h b/src/Ai/Raid/MoltenCore/Multiplier/RaidMcMultipliers.h index 56dc7a5f80..9ad26a5fbb 100644 --- a/src/Ai/Raid/MoltenCore/Multiplier/RaidMcMultipliers.h +++ b/src/Ai/Raid/MoltenCore/Multiplier/RaidMcMultipliers.h @@ -7,21 +7,21 @@ class GarrDisableDpsAoeMultiplier : public Multiplier { public: GarrDisableDpsAoeMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "garr disable dps aoe multiplier") {} - float GetValue(Action* action) override; + float GetValue(Action& action) override; }; class BaronGeddonAbilityMultiplier : public Multiplier { public: BaronGeddonAbilityMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "baron geddon ability multiplier") {} - float GetValue(Action* action) override; + float GetValue(Action& action) override; }; class GolemaggMultiplier : public Multiplier { public: GolemaggMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "golemagg multiplier") {} - float GetValue(Action* action) override; + float GetValue(Action& action) override; }; #endif diff --git a/src/Ai/Raid/MoltenCore/RaidMcActionContext.h b/src/Ai/Raid/MoltenCore/RaidMcActionContext.h deleted file mode 100644 index 79a4a95a85..0000000000 --- a/src/Ai/Raid/MoltenCore/RaidMcActionContext.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef _PLAYERBOT_RAIDMCACTIONCONTEXT_H -#define _PLAYERBOT_RAIDMCACTIONCONTEXT_H - -#include "Action.h" -#include "NamedObjectContext.h" -#include "RaidMcActions.h" - -class RaidMcActionContext : public NamedObjectContext -{ -public: - RaidMcActionContext() - { - creators["mc lucifron shadow resistance"] = &RaidMcActionContext::lucifron_shadow_resistance; - creators["mc magmadar fire resistance"] = &RaidMcActionContext::magmadar_fire_resistance; - creators["mc gehennas shadow resistance"] = &RaidMcActionContext::gehennas_shadow_resistance; - creators["mc garr fire resistance"] = &RaidMcActionContext::garr_fire_resistance; - creators["mc baron geddon fire resistance"] = &RaidMcActionContext::baron_geddon_fire_resistance; - creators["mc move from group"] = &RaidMcActionContext::check_should_move_from_group; - creators["mc move from baron geddon"] = &RaidMcActionContext::move_from_baron_geddon; - creators["mc shazzrah move away"] = &RaidMcActionContext::shazzrah_move_away; - creators["mc sulfuron harbinger fire resistance"] = &RaidMcActionContext::sulfuron_harbinger_fire_resistance; - creators["mc golemagg fire resistance"] = &RaidMcActionContext::golemagg_fire_resistance; - creators["mc golemagg mark boss"] = &RaidMcActionContext::golemagg_mark_boss; - creators["mc golemagg main tank attack golemagg"] = &RaidMcActionContext::golemagg_main_tank_attack_golemagg; - creators["mc golemagg assist tank attack core rager"] = &RaidMcActionContext::golemagg_assist_tank_attack_core_rager; - creators["mc majordomo shadow resistance"] = &RaidMcActionContext::majordomo_shadow_resistance; - creators["mc ragnaros fire resistance"] = &RaidMcActionContext::ragnaros_fire_resistance; - } - -private: - static Action* lucifron_shadow_resistance(PlayerbotAI* botAI) { return new BossShadowResistanceAction(botAI, "lucifron"); } - static Action* magmadar_fire_resistance(PlayerbotAI* botAI) { return new BossFireResistanceAction(botAI, "magmadar"); } - static Action* gehennas_shadow_resistance(PlayerbotAI* botAI) { return new BossShadowResistanceAction(botAI, "gehennas"); } - static Action* garr_fire_resistance(PlayerbotAI* botAI) { return new BossFireResistanceAction(botAI, "garr"); } - static Action* baron_geddon_fire_resistance(PlayerbotAI* botAI) { return new BossFireResistanceAction(botAI, "baron geddon"); } - static Action* check_should_move_from_group(PlayerbotAI* botAI) { return new McMoveFromGroupAction(botAI); } - static Action* move_from_baron_geddon(PlayerbotAI* botAI) { return new McMoveFromBaronGeddonAction(botAI); } - static Action* shazzrah_move_away(PlayerbotAI* botAI) { return new McShazzrahMoveAwayAction(botAI); } - static Action* sulfuron_harbinger_fire_resistance(PlayerbotAI* botAI) { return new BossFireResistanceAction(botAI, "sulfuron harbinger"); } - static Action* golemagg_fire_resistance(PlayerbotAI* botAI) { return new BossFireResistanceAction(botAI, "golemagg the incinerator"); } - static Action* golemagg_mark_boss(PlayerbotAI* botAI) { return new McGolemaggMarkBossAction(botAI); } - static Action* golemagg_main_tank_attack_golemagg(PlayerbotAI* botAI) { return new McGolemaggMainTankAttackGolemaggAction(botAI); } - static Action* golemagg_assist_tank_attack_core_rager(PlayerbotAI* botAI) { return new McGolemaggAssistTankAttackCoreRagerAction(botAI); } - static Action* majordomo_shadow_resistance(PlayerbotAI* botAI) { return new BossShadowResistanceAction(botAI, "majordomo executus"); } - static Action* ragnaros_fire_resistance(PlayerbotAI* botAI) { return new BossFireResistanceAction(botAI, "ragnaros"); } -}; - -#endif diff --git a/src/Ai/Raid/MoltenCore/Strategy/RaidMcStrategy.cpp b/src/Ai/Raid/MoltenCore/Strategy/RaidMcStrategy.cpp index 3eddb76a79..122163ac19 100644 --- a/src/Ai/Raid/MoltenCore/Strategy/RaidMcStrategy.cpp +++ b/src/Ai/Raid/MoltenCore/Strategy/RaidMcStrategy.cpp @@ -1,76 +1,153 @@ #include "RaidMcStrategy.h" +#include "CreateNextAction.h" #include "RaidMcMultipliers.h" #include "Strategy.h" +#include "RaidMcActions.h" void RaidMcStrategy::InitTriggers(std::vector& triggers) { // Lucifron triggers.push_back( - new TriggerNode("mc lucifron shadow resistance", - { NextAction("mc lucifron shadow resistance", ACTION_RAID) })); + new TriggerNode( + "mc lucifron shadow resistance", + { + CreateNextAction(ACTION_RAID) + } + ) + ); // Magmadar // TODO: Fear ward / tremor totem, or general anti-fear strat development. Same as King Dred (Drak'Tharon) and faction commander (Nexus). triggers.push_back( - new TriggerNode("mc magmadar fire resistance", - { NextAction("mc magmadar fire resistance", ACTION_RAID) })); + new TriggerNode( + "mc magmadar fire resistance", + { + CreateNextAction(ACTION_RAID) + } + ) + ); // Gehennas triggers.push_back( - new TriggerNode("mc gehennas shadow resistance", - { NextAction("mc gehennas shadow resistance", ACTION_RAID) })); + new TriggerNode( + "mc gehennas shadow resistance", + { + CreateNextAction(ACTION_RAID) + } + ) + ); // Garr triggers.push_back( - new TriggerNode("mc garr fire resistance", - { NextAction("mc garr fire resistance", ACTION_RAID) })); + new TriggerNode( + "mc garr fire resistance", + { + CreateNextAction(ACTION_RAID) + } + ) + ); // Baron Geddon triggers.push_back( - new TriggerNode("mc baron geddon fire resistance", - { NextAction("mc baron geddon fire resistance", ACTION_RAID) })); + new TriggerNode( + "mc baron geddon fire resistance", + { + CreateNextAction(ACTION_RAID) + } + ) + ); triggers.push_back( - new TriggerNode("mc living bomb debuff", - { NextAction("mc move from group", ACTION_RAID) })); + new TriggerNode( + "mc living bomb debuff", + { + CreateNextAction(ACTION_RAID) + } + ) + ); triggers.push_back( - new TriggerNode("mc baron geddon inferno", - { NextAction("mc move from baron geddon", ACTION_RAID) })); + new TriggerNode( + "mc baron geddon inferno", + { + CreateNextAction(ACTION_RAID) + } + ) + ); // Shazzrah triggers.push_back( - new TriggerNode("mc shazzrah ranged", - { NextAction("mc shazzrah move away", ACTION_RAID) })); + new TriggerNode( + "mc shazzrah ranged", + { + CreateNextAction(ACTION_RAID) + } + ) + ); // Sulfuron Harbinger // Alternatively, shadow resistance is also possible. triggers.push_back( - new TriggerNode("mc sulfuron harbinger fire resistance", - { NextAction("mc sulfuron harbinger fire resistance", ACTION_RAID) })); + new TriggerNode( + "mc sulfuron harbinger fire resistance", + { + CreateNextAction(ACTION_RAID) + } + ) + ); // Golemagg the Incinerator triggers.push_back( - new TriggerNode("mc golemagg fire resistance", - { NextAction("mc golemagg fire resistance", ACTION_RAID) })); + new TriggerNode( + "mc golemagg fire resistance", + { + CreateNextAction(ACTION_RAID) + } + ) + ); triggers.push_back( - new TriggerNode("mc golemagg mark boss", - { NextAction("mc golemagg mark boss", ACTION_RAID) })); + new TriggerNode( + "mc golemagg mark boss", + { + CreateNextAction(ACTION_RAID) + } + ) + ); triggers.push_back( - new TriggerNode("mc golemagg is main tank", - { NextAction("mc golemagg main tank attack golemagg", ACTION_RAID) })); + new TriggerNode( + "mc golemagg is main tank", + { + CreateNextAction(ACTION_RAID) + } + ) + ); triggers.push_back( - new TriggerNode("mc golemagg is assist tank", - { NextAction("mc golemagg assist tank attack core rager", ACTION_RAID) })); + new TriggerNode( + "mc golemagg is assist tank", + { + CreateNextAction(ACTION_RAID) + } + ) + ); // Majordomo Executus triggers.push_back( - new TriggerNode("mc majordomo shadow resistance", - { NextAction("mc majordomo shadow resistance", ACTION_RAID) })); + new TriggerNode( + "mc majordomo shadow resistance", + { + CreateNextAction(ACTION_RAID) + } + ) + ); // Ragnaros triggers.push_back( - new TriggerNode("mc ragnaros fire resistance", - { NextAction("mc ragnaros fire resistance", ACTION_RAID) })); + new TriggerNode( + "mc ragnaros fire resistance", + { + CreateNextAction(ACTION_RAID) + } + ) + ); } void RaidMcStrategy::InitMultipliers(std::vector& multipliers) diff --git a/src/Ai/Raid/ObsidianSanctum/Action/RaidOsActions.cpp b/src/Ai/Raid/ObsidianSanctum/Action/RaidOsActions.cpp index 724b91902f..c6834925f1 100644 --- a/src/Ai/Raid/ObsidianSanctum/Action/RaidOsActions.cpp +++ b/src/Ai/Raid/ObsidianSanctum/Action/RaidOsActions.cpp @@ -3,14 +3,11 @@ #include "Playerbots.h" -bool SartharionTankPositionAction::Execute(Event event) +bool SartharionTankPositionAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "sartharion"); if (!boss) { return false; } - // Unit* shadron = AI_VALUE2(Unit*, "find target", "shadron"); - // Unit* tenebron = AI_VALUE2(Unit*, "find target", "tenebron"); - // Unit* vesperon = AI_VALUE2(Unit*, "find target", "vesperon"); Unit* shadron = nullptr; Unit* tenebron = nullptr; Unit* vesperon = nullptr; @@ -84,7 +81,7 @@ bool SartharionTankPositionAction::Execute(Event event) return false; } -bool AvoidTwilightFissureAction::Execute(Event event) +bool AvoidTwilightFissureAction::Execute(Event) { const float radius = 5.0f; @@ -104,7 +101,7 @@ bool AvoidTwilightFissureAction::Execute(Event event) return false; } -bool AvoidFlameTsunamiAction::Execute(Event event) +bool AvoidFlameTsunamiAction::Execute(Event) { // Adjustable, this is the acceptable distance to stack point that will be accepted as "safe" float looseDistance = 4.0f; @@ -167,7 +164,7 @@ bool AvoidFlameTsunamiAction::Execute(Event event) return false; } -bool SartharionAttackPriorityAction::Execute(Event event) +bool SartharionAttackPriorityAction::Execute(Event) { Unit* sartharion = AI_VALUE2(Unit*, "find target", "sartharion"); Unit* shadron = AI_VALUE2(Unit*, "find target", "shadron"); @@ -206,7 +203,7 @@ bool SartharionAttackPriorityAction::Execute(Event event) return false; } -bool EnterTwilightPortalAction::Execute(Event event) +bool EnterTwilightPortalAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "sartharion"); if (!boss || !boss->HasAura(SPELL_GIFT_OF_TWILIGHT_FIRE)) { return false; } @@ -227,7 +224,7 @@ bool EnterTwilightPortalAction::Execute(Event event) return true; } -bool ExitTwilightPortalAction::Execute(Event event) +bool ExitTwilightPortalAction::Execute(Event) { GameObject* portal = bot->FindNearestGameObject(GO_NORMAL_PORTAL, 100.0f); if (!portal) { return false; } diff --git a/src/Ai/Raid/ObsidianSanctum/Multiplier/RaidOsMultipliers.cpp b/src/Ai/Raid/ObsidianSanctum/Multiplier/RaidOsMultipliers.cpp index bc63f967d0..04c8120696 100644 --- a/src/Ai/Raid/ObsidianSanctum/Multiplier/RaidOsMultipliers.cpp +++ b/src/Ai/Raid/ObsidianSanctum/Multiplier/RaidOsMultipliers.cpp @@ -4,44 +4,40 @@ #include "DKActions.h" #include "DruidActions.h" #include "DruidBearActions.h" -#include "FollowActions.h" -#include "GenericActions.h" #include "GenericSpellActions.h" #include "MovementActions.h" #include "PaladinActions.h" -#include "RaidOsActions.h" -#include "RaidOsTriggers.h" #include "ReachTargetActions.h" -#include "ScriptedCreature.h" +#include "Playerbots.h" #include "WarriorActions.h" -float SartharionMultiplier::GetValue(Action* action) +float SartharionMultiplier::GetValue(Action& action) { Unit* boss = AI_VALUE2(Unit*, "find target", "sartharion"); if (!boss) { return 1.0f; } - Unit* target = action->GetTarget(); + Unit* target = action.GetTarget(); - if (botAI->IsMainTank(bot) && dynamic_cast(action)) + if (botAI->IsMainTank(bot) && dynamic_cast(&action)) { // return 0.0f; } - if (botAI->IsDps(bot) && dynamic_cast(action)) + if (botAI->IsDps(bot) && dynamic_cast(&action)) { return 0.0f; } if (botAI->IsMainTank(bot) && target && target != boss && - (dynamic_cast(action) || dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action))) + (dynamic_cast(&action) || dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action))) { return 0.0f; } if (botAI->IsAssistTank(bot) && target && target == boss && - (dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action))) + (dynamic_cast(&action) || dynamic_cast(&action) || + dynamic_cast(&action) || dynamic_cast(&action))) { return 0.0f; } diff --git a/src/Ai/Raid/ObsidianSanctum/Multiplier/RaidOsMultipliers.h b/src/Ai/Raid/ObsidianSanctum/Multiplier/RaidOsMultipliers.h index 802335e133..52f55b82ff 100644 --- a/src/Ai/Raid/ObsidianSanctum/Multiplier/RaidOsMultipliers.h +++ b/src/Ai/Raid/ObsidianSanctum/Multiplier/RaidOsMultipliers.h @@ -10,7 +10,7 @@ class SartharionMultiplier : public Multiplier SartharionMultiplier(PlayerbotAI* ai) : Multiplier(ai, "sartharion") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; #endif diff --git a/src/Ai/Raid/ObsidianSanctum/RaidOsActionContext.h b/src/Ai/Raid/ObsidianSanctum/RaidOsActionContext.h deleted file mode 100644 index 55afe52603..0000000000 --- a/src/Ai/Raid/ObsidianSanctum/RaidOsActionContext.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef _PLAYERBOT_RAIDOSACTIONCONTEXT_H -#define _PLAYERBOT_RAIDOSACTIONCONTEXT_H - -#include "Action.h" -#include "NamedObjectContext.h" -#include "RaidOsActions.h" - -class RaidOsActionContext : public NamedObjectContext -{ -public: - RaidOsActionContext() - { - creators["sartharion tank position"] = &RaidOsActionContext::tank_position; - creators["avoid twilight fissure"] = &RaidOsActionContext::avoid_twilight_fissure; - creators["avoid flame tsunami"] = &RaidOsActionContext::avoid_flame_tsunami; - creators["sartharion attack priority"] = &RaidOsActionContext::attack_priority; - creators["enter twilight portal"] = &RaidOsActionContext::enter_twilight_portal; - creators["exit twilight portal"] = &RaidOsActionContext::exit_twilight_portal; - } - -private: - static Action* tank_position(PlayerbotAI* ai) { return new SartharionTankPositionAction(ai); } - static Action* avoid_twilight_fissure(PlayerbotAI* ai) { return new AvoidTwilightFissureAction(ai); } - static Action* avoid_flame_tsunami(PlayerbotAI* ai) { return new AvoidFlameTsunamiAction(ai); } - static Action* attack_priority(PlayerbotAI* ai) { return new SartharionAttackPriorityAction(ai); } - static Action* enter_twilight_portal(PlayerbotAI* ai) { return new EnterTwilightPortalAction(ai); } - static Action* exit_twilight_portal(PlayerbotAI* ai) { return new ExitTwilightPortalAction(ai); } -}; - -#endif diff --git a/src/Ai/Raid/ObsidianSanctum/Strategy/RaidOsStrategy.cpp b/src/Ai/Raid/ObsidianSanctum/Strategy/RaidOsStrategy.cpp index 4468de991f..9fd1a8b865 100644 --- a/src/Ai/Raid/ObsidianSanctum/Strategy/RaidOsStrategy.cpp +++ b/src/Ai/Raid/ObsidianSanctum/Strategy/RaidOsStrategy.cpp @@ -1,29 +1,69 @@ #include "RaidOsStrategy.h" +#include "CreateNextAction.h" +#include "RaidOsActions.h" #include "RaidOsMultipliers.h" -#include "Strategy.h" +#include "MovementActions.h" void RaidOsStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("sartharion tank", - { NextAction("sartharion tank position", ACTION_MOVE) })); + new TriggerNode( + "sartharion tank", + { + CreateNextAction(ACTION_MOVE) + } + ) + ); triggers.push_back( - new TriggerNode("twilight fissure", - { NextAction("avoid twilight fissure", ACTION_RAID + 2) })); + new TriggerNode( + "twilight fissure", + { + CreateNextAction(ACTION_RAID + 2.0f) + } + ) + ); triggers.push_back( - new TriggerNode("flame tsunami", - { NextAction("avoid flame tsunami", ACTION_RAID + 1) })); + new TriggerNode( + "flame tsunami", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); triggers.push_back( - new TriggerNode("sartharion dps", - { NextAction("sartharion attack priority", ACTION_RAID) })); + new TriggerNode( + "sartharion dps", + { + CreateNextAction(ACTION_RAID) + } + ) + ); // Flank dragon positioning - triggers.push_back(new TriggerNode("sartharion melee positioning", - { NextAction("rear flank", ACTION_MOVE + 4) })); + triggers.push_back( + new TriggerNode( + "sartharion melee positioning", + { + CreateNextAction(ACTION_MOVE + 4.0f) + } + ) + ); - triggers.push_back(new TriggerNode("twilight portal enter", - { NextAction("enter twilight portal", ACTION_RAID + 1) })); - triggers.push_back(new TriggerNode("twilight portal exit", - { NextAction("exit twilight portal", ACTION_RAID + 1) })); + triggers.push_back( + new TriggerNode( + "twilight portal enter", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); + triggers.push_back( + new TriggerNode( + "twilight portal exit", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); } void RaidOsStrategy::InitMultipliers(std::vector &multipliers) diff --git a/src/Ai/Raid/Onyxia/Action/RaidOnyxiaActions.cpp b/src/Ai/Raid/Onyxia/Action/RaidOnyxiaActions.cpp index 9fa4612bf6..aa2eb31229 100644 --- a/src/Ai/Raid/Onyxia/Action/RaidOnyxiaActions.cpp +++ b/src/Ai/Raid/Onyxia/Action/RaidOnyxiaActions.cpp @@ -1,4 +1,3 @@ -// RaidOnyxiaActions.cpp #include "RaidOnyxiaActions.h" #include "GenericSpellActions.h" @@ -7,7 +6,7 @@ #include "Playerbots.h" #include "PositionAction.h" -bool RaidOnyxiaMoveToSideAction::Execute(Event event) +bool RaidOnyxiaMoveToSideAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "onyxia"); if (!boss) @@ -38,7 +37,7 @@ bool RaidOnyxiaMoveToSideAction::Execute(Event event) return false; } -bool RaidOnyxiaSpreadOutAction::Execute(Event event) +bool RaidOnyxiaSpreadOutAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "onyxia"); @@ -64,7 +63,7 @@ bool RaidOnyxiaSpreadOutAction::Execute(Event event) return MoveFromGroup(9.0f); // move 9 yards } -bool RaidOnyxiaMoveToSafeZoneAction::Execute(Event event) +bool RaidOnyxiaMoveToSafeZoneAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "onyxia"); if (!boss) @@ -105,7 +104,7 @@ bool RaidOnyxiaMoveToSafeZoneAction::Execute(Event event) false, false, false, false, MovementPriority::MOVEMENT_COMBAT); } -bool RaidOnyxiaKillWhelpsAction::Execute(Event event) +bool RaidOnyxiaKillWhelpsAction::Execute(Event) { Unit* currentTarget = AI_VALUE(Unit*, "current target"); // If already attacking a whelp, don't swap targets @@ -129,7 +128,7 @@ bool RaidOnyxiaKillWhelpsAction::Execute(Event event) return false; } -bool OnyxiaAvoidEggsAction::Execute(Event event) +bool OnyxiaAvoidEggsAction::Execute(Event) { Position botPos = Position(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ()); diff --git a/src/Ai/Raid/Onyxia/RaidOnyxiaActionContext.h b/src/Ai/Raid/Onyxia/RaidOnyxiaActionContext.h deleted file mode 100644 index b2923f969f..0000000000 --- a/src/Ai/Raid/Onyxia/RaidOnyxiaActionContext.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _PLAYERBOT_RAIDONYXIAACTIONS_CONTEXT_H -#define _PLAYERBOT_RAIDONYXIAACTIONS_CONTEXT_H - -#include "Action.h" -#include "NamedObjectContext.h" -#include "RaidOnyxiaActions.h" - -class RaidOnyxiaActionContext : public NamedObjectContext -{ -public: - RaidOnyxiaActionContext() - { - creators["ony move to side"] = &RaidOnyxiaActionContext::move_to_side; - creators["ony spread out"] = &RaidOnyxiaActionContext::spread_out; - creators["ony move to safe zone"] = &RaidOnyxiaActionContext::move_to_safe_zone; - creators["ony kill whelps"] = &RaidOnyxiaActionContext::kill_whelps; - creators["ony avoid eggs move"] = &RaidOnyxiaActionContext::avoid_eggs; - } - -private: - static Action* move_to_side(PlayerbotAI* ai) { return new RaidOnyxiaMoveToSideAction(ai); } - static Action* spread_out(PlayerbotAI* ai) { return new RaidOnyxiaSpreadOutAction(ai); } - static Action* move_to_safe_zone(PlayerbotAI* ai) { return new RaidOnyxiaMoveToSafeZoneAction(ai); } - static Action* kill_whelps(PlayerbotAI* ai) { return new RaidOnyxiaKillWhelpsAction(ai); } - static Action* avoid_eggs(PlayerbotAI* ai) { return new OnyxiaAvoidEggsAction(ai); } -}; - -#endif diff --git a/src/Ai/Raid/Onyxia/Strategy/RaidOnyxiaStrategy.cpp b/src/Ai/Raid/Onyxia/Strategy/RaidOnyxiaStrategy.cpp index b1217f59eb..cc2232049f 100644 --- a/src/Ai/Raid/Onyxia/Strategy/RaidOnyxiaStrategy.cpp +++ b/src/Ai/Raid/Onyxia/Strategy/RaidOnyxiaStrategy.cpp @@ -1,30 +1,60 @@ #include "RaidOnyxiaStrategy.h" +#include "RaidOnyxiaActions.h" +#include "CreateNextAction.h" void RaidOnyxiaStrategy::InitTriggers(std::vector& triggers) { // ----------- Phase 1 (100% - 65%) ----------- - triggers.push_back(new TriggerNode( - "ony near tail", { NextAction("ony move to side", ACTION_RAID + 2) })); + triggers.push_back( + new TriggerNode( + "ony near tail", + { + CreateNextAction(ACTION_RAID + 2.0f) + } + ) + ); - triggers.push_back(new TriggerNode( - "ony avoid eggs", { NextAction("ony avoid eggs move", ACTION_EMERGENCY + 5) })); + triggers.push_back( + new TriggerNode( + "ony avoid eggs", + { + CreateNextAction(ACTION_EMERGENCY + 5.0f) + } + ) + ); // ----------- Phase 2 (65% - 40%) ----------- triggers.push_back( - new TriggerNode("ony deep breath warning", - { NextAction("ony move to safe zone", ACTION_EMERGENCY + 5) })); + new TriggerNode( + "ony deep breath warning", + { + CreateNextAction(ACTION_EMERGENCY + 5.0f) + } + ) + ); triggers.push_back( - new TriggerNode("ony fireball splash incoming", - { NextAction("ony spread out", ACTION_EMERGENCY + 2) })); + new TriggerNode( + "ony fireball splash incoming", + { + CreateNextAction(ACTION_EMERGENCY + 2.0f) + } + ) + ); - triggers.push_back(new TriggerNode( - "ony whelps spawn", { NextAction("ony kill whelps", ACTION_RAID + 1) })); + triggers.push_back( + new TriggerNode( + "ony whelps spawn", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); } -void RaidOnyxiaStrategy::InitMultipliers(std::vector& multipliers) +void RaidOnyxiaStrategy::InitMultipliers(std::vector&) { // Empty for now } diff --git a/src/Ai/Raid/Ulduar/Action/RaidUlduarActions.cpp b/src/Ai/Raid/Ulduar/Action/RaidUlduarActions.cpp index b7c3723bb3..80a72d6e13 100644 --- a/src/Ai/Raid/Ulduar/Action/RaidUlduarActions.cpp +++ b/src/Ai/Raid/Ulduar/Action/RaidUlduarActions.cpp @@ -7,6 +7,7 @@ #include #include "AiObjectContext.h" +#include "ChooseTargetActions.h" #include "DBCEnums.h" #include "GameObject.h" #include "Group.h" @@ -18,16 +19,14 @@ #include "Playerbots.h" #include "Position.h" #include "RaidUlduarBossHelper.h" -#include "RaidUlduarScripts.h" -#include "RaidUlduarStrategy.h" #include "RtiValue.h" -#include "ScriptedCreature.h" #include "ServerFacade.h" #include "SharedDefines.h" #include "Unit.h" #include "Vehicle.h" #include #include +#include "../../../../../../src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h" const std::string ADD_STRATEGY_CHAR = "+"; const std::string REMOVE_STRATEGY_CHAR = "-"; @@ -50,7 +49,7 @@ const Position yoggPortalLoc[] = { {1960.62f, -32.00f, 325.5f}, {1981.98f, -5.69f, 325.5f}, {1982.78f, -45.73f, 325.5f}, {2000.66f, -29.68f, 325.5f}, {1999.88f, -19.61f, 325.5f}, {1961.37f, -19.54f, 325.5f}}; -bool FlameLeviathanVehicleAction::Execute(Event event) +bool FlameLeviathanVehicleAction::Execute(Event) { vehicleBase_ = bot->GetVehicleBase(); vehicle_ = bot->GetVehicle(); @@ -109,7 +108,7 @@ bool FlameLeviathanVehicleAction::MoveAvoidChasing(Unit* target) return false; if (avoidChaseIdx == -1) { - for (int i = 0; i < corners.size(); i++) + for (uint64_t i = 0; i < corners.size(); i++) { if (bot->GetExactDist(corners[i]) > target->GetExactDist(corners[i])) continue; @@ -272,7 +271,7 @@ bool FlameLeviathanVehicleAction::ChopperAction(Unit* target) return false; } -bool FlameLeviathanEnterVehicleAction::Execute(Event event) +bool FlameLeviathanEnterVehicleAction::Execute(Event) { // do not switch vehicles yet if (bot->GetVehicle()) @@ -417,7 +416,7 @@ bool FlameLeviathanEnterVehicleAction::AllMainVehiclesOnUse() return demolisher >= maxC && siege >= maxC; } -bool RazorscaleAvoidDevouringFlameAction::Execute(Event event) +bool RazorscaleAvoidDevouringFlameAction::Execute(Event) { RazorscaleBossHelper razorscaleHelper(botAI); @@ -498,7 +497,7 @@ bool RazorscaleAvoidDevouringFlameAction::isUseful() return false; // No nearby flames or bot is at a safe distance } -bool RazorscaleAvoidSentinelAction::Execute(Event event) +bool RazorscaleAvoidSentinelAction::Execute(Event) { bool isMainTank = botAI->IsMainTank(bot); bool isRanged = botAI->IsRanged(bot); @@ -620,7 +619,7 @@ bool RazorscaleAvoidSentinelAction::isUseful() return false; } -bool RazorscaleAvoidWhirlwindAction::Execute(Event event) +bool RazorscaleAvoidWhirlwindAction::Execute(Event) { if (botAI->IsTank(bot)) { @@ -737,7 +736,7 @@ bool RazorscaleIgnoreBossAction::isUseful() return false; } -bool RazorscaleIgnoreBossAction::Execute(Event event) +bool RazorscaleIgnoreBossAction::Execute(Event) { if (!bot) { @@ -894,7 +893,7 @@ bool RazorscaleGroundedAction::isUseful() return false; } -bool RazorscaleGroundedAction::Execute(Event event) +bool RazorscaleGroundedAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "razorscale"); if (!boss || !boss->IsAlive() || boss->GetPositionZ() > RazorscaleBossHelper::RAZORSCALE_FLYING_Z_THRESHOLD) @@ -977,7 +976,7 @@ bool RazorscaleGroundedAction::Execute(Event event) return false; } -bool RazorscaleHarpoonAction::Execute(Event event) +bool RazorscaleHarpoonAction::Execute(Event) { if (!bot) { @@ -1145,7 +1144,7 @@ bool RazorscaleFuseArmorAction::isUseful() return false; } -bool RazorscaleFuseArmorAction::Execute(Event event) +bool RazorscaleFuseArmorAction::Execute(Event) { // We already know from isUseful() that: // 1) This bot can tank, AND @@ -1164,7 +1163,7 @@ bool IronAssemblyLightningTendrilsAction::isUseful() return ironAssemblyLightningTendrilsTrigger.IsActive(); } -bool IronAssemblyLightningTendrilsAction::Execute(Event event) +bool IronAssemblyLightningTendrilsAction::Execute(Event) { const float radius = 18.0f + 10.0f; // 18 yards + 10 yards for safety @@ -1188,7 +1187,7 @@ bool IronAssemblyOverloadAction::isUseful() return ironAssemblyOverloadTrigger.IsActive(); } -bool IronAssemblyOverloadAction::Execute(Event event) +bool IronAssemblyOverloadAction::Execute(Event) { const float radius = 20.0f + 5.0f; // 20 yards + 5 yards for safety @@ -1212,7 +1211,7 @@ bool IronAssemblyRuneOfPowerAction::isUseful() return ironAssemblyRuneOfPowerTrigger.IsActive(); } -bool IronAssemblyRuneOfPowerAction::Execute(Event event) +bool IronAssemblyRuneOfPowerAction::Execute(Event) { Unit* target = botAI->GetUnit(bot->GetTarget()); if (!target || !target->IsAlive()) @@ -1227,7 +1226,7 @@ bool KologarnMarkDpsTargetAction::isUseful() return kologarnMarkDpsTargetTrigger.IsActive(); } -bool KologarnMarkDpsTargetAction::Execute(Event event) +bool KologarnMarkDpsTargetAction::Execute(Event) { Unit* targetToMark = nullptr; Unit* additionalTargetToMark = nullptr; @@ -1249,7 +1248,6 @@ bool KologarnMarkDpsTargetAction::Execute(Event event) if (!target) continue; - uint32 creatureId = target->GetEntry(); if (target->GetEntry() == NPC_RUBBLE && target->IsAlive()) { targetToMark = target; @@ -1362,7 +1360,7 @@ bool KologarnMarkDpsTargetAction::Execute(Event event) return false; } -bool KologarnFallFromFloorAction::Execute(Event event) +bool KologarnFallFromFloorAction::Execute(Event) { return bot->TeleportTo(bot->GetMapId(), ULDUAR_KOLOGARN_RESTORE_POSITION.GetPositionX(), ULDUAR_KOLOGARN_RESTORE_POSITION.GetPositionY(), @@ -1376,7 +1374,7 @@ bool KologarnFallFromFloorAction::isUseful() return kologarnFallFromFloorTrigger.IsActive(); } -bool KologarnRubbleSlowdownAction::Execute(Event event) +bool KologarnRubbleSlowdownAction::Execute(Event) { Group* group = bot->GetGroup(); if (!group) @@ -1391,7 +1389,7 @@ bool KologarnRubbleSlowdownAction::Execute(Event event) return botAI->CastSpell("frost trap", currentSkullUnit); } -bool KologarnEyebeamAction::Execute(Event event) +bool KologarnEyebeamAction::Execute(Event) { float distanceToLeftPoint = bot->GetExactDist(ULDUAR_KOLOGARN_EYEBEAM_LEFT_POSITION); float distanceToRightPoint = bot->GetExactDist(ULDUAR_KOLOGARN_EYEBEAM_RIGHT_POSITION); @@ -1450,7 +1448,7 @@ bool KologarnRtiTargetAction::isUseful() return kologarnRtiTargetTrigger.IsActive(); } -bool KologarnRtiTargetAction::Execute(Event event) +bool KologarnRtiTargetAction::Execute(Event) { if (botAI->IsMainTank(bot) || botAI->IsAssistTankOfIndex(bot, 0)) { @@ -1473,13 +1471,13 @@ bool KologarnCrunchArmorAction::isUseful() return botAI->HasCheat(BotCheatMask::raid); } -bool KologarnCrunchArmorAction::Execute(Event event) +bool KologarnCrunchArmorAction::Execute(Event) { bot->RemoveAura(SPELL_CRUNCH_ARMOR); return true; } -bool AuriayaFallFromFloorAction::Execute(Event event) +bool AuriayaFallFromFloorAction::Execute(Event) { Player* master = botAI->GetMaster(); @@ -1525,7 +1523,7 @@ bool HodirMoveSnowpackedIcicleAction::isUseful() return true; } -bool HodirMoveSnowpackedIcicleAction::Execute(Event event) +bool HodirMoveSnowpackedIcicleAction::Execute(Event) { Creature* target = bot->FindNearestCreature(NPC_SNOWPACKED_ICICLE, 100.0f); if (!target) @@ -1535,7 +1533,7 @@ bool HodirMoveSnowpackedIcicleAction::Execute(Event event) false, false, true, MovementPriority::MOVEMENT_NORMAL, true); } -bool HodirBitingColdJumpAction::Execute(Event event) +bool HodirBitingColdJumpAction::Execute(Event) { bot->RemoveAurasDueToSpell(SPELL_BITING_COLD_PLAYER_AURA); @@ -1591,7 +1589,7 @@ bool FreyaMoveAwayNatureBombAction::isUseful() return true; } -bool FreyaMoveAwayNatureBombAction::Execute(Event event) +bool FreyaMoveAwayNatureBombAction::Execute(Event) { GameObject* target = bot->FindNearestGameObject(GOBJECT_NATURE_BOMB, 12.0f); if (!target) @@ -1606,7 +1604,7 @@ bool FreyaMarkDpsTargetAction::isUseful() return freyaMarkDpsTargetTrigger.IsActive(); } -bool FreyaMarkDpsTargetAction::Execute(Event event) +bool FreyaMarkDpsTargetAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "freya"); if (!boss || !boss->IsAlive()) @@ -1762,7 +1760,7 @@ bool FreyaMoveToHealingSporeAction::isUseful() return freyaMoveToHealingSporeTrigger.IsActive(); } -bool FreyaMoveToHealingSporeAction::Execute(Event event) +bool FreyaMoveToHealingSporeAction::Execute(Event) { GuidVector targets = AI_VALUE(GuidVector, "nearest npcs"); Creature* nearestSpore = nullptr; @@ -1804,7 +1802,7 @@ bool ThorimUnbalancingStrikeAction::isUseful() return botAI->HasCheat(BotCheatMask::raid); } -bool ThorimUnbalancingStrikeAction::Execute(Event event) +bool ThorimUnbalancingStrikeAction::Execute(Event) { bot->RemoveAura(SPELL_UNBALANCING_STRIKE); return true; @@ -1816,7 +1814,7 @@ bool ThorimMarkDpsTargetAction::isUseful() return thorimMarkDpsTargetTrigger.IsActive(); } -bool ThorimMarkDpsTargetAction::Execute(Event event) +bool ThorimMarkDpsTargetAction::Execute(Event) { Unit* targetToMark = nullptr; @@ -1917,7 +1915,7 @@ bool ThorimArenaPositioningAction::isUseful() return thorimArenaPositioningTrigger.IsActive(); } -bool ThorimArenaPositioningAction::Execute(Event event) +bool ThorimArenaPositioningAction::Execute(Event) { FollowMasterStrategy followMasterStrategy(botAI); @@ -1939,7 +1937,7 @@ bool ThorimGauntletPositioningAction::isUseful() return thorimGauntletPositioningTrigger.IsActive(); } -bool ThorimGauntletPositioningAction::Execute(Event event) +bool ThorimGauntletPositioningAction::Execute(Event) { FollowMasterStrategy followMasterStrategy(botAI); @@ -2113,7 +2111,7 @@ bool ThorimGauntletPositioningAction::Execute(Event event) return false; } -bool ThorimFallFromFloorAction::Execute(Event event) +bool ThorimFallFromFloorAction::Execute(Event) { Player* master = botAI->GetMaster(); @@ -2130,7 +2128,7 @@ bool ThorimFallFromFloorAction::isUseful() return thorimFallFromFloorTrigger.IsActive(); } -bool ThorimPhase2PositioningAction::Execute(Event event) +bool ThorimPhase2PositioningAction::Execute(Event) { Position targetPosition; bool backward = false; @@ -2190,7 +2188,7 @@ bool ThorimPhase2PositioningAction::isUseful() return thorimPhase2PositioningTrigger.IsActive(); } -bool MimironShockBlastAction::Execute(Event event) +bool MimironShockBlastAction::Execute(Event) { Unit* leviathanMkII = nullptr; Unit* vx001 = nullptr; @@ -2264,7 +2262,7 @@ bool MimironShockBlastAction::isUseful() return mimironShockBlastTrigger.IsActive(); } -bool MimironPhase1PositioningAction::Execute(Event event) +bool MimironPhase1PositioningAction::Execute(Event) { SET_AI_VALUE(float, "disperse distance", 6.0f); return true; @@ -2276,7 +2274,7 @@ bool MimironPhase1PositioningAction::isUseful() return mimironPhase1PositioningTrigger.IsActive(); } -bool MimironP3Wx2LaserBarrageAction::Execute(Event event) +bool MimironP3Wx2LaserBarrageAction::Execute(Event) { auto master = botAI->GetMaster(); if (!master || !master->IsAlive()) @@ -2300,7 +2298,7 @@ bool MimironRapidBurstAction::isUseful() return mimironRapidBurstTrigger.IsActive(); } -bool MimironRapidBurstAction::Execute(Event event) +bool MimironRapidBurstAction::Execute(Event) { Unit* leviathanMkII = nullptr; @@ -2407,7 +2405,7 @@ bool MimironRapidBurstAction::Execute(Event event) return true; } -bool MimironAerialCommandUnitAction::Execute(Event event) +bool MimironAerialCommandUnitAction::Execute(Event) { Unit* boss = nullptr; Unit* bombBot = nullptr; @@ -2479,9 +2477,8 @@ bool MimironRocketStrikeAction::isUseful() return mimironRocketStrikeTrigger.IsActive(); } -bool MimironRocketStrikeAction::Execute(Event event) +bool MimironRocketStrikeAction::Execute(Event) { - Unit* leviathanMkII = nullptr; Unit* vx001 = nullptr; Unit* aerialCommandUnit = nullptr; @@ -2493,11 +2490,7 @@ bool MimironRocketStrikeAction::Execute(Event event) if (!target || !target->IsAlive()) continue; - if (target->GetEntry() == NPC_LEVIATHAN_MKII) - { - leviathanMkII = target; - } - else if (target->GetEntry() == NPC_VX001) + if (target->GetEntry() == NPC_VX001) { vx001 = target; } @@ -2540,7 +2533,7 @@ bool MimironRocketStrikeAction::Execute(Event event) } } -bool MimironPhase4MarkDpsAction::Execute(Event event) +bool MimironPhase4MarkDpsAction::Execute(Event) { Unit* leviathanMkII = nullptr; Unit* vx001 = nullptr; @@ -2615,7 +2608,7 @@ bool MimironPhase4MarkDpsAction::Execute(Event event) } } - botAI->DoSpecificAction("attack rti target"); + botAI->DoSpecificAction(CreateNextAction(1.0f).factory); return true; } else @@ -2629,7 +2622,7 @@ bool MimironPhase4MarkDpsAction::Execute(Event event) } } -bool MimironCheatAction::Execute(Event event) +bool MimironCheatAction::Execute(Event) { GuidVector targets = AI_VALUE(GuidVector, "nearest npcs"); for (const ObjectGuid& guid : targets) @@ -2651,7 +2644,7 @@ bool MimironCheatAction::Execute(Event event) return true; } -bool VezaxCheatAction::Execute(Event event) +bool VezaxCheatAction::Execute(Event) { // Restore bot's mana to full uint32 maxMana = bot->GetMaxPower(POWER_MANA); @@ -2663,7 +2656,7 @@ bool VezaxCheatAction::Execute(Event event) return true; } -bool VezaxShadowCrashAction::Execute(Event event) +bool VezaxShadowCrashAction::Execute(Event) { // Find General Vezax boss Unit* boss = AI_VALUE2(Unit*, "find target", "general vezax"); @@ -2707,7 +2700,7 @@ bool VezaxShadowCrashAction::Execute(Event event) true); } -bool VezaxMarkOfTheFacelessAction::Execute(Event event) +bool VezaxMarkOfTheFacelessAction::Execute(Event) { return MoveTo(bot->GetMapId(), ULDUAR_VEZAX_MARK_OF_THE_FACELESS_SPOT.GetPositionX(), ULDUAR_VEZAX_MARK_OF_THE_FACELESS_SPOT.GetPositionY(), @@ -2715,7 +2708,7 @@ bool VezaxMarkOfTheFacelessAction::Execute(Event event) MovementPriority::MOVEMENT_FORCED, true, false); } -bool YoggSaronOminousCloudCheatAction::Execute(Event event) +bool YoggSaronOminousCloudCheatAction::Execute(Event) { YoggSaronTrigger yoggSaronTrigger(botAI); @@ -2735,14 +2728,14 @@ bool YoggSaronOminousCloudCheatAction::Execute(Event event) return true; } -bool YoggSaronGuardianPositioningAction::Execute(Event event) +bool YoggSaronGuardianPositioningAction::Execute(Event) { return MoveTo(bot->GetMapId(), ULDUAR_YOGG_SARON_MIDDLE.GetPositionX(), ULDUAR_YOGG_SARON_MIDDLE.GetPositionY(), ULDUAR_YOGG_SARON_MIDDLE.GetPositionZ(), false, false, false, true, MovementPriority::MOVEMENT_FORCED, true, false); } -bool YoggSaronSanityAction::Execute(Event event) +bool YoggSaronSanityAction::Execute(Event) { Creature* sanityWell = bot->FindNearestCreature(NPC_SANITY_WELL, 200.0f); @@ -2751,7 +2744,7 @@ bool YoggSaronSanityAction::Execute(Event event) true, false); } -bool YoggSaronMarkTargetAction::Execute(Event event) +bool YoggSaronMarkTargetAction::Execute(Event) { Group* group = bot->GetGroup(); if (!group) @@ -2820,7 +2813,7 @@ bool YoggSaronMarkTargetAction::Execute(Event event) GuidVector targets = AI_VALUE(GuidVector, "nearest npcs"); - int lowestHealth = std::numeric_limits::max(); + uint64_t lowestHealth = std::numeric_limits::max(); Unit* lowestHealthUnit = nullptr; for (const ObjectGuid& guid : targets) { @@ -2880,7 +2873,7 @@ bool YoggSaronMarkTargetAction::Execute(Event event) return false; } -bool YoggSaronBrainLinkAction::Execute(Event event) +bool YoggSaronBrainLinkAction::Execute(Event) { Group* group = bot->GetGroup(); if (!group) @@ -2900,7 +2893,7 @@ bool YoggSaronBrainLinkAction::Execute(Event event) return false; } -bool YoggSaronMoveToEnterPortalAction::Execute(Event event) +bool YoggSaronMoveToEnterPortalAction::Execute(Event) { Group* group = bot->GetGroup(); if (!group) @@ -2964,12 +2957,12 @@ bool YoggSaronMoveToEnterPortalAction::Execute(Event event) { return MoveNear(bot->GetMapId(), assignedPortalPosition.GetPositionX(), assignedPortalPosition.GetPositionY(), - assignedPortalPosition.GetPositionZ(), sPlayerbotAIConfig->contactDistance, + assignedPortalPosition.GetPositionZ(), sPlayerbotAIConfig.contactDistance, MovementPriority::MOVEMENT_FORCED); } } -bool YoggSaronFallFromFloorAction::Execute(Event event) +bool YoggSaronFallFromFloorAction::Execute(Event) { std::string rtiMark = AI_VALUE(std::string, "rti"); if (rtiMark == "skull") @@ -3001,7 +2994,7 @@ bool YoggSaronFallFromFloorAction::Execute(Event event) return false; } -bool YoggSaronBossRoomMovementCheatAction::Execute(Event event) +bool YoggSaronBossRoomMovementCheatAction::Execute(Event) { FollowMasterStrategy followMasterStrategy(botAI); if (botAI->HasStrategy(followMasterStrategy.getName(), BotState::BOT_STATE_NON_COMBAT)) @@ -3037,7 +3030,7 @@ bool YoggSaronBossRoomMovementCheatAction::Execute(Event event) currentSkullUnit->GetPositionZ(), bot->GetOrientation()); } -bool YoggSaronUsePortalAction::Execute(Event event) +bool YoggSaronUsePortalAction::Execute(Event) { Creature* assignedPortal = bot->FindNearestCreature(NPC_DESCEND_INTO_MADNESS, 2.0f, true); if (!assignedPortal) @@ -3054,7 +3047,7 @@ bool YoggSaronUsePortalAction::Execute(Event event) return assignedPortal->HandleSpellClick(bot); } -bool YoggSaronIllusionRoomAction::Execute(Event event) +bool YoggSaronIllusionRoomAction::Execute(Event) { YoggSaronTrigger yoggSaronTrigger(botAI); @@ -3172,11 +3165,11 @@ bool YoggSaronIllusionRoomAction::SetBrainRtiTarget(YoggSaronTrigger yoggSaronTr false); } - botAI->DoSpecificAction("attack rti target"); + botAI->DoSpecificAction(CreateNextAction(1.0f).factory); return true; } -bool YoggSaronMoveToExitPortalAction::Execute(Event event) +bool YoggSaronMoveToExitPortalAction::Execute(Event) { GameObject* portal = bot->FindNearestGameObject(GO_FLEE_TO_THE_SURFACE_PORTAL, 100.0f); if (!portal) @@ -3207,7 +3200,7 @@ bool YoggSaronMoveToExitPortalAction::Execute(Event event) return true; } -bool YoggSaronLunaticGazeAction::Execute(Event event) +bool YoggSaronLunaticGazeAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "yogg-saron"); if (!boss || !boss->IsAlive()) @@ -3229,7 +3222,7 @@ bool YoggSaronLunaticGazeAction::Execute(Event event) return true; } -bool YoggSaronPhase3PositioningAction::Execute(Event event) +bool YoggSaronPhase3PositioningAction::Execute(Event) { if (botAI->IsRanged(bot)) { diff --git a/src/Ai/Raid/Ulduar/Action/RaidUlduarActions.h b/src/Ai/Raid/Ulduar/Action/RaidUlduarActions.h index c3d5c0d637..0296a20d77 100644 --- a/src/Ai/Raid/Ulduar/Action/RaidUlduarActions.h +++ b/src/Ai/Raid/Ulduar/Action/RaidUlduarActions.h @@ -3,12 +3,11 @@ #include "Action.h" #include "AttackAction.h" +#include "BossAuraActions.h" #include "GenericActions.h" #include "GenericSpellActions.h" #include "MovementActions.h" #include "PlayerbotAI.h" -#include "Playerbots.h" -#include "RaidUlduarBossHelper.h" #include "RaidUlduarTriggers.h" #include "Vehicle.h" @@ -107,6 +106,24 @@ class RazorscaleFuseArmorAction : public MovementAction bool isUseful() override; }; +class RazorscaleFireResistanceAction : public BossFireResistanceAction +{ +public: + RazorscaleFireResistanceAction(PlayerbotAI* botAI) + : BossFireResistanceAction(botAI, "razorscale") + { + } +}; + +class HodirFrostResistanceAction : public BossFrostResistanceAction +{ +public: + HodirFrostResistanceAction(PlayerbotAI* botAI) + : BossFrostResistanceAction(botAI, "hodir") + { + } +}; + class HodirMoveSnowpackedIcicleAction : public MovementAction { public: @@ -115,6 +132,15 @@ class HodirMoveSnowpackedIcicleAction : public MovementAction bool isUseful() override; }; +class IgnisFireResistanceAction : public BossFireResistanceAction +{ +public: + IgnisFireResistanceAction(PlayerbotAI* botAI) + : BossFireResistanceAction(botAI, "ignis") + { + } +}; + class IronAssemblyLightningTendrilsAction : public MovementAction { public: @@ -139,6 +165,15 @@ class IronAssemblyRuneOfPowerAction : public MovementAction bool isUseful() override; }; +class KologarnNatureResistanceAction : public BossNatureResistanceAction +{ +public: + KologarnNatureResistanceAction(PlayerbotAI* botAI) + : BossNatureResistanceAction(botAI, "kologarn") + { + } +}; + class KologarnMarkDpsTargetAction : public Action { public: @@ -202,6 +237,24 @@ class HodirBitingColdJumpAction : public MovementAction bool isUseful() override; }; +class FreyaFireResistanceAction : public BossFireResistanceAction +{ +public: + FreyaFireResistanceAction(PlayerbotAI* botAI) + : BossFireResistanceAction(botAI, "freya") + { + } +}; + +class FreyaNatureResistanceAction : public BossNatureResistanceAction +{ +public: + FreyaNatureResistanceAction(PlayerbotAI* botAI) + : BossNatureResistanceAction(botAI, "freya") + { + } +}; + class FreyaMoveAwayNatureBombAction : public MovementAction { public: @@ -227,6 +280,24 @@ class FreyaMoveToHealingSporeAction : public MovementAction bool isUseful() override; }; +class ThorimNatureResistanceAction : public BossNatureResistanceAction +{ +public: + ThorimNatureResistanceAction(PlayerbotAI* botAI) + : BossNatureResistanceAction(botAI, "thorim") + { + } +}; + +class ThorimFrostResistanceAction : public BossFrostResistanceAction +{ +public: + ThorimFrostResistanceAction(PlayerbotAI* botAI) + : BossFrostResistanceAction(botAI, "thorim") + { + } +}; + class ThorimUnbalancingStrikeAction : public Action { public: @@ -280,6 +351,15 @@ class ThorimPhase2PositioningAction : public MovementAction bool isUseful() override; }; +class MimironFireResistanceAction : public BossFireResistanceAction +{ +public: + MimironFireResistanceAction(PlayerbotAI* botAI) + : BossFireResistanceAction(botAI, "mimiron") + { + } +}; + class MimironShockBlastAction : public MovementAction { public: @@ -355,6 +435,15 @@ class MimironCheatAction : public Action bool Execute(Event event) override; }; +class VezaxShadowResistanceAction : public BossShadowResistanceAction +{ +public: + VezaxShadowResistanceAction(PlayerbotAI* botAI) + : BossShadowResistanceAction(botAI, "vezax") + { + } +}; + class VezaxCheatAction : public Action { public: @@ -379,6 +468,24 @@ class VezaxMarkOfTheFacelessAction : public MovementAction bool Execute(Event event) override; }; +class SaraShadowResistanceAction : public BossShadowResistanceAction +{ +public: + SaraShadowResistanceAction(PlayerbotAI* botAI) + : BossShadowResistanceAction(botAI, "sara") + { + } +}; + +class YoggSaronShadowResistanceAction : public BossShadowResistanceAction +{ +public: + YoggSaronShadowResistanceAction(PlayerbotAI* botAI) + : BossShadowResistanceAction(botAI, "yogg-saron") + { + } +}; + class YoggSaronOminousCloudCheatAction : public Action { public: diff --git a/src/Ai/Raid/Ulduar/Multiplier/RaidUlduarMultipliers.cpp b/src/Ai/Raid/Ulduar/Multiplier/RaidUlduarMultipliers.cpp index 16df9c9af2..a803d8e54f 100644 --- a/src/Ai/Raid/Ulduar/Multiplier/RaidUlduarMultipliers.cpp +++ b/src/Ai/Raid/Ulduar/Multiplier/RaidUlduarMultipliers.cpp @@ -1,28 +1,6 @@ #include "RaidUlduarMultipliers.h" -#include "ChooseTargetActions.h" -#include "DKActions.h" -#include "DruidActions.h" -#include "DruidBearActions.h" -#include "FollowActions.h" -#include "GenericActions.h" -#include "GenericSpellActions.h" -#include "HunterActions.h" -#include "MageActions.h" -#include "MovementActions.h" -#include "PaladinActions.h" -#include "PriestActions.h" -#include "RaidUlduarActions.h" -#include "ReachTargetActions.h" -#include "RogueActions.h" -#include "ScriptedCreature.h" -#include "ShamanActions.h" -#include "UseMeetingStoneAction.h" -#include "WarriorActions.h" - -float FlameLeviathanMultiplier::GetValue(Action* action) +float FlameLeviathanMultiplier::GetValue(Action&) { - // if (dynamic_cast(action)) - // return 0.0f; return 1.0f; -} \ No newline at end of file +} diff --git a/src/Ai/Raid/Ulduar/Multiplier/RaidUlduarMultipliers.h b/src/Ai/Raid/Ulduar/Multiplier/RaidUlduarMultipliers.h index 736d9483b2..f00e7b343e 100644 --- a/src/Ai/Raid/Ulduar/Multiplier/RaidUlduarMultipliers.h +++ b/src/Ai/Raid/Ulduar/Multiplier/RaidUlduarMultipliers.h @@ -3,7 +3,6 @@ #define _PLAYERRBOT_RAIDULDUARMULTIPLIERS_H_ #include "Multiplier.h" -#include "Ai/Raid/Ulduar/RaidUlduarBossHelper.h" class FlameLeviathanMultiplier : public Multiplier { @@ -11,7 +10,7 @@ class FlameLeviathanMultiplier : public Multiplier FlameLeviathanMultiplier(PlayerbotAI* ai) : Multiplier(ai, "flame leviathan") {} public: - virtual float GetValue(Action* action); + virtual float GetValue(Action& action); }; -#endif \ No newline at end of file +#endif diff --git a/src/Ai/Raid/Ulduar/RaidUlduarActionContext.h b/src/Ai/Raid/Ulduar/RaidUlduarActionContext.h deleted file mode 100644 index 84c1bb8505..0000000000 --- a/src/Ai/Raid/Ulduar/RaidUlduarActionContext.h +++ /dev/null @@ -1,158 +0,0 @@ -// /* -// * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it -// and/or modify it under version 3 of the License, or (at your option), any later version. -// */ - -#ifndef _PLAYERBOT_RAIDULDUARACTIONCONTEXT_H -#define _PLAYERBOT_RAIDULDUARACTIONCONTEXT_H - -#include "Action.h" -#include "NamedObjectContext.h" -#include "RaidUlduarActions.h" -#include "BossAuraActions.h" - -class RaidUlduarActionContext : public NamedObjectContext -{ -public: - RaidUlduarActionContext() - { - creators["flame leviathan vehicle"] = &RaidUlduarActionContext::flame_leviathan_vehicle; - creators["flame leviathan enter vehicle"] = &RaidUlduarActionContext::flame_leviathan_enter_vehicle; - creators["razorscale avoid devouring flames"] = &RaidUlduarActionContext::razorscale_avoid_devouring_flames; - creators["razorscale avoid sentinel"] = &RaidUlduarActionContext::razorscale_avoid_sentinel; - creators["razorscale ignore flying alone"] = &RaidUlduarActionContext::razorscale_ignore_flying_alone; - creators["razorscale avoid whirlwind"] = &RaidUlduarActionContext::razorscale_avoid_whirlwind; - creators["razorscale grounded"] = &RaidUlduarActionContext::razorscale_grounded; - creators["razorscale harpoon action"] = &RaidUlduarActionContext::razorscale_harpoon_action; - creators["razorscale fuse armor action"] = &RaidUlduarActionContext::razorscale_fuse_armor_action; - creators["razorscale fire resistance action"] = &RaidUlduarActionContext::razorscale_fire_resistance_action; - creators["ignis fire resistance action"] = &RaidUlduarActionContext::ignis_fire_resistance_action; - creators["iron assembly lightning tendrils action"] = &RaidUlduarActionContext::iron_assembly_lightning_tendrils_action; - creators["iron assembly overload action"] = &RaidUlduarActionContext::iron_assembly_overload_action; - creators["iron assembly rune of power action"] = &RaidUlduarActionContext::iron_assembly_rune_of_power_action; - creators["kologarn mark dps target action"] = &RaidUlduarActionContext::kologarn_mark_dps_target_action; - creators["kologarn fall from floor action"] = &RaidUlduarActionContext::kologarn_fall_from_floor_action; - creators["kologarn nature resistance action"] = &RaidUlduarActionContext::kologarn_nature_resistance_action; - creators["kologarn rubble slowdown action"] = &RaidUlduarActionContext::kologarn_rubble_slowdown_action; - creators["kologarn eyebeam action"] = &RaidUlduarActionContext::kologarn_eyebeam_action; - creators["kologarn rti target action"] = &RaidUlduarActionContext::kologarn_rti_target_action; - creators["kologarn crunch armor action"] = &RaidUlduarActionContext::kologarn_crunch_armor_action; - creators["auriaya fall from floor action"] = &RaidUlduarActionContext::auriaya_fall_from_floor_action; - creators["hodir move snowpacked icicle"] = &RaidUlduarActionContext::hodir_move_snowpacked_icicle; - creators["hodir biting cold jump"] = &RaidUlduarActionContext::hodir_biting_cold_jump; - creators["hodir frost resistance action"] = &RaidUlduarActionContext::hodir_frost_resistance_action; - creators["freya move away nature bomb"] = &RaidUlduarActionContext::freya_move_away_nature_bomb; - creators["freya fire resistance action"] = &RaidUlduarActionContext::freya_fire_resistance_action; - creators["freya nature resistance action"] = &RaidUlduarActionContext::freya_nature_resistance_action; - creators["freya mark dps target action"] = &RaidUlduarActionContext::freya_mark_dps_target_action; - creators["freya move to healing spore action"] = &RaidUlduarActionContext::freya_move_to_healing_spore_action; - creators["thorim frost resistance action"] = &RaidUlduarActionContext::thorim_frost_resistance_action; - creators["thorim nature resistance action"] = &RaidUlduarActionContext::thorim_nature_resistance_action; - creators["thorim unbalancing strike action"] = &RaidUlduarActionContext::thorim_unbalancing_strike_action; - creators["thorim mark dps target action"] = &RaidUlduarActionContext::thorim_mark_dps_target_action; - creators["thorim arena positioning action"] = &RaidUlduarActionContext::thorim_arena_positioning_action; - creators["thorim gauntlet positioning action"] = &RaidUlduarActionContext::thorim_gauntlet_positioning_action; - creators["thorim phase 2 positioning action"] = &RaidUlduarActionContext::thorim_phase2_positioning_action; - creators["mimiron fire resistance action"] = &RaidUlduarActionContext::mimiron_fire_resistance_action; - creators["mimiron shock blast action"] = &RaidUlduarActionContext::mimiron_shock_blast_action; - creators["mimiron phase 1 positioning action"] = &RaidUlduarActionContext::mimiron_phase_1_positioning_action; - creators["mimiron p3wx2 laser barrage action"] = &RaidUlduarActionContext::mimiron_p3wx2_laser_barrage_action; - creators["mimiron rapid burst action"] = &RaidUlduarActionContext::mimiron_rapid_burst_action; - creators["mimiron aerial command unit action"] = &RaidUlduarActionContext::mimiron_aerial_command_unit_action; - creators["mimiron rocket strike action"] = &RaidUlduarActionContext::mimiron_rocket_strike_action; - creators["mimiron phase 4 mark dps action"] = &RaidUlduarActionContext::mimiron_phase_4_mark_dps_action; - creators["mimiron cheat action"] = &RaidUlduarActionContext::mimiron_cheat_action; - creators["vezax cheat action"] = &RaidUlduarActionContext::vezax_cheat_action; - creators["vezax shadow crash action"] = &RaidUlduarActionContext::vezax_shadow_crash_action; - creators["vezax mark of the faceless action"] = &RaidUlduarActionContext::vezax_mark_of_the_faceless_action; - creators["vezax shadow resistance action"] = &RaidUlduarActionContext::vezax_shadow_resistance_action; - creators["sara shadow resistance action"] = &RaidUlduarActionContext::sara_shadow_resistance_action; - creators["yogg-saron shadow resistance action"] = &RaidUlduarActionContext::yogg_saron_shadow_resistance_action; - creators["yogg-saron ominous cloud cheat action"] = &RaidUlduarActionContext::yogg_saron_ominous_cloud_cheat_action; - creators["yogg-saron guardian positioning action"] = &RaidUlduarActionContext::yogg_saron_guardian_positioning_action; - creators["yogg-saron sanity action"] = &RaidUlduarActionContext::yogg_saron_sanity_action; - creators["yogg-saron death orb action"] = &RaidUlduarActionContext::yogg_saron_death_orb_action; - creators["yogg-saron malady of the mind action"] = &RaidUlduarActionContext::yogg_saron_malady_of_the_mind_action; - creators["yogg-saron mark target action"] = &RaidUlduarActionContext::yogg_saron_mark_target_action; - creators["yogg-saron brain link action"] = &RaidUlduarActionContext::yogg_saron_brain_link_action; - creators["yogg-saron move to enter portal action"] = &RaidUlduarActionContext::yogg_saron_move_to_enter_portal_action; - creators["yogg-saron use portal action"] = &RaidUlduarActionContext::yogg_saron_use_portal_action; - creators["yogg-saron fall from floor action"] = &RaidUlduarActionContext::yogg_saron_fall_from_floor_action; - creators["yogg-saron boss room movement cheat action"] = &RaidUlduarActionContext::yogg_saron_boss_room_movement_cheat_action; - creators["yogg-saron illusion room action"] = &RaidUlduarActionContext::yogg_saron_illusion_room_action; - creators["yogg-saron move to exit portal action"] = &RaidUlduarActionContext::yogg_saron_move_to_exit_portal_action; - creators["yogg-saron lunatic gaze action"] = &RaidUlduarActionContext::yogg_saron_lunatic_gaze_action; - creators["yogg-saron phase 3 positioning action"] = &RaidUlduarActionContext::yogg_saron_phase_3_positioning_action; - } - -private: - static Action* flame_leviathan_vehicle(PlayerbotAI* ai) { return new FlameLeviathanVehicleAction(ai); } - static Action* flame_leviathan_enter_vehicle(PlayerbotAI* ai) { return new FlameLeviathanEnterVehicleAction(ai); } - static Action* razorscale_avoid_devouring_flames(PlayerbotAI* ai) { return new RazorscaleAvoidDevouringFlameAction(ai); } - static Action* razorscale_avoid_sentinel(PlayerbotAI* ai) { return new RazorscaleAvoidSentinelAction(ai); } - static Action* razorscale_ignore_flying_alone(PlayerbotAI* ai) { return new RazorscaleIgnoreBossAction(ai); } - static Action* razorscale_avoid_whirlwind(PlayerbotAI* ai) { return new RazorscaleAvoidWhirlwindAction(ai); } - static Action* razorscale_grounded(PlayerbotAI* ai) { return new RazorscaleGroundedAction(ai); } - static Action* razorscale_harpoon_action(PlayerbotAI* ai) { return new RazorscaleHarpoonAction(ai); } - static Action* razorscale_fuse_armor_action(PlayerbotAI* ai) { return new RazorscaleFuseArmorAction(ai); } - static Action* razorscale_fire_resistance_action(PlayerbotAI* ai) { return new BossFireResistanceAction(ai, "razorscale"); } - static Action* ignis_fire_resistance_action(PlayerbotAI* ai) { return new BossFireResistanceAction(ai, "ignis the furnace master"); } - static Action* iron_assembly_lightning_tendrils_action(PlayerbotAI* ai) { return new IronAssemblyLightningTendrilsAction(ai); } - static Action* iron_assembly_overload_action(PlayerbotAI* ai) { return new IronAssemblyOverloadAction(ai); } - static Action* iron_assembly_rune_of_power_action(PlayerbotAI* ai) { return new IronAssemblyRuneOfPowerAction(ai); } - static Action* kologarn_mark_dps_target_action(PlayerbotAI* ai) { return new KologarnMarkDpsTargetAction(ai); } - static Action* kologarn_fall_from_floor_action(PlayerbotAI* ai) { return new KologarnFallFromFloorAction(ai); } - static Action* kologarn_nature_resistance_action(PlayerbotAI* ai) { return new BossNatureResistanceAction(ai, "kologarn"); } - static Action* kologarn_rubble_slowdown_action(PlayerbotAI* ai) { return new KologarnRubbleSlowdownAction(ai); } - static Action* kologarn_eyebeam_action(PlayerbotAI* ai) { return new KologarnEyebeamAction(ai); } - static Action* kologarn_rti_target_action(PlayerbotAI* ai) { return new KologarnRtiTargetAction(ai); } - static Action* kologarn_crunch_armor_action(PlayerbotAI* ai) { return new KologarnCrunchArmorAction(ai); } - static Action* auriaya_fall_from_floor_action(PlayerbotAI* ai) { return new AuriayaFallFromFloorAction(ai); } - static Action* hodir_move_snowpacked_icicle(PlayerbotAI* ai) { return new HodirMoveSnowpackedIcicleAction(ai); } - static Action* hodir_biting_cold_jump(PlayerbotAI* ai) { return new HodirBitingColdJumpAction(ai); } - static Action* hodir_frost_resistance_action(PlayerbotAI* ai) { return new BossFrostResistanceAction(ai, "hodir"); } - static Action* freya_move_away_nature_bomb(PlayerbotAI* ai) { return new FreyaMoveAwayNatureBombAction(ai); } - static Action* freya_fire_resistance_action(PlayerbotAI* ai) { return new BossFireResistanceAction(ai, "freya"); } - static Action* freya_nature_resistance_action(PlayerbotAI* ai) { return new BossNatureResistanceAction(ai, "freya"); } - static Action* freya_mark_dps_target_action(PlayerbotAI* ai) { return new FreyaMarkDpsTargetAction(ai); } - static Action* freya_move_to_healing_spore_action(PlayerbotAI* ai) { return new FreyaMoveToHealingSporeAction(ai); } - static Action* thorim_frost_resistance_action(PlayerbotAI* ai) { return new BossFrostResistanceAction(ai, "thorim"); } - static Action* thorim_nature_resistance_action(PlayerbotAI* ai) { return new BossNatureResistanceAction(ai, "thorim"); } - static Action* thorim_unbalancing_strike_action(PlayerbotAI* ai) { return new ThorimUnbalancingStrikeAction(ai); } - static Action* thorim_mark_dps_target_action(PlayerbotAI* ai) { return new ThorimMarkDpsTargetAction(ai); } - static Action* thorim_arena_positioning_action(PlayerbotAI* ai) { return new ThorimArenaPositioningAction(ai); } - static Action* thorim_gauntlet_positioning_action(PlayerbotAI* ai) { return new ThorimGauntletPositioningAction(ai); } - static Action* thorim_phase2_positioning_action(PlayerbotAI* ai) { return new ThorimPhase2PositioningAction(ai); } - static Action* mimiron_fire_resistance_action(PlayerbotAI* ai) { return new BossFireResistanceAction(ai, "mimiron"); } - static Action* mimiron_shock_blast_action(PlayerbotAI* ai) { return new MimironShockBlastAction(ai); } - static Action* mimiron_phase_1_positioning_action(PlayerbotAI* ai) { return new MimironPhase1PositioningAction(ai); } - static Action* mimiron_p3wx2_laser_barrage_action(PlayerbotAI* ai) { return new MimironP3Wx2LaserBarrageAction(ai); } - static Action* mimiron_rapid_burst_action(PlayerbotAI* ai) { return new MimironRapidBurstAction(ai); } - static Action* mimiron_aerial_command_unit_action(PlayerbotAI* ai) { return new MimironAerialCommandUnitAction(ai); } - static Action* mimiron_rocket_strike_action(PlayerbotAI* ai) { return new MimironRocketStrikeAction(ai); } - static Action* mimiron_phase_4_mark_dps_action(PlayerbotAI* ai) { return new MimironPhase4MarkDpsAction(ai); } - static Action* mimiron_cheat_action(PlayerbotAI* ai) { return new MimironCheatAction(ai); } - static Action* vezax_cheat_action(PlayerbotAI* ai) { return new VezaxCheatAction(ai); } - static Action* vezax_shadow_crash_action(PlayerbotAI* ai) { return new VezaxShadowCrashAction(ai); } - static Action* vezax_mark_of_the_faceless_action(PlayerbotAI* ai) { return new VezaxMarkOfTheFacelessAction(ai); } - static Action* vezax_shadow_resistance_action(PlayerbotAI* ai) { return new BossShadowResistanceAction(ai, "general vezax"); } - static Action* sara_shadow_resistance_action(PlayerbotAI* ai) { return new BossShadowResistanceAction(ai, "sara"); } - static Action* yogg_saron_shadow_resistance_action(PlayerbotAI* ai) { return new BossShadowResistanceAction(ai, "yogg-saron"); } - static Action* yogg_saron_ominous_cloud_cheat_action(PlayerbotAI* ai) { return new YoggSaronOminousCloudCheatAction(ai); } - static Action* yogg_saron_guardian_positioning_action(PlayerbotAI* ai) { return new YoggSaronGuardianPositioningAction(ai); } - static Action* yogg_saron_sanity_action(PlayerbotAI* ai) { return new YoggSaronSanityAction(ai); } - static Action* yogg_saron_death_orb_action(PlayerbotAI* ai) { return new YoggSaronDeathOrbAction(ai); } - static Action* yogg_saron_malady_of_the_mind_action(PlayerbotAI* ai) { return new YoggSaronMaladyOfTheMindAction(ai); } - static Action* yogg_saron_mark_target_action(PlayerbotAI* ai) { return new YoggSaronMarkTargetAction(ai); } - static Action* yogg_saron_brain_link_action(PlayerbotAI* ai) { return new YoggSaronBrainLinkAction(ai); } - static Action* yogg_saron_move_to_enter_portal_action(PlayerbotAI* ai) { return new YoggSaronMoveToEnterPortalAction(ai); } - static Action* yogg_saron_use_portal_action(PlayerbotAI* ai) { return new YoggSaronUsePortalAction(ai); } - static Action* yogg_saron_fall_from_floor_action(PlayerbotAI* ai) { return new YoggSaronFallFromFloorAction(ai); } - static Action* yogg_saron_boss_room_movement_cheat_action(PlayerbotAI* ai) { return new YoggSaronBossRoomMovementCheatAction(ai); } - static Action* yogg_saron_illusion_room_action(PlayerbotAI* ai) { return new YoggSaronIllusionRoomAction(ai); } - static Action* yogg_saron_move_to_exit_portal_action(PlayerbotAI* ai) { return new YoggSaronMoveToExitPortalAction(ai); } - static Action* yogg_saron_lunatic_gaze_action(PlayerbotAI* ai) { return new YoggSaronLunaticGazeAction(ai); } - static Action* yogg_saron_phase_3_positioning_action(PlayerbotAI* ai) { return new YoggSaronPhase3PositioningAction(ai); } -}; - -#endif diff --git a/src/Ai/Raid/Ulduar/Strategy/RaidUlduarStrategy.cpp b/src/Ai/Raid/Ulduar/Strategy/RaidUlduarStrategy.cpp index 3b9a426cc6..766fda1600 100644 --- a/src/Ai/Raid/Ulduar/Strategy/RaidUlduarStrategy.cpp +++ b/src/Ai/Raid/Ulduar/Strategy/RaidUlduarStrategy.cpp @@ -1,323 +1,671 @@ #include "RaidUlduarStrategy.h" #include "RaidUlduarMultipliers.h" +#include "RaidUlduarActions.h" +#include "CreateNextAction.h" void RaidUlduarStrategy::InitTriggers(std::vector& triggers) { // // Flame Leviathan // - triggers.push_back(new TriggerNode( - "flame leviathan vehicle near", - { NextAction("flame leviathan enter vehicle", ACTION_RAID + 2) })); - - triggers.push_back(new TriggerNode( - "flame leviathan on vehicle", - { NextAction("flame leviathan vehicle", ACTION_RAID + 1) })); + triggers.push_back( + new TriggerNode( + "flame leviathan vehicle near", + { + CreateNextAction(ACTION_RAID + 2.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "flame leviathan on vehicle", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); // // Razorscale // - triggers.push_back(new TriggerNode( - "razorscale avoid devouring flames", - { NextAction("razorscale avoid devouring flames", ACTION_RAID + 1) })); - - triggers.push_back(new TriggerNode( - "razorscale avoid sentinel", - { NextAction("razorscale avoid sentinel", ACTION_RAID + 2) })); - - triggers.push_back(new TriggerNode( - "razorscale flying alone", - { NextAction("razorscale ignore flying alone", ACTION_MOVE + 5) })); - - triggers.push_back(new TriggerNode( - "razorscale avoid whirlwind", - { NextAction("razorscale avoid whirlwind", ACTION_RAID + 3) })); - - triggers.push_back(new TriggerNode( - "razorscale grounded", - { NextAction("razorscale grounded", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "razorscale harpoon trigger", - { NextAction("razorscale harpoon action", ACTION_MOVE) })); - - triggers.push_back(new TriggerNode( - "razorscale fuse armor trigger", - { NextAction("razorscale fuse armor action", ACTION_RAID + 2) })); - - triggers.push_back(new TriggerNode( - "razorscale fire resistance trigger", - { NextAction("razorscale fire resistance action", ACTION_RAID) })); + triggers.push_back( + new TriggerNode( + "razorscale avoid devouring flames", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "razorscale avoid sentinel", + { + CreateNextAction(ACTION_RAID + 2.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "razorscale flying alone", + { + CreateNextAction(ACTION_MOVE + 5.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "razorscale avoid whirlwind", + { + CreateNextAction(ACTION_RAID + 3.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "razorscale grounded", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "razorscale harpoon trigger", + { + CreateNextAction(ACTION_MOVE) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "razorscale fuse armor trigger", + { + CreateNextAction(ACTION_RAID + 2.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "razorscale fire resistance trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); // // Ignis // - triggers.push_back(new TriggerNode( - "ignis fire resistance trigger", - { NextAction("ignis fire resistance action", ACTION_RAID) })); + triggers.push_back( + new TriggerNode( + "ignis fire resistance trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); // // Iron Assembly // - triggers.push_back(new TriggerNode( - "iron assembly lightning tendrils trigger", - { NextAction("iron assembly lightning tendrils action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "iron assembly overload trigger", - { NextAction("iron assembly overload action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "iron assembly rune of power trigger", - { NextAction("iron assembly rune of power action", ACTION_RAID) })); + triggers.push_back( + new TriggerNode( + "iron assembly lightning tendrils trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "iron assembly overload trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "iron assembly rune of power trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); // // Kologarn // - triggers.push_back(new TriggerNode( - "kologarn fall from floor trigger", - { NextAction("kologarn fall from floor action", ACTION_RAID + 1) })); - - triggers.push_back(new TriggerNode( - "kologarn rti target trigger", - { NextAction("kologarn rti target action", ACTION_RAID + 1) })); - - triggers.push_back(new TriggerNode( - "kologarn eyebeam trigger", - { NextAction("kologarn eyebeam action", ACTION_RAID + 1) })); - - triggers.push_back(new TriggerNode( - "kologarn attack dps target trigger", - { NextAction("attack rti target", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "kologarn mark dps target trigger", - { NextAction("kologarn mark dps target action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "kologarn nature resistance trigger", - { NextAction("kologarn nature resistance action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "kologarn rubble slowdown trigger", - { NextAction("kologarn rubble slowdown action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "kologarn crunch armor trigger", - { NextAction("kologarn crunch armor action", ACTION_RAID) })); + triggers.push_back( + new TriggerNode( + "kologarn fall from floor trigger", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "kologarn rti target trigger", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "kologarn eyebeam trigger", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "kologarn attack dps target trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "kologarn mark dps target trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "kologarn nature resistance trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "kologarn rubble slowdown trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "kologarn crunch armor trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); // // Auriaya // - triggers.push_back(new TriggerNode( - "auriaya fall from floor trigger", - { NextAction("auriaya fall from floor action", ACTION_RAID) })); + triggers.push_back( + new TriggerNode( + "auriaya fall from floor trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); // // Hodir // - triggers.push_back(new TriggerNode( - "hodir near snowpacked icicle", - { NextAction("hodir move snowpacked icicle", ACTION_RAID + 1) })); - - triggers.push_back(new TriggerNode( + triggers.push_back( + new TriggerNode( + "hodir near snowpacked icicle", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( "hodir biting cold", - { NextAction("hodir biting cold jump", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "hodir frost resistance trigger", - { NextAction("hodir frost resistance action", ACTION_RAID) })); + { + CreateNextAction(ACTION_RAID) + } + ) +); + + triggers.push_back( + new TriggerNode( + "hodir frost resistance trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); // // Freya // - triggers.push_back(new TriggerNode( - "freya near nature bomb", - { NextAction("freya move away nature bomb", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "freya nature resistance trigger", - { NextAction("freya nature resistance action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "freya fire resistance trigger", - { NextAction("freya fire resistance action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "freya mark dps target trigger", - { NextAction("freya mark dps target action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( + triggers.push_back( + new TriggerNode( + "freya near nature bomb", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "freya nature resistance trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "freya fire resistance trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "freya mark dps target trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( "freya move to healing spore trigger", - { NextAction("freya move to healing spore action", ACTION_RAID) })); + { + CreateNextAction(ACTION_RAID) + } + ) +); // // Thorim // - triggers.push_back(new TriggerNode( - "thorim nature resistance trigger", - { NextAction("thorim nature resistance action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "thorim frost resistance trigger", - { NextAction("thorim frost resistance action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "thorim unbalancing strike trigger", - { NextAction("thorim unbalancing strike action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "thorim mark dps target trigger", - { NextAction("thorim mark dps target action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "thorim gauntlet positioning trigger", - { NextAction("thorim gauntlet positioning action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "thorim arena positioning trigger", - { NextAction("thorim arena positioning action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "thorim fall from floor trigger", - { NextAction("thorim fall from floor action", ACTION_RAID + 1) })); - - triggers.push_back(new TriggerNode( - "thorim phase 2 positioning trigger", - { NextAction("thorim phase 2 positioning action", ACTION_RAID) })); + triggers.push_back( + new TriggerNode( + "thorim nature resistance trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "thorim frost resistance trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "thorim unbalancing strike trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "thorim mark dps target trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "thorim gauntlet positioning trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "thorim arena positioning trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "thorim fall from floor trigger", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "thorim phase 2 positioning trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); // // Mimiron // - triggers.push_back(new TriggerNode( - "mimiron p3wx2 laser barrage trigger", - { NextAction("mimiron p3wx2 laser barrage action", ACTION_RAID + 2) })); - - triggers.push_back(new TriggerNode( - "mimiron shock blast trigger", - { NextAction("mimiron shock blast action", ACTION_RAID + 1) })); - - triggers.push_back(new TriggerNode( - "mimiron fire resistance trigger", - { NextAction("mimiron fire resistance action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "mimiron phase 1 positioning trigger", - { NextAction("mimiron phase 1 positioning action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "mimiron rapid burst trigger", - { NextAction("mimiron rapid burst action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "mimiron aerial command unit trigger", - { NextAction("mimiron aerial command unit action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "mimiron rocket strike trigger", - { NextAction("mimiron rocket strike action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "mimiron phase 4 mark dps trigger", - { NextAction("mimiron phase 4 mark dps action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "mimiron cheat trigger", - { NextAction("mimiron cheat action", ACTION_RAID) })); + triggers.push_back( + new TriggerNode( + "mimiron p3wx2 laser barrage trigger", + { + CreateNextAction(ACTION_RAID + 2.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "mimiron shock blast trigger", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "mimiron fire resistance trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "mimiron phase 1 positioning trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "mimiron rapid burst trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "mimiron aerial command unit trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "mimiron rocket strike trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "mimiron phase 4 mark dps trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "mimiron cheat trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); // // General Vezax // - triggers.push_back(new TriggerNode( - "vezax cheat trigger", - { NextAction("vezax cheat action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "vezax shadow crash trigger", - { NextAction("vezax shadow crash action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "vezax mark of the faceless trigger", - { NextAction("vezax mark of the faceless action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "vezax shadow resistance trigger", - { NextAction("vezax shadow resistance action", ACTION_RAID) })); + triggers.push_back( + new TriggerNode( + "vezax cheat trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "vezax shadow crash trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "vezax mark of the faceless trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "vezax shadow resistance trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); // // Yogg-Saron // - triggers.push_back(new TriggerNode( - "sara shadow resistance trigger", - { NextAction("sara shadow resistance action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "yogg-saron shadow resistance trigger", - { NextAction("yogg-saron shadow resistance action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "yogg-saron ominous cloud cheat trigger", - { NextAction("yogg-saron ominous cloud cheat action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "yogg-saron guardian positioning trigger", - { NextAction("yogg-saron guardian positioning action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "yogg-saron sanity trigger", - { NextAction("yogg-saron sanity action", ACTION_RAID + 1) })); - - triggers.push_back(new TriggerNode( - "yogg-saron death orb trigger", - { NextAction("yogg-saron death orb action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "yogg-saron malady of the mind trigger", - { NextAction("yogg-saron malady of the mind action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "yogg-saron mark target trigger", - { NextAction("yogg-saron mark target action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "yogg-saron brain link trigger", - { NextAction("yogg-saron brain link action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "yogg-saron move to enter portal trigger", - { NextAction("yogg-saron move to enter portal action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "yogg-saron use portal trigger", - { NextAction("yogg-saron use portal action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "yogg-saron fall from floor trigger", - { NextAction("yogg-saron fall from floor action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "yogg-saron boss room movement cheat trigger", - { NextAction("yogg-saron boss room movement cheat action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "yogg-saron illusion room trigger", - { NextAction("yogg-saron illusion room action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "yogg-saron move to exit portal trigger", - { NextAction("yogg-saron move to exit portal action", ACTION_RAID) })); - - triggers.push_back(new TriggerNode( - "yogg-saron lunatic gaze trigger", - { NextAction("yogg-saron lunatic gaze action", ACTION_EMERGENCY) })); - - triggers.push_back(new TriggerNode( - "yogg-saron phase 3 positioning trigger", - { NextAction("yogg-saron phase 3 positioning action", ACTION_RAID) })); + triggers.push_back( + new TriggerNode( + "sara shadow resistance trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "yogg-saron shadow resistance trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "yogg-saron ominous cloud cheat trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "yogg-saron guardian positioning trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "yogg-saron sanity trigger", + { + CreateNextAction(ACTION_RAID + 1) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "yogg-saron death orb trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "yogg-saron malady of the mind trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "yogg-saron mark target trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "yogg-saron brain link trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "yogg-saron move to enter portal trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "yogg-saron use portal trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "yogg-saron fall from floor trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "yogg-saron boss room movement cheat trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "yogg-saron illusion room trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "yogg-saron move to exit portal trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "yogg-saron lunatic gaze trigger", + { + CreateNextAction(ACTION_EMERGENCY) + } + ) + ); + + triggers.push_back( + new TriggerNode( + "yogg-saron phase 3 positioning trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); } void RaidUlduarStrategy::InitMultipliers(std::vector& multipliers) { - multipliers.push_back(new FlameLeviathanMultiplier(botAI)); + multipliers.push_back( + new FlameLeviathanMultiplier(botAI)); } diff --git a/src/Ai/Raid/Ulduar/Trigger/RaidUlduarTriggers.cpp b/src/Ai/Raid/Ulduar/Trigger/RaidUlduarTriggers.cpp index f883917ed0..1d1384920d 100644 --- a/src/Ai/Raid/Ulduar/Trigger/RaidUlduarTriggers.cpp +++ b/src/Ai/Raid/Ulduar/Trigger/RaidUlduarTriggers.cpp @@ -1,19 +1,18 @@ #include "RaidUlduarTriggers.h" -#include "EventMap.h" #include "GameObject.h" #include "Object.h" #include "PlayerbotAI.h" #include "Playerbots.h" #include "RaidUlduarBossHelper.h" -#include "RaidUlduarScripts.h" -#include "ScriptedCreature.h" +#include "RangeTriggers.h" #include "SharedDefines.h" #include "Trigger.h" #include "Vehicle.h" #include #include #include +#include "../../../../../../../src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h" const std::vector availableVehicles = {NPC_VEHICLE_CHOPPER, NPC_SALVAGED_DEMOLISHER, NPC_SALVAGED_DEMOLISHER_TURRET, NPC_SALVAGED_SIEGE_ENGINE, @@ -350,7 +349,6 @@ bool KologarnMarkDpsTargetTrigger::IsActive() if (!target) continue; - uint32 creatureId = target->GetEntry(); if (target->GetEntry() == NPC_RUBBLE && target->IsAlive()) { return true; // Found a rubble to mark @@ -854,8 +852,6 @@ bool ThorimMarkDpsTargetTrigger::IsActive() Unit* runicColossus = AI_VALUE2(Unit*, "find target", "runic colossus"); Unit* ancientRuneGiant = AI_VALUE2(Unit*, "find target", "ancient rune giant"); - Unit* ironHonorGuard = AI_VALUE2(Unit*, "find target", "iron ring guard"); - Unit* ironRingGuard = AI_VALUE2(Unit*, "find target", "iron honor guard"); if (acolyte && acolyte->IsAlive() && (!currentCrossUnit || currentCrossUnit->GetEntry() != acolyte->GetEntry())) return true; @@ -1094,7 +1090,7 @@ bool ThorimPhase2PositioningTrigger::IsActive() Unit* boss = AI_VALUE2(Unit*, "find target", "thorim"); if (!boss || !boss->IsInWorld() || boss->IsDuringRemoveFromWorld()) - return false; + return false; if (!boss->IsAlive()) return false; @@ -1181,8 +1177,6 @@ bool MimironPhase1PositioningTrigger::IsActive() } Unit* leviathanMkII = nullptr; - Unit* vx001 = nullptr; - Unit* aerialCommandUnit = nullptr; GuidVector targets = AI_VALUE(GuidVector, "possible targets"); Unit* target = nullptr; @@ -1621,7 +1615,7 @@ bool VezaxCheatTrigger::IsActive() return false; } - return AI_VALUE2(uint8, "mana", "self target") < sPlayerbotAIConfig->lowMana; + return AI_VALUE2(uint8, "mana", "self target") < sPlayerbotAIConfig.lowMana; } bool VezaxShadowCrashTrigger::IsActive() @@ -1796,7 +1790,7 @@ Unit* YoggSaronTrigger::GetIllusionRoomRtiTarget() return nullptr; } - uint8 rtiIndex = RtiTargetValue::GetRtiIndex(AI_VALUE(std::string, "rti")); + int32_t rtiIndex = RtiTargetValue::GetRtiIndex(AI_VALUE(std::string, "rti")); if (rtiIndex == -1) { return nullptr; // Invalid RTI mark diff --git a/src/Ai/Raid/Ulduar/Trigger/RaidUlduarTriggers.h b/src/Ai/Raid/Ulduar/Trigger/RaidUlduarTriggers.h index 129c3d4dba..f14a69471b 100644 --- a/src/Ai/Raid/Ulduar/Trigger/RaidUlduarTriggers.h +++ b/src/Ai/Raid/Ulduar/Trigger/RaidUlduarTriggers.h @@ -1,12 +1,11 @@ #ifndef _PLAYERBOT_RAIDULDUARTRIGGERS_H #define _PLAYERBOT_RAIDULDUARTRIGGERS_H -#include "EventMap.h" -#include "GenericTriggers.h" -#include "PlayerbotAIConfig.h" -#include "RaidUlduarBossHelper.h" +// #include "GenericTriggers.h" #include "Trigger.h" +#include "Position.h" + enum UlduarIDs { // Iron Assembly @@ -78,7 +77,7 @@ enum UlduarIDs SPELL_P3WX2_LASER_BARRAGE_AURA_1 = 63274, SPELL_P3WX2_LASER_BARRAGE_AURA_2 = 63300, - // General Vezax + // // General Vezax SPELL_MARK_OF_THE_FACELESS = 63276, SPELL_SHADOW_CRASH = 63277, diff --git a/src/Ai/Raid/VaultOfArchavon/Action/RaidVoAActions.cpp b/src/Ai/Raid/VaultOfArchavon/Action/RaidVoAActions.cpp index 05d6328e5c..14bd727784 100644 --- a/src/Ai/Raid/VaultOfArchavon/Action/RaidVoAActions.cpp +++ b/src/Ai/Raid/VaultOfArchavon/Action/RaidVoAActions.cpp @@ -10,7 +10,7 @@ const Position VOA_EMALON_RESTORE_POSITION = Position(-221.8f, -243.8f, 96.8f, 4.7f); -bool EmalonMarkBossAction::Execute(Event event) +bool EmalonMarkBossAction::Execute(Event) { Unit* boss = AI_VALUE2(Unit*, "find target", "emalon the storm watcher"); if (!boss || !boss->IsAlive()) @@ -72,7 +72,7 @@ bool EmalonMarkBossAction::isUseful() return emalonMarkBossTrigger.IsActive(); } -bool EmalonLightingNovaAction::Execute(Event event) +bool EmalonLightingNovaAction::Execute(Event) { const float radius = 25.0f; // 20 yards + 5 yard for safety for 10 man. For 25man there is no maximum range but 25 yards should be ok @@ -96,7 +96,7 @@ bool EmalonLightingNovaAction::isUseful() return emalonLightingNovaTrigger.IsActive(); } -bool EmalonOverchargeAction::Execute(Event event) +bool EmalonOverchargeAction::Execute(Event) { // Check if there is any overcharged minion Unit* minion = nullptr; @@ -173,7 +173,7 @@ bool EmalonOverchargeAction::isUseful() return emalonOverchargeTrigger.IsActive(); } -bool EmalonFallFromFloorAction::Execute(Event event) +bool EmalonFallFromFloorAction::Execute(Event) { return bot->TeleportTo(bot->GetMapId(), VOA_EMALON_RESTORE_POSITION.GetPositionX(), VOA_EMALON_RESTORE_POSITION.GetPositionY(), VOA_EMALON_RESTORE_POSITION.GetPositionZ(), diff --git a/src/Ai/Raid/VaultOfArchavon/RaidVoAActionContext.h b/src/Ai/Raid/VaultOfArchavon/RaidVoAActionContext.h deleted file mode 100644 index b304826b8f..0000000000 --- a/src/Ai/Raid/VaultOfArchavon/RaidVoAActionContext.h +++ /dev/null @@ -1,36 +0,0 @@ -// /* -// * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it -// and/or modify it under version 3 of the License, or (at your option), any later version. -// */ - -#ifndef _PLAYERBOT_RAIDVOAACTIONCONTEXT_H -#define _PLAYERBOT_RAIDVOAACTIONCONTEXT_H - -#include "Action.h" -#include "NamedObjectContext.h" -#include "RaidVoAActions.h" -#include "PlayerbotAI.h" - -class RaidVoAActionContext : public NamedObjectContext -{ -public: - RaidVoAActionContext() - { - creators["emalon mark boss action"] = &RaidVoAActionContext::emalon_mark_boss_action; - creators["emalon lighting nova action"] = &RaidVoAActionContext::emalon_lighting_nova_action; - creators["emalon overcharge action"] = &RaidVoAActionContext::emalon_overcharge_action; - creators["emalon fall from floor action"] = &RaidVoAActionContext::emalon_fall_from_floor_action; - creators["emalon nature resistance action"] = &RaidVoAActionContext::emalon_nature_resistance_action; - creators["koralon fire resistance action"] = &RaidVoAActionContext::koralon_fire_resistance_action; - } - -private: - static Action* emalon_mark_boss_action(PlayerbotAI* ai) { return new EmalonMarkBossAction(ai); } - static Action* emalon_lighting_nova_action(PlayerbotAI* ai) { return new EmalonLightingNovaAction(ai); } - static Action* emalon_overcharge_action(PlayerbotAI* ai) { return new EmalonOverchargeAction(ai); } - static Action* emalon_fall_from_floor_action(PlayerbotAI* ai) { return new EmalonFallFromFloorAction(ai); } - static Action* emalon_nature_resistance_action(PlayerbotAI* ai) { return new BossNatureResistanceAction(ai, "emalon the storm watcher"); } - static Action* koralon_fire_resistance_action(PlayerbotAI* ai) { return new BossFireResistanceAction(ai, "koralon the flame watcher"); } -}; - -#endif diff --git a/src/Ai/Raid/VaultOfArchavon/Strategy/RaidVoAStrategy.cpp b/src/Ai/Raid/VaultOfArchavon/Strategy/RaidVoAStrategy.cpp index db81477a80..27c180597e 100644 --- a/src/Ai/Raid/VaultOfArchavon/Strategy/RaidVoAStrategy.cpp +++ b/src/Ai/Raid/VaultOfArchavon/Strategy/RaidVoAStrategy.cpp @@ -1,39 +1,71 @@ #include "RaidVoAStrategy.h" -#include "Action.h" -#include "Strategy.h" #include "Trigger.h" #include "vector" +#include "CreateNextAction.h" +#include "RaidVoAActions.h" +#include "BossAuraActions.h" + void RaidVoAStrategy::InitTriggers(std::vector& triggers) { // // Emalon the Storm Watcher // - triggers.push_back(new TriggerNode( - "emalon lighting nova trigger", - { NextAction("emalon lighting nova action", ACTION_RAID + 1) })); + triggers.push_back( + new TriggerNode( + "emalon lighting nova trigger", + { + CreateNextAction(ACTION_RAID + 1.0f) + } + ) + ); - triggers.push_back(new TriggerNode( - "emalon mark boss trigger", - { NextAction("emalon mark boss action", ACTION_RAID) })); + triggers.push_back( + new TriggerNode( + "emalon mark boss trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); - triggers.push_back(new TriggerNode( - "emalon overcharge trigger", - { NextAction("emalon overcharge action", ACTION_RAID) })); + triggers.push_back( + new TriggerNode( + "emalon overcharge trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); - triggers.push_back(new TriggerNode( - "emalon fall from floor trigger", - { NextAction("emalon fall from floor action", ACTION_RAID) })); + triggers.push_back( + new TriggerNode( + "emalon fall from floor trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); - triggers.push_back(new TriggerNode( - "emalon nature resistance trigger", - { NextAction("emalon nature resistance action", ACTION_RAID) })); + triggers.push_back( + new TriggerNode( + "emalon nature resistance trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); // // Koralon the Flame Watcher // - triggers.push_back(new TriggerNode( - "koralon fire resistance trigger", - { NextAction("koralon fire resistance action", ACTION_RAID) })); + triggers.push_back( + new TriggerNode( + "koralon fire resistance trigger", + { + CreateNextAction(ACTION_RAID) + } + ) + ); } diff --git a/src/Ai/World/Rpg/Action/NewRpgAction.cpp b/src/Ai/World/Rpg/Action/NewRpgAction.cpp index 01595edf79..391144c33b 100644 --- a/src/Ai/World/Rpg/Action/NewRpgAction.cpp +++ b/src/Ai/World/Rpg/Action/NewRpgAction.cpp @@ -1,12 +1,10 @@ #include "NewRpgAction.h" #include -#include #include #include "BroadcastHelper.h" #include "ChatHelper.h" -#include "DBCStores.h" #include "G3D/Vector2.h" #include "GossipDef.h" #include "IVMapMgr.h" @@ -20,16 +18,11 @@ #include "PathGenerator.h" #include "Player.h" #include "PlayerbotAI.h" -#include "Playerbots.h" -#include "Position.h" #include "QuestDef.h" #include "Random.h" -#include "RandomPlayerbotMgr.h" #include "SharedDefines.h" -#include "StatsWeightCalculator.h" #include "Timer.h" #include "TravelMgr.h" -#include "World.h" bool TellRpgStatusAction::Execute(Event event) { @@ -61,7 +54,7 @@ bool StartRpgDoQuestAction::Execute(Event event) return false; } -bool NewRpgStatusUpdateAction::Execute(Event event) +bool NewRpgStatusUpdateAction::Execute(Event) { NewRpgInfo& info = botAI->rpgInfo; switch (info.status) @@ -150,7 +143,7 @@ bool NewRpgStatusUpdateAction::Execute(Event event) return false; } -bool NewRpgGoGrindAction::Execute(Event event) +bool NewRpgGoGrindAction::Execute(Event) { if (SearchQuestGiverAndAcceptOrReward()) return true; @@ -158,7 +151,7 @@ bool NewRpgGoGrindAction::Execute(Event event) return MoveFarTo(botAI->rpgInfo.go_grind.pos); } -bool NewRpgGoCampAction::Execute(Event event) +bool NewRpgGoCampAction::Execute(Event) { if (SearchQuestGiverAndAcceptOrReward()) return true; @@ -166,7 +159,7 @@ bool NewRpgGoCampAction::Execute(Event event) return MoveFarTo(botAI->rpgInfo.go_camp.pos); } -bool NewRpgWanderRandomAction::Execute(Event event) +bool NewRpgWanderRandomAction::Execute(Event) { if (SearchQuestGiverAndAcceptOrReward()) return true; @@ -174,7 +167,7 @@ bool NewRpgWanderRandomAction::Execute(Event event) return MoveRandomNear(); } -bool NewRpgWanderNpcAction::Execute(Event event) +bool NewRpgWanderNpcAction::Execute(Event) { NewRpgInfo& info = botAI->rpgInfo; if (!info.wander_npc.npcOrGo) @@ -216,14 +209,12 @@ bool NewRpgWanderNpcAction::Execute(Event event) return true; } -bool NewRpgDoQuestAction::Execute(Event event) +bool NewRpgDoQuestAction::Execute(Event) { if (SearchQuestGiverAndAcceptOrReward()) return true; - NewRpgInfo& info = botAI->rpgInfo; uint32 questId = RPG_INFO(quest, questId); - const Quest* quest = RPG_INFO(quest, quest); uint8 questStatus = bot->GetQuestStatus(questId); switch (questStatus) { @@ -408,7 +399,7 @@ bool NewRpgDoQuestAction::DoCompletedQuest() return false; } -bool NewRpgTravelFlightAction::Execute(Event event) +bool NewRpgTravelFlightAction::Execute(Event) { if (bot->IsInFlight()) { @@ -421,7 +412,6 @@ bool NewRpgTravelFlightAction::Execute(Event event) botAI->rpgInfo.ChangeToIdle(); return true; } - const TaxiNodesEntry* entry = sTaxiNodesStore.LookupEntry(botAI->rpgInfo.flight.toNode); if (bot->GetDistance(flightMaster) > INTERACTION_DISTANCE) { return MoveFarTo(flightMaster); diff --git a/src/Ai/World/Rpg/Action/NewRpgBaseAction.cpp b/src/Ai/World/Rpg/Action/NewRpgBaseAction.cpp index 4898d7e36c..5a1ff2dc46 100644 --- a/src/Ai/World/Rpg/Action/NewRpgBaseAction.cpp +++ b/src/Ai/World/Rpg/Action/NewRpgBaseAction.cpp @@ -371,7 +371,6 @@ bool NewRpgBaseAction::IsWithinInteractionDist(Object* questGiver) case TYPEID_GAMEOBJECT: { ObjectGuid guid = questGiver->GetGUID(); - GameobjectTypes type = GAMEOBJECT_TYPE_QUESTGIVER; if (GameObject* go = bot->GetMap()->GetGameObject(guid)) { if (go->IsWithinDistInMap(bot)) @@ -557,7 +556,9 @@ bool NewRpgBaseAction::OrganizeQuestLog() continue; const Quest* quest = sObjectMgr->GetQuestTemplate(questId); - if (quest->GetZoneOrSort() < 0 || (quest->GetZoneOrSort() > 0 && quest->GetZoneOrSort() != bot->GetZoneId())) + const int64_t botZoneId = this->bot->GetZoneId(); + + if (quest->GetZoneOrSort() < 0 || (quest->GetZoneOrSort() > 0 && quest->GetZoneOrSort() != botZoneId)) { LOG_DEBUG("playerbots", "[New RPG] {} drop quest {}", bot->GetName(), questId); WorldPacket packet(CMSG_QUESTLOG_REMOVE_QUEST); @@ -820,7 +821,7 @@ bool NewRpgBaseAction::GetQuestPOIPosAndObjectiveIdx(uint32 questId, std::vector continue; bool inComplete = false; - for (uint32 objective : incompleteObjectiveIdx) + for (int64_t objective : incompleteObjectiveIdx) { if (qPoi.ObjectiveIndex == objective) { @@ -866,7 +867,7 @@ bool NewRpgBaseAction::GetQuestPOIPosAndObjectiveIdx(uint32 questId, std::vector WorldPosition NewRpgBaseAction::SelectRandomGrindPos(Player* bot) { - const std::vector& locs = sRandomPlayerbotMgr->locsPerLevelCache[bot->GetLevel()]; + const std::vector& locs = sRandomPlayerbotMgr.locsPerLevelCache[bot->GetLevel()]; float hiRange = 500.0f; float loRange = 2500.0f; if (bot->GetLevel() < 5) @@ -925,8 +926,8 @@ WorldPosition NewRpgBaseAction::SelectRandomGrindPos(Player* bot) WorldPosition NewRpgBaseAction::SelectRandomCampPos(Player* bot) { const std::vector& locs = IsAlliance(bot->getRace()) - ? sRandomPlayerbotMgr->allianceStarterPerLevelCache[bot->GetLevel()] - : sRandomPlayerbotMgr->hordeStarterPerLevelCache[bot->GetLevel()]; + ? sRandomPlayerbotMgr.allianceStarterPerLevelCache[bot->GetLevel()] + : sRandomPlayerbotMgr.hordeStarterPerLevelCache[bot->GetLevel()]; bool inCity = false; @@ -969,7 +970,7 @@ WorldPosition NewRpgBaseAction::SelectRandomCampPos(Player* bot) bool NewRpgBaseAction::SelectRandomFlightTaxiNode(ObjectGuid& flightMaster, uint32& fromNode, uint32& toNode) { - Creature* nearestFlightMaster = sFlightMasterCache->GetNearestFlightMaster(bot); + Creature* nearestFlightMaster = FlightMasterCache::Instance().GetNearestFlightMaster(bot); if (!nearestFlightMaster || bot->GetDistance(nearestFlightMaster) > 500.0f) return false; @@ -1015,8 +1016,8 @@ bool NewRpgBaseAction::SelectRandomFlightTaxiNode(ObjectGuid& flightMaster, uint capital = zone->flags & AREA_FLAG_CAPITAL; } - auto itr = sRandomPlayerbotMgr->zone2LevelBracket.find(nodeZoneId); - if (!capital && itr == sRandomPlayerbotMgr->zone2LevelBracket.end()) + auto itr = sRandomPlayerbotMgr.zone2LevelBracket.find(nodeZoneId); + if (!capital && itr == sRandomPlayerbotMgr.zone2LevelBracket.end()) continue; if (!capital && (bot->GetLevel() < itr->second.low || bot->GetLevel() > itr->second.high)) @@ -1040,13 +1041,13 @@ bool NewRpgBaseAction::RandomChangeStatus(std::vector candidateSta uint32 probSum = 0; for (NewRpgStatus status : candidateStatus) { - if (sPlayerbotAIConfig->RpgStatusProbWeight[status] == 0) + if (sPlayerbotAIConfig.RpgStatusProbWeight[status] == 0) continue; if (CheckRpgStatusAvailable(status)) { availableStatus.push_back(status); - probSum += sPlayerbotAIConfig->RpgStatusProbWeight[status]; + probSum += sPlayerbotAIConfig.RpgStatusProbWeight[status]; } } // Safety check. Default to "rest" if all RPG weights = 0 @@ -1061,7 +1062,7 @@ bool NewRpgBaseAction::RandomChangeStatus(std::vector candidateSta NewRpgStatus chosenStatus = RPG_STATUS_END; for (NewRpgStatus status : availableStatus) { - accumulate += sPlayerbotAIConfig->RpgStatusProbWeight[status]; + accumulate += sPlayerbotAIConfig.RpgStatusProbWeight[status]; if (accumulate >= rand) { chosenStatus = status; diff --git a/src/Ai/World/Rpg/NewRpgInfo.cpp b/src/Ai/World/Rpg/NewRpgInfo.cpp index ff830464a5..18500331c4 100644 --- a/src/Ai/World/Rpg/NewRpgInfo.cpp +++ b/src/Ai/World/Rpg/NewRpgInfo.cpp @@ -66,7 +66,7 @@ void NewRpgInfo::ChangeToIdle() status = RPG_IDLE; } -bool NewRpgInfo::CanChangeTo(NewRpgStatus status) { return true; } +bool NewRpgInfo::CanChangeTo(NewRpgStatus) { return true; } void NewRpgInfo::Reset() { diff --git a/src/Ai/World/Rpg/Strategy/NewRpgStrategy.cpp b/src/Ai/World/Rpg/Strategy/NewRpgStrategy.cpp index 030ad6b4fc..5b526035ee 100644 --- a/src/Ai/World/Rpg/Strategy/NewRpgStrategy.cpp +++ b/src/Ai/World/Rpg/Strategy/NewRpgStrategy.cpp @@ -5,7 +5,8 @@ #include "NewRpgStrategy.h" -#include "Playerbots.h" +#include "NewRpgAction.h" +#include "CreateNextAction.h" NewRpgStrategy::NewRpgStrategy(PlayerbotAI* botAI) : Strategy(botAI) {} @@ -13,7 +14,7 @@ std::vector NewRpgStrategy::getDefaultActions() { // the releavance should be greater than grind return { - NextAction("new rpg status update", 11.0f) + CreateNextAction(11.0f) }; } @@ -23,7 +24,7 @@ void NewRpgStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "go grind status", { - NextAction("new rpg go grind", 3.0f) + CreateNextAction(3.0f) } ) ); @@ -31,7 +32,7 @@ void NewRpgStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "go camp status", { - NextAction("new rpg go camp", 3.0f) + CreateNextAction(3.0f) } ) ); @@ -39,7 +40,7 @@ void NewRpgStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "wander random status", { - NextAction("new rpg wander random", 3.0f) + CreateNextAction(3.0f) } ) ); @@ -47,7 +48,7 @@ void NewRpgStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "wander npc status", { - NextAction("new rpg wander npc", 3.0f) + CreateNextAction(3.0f) } ) ); @@ -55,7 +56,7 @@ void NewRpgStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "do quest status", { - NextAction("new rpg do quest", 3.0f) + CreateNextAction(3.0f) } ) ); @@ -63,13 +64,13 @@ void NewRpgStrategy::InitTriggers(std::vector& triggers) new TriggerNode( "travel flight status", { - NextAction("new rpg travel flight", 3.0f) + CreateNextAction(3.0f) } ) ); } -void NewRpgStrategy::InitMultipliers(std::vector& multipliers) +void NewRpgStrategy::InitMultipliers(std::vector&) { } diff --git a/src/Ai/World/Rpg/Strategy/NewRpgStrategy.h b/src/Ai/World/Rpg/Strategy/NewRpgStrategy.h index 47b2a550d4..7d28103e74 100644 --- a/src/Ai/World/Rpg/Strategy/NewRpgStrategy.h +++ b/src/Ai/World/Rpg/Strategy/NewRpgStrategy.h @@ -8,7 +8,6 @@ #include "Strategy.h" #include "TravelMgr.h" -#include "NewRpgInfo.h" class PlayerbotAI; diff --git a/src/Bot/Cmd/PlayerbotCommandServer.cpp b/src/Bot/Cmd/PlayerbotCommandServer.cpp index 83931229a0..ac6f5a7431 100644 --- a/src/Bot/Cmd/PlayerbotCommandServer.cpp +++ b/src/Bot/Cmd/PlayerbotCommandServer.cpp @@ -10,10 +10,9 @@ #include #include #include -#include +#include "RandomPlayerbotMgr.h" #include "IoContext.h" -#include "Playerbots.h" using boost::asio::ip::tcp; typedef boost::shared_ptr socket_ptr; @@ -27,7 +26,7 @@ bool ReadLine(socket_ptr sock, std::string* buffer, std::string* line) char buf[1025]; boost::system::error_code error; size_t n = sock->read_some(boost::asio::buffer(buf), error); - if (n == -1 || error == boost::asio::error::eof) + if (error == boost::asio::error::eof) return false; else if (error) throw boost::system::system_error(error); // Some other error. @@ -48,7 +47,7 @@ void session(socket_ptr sock) std::string buffer, request; while (ReadLine(sock, &buffer, &request)) { - std::string const response = sRandomPlayerbotMgr->HandleRemoteCommand(request) + "\n"; + std::string const response = RandomPlayerbotMgr::instance().HandleRemoteCommand(request) + "\n"; boost::asio::write(*sock, boost::asio::buffer(response.c_str(), response.size())); request = ""; } @@ -72,19 +71,19 @@ void server(Acore::Asio::IoContext& io_service, short port) void Run() { - if (!sPlayerbotAIConfig->commandServerPort) + if (!sPlayerbotAIConfig.commandServerPort) { return; } std::ostringstream s; - s << "Starting Playerbots Command Server on port " << sPlayerbotAIConfig->commandServerPort; + s << "Starting Playerbots Command Server on port " << sPlayerbotAIConfig.commandServerPort; LOG_INFO("playerbots", "{}", s.str().c_str()); try { Acore::Asio::IoContext io_service; - server(io_service, sPlayerbotAIConfig->commandServerPort); + server(io_service, sPlayerbotAIConfig.commandServerPort); } catch (std::exception& e) diff --git a/src/Bot/Cmd/PlayerbotCommandServer.h b/src/Bot/Cmd/PlayerbotCommandServer.h index e1b93a338e..eb410c644c 100644 --- a/src/Bot/Cmd/PlayerbotCommandServer.h +++ b/src/Bot/Cmd/PlayerbotCommandServer.h @@ -9,17 +9,24 @@ class PlayerbotCommandServer { public: - PlayerbotCommandServer() {} - virtual ~PlayerbotCommandServer() {} - static PlayerbotCommandServer* instance() + static PlayerbotCommandServer& instance() { static PlayerbotCommandServer instance; - return &instance; + + return instance; } void Start(); -}; -#define sPlayerbotCommandServer PlayerbotCommandServer::instance() +private: + PlayerbotCommandServer() = default; + ~PlayerbotCommandServer() = default; + + PlayerbotCommandServer(const PlayerbotCommandServer&) = delete; + PlayerbotCommandServer& operator=(const PlayerbotCommandServer&) = delete; + + PlayerbotCommandServer(PlayerbotCommandServer&&) = delete; + PlayerbotCommandServer& operator=(PlayerbotCommandServer&&) = delete; +}; #endif diff --git a/src/Bot/Debug/NextAction.h b/src/Bot/Debug/NextAction.h new file mode 100644 index 0000000000..7c0e56da72 --- /dev/null +++ b/src/Bot/Debug/NextAction.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +class Action; +class PlayerbotAI; + +struct NextAction +{ + using Factory = std::unique_ptr(*)(PlayerbotAI* botAI); + + float weight; + Factory factory; +}; diff --git a/src/Bot/Debug/PerfMonitor.cpp b/src/Bot/Debug/PerfMonitor.cpp index c6d134edb9..82eece916f 100644 --- a/src/Bot/Debug/PerfMonitor.cpp +++ b/src/Bot/Debug/PerfMonitor.cpp @@ -10,7 +10,7 @@ PerfMonitorOperation* PerfMonitor::start(PerformanceMetric metric, std::string const name, PerformanceStack* stack) { - if (!sPlayerbotAIConfig->perfMonEnabled) + if (!sPlayerbotAIConfig.perfMonEnabled) return nullptr; std::string stackName = name; diff --git a/src/Bot/Debug/PerfMonitor.h b/src/Bot/Debug/PerfMonitor.h index 0d3eb8aad1..156392ee21 100644 --- a/src/Bot/Debug/PerfMonitor.h +++ b/src/Bot/Debug/PerfMonitor.h @@ -11,17 +11,16 @@ #include #include #include - -#include "Common.h" +#include typedef std::vector PerformanceStack; struct PerformanceData { - uint64 minTime; - uint64 maxTime; - uint64 totalTime; - uint32 count; + uint64_t minTime; + uint64_t maxTime; + uint64_t totalTime; + uint32_t count; std::mutex lock; }; @@ -50,21 +49,28 @@ class PerfMonitorOperation class PerfMonitor { public: - PerfMonitor(){}; - virtual ~PerfMonitor(){}; - static PerfMonitor* instance() + static PerfMonitor& instance() { static PerfMonitor instance; - return &instance; + + return instance; } -public: PerfMonitorOperation* start(PerformanceMetric metric, std::string const name, PerformanceStack* stack = nullptr); void PrintStats(bool perTick = false, bool fullStack = false); void Reset(); private: + PerfMonitor() = default; + virtual ~PerfMonitor() = default; + + PerfMonitor(const PerfMonitor&) = delete; + PerfMonitor& operator=(const PerfMonitor&) = delete; + + PerfMonitor(PerfMonitor&&) = delete; + PerfMonitor& operator=(PerfMonitor&&) = delete; + std::map > data; std::mutex lock; }; diff --git a/src/Bot/Engine/Action/Action.cpp b/src/Bot/Engine/Action/Action.cpp index 464f9dcfd2..d1e06fbf51 100644 --- a/src/Bot/Engine/Action/Action.cpp +++ b/src/Bot/Engine/Action/Action.cpp @@ -5,8 +5,9 @@ #include "Action.h" -#include "Playerbots.h" +#include "AiObjectContext.h" #include "Timer.h" +#include "ActionBasket.h" Value* Action::GetTargetValue() { return context->GetValue(GetTargetName()); } diff --git a/src/Bot/Engine/Action/Action.h b/src/Bot/Engine/Action/Action.h index 2395c5ea87..0e0e920a2a 100644 --- a/src/Bot/Engine/Action/Action.h +++ b/src/Bot/Engine/Action/Action.h @@ -5,46 +5,17 @@ #pragma once +#include + #include "AiObject.h" -#include "Common.h" #include "Event.h" #include "Value.h" +#include "NextAction.h" +#include "ActionFactoryRegistry.h" class PlayerbotAI; class Unit; -class NextAction -{ -public: - NextAction(std::string const name, float relevance = 0.0f) - : relevance(relevance), name(name) {} // name after relevance - whipowill - NextAction(NextAction const& o) : relevance(o.relevance), name(o.name) {} // name after relevance - whipowill - - std::string const getName() { return name; } - float getRelevance() { return relevance; } - - static std::vector merge(std::vector const& what, std::vector const& with) - { - std::vector result = {}; - - for (NextAction const& action : what) - { - result.push_back(action); - } - - for (NextAction const& action : with) - { - result.push_back(action); - } - - return result; - }; - -private: - float relevance; - std::string name; -}; - class Action : public AiNamedObject { public: @@ -55,9 +26,15 @@ class Action : public AiNamedObject Aoe = 2 }; - Action(PlayerbotAI* botAI, std::string const name = "action") - : AiNamedObject(botAI, name), verbose(false) {} // verbose after ainamedobject - whipowill - virtual ~Action(void) {} + Action(PlayerbotAI* botAI, std::string const name = "action") : AiNamedObject(botAI, name), verbose(false) {} + virtual ~Action() {} + + NextAction::Factory getFactoryFromInstance() + { + const std::type_index key(typeid(*this)); + + return ActionFactoryRegistry::GetFactoryByType(key); + } virtual bool Execute([[maybe_unused]] Event event) { return true; } virtual bool isPossible() { return true; } @@ -79,69 +56,3 @@ class Action : public AiNamedObject bool verbose; float relevance = 0; }; - -class ActionNode -{ -public: - ActionNode( - std::string name, - std::vector prerequisites = {}, - std::vector alternatives = {}, - std::vector continuers = {} - ) : - name(std::move(name)), - action(nullptr), - continuers(continuers), - alternatives(alternatives), - prerequisites(prerequisites) - {} - - virtual ~ActionNode() = default; - - Action* getAction() { return action; } - void setAction(Action* action) { this->action = action; } - const std::string getName() { return name; } - - std::vector getContinuers() - { - return NextAction::merge(this->continuers, action->getContinuers()); - } - std::vector getAlternatives() - { - return NextAction::merge(this->alternatives, action->getAlternatives()); - } - std::vector getPrerequisites() - { - return NextAction::merge(this->prerequisites, action->getPrerequisites()); - } - -private: - const std::string name; - Action* action; - std::vector continuers; - std::vector alternatives; - std::vector prerequisites; -}; - -class ActionBasket -{ -public: - ActionBasket(ActionNode* action, float relevance, bool skipPrerequisites, Event event); - - virtual ~ActionBasket(void) {} - - float getRelevance() { return relevance; } - ActionNode* getAction() { return action; } - Event getEvent() { return event; } - bool isSkipPrerequisites() { return skipPrerequisites; } - void AmendRelevance(float k) { relevance *= k; } - void setRelevance(float relevance) { this->relevance = relevance; } - bool isExpired(uint32_t msecs); - -private: - ActionNode* action; - float relevance; - bool skipPrerequisites; - Event event; - uint32_t created; -}; diff --git a/src/Bot/Engine/Action/ActionBasket.h b/src/Bot/Engine/Action/ActionBasket.h new file mode 100644 index 0000000000..555ea53f83 --- /dev/null +++ b/src/Bot/Engine/Action/ActionBasket.h @@ -0,0 +1,29 @@ + +#pragma once + +#include "ActionNode.h" +#include "Action.h" +#include "Event.h" + +class ActionBasket +{ +public: + ActionBasket(ActionNode* action, float relevance, bool skipPrerequisites, Event event); + + virtual ~ActionBasket(void) {} + + float getRelevance() { return relevance; } + ActionNode* getAction() { return action; } + Event getEvent() { return event; } + bool isSkipPrerequisites() { return skipPrerequisites; } + void AmendRelevance(float k) { relevance *= k; } + void setRelevance(float relevance) { this->relevance = relevance; } + bool isExpired(uint32_t msecs); + +private: + ActionNode* action; + float relevance; + bool skipPrerequisites; + Event event; + uint32_t created; +}; diff --git a/src/Bot/Engine/Action/ActionFactoryRegistry.h b/src/Bot/Engine/Action/ActionFactoryRegistry.h new file mode 100644 index 0000000000..e93f928015 --- /dev/null +++ b/src/Bot/Engine/Action/ActionFactoryRegistry.h @@ -0,0 +1,80 @@ +#pragma once + +#include +#include +#include + +class Action; +class PlayerbotAI; + +class ActionFactoryRegistry +{ +public: + using Factory = std::unique_ptr(*)(PlayerbotAI* const botAI); + + static void RegisterByType(const std::type_index key, const Factory factory) + { + std::unordered_map& map = ActionFactoryRegistry::GetTypeMap(); + + map.insert(std::make_pair(key, factory)); + } + + static void RegisterByName(const std::string& name, const Factory factory) + { + std::lock_guard lock(ActionFactoryRegistry::GetMutex()); + + ActionFactoryRegistry::GetNameMap().insert(std::make_pair(name, factory)); + } + + static Factory GetFactoryByType(const std::type_index key) + { + std::lock_guard lock(ActionFactoryRegistry::GetMutex()); + + std::unordered_map& map = ActionFactoryRegistry::GetTypeMap(); + const std::unordered_map::const_iterator it = map.find(key); + + if (it == map.end()) + { + return static_cast(nullptr); + } + + return it->second; + } + + static Factory GetFactoryByName(const std::string_view name) + { + std::lock_guard lock(ActionFactoryRegistry::GetMutex()); + + std::unordered_map& map = ActionFactoryRegistry::GetNameMap(); + const std::unordered_map::const_iterator it = map.find(std::string(name)); + + if (it == map.end()) + { + return static_cast(nullptr); + } + + return it->second; + } + +private: + static std::unordered_map& GetTypeMap() + { + static std::unordered_map map; + + return map; + } + + static std::unordered_map& GetNameMap() + { + static std::unordered_map map; + + return map; + } + + static std::mutex& GetMutex() + { + static std::mutex mtx; + + return mtx; + } +}; diff --git a/src/Bot/Engine/Action/ActionNode.h b/src/Bot/Engine/Action/ActionNode.h new file mode 100644 index 0000000000..f7b70fe5d5 --- /dev/null +++ b/src/Bot/Engine/Action/ActionNode.h @@ -0,0 +1,67 @@ +#pragma once + +#include "Action.h" +#include "NextAction.h" + +class ActionNode +{ +public: + ActionNode( + std::vector prerequisites = {}, + std::vector alternatives = {}, + std::vector continuers = {} + ) : + action(nullptr), + continuers(continuers), + alternatives(alternatives), + prerequisites(prerequisites) + {} + + virtual ~ActionNode() = default; + + Action& getAction() const + { + return *this->action; + } + + void setAction(std::unique_ptr action) + { + this->action = std::move(action); + } + + static std::vector MergeNextActions(std::vector what, std::vector with) + { + std::vector result = {}; + + for (NextAction const& nextAction : what) + { + result.push_back(nextAction); + } + + for (NextAction const& nextAction : with) + { + result.push_back(nextAction); + } + + return result; + } + + std::vector getContinuers() + { + return ActionNode::MergeNextActions(this->continuers, this->action->getContinuers()); + } + std::vector getAlternatives() + { + return ActionNode::MergeNextActions(this->alternatives, this->action->getAlternatives()); + } + std::vector getPrerequisites() + { + return ActionNode::MergeNextActions(this->prerequisites, this->action->getPrerequisites()); + } + +private: + std::unique_ptr action; + std::vector continuers; + std::vector alternatives; + std::vector prerequisites; +}; diff --git a/src/Bot/Engine/AiObjectContext.cpp b/src/Bot/Engine/AiObjectContext.cpp index b6d5f7de0d..fee7a8f237 100644 --- a/src/Bot/Engine/AiObjectContext.cpp +++ b/src/Bot/Engine/AiObjectContext.cpp @@ -5,67 +5,61 @@ #include "AiObjectContext.h" -#include "ActionContext.h" -#include "ChatActionContext.h" +#include "AzjolNerubTriggerContext.h" #include "ChatTriggerContext.h" +#include "CullingOfStratholmeTriggerContext.h" #include "DKAiObjectContext.h" +#include "DrakTharonKeepTriggerContext.h" #include "DruidAiObjectContext.h" +#include "ForgeOfSoulsTriggerContext.h" +#include "GundrakTriggerContext.h" +#include "HallsOfLightningTriggerContext.h" +#include "HallsOfStoneTriggerContext.h" #include "HunterAiObjectContext.h" #include "MageAiObjectContext.h" +#include "NexusTriggerContext.h" +#include "OculusTriggerContext.h" +#include "OldKingdomTriggerContext.h" #include "PaladinAiObjectContext.h" +#include "PitOfSaronTriggerContext.h" #include "Playerbots.h" #include "PriestAiObjectContext.h" -#include "RaidUlduarActionContext.h" #include "RaidUlduarTriggerContext.h" #include "RogueAiObjectContext.h" #include "ShamanAiObjectContext.h" -#include "SharedValueContext.h" #include "StrategyContext.h" +#include "TrialOfTheChampionTriggerContext.h" #include "TriggerContext.h" +#include "UtgardeKeepTriggerContext.h" +#include "UtgardePinnacleTriggerContext.h" #include "ValueContext.h" +#include "VioletHoldTriggerContext.h" #include "WarlockAiObjectContext.h" #include "WarriorAiObjectContext.h" -#include "WorldPacketActionContext.h" #include "WorldPacketTriggerContext.h" #include "Ai/Dungeon/DungeonStrategyContext.h" -#include "Ai/Dungeon/WotlkDungeonActionContext.h" -#include "Ai/Dungeon/WotlkDungeonTriggerContext.h" #include "Ai/Raid/RaidStrategyContext.h" -#include "Ai/Raid/Aq20/RaidAq20ActionContext.h" #include "Ai/Raid/Aq20/RaidAq20TriggerContext.h" -#include "Ai/Raid/MoltenCore/RaidMcActionContext.h" #include "Ai/Raid/MoltenCore/RaidMcTriggerContext.h" -#include "Ai/Raid/BlackwingLair/RaidBwlActionContext.h" #include "Ai/Raid/BlackwingLair/RaidBwlTriggerContext.h" -#include "Ai/Raid/Karazhan/RaidKarazhanActionContext.h" #include "Ai/Raid/Karazhan/RaidKarazhanTriggerContext.h" -#include "Ai/Raid/Magtheridon/RaidMagtheridonActionContext.h" #include "Ai/Raid/Magtheridon/RaidMagtheridonTriggerContext.h" -#include "Ai/Raid/GruulsLair/RaidGruulsLairActionContext.h" #include "Ai/Raid/GruulsLair/RaidGruulsLairTriggerContext.h" -#include "Ai/Raid/EyeOfEternity/RaidEoEActionContext.h" #include "Ai/Raid/EyeOfEternity/RaidEoETriggerContext.h" -#include "Ai/Raid/VaultOfArchavon/RaidVoAActionContext.h" #include "Ai/Raid/VaultOfArchavon/RaidVoATriggerContext.h" -#include "Ai/Raid/ObsidianSanctum/RaidOsActionContext.h" #include "Ai/Raid/ObsidianSanctum/RaidOsTriggerContext.h" -#include "Ai/Raid/Onyxia/RaidOnyxiaActionContext.h" #include "Ai/Raid/Onyxia/RaidOnyxiaTriggerContext.h" -#include "Ai/Raid/Icecrown/RaidIccActionContext.h" #include "Ai/Raid/Icecrown/RaidIccTriggerContext.h" SharedNamedObjectContextList AiObjectContext::sharedStrategyContexts; -SharedNamedObjectContextList AiObjectContext::sharedActionContexts; SharedNamedObjectContextList AiObjectContext::sharedTriggerContexts; SharedNamedObjectContextList AiObjectContext::sharedValueContexts; AiObjectContext::AiObjectContext(PlayerbotAI* botAI, SharedNamedObjectContextList& sharedStrategyContext, - SharedNamedObjectContextList& sharedActionContext, SharedNamedObjectContextList& sharedTriggerContext, SharedNamedObjectContextList& sharedValueContext) : PlayerbotAIAware(botAI), strategyContexts(sharedStrategyContext), - actionContexts(sharedActionContext), triggerContexts(sharedTriggerContext), valueContexts(sharedValueContext) { @@ -89,7 +83,6 @@ void AiObjectContext::BuildAllSharedContexts() void AiObjectContext::BuildSharedContexts() { BuildSharedStrategyContexts(sharedStrategyContexts); - BuildSharedActionContexts(sharedActionContexts); BuildSharedTriggerContexts(sharedTriggerContexts); BuildSharedValueContexts(sharedValueContexts); } @@ -104,40 +97,6 @@ void AiObjectContext::BuildSharedStrategyContexts(SharedNamedObjectContextList& actionContexts) -{ - actionContexts.Add(new ActionContext()); - actionContexts.Add(new ChatActionContext()); - actionContexts.Add(new WorldPacketActionContext()); - actionContexts.Add(new RaidAq20ActionContext()); - actionContexts.Add(new RaidMcActionContext()); - actionContexts.Add(new RaidBwlActionContext()); - actionContexts.Add(new RaidKarazhanActionContext()); - actionContexts.Add(new RaidMagtheridonActionContext()); - actionContexts.Add(new RaidGruulsLairActionContext()); - actionContexts.Add(new RaidOsActionContext()); - actionContexts.Add(new RaidEoEActionContext()); - actionContexts.Add(new RaidVoAActionContext()); - actionContexts.Add(new RaidUlduarActionContext()); - actionContexts.Add(new RaidOnyxiaActionContext()); - actionContexts.Add(new RaidIccActionContext()); - actionContexts.Add(new WotlkDungeonUKActionContext()); - actionContexts.Add(new WotlkDungeonNexActionContext()); - actionContexts.Add(new WotlkDungeonANActionContext()); - actionContexts.Add(new WotlkDungeonOKActionContext()); - actionContexts.Add(new WotlkDungeonDTKActionContext()); - actionContexts.Add(new WotlkDungeonVHActionContext()); - actionContexts.Add(new WotlkDungeonGDActionContext()); - actionContexts.Add(new WotlkDungeonHoSActionContext()); - actionContexts.Add(new WotlkDungeonHoLActionContext()); - actionContexts.Add(new WotlkDungeonOccActionContext()); - actionContexts.Add(new WotlkDungeonUPActionContext()); - actionContexts.Add(new WotlkDungeonCoSActionContext()); - actionContexts.Add(new WotlkDungeonFoSActionContext()); - actionContexts.Add(new WotlkDungeonPoSActionContext()); - actionContexts.Add(new WotlkDungeonToCActionContext()); -} - void AiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts) { triggerContexts.Add(new TriggerContext()); @@ -235,8 +194,6 @@ std::set AiObjectContext::GetSiblingStrategy(std::string const name Trigger* AiObjectContext::GetTrigger(std::string const name) { return triggerContexts.GetContextObject(name, botAI); } -Action* AiObjectContext::GetAction(std::string const name) { return actionContexts.GetContextObject(name, botAI); } - UntypedValue* AiObjectContext::GetUntypedValue(std::string const name) { return valueContexts.GetContextObject(name, botAI); @@ -246,8 +203,6 @@ std::set AiObjectContext::GetValues() { return valueContexts.GetCre std::set AiObjectContext::GetSupportedStrategies() { return strategyContexts.supports(); } -std::set AiObjectContext::GetSupportedActions() { return actionContexts.supports(); } - std::string const AiObjectContext::FormatValues() { std::ostringstream out; diff --git a/src/Bot/Engine/AiObjectContext.h b/src/Bot/Engine/AiObjectContext.h index 3ffd1850ff..9950428adb 100644 --- a/src/Bot/Engine/AiObjectContext.h +++ b/src/Bot/Engine/AiObjectContext.h @@ -9,15 +9,15 @@ #include #include -#include "Common.h" -#include "DynamicObject.h" #include "NamedObjectContext.h" #include "PlayerbotAIAware.h" -#include "Strategy.h" #include "Trigger.h" #include "Value.h" class PlayerbotAI; +class Strategy; + +class Strategy; typedef Strategy* (*StrategyCreator)(PlayerbotAI* botAI); typedef Action* (*ActionCreator)(PlayerbotAI* botAI); @@ -30,7 +30,6 @@ class AiObjectContext : public PlayerbotAIAware static BoolCalculatedValue* custom_glyphs(PlayerbotAI* ai); // Added for cutom glyphs AiObjectContext(PlayerbotAI* botAI, SharedNamedObjectContextList& sharedStrategyContext = sharedStrategyContexts, - SharedNamedObjectContextList& sharedActionContext = sharedActionContexts, SharedNamedObjectContextList& sharedTriggerContext = sharedTriggerContexts, SharedNamedObjectContextList& sharedValueContext = sharedValueContexts); virtual ~AiObjectContext() {} @@ -38,7 +37,6 @@ class AiObjectContext : public PlayerbotAIAware virtual Strategy* GetStrategy(std::string const name); virtual std::set GetSiblingStrategy(std::string const name); virtual Trigger* GetTrigger(std::string const name); - virtual Action* GetAction(std::string const name); virtual UntypedValue* GetUntypedValue(std::string const name); template @@ -63,7 +61,6 @@ class AiObjectContext : public PlayerbotAIAware std::set GetValues(); std::set GetSupportedStrategies(); - std::set GetSupportedActions(); std::string const FormatValues(); std::vector Save(); @@ -75,19 +72,16 @@ class AiObjectContext : public PlayerbotAIAware static void BuildSharedContexts(); static void BuildSharedStrategyContexts(SharedNamedObjectContextList& strategyContexts); - static void BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts); static void BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts); static void BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts); protected: NamedObjectContextList strategyContexts; - NamedObjectContextList actionContexts; NamedObjectContextList triggerContexts; NamedObjectContextList valueContexts; private: static SharedNamedObjectContextList sharedStrategyContexts; - static SharedNamedObjectContextList sharedActionContexts; static SharedNamedObjectContextList sharedTriggerContexts; static SharedNamedObjectContextList sharedValueContexts; }; diff --git a/src/Bot/Engine/Engine.cpp b/src/Bot/Engine/Engine.cpp index 6ed61a1a4b..2759485a6b 100644 --- a/src/Bot/Engine/Engine.cpp +++ b/src/Bot/Engine/Engine.cpp @@ -13,48 +13,54 @@ #include "Strategy.h" #include "Timer.h" +#include "ActionNode.h" +#include "ActionBasket.h" +#include "NextAction.h" + Engine::Engine(PlayerbotAI* botAI, AiObjectContext* factory) : PlayerbotAIAware(botAI), aiObjectContext(factory) { lastRelevance = 0.0f; testMode = false; } -bool ActionExecutionListeners::Before(Action* action, Event event) +bool ActionExecutionListeners::before(Action& action, Event event) { bool result = true; - for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) + + for (std::list::iterator i = this->listeners.begin(); i != this->listeners.end(); i++) { - result &= (*i)->Before(action, event); + result &= (*i)->before(action, event); } return result; } -void ActionExecutionListeners::After(Action* action, bool executed, Event event) +void ActionExecutionListeners::after(Action& action, bool executed, Event event) { for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { - (*i)->After(action, executed, event); + (*i)->after(action, executed, event); } } -bool ActionExecutionListeners::OverrideResult(Action* action, bool executed, Event event) +bool ActionExecutionListeners::overrideResult(Action& action, bool executed, Event event) { bool result = executed; for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { - result = (*i)->OverrideResult(action, result, event); + result = (*i)->overrideResult(action, result, event); } return result; } -bool ActionExecutionListeners::AllowExecution(Action* action, Event event) +bool ActionExecutionListeners::allowExecution(Action& action, Event event) { bool result = true; + for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { - result &= (*i)->AllowExecution(action, event); + result &= (*i)->allowExecution(action, event); } return result; @@ -138,11 +144,11 @@ void Engine::Init() } } -bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal) +bool Engine::doNextAction(Unit*, uint32, bool minimal) { LogAction("--- AI Tick ---"); - if (sPlayerbotAIConfig->logValuesPerTick) + if (sPlayerbotAIConfig.logValuesPerTick) LogValues(); bool actionExecuted = false; @@ -154,11 +160,12 @@ bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal) PushDefaultActions(); uint32 iterations = 0; - uint32 iterationsPerTick = queue.Size() * (minimal ? 2 : sPlayerbotAIConfig->iterationsPerTick); + uint32 iterationsPerTick = this->queue.Size() * (minimal ? 2 : sPlayerbotAIConfig.iterationsPerTick); while (++iterations <= iterationsPerTick) { - basket = queue.Peek(); + basket = this->queue.Peek(); + if (!basket) break; @@ -169,72 +176,74 @@ bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal) continue; Event event = basket->getEvent(); - ActionNode* actionNode = queue.Pop(); // NOTE: Pop() deletes basket - Action* action = InitializeAction(actionNode); + ActionNode* actionNode = this->queue.Pop(); // NOTE: Pop() deletes basket + Action& action = actionNode->getAction(); - if (!action) + if (!action.isUseful()) { - LogAction("A:%s - UNKNOWN", actionNode->getName().c_str()); + LogAction("A:%s - USELESS", action.getName().c_str()); + lastRelevance = relevance; + delete actionNode; // Always delete after processing the action node + + continue; } - else if (action->isUseful()) + + // Apply multipliers early to avoid unnecessary iterations + for (Multiplier* multiplier : multipliers) { - // Apply multipliers early to avoid unnecessary iterations - for (Multiplier* multiplier : multipliers) - { - relevance *= multiplier->GetValue(action); - action->setRelevance(relevance); - - if (relevance <= 0) - { - LogAction("Multiplier %s made action %s useless", multiplier->getName().c_str(), action->getName().c_str()); - break; - } - } + relevance *= multiplier->GetValue(action); + action.setRelevance(relevance); - if (action->isPossible() && relevance > 0) + if (relevance <= 0) { - if (!skipPrerequisites) - { - LogAction("A:%s - PREREQ", action->getName().c_str()); - - if (MultiplyAndPush(actionNode->getPrerequisites(), relevance + 0.002f, false, event, "prereq")) - { - PushAgain(actionNode, relevance + 0.001f, event); - continue; - } - } - - PerfMonitorOperation* pmo = sPerfMonitor->start(PERF_MON_ACTION, action->getName(), &aiObjectContext->performanceStack); - actionExecuted = ListenAndExecute(action, event); - if (pmo) - pmo->finish(); - - if (actionExecuted) - { - LogAction("A:%s - OK", action->getName().c_str()); - MultiplyAndPush(actionNode->getContinuers(), relevance, false, event, "cont"); - lastRelevance = relevance; - delete actionNode; // Safe memory management - break; - } - else - { - LogAction("A:%s - FAILED", action->getName().c_str()); - MultiplyAndPush(actionNode->getAlternatives(), relevance + 0.003f, false, event, "alt"); - } + LogAction("Multiplier %s made action %s useless", multiplier->getName().c_str(), action.getName().c_str()); + break; } - else + } + + if (relevance <= 0.0f || !action.isPossible()) + { + this->multiplyAndPush(actionNode->getAlternatives(), relevance + 0.003f, false, event); + + delete actionNode; + + continue; + } + + if (!skipPrerequisites) + { + LogAction("A:%s - PREREQ", action.getName().c_str()); + + if (multiplyAndPush(actionNode->getPrerequisites(), relevance + 0.002f, false, event)) { - LogAction("A:%s - IMPOSSIBLE", action->getName().c_str()); - MultiplyAndPush(actionNode->getAlternatives(), relevance + 0.003f, false, event, "alt"); + PushAgain(actionNode, relevance + 0.001f, event); + continue; } } - else + + PerfMonitorOperation* pmo = sPerfMonitor.start(PERF_MON_ACTION, action.getName(), &aiObjectContext->performanceStack); + + actionExecuted = this->listenAndExecute(action, event); + + if (pmo) + pmo->finish(); + + if (actionExecuted) { - LogAction("A:%s - USELESS", action->getName().c_str()); + LogAction("A:%s - OK", action.getName().c_str()); + + this->multiplyAndPush(actionNode->getContinuers(), relevance, false, event); + lastRelevance = relevance; + + delete actionNode; // Safe memory management + + break; } + // LogAction("A:%s - FAILED", action->getName().c_str()); + this->multiplyAndPush(actionNode->getAlternatives(), relevance + 0.003f, false, event); + delete actionNode; // Always delete after processing the action node } @@ -246,7 +255,7 @@ bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal) if (!actionExecuted) LogAction("no actions executed"); - queue.RemoveExpired(); + this->queue.RemoveExpired(); return actionExecuted; } @@ -254,91 +263,83 @@ bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal) ActionNode* Engine::CreateActionNode(std::string const name) { ActionNode* node = actionNodeFactories.GetContextObject(name, botAI); - if (node) + + if (node != nullptr) + { return node; + } - return new ActionNode(name, - /*P*/ {}, - /*A*/ {}, - /*C*/ {}); + return new ActionNode( + /*P*/ {}, + /*A*/ {}, + /*C*/ {} + ); } -bool Engine::MultiplyAndPush( +bool Engine::multiplyAndPush( std::vector actions, float forceRelevance, bool skipPrerequisites, - Event event, - char const* pushType + Event event ) { bool pushed = false; - for (NextAction nextAction : actions) + for (const NextAction& nextAction : actions) { - ActionNode* action = this->CreateActionNode(nextAction.getName()); - - this->InitializeAction(action); - - float k = nextAction.getRelevance(); + float k = nextAction.weight; if (forceRelevance > 0.0f) { k = forceRelevance; } - if (k > 0) + if (k <= 0.0f) { - this->LogAction("PUSH:%s - %f (%s)", action->getName().c_str(), k, pushType); - queue.Push(new ActionBasket(action, k, skipPrerequisites, event)); - pushed = true; - continue; } - delete action; + std::unique_ptr action = nextAction.factory(this->botAI); + ActionNode* actionNode = this->CreateActionNode(action->getName()); + + actionNode->setAction(std::move(action)); + this->queue.Push(new ActionBasket(actionNode, k, skipPrerequisites, event)); + pushed = true; } return pushed; } -ActionResult Engine::ExecuteAction(std::string const name, Event event, std::string const qualifier) +ActionResult Engine::ExecuteAction(NextAction::Factory actionFactory, Event event) { bool result = false; - ActionNode* actionNode = CreateActionNode(name); - if (!actionNode) - return ACTION_RESULT_UNKNOWN; + std::unique_ptr actionToExecute = actionFactory(this->botAI); + ActionNode* actionNode = this->CreateActionNode(actionToExecute->getName()); - Action* action = InitializeAction(actionNode); - if (!action) - { - delete actionNode; - return ACTION_RESULT_UNKNOWN; - } + actionNode->setAction(std::move(actionToExecute)); - if (!qualifier.empty()) - { - if (Qualified* q = dynamic_cast(action)) - q->Qualify(qualifier); - } + Action& action = actionNode->getAction(); - if (!action->isPossible()) + if (!action.isPossible()) { delete actionNode; + return ACTION_RESULT_IMPOSSIBLE; } - if (!action->isUseful()) + if (!action.isUseful()) { delete actionNode; + return ACTION_RESULT_USELESS; } - action->MakeVerbose(); + action.MakeVerbose(); - result = ListenAndExecute(action, event); - MultiplyAndPush(action->getContinuers(), 0.0f, false, event, "default"); + result = this->listenAndExecute(action, event); + this->multiplyAndPush(action.getContinuers(), 0.0f, false, event); delete actionNode; @@ -457,7 +458,7 @@ void Engine::ProcessTriggers(bool minimal) continue; PerfMonitorOperation* pmo = - sPerfMonitor->start(PERF_MON_TRIGGER, trigger->getName(), &aiObjectContext->performanceStack); + sPerfMonitor.start(PERF_MON_TRIGGER, trigger->getName(), &aiObjectContext->performanceStack); Event event = trigger->Check(); if (pmo) pmo->finish(); @@ -478,7 +479,8 @@ void Engine::ProcessTriggers(bool minimal) continue; Event event = fires[trigger]; - MultiplyAndPush(node->getHandlers(), 0.0f, false, event, "trigger"); + + this->multiplyAndPush(node->getHandlers(), 0.0f, false, event); } for (std::vector::iterator i = triggers.begin(); i != triggers.end(); i++) @@ -494,7 +496,7 @@ void Engine::PushDefaultActions() { Strategy* strategy = i->second; Event emptyEvent; - MultiplyAndPush(strategy->getDefaultActions(), 0.0f, false, emptyEvent, "default"); + this->multiplyAndPush(strategy->getDefaultActions(), 0.0f, false, emptyEvent); } } @@ -527,9 +529,14 @@ std::vector Engine::GetStrategies() void Engine::PushAgain(ActionNode* actionNode, float relevance, Event event) { - std::vector nextAction = { NextAction(actionNode->getName(), relevance) }; + NextAction::Factory factory = actionNode->getAction().getFactoryFromInstance(); - MultiplyAndPush(nextAction, relevance, true, event, "again"); + NextAction nextAction = NextAction{ + .weight = relevance, + .factory = factory + }; + + this->multiplyAndPush({ nextAction }, relevance, true, event); delete actionNode; } @@ -544,46 +551,27 @@ bool Engine::ContainsStrategy(StrategyType type) return false; } -Action* Engine::InitializeAction(ActionNode* actionNode) -{ - Action* action = actionNode->getAction(); - if (!action) - { - action = aiObjectContext->GetAction(actionNode->getName()); - actionNode->setAction(action); - } - - return action; -} - -bool Engine::ListenAndExecute(Action* action, Event event) +bool Engine::listenAndExecute(Action& action, Event event) { bool actionExecuted = false; - if (action == nullptr) - { - LOG_ERROR("playerbots", "Action is nullptr"); - - return actionExecuted; - } - - if (actionExecutionListeners.Before(action, event)) + if (this->actionExecutionListeners.before(action, event)) { - actionExecuted = actionExecutionListeners.AllowExecution(action, event) ? action->Execute(event) : true; + actionExecuted = this->actionExecutionListeners.allowExecution(action, event) ? action.Execute(event) : true; } if (botAI->HasStrategy("debug", BOT_STATE_NON_COMBAT)) { std::ostringstream out; out << "do: "; - out << action->getName(); + out << action.getName(); if (actionExecuted) out << " 1 ("; else out << " 0 ("; - out << action->getRelevance() << ")"; + out << action.getRelevance() << ")"; if (!event.GetSource().empty()) out << " [" << event.GetSource() << "]"; @@ -591,15 +579,15 @@ bool Engine::ListenAndExecute(Action* action, Event event) botAI->TellMasterNoFacing(out); } - actionExecuted = actionExecutionListeners.OverrideResult(action, actionExecuted, event); - actionExecutionListeners.After(action, actionExecuted, event); + actionExecuted = actionExecutionListeners.overrideResult(action, actionExecuted, event); + actionExecutionListeners.after(action, actionExecuted, event); return actionExecuted; } void Engine::LogAction(char const* format, ...) { Player* bot = botAI->GetBot(); - if (sPlayerbotAIConfig->logInGroupOnly && (!bot->GetGroup() || !botAI->HasRealPlayerMaster()) && !testMode) + if (sPlayerbotAIConfig.logInGroupOnly && (!bot->GetGroup() || !botAI->HasRealPlayerMaster()) && !testMode) return; char buf[1024]; @@ -661,7 +649,7 @@ void Engine::LogValues() return; Player* bot = botAI->GetBot(); - if (sPlayerbotAIConfig->logInGroupOnly && (!bot->GetGroup() || !botAI->HasRealPlayerMaster())) + if (sPlayerbotAIConfig.logInGroupOnly && (!bot->GetGroup() || !botAI->HasRealPlayerMaster())) return; std::string const text = botAI->GetAiObjectContext()->FormatValues(); diff --git a/src/Bot/Engine/Engine.h b/src/Bot/Engine/Engine.h index 8a7c34189d..bc78535df8 100644 --- a/src/Bot/Engine/Engine.h +++ b/src/Bot/Engine/Engine.h @@ -14,6 +14,8 @@ #include "Strategy.h" #include "Trigger.h" +#include "NextAction.h" + class Action; class ActionNode; class AiObjectContext; @@ -35,10 +37,10 @@ class ActionExecutionListener public: virtual ~ActionExecutionListener(){}; - virtual bool Before(Action* action, Event event) = 0; - virtual bool AllowExecution(Action* action, Event event) = 0; - virtual void After(Action* action, bool executed, Event event) = 0; - virtual bool OverrideResult(Action* action, bool executed, Event event) = 0; + virtual bool before(Action& action, Event event) = 0; + virtual bool allowExecution(Action& action, Event event) = 0; + virtual void after(Action& action, bool executed, Event event) = 0; + virtual bool overrideResult(Action& action, bool executed, Event event) = 0; }; class ActionExecutionListeners : public ActionExecutionListener @@ -46,10 +48,10 @@ class ActionExecutionListeners : public ActionExecutionListener public: virtual ~ActionExecutionListeners(); - bool Before(Action* action, Event event) override; - bool AllowExecution(Action* action, Event event) override; - void After(Action* action, bool executed, Event event) override; - bool OverrideResult(Action* action, bool executed, Event event) override; + bool before(Action& action, Event event) override; + bool allowExecution(Action& action, Event event) override; + void after(Action& action, bool executed, Event event) override; + bool overrideResult(Action& action, bool executed, Event event) override; void Add(ActionExecutionListener* listener) { listeners.push_back(listener); } @@ -78,8 +80,8 @@ class Engine : public PlayerbotAIAware void ChangeStrategy(std::string const names); std::string const GetLastAction() { return lastAction; } - virtual bool DoNextAction(Unit*, uint32 depth = 0, bool minimal = false); - ActionResult ExecuteAction(std::string const name, Event event = Event(), std::string const qualifier = ""); + virtual bool doNextAction(Unit*, uint32 depth = 0, bool minimal = false); + ActionResult ExecuteAction(NextAction::Factory actionFactory, Event event = Event()); void AddActionExecutionListener(ActionExecutionListener* listener) { actionExecutionListeners.Add(listener); } @@ -90,15 +92,13 @@ class Engine : public PlayerbotAIAware bool testMode; private: - bool MultiplyAndPush(std::vector actions, float forceRelevance, bool skipPrerequisites, Event event, - const char* pushType); + ActionNode* CreateActionNode(std::string const name); + bool multiplyAndPush(std::vector actions, float forceRelevance, bool skipPrerequisites, Event event); void Reset(); void ProcessTriggers(bool minimal); void PushDefaultActions(); void PushAgain(ActionNode* actionNode, float relevance, Event event); - ActionNode* CreateActionNode(std::string const name); - Action* InitializeAction(ActionNode* actionNode); - bool ListenAndExecute(Action* action, Event event); + bool listenAndExecute(Action& action, Event event); void LogAction(char const* format, ...); void LogValues(); diff --git a/src/Bot/Engine/ExternalEventHelper.cpp b/src/Bot/Engine/ExternalEventHelper.cpp index 2f42eee920..4f354764b8 100644 --- a/src/Bot/Engine/ExternalEventHelper.cpp +++ b/src/Bot/Engine/ExternalEventHelper.cpp @@ -58,8 +58,11 @@ void ExternalEventHelper::HandlePacket(std::map& handlers, bool ExternalEventHelper::HandleCommand(std::string const name, std::string const param, Player* owner) { Trigger* trigger = aiObjectContext->GetTrigger(name); + if (!trigger) + { return false; + } trigger->ExternalEvent(param, owner); diff --git a/src/Bot/Engine/Multiplier.h b/src/Bot/Engine/Multiplier.h index 5a8bba68b3..a9aae21197 100644 --- a/src/Bot/Engine/Multiplier.h +++ b/src/Bot/Engine/Multiplier.h @@ -17,7 +17,7 @@ class Multiplier : public AiNamedObject Multiplier(PlayerbotAI* botAI, std::string const name) : AiNamedObject(botAI, name) {} virtual ~Multiplier() {} - virtual float GetValue([[maybe_unused]] Action* action) { return 1.0f; } + virtual float GetValue([[maybe_unused]] Action& action) { return 1.0f; } }; #endif diff --git a/src/Bot/Engine/NamedObjectContext.h b/src/Bot/Engine/NamedObjectContext.h index b60232a5c3..7319a1eca4 100644 --- a/src/Bot/Engine/NamedObjectContext.h +++ b/src/Bot/Engine/NamedObjectContext.h @@ -6,14 +6,12 @@ #ifndef _PLAYERBOT_NAMEDOBJECTCONEXT_H #define _PLAYERBOT_NAMEDOBJECTCONEXT_H -#include #include +#include #include -#include #include #include - -#include "Common.h" +#include class PlayerbotAI; @@ -22,9 +20,9 @@ class Qualified public: Qualified(){}; Qualified(std::string const qualifier) : qualifier(qualifier) {} - Qualified(int32 qualifier1) { Qualify(qualifier1); } + Qualified(int32_t qualifier1) { Qualify(qualifier1); } - virtual void Qualify(int qual); + virtual void Qualify(int32_t qual); virtual void Qualify(std::string const qual) { qualifier = qual; } @@ -33,7 +31,7 @@ class Qualified static std::string const MultiQualify(const std::vector& qualifiers, const std::string& separator, const std::string_view brackets = "{}"); static std::vector getMultiQualifiers(const std::string& qualifier1); - static int32 getMultiQualifier(const std::string& qualifier1, uint32 pos); + static int32_t getMultiQualifier(const std::string& qualifier1, uint32_t pos); protected: std::string qualifier; @@ -172,7 +170,19 @@ class NamedObjectContextList for (typename std::unordered_map::const_iterator i = created.begin(); i != created.end(); i++) { if (i->second) + { + // @TODO: This needs to be addressed by refactoring those raw pointers to std::unique_ptr or values. +#if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdelete-incomplete" +#endif + delete i->second; + +#if defined(__clang__) + #pragma clang diagnostic pop +#endif + } } created.clear(); diff --git a/src/Bot/Engine/PassiveMultiplier.cpp b/src/Bot/Engine/PassiveMultiplier.cpp index 0b95e01a57..9b5e6bb518 100644 --- a/src/Bot/Engine/PassiveMultiplier.cpp +++ b/src/Bot/Engine/PassiveMultiplier.cpp @@ -31,12 +31,9 @@ PassiveMultiplier::PassiveMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "pa } } -float PassiveMultiplier::GetValue(Action* action) +float PassiveMultiplier::GetValue(Action& action) { - if (!action) - return 1.0f; - - std::string const name = action->getName(); + std::string const name = action.getName(); for (std::vector::iterator i = allowedActions.begin(); i != allowedActions.end(); i++) { diff --git a/src/Bot/Engine/PassiveMultiplier.h b/src/Bot/Engine/PassiveMultiplier.h index b407f93378..af60828ae0 100644 --- a/src/Bot/Engine/PassiveMultiplier.h +++ b/src/Bot/Engine/PassiveMultiplier.h @@ -18,7 +18,7 @@ class PassiveMultiplier : public Multiplier public: PassiveMultiplier(PlayerbotAI* botAI); - float GetValue(Action* action) override; + float GetValue(Action& action) override; private: static std::vector allowedActions; diff --git a/src/Bot/Engine/PlayerbotAIBase.cpp b/src/Bot/Engine/PlayerbotAIBase.cpp index c034979340..cf4ad172cc 100644 --- a/src/Bot/Engine/PlayerbotAIBase.cpp +++ b/src/Bot/Engine/PlayerbotAIBase.cpp @@ -14,7 +14,7 @@ void PlayerbotAIBase::UpdateAI(uint32 elapsed, bool minimal) if (totalPmo) totalPmo->finish(); - totalPmo = sPerfMonitor->start(PERF_MON_TOTAL, "PlayerbotAIBase::FullTick"); + totalPmo = sPerfMonitor.start(PERF_MON_TOTAL, "PlayerbotAIBase::FullTick"); if (nextAICheckDelay > elapsed) nextAICheckDelay -= elapsed; @@ -35,7 +35,7 @@ void PlayerbotAIBase::SetNextCheckDelay(uint32 const delay) nextAICheckDelay = delay; - // if (nextAICheckDelay > sPlayerbotAIConfig->globalCoolDown) + // if (nextAICheckDelay > sPlayerbotAIConfig.globalCoolDown) // LOG_DEBUG("playerbots", "std::set next check delay: {}", nextAICheckDelay); } @@ -43,7 +43,7 @@ void PlayerbotAIBase::IncreaseNextCheckDelay(uint32 delay) { nextAICheckDelay += delay; - // if (nextAICheckDelay > sPlayerbotAIConfig->globalCoolDown) + // if (nextAICheckDelay > sPlayerbotAIConfig.globalCoolDown) // LOG_DEBUG("playerbots", "increase next check delay: {}", nextAICheckDelay); } @@ -55,6 +55,6 @@ void PlayerbotAIBase::YieldThread(uint32 delay) nextAICheckDelay = delay; } -bool PlayerbotAIBase::IsActive() { return nextAICheckDelay < sPlayerbotAIConfig->maxWaitForMove; } +bool PlayerbotAIBase::IsActive() { return nextAICheckDelay < sPlayerbotAIConfig.maxWaitForMove; } bool PlayerbotAIBase::IsBotAI() const { return _isBotAI; } diff --git a/src/Bot/Engine/PlayerbotAIBase.h b/src/Bot/Engine/PlayerbotAIBase.h index 03c762a58f..d0e0b775b2 100644 --- a/src/Bot/Engine/PlayerbotAIBase.h +++ b/src/Bot/Engine/PlayerbotAIBase.h @@ -17,7 +17,7 @@ class PlayerbotAIBase bool CanUpdateAI(); void SetNextCheckDelay(uint32 const delay); void IncreaseNextCheckDelay(uint32 delay); - void YieldThread(uint32 delay = sPlayerbotAIConfig->reactDelay); + void YieldThread(uint32 delay = sPlayerbotAIConfig.reactDelay); virtual void UpdateAI(uint32 elapsed, bool minimal = false); virtual void UpdateAIInternal(uint32 elapsed, bool minimal = false) = 0; bool IsActive(); diff --git a/src/Bot/Engine/Strategy/CustomStrategy.cpp b/src/Bot/Engine/Strategy/CustomStrategy.cpp index d4dd3e514e..7776c0fd23 100644 --- a/src/Bot/Engine/Strategy/CustomStrategy.cpp +++ b/src/Bot/Engine/Strategy/CustomStrategy.cpp @@ -17,17 +17,26 @@ NextAction toNextAction(std::string const action) std::vector tokens = split(action, '!'); if (tokens[0].empty()) + { throw std::invalid_argument("Invalid action"); + } - if (tokens.size() == 2) - return NextAction(tokens[0], atof(tokens[1].c_str())); + const float weight = (tokens.size() == 2) ? atof(tokens[1].c_str()) : ACTION_NORMAL; + const std::string name = tokens[0]; - if (tokens.size() == 1) - return NextAction(tokens[0], ACTION_NORMAL); + const NextAction::Factory factory = ActionFactoryRegistry::GetFactoryByName(name); - LOG_ERROR("playerbots", "Invalid action {}", action.c_str()); + if (factory == nullptr) + { + LOG_ERROR("playerbots", "Invalid action {}", action.c_str()); + + throw std::invalid_argument("Invalid action"); + } - throw std::invalid_argument("Invalid action"); + return NextAction{ + .weight = weight, + .factory = factory, + }; } std::vector toNextActionArray(const std::string actions) @@ -35,7 +44,7 @@ std::vector toNextActionArray(const std::string actions) const std::vector tokens = split(actions, ','); std::vector res = {}; - for (const std::string token : tokens) + for (const std::string& token : tokens) { res.push_back(toNextAction(token)); } diff --git a/src/Bot/Engine/Strategy/Strategy.cpp b/src/Bot/Engine/Strategy/Strategy.cpp index d6193e11e4..24d8a6c8d9 100644 --- a/src/Bot/Engine/Strategy/Strategy.cpp +++ b/src/Bot/Engine/Strategy/Strategy.cpp @@ -4,8 +4,10 @@ */ #include "Strategy.h" - -#include "Playerbots.h" +#include "CreateNextAction.h" +#include "FollowActions.h" +#include "NonCombatActions.h" +#include "UseItemAction.h" class ActionNodeFactoryInternal : public NamedObjectFactory { @@ -16,7 +18,7 @@ class ActionNodeFactoryInternal : public NamedObjectFactory creators["healthstone"] = &healthstone; creators["be near"] = &follow_master_random; creators["attack anything"] = &attack_anything; - creators["move random"] = &move_random; + // creators["move random"] = &move_random; creators["move to loot"] = &move_to_loot; creators["food"] = &food; creators["drink"] = &drink; @@ -29,7 +31,6 @@ class ActionNodeFactoryInternal : public NamedObjectFactory static ActionNode* melee([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "melee", /*P*/ {}, /*A*/ {}, /*C*/ {} @@ -39,9 +40,8 @@ class ActionNodeFactoryInternal : public NamedObjectFactory static ActionNode* healthstone([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "healthstone", /*P*/ {}, - /*A*/ { NextAction("healing potion") }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } @@ -49,9 +49,8 @@ class ActionNodeFactoryInternal : public NamedObjectFactory static ActionNode* follow_master_random([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "be near", /*P*/ {}, - /*A*/ { NextAction("follow") }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } @@ -59,27 +58,25 @@ class ActionNodeFactoryInternal : public NamedObjectFactory static ActionNode* attack_anything([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "attack anything", /*P*/ {}, /*A*/ {}, /*C*/ {} ); } - static ActionNode* move_random([[maybe_unused]] PlayerbotAI* botAI) - { - return new ActionNode( - "move random", - /*P*/ {}, - /*A*/ { NextAction("stay line") }, - /*C*/ {} - ); - } + // "stay line" does not exist + // static ActionNode* move_random([[maybe_unused]] PlayerbotAI* botAI) + // { + // return new ActionNode( + // /*P*/ {}, + // /*A*/ { CreateNextAction("stay line") }, + // /*C*/ {} + // ); + // } static ActionNode* move_to_loot([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "move to loot", /*P*/ {}, /*A*/ {}, /*C*/ {} @@ -89,7 +86,6 @@ class ActionNodeFactoryInternal : public NamedObjectFactory static ActionNode* food([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "food", /*P*/ {}, /*A*/ {}, /*C*/ {} @@ -99,7 +95,6 @@ class ActionNodeFactoryInternal : public NamedObjectFactory static ActionNode* drink([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "drink", /*P*/ {}, /*A*/ {}, /*C*/ {} @@ -109,7 +104,6 @@ class ActionNodeFactoryInternal : public NamedObjectFactory static ActionNode* mana_potion([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "mana potion", /*P*/ {}, /*A*/ {}, /*C*/ {} @@ -119,9 +113,8 @@ class ActionNodeFactoryInternal : public NamedObjectFactory static ActionNode* healing_potion([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "healing potion", /*P*/ {}, - /*A*/ { NextAction("food") }, + /*A*/ { CreateNextAction(1.0f) }, /*C*/ {} ); } @@ -129,7 +122,6 @@ class ActionNodeFactoryInternal : public NamedObjectFactory static ActionNode* flee([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode( - "flee", /*P*/ {}, /*A*/ {}, /*C*/ {} @@ -142,4 +134,7 @@ Strategy::Strategy(PlayerbotAI* botAI) : PlayerbotAIAware(botAI) actionNodeFactories.Add(new ActionNodeFactoryInternal()); } -ActionNode* Strategy::GetAction(std::string const name) { return actionNodeFactories.GetContextObject(name, botAI); } +ActionNode* Strategy::GetAction(std::string const name) +{ + return actionNodeFactories.GetContextObject(name, botAI); +} diff --git a/src/Bot/Engine/Strategy/Strategy.h b/src/Bot/Engine/Strategy/Strategy.h index 8f57bc0784..cb98fba09f 100644 --- a/src/Bot/Engine/Strategy/Strategy.h +++ b/src/Bot/Engine/Strategy/Strategy.h @@ -11,6 +11,7 @@ #include "NamedObjectContext.h" #include "PlayerbotAIAware.h" #include "Trigger.h" +#include "ActionNode.h" enum StrategyType : uint32 { diff --git a/src/Bot/Engine/Trigger/Trigger.cpp b/src/Bot/Engine/Trigger/Trigger.cpp index 07105be299..3166001c2f 100644 --- a/src/Bot/Engine/Trigger/Trigger.cpp +++ b/src/Bot/Engine/Trigger/Trigger.cpp @@ -5,9 +5,8 @@ #include "Trigger.h" +#include "AiObjectContext.h" #include "Event.h" -#include "Playerbots.h" -#include "Timer.h" Trigger::Trigger(PlayerbotAI* botAI, std::string const name, int32 checkInterval) : AiNamedObject(botAI, name), @@ -28,18 +27,20 @@ Event Trigger::Check() return event; } -Value* Trigger::GetTargetValue() { return context->GetValue(GetTargetName()); } +Value* Trigger::GetTargetValue() { return this->context->GetValue(GetTargetName()); } Unit* Trigger::GetTarget() { return GetTargetValue()->Get(); } bool Trigger::needCheck(uint32 now) { - if (checkInterval < 2) + if (this->checkInterval < 2) return true; - if (!lastCheckTime || now - lastCheckTime >= checkInterval) + const int64_t signedLastCheckTime = this->lastCheckTime; + + if (!this->lastCheckTime || now - signedLastCheckTime >= this->checkInterval) { - lastCheckTime = now; + this->lastCheckTime = now; return true; } diff --git a/src/Bot/Engine/Trigger/Trigger.h b/src/Bot/Engine/Trigger/Trigger.h index d32845dc52..671e70d804 100644 --- a/src/Bot/Engine/Trigger/Trigger.h +++ b/src/Bot/Engine/Trigger/Trigger.h @@ -6,7 +6,9 @@ #pragma once #include "Action.h" -#include "Common.h" +#include "Event.h" +#include "NextAction.h" +#include "Value.h" class PlayerbotAI; class Unit; @@ -72,7 +74,7 @@ class TriggerNode float getFirstRelevance() { if (this->handlers.size() > 0) - return this->handlers[0].getRelevance(); + return this->handlers[0].weight; return -1; } diff --git a/src/Bot/Engine/Value/Value.cpp b/src/Bot/Engine/Value/Value.cpp index c559e03816..ae14d15286 100644 --- a/src/Bot/Engine/Value/Value.cpp +++ b/src/Bot/Engine/Value/Value.cpp @@ -123,7 +123,7 @@ Unit* UnitCalculatedValue::Get() { if (checkInterval < 2) { - PerfMonitorOperation* pmo = sPerfMonitor->start( + PerfMonitorOperation* pmo = sPerfMonitor.start( PERF_MON_VALUE, this->getName(), this->context ? &this->context->performanceStack : nullptr); value = Calculate(); if (pmo) @@ -135,7 +135,7 @@ Unit* UnitCalculatedValue::Get() if (!lastCheckTime || now - lastCheckTime >= checkInterval) { lastCheckTime = now; - PerfMonitorOperation* pmo = sPerfMonitor->start( + PerfMonitorOperation* pmo = sPerfMonitor.start( PERF_MON_VALUE, this->getName(), this->context ? &this->context->performanceStack : nullptr); value = Calculate(); if (pmo) diff --git a/src/Bot/Engine/Value/Value.h b/src/Bot/Engine/Value/Value.h index b37e162050..4ab7b3fbb0 100644 --- a/src/Bot/Engine/Value/Value.h +++ b/src/Bot/Engine/Value/Value.h @@ -72,7 +72,7 @@ class CalculatedValue : public UntypedValue, public Value { if (checkInterval < 2) { - // PerfMonitorOperation* pmo = sPerfMonitor->start(PERF_MON_VALUE, this->getName(), + // PerfMonitorOperation* pmo = sPerfMonitor.start(PERF_MON_VALUE, this->getName(), // this->context ? &this->context->performanceStack : nullptr); value = Calculate(); // if (pmo) @@ -84,7 +84,7 @@ class CalculatedValue : public UntypedValue, public Value if (!lastCheckTime || now - lastCheckTime >= checkInterval) { lastCheckTime = now; - // PerfMonitorOperation* pmo = sPerfMonitor->start(PERF_MON_VALUE, this->getName(), + // PerfMonitorOperation* pmo = sPerfMonitor.start(PERF_MON_VALUE, this->getName(), // this->context ? &this->context->performanceStack : nullptr); value = Calculate(); // if (pmo) @@ -105,7 +105,7 @@ class CalculatedValue : public UntypedValue, public Value { if (checkInterval < 2) { - // PerfMonitorOperation* pmo = sPerfMonitor->start(PERF_MON_VALUE, this->getName(), + // PerfMonitorOperation* pmo = sPerfMonitor.start(PERF_MON_VALUE, this->getName(), // this->context ? &this->context->performanceStack : nullptr); value = Calculate(); // if (pmo) @@ -117,7 +117,7 @@ class CalculatedValue : public UntypedValue, public Value if (!lastCheckTime || now - lastCheckTime >= checkInterval) { lastCheckTime = now; - // PerfMonitorOperation* pmo = sPerfMonitor->start(PERF_MON_VALUE, this->getName(), + // PerfMonitorOperation* pmo = sPerfMonitor.start(PERF_MON_VALUE, this->getName(), // this->context ? &this->context->performanceStack : nullptr); value = Calculate(); // if (pmo) @@ -154,11 +154,11 @@ class SingleCalculatedValue : public CalculatedValue { this->lastCheckTime = now; - PerfMonitorOperation* pmo = sPerfMonitor->start( - PERF_MON_VALUE, this->getName(), this->context ? &this->context->performanceStack : nullptr); + // PerfMonitorOperation* pmo = sPerfMonitor.start( + // PERF_MON_VALUE, this->getName(), this->context ? &this->context->performanceStack : nullptr); this->value = this->Calculate(); - if (pmo) - pmo->finish(); + // if (pmo) + // pmo->finish(); } return this->value; diff --git a/src/Bot/Factory/AiFactory.cpp b/src/Bot/Factory/AiFactory.cpp index 8ca3534b1d..84b3a7dc53 100644 --- a/src/Bot/Factory/AiFactory.cpp +++ b/src/Bot/Factory/AiFactory.cpp @@ -281,7 +281,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa if (!player->InBattleground()) engine->addStrategiesNoInit("racials", "chat", "default", "cast time", "potions", "duel", "boost", nullptr); - if (sPlayerbotAIConfig->autoAvoidAoe && facade->HasRealPlayerMaster()) + if (sPlayerbotAIConfig.autoAvoidAoe && facade->HasRealPlayerMaster()) engine->addStrategy("avoid aoe", false); engine->addStrategy("formation", false); @@ -399,13 +399,13 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa if (PlayerbotAI::IsHeal(player, true)) { - if (sPlayerbotAIConfig->autoSaveMana) + if (sPlayerbotAIConfig.autoSaveMana) engine->addStrategy("save mana", false); - if (!sPlayerbotAIConfig->IsRestrictedHealerDPSMap(player->GetMapId())) + if (!sPlayerbotAIConfig.IsRestrictedHealerDPSMap(player->GetMapId())) engine->addStrategy("healer dps", false); } - if (facade->IsRealPlayer() || sRandomPlayerbotMgr->IsRandomBot(player)) + if (facade->IsRealPlayer() || sRandomPlayerbotMgr.IsRandomBot(player)) { if (!player->GetGroup()) { @@ -448,10 +448,10 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa } } } - if (sRandomPlayerbotMgr->IsRandomBot(player)) - engine->ChangeStrategy(sPlayerbotAIConfig->randomBotCombatStrategies); + if (sRandomPlayerbotMgr.IsRandomBot(player)) + engine->ChangeStrategy(sPlayerbotAIConfig.randomBotCombatStrategies); else - engine->ChangeStrategy(sPlayerbotAIConfig->combatStrategies); + engine->ChangeStrategy(sPlayerbotAIConfig.combatStrategies); // Battleground switch if (player->InBattleground() && player->GetBattleground()) @@ -586,10 +586,10 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const "gather", "duel", "pvp", "buff", "mount", "emote", nullptr); } - if (sPlayerbotAIConfig->autoSaveMana && PlayerbotAI::IsHeal(player, true)) + if (sPlayerbotAIConfig.autoSaveMana && PlayerbotAI::IsHeal(player, true)) nonCombatEngine->addStrategy("save mana", false); - if ((sRandomPlayerbotMgr->IsRandomBot(player)) && !player->InBattleground()) + if ((sRandomPlayerbotMgr.IsRandomBot(player)) && !player->InBattleground()) { Player* master = facade->GetMaster(); @@ -597,7 +597,7 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const if (!urand(0, 3)) nonCombatEngine->addStrategy("start duel", false); - if (sPlayerbotAIConfig->randomBotJoinLfg) + if (sPlayerbotAIConfig.randomBotJoinLfg) nonCombatEngine->addStrategy("lfg", false); if (!player->GetGroup() || player->GetGroup()->GetLeaderGUID() == player->GetGUID()) @@ -612,9 +612,9 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const // nonCombatEngine->addStrategy("guild"); nonCombatEngine->addStrategy("grind", false); - if (sPlayerbotAIConfig->enableNewRpgStrategy) + if (sPlayerbotAIConfig.enableNewRpgStrategy) nonCombatEngine->addStrategy("new rpg", false); - else if (sPlayerbotAIConfig->autoDoQuests) + else if (sPlayerbotAIConfig.autoDoQuests) { // nonCombatEngine->addStrategy("travel"); nonCombatEngine->addStrategy("rpg", false); @@ -622,13 +622,13 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const else nonCombatEngine->addStrategy("move random", false); - if (sPlayerbotAIConfig->randomBotJoinBG) + if (sPlayerbotAIConfig.randomBotJoinBG) nonCombatEngine->addStrategy("bg", false); // if (!master || GET_PLAYERBOT_AI(master)) // nonCombatEngine->addStrategy("maintenance"); - nonCombatEngine->ChangeStrategy(sPlayerbotAIConfig->randomBotNonCombatStrategies); + nonCombatEngine->ChangeStrategy(sPlayerbotAIConfig.randomBotNonCombatStrategies); } else { @@ -637,14 +637,14 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const if (master) { PlayerbotAI* masterBotAI = GET_PLAYERBOT_AI(master); - if (masterBotAI || sRandomPlayerbotMgr->IsRandomBot(player)) + if (masterBotAI || sRandomPlayerbotMgr.IsRandomBot(player)) { // nonCombatEngine->addStrategy("pvp", false); // nonCombatEngine->addStrategy("collision"); // nonCombatEngine->addStrategy("group"); // nonCombatEngine->addStrategy("guild"); - // if (sPlayerbotAIConfig->autoDoQuests) + // if (sPlayerbotAIConfig.autoDoQuests) // { // // nonCombatEngine->addStrategy("travel"); // nonCombatEngine->addStrategy("rpg"); @@ -657,19 +657,19 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const // if (masterBotAI) // nonCombatEngine->addStrategy("maintenance"); - nonCombatEngine->ChangeStrategy(sPlayerbotAIConfig->randomBotNonCombatStrategies); + nonCombatEngine->ChangeStrategy(sPlayerbotAIConfig.randomBotNonCombatStrategies); } else { // nonCombatEngine->addStrategy("pvp", false); - nonCombatEngine->ChangeStrategy(sPlayerbotAIConfig->nonCombatStrategies); + nonCombatEngine->ChangeStrategy(sPlayerbotAIConfig.nonCombatStrategies); } } } } } else - nonCombatEngine->ChangeStrategy(sPlayerbotAIConfig->nonCombatStrategies); + nonCombatEngine->ChangeStrategy(sPlayerbotAIConfig.nonCombatStrategies); // Battleground switch if (player->InBattleground() && player->GetBattleground()) @@ -726,7 +726,7 @@ void AiFactory::AddDefaultDeadStrategies(Player* player, PlayerbotAI* const faca (void)facade; // unused and remove warning deadEngine->addStrategiesNoInit("dead", "stay", "chat", "default", "follow", nullptr); - if (sRandomPlayerbotMgr->IsRandomBot(player) && !player->GetGroup()) + if (sRandomPlayerbotMgr.IsRandomBot(player) && !player->GetGroup()) deadEngine->removeStrategy("follow", false); } diff --git a/src/Bot/Factory/AiFactory.h b/src/Bot/Factory/AiFactory.h index 3d11d80aeb..052aefc4b5 100644 --- a/src/Bot/Factory/AiFactory.h +++ b/src/Bot/Factory/AiFactory.h @@ -6,16 +6,16 @@ #ifndef _PLAYERBOT_AIFACTORY_H #define _PLAYERBOT_AIFACTORY_H +#include #include - -#include "Common.h" +#include class AiObjectContext; class Engine; class Player; class PlayerbotAI; -enum BotRoles : uint8; +enum BotRoles : uint8_t; class AiFactory { @@ -28,8 +28,8 @@ class AiFactory static void AddDefaultDeadStrategies(Player* player, PlayerbotAI* const facade, Engine* deadEngine); static void AddDefaultCombatStrategies(Player* player, PlayerbotAI* const facade, Engine* engine); - static uint8 GetPlayerSpecTab(Player* player); - static std::map GetPlayerSpecTabs(Player* player); + static uint8_t GetPlayerSpecTab(Player* player); + static std::map GetPlayerSpecTabs(Player* player); static BotRoles GetPlayerRoles(Player* player); static std::string GetPlayerSpecName(Player* player); }; diff --git a/src/Bot/Factory/PlayerbotFactory.cpp b/src/Bot/Factory/PlayerbotFactory.cpp index 67f5909c11..f1bd73b131 100644 --- a/src/Bot/Factory/PlayerbotFactory.cpp +++ b/src/Bot/Factory/PlayerbotFactory.cpp @@ -5,7 +5,6 @@ #include "PlayerbotFactory.h" -#include #include #include "AccountMgr.h" @@ -20,9 +19,7 @@ #include "ItemTemplate.h" #include "ItemVisitors.h" #include "Log.h" -#include "LogCommon.h" #include "LootMgr.h" -#include "MapMgr.h" #include "ObjectMgr.h" #include "PerfMonitor.h" #include "PetDefines.h" @@ -37,7 +34,6 @@ #include "RandomPlayerbotFactory.h" #include "ReputationMgr.h" #include "SharedDefines.h" -#include "SpellAuraDefines.h" #include "StatsWeightCalculator.h" #include "World.h" #include "AiObjectContext.h" @@ -68,18 +64,18 @@ PlayerbotFactory::PlayerbotFactory(Player* bot, uint32 level, uint32 itemQuality botAI = GET_PLAYERBOT_AI(bot); if (!this->itemQuality) { - uint32 gs = sPlayerbotAIConfig->randomGearScoreLimit == 0 + uint32 gs = sPlayerbotAIConfig.randomGearScoreLimit == 0 ? 0 - : PlayerbotFactory::CalcMixedGearScore(sPlayerbotAIConfig->randomGearScoreLimit, - sPlayerbotAIConfig->randomGearQualityLimit); - this->itemQuality = sPlayerbotAIConfig->randomGearQualityLimit; + : PlayerbotFactory::CalcMixedGearScore(sPlayerbotAIConfig.randomGearScoreLimit, + sPlayerbotAIConfig.randomGearQualityLimit); + this->itemQuality = sPlayerbotAIConfig.randomGearQualityLimit; this->gearScoreLimit = gs; } } void PlayerbotFactory::Init() { - if (sPlayerbotAIConfig->randomBotPreQuests) + if (sPlayerbotAIConfig.randomBotPreQuests) { ObjectMgr::QuestMap const& questTemplates = sObjectMgr->GetQuestTemplates(); for (ObjectMgr::QuestMap::const_iterator i = questTemplates.begin(); i != questTemplates.end(); ++i) @@ -111,8 +107,8 @@ void PlayerbotFactory::Init() } } - for (std::vector::iterator i = sPlayerbotAIConfig->randomBotQuestIds.begin(); - i != sPlayerbotAIConfig->randomBotQuestIds.end(); ++i) + for (std::vector::iterator i = sPlayerbotAIConfig.randomBotQuestIds.begin(); + i != sPlayerbotAIConfig.randomBotQuestIds.end(); ++i) { uint32 questId = *i; AddPrevQuests(questId, specialQuestIds); @@ -190,7 +186,7 @@ void PlayerbotFactory::Init() continue; } - if (sRandomItemMgr->IsTestItem(gemId)) + if (sRandomItemMgr.IsTestItem(gemId)) { continue; } @@ -218,12 +214,12 @@ void PlayerbotFactory::Prepare() { bot->SetUInt32Value(PLAYER_XP, 0); } - if (!sPlayerbotAIConfig->randomBotShowHelmet || !urand(0, 4)) + if (!sPlayerbotAIConfig.randomBotShowHelmet || !urand(0, 4)) { bot->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_HELM); } - if (!sPlayerbotAIConfig->randomBotShowCloak || !urand(0, 4)) + if (!sPlayerbotAIConfig.randomBotShowCloak || !urand(0, 4)) { bot->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_CLOAK); } @@ -231,26 +227,30 @@ void PlayerbotFactory::Prepare() void PlayerbotFactory::Randomize(bool incremental) { - // if (sPlayerbotAIConfig->disableRandomLevels) + // if (sPlayerbotAIConfig.disableRandomLevels) // { // return; // } - LOG_DEBUG("playerbots", "{} randomizing {} (level {} class = {})...", (incremental ? "Incremental" : "Full"), + LOG_ERROR("playerbots", "{} randomizing {} (level {} class = {})...", (incremental ? "Incremental" : "Full"), bot->GetName().c_str(), level, bot->getClass()); // LOG_DEBUG("playerbots", "Preparing to {} randomize...", (incremental ? "incremental" : "full")); Prepare(); LOG_DEBUG("playerbots", "Resetting player..."); - PerfMonitorOperation* pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Reset"); - if (!sPlayerbotAIConfig->equipmentPersistence || level < sPlayerbotAIConfig->equipmentPersistenceLevel) + PerfMonitorOperation* pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_Reset"); + + const int64_t botLevel = this->level; + + if (!PlayerbotAIConfig::instance().equipmentPersistence || botLevel < PlayerbotAIConfig::instance().equipmentPersistenceLevel) { bot->resetTalents(true); } + if (!incremental) { ClearSkills(); ClearSpells(); ResetQuests(); - if (!sPlayerbotAIConfig->equipmentPersistence || level < sPlayerbotAIConfig->equipmentPersistenceLevel) + if (!PlayerbotAIConfig::instance().equipmentPersistence || botLevel < PlayerbotAIConfig::instance().equipmentPersistenceLevel) { ClearAllItems(); } @@ -266,15 +266,15 @@ void PlayerbotFactory::Randomize(bool incremental) if (pmo) pmo->finish(); - // pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Immersive"); + // pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_Immersive"); // LOG_INFO("playerbots", "Initializing immersive..."); // InitImmersive(); // if (pmo) // pmo->finish(); - if (sPlayerbotAIConfig->randomBotPreQuests) + if (sPlayerbotAIConfig.randomBotPreQuests) { - pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Quests"); + pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_Quests"); InitInstanceQuests(); InitAttunementQuests(); if (pmo) @@ -282,157 +282,157 @@ void PlayerbotFactory::Randomize(bool incremental) } else { - pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Quests"); + pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_Quests"); InitAttunementQuests(); if (pmo) pmo->finish(); } LOG_DEBUG("playerbots", "Initializing skills (step 1)..."); - pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Skills1"); + pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_Skills1"); bot->LearnDefaultSkills(); InitSkills(); if (pmo) pmo->finish(); - pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Spells1"); + pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_Spells1"); LOG_DEBUG("playerbots", "Initializing spells (step 1)..."); InitClassSpells(); InitAvailableSpells(); if (pmo) pmo->finish(); - pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Talents"); + pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_Talents"); LOG_DEBUG("playerbots", "Initializing talents..."); - if (!incremental || !sPlayerbotAIConfig->equipmentPersistence || - bot->GetLevel() < sPlayerbotAIConfig->equipmentPersistenceLevel) + if (!incremental || !sPlayerbotAIConfig.equipmentPersistence || + bot->GetLevel() < sPlayerbotAIConfig.equipmentPersistenceLevel) { InitTalentsTree(); } - sRandomPlayerbotMgr->SetValue(bot->GetGUID().GetCounter(), "specNo", 0); + sRandomPlayerbotMgr.SetValue(bot->GetGUID().GetCounter(), "specNo", 0); if (botAI) { - sPlayerbotRepository->Reset(botAI); + PlayerbotRepository::instance().Reset(botAI); // botAI->DoSpecificAction("auto talents"); botAI->ResetStrategies(false); // fix wrong stored strategy } if (pmo) pmo->finish(); - pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Spells2"); + pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_Spells2"); LOG_DEBUG("playerbots", "Initializing spells (step 2)..."); InitAvailableSpells(); if (pmo) pmo->finish(); - pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Reputation"); + pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_Reputation"); LOG_DEBUG("playerbots", "Initializing reputation..."); InitReputation(); if (pmo) pmo->finish(); LOG_DEBUG("playerbots", "Initializing special spells..."); - pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Spells3"); + pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_Spells3"); InitSpecialSpells(); if (pmo) pmo->finish(); - pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Mounts"); + pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_Mounts"); LOG_DEBUG("playerbots", "Initializing mounts..."); InitMounts(); // bot->SaveToDB(false, false); if (pmo) pmo->finish(); - // pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Skills2"); + // pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_Skills2"); // LOG_INFO("playerbots", "Initializing skills (step 2)..."); // UpdateTradeSkills(); // if (pmo) // pmo->finish(); - pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Equip"); + pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_Equip"); LOG_DEBUG("playerbots", "Initializing equipmemt..."); - if (!incremental || !sPlayerbotAIConfig->equipmentPersistence || - bot->GetLevel() < sPlayerbotAIConfig->equipmentPersistenceLevel) + if (!incremental || !sPlayerbotAIConfig.equipmentPersistence || + bot->GetLevel() < sPlayerbotAIConfig.equipmentPersistenceLevel) { - if (sPlayerbotAIConfig->incrementalGearInit || !incremental) - InitEquipment(incremental, incremental ? false : sPlayerbotAIConfig->twoRoundsGearInit); + if (sPlayerbotAIConfig.incrementalGearInit || !incremental) + InitEquipment(incremental, incremental ? false : sPlayerbotAIConfig.twoRoundsGearInit); } // bot->SaveToDB(false, false); if (pmo) pmo->finish(); - // if (bot->GetLevel() >= sPlayerbotAIConfig->minEnchantingBotLevel) + // if (bot->GetLevel() >= sPlayerbotAIConfig.minEnchantingBotLevel) // { - // pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Enchant"); + // pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_Enchant"); // LOG_INFO("playerbots", "Initializing enchant templates..."); // LoadEnchantContainer(); // if (pmo) // pmo->finish(); // } - pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Bags"); + pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_Bags"); LOG_DEBUG("playerbots", "Initializing bags..."); InitBags(); // bot->SaveToDB(false, false); if (pmo) pmo->finish(); - pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Ammo"); + pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_Ammo"); LOG_DEBUG("playerbots", "Initializing ammo..."); InitAmmo(); if (pmo) pmo->finish(); - pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Food"); + pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_Food"); LOG_DEBUG("playerbots", "Initializing food..."); InitFood(); if (pmo) pmo->finish(); - pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Potions"); + pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_Potions"); LOG_DEBUG("playerbots", "Initializing potions..."); InitPotions(); if (pmo) pmo->finish(); - pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Reagents"); + pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_Reagents"); LOG_DEBUG("playerbots", "Initializing reagents..."); InitReagents(); if (pmo) pmo->finish(); - pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Keys"); + pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_Keys"); LOG_DEBUG("playerbots", "Initializing keys..."); InitKeyring(); if (pmo) pmo->finish(); - // pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_EqSets"); + // pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_EqSets"); // LOG_DEBUG("playerbots", "Initializing second equipment set..."); // InitSecondEquipmentSet(); // if (pmo) // pmo->finish(); - if (bot->GetLevel() >= sPlayerbotAIConfig->minEnchantingBotLevel) + if (bot->GetLevel() >= sPlayerbotAIConfig.minEnchantingBotLevel) { ApplyEnchantAndGemsNew(); } // { - // pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_EnchantTemplate"); + // pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_EnchantTemplate"); // LOG_INFO("playerbots", "Initializing enchant templates..."); // ApplyEnchantTemplate(); // if (pmo) // pmo->finish(); // } - pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Inventory"); + pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_Inventory"); LOG_DEBUG("playerbots", "Initializing inventory..."); // InitInventory(); if (pmo) pmo->finish(); - pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Consumable"); + pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_Consumable"); LOG_DEBUG("playerbots", "Initializing consumables..."); InitConsumables(); if (pmo) @@ -442,9 +442,9 @@ void PlayerbotFactory::Randomize(bool incremental) InitGlyphs(); // bot->SaveToDB(false, false); - pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Guilds"); + pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_Guilds"); // bot->SaveToDB(false, false); - if (sPlayerbotAIConfig->randomBotGuildCount > 0) + if (sPlayerbotAIConfig.randomBotGuildCount > 0) { LOG_DEBUG("playerbots", "Initializing guilds..."); InitGuild(); @@ -455,7 +455,7 @@ void PlayerbotFactory::Randomize(bool incremental) if (bot->GetLevel() >= 70) { - pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Arenas"); + pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_Arenas"); // LOG_INFO("playerbots", "Initializing arena teams..."); InitArenaTeam(); if (pmo) @@ -470,7 +470,7 @@ void PlayerbotFactory::Randomize(bool incremental) } if (bot->GetLevel() >= 10) { - pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Pet"); + pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_Pet"); LOG_DEBUG("playerbots", "Initializing pet..."); InitPet(); // bot->SaveToDB(false, false); @@ -479,13 +479,16 @@ void PlayerbotFactory::Randomize(bool incremental) pmo->finish(); } - pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Save"); + pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "PlayerbotFactory_Save"); LOG_DEBUG("playerbots", "Saving to DB..."); bot->SetMoney(urand(level * 100000, level * 5 * 100000)); bot->SetHealth(bot->GetMaxHealth()); bot->SetPower(POWER_MANA, bot->GetMaxPower(POWER_MANA)); bot->SaveToDB(false, false); LOG_DEBUG("playerbots", "Initialization Done."); + + LOG_DEBUG("playerbots", "Bot #{} {}:{} <{}>: randomized", bot->GetGUID().GetRawValue(), + bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", bot->GetLevel(), bot->GetName().c_str()); if (pmo) pmo->finish(); } @@ -493,41 +496,50 @@ void PlayerbotFactory::Randomize(bool incremental) void PlayerbotFactory::Refresh() { // Prepare(); - // if (!sPlayerbotAIConfig->equipmentPersistence || bot->GetLevel() < sPlayerbotAIConfig->equipmentPersistenceLevel) + // if (!sPlayerbotAIConfig.equipmentPersistence || bot->GetLevel() < sPlayerbotAIConfig.equipmentPersistenceLevel) // { // InitEquipment(true); // } - InitAttunementQuests(); - ClearInventory(); - InitAmmo(); - InitFood(); - InitReagents(); - InitConsumables(); - InitPotions(); - InitPet(); - InitPetTalents(); - InitSkills(); - InitClassSpells(); - InitAvailableSpells(); - InitReputation(); - InitSpecialSpells(); - InitMounts(); - InitKeyring(); - if (!sPlayerbotAIConfig->equipmentPersistence || bot->GetLevel() < sPlayerbotAIConfig->equipmentPersistenceLevel) + if (!sPlayerbotAIConfig.disableRandomBotPeriodicRandomization) + { + InitAttunementQuests(); + ClearInventory(); + InitAmmo(); + InitFood(); + InitReagents(); + InitConsumables(); + InitPotions(); + InitPet(); + InitPetTalents(); + InitClassSpells(); + InitAvailableSpells(); + InitSkills(); + InitReputation(); + InitSpecialSpells(); + InitMounts(); + InitKeyring(); + } + if (!sPlayerbotAIConfig.equipmentPersistence || bot->GetLevel() < sPlayerbotAIConfig.equipmentPersistenceLevel) { InitTalentsTree(true, true, true); } - if (bot->GetLevel() >= sPlayerbotAIConfig->minEnchantingBotLevel) + if (bot->GetLevel() >= sPlayerbotAIConfig.minEnchantingBotLevel && !sPlayerbotAIConfig.disableRandomBotPeriodicRandomization) { ApplyEnchantAndGemsNew(); } bot->DurabilityRepairAll(false, 1.0f, false); if (bot->isDead()) + { bot->ResurrectPlayer(1.0f, false); - uint32 money = urand(level * 1000, level * 5 * 1000); - if (bot->GetMoney() < money) - bot->SetMoney(money); - // bot->SaveToDB(false, false); + } + + if (!sPlayerbotAIConfig.disableRandomBotPeriodicRandomization) + { + uint32 money = urand(level * 1000, level * 5 * 1000); + if (bot->GetMoney() < money) + bot->SetMoney(money); + } +// bot->SaveToDB(false, false); } void PlayerbotFactory::InitConsumables() @@ -746,7 +758,7 @@ void PlayerbotFactory::InitConsumables() void PlayerbotFactory::InitPetTalents() { - if (bot->GetLevel() <= 70 && sPlayerbotAIConfig->limitTalentsExpansion) + if (bot->GetLevel() <= 70 && sPlayerbotAIConfig.limitTalentsExpansion) return; Pet* pet = bot->GetPet(); @@ -794,7 +806,7 @@ void PlayerbotFactory::InitPetTalents() } std::vector> order = - sPlayerbotAIConfig->parsedHunterPetLinkOrder[pet_family->petTalentType][20]; + sPlayerbotAIConfig.parsedHunterPetLinkOrder[pet_family->petTalentType][20]; uint32 maxTalentPoints = pet->GetMaxTalentPointsForLevel(pet->GetLevel()); if (order.empty()) @@ -817,7 +829,7 @@ void PlayerbotFactory::InitPetTalents() int index = urand(0, spells_row.size() - 1); TalentEntry const* talentInfo = spells_row[index]; int maxRank = 0; - for (int rank = 0; rank < std::min((uint32)MAX_TALENT_RANK, (uint32)pet->GetFreeTalentPoints()); ++rank) + for (uint8_t rank = 0; rank < std::min((uint32)MAX_TALENT_RANK, (uint32)pet->GetFreeTalentPoints()); ++rank) { uint32 spellId = talentInfo->RankID[rank]; if (!spellId) @@ -842,16 +854,16 @@ void PlayerbotFactory::InitPetTalents() uint32 spec = pet_family->petTalentType; uint32 startPoints = pet->GetMaxTalentPointsForLevel(pet->GetLevel()); while (startPoints > 1 && startPoints < 20 && - sPlayerbotAIConfig->parsedHunterPetLinkOrder[spec][startPoints].size() == 0) + sPlayerbotAIConfig.parsedHunterPetLinkOrder[spec][startPoints].size() == 0) { startPoints--; } for (uint32 points = startPoints; points <= 20; points++) { - if (sPlayerbotAIConfig->parsedHunterPetLinkOrder[spec][points].size() == 0) + if (sPlayerbotAIConfig.parsedHunterPetLinkOrder[spec][points].size() == 0) continue; - for (std::vector& p : sPlayerbotAIConfig->parsedHunterPetLinkOrder[spec][points]) + for (std::vector& p : sPlayerbotAIConfig.parsedHunterPetLinkOrder[spec][points]) { uint32 row = p[0], col = p[1], lvl = p[2]; uint32 talentID = 0; @@ -924,17 +936,17 @@ void PlayerbotFactory::InitPet() if (itr->second.minlevel > bot->GetLevel()) continue; - bool onlyWolf = sPlayerbotAIConfig->hunterWolfPet == 2 || - (sPlayerbotAIConfig->hunterWolfPet == 1 && + bool onlyWolf = sPlayerbotAIConfig.hunterWolfPet == 2 || + (sPlayerbotAIConfig.hunterWolfPet == 1 && bot->GetLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)); // Wolf only (for higher dps) if (onlyWolf && itr->second.family != CREATURE_FAMILY_WOLF) continue; // Exclude configured pet families - if (std::find(sPlayerbotAIConfig->excludedHunterPetFamilies.begin(), - sPlayerbotAIConfig->excludedHunterPetFamilies.end(), - itr->second.family) != sPlayerbotAIConfig->excludedHunterPetFamilies.end()) + if (std::find(sPlayerbotAIConfig.excludedHunterPetFamilies.begin(), + sPlayerbotAIConfig.excludedHunterPetFamilies.end(), + itr->second.family) != sPlayerbotAIConfig.excludedHunterPetFamilies.end()) continue; ids.push_back(itr->first); @@ -954,8 +966,6 @@ void PlayerbotFactory::InitPet() continue; if (co->Name.size() > 21) continue; - uint32 guid = map->GenerateLowGuid(); - uint32 pet_number = sObjectMgr->GeneratePetNumber(); if (bot->GetPetStable() && bot->GetPetStable()->CurrentPet) { auto petGuid = bot->GetPetStable()->CurrentPet.value(); // To correct the build warnin in VS @@ -1123,8 +1133,8 @@ void PlayerbotFactory::InitTalentsTree(bool increment /*false*/, bool use_templa bool isCat = !bot->HasAura(16931); if (!isCat && bot->GetLevel() == 20) { - uint32 bearP = sPlayerbotAIConfig->randomClassSpecProb[cls][1]; - uint32 catP = sPlayerbotAIConfig->randomClassSpecProb[cls][3]; + uint32 bearP = sPlayerbotAIConfig.randomClassSpecProb[cls][1]; + uint32 catP = sPlayerbotAIConfig.randomClassSpecProb[cls][3]; if (urand(1, bearP + catP) <= catP) isCat = true; } @@ -1139,14 +1149,14 @@ void PlayerbotFactory::InitTalentsTree(bool increment /*false*/, bool use_templa uint32 pointSum = 0; for (int i = 0; i < MAX_SPECNO; i++) { - pointSum += sPlayerbotAIConfig->randomClassSpecProb[cls][i]; + pointSum += sPlayerbotAIConfig.randomClassSpecProb[cls][i]; } uint32 point = urand(1, pointSum); uint32 currentP = 0; int i; for (i = 0; i < MAX_SPECNO; i++) { - currentP += sPlayerbotAIConfig->randomClassSpecProb[cls][i]; + currentP += sPlayerbotAIConfig.randomClassSpecProb[cls][i]; if (point <= currentP) { specTab = i; @@ -1204,17 +1214,17 @@ void PlayerbotFactory::InitTalentsBySpecNo(Player* bot, int specNo, bool reset) spells_row[talentInfo->Row].push_back(talentInfo); } while (startLevel > 1 && startLevel < 80 && - sPlayerbotAIConfig->parsedSpecLinkOrder[cls][specNo][startLevel].size() == 0) + sPlayerbotAIConfig.parsedSpecLinkOrder[cls][specNo][startLevel].size() == 0) { startLevel--; } for (int level = startLevel; level <= 80; level++) { - if (sPlayerbotAIConfig->parsedSpecLinkOrder[cls][specNo][level].size() == 0) + if (sPlayerbotAIConfig.parsedSpecLinkOrder[cls][specNo][level].size() == 0) { continue; } - for (std::vector& p : sPlayerbotAIConfig->parsedSpecLinkOrder[cls][specNo][level]) + for (std::vector& p : sPlayerbotAIConfig.parsedSpecLinkOrder[cls][specNo][level]) { uint32 tab = p[0], row = p[1], col = p[2], lvl = p[3]; uint32 talentID = -1; @@ -1341,7 +1351,7 @@ class DestroyItemsVisitor : public IterateItemsVisitor if (keep.find(id) != keep.end()) return false; - if (sPlayerbotAIConfig->IsInRandomQuestItemList(id)) + if (sPlayerbotAIConfig.IsInRandomQuestItemList(id)) return true; return false; @@ -1575,138 +1585,9 @@ void Shuffle(std::vector& items) } } -// void PlayerbotFactory::InitEquipmentNew(bool incremental) -// { -// if (incremental) -// { -// DestroyItemsVisitor visitor(bot); -// IterateItems(&visitor, (IterateItemsMask)(ITERATE_ITEMS_IN_BAGS | ITERATE_ITEMS_IN_BANK)); -// } -// else -// { -// DestroyItemsVisitor visitor(bot); -// IterateItems(&visitor, ITERATE_ALL_ITEMS); -// } - -// std::string const& specName = AiFactory::GetPlayerSpecName(bot); -// if (specName.empty()) -// return; - -// // look for upgrades -// for (uint8 slot = 0; slot < EQUIPMENT_SLOT_END; ++slot) -// { -// if (slot == EQUIPMENT_SLOT_TABARD && !bot->GetGuildId()) -// continue; - -// bool isUpgrade = false; -// bool found = false; -// bool noItem = false; -// uint32 quality = urand(ITEM_QUALITY_UNCOMMON, ITEM_QUALITY_EPIC); -// uint32 attempts = 10; -// if (urand(0, 100) < 100 * sPlayerbotAIConfig->randomGearLoweringChance && quality > ITEM_QUALITY_NORMAL) -// { -// quality--; -// } -// // current item; -// Item* oldItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, slot); -// if (oldItem) -// isUpgrade = true; - -// uint32 itemInSlot = isUpgrade ? oldItem->GetTemplate()->ItemId : 0; - -// uint32 maxLevel = sPlayerbotAIConfig->randomBotMaxLevel; -// if (maxLevel > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) -// maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); - -// uint32 minLevel = sPlayerbotAIConfig->randomBotMinLevel; -// if (minLevel < sWorld->getIntConfig(CONFIG_START_PLAYER_LEVEL)) -// minLevel = sWorld->getIntConfig(CONFIG_START_PLAYER_LEVEL); - -// // test -// do -// { -// if (isUpgrade) -// { -// std::vector ids = sRandomItemMgr->GetUpgradeList(bot, specName, slot, 0, itemInSlot); -// if (!ids.empty()) -// Shuffle(ids); - -// for (uint32 index = 0; index < ids.size(); ++index) -// { -// uint32 newItemId = ids[index]; -// if (incremental && !IsDesiredReplacement(oldItem)) -// { -// continue; -// } - -// uint16 dest; -// if (!CanEquipUnseenItem(slot, dest, newItemId)) -// continue; - -// if (oldItem) -// { -// bot->RemoveItem(INVENTORY_SLOT_BAG_0, slot, true); -// oldItem->DestroyForPlayer(bot); -// } - -// Item* newItem = bot->EquipNewItem(dest, newItemId, true); -// if (newItem) -// { -// newItem->AddToWorld(); -// newItem->AddToUpdateQueueOf(bot); -// bot->AutoUnequipOffhandIfNeed(); -// newItem->SetOwnerGUID(bot->GetGUID()); -// EnchantItem(newItem); -// LOG_INFO("playerbots", "Bot {} {}:{} <{}>: Equip: {}, slot: {}, Old item: {}", -// bot->GetGUID().ToString().c_str(), IsAlliance(bot->getRace()) ? "A" : "H", -// bot->GetLevel(), bot->GetName(), newItemId, slot, itemInSlot); -// found = true; -// break; -// } -// } -// } -// else -// { -// std::vector ids = sRandomItemMgr->GetUpgradeList(bot, specName, slot, quality, itemInSlot); -// if (!ids.empty()) -// Shuffle(ids); - -// for (uint32 index = 0; index < ids.size(); ++index) -// { -// uint32 newItemId = ids[index]; -// uint16 dest; -// if (!CanEquipUnseenItem(slot, dest, newItemId)) -// continue; - -// Item* newItem = bot->EquipNewItem(dest, newItemId, true); -// if (newItem) -// { -// bot->AutoUnequipOffhandIfNeed(); -// newItem->SetOwnerGUID(bot->GetGUID()); -// EnchantItem(newItem); -// found = true; -// LOG_INFO("playerbots", "Bot {} {}:{} <{}>: Equip: {}, slot: {}", -// bot->GetGUID().ToString().c_str(), IsAlliance(bot->getRace()) ? "A" : "H", -// bot->GetLevel(), bot->GetName(), newItemId, slot); -// break; -// } -// } -// } -// quality--; -// } while (!found && quality != ITEM_QUALITY_POOR); -// if (!found) -// { -// LOG_INFO("playerbots", "Bot {} {}:{} <{}>: no item for slot {}", -// bot->GetGUID().ToString().c_str(), IsAlliance(bot->getRace()) ? "A" : "H", bot->GetLevel(), -// bot->GetName(), slot); -// continue; -// } -// } -// } - void PlayerbotFactory::InitEquipment(bool incremental, bool second_chance) { - if (incremental && !sPlayerbotAIConfig->incrementalGearInit) + if (incremental && !sPlayerbotAIConfig.incrementalGearInit) return; if (level < 5) @@ -1785,19 +1666,19 @@ void PlayerbotFactory::InitEquipment(bool incremental, bool second_chance) oldItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, slot); - int32 desiredQuality = itemQuality; - if (urand(0, 100) < 100 * sPlayerbotAIConfig->randomGearLoweringChance && desiredQuality > ITEM_QUALITY_NORMAL) + uint32_t desiredQuality = itemQuality; + if (urand(0, 100) < 100 * sPlayerbotAIConfig.randomGearLoweringChance && desiredQuality > ITEM_QUALITY_NORMAL) { desiredQuality--; } do { - for (uint32 requiredLevel = bot->GetLevel(); requiredLevel > std::max((int32)bot->GetLevel() - delta, 0); + for (uint32 requiredLevel = bot->GetLevel(); requiredLevel > std::max((int32)bot->GetLevel() - delta, 0); requiredLevel--) { for (InventoryType inventoryType : GetPossibleInventoryTypeListBySlot((EquipmentSlots)slot)) { - for (uint32 itemId : sRandomItemMgr->GetCachedEquipments(requiredLevel, inventoryType)) + for (uint32 itemId : sRandomItemMgr.GetCachedEquipments(requiredLevel, inventoryType)) { if (itemId == 46978) // shaman earth ring totem { @@ -1808,10 +1689,10 @@ void PlayerbotFactory::InitEquipment(bool incremental, bool second_chance) continue; // disable next expansion gear - if (sPlayerbotAIConfig->limitGearExpansion && bot->GetLevel() <= 60 && itemId >= 23728) + if (sPlayerbotAIConfig.limitGearExpansion && bot->GetLevel() <= 60 && itemId >= 23728) continue; - if (sPlayerbotAIConfig->limitGearExpansion && bot->GetLevel() <= 70 && itemId >= 35570 && + if (sPlayerbotAIConfig.limitGearExpansion && bot->GetLevel() <= 70 && itemId >= 35570 && itemId != 36737 && itemId != 37739 && itemId != 37740) // transition point from TBC -> WOTLK isn't as clear, and there are other // wearable TBC items above 35570 but nothing of significance @@ -1862,7 +1743,7 @@ void PlayerbotFactory::InitEquipment(bool incremental, bool second_chance) float bestScoreForSlot = -1; uint32 bestItemForSlot = 0; - for (int index = 0; index < ids.size(); index++) + for (size_t index = 0; index < ids.size(); index++) { uint32 newItemId = ids[index]; @@ -1916,7 +1797,7 @@ void PlayerbotFactory::InitEquipment(bool incremental, bool second_chance) if (oldItem) continue; - Item* newItem = bot->EquipNewItem(dest, bestItemForSlot, true); + bot->EquipNewItem(dest, bestItemForSlot, true); bot->AutoUnequipOffhandIfNeed(); // if (newItem) // { @@ -1947,7 +1828,7 @@ void PlayerbotFactory::InitEquipment(bool incremental, bool second_chance) (slot != EQUIPMENT_SLOT_RANGED)) continue; - if (Item* oldItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, slot)) + if (bot->GetItemByPos(INVENTORY_SLOT_BAG_0, slot) != nullptr) bot->DestroyItem(INVENTORY_SLOT_BAG_0, slot, true); std::vector& ids = items[slot]; @@ -1956,7 +1837,7 @@ void PlayerbotFactory::InitEquipment(bool incremental, bool second_chance) float bestScoreForSlot = -1; uint32 bestItemForSlot = 0; - for (int index = 0; index < ids.size(); index++) + for (size_t index = 0; index < ids.size(); index++) { uint32 newItemId = ids[index]; @@ -1985,7 +1866,7 @@ void PlayerbotFactory::InitEquipment(bool incremental, bool second_chance) { continue; } - Item* newItem = bot->EquipNewItem(dest, bestItemForSlot, true); + bot->EquipNewItem(dest, bestItemForSlot, true); bot->AutoUnequipOffhandIfNeed(); // if (newItem) // { @@ -1996,6 +1877,7 @@ void PlayerbotFactory::InitEquipment(bool incremental, bool second_chance) } } +// Unused method. bool PlayerbotFactory::IsDesiredReplacement(Item* item) { if (!item) @@ -2007,13 +1889,8 @@ bool PlayerbotFactory::IsDesiredReplacement(Item* item) { return true; } - // if (!requiredLevel) - // { - // requiredLevel = sRandomItemMgr->GetMinLevelFromCache(proto->ItemId); - // } - uint32 delta = 1 + (80 - bot->GetLevel()) / 10; - return proto->Quality < ITEM_QUALITY_RARE || int32(bot->GetLevel() - requiredLevel) > delta; + return proto->Quality < ITEM_QUALITY_RARE || (bot->GetLevel() - requiredLevel) > delta; } inline Item* StoreNewItemInInventorySlot(Player* player, uint32 newItemId, uint32 count) @@ -2031,115 +1908,6 @@ inline Item* StoreNewItemInInventorySlot(Player* player, uint32 newItemId, uint3 return nullptr; } -// void PlayerbotFactory::InitSecondEquipmentSet() -// { -// if (bot->getClass() == CLASS_MAGE || bot->getClass() == CLASS_WARLOCK || bot->getClass() == CLASS_PRIEST) -// return; - -// std::map> items; - -// uint32 desiredQuality = itemQuality; -// while (urand(0, 100) < 100 * sPlayerbotAIConfig->randomGearLoweringChance && desiredQuality > -// ITEM_QUALITY_NORMAL) -// { -// desiredQuality--; -// } - -// ItemTemplateContainer const* itemTemplate = sObjectMgr->GetItemTemplateStore(); -// do -// { -// for (auto const& itr : *itemTemplate) -// { -// ItemTemplate const* proto = &itr.second; -// if (!proto) -// continue; -// if (!CanEquipItem(proto, desiredQuality)) -// continue; - -// if (proto->Class == ITEM_CLASS_WEAPON) -// { -// //if (!CanEquipWeapon(proto)) -// // continue; - -// if (sRandomItemMgr->HasStatWeight(proto->ItemId)) -// { -// if (!sRandomItemMgr->GetLiveStatWeight(bot, proto->ItemId)) -// continue; -// } - -// Item* existingItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND); -// if (existingItem) -// { -// switch (existingItem->GetTemplate()->SubClass) -// { -// case ITEM_SUBCLASS_WEAPON_AXE: -// case ITEM_SUBCLASS_WEAPON_DAGGER: -// case ITEM_SUBCLASS_WEAPON_FIST: -// case ITEM_SUBCLASS_WEAPON_MACE: -// case ITEM_SUBCLASS_WEAPON_SWORD: -// if (proto->SubClass == ITEM_SUBCLASS_WEAPON_AXE || proto->SubClass == -// ITEM_SUBCLASS_WEAPON_DAGGER || proto->SubClass == ITEM_SUBCLASS_WEAPON_FIST || -// proto->SubClass == ITEM_SUBCLASS_WEAPON_MACE || proto->SubClass == -// ITEM_SUBCLASS_WEAPON_SWORD) continue; -// break; -// default: -// if (proto->SubClass != ITEM_SUBCLASS_WEAPON_AXE && proto->SubClass != -// ITEM_SUBCLASS_WEAPON_DAGGER && proto->SubClass != ITEM_SUBCLASS_WEAPON_FIST && -// proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE && proto->SubClass != -// ITEM_SUBCLASS_WEAPON_SWORD) continue; -// break; -// } -// } -// } -// else if (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD) -// { -// //if (!CanEquipArmor(proto)) -// // continue; - -// if (sRandomItemMgr->HasStatWeight(proto->ItemId)) -// { -// if (!sRandomItemMgr->GetLiveStatWeight(bot, proto->ItemId)) -// continue; -// } - -// if (Item* existingItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND)) -// if (existingItem->GetTemplate()->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD) -// continue; -// } -// else -// continue; - -// items[proto->Class].push_back(itr.first); -// } -// } while (items[ITEM_CLASS_ARMOR].empty() && items[ITEM_CLASS_WEAPON].empty() && desiredQuality-- > -// ITEM_QUALITY_NORMAL); - -// for (std::map>::iterator i = items.begin(); i != items.end(); ++i) -// { -// std::vector& ids = i->second; -// if (ids.empty()) -// { -// LOG_DEBUG("playerbots", "{}: no items to make second equipment set for slot {}", -// bot->GetName().c_str(), i->first); continue; -// } - -// for (uint32 attempts = 0; attempts < 15; attempts++) -// { -// uint32 index = urand(0, ids.size() - 1); -// uint32 newItemId = ids[index]; - -// if (Item* newItem = StoreNewItemInInventorySlot(bot, newItemId, 1)) -// { -// newItem->SetOwnerGUID(bot->GetGUID()); -// EnchantItem(newItem); -// newItem->AddToWorld(); -// newItem->AddToUpdateQueueOf(bot); -// break; -// } -// } -// } -// } - void PlayerbotFactory::InitBags(bool destroyOld) { for (uint8 slot = INVENTORY_SLOT_BAG_START; slot < INVENTORY_SLOT_BAG_END; ++slot) @@ -2162,7 +1930,9 @@ void PlayerbotFactory::InitBags(bool destroyOld) { continue; } - Item* newItem = bot->EquipNewItem(dest, newItemId, true); + + bot->EquipNewItem(dest, newItemId, true); + // if (newItem) // { // newItem->AddToWorld(); @@ -2173,10 +1943,10 @@ void PlayerbotFactory::InitBags(bool destroyOld) void PlayerbotFactory::EnchantItem(Item* item) { - if (bot->GetLevel() < sPlayerbotAIConfig->minEnchantingBotLevel) + if (bot->GetLevel() < sPlayerbotAIConfig.minEnchantingBotLevel) return; - if (urand(0, 100) < 100 * sPlayerbotAIConfig->randomGearLoweringChance) + if (urand(0, 100) < 100 * sPlayerbotAIConfig.randomGearLoweringChance) return; ItemTemplate const* proto = item->GetTemplate(); @@ -2277,10 +2047,11 @@ bool PlayerbotFactory::CanEquipUnseenItem(uint8 slot, uint16& dest, uint32 item) return false; } +// Unused method but looks pretty good. void PlayerbotFactory::InitTradeSkills() { - uint16 firstSkill = sRandomPlayerbotMgr->GetValue(bot, "firstSkill"); - uint16 secondSkill = sRandomPlayerbotMgr->GetValue(bot, "secondSkill"); + uint16 firstSkill = sRandomPlayerbotMgr.GetValue(bot, "firstSkill"); + uint16 secondSkill = sRandomPlayerbotMgr.GetValue(bot, "secondSkill"); if (!firstSkill || !secondSkill) { std::vector firstSkills; @@ -2332,8 +2103,8 @@ void PlayerbotFactory::InitTradeSkills() break; } - sRandomPlayerbotMgr->SetValue(bot, "firstSkill", firstSkill); - sRandomPlayerbotMgr->SetValue(bot, "secondSkill", secondSkill); + sRandomPlayerbotMgr.SetValue(bot, "firstSkill", firstSkill); + sRandomPlayerbotMgr.SetValue(bot, "secondSkill", secondSkill); } SetRandomSkill(SKILL_FIRST_AID); @@ -2355,17 +2126,16 @@ void PlayerbotFactory::UpdateTradeSkills() void PlayerbotFactory::InitSkills() { - //uint32 maxValue = level * 5; //not used, line marked for removal. bot->UpdateSkillsForLevel(); bot->SetSkill(SKILL_RIDING, 0, 0, 0); - if (bot->GetLevel() >= sPlayerbotAIConfig->useGroundMountAtMinLevel) + if (bot->GetLevel() >= sPlayerbotAIConfig.useGroundMountAtMinLevel) bot->learnSpell(33388); - if (bot->GetLevel() >= sPlayerbotAIConfig->useFastGroundMountAtMinLevel) + if (bot->GetLevel() >= sPlayerbotAIConfig.useFastGroundMountAtMinLevel) bot->learnSpell(33391); - if (bot->GetLevel() >= sPlayerbotAIConfig->useFlyMountAtMinLevel) + if (bot->GetLevel() >= sPlayerbotAIConfig.useFlyMountAtMinLevel) bot->learnSpell(34090); - if (bot->GetLevel() >= sPlayerbotAIConfig->useFastFlyMountAtMinLevel) + if (bot->GetLevel() >= sPlayerbotAIConfig.useFastFlyMountAtMinLevel) bot->learnSpell(34091); uint32 skillLevel = bot->GetLevel() < 40 ? 0 : 1; @@ -2484,20 +2254,6 @@ void PlayerbotFactory::InitSkills() default: break; } - - // switch (bot->getClass()) - // { - // case CLASS_WARRIOR: - // case CLASS_PALADIN: - // bot->SetSkill(SKILL_PLATE_MAIL, 0, skillLevel, skillLevel); - // break; - // case CLASS_SHAMAN: - // case CLASS_HUNTER: - // bot->SetSkill(SKILL_MAIL, 0, skillLevel, skillLevel); - // break; - // default: - // break; - // } } void PlayerbotFactory::SetRandomSkill(uint16 id) @@ -2680,8 +2436,8 @@ void PlayerbotFactory::InitClassSpells() void PlayerbotFactory::InitSpecialSpells() { - for (std::vector::iterator i = sPlayerbotAIConfig->randomBotSpellIds.begin(); - i != sPlayerbotAIConfig->randomBotSpellIds.end(); ++i) + for (std::vector::iterator i = sPlayerbotAIConfig.randomBotSpellIds.begin(); + i != sPlayerbotAIConfig.randomBotSpellIds.end(); ++i) { uint32 spellId = *i; bot->learnSpell(spellId); @@ -2729,7 +2485,7 @@ void PlayerbotFactory::InitTalents(uint32 specNo) int index = urand(0, spells_row.size() - 1); TalentEntry const* talentInfo = spells_row[index]; int maxRank = 0; - for (int rank = 0; rank < std::min((uint32)MAX_TALENT_RANK, bot->GetFreeTalentPoints()); ++rank) + for (uint32_t rank = 0; rank < std::min((uint32)MAX_TALENT_RANK, bot->GetFreeTalentPoints()); ++rank) { uint32 spellId = talentInfo->RankID[rank]; if (!spellId) @@ -2752,13 +2508,13 @@ void PlayerbotFactory::InitTalents(uint32 specNo) void PlayerbotFactory::InitTalentsByTemplate(uint32 specTab) { - // if (sPlayerbotAIConfig->parsedSpecLinkOrder[bot->getClass()][specNo][80].size() == 0) + // if (sPlayerbotAIConfig.parsedSpecLinkOrder[bot->getClass()][specNo][80].size() == 0) // { // return; // } uint32 cls = bot->getClass(); int startLevel = bot->GetLevel(); - uint32 specIndex = sPlayerbotAIConfig->randomClassSpecIndex[cls][specTab]; + uint32 specIndex = sPlayerbotAIConfig.randomClassSpecIndex[cls][specTab]; uint32 classMask = bot->getClassMask(); std::unordered_map> spells_row; for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i) @@ -2777,23 +2533,23 @@ void PlayerbotFactory::InitTalentsByTemplate(uint32 specTab) spells_row[talentInfo->Row].push_back(talentInfo); } while (startLevel > 1 && startLevel < 80 && - sPlayerbotAIConfig->parsedSpecLinkOrder[cls][specIndex][startLevel].size() == 0) + sPlayerbotAIConfig.parsedSpecLinkOrder[cls][specIndex][startLevel].size() == 0) { startLevel--; } for (int level = startLevel; level <= 80; level++) { - if (sPlayerbotAIConfig->parsedSpecLinkOrder[cls][specIndex][level].size() == 0) + if (sPlayerbotAIConfig.parsedSpecLinkOrder[cls][specIndex][level].size() == 0) { continue; } - for (std::vector& p : sPlayerbotAIConfig->parsedSpecLinkOrder[cls][specIndex][level]) + for (std::vector& p : sPlayerbotAIConfig.parsedSpecLinkOrder[cls][specIndex][level]) { uint32 tab = p[0], row = p[1], col = p[2], lvl = p[3]; - if (sPlayerbotAIConfig->limitTalentsExpansion && bot->GetLevel() <= 60 && (row > 6 || (row == 6 && col != 1))) + if (sPlayerbotAIConfig.limitTalentsExpansion && bot->GetLevel() <= 60 && (row > 6 || (row == 6 && col != 1))) continue; - if (sPlayerbotAIConfig->limitTalentsExpansion && bot->GetLevel() <= 70 && (row > 8 || (row == 8 && col != 1))) + if (sPlayerbotAIConfig.limitTalentsExpansion && bot->GetLevel() <= 70 && (row > 8 || (row == 8 && col != 1))) continue; uint32 talentID = 0; @@ -2848,8 +2604,8 @@ void PlayerbotFactory::InitTalentsByTemplate(uint32 specTab) ObjectGuid PlayerbotFactory::GetRandomBot() { GuidVector guids; - for (std::vector::iterator i = sPlayerbotAIConfig->randomBotAccounts.begin(); - i != sPlayerbotAIConfig->randomBotAccounts.end(); i++) + for (std::vector::iterator i = sPlayerbotAIConfig.randomBotAccounts.begin(); + i != sPlayerbotAIConfig.randomBotAccounts.end(); i++) { uint32 accountId = *i; if (!AccountMgr::GetCharactersCount(accountId)) @@ -2891,7 +2647,6 @@ void PlayerbotFactory::AddPrevQuests(uint32 questId, std::list& questIds void PlayerbotFactory::InitQuests(std::list& questMap, bool withRewardItem) { - uint32 count = 0; for (std::list::iterator i = questMap.begin(); i != questMap.end(); ++i) { uint32 questId = *i; @@ -2945,6 +2700,8 @@ void PlayerbotFactory::InitInstanceQuests() void PlayerbotFactory::ClearInventory() { + LOG_ERROR("playerbots", "Clearing inventory for {}", bot->GetName()); + DestroyItemsVisitor visitor(bot); IterateItems(&visitor); } @@ -2981,7 +2738,7 @@ void PlayerbotFactory::InitAmmo() if (!subClass) return; - std::vector ammoEntryList = sRandomItemMgr->GetAmmo(level, subClass); + std::vector ammoEntryList = sRandomItemMgr.GetAmmo(level, subClass); uint32 entry = 0; for (uint32 tEntry : ammoEntryList) { @@ -2990,10 +2747,10 @@ void PlayerbotFactory::InitAmmo() continue; // disable next expansion ammo - if (sPlayerbotAIConfig->limitGearExpansion && bot->GetLevel() <= 60 && tEntry >= 23728) + if (sPlayerbotAIConfig.limitGearExpansion && bot->GetLevel() <= 60 && tEntry >= 23728) continue; - if (sPlayerbotAIConfig->limitGearExpansion && bot->GetLevel() <= 70 && tEntry >= 35570) + if (sPlayerbotAIConfig.limitGearExpansion && bot->GetLevel() <= 70 && tEntry >= 35570) continue; entry = tEntry; @@ -3023,10 +2780,10 @@ uint32 PlayerbotFactory::CalcMixedGearScore(uint32 gs, uint32 quality) void PlayerbotFactory::InitMounts() { - uint32 firstmount = sPlayerbotAIConfig->useGroundMountAtMinLevel; - uint32 secondmount = sPlayerbotAIConfig->useFastGroundMountAtMinLevel; - uint32 thirdmount = sPlayerbotAIConfig->useFlyMountAtMinLevel; - uint32 fourthmount = sPlayerbotAIConfig->useFastFlyMountAtMinLevel; + uint32 firstmount = sPlayerbotAIConfig.useGroundMountAtMinLevel; + uint32 secondmount = sPlayerbotAIConfig.useFastGroundMountAtMinLevel; + uint32 thirdmount = sPlayerbotAIConfig.useFlyMountAtMinLevel; + uint32 fourthmount = sPlayerbotAIConfig.useFastFlyMountAtMinLevel; if (bot->GetLevel() < firstmount) return; @@ -3165,7 +2922,7 @@ void PlayerbotFactory::InitPotions() if (!visitor.GetResult().empty()) continue; - uint32 itemId = sRandomItemMgr->GetRandomPotion(level, effect); + uint32 itemId = sRandomItemMgr.GetRandomPotion(level, effect); if (!itemId) { // LOG_INFO("playerbots", "No potions (type {}) available for bot {} ({} level)", effect, @@ -3263,7 +3020,7 @@ void PlayerbotFactory::InitFood() } uint32 categories[] = {11, 59}; - for (int i = 0; i < sizeof(categories) / sizeof(uint32); ++i) + for (uint64_t i = 0; i < sizeof(categories) / sizeof(uint32); ++i) { uint32 category = categories[i]; std::vector& ids = items[category]; @@ -3296,7 +3053,6 @@ void PlayerbotFactory::InitFood() void PlayerbotFactory::InitReagents() { - int specTab = AiFactory::GetPlayerSpecTab(bot); std::vector> items; switch (bot->getClass()) { @@ -3499,7 +3255,7 @@ void PlayerbotFactory::InitGlyphs(bool increment) } } - if (sPlayerbotAIConfig->limitTalentsExpansion && bot->GetLevel() <= 70) + if (sPlayerbotAIConfig.limitTalentsExpansion && bot->GetLevel() <= 70) { bot->SendTalentsInfoData(false); return; @@ -3722,10 +3478,10 @@ void PlayerbotFactory::InitGlyphs(bool increment) // GlyphSlotEntry const *gs = sGlyphSlotStore.LookupEntry(slot); // if (!gs) // continue; - if (sPlayerbotAIConfig->parsedSpecGlyph[cls][tab].size() > slotIndex && - sPlayerbotAIConfig->parsedSpecGlyph[cls][tab][slotIndex] != 0) + if (sPlayerbotAIConfig.parsedSpecGlyph[cls][tab].size() > slotIndex && + sPlayerbotAIConfig.parsedSpecGlyph[cls][tab][slotIndex] != 0) { - uint32 itemId = sPlayerbotAIConfig->parsedSpecGlyph[cls][tab][slotIndex]; + uint32 itemId = sPlayerbotAIConfig.parsedSpecGlyph[cls][tab][slotIndex]; ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId); if (proto->Class != ITEM_CLASS_GLYPH) continue; @@ -3859,7 +3615,7 @@ Item* PlayerbotFactory::StoreItem(uint32 itemId, uint32 count) void PlayerbotFactory::InitInventoryTrade() { - uint32 itemId = sRandomItemMgr->GetRandomTrade(level); + uint32 itemId = sRandomItemMgr.GetRandomTrade(level); if (!itemId) { LOG_ERROR("playerbots", "No trade items available for bot {} ({} level)", bot->GetName().c_str(), @@ -3895,7 +3651,7 @@ void PlayerbotFactory::InitInventoryEquip() std::vector ids; uint32 desiredQuality = itemQuality; - if (urand(0, 100) < 100 * sPlayerbotAIConfig->randomGearLoweringChance && desiredQuality > ITEM_QUALITY_NORMAL) + if (urand(0, 100) < 100 * sPlayerbotAIConfig.randomGearLoweringChance && desiredQuality > ITEM_QUALITY_NORMAL) { desiredQuality--; } @@ -3949,21 +3705,21 @@ void PlayerbotFactory::InitGuild() return; } - std::string guildName = sPlayerbotGuildMgr->AssignToGuild(bot); + std::string guildName = PlayerbotGuildMgr::instance().AssignToGuild(bot); if (guildName.empty()) return; Guild* guild = sGuildMgr->GetGuildByName(guildName); if (!guild) { - if (!sPlayerbotGuildMgr->CreateGuild(bot, guildName)) + if (!PlayerbotGuildMgr::instance().CreateGuild(bot, guildName)) LOG_ERROR("playerbots","Failed to create guild {} for bot {}", guildName, bot->GetName()); return; } else { if (guild->AddMember(bot->GetGUID(),urand(GR_OFFICER, GR_INITIATE))) - sPlayerbotGuildMgr->OnGuildUpdate(guild); + PlayerbotGuildMgr::instance().OnGuildUpdate(guild); else LOG_ERROR("playerbots","Bot {} failed to join guild {}.", bot->GetName(), guildName); } @@ -3972,6 +3728,7 @@ void PlayerbotFactory::InitGuild() StoreItem(5976, 1); } +// Unused method void PlayerbotFactory::InitImmersive() { uint32 owner = bot->GetGUID().GetCounter(); @@ -3985,7 +3742,7 @@ void PlayerbotFactory::InitImmersive() std::ostringstream name; name << "immersive_stat_" << i; - uint32 value = sRandomPlayerbotMgr->GetValue(owner, name.str()); + uint32 value = sRandomPlayerbotMgr.GetValue(owner, name.str()); if (value) initialized = true; @@ -4058,7 +3815,7 @@ void PlayerbotFactory::InitImmersive() std::ostringstream name; name << "immersive_stat_" << i; - sRandomPlayerbotMgr->SetValue(owner, name.str(), percentMap[type]); + sRandomPlayerbotMgr.SetValue(owner, name.str(), percentMap[type]); } } } @@ -4066,15 +3823,15 @@ void PlayerbotFactory::InitImmersive() void PlayerbotFactory::InitArenaTeam() { - if (!sPlayerbotAIConfig->IsInRandomAccountList(bot->GetSession()->GetAccountId())) + if (!sPlayerbotAIConfig.IsInRandomAccountList(bot->GetSession()->GetAccountId())) return; // Currently the teams are only remade after a server restart and if deleteRandomBotArenaTeams = 1 // This is because randomBotArenaTeams is only empty on server restart. // A manual reinitalization (.playerbots rndbot init) is also required after the teams have been deleted. - if (sPlayerbotAIConfig->randomBotArenaTeams.empty()) + if (sPlayerbotAIConfig.randomBotArenaTeams.empty()) { - if (sPlayerbotAIConfig->deleteRandomBotArenaTeams) + if (sPlayerbotAIConfig.deleteRandomBotArenaTeams) { LOG_INFO("playerbots", "Deleting random bot arena teams..."); @@ -4099,14 +3856,14 @@ void PlayerbotFactory::InitArenaTeam() LOG_INFO("playerbots", "Random bot arena teams deleted"); } - RandomPlayerbotFactory::CreateRandomArenaTeams(ARENA_TYPE_2v2, sPlayerbotAIConfig->randomBotArenaTeam2v2Count); - RandomPlayerbotFactory::CreateRandomArenaTeams(ARENA_TYPE_3v3, sPlayerbotAIConfig->randomBotArenaTeam3v3Count); - RandomPlayerbotFactory::CreateRandomArenaTeams(ARENA_TYPE_5v5, sPlayerbotAIConfig->randomBotArenaTeam5v5Count); + RandomPlayerbotFactory::CreateRandomArenaTeams(ARENA_TYPE_2v2, sPlayerbotAIConfig.randomBotArenaTeam2v2Count); + RandomPlayerbotFactory::CreateRandomArenaTeams(ARENA_TYPE_3v3, sPlayerbotAIConfig.randomBotArenaTeam3v3Count); + RandomPlayerbotFactory::CreateRandomArenaTeams(ARENA_TYPE_5v5, sPlayerbotAIConfig.randomBotArenaTeam5v5Count); } std::vector arenateams; - for (std::vector::iterator i = sPlayerbotAIConfig->randomBotArenaTeams.begin(); - i != sPlayerbotAIConfig->randomBotArenaTeams.end(); ++i) + for (std::vector::iterator i = sPlayerbotAIConfig.randomBotArenaTeams.begin(); + i != sPlayerbotAIConfig.randomBotArenaTeams.end(); ++i) arenateams.push_back(*i); if (arenateams.empty()) @@ -4282,13 +4039,13 @@ void PlayerbotFactory::ApplyEnchantTemplate(uint8 spec) // const SpellItemEnchantmentEntry* a = sSpellItemEnchantmentStore.LookupEntry(1); } -void PlayerbotFactory::ApplyEnchantAndGemsNew(bool destroyOld) +void PlayerbotFactory::ApplyEnchantAndGemsNew(bool) { //int32 bestGemEnchantId[4] = {-1, -1, -1, -1}; // 1, 2, 4, 8 color //not used, line marked for removal. //float bestGemScore[4] = {0, 0, 0, 0}; //not used, line marked for removal. std::vector curCount = GetCurrentGemsCount(); uint8 jewelersCount = 0; - int requiredActive = 2; + const uint8_t requiredActive = 2; std::vector availableGems; for (const uint32& enchantGem : enchantGemIdCache) { @@ -4300,7 +4057,7 @@ void PlayerbotFactory::ApplyEnchantAndGemsNew(bool destroyOld) if (!gemProperties) continue; - if (sPlayerbotAIConfig->limitEnchantExpansion && bot->GetLevel() <= 70 && enchantGem >= 39900) + if (sPlayerbotAIConfig.limitEnchantExpansion && bot->GetLevel() <= 70 && enchantGem >= 39900) continue; uint32 requiredLevel = gemTemplate->ItemLevel; @@ -4363,10 +4120,10 @@ void PlayerbotFactory::ApplyEnchantAndGemsNew(bool destroyOld) } // disable next expansion enchantments - if (sPlayerbotAIConfig->limitEnchantExpansion && bot->GetLevel() <= 60 && enchantSpell >= 27899) + if (sPlayerbotAIConfig.limitEnchantExpansion && bot->GetLevel() <= 60 && enchantSpell >= 27899) continue; - if (sPlayerbotAIConfig->limitEnchantExpansion && bot->GetLevel() <= 70 && enchantSpell >= 44483) + if (sPlayerbotAIConfig.limitEnchantExpansion && bot->GetLevel() <= 70 && enchantSpell >= 44483) continue; for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j) @@ -4419,7 +4176,6 @@ void PlayerbotFactory::ApplyEnchantAndGemsNew(bool destroyOld) continue; } int32 enchantIdChosen = -1; - int32 colorChosen; bool jewelersGemChosen; float bestGemScore = -1; for (uint32& enchantGem : availableGems) @@ -4450,7 +4206,7 @@ void PlayerbotFactory::ApplyEnchantAndGemsNew(bool destroyOld) if (curCount[0] != 0) { // Ensure meta gem activation - for (int i = 1; i < curCount.size(); i++) + for (size_t i = 1; i < curCount.size(); i++) { if (curCount[i] < requiredActive && (gemProperties->color & (1 << i))) { @@ -4464,7 +4220,6 @@ void PlayerbotFactory::ApplyEnchantAndGemsNew(bool destroyOld) if (score > bestGemScore) { enchantIdChosen = enchant_id; - colorChosen = gemProperties->color; bestGemScore = score; jewelersGemChosen = isJewelersGem; } diff --git a/src/Bot/Factory/RandomPlayerbotFactory.cpp b/src/Bot/Factory/RandomPlayerbotFactory.cpp index 5a4672f5eb..997182012f 100644 --- a/src/Bot/Factory/RandomPlayerbotFactory.cpp +++ b/src/Bot/Factory/RandomPlayerbotFactory.cpp @@ -8,17 +8,12 @@ #include "AccountMgr.h" #include "ArenaTeamMgr.h" #include "DatabaseEnv.h" -#include "GuildMgr.h" -#include "PlayerbotFactory.h" -#include "Playerbots.h" -#include "PlayerbotGuildMgr.h" +#include "PlayerbotAI.h" #include "ScriptMgr.h" #include "SharedDefines.h" #include "SocialMgr.h" #include "Timer.h" -#include "Guild.h" // EmblemInfo::SaveToDB #include "Log.h" -#include "GuildMgr.h" constexpr RandomPlayerbotFactory::NameRaceAndGender RandomPlayerbotFactory::CombineRaceAndGender(uint8 race, uint8 gender) @@ -244,7 +239,7 @@ std::string const RandomPlayerbotFactory::CreateRandomBotName(NameRaceAndGender botName += (botName.size() < 2) ? groupFormEnd[gender][rand() % 4] : ""; // Replace Catagory value with random Letter from that Catagory's Letter string for a given bot gender - for (int i = 0; i < botName.size(); i++) + for (size_t i = 0; i < botName.size(); i++) { botName[i] = groupLetter[gender][groupCategory.find(botName[i])] [rand() % groupLetter[gender][groupCategory.find(botName[i])].size()]; @@ -277,7 +272,7 @@ std::string const RandomPlayerbotFactory::CreateRandomBotName(NameRaceAndGender botName.clear(); continue; } - return std::move(botName); + return botName; } // TRUE RANDOM NAME GENERATION @@ -302,11 +297,11 @@ std::string const RandomPlayerbotFactory::CreateRandomBotName(NameRaceAndGender botName.clear(); continue; } - return std::move(botName); + return botName; } LOG_ERROR("playerbots", "Random name generation failed."); botName.clear(); - return std::move(botName); + return botName; } // Calculates the total number of required accounts, either using the specified randomBotAccountCount @@ -317,14 +312,14 @@ uint32 RandomPlayerbotFactory::CalculateTotalAccountCount() { // Reset account types if features are disabled // Reset is done here to precede needed accounts calculations - if (sPlayerbotAIConfig->maxRandomBots == 0 || sPlayerbotAIConfig->addClassAccountPoolSize == 0) + if (sPlayerbotAIConfig.maxRandomBots == 0 || sPlayerbotAIConfig.addClassAccountPoolSize == 0) { - if (sPlayerbotAIConfig->maxRandomBots == 0) + if (sPlayerbotAIConfig.maxRandomBots == 0) { PlayerbotsDatabase.Execute("UPDATE playerbots_account_type SET account_type = 0 WHERE account_type = 1"); LOG_INFO("playerbots", "MaxRandomBots set to 0, any RNDbot accounts (type 1) will be unassigned (type 0)"); } - if (sPlayerbotAIConfig->addClassAccountPoolSize == 0) + if (sPlayerbotAIConfig.addClassAccountPoolSize == 0) { PlayerbotsDatabase.Execute("UPDATE playerbots_account_type SET account_type = 0 WHERE account_type = 2"); LOG_INFO("playerbots", "AddClassAccountPoolSize set to 0, any AddClass accounts (type 2) will be unassigned (type 0)"); @@ -334,8 +329,8 @@ uint32 RandomPlayerbotFactory::CalculateTotalAccountCount() for (int waited = 0; waited < 1000; waited += 50) { QueryResult res = PlayerbotsDatabase.Query("SELECT COUNT(*) FROM playerbots_account_type WHERE account_type IN ({}, {})", - sPlayerbotAIConfig->maxRandomBots == 0 ? 1 : -1, - sPlayerbotAIConfig->addClassAccountPoolSize == 0 ? 2 : -1); + sPlayerbotAIConfig.maxRandomBots == 0 ? 1 : -1, + sPlayerbotAIConfig.addClassAccountPoolSize == 0 ? 2 : -1); if (!res || res->Fetch()[0].Get() == 0) { @@ -347,8 +342,8 @@ uint32 RandomPlayerbotFactory::CalculateTotalAccountCount() } // Checks if randomBotAccountCount is set, otherwise calculate it dynamically. - if (sPlayerbotAIConfig->randomBotAccountCount > 0) - return sPlayerbotAIConfig->randomBotAccountCount; + if (sPlayerbotAIConfig.randomBotAccountCount > 0) + return sPlayerbotAIConfig.randomBotAccountCount; // Check existing account types uint32 existingRndBotAccounts = 0; @@ -374,17 +369,17 @@ uint32 RandomPlayerbotFactory::CalculateTotalAccountCount() int divisor = CalculateAvailableCharsPerAccount(); // Calculate max bots - int maxBots = sPlayerbotAIConfig->maxRandomBots; + int maxBots = sPlayerbotAIConfig.maxRandomBots; // Take periodic online - offline into account - if (sPlayerbotAIConfig->enablePeriodicOnlineOffline) + if (sPlayerbotAIConfig.enablePeriodicOnlineOffline) { - maxBots *= sPlayerbotAIConfig->periodicOnlineOfflineRatio; + maxBots *= sPlayerbotAIConfig.periodicOnlineOfflineRatio; } // Calculate number of accounts needed for RNDbots // Result is rounded up for maxBots not cleanly divisible by the divisor uint32 neededRndBotAccounts = (maxBots + divisor - 1) / divisor; - uint32 neededAddClassAccounts = sPlayerbotAIConfig->addClassAccountPoolSize; + uint32 neededAddClassAccounts = sPlayerbotAIConfig.addClassAccountPoolSize; // Start with existing total uint32 existingTotal = existingRndBotAccounts + existingAddClassAccounts + existingUnassignedAccounts; @@ -425,12 +420,12 @@ uint32 RandomPlayerbotFactory::CalculateTotalAccountCount() uint32 RandomPlayerbotFactory::CalculateAvailableCharsPerAccount() { - bool noDK = sPlayerbotAIConfig->disableDeathKnightLogin || sWorld->getIntConfig(CONFIG_EXPANSION) != EXPANSION_WRATH_OF_THE_LICH_KING; + bool noDK = sPlayerbotAIConfig.disableDeathKnightLogin || sWorld->getIntConfig(CONFIG_EXPANSION) != EXPANSION_WRATH_OF_THE_LICH_KING; uint32 availableChars = noDK ? 9 : 10; - uint32 hordeRatio = sPlayerbotAIConfig->randomBotHordeRatio; - uint32 allianceRatio = sPlayerbotAIConfig->randomBotAllianceRatio; + uint32 hordeRatio = sPlayerbotAIConfig.randomBotHordeRatio; + uint32 allianceRatio = sPlayerbotAIConfig.randomBotAllianceRatio; // horde : alliance = 50 : 50 -> 0% // horde : alliance = 0 : 50 -> 50% @@ -451,7 +446,7 @@ void RandomPlayerbotFactory::CreateRandomBots() { /* multi-thread here is meaningless? since the async db operations */ - if (sPlayerbotAIConfig->deleteRandomBotAccounts) + if (sPlayerbotAIConfig.deleteRandomBotAccounts) { std::vector botAccounts; std::vector botFriends; @@ -462,7 +457,7 @@ void RandomPlayerbotFactory::CreateRandomBots() for (uint32 accountNumber = 0; accountNumber < totalAccountCount; ++accountNumber) { std::ostringstream out; - out << sPlayerbotAIConfig->randomBotAccountPrefix << accountNumber; + out << sPlayerbotAIConfig.randomBotAccountPrefix << accountNumber; std::string const accountName = out.str(); if (uint32 accountId = AccountMgr::GetId(accountName)) @@ -482,7 +477,7 @@ void RandomPlayerbotFactory::CreateRandomBots() // Delete all characters from bot accounts CharacterDatabase.Execute("DELETE FROM characters WHERE account IN (SELECT id FROM " + loginDBName + ".account WHERE username LIKE '{}%%')", - sPlayerbotAIConfig->randomBotAccountPrefix.c_str()); + sPlayerbotAIConfig.randomBotAccountPrefix.c_str()); // Wait for the characters to be deleted before proceeding to dependent deletes while (CharacterDatabase.QueueSize()) @@ -496,7 +491,7 @@ void RandomPlayerbotFactory::CreateRandomBots() // Clean up orphaned entries in playerbots_db_store PlayerbotsDatabase.Execute("DELETE FROM playerbots_db_store WHERE guid NOT IN (SELECT guid FROM " + characterDBName + ".characters WHERE account IN (SELECT id FROM " + loginDBName + ".account WHERE username NOT LIKE '{}%%'))", - sPlayerbotAIConfig->randomBotAccountPrefix.c_str()); + sPlayerbotAIConfig.randomBotAccountPrefix.c_str()); // Clean up orphaned records in character-related tables CharacterDatabase.Execute("DELETE FROM arena_team_member WHERE guid NOT IN (SELECT guid FROM characters)"); @@ -551,7 +546,7 @@ void RandomPlayerbotFactory::CreateRandomBots() // Finally, delete the bot accounts themselves LOG_INFO("playerbots", "Deleting random bot accounts..."); QueryResult results = LoginDatabase.Query("SELECT id FROM account WHERE username LIKE '{}%%'", - sPlayerbotAIConfig->randomBotAccountPrefix.c_str()); + sPlayerbotAIConfig.randomBotAccountPrefix.c_str()); int32 deletion_count = 0; if (results) { @@ -601,7 +596,7 @@ void RandomPlayerbotFactory::CreateRandomBots() for (uint32 accountNumber = 0; accountNumber < totalAccountCount; ++accountNumber) { std::ostringstream out; - out << sPlayerbotAIConfig->randomBotAccountPrefix << accountNumber; + out << sPlayerbotAIConfig.randomBotAccountPrefix << accountNumber; std::string const accountName = out.str(); LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_ACCOUNT_ID_BY_USERNAME); @@ -613,7 +608,7 @@ void RandomPlayerbotFactory::CreateRandomBots() } account_creation++; std::string password = ""; - if (sPlayerbotAIConfig->randomBotRandomPassword) + if (sPlayerbotAIConfig.randomBotRandomPassword) { for (int i = 0; i < 10; i++) { @@ -649,7 +644,7 @@ void RandomPlayerbotFactory::CreateRandomBots() for (uint32 accountNumber = 0; accountNumber < totalAccountCount; ++accountNumber) { std::ostringstream out; - out << sPlayerbotAIConfig->randomBotAccountPrefix << accountNumber; + out << sPlayerbotAIConfig.randomBotAccountPrefix << accountNumber; std::string const accountName = out.str(); LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_ACCOUNT_ID_BY_USERNAME); @@ -661,7 +656,7 @@ void RandomPlayerbotFactory::CreateRandomBots() Field* fields = result->Fetch(); uint32 accountId = fields[0].Get(); - sPlayerbotAIConfig->randomBotAccounts.push_back(accountId); + sPlayerbotAIConfig.randomBotAccounts.push_back(accountId); uint32 count = AccountMgr::GetCharactersCount(accountId); if (count >= 10) @@ -746,13 +741,13 @@ void RandomPlayerbotFactory::CreateRandomBots() for (WorldSession* session : sessionBots) delete session; - for (uint32 accountId : sPlayerbotAIConfig->randomBotAccounts) + for (uint32 accountId : sPlayerbotAIConfig.randomBotAccounts) { totalRandomBotChars += AccountMgr::GetCharactersCount(accountId); } LOG_INFO("server.loading", ">> {} random bot accounts with {} characters available", - sPlayerbotAIConfig->randomBotAccounts.size(), totalRandomBotChars); + sPlayerbotAIConfig.randomBotAccounts.size(), totalRandomBotChars); } std::string const RandomPlayerbotFactory::CreateRandomGuildName() @@ -763,7 +758,7 @@ std::string const RandomPlayerbotFactory::CreateRandomGuildName() if (!result) { LOG_ERROR("playerbots", "No more names left for random guilds"); - return std::move(guildName); + return guildName; } Field* fields = result->Fetch(); @@ -777,13 +772,13 @@ std::string const RandomPlayerbotFactory::CreateRandomGuildName() if (!result) { LOG_ERROR("playerbots", "No more names left for random guilds"); - return std::move(guildName); + return guildName; } fields = result->Fetch(); guildName = fields[0].Get(); - return std::move(guildName); + return guildName; } void RandomPlayerbotFactory::CreateRandomArenaTeams(ArenaType type, uint32 count) @@ -811,7 +806,7 @@ void RandomPlayerbotFactory::CreateRandomArenaTeams(ArenaType type, uint32 count if (arenateam) { ++arenaTeamNumber; - sPlayerbotAIConfig->randomBotArenaTeams.push_back(arenateam->GetId()); + sPlayerbotAIConfig.randomBotArenaTeams.push_back(arenateam->GetId()); } else { @@ -872,7 +867,7 @@ void RandomPlayerbotFactory::CreateRandomArenaTeams(ArenaType type, uint32 count // set random rating arenateam->SetRatingForAll( - urand(sPlayerbotAIConfig->randomBotArenaTeamMinRating, sPlayerbotAIConfig->randomBotArenaTeamMaxRating)); + urand(sPlayerbotAIConfig.randomBotArenaTeamMinRating, sPlayerbotAIConfig.randomBotArenaTeamMaxRating)); // set random emblem uint32 backgroundColor = urand(0xFF000000, 0xFFFFFFFF); @@ -891,7 +886,7 @@ void RandomPlayerbotFactory::CreateRandomArenaTeams(ArenaType type, uint32 count arenateam->SaveToDB(); sArenaTeamMgr->AddArenaTeam(arenateam); - sPlayerbotAIConfig->randomBotArenaTeams.push_back(arenateam->GetId()); + sPlayerbotAIConfig.randomBotArenaTeams.push_back(arenateam->GetId()); } LOG_DEBUG("playerbots", "{} random bot {}vs{} arena teams available", arenaTeamNumber, type, type); @@ -905,7 +900,7 @@ std::string const RandomPlayerbotFactory::CreateRandomArenaTeamName() if (!result) { LOG_ERROR("playerbots", "No more names left for random arena teams"); - return std::move(arenaTeamName); + return arenaTeamName; } Field* fields = result->Fetch(); @@ -920,11 +915,11 @@ std::string const RandomPlayerbotFactory::CreateRandomArenaTeamName() if (!result) { LOG_ERROR("playerbots", "No more names left for random arena teams"); - return std::move(arenaTeamName); + return arenaTeamName; } fields = result->Fetch(); arenaTeamName = fields[0].Get(); - return std::move(arenaTeamName); + return arenaTeamName; } diff --git a/src/Bot/PlayerbotAI.cpp b/src/Bot/PlayerbotAI.cpp index 39db7c5948..78e1b3ac0f 100644 --- a/src/Bot/PlayerbotAI.cpp +++ b/src/Bot/PlayerbotAI.cpp @@ -16,7 +16,6 @@ #include "CharacterPackets.h" #include "ChatHelper.h" #include "Common.h" -#include "CreatureAIImpl.h" #include "CreatureData.h" #include "EmoteAction.h" #include "Engine.h" @@ -25,7 +24,6 @@ #include "GameObjectData.h" #include "GameTime.h" #include "GuildMgr.h" -#include "GuildTaskMgr.h" #include "LFGMgr.h" #include "LastMovementValue.h" #include "LastSpellCastValue.h" @@ -33,7 +31,6 @@ #include "LootObjectStack.h" #include "MapMgr.h" #include "MotionMaster.h" -#include "MoveSpline.h" #include "MoveSplineInit.h" #include "NewRpgStrategy.h" #include "ObjectGuid.h" @@ -41,11 +38,9 @@ #include "PerfMonitor.h" #include "Player.h" #include "PlayerbotAIConfig.h" -#include "PlayerbotRepository.h" #include "PlayerbotMgr.h" #include "PlayerbotGuildMgr.h" #include "Playerbots.h" -#include "PointMovementGenerator.h" #include "PositionValue.h" #include "RandomPlayerbotMgr.h" #include "SayAction.h" @@ -59,6 +54,7 @@ #include "Unit.h" #include "UpdateTime.h" #include "Vehicle.h" +#include "GlobalPlayerInspector.h" const int SPELL_TITAN_GRIP = 49152; @@ -153,7 +149,7 @@ PlayerbotAI::PlayerbotAI(Player* bot) engines[BOT_STATE_COMBAT] = AiFactory::createCombatEngine(bot, this, aiObjectContext); engines[BOT_STATE_NON_COMBAT] = AiFactory::createNonCombatEngine(bot, this, aiObjectContext); engines[BOT_STATE_DEAD] = AiFactory::createDeadEngine(bot, this, aiObjectContext); - if (sPlayerbotAIConfig->applyInstanceStrategies) + if (sPlayerbotAIConfig.applyInstanceStrategies) ApplyInstanceStrategies(bot->GetMapId()); currentEngine = engines[BOT_STATE_NON_COMBAT]; currentState = BOT_STATE_NON_COMBAT; @@ -233,7 +229,7 @@ PlayerbotAI::~PlayerbotAI() delete aiObjectContext; if (bot) - sPlayerbotsMgr->RemovePlayerBotData(bot->GetGUID(), true); + PlayerbotsMgr::instance().RemovePlayerBotData(bot->GetGUID(), true); } void PlayerbotAI::UpdateAI(uint32 elapsed, bool minimal) @@ -251,7 +247,7 @@ void PlayerbotAI::UpdateAI(uint32 elapsed, bool minimal) // Handle cheat options (set bot health and power if cheats are enabled) if (bot->IsAlive() && - (static_cast(GetCheat()) > 0 || static_cast(sPlayerbotAIConfig->botCheatMask) > 0)) + (static_cast(GetCheat()) > 0 || static_cast(sPlayerbotAIConfig.botCheatMask) > 0)) { if (HasCheat(BotCheatMask::health)) bot->SetFullHealth(); @@ -332,7 +328,7 @@ void PlayerbotAI::UpdateAI(uint32 elapsed, bool minimal) if (spellTarget && !bot->HasInArc(CAST_ANGLE_IN_FRONT, spellTarget) && (spellInfo->FacingCasterFlags & SPELL_FACING_FLAG_INFRONT)) { - sServerFacade->SetFacingTo(bot, spellTarget); + ServerFacade::instance().SetFacingTo(bot, spellTarget); } // Wait for spell cast @@ -387,7 +383,7 @@ void PlayerbotAI::UpdateAIGroupMaster() Group* group = bot->GetGroup(); - bool IsRandomBot = sRandomPlayerbotMgr->IsRandomBot(bot); + bool IsRandomBot = sRandomPlayerbotMgr.IsRandomBot(bot); // If bot is not in group verify that for is RandomBot before clearing master and resetting. if (!group) @@ -451,7 +447,7 @@ void PlayerbotAI::UpdateAIInternal([[maybe_unused]] uint32 elapsed, bool minimal std::string const mapString = WorldPosition(bot).isOverworld() ? std::to_string(bot->GetMapId()) : "I"; PerfMonitorOperation* pmo = - sPerfMonitor->start(PERF_MON_TOTAL, "PlayerbotAI::UpdateAIInternal " + mapString); + sPerfMonitor.start(PERF_MON_TOTAL, "PlayerbotAI::UpdateAIInternal " + mapString); ExternalEventHelper helper(aiObjectContext); // chat replies @@ -503,12 +499,12 @@ void PlayerbotAI::UpdateAIInternal([[maybe_unused]] uint32 elapsed, bool minimal } else { - sRandomPlayerbotMgr->LogoutPlayerBot(bot->GetGUID()); + sRandomPlayerbotMgr.LogoutPlayerBot(bot->GetGUID()); } return; } - SetNextCheckDelay(sPlayerbotAIConfig->reactDelay); + SetNextCheckDelay(sPlayerbotAIConfig.reactDelay); return; } @@ -583,10 +579,10 @@ void PlayerbotAI::HandleCommand(uint32 type, const std::string& text, Player& fr if (type == CHAT_MSG_SYSTEM) return; - if (filtered.find(sPlayerbotAIConfig->commandSeparator) != std::string::npos) + if (filtered.find(sPlayerbotAIConfig.commandSeparator) != std::string::npos) { std::vector commands; - split(commands, filtered, sPlayerbotAIConfig->commandSeparator.c_str()); + split(commands, filtered, sPlayerbotAIConfig.commandSeparator.c_str()); for (std::vector::iterator i = commands.begin(); i != commands.end(); ++i) { HandleCommand(type, *i, fromPlayer); @@ -594,12 +590,12 @@ void PlayerbotAI::HandleCommand(uint32 type, const std::string& text, Player& fr return; } - if (!sPlayerbotAIConfig->commandPrefix.empty()) + if (!sPlayerbotAIConfig.commandPrefix.empty()) { - if (filtered.find(sPlayerbotAIConfig->commandPrefix) != 0) + if (filtered.find(sPlayerbotAIConfig.commandPrefix) != 0) return; - filtered = filtered.substr(sPlayerbotAIConfig->commandPrefix.size()); + filtered = filtered.substr(sPlayerbotAIConfig.commandPrefix.size()); } if (chatMap.empty()) @@ -631,7 +627,7 @@ void PlayerbotAI::HandleCommand(uint32 type, const std::string& text, Player& fr WorldPacket data; ChatHandler::BuildChatPacket(data, CHAT_MSG_ADDON, response.c_str(), LANG_ADDON, CHAT_TAG_NONE, bot->GetGUID(), bot->GetName()); - sServerFacade->SendPacket(&fromPlayer, &data); + ServerFacade::instance().SendPacket(&fromPlayer, &data); return; } @@ -651,16 +647,31 @@ void PlayerbotAI::HandleCommand(uint32 type, const std::string& text, Player& fr (filtered.size() > 3 && filtered.substr(0, 3) == "do ")) { Event event("do", "", &fromPlayer); + std::string action = filtered.substr(filtered.find(" ") + 1); - DoSpecificAction(action, event); + + NextAction::Factory factory = ActionFactoryRegistry::GetFactoryByName(action); + + if (factory != nullptr) + { + this->DoSpecificAction(factory, event); + } } if (ChatHelper::parseValue("command", filtered).substr(0, 3) == "do ") { Event event("do", "", &fromPlayer); + std::string action = ChatHelper::parseValue("command", filtered); + action = action.substr(3); - DoSpecificAction(action, event); + + NextAction::Factory factory = ActionFactoryRegistry::GetFactoryByName(action); + + if (factory != nullptr) + { + this->DoSpecificAction(factory, event); + } } else if (type != CHAT_MSG_WHISPER && filtered.size() > 6 && filtered.substr(0, 6) == "queue ") { @@ -761,10 +772,10 @@ void PlayerbotAI::HandleTeleportAck() } // apply instance-related strategies after map attach - if (sPlayerbotAIConfig->applyInstanceStrategies) + if (sPlayerbotAIConfig.applyInstanceStrategies) ApplyInstanceStrategies(bot->GetMapId(), true); - if (sPlayerbotAIConfig->restrictHealerDPS) + if (sPlayerbotAIConfig.restrictHealerDPS) EvaluateHealerDpsStrategy(); // reset AI state after teleport @@ -855,7 +866,7 @@ void PlayerbotAI::Reset(bool full) aiObjectContext->GetValue("last taxi")->Get().Set(nullptr); aiObjectContext->GetValue("travel target") ->Get() - ->setTarget(sTravelMgr->nullTravelDestination, sTravelMgr->nullWorldPosition, true); + ->setTarget(TravelMgr::instance().nullTravelDestination, TravelMgr::instance().nullWorldPosition, true); aiObjectContext->GetValue("travel target")->Get()->setStatus(TRAVEL_STATUS_EXPIRED); aiObjectContext->GetValue("travel target")->Get()->setExpireIn(1000); rpgInfo = NewRpgInfo(); @@ -895,6 +906,7 @@ bool PlayerbotAI::IsAllowedCommand(std::string const text) unsecuredCommands.insert("invite"); unsecuredCommands.insert("leave"); unsecuredCommands.insert("lfg"); + unsecuredCommands.insert("pvp stats"); unsecuredCommands.insert("rpg status"); } @@ -920,10 +932,10 @@ void PlayerbotAI::HandleCommand(uint32 type, std::string const text, Player* fro if (type == CHAT_MSG_SYSTEM) return; - if (text.find(sPlayerbotAIConfig->commandSeparator) != std::string::npos) + if (text.find(sPlayerbotAIConfig.commandSeparator) != std::string::npos) { std::vector commands; - split(commands, text, sPlayerbotAIConfig->commandSeparator.c_str()); + split(commands, text, sPlayerbotAIConfig.commandSeparator.c_str()); for (std::vector::iterator i = commands.begin(); i != commands.end(); ++i) { HandleCommand(type, *i, fromPlayer); @@ -933,12 +945,12 @@ void PlayerbotAI::HandleCommand(uint32 type, std::string const text, Player* fro } std::string filtered = text; - if (!sPlayerbotAIConfig->commandPrefix.empty()) + if (!sPlayerbotAIConfig.commandPrefix.empty()) { - if (filtered.find(sPlayerbotAIConfig->commandPrefix) != 0) + if (filtered.find(sPlayerbotAIConfig.commandPrefix) != 0) return; - filtered = filtered.substr(sPlayerbotAIConfig->commandPrefix.size()); + filtered = filtered.substr(sPlayerbotAIConfig.commandPrefix.size()); } if (chatMap.empty()) @@ -962,6 +974,7 @@ void PlayerbotAI::HandleCommand(uint32 type, std::string const text, Player* fro } filtered = chatFilter.Filter(trim(filtered)); + if (filtered.empty()) return; @@ -989,7 +1002,13 @@ void PlayerbotAI::HandleCommand(uint32 type, std::string const text, Player* fro (filtered.size() > 3 && filtered.substr(0, 3) == "do ")) { std::string const action = filtered.substr(filtered.find(" ") + 1); - DoSpecificAction(action); + + NextAction::Factory factory = ActionFactoryRegistry::GetFactoryByName(action); + + if (factory != nullptr) + { + this->DoSpecificAction(factory); + } } else if (type != CHAT_MSG_WHISPER && filtered.size() > 6 && filtered.substr(0, 6) == "queue ") { @@ -1100,7 +1119,7 @@ void PlayerbotAI::HandleBotOutgoingPacket(WorldPacket const& packet) } case SMSG_MESSAGECHAT: // do not react to self or if not ready to reply { - if (!sPlayerbotAIConfig->randomBotTalk) + if (!sPlayerbotAIConfig.randomBotTalk) return; if (!AllowActivity()) @@ -1156,7 +1175,7 @@ void PlayerbotAI::HandleBotOutgoingPacket(WorldPacket const& packet) bool isFromFreeBot = false; sCharacterCache->GetCharacterNameByGuid(guid1, name); uint32 accountId = sCharacterCache->GetCharacterAccountIdByGuid(guid1); - isFromFreeBot = sPlayerbotAIConfig->IsInRandomAccountList(accountId); + isFromFreeBot = sPlayerbotAIConfig.IsInRandomAccountList(accountId); bool isMentioned = message.find(bot->GetName()) != std::string::npos; // ChatChannelSource chatChannelSource = GetChatChannelSource(bot, msgtype, chanName); @@ -1174,20 +1193,20 @@ void PlayerbotAI::HandleBotOutgoingPacket(WorldPacket const& packet) if (lang == LANG_ADDON) return; - if (message.starts_with(sPlayerbotAIConfig->toxicLinksPrefix) && + if (message.starts_with(sPlayerbotAIConfig.toxicLinksPrefix) && (GetChatHelper()->ExtractAllItemIds(message).size() > 0 || GetChatHelper()->ExtractAllQuestIds(message).size() > 0) && - sPlayerbotAIConfig->toxicLinksRepliesChance) + sPlayerbotAIConfig.toxicLinksRepliesChance) { - if (urand(0, 50) > 0 || urand(1, 100) > sPlayerbotAIConfig->toxicLinksRepliesChance) + if (urand(0, 50) > 0 || urand(1, 100) > sPlayerbotAIConfig.toxicLinksRepliesChance) { return; } } else if ((GetChatHelper()->ExtractAllItemIds(message).count(19019) && - sPlayerbotAIConfig->thunderfuryRepliesChance)) + sPlayerbotAIConfig.thunderfuryRepliesChance)) { - if (urand(0, 60) > 0 || urand(1, 100) > sPlayerbotAIConfig->thunderfuryRepliesChance) + if (urand(0, 60) > 0 || urand(1, 100) > sPlayerbotAIConfig.thunderfuryRepliesChance) { return; } @@ -1197,8 +1216,8 @@ void PlayerbotAI::HandleBotOutgoingPacket(WorldPacket const& packet) if (isFromFreeBot && urand(0, 20)) return; - // if (msgtype == CHAT_MSG_GUILD && (!sPlayerbotAIConfig->guildRepliesRate || urand(1, 100) >= - // sPlayerbotAIConfig->guildRepliesRate)) return; + // if (msgtype == CHAT_MSG_GUILD && (!sPlayerbotAIConfig.guildRepliesRate || urand(1, 100) >= + // sPlayerbotAIConfig.guildRepliesRate)) return; if (!isFromFreeBot) { @@ -1285,7 +1304,7 @@ void PlayerbotAI::HandleBotOutgoingPacket(WorldPacket const& packet) // bot->GetMotionMaster()->MoveKnockbackFrom(fx, fy, horizontalSpeed, verticalSpeed); // // set delay based on actual distance - // float newdis = sqrt(sServerFacade->GetDistance2d(bot, fx, fy)); + // float newdis = sqrt(ServerFacade::instance().GetDistance2d(bot, fx, fy)); // SetNextCheckDelay((uint32)((newdis / dis) * moveTimeHalf * 4 * IN_MILLISECONDS)); // // add moveflags @@ -1347,9 +1366,9 @@ int32 PlayerbotAI::CalculateGlobalCooldown(uint32 spellid) return 0; if (bot->HasSpellCooldown(spellid)) - return sPlayerbotAIConfig->globalCoolDown; + return sPlayerbotAIConfig.globalCoolDown; - return sPlayerbotAIConfig->reactDelay; + return sPlayerbotAIConfig.reactDelay; } void PlayerbotAI::HandleMasterIncomingPacket(WorldPacket const& packet) @@ -1410,7 +1429,7 @@ void PlayerbotAI::DoNextAction(bool min) { if (!bot->IsInWorld() || bot->IsBeingTeleported() || (GetMaster() && GetMaster()->IsBeingTeleported())) { - SetNextCheckDelay(sPlayerbotAIConfig->globalCoolDown); + SetNextCheckDelay(sPlayerbotAIConfig.globalCoolDown); return; } @@ -1454,16 +1473,25 @@ void PlayerbotAI::DoNextAction(bool min) } } - bool minimal = !AllowActivity(); + bool minimal = !this->AllowActivity(); + + const GlobalPlayerInspector playerInspector(this->bot->GetGUID().GetRawValue()); - currentEngine->DoNextAction(nullptr, 0, (minimal || min)); + if (!minimal && playerInspector.isDrinking() && playerInspector.shouldBeDrinking(95.0f)) + { + this->SetNextCheckDelay(500); + + return; + } + + currentEngine->doNextAction(nullptr, 0, (minimal || min)); if (minimal) { if (!bot->isAFK() && !bot->InBattleground() && !HasRealPlayerMaster()) bot->ToggleAFK(); - SetNextCheckDelay(sPlayerbotAIConfig->passiveDelay); + SetNextCheckDelay(sPlayerbotAIConfig.passiveDelay); return; } else if (bot->isAFK()) @@ -1471,7 +1499,8 @@ void PlayerbotAI::DoNextAction(bool min) if (master && master->IsInWorld()) { - float distance = sServerFacade->GetDistance2d(bot, master); + float distance = ServerFacade::instance().GetDistance2d(bot, master); + if (master->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_WALKING) && distance < 20.0f) bot->m_movementInfo.AddMovementFlag(MOVEMENTFLAG_WALKING); else @@ -1636,13 +1665,17 @@ void PlayerbotAI::ApplyInstanceStrategies(uint32 mapId, bool tellMaster) } } -bool PlayerbotAI::DoSpecificAction(std::string const name, Event event, bool silent, std::string const qualifier) +bool PlayerbotAI::DoSpecificAction(NextAction::Factory actionFactory, Event event, bool silent) { std::ostringstream out; + std::unique_ptr localAction = actionFactory(this); + + const std::string name = localAction->getName(); + for (uint8 i = 0; i < BOT_STATE_MAX; i++) { - ActionResult res = engines[i]->ExecuteAction(name, event, qualifier); + ActionResult res = engines[i]->ExecuteAction(actionFactory, event); switch (res) { case ACTION_RESULT_UNKNOWN: @@ -1704,7 +1737,7 @@ bool PlayerbotAI::PlayEmote(uint32 emote) WorldPacket data(SMSG_TEXT_EMOTE); data << (TextEmotes)emote; data << EmoteAction::GetNumberOfEmoteVariants((TextEmotes)emote, bot->getRace(), bot->getGender()); - data << ((master && (sServerFacade->GetDistance2d(bot, master) < 30.0f) && urand(0, 1)) ? master->GetGUID() + data << ((master && (ServerFacade::instance().GetDistance2d(bot, master) < 30.0f) && urand(0, 1)) ? master->GetGUID() : (bot->GetTarget() && urand(0, 1)) ? bot->GetTarget() : ObjectGuid::Empty); bot->GetSession()->HandleTextEmoteOpcode(data); @@ -1725,7 +1758,7 @@ bool PlayerbotAI::ContainsStrategy(StrategyType type) bool PlayerbotAI::HasStrategy(std::string const name, BotState type) { return engines[type]->HasStrategy(name); } -void PlayerbotAI::ResetStrategies(bool load) +void PlayerbotAI::ResetStrategies(bool) { for (uint8 i = 0; i < BOT_STATE_MAX; i++) engines[i]->removeAllStrategies(); @@ -1733,14 +1766,14 @@ void PlayerbotAI::ResetStrategies(bool load) AiFactory::AddDefaultCombatStrategies(bot, this, engines[BOT_STATE_COMBAT]); AiFactory::AddDefaultNonCombatStrategies(bot, this, engines[BOT_STATE_NON_COMBAT]); AiFactory::AddDefaultDeadStrategies(bot, this, engines[BOT_STATE_DEAD]); - if (sPlayerbotAIConfig->applyInstanceStrategies) + if (sPlayerbotAIConfig.applyInstanceStrategies) ApplyInstanceStrategies(bot->GetMapId()); for (uint8 i = 0; i < BOT_STATE_MAX; i++) engines[i]->Init(); // if (load) - // sPlayerbotRepository->Load(this); + // PlayerbotRepository::instance().Load(this); } bool PlayerbotAI::IsRanged(Player* player, bool bySpec) @@ -2718,7 +2751,7 @@ bool PlayerbotAI::SayToParty(const std::string& msg) for (auto reciever : GetPlayersInGroup()) { - sServerFacade->SendPacket(reciever, &data); + ServerFacade::instance().SendPacket(reciever, &data); } return true; @@ -2735,7 +2768,7 @@ bool PlayerbotAI::SayToRaid(const std::string& msg) for (auto reciever : GetPlayersInGroup()) { - sServerFacade->SendPacket(reciever, &data); + ServerFacade::instance().SendPacket(reciever, &data); } return true; @@ -2802,7 +2835,7 @@ bool PlayerbotAI::TellMasterNoFacing(std::string const text, PlayerbotSecurityLe masterBotAI = GET_PLAYERBOT_AI(master); if ((!master || (masterBotAI && !masterBotAI->IsRealPlayer())) && - (sPlayerbotAIConfig->randomBotSayWithoutMaster || HasStrategy("debug", BOT_STATE_NON_COMBAT))) + (sPlayerbotAIConfig.randomBotSayWithoutMaster || HasStrategy("debug", BOT_STATE_NON_COMBAT))) { bot->Say(text, (bot->GetTeamId() == TEAM_ALLIANCE ? LANG_COMMON : LANG_ORCISH)); return true; @@ -2813,7 +2846,7 @@ bool PlayerbotAI::TellMasterNoFacing(std::string const text, PlayerbotSecurityLe time_t lastSaid = whispers[text]; - if (!lastSaid || (time(nullptr) - lastSaid) >= sPlayerbotAIConfig->repeatDelay / 1000) + if (!lastSaid || (time(nullptr) - lastSaid) >= sPlayerbotAIConfig.repeatDelay / 1000) { whispers[text] = time(nullptr); @@ -2851,10 +2884,10 @@ bool PlayerbotAI::IsTellAllowed(PlayerbotSecurityLevel securityLevel) if (!GetSecurity()->CheckLevelFor(securityLevel, true, master)) return false; - if (sPlayerbotAIConfig->whisperDistance && !bot->GetGroup() && sRandomPlayerbotMgr->IsRandomBot(bot) && + if (sPlayerbotAIConfig.whisperDistance && !bot->GetGroup() && sRandomPlayerbotMgr.IsRandomBot(bot) && master->GetSession()->GetSecurity() < SEC_GAMEMASTER && (bot->GetMapId() != master->GetMapId() || - sServerFacade->GetDistance2d(bot, master) > sPlayerbotAIConfig->whisperDistance)) + ServerFacade::instance().GetDistance2d(bot, master) > sPlayerbotAIConfig.whisperDistance)) return false; return true; @@ -2869,7 +2902,7 @@ bool PlayerbotAI::TellMaster(std::string const text, PlayerbotSecurityLevel secu { if (!master) { - if (sPlayerbotAIConfig->randomBotSayWithoutMaster) + if (sPlayerbotAIConfig.randomBotSayWithoutMaster) return TellMasterNoFacing(text, securityLevel); } if (!TellMasterNoFacing(text, securityLevel)) @@ -2878,7 +2911,7 @@ bool PlayerbotAI::TellMaster(std::string const text, PlayerbotSecurityLevel secu if (!bot->isMoving() && !bot->IsInCombat() && bot->GetMapId() == master->GetMapId() && !bot->HasUnitState(UNIT_STATE_IN_FLIGHT) && !bot->IsFlying()) { - if (!bot->HasInArc(EMOTE_ANGLE_IN_FRONT, master, sPlayerbotAIConfig->sightDistance)) + if (!bot->HasInArc(EMOTE_ANGLE_IN_FRONT, master, sPlayerbotAIConfig.sightDistance)) bot->SetFacingToObject(master); bot->HandleEmoteCommand(EMOTE_ONESHOT_TALK); @@ -3092,7 +3125,7 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, { if (!spellid) { - if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) + if (!sPlayerbotAIConfig.logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { LOG_DEBUG("playerbots", "Can cast spell failed. No spellid. - spellid: {}, bot name: {}", spellid, bot->GetName()); @@ -3102,7 +3135,7 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, if (bot->HasUnitState(UNIT_STATE_LOST_CONTROL)) { - if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) + if (!sPlayerbotAIConfig.logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { LOG_DEBUG("playerbots", "Can cast spell failed. Unit state lost control. - spellid: {}, bot name: {}", spellid, bot->GetName()); @@ -3122,7 +3155,7 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, if (checkHasSpell && !bot->HasSpell(spellid)) { - if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) + if (!sPlayerbotAIConfig.logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { LOG_DEBUG("playerbots", "Can cast spell failed. Bot not has spell. - target name: {}, spellid: {}, bot name: {}", @@ -3133,7 +3166,7 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, if (bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL) != nullptr) { - if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) + if (!sPlayerbotAIConfig.logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { LOG_DEBUG( "playerbots", @@ -3145,7 +3178,7 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, if (bot->HasSpellCooldown(spellid)) { - if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) + if (!sPlayerbotAIConfig.logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { LOG_DEBUG("playerbots", "Can cast spell failed. Spell not has cooldown. - target name: {}, spellid: {}, bot name: {}", @@ -3157,7 +3190,7 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellid); if (!spellInfo) { - if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) + if (!sPlayerbotAIConfig.logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { LOG_DEBUG("playerbots", "Can cast spell failed. No spellInfo. - target name: {}, spellid: {}, bot name: {}", target->GetName(), spellid, bot->GetName()); @@ -3167,7 +3200,7 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, if ((bot->GetShapeshiftForm() == FORM_FLIGHT || bot->GetShapeshiftForm() == FORM_FLIGHT_EPIC) && !bot->IsInCombat()) { - if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) + if (!sPlayerbotAIConfig.logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { LOG_DEBUG( "playerbots", @@ -3181,7 +3214,7 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, // bool interruptOnMove = spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT; if ((CastingTime || spellInfo->IsAutoRepeatRangedSpell()) && bot->isMoving()) { - if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) + if (!sPlayerbotAIConfig.logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { LOG_DEBUG("playerbots", "Casting time and bot is moving - target name: {}, spellid: {}, bot name: {}", target->GetName(), spellid, bot->GetName()); @@ -3196,7 +3229,7 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, { if (spellid != 44572) // Deep Freeze { - if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) + if (!sPlayerbotAIConfig.logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { LOG_DEBUG("playerbots", "target is immuned to spell - target name: {}, spellid: {}, bot name: {}", target->GetName(), spellid, bot->GetName()); @@ -3206,9 +3239,9 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, // Otherwise, allow Deep Freeze even if immune } - if (bot != target && sServerFacade->GetDistance2d(bot, target) > sPlayerbotAIConfig->sightDistance) + if (bot != target && ServerFacade::instance().GetDistance2d(bot, target) > sPlayerbotAIConfig.sightDistance) { - if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) + if (!sPlayerbotAIConfig.logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { LOG_DEBUG("playerbots", "target is out of sight distance - target name: {}, spellid: {}, bot name: {}", target->GetName(), spellid, bot->GetName()); @@ -3234,7 +3267,7 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, SpellCastResult result = spell->CheckCast(true); delete spell; - // if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) + // if (!sPlayerbotAIConfig.logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) // { // if (result != SPELL_FAILED_NOT_READY && result != SPELL_CAST_OK) // { @@ -3258,7 +3291,7 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, case SPELL_FAILED_OUT_OF_RANGE: return true; default: - if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) + if (!sPlayerbotAIConfig.logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { LOG_DEBUG("playerbots", "CanCastSpell Check Failed. - target name: {}, spellid: {}, bot name: {}, result: {}", @@ -3294,7 +3327,7 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, GameObject* goTarget, bool checkH if (CastingTime > 0 && bot->isMoving()) return false; - if (sServerFacade->GetDistance2d(bot, goTarget) > sPlayerbotAIConfig->sightDistance) + if (ServerFacade::instance().GetDistance2d(bot, goTarget) > sPlayerbotAIConfig.sightDistance) return false; // ObjectGuid oldSel = bot->GetTarget(); @@ -3347,7 +3380,7 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, float x, float y, float z, bool c if (!itemTarget) { - if (bot->GetDistance(x, y, z) > sPlayerbotAIConfig->sightDistance) + if (bot->GetDistance(x, y, z) > sPlayerbotAIConfig.sightDistance) return false; } @@ -3449,7 +3482,7 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget) if (bot->IsFlying() || bot->HasUnitState(UNIT_STATE_IN_FLIGHT)) { - // if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) + // if (!sPlayerbotAIConfig.logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) // { // LOG_DEBUG("playerbots", "Spell cast is flying - target name: {}, spellid: {}, bot name: {}}", // target->GetName(), spellId, bot->GetName()); @@ -3472,13 +3505,13 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget) WorldObject* faceTo = target; if (!bot->HasInArc(CAST_ANGLE_IN_FRONT, faceTo) && (spellInfo->FacingCasterFlags & SPELL_FACING_FLAG_INFRONT)) { - sServerFacade->SetFacingTo(bot, faceTo); + ServerFacade::instance().SetFacingTo(bot, faceTo); // failWithDelay = true; } if (failWithDelay) { - SetNextCheckDelay(sPlayerbotAIConfig->reactDelay); + SetNextCheckDelay(sPlayerbotAIConfig.reactDelay); return false; } @@ -3495,7 +3528,7 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget) { bot->GetTradeData()->SetSpell(spellId); delete spell; - // if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) + // if (!sPlayerbotAIConfig.logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) // { // LOG_DEBUG("playerbots", "Spell cast no item - target name: {}, spellid: {}, bot name: {}", // target->GetName(), spellId, bot->GetName()); @@ -3557,7 +3590,7 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget) if (bot->isMoving() && spell->GetCastTime()) { // bot->StopMoving(); - SetNextCheckDelay(sPlayerbotAIConfig->reactDelay); + SetNextCheckDelay(sPlayerbotAIConfig.reactDelay); spell->cancel(); delete spell; return false; @@ -3565,7 +3598,7 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget) // spell->m_targets.SetUnitTarget(target); // SpellCastResult spellSuccess = spell->CheckCast(true); - // if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) + // if (!sPlayerbotAIConfig.logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) // { // LOG_DEBUG("playerbots", "Spell cast result - target name: {}, spellid: {}, bot name: {}, result: {}", // target->GetName(), spellId, bot->GetName(), spellSuccess); @@ -3577,7 +3610,7 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget) if (result != SPELL_CAST_OK) { - // if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) + // if (!sPlayerbotAIConfig.logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) // { // LOG_DEBUG("playerbots", "Spell cast failed. - target name: {}, spellid: {}, bot name: {}, result: {}", // target->GetName(), spellId, bot->GetName(), result); @@ -3645,7 +3678,7 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget) // { // spell->cancel(); // delete spell; - // if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) + // if (!sPlayerbotAIConfig.logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) // { // LOG_DEBUG("playerbots", "Spell cast loot - target name: {}, spellid: {}, bot name: {}", // target->GetName(), spellId, bot->GetName()); @@ -3725,7 +3758,7 @@ bool PlayerbotAI::CastSpell(uint32 spellId, float x, float y, float z, Item* ite if (failWithDelay) { - SetNextCheckDelay(sPlayerbotAIConfig->globalCoolDown); + SetNextCheckDelay(sPlayerbotAIConfig.globalCoolDown); return false; } @@ -3768,7 +3801,7 @@ bool PlayerbotAI::CastSpell(uint32 spellId, float x, float y, float z, Item* ite if (bot->isMoving() && spell->GetCastTime()) { // bot->StopMoving(); - SetNextCheckDelay(sPlayerbotAIConfig->reactDelay); + SetNextCheckDelay(sPlayerbotAIConfig.reactDelay); spell->cancel(); delete spell; return false; @@ -3846,12 +3879,12 @@ bool PlayerbotAI::CanCastVehicleSpell(uint32 spellId, Unit* target) if (CastingTime && vehicleBase->isMoving()) return false; - if (vehicleBase != spellTarget && sServerFacade->GetDistance2d(vehicleBase, spellTarget) > 120.0f) + if (vehicleBase != spellTarget && ServerFacade::instance().GetDistance2d(vehicleBase, spellTarget) > 120.0f) return false; if (!target && siegePos.isSet()) { - if (sServerFacade->GetDistance2d(vehicleBase, siegePos.x, siegePos.y) > 120.0f) + if (ServerFacade::instance().GetDistance2d(vehicleBase, siegePos.x, siegePos.y) > 120.0f) return false; } @@ -3921,7 +3954,7 @@ bool PlayerbotAI::CastVehicleSpell(uint32 spellId, Unit* target) PositionInfo siegePos = GetAiObjectContext()->GetValue("position")->Get()["bg siege"]; if (!target && siegePos.isSet()) { - if (sServerFacade->GetDistance2d(vehicleBase, siegePos.x, siegePos.y) > 120.0f) + if (ServerFacade::instance().GetDistance2d(vehicleBase, siegePos.x, siegePos.y) > 120.0f) return false; } @@ -3959,7 +3992,7 @@ bool PlayerbotAI::CastVehicleSpell(uint32 spellId, Unit* target) if (failWithDelay) { - SetNextCheckDelay(sPlayerbotAIConfig->reactDelay); + SetNextCheckDelay(sPlayerbotAIConfig.reactDelay); return false; } @@ -4000,7 +4033,7 @@ bool PlayerbotAI::CastVehicleSpell(uint32 spellId, Unit* target) if (seat->CanControl() && vehicleBase->isMoving() && spell->GetCastTime()) { vehicleBase->StopMoving(); - SetNextCheckDelay(sPlayerbotAIConfig->globalCoolDown); + SetNextCheckDelay(sPlayerbotAIConfig.globalCoolDown); spell->cancel(); // delete spell; return false; @@ -4077,7 +4110,7 @@ void PlayerbotAI::WaitForSpellCast(Spell* spell) castTime += duration; } - SetNextCheckDelay(castTime + sPlayerbotAIConfig->reactDelay); + SetNextCheckDelay(castTime + sPlayerbotAIConfig.reactDelay); } void PlayerbotAI::InterruptSpell() @@ -4169,8 +4202,8 @@ bool PlayerbotAI::HasAuraToDispel(Unit* target, uint32 dispelType) if (!aura || aura->IsPassive() || aura->IsRemoved()) continue; - if (sPlayerbotAIConfig->dispelAuraDuration && aura->GetDuration() && - aura->GetDuration() < (int32)sPlayerbotAIConfig->dispelAuraDuration) + if (sPlayerbotAIConfig.dispelAuraDuration && aura->GetDuration() && + aura->GetDuration() < (int32)sPlayerbotAIConfig.dispelAuraDuration) continue; SpellInfo const* spellInfo = aura->GetSpellInfo(); @@ -4290,7 +4323,7 @@ bool PlayerbotAI::HasRealPlayerMaster() bool PlayerbotAI::HasActivePlayerMaster() { return master && !GET_PLAYERBOT_AI(master); } -bool PlayerbotAI::IsAlt() { return HasRealPlayerMaster() && !sRandomPlayerbotMgr->IsRandomBot(bot); } +bool PlayerbotAI::IsAlt() { return HasRealPlayerMaster() && !sRandomPlayerbotMgr.IsRandomBot(bot); } Player* PlayerbotAI::GetGroupLeader() { @@ -4379,7 +4412,7 @@ bool PlayerbotAI::HasPlayerNearby(WorldPosition* pos, float range) { float sqRange = range * range; bool nearPlayer = false; - for (auto& player : sRandomPlayerbotMgr->GetPlayers()) + for (auto& player : sRandomPlayerbotMgr.GetPlayers()) { if (!player->IsGameMaster() || player->isGMVisible()) { @@ -4413,9 +4446,9 @@ bool PlayerbotAI::HasManyPlayersNearby(uint32 trigerrValue, float range) float sqRange = range * range; uint32 found = 0; - for (auto& player : sRandomPlayerbotMgr->GetPlayers()) + for (auto& player : sRandomPlayerbotMgr.GetPlayers()) { - if ((!player->IsGameMaster() || player->isGMVisible()) && sServerFacade->GetDistance2d(player, bot) < sqRange) + if ((!player->IsGameMaster() || player->isGMVisible()) && ServerFacade::instance().GetDistance2d(player, bot) < sqRange) { found++; @@ -4461,7 +4494,7 @@ inline bool ZoneHasRealPlayers(Player* bot) return false; } - for (Player* player : sRandomPlayerbotMgr->GetPlayers()) + for (Player* player : sRandomPlayerbotMgr.GetPlayers()) { if (player->GetMapId() != bot->GetMapId()) continue; @@ -4492,7 +4525,7 @@ bool PlayerbotAI::AllowActive(ActivityType activityType) return false; // when botActiveAlone is 100% and smartScale disabled - if (sPlayerbotAIConfig->botActiveAlone >= 100 && !sPlayerbotAIConfig->botActiveAloneSmartScale) + if (sPlayerbotAIConfig.botActiveAlone >= 100 && !sPlayerbotAIConfig.botActiveAloneSmartScale) { return true; } @@ -4510,7 +4543,7 @@ bool PlayerbotAI::AllowActive(ActivityType activityType) // which prevents unneeded expensive GameTime calls. if (_isBotInitializing) { - _isBotInitializing = GameTime::GetUptime().count() < sPlayerbotAIConfig->maxRandomBots * 0.11; + _isBotInitializing = GameTime::GetUptime().count() < sPlayerbotAIConfig.maxRandomBots * 0.11; // no activity allowed during bot initialization if (_isBotInitializing) @@ -4532,7 +4565,7 @@ bool PlayerbotAI::AllowActive(ActivityType activityType) } // bot map has active players. - if (sPlayerbotAIConfig->BotActiveAloneForceWhenInMap) + if (sPlayerbotAIConfig.BotActiveAloneForceWhenInMap) { if (HasRealPlayers(bot->GetMap())) { @@ -4541,7 +4574,7 @@ bool PlayerbotAI::AllowActive(ActivityType activityType) } // bot zone has active players. - if (sPlayerbotAIConfig->BotActiveAloneForceWhenInZone) + if (sPlayerbotAIConfig.BotActiveAloneForceWhenInZone) { if (ZoneHasRealPlayers(bot)) { @@ -4550,7 +4583,7 @@ bool PlayerbotAI::AllowActive(ActivityType activityType) } // when in real guild - if (sPlayerbotAIConfig->BotActiveAloneForceWhenInGuild) + if (sPlayerbotAIConfig.BotActiveAloneForceWhenInGuild) { if (IsInRealGuild()) { @@ -4559,7 +4592,7 @@ bool PlayerbotAI::AllowActive(ActivityType activityType) } // Player is near. Always active. - if (HasPlayerNearby(sPlayerbotAIConfig->BotActiveAloneForceWhenInRadius)) + if (HasPlayerNearby(sPlayerbotAIConfig.BotActiveAloneForceWhenInRadius)) { return true; } @@ -4631,13 +4664,13 @@ bool PlayerbotAI::AllowActive(ActivityType activityType) } // HasFriend - if (sPlayerbotAIConfig->BotActiveAloneForceWhenIsFriend) + if (sPlayerbotAIConfig.BotActiveAloneForceWhenIsFriend) { // shouldnt be needed analyse in future if (!bot->GetGUID()) return false; - for (auto& player : sRandomPlayerbotMgr->GetPlayers()) + for (auto& player : sRandomPlayerbotMgr.GetPlayers()) { if (!player || !player->GetSession() || !player->IsInWorld() || player->IsDuringRemoveFromWorld() || player->GetSession()->isLogingOut()) @@ -4669,7 +4702,7 @@ bool PlayerbotAI::AllowActive(ActivityType activityType) return false; } - if (sPlayerbotAIConfig->botActiveAlone <= 0) + if (sPlayerbotAIConfig.botActiveAlone <= 0) { return false; } @@ -4681,19 +4714,19 @@ bool PlayerbotAI::AllowActive(ActivityType activityType) // Below is code to have a specified % of bots active at all times. // The default is 100%. With 1% of all bots going active or inactive each minute. - uint32 mod = sPlayerbotAIConfig->botActiveAlone > 100 ? 100 : sPlayerbotAIConfig->botActiveAlone; - if (sPlayerbotAIConfig->botActiveAloneSmartScale && - bot->GetLevel() >= sPlayerbotAIConfig->botActiveAloneSmartScaleWhenMinLevel && - bot->GetLevel() <= sPlayerbotAIConfig->botActiveAloneSmartScaleWhenMaxLevel) + uint32 mod = sPlayerbotAIConfig.botActiveAlone > 100 ? 100 : sPlayerbotAIConfig.botActiveAlone; + if (sPlayerbotAIConfig.botActiveAloneSmartScale && + bot->GetLevel() >= sPlayerbotAIConfig.botActiveAloneSmartScaleWhenMinLevel && + bot->GetLevel() <= sPlayerbotAIConfig.botActiveAloneSmartScaleWhenMaxLevel) { mod = AutoScaleActivity(mod); } uint32 ActivityNumber = - GetFixedBotNumer(100, sPlayerbotAIConfig->botActiveAlone * static_cast(mod) / 100 * 0.01f); + GetFixedBotNumer(100, sPlayerbotAIConfig.botActiveAlone * static_cast(mod) / 100 * 0.01f); return ActivityNumber <= - (sPlayerbotAIConfig->botActiveAlone * mod) / + (sPlayerbotAIConfig.botActiveAlone * mod) / 100; // The given percentage of bots should be active and rotate 1% of those active bots each minute. } @@ -4725,8 +4758,8 @@ uint32 PlayerbotAI::AutoScaleActivity(uint32 mod) { // Current max server update time (ms), and the configured floor/ceiling values for bot scaling uint32 maxDiff = sWorldUpdateTime.GetMaxUpdateTimeOfCurrentTable(); - uint32 diffLimitFloor = sPlayerbotAIConfig->botActiveAloneSmartScaleDiffLimitfloor; - uint32 diffLimitCeiling = sPlayerbotAIConfig->botActiveAloneSmartScaleDiffLimitCeiling; + uint32 diffLimitFloor = sPlayerbotAIConfig.botActiveAloneSmartScaleDiffLimitfloor; + uint32 diffLimitCeiling = sPlayerbotAIConfig.botActiveAloneSmartScaleDiffLimitCeiling; if (diffLimitCeiling <= diffLimitFloor) { @@ -5318,19 +5351,19 @@ float PlayerbotAI::GetRange(std::string const type) return val; if (type == "spell") - return sPlayerbotAIConfig->spellDistance; + return sPlayerbotAIConfig.spellDistance; if (type == "shoot") - return sPlayerbotAIConfig->shootDistance; + return sPlayerbotAIConfig.shootDistance; if (type == "flee") - return sPlayerbotAIConfig->fleeDistance; + return sPlayerbotAIConfig.fleeDistance; if (type == "heal") - return sPlayerbotAIConfig->healDistance; + return sPlayerbotAIConfig.healDistance; if (type == "melee") - return sPlayerbotAIConfig->meleeDistance; + return sPlayerbotAIConfig.meleeDistance; return 0; } @@ -5999,7 +6032,7 @@ bool PlayerbotAI::IsInRealGuild() if (!bot->GetGuildId()) return false; - return sPlayerbotGuildMgr->IsRealGuild(bot->GetGuildId()); + return PlayerbotGuildMgr::instance().IsRealGuild(bot->GetGuildId()); } void PlayerbotAI::QueueChatResponse(const ChatQueuedReply chatReply) { chatReplies.push_back(std::move(chatReply)); } @@ -6553,17 +6586,17 @@ std::set PlayerbotAI::GetCurrentIncompleteQuestIds() uint32 PlayerbotAI::GetReactDelay() { - uint32 base = sPlayerbotAIConfig->reactDelay; // Default 100(ms) + uint32 base = sPlayerbotAIConfig.reactDelay; // Default 100(ms) // If dynamic react delay is disabled, use a static calculation - if (!sPlayerbotAIConfig->dynamicReactDelay) + if (!sPlayerbotAIConfig.dynamicReactDelay) { if (HasRealPlayerMaster()) return base; bool inBG = bot->InBattleground() || bot->InArena(); - if (sPlayerbotAIConfig->fastReactInBG && inBG) + if (sPlayerbotAIConfig.fastReactInBG && inBG) return base; bool inCombat = bot->IsInCombat(); @@ -6588,11 +6621,11 @@ uint32 PlayerbotAI::GetReactDelay() { if (bot->IsInCombat() || currentState == BOT_STATE_COMBAT) { - return static_cast(base * (sPlayerbotAIConfig->fastReactInBG ? 2.5f : 5.0f)); + return static_cast(base * (sPlayerbotAIConfig.fastReactInBG ? 2.5f : 5.0f)); } else { - return static_cast(base * (sPlayerbotAIConfig->fastReactInBG ? 1.0f : 10.0f)); + return static_cast(base * (sPlayerbotAIConfig.fastReactInBG ? 1.0f : 10.0f)); } } @@ -6765,7 +6798,7 @@ void PlayerbotAI::EvaluateHealerDpsStrategy() if (!IsHeal(bot, true)) return; - if (sPlayerbotAIConfig->IsRestrictedHealerDPSMap(bot->GetMapId())) + if (sPlayerbotAIConfig.IsRestrictedHealerDPSMap(bot->GetMapId())) ChangeStrategy("-healer dps", BOT_STATE_COMBAT); else ChangeStrategy("+healer dps", BOT_STATE_COMBAT); diff --git a/src/Bot/PlayerbotAI.h b/src/Bot/PlayerbotAI.h index b2df4352cc..7c72add07f 100644 --- a/src/Bot/PlayerbotAI.h +++ b/src/Bot/PlayerbotAI.h @@ -6,13 +6,11 @@ #ifndef _PLAYERBOT_PLAYERbotAI_H #define _PLAYERBOT_PLAYERbotAI_H -#include #include #include "Chat.h" #include "ChatFilter.h" #include "ChatHelper.h" -#include "Common.h" #include "CreatureData.h" #include "Event.h" #include "Item.h" @@ -25,6 +23,7 @@ #include "SpellAuras.h" #include "Util.h" #include "WorldPacket.h" +#include "NextAction.h" class AiObjectContext; class Creature; @@ -402,8 +401,7 @@ class PlayerbotAI : public PlayerbotAIBase void ChangeEngineOnCombat(); void ChangeEngineOnNonCombat(); void DoNextAction(bool minimal = false); - virtual bool DoSpecificAction(std::string const name, Event event = Event(), bool silent = false, - std::string const qualifier = ""); + virtual bool DoSpecificAction(NextAction::Factory actionFactory, Event event = Event(), bool silent = false); void ChangeStrategy(std::string const name, BotState type); void ClearStrategies(BotState type); std::vector GetStrategies(BotState type); @@ -491,7 +489,7 @@ class PlayerbotAI : public PlayerbotAIBase void ImbueItem(Item* item); void EnchantItemT(uint32 spellid, uint8 slot); uint32 GetBuffedCount(Player* player, std::string const spellname); - int32 GetNearGroupMemberCount(float dis = sPlayerbotAIConfig->sightDistance); + int32 GetNearGroupMemberCount(float dis = sPlayerbotAIConfig.sightDistance); virtual bool CanCastSpell(std::string const name, Unit* target, Item* itemTarget = nullptr); virtual bool CastSpell(std::string const name, Unit* target, Item* itemTarget = nullptr); @@ -545,9 +543,9 @@ class PlayerbotAI : public PlayerbotAIBase uint32 GetFixedBotNumer(uint32 maxNum = 100, float cyclePerMin = 1); GrouperType GetGrouperType(); GuilderType GetGuilderType(); - bool HasPlayerNearby(WorldPosition* pos, float range = sPlayerbotAIConfig->reactDistance); - bool HasPlayerNearby(float range = sPlayerbotAIConfig->reactDistance); - bool HasManyPlayersNearby(uint32 trigerrValue = 20, float range = sPlayerbotAIConfig->sightDistance); + bool HasPlayerNearby(WorldPosition* pos, float range = sPlayerbotAIConfig.reactDistance); + bool HasPlayerNearby(float range = sPlayerbotAIConfig.reactDistance); + bool HasManyPlayersNearby(uint32 trigerrValue = 20, float range = sPlayerbotAIConfig.sightDistance); bool AllowActive(ActivityType activityType); bool AllowActivity(ActivityType activityType = ALL_ACTIVITY, bool checkNow = false); uint32 AutoScaleActivity(uint32 mod); @@ -562,7 +560,7 @@ class PlayerbotAI : public PlayerbotAIBase bool HasCheat(BotCheatMask mask) { return ((uint32)mask & (uint32)cheatMask) != 0 || - ((uint32)mask & (uint32)sPlayerbotAIConfig->botCheatMask) != 0; + ((uint32)mask & (uint32)sPlayerbotAIConfig.botCheatMask) != 0; } BotCheatMask GetCheat() { return cheatMask; } void SetCheat(BotCheatMask mask) { cheatMask = mask; } diff --git a/src/Bot/PlayerbotMgr.cpp b/src/Bot/PlayerbotMgr.cpp index e01afb0f7c..7e081a4fc9 100644 --- a/src/Bot/PlayerbotMgr.cpp +++ b/src/Bot/PlayerbotMgr.cpp @@ -7,7 +7,6 @@ #include #include -#include #include #include #include @@ -20,11 +19,9 @@ #include "Common.h" #include "Define.h" #include "Group.h" -#include "GroupMgr.h" #include "GuildMgr.h" #include "ObjectAccessor.h" #include "ObjectGuid.h" -#include "ObjectMgr.h" #include "PlayerbotAIConfig.h" #include "PlayerbotRepository.h" #include "PlayerbotFactory.h" @@ -74,7 +71,6 @@ class PlayerbotLoginQueryHolder : public LoginQueryHolder { private: uint32 masterAccountId; - PlayerbotHolder* playerbotHolder; public: PlayerbotLoginQueryHolder(uint32 masterAccount, uint32 accountId, ObjectGuid guid) : LoginQueryHolder(accountId, guid), masterAccountId(masterAccount) @@ -102,11 +98,11 @@ void PlayerbotHolder::AddPlayerBot(ObjectGuid playerGuid, uint32 masterAccountId Player* masterPlayer = masterSession ? masterSession->GetPlayer() : nullptr; bool isRndbot = !masterAccountId; - bool sameAccount = sPlayerbotAIConfig->allowAccountBots && accountId == masterAccountId; + bool sameAccount = sPlayerbotAIConfig.allowAccountBots && accountId == masterAccountId; Guild* guild = masterPlayer ? sGuildMgr->GetGuildById(masterPlayer->GetGuildId()) : nullptr; - bool sameGuild = sPlayerbotAIConfig->allowGuildBots && guild && guild->GetMember(playerGuid); - bool addClassBot = sRandomPlayerbotMgr->IsAddclassBot(playerGuid.GetCounter()); - bool linkedAccount = sPlayerbotAIConfig->allowTrustedAccountBots && IsAccountLinked(accountId, masterAccountId); + bool sameGuild = sPlayerbotAIConfig.allowGuildBots && guild && guild->GetMember(playerGuid); + bool addClassBot = sRandomPlayerbotMgr.IsAddclassBot(playerGuid.GetCounter()); + bool linkedAccount = sPlayerbotAIConfig.allowTrustedAccountBots && IsAccountLinked(accountId, masterAccountId); bool allowed = true; std::ostringstream out; @@ -125,11 +121,11 @@ void PlayerbotHolder::AddPlayerBot(ObjectGuid playerGuid, uint32 masterAccountId LOG_DEBUG("playerbots", "PlayerbotMgr not found for master player with GUID: {}", masterPlayer->GetGUID().GetRawValue()); return; } - uint32 count = mgr->GetPlayerbotsCount() + botLoading.size(); - if (count >= sPlayerbotAIConfig->maxAddedBots) + int64_t count = mgr->GetPlayerbotsCount() + botLoading.size(); + if (count >= PlayerbotAIConfig::instance().maxAddedBots) { allowed = false; - out << "Failure: You have added too many bots (more than " << sPlayerbotAIConfig->maxAddedBots << ")"; + out << "Failure: You have added too many bots (more than " << sPlayerbotAIConfig.maxAddedBots << ")"; } } if (!allowed) @@ -156,7 +152,6 @@ void PlayerbotHolder::AddPlayerBot(ObjectGuid playerGuid, uint32 masterAccountId [](SQLQueryHolderBase const& queryHolder) { PlayerbotLoginQueryHolder const& holder = static_cast(queryHolder); - PlayerbotHolder* mgr = sRandomPlayerbotMgr; // could be null uint32 masterAccountId = holder.GetMasterAccountId(); if (masterAccountId) @@ -164,14 +159,25 @@ void PlayerbotHolder::AddPlayerBot(ObjectGuid playerGuid, uint32 masterAccountId // verify and find current world session of master WorldSession* masterSession = sWorldSessionMgr->FindSession(masterAccountId); Player* masterPlayer = masterSession ? masterSession->GetPlayer() : nullptr; + if (masterPlayer) - mgr = GET_PLAYERBOT_MGR(masterPlayer); + { + PlayerbotHolder* mgr = PlayerbotsMgr::instance().GetPlayerbotMgr(masterPlayer); + + if (mgr != nullptr) + { + mgr->HandlePlayerBotLoginCallback(holder); + + return; + } + + PlayerbotHolder::botLoading.erase(holder.GetGuid()); + + return; + } } - if (mgr) - mgr->HandlePlayerBotLoginCallback(holder); - else - PlayerbotHolder::botLoading.erase(holder.GetGuid()); + RandomPlayerbotMgr ::instance().HandlePlayerBotLoginCallback(holder); }); } @@ -216,9 +222,9 @@ void PlayerbotHolder::HandlePlayerBotLoginCallback(PlayerbotLoginQueryHolder con masterAccountId); } - sRandomPlayerbotMgr->OnPlayerLogin(bot); + sRandomPlayerbotMgr.OnPlayerLogin(bot); auto op = std::make_unique(bot->GetGUID(), masterAccountId); - sPlayerbotWorldProcessor->QueueOperation(std::move(op)); + PlayerbotWorldThreadProcessor::instance().QueueOperation(std::move(op)); PlayerbotHolder::botLoading.erase(holder.GetGuid()); } @@ -312,8 +318,8 @@ void PlayerbotMgr::CancelLogout() } } - for (PlayerBotMap::const_iterator it = sRandomPlayerbotMgr->GetPlayerBotsBegin(); - it != sRandomPlayerbotMgr->GetPlayerBotsEnd(); ++it) + for (PlayerBotMap::const_iterator it = sRandomPlayerbotMgr.GetPlayerBotsBegin(); + it != sRandomPlayerbotMgr.GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); @@ -341,7 +347,7 @@ void PlayerbotHolder::LogoutPlayerBot(ObjectGuid guid) // Queue group cleanup operation for world thread auto cleanupOp = std::make_unique(guid); - sPlayerbotWorldProcessor->QueueOperation(std::move(cleanupOp)); + PlayerbotWorldThreadProcessor::instance().QueueOperation(std::move(cleanupOp)); LOG_DEBUG("playerbots", "Bot {} logging out", bot->GetName().c_str()); bot->SaveToDB(false, false); @@ -442,7 +448,7 @@ void PlayerbotHolder::DisablePlayerBot(ObjectGuid guid) Group* group = bot->GetGroup(); if (group && !bot->InBattleground() && !bot->InBattlegroundQueue() && botAI->HasActivePlayerMaster()) { - sPlayerbotRepository->Save(botAI); + PlayerbotRepository::instance().Save(botAI); } LOG_DEBUG("playerbots", "Bot {} logged out", bot->GetName().c_str()); @@ -488,7 +494,7 @@ void PlayerbotHolder::OnBotLogin(Player* const bot) return; } - sPlayerbotsMgr->AddPlayerbotData(bot, true); + PlayerbotsMgr::instance().AddPlayerbotData(bot, true); playerBots[bot->GetGUID()] = bot; OnBotLoginInternal(bot); @@ -528,10 +534,10 @@ void PlayerbotHolder::OnBotLogin(Player* const bot) // Don't disband alt groups when master goes away // Controlled by config - if (sPlayerbotAIConfig->KeepAltsInGroup()) + if (sPlayerbotAIConfig.KeepAltsInGroup()) { uint32 account = sCharacterCache->GetCharacterAccountIdByGuid(member); - if (!sPlayerbotAIConfig->IsInRandomAccountList(account)) + if (!sPlayerbotAIConfig.IsInRandomAccountList(account)) { groupValid = true; break; @@ -552,9 +558,9 @@ void PlayerbotHolder::OnBotLogin(Player* const bot) } else { - botAI->ResetStrategies(!sRandomPlayerbotMgr->IsRandomBot(bot)); + botAI->ResetStrategies(!sRandomPlayerbotMgr.IsRandomBot(bot)); } - sPlayerbotRepository->Load(botAI); + PlayerbotRepository::instance().Load(botAI); if (master && !master->HasUnitState(UNIT_STATE_IN_FLIGHT)) { @@ -580,52 +586,52 @@ void PlayerbotHolder::OnBotLogin(Player* const bot) { // Queue ConvertToRaid operation auto convertOp = std::make_unique(master->GetGUID()); - sPlayerbotWorldProcessor->QueueOperation(std::move(convertOp)); + PlayerbotWorldThreadProcessor::instance().QueueOperation(std::move(convertOp)); } if (mgroup->isRaidGroup()) { // Queue AddMember operation auto addOp = std::make_unique(master->GetGUID(), bot->GetGUID()); - sPlayerbotWorldProcessor->QueueOperation(std::move(addOp)); + PlayerbotWorldThreadProcessor::instance().QueueOperation(std::move(addOp)); } } else { // Queue AddMember operation auto addOp = std::make_unique(master->GetGUID(), bot->GetGUID()); - sPlayerbotWorldProcessor->QueueOperation(std::move(addOp)); + PlayerbotWorldThreadProcessor::instance().QueueOperation(std::move(addOp)); } } else if (master && !group) { // Queue group creation and AddMember operation auto inviteOp = std::make_unique(master->GetGUID(), bot->GetGUID()); - sPlayerbotWorldProcessor->QueueOperation(std::move(inviteOp)); + PlayerbotWorldThreadProcessor::instance().QueueOperation(std::move(inviteOp)); } // if (master) // { // // bot->TeleportTo(master); // } uint32 accountId = bot->GetSession()->GetAccountId(); - bool isRandomAccount = sPlayerbotAIConfig->IsInRandomAccountList(accountId); + bool isRandomAccount = sPlayerbotAIConfig.IsInRandomAccountList(accountId); - if (isRandomAccount && sPlayerbotAIConfig->randomBotFixedLevel) + if (isRandomAccount && sPlayerbotAIConfig.randomBotFixedLevel) { bot->SetPlayerFlag(PLAYER_FLAGS_NO_XP_GAIN); } - else if (isRandomAccount && !sPlayerbotAIConfig->randomBotFixedLevel) + else if (isRandomAccount && !sPlayerbotAIConfig.randomBotFixedLevel) { bot->RemovePlayerFlag(PLAYER_FLAGS_NO_XP_GAIN); } bot->SaveToDB(false, false); - bool addClassBot = sRandomPlayerbotMgr->IsAccountType(accountId, 2); + bool addClassBot = sRandomPlayerbotMgr.IsAccountType(accountId, 2); if (addClassBot && master && abs((int)master->GetLevel() - (int)bot->GetLevel()) > 3) { // PlayerbotFactory factory(bot, master->GetLevel()); // factory.Randomize(false); uint32 mixedGearScore = - PlayerbotAI::GetMixedGearScore(master, true, false, 12) * sPlayerbotAIConfig->autoInitEquipLevelLimitRatio; + PlayerbotAI::GetMixedGearScore(master, true, false, 12) * sPlayerbotAIConfig.autoInitEquipLevelLimitRatio; // work around: distinguish from 0 if no gear if (mixedGearScore == 0) mixedGearScore = 1; @@ -634,7 +640,7 @@ void PlayerbotHolder::OnBotLogin(Player* const bot) } // bots join World chat if not solo oriented - if (bot->GetLevel() >= 10 && sRandomPlayerbotMgr->IsRandomBot(bot) && GET_PLAYERBOT_AI(bot) && + if (bot->GetLevel() >= 10 && sRandomPlayerbotMgr.IsRandomBot(bot) && GET_PLAYERBOT_AI(bot) && GET_PLAYERBOT_AI(bot)->GetGrouperType() != GrouperType::SOLO) { // TODO make action/config @@ -700,14 +706,13 @@ void PlayerbotHolder::OnBotLogin(Player* const bot) } std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, ObjectGuid guid, ObjectGuid masterguid, - bool admin, uint32 masterAccountId, uint32 masterGuildId) + bool admin, uint32 masterAccountId, uint32) { - if (!sPlayerbotAIConfig->enabled || guid.IsEmpty()) + if (!sPlayerbotAIConfig.enabled || guid.IsEmpty()) return "bot system is disabled"; - uint32 botAccount = sCharacterCache->GetCharacterAccountIdByGuid(guid); - //bool isRandomBot = sRandomPlayerbotMgr->IsRandomBot(guid.GetCounter()); //not used, line marked for removal. - //bool isRandomAccount = sPlayerbotAIConfig->IsInRandomAccountList(botAccount); //not used, shadowed, line marked for removal. + //bool isRandomBot = sRandomPlayerbotMgr.IsRandomBot(guid.GetCounter()); //not used, line marked for removal. + //bool isRandomAccount = sPlayerbotAIConfig.IsInRandomAccountList(botAccount); //not used, shadowed, line marked for removal. //bool isMasterAccount = (masterAccountId == botAccount); //not used, line marked for removal. if (cmd == "add" || cmd == "addaccount" || cmd == "login") @@ -720,13 +725,15 @@ std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, Obje { uint32 accountId = sCharacterCache->GetCharacterAccountIdByGuid(guid); if (!accountId) + { return "character not found"; + } - if (!sPlayerbotAIConfig->allowAccountBots && accountId != masterAccountId && - !(sPlayerbotAIConfig->allowTrustedAccountBots && IsAccountLinked(accountId, masterAccountId))) - { - return "you can only add bots from your own account or linked accounts"; - } + if (!sPlayerbotAIConfig.allowAccountBots && accountId != masterAccountId && + !(sPlayerbotAIConfig.allowTrustedAccountBots && IsAccountLinked(accountId, masterAccountId))) + { + return "you can only add bots from your own account or linked accounts"; + } } AddPlayerBot(guid, masterAccountId); @@ -748,12 +755,12 @@ std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, Obje // { Player* bot = GetPlayerBot(guid); if (!bot) - bot = sRandomPlayerbotMgr->GetPlayerBot(guid); + bot = sRandomPlayerbotMgr.GetPlayerBot(guid); if (!bot) return "bot not found"; - bool addClassBot = sRandomPlayerbotMgr->IsAddclassBot(guid.GetCounter()); + bool addClassBot = sRandomPlayerbotMgr.IsAddclassBot(guid.GetCounter()); if (!addClassBot) return "ERROR: You can not use this command on non-addclass bot."; @@ -771,7 +778,7 @@ std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, Obje { if (Player* master = GET_PLAYERBOT_AI(bot)->GetMaster()) { - if (master->GetSession()->GetSecurity() <= SEC_PLAYER && sPlayerbotAIConfig->autoInitOnly && + if (master->GetSession()->GetSecurity() <= SEC_PLAYER && sPlayerbotAIConfig.autoInitOnly && cmd != "init=auto") { return "The command is not allowed, use init=auto instead."; @@ -818,7 +825,7 @@ std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, Obje else if (cmd == "init=auto") { uint32 mixedGearScore = PlayerbotAI::GetMixedGearScore(master, true, false, 12) * - sPlayerbotAIConfig->autoInitEquipLevelLimitRatio; + sPlayerbotAIConfig.autoInitEquipLevelLimitRatio; // work around: distinguish from 0 if no gear if (mixedGearScore == 0) mixedGearScore = 1; @@ -858,7 +865,7 @@ std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, Obje } else if (cmd == "random") { - sRandomPlayerbotMgr->Randomize(bot); + sRandomPlayerbotMgr.Randomize(bot); return "ok"; } else if (cmd == "quests") @@ -886,7 +893,7 @@ static uint8 GetOfflinePlayerGender(ObjectGuid guid) bool PlayerbotMgr::HandlePlayerbotMgrCommand(ChatHandler* handler, char const* args) { - if (!sPlayerbotAIConfig->enabled) + if (!sPlayerbotAIConfig.enabled) { handler->PSendSysMessage("|cffff0000Playerbot system is currently disabled!"); return false; @@ -1052,7 +1059,7 @@ std::vector PlayerbotHolder::HandlePlayerbotCommand(char const* arg { if (master->GetSession()->GetSecurity() >= SEC_GAMEMASTER) { - sPlayerbotAIConfig->Initialize(); + sPlayerbotAIConfig.Initialize(); messages.push_back("Config reloaded."); return messages; } @@ -1065,11 +1072,11 @@ std::vector PlayerbotHolder::HandlePlayerbotCommand(char const* arg if (!strcmp(cmd, "tweak")) { - sPlayerbotAIConfig->tweakValue = sPlayerbotAIConfig->tweakValue++; - if (sPlayerbotAIConfig->tweakValue > 2) - sPlayerbotAIConfig->tweakValue = 0; + sPlayerbotAIConfig.tweakValue = sPlayerbotAIConfig.tweakValue++; + if (sPlayerbotAIConfig.tweakValue > 2) + sPlayerbotAIConfig.tweakValue = 0; - messages.push_back("Set tweakvalue to " + std::to_string(sPlayerbotAIConfig->tweakValue)); + messages.push_back("Set tweakvalue to " + std::to_string(sPlayerbotAIConfig.tweakValue)); return messages; } @@ -1080,14 +1087,14 @@ std::vector PlayerbotHolder::HandlePlayerbotCommand(char const* arg messages.push_back("Disable player botAI"); delete GET_PLAYERBOT_AI(master); } - else if (sPlayerbotAIConfig->selfBotLevel == 0) + else if (sPlayerbotAIConfig.selfBotLevel == 0) messages.push_back("Self-bot is disabled"); - else if (sPlayerbotAIConfig->selfBotLevel == 1 && master->GetSession()->GetSecurity() < SEC_GAMEMASTER) + else if (sPlayerbotAIConfig.selfBotLevel == 1 && master->GetSession()->GetSecurity() < SEC_GAMEMASTER) messages.push_back("You do not have permission to enable player botAI"); else { messages.push_back("Enable player botAI"); - sPlayerbotsMgr->AddPlayerbotData(master, true); + PlayerbotsMgr::instance().AddPlayerbotData(master, true); GET_PLAYERBOT_AI(master)->SetMaster(master); } @@ -1102,7 +1109,7 @@ std::vector PlayerbotHolder::HandlePlayerbotCommand(char const* arg if (!strcmp(cmd, "addclass")) { - if (sPlayerbotAIConfig->addClassCommand == 0 && master->GetSession()->GetSecurity() < SEC_GAMEMASTER) + if (sPlayerbotAIConfig.addClassCommand == 0 && master->GetSession()->GetSecurity() < SEC_GAMEMASTER) { messages.push_back("You do not have permission to create bot by addclass command"); return messages; @@ -1183,7 +1190,7 @@ std::vector PlayerbotHolder::HandlePlayerbotCommand(char const* arg return messages; } uint8 teamId = master->GetTeamId(true); - const std::unordered_set &guidCache = sRandomPlayerbotMgr->addclassCache[RandomPlayerbotMgr::GetTeamClassIdx(teamId == TEAM_ALLIANCE, claz)]; + const std::unordered_set &guidCache = sRandomPlayerbotMgr.addclassCache[RandomPlayerbotMgr::GetTeamClassIdx(teamId == TEAM_ALLIANCE, claz)]; for (const ObjectGuid &guid: guidCache) { // If the user requested a specific gender, skip any character that doesn't match. @@ -1194,7 +1201,7 @@ std::vector PlayerbotHolder::HandlePlayerbotCommand(char const* arg if (ObjectAccessor::FindConnectedPlayer(guid)) continue; uint32 guildId = sCharacterCache->GetCharacterGuildIdByGuid(guid); - if (guildId && sPlayerbotGuildMgr->IsRealGuild(guildId)) + if (guildId && PlayerbotGuildMgr::instance().IsRealGuild(guildId)) continue; AddPlayerBot(guid, master->GetSession()->GetAccountId()); messages.push_back("Add class " + std::string(charname)); @@ -1424,7 +1431,7 @@ std::string const PlayerbotHolder::ListBots(Player* master) for (Group::member_citerator itr = groupSlot.begin(); itr != groupSlot.end(); itr++) { Player* member = ObjectAccessor::FindPlayer(itr->guid); - if (member && sRandomPlayerbotMgr->IsRandomBot(member)) + if (member && sRandomPlayerbotMgr.IsRandomBot(member)) { std::string const name = member->GetName(); @@ -1452,7 +1459,7 @@ std::string const PlayerbotHolder::ListBots(Player* master) return out.str(); } -std::string const PlayerbotHolder::LookupBots(Player* master) +std::string const PlayerbotHolder::LookupBots(Player*) { std::list messages; messages.push_back("Classes Available:"); @@ -1494,12 +1501,12 @@ PlayerbotMgr::PlayerbotMgr(Player* const master) : PlayerbotHolder(), master(mas PlayerbotMgr::~PlayerbotMgr() { if (master) - sPlayerbotsMgr->RemovePlayerBotData(master->GetGUID(), false); + PlayerbotsMgr::instance().RemovePlayerBotData(master->GetGUID(), false); } void PlayerbotMgr::UpdateAIInternal(uint32 elapsed, bool /*minimal*/) { - SetNextCheckDelay(sPlayerbotAIConfig->reactDelay); + SetNextCheckDelay(sPlayerbotAIConfig.reactDelay); CheckTellErrors(elapsed); } @@ -1509,10 +1516,10 @@ void PlayerbotMgr::HandleCommand(uint32 type, std::string const text) if (!master) return; - if (text.find(sPlayerbotAIConfig->commandSeparator) != std::string::npos) + if (text.find(sPlayerbotAIConfig.commandSeparator) != std::string::npos) { std::vector commands; - split(commands, text, sPlayerbotAIConfig->commandSeparator.c_str()); + split(commands, text, sPlayerbotAIConfig.commandSeparator.c_str()); for (std::vector::iterator i = commands.begin(); i != commands.end(); ++i) { HandleCommand(type, *i); @@ -1529,8 +1536,8 @@ void PlayerbotMgr::HandleCommand(uint32 type, std::string const text) botAI->HandleCommand(type, text, master); } - for (PlayerBotMap::const_iterator it = sRandomPlayerbotMgr->GetPlayerBotsBegin(); - it != sRandomPlayerbotMgr->GetPlayerBotsEnd(); ++it) + for (PlayerBotMap::const_iterator it = sRandomPlayerbotMgr.GetPlayerBotsBegin(); + it != sRandomPlayerbotMgr.GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); @@ -1551,8 +1558,8 @@ void PlayerbotMgr::HandleMasterIncomingPacket(WorldPacket const& packet) botAI->HandleMasterIncomingPacket(packet); } - for (PlayerBotMap::const_iterator it = sRandomPlayerbotMgr->GetPlayerBotsBegin(); - it != sRandomPlayerbotMgr->GetPlayerBotsEnd(); ++it) + for (PlayerBotMap::const_iterator it = sRandomPlayerbotMgr.GetPlayerBotsBegin(); + it != sRandomPlayerbotMgr.GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); @@ -1587,8 +1594,8 @@ void PlayerbotMgr::HandleMasterOutgoingPacket(WorldPacket const& packet) botAI->HandleMasterOutgoingPacket(packet); } - for (PlayerBotMap::const_iterator it = sRandomPlayerbotMgr->GetPlayerBotsBegin(); - it != sRandomPlayerbotMgr->GetPlayerBotsEnd(); ++it) + for (PlayerBotMap::const_iterator it = sRandomPlayerbotMgr.GetPlayerBotsBegin(); + it != sRandomPlayerbotMgr.GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); @@ -1605,8 +1612,8 @@ void PlayerbotMgr::SaveToDB() bot->SaveToDB(false, false); } - for (PlayerBotMap::const_iterator it = sRandomPlayerbotMgr->GetPlayerBotsBegin(); - it != sRandomPlayerbotMgr->GetPlayerBotsEnd(); ++it) + for (PlayerBotMap::const_iterator it = sRandomPlayerbotMgr.GetPlayerBotsBegin(); + it != sRandomPlayerbotMgr.GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; if (GET_PLAYERBOT_AI(bot) && GET_PLAYERBOT_AI(bot)->GetMaster() == GetMaster()) @@ -1648,12 +1655,12 @@ void PlayerbotMgr::OnPlayerLogin(Player* player) usedLocale = LOCALE_enUS; // fallback // set locale priority for bot texts - sPlayerbotTextMgr->AddLocalePriority(usedLocale); + PlayerbotTextMgr::instance().AddLocalePriority(usedLocale); - if (sPlayerbotAIConfig->selfBotLevel > 2) + if (sPlayerbotAIConfig.selfBotLevel > 2) HandlePlayerbotCommand("self", player); - if (!sPlayerbotAIConfig->botAutologin) + if (!sPlayerbotAIConfig.botAutologin) return; uint32 accountId = session->GetAccountId(); @@ -1690,10 +1697,10 @@ void PlayerbotMgr::TellError(std::string const botName, std::string const text) errors[text] = names; } -void PlayerbotMgr::CheckTellErrors(uint32 elapsed) +void PlayerbotMgr::CheckTellErrors(uint32) { time_t now = time(nullptr); - if ((now - lastErrorTell) < sPlayerbotAIConfig->errorDelay / 1000) + if ((now - lastErrorTell) < sPlayerbotAIConfig.errorDelay / 1000) return; lastErrorTell = now; @@ -1777,7 +1784,7 @@ void PlayerbotsMgr::RemovePlayerBotData(ObjectGuid const& guid, bool is_AI) PlayerbotAI* PlayerbotsMgr::GetPlayerbotAI(Player* player) { - if (!(sPlayerbotAIConfig->enabled) || !player) + if (!(sPlayerbotAIConfig.enabled) || !player) { return nullptr; } @@ -1797,7 +1804,7 @@ PlayerbotAI* PlayerbotsMgr::GetPlayerbotAI(Player* player) PlayerbotMgr* PlayerbotsMgr::GetPlayerbotMgr(Player* player) { - if (!(sPlayerbotAIConfig->enabled) || !player) + if (!(sPlayerbotAIConfig.enabled) || !player) { return nullptr; } diff --git a/src/Bot/PlayerbotMgr.h b/src/Bot/PlayerbotMgr.h index 7ee576006b..b80f6f2363 100644 --- a/src/Bot/PlayerbotMgr.h +++ b/src/Bot/PlayerbotMgr.h @@ -6,12 +6,9 @@ #ifndef _PLAYERBOT_PLAYERBOTMGR_H #define _PLAYERBOT_PLAYERBOTMGR_H -#include "Common.h" #include "ObjectGuid.h" #include "Player.h" #include "PlayerbotAIBase.h" -#include "QueryHolder.h" -#include "QueryResult.h" class ChatHandler; class PlayerbotAI; @@ -101,13 +98,10 @@ class PlayerbotMgr : public PlayerbotHolder class PlayerbotsMgr { public: - PlayerbotsMgr() {} - ~PlayerbotsMgr() {} - - static PlayerbotsMgr* instance() + static PlayerbotsMgr& instance() { static PlayerbotsMgr instance; - return &instance; + return instance; } void AddPlayerbotData(Player* player, bool isBotAI); @@ -117,6 +111,15 @@ class PlayerbotsMgr PlayerbotMgr* GetPlayerbotMgr(Player* player); private: + PlayerbotsMgr() = default; + ~PlayerbotsMgr() = default; + + PlayerbotsMgr(const PlayerbotsMgr&) = delete; + PlayerbotsMgr& operator=(const PlayerbotsMgr&) = delete; + + PlayerbotsMgr(PlayerbotsMgr&&) = delete; + PlayerbotsMgr& operator=(PlayerbotsMgr&&) = delete; + std::unordered_map _playerbotsAIMap; std::unordered_map _playerbotsMgrMap; }; diff --git a/src/Bot/RandomPlayerbotMgr.cpp b/src/Bot/RandomPlayerbotMgr.cpp index 4d589ef1b4..06bb147edb 100644 --- a/src/Bot/RandomPlayerbotMgr.cpp +++ b/src/Bot/RandomPlayerbotMgr.cpp @@ -14,12 +14,9 @@ #include #include -#include "AccountMgr.h" #include "AiFactory.h" -#include "ArenaTeamMgr.h" #include "Battleground.h" #include "BattlegroundMgr.h" -#include "CellImpl.h" #include "ChannelMgr.h" #include "DBCStores.h" #include "DBCStructure.h" @@ -28,9 +25,6 @@ #include "FleeManager.h" #include "FlightMasterCache.h" #include "GridNotifiers.h" -#include "GridNotifiersImpl.h" -#include "GuildMgr.h" -#include "GuildTaskMgr.h" #include "LFGMgr.h" #include "MapMgr.h" #include "NewRpgInfo.h" @@ -40,7 +34,6 @@ #include "Player.h" #include "PlayerbotAI.h" #include "PlayerbotAIConfig.h" -#include "PlayerbotCommandServer.h" #include "PlayerbotFactory.h" #include "Playerbots.h" #include "Position.h" @@ -50,8 +43,14 @@ #include "SharedDefines.h" #include "TravelMgr.h" #include "Unit.h" -#include "UpdateTime.h" #include "World.h" +#include "PlayerGuildRegistry.h" +#include "Cell.h" +#include "GridNotifiers.h" +// Required for Cell because of poor AC implementation +#include "CellImpl.h" +// Required for GridNotifiers because of poor AC implementation +#include "GridNotifiersImpl.h" struct GuidClassRaceInfo { @@ -102,7 +101,7 @@ static const std::unordered_map> cityToBankers = { // Quick lookup map: banker entry → location static std::unordered_map bankerEntryToLocation; -void PrintStatsThread() { sRandomPlayerbotMgr->PrintStats(); } +void PrintStatsThread() { sRandomPlayerbotMgr.PrintStats(); } void activatePrintStatsThread() { @@ -110,7 +109,7 @@ void activatePrintStatsThread() t.detach(); } -void CheckBgQueueThread() { sRandomPlayerbotMgr->CheckBgQueue(); } +void CheckBgQueueThread() { sRandomPlayerbotMgr.CheckBgQueue(); } void activateCheckBgQueueThread() { @@ -118,7 +117,7 @@ void activateCheckBgQueueThread() t.detach(); } -void CheckLfgQueueThread() { sRandomPlayerbotMgr->CheckLfgQueue(); } +void CheckLfgQueueThread() { sRandomPlayerbotMgr.CheckLfgQueue(); } void activateCheckLfgQueueThread() { @@ -126,7 +125,7 @@ void activateCheckLfgQueueThread() t.detach(); } -void CheckPlayersThread() { sRandomPlayerbotMgr->CheckPlayers(); } +void CheckPlayersThread() { sRandomPlayerbotMgr.CheckPlayers(); } void activateCheckPlayersThread() { @@ -215,36 +214,6 @@ double botPIDImpl::calculate(double setpoint, double pv) botPIDImpl::~botPIDImpl() {} -RandomPlayerbotMgr::RandomPlayerbotMgr() : PlayerbotHolder(), processTicks(0) -{ - playersLevel = sPlayerbotAIConfig->randombotStartingLevel; - - if (sPlayerbotAIConfig->enabled || sPlayerbotAIConfig->randomBotAutologin) - { - sPlayerbotCommandServer->Start(); - } - - BattlegroundData.clear(); // Clear here and here only. - - // Cleanup on server start: orphaned pet data that's often left behind by bot pets that no longer exist in the DB - CharacterDatabase.Execute("DELETE FROM pet_aura WHERE guid NOT IN (SELECT id FROM character_pet)"); - CharacterDatabase.Execute("DELETE FROM pet_spell WHERE guid NOT IN (SELECT id FROM character_pet)"); - CharacterDatabase.Execute("DELETE FROM pet_spell_cooldown WHERE guid NOT IN (SELECT id FROM character_pet)"); - - for (int bracket = BG_BRACKET_ID_FIRST; bracket < MAX_BATTLEGROUND_BRACKETS; ++bracket) - { - for (int queueType = BATTLEGROUND_QUEUE_AV; queueType < MAX_BATTLEGROUND_QUEUE_TYPES; ++queueType) - { - BattlegroundData[queueType][bracket] = BattlegroundInfo(); - } - } - BgCheckTimer = 0; - LfgCheckTimer = 0; - PlayersCheckTimer = 0; -} - -RandomPlayerbotMgr::~RandomPlayerbotMgr() {} - uint32 RandomPlayerbotMgr::GetMaxAllowedBotCount() { return GetEventValue(0, "bot_count"); } void RandomPlayerbotMgr::LogPlayerLocation() @@ -253,9 +222,9 @@ void RandomPlayerbotMgr::LogPlayerLocation() try { - sPlayerbotAIConfig->openLog("player_location.csv", "w"); + sPlayerbotAIConfig.openLog("player_location.csv", "w"); - if (sPlayerbotAIConfig->randomBotAutologin) + if (sPlayerbotAIConfig.randomBotAutologin) { for (auto i : GetAllBots()) { @@ -264,7 +233,7 @@ void RandomPlayerbotMgr::LogPlayerLocation() continue; std::ostringstream out; - out << sPlayerbotAIConfig->GetTimestampStr() << "+00,"; + out << sPlayerbotAIConfig.GetTimestampStr() << "+00,"; out << "RND" << ","; out << bot->GetName() << ","; @@ -298,7 +267,7 @@ void RandomPlayerbotMgr::LogPlayerLocation() out << (bot->IsInCombat() ? "combat" : "safe") << ","; out << (bot->isDead() ? (bot->GetCorpse() ? "ghost" : "dead") : "alive"); - sPlayerbotAIConfig->log("player_location.csv", out.str().c_str()); + sPlayerbotAIConfig.log("player_location.csv", out.str().c_str()); } for (auto i : GetPlayers()) @@ -308,7 +277,7 @@ void RandomPlayerbotMgr::LogPlayerLocation() continue; std::ostringstream out; - out << sPlayerbotAIConfig->GetTimestampStr() << "+00,"; + out << sPlayerbotAIConfig.GetTimestampStr() << "+00,"; out << "PLR" << ","; out << bot->GetName() << ","; @@ -342,7 +311,7 @@ void RandomPlayerbotMgr::LogPlayerLocation() out << (bot->IsInCombat() ? "combat" : "safe") << ","; out << (bot->isDead() ? (bot->GetCorpse() ? "ghost" : "dead") : "alive"); - sPlayerbotAIConfig->log("player_location.csv", out.str().c_str()); + sPlayerbotAIConfig.log("player_location.csv", out.str().c_str()); } } } @@ -354,17 +323,17 @@ void RandomPlayerbotMgr::LogPlayerLocation() } } -void RandomPlayerbotMgr::UpdateAIInternal(uint32 elapsed, bool /*minimal*/) +void RandomPlayerbotMgr::UpdateAIInternal(uint32, bool /*minimal*/) { if (totalPmo) totalPmo->finish(); - totalPmo = sPerfMonitor->start(PERF_MON_TOTAL, "RandomPlayerbotMgr::FullTick"); + totalPmo = sPerfMonitor.start(PERF_MON_TOTAL, "RandomPlayerbotMgr::FullTick"); - if (!sPlayerbotAIConfig->randomBotAutologin || !sPlayerbotAIConfig->enabled) + if (!sPlayerbotAIConfig.randomBotAutologin || !sPlayerbotAIConfig.enabled) return; - /*if (sPlayerbotAIConfig->enablePrototypePerformanceDiff) + /*if (sPlayerbotAIConfig.enablePrototypePerformanceDiff) { LOG_INFO("playerbots", "---------------------------------------"); LOG_INFO("playerbots", @@ -374,13 +343,13 @@ void RandomPlayerbotMgr::UpdateAIInternal(uint32 elapsed, bool /*minimal*/) }*/ uint32 maxAllowedBotCount = GetEventValue(0, "bot_count"); - if (!maxAllowedBotCount || (maxAllowedBotCount < sPlayerbotAIConfig->minRandomBots || - maxAllowedBotCount > sPlayerbotAIConfig->maxRandomBots)) + if (!maxAllowedBotCount || (maxAllowedBotCount < sPlayerbotAIConfig.minRandomBots || + maxAllowedBotCount > sPlayerbotAIConfig.maxRandomBots)) { - maxAllowedBotCount = urand(sPlayerbotAIConfig->minRandomBots, sPlayerbotAIConfig->maxRandomBots); + maxAllowedBotCount = urand(sPlayerbotAIConfig.minRandomBots, sPlayerbotAIConfig.maxRandomBots); SetEventValue(0, "bot_count", maxAllowedBotCount, - urand(sPlayerbotAIConfig->randomBotCountChangeMinInterval, - sPlayerbotAIConfig->randomBotCountChangeMaxInterval)); + urand(sPlayerbotAIConfig.randomBotCountChangeMinInterval, + sPlayerbotAIConfig.randomBotCountChangeMaxInterval)); } GetBots(); @@ -389,25 +358,25 @@ void RandomPlayerbotMgr::UpdateAIInternal(uint32 elapsed, bool /*minimal*/) uint32 onlineBotCount = playerBots.size(); uint32 onlineBotFocus = 75; - if (onlineBotCount < (uint32)(sPlayerbotAIConfig->minRandomBots * 90 / 100)) + if (onlineBotCount < (uint32)(sPlayerbotAIConfig.minRandomBots * 90 / 100)) onlineBotFocus = 25; // only keep updating till initializing time has completed, // which prevents unneeded expensive GameTime calls. if (_isBotInitializing) { - _isBotInitializing = GameTime::GetUptime().count() < sPlayerbotAIConfig->maxRandomBots * (0.11 + 0.4); + _isBotInitializing = GameTime::GetUptime().count() < sPlayerbotAIConfig.maxRandomBots * (0.11 + 0.4); } - uint32 updateIntervalTurboBoost = _isBotInitializing ? 1 : sPlayerbotAIConfig->randomBotUpdateInterval; + uint32 updateIntervalTurboBoost = _isBotInitializing ? 1 : sPlayerbotAIConfig.randomBotUpdateInterval; SetNextCheckDelay(updateIntervalTurboBoost * (onlineBotFocus + 25) * 10); - PerfMonitorOperation* pmo = sPerfMonitor->start( + PerfMonitorOperation* pmo = sPerfMonitor.start( PERF_MON_TOTAL, onlineBotCount < maxAllowedBotCount ? "RandomPlayerbotMgr::Login" : "RandomPlayerbotMgr::UpdateAIInternal"); bool realPlayerIsLogged = false; - if (sPlayerbotAIConfig->disabledWithoutRealPlayer) + if (sPlayerbotAIConfig.disabledWithoutRealPlayer) { if (sWorldSessionMgr->GetActiveAndQueuedSessionCount() > 0) { @@ -416,7 +385,7 @@ void RandomPlayerbotMgr::UpdateAIInternal(uint32 elapsed, bool /*minimal*/) if (DelayLoginBotsTimer == 0) { - DelayLoginBotsTimer = time(nullptr) + sPlayerbotAIConfig->disabledWithoutRealPlayerLoginDelay; + DelayLoginBotsTimer = time(nullptr) + sPlayerbotAIConfig.disabledWithoutRealPlayerLoginDelay; } } else @@ -427,7 +396,7 @@ void RandomPlayerbotMgr::UpdateAIInternal(uint32 elapsed, bool /*minimal*/) } if (RealPlayerLastTimeSeen != 0 && onlineBotCount > 0 && - time(nullptr) > RealPlayerLastTimeSeen + sPlayerbotAIConfig->disabledWithoutRealPlayerLogoutDelay) + time(nullptr) > RealPlayerLastTimeSeen + sPlayerbotAIConfig.disabledWithoutRealPlayerLogoutDelay) { LogoutAllBots(); LOG_INFO("playerbots", "Logout all bots due no real player session."); @@ -435,7 +404,7 @@ void RandomPlayerbotMgr::UpdateAIInternal(uint32 elapsed, bool /*minimal*/) } if (availableBotCount < maxAllowedBotCount && - (sPlayerbotAIConfig->disabledWithoutRealPlayer == false || + (sPlayerbotAIConfig.disabledWithoutRealPlayer == false || (realPlayerIsLogged && DelayLoginBotsTimer != 0 && time(nullptr) >= DelayLoginBotsTimer))) { AddRandomBots(); @@ -446,25 +415,25 @@ void RandomPlayerbotMgr::UpdateAIInternal(uint32 elapsed, bool /*minimal*/) AddRandomBots(); } - if (sPlayerbotAIConfig->syncLevelWithPlayers && !players.empty()) + if (sPlayerbotAIConfig.syncLevelWithPlayers && !players.empty()) { if (time(nullptr) > (PlayersCheckTimer + 60)) - sRandomPlayerbotMgr->CheckPlayers(); + sRandomPlayerbotMgr.CheckPlayers(); } - if (sPlayerbotAIConfig->randomBotJoinBG /* && !players.empty()*/) + if (sPlayerbotAIConfig.randomBotJoinBG /* && !players.empty()*/) { if (time(nullptr) > (BgCheckTimer + 35)) - sRandomPlayerbotMgr->CheckBgQueue(); + sRandomPlayerbotMgr.CheckBgQueue(); } - if (sPlayerbotAIConfig->randomBotJoinLfg /* && !players.empty()*/) + if (sPlayerbotAIConfig.randomBotJoinLfg /* && !players.empty()*/) { if (time(nullptr) > (LfgCheckTimer + 30)) - sRandomPlayerbotMgr->CheckLfgQueue(); + sRandomPlayerbotMgr.CheckLfgQueue(); } - if (sPlayerbotAIConfig->randomBotAutologin && time(nullptr) > (printStatsTimer + 300)) + if (sPlayerbotAIConfig.randomBotAutologin && time(nullptr) > (printStatsTimer + 300)) { if (!printStatsTimer) { @@ -472,18 +441,18 @@ void RandomPlayerbotMgr::UpdateAIInternal(uint32 elapsed, bool /*minimal*/) } else { - sRandomPlayerbotMgr->PrintStats(); + sRandomPlayerbotMgr.PrintStats(); // activatePrintStatsThread(); } } - uint32 updateBots = sPlayerbotAIConfig->randomBotsPerInterval * onlineBotFocus / 100; + uint32 updateBots = sPlayerbotAIConfig.randomBotsPerInterval * onlineBotFocus / 100; uint32 maxNewBots = onlineBotCount < maxAllowedBotCount && - (sPlayerbotAIConfig->disabledWithoutRealPlayer == false || + (sPlayerbotAIConfig.disabledWithoutRealPlayer == false || (realPlayerIsLogged && DelayLoginBotsTimer != 0 && time(nullptr) >= DelayLoginBotsTimer)) ? maxAllowedBotCount - onlineBotCount : 0; - uint32 loginBots = std::min(sPlayerbotAIConfig->randomBotsPerInterval - updateBots, maxNewBots); + uint32 loginBots = std::min(sPlayerbotAIConfig.randomBotsPerInterval - updateBots, maxNewBots); if (!availableBots.empty()) { @@ -531,7 +500,7 @@ void RandomPlayerbotMgr::UpdateAIInternal(uint32 elapsed, bool /*minimal*/) if (pmo) pmo->finish(); - if (sPlayerbotAIConfig->hasLog("player_location.csv")) + if (sPlayerbotAIConfig.hasLog("player_location.csv")) { LogPlayerLocation(); } @@ -546,8 +515,8 @@ void RandomPlayerbotMgr::UpdateAIInternal(uint32 elapsed, bool /*minimal*/) // // // % increase/decrease wanted diff , avg diff // float activityPercentageMod = pid.calculate( -// sRandomPlayerbotMgr->GetPlayers().empty() ? sPlayerbotAIConfig->diffEmpty : -// sPlayerbotAIConfig->diffWithPlayer, sWorldUpdateTime.GetAverageUpdateTime()); +// sRandomPlayerbotMgr.GetPlayers().empty() ? sPlayerbotAIConfig.diffEmpty : +// sPlayerbotAIConfig.diffWithPlayer, sWorldUpdateTime.GetAverageUpdateTime()); // // activityPercentage = activityPercentageMod + 50; // @@ -573,7 +542,7 @@ void RandomPlayerbotMgr::AssignAccountTypes() std::vector allRandomBotAccounts; QueryResult allAccounts = LoginDatabase.Query( "SELECT id FROM account WHERE username LIKE '{}%%' ORDER BY id", - sPlayerbotAIConfig->randomBotAccountPrefix.c_str()); + sPlayerbotAIConfig.randomBotAccountPrefix.c_str()); if (allAccounts) { @@ -614,15 +583,15 @@ void RandomPlayerbotMgr::AssignAccountTypes() // Calculate needed RNDbot accounts uint32 neededRndBotAccounts = 0; - if (sPlayerbotAIConfig->maxRandomBots > 0) + if (sPlayerbotAIConfig.maxRandomBots > 0) { int divisor = RandomPlayerbotFactory::CalculateAvailableCharsPerAccount(); - int maxBots = sPlayerbotAIConfig->maxRandomBots; + int maxBots = sPlayerbotAIConfig.maxRandomBots; // Take periodic online-offline into account - if (sPlayerbotAIConfig->enablePeriodicOnlineOffline) + if (sPlayerbotAIConfig.enablePeriodicOnlineOffline) { - maxBots *= sPlayerbotAIConfig->periodicOnlineOfflineRatio; + maxBots *= sPlayerbotAIConfig.periodicOnlineOfflineRatio; } // Calculate base accounts needed for RNDbots, ensuring round up for maxBots not cleanly divisible by the divisor @@ -663,7 +632,7 @@ void RandomPlayerbotMgr::AssignAccountTypes() } // Assign AddClass accounts from highest position if needed - uint32 neededAddClassAccounts = sPlayerbotAIConfig->addClassAccountPoolSize; + uint32 neededAddClassAccounts = sPlayerbotAIConfig.addClassAccountPoolSize; if (existingAddClassAccounts < neededAddClassAccounts) { @@ -719,16 +688,16 @@ uint32 RandomPlayerbotMgr::AddRandomBots() { // Calculate how many bots to add maxAllowedBotCount -= currentBots.size(); - maxAllowedBotCount = std::min(sPlayerbotAIConfig->randomBotsPerInterval, maxAllowedBotCount); + maxAllowedBotCount = std::min(sPlayerbotAIConfig.randomBotsPerInterval, maxAllowedBotCount); // Single RNG instance for all shuffling std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count()); // Only need to track the Alliance count, as it's in Phase 1 - uint32 totalRatio = sPlayerbotAIConfig->randomBotAllianceRatio + sPlayerbotAIConfig->randomBotHordeRatio; - uint32 allowedAllianceCount = maxAllowedBotCount * (sPlayerbotAIConfig->randomBotAllianceRatio) / totalRatio; + uint32 totalRatio = sPlayerbotAIConfig.randomBotAllianceRatio + sPlayerbotAIConfig.randomBotHordeRatio; + uint32 allowedAllianceCount = maxAllowedBotCount * (sPlayerbotAIConfig.randomBotAllianceRatio) / totalRatio; - uint32 remainder = maxAllowedBotCount * (sPlayerbotAIConfig->randomBotAllianceRatio) % totalRatio; + uint32 remainder = maxAllowedBotCount * (sPlayerbotAIConfig.randomBotAllianceRatio) % totalRatio; // Fix #1082: Randomly add one based on reminder if (remainder && urand(1, totalRatio) <= remainder) @@ -738,13 +707,13 @@ uint32 RandomPlayerbotMgr::AddRandomBots() // Determine which accounts to use based on EnablePeriodicOnlineOffline std::vector accountsToUse; - if (sPlayerbotAIConfig->enablePeriodicOnlineOffline) + if (sPlayerbotAIConfig.enablePeriodicOnlineOffline) { // Calculate how many accounts can be used // With enablePeriodicOnlineOffline, don't use all of rndBotTypeAccounts right away. Fraction results are rounded up - uint32 accountsToUseCount = (rndBotTypeAccounts.size() + sPlayerbotAIConfig->periodicOnlineOfflineRatio - 1) - / sPlayerbotAIConfig->periodicOnlineOfflineRatio; + uint32 accountsToUseCount = (rndBotTypeAccounts.size() + sPlayerbotAIConfig.periodicOnlineOfflineRatio - 1) + / sPlayerbotAIConfig.periodicOnlineOfflineRatio; // Randomly select accounts std::vector shuffledAccounts = rndBotTypeAccounts; @@ -814,15 +783,15 @@ uint32 RandomPlayerbotMgr::AddRandomBots() GetEventValue(charInfo.guid, "logout") || GetPlayerBot(charInfo.guid) || std::find(currentBots.begin(), currentBots.end(), charInfo.guid) != currentBots.end() || - (sPlayerbotAIConfig->disableDeathKnightLogin && charInfo.rClass == CLASS_DEATH_KNIGHT)) + (sPlayerbotAIConfig.disableDeathKnightLogin && charInfo.rClass == CLASS_DEATH_KNIGHT)) { return false; } - uint32 add_time = sPlayerbotAIConfig->enablePeriodicOnlineOffline - ? urand(sPlayerbotAIConfig->minRandomBotInWorldTime, - sPlayerbotAIConfig->maxRandomBotInWorldTime) - : sPlayerbotAIConfig->permanentlyInWorldTime; + uint32 add_time = sPlayerbotAIConfig.enablePeriodicOnlineOffline + ? urand(sPlayerbotAIConfig.minRandomBotInWorldTime, + sPlayerbotAIConfig.maxRandomBotInWorldTime) + : sPlayerbotAIConfig.permanentlyInWorldTime; SetEventValue(charInfo.guid, "add", 1, add_time); SetEventValue(charInfo.guid, "logout", 0, 0); @@ -1026,7 +995,7 @@ void RandomPlayerbotMgr::CheckBgQueue() // Arena logic bool isRated = false; - if (uint8 arenaType = BattlegroundMgr::BGArenaType(queueTypeId)) + if (BattlegroundMgr::BGArenaType(queueTypeId)) { BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(queueTypeId); GroupQueueInfo ginfo; @@ -1113,7 +1082,7 @@ void RandomPlayerbotMgr::CheckBgQueue() BattlegroundData[queueTypeId][bracketId].minLevel = pvpDiff->minLevel; BattlegroundData[queueTypeId][bracketId].maxLevel = pvpDiff->maxLevel; - if (uint8 arenaType = BattlegroundMgr::BGArenaType(queueTypeId)) + if (BattlegroundMgr::BGArenaType(queueTypeId)) { bool isRated = false; BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(queueTypeId); @@ -1187,24 +1156,24 @@ void RandomPlayerbotMgr::CheckBgQueue() } // If enabled, wait for all bots to have logged in before queueing for Arena's / BG's - if (sPlayerbotAIConfig->randomBotAutoJoinBG && playerBots.size() >= GetMaxAllowedBotCount()) + if (sPlayerbotAIConfig.randomBotAutoJoinBG && playerBots.size() >= GetMaxAllowedBotCount()) { - uint32 randomBotAutoJoinArenaBracket = sPlayerbotAIConfig->randomBotAutoJoinArenaBracket; - uint32 randomBotAutoJoinBGRatedArena2v2Count = sPlayerbotAIConfig->randomBotAutoJoinBGRatedArena2v2Count; - uint32 randomBotAutoJoinBGRatedArena3v3Count = sPlayerbotAIConfig->randomBotAutoJoinBGRatedArena3v3Count; - uint32 randomBotAutoJoinBGRatedArena5v5Count = sPlayerbotAIConfig->randomBotAutoJoinBGRatedArena5v5Count; + uint32 randomBotAutoJoinArenaBracket = sPlayerbotAIConfig.randomBotAutoJoinArenaBracket; + uint32 randomBotAutoJoinBGRatedArena2v2Count = sPlayerbotAIConfig.randomBotAutoJoinBGRatedArena2v2Count; + uint32 randomBotAutoJoinBGRatedArena3v3Count = sPlayerbotAIConfig.randomBotAutoJoinBGRatedArena3v3Count; + uint32 randomBotAutoJoinBGRatedArena5v5Count = sPlayerbotAIConfig.randomBotAutoJoinBGRatedArena5v5Count; - uint32 randomBotAutoJoinBGICCount = sPlayerbotAIConfig->randomBotAutoJoinBGICCount; - uint32 randomBotAutoJoinBGEYCount = sPlayerbotAIConfig->randomBotAutoJoinBGEYCount; - uint32 randomBotAutoJoinBGAVCount = sPlayerbotAIConfig->randomBotAutoJoinBGAVCount; - uint32 randomBotAutoJoinBGABCount = sPlayerbotAIConfig->randomBotAutoJoinBGABCount; - uint32 randomBotAutoJoinBGWSCount = sPlayerbotAIConfig->randomBotAutoJoinBGWSCount; + uint32 randomBotAutoJoinBGICCount = sPlayerbotAIConfig.randomBotAutoJoinBGICCount; + uint32 randomBotAutoJoinBGEYCount = sPlayerbotAIConfig.randomBotAutoJoinBGEYCount; + uint32 randomBotAutoJoinBGAVCount = sPlayerbotAIConfig.randomBotAutoJoinBGAVCount; + uint32 randomBotAutoJoinBGABCount = sPlayerbotAIConfig.randomBotAutoJoinBGABCount; + uint32 randomBotAutoJoinBGWSCount = sPlayerbotAIConfig.randomBotAutoJoinBGWSCount; - std::vector icBrackets = parseBrackets(sPlayerbotAIConfig->randomBotAutoJoinICBrackets); - std::vector eyBrackets = parseBrackets(sPlayerbotAIConfig->randomBotAutoJoinEYBrackets); - std::vector avBrackets = parseBrackets(sPlayerbotAIConfig->randomBotAutoJoinAVBrackets); - std::vector abBrackets = parseBrackets(sPlayerbotAIConfig->randomBotAutoJoinABBrackets); - std::vector wsBrackets = parseBrackets(sPlayerbotAIConfig->randomBotAutoJoinWSBrackets); + std::vector icBrackets = parseBrackets(sPlayerbotAIConfig.randomBotAutoJoinICBrackets); + std::vector eyBrackets = parseBrackets(sPlayerbotAIConfig.randomBotAutoJoinEYBrackets); + std::vector avBrackets = parseBrackets(sPlayerbotAIConfig.randomBotAutoJoinAVBrackets); + std::vector abBrackets = parseBrackets(sPlayerbotAIConfig.randomBotAutoJoinABBrackets); + std::vector wsBrackets = parseBrackets(sPlayerbotAIConfig.randomBotAutoJoinWSBrackets); // Check both bgInstanceCount / bgInstances.size // to help counter against potentional inconsistencies @@ -1369,7 +1338,7 @@ void RandomPlayerbotMgr::CheckPlayers() LOG_INFO("playerbots", "Checking Players..."); if (!playersLevel) - playersLevel = sPlayerbotAIConfig->randombotStartingLevel; + playersLevel = sPlayerbotAIConfig.randombotStartingLevel; for (std::vector::iterator i = players.begin(); i != players.end(); ++i) { @@ -1393,7 +1362,7 @@ void RandomPlayerbotMgr::ScheduleRandomize(uint32 bot, uint32 time) { SetEventVa void RandomPlayerbotMgr::ScheduleTeleport(uint32 bot, uint32 time) { if (!time) - time = 60 + urand(sPlayerbotAIConfig->randomBotUpdateInterval, sPlayerbotAIConfig->randomBotUpdateInterval * 3); + time = 60 + urand(sPlayerbotAIConfig.randomBotUpdateInterval, sPlayerbotAIConfig.randomBotUpdateInterval * 3); SetEventValue(bot, "teleport", 1, time); } @@ -1401,8 +1370,8 @@ void RandomPlayerbotMgr::ScheduleTeleport(uint32 bot, uint32 time) void RandomPlayerbotMgr::ScheduleChangeStrategy(uint32 bot, uint32 time) { if (!time) - time = urand(sPlayerbotAIConfig->minRandomBotChangeStrategyTime, - sPlayerbotAIConfig->maxRandomBotChangeStrategyTime); + time = urand(sPlayerbotAIConfig.minRandomBotChangeStrategyTime, + sPlayerbotAIConfig.maxRandomBotChangeStrategyTime); SetEventValue(bot, "change_strategy", 1, time); } @@ -1440,7 +1409,7 @@ bool RandomPlayerbotMgr::ProcessBot(uint32 bot) AddPlayerBot(botGUID, 0); randomTime = urand(1, 2); - uint32 randomBotUpdateInterval = _isBotInitializing ? 1 : sPlayerbotAIConfig->randomBotUpdateInterval; + uint32 randomBotUpdateInterval = _isBotInitializing ? 1 : sPlayerbotAIConfig.randomBotUpdateInterval; randomTime = urand(std::max(5, static_cast(randomBotUpdateInterval * 0.5)), std::max(12, static_cast(randomBotUpdateInterval * 2))); SetEventValue(bot, "update", 1, randomTime); @@ -1477,7 +1446,7 @@ bool RandomPlayerbotMgr::ProcessBot(uint32 bot) if (botAI) { // botAI->GetAiObjectContext()->GetValue("random bot update")->Set(true); - if (!sRandomPlayerbotMgr->IsRandomBot(player)) + if (!sRandomPlayerbotMgr.IsRandomBot(player)) update = false; if (player->GetGroup() && botAI->GetGroupLeader()) @@ -1489,14 +1458,14 @@ bool RandomPlayerbotMgr::ProcessBot(uint32 bot) } } - // if (botAI->HasPlayerNearby(sPlayerbotAIConfig->grindDistance)) + // if (botAI->HasPlayerNearby(sPlayerbotAIConfig.grindDistance)) // update = false; } if (update) ProcessBot(player); - randomTime = urand(sPlayerbotAIConfig->minRandomBotReviveTime, sPlayerbotAIConfig->maxRandomBotReviveTime); + randomTime = urand(sPlayerbotAIConfig.minRandomBotReviveTime, sPlayerbotAIConfig.maxRandomBotReviveTime); SetEventValue(bot, "update", 1, randomTime); return true; @@ -1510,17 +1479,71 @@ bool RandomPlayerbotMgr::ProcessBot(uint32 bot) LogoutPlayerBot(botGUID); currentBots.remove(bot); SetEventValue(bot, "logout", 1, - urand(sPlayerbotAIConfig->minRandomBotInWorldTime, sPlayerbotAIConfig->maxRandomBotInWorldTime)); + urand(sPlayerbotAIConfig.minRandomBotInWorldTime, sPlayerbotAIConfig.maxRandomBotInWorldTime)); return true; } return false; } -bool RandomPlayerbotMgr::ProcessBot(Player* bot) +bool RandomPlayerbotMgr::ProcessBotRandomization(Player* bot) { + if (sPlayerbotAIConfig.disableRandomBotPeriodicRandomization) + return false; + + uint64_t botId = bot->GetGUID().GetRawValue(); + uint32_t botGuildId = bot->GetGuildId(); + + if (sPlayerGuildRegistry.Contains(botGuildId)) + { + LOG_DEBUG("playerbots", "Bot #{} {}:{} <{}>: Randomization skipped because it is part of a guild with at least one non random bot.", bot->GetGUID().GetRawValue(), IsAlliance(bot->getRace()) ? "A" : "H", + bot->GetLevel(), bot->GetName().c_str()); + + return false; + } + + uint32_t timeUntilRandomize = GetEventValue(botId, "randomize"); + + if (timeUntilRandomize > 0) + return false; + + Randomize(bot); + + uint32 time = urand(sPlayerbotAIConfig.minRandomBotRandomizeTime, sPlayerbotAIConfig.maxRandomBotRandomizeTime); + + ScheduleRandomize(botId, time); + + return true; +} + +bool RandomPlayerbotMgr::ProcessBotTeleportation(Player* bot) +{ + if (sPlayerbotAIConfig.disableRandomBotPeriodicTeleportation) + return false; + + uint64_t botId = bot->GetGUID().GetRawValue(); + uint32_t timeUntilTeleport = GetEventValue(botId, "teleport"); + if (timeUntilTeleport > 0) + return false; + + LOG_DEBUG("playerbots", "Bot #{} <{}>: teleport for level and refresh", botId, bot->GetName()); + + Refresh(bot); + RandomTeleportForLevel(bot); + + uint32_t time = urand(sPlayerbotAIConfig.minRandomBotTeleportInterval, + sPlayerbotAIConfig.maxRandomBotTeleportInterval); + + ScheduleTeleport(botId, time); + + return true; +} + +bool RandomPlayerbotMgr::ProcessBot(Player* bot) +{ PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); + if (!botAI) return false; @@ -1538,10 +1561,10 @@ bool RandomPlayerbotMgr::ProcessBot(Player* bot) if (!GetEventValue(botId, "dead")) { uint32 randomTime = - urand(sPlayerbotAIConfig->minRandomBotReviveTime, sPlayerbotAIConfig->maxRandomBotReviveTime); + urand(sPlayerbotAIConfig.minRandomBotReviveTime, sPlayerbotAIConfig.maxRandomBotReviveTime); LOG_DEBUG("playerbots", "Mark bot {} as dead, will be revived in {}s.", bot->GetName().c_str(), randomTime); - SetEventValue(botId, "dead", 1, sPlayerbotAIConfig->maxRandomBotInWorldTime); + SetEventValue(botId, "dead", 1, sPlayerbotAIConfig.maxRandomBotInWorldTime); SetEventValue(botId, "revive", 1, randomTime); return false; } @@ -1557,6 +1580,7 @@ bool RandomPlayerbotMgr::ProcessBot(Player* bot) // leave group if leader is rndbot Group* group = bot->GetGroup(); + if (group && !group->isLFGGroup() && IsRandomBot(group->GetLeader())) { botAI->LeaveOrDisbandGroup(); @@ -1565,6 +1589,7 @@ bool RandomPlayerbotMgr::ProcessBot(Player* bot) // only randomize and teleport idle bots bool idleBot = false; + if (TravelTarget* target = botAI->GetAiObjectContext()->GetValue("travel target")->Get()) { if (target->getTravelState() == TravelState::TRAVEL_STATE_IDLE) @@ -1579,59 +1604,15 @@ bool RandomPlayerbotMgr::ProcessBot(Player* bot) if (idleBot) { - // randomize - uint32 randomize = GetEventValue(botId, "randomize"); - if (!randomize) - { - // bool randomiser = true; - // if (player->GetGuildId()) - // { - // if (Guild* guild = sGuildMgr->GetGuildById(player->GetGuildId())) - // { - // if (guild->GetLeaderGUID() == player->GetGUID()) - // { - // for (std::vector::iterator i = players.begin(); i != players.end(); ++i) - // sGuildTaskMgr->Update(*i, player); - // } - - // uint32 accountId = sCharacterCache->GetCharacterAccountIdByGuid(guild->GetLeaderGUID()); - // if (!sPlayerbotAIConfig->IsInRandomAccountList(accountId)) - // { - // uint8 rank = player->GetRank(); - // randomiser = rank < 4 ? false : true; - // } - // } - // } - // if (randomiser) - // { - Randomize(bot); - LOG_DEBUG("playerbots", "Bot #{} {}:{} <{}>: randomized", botId, - bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", bot->GetLevel(), bot->GetName()); - uint32 randomTime = - urand(sPlayerbotAIConfig->minRandomBotRandomizeTime, sPlayerbotAIConfig->maxRandomBotRandomizeTime); - ScheduleRandomize(botId, randomTime); - return true; - } + bool hasBeenRandomized = ProcessBotRandomization(bot); - // uint32 changeStrategy = GetEventValue(bot, "change_strategy"); - // if (!changeStrategy) - // { - // LOG_INFO("playerbots", "Changing strategy for bot #{} <{}>", bot, player->GetName().c_str()); - // ChangeStrategy(player); - // return true; - // } + if (hasBeenRandomized) + return true; - uint32 teleport = GetEventValue(botId, "teleport"); - if (!teleport) - { - LOG_DEBUG("playerbots", "Bot #{} <{}>: teleport for level and refresh", botId, bot->GetName()); - Refresh(bot); - RandomTeleportForLevel(bot); - uint32 time = urand(sPlayerbotAIConfig->minRandomBotTeleportInterval, - sPlayerbotAIConfig->maxRandomBotTeleportInterval); - ScheduleTeleport(botId, time); - return true; - } + bool hasBeenTeleported = ProcessBotTeleportation(bot); + + if (hasBeenTeleported) + return true; } return false; @@ -1641,7 +1622,6 @@ void RandomPlayerbotMgr::Revive(Player* player) { uint32 bot = player->GetGUID().GetCounter(); - // LOG_INFO("playerbots", "Bot {} revived", player->GetName().c_str()); SetEventValue(bot, "dead", 0, 0); SetEventValue(bot, "revive", 0, 0); @@ -1680,7 +1660,7 @@ void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector& return; } - // if (sPlayerbotAIConfig->randomBotRpgChance < 0) + // if (sPlayerbotAIConfig.randomBotRpgChance < 0) // return; if (locs.empty()) @@ -1694,12 +1674,12 @@ void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector& tlocs.push_back(WorldPosition(loc)); // Do not teleport to maps disabled in config tlocs.erase(std::remove_if(tlocs.begin(), tlocs.end(), - [bot](WorldPosition l) + [](WorldPosition l) { std::vector::iterator i = - find(sPlayerbotAIConfig->randomBotMaps.begin(), - sPlayerbotAIConfig->randomBotMaps.end(), l.getMapId()); - return i == sPlayerbotAIConfig->randomBotMaps.end(); + find(sPlayerbotAIConfig.randomBotMaps.begin(), + sPlayerbotAIConfig.randomBotMaps.end(), l.getMapId()); + return i == sPlayerbotAIConfig.randomBotMaps.end(); }), tlocs.end()); if (tlocs.empty()) @@ -1708,17 +1688,17 @@ void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector& return; } - PerfMonitorOperation* pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "RandomTeleportByLocations"); + PerfMonitorOperation* pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "RandomTeleportByLocations"); std::shuffle(std::begin(tlocs), std::end(tlocs), RandomEngine::Instance()); for (uint32 i = 0; i < tlocs.size(); i++) { WorldLocation loc = tlocs[i]; - float x = loc.GetPositionX(); // + (attemtps > 0 ? urand(0, sPlayerbotAIConfig->grindDistance) - - // sPlayerbotAIConfig->grindDistance / 2 : 0); - float y = loc.GetPositionY(); // + (attemtps > 0 ? urand(0, sPlayerbotAIConfig->grindDistance) - - // sPlayerbotAIConfig->grindDistance / 2 : 0); + float x = loc.GetPositionX(); // + (attemtps > 0 ? urand(0, sPlayerbotAIConfig.grindDistance) - + // sPlayerbotAIConfig.grindDistance / 2 : 0); + float y = loc.GetPositionY(); // + (attemtps > 0 ? urand(0, sPlayerbotAIConfig.grindDistance) - + // sPlayerbotAIConfig.grindDistance / 2 : 0); float z = loc.GetPositionZ(); Map* map = sMapMgr->FindMap(loc.GetMapId(), 0); @@ -1815,7 +1795,7 @@ void RandomPlayerbotMgr::PrepareZone2LevelBracket() zone2LevelBracket[3525] = {10, 21}; // Bloodmyst Isle // Classic WoW - High - level zones - zone2LevelBracket[10] = {19, 33}; // Deadwind Pass + zone2LevelBracket[10] = {19, 33}; // Duskwood zone2LevelBracket[11] = {21, 30}; // Wetlands zone2LevelBracket[44] = {16, 28}; // Redridge Mountains zone2LevelBracket[267] = {20, 34}; // Hillsbrad Foothills @@ -1869,7 +1849,7 @@ void RandomPlayerbotMgr::PrepareZone2LevelBracket() zone2LevelBracket[4197] = {79, 80}; // Wintergrasp // Override with values from config - for (auto const& [zoneId, bracketPair] : sPlayerbotAIConfig->zoneBrackets) + for (auto const& [zoneId, bracketPair] : sPlayerbotAIConfig.zoneBrackets) { zone2LevelBracket[zoneId] = {bracketPair.first, bracketPair.second}; } @@ -1877,7 +1857,7 @@ void RandomPlayerbotMgr::PrepareZone2LevelBracket() void RandomPlayerbotMgr::PrepareTeleportCache() { - uint32 maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); + int64_t maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); LOG_INFO("playerbots", "Preparing random teleport caches for {} levels...", maxLevel); @@ -1920,7 +1900,7 @@ void RandomPlayerbotMgr::PrepareTeleportCache() "INNER JOIN creature_template t on c.id1 = t.entry " "ORDER BY " "t.minlevel;", - sPlayerbotAIConfig->randomBotMapsAsString.c_str()); + sPlayerbotAIConfig.randomBotMapsAsString.c_str()); uint32 collected_locs = 0; if (results) { @@ -1931,13 +1911,13 @@ void RandomPlayerbotMgr::PrepareTeleportCache() float x = fields[1].Get(); float y = fields[2].Get(); float z = fields[3].Get(); - uint32 min_level = fields[4].Get(); - uint32 max_level = fields[5].Get(); - uint32 level = (min_level + max_level + 1) / 2; + int64_t min_level = fields[4].Get(); + int64_t max_level = fields[5].Get(); + int64_t level = (min_level + max_level + 1) / 2; WorldLocation loc(mapId, x, y, z, 0); collected_locs++; - for (int32 l = (int32)level - (int32)sPlayerbotAIConfig->randomBotTeleLowerLevel; - l <= (int32)level + (int32)sPlayerbotAIConfig->randomBotTeleHigherLevel; l++) + for (int32 l = (int32)level - (int32)sPlayerbotAIConfig.randomBotTeleLowerLevel; + l <= (int32)level + (int32)sPlayerbotAIConfig.randomBotTeleHigherLevel; l++) { if (l < 1 || l > maxLevel) { @@ -1949,7 +1929,7 @@ void RandomPlayerbotMgr::PrepareTeleportCache() } LOG_INFO("playerbots", ">> {} locations for level collected.", collected_locs); - if (sPlayerbotAIConfig->enableNewRpgStrategy) + if (sPlayerbotAIConfig.enableNewRpgStrategy) { PrepareZone2LevelBracket(); LOG_INFO("playerbots", "Preparing innkeepers / flightmasters locations for level..."); @@ -1972,7 +1952,7 @@ void RandomPlayerbotMgr::PrepareTeleportCache() "AND map IN ({}) " "ORDER BY " "t.minlevel;", - sPlayerbotAIConfig->randomBotMapsAsString.c_str()); + sPlayerbotAIConfig.randomBotMapsAsString.c_str()); collected_locs = 0; if (results) { @@ -2005,17 +1985,17 @@ void RandomPlayerbotMgr::PrepareTeleportCache() { WorldPosition pos(mapId, x, y, z, orient); if (forHorde) - sFlightMasterCache->AddHordeFlightMaster(guid, pos); + FlightMasterCache::Instance().AddHordeFlightMaster(guid, pos); if (forAlliance) - sFlightMasterCache->AddAllianceFlightMaster(guid, pos); + FlightMasterCache::Instance().AddAllianceFlightMaster(guid, pos); } const AreaTableEntry* area = sAreaTableStore.LookupEntry(map->GetAreaId(PHASEMASK_NORMAL, x, y, z)); uint32 zoneId = area->zone ? area->zone : area->ID; if (zone2LevelBracket.find(zoneId) == zone2LevelBracket.end()) continue; LevelBracket bracket = zone2LevelBracket[zoneId]; - for (int i = bracket.low; i <= bracket.high; i++) + for (uint32_t i = bracket.low; i <= bracket.high; i++) { if (forHorde) { @@ -2077,7 +2057,7 @@ void RandomPlayerbotMgr::PrepareTeleportCache() "AND map IN ({}) " "ORDER BY " "t.minlevel;", - sPlayerbotAIConfig->randomBotMapsAsString.c_str()); + sPlayerbotAIConfig.randomBotMapsAsString.c_str()); collected_locs = 0; if (results) { @@ -2157,16 +2137,16 @@ void RandomPlayerbotMgr::PrepareAddclassCache() void RandomPlayerbotMgr::Init() { - if (sPlayerbotAIConfig->addClassCommand) - sRandomPlayerbotMgr->PrepareAddclassCache(); + if (sPlayerbotAIConfig.addClassCommand) + sRandomPlayerbotMgr.PrepareAddclassCache(); - if (sPlayerbotAIConfig->enabled) + if (sPlayerbotAIConfig.enabled) { - sRandomPlayerbotMgr->PrepareTeleportCache(); + sRandomPlayerbotMgr.PrepareTeleportCache(); } - if (sPlayerbotAIConfig->randomBotJoinBG) - sRandomPlayerbotMgr->LoadBattleMastersCache(); + if (sPlayerbotAIConfig.randomBotJoinBG) + sRandomPlayerbotMgr.LoadBattleMastersCache(); PlayerbotsDatabase.Execute("DELETE FROM playerbots_random_bots WHERE event = 'add'"); } @@ -2179,17 +2159,17 @@ void RandomPlayerbotMgr::RandomTeleportForLevel(Player* bot) uint32 level = bot->GetLevel(); uint8 race = bot->getRace(); std::vector* locs = nullptr; - if (sPlayerbotAIConfig->enableNewRpgStrategy) + if (sPlayerbotAIConfig.enableNewRpgStrategy) locs = IsAlliance(race) ? &allianceStarterPerLevelCache[level] : &hordeStarterPerLevelCache[level]; else locs = &locsPerLevelCache[level]; - if (level >= 10 && urand(0, 100) < sPlayerbotAIConfig->probTeleToBankers * 100) + if (level >= 10 && urand(0, 100) < sPlayerbotAIConfig.probTeleToBankers * 100) { std::vector fallbackLocs; for (auto& bLoc : bankerLocsPerLevelCache[level]) fallbackLocs.push_back(bLoc.loc); - if (!sPlayerbotAIConfig->enableWeightTeleToCityBankers) + if (!sPlayerbotAIConfig.enableWeightTeleToCityBankers) { RandomTeleport(bot, fallbackLocs, true); return; @@ -2227,16 +2207,16 @@ void RandomPlayerbotMgr::RandomTeleportForLevel(Player* bot) int weight = 0; switch (city) { - case CityId::STORMWIND: weight = sPlayerbotAIConfig->weightTeleToStormwind; break; - case CityId::IRONFORGE: weight = sPlayerbotAIConfig->weightTeleToIronforge; break; - case CityId::DARNASSUS: weight = sPlayerbotAIConfig->weightTeleToDarnassus; break; - case CityId::EXODAR: weight = sPlayerbotAIConfig->weightTeleToExodar; break; - case CityId::ORGRIMMAR: weight = sPlayerbotAIConfig->weightTeleToOrgrimmar; break; - case CityId::UNDERCITY: weight = sPlayerbotAIConfig->weightTeleToUndercity; break; - case CityId::THUNDER_BLUFF: weight = sPlayerbotAIConfig->weightTeleToThunderBluff; break; - case CityId::SILVERMOON_CITY: weight = sPlayerbotAIConfig->weightTeleToSilvermoonCity; break; - case CityId::SHATTRATH_CITY: weight = sPlayerbotAIConfig->weightTeleToShattrathCity; break; - case CityId::DALARAN: weight = sPlayerbotAIConfig->weightTeleToDalaran; break; + case CityId::STORMWIND: weight = sPlayerbotAIConfig.weightTeleToStormwind; break; + case CityId::IRONFORGE: weight = sPlayerbotAIConfig.weightTeleToIronforge; break; + case CityId::DARNASSUS: weight = sPlayerbotAIConfig.weightTeleToDarnassus; break; + case CityId::EXODAR: weight = sPlayerbotAIConfig.weightTeleToExodar; break; + case CityId::ORGRIMMAR: weight = sPlayerbotAIConfig.weightTeleToOrgrimmar; break; + case CityId::UNDERCITY: weight = sPlayerbotAIConfig.weightTeleToUndercity; break; + case CityId::THUNDER_BLUFF: weight = sPlayerbotAIConfig.weightTeleToThunderBluff; break; + case CityId::SILVERMOON_CITY: weight = sPlayerbotAIConfig.weightTeleToSilvermoonCity; break; + case CityId::SHATTRATH_CITY: weight = sPlayerbotAIConfig.weightTeleToShattrathCity; break; + case CityId::DALARAN: weight = sPlayerbotAIConfig.weightTeleToDalaran; break; default: weight = 0; break; } if (weight <= 0) continue; @@ -2284,7 +2264,7 @@ void RandomPlayerbotMgr::RandomTeleportGrindForLevel(Player* bot) uint32 level = bot->GetLevel(); uint8 race = bot->getRace(); std::vector* locs = nullptr; - if (sPlayerbotAIConfig->enableNewRpgStrategy) + if (sPlayerbotAIConfig.enableNewRpgStrategy) locs = IsAlliance(race) ? &allianceStarterPerLevelCache[level] : &hordeStarterPerLevelCache[level]; else locs = &locsPerLevelCache[level]; @@ -2299,11 +2279,11 @@ void RandomPlayerbotMgr::RandomTeleport(Player* bot) if (bot->InBattleground()) return; - PerfMonitorOperation* pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "RandomTeleport"); + PerfMonitorOperation* pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "RandomTeleport"); std::vector locs; std::list targets; - float range = sPlayerbotAIConfig->randomBotTeleportDistance; + float range = sPlayerbotAIConfig.randomBotTeleportDistance; Acore::AnyUnitInObjectRangeCheck u_check(bot, range); Acore::UnitListSearcher searcher(bot, targets, u_check); Cell::VisitObjects(bot, searcher, range); @@ -2313,7 +2293,7 @@ void RandomPlayerbotMgr::RandomTeleport(Player* bot) for (Unit* unit : targets) { bot->UpdatePosition(*unit); - FleeManager manager(bot, sPlayerbotAIConfig->sightDistance, 0, true); + FleeManager manager(bot, sPlayerbotAIConfig.sightDistance, 0, true); float rx, ry, rz; if (manager.CalculateDestination(&rx, &ry, &rz)) { @@ -2335,33 +2315,39 @@ void RandomPlayerbotMgr::RandomTeleport(Player* bot) void RandomPlayerbotMgr::Randomize(Player* bot) { + uint8 level = bot->GetLevel(); + + LOG_ERROR("playerbots", "randomizing bot {}", bot->GetName()); + if (bot->InBattleground()) return; if (bot->GetLevel() < 3 || (bot->GetLevel() < 56 && bot->getClass() == CLASS_DEATH_KNIGHT)) { RandomizeFirst(bot); + + return; } - else if (bot->GetLevel() < sPlayerbotAIConfig->randomBotMaxLevel || !sPlayerbotAIConfig->downgradeMaxLevelBot) + + if (bot->GetLevel() < sPlayerbotAIConfig.randomBotMaxLevel || !sPlayerbotAIConfig.downgradeMaxLevelBot) { - uint8 level = bot->GetLevel(); PlayerbotFactory factory(bot, level); + factory.Randomize(true); - // IncreaseLevel(bot); - } - else - { - RandomizeFirst(bot); + + return; } + + RandomizeFirst(bot); } void RandomPlayerbotMgr::IncreaseLevel(Player* bot) { - uint32 maxLevel = sPlayerbotAIConfig->randomBotMaxLevel; + uint32 maxLevel = sPlayerbotAIConfig.randomBotMaxLevel; if (maxLevel > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); - PerfMonitorOperation* pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "IncreaseLevel"); + PerfMonitorOperation* pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "IncreaseLevel"); uint32 lastLevel = GetValue(bot, "level"); uint8 level = bot->GetLevel() + 1; if (level > maxLevel) @@ -2384,27 +2370,27 @@ void RandomPlayerbotMgr::RandomizeFirst(Player* bot) if (!botAI) return; - uint32 maxLevel = sPlayerbotAIConfig->randomBotMaxLevel; + uint32 maxLevel = sPlayerbotAIConfig.randomBotMaxLevel; if (maxLevel > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); // if lvl sync is enabled, max level is limited by online players lvl - if (sPlayerbotAIConfig->syncLevelWithPlayers) - maxLevel = std::max(sPlayerbotAIConfig->randomBotMinLevel, + if (sPlayerbotAIConfig.syncLevelWithPlayers) + maxLevel = std::max(sPlayerbotAIConfig.randomBotMinLevel, std::min(playersLevel, sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))); - uint32 minLevel = sPlayerbotAIConfig->randomBotMinLevel; + uint32 minLevel = sPlayerbotAIConfig.randomBotMinLevel; if (bot->getClass() == CLASS_DEATH_KNIGHT) { maxLevel = std::max(maxLevel, sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_LEVEL)); minLevel = std::max(minLevel, sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_LEVEL)); } - PerfMonitorOperation* pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "RandomizeFirst"); + PerfMonitorOperation* pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "RandomizeFirst"); uint32 level; - if (sPlayerbotAIConfig->downgradeMaxLevelBot && bot->GetLevel() >= sPlayerbotAIConfig->randomBotMaxLevel) + if (sPlayerbotAIConfig.downgradeMaxLevelBot && bot->GetLevel() >= sPlayerbotAIConfig.randomBotMaxLevel) { if (bot->getClass() == CLASS_DEATH_KNIGHT) { @@ -2412,18 +2398,18 @@ void RandomPlayerbotMgr::RandomizeFirst(Player* bot) } else { - level = sPlayerbotAIConfig->randomBotMinLevel; + level = sPlayerbotAIConfig.randomBotMinLevel; } } else { uint32 roll = urand(1, 100); - if (roll <= 100 * sPlayerbotAIConfig->randomBotMaxLevelChance) + if (roll <= 100 * sPlayerbotAIConfig.randomBotMaxLevelChance) { level = maxLevel; } else if (roll <= - (100 * (sPlayerbotAIConfig->randomBotMaxLevelChance + sPlayerbotAIConfig->randomBotMinLevelChance))) + (100 * (sPlayerbotAIConfig.randomBotMaxLevelChance + sPlayerbotAIConfig.randomBotMinLevelChance))) { level = minLevel; } @@ -2433,11 +2419,11 @@ void RandomPlayerbotMgr::RandomizeFirst(Player* bot) } } - if (sPlayerbotAIConfig->disableRandomLevels) + if (sPlayerbotAIConfig.disableRandomLevels) { - level = bot->getClass() == CLASS_DEATH_KNIGHT ? std::max(sPlayerbotAIConfig->randombotStartingLevel, + level = bot->getClass() == CLASS_DEATH_KNIGHT ? std::max(sPlayerbotAIConfig.randombotStartingLevel, sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_LEVEL)) - : sPlayerbotAIConfig->randombotStartingLevel; + : sPlayerbotAIConfig.randombotStartingLevel; } SetValue(bot, "level", level); @@ -2445,9 +2431,9 @@ void RandomPlayerbotMgr::RandomizeFirst(Player* bot) factory.Randomize(false); uint32 randomTime = - urand(sPlayerbotAIConfig->minRandomBotRandomizeTime, sPlayerbotAIConfig->maxRandomBotRandomizeTime); + urand(sPlayerbotAIConfig.minRandomBotRandomizeTime, sPlayerbotAIConfig.maxRandomBotRandomizeTime); uint32 inworldTime = - urand(sPlayerbotAIConfig->minRandomBotInWorldTime, sPlayerbotAIConfig->maxRandomBotInWorldTime); + urand(sPlayerbotAIConfig.minRandomBotInWorldTime, sPlayerbotAIConfig.maxRandomBotInWorldTime); PlayerbotsDatabasePreparedStatement* stmt = PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_UPD_RANDOM_BOTS); stmt->SetData(0, randomTime); @@ -2479,16 +2465,16 @@ void RandomPlayerbotMgr::RandomizeMin(Player* bot) if (!botAI) return; - PerfMonitorOperation* pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "RandomizeMin"); - uint32 level = sPlayerbotAIConfig->randomBotMinLevel; + PerfMonitorOperation* pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "RandomizeMin"); + uint32 level = sPlayerbotAIConfig.randomBotMinLevel; SetValue(bot, "level", level); PlayerbotFactory factory(bot, level); factory.Randomize(false); uint32 randomTime = - urand(sPlayerbotAIConfig->minRandomBotRandomizeTime, sPlayerbotAIConfig->maxRandomBotRandomizeTime); + urand(sPlayerbotAIConfig.minRandomBotRandomizeTime, sPlayerbotAIConfig.maxRandomBotRandomizeTime); uint32 inworldTime = - urand(sPlayerbotAIConfig->minRandomBotInWorldTime, sPlayerbotAIConfig->maxRandomBotInWorldTime); + urand(sPlayerbotAIConfig.minRandomBotInWorldTime, sPlayerbotAIConfig.maxRandomBotInWorldTime); PlayerbotsDatabasePreparedStatement* stmt = PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_UPD_RANDOM_BOTS); stmt->SetData(0, randomTime); @@ -2518,7 +2504,7 @@ void RandomPlayerbotMgr::Clear(Player* bot) factory.ClearEverything(); } -uint32 RandomPlayerbotMgr::GetZoneLevel(uint16 mapId, float teleX, float teleY, float teleZ) +uint32 RandomPlayerbotMgr::GetZoneLevel(uint16 mapId, float teleX, float teleY, float) { uint32 maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); @@ -2527,8 +2513,8 @@ uint32 RandomPlayerbotMgr::GetZoneLevel(uint16 mapId, float teleX, float teleY, "SELECT AVG(t.minlevel) minlevel, AVG(t.maxlevel) maxlevel FROM creature c " "INNER JOIN creature_template t ON c.id1 = t.entry WHERE map = {} AND minlevel > 1 AND ABS(position_x - {}) < " "{} AND ABS(position_y - {}) < {}", - mapId, teleX, sPlayerbotAIConfig->randomBotTeleportDistance / 2, teleY, - sPlayerbotAIConfig->randomBotTeleportDistance / 2); + mapId, teleX, sPlayerbotAIConfig.randomBotTeleportDistance / 2, teleY, + sPlayerbotAIConfig.randomBotTeleportDistance / 2); if (results) { @@ -2560,7 +2546,7 @@ void RandomPlayerbotMgr::Refresh(Player* bot) botAI->ResetStrategies(false); } - // if (sPlayerbotAIConfig->disableRandomLevels) + // if (sPlayerbotAIConfig.disableRandomLevels) // return; if (bot->InBattleground()) @@ -2568,7 +2554,7 @@ void RandomPlayerbotMgr::Refresh(Player* bot) LOG_DEBUG("playerbots", "Refreshing bot {} <{}>", bot->GetGUID().ToString().c_str(), bot->GetName().c_str()); - PerfMonitorOperation* pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "Refresh"); + PerfMonitorOperation* pmo = sPerfMonitor.start(PERF_MON_RNDBOT, "Refresh"); botAI->Reset(); @@ -2612,7 +2598,7 @@ bool RandomPlayerbotMgr::IsRandomBot(Player* bot) bool RandomPlayerbotMgr::IsRandomBot(ObjectGuid::LowType bot) { ObjectGuid guid = ObjectGuid::Create(bot); - if (!sPlayerbotAIConfig->IsInRandomAccountList(sCharacterCache->GetCharacterAccountIdByGuid(guid))) + if (!sPlayerbotAIConfig.IsInRandomAccountList(sCharacterCache->GetCharacterAccountIdByGuid(guid))) return false; if (std::find(currentBots.begin(), currentBots.end(), bot) != currentBots.end()) @@ -2711,7 +2697,7 @@ std::vector RandomPlayerbotMgr::GetBgBots(uint32 bracket) } while (result->NextRow()); } - return std::move(BgBots); + return BgBots; } CachedEvent* RandomPlayerbotMgr::FindEvent(uint32 bot, std::string const& event) @@ -2841,7 +2827,7 @@ std::string RandomPlayerbotMgr::GetData(uint32 bot, std::string const& type) { r void RandomPlayerbotMgr::SetValue(uint32 bot, std::string const& type, uint32 value, std::string const& data) { - SetEventValue(bot, type, value, sPlayerbotAIConfig->maxRandomBotInWorldTime, data); + SetEventValue(bot, type, value, sPlayerbotAIConfig.maxRandomBotInWorldTime, data); } void RandomPlayerbotMgr::SetValue(Player* bot, std::string const& type, uint32 value, std::string const& data) @@ -2849,9 +2835,9 @@ void RandomPlayerbotMgr::SetValue(Player* bot, std::string const& type, uint32 v SetValue(bot->GetGUID().GetCounter(), type, value, data); } -bool RandomPlayerbotMgr::HandlePlayerbotConsoleCommand(ChatHandler* handler, char const* args) +bool RandomPlayerbotMgr::HandlePlayerbotConsoleCommand(ChatHandler*, char const* args) { - if (!sPlayerbotAIConfig->enabled) + if (!sPlayerbotAIConfig.enabled) { LOG_ERROR("playerbots", "Playerbots system is currently disabled!"); return false; @@ -2868,27 +2854,27 @@ bool RandomPlayerbotMgr::HandlePlayerbotConsoleCommand(ChatHandler* handler, cha if (cmd == "reset") { PlayerbotsDatabase.Execute(PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_DEL_RANDOM_BOTS)); - sRandomPlayerbotMgr->eventCache.clear(); + sRandomPlayerbotMgr.eventCache.clear(); LOG_INFO("playerbots", "Random bots were reset for all players. Please restart the Server."); return true; } if (cmd == "stats") { - sRandomPlayerbotMgr->PrintStats(); + sRandomPlayerbotMgr.PrintStats(); // activatePrintStatsThread(); return true; } if (cmd == "reload") { - sPlayerbotAIConfig->Initialize(); + sPlayerbotAIConfig.Initialize(); return true; } if (cmd == "update") { - sRandomPlayerbotMgr->UpdateAIInternal(0); + sRandomPlayerbotMgr.UpdateAIInternal(0); return true; } @@ -2913,8 +2899,8 @@ bool RandomPlayerbotMgr::HandlePlayerbotConsoleCommand(ChatHandler* handler, cha std::string const name = cmd.size() > prefix.size() + 1 ? cmd.substr(1 + prefix.size()) : "%"; std::vector botIds; - for (std::vector::iterator i = sPlayerbotAIConfig->randomBotAccounts.begin(); - i != sPlayerbotAIConfig->randomBotAccounts.end(); ++i) + for (std::vector::iterator i = sPlayerbotAIConfig.randomBotAccounts.begin(); + i != sPlayerbotAIConfig.randomBotAccounts.end(); ++i) { uint32 account = *i; if (QueryResult results = CharacterDatabase.Query( @@ -2926,7 +2912,7 @@ bool RandomPlayerbotMgr::HandlePlayerbotConsoleCommand(ChatHandler* handler, cha uint32 botId = fields[0].Get(); ObjectGuid guid = ObjectGuid::Create(botId); - if (!sRandomPlayerbotMgr->IsRandomBot(guid.GetCounter())) + if (!sRandomPlayerbotMgr.IsRandomBot(guid.GetCounter())) { continue; } @@ -2957,13 +2943,13 @@ bool RandomPlayerbotMgr::HandlePlayerbotConsoleCommand(ChatHandler* handler, cha bot->GetName().c_str()); ConsoleCommandHandler handler = j->second; - (sRandomPlayerbotMgr->*handler)(bot); + (sRandomPlayerbotMgr.*handler)(bot); } return true; } - // std::vector messages = sRandomPlayerbotMgr->HandlePlayerbotCommand(args); + // std::vector messages = sRandomPlayerbotMgr.HandlePlayerbotCommand(args); // for (std::vector::iterator i = messages.begin(); i != messages.end(); ++i) // { // LOG_INFO("playerbots", "{}", i->c_str()); @@ -3021,15 +3007,15 @@ void RandomPlayerbotMgr::OnBotLoginInternal(Player* const bot) if (_isBotLogging) { LOG_INFO("playerbots", "{}/{} Bot {} logged in", playerBots.size(), - sRandomPlayerbotMgr->GetMaxAllowedBotCount(), bot->GetName().c_str()); + sRandomPlayerbotMgr.GetMaxAllowedBotCount(), bot->GetName().c_str()); - if (playerBots.size() == sRandomPlayerbotMgr->GetMaxAllowedBotCount()) + if (playerBots.size() == sRandomPlayerbotMgr.GetMaxAllowedBotCount()) { _isBotLogging = false; } } - if (sPlayerbotAIConfig->randomBotFixedLevel) + if (sPlayerbotAIConfig.randomBotFixedLevel) { bot->SetPlayerFlag(PLAYER_FLAGS_NO_XP_GAIN); } @@ -3081,18 +3067,18 @@ void RandomPlayerbotMgr::OnPlayerLogin(Player* player) { WorldPosition botPos(player); - // botPos.GetReachableRandomPointOnGround(player, sPlayerbotAIConfig->reactDistance * 2, true); + // botPos.GetReachableRandomPointOnGround(player, sPlayerbotAIConfig.reactDistance * 2, true); // player->TeleportTo(botPos); // player->Relocate(botPos.coord_x, botPos.coord_y, botPos.coord_z, botPos.orientation); if (!player->GetFactionTemplateEntry()) { - botPos.GetReachableRandomPointOnGround(player, sPlayerbotAIConfig->reactDistance * 2, true); + botPos.GetReachableRandomPointOnGround(player, sPlayerbotAIConfig.reactDistance * 2, true); } else { - std::vector dests = sTravelMgr->getRpgTravelDestinations(player, true, true, 200000.0f); + std::vector dests = TravelMgr::instance().getRpgTravelDestinations(player, true, true, 200000.0f); do { @@ -3178,10 +3164,6 @@ void RandomPlayerbotMgr::PrintStats() uint32 heal = 0; uint32 tank = 0; uint32 active = 0; - uint32 update = 0; - uint32 randomize = 0; - uint32 teleport = 0; - uint32 changeStrategy = 0; uint32 dead = 0; uint32 combat = 0; // uint32 revive = 0; //not used, line marked for removal. @@ -3222,19 +3204,6 @@ void RandomPlayerbotMgr::PrintStats() if (botAI->AllowActivity()) ++active; - if (botAI->GetAiObjectContext()->GetValue("random bot update")->Get()) - ++update; - - uint32 botId = bot->GetGUID().GetCounter(); - if (!GetEventValue(botId, "randomize")) - ++randomize; - - if (!GetEventValue(botId, "teleport")) - ++teleport; - - if (!GetEventValue(botId, "change_strategy")) - ++changeStrategy; - if (bot->isDead()) { ++dead; @@ -3281,7 +3250,7 @@ void RandomPlayerbotMgr::PrintStats() zoneCount[bot->GetZoneId()]++; - if (sPlayerbotAIConfig->enableNewRpgStrategy) + if (sPlayerbotAIConfig.enableNewRpgStrategy) { rpgStatusCount[botAI->rpgInfo.status]++; rpgStasticTotal += botAI->rpgStatistic; @@ -3355,7 +3324,7 @@ void RandomPlayerbotMgr::PrintStats() LOG_INFO("playerbots", " In Rest: {}", rest); LOG_INFO("playerbots", " Dead: {}", dead); - if (sPlayerbotAIConfig->enableNewRpgStrategy) + if (sPlayerbotAIConfig.enableNewRpgStrategy) { LOG_INFO("playerbots", "Bots rpg status:"); LOG_INFO("playerbots", @@ -3381,8 +3350,8 @@ double RandomPlayerbotMgr::GetBuyMultiplier(Player* bot) if (!value) { value = urand(50, 120); - uint32 validIn = urand(sPlayerbotAIConfig->minRandomBotsPriceChangeInterval, - sPlayerbotAIConfig->maxRandomBotsPriceChangeInterval); + uint32 validIn = urand(sPlayerbotAIConfig.minRandomBotsPriceChangeInterval, + sPlayerbotAIConfig.maxRandomBotsPriceChangeInterval); SetEventValue(id, "buymultiplier", value, validIn); } @@ -3396,8 +3365,8 @@ double RandomPlayerbotMgr::GetSellMultiplier(Player* bot) if (!value) { value = urand(80, 250); - uint32 validIn = urand(sPlayerbotAIConfig->minRandomBotsPriceChangeInterval, - sPlayerbotAIConfig->maxRandomBotsPriceChangeInterval); + uint32 validIn = urand(sPlayerbotAIConfig.minRandomBotsPriceChangeInterval, + sPlayerbotAIConfig.maxRandomBotsPriceChangeInterval); SetEventValue(id, "sellmultiplier", value, validIn); } @@ -3426,7 +3395,7 @@ void RandomPlayerbotMgr::SetTradeDiscount(Player* bot, Player* master, uint32 va std::ostringstream name; name << "trade_discount_" << masterId; - SetEventValue(botId, name.str(), value, sPlayerbotAIConfig->maxRandomBotInWorldTime); + SetEventValue(botId, name.str(), value, sPlayerbotAIConfig.maxRandomBotInWorldTime); } uint32 RandomPlayerbotMgr::GetTradeDiscount(Player* bot, Player* master) @@ -3469,7 +3438,7 @@ void RandomPlayerbotMgr::ChangeStrategy(Player* player) { uint32 bot = player->GetGUID().GetCounter(); - if (frand(0.f, 100.f) > sPlayerbotAIConfig->randomBotRpgChance) + if (frand(0.f, 100.f) > sPlayerbotAIConfig.randomBotRpgChance) { LOG_INFO("playerbots", "Bot #{} <{}>: sent to grind spot", bot, player->GetName().c_str()); ScheduleTeleport(bot, 30); @@ -3479,7 +3448,7 @@ void RandomPlayerbotMgr::ChangeStrategy(Player* player) LOG_INFO("playerbots", "Changing strategy for bot #{} <{}> to RPG", bot, player->GetName().c_str()); LOG_INFO("playerbots", "Bot #{} <{}>: sent to inn", bot, player->GetName().c_str()); RandomTeleportForLevel(player); - SetEventValue(bot, "teleport", 1, sPlayerbotAIConfig->maxRandomBotInWorldTime); + SetEventValue(bot, "teleport", 1, sPlayerbotAIConfig.maxRandomBotInWorldTime); } ScheduleChangeStrategy(bot); @@ -3489,7 +3458,7 @@ void RandomPlayerbotMgr::ChangeStrategyOnce(Player* player) { uint32 bot = player->GetGUID().GetCounter(); - if (frand(0.f, 100.f) > sPlayerbotAIConfig->randomBotRpgChance) // select grind / pvp + if (frand(0.f, 100.f) > sPlayerbotAIConfig.randomBotRpgChance) // select grind / pvp { LOG_INFO("playerbots", "Bot #{} <{}>: sent to grind spot", bot, player->GetName().c_str()); RandomTeleportForLevel(player); @@ -3565,7 +3534,7 @@ ObjectGuid RandomPlayerbotMgr::GetBattleMasterGUID(Player* bot, BattlegroundType for (auto i = begin(Bms); i != end(Bms); ++i) { - CreatureData const* data = sRandomPlayerbotMgr->GetCreatureDataByEntry(*i); + CreatureData const* data = sRandomPlayerbotMgr.GetCreatureDataByEntry(*i); if (!data) continue; @@ -3596,7 +3565,7 @@ ObjectGuid RandomPlayerbotMgr::GetBattleMasterGUID(Player* bot, BattlegroundType if (Bm->getDeathState() == DeathState::Dead) continue; - float dist2 = sServerFacade->GetDistance2d(bot, data->posX, data->posY); + float dist2 = ServerFacade::instance().GetDistance2d(bot, data->posX, data->posY); if (dist2 < dist1) { dist1 = dist2; diff --git a/src/Bot/RandomPlayerbotMgr.h b/src/Bot/RandomPlayerbotMgr.h index 26d09d454e..74179e681d 100644 --- a/src/Bot/RandomPlayerbotMgr.h +++ b/src/Bot/RandomPlayerbotMgr.h @@ -10,6 +10,7 @@ #include "ObjectGuid.h" #include "PlayerbotMgr.h" #include "GameTime.h" +#include "PlayerbotCommandServer.h" struct BattlegroundInfo { @@ -88,12 +89,11 @@ class botPID class RandomPlayerbotMgr : public PlayerbotHolder { public: - RandomPlayerbotMgr(); - virtual ~RandomPlayerbotMgr(); - static RandomPlayerbotMgr* instance() + static RandomPlayerbotMgr& instance() { static RandomPlayerbotMgr instance; - return &instance; + + return instance; } void LogPlayerLocation(); @@ -192,6 +192,43 @@ class RandomPlayerbotMgr : public PlayerbotHolder void OnBotLoginInternal(Player* const bot) override; private: + RandomPlayerbotMgr() : PlayerbotHolder(), processTicks(0) + { + this->playersLevel = sPlayerbotAIConfig.randombotStartingLevel; + + if (sPlayerbotAIConfig.enabled || sPlayerbotAIConfig.randomBotAutologin) + { + PlayerbotCommandServer::instance().Start(); + } + + BattlegroundData.clear(); // Clear here and here only. + + // Cleanup on server start: orphaned pet data that's often left behind by bot pets that no longer exist in the DB + CharacterDatabase.Execute("DELETE FROM pet_aura WHERE guid NOT IN (SELECT id FROM character_pet)"); + CharacterDatabase.Execute("DELETE FROM pet_spell WHERE guid NOT IN (SELECT id FROM character_pet)"); + CharacterDatabase.Execute("DELETE FROM pet_spell_cooldown WHERE guid NOT IN (SELECT id FROM character_pet)"); + + for (int bracket = BG_BRACKET_ID_FIRST; bracket < MAX_BATTLEGROUND_BRACKETS; ++bracket) + { + for (int queueType = BATTLEGROUND_QUEUE_AV; queueType < MAX_BATTLEGROUND_QUEUE_TYPES; ++queueType) + { + this->BattlegroundData[queueType][bracket] = BattlegroundInfo(); + } + } + + this->BgCheckTimer = 0; + this->LfgCheckTimer = 0; + this->PlayersCheckTimer = 0; + } + + ~RandomPlayerbotMgr() = default; + + RandomPlayerbotMgr(const RandomPlayerbotMgr&) = delete; + RandomPlayerbotMgr& operator=(const RandomPlayerbotMgr&) = delete; + + RandomPlayerbotMgr(RandomPlayerbotMgr&&) = delete; + RandomPlayerbotMgr& operator=(RandomPlayerbotMgr&&) = delete; + // pid values are set in constructor botPID pid = botPID(1, 50, -50, 0, 0, 0); float activityMod = 0.25; @@ -213,6 +250,8 @@ class RandomPlayerbotMgr : public PlayerbotHolder time_t printStatsTimer; uint32 AddRandomBots(); bool ProcessBot(uint32 bot); + bool ProcessBotRandomization(Player* bot); + bool ProcessBotTeleportation(Player* bot); void ScheduleRandomize(uint32 bot, uint32 time); void RandomTeleport(Player* bot); void RandomTeleport(Player* bot, std::vector& locs, bool hearth = false); diff --git a/src/Db/FlightMasterCache.cpp b/src/Db/FlightMasterCache.cpp index c708e09cb8..effe249936 100644 --- a/src/Db/FlightMasterCache.cpp +++ b/src/Db/FlightMasterCache.cpp @@ -13,7 +13,7 @@ void FlightMasterCache::AddAllianceFlightMaster(uint32 entry, WorldPosition pos) Creature* FlightMasterCache::GetNearestFlightMaster(Player* bot) { std::map& flightMasterCache = - (bot->GetTeamId() == ALLIANCE) ? allianceFlightMasterCache : hordeFlightMasterCache; + (bot->GetTeamId() == TEAM_ALLIANCE) ? allianceFlightMasterCache : hordeFlightMasterCache; Creature* nearestFlightMaster = nullptr; float nearestDistance = std::numeric_limits::max(); diff --git a/src/Db/FlightMasterCache.h b/src/Db/FlightMasterCache.h index 519d6fc7c8..7f8b95310d 100644 --- a/src/Db/FlightMasterCache.h +++ b/src/Db/FlightMasterCache.h @@ -8,10 +8,11 @@ class FlightMasterCache { public: - static FlightMasterCache* Instance() + static FlightMasterCache& Instance() { static FlightMasterCache instance; - return &instance; + + return instance; } Creature* GetNearestFlightMaster(Player* bot); @@ -19,9 +20,17 @@ class FlightMasterCache void AddAllianceFlightMaster(uint32 entry, WorldPosition pos); private: + FlightMasterCache() = default; + ~FlightMasterCache() = default; + + FlightMasterCache(const FlightMasterCache&) = delete; + FlightMasterCache& operator=(const FlightMasterCache&) = delete; + + FlightMasterCache(FlightMasterCache&&) = delete; + FlightMasterCache& operator=(FlightMasterCache&&) = delete; + std::map allianceFlightMasterCache; std::map hordeFlightMasterCache; }; -#define sFlightMasterCache FlightMasterCache::Instance() #endif diff --git a/src/Db/PlayerbotDungeonRepository.cpp b/src/Db/PlayerbotDungeonRepository.cpp index 3ee40e5616..5e1f370b6a 100644 --- a/src/Db/PlayerbotDungeonRepository.cpp +++ b/src/Db/PlayerbotDungeonRepository.cpp @@ -3,9 +3,15 @@ * and/or modify it under version 3 of the License, or (at your option), any later version. */ -#include "PlayerbotDungeonRepository.h" +#include "Log.h" +#include "Timer.h" +#include "DatabaseEnv.h" +#include "Field.h" +#include "World.h" +// Required import due to poor implementation by AC +#include "QueryResult.h" -#include "Playerbots.h" +#include "PlayerbotDungeonRepository.h" std::vector const PlayerbotDungeonRepository::GetDungeonSuggestions() { diff --git a/src/Db/PlayerbotDungeonRepository.h b/src/Db/PlayerbotDungeonRepository.h index 8c709152a8..160a7622c3 100644 --- a/src/Db/PlayerbotDungeonRepository.h +++ b/src/Db/PlayerbotDungeonRepository.h @@ -6,10 +6,9 @@ #ifndef _PLAYERBOT_PLAYERBOTDUNGEONREPOSITORY_H #define _PLAYERBOT_PLAYERBOTDUNGEONREPOSITORY_H -#include #include +#include -#include "Common.h" #include "DBCEnums.h" struct DungeonSuggestion @@ -22,24 +21,31 @@ struct DungeonSuggestion std::string strategy; }; +// @TODO: Completely unused at this moment. class PlayerbotDungeonRepository { public: - PlayerbotDungeonRepository(){}; - ~PlayerbotDungeonRepository(){}; - static PlayerbotDungeonRepository* instance() + static PlayerbotDungeonRepository& instance() { static PlayerbotDungeonRepository instance; - return &instance; + + return instance; } void LoadDungeonSuggestions(); std::vector const GetDungeonSuggestions(); private: + PlayerbotDungeonRepository() = default; + ~PlayerbotDungeonRepository() = default; + + PlayerbotDungeonRepository(const PlayerbotDungeonRepository&) = delete; + PlayerbotDungeonRepository& operator=(const PlayerbotDungeonRepository&) = delete; + + PlayerbotDungeonRepository(PlayerbotDungeonRepository&&) = delete; + PlayerbotDungeonRepository& operator=(PlayerbotDungeonRepository&&) = delete; + std::vector m_dungeonSuggestions; }; -#define sPlayerbotDungeonRepository PlayerbotDungeonRepository::instance() - #endif diff --git a/src/Db/PlayerbotRepository.cpp b/src/Db/PlayerbotRepository.cpp index 886cebb833..6d2d519d86 100644 --- a/src/Db/PlayerbotRepository.cpp +++ b/src/Db/PlayerbotRepository.cpp @@ -4,10 +4,7 @@ */ #include "PlayerbotRepository.h" - -#include - -#include "Playerbots.h" +#include "AiObjectContext.h" void PlayerbotRepository::Load(PlayerbotAI* botAI) { @@ -68,7 +65,7 @@ void PlayerbotRepository::Save(PlayerbotAI* botAI) SaveValue(guid, "dead", FormatStrategies("dead", botAI->GetStrategies(BOT_STATE_DEAD))); } -std::string const PlayerbotRepository::FormatStrategies(std::string const type, std::vector strategies) +std::string const PlayerbotRepository::FormatStrategies(std::string const, std::vector strategies) { std::ostringstream out; for (std::vector::iterator i = strategies.begin(); i != strategies.end(); ++i) diff --git a/src/Db/PlayerbotRepository.h b/src/Db/PlayerbotRepository.h index 90dbce54af..b7b9b4b3cc 100644 --- a/src/Db/PlayerbotRepository.h +++ b/src/Db/PlayerbotRepository.h @@ -6,21 +6,20 @@ #ifndef _PLAYERBOT_PLAYERBOTREPOSITORY_H #define _PLAYERBOT_PLAYERBOTREPOSITORY_H +#include +#include #include -#include "Common.h" - -class PlayerbotAI; +#include "PlayerbotAI.h" class PlayerbotRepository { public: - PlayerbotRepository() {} - virtual ~PlayerbotRepository() {} - static PlayerbotRepository* instance() + static PlayerbotRepository& instance() { static PlayerbotRepository instance; - return &instance; + + return instance; } void Save(PlayerbotAI* botAI); @@ -28,10 +27,17 @@ class PlayerbotRepository void Reset(PlayerbotAI* botAI); private: - void SaveValue(uint32 guid, std::string const key, std::string const value); + PlayerbotRepository() = default; + ~PlayerbotRepository() = default; + + PlayerbotRepository(const PlayerbotRepository&) = delete; + PlayerbotRepository& operator=(const PlayerbotRepository&) = delete; + + PlayerbotRepository(PlayerbotRepository&&) = delete; + PlayerbotRepository& operator=(PlayerbotRepository&&) = delete; + + void SaveValue(uint32_t guid, std::string const key, std::string const value); std::string const FormatStrategies(std::string const type, std::vector strategies); }; -#define sPlayerbotRepository PlayerbotRepository::instance() - #endif diff --git a/src/Db/PlayerbotSpellRepository.cpp b/src/Db/PlayerbotSpellRepository.cpp index 6642eeeea2..7cb6dfaffc 100644 --- a/src/Db/PlayerbotSpellRepository.cpp +++ b/src/Db/PlayerbotSpellRepository.cpp @@ -1,5 +1,13 @@ +#include "Log.h" +#include "DBCStores.h" +#include "DatabaseEnv.h" +#include "Field.h" +// Required due to poor implementation on AC side +#include "QueryResult.h" + #include "PlayerbotSpellRepository.h" + // caches the result set void PlayerbotSpellRepository::Initialize() { diff --git a/src/Db/PlayerbotSpellRepository.h b/src/Db/PlayerbotSpellRepository.h index 55046e5956..7b026dd296 100644 --- a/src/Db/PlayerbotSpellRepository.h +++ b/src/Db/PlayerbotSpellRepository.h @@ -6,29 +6,37 @@ #ifndef _PLAYERBOT_PLAYERBOTSPELLREPOSITORY_H #define _PLAYERBOT_PLAYERBOTSPELLREPOSITORY_H -#include "Playerbots.h" +#include + +#include "DBCStructure.h" class PlayerbotSpellRepository { public: - static PlayerbotSpellRepository* Instance() + static PlayerbotSpellRepository& Instance() { static PlayerbotSpellRepository instance; - return &instance; + + return instance; } - void Initialize(); // call once on startup + void Initialize(); - SkillLineAbilityEntry const* GetSkillLine(uint32 spellId) const; - bool IsItemBuyable(uint32 itemId) const; + SkillLineAbilityEntry const* GetSkillLine(uint32_t spellId) const; + bool IsItemBuyable(uint32_t itemId) const; private: PlayerbotSpellRepository() = default; + ~PlayerbotSpellRepository() = default; - std::map skillSpells; - std::set vendorItems; -}; + PlayerbotSpellRepository(const PlayerbotSpellRepository&) = delete; + PlayerbotSpellRepository& operator=(const PlayerbotSpellRepository&) = delete; -#define sPlayerbotSpellRepository PlayerbotSpellRepository::Instance() + PlayerbotSpellRepository(PlayerbotSpellRepository&&) = delete; + PlayerbotSpellRepository& operator=(PlayerbotSpellRepository&&) = delete; + + std::map skillSpells; + std::set vendorItems; +}; #endif diff --git a/src/Mgr/Guild/GuildTaskMgr.cpp b/src/Mgr/Guild/GuildTaskMgr.cpp index 8fb4711dd7..96162c044a 100644 --- a/src/Mgr/Guild/GuildTaskMgr.cpp +++ b/src/Mgr/Guild/GuildTaskMgr.cpp @@ -26,14 +26,14 @@ enum GuildTaskType void GuildTaskMgr::Update(Player* player, Player* guildMaster) { - if (!sPlayerbotAIConfig->guildTaskEnabled) + if (!sPlayerbotAIConfig.guildTaskEnabled) return; if (!GetTaskValue(0, 0, "advert_cleanup")) { CleanupAdverts(); RemoveDuplicatedAdverts(); - SetTaskValue(0, 0, "advert_cleanup", 1, sPlayerbotAIConfig->guildTaskAdvertCleanupTime); + SetTaskValue(0, 0, "advert_cleanup", 1, sPlayerbotAIConfig.guildTaskAdvertCleanupTime); } PlayerbotAI* masterBotAI = GET_PLAYERBOT_AI(guildMaster); @@ -69,8 +69,8 @@ void GuildTaskMgr::Update(Player* player, Player* guildMaster) SetTaskValue(owner, guildId, "killTask", 0, 0); SetTaskValue(owner, guildId, "killCount", 0, 0); SetTaskValue(owner, guildId, "payment", 0, 0); - SetTaskValue(owner, guildId, "thanks", 1, 2 * sPlayerbotAIConfig->maxGuildTaskChangeTime); - SetTaskValue(owner, guildId, "reward", 1, 2 * sPlayerbotAIConfig->maxGuildTaskChangeTime); + SetTaskValue(owner, guildId, "thanks", 1, 2 * sPlayerbotAIConfig.maxGuildTaskChangeTime); + SetTaskValue(owner, guildId, "reward", 1, 2 * sPlayerbotAIConfig.maxGuildTaskChangeTime); uint32 task = CreateTask(player, guildId); @@ -80,11 +80,11 @@ void GuildTaskMgr::Update(Player* player, Player* guildMaster) player->GetName().c_str()); } - uint32 time = urand(sPlayerbotAIConfig->minGuildTaskChangeTime, sPlayerbotAIConfig->maxGuildTaskChangeTime); + uint32 time = urand(sPlayerbotAIConfig.minGuildTaskChangeTime, sPlayerbotAIConfig.maxGuildTaskChangeTime); SetTaskValue(owner, guildId, "activeTask", task, time); SetTaskValue(owner, guildId, "advertisement", 1, - urand(sPlayerbotAIConfig->minGuildTaskAdvertisementTime, - sPlayerbotAIConfig->maxGuildTaskAdvertisementTime)); + urand(sPlayerbotAIConfig.minGuildTaskAdvertisementTime, + sPlayerbotAIConfig.maxGuildTaskAdvertisementTime)); LOG_DEBUG("playerbots", "{} / {}: guild task {} is set for {} secs", guild->GetName().c_str(), player->GetName().c_str(), task, time); @@ -101,8 +101,8 @@ void GuildTaskMgr::Update(Player* player, Player* guildMaster) if (SendAdvertisement(trans, owner, guildId)) { SetTaskValue(owner, guildId, "advertisement", 1, - urand(sPlayerbotAIConfig->minGuildTaskAdvertisementTime, - sPlayerbotAIConfig->maxGuildTaskAdvertisementTime)); + urand(sPlayerbotAIConfig.minGuildTaskAdvertisementTime, + sPlayerbotAIConfig.maxGuildTaskAdvertisementTime)); } else { @@ -118,7 +118,7 @@ void GuildTaskMgr::Update(Player* player, Player* guildMaster) if (SendThanks(trans, owner, guildId, GetTaskValue(owner, guildId, "payment"))) { - SetTaskValue(owner, guildId, "thanks", 1, 2 * sPlayerbotAIConfig->maxGuildTaskChangeTime); + SetTaskValue(owner, guildId, "thanks", 1, 2 * sPlayerbotAIConfig.maxGuildTaskChangeTime); SetTaskValue(owner, guildId, "payment", 0, 0); } else @@ -135,7 +135,7 @@ void GuildTaskMgr::Update(Player* player, Player* guildMaster) if (Reward(trans, owner, guildId)) { - SetTaskValue(owner, guildId, "reward", 1, 2 * sPlayerbotAIConfig->maxGuildTaskChangeTime); + SetTaskValue(owner, guildId, "reward", 1, 2 * sPlayerbotAIConfig.maxGuildTaskChangeTime); SetTaskValue(owner, guildId, "payment", 0, 0); } else @@ -190,7 +190,7 @@ bool GuildTaskMgr::CreateItemTask(Player* player, uint32 guildId) return false; RandomItemBySkillGuildTaskPredicate predicate(player); - uint32 itemId = sRandomItemMgr->GetRandomItem(player->GetLevel() - 5, RANDOM_ITEM_GUILD_TASK, &predicate); + uint32 itemId = sRandomItemMgr.GetRandomItem(player->GetLevel() - 5, RANDOM_ITEM_GUILD_TASK, &predicate); if (!itemId) { LOG_ERROR("playerbots", "{} / {}: no items avaible for item task", @@ -204,9 +204,9 @@ bool GuildTaskMgr::CreateItemTask(Player* player, uint32 guildId) player->GetName().c_str(), itemId, count); SetTaskValue(player->GetGUID().GetCounter(), guildId, "itemCount", count, - sPlayerbotAIConfig->maxGuildTaskChangeTime); + sPlayerbotAIConfig.maxGuildTaskChangeTime); SetTaskValue(player->GetGUID().GetCounter(), guildId, "itemTask", itemId, - sPlayerbotAIConfig->maxGuildTaskChangeTime); + sPlayerbotAIConfig.maxGuildTaskChangeTime); return true; } @@ -239,8 +239,8 @@ bool GuildTaskMgr::CreateKillTask(Player* player, uint32 guildId) if (strstr(name.c_str(), "UNUSED")) continue; - float dist = sServerFacade->GetDistance2d(player, x, y); - if (dist > sPlayerbotAIConfig->guildTaskKillTaskDistance || player->GetMapId() != map) + float dist = ServerFacade::instance().GetDistance2d(player, x, y); + if (dist > sPlayerbotAIConfig.guildTaskKillTaskDistance || player->GetMapId() != map) continue; if (find(ids.begin(), ids.end(), id) == ids.end()) @@ -262,7 +262,7 @@ bool GuildTaskMgr::CreateKillTask(Player* player, uint32 guildId) player->GetName().c_str(), creatureId); SetTaskValue(player->GetGUID().GetCounter(), guildId, "killTask", creatureId, - sPlayerbotAIConfig->maxGuildTaskChangeTime); + sPlayerbotAIConfig.maxGuildTaskChangeTime); return true; } @@ -525,7 +525,7 @@ uint32 GuildTaskMgr::GetMaxItemTaskCount(uint32 itemId) bool GuildTaskMgr::IsGuildTaskItem(uint32 itemId, uint32 guildId) { - if (!sPlayerbotAIConfig->guildTaskEnabled) + if (!sPlayerbotAIConfig.guildTaskEnabled) { return 0; } @@ -553,7 +553,7 @@ bool GuildTaskMgr::IsGuildTaskItem(uint32 itemId, uint32 guildId) std::map GuildTaskMgr::GetTaskValues(uint32 owner, std::string const type, [[maybe_unused]] uint32* validIn /* = nullptr */) { - if (!sPlayerbotAIConfig->guildTaskEnabled) + if (!sPlayerbotAIConfig.guildTaskEnabled) { return std::map(); } @@ -586,7 +586,7 @@ std::map GuildTaskMgr::GetTaskValues(uint32 owner, std::string c uint32 GuildTaskMgr::GetTaskValue(uint32 owner, uint32 guildId, std::string const type, [[maybe_unused]] uint32* validIn /* = nullptr */) { - if (!sPlayerbotAIConfig->guildTaskEnabled) + if (!sPlayerbotAIConfig.guildTaskEnabled) { return 0; } @@ -639,7 +639,7 @@ uint32 GuildTaskMgr::SetTaskValue(uint32 owner, uint32 guildId, std::string cons bool GuildTaskMgr::HandleConsoleCommand(ChatHandler* /* handler */, char const* args) { - if (!sPlayerbotAIConfig->guildTaskEnabled) + if (!sPlayerbotAIConfig.guildTaskEnabled) { LOG_ERROR("playerbots", "Guild task system is currently disabled!"); return false; @@ -703,8 +703,8 @@ bool GuildTaskMgr::HandleConsoleCommand(ChatHandler* /* handler */, char const* if (value == GUILD_TASK_TYPE_ITEM) { name << "ItemTask"; - uint32 itemId = sGuildTaskMgr->GetTaskValue(owner, guildId, "itemTask"); - uint32 itemCount = sGuildTaskMgr->GetTaskValue(owner, guildId, "itemCount"); + uint32 itemId = GuildTaskMgr::instance().GetTaskValue(owner, guildId, "itemTask"); + uint32 itemCount = GuildTaskMgr::instance().GetTaskValue(owner, guildId, "itemCount"); if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId)) { @@ -735,7 +735,7 @@ bool GuildTaskMgr::HandleConsoleCommand(ChatHandler* /* handler */, char const* else if (value == GUILD_TASK_TYPE_KILL) { name << "KillTask"; - uint32 creatureId = sGuildTaskMgr->GetTaskValue(owner, guildId, "killTask"); + uint32 creatureId = GuildTaskMgr::instance().GetTaskValue(owner, guildId, "killTask"); if (CreatureTemplate const* proto = sObjectMgr->GetCreatureTemplate(creatureId)) { @@ -758,22 +758,22 @@ bool GuildTaskMgr::HandleConsoleCommand(ChatHandler* /* handler */, char const* continue; uint32 advertValidIn = 0; - uint32 advert = sGuildTaskMgr->GetTaskValue(owner, guildId, "advertisement", &advertValidIn); + uint32 advert = GuildTaskMgr::instance().GetTaskValue(owner, guildId, "advertisement", &advertValidIn); if (advert && advertValidIn < validIn) name << " advert in " << formatTime(advertValidIn); uint32 thanksValidIn = 0; - uint32 thanks = sGuildTaskMgr->GetTaskValue(owner, guildId, "thanks", &thanksValidIn); + uint32 thanks = GuildTaskMgr::instance().GetTaskValue(owner, guildId, "thanks", &thanksValidIn); if (thanks && thanksValidIn < validIn) name << " thanks in " << formatTime(thanksValidIn); uint32 rewardValidIn = 0; - uint32 reward = sGuildTaskMgr->GetTaskValue(owner, guildId, "reward", &rewardValidIn); + uint32 reward = GuildTaskMgr::instance().GetTaskValue(owner, guildId, "reward", &rewardValidIn); if (reward && rewardValidIn < validIn) name << " reward in " << formatTime(rewardValidIn); uint32 paymentValidIn = 0; - uint32 payment = sGuildTaskMgr->GetTaskValue(owner, guildId, "payment", &paymentValidIn); + uint32 payment = GuildTaskMgr::instance().GetTaskValue(owner, guildId, "payment", &paymentValidIn); if (payment && paymentValidIn < validIn) name << " payment " << ChatHelper::formatMoney(payment) << " in " << formatTime(paymentValidIn); @@ -788,8 +788,8 @@ bool GuildTaskMgr::HandleConsoleCommand(ChatHandler* /* handler */, char const* if (cmd == "cleanup") { - sGuildTaskMgr->CleanupAdverts(); - sGuildTaskMgr->RemoveDuplicatedAdverts(); + GuildTaskMgr::instance().CleanupAdverts(); + GuildTaskMgr::instance().RemoveDuplicatedAdverts(); return true; } @@ -840,10 +840,10 @@ bool GuildTaskMgr::HandleConsoleCommand(ChatHandler* /* handler */, char const* continue; if (reward) - sGuildTaskMgr->Reward(trans, owner, guildId); + GuildTaskMgr::instance().Reward(trans, owner, guildId); if (advert) - sGuildTaskMgr->SendAdvertisement(trans, owner, guildId); + GuildTaskMgr::instance().SendAdvertisement(trans, owner, guildId); } while (result->NextRow()); CharacterDatabase.CommitTransaction(trans); @@ -868,7 +868,7 @@ bool GuildTaskMgr::CheckItemTask(uint32 itemId, uint32 obtained, Player* ownerPl if (!guild) return false; - if (!sRandomPlayerbotMgr->IsRandomBot(bot)) + if (!sRandomPlayerbotMgr.IsRandomBot(bot)) return false; LOG_DEBUG("playerbots", "{} / {}: checking guild task", guild->GetName().c_str(), ownerPlayer->GetName().c_str()); @@ -891,7 +891,7 @@ bool GuildTaskMgr::CheckItemTask(uint32 itemId, uint32 obtained, Player* ownerPl return false; } - uint32 rewardTime = urand(sPlayerbotAIConfig->minGuildTaskRewardTime, sPlayerbotAIConfig->maxGuildTaskRewardTime); + uint32 rewardTime = urand(sPlayerbotAIConfig.minGuildTaskRewardTime, sPlayerbotAIConfig.maxGuildTaskRewardTime); if (byMail) { ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId); @@ -915,7 +915,7 @@ bool GuildTaskMgr::CheckItemTask(uint32 itemId, uint32 obtained, Player* ownerPl { LOG_DEBUG("playerbots", "{} / {}: guild task progress {}/{}", guild->GetName().c_str(), ownerPlayer->GetName().c_str(), obtained, count); - SetTaskValue(owner, guildId, "itemCount", count - obtained, sPlayerbotAIConfig->maxGuildTaskChangeTime); + SetTaskValue(owner, guildId, "itemCount", count - obtained, sPlayerbotAIConfig.maxGuildTaskChangeTime); SetTaskValue(owner, guildId, "thanks", 1, rewardTime - 30); SendCompletionMessage(ownerPlayer, "made a progress with"); } @@ -961,7 +961,7 @@ bool GuildTaskMgr::Reward(CharacterDatabaseTransaction& trans, uint32 owner, uin body << leader->GetName() << "\n"; rewardType = proto->Quality > ITEM_QUALITY_NORMAL ? RANDOM_ITEM_GUILD_TASK_REWARD_EQUIP_BLUE : RANDOM_ITEM_GUILD_TASK_REWARD_EQUIP_GREEN; - itemId = sRandomItemMgr->GetRandomItem(player->GetLevel() - 5, rewardType); + itemId = sRandomItemMgr.GetRandomItem(player->GetLevel() - 5, rewardType); } else if (killTask) { @@ -977,7 +977,7 @@ bool GuildTaskMgr::Reward(CharacterDatabaseTransaction& trans, uint32 owner, uin body << leader->GetName() << "\n"; rewardType = proto->rank == CREATURE_ELITE_RARE ? RANDOM_ITEM_GUILD_TASK_REWARD_TRADE : RANDOM_ITEM_GUILD_TASK_REWARD_TRADE_RARE; - itemId = sRandomItemMgr->GetRandomItem(player->GetLevel(), rewardType); + itemId = sRandomItemMgr.GetRandomItem(player->GetLevel(), rewardType); if (itemId) { ItemTemplate const* itemProto = sObjectMgr->GetItemTemplate(itemId); @@ -1086,7 +1086,7 @@ void GuildTaskMgr::CheckKillTaskInternal(Player* player, Unit* victim) LOG_DEBUG("playerbots", "{} / {}: guild task complete", guild->GetName().c_str(), player->GetName().c_str()); SetTaskValue(owner, guildId, "reward", 1, - urand(sPlayerbotAIConfig->minGuildTaskRewardTime, sPlayerbotAIConfig->maxGuildTaskRewardTime)); + urand(sPlayerbotAIConfig.minGuildTaskRewardTime, sPlayerbotAIConfig.maxGuildTaskRewardTime)); SendCompletionMessage(player, "completed"); } @@ -1094,7 +1094,7 @@ void GuildTaskMgr::CheckKillTaskInternal(Player* player, Unit* victim) void GuildTaskMgr::CleanupAdverts() { - uint32 deliverTime = time(nullptr) - sPlayerbotAIConfig->minGuildTaskChangeTime; + uint32 deliverTime = time(nullptr) - sPlayerbotAIConfig.minGuildTaskChangeTime; QueryResult result = CharacterDatabase.Query( "SELECT id, receiver FROM mail WHERE subject LIKE 'Guild Task%%' AND deliver_time <= {}", deliverTime); if (!result) @@ -1200,7 +1200,7 @@ bool GuildTaskMgr::CheckTaskTransfer(std::string const text, Player* ownerPlayer if (!guild) return false; - if (!sRandomPlayerbotMgr->IsRandomBot(bot)) + if (!sRandomPlayerbotMgr.IsRandomBot(bot)) return false; if (text.empty()) diff --git a/src/Mgr/Guild/GuildTaskMgr.h b/src/Mgr/Guild/GuildTaskMgr.h index c050281ca6..6251f2c1e2 100644 --- a/src/Mgr/Guild/GuildTaskMgr.h +++ b/src/Mgr/Guild/GuildTaskMgr.h @@ -7,56 +7,61 @@ #define _PLAYERBOT_GUILDTASKMGR_H #include +#include +#include -#include "Common.h" -#include "Transaction.h" - -class ChatHandler; -class Player; -class Unit; +#include "DatabaseEnvFwd.h" +#include "Unit.h" +#include "Player.h" +#include "Chat.h" class GuildTaskMgr { public: - GuildTaskMgr(){}; - virtual ~GuildTaskMgr(){}; - - static GuildTaskMgr* instance() + static GuildTaskMgr& instance() { static GuildTaskMgr instance; - return &instance; + + return instance; } void Update(Player* owner, Player* guildMaster); static bool HandleConsoleCommand(ChatHandler* handler, char const* args); - bool IsGuildTaskItem(uint32 itemId, uint32 guildId); - bool CheckItemTask(uint32 itemId, uint32 obtained, Player* owner, Player* bot, bool byMail = false); + bool IsGuildTaskItem(uint32_t itemId, uint32_t guildId); + bool CheckItemTask(uint32_t itemId, uint32_t obtained, Player* owner, Player* bot, bool byMail = false); void CheckKillTask(Player* owner, Unit* victim); void CheckKillTaskInternal(Player* owner, Unit* victim); bool CheckTaskTransfer(std::string const text, Player* owner, Player* bot); private: - std::map GetTaskValues(uint32 owner, std::string const type, uint32* validIn = nullptr); - uint32 GetTaskValue(uint32 owner, uint32 guildId, std::string const type, uint32* validIn = nullptr); - uint32 SetTaskValue(uint32 owner, uint32 guildId, std::string const type, uint32 value, uint32 validIn); - uint32 CreateTask(Player* owner, uint32 guildId); - bool SendAdvertisement(CharacterDatabaseTransaction& trans, uint32 owner, uint32 guildId); - bool SendItemAdvertisement(CharacterDatabaseTransaction& trans, uint32 itemId, uint32 owner, uint32 guildId, - uint32 validIn); - bool SendKillAdvertisement(CharacterDatabaseTransaction& trans, uint32 creatureId, uint32 owner, uint32 guildId, - uint32 validIn); - bool SendThanks(CharacterDatabaseTransaction& trans, uint32 owner, uint32 guildId, uint32 payment); - bool Reward(CharacterDatabaseTransaction& trans, uint32 owner, uint32 guildId); - bool CreateItemTask(Player* owner, uint32 guildId); - bool CreateKillTask(Player* owner, uint32 guildId); - uint32 GetMaxItemTaskCount(uint32 itemId); + GuildTaskMgr() = default; + ~GuildTaskMgr() = default; + + GuildTaskMgr(const GuildTaskMgr&) = delete; + GuildTaskMgr& operator=(const GuildTaskMgr&) = delete; + + GuildTaskMgr(GuildTaskMgr&&) = delete; + GuildTaskMgr& operator=(GuildTaskMgr&&) = delete; + + std::map GetTaskValues(uint32_t owner, std::string const type, uint32_t* validIn = nullptr); + uint32_t GetTaskValue(uint32_t owner, uint32_t guildId, std::string const type, uint32_t* validIn = nullptr); + uint32_t SetTaskValue(uint32_t owner, uint32_t guildId, std::string const type, uint32_t value, uint32_t validIn); + uint32_t CreateTask(Player* owner, uint32_t guildId); + bool SendAdvertisement(CharacterDatabaseTransaction& trans, uint32_t owner, uint32_t guildId); + bool SendItemAdvertisement(CharacterDatabaseTransaction& trans, uint32_t itemId, uint32_t owner, uint32_t guildId, + uint32_t validIn); + bool SendKillAdvertisement(CharacterDatabaseTransaction& trans, uint32_t creatureId, uint32_t owner, uint32_t guildId, + uint32_t validIn); + bool SendThanks(CharacterDatabaseTransaction& trans, uint32_t owner, uint32_t guildId, uint32_t payment); + bool Reward(CharacterDatabaseTransaction& trans, uint32_t owner, uint32_t guildId); + bool CreateItemTask(Player* owner, uint32_t guildId); + bool CreateKillTask(Player* owner, uint32_t guildId); + uint32_t GetMaxItemTaskCount(uint32_t itemId); void CleanupAdverts(); void RemoveDuplicatedAdverts(); - void DeleteMail(std::vector buffer); + void DeleteMail(std::vector buffer); void SendCompletionMessage(Player* player, std::string const verb); }; -#define sGuildTaskMgr GuildTaskMgr::instance() - #endif diff --git a/src/Mgr/Guild/PlayerbotGuildMgr.cpp b/src/Mgr/Guild/PlayerbotGuildMgr.cpp index c1f7aa5b2d..0885e7ed30 100644 --- a/src/Mgr/Guild/PlayerbotGuildMgr.cpp +++ b/src/Mgr/Guild/PlayerbotGuildMgr.cpp @@ -4,15 +4,12 @@ #include "DatabaseEnv.h" #include "Guild.h" #include "GuildMgr.h" -#include "RandomPlayerbotMgr.h" #include "ScriptMgr.h" -PlayerbotGuildMgr::PlayerbotGuildMgr(){} - void PlayerbotGuildMgr::Init() { _guildCache.clear(); - if (sPlayerbotAIConfig->deleteRandomBotGuilds) + if (sPlayerbotAIConfig.deleteRandomBotGuilds) DeleteBotGuilds(); LoadGuildNames(); @@ -38,7 +35,7 @@ bool PlayerbotGuildMgr::CreateGuild(Player* player, std::string guildName) entry.name = guildName; entry.memberCount = 1; entry.status = 1; - entry.maxMembers = sPlayerbotAIConfig->randomBotGuildSizeMax; + entry.maxMembers = sPlayerbotAIConfig.randomBotGuildSizeMax; entry.faction = player->GetTeamId(); _guildCache[guild->GetId()] = entry; @@ -113,7 +110,7 @@ std::string PlayerbotGuildMgr::AssignToGuild(Player* player) } ); - if (count < sPlayerbotAIConfig->randomBotGuildCount) + if (count < sPlayerbotAIConfig.randomBotGuildCount) { for (auto& key : _shuffled_guild_keys) { @@ -214,7 +211,7 @@ void PlayerbotGuildMgr::ValidateGuildCache() uint32 guildId = it->first; GuildCache cache; cache.name = it->second; - cache.maxMembers = sPlayerbotAIConfig->randomBotGuildSizeMax; + cache.maxMembers = sPlayerbotAIConfig.randomBotGuildSizeMax; Guild* guild = sGuildMgr ->GetGuildById(guildId); if (!guild) @@ -224,7 +221,7 @@ void PlayerbotGuildMgr::ValidateGuildCache() ObjectGuid leaderGuid = guild->GetLeaderGUID(); CharacterCacheEntry const* leaderEntry = sCharacterCache->GetCharacterCacheByGuid(leaderGuid); uint32 leaderAccount = leaderEntry->AccountId; - cache.hasRealPlayer = !(sPlayerbotAIConfig->IsInRandomAccountList(leaderAccount)); + cache.hasRealPlayer = !(sPlayerbotAIConfig.IsInRandomAccountList(leaderAccount)); cache.faction = Player::TeamIdForRace(leaderEntry->Race); if (cache.memberCount == 0) cache.status = 0; // empty @@ -306,7 +303,7 @@ class BotGuildCacheWorldScript : public WorldScript if (_validateTimer >= _validateInterval) // Validate every hour { _validateTimer = 0; - sPlayerbotGuildMgr->ValidateGuildCache(); + PlayerbotGuildMgr::instance().ValidateGuildCache(); LOG_INFO("playerbots", "Scheduled guild cache validation"); } } diff --git a/src/Mgr/Guild/PlayerbotGuildMgr.h b/src/Mgr/Guild/PlayerbotGuildMgr.h index 0df0df7371..499a33e606 100644 --- a/src/Mgr/Guild/PlayerbotGuildMgr.h +++ b/src/Mgr/Guild/PlayerbotGuildMgr.h @@ -5,15 +5,14 @@ #include "Player.h" #include "PlayerbotAI.h" -class PlayerbotAI; - class PlayerbotGuildMgr { public: - static PlayerbotGuildMgr* instance() + static PlayerbotGuildMgr& instance() { static PlayerbotGuildMgr instance; - return &instance; + + return instance; } void Init(); @@ -29,7 +28,15 @@ class PlayerbotGuildMgr bool IsRealGuild(Player* bot); private: - PlayerbotGuildMgr(); + PlayerbotGuildMgr() = default; + ~PlayerbotGuildMgr() = default; + + PlayerbotGuildMgr(const PlayerbotGuildMgr&) = delete; + PlayerbotGuildMgr& operator=(const PlayerbotGuildMgr&) = delete; + + PlayerbotGuildMgr(PlayerbotGuildMgr&&) = delete; + PlayerbotGuildMgr& operator=(PlayerbotGuildMgr&&) = delete; + std::unordered_map _guildNames; struct GuildCache @@ -47,6 +54,4 @@ class PlayerbotGuildMgr void PlayerBotsGuildValidationScript(); -#define sPlayerbotGuildMgr PlayerbotGuildMgr::instance() - #endif \ No newline at end of file diff --git a/src/Mgr/Item/RandomItemMgr.cpp b/src/Mgr/Item/RandomItemMgr.cpp index 87b8379355..8939e349b0 100644 --- a/src/Mgr/Item/RandomItemMgr.cpp +++ b/src/Mgr/Item/RandomItemMgr.cpp @@ -7,7 +7,9 @@ #include "ItemTemplate.h" #include "LootValues.h" -#include "Playerbots.h" +#include "Player.h" +#include "PlayerbotAIConfig.h" +#include "SpellMgr.h" char* strstri(char const* str1, char const* str2); std::set RandomItemMgr::itemCache; @@ -176,7 +178,7 @@ RandomItemMgr::~RandomItemMgr() predicates.clear(); } -bool RandomItemMgr::HandleConsoleCommand(ChatHandler* handler, char const* args) +bool RandomItemMgr::HandleConsoleCommand(ChatHandler*, char const* args) { if (!args || !*args) { @@ -272,7 +274,7 @@ void RandomItemMgr::BuildRandomItemCache() } } - uint32 maxLevel = sPlayerbotAIConfig->randomBotMaxLevel; + uint32 maxLevel = sPlayerbotAIConfig.randomBotMaxLevel; if (maxLevel > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); @@ -1269,7 +1271,7 @@ void RandomItemMgr::BuildItemInfoCache() uint32 RandomItemMgr::CalculateStatWeight(uint8 playerclass, uint8 spec, ItemTemplate const* proto) { - uint32 statWeight = 0; + int64_t statWeight = 0; bool isCasterItem = false; bool isAttackItem = false; bool noCaster = (Classes)playerclass == CLASS_WARRIOR || (Classes)playerclass == CLASS_ROGUE || @@ -1700,7 +1702,7 @@ std::vector RandomItemMgr::GetQuestIdsForItem(uint32 itemId) } } - return std::move(questIds); + return questIds; } uint32 RandomItemMgr::GetUpgrade(Player* player, std::string spec, uint8 slot, uint32 quality, uint32 itemId) @@ -1782,10 +1784,19 @@ uint32 RandomItemMgr::GetUpgrade(Player* player, std::string spec, uint8 slot, u } // skip no stats trinkets - if (info.weights[specId] == 1 && info.slot == EQUIPMENT_SLOT_NECK || info.slot == EQUIPMENT_SLOT_TRINKET1 || - info.slot == EQUIPMENT_SLOT_TRINKET2 || info.slot == EQUIPMENT_SLOT_FINGER1 || - info.slot == EQUIPMENT_SLOT_FINGER2) + if ( + info.weights[specId] == 1 + && ( + info.slot == EQUIPMENT_SLOT_NECK + || info.slot == EQUIPMENT_SLOT_TRINKET1 + || info.slot == EQUIPMENT_SLOT_TRINKET2 + || info.slot == EQUIPMENT_SLOT_FINGER1 + || info.slot == EQUIPMENT_SLOT_FINGER2 + ) + ) + { continue; + } // check if item stat score is the best among class specs uint32 bestSpecId = 0; @@ -1823,16 +1834,15 @@ uint32 RandomItemMgr::GetUpgrade(Player* player, std::string spec, uint8 slot, u } std::vector RandomItemMgr::GetUpgradeList(Player* player, std::string spec, uint8 slot, uint32 quality, - uint32 itemId, uint32 amount) + uint32 itemId, uint32) { std::vector listItems; if (!player) - return std::move(listItems); + return listItems; // get old item statWeight uint32 oldStatWeight = 0; uint32 specId = 0; - uint32 closestUpgrade = 0; uint32 closestUpgradeWeight = 0; std::vector classspecs; @@ -1848,7 +1858,7 @@ std::vector RandomItemMgr::GetUpgradeList(Player* player, std::string sp } if (!specId) - return std::move(listItems); + return listItems; if (itemId && itemInfoCache.find(itemId) != itemInfoCache.end()) { @@ -1933,7 +1943,6 @@ std::vector RandomItemMgr::GetUpgradeList(Player* player, std::string sp // pick closest upgrade if (info.weights[specId] > closestUpgradeWeight) { - closestUpgrade = info.itemId; closestUpgradeWeight = info.weights[specId]; } } @@ -1942,7 +1951,7 @@ std::vector RandomItemMgr::GetUpgradeList(Player* player, std::string sp LOG_INFO("playerbots", "New Items: {}, Old item:%d, New items max: {}", listItems.size(), oldStatWeight, closestUpgradeWeight); - return std::move(listItems); + return listItems; } bool RandomItemMgr::HasStatWeight(uint32 itemId) @@ -2092,7 +2101,7 @@ uint32 RandomItemMgr::GetLiveStatWeight(Player* player, uint32 itemId) void RandomItemMgr::BuildEquipCache() { - uint32 maxLevel = sPlayerbotAIConfig->randomBotMaxLevel; + uint32 maxLevel = sPlayerbotAIConfig.randomBotMaxLevel; if (maxLevel > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); @@ -2218,7 +2227,7 @@ void RandomItemMgr::BuildEquipCacheNew() if (quest->GetRequiredClasses()) continue; - for (int j = 0; j < quest->GetRewChoiceItemsCount(); j++) + for (uint32_t j = 0; j < quest->GetRewChoiceItemsCount(); j++) if (uint32 itemId = quest->RewardChoiceItemId[j]) { ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId); @@ -2229,7 +2238,7 @@ void RandomItemMgr::BuildEquipCacheNew() questItemIds.insert(itemId); } - for (int j = 0; j < quest->GetRewItemsCount(); j++) + for (uint32_t j = 0; j < quest->GetRewItemsCount(); j++) if (uint32 itemId = quest->RewardItemId[j]) { ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId); @@ -2374,9 +2383,6 @@ void RandomItemMgr::BuildPotionCache() if (proto->Duration & 0x80000000) continue; - if (proto->AllowableClass != -1) - continue; - bool hybrid = false; SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(proto->Spells[0].SpellId); if (!spellInfo) @@ -2415,7 +2421,7 @@ void RandomItemMgr::BuildPotionCache() void RandomItemMgr::BuildFoodCache() { - uint32 maxLevel = sPlayerbotAIConfig->randomBotMaxLevel; + uint32 maxLevel = sPlayerbotAIConfig.randomBotMaxLevel; if (maxLevel > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); @@ -2548,7 +2554,7 @@ uint32 RandomItemMgr::GetRandomFood(uint32 level, uint32 category) void RandomItemMgr::BuildTradeCache() { - uint32 maxLevel = sPlayerbotAIConfig->randomBotMaxLevel; + uint32 maxLevel = sPlayerbotAIConfig.randomBotMaxLevel; if (maxLevel > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); @@ -2767,7 +2773,9 @@ inline bool IsCraftedBySpellInfo(ItemTemplate const* proto, SpellInfo const* spe continue; } - if (proto->ItemId == spellInfo->Reagent[x]) + const int64_t itemTemplateId = proto->ItemId; + + if (itemTemplateId == spellInfo->Reagent[x]) { return true; } diff --git a/src/Mgr/Item/RandomItemMgr.h b/src/Mgr/Item/RandomItemMgr.h index 216ddf9bfc..54e2e63516 100644 --- a/src/Mgr/Item/RandomItemMgr.h +++ b/src/Mgr/Item/RandomItemMgr.h @@ -12,7 +12,6 @@ #include #include "AiFactory.h" -#include "Common.h" #include "ItemTemplate.h" class ChatHandler; @@ -135,12 +134,11 @@ typedef std::map BotEquipCache; class RandomItemMgr { public: - RandomItemMgr(); - virtual ~RandomItemMgr(); - static RandomItemMgr* instance() + static RandomItemMgr& instance() { static RandomItemMgr instance; - return &instance; + + return instance; } public: @@ -191,6 +189,17 @@ class RandomItemMgr bool CheckItemStats(uint8 clazz, uint8 sp, uint8 ap, uint8 tank); private: + // Implemented in RandomItemMgr.cpp + RandomItemMgr(); + // Implemented in RandomItemMgr.cpp + ~RandomItemMgr(); + + RandomItemMgr(const RandomItemMgr&) = delete; + RandomItemMgr& operator=(const RandomItemMgr&) = delete; + + RandomItemMgr(RandomItemMgr&&) = delete; + RandomItemMgr& operator=(RandomItemMgr&&) = delete; + std::map randomItemCache; std::map predicates; BotEquipCache equipCache; diff --git a/src/Mgr/Item/StatsCollector.cpp b/src/Mgr/Item/StatsCollector.cpp index 4f719fea4e..efc2420889 100644 --- a/src/Mgr/Item/StatsCollector.cpp +++ b/src/Mgr/Item/StatsCollector.cpp @@ -1,18 +1,13 @@ #include "StatsCollector.h" -#include - #include "DBCStores.h" -#include "ItemEnchantmentMgr.h" #include "ItemTemplate.h" -#include "ObjectMgr.h" #include "PlayerbotAI.h" #include "PlayerbotAIAware.h" #include "SharedDefines.h" #include "SpellAuraDefines.h" #include "SpellInfo.h" #include "SpellMgr.h" -#include "UpdateFields.h" #include "Util.h" StatsCollector::StatsCollector(CollectorType type, int32 cls) : type_(type), cls_(cls) { Reset(); } @@ -39,7 +34,7 @@ void StatsCollector::CollectItemStats(ItemTemplate const* proto) } stats[STATS_TYPE_ARMOR] += proto->Armor; stats[STATS_TYPE_BLOCK_VALUE] += proto->Block; - for (int i = 0; i < proto->StatsCount; i++) + for (uint32_t i = 0; i < proto->StatsCount; i++) { const _ItemStat& stat = proto->ItemStat[i]; const int32& val = stat.ItemStatValue; diff --git a/src/Mgr/Item/StatsWeightCalculator.cpp b/src/Mgr/Item/StatsWeightCalculator.cpp index 1b3f3dcfcb..777f1fb847 100644 --- a/src/Mgr/Item/StatsWeightCalculator.cpp +++ b/src/Mgr/Item/StatsWeightCalculator.cpp @@ -500,7 +500,7 @@ void StatsWeightCalculator::CalculateItemSetMod(Player* player, ItemTemplate con weight_ *= multiplier; } -void StatsWeightCalculator::CalculateSocketBonus(Player* player, ItemTemplate const* proto) +void StatsWeightCalculator::CalculateSocketBonus(Player*, ItemTemplate const* proto) { uint32 socketNum = 0; for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT + MAX_GEM_SOCKETS; diff --git a/src/Mgr/Move/FleeManager.cpp b/src/Mgr/Move/FleeManager.cpp index 34e17fe391..d3d1a8bb02 100644 --- a/src/Mgr/Move/FleeManager.cpp +++ b/src/Mgr/Move/FleeManager.cpp @@ -34,7 +34,7 @@ void FleeManager::calculateDistanceToCreatures(FleePoint* point) if (!unit) continue; - float d = sServerFacade->GetDistance2d(unit, point->x, point->y); + float d = ServerFacade::instance().GetDistance2d(unit, point->x, point->y); point->sumDistance += d; if (point->minDistance < 0 || point->minDistance > d) point->minDistance = d; @@ -81,11 +81,11 @@ void FleeManager::calculatePossibleDestinations(std::vector& points) enemyOri.push_back(ori); } - float distIncrement = std::max(sPlayerbotAIConfig->followDistance, - (maxAllowedDistance - sPlayerbotAIConfig->tooCloseDistance) / 10.0f); - for (float dist = maxAllowedDistance; dist >= sPlayerbotAIConfig->tooCloseDistance; dist -= distIncrement) + float distIncrement = std::max(sPlayerbotAIConfig.followDistance, + (maxAllowedDistance - sPlayerbotAIConfig.tooCloseDistance) / 10.0f); + for (float dist = maxAllowedDistance; dist >= sPlayerbotAIConfig.tooCloseDistance; dist -= distIncrement) { - float angleIncrement = std::max(M_PI / 20, M_PI / 4 / (1.0 + dist - sPlayerbotAIConfig->tooCloseDistance)); + float angleIncrement = std::max(M_PI / 20, M_PI / 4 / (1.0 + dist - sPlayerbotAIConfig.tooCloseDistance)); for (float add = 0.0f; add < M_PI / 4 + angleIncrement; add += angleIncrement) { for (float angle = add; angle < add + 2 * static_cast(M_PI) + angleIncrement; @@ -97,8 +97,8 @@ void FleeManager::calculatePossibleDestinations(std::vector& points) float x = botPosX + cos(angle) * maxAllowedDistance, y = botPosY + sin(angle) * maxAllowedDistance, z = botPosZ + CONTACT_DISTANCE; if (forceMaxDistance && - sServerFacade->IsDistanceLessThan(sServerFacade->GetDistance2d(bot, x, y), - maxAllowedDistance - sPlayerbotAIConfig->tooCloseDistance)) + ServerFacade::instance().IsDistanceLessThan(ServerFacade::instance().GetDistance2d(bot, x, y), + maxAllowedDistance - sPlayerbotAIConfig.tooCloseDistance)) continue; bot->UpdateAllowedPositionZ(x, y, z); @@ -113,8 +113,8 @@ void FleeManager::calculatePossibleDestinations(std::vector& points) FleePoint* point = new FleePoint(botAI, x, y, z); calculateDistanceToCreatures(point); - if (sServerFacade->IsDistanceGreaterOrEqualThan(point->minDistance - start.minDistance, - sPlayerbotAIConfig->followDistance)) + if (ServerFacade::instance().IsDistanceGreaterOrEqualThan(point->minDistance - start.minDistance, + sPlayerbotAIConfig.followDistance)) points.push_back(point); else delete point; @@ -189,8 +189,8 @@ bool FleeManager::isUseful() creature->GetAttackDistance(bot) * creature->GetAttackDistance(bot)) return true; - // float d = sServerFacade->GetDistance2d(unit, bot); - // if (sServerFacade->IsDistanceLessThan(d, sPlayerbotAIConfig->aggroDistance)) return true; + // float d = ServerFacade::instance().GetDistance2d(unit, bot); + // if (ServerFacade::instance().IsDistanceLessThan(d, sPlayerbotAIConfig.aggroDistance)) return true; } return false; diff --git a/src/Mgr/Security/PlayerbotSecurity.cpp b/src/Mgr/Security/PlayerbotSecurity.cpp index 68bb2db29a..4a3bd36553 100644 --- a/src/Mgr/Security/PlayerbotSecurity.cpp +++ b/src/Mgr/Security/PlayerbotSecurity.cpp @@ -47,7 +47,7 @@ PlayerbotSecurityLevel PlayerbotSecurity::LevelFor(Player* from, DenyReason* rea return PLAYERBOT_SECURITY_DENY_ALL; } - if (sPlayerbotAIConfig->IsInRandomAccountList(account)) + if (sPlayerbotAIConfig.IsInRandomAccountList(account)) { // (duplicate check in case of faction change) if (botAI->IsOpposing(from)) @@ -72,7 +72,7 @@ PlayerbotSecurityLevel PlayerbotSecurity::LevelFor(Player* from, DenyReason* rea return PLAYERBOT_SECURITY_TALK; } - if (sPlayerbotAIConfig->groupInvitationPermission <= 0) + if (sPlayerbotAIConfig.groupInvitationPermission <= 0) { if (reason) *reason = PLAYERBOT_DENY_NONE; @@ -80,7 +80,7 @@ PlayerbotSecurityLevel PlayerbotSecurity::LevelFor(Player* from, DenyReason* rea return PLAYERBOT_SECURITY_TALK; } - if (sPlayerbotAIConfig->groupInvitationPermission <= 1) + if (sPlayerbotAIConfig.groupInvitationPermission <= 1) { int32 levelDiff = int32(bot->GetLevel()) - int32(from->GetLevel()); if (levelDiff > 5) @@ -98,7 +98,7 @@ PlayerbotSecurityLevel PlayerbotSecurity::LevelFor(Player* from, DenyReason* rea int32 botGS = static_cast(botAI->GetEquipGearScore(bot)); int32 fromGS = static_cast(botAI->GetEquipGearScore(from)); - if (sPlayerbotAIConfig->gearscorecheck && botGS && bot->GetLevel() > 15 && botGS > fromGS) + if (sPlayerbotAIConfig.gearscorecheck && botGS && bot->GetLevel() > 15 && botGS > fromGS) { uint32 diffPct = uint32(100 * (botGS - fromGS) / botGS); uint32 reqPct = uint32(12 * sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) / from->GetLevel()); @@ -277,7 +277,7 @@ bool PlayerbotSecurity::CheckLevelFor(PlayerbotSecurityLevel level, bool silent, ObjectGuid guid = from->GetGUID(); time_t lastSaid = whispers[guid][text]; - if (!lastSaid || (time(nullptr) - lastSaid) >= sPlayerbotAIConfig->repeatDelay / 1000) + if (!lastSaid || (time(nullptr) - lastSaid) >= sPlayerbotAIConfig.repeatDelay / 1000) { whispers[guid][text] = time(nullptr); diff --git a/src/Mgr/Talent/Talentspec.cpp b/src/Mgr/Talent/Talentspec.cpp index 06e70b841c..74106d25bb 100644 --- a/src/Mgr/Talent/Talentspec.cpp +++ b/src/Mgr/Talent/Talentspec.cpp @@ -6,7 +6,9 @@ #include "Talentspec.h" #include "Event.h" -#include "Playerbots.h" +#include "Player.h" +#include "SpellMgr.h" +#include "World.h" uint32 TalentSpec::TalentListEntry::tabPage() const { @@ -140,7 +142,7 @@ bool TalentSpec::CheckTalents(uint32 level, std::ostringstream* out) } // Set the talents for the bots to the current spec. -void TalentSpec::ApplyTalents(Player* bot, std::ostringstream* out) +void TalentSpec::ApplyTalents(Player* bot, std::ostringstream*) { for (auto& entry : talents) { @@ -317,7 +319,7 @@ std::vector TalentSpec::GetTalentTree(uint32 tabpag if (entry.tabPage() == tabpage) retList.push_back(entry); - return std::move(retList); + return retList; } uint32 TalentSpec::GetTalentPoints(int32 tabpage) { return GetTalentPoints(talents, tabpage); }; @@ -330,8 +332,14 @@ uint32 TalentSpec::GetTalentPoints(std::vector& talents, int32 uint32 tPoints = 0; for (auto& entry : talents) - if (entry.tabPage() == tabpage) + { + const int64_t entryTabPage = entry.tabPage(); + + if (entryTabPage == tabpage) + { tPoints = tPoints + entry.rank; + } + } return tPoints; } @@ -368,7 +376,7 @@ std::string const TalentSpec::GetTalentLink() if (treeLink[2] != "0") link = link + "-" + treeLink[2]; - return std::move(link); + return link; } uint32 TalentSpec::highestTree() @@ -395,7 +403,7 @@ uint32 TalentSpec::highestTree() return 0; } -std::string const TalentSpec::FormatSpec(Player* bot) +std::string const TalentSpec::FormatSpec(Player*) { // uint8 cls = bot->getClass(); //not used, (used in lined 403), line marked for removal. @@ -446,7 +454,7 @@ std::vector TalentSpec::SubTalentList(std::vector +#include +#include "Player.h" struct TalentEntry; struct TalentTabEntry; @@ -25,17 +27,17 @@ class TalentSpec public: struct TalentListEntry { - uint32 entry; - uint32 rank; - uint32 maxRank; + uint32_t entry; + uint32_t rank; + uint32_t maxRank; TalentEntry const* talentInfo; TalentTabEntry const* talentTabInfo; - uint32 tabPage() const; + uint32_t tabPage() const; }; TalentSpec(){}; virtual ~TalentSpec() {} - TalentSpec(uint32 classMask); + TalentSpec(uint32_t classMask); TalentSpec(TalentSpec* base, std::string const link); TalentSpec(Player* bot); TalentSpec(Player* bot, std::string const link); diff --git a/src/Mgr/Text/PlayerbotTextMgr.cpp b/src/Mgr/Text/PlayerbotTextMgr.cpp index 1dce9a29a5..353131095a 100644 --- a/src/Mgr/Text/PlayerbotTextMgr.cpp +++ b/src/Mgr/Text/PlayerbotTextMgr.cpp @@ -2,12 +2,14 @@ * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it * and/or modify it under version 3 of the License, or (at your option), any later version. */ +#include "DatabaseEnv.h" +#include "WorldSessionMgr.h" +#include "Random.h" +// Required due to a poor implementation by AC +#include "QueryResult.h" #include "PlayerbotTextMgr.h" -#include "Playerbots.h" -#include "WorldSessionMgr.h" - void PlayerbotTextMgr::replaceAll(std::string& str, const std::string& from, const std::string& to) { if (from.empty()) @@ -101,6 +103,7 @@ std::string PlayerbotTextMgr::GetBotText(std::string name, std::map placeholders) { diff --git a/src/Mgr/Text/PlayerbotTextMgr.h b/src/Mgr/Text/PlayerbotTextMgr.h index f4ec2c403c..5f173fdd16 100644 --- a/src/Mgr/Text/PlayerbotTextMgr.h +++ b/src/Mgr/Text/PlayerbotTextMgr.h @@ -11,9 +11,6 @@ #include "Common.h" -#define BOT_TEXT1(name) sPlayerbotTextMgr->GetBotText(name) -#define BOT_TEXT2(name, replace) sPlayerbotTextMgr->GetBotText(name, replace) - struct BotTextEntry { BotTextEntry(std::string name, std::map text, uint32 say_type, uint32 reply_type) @@ -63,18 +60,11 @@ enum ChatReplyType class PlayerbotTextMgr { public: - PlayerbotTextMgr() - { - for (uint8 i = 0; i < MAX_LOCALES; ++i) - { - botTextLocalePriority[i] = 0; - } - }; - virtual ~PlayerbotTextMgr(){}; - static PlayerbotTextMgr* instance() + static PlayerbotTextMgr& instance() { static PlayerbotTextMgr instance; - return &instance; + + return instance; } std::string GetBotText(std::string name, std::map placeholders); @@ -95,11 +85,25 @@ class PlayerbotTextMgr void ResetLocalePriority(); private: + PlayerbotTextMgr() + { + for (uint8 i = 0; i < MAX_LOCALES; ++i) + { + botTextLocalePriority[i] = 0; + } + }; + ~PlayerbotTextMgr() = default; + + PlayerbotTextMgr(const PlayerbotTextMgr&) = delete; + PlayerbotTextMgr& operator=(const PlayerbotTextMgr&) = delete; + + PlayerbotTextMgr(PlayerbotTextMgr&&) = delete; + PlayerbotTextMgr& operator=(PlayerbotTextMgr&&) = delete; + + std::map> botTexts; std::map botTextChance; uint32 botTextLocalePriority[MAX_LOCALES]; }; -#define sPlayerbotTextMgr PlayerbotTextMgr::instance() - #endif diff --git a/src/Mgr/Travel/TravelMgr.cpp b/src/Mgr/Travel/TravelMgr.cpp index ab70576502..dd0fe86d6c 100644 --- a/src/Mgr/Travel/TravelMgr.cpp +++ b/src/Mgr/Travel/TravelMgr.cpp @@ -8,17 +8,18 @@ #include #include -#include "CellImpl.h" +#include "Talentspec.h" #include "ChatHelper.h" #include "MMapFactory.h" #include "MapMgr.h" #include "PathGenerator.h" #include "Playerbots.h" -#include "StrategyContext.h" #include "TransportMgr.h" -#include "VMapFactory.h" #include "VMapMgr2.h" +#include "Map.h" +#include "DynamicObject.h" #include "Corpse.h" +#include "CellImpl.h" WorldPosition::WorldPosition(std::string const str) { @@ -116,16 +117,18 @@ WorldPosition::WorldPosition(std::vector list, WorldPositionConst } } +// We have to disable this Clang rule because the bug resides in AC which we cannot act on. + WorldPosition::WorldPosition(uint32 mapid, GridCoord grid) - : WorldLocation(mapid, (int32(grid.x_coord) - CENTER_GRID_ID - 0.5) * SIZE_OF_GRIDS + CENTER_GRID_OFFSET, - (int32(grid.y_coord) - CENTER_GRID_ID - 0.5) * SIZE_OF_GRIDS + CENTER_GRID_OFFSET, 0, 0) + : WorldLocation(mapid, (int32(grid.x_coord) - CENTER_GRID_ID - 0.5) * SIZE_OF_GRIDS + CENTER_GRID_OFFSET, // NOLINT(bugprone-integer-division) + (int32(grid.y_coord) - CENTER_GRID_ID - 0.5) * SIZE_OF_GRIDS + CENTER_GRID_OFFSET, 0, 0) // NOLINT(bugprone-integer-division) { } WorldPosition::WorldPosition(uint32 mapid, CellCoord cell) : WorldLocation( - mapid, (int32(cell.x_coord) - CENTER_GRID_CELL_ID - 0.5) * SIZE_OF_GRID_CELL + CENTER_GRID_CELL_OFFSET, - (int32(cell.y_coord) - CENTER_GRID_CELL_ID - 0.5) * SIZE_OF_GRID_CELL + CENTER_GRID_CELL_OFFSET, 0, 0) + mapid, (int32(cell.x_coord) - CENTER_GRID_CELL_ID - 0.5) * SIZE_OF_GRID_CELL + CENTER_GRID_CELL_OFFSET, // NOLINT(bugprone-integer-division) + (int32(cell.y_coord) - CENTER_GRID_CELL_ID - 0.5) * SIZE_OF_GRID_CELL + CENTER_GRID_CELL_OFFSET, 0, 0) // NOLINT(bugprone-integer-division) { } @@ -246,7 +249,7 @@ float WorldPosition::distance(WorldPosition* center) return relPoint(center).size(); // this -> mapTransfer | mapTransfer -> center - return sTravelMgr->mapTransDistance(*this, *center); + return TravelMgr::instance().mapTransDistance(*this, *center); }; float WorldPosition::fDist(WorldPosition* center) @@ -255,7 +258,7 @@ float WorldPosition::fDist(WorldPosition* center) return sqrt(sqDistance2d(center)); // this -> mapTransfer | mapTransfer -> center - return sTravelMgr->fastMapTransDistance(*this, *center); + return TravelMgr::instance().fastMapTransDistance(*this, *center); }; float mapTransfer::fDist(WorldPosition start, WorldPosition end) @@ -428,7 +431,7 @@ void WorldPosition::printWKT(std::vector points, std::ostringstre WorldPosition WorldPosition::getDisplayLocation() { - WorldPosition pos = sTravelNodeMap->getMapOffset(getMapId()); + WorldPosition pos = TravelNodeMap::instance().getMapOffset(getMapId()); return offset(const_cast(&pos)); } @@ -479,10 +482,10 @@ std::string const WorldPosition::getAreaName(bool fullName, bool zoneName) } } - return std::move(areaName); + return areaName; } -std::set WorldPosition::getTransports(uint32 entry) +std::set WorldPosition::getTransports(uint32) { /* if (!entry) @@ -627,78 +630,78 @@ void WorldPosition::loadMapAndVMap(uint32 mapId, uint8 x, uint8 y) { std::string const fileName = "load_map_grid.csv"; - if (isOverworld() && false || false) - { - if (!MMAP::MMapFactory::createOrGetMMapMgr()->loadMap(mapId, x, y)) - if (sPlayerbotAIConfig->hasLog(fileName)) - { - std::ostringstream out; - out << sPlayerbotAIConfig->GetTimestampStr(); - out << "+00,\"mmap\", " << x << "," << y << "," << (sTravelMgr->isBadMmap(mapId, x, y) ? "0" : "1") - << ","; - printWKT(fromGridCoord(GridCoord(x, y)), out, 1, true); - sPlayerbotAIConfig->log(fileName, out.str().c_str()); - } - } - else - { + // if (isOverworld() && false || false) + // { + // if (!MMAP::MMapFactory::createOrGetMMapMgr()->loadMap(mapId, x, y)) + // if (sPlayerbotAIConfig.hasLog(fileName)) + // { + // std::ostringstream out; + // out << sPlayerbotAIConfig.GetTimestampStr(); + // out << "+00,\"mmap\", " << x << "," << y << "," << (TravelMgr::instance().isBadMmap(mapId, x, y) ? "0" : "1") + // << ","; + // printWKT(fromGridCoord(GridCoord(x, y)), out, 1, true); + // sPlayerbotAIConfig.log(fileName, out.str().c_str()); + // } + // } + // else + // { // This needs to be disabled or maps will not load. // Needs more testing to check for impact on movement. - if (false) - if (!sTravelMgr->isBadVmap(mapId, x, y)) - { - // load VMAPs for current map/grid... - const MapEntry* i_mapEntry = sMapStore.LookupEntry(mapId); - //const char* mapName = i_mapEntry ? i_mapEntry->name[sWorld->GetDefaultDbcLocale()] : "UNNAMEDMAP\x0"; //not used, (usage are commented out below), line marked for removal. - - int vmapLoadResult = VMAP::VMapFactory::createOrGetVMapMgr()->loadMap( - (sWorld->GetDataPath() + "vmaps").c_str(), mapId, x, y); - switch (vmapLoadResult) - { - case VMAP::VMAP_LOAD_RESULT_OK: - // LOG_ERROR("playerbots", "VMAP loaded name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})", - // mapName, mapId, x, y, x, y); - break; - case VMAP::VMAP_LOAD_RESULT_ERROR: - // LOG_ERROR("playerbots", "Could not load VMAP name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, - // y:{})", mapName, mapId, x, y, x, y); - sTravelMgr->addBadVmap(mapId, x, y); - break; - case VMAP::VMAP_LOAD_RESULT_IGNORED: - sTravelMgr->addBadVmap(mapId, x, y); - // LOG_INFO("playerbots", "Ignored VMAP name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})", - // mapName, mapId, x, y, x, y); - break; - } - - if (sPlayerbotAIConfig->hasLog(fileName)) - { - std::ostringstream out; - out << sPlayerbotAIConfig->GetTimestampStr(); - out << "+00,\"vmap\", " << x << "," << y << ", " << (sTravelMgr->isBadVmap(mapId, x, y) ? "0" : "1") - << ","; - printWKT(frommGridCoord(mGridCoord(x, y)), out, 1, true); - sPlayerbotAIConfig->log(fileName, out.str().c_str()); - } - } - - if (!sTravelMgr->isBadMmap(mapId, x, y)) + // if (false) + // if (!TravelMgr::instance().isBadVmap(mapId, x, y)) + // { + // // load VMAPs for current map/grid... + // const MapEntry* i_mapEntry = sMapStore.LookupEntry(mapId); + // //const char* mapName = i_mapEntry ? i_mapEntry->name[sWorld->GetDefaultDbcLocale()] : "UNNAMEDMAP\x0"; //not used, (usage are commented out below), line marked for removal. + + // int vmapLoadResult = VMAP::VMapFactory::createOrGetVMapMgr()->loadMap( + // (sWorld->GetDataPath() + "vmaps").c_str(), mapId, x, y); + // switch (vmapLoadResult) + // { + // case VMAP::VMAP_LOAD_RESULT_OK: + // // LOG_ERROR("playerbots", "VMAP loaded name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})", + // // mapName, mapId, x, y, x, y); + // break; + // case VMAP::VMAP_LOAD_RESULT_ERROR: + // // LOG_ERROR("playerbots", "Could not load VMAP name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, + // // y:{})", mapName, mapId, x, y, x, y); + // TravelMgr::instance().addBadVmap(mapId, x, y); + // break; + // case VMAP::VMAP_LOAD_RESULT_IGNORED: + // TravelMgr::instance().addBadVmap(mapId, x, y); + // // LOG_INFO("playerbots", "Ignored VMAP name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})", + // // mapName, mapId, x, y, x, y); + // break; + // } + + // if (sPlayerbotAIConfig.hasLog(fileName)) + // { + // std::ostringstream out; + // out << sPlayerbotAIConfig.GetTimestampStr(); + // out << "+00,\"vmap\", " << x << "," << y << ", " << (TravelMgr::instance().isBadVmap(mapId, x, y) ? "0" : "1") + // << ","; + // printWKT(frommGridCoord(mGridCoord(x, y)), out, 1, true); + // sPlayerbotAIConfig.log(fileName, out.str().c_str()); + // } + // } + + if (!TravelMgr::instance().isBadMmap(mapId, x, y)) { // load navmesh if (!MMAP::MMapFactory::createOrGetMMapMgr()->loadMap(mapId, x, y)) - sTravelMgr->addBadMmap(mapId, x, y); + TravelMgr::instance().addBadMmap(mapId, x, y); - if (sPlayerbotAIConfig->hasLog(fileName)) + if (sPlayerbotAIConfig.hasLog(fileName)) { std::ostringstream out; - out << sPlayerbotAIConfig->GetTimestampStr(); - out << "+00,\"mmap\", " << x << "," << y << "," << (sTravelMgr->isBadMmap(mapId, x, y) ? "0" : "1") + out << sPlayerbotAIConfig.GetTimestampStr(); + out << "+00,\"mmap\", " << x << "," << y << "," << (TravelMgr::instance().isBadMmap(mapId, x, y) ? "0" : "1") << ","; printWKT(fromGridCoord(GridCoord(x, y)), out, 1, true); - sPlayerbotAIConfig->log(fileName, out.str().c_str()); + sPlayerbotAIConfig.log(fileName, out.str().c_str()); } } - } + // } } void WorldPosition::loadMapAndVMaps(WorldPosition secondPos) @@ -733,21 +736,21 @@ std::vector WorldPosition::getPathStepFrom(WorldPosition startPos Movement::PointsArray points = path.GetPath(); PathType type = path.GetPathType(); - if (sPlayerbotAIConfig->hasLog("pathfind_attempt_point.csv")) + if (sPlayerbotAIConfig.hasLog("pathfind_attempt_point.csv")) { std::ostringstream out; out << std::fixed << std::setprecision(1); printWKT({startPos, *this}, out); - sPlayerbotAIConfig->log("pathfind_attempt_point.csv", out.str().c_str()); + sPlayerbotAIConfig.log("pathfind_attempt_point.csv", out.str().c_str()); } - if (sPlayerbotAIConfig->hasLog("pathfind_attempt.csv") && (type == PATHFIND_INCOMPLETE || type == PATHFIND_NORMAL)) + if (sPlayerbotAIConfig.hasLog("pathfind_attempt.csv") && (type == PATHFIND_INCOMPLETE || type == PATHFIND_NORMAL)) { std::ostringstream out; - out << sPlayerbotAIConfig->GetTimestampStr() << "+00,"; + out << sPlayerbotAIConfig.GetTimestampStr() << "+00,"; out << std::fixed << std::setprecision(1) << type << ","; printWKT(fromPointsArray(points), out, 1); - sPlayerbotAIConfig->log("pathfind_attempt.csv", out.str().c_str()); + sPlayerbotAIConfig.log("pathfind_attempt.csv", out.str().c_str()); } if (type == PATHFIND_INCOMPLETE || type == PATHFIND_NORMAL) @@ -796,7 +799,7 @@ std::vector WorldPosition::getPathFromPath(std::vectortargetPosRecalcDistance) + if (subPath.empty() || currentPos.distance(&subPath.back()) < sPlayerbotAIConfig.targetPosRecalcDistance) break; // Append the path excluding the start (this should be the same as the end of the startPath) @@ -1071,7 +1074,7 @@ std::vector TravelDestination::sortedPoints(WorldPosition* pos) std::vector TravelDestination::nextPoint(WorldPosition* pos, bool ignoreFull) { - return sTravelMgr->getNextPoint(pos, ignoreFull ? points : getPoints()); + return TravelMgr::instance().getNextPoint(pos, ignoreFull ? points : getPoints()); } bool TravelDestination::isFull(bool ignoreFull) @@ -1108,7 +1111,7 @@ bool QuestRelationTravelDestination::isActive(Player* bot) if (!bot->GetMap()->GetEntry()->IsWorldMap() || !bot->CanTakeQuest(questTemplate, false)) return false; - //uint32 dialogStatus = sTravelMgr->getDialogStatus(bot, entry, questTemplate); //not used, shadowed by the next declaration, line marked for removal. + //uint32 dialogStatus = TravelMgr::instance().getDialogStatus(bot, entry, questTemplate); //not used, shadowed by the next declaration, line marked for removal. if (AI_VALUE(bool, "can fight equal")) { @@ -1197,7 +1200,7 @@ bool QuestObjectiveTravelDestination::isActive(Player* bot) if (questTemplate->GetType() == QUEST_TYPE_ELITE && !AI_VALUE(bool, "can fight elite")) return false; - if (!sTravelMgr->getObjectiveStatus(bot, questTemplate, objective)) + if (!TravelMgr::instance().getObjectiveStatus(bot, questTemplate, objective)) return false; WorldPosition botPos(bot); @@ -1207,9 +1210,13 @@ bool QuestObjectiveTravelDestination::isActive(Player* bot) GuidVector targets = AI_VALUE(GuidVector, "possible targets"); for (auto& target : targets) - if (target.GetEntry() == getEntry() && target.IsCreature() && botAI->GetCreature(target) && + { + const int64_t targetEntry = target.GetEntry(); + + if (targetEntry == getEntry() && target.IsCreature() && botAI->GetCreature(target) && botAI->GetCreature(target)->IsAlive()) return true; + } return false; } @@ -1259,7 +1266,9 @@ bool RpgTravelDestination::isActive(Player* bot) for (ObjectGuid const guid : ignoreList) { - if (guid.GetEntry() == getEntry()) + const int64_t guidGetEntry = guid.GetEntry(); + + if (guidGetEntry == getEntry()) { return false; } @@ -1405,9 +1414,13 @@ bool BossTravelDestination::isActive(Player* bot) GuidVector targets = AI_VALUE(GuidVector, "possible targets"); for (auto& target : targets) - if (target.GetEntry() == getEntry() && target.IsCreature() && botAI->GetCreature(target) && + { + const int64_t targetEntry = target.GetEntry(); + + if (targetEntry == getEntry() && target.IsCreature() && botAI->GetCreature(target) && botAI->GetCreature(target)->IsAlive()) return true; + } return false; } @@ -1435,8 +1448,8 @@ TravelTarget::~TravelTarget() return; releaseVisitors(); - // sTravelMgr->botTargets.erase(std::remove(sTravelMgr->botTargets.begin(), sTravelMgr->botTargets.end(), this), - // sTravelMgr->botTargets.end()); + // TravelMgr::instance().botTargets.erase(std::remove(TravelMgr::instance().botTargets.begin(), TravelMgr::instance().botTargets.end(), this), + // TravelMgr::instance().botTargets.end()); } void TravelTarget::setTarget(TravelDestination* tDestination1, WorldPosition* wPosition1, bool groupCopy1) @@ -1509,7 +1522,7 @@ void TravelTarget::setStatus(TravelStatus status) statusTime = 1; break; case TRAVEL_STATUS_TRAVEL: - statusTime = getMaxTravelTime() * 2 + sPlayerbotAIConfig->maxWaitForMove; + statusTime = getMaxTravelTime() * 2 + sPlayerbotAIConfig.maxWaitForMove; break; case TRAVEL_STATUS_WORK: statusTime = tDestination->getExpireDelay(); @@ -1578,7 +1591,7 @@ bool TravelTarget::isTraveling() if (!botAI->HasStrategy("travel", BOT_STATE_NON_COMBAT)) { - setTarget(sTravelMgr->nullTravelDestination, sTravelMgr->nullWorldPosition, true); + setTarget(TravelMgr::instance().nullTravelDestination, TravelMgr::instance().nullWorldPosition, true); return false; } @@ -1610,7 +1623,7 @@ bool TravelTarget::isWorking() if (!botAI->HasStrategy("travel", BOT_STATE_NON_COMBAT)) { - setTarget(sTravelMgr->nullTravelDestination, sTravelMgr->nullWorldPosition, true); + setTarget(TravelMgr::instance().nullTravelDestination, TravelMgr::instance().nullWorldPosition, true); return false; } @@ -1767,7 +1780,7 @@ void TravelMgr::logQuestError(uint32 errorNr, Quest* quest, uint32 objective, ui void TravelMgr::LoadQuestTravelTable() { - if (!sTravelMgr->quests.empty()) + if (!TravelMgr::instance().quests.empty()) return; // Clearing store (for reloading case) @@ -1960,7 +1973,7 @@ void TravelMgr::LoadQuestTravelTable() bool loadQuestData = true; if (loadQuestData) { - questGuidpMap questMap = GAI_VALUE(questGuidpMap, "quest guidp map"); + questGuidpMap questMap = SharedValueContext::instance().getGlobalValue("quest guidp map")->Get(); for (auto& q : questMap) { @@ -1982,7 +1995,7 @@ void TravelMgr::LoadQuestTravelTable() if (flag & (uint32)QuestRelationFlag::questGiver) { loc = new QuestRelationTravelDestination( - questId, entry, 0, sPlayerbotAIConfig->tooCloseDistance, sPlayerbotAIConfig->sightDistance); + questId, entry, 0, sPlayerbotAIConfig.tooCloseDistance, sPlayerbotAIConfig.sightDistance); loc->setExpireDelay(5 * 60 * 1000); loc->setMaxVisitors(15, 0); container->questGivers.push_back(loc); @@ -1991,7 +2004,7 @@ void TravelMgr::LoadQuestTravelTable() if (flag & (uint32)QuestRelationFlag::questTaker) { loc = new QuestRelationTravelDestination( - questId, entry, 1, sPlayerbotAIConfig->tooCloseDistance, sPlayerbotAIConfig->sightDistance); + questId, entry, 1, sPlayerbotAIConfig.tooCloseDistance, sPlayerbotAIConfig.sightDistance); loc->setExpireDelay(5 * 60 * 1000); loc->setMaxVisitors(15, 0); container->questTakers.push_back(loc); @@ -2010,8 +2023,8 @@ void TravelMgr::LoadQuestTravelTable() objective = 3; loc = new QuestObjectiveTravelDestination(questId, entry, objective, - sPlayerbotAIConfig->tooCloseDistance, - sPlayerbotAIConfig->sightDistance); + sPlayerbotAIConfig.tooCloseDistance, + sPlayerbotAIConfig.sightDistance); loc->setExpireDelay(1 * 60 * 1000); loc->setMaxVisitors(100, 1); container->questObjectives.push_back(loc); @@ -2060,8 +2073,8 @@ void TravelMgr::LoadQuestTravelTable() int32 entry = r.type == 0 ? r.entry : r.entry * -1; - loc = new QuestRelationTravelDestination(r.questId, entry, r.role, sPlayerbotAIConfig->tooCloseDistance, - sPlayerbotAIConfig->sightDistance); loc->setExpireDelay(5 * 60 * 1000); loc->setMaxVisitors(15, 0); + loc = new QuestRelationTravelDestination(r.questId, entry, r.role, sPlayerbotAIConfig.tooCloseDistance, + sPlayerbotAIConfig.sightDistance); loc->setExpireDelay(5 * 60 * 1000); loc->setMaxVisitors(15, 0); for (auto& u : units) { @@ -2098,8 +2111,8 @@ void TravelMgr::LoadQuestTravelTable() uint32 reqEntry = quest->RequiredNpcOrGo[i]; - loc = new QuestObjectiveTravelDestination(questId, reqEntry, i, sPlayerbotAIConfig->tooCloseDistance, - sPlayerbotAIConfig->sightDistance); loc->setExpireDelay(1 * 60 * 1000); loc->setMaxVisitors(100, 1); + loc = new QuestObjectiveTravelDestination(questId, reqEntry, i, sPlayerbotAIConfig.tooCloseDistance, + sPlayerbotAIConfig.sightDistance); loc->setExpireDelay(1 * 60 * 1000); loc->setMaxVisitors(100, 1); for (auto& u : units) { @@ -2149,8 +2162,8 @@ void TravelMgr::LoadQuestTravelTable() int32 entry = l.type == 0 ? l.entry : l.entry * -1; - loc = new QuestObjectiveTravelDestination(questId, entry, i, sPlayerbotAIConfig->tooCloseDistance, - sPlayerbotAIConfig->sightDistance, l.item); loc->setExpireDelay(1 * 60 * 1000); loc->setMaxVisitors(100, 1); + loc = new QuestObjectiveTravelDestination(questId, entry, i, sPlayerbotAIConfig.tooCloseDistance, + sPlayerbotAIConfig.sightDistance, l.item); loc->setExpireDelay(1 * 60 * 1000); loc->setMaxVisitors(100, 1); for (auto& u : units) { @@ -2238,8 +2251,8 @@ void TravelMgr::LoadQuestTravelTable() { if ((cInfo->npcflag & *i) != 0) { - rLoc = new RpgTravelDestination(u.entry, sPlayerbotAIConfig->tooCloseDistance, - sPlayerbotAIConfig->sightDistance); + rLoc = new RpgTravelDestination(u.entry, sPlayerbotAIConfig.tooCloseDistance, + sPlayerbotAIConfig.sightDistance); rLoc->setExpireDelay(5 * 60 * 1000); rLoc->setMaxVisitors(15, 0); @@ -2251,8 +2264,8 @@ void TravelMgr::LoadQuestTravelTable() if (cInfo->mingold > 0) { - gLoc = new GrindTravelDestination(u.entry, sPlayerbotAIConfig->tooCloseDistance, - sPlayerbotAIConfig->sightDistance); + gLoc = new GrindTravelDestination(u.entry, sPlayerbotAIConfig.tooCloseDistance, + sPlayerbotAIConfig.sightDistance); gLoc->setExpireDelay(5 * 60 * 1000); gLoc->setMaxVisitors(100, 0); @@ -2265,8 +2278,8 @@ void TravelMgr::LoadQuestTravelTable() { std::string const nodeName = cInfo->Name; - bLoc = new BossTravelDestination(u.entry, sPlayerbotAIConfig->tooCloseDistance, - sPlayerbotAIConfig->sightDistance); + bLoc = new BossTravelDestination(u.entry, sPlayerbotAIConfig.tooCloseDistance, + sPlayerbotAIConfig.sightDistance); bLoc->setExpireDelay(5 * 60 * 1000); bLoc->setMaxVisitors(0, 0); @@ -2298,8 +2311,8 @@ void TravelMgr::LoadQuestTravelTable() if (iloc == exploreLocs.end()) { - loc = new ExploreTravelDestination(area->ID, sPlayerbotAIConfig->tooCloseDistance, - sPlayerbotAIConfig->sightDistance); + loc = new ExploreTravelDestination(area->ID, sPlayerbotAIConfig.tooCloseDistance, + sPlayerbotAIConfig.sightDistance); loc->setMaxVisitors(1000, 0); loc->setCooldownDelay(1000); loc->setExpireDelay(1000); @@ -2315,23 +2328,23 @@ void TravelMgr::LoadQuestTravelTable() } // Clear these logs files - sPlayerbotAIConfig->openLog("zones.csv", "w"); - sPlayerbotAIConfig->openLog("creatures.csv", "w"); - sPlayerbotAIConfig->openLog("gos.csv", "w"); - sPlayerbotAIConfig->openLog("bot_movement.csv", "w"); - sPlayerbotAIConfig->openLog("bot_pathfinding.csv", "w"); - sPlayerbotAIConfig->openLog("pathfind_attempt.csv", "w"); - sPlayerbotAIConfig->openLog("pathfind_attempt_point.csv", "w"); - sPlayerbotAIConfig->openLog("pathfind_result.csv", "w"); - sPlayerbotAIConfig->openLog("load_map_grid.csv", "w"); - sPlayerbotAIConfig->openLog("strategy.csv", "w"); + sPlayerbotAIConfig.openLog("zones.csv", "w"); + sPlayerbotAIConfig.openLog("creatures.csv", "w"); + sPlayerbotAIConfig.openLog("gos.csv", "w"); + sPlayerbotAIConfig.openLog("bot_movement.csv", "w"); + sPlayerbotAIConfig.openLog("bot_pathfinding.csv", "w"); + sPlayerbotAIConfig.openLog("pathfind_attempt.csv", "w"); + sPlayerbotAIConfig.openLog("pathfind_attempt_point.csv", "w"); + sPlayerbotAIConfig.openLog("pathfind_result.csv", "w"); + sPlayerbotAIConfig.openLog("load_map_grid.csv", "w"); + sPlayerbotAIConfig.openLog("strategy.csv", "w"); - sPlayerbotAIConfig->openLog("unload_grid.csv", "w"); - sPlayerbotAIConfig->openLog("unload_obj.csv", "w"); + sPlayerbotAIConfig.openLog("unload_grid.csv", "w"); + sPlayerbotAIConfig.openLog("unload_obj.csv", "w"); - sTravelNodeMap->loadNodeStore(); + TravelNodeMap::instance().loadNodeStore(); - sTravelNodeMap->generateAll(); + TravelNodeMap::instance().generateAll(); /* bool fullNavPointReload = false; @@ -2340,9 +2353,9 @@ void TravelMgr::LoadQuestTravelTable() if (!fullNavPointReload && true) TravelNodeStore::loadNodes(); - //sTravelNodeMap->loadNodeStore(); + //TravelNodeMap::instance().loadNodeStore(); - for (auto node : sTravelNodeMap->getNodes()) + for (auto node : TravelNodeMap::instance().getNodes()) { node->setLinked(true); } @@ -2384,7 +2397,7 @@ void TravelMgr::LoadQuestTravelTable() else nodeName += " flightMaster"; - sTravelNodeMap->addNode(&pos, nodeName, true, true); + TravelNodeMap::instance().addNode(&pos, nodeName, true, true); break; } @@ -2414,8 +2427,8 @@ void TravelMgr::LoadQuestTravelTable() WorldPosition startPos(startTaxiNode->map_id, startTaxiNode->x, startTaxiNode->y, startTaxiNode->z); WorldPosition endPos(endTaxiNode->map_id, endTaxiNode->x, endTaxiNode->y, endTaxiNode->z); - TravelNode* startNode = sTravelNodeMap->getNode(&startPos, nullptr, 15.0f); - TravelNode* endNode = sTravelNodeMap->getNode(&endPos, nullptr, 15.0f); + TravelNode* startNode = TravelNodeMap::instance().getNode(&startPos, nullptr, 15.0f); + TravelNode* endNode = TravelNodeMap::instance().getNode(&endPos, nullptr, 15.0f); if (!startNode || !endNode) continue; @@ -2448,7 +2461,7 @@ void TravelMgr::LoadQuestTravelTable() if (cInfo->rank == 3 || (cInfo->rank == 1 && !pos.isOverworld() && u.c == 1)) { std::string const nodeName = cInfo->Name; - sTravelNodeMap->addNode(&pos, nodeName, true, true); + TravelNodeMap::instance().addNode(&pos, nodeName, true, true); } } @@ -2475,7 +2488,7 @@ void TravelMgr::LoadQuestTravelTable() pos = WorldPosition(info->mapId, info->positionX, info->positionY, info->positionZ, info->orientation); std::string const nodeName = startNames[i] + " start"; - sTravelNodeMap->addNode(&pos, nodeName, true, true); + TravelNodeMap::instance().addNode(&pos, nodeName, true, true); } } @@ -2530,7 +2543,7 @@ void TravelMgr::LoadQuestTravelTable() if (pos.distance(&lPos) == 0) { - TravelNode* node = sTravelNodeMap->addNode(&pos, data->name, true, true, true, + TravelNode* node = TravelNodeMap::instance().addNode(&pos, data->name, true, true, true, iter.first); if (!prevNode) @@ -2566,7 +2579,7 @@ void TravelMgr::LoadQuestTravelTable() if (pos.distance(&lPos) == 0) { - TravelNode* node = sTravelNodeMap->addNode(&pos, data->name, true, true, true, + TravelNode* node = TravelNodeMap::instance().addNode(&pos, data->name, true, true, true, iter.first); if (node != prevNode) { float totalTime = (p.second->TimeSeg - timeStart) / 1000.0f; @@ -2605,7 +2618,7 @@ void TravelMgr::LoadQuestTravelTable() if (p->delay > 0) { - TravelNode* node = sTravelNodeMap->addNode(&pos, data->name, true, true, true, iter.first); + TravelNode* node = TravelNodeMap::instance().addNode(&pos, data->name, true, true, true, iter.first); if (!prevNode) { @@ -2638,7 +2651,7 @@ void TravelMgr::LoadQuestTravelTable() if (p->delay > 0) { - TravelNode* node = sTravelNodeMap->getNode(&pos, nullptr, 5.0f); + TravelNode* node = TravelNodeMap::instance().getNode(&pos, nullptr, 5.0f); if (node != prevNode) { TravelNodePath travelPath(0.1f, 0.0, (uint8) TravelNodePathType::transport, entry, @@ -2667,13 +2680,13 @@ void TravelMgr::LoadQuestTravelTable() WorldPosition pos = WorldPosition(points, WP_MEAN_CENTROID); - TravelNode* node = sTravelNodeMap->addNode(&pos, pos.getAreaName(), true, true, false); + TravelNode* node = TravelNodeMap::instance().addNode(&pos, pos.getAreaName(), true, true, false); } - LOG_INFO("playerbots", ">> Loaded {} navigation points.", sTravelNodeMap->getNodes().size()); + LOG_INFO("playerbots", ">> Loaded {} navigation points.", TravelNodeMap::instance().getNodes().size()); } - sTravelNodeMap->calcMapOffset(); + TravelNodeMap::instance().calcMapOffset(); loadMapTransfers(); */ @@ -2692,14 +2705,14 @@ void TravelMgr::LoadQuestTravelTable() //PathGenerator std::vector ppath; - uint32 cur = 0, max = sTravelNodeMap->getNodes().size(); + uint32 cur = 0, max = TravelNodeMap::instance().getNodes().size(); - for (auto& startNode : sTravelNodeMap->getNodes()) + for (auto& startNode : TravelNodeMap::instance().getNodes()) { if (!preloadReLinkFullyLinked && startNode->isLinked()) continue; - for (auto& endNode : sTravelNodeMap->getNodes()) + for (auto& endNode : TravelNodeMap::instance().getNodes()) { if (startNode == endNode) continue; @@ -2734,18 +2747,18 @@ void TravelMgr::LoadQuestTravelTable() if (preloadSubPrint && (cur * 50) / max > ((cur - 1) * 50) / max) { - sTravelNodeMap->printMap(); - sTravelNodeMap->printNodeStore(); + TravelNodeMap::instance().printMap(); + TravelNodeMap::instance().printNodeStore(); } } if (!preloadSubPrint) { - sTravelNodeMap->printNodeStore(); - sTravelNodeMap->printMap(); + TravelNodeMap::instance().printNodeStore(); + TravelNodeMap::instance().printMap(); } - LOG_INFO("playerbots", ">> Loaded paths for {} nodes.", sTravelNodeMap->getNodes().size()); + LOG_INFO("playerbots", ">> Loaded paths for {} nodes.", TravelNodeMap::instance().getNodes().size()); } bool removeLowLinkNodes = false || fullNavPointReload || storeNavPointReload; @@ -2754,7 +2767,7 @@ void TravelMgr::LoadQuestTravelTable() { std::vector goodNodes; std::vector remNodes; - for (auto& node : sTravelNodeMap->getNodes()) + for (auto& node : TravelNodeMap::instance().getNodes()) { if (!node->getPosition()->isOverworld()) continue; @@ -2774,9 +2787,9 @@ void TravelMgr::LoadQuestTravelTable() } for (auto& node : remNodes) - sTravelNodeMap->removeNode(node); + TravelNodeMap::instance().removeNode(node); - LOG_INFO("playerbots", ">> Checked {} nodes.", sTravelNodeMap->getNodes().size()); + LOG_INFO("playerbots", ">> Checked {} nodes.", TravelNodeMap::instance().getNodes().size()); } bool cleanUpNodeLinks = false || fullNavPointReload || storeNavPointReload; @@ -2786,22 +2799,22 @@ void TravelMgr::LoadQuestTravelTable() { //Routes uint32 cur = 0; - uint32 max = sTravelNodeMap->getNodes().size(); + uint32 max = TravelNodeMap::instance().getNodes().size(); //Clean up node links - for (auto& startNode : sTravelNodeMap->getNodes()) + for (auto& startNode : TravelNodeMap::instance().getNodes()) { startNode->cropUselessLinks(); cur++; if (cleanUpSubPrint && (cur * 10) / max > ((cur - 1) * 10) / max) { - sTravelNodeMap->printMap(); - sTravelNodeMap->printNodeStore(); + TravelNodeMap::instance().printMap(); + TravelNodeMap::instance().printNodeStore(); } } - LOG_INFO("playerbots", ">> Cleaned paths for {} nodes.", sTravelNodeMap->getNodes().size()); + LOG_INFO("playerbots", ">> Cleaned paths for {} nodes.", TravelNodeMap::instance().getNodes().size()); } bool reCalculateCost = false || fullNavPointReload || storeNavPointReload; @@ -2809,7 +2822,7 @@ void TravelMgr::LoadQuestTravelTable() if (reCalculateCost) { - for (auto& startNode : sTravelNodeMap->getNodes()) + for (auto& startNode : TravelNodeMap::instance().getNodes()) { for (auto& path : *startNode->getLinks()) { @@ -2825,14 +2838,14 @@ void TravelMgr::LoadQuestTravelTable() } } - LOG_INFO("playerbots", ">> Calculated pathcost for {} nodes.", sTravelNodeMap->getNodes().size()); + LOG_INFO("playerbots", ">> Calculated pathcost for {} nodes.", TravelNodeMap::instance().getNodes().size()); } bool mirrorMissingPaths = true || fullNavPointReload || storeNavPointReload; if (mirrorMissingPaths) { - for (auto& startNode : sTravelNodeMap->getNodes()) + for (auto& startNode : TravelNodeMap::instance().getNodes()) { for (auto& path : *startNode->getLinks()) { @@ -2855,16 +2868,16 @@ void TravelMgr::LoadQuestTravelTable() } } - LOG_INFO("playerbots", ">> Reversed missing paths for {} nodes.", sTravelNodeMap->getNodes().size()); + LOG_INFO("playerbots", ">> Reversed missing paths for {} nodes.", TravelNodeMap::instance().getNodes().size()); } */ - sTravelNodeMap->printMap(); - sTravelNodeMap->printNodeStore(); - sTravelNodeMap->saveNodeStore(); + TravelNodeMap::instance().printMap(); + TravelNodeMap::instance().printNodeStore(); + TravelNodeMap::instance().saveNodeStore(); // Creature/gos/zone export. - if (sPlayerbotAIConfig->hasLog("creatures.csv")) + if (sPlayerbotAIConfig.hasLog("creatures.csv")) { for (CreatureData const* cData : WorldPosition().getCreaturesNear()) { @@ -2889,11 +2902,11 @@ void TravelMgr::LoadQuestTravelTable() out << point.getAreaName() << ","; out << std::fixed; - sPlayerbotAIConfig->log("creatures.csv", out.str().c_str()); + sPlayerbotAIConfig.log("creatures.csv", out.str().c_str()); } } - if (sPlayerbotAIConfig->hasLog("vmangoslines.csv")) + if (sPlayerbotAIConfig.hasLog("vmangoslines.csv")) { uint32 mapId = 0; std::vector pos; @@ -2924,7 +2937,7 @@ void TravelMgr::LoadQuestTravelTable() WorldPosition().printWKT(pos, out, 1); out << std::fixed; - sPlayerbotAIConfig->log("vmangoslines.csv", out.str().c_str()); + sPlayerbotAIConfig.log("vmangoslines.csv", out.str().c_str()); static float const ironforgeAreaSouthLimit[] = { -7491.33f, 3093.740f, -7472.04f, -391.880f, -6366.68f, -730.100f, -6063.96f, -1411.76f, @@ -2951,7 +2964,7 @@ void TravelMgr::LoadQuestTravelTable() WorldPosition().printWKT(pos, out, 1); out << std::fixed; - sPlayerbotAIConfig->log("vmangoslines.csv", out.str().c_str()); + sPlayerbotAIConfig.log("vmangoslines.csv", out.str().c_str()); static float const stormwindAreaNorthLimit[] = { -8004.250f, 3714.110f, -8075.000f, -179.000f, -8638.000f, 169.0000f, -9044.000f, 35.00000f, @@ -2979,7 +2992,7 @@ void TravelMgr::LoadQuestTravelTable() WorldPosition().printWKT(pos, out, 1); out << std::fixed; - sPlayerbotAIConfig->log("vmangoslines.csv", out.str().c_str()); + sPlayerbotAIConfig.log("vmangoslines.csv", out.str().c_str()); static float const stormwindAreaSouthLimit[] = { -8725.3378910f, 3535.62402300f, -9525.6992190f, 910.13256800f, -9796.9531250f, 839.06958000f, @@ -3010,7 +3023,7 @@ void TravelMgr::LoadQuestTravelTable() WorldPosition().printWKT(pos, out, 1); out << std::fixed; - sPlayerbotAIConfig->log("vmangoslines.csv", out.str().c_str()); + sPlayerbotAIConfig.log("vmangoslines.csv", out.str().c_str()); mapId = 1; @@ -3044,7 +3057,7 @@ void TravelMgr::LoadQuestTravelTable() WorldPosition().printWKT(pos, out, 1); out << std::fixed; - sPlayerbotAIConfig->log("vmangoslines.csv", out.str().c_str()); + sPlayerbotAIConfig.log("vmangoslines.csv", out.str().c_str()); static float const durotarSouthLimit[] = { 2755.0f, -3766.f, 2225.0f, -3596.f, 1762.0f, -3746.f, 1564.0f, -3943.f, 1184.0f, -3915.f, 737.00f, @@ -3072,7 +3085,7 @@ void TravelMgr::LoadQuestTravelTable() WorldPosition().printWKT(pos, out, 1); out << std::fixed; - sPlayerbotAIConfig->log("vmangoslines.csv", out.str().c_str()); + sPlayerbotAIConfig.log("vmangoslines.csv", out.str().c_str()); static float const valleyoftrialsSouthLimit[] = {-324.f, -3869.f, -774.f, -3992.f, -965.f, -4290.f, -932.f, -4349.f, -828.f, -4414.f, -661.f, -4541.f, -521.f, -4582.f}; @@ -3097,7 +3110,7 @@ void TravelMgr::LoadQuestTravelTable() WorldPosition().printWKT(pos, out, 1); out << std::fixed; - sPlayerbotAIConfig->log("vmangoslines.csv", out.str().c_str()); + sPlayerbotAIConfig.log("vmangoslines.csv", out.str().c_str()); static float const middleToSouthLimit[] = { -2402.010000f, 4255.7000000f, -2475.933105f, 3199.5683590f, // Desolace @@ -3129,7 +3142,7 @@ void TravelMgr::LoadQuestTravelTable() WorldPosition().printWKT(pos, out, 1); out << std::fixed; - sPlayerbotAIConfig->log("vmangoslines.csv", out.str().c_str()); + sPlayerbotAIConfig.log("vmangoslines.csv", out.str().c_str()); static float const orgrimmarSouthLimit[] = { 2132.5076f, -3912.2478f, 1944.4298f, -3855.2583f, 1735.6906f, -3834.2417f, 1654.3671f, -3380.9902f, @@ -3157,7 +3170,7 @@ void TravelMgr::LoadQuestTravelTable() WorldPosition().printWKT(pos, out, 1); out << std::fixed; - sPlayerbotAIConfig->log("vmangoslines.csv", out.str().c_str()); + sPlayerbotAIConfig.log("vmangoslines.csv", out.str().c_str()); static float const feralasThousandNeedlesSouthLimit[] = { -6495.4995f, -4711.9810f, -6674.9995f, -4515.0019f, -6769.5717f, -4122.4272f, -6838.2651f, -3874.2792f, @@ -3187,10 +3200,10 @@ void TravelMgr::LoadQuestTravelTable() WorldPosition().printWKT(pos, out, 1); out << std::fixed; - sPlayerbotAIConfig->log("vmangoslines.csv", out.str().c_str()); + sPlayerbotAIConfig.log("vmangoslines.csv", out.str().c_str()); } - if (sPlayerbotAIConfig->hasLog("gos.csv")) + if (sPlayerbotAIConfig.hasLog("gos.csv")) { for (GameObjectData const* gData : WorldPosition().getGameObjectsNear()) { @@ -3212,11 +3225,11 @@ void TravelMgr::LoadQuestTravelTable() out << point.getAreaName() << ","; out << std::fixed; - sPlayerbotAIConfig->log("gos.csv", out.str().c_str()); + sPlayerbotAIConfig.log("gos.csv", out.str().c_str()); } } - if (sPlayerbotAIConfig->hasLog("zones.csv")) + if (sPlayerbotAIConfig.hasLog("zones.csv")) { std::unordered_map> zoneLocs; @@ -3238,7 +3251,7 @@ void TravelMgr::LoadQuestTravelTable() if (loc.second.empty()) continue; - if (!sTravelNodeMap->getMapOffset(loc.second.front().getMapId()) && loc.second.front().getMapId() != 0) + if (!TravelNodeMap::instance().getMapOffset(loc.second.front().getMapId()) && loc.second.front().getMapId() != 0) continue; std::vector points = loc.second; @@ -3266,13 +3279,13 @@ void TravelMgr::LoadQuestTravelTable() point.printWKT(points, out, 0); - sPlayerbotAIConfig->log("zones.csv", out.str().c_str()); + sPlayerbotAIConfig.log("zones.csv", out.str().c_str()); } } bool printStrategyMap = false; - if (printStrategyMap && sPlayerbotAIConfig->hasLog("strategy.csv")) + if (printStrategyMap && sPlayerbotAIConfig.hasLog("strategy.csv")) { static std::map classes; static std::map> specs; @@ -3328,7 +3341,7 @@ void TravelMgr::LoadQuestTravelTable() // Use randombot 0. std::ostringstream cout; - cout << sPlayerbotAIConfig->randomBotAccountPrefix << 0; + cout << sPlayerbotAIConfig.randomBotAccountPrefix << 0; std::string const accountName = cout.str(); LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_ACCOUNT_ID_BY_USERNAME); @@ -3416,7 +3429,7 @@ void TravelMgr::LoadQuestTravelTable() for (NextAction nextAction : defaultActions) { std::ostringstream aout; - aout << nextAction.getRelevance() << "," << nextAction.getName() + aout << nextAction.weight << "," << nextAction.factory(botAI)->getName() << ",,S:" << stratName; if (actions.find(aout.str().c_str()) != actions.end()) @@ -3445,7 +3458,7 @@ void TravelMgr::LoadQuestTravelTable() for (NextAction nextAction : nextActions) { std::ostringstream aout; - aout << nextAction.getRelevance() << "," << nextAction.getName() + aout << nextAction.weight << "," << nextAction.factory(botAI)->getName() << "," << triggerNode->getName() << "," << stratName; if (actions.find(aout.str().c_str()) != actions.end()) @@ -3502,7 +3515,7 @@ void TravelMgr::LoadQuestTravelTable() return false; }); - sPlayerbotAIConfig->log("strategy.csv", "relevance, action, trigger, strategy, classes"); + sPlayerbotAIConfig.log("strategy.csv", "relevance, action, trigger, strategy, classes"); for (auto& actionkey : actionKeys) { @@ -3607,17 +3620,17 @@ void TravelMgr::LoadQuestTravelTable() out << actionkey << "\n"; } - sPlayerbotAIConfig->log("strategy.csv", out.str().c_str()); + sPlayerbotAIConfig.log("strategy.csv", out.str().c_str()); } } /* - sPlayerbotAIConfig->openLog(7, "w"); + sPlayerbotAIConfig.openLog(7, "w"); //Zone area map REMOVE! uint32 k = 0; - for (auto& node : sTravelNodeMap->getNodes()) + for (auto& node : TravelNodeMap::instance().getNodes()) { WorldPosition* pos = node->getPosition(); //map area @@ -3642,7 +3655,7 @@ void TravelMgr::LoadQuestTravelTable() std::ostringstream out; out << std::fixed << area << "," << npos.getDisplayX() << "," << npos.getDisplayY(); - sPlayerbotAIConfig->log(7, out.str().c_str()); + sPlayerbotAIConfig.log(7, out.str().c_str()); } } k++; @@ -3653,7 +3666,7 @@ void TravelMgr::LoadQuestTravelTable() //Explore map output (REMOVE!) - sPlayerbotAIConfig->openLog(5, "w"); + sPlayerbotAIConfig.openLog(5, "w"); for (auto i : exploreLocs) { for (auto j : i.second->getPoints()) @@ -3662,7 +3675,7 @@ void TravelMgr::LoadQuestTravelTable() std::string const name = i.second->getTitle(); name.erase(remove(name.begin(), name.end(), '\"'), name.end()); out << std::fixed << std::setprecision(2) << name.c_str() << "," << i.first << "," << j->getDisplayX() << - "," << j->getDisplayY() << "," << j->getX() << "," << j->getY() << "," << j->getZ(); sPlayerbotAIConfig->log(5, + "," << j->getDisplayY() << "," << j->getX() << "," << j->getY() << "," << j->getZ(); sPlayerbotAIConfig.log(5, out.str().c_str()); } } @@ -3783,7 +3796,7 @@ uint32 TravelMgr::getDialogStatus(Player* pPlayer, int32 questgiver, Quest const // Selects a random WorldPosition from a list. Use a distance weighted distribution. std::vector TravelMgr::getNextPoint(WorldPosition* center, std::vector points, - uint32 amount) + uint32) { std::vector retVec; @@ -3897,7 +3910,7 @@ bool TravelMgr::getObjectiveStatus(Player* bot, Quest const* pQuest, uint32 obje if (bot->GetQuestStatus(questId) != QUEST_STATUS_INCOMPLETE) return false; - QuestStatusData* questStatus = sTravelMgr->getQuestStatus(bot, questId); + QuestStatusData* questStatus = TravelMgr::instance().getQuestStatus(bot, questId); uint32 reqCount = pQuest->RequiredItemCount[objective]; uint32 hasCount = questStatus->ItemCount[objective]; @@ -4037,7 +4050,7 @@ std::vector TravelMgr::getRpgTravelDestinations(Player* bot, retTravelLocations.push_back(dest); } - return std::move(retTravelLocations); + return retTravelLocations; } std::vector TravelMgr::getExploreTravelDestinations(Player* bot, bool ignoreFull, @@ -4097,7 +4110,7 @@ void TravelMgr::setNullTravelTarget(Player* player) TravelTarget* target = playerBotAI->GetAiObjectContext()->GetValue("travel target")->Get(); if (target) - target->setTarget(sTravelMgr->nullTravelDestination, sTravelMgr->nullWorldPosition, true); + target->setTarget(TravelMgr::instance().nullTravelDestination, TravelMgr::instance().nullWorldPosition, true); } void TravelMgr::addMapTransfer(WorldPosition start, WorldPosition end, float portalDistance, bool makeShortcuts) @@ -4146,7 +4159,7 @@ void TravelMgr::addMapTransfer(WorldPosition start, WorldPosition end, float por void TravelMgr::loadMapTransfers() { - for (auto& node : sTravelNodeMap->getNodes()) + for (auto& node : TravelNodeMap::instance().getNodes()) { for (auto& link : *node->getLinks()) { @@ -4233,15 +4246,15 @@ void TravelMgr::printGrid(uint32 mapId, int x, int y, std::string const type) { std::string const fileName = "unload_grid.csv"; - if (sPlayerbotAIConfig->hasLog(fileName)) + if (sPlayerbotAIConfig.hasLog(fileName)) { WorldPosition p = WorldPosition(mapId, 0, 0, 0, 0); std::ostringstream out; - out << sPlayerbotAIConfig->GetTimestampStr(); + out << sPlayerbotAIConfig.GetTimestampStr(); out << "+00, " << 0 << 0 << x << "," << y << ", " << type << ","; p.printWKT(p.fromGridCoord(GridCoord(x, y)), out, 1, true); - sPlayerbotAIConfig->log(fileName, out.str().c_str()); + sPlayerbotAIConfig.log(fileName, out.str().c_str()); } } @@ -4249,7 +4262,7 @@ void TravelMgr::printObj(WorldObject* obj, std::string const type) { std::string fileName = "unload_grid.csv"; - if (sPlayerbotAIConfig->hasLog(fileName)) + if (sPlayerbotAIConfig.hasLog(fileName)) { WorldPosition p = WorldPosition(obj); @@ -4261,40 +4274,40 @@ void TravelMgr::printObj(WorldObject* obj, std::string const type) { std::ostringstream out; - out << sPlayerbotAIConfig->GetTimestampStr(); + out << sPlayerbotAIConfig.GetTimestampStr(); out << "+00, " << obj->GetGUID().GetEntry() << "," << obj->GetGUID().GetCounter() << "," << cell.GridX() << "," << cell.GridY() << ", " << type << ","; p.printWKT(vcell, out, 1, true); - sPlayerbotAIConfig->log(fileName, out.str().c_str()); + sPlayerbotAIConfig.log(fileName, out.str().c_str()); } { std::ostringstream out; - out << sPlayerbotAIConfig->GetTimestampStr(); + out << sPlayerbotAIConfig.GetTimestampStr(); out << "+00, " << obj->GetGUID().GetEntry() << "," << obj->GetGUID().GetCounter() << "," << cell.GridX() << "," << cell.GridY() << ", " << type << ","; p.printWKT(vgrid, out, 1, true); - sPlayerbotAIConfig->log(fileName, out.str().c_str()); + sPlayerbotAIConfig.log(fileName, out.str().c_str()); } } fileName = "unload_obj.csv"; - if (sPlayerbotAIConfig->hasLog(fileName)) + if (sPlayerbotAIConfig.hasLog(fileName)) { WorldPosition p = WorldPosition(obj); Cell cell(obj->GetPositionX(), obj->GetPositionY()); { std::ostringstream out; - out << sPlayerbotAIConfig->GetTimestampStr(); + out << sPlayerbotAIConfig.GetTimestampStr(); out << "+00, " << obj->GetGUID().GetEntry() << "," << obj->GetGUID().GetCounter() << "," << cell.GridX() << "," << cell.GridY() << ", " << type << ","; p.printWKT({p}, out, 0); - sPlayerbotAIConfig->log(fileName, out.str().c_str()); + sPlayerbotAIConfig.log(fileName, out.str().c_str()); } } } diff --git a/src/Mgr/Travel/TravelMgr.h b/src/Mgr/Travel/TravelMgr.h index 39a79a4078..3223444bfe 100644 --- a/src/Mgr/Travel/TravelMgr.h +++ b/src/Mgr/Travel/TravelMgr.h @@ -10,7 +10,6 @@ #include #include "AiObject.h" -#include "Corpse.h" #include "CreatureData.h" #include "GameObject.h" #include "GridDefines.h" @@ -298,11 +297,11 @@ class WorldPosition : public WorldLocation std::vector getPathTo(WorldPosition endPos, Unit* bot) { return endPos.getPathFrom(*this, bot); } - bool isPathTo(std::vector path, float maxDistance = sPlayerbotAIConfig->targetPosRecalcDistance) + bool isPathTo(std::vector path, float maxDistance = sPlayerbotAIConfig.targetPosRecalcDistance) { return !path.empty() && distance(path.back()) < maxDistance; }; - bool cropPathTo(std::vector& path, float maxDistance = sPlayerbotAIConfig->targetPosRecalcDistance); + bool cropPathTo(std::vector& path, float maxDistance = sPlayerbotAIConfig.targetPosRecalcDistance); bool canPathTo(WorldPosition endPos, Unit* bot) { return endPos.isPathTo(getPathTo(endPos, bot)); } float getPathLength(std::vector points) @@ -848,12 +847,11 @@ class TravelTarget : AiObject class TravelMgr { public: - TravelMgr(){}; - - static TravelMgr* instance() + static TravelMgr& instance() { static TravelMgr instance; - return &instance; + + return instance; } void Clear(); @@ -922,7 +920,6 @@ class TravelMgr void printGrid(uint32 mapId, int x, int y, std::string const type); void printObj(WorldObject* obj, std::string const type); - // protected: void logQuestError(uint32 errorNr, Quest* quest, uint32 objective = 0, uint32 unitId = 0, uint32 itemId = 0); std::vector avoidLoaded; @@ -939,8 +936,16 @@ class TravelMgr std::unordered_map, std::vector, boost::hash>> mapTransfersMap; -}; -#define sTravelMgr TravelMgr::instance() +private: + TravelMgr() = default; + ~TravelMgr() = default; + + TravelMgr(const TravelMgr&) = delete; + TravelMgr& operator=(const TravelMgr&) = delete; + + TravelMgr(TravelMgr&&) = delete; + TravelMgr& operator=(TravelMgr&&) = delete; +}; #endif diff --git a/src/Mgr/Travel/TravelNode.cpp b/src/Mgr/Travel/TravelNode.cpp index d3c03ed97e..0cb88f9b11 100644 --- a/src/Mgr/Travel/TravelNode.cpp +++ b/src/Mgr/Travel/TravelNode.cpp @@ -323,7 +323,7 @@ void TravelNode::removeLinkTo(TravelNode* node, bool removePaths) else { // Remove all references to this node. - for (auto& node : sTravelNodeMap->getNodes()) + for (auto& node : TravelNodeMap::instance().getNodes()) { if (node->hasPathTo(this)) node->removeLinkTo(this, removePaths); @@ -364,7 +364,7 @@ std::vector TravelNode::getNodeMap(bool importantOnly, std::vector< } } - return std::move(closeList); + return closeList; } bool TravelNode::isUselessLink(TravelNode* farNode) @@ -397,7 +397,7 @@ bool TravelNode::isUselessLink(TravelNode* farNode) } else { - TravelNodeRoute route = sTravelNodeMap->getRoute(nearNode, farNode, nullptr); + TravelNodeRoute route = TravelNodeMap::instance().getRoute(nearNode, farNode, nullptr); if (route.isEmpty()) continue; @@ -432,7 +432,7 @@ bool TravelNode::cropUselessLinks() this->removeLinkTo(farNode); hasRemoved = true; - if (sPlayerbotAIConfig->hasLog("crop.csv")) + if (sPlayerbotAIConfig.hasLog("crop.csv")) { std::ostringstream out; out << getName() << ","; @@ -440,7 +440,7 @@ bool TravelNode::cropUselessLinks() WorldPosition().printWKT({*getPosition(), *farNode->getPosition()}, out, 1); out << std::fixed; - sPlayerbotAIConfig->log("crop.csv", out.str().c_str()); + sPlayerbotAIConfig.log("crop.csv", out.str().c_str()); } } @@ -449,7 +449,7 @@ bool TravelNode::cropUselessLinks() farNode->removeLinkTo(this); hasRemoved = true; - if (sPlayerbotAIConfig->hasLog("crop.csv")) + if (sPlayerbotAIConfig.hasLog("crop.csv")) { std::ostringstream out; out << getName() << ","; @@ -457,7 +457,7 @@ bool TravelNode::cropUselessLinks() WorldPosition().printWKT({*getPosition(), *farNode->getPosition()}, out, 1); out << std::fixed; - sPlayerbotAIConfig->log("crop.csv", out.str().c_str()); + sPlayerbotAIConfig.log("crop.csv", out.str().c_str()); } } } @@ -496,7 +496,7 @@ bool TravelNode::cropUselessLinks() } else { - TravelNodeRoute route = sTravelNodeMap->getRoute(firstNode, secondNode, false); + TravelNodeRoute route = TravelNodeMap::instance().getRoute(firstNode, secondNode, false); if (route.isEmpty()) continue; @@ -544,7 +544,7 @@ bool TravelNode::cropUselessLinks() } else { - TravelNodeRoute route = sTravelNodeMap->getRoute(firstNode, secondNode, false); + TravelNodeRoute route = TravelNodeMap::instance().getRoute(firstNode, secondNode, false); if (route.isEmpty()) continue; @@ -579,7 +579,7 @@ bool TravelNode::isEqual(TravelNode* compareNode) if (!compareNode->hasLinkTo(this)) return false; - for (auto& node : sTravelNodeMap->getNodes()) + for (auto& node : TravelNodeMap::instance().getNodes()) { if (node == this || node == compareNode) continue; @@ -611,11 +611,11 @@ void TravelNode::print([[maybe_unused]] bool printFailed) out << (isImportant() ? 1 : 0) << ","; out << mapSize; - sPlayerbotAIConfig->log("travelNodes.csv", out.str().c_str()); + sPlayerbotAIConfig.log("travelNodes.csv", out.str().c_str()); std::vector ppath; - for (auto& endNode : sTravelNodeMap->getNodes()) + for (auto& endNode : TravelNodeMap::instance().getNodes()) { if (endNode == this) continue; @@ -665,7 +665,7 @@ void TravelNode::print([[maybe_unused]] bool printFailed) out << std::to_string(path->getMaxLevelCreature()[1]) << ","; out << std::to_string(path->getMaxLevelCreature()[2]); - sPlayerbotAIConfig->log("travelPaths.csv", out.str().c_str()); + sPlayerbotAIConfig.log("travelPaths.csv", out.str().c_str()); } } } @@ -695,8 +695,8 @@ bool TravelPath::makeShortCut(WorldPosition startPos, float maxDist) totalDist += p.point.sqDistance(std::prev(&p)->point); if (curDist < - sPlayerbotAIConfig->tooCloseDistance * - sPlayerbotAIConfig->tooCloseDistance) // We are on the path. This is a good starting point + sPlayerbotAIConfig.tooCloseDistance * + sPlayerbotAIConfig.tooCloseDistance) // We are on the path. This is a good starting point { minDist = curDist; totalDist = curDist; @@ -731,11 +731,11 @@ bool TravelPath::makeShortCut(WorldPosition startPos, float maxDist) WorldPosition beginPos = newPath.begin()->point; // The old path seems to be the best. - if (beginPos.distance(firstNode) < sPlayerbotAIConfig->tooCloseDistance) + if (beginPos.distance(firstNode) < sPlayerbotAIConfig.tooCloseDistance) return false; // We are (nearly) on the new path. Just follow the rest. - if (beginPos.distance(startPos) < sPlayerbotAIConfig->tooCloseDistance) + if (beginPos.distance(startPos) < sPlayerbotAIConfig.tooCloseDistance) { fullPath = newPath; return true; @@ -891,7 +891,7 @@ WorldPosition TravelPath::getNextPoint(WorldPosition startPos, float maxDist, Tr } // We have to move far for next point. Try to make a cropped path. - if (moveDist < sPlayerbotAIConfig->targetPosRecalcDistance && std::next(startP) != ed) + if (moveDist < sPlayerbotAIConfig.targetPosRecalcDistance && std::next(startP) != ed) { // std::vector path = startPos.getPathTo(std::next(startP)->point, nullptr); // startP->point = startPos.lastInRange(path, -1, maxDist); @@ -905,7 +905,7 @@ std::ostringstream const TravelPath::print() { std::ostringstream out; - out << sPlayerbotAIConfig->GetTimestampStr(); + out << sPlayerbotAIConfig.GetTimestampStr(); out << "+00," << "1,"; out << std::fixed; @@ -1031,7 +1031,7 @@ std::ostringstream const TravelNodeRoute::print() { std::ostringstream out; - out << sPlayerbotAIConfig->GetTimestampStr(); + out << sPlayerbotAIConfig.GetTimestampStr(); out << "+00" << ",0," << "\"LINESTRING("; @@ -1046,34 +1046,6 @@ std::ostringstream const TravelNodeRoute::print() return out; } -TravelNodeMap::TravelNodeMap(TravelNodeMap* baseMap) -{ - TravelNode* newNode; - - baseMap->m_nMapMtx.lock_shared(); - - for (auto& node : baseMap->getNodes()) - { - newNode = new TravelNode(node); - - m_nodes.push_back(newNode); - } - - for (auto& node : baseMap->getNodes()) - { - newNode = getNode(node); - - for (auto& path : *node->getPaths()) - { - TravelNode* endNode = getNode(path.first); - - newNode->setPathTo(endNode, path.second); - } - } - - baseMap->m_nMapMtx.unlock_shared(); -} - TravelNode* TravelNodeMap::addNode(WorldPosition pos, std::string const preferedName, bool isImportant, bool checkDuplicate, [[maybe_unused]] bool transport, [[maybe_unused]] uint32 transportId) @@ -1163,7 +1135,7 @@ std::vector TravelNodeMap::getNodes(WorldPosition pos, float range) [pos](TravelNode* i, TravelNode* j) { return i->getPosition()->distance(pos) < j->getPosition()->distance(pos); }); - return std::move(retVec); + return retVec; } TravelNode* TravelNodeMap::getNode(WorldPosition pos, [[maybe_unused]] std::vector& ppath, Unit* bot, @@ -1178,7 +1150,7 @@ TravelNode* TravelNodeMap::getNode(WorldPosition pos, [[maybe_unused]] std::vect uint32 c = 0; - std::vector nodes = sTravelNodeMap->getNodes(pos, range); + std::vector nodes = TravelNodeMap::instance().getNodes(pos, range); for (auto& node : nodes) { if (!bot || pos.canPathTo(*node->getPosition(), bot)) @@ -1233,14 +1205,14 @@ TravelNodeRoute TravelNodeMap::getRoute(TravelNode* start, TravelNode* goal, Pla { AiObjectContext* context = botAI->GetAiObjectContext(); - TravelNode* homeNode = sTravelNodeMap->getNode(AI_VALUE(WorldPosition, "home bind"), nullptr, 10.0f); + TravelNode* homeNode = TravelNodeMap::instance().getNode(AI_VALUE(WorldPosition, "home bind"), nullptr, 10.0f); if (homeNode) { - PortalNode* portNode = (PortalNode*)sTravelNodeMap->teleportNodes[bot->GetGUID()][8690]; + PortalNode* portNode = (PortalNode*)TravelNodeMap::instance().teleportNodes[bot->GetGUID()][8690]; { portNode = new PortalNode(start); - sTravelNodeMap->teleportNodes[bot->GetGUID()][8690] = portNode; + TravelNodeMap::instance().teleportNodes[bot->GetGUID()][8690] = portNode; } portNode->SetPortal(start, homeNode, 8690); @@ -1370,7 +1342,7 @@ TravelNodeRoute TravelNodeMap::getRoute(WorldPosition startPos, WorldPosition en WorldPosition startNodePosition = *startNode->getPosition(); WorldPosition endNodePosition = *endNode->getPosition(); - float maxStartDistance = startNode->isTransport() ? 20.0f : sPlayerbotAIConfig->targetPosRecalcDistance; + float maxStartDistance = startNode->isTransport() ? 20.0f : sPlayerbotAIConfig.targetPosRecalcDistance; TravelNodeRoute route = getRoute(startNode, endNode, bot); @@ -1403,10 +1375,10 @@ TravelNodeRoute TravelNodeMap::getRoute(WorldPosition startPos, WorldPosition en if (bot && !bot->HasSpellCooldown(8690)) { startPath.clear(); - TravelNode* botNode = sTravelNodeMap->teleportNodes[bot->GetGUID()][0]; + TravelNode* botNode = TravelNodeMap::instance().teleportNodes[bot->GetGUID()][0]; { botNode = new TravelNode(startPos, "Bot Pos", false); - sTravelNodeMap->teleportNodes[bot->GetGUID()][0] = botNode; + TravelNodeMap::instance().teleportNodes[bot->GetGUID()][0] = botNode; } botNode->setPoint(startPos); @@ -1440,37 +1412,37 @@ TravelPath TravelNodeMap::getFullPath(WorldPosition startPos, WorldPosition endP //[[Node pathfinding system]] // We try to find nodes near the bot and near the end position that have a route between them. // Then bot has to move towards/along the route. - sTravelNodeMap->m_nMapMtx.lock_shared(); + TravelNodeMap::instance().m_nMapMtx.lock_shared(); // Find the route of nodes starting at a node closest to the start position and ending at a node closest to the // endposition. Also returns longPath: The path from the start position to the first node in the route. - TravelNodeRoute route = sTravelNodeMap->getRoute(startPos, endPos, beginPath, bot); + TravelNodeRoute route = TravelNodeMap::instance().getRoute(startPos, endPos, beginPath, bot); if (route.isEmpty()) return movePath; - if (sPlayerbotAIConfig->hasLog("bot_pathfinding.csv")) + if (sPlayerbotAIConfig.hasLog("bot_pathfinding.csv")) { if (botAI->HasStrategy("debug move", BOT_STATE_NON_COMBAT)) { - sPlayerbotAIConfig->openLog("bot_pathfinding.csv", "w"); - sPlayerbotAIConfig->log("bot_pathfinding.csv", route.print().str().c_str()); + sPlayerbotAIConfig.openLog("bot_pathfinding.csv", "w"); + sPlayerbotAIConfig.log("bot_pathfinding.csv", route.print().str().c_str()); } } endPath = route.getNodes().back()->getPosition()->getPathTo(endPos, nullptr); movePath = route.buildPath(beginPath, endPath); - if (sPlayerbotAIConfig->hasLog("bot_pathfinding.csv")) + if (sPlayerbotAIConfig.hasLog("bot_pathfinding.csv")) { if (botAI->HasStrategy("debug move", BOT_STATE_NON_COMBAT)) { - sPlayerbotAIConfig->openLog("bot_pathfinding.csv", "w"); - sPlayerbotAIConfig->log("bot_pathfinding.csv", movePath.print().str().c_str()); + sPlayerbotAIConfig.openLog("bot_pathfinding.csv", "w"); + sPlayerbotAIConfig.log("bot_pathfinding.csv", movePath.print().str().c_str()); } } - sTravelNodeMap->m_nMapMtx.unlock_shared(); + TravelNodeMap::instance().m_nMapMtx.unlock_shared(); return movePath; } @@ -1511,7 +1483,7 @@ TravelNode* TravelNodeMap::addZoneLinkNode(TravelNode* startNode) if (!getNode(pos, nullptr, 100.0f)) { std::string const nodeName = zoneName + " to " + newZoneName; - return sTravelNodeMap->addNode(pos, nodeName, false, true); + return TravelNodeMap::instance().addNode(pos, nodeName, false, true); } zoneName = newZoneName; @@ -1550,7 +1522,7 @@ TravelNode* TravelNodeMap::addRandomExtNode(TravelNode* startNode) WorldPosition point = path[urand(0, path.size() - 1)]; if (!getNode(point, nullptr, 100.0f)) - return sTravelNodeMap->addNode(point, startNode->getName(), false, true); + return TravelNodeMap::instance().addNode(point, startNode->getName(), false, true); } return nullptr; @@ -1606,7 +1578,7 @@ void TravelNodeMap::manageNodes(Unit* bot, bool mapFull) m_nMapMtx.unlock(); } - sTravelNodeMap->m_nMapMtx.lock_shared(); + TravelNodeMap::instance().m_nMapMtx.lock_shared(); if (!rePrint && mapFull) printMap(); @@ -1643,13 +1615,13 @@ void TravelNodeMap::generateNpcNodes() else if (cInfo->npcflag & UNIT_NPC_FLAG_SPIRITGUIDE) nodeName += " spiritguide"; - /*TravelNode* node = */ sTravelNodeMap->addNode(guidP, nodeName, true, true); //node not used, fragment marked for removal. + /*TravelNode* node = */ TravelNodeMap::instance().addNode(guidP, nodeName, true, true); //node not used, fragment marked for removal. } else if (cInfo->rank == 3) { std::string const nodeName = cInfo->Name; - sTravelNodeMap->addNode(guidP, nodeName, true, true); + TravelNodeMap::instance().addNode(guidP, nodeName, true, true); } else if (cInfo->rank == 1 && !guidP.isOverworld()) { @@ -1672,7 +1644,7 @@ void TravelNodeMap::generateNpcNodes() std::string const nodeName = cInfo->Name; - sTravelNodeMap->addNode(guidP, nodeName, true, true); + TravelNodeMap::instance().addNode(guidP, nodeName, true, true); } } @@ -1701,7 +1673,7 @@ void TravelNodeMap::generateStartNodes() std::string const nodeName = startNames[i] + " start"; - sTravelNodeMap->addNode(pos, nodeName, true, true); + TravelNodeMap::instance().addNode(pos, nodeName, true, true); break; } @@ -1733,7 +1705,7 @@ void TravelNodeMap::generateAreaTriggerNodes() else nodeName = inPos.getAreaName(false) + " portal"; - sTravelNodeMap->addNode(inPos, nodeName, true, true); + TravelNodeMap::instance().addNode(inPos, nodeName, true, true); } // Exit nodes @@ -1759,11 +1731,11 @@ void TravelNodeMap::generateAreaTriggerNodes() else nodeName = inPos.getAreaName(false) + " portal"; - //TravelNode* entryNode = sTravelNodeMap->getNode(outPos, nullptr, 20.0f); // Entry side, portal exit. //not used, line marked for removal. + //TravelNode* entryNode = TravelNodeMap::instance().getNode(outPos, nullptr, 20.0f); // Entry side, portal exit. //not used, line marked for removal. - TravelNode* outNode = sTravelNodeMap->addNode(outPos, nodeName, true, true); // Exit size, portal exit. + TravelNode* outNode = TravelNodeMap::instance().addNode(outPos, nodeName, true, true); // Exit size, portal exit. - TravelNode* inNode = sTravelNodeMap->getNode(inPos, nullptr, 5.0f); // Entry side, portal center. + TravelNode* inNode = TravelNodeMap::instance().getNode(inPos, nullptr, 5.0f); // Entry side, portal center. // Portal link from area trigger to area trigger destination. if (outNode && inNode) @@ -1826,7 +1798,7 @@ void TravelNodeMap::generateTransportNodes() if (pos.distance(&lPos) == 0) { TravelNode* node = - sTravelNodeMap->addNode(pos, data->name, true, true, true, itr.first); + TravelNodeMap::instance().addNode(pos, data->name, true, true, true, itr.first); if (!prevNode) { @@ -1866,7 +1838,7 @@ void TravelNodeMap::generateTransportNodes() if (pos.distance(&lPos) == 0) { TravelNode* node = - sTravelNodeMap->addNode(pos, data->name, true, true, true, itr.first); + TravelNodeMap::instance().addNode(pos, data->name, true, true, true, itr.first); if (node != prevNode) { if (p.second->TimeSeg < timeStart) @@ -1911,7 +1883,7 @@ void TravelNodeMap::generateTransportNodes() if (p->delay > 0) { - TravelNode* node = sTravelNodeMap->addNode(pos, data->name, true, true, true, itr.first); + TravelNode* node = TravelNodeMap::instance().addNode(pos, data->name, true, true, true, itr.first); if (!prevNode) { @@ -1946,7 +1918,7 @@ void TravelNodeMap::generateTransportNodes() if (p->delay > 0) { - TravelNode* node = sTravelNodeMap->getNode(pos, nullptr, 5.0f); + TravelNode* node = TravelNodeMap::instance().getNode(pos, nullptr, 5.0f); if (node != prevNode) { @@ -1968,7 +1940,7 @@ void TravelNodeMap::generateTransportNodes() void TravelNodeMap::generateZoneMeanNodes() { // Zone means - for (auto& loc : sTravelMgr->exploreLocs) + for (auto& loc : TravelMgr::instance().exploreLocs) { std::vector points; @@ -1981,7 +1953,7 @@ void TravelNodeMap::generateZoneMeanNodes() WorldPosition pos = WorldPosition(points, WP_MEAN_CENTROID); - /*TravelNode* node = */sTravelNodeMap->addNode(pos, pos.getAreaName(), true, true, false); //node not used, but addNode as side effect, fragment marked for removal. + /*TravelNode* node = */TravelNodeMap::instance().addNode(pos, pos.getAreaName(), true, true, false); //node not used, but addNode as side effect, fragment marked for removal. } } @@ -2006,19 +1978,19 @@ void TravelNodeMap::generateWalkPaths() std::map nodeMaps; - for (auto& startNode : sTravelNodeMap->getNodes()) + for (auto& startNode : TravelNodeMap::instance().getNodes()) { nodeMaps[startNode->getMapId()] = true; } for (auto& map : nodeMaps) { - for (auto& startNode : sTravelNodeMap->getNodes(WorldPosition(map.first, 1, 1))) + for (auto& startNode : TravelNodeMap::instance().getNodes(WorldPosition(map.first, 1, 1))) { if (startNode->isLinked()) continue; - for (auto& endNode : sTravelNodeMap->getNodes(*startNode->getPosition(), 2000.0f)) + for (auto& endNode : TravelNodeMap::instance().getNodes(*startNode->getPosition(), 2000.0f)) { if (startNode == endNode) continue; @@ -2036,7 +2008,7 @@ void TravelNodeMap::generateWalkPaths() } } - LOG_INFO("playerbots", ">> Generated paths for {} nodes.", sTravelNodeMap->getNodes().size()); + LOG_INFO("playerbots", ">> Generated paths for {} nodes.", TravelNodeMap::instance().getNodes().size()); } void TravelNodeMap::generateTaxiPaths() @@ -2066,8 +2038,8 @@ void TravelNodeMap::generateTaxiPaths() WorldPosition startPos(startTaxiNode->map_id, startTaxiNode->x, startTaxiNode->y, startTaxiNode->z); WorldPosition endPos(endTaxiNode->map_id, endTaxiNode->x, endTaxiNode->y, endTaxiNode->z); - TravelNode* startNode = sTravelNodeMap->getNode(startPos, nullptr, 15.0f); - TravelNode* endNode = sTravelNodeMap->getNode(endPos, nullptr, 15.0f); + TravelNode* startNode = TravelNodeMap::instance().getNode(startPos, nullptr, 15.0f); + TravelNode* endNode = TravelNodeMap::instance().getNode(endPos, nullptr, 15.0f); if (!startNode || !endNode) continue; @@ -2090,7 +2062,7 @@ void TravelNodeMap::removeLowNodes() { std::vector goodNodes; std::vector remNodes; - for (auto& node : sTravelNodeMap->getNodes()) + for (auto& node : TravelNodeMap::instance().getNodes()) { if (!node->getPosition()->isOverworld()) continue; @@ -2110,13 +2082,13 @@ void TravelNodeMap::removeLowNodes() } for (auto& node : remNodes) - sTravelNodeMap->removeNode(node); + TravelNodeMap::instance().removeNode(node); } void TravelNodeMap::removeUselessPaths() { // Clean up node links - for (auto& startNode : sTravelNodeMap->getNodes()) + for (auto& startNode : TravelNodeMap::instance().getNodes()) { for (auto& path : *startNode->getPaths()) if (path.second.getComplete() && startNode->hasLinkTo(path.first)) @@ -2127,7 +2099,7 @@ void TravelNodeMap::removeUselessPaths() { uint32 rem = 0; // Clean up node links - for (auto& startNode : sTravelNodeMap->getNodes()) + for (auto& startNode : TravelNodeMap::instance().getNodes()) { if (startNode->cropUselessLinks()) rem++; @@ -2146,7 +2118,7 @@ void TravelNodeMap::removeUselessPaths() void TravelNodeMap::calculatePathCosts() { - for (auto& startNode : sTravelNodeMap->getNodes()) + for (auto& startNode : TravelNodeMap::instance().getNodes()) { for (auto& path : *startNode->getLinks()) { @@ -2162,7 +2134,7 @@ void TravelNodeMap::calculatePathCosts() } } - LOG_INFO("playerbots", ">> Calculated pathcost for {} nodes.", sTravelNodeMap->getNodes().size()); + LOG_INFO("playerbots", ">> Calculated pathcost for {} nodes.", TravelNodeMap::instance().getNodes().size()); } void TravelNodeMap::generatePaths() @@ -2188,7 +2160,7 @@ void TravelNodeMap::generateAll() calcMapOffset(); LOG_INFO("playerbots", "-Generating maptransfers"); - sTravelMgr->loadMapTransfers(); + TravelMgr::instance().loadMapTransfers(); if (hasToGen || hasToFullGen) { @@ -2201,14 +2173,14 @@ void TravelNodeMap::generateAll() void TravelNodeMap::printMap() { - if (!sPlayerbotAIConfig->hasLog("travelNodes.csv") && !sPlayerbotAIConfig->hasLog("travelPaths.csv")) + if (!sPlayerbotAIConfig.hasLog("travelNodes.csv") && !sPlayerbotAIConfig.hasLog("travelPaths.csv")) return; printf("\r [Qgis] \r\x3D"); fflush(stdout); - sPlayerbotAIConfig->openLog("travelNodes.csv", "w"); - sPlayerbotAIConfig->openLog("travelPaths.csv", "w"); + sPlayerbotAIConfig.openLog("travelNodes.csv", "w"); + sPlayerbotAIConfig.openLog("travelPaths.csv", "w"); std::vector anodes = getNodes(); @@ -2224,26 +2196,26 @@ void TravelNodeMap::printNodeStore() { std::string const nodeStore = "TravelNodeStore.h"; - if (!sPlayerbotAIConfig->hasLog(nodeStore)) + if (!sPlayerbotAIConfig.hasLog(nodeStore)) return; printf("\r [Map] \r\x3D"); fflush(stdout); - sPlayerbotAIConfig->openLog(nodeStore, "w"); + sPlayerbotAIConfig.openLog(nodeStore, "w"); std::unordered_map saveNodes; std::vector anodes = getNodes(); - sPlayerbotAIConfig->log(nodeStore, "#pragma once"); - sPlayerbotAIConfig->log(nodeStore, "#include \"TravelMgr.h\""); - sPlayerbotAIConfig->log(nodeStore, "class TravelNodeStore"); - sPlayerbotAIConfig->log(nodeStore, " {"); - sPlayerbotAIConfig->log(nodeStore, " public:"); - sPlayerbotAIConfig->log(nodeStore, " static void loadNodes()"); - sPlayerbotAIConfig->log(nodeStore, " {"); - sPlayerbotAIConfig->log(nodeStore, " TravelNode** nodes = new TravelNode*[%zu];", anodes.size()); + sPlayerbotAIConfig.log(nodeStore, "#pragma once"); + sPlayerbotAIConfig.log(nodeStore, "#include \"TravelMgr.h\""); + sPlayerbotAIConfig.log(nodeStore, "class TravelNodeStore"); + sPlayerbotAIConfig.log(nodeStore, " {"); + sPlayerbotAIConfig.log(nodeStore, " public:"); + sPlayerbotAIConfig.log(nodeStore, " static void loadNodes()"); + sPlayerbotAIConfig.log(nodeStore, " {"); + sPlayerbotAIConfig.log(nodeStore, " TravelNode** nodes = new TravelNode*[%zu];", anodes.size()); for (uint32 i = 0; i < anodes.size(); i++) { @@ -2266,7 +2238,7 @@ void TravelNodeMap::printNodeStore() /* out << std::fixed << std::setprecision(2) << " nodes[" << i << "] = - sTravelNodeMap->addNode(&WorldPosition(" << node->getMapId() << "," << node->getX() << "f," << node->getY() + TravelNodeMap::instance().addNode(&WorldPosition(" << node->getMapId() << "," << node->getX() << "f," << node->getY() << "f," << node->getZ() << "f,"<< node->getO() <<"f), \"" << name << "\", " << (node->isImportant() ? "true" : "false") << ", true"; if (node->isTransport()) @@ -2274,7 +2246,7 @@ void TravelNodeMap::printNodeStore() out << ");"; */ - sPlayerbotAIConfig->log(nodeStore, out.str().c_str()); + sPlayerbotAIConfig.log(nodeStore, out.str().c_str()); saveNodes.insert(std::make_pair(node, i)); } @@ -2297,12 +2269,12 @@ void TravelNodeMap::printNodeStore() // out << std::fixed << std::setprecision(1) << " nodes[" << i << "]->setPathTo(nodes[" << // saveNodes.find(Link.first)->second << "],TravelNodePath("; out << Link.second->print() << "), true);"; - sPlayerbotAIConfig->log(nodeStore, out.str().c_str()); + sPlayerbotAIConfig.log(nodeStore, out.str().c_str()); } } - sPlayerbotAIConfig->log(nodeStore, " }"); - sPlayerbotAIConfig->log(nodeStore, "};"); + sPlayerbotAIConfig.log(nodeStore, " }"); + sPlayerbotAIConfig.log(nodeStore, "};"); printf("\r [Done] \r\x3D"); fflush(stdout); @@ -2322,7 +2294,7 @@ void TravelNodeMap::saveNodeStore() trans->Append(PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_DEL_TRAVELNODE_PATH)); std::unordered_map saveNodes; - std::vector anodes = sTravelNodeMap->getNodes(); + std::vector anodes = TravelNodeMap::instance().getNodes(); for (uint32 i = 0; i < anodes.size(); i++) { diff --git a/src/Mgr/Travel/TravelNode.h b/src/Mgr/Travel/TravelNode.h index 3a86cbb169..41419f8a97 100644 --- a/src/Mgr/Travel/TravelNode.h +++ b/src/Mgr/Travel/TravelNode.h @@ -477,13 +477,11 @@ class TravelNodeStub class TravelNodeMap { public: - TravelNodeMap(){}; - TravelNodeMap(TravelNodeMap* baseMap); - - static TravelNodeMap* instance() + static TravelNodeMap& instance() { static TravelNodeMap instance; - return &instance; + + return instance; } TravelNode* addNode(WorldPosition pos, std::string const preferedName = "Travel Node", bool isImportant = false, @@ -586,6 +584,15 @@ class TravelNodeMap std::unordered_map> teleportNodes; private: + TravelNodeMap() = default; + ~TravelNodeMap() = default; + + TravelNodeMap(const TravelNodeMap&) = delete; + TravelNodeMap& operator=(const TravelNodeMap&) = delete; + + TravelNodeMap(TravelNodeMap&&) = delete; + TravelNodeMap& operator=(TravelNodeMap&&) = delete; + std::vector m_nodes; std::vector> mapOffsets; diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index b9ef257d95..67e9bc7153 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -653,6 +653,9 @@ bool PlayerbotAIConfig::Initialize() selfBotLevel = sConfigMgr->GetOption("AiPlayerbot.SelfBotLevel", 1); + disableRandomBotPeriodicRandomization = sConfigMgr->GetOption("AiPlayerbot.DisableRandomBotPeriodicRandomization", false); + disableRandomBotPeriodicTeleportation = sConfigMgr->GetOption("AiPlayerbot.DisableRandomBotPeriodicTeleportation", false); + RandomPlayerbotFactory::CreateRandomBots(); if (World::IsStopped()) { @@ -660,25 +663,25 @@ bool PlayerbotAIConfig::Initialize() } // Assign account types after accounts are created - sRandomPlayerbotMgr->AssignAccountTypes(); + sRandomPlayerbotMgr.AssignAccountTypes(); - if (sPlayerbotAIConfig->enabled) + if (sPlayerbotAIConfig.enabled) { - sRandomPlayerbotMgr->Init(); + sRandomPlayerbotMgr.Init(); } - sPlayerbotGuildMgr->Init(); - sRandomItemMgr->Init(); - sRandomItemMgr->InitAfterAhBot(); - sPlayerbotTextMgr->LoadBotTexts(); - sPlayerbotTextMgr->LoadBotTextChance(); + PlayerbotGuildMgr::instance().Init(); + sRandomItemMgr.Init(); + sRandomItemMgr.InitAfterAhBot(); + PlayerbotTextMgr::instance().LoadBotTexts(); + PlayerbotTextMgr::instance().LoadBotTextChance(); PlayerbotFactory::Init(); AiObjectContext::BuildAllSharedContexts(); - if (sPlayerbotAIConfig->randomBotSuggestDungeons) + if (sPlayerbotAIConfig.randomBotSuggestDungeons) { - sPlayerbotDungeonRepository->LoadDungeonSuggestions(); + PlayerbotDungeonRepository::instance().LoadDungeonSuggestions(); } excludedHunterPetFamilies.clear(); @@ -898,7 +901,7 @@ std::vector> PlayerbotAIConfig::ParseTempTalentsOrder(uint32 spells[talentTabInfo->tabpage].push_back(talentInfo); } - for (int tab = 0; tab < 3; tab++) + for (uint64_t tab = 0; tab < 3; tab++) { if (tab_links.size() <= tab) { @@ -907,7 +910,8 @@ std::vector> PlayerbotAIConfig::ParseTempTalentsOrder(uint32 std::sort(spells[tab].begin(), spells[tab].end(), [&](TalentEntry const* lhs, TalentEntry const* rhs) { return lhs->Row != rhs->Row ? lhs->Row < rhs->Row : lhs->Col < rhs->Col; }); - for (int i = 0; i < tab_links[tab].size(); i++) + + for (uint64_t i = 0; i < tab_links[tab].size(); ++i) { if (i >= spells[tab].size()) { @@ -956,7 +960,8 @@ std::vector> PlayerbotAIConfig::ParseTempPetTalentsOrder(uin std::sort(spells.begin(), spells.end(), [&](TalentEntry const* lhs, TalentEntry const* rhs) { return lhs->Row != rhs->Row ? lhs->Row < rhs->Row : lhs->Col < rhs->Col; }); - for (int i = 0; i < tab_link.size(); i++) + + for (uint64_t i = 0; i < tab_link.size(); ++i) { if (i >= spells.size()) { diff --git a/src/PlayerbotAIConfig.h b/src/PlayerbotAIConfig.h index fb112fc907..0f7aa2c302 100644 --- a/src/PlayerbotAIConfig.h +++ b/src/PlayerbotAIConfig.h @@ -8,11 +8,14 @@ #include #include +#include +#include +#include +#include +#include -#include "Common.h" #include "DBCEnums.h" #include "SharedDefines.h" -#include "Talentspec.h" enum class BotCheatMask : uint32 { @@ -62,11 +65,11 @@ enum NewRpgStatus : int class PlayerbotAIConfig { public: - PlayerbotAIConfig(){}; - static PlayerbotAIConfig* instance() + static PlayerbotAIConfig& instance() { static PlayerbotAIConfig instance; - return &instance; + + return instance; } bool Initialize(); @@ -305,6 +308,9 @@ class PlayerbotAIConfig std::vector botCheats; uint32 botCheatMask = 0; + bool disableRandomBotPeriodicRandomization; + bool disableRandomBotPeriodicTeleportation; + struct worldBuff { uint32 spellId; @@ -449,6 +455,16 @@ class PlayerbotAIConfig bool IsRestrictedHealerDPSMap(uint32 mapId) const; std::vector excludedHunterPetFamilies; + +private: + PlayerbotAIConfig() = default; + ~PlayerbotAIConfig() = default; + + PlayerbotAIConfig(const PlayerbotAIConfig&) = delete; + PlayerbotAIConfig& operator=(const PlayerbotAIConfig&) = delete; + + PlayerbotAIConfig(PlayerbotAIConfig&&) = delete; + PlayerbotAIConfig& operator=(PlayerbotAIConfig&&) = delete; }; #define sPlayerbotAIConfig PlayerbotAIConfig::instance() diff --git a/src/PlayerbotTitleMgr.cpp b/src/PlayerbotTitleMgr.cpp new file mode 100644 index 0000000000..a4d32c10f5 --- /dev/null +++ b/src/PlayerbotTitleMgr.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#include // Added for gender choice + +enum Titles +{ + /** + * Classic + */ + + /** + * PvP + */ + + // Alliance + PRIVATE = 1, + CORPORAL = 2, + SERGEANT = 3, + MASTER_SERGEANT = 4, + SERGEANT_MAJOR = 5, + KNIGHT = 6, + KNIGHT_LIEUTENANT = 7, + KNIGHT_CAPTAIN = 8, + KNIGHT_CHAMPION = 9, + LIEUTENANT_COMMANDER = 10, + COMMANDER = 11, + MARSHAL = 12, + FIELD_MARSHAL = 13, + GRAND_MARSHAL = 14, + + // Horde + SCOUT = 15, + GRUNT = 16, + SERGEANT_H = 17, + SENIOR_SERGEANT = 18, + FIRST_SERGEANT = 19, + STONE_GUARD = 20, + BLOOD_GUARD = 21, + LEGIONNAIRE = 22, + CENTURION = 23, + CHAMPION = 24, + LIEUTENANT_GENERAL = 25, + GENERAL = 26, + WARLORD = 27, + HIGH_WARLORD = 28, + + /* + * PvE + */ + + SCARAB_LORD = 46, + + /** + * The Burning Crusade + */ + + /* + * PvP + */ + + // Arena + + GLADIATOR = 42, + DUELIST = 43, + RIVAL = 44, + CHALLENGER = 45, + MERCILESS_GLADIATOR = 62, + VENGEFUL_GLADIATOR = 71, + BRUTAL_GLADIATOR = 80, + + /** + * PvE + */ + + CHAMPION_OF_THE_NAARU = 53, + OF_THE_SHATTERED_SUN = 63, + HAND_OF_ADAL = 64, + + /** + * Wrath of the Lich King + */ + + /** + * PvP + */ + + BATTLEMASTER = 72, + ARENA_MASTER = 82, + + // Alliance + + JUSTICAR = 48, + + // Horde + + CONQUEROR = 47, + + /** + * Seasonal Events + */ + + ELDER = 74, + FLAME_WARDEN = 75, // Alliance + FLAME_KEEPER = 76, // Horde + + /** + * Miscellaneous + */ + + THE_EXALTED = 77, // 40 Exalted reputation + THE_EXPLORER = 78, // Explore all areas + THE_DIPLOMAT = 79, // Exalted Timbermaw, Sporeggar & Kurenai/Mag'har + THE_SEEKER = 81, // Complete 3000 quests + SALTY = 83, // Fishing + CHEF = 84, // Cooking + + /** + * Realm first + */ + + /** + * Unused + */ + + THE_SUPREME = 85, + OF_THE_TEN_STORMS = 86, + OF_THE_EMERALD_DREAM = 87, // Used in retail in Dragonflight only + PROPHET = 89, + THE_MALEFIC = 90, + STALKER = 91, // Used in retail in Warlords of Draenor only + OF_THE_EBON_BLADE = 92, + ARCHMAGE = 93, // Used in retail in Legion only + WARBRINGER = 94, // Used in retail in Legion only + ASSASSIN = 95, + GRAND_MASTER_ALCHEMIST = 96, + GRAND_MASTER_BLACKSMITH = 97, + IRON_CHEF = 98, + GRAND_MASTER_ENCHANTER = 99, + GRAND_MASTER_ENGINEER = 100, + DOCTOR = 101, + GRAND_MASTER_ANGLER = 102, + +}; + +class PlayerbotTitleMgr +{ +public: +private: +}; diff --git a/src/Script/PlayerbotCommandScript.cpp b/src/Script/PlayerbotCommandScript.cpp index 4e3c5611f2..c12ed50afa 100644 --- a/src/Script/PlayerbotCommandScript.cpp +++ b/src/Script/PlayerbotCommandScript.cpp @@ -72,37 +72,37 @@ class playerbots_commandscript : public CommandScript return GuildTaskMgr::HandleConsoleCommand(handler, args); } - static bool HandlePerfMonCommand(ChatHandler* handler, char const* args) + static bool HandlePerfMonCommand(ChatHandler*, char const* args) { if (!strcmp(args, "reset")) { - sPerfMonitor->Reset(); + sPerfMonitor.Reset(); return true; } if (!strcmp(args, "tick")) { - sPerfMonitor->PrintStats(true, false); + sPerfMonitor.PrintStats(true, false); return true; } if (!strcmp(args, "stack")) { - sPerfMonitor->PrintStats(false, true); + sPerfMonitor.PrintStats(false, true); return true; } if (!strcmp(args, "toggle")) { - sPlayerbotAIConfig->perfMonEnabled = !sPlayerbotAIConfig->perfMonEnabled; - if (sPlayerbotAIConfig->perfMonEnabled) + sPlayerbotAIConfig.perfMonEnabled = !sPlayerbotAIConfig.perfMonEnabled; + if (sPlayerbotAIConfig.perfMonEnabled) LOG_INFO("playerbots", "Performance monitor enabled"); else LOG_INFO("playerbots", "Performance monitor disabled"); return true; } - sPerfMonitor->PrintStats(); + sPerfMonitor.PrintStats(); return true; } @@ -122,7 +122,7 @@ class playerbots_commandscript : public CommandScript Player* player = handler->GetSession()->GetPlayer(); std::string key = args; - PlayerbotMgr* mgr = sPlayerbotsMgr->GetPlayerbotMgr(player); + PlayerbotMgr* mgr = PlayerbotsMgr::instance().GetPlayerbotMgr(player); if (mgr) { mgr->HandleSetSecurityKeyCommand(player, key); @@ -151,7 +151,7 @@ class playerbots_commandscript : public CommandScript Player* player = handler->GetSession()->GetPlayer(); - PlayerbotMgr* mgr = sPlayerbotsMgr->GetPlayerbotMgr(player); + PlayerbotMgr* mgr = PlayerbotsMgr::instance().GetPlayerbotMgr(player); if (mgr) { mgr->HandleLinkAccountCommand(player, accountName, key); @@ -168,7 +168,7 @@ class playerbots_commandscript : public CommandScript { Player* player = handler->GetSession()->GetPlayer(); - PlayerbotMgr* mgr = sPlayerbotsMgr->GetPlayerbotMgr(player); + PlayerbotMgr* mgr = PlayerbotsMgr::instance().GetPlayerbotMgr(player); if (mgr) { mgr->HandleViewLinkedAccountsCommand(player); @@ -195,7 +195,7 @@ class playerbots_commandscript : public CommandScript Player* player = handler->GetSession()->GetPlayer(); - PlayerbotMgr* mgr = sPlayerbotsMgr->GetPlayerbotMgr(player); + PlayerbotMgr* mgr = PlayerbotsMgr::instance().GetPlayerbotMgr(player); if (mgr) { mgr->HandleUnlinkAccountCommand(player, accountName); diff --git a/src/Script/Playerbots.cpp b/src/Script/Playerbots.cpp index 8a8e1e0b73..76e015e8c3 100644 --- a/src/Script/Playerbots.cpp +++ b/src/Script/Playerbots.cpp @@ -16,14 +16,16 @@ */ #include "Playerbots.h" +#include +#include #include "Channel.h" #include "Config.h" #include "DatabaseEnv.h" #include "DatabaseLoader.h" #include "GuildTaskMgr.h" -#include "Metric.h" #include "PlayerScript.h" +#include "GuildScript.h" #include "PlayerbotAIConfig.h" #include "PlayerbotGuildMgr.h" #include "PlayerbotSpellRepository.h" @@ -33,6 +35,11 @@ #include "PlayerbotCommandScript.h" #include "cmath" #include "BattleGroundTactics.h" +#include "PlayerGuildRegistry.h" +#include "Log.h" +#include "PlayerGuildRegistry.h" +#include "PlayerGuildRepository.h" +#include "Guild.h" class PlayerbotsDatabaseScript : public DatabaseScript { @@ -98,24 +105,24 @@ class PlayerbotsPlayerScript : public PlayerScript { if (!player->GetSession()->IsBot()) { - sPlayerbotsMgr->AddPlayerbotData(player, false); - sRandomPlayerbotMgr->OnPlayerLogin(player); + PlayerbotsMgr::instance().AddPlayerbotData(player, false); + sRandomPlayerbotMgr.OnPlayerLogin(player); // Before modifying the following messages, please make sure it does not violate the AGPLv3.0 license // especially if you are distributing a repack or hosting a public server // e.g. you can replace the URL with your own repository, // but it should be publicly accessible and include all modifications you've made - if (sPlayerbotAIConfig->enabled) + if (sPlayerbotAIConfig.enabled) { ChatHandler(player->GetSession()).SendSysMessage( "|cff00ff00This server runs with |cff00ccffmod-playerbots|r " "|cffcccccchttps://github.com/mod-playerbots/mod-playerbots|r"); } - if (sPlayerbotAIConfig->enabled || sPlayerbotAIConfig->randomBotAutologin) + if (sPlayerbotAIConfig.enabled || sPlayerbotAIConfig.randomBotAutologin) { std::string roundedTime = - std::to_string(std::ceil((sPlayerbotAIConfig->maxRandomBots * 0.11 / 60) * 10) / 10.0); + std::to_string(std::ceil((sPlayerbotAIConfig.maxRandomBots * 0.11 / 60) * 10) / 10.0); roundedTime = roundedTime.substr(0, roundedTime.find('.') + 2); ChatHandler(player->GetSession()).SendSysMessage( @@ -125,54 +132,11 @@ class PlayerbotsPlayerScript : public PlayerScript } } - bool OnPlayerBeforeTeleport(Player* /*player*/, uint32 /*mapid*/, float /*x*/, float /*y*/, float /*z*/, float /*orientation*/, uint32 /*options*/, Unit* /*target*/) override - { - /* for now commmented out until proven its actually required - * havent seen any proof CleanVisibilityReferences() is needed - - // If the player is not safe to touch, do nothing - if (!player) - return true; - - // If same map or not in world do nothing - if (!player->IsInWorld() || player->GetMapId() == mapid) - return true; - - // If real player do nothing - PlayerbotAI* ai = GET_PLAYERBOT_AI(player); - if (!ai || ai->IsRealPlayer()) - return true; - - // Cross-map bot teleport: defer visibility reference cleanup. - // CleanVisibilityReferences() erases this bot's GUID from other objects' visibility containers. - // This is intentionally done via the event queue (instead of directly here) because erasing - // from other players' visibility maps inside the teleport call stack can hit unsafe re-entrancy - // or iterator invalidation while visibility updates are in progress - ObjectGuid guid = player->GetGUID(); - player->m_Events.AddEventAtOffset( - [guid, mapid]() - { - // do nothing, if the player is not safe to touch - Player* p = ObjectAccessor::FindPlayer(guid); - if (!p || !p->IsInWorld() || p->IsDuringRemoveFromWorld()) - return; - - // do nothing if we are already on the target map - if (p->GetMapId() == mapid) - return; - - p->GetObjectVisibilityContainer().CleanVisibilityReferences(); - }, - Milliseconds(0)); - - */ - - return true; - } - void OnPlayerAfterUpdate(Player* player, uint32 diff) override { - if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player)) + PlayerbotAI* const botAI = PlayerbotsMgr::instance().GetPlayerbotAI(player); + + if (botAI != nullptr) { botAI->UpdateAI(diff); } @@ -185,19 +149,26 @@ class PlayerbotsPlayerScript : public PlayerScript bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Player* receiver) override { - if (type == CHAT_MSG_WHISPER) + if (type != CHAT_MSG_WHISPER) { - if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(receiver)) - { - botAI->HandleCommand(type, msg, player); + return true; + } - // hotfix; otherwise the server will crash when whispering logout - // https://github.com/mod-playerbots/mod-playerbots/pull/1838 - // TODO: find the root cause and solve it. (does not happen in party chat) - if (msg == "logout") - return false; - } + PlayerbotAI* const botAI = PlayerbotsMgr::instance().GetPlayerbotAI(receiver); + + if (botAI == nullptr) + { + return true; } + + botAI->HandleCommand(type, msg, player); + + // hotfix; otherwise the server will crash when whispering logout + // https://github.com/mod-playerbots/mod-playerbots/pull/1838 + // TODO: find the root cause and solve it. (does not happen in party chat) + if (msg == "logout") + return false; + return true; } @@ -205,56 +176,77 @@ class PlayerbotsPlayerScript : public PlayerScript { for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next()) { - if (Player* member = itr->GetSource()) + Player* const member = itr->GetSource(); + + if (member == nullptr) { - if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(member)) - { - botAI->HandleCommand(type, msg, player); - } + continue; + } + + PlayerbotAI* const botAI = PlayerbotsMgr::instance().GetPlayerbotAI(member); + + if (botAI == nullptr) + { + continue; } + + botAI->HandleCommand(type, msg, player); } + return true; } - bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Guild* guild) override + bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Guild*) override { - if (type == CHAT_MSG_GUILD) + if (type != CHAT_MSG_GUILD) { - if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player)) + return true; + } + + PlayerbotMgr* playerbotMgr = PlayerbotsMgr::instance().GetPlayerbotMgr(player); + + if (playerbotMgr == nullptr) + { + return true; + } + + for (PlayerBotMap::const_iterator it = playerbotMgr->GetPlayerBotsBegin(); it != playerbotMgr->GetPlayerBotsEnd(); ++it) + { + Player* const bot = it->second; + + if (bot == nullptr) { - for (PlayerBotMap::const_iterator it = playerbotMgr->GetPlayerBotsBegin(); - it != playerbotMgr->GetPlayerBotsEnd(); ++it) - { - if (Player* const bot = it->second) - { - if (bot->GetGuildId() == player->GetGuildId()) - { - GET_PLAYERBOT_AI(bot)->HandleCommand(type, msg, player); - } - } - } + continue; } + + if (bot->GetGuildId() != player->GetGuildId()) + { + continue; + } + + PlayerbotsMgr::instance().GetPlayerbotAI(bot)->HandleCommand(type, msg, player); } + return true; } bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Channel* channel) override { - if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player)) + PlayerbotMgr* const playerbotMgr = PlayerbotsMgr::instance().GetPlayerbotMgr(player); + + if (playerbotMgr != nullptr && channel->GetFlags() & 0x18) { - if (channel->GetFlags() & 0x18) - { - playerbotMgr->HandleCommand(type, msg); - } + playerbotMgr->HandleCommand(type, msg); } - sRandomPlayerbotMgr->HandleCommand(type, msg, player); + sRandomPlayerbotMgr.HandleCommand(type, msg, player); + return true; } bool OnPlayerBeforeAchievementComplete(Player* player, AchievementEntry const* achievement) override { - if ((sRandomPlayerbotMgr->IsRandomBot(player) || sRandomPlayerbotMgr->IsAddclassBot(player)) && + if ((sRandomPlayerbotMgr.IsRandomBot(player) || sRandomPlayerbotMgr.IsAddclassBot(player)) && (achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL))) { return false; @@ -266,11 +258,11 @@ class PlayerbotsPlayerScript : public PlayerScript void OnPlayerGiveXP(Player* player, uint32& amount, Unit* /*victim*/, uint8 /*xpSource*/) override { // early return - if (sPlayerbotAIConfig->randomBotXPRate == 1.0 || !player) + if (sPlayerbotAIConfig.randomBotXPRate == 1.0 || !player) return; // no XP multiplier, when player is no bot. - if (!player->GetSession()->IsBot() || !sRandomPlayerbotMgr->IsRandomBot(player)) + if (!player->GetSession()->IsBot() || !sRandomPlayerbotMgr.IsRandomBot(player)) return; // no XP multiplier, when bot is in a group with a real player. @@ -292,7 +284,7 @@ class PlayerbotsPlayerScript : public PlayerScript } // otherwise apply bot XP multiplier. - amount = static_cast(std::round(static_cast(amount) * sPlayerbotAIConfig->randomBotXPRate)); + amount = static_cast(std::round(static_cast(amount) * sPlayerbotAIConfig.randomBotXPRate)); } }; @@ -303,7 +295,9 @@ class PlayerbotsMiscScript : public MiscScript void OnDestructPlayer(Player* player) override { - if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player)) + PlayerbotAI* botAI = PlayerbotsMgr::instance().GetPlayerbotAI(player); + + if (botAI != nullptr) { delete botAI; } @@ -360,20 +354,26 @@ class PlayerbotsWorldScript : public WorldScript LOG_INFO("server.loading", " "); LOG_INFO("server.loading", "Load Playerbots Config..."); - sPlayerbotAIConfig->Initialize(); + sPlayerbotAIConfig.Initialize(); LOG_INFO("server.loading", ">> Loaded playerbots config in {} ms", GetMSTimeDiffToNow(oldMSTime)); LOG_INFO("server.loading", " "); - sPlayerbotSpellRepository->Initialize(); + PlayerbotSpellRepository::Instance().Initialize(); LOG_INFO("server.loading", "Playerbots World Thread Processor initialized"); - } + + uint32_t beforeGuildRegistryInit = getMSTime(); + + sPlayerGuildRegistry.Initialize(); + + LOG_INFO("server.loading", ">> Initialized PlayerGuildRegistry in {} ms", GetMSTimeDiffToNow(beforeGuildRegistryInit)); + } void OnUpdate(uint32 diff) override { - sPlayerbotWorldProcessor->Update(diff); - sRandomPlayerbotMgr->UpdateAI(diff); // World thread only + PlayerbotWorldThreadProcessor::instance().Update(diff); + sRandomPlayerbotMgr.UpdateAI(diff); // World thread only } }; @@ -385,10 +385,12 @@ class PlayerbotsScript : public PlayerbotScript bool OnPlayerbotCheckLFGQueue(lfg::Lfg5Guids const& guidsList) override { bool nonBotFound = false; + for (ObjectGuid const& guid : guidsList.guids) { Player* player = ObjectAccessor::FindPlayer(guid); - if (guid.IsGroup() || (player && !GET_PLAYERBOT_AI(player))) + + if (guid.IsGroup() || (player && !PlayerbotsMgr::instance().GetPlayerbotAI(player))) { nonBotFound = true; break; @@ -401,41 +403,57 @@ class PlayerbotsScript : public PlayerbotScript void OnPlayerbotCheckKillTask(Player* player, Unit* victim) override { if (player) - sGuildTaskMgr->CheckKillTask(player, victim); + GuildTaskMgr::instance().CheckKillTask(player, victim); } void OnPlayerbotCheckPetitionAccount(Player* player, bool& found) override { - if (found && GET_PLAYERBOT_AI(player)) + if (!found) + { + return; + } + + if (PlayerbotsMgr::instance().GetPlayerbotAI(player) != nullptr) + { found = false; + } } bool OnPlayerbotCheckUpdatesToSend(Player* player) override { - if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player)) - return botAI->IsRealPlayer(); + PlayerbotAI* botAI = PlayerbotsMgr::instance().GetPlayerbotAI(player); - return true; + if (botAI == nullptr) + { + return true; + } + + return botAI->IsRealPlayer(); } void OnPlayerbotPacketSent(Player* player, WorldPacket const* packet) override { - if (!player) + if (player == nullptr) + { return; + } + + PlayerbotAI* botAI = PlayerbotsMgr::instance().GetPlayerbotAI(player); - if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player)) + if (botAI != nullptr) { botAI->HandleBotOutgoingPacket(*packet); } + if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player)) { playerbotMgr->HandleMasterOutgoingPacket(*packet); } } - void OnPlayerbotUpdate(uint32 diff) override + void OnPlayerbotUpdate(uint32) override { - sRandomPlayerbotMgr->UpdateSessions(); // Per-bot updates only + sRandomPlayerbotMgr.UpdateSessions(); // Per-bot updates only } void OnPlayerbotUpdateSessions(Player* player) override @@ -449,20 +467,21 @@ class PlayerbotsScript : public PlayerbotScript { if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player)) { - PlayerbotAI* botAI = GET_PLAYERBOT_AI(player); - if (!botAI || botAI->IsRealPlayer()) + PlayerbotAI* botAI = PlayerbotsMgr::instance().GetPlayerbotAI(player); + + if (botAI == nullptr || botAI->IsRealPlayer()) { playerbotMgr->LogoutAllBots(); } } - sRandomPlayerbotMgr->OnPlayerLogout(player); + sRandomPlayerbotMgr.OnPlayerLogout(player); } void OnPlayerbotLogoutBots() override { LOG_INFO("playerbots", "Logging out all bots..."); - sRandomPlayerbotMgr->LogoutAllBots(); + sRandomPlayerbotMgr.LogoutAllBots(); } }; @@ -504,6 +523,81 @@ class PlayerBotsBGScript : public BGScript }; void AddPlayerbotsSecureLoginScripts(); +class PlayerbotsGuildScript : public GuildScript +{ + public: + + PlayerbotsGuildScript() : GuildScript("PlayerbotsGuildScript") {} + + void OnAddMember(Guild* guild, Player* player, [[maybe_unused]] uint8_t& plRank) + { + if (sRandomPlayerbotMgr.IsRandomBot(player)) + return; + + uint32_t guildId = guild->GetId(); + + if (sPlayerGuildRegistry.Contains(guildId)) + return; + + sPlayerGuildRegistry.Add(guildId); + + LOG_DEBUG("playerbots", "Added guild with id {} to PlayerGuildRegistry because it now contains a non random bot.", guildId); + } + + /** + * @brief Handles the player guilds registry maintenance when a member is removed from a guild. + * + * This hook is executed BEFORE the member is removed within the core. This method handles this properly and already handles + * the eventual change where the hook is being ran AFTER the removal making it future-proof. + */ + void OnGuildRemoveMember(Guild* guild, Player* player) + { + if (sRandomPlayerbotMgr.IsRandomBot(player)) + return; + + uint32_t guildId = guild->GetId(); + + if (!sPlayerGuildRegistry.Contains(guildId)) + return; + + // This does a non prepared database query. Since this event should be quite rare, it does not need to be overly optimised for now. + std::unordered_set memberIds = sPlayerGuildRepository.GetGuildMembersIds(guildId); + + uint64_t removedCharacterId = player->GetGUID().GetRawValue(); + + bool noNonRandomBotMember = memberIds.empty(); + bool removedPlayerWasLastNonBotMember = memberIds.size() == 1 && memberIds.find(removedCharacterId) != memberIds.end(); + + if (noNonRandomBotMember || removedPlayerWasLastNonBotMember) + { + sPlayerGuildRegistry.Remove(guildId); + } + } + + void OnGuildDisband(Guild* guild) + { + uint32_t guildId = guild->GetId(); + + if (!sPlayerGuildRegistry.Contains(guildId)) + return; + + sPlayerGuildRegistry.Remove(guildId); + } + + void OnGuildCreate(Guild* guild, [[maybe_unused]] Player* leader, [[maybe_unused]] const std::string& name) + { + uint32_t guildId = guild->GetId(); + + std::unordered_set memberIds = sPlayerGuildRepository.GetGuildMembersIds(guildId); + + bool nonRandomBotMember = !memberIds.empty(); + + if (nonRandomBotMember) + { + sPlayerGuildRegistry.Add(guildId); + } + } +}; void AddPlayerbotsScripts() { @@ -514,6 +608,7 @@ void AddPlayerbotsScripts() new PlayerbotsWorldScript(); new PlayerbotsScript(); new PlayerBotsBGScript(); + new PlayerbotsGuildScript(); AddPlayerbotsSecureLoginScripts(); AddPlayerbotsCommandscripts(); PlayerBotsGuildValidationScript(); diff --git a/src/Script/Playerbots.h b/src/Script/Playerbots.h index 72ea9e4f79..006f058f9d 100644 --- a/src/Script/Playerbots.h +++ b/src/Script/Playerbots.h @@ -27,8 +27,8 @@ int strcmpi(char const* s1, char const* s2); #define CAST_ANGLE_IN_FRONT (2.f * static_cast(M_PI) / 3.f) #define EMOTE_ANGLE_IN_FRONT (2.f * static_cast(M_PI) / 6.f) -#define GET_PLAYERBOT_AI(object) sPlayerbotsMgr->GetPlayerbotAI(object) -#define GET_PLAYERBOT_MGR(object) sPlayerbotsMgr->GetPlayerbotMgr(object) +#define GET_PLAYERBOT_AI(object) sPlayerbotsMgr.GetPlayerbotAI(object) +#define GET_PLAYERBOT_MGR(object) sPlayerbotsMgr.GetPlayerbotMgr(object) #define AI_VALUE(type, name) context->GetValue(name)->Get() #define AI_VALUE2(type, name, param) context->GetValue(name, param)->Get() @@ -43,10 +43,10 @@ int strcmpi(char const* s1, char const* s2); #define RESET_AI_VALUE(type, name) context->GetValue(name)->Reset() #define RESET_AI_VALUE2(type, name, param) context->GetValue(name, param)->Reset() -#define PAI_VALUE(type, name) sPlayerbotsMgr->GetPlayerbotAI(player)->GetAiObjectContext()->GetValue(name)->Get() +#define PAI_VALUE(type, name) sPlayerbotsMgr.GetPlayerbotAI(player)->GetAiObjectContext()->GetValue(name)->Get() #define PAI_VALUE2(type, name, param) \ - sPlayerbotsMgr->GetPlayerbotAI(player)->GetAiObjectContext()->GetValue(name, param)->Get() -#define GAI_VALUE(type, name) sSharedValueContext->getGlobalValue(name)->Get() -#define GAI_VALUE2(type, name, param) sSharedValueContext->getGlobalValue(name, param)->Get() + sPlayerbotsMgr.GetPlayerbotAI(player)->GetAiObjectContext()->GetValue(name, param)->Get() +#define GAI_VALUE(type, name) sSharedValueContext.getGlobalValue(name)->Get() +#define GAI_VALUE2(type, name, param) sSharedValueContext.getGlobalValue(name, param)->Get() #endif diff --git a/src/Script/PlayerbotsSecureLogin.cpp b/src/Script/PlayerbotsSecureLogin.cpp index aa5d103d58..fc54a82b7d 100644 --- a/src/Script/PlayerbotsSecureLogin.cpp +++ b/src/Script/PlayerbotsSecureLogin.cpp @@ -29,6 +29,7 @@ namespace return; PlayerbotAI* ai = GET_PLAYERBOT_AI(target); + if (!ai) return; @@ -41,11 +42,7 @@ namespace } } - if (sRandomPlayerbotMgr) - { - sRandomPlayerbotMgr->LogoutPlayerBot(target->GetGUID()); - return; - } + sRandomPlayerbotMgr.LogoutPlayerBot(target->GetGUID()); } } diff --git a/src/Script/WorldThr/PlayerbotOperations.h b/src/Script/WorldThr/PlayerbotOperations.h index cd8851902c..91940b6da7 100644 --- a/src/Script/WorldThr/PlayerbotOperations.h +++ b/src/Script/WorldThr/PlayerbotOperations.h @@ -355,7 +355,7 @@ class ArenaGroupFormationOperation : public PlayerbotOperation if (!member || !newGroup->IsMember(memberGuid)) continue; - PlayerbotAI* memberBotAI = sPlayerbotsMgr->GetPlayerbotAI(member); + PlayerbotAI* memberBotAI = PlayerbotsMgr::instance().GetPlayerbotAI(member); if (memberBotAI) memberBotAI->Reset(); @@ -412,13 +412,13 @@ class BotLogoutGroupCleanupOperation : public PlayerbotOperation if (!bot) return false; - PlayerbotAI* botAI = sPlayerbotsMgr->GetPlayerbotAI(bot); + PlayerbotAI* botAI = PlayerbotsMgr::instance().GetPlayerbotAI(bot); if (!botAI) return false; Group* group = bot->GetGroup(); if (group && !bot->InBattleground() && !bot->InBattlegroundQueue() && botAI->HasActivePlayerMaster()) - sPlayerbotRepository->Save(botAI); + PlayerbotRepository::instance().Save(botAI); return true; } @@ -448,7 +448,7 @@ class AddPlayerBotOperation : public PlayerbotOperation bool Execute() override { - sRandomPlayerbotMgr->AddPlayerBot(m_botGuid, m_masterAccountId); + sRandomPlayerbotMgr.AddPlayerBot(m_botGuid, m_masterAccountId); return true; } @@ -479,23 +479,35 @@ class OnBotLoginOperation : public PlayerbotOperation bool Execute() override { // find and verify bot still exists - Player* bot = ObjectAccessor::FindConnectedPlayer(m_botGuid); + Player* bot = ObjectAccessor::FindConnectedPlayer(this->m_botGuid); + if (!bot) + { return false; + } - PlayerbotHolder* holder = sRandomPlayerbotMgr; - if (m_masterAccountId) + if (this->m_masterAccountId) { - WorldSession* masterSession = sWorldSessionMgr->FindSession(m_masterAccountId); + WorldSession* masterSession = sWorldSessionMgr->FindSession(this->m_masterAccountId); Player* masterPlayer = masterSession ? masterSession->GetPlayer() : nullptr; - if (masterPlayer) - holder = GET_PLAYERBOT_MGR(masterPlayer); + + if (masterPlayer != nullptr) + { + PlayerbotMgr* manager = PlayerbotsMgr::instance().GetPlayerbotMgr(masterPlayer); + + if (manager == nullptr) + { + return false; + } + + manager->OnBotLogin(bot); + + return true; + } } - if (!holder) - return false; + sRandomPlayerbotMgr.OnBotLogin(bot); - holder->OnBotLogin(bot); return true; } diff --git a/src/Script/WorldThr/PlayerbotWorldThreadProcessor.cpp b/src/Script/WorldThr/PlayerbotWorldThreadProcessor.cpp index c776eb1207..f84bf62174 100644 --- a/src/Script/WorldThr/PlayerbotWorldThreadProcessor.cpp +++ b/src/Script/WorldThr/PlayerbotWorldThreadProcessor.cpp @@ -3,27 +3,13 @@ * and/or modify it under version 3 of the License, or (at your option), any later version. */ -#include "PlayerbotWorldThreadProcessor.h" - -#include "Log.h" -#include "PlayerbotAIConfig.h" - #include -PlayerbotWorldThreadProcessor::PlayerbotWorldThreadProcessor() - : m_enabled(true), m_maxQueueSize(10000), m_batchSize(100), m_queueWarningThreshold(80), - m_timeSinceLastUpdate(0), m_updateInterval(50) // Process at least every 50ms -{ - LOG_INFO("playerbots", "PlayerbotWorldThreadProcessor initialized"); -} +#include "PlayerbotWorldThreadProcessor.h" -PlayerbotWorldThreadProcessor::~PlayerbotWorldThreadProcessor() { ClearQueue(); } +#include "Timer.h" +#include "Log.h" -PlayerbotWorldThreadProcessor* PlayerbotWorldThreadProcessor::instance() -{ - static PlayerbotWorldThreadProcessor instance; - return &instance; -} void PlayerbotWorldThreadProcessor::Update(uint32 diff) { diff --git a/src/Script/WorldThr/PlayerbotWorldThreadProcessor.h b/src/Script/WorldThr/PlayerbotWorldThreadProcessor.h index e37d2b5ba5..94b91b97ba 100644 --- a/src/Script/WorldThr/PlayerbotWorldThreadProcessor.h +++ b/src/Script/WorldThr/PlayerbotWorldThreadProcessor.h @@ -6,13 +6,15 @@ #ifndef _PLAYERBOT_WORLD_THREAD_PROCESSOR_H #define _PLAYERBOT_WORLD_THREAD_PROCESSOR_H -#include "Common.h" -#include "PlayerbotOperation.h" - #include #include #include +#include "Log.h" + +#include "PlayerbotOperation.h" + + /** * @brief Processes thread-unsafe bot operations in the world thread * @@ -28,15 +30,17 @@ * * Usage: * auto op = std::make_unique(botGuid, params); - * sPlayerbotWorldProcessor->QueueOperation(std::move(op)); + * PlayerbotWorldThreadProcessor::instance().QueueOperation(std::move(op)); */ class PlayerbotWorldThreadProcessor { public: - PlayerbotWorldThreadProcessor(); - ~PlayerbotWorldThreadProcessor(); + static PlayerbotWorldThreadProcessor& instance() + { + static PlayerbotWorldThreadProcessor instance; - static PlayerbotWorldThreadProcessor* instance(); + return instance; + } /** * @brief Update and process queued operations (called from world thread) @@ -103,6 +107,21 @@ class PlayerbotWorldThreadProcessor bool IsEnabled() const { return m_enabled; } private: + PlayerbotWorldThreadProcessor() + : m_enabled(true), + m_maxQueueSize(10000), + m_batchSize(100), + m_queueWarningThreshold(80), + m_timeSinceLastUpdate(0), + m_updateInterval(50) // Process at least every 50ms + { + LOG_INFO("playerbots", "PlayerbotWorldThreadProcessor initialized"); + } + ~PlayerbotWorldThreadProcessor() + { + this->ClearQueue(); + } + /** * @brief Process a single batch of operations * @@ -137,6 +156,4 @@ class PlayerbotWorldThreadProcessor uint32 m_updateInterval; // Minimum ms between updates }; -#define sPlayerbotWorldProcessor PlayerbotWorldThreadProcessor::instance() - #endif diff --git a/src/Script/WorldThr/Queue.cpp b/src/Script/WorldThr/Queue.cpp index 136e1b4381..12bf806efe 100644 --- a/src/Script/WorldThr/Queue.cpp +++ b/src/Script/WorldThr/Queue.cpp @@ -4,8 +4,6 @@ */ #include "Queue.h" -#include "AiObjectContext.h" -#include "Log.h" #include "PlayerbotAIConfig.h" void Queue::Push(ActionBasket* action) @@ -17,7 +15,7 @@ void Queue::Push(ActionBasket* action) for (ActionBasket* basket : actions) { - if (action->getAction()->getName() == basket->getAction()->getName()) + if (action->getAction()->getAction().getName() == basket->getAction()->getAction().getName()) { updateExistingBasket(basket, action); return; @@ -50,7 +48,7 @@ uint32 Queue::Size() void Queue::RemoveExpired() { - if (!sPlayerbotAIConfig->expireActionTime) + if (!sPlayerbotAIConfig.expireActionTime) { return; } @@ -113,7 +111,7 @@ ActionNode* Queue::extractAndDeleteBasket(ActionBasket* basket) void Queue::collectExpiredBaskets(std::list& expiredBaskets) { - uint32 expiryTime = sPlayerbotAIConfig->expireActionTime; + uint32 expiryTime = sPlayerbotAIConfig.expireActionTime; for (ActionBasket* basket : actions) { if (basket->isExpired(expiryTime)) diff --git a/src/Script/WorldThr/Queue.h b/src/Script/WorldThr/Queue.h index b8a486dc85..fe12597439 100644 --- a/src/Script/WorldThr/Queue.h +++ b/src/Script/WorldThr/Queue.h @@ -6,8 +6,7 @@ #ifndef PLAYERBOT_QUEUE_H #define PLAYERBOT_QUEUE_H -#include "Action.h" -#include "Common.h" +#include "ActionBasket.h" /** * @class Queue @@ -56,7 +55,7 @@ class Queue /** * @brief Removes and deletes expired actions from the queue * - * Uses sPlayerbotAIConfig->expireActionTime to determine if actions have expired. + * Uses sPlayerbotAIConfig.expireActionTime to determine if actions have expired. * Both the ActionNode and ActionBasket are deleted for expired actions. */ void RemoveExpired(); diff --git a/src/Util/BroadcastHelper.cpp b/src/Util/BroadcastHelper.cpp index 19979d3d9f..246344bdaf 100644 --- a/src/Util/BroadcastHelper.cpp +++ b/src/Util/BroadcastHelper.cpp @@ -28,29 +28,29 @@ bool BroadcastHelper::BroadcastTest(PlayerbotAI* ai, Player* /* bot */) int32 rand = urand(0, 1); - if (rand == 1 && ai->SayToChannel(BOT_TEXT2("Posted to trade, %rand1, %rand2, %rand3", placeholders), ChatChannelId::TRADE)) + if (rand == 1 && ai->SayToChannel(PlayerbotTextMgr::instance().GetBotText("Posted to trade, %rand1, %rand2, %rand3", placeholders), ChatChannelId::TRADE)) return true; - else if (ai->SayToChannel(BOT_TEXT2("Posted to GuildRecruitment, %rand1, %rand2, %rand3", placeholders), ChatChannelId::GUILD_RECRUITMENT)) + else if (ai->SayToChannel(PlayerbotTextMgr::instance().GetBotText("Posted to GuildRecruitment, %rand1, %rand2, %rand3", placeholders), ChatChannelId::GUILD_RECRUITMENT)) return true; - return ai->SayToChannel(BOT_TEXT2("Posted to trade, %rand1, %rand2, %rand3", placeholders), ChatChannelId::TRADE); + return ai->SayToChannel(PlayerbotTextMgr::instance().GetBotText("Posted to trade, %rand1, %rand2, %rand3", placeholders), ChatChannelId::TRADE); //int32 rand = urand(1, 8); - if (rand == 1 && ai->SayToGuild(BOT_TEXT2("Posted to guild, %rand1, %rand2, %rand3", placeholders))) + if (rand == 1 && ai->SayToGuild(PlayerbotTextMgr::instance().GetBotText("Posted to guild, %rand1, %rand2, %rand3", placeholders))) return true; - else if (rand == 2 && ai->SayToWorld(BOT_TEXT2("Posted to world, %rand1, %rand2, %rand3", placeholders))) + else if (rand == 2 && ai->SayToWorld(PlayerbotTextMgr::instance().GetBotText("Posted to world, %rand1, %rand2, %rand3", placeholders))) return true; - else if (rand == 3 && ai->SayToChannel(BOT_TEXT2("Posted to general, %rand1, %rand2, %rand3", placeholders), ChatChannelId::GENERAL)) + else if (rand == 3 && ai->SayToChannel(PlayerbotTextMgr::instance().GetBotText("Posted to general, %rand1, %rand2, %rand3", placeholders), ChatChannelId::GENERAL)) return true; - else if (rand == 4 && ai->SayToChannel(BOT_TEXT2("Posted to trade, %rand1, %rand2, %rand3", placeholders), ChatChannelId::TRADE)) + else if (rand == 4 && ai->SayToChannel(PlayerbotTextMgr::instance().GetBotText("Posted to trade, %rand1, %rand2, %rand3", placeholders), ChatChannelId::TRADE)) return true; - else if (rand == 5 && ai->SayToChannel(BOT_TEXT2("Posted to LFG, %rand1, %rand2, %rand3", placeholders), ChatChannelId::LOOKING_FOR_GROUP)) + else if (rand == 5 && ai->SayToChannel(PlayerbotTextMgr::instance().GetBotText("Posted to LFG, %rand1, %rand2, %rand3", placeholders), ChatChannelId::LOOKING_FOR_GROUP)) return true; - else if (rand == 6 && ai->SayToChannel(BOT_TEXT2("Posted to LocalDefense, %rand1, %rand2, %rand3", placeholders), ChatChannelId::LOCAL_DEFENSE)) + else if (rand == 6 && ai->SayToChannel(PlayerbotTextMgr::instance().GetBotText("Posted to LocalDefense, %rand1, %rand2, %rand3", placeholders), ChatChannelId::LOCAL_DEFENSE)) return true; - else if (rand == 7 && ai->SayToChannel(BOT_TEXT2("Posted to WorldDefense, %rand1, %rand2, %rand3", placeholders), ChatChannelId::WORLD_DEFENSE)) + else if (rand == 7 && ai->SayToChannel(PlayerbotTextMgr::instance().GetBotText("Posted to WorldDefense, %rand1, %rand2, %rand3", placeholders), ChatChannelId::WORLD_DEFENSE)) return true; - else if (rand == 8 && ai->SayToChannel(BOT_TEXT2("Posted to GuildRecruitment, %rand1, %rand2, %rand3", placeholders), ChatChannelId::GUILD_RECRUITMENT)) + else if (rand == 8 && ai->SayToChannel(PlayerbotTextMgr::instance().GetBotText("Posted to GuildRecruitment, %rand1, %rand2, %rand3", placeholders), ChatChannelId::GUILD_RECRUITMENT)) return true; return false; @@ -63,7 +63,7 @@ bool BroadcastHelper::BroadcastTest(PlayerbotAI* ai, Player* /* bot */) */ bool BroadcastHelper::BroadcastToChannelWithGlobalChance(PlayerbotAI* ai, std::string message, std::list> toChannels) { - if (!sPlayerbotAIConfig->enableBroadcasts) + if (!sPlayerbotAIConfig.enableBroadcasts) return false; if (message.empty()) { @@ -74,14 +74,14 @@ bool BroadcastHelper::BroadcastToChannelWithGlobalChance(PlayerbotAI* ai, std::s { uint32 roll = urand(1, 100); uint32 chance = pair.second; - uint32 broadcastRoll = urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue); + uint32 broadcastRoll = urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue); switch (pair.first) { case TO_GUILD: { if (roll <= chance - && broadcastRoll <= sPlayerbotAIConfig->broadcastToGuildGlobalChance + && broadcastRoll <= sPlayerbotAIConfig.broadcastToGuildGlobalChance && ai->SayToGuild(message)) { return true; @@ -91,7 +91,7 @@ bool BroadcastHelper::BroadcastToChannelWithGlobalChance(PlayerbotAI* ai, std::s case TO_WORLD: { if (roll <= chance - && broadcastRoll <= sPlayerbotAIConfig->broadcastToWorldGlobalChance + && broadcastRoll <= sPlayerbotAIConfig.broadcastToWorldGlobalChance && ai->SayToWorld(message)) { return true; @@ -101,7 +101,7 @@ bool BroadcastHelper::BroadcastToChannelWithGlobalChance(PlayerbotAI* ai, std::s case TO_GENERAL: { if (roll <= chance - && broadcastRoll <= sPlayerbotAIConfig->broadcastToGeneralGlobalChance + && broadcastRoll <= sPlayerbotAIConfig.broadcastToGeneralGlobalChance && ai->SayToChannel(message, ChatChannelId::GENERAL)) { return true; @@ -111,7 +111,7 @@ bool BroadcastHelper::BroadcastToChannelWithGlobalChance(PlayerbotAI* ai, std::s case TO_TRADE: { if (roll <= chance - && broadcastRoll <= sPlayerbotAIConfig->broadcastToTradeGlobalChance + && broadcastRoll <= sPlayerbotAIConfig.broadcastToTradeGlobalChance && ai->SayToChannel(message, ChatChannelId::TRADE)) { return true; @@ -121,7 +121,7 @@ bool BroadcastHelper::BroadcastToChannelWithGlobalChance(PlayerbotAI* ai, std::s case TO_LOOKING_FOR_GROUP: { if (roll <= chance - && broadcastRoll <= sPlayerbotAIConfig->broadcastToLFGGlobalChance + && broadcastRoll <= sPlayerbotAIConfig.broadcastToLFGGlobalChance && ai->SayToChannel(message, ChatChannelId::LOOKING_FOR_GROUP)) { return true; @@ -131,7 +131,7 @@ bool BroadcastHelper::BroadcastToChannelWithGlobalChance(PlayerbotAI* ai, std::s case TO_LOCAL_DEFENSE: { if (roll <= chance - && broadcastRoll <= sPlayerbotAIConfig->broadcastToLocalDefenseGlobalChance + && broadcastRoll <= sPlayerbotAIConfig.broadcastToLocalDefenseGlobalChance && ai->SayToChannel(message, ChatChannelId::LOCAL_DEFENSE)) { return true; @@ -141,7 +141,7 @@ bool BroadcastHelper::BroadcastToChannelWithGlobalChance(PlayerbotAI* ai, std::s case TO_WORLD_DEFENSE: { if (roll <= chance - && broadcastRoll <= sPlayerbotAIConfig->broadcastToWorldDefenseGlobalChance + && broadcastRoll <= sPlayerbotAIConfig.broadcastToWorldDefenseGlobalChance && ai->SayToChannel(message, ChatChannelId::WORLD_DEFENSE)) { return true; @@ -151,7 +151,7 @@ bool BroadcastHelper::BroadcastToChannelWithGlobalChance(PlayerbotAI* ai, std::s case TO_GUILD_RECRUITMENT: { if (roll <= chance - && broadcastRoll <= sPlayerbotAIConfig->broadcastToGuildRecruitmentGlobalChance + && broadcastRoll <= sPlayerbotAIConfig.broadcastToGuildRecruitmentGlobalChance && ai->SayToChannel(message, ChatChannelId::GUILD_RECRUITMENT)) { return true; @@ -168,14 +168,14 @@ bool BroadcastHelper::BroadcastToChannelWithGlobalChance(PlayerbotAI* ai, std::s bool BroadcastHelper::BroadcastLootingItem(PlayerbotAI* ai, Player* bot, ItemTemplate const* proto) { - if (!sPlayerbotAIConfig->enableBroadcasts) + if (!sPlayerbotAIConfig.enableBroadcasts) return false; std::map placeholders; placeholders["%item_link"] = ai->GetChatHelper()->FormatItem(proto); AreaTableEntry const* current_area = ai->GetCurrentArea(); AreaTableEntry const* current_zone = ai->GetCurrentZone(); - placeholders["%area_name"] = current_area ? ai->GetLocalizedAreaName(current_area) : BOT_TEXT1("string_unknown_area"); - placeholders["%zone_name"] = current_zone ? ai->GetLocalizedAreaName(current_zone) : BOT_TEXT1("string_unknown_area"); + placeholders["%area_name"] = current_area ? ai->GetLocalizedAreaName(current_area) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); + placeholders["%zone_name"] = current_zone ? ai->GetLocalizedAreaName(current_zone) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); placeholders["%my_class"] = ai->GetChatHelper()->FormatClass(bot->getClass()); placeholders["%my_race"] = ai->GetChatHelper()->FormatRace(bot->getRace()); placeholders["%my_level"] = std::to_string(bot->GetLevel()); @@ -183,71 +183,71 @@ bool BroadcastHelper::BroadcastLootingItem(PlayerbotAI* ai, Player* bot, ItemTem switch (proto->Quality) { case ITEM_QUALITY_POOR: - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceLootingItemPoor) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceLootingItemPoor) { return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("broadcast_looting_item_poor", placeholders), + PlayerbotTextMgr::instance().GetBotText("broadcast_looting_item_poor", placeholders), { {TO_GUILD, 50}, {TO_WORLD, 50}, {TO_GENERAL, 100} } ); } break; case ITEM_QUALITY_NORMAL: - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceLootingItemNormal) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceLootingItemNormal) { return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("broadcast_looting_item_normal", placeholders), + PlayerbotTextMgr::instance().GetBotText("broadcast_looting_item_normal", placeholders), { {TO_GUILD, 50}, {TO_WORLD, 50}, {TO_GENERAL, 100} } ); } break; case ITEM_QUALITY_UNCOMMON: - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceLootingItemUncommon) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceLootingItemUncommon) { return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("broadcast_looting_item_uncommon", placeholders), + PlayerbotTextMgr::instance().GetBotText("broadcast_looting_item_uncommon", placeholders), { {TO_GUILD, 50}, {TO_WORLD, 50}, {TO_GENERAL, 100} } ); } break; case ITEM_QUALITY_RARE: - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceLootingItemRare) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceLootingItemRare) { return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("broadcast_looting_item_rare", placeholders), + PlayerbotTextMgr::instance().GetBotText("broadcast_looting_item_rare", placeholders), { {TO_GUILD, 50}, {TO_WORLD, 50}, {TO_GENERAL, 100} } ); } break; case ITEM_QUALITY_EPIC: - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceLootingItemEpic) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceLootingItemEpic) { return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("broadcast_looting_item_epic", placeholders), + PlayerbotTextMgr::instance().GetBotText("broadcast_looting_item_epic", placeholders), { {TO_GUILD, 50}, {TO_WORLD, 50}, {TO_GENERAL, 100} } ); } break; case ITEM_QUALITY_LEGENDARY: - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceLootingItemLegendary) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceLootingItemLegendary) { return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("broadcast_looting_item_legendary", placeholders), + PlayerbotTextMgr::instance().GetBotText("broadcast_looting_item_legendary", placeholders), { {TO_GUILD, 50}, {TO_WORLD, 50}, {TO_GENERAL, 100} } ); } break; case ITEM_QUALITY_ARTIFACT: - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceLootingItemArtifact) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceLootingItemArtifact) { return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("broadcast_looting_item_artifact", placeholders), + PlayerbotTextMgr::instance().GetBotText("broadcast_looting_item_artifact", placeholders), { {TO_GUILD, 50}, {TO_WORLD, 50}, {TO_GENERAL, 100} } ); } @@ -261,23 +261,23 @@ bool BroadcastHelper::BroadcastLootingItem(PlayerbotAI* ai, Player* bot, ItemTem bool BroadcastHelper::BroadcastQuestAccepted(PlayerbotAI* ai, Player* bot, const Quest* quest) { - if (!sPlayerbotAIConfig->enableBroadcasts) + if (!sPlayerbotAIConfig.enableBroadcasts) return false; - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceQuestAccepted) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceQuestAccepted) { std::map placeholders; placeholders["%quest_link"] = ai->GetChatHelper()->FormatQuest(quest); AreaTableEntry const* current_area = ai->GetCurrentArea(); AreaTableEntry const* current_zone = ai->GetCurrentZone(); - placeholders["%area_name"] = current_area ? ai->GetLocalizedAreaName(current_area) : BOT_TEXT1("string_unknown_area"); - placeholders["%zone_name"] = current_zone ? ai->GetLocalizedAreaName(current_zone) : BOT_TEXT1("string_unknown_area"); + placeholders["%area_name"] = current_area ? ai->GetLocalizedAreaName(current_area) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); + placeholders["%zone_name"] = current_zone ? ai->GetLocalizedAreaName(current_zone) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); placeholders["%my_class"] = ai->GetChatHelper()->FormatClass(bot->getClass()); placeholders["%my_race"] = ai->GetChatHelper()->FormatRace(bot->getRace()); placeholders["%my_level"] = std::to_string(bot->GetLevel()); return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("broadcast_quest_accepted_generic", placeholders), + PlayerbotTextMgr::instance().GetBotText("broadcast_quest_accepted_generic", placeholders), { {TO_GUILD, 50}, {TO_WORLD, 50}, {TO_GENERAL, 100} } ); } @@ -287,13 +287,13 @@ bool BroadcastHelper::BroadcastQuestAccepted(PlayerbotAI* ai, Player* bot, const bool BroadcastHelper::BroadcastQuestUpdateAddKill(PlayerbotAI* ai, Player* bot, Quest const* quest, uint32 availableCount, uint32 requiredCount, std::string obectiveName) { - if (!sPlayerbotAIConfig->enableBroadcasts) + if (!sPlayerbotAIConfig.enableBroadcasts) return false; std::map placeholders; AreaTableEntry const* current_area = ai->GetCurrentArea(); AreaTableEntry const* current_zone = ai->GetCurrentZone(); - placeholders["%area_name"] = current_area ? ai->GetLocalizedAreaName(current_area) : BOT_TEXT1("string_unknown_area"); - placeholders["%zone_name"] = current_zone ? ai->GetLocalizedAreaName(current_zone) : BOT_TEXT1("string_unknown_area"); + placeholders["%area_name"] = current_area ? ai->GetLocalizedAreaName(current_area) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); + placeholders["%zone_name"] = current_zone ? ai->GetLocalizedAreaName(current_zone) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); placeholders["%quest_link"] = ai->GetChatHelper()->FormatQuest(quest); placeholders["%quest_obj_name"] = obectiveName; placeholders["%my_class"] = ai->GetChatHelper()->FormatClass(bot->getClass()); @@ -305,20 +305,20 @@ bool BroadcastHelper::BroadcastQuestUpdateAddKill(PlayerbotAI* ai, Player* bot, placeholders["%quest_obj_full_formatted"] = ai->GetChatHelper()->FormatQuestObjective(obectiveName, availableCount, requiredCount); if (availableCount < requiredCount - && urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceQuestUpdateObjectiveProgress) + && urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceQuestUpdateObjectiveProgress) { return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("broadcast_quest_update_add_kill_objective_progress", placeholders), + PlayerbotTextMgr::instance().GetBotText("broadcast_quest_update_add_kill_objective_progress", placeholders), { {TO_GUILD, 50}, {TO_WORLD, 50}, {TO_GENERAL, 100} } ); } else if (availableCount == requiredCount - && urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceQuestUpdateObjectiveCompleted) + && urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceQuestUpdateObjectiveCompleted) { return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("broadcast_quest_update_add_kill_objective_completed", placeholders), + PlayerbotTextMgr::instance().GetBotText("broadcast_quest_update_add_kill_objective_completed", placeholders), { {TO_GUILD, 50}, {TO_WORLD, 50}, {TO_GENERAL, 100} } ); } @@ -328,13 +328,13 @@ bool BroadcastHelper::BroadcastQuestUpdateAddKill(PlayerbotAI* ai, Player* bot, bool BroadcastHelper::BroadcastQuestUpdateAddItem(PlayerbotAI* ai, Player* bot, Quest const* quest, uint32 availableCount, uint32 requiredCount, const ItemTemplate* proto) { - if (!sPlayerbotAIConfig->enableBroadcasts) + if (!sPlayerbotAIConfig.enableBroadcasts) return false; std::map placeholders; AreaTableEntry const* current_area = ai->GetCurrentArea(); AreaTableEntry const* current_zone = ai->GetCurrentZone(); - placeholders["%area_name"] = current_area ? ai->GetLocalizedAreaName(current_area) : BOT_TEXT1("string_unknown_area"); - placeholders["%zone_name"] = current_zone ? ai->GetLocalizedAreaName(current_zone) : BOT_TEXT1("string_unknown_area"); + placeholders["%area_name"] = current_area ? ai->GetLocalizedAreaName(current_area) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); + placeholders["%zone_name"] = current_zone ? ai->GetLocalizedAreaName(current_zone) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); placeholders["%quest_link"] = ai->GetChatHelper()->FormatQuest(quest); std::string itemLinkFormatted = ai->GetChatHelper()->FormatItem(proto); placeholders["%item_link"] = itemLinkFormatted; @@ -347,20 +347,20 @@ bool BroadcastHelper::BroadcastQuestUpdateAddItem(PlayerbotAI* ai, Player* bot, placeholders["%quest_obj_full_formatted"] = ai->GetChatHelper()->FormatQuestObjective(itemLinkFormatted, availableCount, requiredCount); if (availableCount < requiredCount - && urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceQuestUpdateObjectiveProgress) + && urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceQuestUpdateObjectiveProgress) { return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("broadcast_quest_update_add_item_objective_progress", placeholders), + PlayerbotTextMgr::instance().GetBotText("broadcast_quest_update_add_item_objective_progress", placeholders), { {TO_GUILD, 50}, {TO_WORLD, 50}, {TO_GENERAL, 100} } ); } else if (availableCount == requiredCount - && urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceQuestUpdateObjectiveCompleted) + && urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceQuestUpdateObjectiveCompleted) { return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("broadcast_quest_update_add_item_objective_completed", placeholders), + PlayerbotTextMgr::instance().GetBotText("broadcast_quest_update_add_item_objective_completed", placeholders), { {TO_GUILD, 50}, {TO_WORLD, 50}, {TO_GENERAL, 100} } ); } @@ -370,23 +370,23 @@ bool BroadcastHelper::BroadcastQuestUpdateAddItem(PlayerbotAI* ai, Player* bot, bool BroadcastHelper::BroadcastQuestUpdateFailedTimer(PlayerbotAI* ai, Player* bot, Quest const* quest) { - if (!sPlayerbotAIConfig->enableBroadcasts) + if (!sPlayerbotAIConfig.enableBroadcasts) return false; - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceQuestUpdateFailedTimer) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceQuestUpdateFailedTimer) { std::map placeholders; placeholders["%quest_link"] = ai->GetChatHelper()->FormatQuest(quest); AreaTableEntry const* current_area = ai->GetCurrentArea(); AreaTableEntry const* current_zone = ai->GetCurrentZone(); - placeholders["%area_name"] = current_area ? ai->GetLocalizedAreaName(current_area) : BOT_TEXT1("string_unknown_area"); - placeholders["%zone_name"] = current_zone ? ai->GetLocalizedAreaName(current_zone) : BOT_TEXT1("string_unknown_area"); + placeholders["%area_name"] = current_area ? ai->GetLocalizedAreaName(current_area) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); + placeholders["%zone_name"] = current_zone ? ai->GetLocalizedAreaName(current_zone) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); placeholders["%my_class"] = ai->GetChatHelper()->FormatClass(bot->getClass()); placeholders["%my_race"] = ai->GetChatHelper()->FormatRace(bot->getRace()); placeholders["%my_level"] = std::to_string(bot->GetLevel()); return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("broadcast_quest_update_failed_timer", placeholders), + PlayerbotTextMgr::instance().GetBotText("broadcast_quest_update_failed_timer", placeholders), { {TO_GUILD, 50}, {TO_WORLD, 50}, {TO_GENERAL, 100} } ); } @@ -396,23 +396,23 @@ bool BroadcastHelper::BroadcastQuestUpdateFailedTimer(PlayerbotAI* ai, Player* b bool BroadcastHelper::BroadcastQuestUpdateComplete(PlayerbotAI* ai, Player* bot, Quest const* quest) { - if (!sPlayerbotAIConfig->enableBroadcasts) + if (!sPlayerbotAIConfig.enableBroadcasts) return false; - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceQuestUpdateComplete) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceQuestUpdateComplete) { std::map placeholders; placeholders["%quest_link"] = ai->GetChatHelper()->FormatQuest(quest); AreaTableEntry const* current_area = ai->GetCurrentArea(); AreaTableEntry const* current_zone = ai->GetCurrentZone(); - placeholders["%area_name"] = current_area ? ai->GetLocalizedAreaName(current_area) : BOT_TEXT1("string_unknown_area"); - placeholders["%zone_name"] = current_zone ? ai->GetLocalizedAreaName(current_zone) : BOT_TEXT1("string_unknown_area"); + placeholders["%area_name"] = current_area ? ai->GetLocalizedAreaName(current_area) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); + placeholders["%zone_name"] = current_zone ? ai->GetLocalizedAreaName(current_zone) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); placeholders["%my_class"] = ai->GetChatHelper()->FormatClass(bot->getClass()); placeholders["%my_race"] = ai->GetChatHelper()->FormatRace(bot->getRace()); placeholders["%my_level"] = std::to_string(bot->GetLevel()); return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("broadcast_quest_update_complete", placeholders), + PlayerbotTextMgr::instance().GetBotText("broadcast_quest_update_complete", placeholders), { {TO_GUILD, 50}, {TO_WORLD, 50}, {TO_GENERAL, 100} } ); } @@ -422,23 +422,23 @@ bool BroadcastHelper::BroadcastQuestUpdateComplete(PlayerbotAI* ai, Player* bot, bool BroadcastHelper::BroadcastQuestTurnedIn(PlayerbotAI* ai, Player* bot, Quest const* quest) { - if (!sPlayerbotAIConfig->enableBroadcasts) + if (!sPlayerbotAIConfig.enableBroadcasts) return false; - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceQuestTurnedIn) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceQuestTurnedIn) { std::map placeholders; placeholders["%quest_link"] = ai->GetChatHelper()->FormatQuest(quest); AreaTableEntry const* current_area = ai->GetCurrentArea(); AreaTableEntry const* current_zone = ai->GetCurrentZone(); - placeholders["%area_name"] = current_area ? ai->GetLocalizedAreaName(current_area) : BOT_TEXT1("string_unknown_area"); - placeholders["%zone_name"] = current_zone ? ai->GetLocalizedAreaName(current_zone) : BOT_TEXT1("string_unknown_area"); + placeholders["%area_name"] = current_area ? ai->GetLocalizedAreaName(current_area) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); + placeholders["%zone_name"] = current_zone ? ai->GetLocalizedAreaName(current_zone) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); placeholders["%my_class"] = ai->GetChatHelper()->FormatClass(bot->getClass()); placeholders["%my_race"] = ai->GetChatHelper()->FormatRace(bot->getRace()); placeholders["%my_level"] = std::to_string(bot->GetLevel()); return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("broadcast_quest_turned_in", placeholders), + PlayerbotTextMgr::instance().GetBotText("broadcast_quest_turned_in", placeholders), { {TO_GUILD, 50}, {TO_WORLD, 50}, {TO_GENERAL, 100} } ); } @@ -448,14 +448,14 @@ bool BroadcastHelper::BroadcastQuestTurnedIn(PlayerbotAI* ai, Player* bot, Quest bool BroadcastHelper::BroadcastKill(PlayerbotAI* ai, Player* bot, Creature *creature) { - if (!sPlayerbotAIConfig->enableBroadcasts) + if (!sPlayerbotAIConfig.enableBroadcasts) return false; std::map placeholders; placeholders["%victim_name"] = creature->GetName(); AreaTableEntry const* current_area = ai->GetCurrentArea(); AreaTableEntry const* current_zone = ai->GetCurrentZone(); - placeholders["%area_name"] = current_area ? ai->GetLocalizedAreaName(current_area) : BOT_TEXT1("string_unknown_area"); - placeholders["%zone_name"] = current_zone ? ai->GetLocalizedAreaName(current_zone) : BOT_TEXT1("string_unknown_area"); + placeholders["%area_name"] = current_area ? ai->GetLocalizedAreaName(current_area) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); + placeholders["%zone_name"] = current_zone ? ai->GetLocalizedAreaName(current_zone) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); placeholders["%victim_level"] = creature->GetLevel(); placeholders["%my_class"] = ai->GetChatHelper()->FormatClass(bot->getClass()); placeholders["%my_race"] = ai->GetChatHelper()->FormatRace(bot->getRace()); @@ -468,24 +468,24 @@ bool BroadcastHelper::BroadcastKill(PlayerbotAI* ai, Player* bot, Creature *crea if (creature->IsPet()) { - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceKillPet) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceKillPet) { return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("broadcast_killed_pet", placeholders), + PlayerbotTextMgr::instance().GetBotText("broadcast_killed_pet", placeholders), { {TO_GUILD, 50}, {TO_WORLD, 50}, {TO_GENERAL, 100} } ); } } else if (creature->IsPlayer()) { - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceKillPlayer) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceKillPlayer) { placeholders["%victim_class"] = ai->GetChatHelper()->FormatClass(creature->getClass()); return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("broadcast_killed_player", placeholders), + PlayerbotTextMgr::instance().GetBotText("broadcast_killed_player", placeholders), { {TO_WORLD_DEFENSE, 50}, {TO_LOCAL_DEFENSE, 50}, {TO_GUILD, 50}, {TO_WORLD, 50}, {TO_GENERAL, 100} } ); } @@ -495,61 +495,61 @@ bool BroadcastHelper::BroadcastKill(PlayerbotAI* ai, Player* bot, Creature *crea switch (creature->GetCreatureTemplate()->rank) { case CREATURE_ELITE_NORMAL: - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceKillNormal) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceKillNormal) { return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("broadcast_killed_normal", placeholders), + PlayerbotTextMgr::instance().GetBotText("broadcast_killed_normal", placeholders), { {TO_GUILD, 50}, {TO_WORLD, 50}, {TO_GENERAL, 100} } ); } break; case CREATURE_ELITE_ELITE: - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceKillElite) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceKillElite) { return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("broadcast_killed_elite", placeholders), + PlayerbotTextMgr::instance().GetBotText("broadcast_killed_elite", placeholders), { {TO_GUILD, 50}, {TO_WORLD, 50}, {TO_GENERAL, 100} } ); } break; case CREATURE_ELITE_RAREELITE: - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceKillRareelite) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceKillRareelite) { return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("broadcast_killed_rareelite", placeholders), + PlayerbotTextMgr::instance().GetBotText("broadcast_killed_rareelite", placeholders), { {TO_GUILD, 50}, {TO_WORLD, 50}, {TO_GENERAL, 100} } ); } break; case CREATURE_ELITE_WORLDBOSS: - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceKillWorldboss) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceKillWorldboss) { return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("broadcast_killed_worldboss", placeholders), + PlayerbotTextMgr::instance().GetBotText("broadcast_killed_worldboss", placeholders), { {TO_GUILD, 50}, {TO_WORLD, 50}, {TO_GENERAL, 100} } ); } break; case CREATURE_ELITE_RARE: - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceKillRare) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceKillRare) { return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("broadcast_killed_rare", placeholders), + PlayerbotTextMgr::instance().GetBotText("broadcast_killed_rare", placeholders), { {TO_GUILD, 50}, {TO_WORLD, 50}, {TO_GENERAL, 100} } ); } break; case CREATURE_UNKNOWN: - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceKillUnknown) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceKillUnknown) { return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("broadcast_killed_unknown", placeholders), + PlayerbotTextMgr::instance().GetBotText("broadcast_killed_unknown", placeholders), { {TO_GUILD, 50}, {TO_WORLD, 50}, {TO_GENERAL, 100} } ); } @@ -564,43 +564,43 @@ bool BroadcastHelper::BroadcastKill(PlayerbotAI* ai, Player* bot, Creature *crea bool BroadcastHelper::BroadcastLevelup(PlayerbotAI* ai, Player* bot) { - if (!sPlayerbotAIConfig->enableBroadcasts) + if (!sPlayerbotAIConfig.enableBroadcasts) return false; uint32 level = bot->GetLevel(); std::map placeholders; AreaTableEntry const* current_area = ai->GetCurrentArea(); AreaTableEntry const* current_zone = ai->GetCurrentZone(); - placeholders["%area_name"] = current_area ? ai->GetLocalizedAreaName(current_area) : BOT_TEXT1("string_unknown_area"); - placeholders["%zone_name"] = current_zone ? ai->GetLocalizedAreaName(current_zone) : BOT_TEXT1("string_unknown_area"); + placeholders["%area_name"] = current_area ? ai->GetLocalizedAreaName(current_area) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); + placeholders["%zone_name"] = current_zone ? ai->GetLocalizedAreaName(current_zone) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); placeholders["%my_class"] = ai->GetChatHelper()->FormatClass(bot->getClass()); placeholders["%my_race"] = ai->GetChatHelper()->FormatRace(bot->getRace()); placeholders["%my_level"] = std::to_string(level); - if (level == sPlayerbotAIConfig->randomBotMaxLevel - && urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceLevelupMaxLevel) + if (level == sPlayerbotAIConfig.randomBotMaxLevel + && urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceLevelupMaxLevel) { return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("broadcast_levelup_max_level", placeholders), + PlayerbotTextMgr::instance().GetBotText("broadcast_levelup_max_level", placeholders), { {TO_GUILD, 30}, {TO_WORLD, 90}, {TO_GENERAL, 100} } ); } // It's divisible by 10 else if (level % 10 == 0 - && urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceLevelupTenX) + && urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceLevelupTenX) { return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("broadcast_levelup_10x", placeholders), + PlayerbotTextMgr::instance().GetBotText("broadcast_levelup_10x", placeholders), { {TO_GUILD, 50}, {TO_WORLD, 90}, {TO_GENERAL, 100} } ); } - else if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceLevelupGeneric) + else if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceLevelupGeneric) { return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("broadcast_levelup_generic", placeholders), + PlayerbotTextMgr::instance().GetBotText("broadcast_levelup_generic", placeholders), { {TO_GUILD, 90}, {TO_WORLD, 90}, {TO_GENERAL, 100} } ); } @@ -610,9 +610,9 @@ bool BroadcastHelper::BroadcastLevelup(PlayerbotAI* ai, Player* bot) bool BroadcastHelper::BroadcastGuildMemberPromotion(PlayerbotAI* ai, Player* /* bot */, Player* player) { - if (!sPlayerbotAIConfig->enableBroadcasts) + if (!sPlayerbotAIConfig.enableBroadcasts) return false; - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceGuildManagement) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceGuildManagement) { std::map placeholders; placeholders["%other_name"] = player->GetName(); @@ -620,7 +620,7 @@ bool BroadcastHelper::BroadcastGuildMemberPromotion(PlayerbotAI* ai, Player* /* placeholders["%other_race"] = ai->GetChatHelper()->FormatRace(player->getRace()); placeholders["%other_level"] = std::to_string(player->GetLevel()); - return ai->SayToGuild(BOT_TEXT2("broadcast_guild_promotion", placeholders)); + return ai->SayToGuild(PlayerbotTextMgr::instance().GetBotText("broadcast_guild_promotion", placeholders)); } return false; @@ -628,7 +628,7 @@ bool BroadcastHelper::BroadcastGuildMemberPromotion(PlayerbotAI* ai, Player* /* bool BroadcastHelper::BroadcastGuildMemberDemotion(PlayerbotAI* ai, Player* /* bot */, Player* player) { - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceGuildManagement) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceGuildManagement) { std::map placeholders; placeholders["%other_name"] = player->GetName(); @@ -636,7 +636,7 @@ bool BroadcastHelper::BroadcastGuildMemberDemotion(PlayerbotAI* ai, Player* /* b placeholders["%other_race"] = ai->GetChatHelper()->FormatRace(player->getRace()); placeholders["%other_level"] = std::to_string(player->GetLevel()); - return ai->SayToGuild(BOT_TEXT2("broadcast_guild_demotion", placeholders)); + return ai->SayToGuild(PlayerbotTextMgr::instance().GetBotText("broadcast_guild_demotion", placeholders)); } return false; @@ -644,25 +644,25 @@ bool BroadcastHelper::BroadcastGuildMemberDemotion(PlayerbotAI* ai, Player* /* b bool BroadcastHelper::BroadcastGuildGroupOrRaidInvite(PlayerbotAI* ai, Player* /* bot */, Player* player, Group* group) { - if (!sPlayerbotAIConfig->enableBroadcasts) + if (!sPlayerbotAIConfig.enableBroadcasts) return false; std::map placeholders; placeholders["%name"] = player->GetName(); AreaTableEntry const* current_area = ai->GetCurrentArea(); AreaTableEntry const* current_zone = ai->GetCurrentZone(); - placeholders["%area_name"] = current_area ? ai->GetLocalizedAreaName(current_area) : BOT_TEXT1("string_unknown_area"); - placeholders["%zone_name"] = current_zone ? ai->GetLocalizedAreaName(current_zone) : BOT_TEXT1("string_unknown_area"); + placeholders["%area_name"] = current_area ? ai->GetLocalizedAreaName(current_area) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); + placeholders["%zone_name"] = current_zone ? ai->GetLocalizedAreaName(current_zone) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); //TODO move texts to sql! if (group && group->isRaidGroup()) { if (urand(0, 3)) { - return ai->SayToGuild(BOT_TEXT2("Hey anyone want to raid in %zone_name", placeholders)); + return ai->SayToGuild(PlayerbotTextMgr::instance().GetBotText("Hey anyone want to raid in %zone_name", placeholders)); } else { - return ai->SayToGuild(BOT_TEXT2("Hey %name I'm raiding in %zone_name do you wan to join me?", placeholders)); + return ai->SayToGuild(PlayerbotTextMgr::instance().GetBotText("Hey %name I'm raiding in %zone_name do you wan to join me?", placeholders)); } } else @@ -670,11 +670,11 @@ bool BroadcastHelper::BroadcastGuildGroupOrRaidInvite(PlayerbotAI* ai, Player* / //(bot->GetTeam() == ALLIANCE ? LANG_COMMON : LANG_ORCISH) if (urand(0, 3)) { - return ai->SayToGuild(BOT_TEXT2("Hey anyone wanna group up in %zone_name?", placeholders)); + return ai->SayToGuild(PlayerbotTextMgr::instance().GetBotText("Hey anyone wanna group up in %zone_name?", placeholders)); } else { - return ai->SayToGuild(BOT_TEXT2("Hey %name do you want join my group? I'm heading for %zone_name", placeholders)); + return ai->SayToGuild(PlayerbotTextMgr::instance().GetBotText("Hey %name do you want join my group? I'm heading for %zone_name", placeholders)); } } @@ -683,9 +683,9 @@ bool BroadcastHelper::BroadcastGuildGroupOrRaidInvite(PlayerbotAI* ai, Player* / bool BroadcastHelper::BroadcastSuggestInstance(PlayerbotAI* ai, std::vector& allowedInstances, Player* bot) { - if (!sPlayerbotAIConfig->enableBroadcasts) + if (!sPlayerbotAIConfig.enableBroadcasts) return false; - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceSuggestInstance) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceSuggestInstance) { std::map placeholders; placeholders["%my_role"] = ChatHelper::FormatClass(bot, AiFactory::GetPlayerSpecTab(bot)); @@ -701,7 +701,7 @@ bool BroadcastHelper::BroadcastSuggestInstance(PlayerbotAI* ai, std::vector& quests, Player* bot) { - if (!sPlayerbotAIConfig->enableBroadcasts) + if (!sPlayerbotAIConfig.enableBroadcasts) return false; - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceSuggestQuest) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceSuggestQuest) { int index = rand() % quests.size(); @@ -730,7 +730,7 @@ bool BroadcastHelper::BroadcastSuggestQuest(PlayerbotAI* ai, std::vector return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("suggest_quest", placeholders), + PlayerbotTextMgr::instance().GetBotText("suggest_quest", placeholders), { {TO_LOOKING_FOR_GROUP, 50}, {TO_GUILD, 50}, {TO_WORLD, 50}, {TO_GENERAL, 100} } ); } @@ -740,9 +740,9 @@ bool BroadcastHelper::BroadcastSuggestQuest(PlayerbotAI* ai, std::vector bool BroadcastHelper::BroadcastSuggestGrindMaterials(PlayerbotAI* ai, std::string item, Player* bot) { - if (!sPlayerbotAIConfig->enableBroadcasts) + if (!sPlayerbotAIConfig.enableBroadcasts) return false; - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceSuggestGrindMaterials) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceSuggestGrindMaterials) { std::map placeholders; @@ -755,7 +755,7 @@ bool BroadcastHelper::BroadcastSuggestGrindMaterials(PlayerbotAI* ai, std::strin return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("suggest_trade", placeholders), + PlayerbotTextMgr::instance().GetBotText("suggest_trade", placeholders), { {TO_TRADE, 50}, {TO_LOOKING_FOR_GROUP, 50}, {TO_GUILD, 50}, {TO_WORLD, 50}, {TO_GENERAL, 100} } ); } @@ -765,9 +765,9 @@ bool BroadcastHelper::BroadcastSuggestGrindMaterials(PlayerbotAI* ai, std::strin bool BroadcastHelper::BroadcastSuggestGrindReputation(PlayerbotAI* ai, std::vector levels, std::vector allowedFactions, Player* bot) { - if (!sPlayerbotAIConfig->enableBroadcasts) + if (!sPlayerbotAIConfig.enableBroadcasts) return false; - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceSuggestGrindReputation) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceSuggestGrindReputation) { std::map placeholders; @@ -787,7 +787,7 @@ bool BroadcastHelper::BroadcastSuggestGrindReputation(PlayerbotAI* ai, std::vect return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("suggest_faction", placeholders), + PlayerbotTextMgr::instance().GetBotText("suggest_faction", placeholders), { {TO_LOOKING_FOR_GROUP, 50}, {TO_GUILD, 50}, {TO_WORLD, 50}, {TO_GENERAL, 100} } ); } @@ -797,9 +797,9 @@ bool BroadcastHelper::BroadcastSuggestGrindReputation(PlayerbotAI* ai, std::vect bool BroadcastHelper::BroadcastSuggestSell(PlayerbotAI* ai, const ItemTemplate* proto, uint32 count, uint32 price, Player* bot) { - if (!sPlayerbotAIConfig->enableBroadcasts) + if (!sPlayerbotAIConfig.enableBroadcasts) return false; - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceSuggestSell) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceSuggestSell) { std::map placeholders; @@ -814,7 +814,7 @@ bool BroadcastHelper::BroadcastSuggestSell(PlayerbotAI* ai, const ItemTemplate* return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("suggest_sell", placeholders), + PlayerbotTextMgr::instance().GetBotText("suggest_sell", placeholders), { {TO_TRADE, 90}, {TO_GENERAL, 100} } ); } @@ -824,24 +824,24 @@ bool BroadcastHelper::BroadcastSuggestSell(PlayerbotAI* ai, const ItemTemplate* bool BroadcastHelper::BroadcastSuggestSomething(PlayerbotAI* ai, Player* bot) { - if (!sPlayerbotAIConfig->enableBroadcasts) + if (!sPlayerbotAIConfig.enableBroadcasts) return false; - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceSuggestSomething) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceSuggestSomething) { std::map placeholders; placeholders["%my_role"] = ChatHelper::FormatClass(bot, AiFactory::GetPlayerSpecTab(bot)); AreaTableEntry const* current_area = ai->GetCurrentArea(); AreaTableEntry const* current_zone = ai->GetCurrentZone(); - placeholders["%area_name"] = current_area ? ai->GetLocalizedAreaName(current_area) : BOT_TEXT1("string_unknown_area"); - placeholders["%zone_name"] = current_zone ? ai->GetLocalizedAreaName(current_zone) : BOT_TEXT1("string_unknown_area"); + placeholders["%area_name"] = current_area ? ai->GetLocalizedAreaName(current_area) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); + placeholders["%zone_name"] = current_zone ? ai->GetLocalizedAreaName(current_zone) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); placeholders["%my_class"] = ai->GetChatHelper()->FormatClass(bot->getClass()); placeholders["%my_race"] = ai->GetChatHelper()->FormatRace(bot->getRace()); placeholders["%my_level"] = std::to_string(bot->GetLevel()); return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("suggest_something", placeholders), + PlayerbotTextMgr::instance().GetBotText("suggest_something", placeholders), { {TO_GUILD, 10}, {TO_WORLD, 70}, {TO_GENERAL, 100} } ); } @@ -851,29 +851,29 @@ bool BroadcastHelper::BroadcastSuggestSomething(PlayerbotAI* ai, Player* bot) bool BroadcastHelper::BroadcastSuggestSomethingToxic(PlayerbotAI* ai, Player* bot) { - if (!sPlayerbotAIConfig->enableBroadcasts) + if (!sPlayerbotAIConfig.enableBroadcasts) return false; - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceSuggestSomethingToxic) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceSuggestSomethingToxic) { //items std::vector botItems = ai->GetInventoryAndEquippedItems(); std::map placeholders; - placeholders["%random_inventory_item_link"] = botItems.size() > 0 ? ai->GetChatHelper()->FormatItem(botItems[rand() % botItems.size()]->GetTemplate()) : BOT_TEXT1("string_empty_link"); + placeholders["%random_inventory_item_link"] = botItems.size() > 0 ? ai->GetChatHelper()->FormatItem(botItems[rand() % botItems.size()]->GetTemplate()) : PlayerbotTextMgr::instance().GetBotText("string_empty_link"); placeholders["%my_role"] = ChatHelper::FormatClass(bot, AiFactory::GetPlayerSpecTab(bot)); AreaTableEntry const* current_area = ai->GetCurrentArea(); AreaTableEntry const* current_zone = ai->GetCurrentZone(); - placeholders["%area_name"] = current_area ? ai->GetLocalizedAreaName(current_area) : BOT_TEXT1("string_unknown_area"); - placeholders["%zone_name"] = current_zone ? ai->GetLocalizedAreaName(current_zone) : BOT_TEXT1("string_unknown_area"); + placeholders["%area_name"] = current_area ? ai->GetLocalizedAreaName(current_area) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); + placeholders["%zone_name"] = current_zone ? ai->GetLocalizedAreaName(current_zone) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); placeholders["%my_class"] = ai->GetChatHelper()->FormatClass(bot->getClass()); placeholders["%my_race"] = ai->GetChatHelper()->FormatRace(bot->getRace()); placeholders["%my_level"] = std::to_string(bot->GetLevel()); return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("suggest_something_toxic", placeholders), + PlayerbotTextMgr::instance().GetBotText("suggest_something_toxic", placeholders), { {TO_GUILD, 10}, {TO_WORLD, 70}, {TO_GENERAL, 100} } ); } @@ -883,9 +883,9 @@ bool BroadcastHelper::BroadcastSuggestSomethingToxic(PlayerbotAI* ai, Player* bo bool BroadcastHelper::BroadcastSuggestToxicLinks(PlayerbotAI* ai, Player* bot) { - if (!sPlayerbotAIConfig->enableBroadcasts) + if (!sPlayerbotAIConfig.enableBroadcasts) return false; - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceSuggestToxicLinks) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceSuggestToxicLinks) { //quests std::vector incompleteQuests; @@ -908,8 +908,8 @@ bool BroadcastHelper::BroadcastSuggestToxicLinks(PlayerbotAI* ai, Player* bot) std::map placeholders; - placeholders["%random_inventory_item_link"] = botItems.size() > 0 ? ai->GetChatHelper()->FormatItem(botItems[rand() % botItems.size()]->GetTemplate()) : BOT_TEXT1("string_empty_link"); - placeholders["%prefix"] = sPlayerbotAIConfig->toxicLinksPrefix; + placeholders["%random_inventory_item_link"] = botItems.size() > 0 ? ai->GetChatHelper()->FormatItem(botItems[rand() % botItems.size()]->GetTemplate()) : PlayerbotTextMgr::instance().GetBotText("string_empty_link"); + placeholders["%prefix"] = sPlayerbotAIConfig.toxicLinksPrefix; if (incompleteQuests.size() > 0) { @@ -924,15 +924,15 @@ bool BroadcastHelper::BroadcastSuggestToxicLinks(PlayerbotAI* ai, Player* bot) placeholders["%my_role"] = ChatHelper::FormatClass(bot, AiFactory::GetPlayerSpecTab(bot)); AreaTableEntry const* current_area = ai->GetCurrentArea(); AreaTableEntry const* current_zone = ai->GetCurrentZone(); - placeholders["%area_name"] = current_area ? ai->GetLocalizedAreaName(current_area) : BOT_TEXT1("string_unknown_area"); - placeholders["%zone_name"] = current_zone ? ai->GetLocalizedAreaName(current_zone) : BOT_TEXT1("string_unknown_area"); + placeholders["%area_name"] = current_area ? ai->GetLocalizedAreaName(current_area) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); + placeholders["%zone_name"] = current_zone ? ai->GetLocalizedAreaName(current_zone) : PlayerbotTextMgr::instance().GetBotText("string_unknown_area"); placeholders["%my_class"] = ai->GetChatHelper()->FormatClass(bot->getClass()); placeholders["%my_race"] = ai->GetChatHelper()->FormatRace(bot->getRace()); placeholders["%my_level"] = std::to_string(bot->GetLevel()); return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("suggest_toxic_links", placeholders), + PlayerbotTextMgr::instance().GetBotText("suggest_toxic_links", placeholders), { {TO_GUILD, 10}, {TO_WORLD, 70}, {TO_GENERAL, 100} } ); } @@ -942,7 +942,7 @@ bool BroadcastHelper::BroadcastSuggestToxicLinks(PlayerbotAI* ai, Player* bot) bool BroadcastHelper::BroadcastSuggestThunderfury(PlayerbotAI* ai, Player* bot) { - if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceSuggestThunderfury) + if (urand(1, sPlayerbotAIConfig.broadcastChanceMaxValue) <= sPlayerbotAIConfig.broadcastChanceSuggestThunderfury) { std::map placeholders; ItemTemplate const* thunderfuryProto = sObjectMgr->GetItemTemplate(19019); @@ -950,7 +950,7 @@ bool BroadcastHelper::BroadcastSuggestThunderfury(PlayerbotAI* ai, Player* bot) return BroadcastToChannelWithGlobalChance( ai, - BOT_TEXT2("thunderfury_spam", placeholders), + PlayerbotTextMgr::instance().GetBotText("thunderfury_spam", placeholders), { {TO_WORLD, 70}, {TO_GENERAL, 100} } ); } diff --git a/src/Util/ServerFacade.cpp b/src/Util/ServerFacade.cpp index d69944c04f..8bd8ee60ef 100644 --- a/src/Util/ServerFacade.cpp +++ b/src/Util/ServerFacade.cpp @@ -4,8 +4,8 @@ */ #include "ServerFacade.h" +#include "Player.h" -#include "Playerbots.h" #include "TargetedMovementGenerator.h" float ServerFacade::GetDistance2d(Unit* unit, WorldObject* wo) @@ -25,13 +25,13 @@ float ServerFacade::GetDistance2d(Unit* unit, float x, float y) bool ServerFacade::IsDistanceLessThan(float dist1, float dist2) { - // return dist1 - dist2 < sPlayerbotAIConfig->targetPosRecalcDistance; + // return dist1 - dist2 < sPlayerbotAIConfig.targetPosRecalcDistance; return dist1 < dist2; } bool ServerFacade::IsDistanceGreaterThan(float dist1, float dist2) { - // return dist1 - dist2 > sPlayerbotAIConfig->targetPosRecalcDistance; + // return dist1 - dist2 > sPlayerbotAIConfig.targetPosRecalcDistance; return dist1 > dist2; } @@ -39,7 +39,7 @@ bool ServerFacade::IsDistanceGreaterOrEqualThan(float dist1, float dist2) { retu bool ServerFacade::IsDistanceLessOrEqualThan(float dist1, float dist2) { return !IsDistanceGreaterThan(dist1, dist2); } -void ServerFacade::SetFacingTo(Player* bot, WorldObject* wo, bool force) +void ServerFacade::SetFacingTo(Player* bot, WorldObject* wo, bool) { if (!bot) return; diff --git a/src/Util/ServerFacade.h b/src/Util/ServerFacade.h index 6668fa9562..978b8e7681 100644 --- a/src/Util/ServerFacade.h +++ b/src/Util/ServerFacade.h @@ -6,8 +6,6 @@ #ifndef _PLAYERBOT_SERVERFACADE_H #define _PLAYERBOT_SERVERFACADE_H -#include "Common.h" - class Player; class Unit; class WorldObject; @@ -29,12 +27,13 @@ class ServerFacade /** * @brief Get singleton instance. * - * @return ServerFacade* Pointer to the singleton instance. + * @return ServerFacade& Reference to the singleton instance. */ - static ServerFacade* instance() + static ServerFacade& instance() { static ServerFacade instance; - return &instance; + + return instance; } public: @@ -123,7 +122,4 @@ class ServerFacade void SendPacket(Player* player, WorldPacket* packet); }; -/** Global singleton accessor. */ -#define sServerFacade ServerFacade::instance() - #endif diff --git a/src/domain/core/inspector/abstract/AbstractInspector.h b/src/domain/core/inspector/abstract/AbstractInspector.h new file mode 100644 index 0000000000..7906180f65 --- /dev/null +++ b/src/domain/core/inspector/abstract/AbstractInspector.h @@ -0,0 +1,19 @@ +#pragma once + +class AbstractInspector +{ +protected: + AbstractInspector() = default; + ~AbstractInspector() = default; + + AbstractInspector(AbstractInspector const&) = default; + AbstractInspector& operator=(AbstractInspector const&) = default; + + AbstractInspector(AbstractInspector&&) = default; + AbstractInspector& operator=(AbstractInspector&&) = default; + + virtual bool isInspectable() const + { + return true; + } +}; diff --git a/src/domain/item/inspector/abstract/AbstractItemInspector.h b/src/domain/item/inspector/abstract/AbstractItemInspector.h new file mode 100644 index 0000000000..55dc9b9be4 --- /dev/null +++ b/src/domain/item/inspector/abstract/AbstractItemInspector.h @@ -0,0 +1,290 @@ +#pragma once + +#include + +#include "ObjectGuid.h" +#include "ObjectAccessor.h" +#include "SharedDefines.h" +#include "Player.h" +#include "ObjectMgr.h" +#include "ItemTemplate.h" +#include "Item.h" + +#include "AbstractInspector.h" +#include "ItemActionStruct.h" +#include "ItemActionEnum.h" + +class AbstractItemInspector : public AbstractInspector +{ +public: + virtual ItemActionStruct determineItemAction() const + { + return this->getDefaultItemAction(); + }; + + uint8_t getBagSlot() const + { + const Item* const item = this->getCurrentItem(); + + if (item == nullptr) + return 0; + + return item->GetBagSlot(); + } + + uint8_t getItemSlot() const + { + const Item* const item = this->getCurrentItem(); + + if (item == nullptr) + return 0; + + return item->GetSlot(); + } + + uint8_t getItemPosition() const + { + const Item* const item = this->getCurrentItem(); + + if (item == nullptr) + return 0; + + return item->GetPos(); + } + + uint32_t getCurrentItemClass() const + { + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return 0; + + return itemTemplate->Class; + } + + uint8_t getCurrentItemInventoryType() const + { + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return 0; + + return itemTemplate->InventoryType; + } + + uint32_t getCurrentItemSubclass() const + { + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return 255; + + return itemTemplate->SubClass; + } + + uint32_t getItemMaxStackSize() const + { + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return 0; + + return itemTemplate->GetMaxStackSize(); + } + + ItemUpdateState getItemUpdateState() const + { + const Item* const item = this->getCurrentItem(); + + if (item == nullptr) + return ITEM_REMOVED; + + return item->GetState(); + } + + uint32_t getItemSellPrice() const + { + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return 0; + + return itemTemplate->SellPrice; + } + + uint32_t getItemCurrentCount() const + { + const Item* const item = this->getCurrentItem(); + + if (item == nullptr) + return 0; + + return item->GetCount(); + } + + bool itemIsSellable() const + { + return this->getItemSellPrice() != 0; + } + + bool itemIsInWorld() const + { + const Item* const item = this->getCurrentItem(); + + if (item == nullptr) + return false; + + return item->IsInWorld(); + } + + bool itemIsInUnsafeContainer() const + { + const Item* const item = this->getCurrentItem(); + + if (item == nullptr) + return true; + + const ObjectGuid containingField = item->GetGuidValue(ITEM_FIELD_CONTAINED); + + return containingField == ObjectGuid::Empty; + } + + const ItemTemplate* getCurrentItemTemplate() const + { + ObjectMgr* const objectManager = ObjectMgr::instance(); + + if (objectManager == nullptr) + return nullptr; + + const Item* const item = this->getCurrentItem(); + + if (item == nullptr) + return nullptr; + + return item->GetTemplate(); + } + + uint32_t getCurrentItemTemplateLowGUID() const + { + return this->itemTemplateLowGUID; + } + + const Item* getCurrentItem() const + { + const ObjectGuid playerGUID = ObjectGuid::Create(this->playerLowGUID); + const Player* const player = ObjectAccessor::FindPlayer(playerGUID); + + if (player == nullptr) + return nullptr; + + const ObjectGuid itemGUID = ObjectGuid::Create(this->itemLowGUID); + Item* const item = player->GetItemByGuid(itemGUID); + + return item; + } + + Item* getMutableCurrentItem() const + { + const ObjectGuid playerGUID = ObjectGuid::Create(this->playerLowGUID); + const Player* const player = ObjectAccessor::FindPlayer(playerGUID); + + if (player == nullptr) + return nullptr; + + const ObjectGuid itemGUID = ObjectGuid::Create(this->itemLowGUID); + Item* const item = player->GetItemByGuid(itemGUID); + + return item; + } + +protected: + AbstractItemInspector( + uint64_t playerLowGUID, + uint64_t itemLowGUID + ) : + itemLowGUID(itemLowGUID), + playerLowGUID(playerLowGUID), + itemTemplateLowGUID(0) + { + const Player* const player = ObjectAccessor::FindPlayer(ObjectGuid::Create(this->playerLowGUID)); + + if (player == nullptr) + return; + + const Item* const item = player->GetItemByGuid(ObjectGuid::Create(this->itemLowGUID)); + + if (item == nullptr) + { + this->itemTemplateLowGUID = 0; + + return; + } + + const ItemTemplate* const itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + this->itemTemplateLowGUID = 0; + + return; + } + + this->itemTemplateLowGUID = itemTemplate->ItemId; + } + + AbstractItemInspector& operator=(AbstractItemInspector const&) = delete; + + ItemActionStruct getDefaultItemAction() const + { + return this->getKeepItemAction(); + } + + ItemActionStruct getKeepItemAction() const + { + return { + .action = ItemActionEnum::NONE, + .bagSlot = 0, + .containerSlot = 0, + .equipmentSlot = 0 + }; + } + + ItemActionStruct getForbiddenItemAction() const + { + return this->getDestroyItemAction(); + } + + ItemActionStruct getDestroyItemAction() const + { + return { + .action = ItemActionEnum::DESTROY, + .bagSlot = this->getBagSlot(), + .containerSlot = 0, + .equipmentSlot = 0 + }; + } + + ItemActionStruct getSellAction() const + { + const bool sellable = this->itemIsSellable(); + + if (sellable) + return { + .action = ItemActionEnum::SELL, + .bagSlot = this->getBagSlot(), + .containerSlot = 0, + .equipmentSlot = 0 + }; + + return { + .action = ItemActionEnum::DESTROY, + .bagSlot = this->getBagSlot(), + .containerSlot = 0, + .equipmentSlot = 0 + }; + } + + const uint64_t itemLowGUID; + const uint64_t playerLowGUID; + uint32_t itemTemplateLowGUID; +}; diff --git a/src/domain/item/inspector/abstract/definition/enum/ItemActionEnum.h b/src/domain/item/inspector/abstract/definition/enum/ItemActionEnum.h new file mode 100644 index 0000000000..4bdbc93083 --- /dev/null +++ b/src/domain/item/inspector/abstract/definition/enum/ItemActionEnum.h @@ -0,0 +1,9 @@ +#pragma once + +enum class ItemActionEnum +{ + NONE = 0, + EQUIP = 1, + SELL = 2, + DESTROY = 3 +}; diff --git a/src/domain/item/inspector/abstract/definition/struct/ItemActionStruct.h b/src/domain/item/inspector/abstract/definition/struct/ItemActionStruct.h new file mode 100644 index 0000000000..a9486d226c --- /dev/null +++ b/src/domain/item/inspector/abstract/definition/struct/ItemActionStruct.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +#include "ItemActionEnum.h" + +struct ItemActionStruct +{ + const ItemActionEnum action; + const uint8_t bagSlot; + const uint8_t containerSlot; + const uint32_t equipmentSlot; +}; diff --git a/src/domain/item/inspector/armor/ArmorItemInspector.h b/src/domain/item/inspector/armor/ArmorItemInspector.h new file mode 100644 index 0000000000..544a5f5814 --- /dev/null +++ b/src/domain/item/inspector/armor/ArmorItemInspector.h @@ -0,0 +1,147 @@ +#pragma once + +#include + +#include "Item.h" +#include "ItemTemplate.h" + +#include "StatsWeightCalculator.h" +#include "AbstractItemInspector.h" +#include "ItemActionStruct.h" +#include "ItemActionEnum.h" +#include "InventoryService.h" + +class ArmorItemInspector : public AbstractItemInspector +{ +public: + ArmorItemInspector( + uint64_t playerLowGUID, + uint64_t itemLowGUID + ) : AbstractItemInspector(playerLowGUID, itemLowGUID) + {} + + bool isInspectable() const override + { + const uint8_t itemClass = this->getCurrentItemClass(); + + return AbstractItemInspector::isInspectable() && itemClass == ITEM_CLASS_ARMOR; + } + + ItemActionStruct determineItemAction() const override + { + if (!this->isInspectable()) + { + LOG_DEBUG("playerbots.armor.inspector", "Item is not inspectable"); + + return this->getDefaultItemAction(); + } + + if (this->isForbiddenItem()) + return this->getForbiddenItemAction(); + + const ObjectGuid playerGUID = ObjectGuid::Create(this->playerLowGUID); + Player* player = ObjectAccessor::FindPlayer(playerGUID); + + if (player == nullptr) + { + LOG_DEBUG("playerbots.armor.inspector", "player nullptr"); + + return this->getDefaultItemAction(); + } + + Item* const item = this->getMutableCurrentItem(); + + if (item == nullptr) + { + LOG_DEBUG("playerbots.armor.inspector", "item nullptr"); + + return this->getDefaultItemAction(); + } + + const InventoryResult canUseItem = player->CanUseItem(item); + + if (canUseItem != EQUIP_ERR_OK) + { + LOG_DEBUG("playerbots.armor.inspector", "player can't use item"); + + return this->getSellAction(); + } + + StatsWeightCalculator statisticsWeightCalculator(player); + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + { + LOG_DEBUG("playerbots.armor.inspector", "item template nullptr"); + + return this->getDefaultItemAction(); + } + + std::vector slots = InventoryService::GetInstance().getItemEquipmentSlots(itemTemplate); + const float newItemStatisticsWeight = statisticsWeightCalculator.CalculateItem(itemTemplate->ItemId); + + statisticsWeightCalculator.Reset(); + + for (uint8_t i = 0; i < slots.size(); ++i) + { + const uint32_t equipmentSlot = slots[i]; + const Item* const currentlyEquippedItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, equipmentSlot); + + if (currentlyEquippedItem == nullptr) + { + LOG_DEBUG("playerbots.armor.inspector", "current item is nullptr"); + + return { + .action = ItemActionEnum::EQUIP, + .bagSlot = this->getBagSlot(), + .containerSlot = this->getItemSlot(), + .equipmentSlot = equipmentSlot + }; + } + + const ItemTemplate* const currentlyEquippedItemTemplate = currentlyEquippedItem->GetTemplate(); + + if (currentlyEquippedItemTemplate == nullptr) + { + LOG_DEBUG("playerbots.armor.inspector", "current item template nullptr"); + + return this->getDefaultItemAction(); + } + + const float existingItemStatisticsWeight = statisticsWeightCalculator.CalculateItem(currentlyEquippedItemTemplate->ItemId); + + if (existingItemStatisticsWeight < newItemStatisticsWeight) + { + LOG_DEBUG("playerbots.armor.inspector", "Current item is worse than item"); + + return { + .action = ItemActionEnum::EQUIP, + .bagSlot = this->getBagSlot(), + .containerSlot = this->getItemSlot(), + .equipmentSlot = equipmentSlot + }; + } + } + + return this->getSellAction(); + } + + bool isForbiddenItem() const + { + const std::unordered_set forbiddenItems = this->getForbiddenItemsGUIDs(); + + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return true; + + return forbiddenItems.contains(itemTemplate->ItemId); + } + +protected: + + const std::unordered_set getForbiddenItemsGUIDs() const + { + return {}; + } +}; diff --git a/src/domain/item/inspector/consumable/AbstractConsumableInspector.h b/src/domain/item/inspector/consumable/AbstractConsumableInspector.h new file mode 100644 index 0000000000..48127cf7f2 --- /dev/null +++ b/src/domain/item/inspector/consumable/AbstractConsumableInspector.h @@ -0,0 +1,74 @@ +#pragma once + +#include "SharedDefines.h" +#include "ItemTemplate.h" +#include "SpellMgr.h" + +#include "AbstractItemInspector.h" + +class AbstractConsumableInspector : public AbstractItemInspector +{ +public: + bool isInspectable() const override + { + const uint8_t itemClass = this->getCurrentItemClass(); + + return itemClass == ITEM_CLASS_CONSUMABLE; + } + + bool isHealthPotion() const + { + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return false; + + const SpellMgr* const spellMgr = SpellMgr::instance(); + + if (spellMgr == nullptr) + return false; + + const SpellInfo* const spellInfo = spellMgr->GetSpellInfo(itemTemplate->Spells[0].SpellId); + + if (spellInfo == nullptr) + return false; + + if (spellInfo->HasEffect(SPELL_EFFECT_HEAL)) + return true; + + return false; + } + + bool isManaPotion() const + { + const ItemTemplate* itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return false; + + const SpellMgr* const spellMgr = SpellMgr::instance(); + + if (spellMgr == nullptr) + return false; + + const SpellInfo* const spellInfo = spellMgr->GetSpellInfo(itemTemplate->Spells[0].SpellId); + + if (spellInfo == nullptr) + return false; + + if (spellInfo->HasEffect(SPELL_EFFECT_ENERGIZE) && spellInfo->PowerType == POWER_MANA) + return true; + + return false; + } + +protected: + AbstractConsumableInspector( + uint64_t playerGUID, + uint64_t itemGUID + ) : + AbstractItemInspector(playerGUID, itemGUID) + {} + + AbstractConsumableInspector& operator=(AbstractConsumableInspector const&) = delete; +}; diff --git a/src/domain/item/inspector/consumable/GlobalConsumableInspector.h b/src/domain/item/inspector/consumable/GlobalConsumableInspector.h new file mode 100644 index 0000000000..809ea3fa42 --- /dev/null +++ b/src/domain/item/inspector/consumable/GlobalConsumableInspector.h @@ -0,0 +1,55 @@ +#pragma once + +#include + +#include "ItemTemplate.h" + +#include "AbstractConsumableInspector.h" +#include "ItemActionStruct.h" + +class GlobalConsumableInspector : public AbstractConsumableInspector +{ +public: + GlobalConsumableInspector( + uint64_t playerLowGUID, + uint64_t itemLowGUID + ) : AbstractConsumableInspector(playerLowGUID, itemLowGUID) + {} + + bool isInspectable() const override + { + const uint8_t itemSubclass = this->getCurrentItemSubclass(); + + return AbstractConsumableInspector::isInspectable() && itemSubclass == ITEM_SUBCLASS_CONSUMABLE; + } + + bool isForbiddenItem() const + { + const std::unordered_set forbiddenItems = this->getForbiddenItemsGUIDs(); + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return false; + + return forbiddenItems.contains(itemTemplate->ItemId); + } + + ItemActionStruct determineItemAction() const override + { + if (!this->isInspectable()) + return this->getDefaultItemAction(); + + if (this->isForbiddenItem()) + return this->getForbiddenItemAction(); + + return this->getSellAction(); + } + +protected: + + std::unordered_set getForbiddenItemsGUIDs() const + { + return {}; + } + +}; diff --git a/src/domain/item/inspector/consumable/consumable/ConsumableConsumableInspector.h b/src/domain/item/inspector/consumable/consumable/ConsumableConsumableInspector.h new file mode 100644 index 0000000000..101db76fc0 --- /dev/null +++ b/src/domain/item/inspector/consumable/consumable/ConsumableConsumableInspector.h @@ -0,0 +1,958 @@ +#pragma once + +#include + +#include "SharedDefines.h" +#include "ItemTemplate.h" + +#include "AbstractConsumableInspector.h" +#include "ItemActionStruct.h" + +class ConsumableConsumableInspector : public AbstractConsumableInspector +{ +public: + ConsumableConsumableInspector( + uint64_t playerLowGUID, + uint64_t itemLowGUID + ) : AbstractConsumableInspector(playerLowGUID, itemLowGUID) + {} + + bool isInspectable() const override + { + const uint8_t itemSubclass = this->getCurrentItemSubclass(); + + return AbstractConsumableInspector::isInspectable() && itemSubclass == ITEM_SUBCLASS_CONSUMABLE; + } + + ItemActionStruct determineItemAction() const override + { + if (!this->isInspectable()) + return this->getDefaultItemAction(); + + if (this->isForbiddenItem()) + return this->getForbiddenItemAction(); + + const ObjectGuid playerGUID = ObjectGuid::Create(this->playerLowGUID); + Player* player = ObjectAccessor::FindPlayer(playerGUID); + + if (player == nullptr) + return this->getDefaultItemAction(); + + const uint8_t playerClass = player->getClass(); + + if (playerClass == CLASS_ROGUE && this->isRoguePoisonItem()) + return this->getDefaultItemAction(); + + if (playerClass == CLASS_MAGE && this->isMageItem()) + return this->getDefaultItemAction(); + + if (playerClass == CLASS_WARLOCK && this->isWarlockItem()) + return this->getDefaultItemAction(); + + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return this->getDefaultItemAction(); + + player = ObjectAccessor::FindPlayer(playerGUID); + + if (player == nullptr) + return this->getDefaultItemAction(); + + if (this->isQuestConsumableItem() && player->HasQuestForItem(itemTemplate->ItemId)) + return this->getDefaultItemAction(); + + if (!this->isUnwantedItem()) + return this->getDefaultItemAction(); + + return this->getSellAction(); + } + + bool isForbiddenItem() const + { + const std::unordered_set forbiddenItems = this->getForbiddenItemsGUIDs(); + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return false; + + return forbiddenItems.contains(itemTemplate->ItemId); + } + + bool isUnwantedItem() const + { + const std::unordered_set unwantedItems = this->getUnwantedItemsGUIDs(); + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return false; + + return unwantedItems.contains(itemTemplate->ItemId); + } + + bool isQuestConsumableItem() const + { + const std::unordered_set questConumableItems = this->getQuestConsumableItemsGUIDs(); + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return false; + + return questConumableItems.contains(itemTemplate->ItemId); + } + + bool isRoguePoisonItem() const + { + const std::unordered_set roguePoisonItems = this->getRoguePoisonsItemsGUIDs(); + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return false; + + return roguePoisonItems.contains(itemTemplate->ItemId); + } + + bool isUsefulConsumableItem() const + { + const std::unordered_set usefulConsumableItems = this->getUsefulConsumableItemsGUIDs(); + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return false; + + return usefulConsumableItems.contains(itemTemplate->ItemId); + } + + bool isWarlockItem() const + { + const std::unordered_set warlockItems = this->getWarlockItemsGUIDs(); + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return false; + + return warlockItems.contains(itemTemplate->ItemId); + } + + bool isMageItem() const + { + const std::unordered_set mageItems = this->getMageItemsGUIDs(); + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return false; + + return mageItems.contains(itemTemplate->ItemId); + } + +protected: + + std::unordered_set getForbiddenItemsGUIDs() const + { + return { + 1199, // Charged Soulstone + 1700, // Admin Warlord's Claymore + 1995, // Deprecated Cat's Paw + 3438, // Ankh of Resurrection + 4420, // NPC Equip 4420 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 4423, // NPC Equip 4423 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 4842, // test => Illegal item that should not even be present in the core as it is not present in any WotLK database + 5046, // Locked Gift => Illegal item that should not even be present in the core as it is not present in any WotLK database + 5047, // Skull Wrapping Paper => Illegal item that should not even be present in the core as it is not present in any WotLK database + 5224, // NPC Equip 5224 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 5225, // NPC Equip 5225 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 5378, // Shane Test (DELETE ME) => Illegal item that should not even be present in the core as it is not present in any WotLK database + 6244, // ggggfg => Illegal item that should not even be present in the core as it is not present in any WotLK database + 6638, // Air Sapta => Apparently this sapta is the only one not needed by shamans? + 6852, // Eternal Eye => Quest item seemingly linked to no quest + 6927, // Big Will's Ear => Quest item seemingly linked to no quest. It was supposedly dropped by Big Will but the quest requires killing him without looting him. + 7147, // NPC Equip 7147 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 7168, // NPC Equip 7168 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 7388, // Skull Key => Quest item seemingly linked to no quest + 9232, // NPC Equip 9232 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 9319, // Nimboya's Laden Pike => Quest item seemingly linked to no quest + 10419, // NPC Equip 10419 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 10448, // NPC Equip 10448 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 10449, // NPC Equip 10449 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 10451, // NPC Equip 10451 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 10452, // NPC Equip 10452 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 10453, // NPC Equip 10453 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 11182, // NPC Equip 11182 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 11183, // NPC Equip 11183 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 11616, // DEBUG Samophlange Manual Page + 12246, // NPC Equip 12246 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 12385, // test => Illegal item that should not even be present in the core as it is not present in any WotLK database + 12439, // NPC Equip 12439 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 12441, // NPC Equip 12441 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 13294, // NPC Equip 13294 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 17350, // NPC Equip 17350 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 17729, // NPC Equip 17729 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 18595, // Blood Opal => Item not present in WotLK. + 19063, // NPC Equip 19063 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 19977, // NPC Equip 19977 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 20365, // NPC Equip 20365 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 20386, // NPC Equip 20386 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 20473, // NPC Equip 20473 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 20905, // NPC Equip 20905 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21238, // Winter Veil Cookie UNUSED + 21556, // NPC Equip 21556 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21739, // Lunar Festival Invitation DEBUG + 21832, // NPC Equip 21832 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21834, // NPC Equip 21834 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21922, // NPC Equip 21922 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21961, // NPC Equip 21961 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21965, // NPC Equip 21965 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21966, // NPC Equip 21966 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21967, // NPC Equip 21967 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21968, // NPC Equip 21968 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21969, // NPC Equip 21969 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21970, // NPC Equip 21970 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21971, // NPC Equip 21971 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21972, // NPC Equip 21972 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21973, // NPC Equip 21973 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21974, // NPC Equip 21974 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21976, // NPC Equip 21976 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21977, // NPC Equip 21977 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21978, // NPC Equip 21978 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 22118, // NPC Equip 22118 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 22124, // NPC Equip 22124 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 22125, // NPC Equip 22125 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 22126, // NPC Equip 22126 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 22127, // NPC Equip 22127 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 22129, // NPC Equip 22129 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 22323, // NPC Equip 22323 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 23163, // Performer's Wand => Unobtainable item + 23164, // Bubbly Beverage => Unobtainable item + 23175, // Tasty Summer Treat => Unobtainable item (iCoke promotion) + 23176, // Fizzy Energy Drink => Unobtainable item (iCoke promotion?) + 23209, // NPC Equip 23209 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 23210, // NPC Equip 23210 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 23496, // NPC Equip 23496 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 23640, // NPC Equip 23640 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 23641, // NPC Equip 23641 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 23715, // Permanent Lung Juice Cocktail => Unobtainable item + 23718, // Permanent Ground Scorpok Assay => Unobtainable item + 23719, // Permanent Cerebral Cortex Compound => Unobtainable item + 23721, // Permanent Gizzard Gum => Unobtainable item + 23722, // Permanent R.O.I.D.S. => Unobtainable item + 23794, // Permanent Sheen of Zanza => Unobtainable item + 23795, // Permanent Spirit of Zanza => Unobtainable item + 23796, // Permanent Swiftness of Zanza => Unobtainable item + 23872, // NPC Equip 23872 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 23982, // NPC Equip 23982 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 26046, // NPC Equip 26046 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 26047, // NPC Equip 26047 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 27504, // NPC Equip 27504 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 28036, // NPC Equip 28036 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 28110, // Fat Gnome and Little Elf => Unobtainable item, probably removed due to tasteless reference to a crime against humanity. + 28131, // Reaver Buster Launcher => Seemingly unobtainable item. + 29585, // NPC Equip 29585 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 29805, // Socrethar's Head => TBC Beta quest item, unobtainable. + 29868, // QAEnchant Gloves +26 Attack Power + 29877, // NPC Equip 29877 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 31954, // NPC Equip 31954 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 32424, // NPC Equip 32424 => Wrong item, should be "Blade's Edge Ogre Brew" + 32426, // NPC Equip 32426 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 32669, // NPC Equip 32669 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 32913, // NPC Equip 32913 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33063, // Really Tough Brewfest Bread + 33090, // NPC Equip 33090 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33100, // NPC Equip 33100 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33217, // NPC Equip 33217 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33218, // Goblin Gumbo + 33219, // Goblin Gumbo Kettle + 33570, // NPC Equip 33570 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33572, // NPC Equip 33572 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33573, // NPC Equip 33573 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33574, // NPC Equip 33574 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33600, // NPC Equip 33600 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33601, // NPC Equip 33601 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33602, // NPC Equip 33602 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33603, // NPC Equip 33603 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33623, // NPC Equip 33623 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33624, // NPC Equip 33624 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33625, // NPC Equip 33625 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33626, // NPC Equip 33626 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33785, // NPC Equip 33785 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33786, // NPC Equip 33786 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33787, // NPC Equip 33787 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33788, // NPC Equip 33788 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33800, // NPC Equip 33800 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 34046, // NPC Equip 34046 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 34047, // NPC Equip 34047 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 34048, // NPC Equip 34048 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 34071, // NPC Equip 34071 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 34151, // NPC Equip 34151 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 34152, // NPC Equip 34152 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 34153, // NPC Equip 34153 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 34154, // NPC Equip 34154 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 34155, // NPC Equip 34155 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 34156, // NPC Equip 34156 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 34250, // NPC Equip 34250 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 34251, // NPC Equip 34251 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 34252, // NPC Equip 34252 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 35120, // NPC Equip 35120 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 35667, // NPC Equip 35667 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 38165, // NPC Equip 38165 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 38236, // NPC Equip 38236 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 38685, // NPC Equip 38685 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 38702, // NPC Equip 38702 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 38704, // NPC Equip 38704 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 39163, // Test expire transform + 39600, // NPC Equip 39600 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 40308, // NPC Equip 40308 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 42437, // NPC Equip 42437 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 42764, // NPC Equip 42764 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 44624, // NPC Equip 44624 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 44628, // NPC Equip 44628 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 44630, // NPC Equip 44630 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 44804, // NPC Equip 44804 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 44805, // NPC Equip 44805 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 44807, // Indalamar's Holy Hand Grenade + 44813, // NPC Equip 44813 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 44816, // NPC Equip 44816 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 44832, // Squirt Gun [PH] + 44866, // Faithful Mule + 44867, // NPC Equip 44867 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 44964, // NPC Equip 44964 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 45126, // Trusty Mount [PH] + 46717, // NPC Equip 46717 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 46765, // Blue War Fuel (Mountain Dew Promotion) + 46766, // Red War Fuel (Mountain Dew Promotion) + 48416, // NPC Equip 48416 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 48601, // Red Rider Air Rifle Ammo + 49223, // Permission Slip + 49224, // NPC Equip 49224 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 49225, // NPC Equip 49225 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 49349, // NPC Equip 49349 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 49372, // NPC Equip 49372 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 49373, // Permission Slip + 49374, // NPC Equip 49374 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 49692, // NPC Equip 49692 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 50076, // NPC Equip 50076 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 50091, // NPC Equip 50091 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 50092, // NPC Equip 50092 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 50093, // Pet Prep: A Beginner's Guide + 50164, // NPC Equip 50164 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 52202, // Elemental Sapta + 52361, // NPC Equip 52361 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 53476, // NPC Equip 53476 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 53477, // NPC Equip 53477 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 54647, // NPC Equip 54647 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 54822, // Sen'jin Overcloak + }; + } + + std::unordered_set getUnwantedItemsGUIDs() const + { + return { + 835, // Large Rope Net + 1127, // Flash Bundle + 1176, // Smelling Salts + 1187, // Spiked Collar + 1191, // Bag of Marbles + 1322, // Fishliver Oil + 1434, // Glowing Wax Stick + 1970, // Restoring Balm + 3434, // Slumber Sand + 3456, // Dog Whistle + 4546, // Call of the Raptor + 4598, // Goblin Fishing Pole + 4941, // Really Sticky Glue + 4945, // Faintly Glowing Skull + 4952, // Stormstout + 4953, // Trogg Brew + 5421, // Fiery Blaze Enchantment + 5457, // Severed Voodoo Claw + 5845, // Flank of Meat + 5951, // Moist Towelette + 7516, // Tabetha's Instructions => Bots don't need instructions. + 8410, // R.O.I.D.S. + 8411, // Lung Juice Cocktail + 8412, // Ground Scorpok Assay + 8423, // Cerebral Cortex Compound + 8424, // Gizzard Gum, + 8432, // Eau de Mixilpixil + 10684, // Colossal Parachute + 10830, // M73 Frag Grenade + 12924, // Ritual Candle + 13149, // Eldarathian Tome of Summoning Vol. 1 + 13151, // The Mystic Studies of Hor'ank + 13152, // The Story With No Conclusion + 13153, // Tome of Mal'cin Vorail + 13154, // Jael'marin's Studies of the Arcane + 13508, // Eye of Arachnida + 13509, // Clutch of Foresight + 13514, // Wail of the Banshee + 13813, // Blessed Sunfruit Juice + 14894, // Lily Root + 15723, // Tea with Sugar + 15778, // Mechanical Yeti + 17048, // Rumsey Rum + 18209, // Energized Sparkplug + 18269, // Gordok Green Grog + 18284, // Kreeg's Stout Beatdown + 18297, // Thornling Seed + 19060, // Warsong Gulch Enriched Ration + 19061, // Warsong Gulch Iron Ration + 19062, // Warsong Gulch Field Ration + 19318, // Bottled Alterac Spring Water + 19997, // Harvest Nectar + 20062, // Arathi Basin Enriched Ration + 20063, // Arathi Basin Field Ration + 20064, // Arathi Basin Iron Ration + 20079, // Spirit of Zanza + 20080, // Sheen of Zanza + 20081, // Swiftness of Zanza + 20222, // Defiler's Enriched Ration + 20223, // Defiler's Field Ration + 20224, // Defiler's Iron Ration + 20225, // Highlander's Enriched Ration + 20226, // Highlander's Field Ration + 20227, // Highlander's Iron Ration + 20388, // Lollipop + 20389, // Candy Corn + 20390, // Candy Bar + 20397, // Hallowed Wand - Pirate + 20398, // Hallowed Wand - Ninja + 20399, // Hallowed Wand - Leper Gnome + 20409, // Hallowed Wand - Ghost + 20410, // Hallowed Wand - Bat + 20411, // Hallowed Wand - Skeleton + 20413, // Hallowed Wand - Random + 20414, // Hallowed Wand - Wisp + 20557, // Hallow's End Pumpkin Treat + 21212, // Fresh Holly + 21241, // Winter Veil Eggnog + 21325, // Mechanical Greench + 21537, // Festival Dumplings + 21711, // Lunar Festival Invitation + 21744, // Lucky Rocket Cluster + 21745, // Elder's Moonstone + 21815, // Love Token + 22192, // Bloodkelp Elixir of Dodging + 22193, // Bloodkelp Elixir of Resistance + 22236, // Buttermilk Delight + 22237, // Dark Desire + 22238, // Very Berry Cream + 22239, // Sweet Surprise + 22259, // Unbestowed Friendship Bracelet + 22260, // Friendship Bracelet + 22743, // Bloodsail Sash + 22778, // Scourgebane Infusion + 22779, // Scourgebane Draught + 22795, // Fel Blossom + 23161, // Freshly-Squeezed Lemonade + 23194, // Lesser Mark of the Dawn + 23195, // Mark of the Dawn + 23196, // Greater Mark of the Dawn + 23211, // Toasted Smorc + 23215, // Bag of Smorc Ingredients + 23246, // Fiery Festival Brew + 23326, // Midsummer Sausage + 23327, // Fire-toasted Bun + 23379, // Cinder Bracers + 23435, // Elderberry Pie + 23492, // Suntouched Special Reserve + 23584, // Loch Modan Lager + 23585, // Stouthammer Lite + 23586, // Aerie Peak Pale Ale + 23985, // Crystal of Vitality + 23986, // Crystal of Insight + 23989, // Crystal of Ferocity + 24006, // Grunt's Waterskin + 24007, // Footman's Waterskin + 24408, // Edible Stalks + 24421, // Nagrand Cherry + 24429, // Expedition Flare + 24540, // Edible Fern + 25498, // Rough Stone Statue + 25880, // Coarse Stone Statue + 25881, // Heavy Stone Statue + 25882, // Solid Stone Statue + 25883, // Dense Stone Statue + 25884, // Primal Stone Statue + 27317, // Elemental Sapta + 27553, // Crimson Steer Energy Drink + 29482, // Ethereum Essence + 30309, // Stonebreaker Brew + 30499, // Brightstone Wine + 30615, // Halaani Whiskey + 30858, // Peon Sleep Potion + 31337, // Orb of the Blackwhelp + 31449, // Distilled Stalker Sight + 31450, // Sealth of the Stalker + 31451, // Pure Energy + 31535, // Bloodboil Poison + 32563, // Grilled Picnic Treat + 32971, // Water Bucket + 33023, // Savory Sausage + 33024, // Pickled Sausage + 33025, // Spicy Smoked Sausage + 33026, // The Golden Link + 33028, // Barleybrew Light + 33028, // Barleybrew Dark + 33030, // Barleybrew Clear + 33031, // Thunder 45 + 33032, // Thunderbrew Ale + 33033, // Thunderbrew Stout + 33034, // Gordok Grog + 33035, // Ogre Mead + 33036, // Mudder's Milk + 33043, // The Essential Brewfest Pretzel + 33226, // Tricky Treat + 33234, // Iced Berry Slush + 33236, // Fizzy Faire Drink "Classic" + 33246, // Funnel Cake + 33254, // Afrazi Forest Strider Drumstick + 33312, // Mana Sapphire + 33929, // Brewfest Brew + 33956, // Harkor's Home Brew + 34017, // Small Step Brew + 34018, // Long Stride Brew + 34019, // Path of Brew + 34020, // Jungle River Water + 34021, // Brewdo Magic + 34022, // Stout Shrunken Head + 34044, // B-Ball + 34063, // Dried Sausage + 34064, // Succulent Sausage + 34065, // Spiced Onion Cheese + 34068, // Weighted Jack-o'-Lantern + 34077, // Crudely Wrapped Gift + 34410, // Honeyed Holiday Ham + 34412, // Sparkling Apple Cider + 34599, // Juggling Torch + 35223, // Papa Hummel's Old-Fashioned Pet Biscuit + 35946, // Fizzcrank Practice Parachute + 36877, // Folded Letter + 37431, // Fetch Ball + 37488, // Wild Winter Pilsner + 37489, // Izzard's Ever Flavor + 37490, // Aromatic Honey Brew + 37491, // Metok's Bubble Bock + 37492, // Springtime Stout + 37493, // Blackrock Lager + 37494, // Stranglethorn Brew + 37495, // Draenic Pale Ale + 37496, // Binary Brew + 37497, // Autumnal Acorn Ale + 37498, // Bartlett's Bitter Brew + 37499, // Lord of Frost's Private Label + 37582, // Pyroblast Cinnamon Ball + 37583, // G.N.E.R.D.S. + 37584, // Soothing Spearmint Candy + 37585, // Chewy Fel Taffy + 37604, // Tooth Pick + 37750, // Fresh Brewfest Hops + 37863, // Direbrew's Remote + 37878, // Worg's Blood Elixir + 37898, // Wild Winter Pilsner + 37899, // Izzard's Ever Flavor + 37900, // Aromatic Honey Brew + 37901, // Metok's Bubble Bock + 37902, // Springtime Stout + 37903, // Blackrock Lager + 37904, // Stranglethorn Brew + 37905, // Draenic Pale Ale + 37906, // Binary Brew + 37907, // Autumnal Acorn Ale + 37908, // Bartlett's Bitter Brew + 37909, // Lord of Frost's Private Label + 37925, // Experimental Mixture + 38291, // Ethereal Mutagen + 38294, // Ethereal Liqueur + 38300, // Diluted Ethereum Essence + 38320, // Dire Brew + 38518, // Cro's Apple + 38577, // Party G.R.E.N.A.D.E. + 38587, // Empty Brewfest Stein + 38626, // Empty Brew Bottle + 39476, // Fresh Goblin Brewfest Hops + 39477, // Fresh Dwarven Brewfest Hops + 39738, // Thunderbrew's Hard Ale + 42342, // Bag of Popcorn + 42350, // Bag of Peanuts + 42381, // Anguish Ale + 42436, // Chocolate Celebration Cake + 42438, // Lovely Cake + 42439, // Big Berry Pie + 43088, // Dalaran Apple Bowl + 43135, // Fate Rune of Fleet Feet + 43352, // Pet Grooming Kit + 43462, // Airy Pale Ale + 43470, // Worg Tooth Oatmeal Stout + 43471, // Rork Red Ribbon + 43472, // Snowfall Lager + 43473, // Drakefire Chile Ale + 43489, // Mohawk Grenade + 43626, // Happy Pet Snack + 44064, // Nepeta Leaf + 44065, // Oracle Secret Solution + 44435, // Windle's Lighter + 44481, // Grindgear Toy Gorilla + 44482, // Trusty Copper Racer + 44599, // Zippy Copper Racer + 44601, // Heavy Copper Racer + 44610, // Fresh Dalaran Bread + 44612, // Dalaran Swiss Wheel + 44613, // Aged Dalaran Sharp Wheel + 44621, // Bottle of Dalaran White + 44622, // Cask of Dalaran White + 44623, // Bottle of Dalaran Red + 44625, // Bottle of Aged Dalaran Red + 44626, // Cask of Aged Dalaran Red + 44627, // Bottle of Peaked Dalaran Red + 44629, // Cask of Peaked Dalaran Red + 44632, // Cask of Dalaran Red + 44698, // Intravenous Healing Potion + 44716, // Mysterious Fermented Liquid + 44792, // Blossoming Branch + 44812, // Turkey Shooter + 44817, // The Mischief Maker + 44818, // Noblegarden Egg + 44844, // Turkey Caller + 44849, // Tiny Green Ragdoll + 44943, // Icy Prism + 45047, // Sandbox Tiger + 46319, // Tournament Brew + 46399, // Thunder's Plunder + 46400, // Barleybrew Gold + 46401, // Crimson Stripe + 46402, // Promise of the Pandaren + 46403, // Chuganpug's Delight + 46711, // Spirit Candle + 46718, // Orange Marigold + 46725, // Red Rider Air Rifle + 46783, // Pink Gumball + 49288, // Little Ivory Raptor Whistle + 49289, // Little White Stallion Bridle + 49856, // "VICTORY" Perfume + 49857, // "Enchantress" Perfume + 49858, // "Forever" Perfume + 49859, // "Bravado" Cologne + 49860, // "Wizardry" Cologne + 49861, // "STALWART" Cologne + 49936, // Lovely Stormwind Card + 49937, // Lovely Undercity Card + 49938, // Lovely Darnassus Card + 49939, // Lovely Orgrimmar Card + 49940, // Lovely Ironforge Card + 49941, // Lovely Thunder Bluff Card + 49942, // Lovely Exodar Card + 49943, // Lovely Silvermoon City Card + 50163, // Lovely Rose + 54455, // Paint Bomb + }; + } + + std::unordered_set getQuestConsumableItemsGUIDs() const + { + return { + 1262, // Keg of Thunderbrew Lager + 5880, // Crate With Holes + 6074, // War Horn Mouthpiece + 6464, // Wailing Essence + 6486, // Singed Scale + 6635, // Earth Sapta + 6636, // Fire Sapta + 6637, // Water Sapta + 6781, // Bartleby's Mug + 6782, // Marshal Haggard's Badge + 6812, // Case of Elunite + 6841, // Vial of Phlogiston + 6842, // Furen's Instructions + 6851, // Essence of the Exile + 6926, // Furen's Notes + 6929, // Bath'rah's Parchment + 7127, // Powdered Azurite + 7227, // Balnir Snapdragons + 7266, // Ur's Treatise on Shadow Magic + 7627, // Dolanaar Delivery + 7629, // Ukor's Burden + 7970, // E.C.A.C. + 8048, // Emerald Dreamcatcher + 8095, // Hinott's Oil + 8548, // Divino-matic Rod + 9546, // Simple Scroll + 9569, // Hallowed Scroll + 10621, // Runed Scroll + 10663, // Essence of Hakkar + 10687, // Empty Vial Labeled #1 + 10688, // Empty Vial Labeled #2 + 10689, // Empty Vial Labeled #3 + 10690, // Empty Vial Labeled #4 + 11148, // Samophlange Manual Page + 11405, // Giant Silver Vein + 11413, // Nagmara's Filled Vial + 11914, // Empty Cursed Ooze Jar + 11948, // Empty Tainted Ooze Jar + 11953, // Empty Pure Sample Jar + 12533, // Roughshod Pike + 12650, // Attuned Dampener + 12712, // Warosh's Mojo + 12884, // Arnak's Hoof + 12885, // Pamela's Doll + 12886, // Pamela's Doll's Head + 12894, // Joseph's Wedding Ring + 12922, // Empty Canteen + 13155, // Resonating Skull + 13156, // Mystic Crystal + 13562, // Remains of Trey Lightforge + 13703, // Kodo Bone + 13761, // Frozen Eggs + 14542, // Kravel's Crate + 15314, // Bundle of Relics + 16282, // Bundle of Hides + 20470, // Solanian's Scrying Orb + 20471, // Scroll of Scourge Magic + 20472, // Solanian's Journal + 23361, // Cleansing Vial + 23417, // Sanctified Crystal + 23645, // Seer's Relic + 24330, // Drain Schematics + 24355, // Ironvine Seeds + 24407, // Uncatalogued Species + 24474, // Violet Scrying Crystal + 25465, // Stormcrow Amulet + 28038, // Seaforium PU-36 Explosive Nether Modulator + 28132, // Area 52 Special + 28513, // Demonic Rune Stone + 28554, // Shredder Spare Parts + 28571, // Blank Scroll + 28580, // B'naar Console Transcription + 28607, // Sunfury Disguise + 28635, // Sunfury Arcanist Robes + 28636, // Sunfury Researcher Gloves + 28637, // Sunfury Guardsman Medallion + 28784, // Unyielding Banner Scrap => Maybe unused quest item? + 29162, // Galaxis Soul Shard + 29324, // Warp-Attuned Orb + 29443, // Bloodmaul Brutebane Brew + 29624, // First Half of Socrethar's Stone + 29625, // Second Half of Socrethar's Stone + 29699, // Socrethar's Teleportation Stone + 29778, // Phase Disruptor + 29796, // Socrethar's Teleportation Stone + 29905, // Kael's Vial Remnant + 29906, // Vashj's Vial Remnant + 30260, // Voren'thal's Package + 30540, // Tally's Waiver (Unsigned) + 30811, // Scroll of Demonic Unbanishing + 31121, // Costume Scraps + 31122, // Overseer Disguise + 31495, // Grishnath Orb + 31517, // Dire Pinfeather + 31518, // Exorcism Feather + 31702, // Challenge from the Horde + 31795, // Draenei Prayer Beads + 32406, // Skyguard Blasting Charges + 32602, // Crystalforged Darkrune + 32848, // Explosives Package + 33079, // Murloc Costume + 33099, // Intact Plague Container + 33277, // Tome of Thomas Thomson + 33349, // Plague Vials + 33614, // Empty Apothecary's Flask => Possibly unaccessible to players but still linked to a quest. + 33615, // Flask of Vrykul Blood => Possibly unaccessible to players but still linked to a quest. + 33616, // Unstable Mix => Possibly unaccessible to players but still linked to a quest. + 33617, // Balanced Concoction => Possibly unaccessible to players but still linked to a quest. + 33619, // Lysander's Strain + 33621, // Plague Spray + 33797, // Portable Brewfest Keg + 34023, // Empty Apothecary's Flask + 34024, // Flask of Vrykul Blood + 34076, // Fish Bladder + 34475, // Arcane Charges + 35704, // Incendiary Explosives + 37173, // Geomancer's Orb + 37198, // Prototype Neural Needler + 37265, // Tua'kea's Breathing Bladder + 37661, // Gossamer Potion + 37877, // Silver Feather + 38629, // Orders from the Lich King + 38657, // Freya's Ward + 39698, // Light-infused Artifact + 40390, // Vic's Emergency Air Tank + 40482, // Dual-plagued Brain + 40725, // Steam-Powered Auctioneer + 44576, // Bright Flare + 44806, // Brightly Colored Shell Fragment + 45784, // Thorim's Sigil + 45786, // Hodir's Sigil + 45787, // Mimiron's Sigil + 45788, // Freya's Sigil + 45791, // Sigils of the Watchers + 45814, // Freya's Sigil + 45815, // Hodir's Sigil + 45816, // Mimiron's Sigil + 45817, // Thorim's Sigil + 45855, // Sigils of the Watchers + }; + } + + std::unordered_set getRoguePoisonsItemsGUIDs() const + { + return { + 2892, // Deadly Poison + 2893, // Deadly Poison II + 3775, // Crippling Poison + 3776, // Crippling Poison II + 5237, // Mind-numbing Poison + 6947, // Instant Poison + 6949, // Instant Poison II + 6950, // Instant Poison III + 6951, // Mind-numbing Poison II => Useless in WotLK but useful in earlier expansions, kept for IP use. + 8926, // Instant Poison IV + 8927, // Instant Poison V + 8928, // Instant Poison VI + 8984, // Deadly Poison III + 8985, // Deadly Poison IV + 9186, // Mind-numbing Poison III => Useless in WotLK but useful in earlier expansions, kept for IP use. + 10918, // Wound Poison + 10920, // Wound Poison II + 10921, // Wound Poison III + 10922, // Wound Poison IV + 20844, // Deadly Poison V + 21835, // Anesthetic Poison + 21927, // Instant Poison VII + 22053, // Deadly Poison VI + 22054, // Deadly Poison VII + 22055, // Wound Poison V + }; + } + + std::unordered_set getUsefulConsumableItemsGUIDs() const + { + return { + 18606, // Alliance Battle Standard + 18607, // Horde Battle Standard + 19045, // Stormpike Battle Standard + 19046, // Frostwolf Battle Standard + 19150, // Sentinel Basic Care Package + 19151, // Sentinel Standard Care Package + 19152, // Sentinel Advanced Care Package + 19153, // Outrider Advanced Care Package + 19154, // Outrider Basic Care Package + 19155, // Outrider Standard Care Package + 19182, // Darkmoon Faire Prize Ticket + 19425, // Mysterious Lockbox + 20228, // Defiler's Advanced Care Package + 20229, // Defiler's Basic Care Package + 20230, // Defiler's Standard Care Package + 20231, // Arathor Advanced Care Package + 20233, // Arathor Basic Care Package + 20236, // Arathor Standard Care Package + 21740, // Small Rocket Recipes + 21741, // Cluster Rocket Recipes + 21742, // Large Rocket Recipes + 21743, // Large Cluster Rocket Recipes + 21746, // Lucky Red Envelope + 24140, // Blackened Urn => Useless in WotLK but useful in earlier expansions, kept for IP use. + 24289, // Chrono-beacon + 24494, // Tears of the Goddess + 24520, // Honor Hold Favor + 24522, // Thrallmar Favor + 24579, // Mark of Honor Hold + 24581, // Mark of Thrallmar + 27388, // Mr. Pinchy + 29735, // Holy Dust + 30690, // Power Converter + 32408, // Naj'entus Spine + 32542, // Imp in a Ball + 33865, // Amani Hex Stick + 33926, // Sealed Scroll Case + 33927, // Brewfest Pony Keg + 33928, // Hollowed Bone Decanter + 34583, // Aldor Supplies Package + 34584, // Scryer Supplies Package + 34585, // Scryer Supplies Package + 34587, // Aldor Supplies Package + 34592, // Aldor Supplies Package + 34593, // Scryer Supplies Package + 34594, // Scryer Supplies Package + 34595, // Aldor Supplies Package + 35232, // Shattered Sun Supplies + 34686, // Brazier of Dancing Flames + 34850, // Midsummer Ground Flower + 35512, // Pocket Full of Snow + 35945, // Brilliant Glass + 36748, // Dark Brewmaiden's Brew + 36862, // Worn Troll Dice + 36863, // Decahedral Dwarven Dice + 37815, // Emerald Essence + 37859, // Amber Essence + 37860, // Ruby Essence + 38186, // Ethereal Credit + 38233, // Path of Illidan + 39878, // Mysterious Egg + 39883, // Cracked Egg + 40110, // Haunted Memento + 41426, // Magically Wrapped Gift + 44113, // Small Spice Bag + 44606, // Toy Train Set + 44717, // Disgusting Jar + 44718, // Ripe Disgusting Jar + 44751, // Hyldnir Spoils + 45011, // Stormwind Banner + 45013, // Thunder Bluff Banner + 45014, // Orgrimmar Banner + 45015, // Sen'jin Banner + 45016, // Undercity Banner + 45017, // Silvermoon City Banner + 45018, // Ironforge Banner + 45019, // Gnomeregan Banner + 45020, // Exodar Banner + 45021, // Darnassus Banner + 45038, // Fragment of Val'anyr + 45039, // Shattered Fragments of Val'anyr + 45057, // Wind-Up Train Wrecker + 45063, // Foam Sword Rack + 45506, // Archivum Data Disc + 45705, // Argent Tournament Invitation + 45798, // Heroic Celestial Planetarium Key + 45857, // Archivum Data Disc + 45896, // Unbound Fragments of Val'anyr + 45897, // Reforged Hammer of Ancient Kings + 46029, // Magnetic Core + 46779, // Path of Cenarius + 46780, // Ogre Pinata + 46843, // Argent Crusader's Banner + 46847, // Seaforium Bombs + 47030, // Huge Seaforium Bombs + 47541, // Argent Pony Bridle + 49631, // Standard Apothecary Serving Kit + 50307, // Infernal Spear + 50471, // The Heartbreaker + 54212, // Instant Statue Pedestal + 54437, // Tiny Green Ragdoll + 54438, // Tiny Blue Ragdoll + 54651, // Gnomeregan Pride + 54653, // Darkspear Pride + }; + } + + std::unordered_set getWarlockItemsGUIDs() const + { + return { + 5232, // Minor Soulstone + 16892, // Lesser Soulstone + 16893, // Soulstone + 16895, // Greater Soulstone + 16896, // Major Soulstone + 22116, // Master Soulstone + 36895, // Demonic Soulstone + }; + } + + std::unordered_set getMageItemsGUIDs() const + { + return { + 5513, // Mana Jade + 8007, // Mana Citrine + 8008, // Mana Ruby + 22044, // Mana Emerald + 36799, // Mana Gem + }; + } +}; diff --git a/src/domain/item/inspector/consumable/elixir/ConsumableElixirInspector.h b/src/domain/item/inspector/consumable/elixir/ConsumableElixirInspector.h new file mode 100644 index 0000000000..89a0313517 --- /dev/null +++ b/src/domain/item/inspector/consumable/elixir/ConsumableElixirInspector.h @@ -0,0 +1,82 @@ +#pragma once + +#include + +#include "ItemTemplate.h" + +#include "AbstractConsumableInspector.h" +#include "ItemActionStruct.h" +#include "ItemActionEnum.h" + +class ConsumableElixirInspector : public AbstractConsumableInspector +{ +public: + ConsumableElixirInspector( + uint64_t playerLowGUID, + uint64_t itemLowGUID + ) : AbstractConsumableInspector(playerLowGUID, itemLowGUID) + {} + + bool isInspectable() const override + { + const uint8_t itemSubclass = this->getCurrentItemSubclass(); + + return AbstractConsumableInspector::isInspectable() && itemSubclass == ITEM_SUBCLASS_ELIXIR; + } + + ItemActionStruct determineItemAction() const override + { + if (!this->isInspectable()) + return this->getDefaultItemAction(); + + if (this->isForbiddenItem()) + return this->getForbiddenItemAction(); + + const uint32_t maxStackSize = this->getItemMaxStackSize(); + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return this->getDefaultItemAction(); + + const ObjectGuid playerGUID = ObjectGuid::Create(this->playerLowGUID); + Player* player = ObjectAccessor::FindPlayer(playerGUID); + + if (player == nullptr) + return this->getDefaultItemAction(); + + const uint32_t totalQuantity = player->GetItemCount(itemTemplate->ItemId); + const ItemTemplate* const refreshedItemTemplate = this->getCurrentItemTemplate(); + + if (refreshedItemTemplate == nullptr) + return this->getDefaultItemAction(); + + if (totalQuantity < maxStackSize) + return { + .action = ItemActionEnum::NONE, + .bagSlot = 0, + .containerSlot = 0, + .equipmentSlot = 0 + }; + + return this->getSellAction(); + } + + bool isForbiddenItem() const + { + const std::unordered_set forbiddenItems = this->getForbiddenItemsGUIDs(); + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return false; + + return forbiddenItems.contains(itemTemplate->ItemId); + } + +protected: + + const std::unordered_set getForbiddenItemsGUIDs() const + { + return {}; + } + +}; diff --git a/src/domain/item/inspector/consumable/potion/ConsumablePotionInspector.h b/src/domain/item/inspector/consumable/potion/ConsumablePotionInspector.h new file mode 100644 index 0000000000..57e23ba035 --- /dev/null +++ b/src/domain/item/inspector/consumable/potion/ConsumablePotionInspector.h @@ -0,0 +1,98 @@ +#pragma once + +#include + +#include "SharedDefines.h" +#include "ItemTemplate.h" + +#include "AbstractConsumableInspector.h" +#include "ItemActionStruct.h" +#include "ItemActionEnum.h" +#include "GlobalPlayerInspector.h" + +class ConsumablePotionInspector : public AbstractConsumableInspector +{ +public: + ConsumablePotionInspector( + uint64_t playerLowGUID, + uint64_t itemLowGUID + ) : AbstractConsumableInspector(playerLowGUID, itemLowGUID) + {} + + bool isInspectable() const + { + const uint8_t itemSubclass = this->getCurrentItemSubclass(); + + return AbstractConsumableInspector::isInspectable() && itemSubclass == ITEM_SUBCLASS_POTION; + } + + ItemActionStruct determineItemAction() const + { + if (!this->isInspectable()) + return this->getDefaultItemAction(); + + if (this->isForbiddenItem()) + return this->getForbiddenItemAction(); + + const uint32_t maxStackSize = this->getItemMaxStackSize(); + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return this->getDefaultItemAction(); + + const ObjectGuid playerGUID = ObjectGuid::Create(this->playerLowGUID); + Player* player = ObjectAccessor::FindPlayer(playerGUID); + + if (player == nullptr) + return this->getDefaultItemAction(); + + const uint32_t totalQuantity = player->GetItemCount(itemTemplate->ItemId); + + if (totalQuantity < maxStackSize) + return { + .action = ItemActionEnum::NONE, + .bagSlot = 0, + .containerSlot = 0, + .equipmentSlot = 0 + }; + + return this->getSellAction(); + } + + bool isForbiddenItem() const + { + const std::unordered_set forbiddenItems = this->getForbiddenItemsGUIDs(); + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return false; + + return forbiddenItems.contains(itemTemplate->ItemId); + } + +protected: + + const std::unordered_set getForbiddenItemsGUIDs() const + { + return { + 2461, // Deprecated Elemental Resistance Potion + 2462, // Deprecated Potion of Lesser Invulnerability (Fix) + 5632, // Deprecated Cowardly Flight Potion + 23578, // Diet McWeaksauce + 23579, // The McWeaksauce Classic + 23696, // [PH] Potion of Heightened Senses [DEP] + 23698, // [PH] Nature Resist Potion [DEP] + 30793, // NPC Equip 30793 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 32762, // Rulkster's Brain Juice + 32763, // Rulkster's Secret Sauce + 34646, // NPC Equip 34646 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 37926, // NPC Equip 37926 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 39971, // NPC Equip 39971 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 40677, // NPC Equip 40677 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 42548, // NPC Equip 42548 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 45276, // Jillian's Genius Juice + 45277, // Jillian's Savior Sauce + }; + } + +}; diff --git a/src/domain/item/inspector/container/ContainerInspector.h b/src/domain/item/inspector/container/ContainerInspector.h new file mode 100644 index 0000000000..1fd7b4bae0 --- /dev/null +++ b/src/domain/item/inspector/container/ContainerInspector.h @@ -0,0 +1,113 @@ +#pragma once + +#include + +#include "SharedDefines.h" +#include "ItemTemplate.h" + +#include "AbstractItemInspector.h" +#include "ItemActionStruct.h" +#include "ItemActionEnum.h" +#include "GlobalPlayerInspector.h" + +class ContainerInspector : public AbstractItemInspector +{ +public: + ContainerInspector( + uint64_t playerLowGUID, + uint64_t itemLowGUID + ) : AbstractItemInspector(playerLowGUID, itemLowGUID) + {} + + bool isInspectable() const override + { + const uint8_t itemSubclass = this->getCurrentItemSubclass(); + + return AbstractItemInspector::isInspectable() && itemSubclass == ITEM_SUBCLASS_CONTAINER; + } + + ItemActionStruct determineItemAction() const override + { + if (!this->isInspectable()) + return this->getDefaultItemAction(); + + if (this->isForbiddenItem()) + return this->getForbiddenItemAction(); + + const ItemTemplate* itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return this->getDestroyItemAction(); + + const GlobalPlayerInspector playerInspector(this->playerLowGUID); + + const uint8_t playerClass = playerInspector.getCurrentPlayerClass(); + const uint32_t inventoryType = itemTemplate->InventoryType; + + // @TODO: Add hunter quiver equipment decision (NOT process) here. + if (inventoryType == INVTYPE_QUIVER && playerClass != CLASS_HUNTER) + return this->getSellAction(); + + const Item* item = this->getCurrentItem(); + + if (item == nullptr) + return this->getKeepItemAction(); + + const Bag* bag = item->ToBag(); + + if (bag == nullptr) + return this->getKeepItemAction(); + + const uint8_t bagSize = bag->GetBagSize(); + + for (uint8_t i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) + { + const Item* const equippedItem = playerInspector.getItemByPosition(INVENTORY_SLOT_BAG_0, i); + + if (equippedItem == nullptr) + return { + .action = ItemActionEnum::EQUIP, + .bagSlot = this->getBagSlot(), + .containerSlot = this->getItemSlot(), + .equipmentSlot = i + }; + + const Bag* const equippedBag = equippedItem->ToBag(); + + if (equippedBag == nullptr) + return this->getKeepItemAction(); + + const uint8_t equippedBagSize = equippedBag->GetBagSize(); + + if (equippedBagSize < bagSize) + return { + .action = ItemActionEnum::EQUIP, + .bagSlot = this->getBagSlot(), + .containerSlot = this->getItemSlot(), + .equipmentSlot = i + }; + } + + return this->getSellAction(); + } + + bool isForbiddenItem() const + { + const std::unordered_set forbiddenItems = this->getForbiddenItemsGUIDs(); + + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return false; + + return forbiddenItems.contains(itemTemplate->ItemId); + } + +protected: + + std::unordered_set getForbiddenItemsGUIDs() const + { + return {}; + } + +}; diff --git a/src/domain/item/inspector/gem/GemInspector.h b/src/domain/item/inspector/gem/GemInspector.h new file mode 100644 index 0000000000..89490de86c --- /dev/null +++ b/src/domain/item/inspector/gem/GemInspector.h @@ -0,0 +1,57 @@ +#pragma once + +#include + +#include "SharedDefines.h" +#include "ItemTemplate.h" + +#include "AbstractItemInspector.h" +#include "ItemActionStruct.h" +#include "ItemActionEnum.h" + +class GemInspector : public AbstractItemInspector +{ +public: + GemInspector( + uint64_t playerLowGUID, + uint64_t itemLowGUID + ) : AbstractItemInspector(playerLowGUID, itemLowGUID) + {} + + bool isInspectable() const override + { + const uint8_t itemClass = this->getCurrentItemClass(); + + return AbstractItemInspector::isInspectable() && itemClass == ITEM_CLASS_GEM; + } + + ItemActionStruct determineItemAction() const override + { + if (!this->isInspectable()) + return this->getDefaultItemAction(); + + if (this->isForbiddenItem()) + return this->getForbiddenItemAction(); + + return this->getSellAction(); + } + + bool isForbiddenItem() const + { + const std::unordered_set forbiddenItems = this->getForbiddenItemsGUIDs(); + + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return false; + + return forbiddenItems.contains(itemTemplate->ItemId); + } + +protected: + + const std::unordered_set getForbiddenItemsGUIDs() const + { + return {}; + } +}; diff --git a/src/domain/item/inspector/generic/GenericItemInspector.h b/src/domain/item/inspector/generic/GenericItemInspector.h new file mode 100644 index 0000000000..ea9d9a4a48 --- /dev/null +++ b/src/domain/item/inspector/generic/GenericItemInspector.h @@ -0,0 +1,56 @@ +#pragma once + +#include + +#include "SharedDefines.h" +#include "ItemTemplate.h" + +#include "AbstractItemInspector.h" +#include "ItemActionStruct.h" +#include "ItemActionEnum.h" + +class GenericItemInspector : public AbstractItemInspector +{ +public: + GenericItemInspector( + uint64_t playerLowGUID, + uint64_t itemLowGUID + ) : AbstractItemInspector(playerLowGUID, itemLowGUID) + {} + + bool isInspectable() const override + { + const uint8_t itemClass = this->getCurrentItemClass(); + + return AbstractItemInspector::isInspectable() && itemClass == ITEM_CLASS_GENERIC; + } + + ItemActionStruct determineItemAction() const override + { + if (!this->isInspectable()) + return this->getDefaultItemAction(); + + if (this->isForbiddenItem()) + return this->getForbiddenItemAction(); + + return this->getSellAction(); + } + + bool isForbiddenItem() const + { + const std::unordered_set forbiddenItems = this->getForbiddenItemsGUIDs(); + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return false; + + return forbiddenItems.contains(itemTemplate->ItemId); + } + +protected: + + const std::unordered_set getForbiddenItemsGUIDs() const + { + return {}; + } +}; diff --git a/src/domain/item/inspector/global/GlobalItemInspector.h b/src/domain/item/inspector/global/GlobalItemInspector.h new file mode 100644 index 0000000000..dad0d1b7ea --- /dev/null +++ b/src/domain/item/inspector/global/GlobalItemInspector.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +#include "SharedDefines.h" +#include "ItemTemplate.h" + +#include "AbstractItemInspector.h" +#include "ItemActionStruct.h" +#include "ItemActionEnum.h" + +class GlobalItemInspector : public AbstractItemInspector +{ +public: + GlobalItemInspector( + uint64_t playerLowGUID, + uint64_t itemLowGUID + ) : AbstractItemInspector(playerLowGUID, itemLowGUID) + {} +}; diff --git a/src/domain/item/inspector/glyph/GlyphInspector.h b/src/domain/item/inspector/glyph/GlyphInspector.h new file mode 100644 index 0000000000..0efaccaa61 --- /dev/null +++ b/src/domain/item/inspector/glyph/GlyphInspector.h @@ -0,0 +1,57 @@ +#pragma once + +#include + +#include "SharedDefines.h" +#include "ItemTemplate.h" + +#include "AbstractItemInspector.h" +#include "ItemActionStruct.h" +#include "ItemActionEnum.h" + +class GlyphInspector : public AbstractItemInspector +{ +public: + GlyphInspector( + uint64_t playerLowGUID, + uint64_t itemLowGUID + ) : AbstractItemInspector(playerLowGUID, itemLowGUID) + {} + + bool isInspectable() const override + { + const uint8_t itemClass = this->getCurrentItemClass(); + + return AbstractItemInspector::isInspectable() && itemClass == ITEM_CLASS_GLYPH; + } + + ItemActionStruct determineItemAction() const override + { + if (!this->isInspectable()) + return this->getDefaultItemAction(); + + if (this->isForbiddenItem()) + return this->getForbiddenItemAction(); + + return this->getSellAction(); + } + + bool isForbiddenItem() const + { + const std::unordered_set forbiddenItems = this->getForbiddenItemsGUIDs(); + + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return false; + + return forbiddenItems.contains(itemTemplate->ItemId); + } + +protected: + + const std::unordered_set getForbiddenItemsGUIDs() const + { + return {}; + } +}; diff --git a/src/domain/item/inspector/key/KeyInspector.h b/src/domain/item/inspector/key/KeyInspector.h new file mode 100644 index 0000000000..0bc61be391 --- /dev/null +++ b/src/domain/item/inspector/key/KeyInspector.h @@ -0,0 +1,57 @@ +#pragma once + +#include + +#include "SharedDefines.h" +#include "ItemTemplate.h" + +#include "AbstractItemInspector.h" +#include "ItemActionStruct.h" +#include "ItemActionEnum.h" + +class KeyInspector : public AbstractItemInspector +{ +public: + KeyInspector( + uint64_t playerLowGUID, + uint64_t itemLowGUID + ) : AbstractItemInspector(playerLowGUID, itemLowGUID) + {} + + bool isInspectable() const override + { + const uint8_t itemClass = this->getCurrentItemClass(); + + return AbstractItemInspector::isInspectable() && itemClass == ITEM_CLASS_KEY; + } + + ItemActionStruct determineItemAction() const override + { + if (!this->isInspectable()) + return this->getDefaultItemAction(); + + if (this->isForbiddenItem()) + return this->getForbiddenItemAction(); + + return this->getKeepItemAction(); + } + + bool isForbiddenItem() const + { + const std::unordered_set forbiddenItems = this->getForbiddenItemsGUIDs(); + + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return false; + + return forbiddenItems.contains(itemTemplate->ItemId); + } + +protected: + + const std::unordered_set getForbiddenItemsGUIDs() const + { + return {}; + } +}; diff --git a/src/domain/item/inspector/miscellaneous/MiscellaneousItemInspector.h b/src/domain/item/inspector/miscellaneous/MiscellaneousItemInspector.h new file mode 100644 index 0000000000..f178f4b14d --- /dev/null +++ b/src/domain/item/inspector/miscellaneous/MiscellaneousItemInspector.h @@ -0,0 +1,56 @@ +#pragma once + +#include + +#include "SharedDefines.h" +#include "ItemTemplate.h" + +#include "AbstractItemInspector.h" +#include "ItemActionStruct.h" +#include "ItemActionEnum.h" + +class MiscellaneousItemInspector : public AbstractItemInspector +{ +public: + MiscellaneousItemInspector( + uint64_t playerLowGUID, + uint64_t itemLowGUID + ) : AbstractItemInspector(playerLowGUID, itemLowGUID) + {} + + bool isInspectable() const override + { + const uint8_t itemClass = this->getCurrentItemClass(); + + return AbstractItemInspector::isInspectable() && itemClass == ITEM_CLASS_MISC; + } + + ItemActionStruct determineItemAction() const override + { + if (!this->isInspectable()) + return this->getDefaultItemAction(); + + if (this->isForbiddenItem()) + return this->getForbiddenItemAction(); + + return this->getSellAction(); + } + + bool isForbiddenItem() const + { + const std::unordered_set forbiddenItems = this->getForbiddenItemsGUIDs(); + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return false; + + return forbiddenItems.contains(itemTemplate->ItemId); + } + +protected: + + const std::unordered_set getForbiddenItemsGUIDs() const + { + return {}; + } +}; diff --git a/src/domain/item/inspector/money/MoneyInspector.h b/src/domain/item/inspector/money/MoneyInspector.h new file mode 100644 index 0000000000..4cbd3fe84f --- /dev/null +++ b/src/domain/item/inspector/money/MoneyInspector.h @@ -0,0 +1,65 @@ +#pragma once + +#include + +#include "SharedDefines.h" +#include "ItemTemplate.h" + +#include "AbstractItemInspector.h" +#include "ItemActionStruct.h" +#include "ItemActionEnum.h" + +class MoneyInspector : public AbstractItemInspector +{ +public: + MoneyInspector( + uint64_t playerLowGUID, + uint64_t itemLowGUID + ) : AbstractItemInspector(playerLowGUID, itemLowGUID) + {} + + bool isInspectable() const override + { + const uint8_t itemClass = this->getCurrentItemClass(); + + return AbstractItemInspector::isInspectable() && itemClass == ITEM_CLASS_MONEY; + } + + ItemActionStruct determineItemAction() const override + { + if (!this->isInspectable()) + return this->getDefaultItemAction(); + + if (this->isForbiddenItem()) + return this->getForbiddenItemAction(); + + return this->getKeepItemAction(); + } + + bool isForbiddenItem() const + { + const std::unordered_set forbiddenItems = this->getForbiddenItemsGUIDs(); + + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return false; + + return forbiddenItems.contains(itemTemplate->ItemId); + } + +protected: + + const std::unordered_set getForbiddenItemsGUIDs() const + { + return { + 37711, // Currency Token Test Token 1 + 37742, // Currency Token Test Token 2 + 38644, // Currency Token Test Token 3 + 41749, // Birmingham Test Item 3 + 43308, // Honor Points (item, not the real currency) + 43949, // zzzOLDDaily Quest Faction Token + 44209, // NPC Equip 44209 => Illegal item that should not even be present in the core as it is not present in any WotLK database + }; + } +}; diff --git a/src/domain/item/inspector/permanent/PermanentItemInspector.h b/src/domain/item/inspector/permanent/PermanentItemInspector.h new file mode 100644 index 0000000000..b2a42aaf84 --- /dev/null +++ b/src/domain/item/inspector/permanent/PermanentItemInspector.h @@ -0,0 +1,43 @@ +#pragma once + +#include + +#include "SharedDefines.h" +#include "ItemTemplate.h" + +#include "AbstractItemInspector.h" +#include "ItemActionStruct.h" +#include "ItemActionEnum.h" + +class PermanentItemInspector : public AbstractItemInspector +{ +public: + PermanentItemInspector( + uint64_t playerLowGUID, + uint64_t itemLowGUID + ) : AbstractItemInspector(playerLowGUID, itemLowGUID) + {} + + bool isInspectable() const override + { + const uint8_t itemClass = this->getCurrentItemClass(); + + return AbstractItemInspector::isInspectable() && itemClass == ITEM_CLASS_PERMANENT; + } + + ItemActionStruct determineItemAction() const override + { + if (!this->isInspectable()) + return this->getDefaultItemAction(); + + if (this->isForbiddenItem()) + return this->getForbiddenItemAction(); + + return this->getSellAction(); + } + + bool isForbiddenItem() const + { + return true; + } +}; diff --git a/src/domain/item/inspector/projectile/ProjectItemInspector.h b/src/domain/item/inspector/projectile/ProjectItemInspector.h new file mode 100644 index 0000000000..02985b1b2d --- /dev/null +++ b/src/domain/item/inspector/projectile/ProjectItemInspector.h @@ -0,0 +1,67 @@ +#pragma once + +#include + +#include "SharedDefines.h" +#include "ItemTemplate.h" + +#include "AbstractItemInspector.h" +#include "ItemActionStruct.h" +#include "ItemActionEnum.h" + +class ProjectItemInspector : public AbstractItemInspector +{ +public: + ProjectItemInspector( + uint64_t playerLowGUID, + uint64_t itemLowGUID + ) : AbstractItemInspector(playerLowGUID, itemLowGUID) + {} + + bool isInspectable() const override + { + const uint8_t itemClass = this->getCurrentItemClass(); + + return AbstractItemInspector::isInspectable() && itemClass == ITEM_CLASS_PROJECTILE; + } + + ItemActionStruct determineItemAction() const override + { + if (!this->isInspectable()) + return this->getDefaultItemAction(); + + if (this->isForbiddenItem()) + return this->getForbiddenItemAction(); + + const ObjectGuid playerGUID = ObjectGuid::Create(this->playerLowGUID); + Player* player = ObjectAccessor::FindPlayer(playerGUID); + + if (player == nullptr) + return this->getDefaultItemAction(); + + const uint8_t playerClass = player->getClass(); + + if (playerClass == CLASS_HUNTER) + return this->getKeepItemAction(); + + return this->getSellAction(); + } + + bool isForbiddenItem() const + { + const std::unordered_set forbiddenItems = this->getForbiddenItemsGUIDs(); + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return false; + + return forbiddenItems.contains(itemTemplate->ItemId); + } + +protected: + + const std::unordered_set getForbiddenItemsGUIDs() const + { + return {}; + } +}; diff --git a/src/domain/item/inspector/quest/QuestItemInspector.h b/src/domain/item/inspector/quest/QuestItemInspector.h new file mode 100644 index 0000000000..551d8144a2 --- /dev/null +++ b/src/domain/item/inspector/quest/QuestItemInspector.h @@ -0,0 +1,70 @@ +#pragma once + +#include + +#include "SharedDefines.h" +#include "ItemTemplate.h" + +#include "AbstractItemInspector.h" +#include "ItemActionStruct.h" +#include "ItemActionEnum.h" + +class QuestItemInspector : public AbstractItemInspector +{ +public: + QuestItemInspector( + uint64_t playerLowGUID, + uint64_t itemLowGUID + ) : AbstractItemInspector(playerLowGUID, itemLowGUID) + {} + + bool isInspectable() const override + { + const uint8_t itemClass = this->getCurrentItemClass(); + + return AbstractItemInspector::isInspectable() && itemClass == ITEM_CLASS_QUEST; + } + + ItemActionStruct determineItemAction() const override + { + if (!this->isInspectable()) + return this->getDefaultItemAction(); + + if (this->isForbiddenItem()) + return this->getForbiddenItemAction(); + + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return this->getDefaultItemAction(); + + const ObjectGuid playerGUID = ObjectGuid::Create(this->playerLowGUID); + Player* player = ObjectAccessor::FindPlayer(playerGUID); + + if (player == nullptr) + return this->getDefaultItemAction(); + + if (player->HasQuestForItem(itemTemplate->ItemId)) + return this->getKeepItemAction(); + + return this->getDestroyItemAction(); + } + + bool isForbiddenItem() const + { + const std::unordered_set forbiddenItems = this->getForbiddenItemsGUIDs(); + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return false; + + return forbiddenItems.contains(itemTemplate->ItemId); + } + +protected: + + const std::unordered_set getForbiddenItemsGUIDs() const + { + return {}; + } +}; diff --git a/src/domain/item/inspector/quiver/QuiverItemInspector.h b/src/domain/item/inspector/quiver/QuiverItemInspector.h new file mode 100644 index 0000000000..d472569369 --- /dev/null +++ b/src/domain/item/inspector/quiver/QuiverItemInspector.h @@ -0,0 +1,56 @@ +#pragma once + +#include + +#include "SharedDefines.h" +#include "ItemTemplate.h" + +#include "AbstractItemInspector.h" +#include "ItemActionStruct.h" +#include "ItemActionEnum.h" + +class QuiverItemInspector : public AbstractItemInspector +{ +public: + QuiverItemInspector( + uint64_t playerLowGUID, + uint64_t itemLowGUID + ) : AbstractItemInspector(playerLowGUID, itemLowGUID) + {} + + bool isInspectable() const override + { + const uint8_t itemClass = this->getCurrentItemClass(); + + return AbstractItemInspector::isInspectable() && itemClass == ITEM_CLASS_QUIVER; + } + + ItemActionStruct determineItemAction() const override + { + if (!this->isInspectable()) + return this->getDefaultItemAction(); + + if (this->isForbiddenItem()) + return this->getForbiddenItemAction(); + + return this->getSellAction(); + } + + bool isForbiddenItem() const + { + const std::unordered_set forbiddenItems = this->getForbiddenItemsGUIDs(); + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return false; + + return forbiddenItems.contains(itemTemplate->ItemId); + } + +protected: + + const std::unordered_set getForbiddenItemsGUIDs() const + { + return {}; + } +}; diff --git a/src/domain/item/inspector/reagent/ReagentItemInspector.h b/src/domain/item/inspector/reagent/ReagentItemInspector.h new file mode 100644 index 0000000000..9c6a6df8e0 --- /dev/null +++ b/src/domain/item/inspector/reagent/ReagentItemInspector.h @@ -0,0 +1,56 @@ +#pragma once + +#include + +#include "SharedDefines.h" +#include "ItemTemplate.h" + +#include "AbstractItemInspector.h" +#include "ItemActionStruct.h" +#include "ItemActionEnum.h" + +class ReagentItemInspector : public AbstractItemInspector +{ +public: + ReagentItemInspector( + uint64_t playerLowGUID, + uint64_t itemLowGUID + ) : AbstractItemInspector(playerLowGUID, itemLowGUID) + {} + + bool isInspectable() const override + { + const uint8_t itemClass = this->getCurrentItemClass(); + + return AbstractItemInspector::isInspectable() && itemClass == ITEM_CLASS_REAGENT; + } + + ItemActionStruct determineItemAction() const override + { + if (!this->isInspectable()) + return this->getDefaultItemAction(); + + if (this->isForbiddenItem()) + return this->getForbiddenItemAction(); + + return this->getSellAction(); + } + + bool isForbiddenItem() const + { + const std::unordered_set forbiddenItems = this->getForbiddenItemsGUIDs(); + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return false; + + return forbiddenItems.contains(itemTemplate->ItemId); + } + +protected: + + const std::unordered_set getForbiddenItemsGUIDs() const + { + return {}; + } +}; diff --git a/src/domain/item/inspector/recipe/RecipeItemInspector.h b/src/domain/item/inspector/recipe/RecipeItemInspector.h new file mode 100644 index 0000000000..f492a60c8a --- /dev/null +++ b/src/domain/item/inspector/recipe/RecipeItemInspector.h @@ -0,0 +1,56 @@ +#pragma once + +#include + +#include "SharedDefines.h" +#include "ItemTemplate.h" + +#include "AbstractItemInspector.h" +#include "ItemActionStruct.h" +#include "ItemActionEnum.h" + +class RecipeItemInspector : public AbstractItemInspector +{ +public: + RecipeItemInspector( + uint64_t playerLowGUID, + uint64_t itemLowGUID + ) : AbstractItemInspector(playerLowGUID, itemLowGUID) + {} + + bool isInspectable() const override + { + const uint8_t itemClass = this->getCurrentItemClass(); + + return AbstractItemInspector::isInspectable() && itemClass == ITEM_CLASS_RECIPE; + } + + ItemActionStruct determineItemAction() const override + { + if (!this->isInspectable()) + return this->getDefaultItemAction(); + + if (this->isForbiddenItem()) + return this->getForbiddenItemAction(); + + return this->getSellAction(); + } + + bool isForbiddenItem() const + { + const std::unordered_set forbiddenItems = this->getForbiddenItemsGUIDs(); + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return false; + + return forbiddenItems.contains(itemTemplate->ItemId); + } + +protected: + + const std::unordered_set getForbiddenItemsGUIDs() const + { + return {}; + } +}; diff --git a/src/domain/item/inspector/trade-good/TradeGoodItemInspector.h b/src/domain/item/inspector/trade-good/TradeGoodItemInspector.h new file mode 100644 index 0000000000..ba57f7d537 --- /dev/null +++ b/src/domain/item/inspector/trade-good/TradeGoodItemInspector.h @@ -0,0 +1,56 @@ +#pragma once + +#include + +#include "SharedDefines.h" +#include "ItemTemplate.h" + +#include "AbstractItemInspector.h" +#include "ItemActionStruct.h" +#include "ItemActionEnum.h" + +class TradeGoodItemInspector : public AbstractItemInspector +{ +public: + TradeGoodItemInspector( + uint64_t playerLowGUID, + uint64_t itemLowGUID + ) : AbstractItemInspector(playerLowGUID, itemLowGUID) + {} + + bool isInspectable() const override + { + const uint8_t itemClass = this->getCurrentItemClass(); + + return AbstractItemInspector::isInspectable() && itemClass == ITEM_CLASS_TRADE_GOODS; + } + + ItemActionStruct determineItemAction() const override + { + if (!this->isInspectable()) + return this->getDefaultItemAction(); + + if (this->isForbiddenItem()) + return this->getForbiddenItemAction(); + + return this->getSellAction(); + } + + bool isForbiddenItem() const + { + const std::unordered_set forbiddenItems = this->getForbiddenItemsGUIDs(); + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return false; + + return forbiddenItems.contains(itemTemplate->ItemId); + } + +protected: + + const std::unordered_set getForbiddenItemsGUIDs() const + { + return {}; + } +}; diff --git a/src/domain/item/inspector/weapon/WeaponItemInspector.h b/src/domain/item/inspector/weapon/WeaponItemInspector.h new file mode 100644 index 0000000000..dd5b057261 --- /dev/null +++ b/src/domain/item/inspector/weapon/WeaponItemInspector.h @@ -0,0 +1,150 @@ +#pragma once + +#include + +#include "SharedDefines.h" +#include "ItemTemplate.h" + +#include "StatsWeightCalculator.h" +#include "AbstractItemInspector.h" +#include "ItemActionStruct.h" +#include "ItemActionEnum.h" +#include "InventoryService.h" +#include "GlobalPlayerInspector.h" + +class WeaponItemInspector : public AbstractItemInspector +{ +public: + WeaponItemInspector( + uint64_t playerLowGUID, + uint64_t itemLowGUID + ) : AbstractItemInspector(playerLowGUID, itemLowGUID) + {} + + bool isInspectable() const override + { + const uint8_t itemClass = this->getCurrentItemClass(); + + return AbstractItemInspector::isInspectable() && itemClass == ITEM_CLASS_WEAPON; + } + + ItemActionStruct determineItemAction() const override + { + if (!this->isInspectable()) + { + LOG_DEBUG("playerbots", "Item is not inspectable."); + + return this->getDefaultItemAction(); + } + + if (this->isForbiddenItem()) + { + LOG_DEBUG("playerbots", "Item is forbidden"); + + return this->getForbiddenItemAction(); + } + + const ObjectGuid playerGUID = ObjectGuid::Create(this->playerLowGUID); + Player* player = ObjectAccessor::FindPlayer(playerGUID); + + if (player == nullptr) + { + LOG_DEBUG("playerbots", "Player is nullptr"); + + return this->getDefaultItemAction(); + } + + Item* currentItem = this->getMutableCurrentItem(); + + if (currentItem == nullptr) + { + LOG_DEBUG("playerbots", "new item had no template"); + + return this->getDefaultItemAction(); + } + + const InventoryResult canUseItem = player->CanUseItem(currentItem); + + if (canUseItem != EQUIP_ERR_OK) + { + LOG_DEBUG("playerbots", "item could not be used, selling"); + + return this->getSellAction(); + } + + StatsWeightCalculator statisticsWeightCalculator(player); + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + { + LOG_DEBUG("playerbots", "Item had no template"); + + return this->getDefaultItemAction(); + } + + std::vector slots = InventoryService::GetInstance().getItemEquipmentSlots(itemTemplate); + + const float newItemStatisticsWeight = statisticsWeightCalculator.CalculateItem(itemTemplate->ItemId); + + statisticsWeightCalculator.Reset(); + + for (uint8_t i = 0; i < slots.size(); ++i) + { + const uint32_t equipmentSlot = slots[i]; + + const Item* const currentlyEquippedItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, equipmentSlot); + + if (currentlyEquippedItem == nullptr) + { + LOG_DEBUG("playerbots.inspector.weapon", "No current item, equipping new"); + + return { + .action = ItemActionEnum::EQUIP, + .bagSlot = this->getBagSlot(), + .containerSlot = this->getItemSlot(), + .equipmentSlot = equipmentSlot + }; + } + + const ItemTemplate* const currentlyEquippedItemTemplate = currentlyEquippedItem->GetTemplate(); + + if (currentlyEquippedItemTemplate == nullptr) + return this->getDefaultItemAction(); + + const float existingItemStatisticsWeight = statisticsWeightCalculator.CalculateItem(currentlyEquippedItemTemplate->ItemId); + + if (existingItemStatisticsWeight < newItemStatisticsWeight) + { + LOG_DEBUG("playerbots.inspector.weapon", "New item is better than old one."); + + return { + .action = ItemActionEnum::EQUIP, + .bagSlot = this->getBagSlot(), + .containerSlot = this->getItemSlot(), + .equipmentSlot = equipmentSlot + }; + } + } + + return this->getSellAction(); + } + + bool isForbiddenItem() const + { + const std::unordered_set forbiddenItems = this->getForbiddenItemsGUIDs(); + + const ItemTemplate* const itemTemplate = this->getCurrentItemTemplate(); + + if (itemTemplate == nullptr) + return false; + + return forbiddenItems.contains(itemTemplate->ItemId); + } + +protected: + + const std::unordered_set getForbiddenItemsGUIDs() const + { + return {}; + } +}; diff --git a/src/domain/player/facade/abstract/AbstractPlayerFacade.h b/src/domain/player/facade/abstract/AbstractPlayerFacade.h new file mode 100644 index 0000000000..d3d8f2fde2 --- /dev/null +++ b/src/domain/player/facade/abstract/AbstractPlayerFacade.h @@ -0,0 +1,36 @@ +#pragma once + +#include + +#include "ObjectGuid.h" +#include "ObjectAccessor.h" +#include "SharedDefines.h" +#include "Player.h" + +class AbstractPlayerFacade +{ +public: + AbstractPlayerFacade( + uint64_t playerGUID + ) : + playerGUID(playerGUID) + {} + + AbstractPlayerFacade& operator=(AbstractPlayerFacade const&) = delete; + + Player* getCurrentPlayer() const + { + const ObjectGuid playerFullGUID = ObjectGuid::Create(this->playerGUID); + Player* const player = ObjectAccessor::FindPlayer(playerFullGUID); + + return player; + } + + bool isMutable() const + { + return true; + } + +protected: + const uint64_t playerGUID; +}; diff --git a/src/domain/player/facade/equipment/PlayerEquipmentFacade.h b/src/domain/player/facade/equipment/PlayerEquipmentFacade.h new file mode 100644 index 0000000000..4bccc2ef6b --- /dev/null +++ b/src/domain/player/facade/equipment/PlayerEquipmentFacade.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include + +#include "Packet.h" +#include "ItemPackets.h" +#include "ObjectGuid.h" +#include "ObjectAccessor.h" +#include "SharedDefines.h" +#include "Player.h" +#include "WorldSession.h" + +#include "AbstractPlayerFacade.h" +#include "PlayerEquipmentFacadeResultEnum.h" +#include "GlobalPlayerInspector.h" +#include "InventoryService.h" + +class PlayerEquipmentFacade : public AbstractPlayerFacade +{ +public: + PlayerEquipmentFacade( + uint64_t playerGUID + ) : + AbstractPlayerFacade(playerGUID) + {} + + PlayerEquipmentFacadeResultEnum equipItem(uint64_t itemLowGUID, EquipmentSlots destinationSlot) + { + if (destinationSlot < EQUIPMENT_SLOT_START || destinationSlot > EQUIPMENT_SLOT_TABARD) + return PlayerEquipmentFacadeResultEnum::IMPOSSIBLE; + + GlobalPlayerInspector playerInspector(this->playerGUID); + GlobalItemInspector itemInspector(this->playerGUID, itemLowGUID); + + if (!playerInspector.canEquipItem(itemLowGUID, destinationSlot)) + return PlayerEquipmentFacadeResultEnum::IMPOSSIBLE; + + Player* const player = this->getCurrentPlayer(); + + if (player == nullptr) + return PlayerEquipmentFacadeResultEnum::IMPOSSIBLE; + + player->SwapItem(itemInspector.getItemPosition(), destinationSlot); + + return PlayerEquipmentFacadeResultEnum::REQUESTED; + } +}; diff --git a/src/domain/player/facade/equipment/definition/enum/PlayerEquipmentFacadeResultEnum.h b/src/domain/player/facade/equipment/definition/enum/PlayerEquipmentFacadeResultEnum.h new file mode 100644 index 0000000000..d7a4a90a6f --- /dev/null +++ b/src/domain/player/facade/equipment/definition/enum/PlayerEquipmentFacadeResultEnum.h @@ -0,0 +1,6 @@ +enum class PlayerEquipmentFacadeResultEnum +{ + REQUESTED = 0, + IMPOSSIBLE = 1 +}; + diff --git a/src/domain/player/facade/inventory/PlayerInventoryFacade.h b/src/domain/player/facade/inventory/PlayerInventoryFacade.h new file mode 100644 index 0000000000..5f424ffe6a --- /dev/null +++ b/src/domain/player/facade/inventory/PlayerInventoryFacade.h @@ -0,0 +1,140 @@ +#pragma once + +#include +#include "Player.h" +#include "WorldSession.h" +#include "AuctionHouseMgr.h" + +#include "AbstractPlayerFacade.h" +#include "PlayerInventoryFacadeResultEnum.h" +#include "GlobalPlayerInspector.h" +#include "GlobalItemInspector.h" + +class PlayerInventoryFacade : public AbstractPlayerFacade +{ +public: + PlayerInventoryFacade( + uint64_t playerGUID + ) : + AbstractPlayerFacade(playerGUID) + {} + + PlayerInventoryFacadeResultEnum equipItem(uint64_t itemLowGUID, uint8_t equipmentSlot) + { + if (equipmentSlot < EQUIPMENT_SLOT_START || equipmentSlot > EQUIPMENT_SLOT_TABARD) + return PlayerInventoryFacadeResultEnum::IMPOSSIBLE; + + GlobalItemInspector itemInspector(this->playerGUID, itemLowGUID); + + const uint8_t inventoryType = itemInspector.getCurrentItemInventoryType(); + + if (inventoryType == INVTYPE_AMMO) + { + Player* const player = this->getCurrentPlayer(); + + if (player == nullptr) + return PlayerInventoryFacadeResultEnum::IMPOSSIBLE; + + player->SetAmmo(itemLowGUID); + + return PlayerInventoryFacadeResultEnum::OK; + } + + const uint32_t itemClass = itemInspector.getCurrentItemClass(); + + if (itemClass == ITEM_CLASS_WEAPON || itemClass == ITEM_CLASS_ARMOR || itemClass == ITEM_CLASS_CONTAINER) + { + Player* const player = this->getCurrentPlayer(); + + if (player == nullptr) + return PlayerInventoryFacadeResultEnum::IMPOSSIBLE; + + const uint16_t overlyCleverSrc = (itemInspector.getBagSlot() << 8) | itemInspector.getItemSlot(); + const uint16_t overlyCleverDest = (INVENTORY_SLOT_BAG_0 << 8) | equipmentSlot; + + player->SwapItem(overlyCleverSrc, overlyCleverDest); + + return PlayerInventoryFacadeResultEnum::OK; + } + + return PlayerInventoryFacadeResultEnum::IMPOSSIBLE; + } + + PlayerInventoryFacadeResultEnum destroyItem(uint64_t itemLowGUID) + { + GlobalPlayerInspector playerInspector(this->playerGUID); + GlobalItemInspector itemInspector(this->playerGUID, itemLowGUID); + Player* const player = this->getCurrentPlayer(); + + if (player == nullptr) + return PlayerInventoryFacadeResultEnum::IMPOSSIBLE; + + Item* item = itemInspector.getMutableCurrentItem(); + + if (item == nullptr) + return PlayerInventoryFacadeResultEnum::IMPOSSIBLE; + + LOG_DEBUG("playerbots.player.facade", "destroying item"); + + uint32_t itemCount = itemInspector.getItemCurrentCount(); + + player->DestroyItemCount(item, itemCount, true); + + return PlayerInventoryFacadeResultEnum::OK; + } + + PlayerInventoryFacadeResultEnum sellItem(uint64_t itemLowGUID) + { + LOG_DEBUG("playerbots.player.facade", "Selling item {}", std::to_string(itemLowGUID)); + + GlobalPlayerInspector playerInspector(this->playerGUID); + GlobalItemInspector itemInspector(this->playerGUID, itemLowGUID); + + const uint32_t sellPrice = itemInspector.getItemSellPrice(); + + LOG_DEBUG("playerbots.player.facade", "Item sell price {}", std::to_string(sellPrice)); + + if (sellPrice == 0) + return this->destroyItem(itemLowGUID); + + const uint32_t itemCount = itemInspector.getItemCurrentCount(); + + LOG_DEBUG("playerbots.player.facade", "Item count {}", std::to_string(itemCount)); + + Player* const player = this->getCurrentPlayer(); + + if (player == nullptr) + return PlayerInventoryFacadeResultEnum::IMPOSSIBLE; + + Item* item = itemInspector.getMutableCurrentItem(); + + if (item == nullptr) + return PlayerInventoryFacadeResultEnum::IMPOSSIBLE; + + const uint32_t totalItemStackValue = sellPrice * itemCount; + + LOG_DEBUG("playerbots.player.facade", "Total item stack value {}", std::to_string(totalItemStackValue)); + + LOG_DEBUG("playerbots.player.facade", "modifiying player money"); + player->ModifyMoney(totalItemStackValue); + // LOG_DEBUG("playerbots.player.facade", "destroying item after sell"); + // player->DestroyItemCount(itemInspector.getBagSlot(), itemInspector.getItemSlot(), true); + + + LOG_DEBUG("playerbots.player.facade", "removing item"); + player->RemoveItem(item->GetBagSlot(), item->GetSlot(), true); + LOG_DEBUG("playerbots.player.facade", "removing item from update queue"); + item->RemoveFromUpdateQueueOf(player); + LOG_DEBUG("playerbots.player.facade", "adding item to buy back slot"); + player->AddItemToBuyBackSlot(item, totalItemStackValue); + LOG_DEBUG("playerbots.player.facade", "Done selling item"); + + return PlayerInventoryFacadeResultEnum::OK; + } + + // PlayerInventoryFacadeResultEnum auctionItem(uint64_t itemLowGUID) + // { + // const AuctionHouseMgr* const auctionHouseManager = AuctionHouseMgr::instance(); + // // const AuctionHouseEntry* const auctionHouseEntry = auctionHouseManager->GetAuctionHouseEntryFromFactionTemplate(); + // } +}; diff --git a/src/domain/player/facade/inventory/definition/enum/PlayerInventoryFacadeResultEnum.h b/src/domain/player/facade/inventory/definition/enum/PlayerInventoryFacadeResultEnum.h new file mode 100644 index 0000000000..d60187392a --- /dev/null +++ b/src/domain/player/facade/inventory/definition/enum/PlayerInventoryFacadeResultEnum.h @@ -0,0 +1,8 @@ +#pragma once + +enum class PlayerInventoryFacadeResultEnum +{ + OK = 0, + IMPOSSIBLE = 1 +}; + diff --git a/src/domain/player/inspector/abstract/AbstractPlayerInspector.h b/src/domain/player/inspector/abstract/AbstractPlayerInspector.h new file mode 100644 index 0000000000..66e5874a08 --- /dev/null +++ b/src/domain/player/inspector/abstract/AbstractPlayerInspector.h @@ -0,0 +1,37 @@ +#pragma once + +#include + +#include "ObjectGuid.h" +#include "ObjectAccessor.h" +#include "Player.h" + +#include "AbstractInspector.h" + +class AbstractPlayerInspector : public AbstractInspector +{ +public: + AbstractPlayerInspector( + uint64_t playerGUID + ) : + playerGUID(playerGUID) + {} + + AbstractPlayerInspector& operator=(AbstractPlayerInspector const&) = delete; + + Player* getCurrentPlayer() const + { + const ObjectGuid playerFullGUID = ObjectGuid::Create(this->playerGUID); + Player* const player = ObjectAccessor::FindPlayer(playerFullGUID); + + return player; + } + + bool isInspectable() const override + { + return true; + } + +protected: + const uint64_t playerGUID; +}; diff --git a/src/domain/player/inspector/global/GlobalPlayerInspector.h b/src/domain/player/inspector/global/GlobalPlayerInspector.h new file mode 100644 index 0000000000..7377c0ec90 --- /dev/null +++ b/src/domain/player/inspector/global/GlobalPlayerInspector.h @@ -0,0 +1,351 @@ +#pragma once + +#include + +#include "ObjectAccessor.h" +#include "SharedDefines.h" +#include "Player.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "Cell.h" +#include "CellImpl.h" + +#include "AiObjectContext.h" +#include "AiFactory.h" +#include "PlayerbotAI.h" +#include "AbstractPlayerInspector.h" +#include "PlayerbotMgr.h" +#include "ItemActionStruct.h" +#include "ItemActionEnum.h" + +class GlobalPlayerInspector : public AbstractPlayerInspector +{ +public: + GlobalPlayerInspector( + uint64_t playerGUID + ) : + AbstractPlayerInspector(playerGUID) + {} + + bool isDrinking() const + { + const Player* const player = this->getCurrentPlayer(); + + if (player == nullptr) + return false; + + if (!player->IsSitState()) + return false; + + return player->HasAuraType(SPELL_AURA_MOD_POWER_REGEN) || player->HasAuraType(SPELL_AURA_MOD_POWER_REGEN_PERCENT); + } + + bool isEating() const + { + const Player* const player = this->getCurrentPlayer(); + + if (player == nullptr) + return false; + + if (!player->IsSitState()) + return false; + + return player->HasAuraType(SPELL_AURA_MOD_REGEN) || player->HasAuraType(SPELL_AURA_MOD_HEALTH_REGEN_PERCENT); + } + + bool shouldBeDrinking(float manaThresholdPercent) const + { + Player* const player = this->getCurrentPlayer(); + + if (player == nullptr) + return false; + + if (!player->HasActivePowerType(POWER_MANA)) + return false; + + if (player->IsInCombat()) + return false; + + if (player->GetPowerPct(POWER_MANA) > manaThresholdPercent) + return false; + + if (player->IsUnderWater()) + return false; + + // Bots must not keep drinking if they have hostile entities close to them! + if (this->hasHostileUnitsInRange(15.0f)) + return false; + + PlayerbotAI* botAI = PlayerbotsMgr::instance().GetPlayerbotAI(player); + + if (botAI == nullptr) + return false; + + AiObjectContext* context = botAI->GetAiObjectContext(); + + if (context == nullptr) + return false; + + bool hasAvailableLoot = context->GetValue("loot target"); + + if (hasAvailableLoot) + return false; + + return true; + } + + bool hasHostileUnitsInRange(float range) const + { + const Player* const player = this->getCurrentPlayer(); + + if (player == nullptr) + return false; + + std::list targets; + + Acore::AnyUnfriendlyAttackableVisibleUnitInObjectRangeCheck u_check(player, range); + Acore::UnitListSearcher searcher(player, targets, u_check); + Cell::VisitObjects(player, searcher, PlayerbotAIConfig::instance().sightDistance); + + return !targets.empty(); + } + + bool canEquipItem(const uint32_t itemLowGUID, uint16_t destinationSlot) const + { + Item* const item = this->getItemByGUID(itemLowGUID); + + if (item == nullptr) + return false; + + const Player* const player = this->getCurrentPlayer(); + + if (player == nullptr) + return false; + + return player->CanEquipItem(item->GetSlot(), destinationSlot, item, true); + } + + bool canUseItem(const uint32_t itemGUID) const + { + const Player* const player = this->getCurrentPlayer(); + + if (player == nullptr) + return false; + + const ObjectGuid itemFullGUID = ObjectGuid::Create(itemGUID); + Item* const item = player->GetItemByGuid(itemFullGUID); + + if (item == nullptr) + return false; + + return player->CanUseItem(item); + } + + uint8_t getCurrentPlayerClass() const + { + const Player* const player = this->getCurrentPlayer(); + + // If the player is offline, we bail out by returning a void class to avoid any offline mutation. + if (player == nullptr) + return CLASS_NONE; + + return player->getClass(); + } + + bool requiresItemForActiveQuest(const uint32_t itemTemplateId) const + { + const Player* const player = this->getCurrentPlayer(); + + // If the player is offline, we consider the item as being in use to avoid modifying an offline inventory. + if (player == nullptr) + return true; + + return player->HasQuestForItem(itemTemplateId); + } + + uint32_t getItemCount(const uint32_t itemTemplateId) const + { + const Player* const player = this->getCurrentPlayer(); + + if (player == nullptr) + return 0; + + return player->GetItemCount(itemTemplateId); + } + + Item* getItemByPosition(const uint16_t slot) const + { + Player* const player = this->getCurrentPlayer(); + + if (player == nullptr) + return nullptr; + + Item* const item = player->GetItemByPos(slot); + + return item; + } + + Item* getItemByPosition(const uint8_t bag, const uint8_t slot) const + { + Player* const player = this->getCurrentPlayer(); + + if (player == nullptr) + return nullptr; + + Item* const item = player->GetItemByPos(bag, slot); + + return item; + } + + uint32_t getPlayerMoney() const + { + Player* const player = this->getCurrentPlayer(); + + if (player == nullptr) + return 0; + + return player->GetMoney(); + } + + // Item* getBagItemByPosition(const uint8_t bagNumber, const uint8_t slot) const + // { + // if (bagNumber >= INVENTORY_SLOT_BAG_END) + // return nullptr; + + // if (bagNumber == 0) + // { + // const Player* const player = this->getCurrentPlayer(); + + // if (player == nullptr) + // return nullptr; + + // return player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot); + // } + + // Player* const player = this->getCurrentPlayer(); + + // if (player == nullptr) + // return nullptr; + + // Item* const bagItem = player->GetItemByPos(INVENTORY_SLOT_BAG_START + bagNumber - 1); + + // if (bagItem == nullptr) + // return nullptr; + + // Bag* const bag = bagItem->ToBag(); + + // if (bag == nullptr) + // return nullptr; + + // return bag->GetItemByPos(slot); + // } + + Item* getItemByGUID(const uint64_t guid) const + { + Player* const player = this->getCurrentPlayer(); + + if (player == nullptr) + return nullptr; + + const ObjectGuid fullItemGUID = ObjectGuid::Create(guid); + + Item* const item = player->GetItemByGuid(fullItemGUID); + + return item; + } + + Item* getMutableItemByGUID(const uint64_t guid) const + { + Player* const player = this->getCurrentPlayer(); + + if (player == nullptr) + return nullptr; + + const ObjectGuid fullItemGUID = ObjectGuid::Create(guid); + + Item* const item = player->GetItemByGuid(fullItemGUID); + + return item; + } + + uint8_t getDominantPlayerTalentTab() const + { + Player* const player = this->getCurrentPlayer(); + + if (player == nullptr) + return 255; + + return AiFactory::GetPlayerSpecTab(player); + } + + Stats getPrimaryStat() const + { + const uint8_t playerClass = this->getCurrentPlayerClass(); + + switch (playerClass) + { + case CLASS_WARRIOR: + return STAT_STRENGTH; + case CLASS_PALADIN: + { + const uint8_t dominantTab = this->getDominantPlayerTalentTab(); + + switch (dominantTab) + { + case PALADIN_TAB_HOLY: + return STAT_INTELLECT; + case PALADIN_TAB_PROTECTION: + return STAT_STAMINA; + case PALADIN_TAB_RETRIBUTION: + return STAT_STRENGTH; + } + + return STAT_STAMINA; + } + case CLASS_HUNTER: + return STAT_AGILITY; + case CLASS_ROGUE: + return STAT_AGILITY; + case CLASS_PRIEST: + return STAT_SPIRIT; + case CLASS_DEATH_KNIGHT: + return STAT_STRENGTH; + case CLASS_SHAMAN: + { + const uint8_t dominantTab = this->getDominantPlayerTalentTab(); + + switch (dominantTab) + { + case SHAMAN_TAB_ELEMENTAL: + return STAT_INTELLECT; + case SHAMAN_TAB_ENHANCEMENT: + return STAT_AGILITY; + case SHAMAN_TAB_RESTORATION: + return STAT_INTELLECT; + } + + return STAT_STAMINA; + } + case CLASS_MAGE: + return STAT_INTELLECT; + case CLASS_DRUID: + { + const uint8_t dominantTab = this->getDominantPlayerTalentTab(); + + switch (dominantTab) + { + case DRUID_TAB_BALANCE: + return STAT_INTELLECT; + case DRUID_TAB_FERAL: + return STAT_AGILITY; + case DRUID_TAB_RESTORATION: + return STAT_SPIRIT; + } + + return STAT_STAMINA; + } + } + + return STAT_STAMINA; + } +}; diff --git a/src/registry/PlayerGuildRegistry.cpp b/src/registry/PlayerGuildRegistry.cpp new file mode 100644 index 0000000000..8613a4c71d --- /dev/null +++ b/src/registry/PlayerGuildRegistry.cpp @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include "PlayerGuildRegistry.h" +#include "PlayerGuildRepository.h" +#include "PlayerbotAIConfig.h" +#include "UInt32VectorToString.h" +#include "DatabaseEnv.h" +#include "QueryResult.h" +#include "Log.h" + +void PlayerGuildRegistry::Initialize() +{ + std::unordered_set playerGuildsIds = sPlayerGuildRepository.GetPlayerGuildsIds(); + + ids_.clear(); + ids_.merge(playerGuildsIds); + + LOG_INFO("server.loading", "[PlayerGuildRegistry] Initialized PlayerGuildRegistry with {} guilds containing non random bot account characters.", Size()); +} + +// Add an ID if not already present +void PlayerGuildRegistry::Add(uint32_t id) +{ + std::lock_guard lock(mutex_); + + ids_.insert(id); +} + +// Remove an ID if present +void PlayerGuildRegistry::Remove(uint32_t id) +{ + std::lock_guard lock(mutex_); + + ids_.erase(id); +} + +// Check if ID is present +bool PlayerGuildRegistry::Contains(uint32_t id) const +{ + std::lock_guard lock(mutex_); + + return ids_.find(id) != ids_.end(); +} + +// Retrieve a copy (thread safe) +std::vector PlayerGuildRegistry::Snapshot() const +{ + std::lock_guard lock(mutex_); + + return std::vector(ids_.begin(), ids_.end()); +} + +std::size_t PlayerGuildRegistry::Size() const +{ + std::lock_guard lock(mutex_); + + return ids_.size(); +} + +bool PlayerGuildRegistry::Empty() const +{ + std::lock_guard lock(mutex_); + + return ids_.empty(); +} diff --git a/src/registry/PlayerGuildRegistry.h b/src/registry/PlayerGuildRegistry.h new file mode 100644 index 0000000000..b03f4e6b9d --- /dev/null +++ b/src/registry/PlayerGuildRegistry.h @@ -0,0 +1,51 @@ +#ifndef PLAYER_GUILD_REGISTRY_H +#define PLAYER_GUILD_REGISTRY_H + +#include +#include +#include +#include + +class PlayerGuildRegistry { +public: + static PlayerGuildRegistry& GetInstance() + { + static PlayerGuildRegistry instance; + return instance; + } + + // Delete copy constructor and assignment operator to enforce singleton pattern + PlayerGuildRegistry(const PlayerGuildRegistry&) = delete; + PlayerGuildRegistry& operator=(const PlayerGuildRegistry&) = delete; + + void Initialize(); + + // Add an ID if not already present + void Add(uint32_t id); + + // Remove an ID if present + void Remove(uint32_t id); + + // Check if ID is present + bool Contains(uint32_t id) const; + + // Retrieve a copy (thread safe) + std::vector Snapshot() const; + + // Get the number of registered guilds + std::size_t Size() const; + + // Check if registry is empty + bool Empty() const; + +private: + PlayerGuildRegistry() = default; + ~PlayerGuildRegistry() = default; + + mutable std::mutex mutex_; + std::unordered_set ids_; +}; + +#define sPlayerGuildRegistry PlayerGuildRegistry::GetInstance() + +#endif diff --git a/src/repository/PlayerGuildRepository.cpp b/src/repository/PlayerGuildRepository.cpp new file mode 100644 index 0000000000..0f09ad69fc --- /dev/null +++ b/src/repository/PlayerGuildRepository.cpp @@ -0,0 +1,76 @@ +#include +#include +#include "PlayerGuildRepository.h" +#include "PlayerbotAIConfig.h" +#include "QueryResult.h" +#include "UInt32VectorToString.h" +#include "DatabaseEnv.h" +#include "Log.h" + +std::unordered_set PlayerGuildRepository::GetPlayerGuildsIds() +{ + std::string randomBotsAccountsIdsString = UInt32VectorToString(sPlayerbotAIConfig.randomBotAccounts); + + std::unordered_set guildIds; + + QueryResult result = CharacterDatabase.Query( + "SELECT DISTINCT(guild.guildid) " + "FROM guild " + "INNER JOIN guild_member ON guild_member.guildid = guild.guildid " + "INNER JOIN characters ON guild_member.guid = characters.guid " + "WHERE characters.account NOT IN ({})", + randomBotsAccountsIdsString + ); + + if (!result) + { + LOG_INFO("playerbots", "[PlayerGuildRepository] No guild found containing real players. PlayerGuildRepository is empty."); + + return guildIds; + } + + do + { + Field* fields = result->Fetch(); + uint32_t id = fields[0].Get(); + + LOG_INFO("playerbots", "[PlayerGuildRepository] Adding guild with id '{}' to registry because it contains at least one non random bot account character.", id); + + guildIds.insert(id); + } while (result->NextRow()); + + return guildIds; +} + +std::unordered_set PlayerGuildRepository::GetGuildMembersIds(uint32_t guildId) +{ + std::string randomBotsAccountsIdsString = UInt32VectorToString(sPlayerbotAIConfig.randomBotAccounts); + + std::unordered_set membersIds; + + QueryResult result = CharacterDatabase.Query( + "SELECT characters.guid " + "INNER JOIN guild_member ON guild_member.guid = characters.guid " + "WHERE guild_member.guildid = {} " + "AND characters.account NOT IN ({})", + guildId, + randomBotsAccountsIdsString + ); + + if (!result) + { + LOG_DEBUG("playerbots", "[PlayerGuildRepository] No non random bot member for guild with id {}", guildId); + + return membersIds; + } + + do + { + Field* fields = result->Fetch(); + uint64_t id = fields[0].Get(); + + membersIds.insert(id); + } while (result->NextRow()); + + return membersIds; +} diff --git a/src/repository/PlayerGuildRepository.h b/src/repository/PlayerGuildRepository.h new file mode 100644 index 0000000000..068ab8e1c6 --- /dev/null +++ b/src/repository/PlayerGuildRepository.h @@ -0,0 +1,30 @@ +#ifndef PLAYER_GUILD_REPOSITORY_H +#define PLAYER_GUILD_REPOSITORY_H + +#include +#include + +class PlayerGuildRepository { +public: + static PlayerGuildRepository& GetInstance() + { + static PlayerGuildRepository instance; + return instance; + } + + // Delete copy constructor and assignment operator to enforce singleton pattern + PlayerGuildRepository(const PlayerGuildRepository&) = delete; + PlayerGuildRepository& operator=(const PlayerGuildRepository&) = delete; + + std::unordered_set GetPlayerGuildsIds(); + + std::unordered_set GetGuildMembersIds(uint32_t guildId); + +private: + PlayerGuildRepository() = default; + ~PlayerGuildRepository() = default; +}; + +#define sPlayerGuildRepository PlayerGuildRepository::GetInstance() + +#endif diff --git a/src/service/inventory/abstract/AbstractItemVisitor.h b/src/service/inventory/abstract/AbstractItemVisitor.h new file mode 100644 index 0000000000..124bcb9b0e --- /dev/null +++ b/src/service/inventory/abstract/AbstractItemVisitor.h @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#pragma once + +#include +#include +#include +#include "Define.h" +#include "ItemTemplate.h" +#include "Player.h" + +#include "Log.h" + +class AbstractItemVisitor +{ +public: + virtual ~AbstractItemVisitor() = default; + + virtual bool process(Player* player, Item* item) + { + return false; + } + + virtual bool visit(Player* player, Item* item) + { + return false; + } + + bool equipArmor(Player* player, Item* item, EquipmentSlots slot) + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + if (itemTemplate->Class != ITEM_CLASS_ARMOR) + return false; + + // Necessary because CanEquipItem is poorly typed. + // We also don't want our parameter to be mutated so we use a disposable variable instead. + uint16_t destinationSlot = slot; + bool canEquipItem = player->CanEquipItem(item->GetSlot(), destinationSlot, item, true); + + if (!canEquipItem) + return false; + + const Item* equippedItem = player->GetItemByPos(slot); + + if (equippedItem == nullptr) + { + player->EquipItem(slot, item, true); + + return true; + } + + player->SwapItem(item->GetSlot(), slot); + + return true; + } + + bool equipWeapon(Player* player, Item* item, EquipmentSlots slot) + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + if (itemTemplate->Class != ITEM_CLASS_WEAPON) + return false; + + // Necessary because CanEquipItem is poorly typed. + // We also don't want our parameter to be mutated so we use a disposable variable instead. + uint16_t destinationSlot = slot; + bool canEquipItem = player->CanEquipItem(item->GetSlot(), destinationSlot, item, true); + + if (!canEquipItem) + return false; + + // In case we need to unequip the off-hand we need at least one slot + if (player->GetFreeInventorySpace() == 0) + return false; + + const Item* equippedItem = player->GetItemByPos(slot); + + if (equippedItem == nullptr) + { + player->EquipItem(slot, item, true); + player->AutoUnequipOffhandIfNeed(); + + return true; + } + + player->SwapItem(item->GetSlot(), slot); + + return true; + } + + void destroy(Player* player, Item* item) + { + if (player == nullptr) + return; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return; + } + + LOG_ERROR("playerbots", "Destroy item {}", std::to_string(itemTemplate->ItemId)); + + player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true); + } + + void destroyAll(Player* player, Item* item) + { + if (player == nullptr) + return; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return; + } + + uint32_t count = item->GetCount(); + + LOG_ERROR("playerbots", "Destroy multiple items of {}, ({})", std::to_string(itemTemplate->ItemId), std::to_string(count)); + + player->DestroyItemCount(item, count, true); + } + + void magicSell(Player* player, Item* item) + { + if (player == nullptr || item == nullptr) + return; + + if (item->GetState() == ITEM_REMOVED) + return; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return; + } + + LOG_ERROR("playerbots", "Magic selling item {}", std::to_string(itemTemplate->ItemId)); + + if (itemTemplate->SellPrice) + { + uint32_t count = item->GetCount(); + + player->ModifyMoney(itemTemplate->SellPrice * count); + LOG_ERROR("playerbots", "Magic sold item {} for {}", std::to_string(itemTemplate->ItemId), std::to_string(itemTemplate->SellPrice * count)); + } + + this->destroy(player, item); + } + +protected: + bool isAllowed(const ItemTemplate* itemTemplate) + { + if (itemTemplate == nullptr) + return false; + + const std::unordered_set forbiddenItemsGUIDs = this->getForbiddenItemsGUIDs(); + + return forbiddenItemsGUIDs.find(itemTemplate->ItemId) == forbiddenItemsGUIDs.end(); + } + + bool isAllowed(Item* item) + { + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + return this->isAllowed(itemTemplate); + } + + virtual const std::unordered_set getForbiddenItemsGUIDs() + { + return {}; + } +}; diff --git a/src/service/inventory/armor/ArmorItemVisitor.h b/src/service/inventory/armor/ArmorItemVisitor.h new file mode 100644 index 0000000000..458e705f3d --- /dev/null +++ b/src/service/inventory/armor/ArmorItemVisitor.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#pragma once + +#include +#include + +#include "InventoryService.h" +#include "Log.h" +#include "StatsWeightCalculator.h" +#include "ItemTemplate.h" +#include "Player.h" + +#include "AbstractItemVisitor.h" + +class ArmorItemVisitor : public AbstractItemVisitor +{ +public: + bool process(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + if (!player->CanUseItem(item)) + return false; + + + StatsWeightCalculator statisticsWeightCalculator = StatsWeightCalculator(player); + std::vector slots = InventoryService::GetInstance().getItemEquipmentSlots(itemTemplate); + + const float newItemStatisticsWeight = statisticsWeightCalculator.CalculateItem(itemTemplate->ItemId); + + statisticsWeightCalculator.Reset(); + + bool hasEquippedArmor = false; + + for (uint8_t i = 0; i < slots.size(); ++i) + { + Item* currentlyEquippedItem = player->GetItemByPos(slots[i]); + + if (currentlyEquippedItem == nullptr) + continue; + + hasEquippedArmor = true; + + const float existingItemStatisticsWeight = statisticsWeightCalculator.CalculateItem(currentlyEquippedItem->GetTemplate()->ItemId); + + if (existingItemStatisticsWeight < newItemStatisticsWeight) + { + this->equipArmor(player, item, slots[i]); + + return true; + } + } + + return false; + } + + bool visit(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + if (itemTemplate->Class != ITEM_CLASS_ARMOR) + { + LOG_ERROR("playerbots", "Item {} was not of class ARMOR ({}), found {}", itemTemplate->ItemId, std::to_string(ITEM_CLASS_ARMOR), std::to_string(itemTemplate->Class)); + + return false; + } + + if (!this->isAllowed(item)) + { + this->destroyAll(player, item); + + return true; + } + + if (this->process(player, item)) + { + LOG_ERROR("playerbots", "Item {} was a useful ARMOR item", itemTemplate->ItemId); + + return true; + } + + this->magicSell(player, item); + + return true; + } +}; diff --git a/src/service/inventory/consumable/ConsumableItemVisitor.h b/src/service/inventory/consumable/ConsumableItemVisitor.h new file mode 100644 index 0000000000..f255baedd0 --- /dev/null +++ b/src/service/inventory/consumable/ConsumableItemVisitor.h @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#pragma once + +#include "ItemTemplate.h" +#include "AbstractItemVisitor.h" +#include "Player.h" + +#include "ConsumableConsumableItemVisitor.h" +#include "ConsumablePotionItemVisitor.h" +#include "ConsumableElixirItemVisitor.h" + +class ConsumableItemVisitor : public AbstractItemVisitor +{ +public: + bool process(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + switch (itemTemplate->SubClass) + { + case ITEM_SUBCLASS_CONSUMABLE: + { + ConsumableConsumableItemVisitor visitor = ConsumableConsumableItemVisitor(); + bool visited = visitor.visit(player, item); + + return visited; + } + + case ITEM_SUBCLASS_POTION: + { + ConsumablePotionItemVisitor visitor = ConsumablePotionItemVisitor(); + bool visited = visitor.visit(player, item); + + return visited; + } + + case ITEM_SUBCLASS_ELIXIR: + { + ConsumableElixirItemVisitor visitor = ConsumableElixirItemVisitor(); + bool visited = visitor.visit(player, item); + + return visited; + } + + default: + + return false; + } + + return false; + } + + bool visit(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + if (itemTemplate->Class != ITEM_CLASS_CONSUMABLE) + { + LOG_ERROR("playerbots", "Item {} was not of class CONSUMABLE ({}), found {}", itemTemplate->ItemId, std::to_string(ITEM_CLASS_ARMOR), std::to_string(itemTemplate->Class)); + + return false; + } + + if (this->process(player, item)) + { + LOG_ERROR("playerbots", "Item {} was a useful CONSUMABLE item", itemTemplate->ItemId); + + return true; + } + + this->magicSell(player, item); + + return true; + } + + void destroyAll(Player* player, Item* item) + { + if (player == nullptr) + return; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return; + } + + uint32_t count = item->GetCount(); + + LOG_ERROR("playerbots", "Destroy multiple items of {}, ({})", std::to_string(item->GetTemplate()->ItemId), std::to_string(count)); + + player->DestroyItemCount(item, count, true); + } + + void magicSell(Player* player, Item* item) + { + if (player == nullptr || item == nullptr) + return; + + if (item->GetState() == ITEM_REMOVED) + return; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return; + } + + LOG_ERROR("playerbots", "Magic selling item {}", std::to_string(itemTemplate->ItemId)); + + uint32_t count = itemTemplate->GetMaxStackSize(); + + if (itemTemplate->SellPrice) + { + player->ModifyMoney(itemTemplate->SellPrice * count); + LOG_ERROR("playerbots", "Magic sold item {} for {}", std::to_string(itemTemplate->ItemId), std::to_string(itemTemplate->SellPrice * count)); + } + + player->DestroyItemCount(item, count, true); + } +}; diff --git a/src/service/inventory/consumable/consumable/ConsumableConsumableItemVisitor.h b/src/service/inventory/consumable/consumable/ConsumableConsumableItemVisitor.h new file mode 100644 index 0000000000..90e1e9ee2a --- /dev/null +++ b/src/service/inventory/consumable/consumable/ConsumableConsumableItemVisitor.h @@ -0,0 +1,914 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#pragma once + +#include "ItemTemplate.h" +#include "AbstractItemVisitor.h" +#include "Player.h" + +class ConsumableConsumableItemVisitor final : public AbstractItemVisitor +{ +public: + + bool process(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + const uint8_t playerClass = player->getClass(); + const bool isRoguePoison = this->getRoguePoisonsItemsGUIDs().find(itemTemplate->ItemId) != this->getRoguePoisonsItemsGUIDs().end(); + + if (playerClass != CLASS_ROGUE && isRoguePoison) + return false; + + const bool isMageItem = this->getMageItemsGUIDs().find(itemTemplate->ItemId) != this->getMageItemsGUIDs().end(); + + if (playerClass != CLASS_MAGE && isMageItem) + return false; + + const bool isWarlockItem = this->getWarlockItemsGUIDs().find(itemTemplate->ItemId) != this->getWarlockItemsGUIDs().end(); + + if (playerClass != CLASS_WARLOCK && isWarlockItem) + return false; + + const bool isUnwantedItem = this->getUnwantedItemsGUIDs().find(itemTemplate->ItemId) != this->getUnwantedItemsGUIDs().end(); + + if (isUnwantedItem) + return false; + + const bool isQuestConsumableItem = this->getQuestConsumableItemsGUIDs().find(itemTemplate->ItemId) != this->getQuestConsumableItemsGUIDs().end(); + + if (isQuestConsumableItem && !player->HasQuestForItem(itemTemplate->ItemId)) + return false; + + return true; + } + + bool visit(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + if (itemTemplate->Class != ITEM_CLASS_CONSUMABLE) + { + LOG_ERROR("playerbots", "Item {} was not of class CONSUMABLE ({}), found {}", itemTemplate->ItemId, std::to_string(ITEM_CLASS_ARMOR), std::to_string(itemTemplate->Class)); + + return false; + } + + if (itemTemplate->SubClass != ITEM_SUBCLASS_CONSUMABLE) + { + LOG_ERROR("playerbots", "Item {} was not of subclass CONSUMABLE ({}), found {}", itemTemplate->ItemId, std::to_string(ITEM_SUBCLASS_CONSUMABLE), std::to_string(itemTemplate->SubClass)); + + return false; + } + + if (!this->isAllowed(item)) + { + this->destroyAll(player, item); + + return true; + } + + if (this->process(player, item)) + { + LOG_ERROR("playerbots", "Item {} was a useful CONSUMABLE item", itemTemplate->ItemId); + + return true; + } + + return false; + } + +protected: + + const std::unordered_set getForbiddenItemsGUIDs() + { + return { + 1199, // Charged Soulstone + 1700, // Admin Warlord's Claymore + 1995, // Deprecated Cat's Paw + 3438, // Ankh of Resurrection + 4420, // NPC Equip 4420 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 4423, // NPC Equip 4423 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 4842, // test => Illegal item that should not even be present in the core as it is not present in any WotLK database + 5046, // Locked Gift => Illegal item that should not even be present in the core as it is not present in any WotLK database + 5047, // Skull Wrapping Paper => Illegal item that should not even be present in the core as it is not present in any WotLK database + 5224, // NPC Equip 5224 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 5225, // NPC Equip 5225 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 5378, // Shane Test (DELETE ME) => Illegal item that should not even be present in the core as it is not present in any WotLK database + 6244, // ggggfg => Illegal item that should not even be present in the core as it is not present in any WotLK database + 6638, // Air Sapta => Apparently this sapta is the only one not needed by shamans? + 6852, // Eternal Eye => Quest item seemingly linked to no quest + 6927, // Big Will's Ear => Quest item seemingly linked to no quest. It was supposedly dropped by Big Will but the quest requires killing him without looting him. + 7147, // NPC Equip 7147 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 7168, // NPC Equip 7168 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 7388, // Skull Key => Quest item seemingly linked to no quest + 9232, // NPC Equip 9232 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 9319, // Nimboya's Laden Pike => Quest item seemingly linked to no quest + 10419, // NPC Equip 10419 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 10448, // NPC Equip 10448 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 10449, // NPC Equip 10449 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 10451, // NPC Equip 10451 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 10452, // NPC Equip 10452 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 10453, // NPC Equip 10453 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 11182, // NPC Equip 11182 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 11183, // NPC Equip 11183 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 11616, // DEBUG Samophlange Manual Page + 12246, // NPC Equip 12246 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 12385, // test => Illegal item that should not even be present in the core as it is not present in any WotLK database + 12439, // NPC Equip 12439 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 12441, // NPC Equip 12441 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 13294, // NPC Equip 13294 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 17350, // NPC Equip 17350 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 17729, // NPC Equip 17729 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 18595, // Blood Opal => Item not present in WotLK. + 19063, // NPC Equip 19063 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 19977, // NPC Equip 19977 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 20365, // NPC Equip 20365 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 20386, // NPC Equip 20386 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 20473, // NPC Equip 20473 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 20905, // NPC Equip 20905 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21238, // Winter Veil Cookie UNUSED + 21556, // NPC Equip 21556 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21739, // Lunar Festival Invitation DEBUG + 21832, // NPC Equip 21832 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21834, // NPC Equip 21834 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21922, // NPC Equip 21922 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21961, // NPC Equip 21961 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21965, // NPC Equip 21965 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21966, // NPC Equip 21966 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21967, // NPC Equip 21967 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21968, // NPC Equip 21968 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21969, // NPC Equip 21969 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21970, // NPC Equip 21970 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21971, // NPC Equip 21971 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21972, // NPC Equip 21972 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21973, // NPC Equip 21973 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21974, // NPC Equip 21974 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21976, // NPC Equip 21976 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21977, // NPC Equip 21977 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 21978, // NPC Equip 21978 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 22118, // NPC Equip 22118 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 22124, // NPC Equip 22124 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 22125, // NPC Equip 22125 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 22126, // NPC Equip 22126 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 22127, // NPC Equip 22127 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 22129, // NPC Equip 22129 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 22323, // NPC Equip 22323 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 23163, // Performer's Wand => Unobtainable item + 23164, // Bubbly Beverage => Unobtainable item + 23175, // Tasty Summer Treat => Unobtainable item (iCoke promotion) + 23176, // Fizzy Energy Drink => Unobtainable item (iCoke promotion?) + 23209, // NPC Equip 23209 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 23210, // NPC Equip 23210 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 23496, // NPC Equip 23496 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 23640, // NPC Equip 23640 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 23641, // NPC Equip 23641 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 23715, // Permanent Lung Juice Cocktail => Unobtainable item + 23718, // Permanent Ground Scorpok Assay => Unobtainable item + 23719, // Permanent Cerebral Cortex Compound => Unobtainable item + 23721, // Permanent Gizzard Gum => Unobtainable item + 23722, // Permanent R.O.I.D.S. => Unobtainable item + 23794, // Permanent Sheen of Zanza => Unobtainable item + 23795, // Permanent Spirit of Zanza => Unobtainable item + 23796, // Permanent Swiftness of Zanza => Unobtainable item + 23872, // NPC Equip 23872 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 23982, // NPC Equip 23982 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 26046, // NPC Equip 26046 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 26047, // NPC Equip 26047 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 27504, // NPC Equip 27504 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 28036, // NPC Equip 28036 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 28110, // Fat Gnome and Little Elf => Unobtainable item, probably removed due to tasteless reference to a crime against humanity. + 28131, // Reaver Buster Launcher => Seemingly unobtainable item. + 29585, // NPC Equip 29585 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 29805, // Socrethar's Head => TBC Beta quest item, unobtainable. + 29868, // QAEnchant Gloves +26 Attack Power + 29877, // NPC Equip 29877 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 31954, // NPC Equip 31954 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 32424, // NPC Equip 32424 => Wrong item, should be "Blade's Edge Ogre Brew" + 32426, // NPC Equip 32426 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 32669, // NPC Equip 32669 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 32913, // NPC Equip 32913 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33063, // Really Tough Brewfest Bread + 33090, // NPC Equip 33090 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33100, // NPC Equip 33100 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33217, // NPC Equip 33217 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33218, // Goblin Gumbo + 33219, // Goblin Gumbo Kettle + 33570, // NPC Equip 33570 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33572, // NPC Equip 33572 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33573, // NPC Equip 33573 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33574, // NPC Equip 33574 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33600, // NPC Equip 33600 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33601, // NPC Equip 33601 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33602, // NPC Equip 33602 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33603, // NPC Equip 33603 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33623, // NPC Equip 33623 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33624, // NPC Equip 33624 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33625, // NPC Equip 33625 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33626, // NPC Equip 33626 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33785, // NPC Equip 33785 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33786, // NPC Equip 33786 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33787, // NPC Equip 33787 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33788, // NPC Equip 33788 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 33800, // NPC Equip 33800 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 34046, // NPC Equip 34046 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 34047, // NPC Equip 34047 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 34048, // NPC Equip 34048 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 34071, // NPC Equip 34071 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 34151, // NPC Equip 34151 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 34152, // NPC Equip 34152 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 34153, // NPC Equip 34153 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 34154, // NPC Equip 34154 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 34155, // NPC Equip 34155 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 34156, // NPC Equip 34156 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 34250, // NPC Equip 34250 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 34251, // NPC Equip 34251 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 34252, // NPC Equip 34252 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 35120, // NPC Equip 35120 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 35667, // NPC Equip 35667 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 38165, // NPC Equip 38165 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 38236, // NPC Equip 38236 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 38685, // NPC Equip 38685 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 38702, // NPC Equip 38702 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 38704, // NPC Equip 38704 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 39163, // Test expire transform + 39600, // NPC Equip 39600 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 40308, // NPC Equip 40308 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 42437, // NPC Equip 42437 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 42764, // NPC Equip 42764 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 44624, // NPC Equip 44624 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 44628, // NPC Equip 44628 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 44630, // NPC Equip 44630 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 44804, // NPC Equip 44804 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 44805, // NPC Equip 44805 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 44807, // Indalamar's Holy Hand Grenade + 44813, // NPC Equip 44813 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 44816, // NPC Equip 44816 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 44832, // Squirt Gun [PH] + 44866, // Faithful Mule + 44867, // NPC Equip 44867 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 44964, // NPC Equip 44964 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 45126, // Trusty Mount [PH] + 46717, // NPC Equip 46717 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 46765, // Blue War Fuel (Mountain Dew Promotion) + 46766, // Red War Fuel (Mountain Dew Promotion) + 48416, // NPC Equip 48416 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 48601, // Red Rider Air Rifle Ammo + 49223, // Permission Slip + 49224, // NPC Equip 49224 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 49225, // NPC Equip 49225 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 49349, // NPC Equip 49349 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 49372, // NPC Equip 49372 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 49373, // Permission Slip + 49374, // NPC Equip 49374 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 49692, // NPC Equip 49692 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 50076, // NPC Equip 50076 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 50091, // NPC Equip 50091 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 50092, // NPC Equip 50092 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 50093, // Pet Prep: A Beginner's Guide + 50164, // NPC Equip 50164 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 52202, // Elemental Sapta + 52361, // NPC Equip 52361 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 53476, // NPC Equip 53476 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 53477, // NPC Equip 53477 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 54647, // NPC Equip 54647 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 54822, // Sen'jin Overcloak + }; + } + + const std::unordered_set getUnwantedItemsGUIDs() + { + return { + 835, // Large Rope Net + 1127, // Flash Bundle + 1176, // Smelling Salts + 1187, // Spiked Collar + 1191, // Bag of Marbles + 1322, // Fishliver Oil + 1434, // Glowing Wax Stick + 1970, // Restoring Balm + 3434, // Slumber Sand + 3456, // Dog Whistle + 4546, // Call of the Raptor + 4598, // Goblin Fishing Pole + 4941, // Really Sticky Glue + 4945, // Faintly Glowing Skull + 4952, // Stormstout + 4953, // Trogg Brew + 5421, // Fiery Blaze Enchantment + 5457, // Severed Voodoo Claw + 5845, // Flank of Meat + 5951, // Moist Towelette + 7516, // Tabetha's Instructions => Bots don't need instructions. + 8410, // R.O.I.D.S. + 8411, // Lung Juice Cocktail + 8412, // Ground Scorpok Assay + 8423, // Cerebral Cortex Compound + 8424, // Gizzard Gum, + 8432, // Eau de Mixilpixil + 10684, // Colossal Parachute + 10830, // M73 Frag Grenade + 12924, // Ritual Candle + 13149, // Eldarathian Tome of Summoning Vol. 1 + 13151, // The Mystic Studies of Hor'ank + 13152, // The Story With No Conclusion + 13153, // Tome of Mal'cin Vorail + 13154, // Jael'marin's Studies of the Arcane + 13508, // Eye of Arachnida + 13509, // Clutch of Foresight + 13514, // Wail of the Banshee + 13813, // Blessed Sunfruit Juice + 14894, // Lily Root + 15723, // Tea with Sugar + 15778, // Mechanical Yeti + 17048, // Rumsey Rum + 18209, // Energized Sparkplug + 18269, // Gordok Green Grog + 18284, // Kreeg's Stout Beatdown + 18297, // Thornling Seed + 19060, // Warsong Gulch Enriched Ration + 19061, // Warsong Gulch Iron Ration + 19062, // Warsong Gulch Field Ration + 19318, // Bottled Alterac Spring Water + 19997, // Harvest Nectar + 20062, // Arathi Basin Enriched Ration + 20063, // Arathi Basin Field Ration + 20064, // Arathi Basin Iron Ration + 20079, // Spirit of Zanza + 20080, // Sheen of Zanza + 20081, // Swiftness of Zanza + 20222, // Defiler's Enriched Ration + 20223, // Defiler's Field Ration + 20224, // Defiler's Iron Ration + 20225, // Highlander's Enriched Ration + 20226, // Highlander's Field Ration + 20227, // Highlander's Iron Ration + 20388, // Lollipop + 20389, // Candy Corn + 20390, // Candy Bar + 20397, // Hallowed Wand - Pirate + 20398, // Hallowed Wand - Ninja + 20399, // Hallowed Wand - Leper Gnome + 20409, // Hallowed Wand - Ghost + 20410, // Hallowed Wand - Bat + 20411, // Hallowed Wand - Skeleton + 20413, // Hallowed Wand - Random + 20414, // Hallowed Wand - Wisp + 20557, // Hallow's End Pumpkin Treat + 21212, // Fresh Holly + 21241, // Winter Veil Eggnog + 21325, // Mechanical Greench + 21537, // Festival Dumplings + 21711, // Lunar Festival Invitation + 21744, // Lucky Rocket Cluster + 21745, // Elder's Moonstone + 21815, // Love Token + 22192, // Bloodkelp Elixir of Dodging + 22193, // Bloodkelp Elixir of Resistance + 22236, // Buttermilk Delight + 22237, // Dark Desire + 22238, // Very Berry Cream + 22239, // Sweet Surprise + 22259, // Unbestowed Friendship Bracelet + 22260, // Friendship Bracelet + 22743, // Bloodsail Sash + 22778, // Scourgebane Infusion + 22779, // Scourgebane Draught + 22795, // Fel Blossom + 23161, // Freshly-Squeezed Lemonade + 23194, // Lesser Mark of the Dawn + 23195, // Mark of the Dawn + 23196, // Greater Mark of the Dawn + 23211, // Toasted Smorc + 23215, // Bag of Smorc Ingredients + 23246, // Fiery Festival Brew + 23326, // Midsummer Sausage + 23327, // Fire-toasted Bun + 23379, // Cinder Bracers + 23435, // Elderberry Pie + 23492, // Suntouched Special Reserve + 23584, // Loch Modan Lager + 23585, // Stouthammer Lite + 23586, // Aerie Peak Pale Ale + 23985, // Crystal of Vitality + 23986, // Crystal of Insight + 23989, // Crystal of Ferocity + 24006, // Grunt's Waterskin + 24007, // Footman's Waterskin + 24408, // Edible Stalks + 24421, // Nagrand Cherry + 24429, // Expedition Flare + 24540, // Edible Fern + 25498, // Rough Stone Statue + 25880, // Coarse Stone Statue + 25881, // Heavy Stone Statue + 25882, // Solid Stone Statue + 25883, // Dense Stone Statue + 25884, // Primal Stone Statue + 27317, // Elemental Sapta + 27553, // Crimson Steer Energy Drink + 29482, // Ethereum Essence + 30309, // Stonebreaker Brew + 30499, // Brightstone Wine + 30615, // Halaani Whiskey + 30858, // Peon Sleep Potion + 31337, // Orb of the Blackwhelp + 31449, // Distilled Stalker Sight + 31450, // Sealth of the Stalker + 31451, // Pure Energy + 31535, // Bloodboil Poison + 32563, // Grilled Picnic Treat + 32971, // Water Bucket + 33023, // Savory Sausage + 33024, // Pickled Sausage + 33025, // Spicy Smoked Sausage + 33026, // The Golden Link + 33028, // Barleybrew Light + 33028, // Barleybrew Dark + 33030, // Barleybrew Clear + 33031, // Thunder 45 + 33032, // Thunderbrew Ale + 33033, // Thunderbrew Stout + 33034, // Gordok Grog + 33035, // Ogre Mead + 33036, // Mudder's Milk + 33043, // The Essential Brewfest Pretzel + 33226, // Tricky Treat + 33234, // Iced Berry Slush + 33236, // Fizzy Faire Drink "Classic" + 33246, // Funnel Cake + 33254, // Afrazi Forest Strider Drumstick + 33312, // Mana Sapphire + 33929, // Brewfest Brew + 33956, // Harkor's Home Brew + 34017, // Small Step Brew + 34018, // Long Stride Brew + 34019, // Path of Brew + 34020, // Jungle River Water + 34021, // Brewdo Magic + 34022, // Stout Shrunken Head + 34044, // B-Ball + 34063, // Dried Sausage + 34064, // Succulent Sausage + 34065, // Spiced Onion Cheese + 34068, // Weighted Jack-o'-Lantern + 34077, // Crudely Wrapped Gift + 34410, // Honeyed Holiday Ham + 34412, // Sparkling Apple Cider + 34599, // Juggling Torch + 35223, // Papa Hummel's Old-Fashioned Pet Biscuit + 35946, // Fizzcrank Practice Parachute + 36877, // Folded Letter + 37431, // Fetch Ball + 37488, // Wild Winter Pilsner + 37489, // Izzard's Ever Flavor + 37490, // Aromatic Honey Brew + 37491, // Metok's Bubble Bock + 37492, // Springtime Stout + 37493, // Blackrock Lager + 37494, // Stranglethorn Brew + 37495, // Draenic Pale Ale + 37496, // Binary Brew + 37497, // Autumnal Acorn Ale + 37498, // Bartlett's Bitter Brew + 37499, // Lord of Frost's Private Label + 37582, // Pyroblast Cinnamon Ball + 37583, // G.N.E.R.D.S. + 37584, // Soothing Spearmint Candy + 37585, // Chewy Fel Taffy + 37604, // Tooth Pick + 37750, // Fresh Brewfest Hops + 37863, // Direbrew's Remote + 37878, // Worg's Blood Elixir + 37898, // Wild Winter Pilsner + 37899, // Izzard's Ever Flavor + 37900, // Aromatic Honey Brew + 37901, // Metok's Bubble Bock + 37902, // Springtime Stout + 37903, // Blackrock Lager + 37904, // Stranglethorn Brew + 37905, // Draenic Pale Ale + 37906, // Binary Brew + 37907, // Autumnal Acorn Ale + 37908, // Bartlett's Bitter Brew + 37909, // Lord of Frost's Private Label + 37925, // Experimental Mixture + 38291, // Ethereal Mutagen + 38294, // Ethereal Liqueur + 38300, // Diluted Ethereum Essence + 38320, // Dire Brew + 38518, // Cro's Apple + 38577, // Party G.R.E.N.A.D.E. + 38587, // Empty Brewfest Stein + 38626, // Empty Brew Bottle + 39476, // Fresh Goblin Brewfest Hops + 39477, // Fresh Dwarven Brewfest Hops + 39738, // Thunderbrew's Hard Ale + 42342, // Bag of Popcorn + 42350, // Bag of Peanuts + 42381, // Anguish Ale + 42436, // Chocolate Celebration Cake + 42438, // Lovely Cake + 42439, // Big Berry Pie + 43088, // Dalaran Apple Bowl + 43135, // Fate Rune of Fleet Feet + 43352, // Pet Grooming Kit + 43462, // Airy Pale Ale + 43470, // Worg Tooth Oatmeal Stout + 43471, // Rork Red Ribbon + 43472, // Snowfall Lager + 43473, // Drakefire Chile Ale + 43489, // Mohawk Grenade + 43626, // Happy Pet Snack + 44064, // Nepeta Leaf + 44065, // Oracle Secret Solution + 44435, // Windle's Lighter + 44481, // Grindgear Toy Gorilla + 44482, // Trusty Copper Racer + 44599, // Zippy Copper Racer + 44601, // Heavy Copper Racer + 44610, // Fresh Dalaran Bread + 44612, // Dalaran Swiss Wheel + 44613, // Aged Dalaran Sharp Wheel + 44621, // Bottle of Dalaran White + 44622, // Cask of Dalaran White + 44623, // Bottle of Dalaran Red + 44625, // Bottle of Aged Dalaran Red + 44626, // Cask of Aged Dalaran Red + 44627, // Bottle of Peaked Dalaran Red + 44629, // Cask of Peaked Dalaran Red + 44632, // Cask of Dalaran Red + 44698, // Intravenous Healing Potion + 44716, // Mysterious Fermented Liquid + 44792, // Blossoming Branch + 44812, // Turkey Shooter + 44817, // The Mischief Maker + 44818, // Noblegarden Egg + 44844, // Turkey Caller + 44849, // Tiny Green Ragdoll + 44943, // Icy Prism + 45047, // Sandbox Tiger + 46319, // Tournament Brew + 46399, // Thunder's Plunder + 46400, // Barleybrew Gold + 46401, // Crimson Stripe + 46402, // Promise of the Pandaren + 46403, // Chuganpug's Delight + 46711, // Spirit Candle + 46718, // Orange Marigold + 46725, // Red Rider Air Rifle + 46783, // Pink Gumball + 49288, // Little Ivory Raptor Whistle + 49289, // Little White Stallion Bridle + 49856, // "VICTORY" Perfume + 49857, // "Enchantress" Perfume + 49858, // "Forever" Perfume + 49859, // "Bravado" Cologne + 49860, // "Wizardry" Cologne + 49861, // "STALWART" Cologne + 49936, // Lovely Stormwind Card + 49937, // Lovely Undercity Card + 49938, // Lovely Darnassus Card + 49939, // Lovely Orgrimmar Card + 49940, // Lovely Ironforge Card + 49941, // Lovely Thunder Bluff Card + 49942, // Lovely Exodar Card + 49943, // Lovely Silvermoon City Card + 50163, // Lovely Rose + 54455, // Paint Bomb + }; + } + + const std::unordered_set getQuestConsumableItemsGUIDs() + { + return { + 1262, // Keg of Thunderbrew Lager + 5880, // Crate With Holes + 6074, // War Horn Mouthpiece + 6464, // Wailing Essence + 6486, // Singed Scale + 6635, // Earth Sapta + 6636, // Fire Sapta + 6637, // Water Sapta + 6781, // Bartleby's Mug + 6782, // Marshal Haggard's Badge + 6812, // Case of Elunite + 6841, // Vial of Phlogiston + 6842, // Furen's Instructions + 6851, // Essence of the Exile + 6926, // Furen's Notes + 6929, // Bath'rah's Parchment + 7127, // Powdered Azurite + 7227, // Balnir Snapdragons + 7266, // Ur's Treatise on Shadow Magic + 7627, // Dolanaar Delivery + 7629, // Ukor's Burden + 7970, // E.C.A.C. + 8048, // Emerald Dreamcatcher + 8095, // Hinott's Oil + 8548, // Divino-matic Rod + 9546, // Simple Scroll + 9569, // Hallowed Scroll + 10621, // Runed Scroll + 10663, // Essence of Hakkar + 10687, // Empty Vial Labeled #1 + 10688, // Empty Vial Labeled #2 + 10689, // Empty Vial Labeled #3 + 10690, // Empty Vial Labeled #4 + 11148, // Samophlange Manual Page + 11405, // Giant Silver Vein + 11413, // Nagmara's Filled Vial + 11914, // Empty Cursed Ooze Jar + 11948, // Empty Tainted Ooze Jar + 11953, // Empty Pure Sample Jar + 12533, // Roughshod Pike + 12650, // Attuned Dampener + 12712, // Warosh's Mojo + 12884, // Arnak's Hoof + 12885, // Pamela's Doll + 12886, // Pamela's Doll's Head + 12894, // Joseph's Wedding Ring + 12922, // Empty Canteen + 13155, // Resonating Skull + 13156, // Mystic Crystal + 13562, // Remains of Trey Lightforge + 13703, // Kodo Bone + 13761, // Frozen Eggs + 14542, // Kravel's Crate + 15314, // Bundle of Relics + 16282, // Bundle of Hides + 20470, // Solanian's Scrying Orb + 20471, // Scroll of Scourge Magic + 20472, // Solanian's Journal + 23361, // Cleansing Vial + 23417, // Sanctified Crystal + 23645, // Seer's Relic + 24330, // Drain Schematics + 24355, // Ironvine Seeds + 24407, // Uncatalogued Species + 24474, // Violet Scrying Crystal + 25465, // Stormcrow Amulet + 28038, // Seaforium PU-36 Explosive Nether Modulator + 28132, // Area 52 Special + 28513, // Demonic Rune Stone + 28554, // Shredder Spare Parts + 28571, // Blank Scroll + 28580, // B'naar Console Transcription + 28607, // Sunfury Disguise + 28635, // Sunfury Arcanist Robes + 28636, // Sunfury Researcher Gloves + 28637, // Sunfury Guardsman Medallion + 28784, // Unyielding Banner Scrap => Maybe unused quest item? + 29162, // Galaxis Soul Shard + 29324, // Warp-Attuned Orb + 29443, // Bloodmaul Brutebane Brew + 29624, // First Half of Socrethar's Stone + 29625, // Second Half of Socrethar's Stone + 29699, // Socrethar's Teleportation Stone + 29778, // Phase Disruptor + 29796, // Socrethar's Teleportation Stone + 29905, // Kael's Vial Remnant + 29906, // Vashj's Vial Remnant + 30260, // Voren'thal's Package + 30540, // Tally's Waiver (Unsigned) + 30811, // Scroll of Demonic Unbanishing + 31121, // Costume Scraps + 31122, // Overseer Disguise + 31495, // Grishnath Orb + 31517, // Dire Pinfeather + 31518, // Exorcism Feather + 31702, // Challenge from the Horde + 31795, // Draenei Prayer Beads + 32406, // Skyguard Blasting Charges + 32602, // Crystalforged Darkrune + 32848, // Explosives Package + 33079, // Murloc Costume + 33099, // Intact Plague Container + 33277, // Tome of Thomas Thomson + 33349, // Plague Vials + 33614, // Empty Apothecary's Flask => Possibly unaccessible to players but still linked to a quest. + 33615, // Flask of Vrykul Blood => Possibly unaccessible to players but still linked to a quest. + 33616, // Unstable Mix => Possibly unaccessible to players but still linked to a quest. + 33617, // Balanced Concoction => Possibly unaccessible to players but still linked to a quest. + 33619, // Lysander's Strain + 33621, // Plague Spray + 33797, // Portable Brewfest Keg + 34023, // Empty Apothecary's Flask + 34024, // Flask of Vrykul Blood + 34076, // Fish Bladder + 34475, // Arcane Charges + 35704, // Incendiary Explosives + 37173, // Geomancer's Orb + 37198, // Prototype Neural Needler + 37265, // Tua'kea's Breathing Bladder + 37661, // Gossamer Potion + 37877, // Silver Feather + 38629, // Orders from the Lich King + 38657, // Freya's Ward + 39698, // Light-infused Artifact + 40390, // Vic's Emergency Air Tank + 40482, // Dual-plagued Brain + 40725, // Steam-Powered Auctioneer + 44576, // Bright Flare + 44806, // Brightly Colored Shell Fragment + 45784, // Thorim's Sigil + 45786, // Hodir's Sigil + 45787, // Mimiron's Sigil + 45788, // Freya's Sigil + 45791, // Sigils of the Watchers + 45814, // Freya's Sigil + 45815, // Hodir's Sigil + 45816, // Mimiron's Sigil + 45817, // Thorim's Sigil + 45855, // Sigils of the Watchers + }; + } + + const std::unordered_set getRoguePoisonsItemsGUIDs() + { + return { + 2892, // Deadly Poison + 2893, // Deadly Poison II + 3775, // Crippling Poison + 3776, // Crippling Poison II + 5237, // Mind-numbing Poison + 6947, // Instant Poison + 6949, // Instant Poison II + 6950, // Instant Poison III + 6951, // Mind-numbing Poison II => Useless in WotLK but useful in earlier expansions, kept for IP use. + 8926, // Instant Poison IV + 8927, // Instant Poison V + 8928, // Instant Poison VI + 8984, // Deadly Poison III + 8985, // Deadly Poison IV + 9186, // Mind-numbing Poison III => Useless in WotLK but useful in earlier expansions, kept for IP use. + 10918, // Wound Poison + 10920, // Wound Poison II + 10921, // Wound Poison III + 10922, // Wound Poison IV + 20844, // Deadly Poison V + 21835, // Anesthetic Poison + 21927, // Instant Poison VII + 22053, // Deadly Poison VI + 22054, // Deadly Poison VII + 22055, // Wound Poison V + }; + } + + const std::unordered_set getUsefulConsumableItemsGUIDs() + { + return { + 18606, // Alliance Battle Standard + 18607, // Horde Battle Standard + 19045, // Stormpike Battle Standard + 19046, // Frostwolf Battle Standard + 19150, // Sentinel Basic Care Package + 19151, // Sentinel Standard Care Package + 19152, // Sentinel Advanced Care Package + 19153, // Outrider Advanced Care Package + 19154, // Outrider Basic Care Package + 19155, // Outrider Standard Care Package + 19182, // Darkmoon Faire Prize Ticket + 19425, // Mysterious Lockbox + 20228, // Defiler's Advanced Care Package + 20229, // Defiler's Basic Care Package + 20230, // Defiler's Standard Care Package + 20231, // Arathor Advanced Care Package + 20233, // Arathor Basic Care Package + 20236, // Arathor Standard Care Package + 21740, // Small Rocket Recipes + 21741, // Cluster Rocket Recipes + 21742, // Large Rocket Recipes + 21743, // Large Cluster Rocket Recipes + 21746, // Lucky Red Envelope + 24140, // Blackened Urn => Useless in WotLK but useful in earlier expansions, kept for IP use. + 24289, // Chrono-beacon + 24494, // Tears of the Goddess + 24520, // Honor Hold Favor + 24522, // Thrallmar Favor + 24579, // Mark of Honor Hold + 24581, // Mark of Thrallmar + 27388, // Mr. Pinchy + 29735, // Holy Dust + 30690, // Power Converter + 32408, // Naj'entus Spine + 32542, // Imp in a Ball + 33865, // Amani Hex Stick + 33926, // Sealed Scroll Case + 33927, // Brewfest Pony Keg + 33928, // Hollowed Bone Decanter + 34583, // Aldor Supplies Package + 34584, // Scryer Supplies Package + 34585, // Scryer Supplies Package + 34587, // Aldor Supplies Package + 34592, // Aldor Supplies Package + 34593, // Scryer Supplies Package + 34594, // Scryer Supplies Package + 34595, // Aldor Supplies Package + 35232, // Shattered Sun Supplies + 34686, // Brazier of Dancing Flames + 34850, // Midsummer Ground Flower + 35512, // Pocket Full of Snow + 35945, // Brilliant Glass + 36748, // Dark Brewmaiden's Brew + 36862, // Worn Troll Dice + 36863, // Decahedral Dwarven Dice + 37815, // Emerald Essence + 37859, // Amber Essence + 37860, // Ruby Essence + 38186, // Ethereal Credit + 38233, // Path of Illidan + 39878, // Mysterious Egg + 39883, // Cracked Egg + 40110, // Haunted Memento + 41426, // Magically Wrapped Gift + 44113, // Small Spice Bag + 44606, // Toy Train Set + 44717, // Disgusting Jar + 44718, // Ripe Disgusting Jar + 44751, // Hyldnir Spoils + 45011, // Stormwind Banner + 45013, // Thunder Bluff Banner + 45014, // Orgrimmar Banner + 45015, // Sen'jin Banner + 45016, // Undercity Banner + 45017, // Silvermoon City Banner + 45018, // Ironforge Banner + 45019, // Gnomeregan Banner + 45020, // Exodar Banner + 45021, // Darnassus Banner + 45038, // Fragment of Val'anyr + 45039, // Shattered Fragments of Val'anyr + 45057, // Wind-Up Train Wrecker + 45063, // Foam Sword Rack + 45506, // Archivum Data Disc + 45705, // Argent Tournament Invitation + 45798, // Heroic Celestial Planetarium Key + 45857, // Archivum Data Disc + 45896, // Unbound Fragments of Val'anyr + 45897, // Reforged Hammer of Ancient Kings + 46029, // Magnetic Core + 46779, // Path of Cenarius + 46780, // Ogre Pinata + 46843, // Argent Crusader's Banner + 46847, // Seaforium Bombs + 47030, // Huge Seaforium Bombs + 47541, // Argent Pony Bridle + 49631, // Standard Apothecary Serving Kit + 50307, // Infernal Spear + 50471, // The Heartbreaker + 54212, // Instant Statue Pedestal + 54437, // Tiny Green Ragdoll + 54438, // Tiny Blue Ragdoll + 54651, // Gnomeregan Pride + 54653, // Darkspear Pride + }; + } + + const std::unordered_set getWarlockItemsGUIDs() + { + return { + 5232, // Minor Soulstone + 16892, // Lesser Soulstone + 16893, // Soulstone + 16895, // Greater Soulstone + 16896, // Major Soulstone + 22116, // Master Soulstone + 36895, // Demonic Soulstone + }; + } + + const std::unordered_set getMageItemsGUIDs() + { + return { + 5513, // Mana Jade + 8007, // Mana Citrine + 8008, // Mana Ruby + 22044, // Mana Emerald + 36799, // Mana Gem + }; + } +}; diff --git a/src/service/inventory/consumable/elixir/ConsumableElixirItemVisitor.h b/src/service/inventory/consumable/elixir/ConsumableElixirItemVisitor.h new file mode 100644 index 0000000000..48eb7f1fb1 --- /dev/null +++ b/src/service/inventory/consumable/elixir/ConsumableElixirItemVisitor.h @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#pragma once + +#include "ItemTemplate.h" +#include "AbstractItemVisitor.h" +#include "Player.h" +#include "SpellAuraDefines.h" +#include "SpellMgr.h" + +#include "AiFactory.h" +#include "PlayerbotAI.h" + +class ConsumableElixirItemVisitor final : public AbstractItemVisitor +{ +public: + bool process(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + if (!this->isAppropriateForPlayer(player, itemTemplate)) + return false; + + const uint32_t stackSize = itemTemplate->GetMaxStackSize(); + const uint32_t totalQuantity = player->GetItemCount(itemTemplate->ItemId); + + if (totalQuantity > stackSize) + return false; + + return true; + } + + bool visit(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + if (itemTemplate->Class != ITEM_CLASS_CONSUMABLE) + { + LOG_ERROR("playerbots", "Item {} was not of class CONSUMABLE ({}), found {}", itemTemplate->ItemId, std::to_string(ITEM_CLASS_ARMOR), std::to_string(itemTemplate->Class)); + + return false; + } + + if (itemTemplate->SubClass != ITEM_SUBCLASS_ELIXIR) + { + LOG_ERROR("playerbots", "Item {} was not of subclass ELIXIR ({}), found {}", itemTemplate->ItemId, std::to_string(ITEM_SUBCLASS_CONSUMABLE), std::to_string(itemTemplate->SubClass)); + + return false; + } + + if (!this->isAllowed(item)) + { + this->destroyAll(player, item); + + return true; + } + + if (this->process(player, item)) + { + LOG_ERROR("playerbots", "Item {} was a useful CONSUMABLE item", itemTemplate->ItemId); + + return true; + } + + return false; + } + +protected: + + const std::unordered_set getForbiddenItemsGUIDs() + { + return { + 2461, // Deprecated Elemental Resistance Potion + 2462, // Deprecated Potion of Lesser Invulnerability (Fix) + 5632, // Deprecated Cowardly Flight Potion + 23578, // Diet McWeaksauce + 23579, // The McWeaksauce Classic + 23696, // [PH] Potion of Heightened Senses [DEP] + 23698, // [PH] Nature Resist Potion [DEP] + 30793, // NPC Equip 30793 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 32762, // Rulkster's Brain Juice + 32763, // Rulkster's Secret Sauce + 34646, // NPC Equip 34646 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 37926, // NPC Equip 37926 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 39971, // NPC Equip 39971 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 40677, // NPC Equip 40677 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 42548, // NPC Equip 42548 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 45276, // Jillian's Genius Juice + 45277, // Jillian's Savior Sauce + }; + } + +private: + + bool isAppropriateForPlayer(Player* player, const ItemTemplate* itemTemplate) + { + if (player == nullptr) + return false; + + const SpellInfo* const spellInfo = SpellMgr::instance()->GetSpellInfo(itemTemplate->Spells[0].SpellId); + + if (spellInfo == nullptr) + return false; + + if (!spellInfo->HasEffect(SPELL_EFFECT_APPLY_AURA)) + return false; + + if (!spellInfo->HasAura(SPELL_AURA_MOD_STAT)) + return false; + + const std::array effects = spellInfo->GetEffects(); + + bool isUseful = false; + + for (const SpellEffectInfo effect : effects) + { + if (effect.MiscValue < STAT_STRENGTH || effect.MiscValue > STAT_SPIRIT) + continue; + + const Stats primaryStat = this->getPrimaryStat(player); + + if (primaryStat == effect.MiscValue) + return true; + } + + return false; + } + + const Stats getPrimaryStat(Player* player) + { + if (player == nullptr) + return STAT_STAMINA; + + const uint8_t playerClass = player->getClass(); + + switch (playerClass) + { + case CLASS_WARRIOR: + return STAT_STRENGTH; + case CLASS_PALADIN: + { + const uint8_t tab = AiFactory::GetPlayerSpecTab(player); + + switch (tab) + { + case PALADIN_TAB_HOLY: + return STAT_INTELLECT; + case PALADIN_TAB_PROTECTION: + return STAT_STAMINA; + case PALADIN_TAB_RETRIBUTION: + return STAT_STRENGTH; + } + + return STAT_STAMINA; + } + case CLASS_HUNTER: + return STAT_AGILITY; + case CLASS_ROGUE: + return STAT_AGILITY; + case CLASS_PRIEST: + return STAT_SPIRIT; + case CLASS_DEATH_KNIGHT: + return STAT_STRENGTH; + case CLASS_SHAMAN: + { + const uint8_t tab = AiFactory::GetPlayerSpecTab(player); + + switch (tab) + { + case SHAMAN_TAB_ELEMENTAL: + return STAT_INTELLECT; + case SHAMAN_TAB_ENHANCEMENT: + return STAT_AGILITY; + case SHAMAN_TAB_RESTORATION: + return STAT_INTELLECT; + } + + return STAT_STAMINA; + } + case CLASS_MAGE: + return STAT_INTELLECT; + case CLASS_DRUID: + { + const uint8_t tab = AiFactory::GetPlayerSpecTab(player); + + switch (tab) + { + case DRUID_TAB_BALANCE: + return STAT_INTELLECT; + case DRUID_TAB_FERAL: + return STAT_AGILITY; + case DRUID_TAB_RESTORATION: + return STAT_SPIRIT; + } + + return STAT_STAMINA; + } + } + } +}; diff --git a/src/service/inventory/consumable/potion/ConsumablePotionItemVisitor.h b/src/service/inventory/consumable/potion/ConsumablePotionItemVisitor.h new file mode 100644 index 0000000000..0be310a2b9 --- /dev/null +++ b/src/service/inventory/consumable/potion/ConsumablePotionItemVisitor.h @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#pragma once + +#include "ItemTemplate.h" +#include "AbstractItemVisitor.h" +#include "Player.h" +#include "SpellMgr.h" + +class ConsumablePotionItemVisitor final : public AbstractItemVisitor +{ +public: + bool process(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + const uint32_t maxStackSize = itemTemplate->GetMaxStackSize(); + const uint32_t totalQuantity = player->GetItemCount(itemTemplate->ItemId); + + if (totalQuantity > maxStackSize) + return false; + + return true; + } + + bool visit(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + if (itemTemplate->Class != ITEM_CLASS_CONSUMABLE) + { + LOG_ERROR("playerbots", "Item {} was not of class CONSUMABLE ({}), found {}", itemTemplate->ItemId, std::to_string(ITEM_CLASS_ARMOR), std::to_string(itemTemplate->Class)); + + return false; + } + + if (itemTemplate->SubClass != ITEM_SUBCLASS_CONSUMABLE) + { + LOG_ERROR("playerbots", "Item {} was not of subclass CONSUMABLE ({}), found {}", itemTemplate->ItemId, std::to_string(ITEM_SUBCLASS_CONSUMABLE), std::to_string(itemTemplate->SubClass)); + + return false; + } + + if (!this->isAllowed(item)) + { + this->destroyAll(player, item); + + return true; + } + + if (this->process(player, item)) + { + LOG_ERROR("playerbots", "Item {} was a useful CONSUMABLE item", itemTemplate->ItemId); + + return true; + } + + return false; + } + +protected: + + const bool isHealthPotion(Item* item) + { + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + return this->isHealthPotion(itemTemplate); + } + + const bool isHealthPotion(const ItemTemplate* itemTemplate) + { + const SpellInfo* const spellInfo = SpellMgr::instance()->GetSpellInfo(itemTemplate->Spells[0].SpellId); + + if (spellInfo == nullptr) + return false; + + if (spellInfo->HasEffect(SPELL_EFFECT_HEAL)) + return true; + + return false; + } + + const bool isManaPotion(const Item* item) + { + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + return this->isManaPotion(itemTemplate); + } + + const bool isManaPotion(const ItemTemplate* ItemTemplate) + { + const SpellInfo* const spellInfo = SpellMgr::instance()->GetSpellInfo(ItemTemplate->Spells[0].SpellId); + + if (spellInfo == nullptr) + return false; + + if (spellInfo->HasEffect(SPELL_EFFECT_ENERGIZE) && spellInfo->PowerType == POWER_MANA) + return true; + + return false; + } + + const std::unordered_set getForbiddenItemsGUIDs() + { + return { + 2461, // Deprecated Elemental Resistance Potion + 2462, // Deprecated Potion of Lesser Invulnerability (Fix) + 5632, // Deprecated Cowardly Flight Potion + 23578, // Diet McWeaksauce + 23579, // The McWeaksauce Classic + 23696, // [PH] Potion of Heightened Senses [DEP] + 23698, // [PH] Nature Resist Potion [DEP] + 30793, // NPC Equip 30793 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 32762, // Rulkster's Brain Juice + 32763, // Rulkster's Secret Sauce + 34646, // NPC Equip 34646 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 37926, // NPC Equip 37926 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 39971, // NPC Equip 39971 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 40677, // NPC Equip 40677 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 42548, // NPC Equip 42548 => Illegal item that should not even be present in the core as it is not present in any WotLK database + 45276, // Jillian's Genius Juice + 45277, // Jillian's Savior Sauce + }; + } + +}; diff --git a/src/service/inventory/container/ContainerItemVisitor.h b/src/service/inventory/container/ContainerItemVisitor.h new file mode 100644 index 0000000000..5f18485c63 --- /dev/null +++ b/src/service/inventory/container/ContainerItemVisitor.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#pragma once + +#include + +#include "SharedDefines.h" +#include "ItemTemplate.h" +#include "Player.h" + +#include "AbstractItemVisitor.h" + +class ContainerItemVisitor : public AbstractItemVisitor +{ +public: + bool process(Player* player, Item* item) override + { + + if (player == nullptr) + return false; + + const Bag* bag = item->ToBag(); + + // @TODO: Handle all container type + if (bag == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + if (itemTemplate->InventoryType == INVTYPE_QUIVER && player->getClass() != CLASS_HUNTER) + return false; + + uint8_t initialSlot = INVENTORY_SLOT_BAG_START; + + if (itemTemplate->InventoryType == INVTYPE_QUIVER) + initialSlot = INVENTORY_SLOT_BAG_END - 1; + + for (uint8_t i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) + { + Bag* equipedBag = player->GetBagByPos(i); + + if (!equipedBag || bag->GetBagSize() > equipedBag->GetBagSize()) + { + player->EquipItem(i, item, true); + + return true; + } + } + + return false; + } + + bool visit(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + if (itemTemplate->Class != ITEM_CLASS_CONTAINER) + { + LOG_ERROR("playerbots", "Item {} was not of class CONTAINER ({}), found {}", itemTemplate->ItemId, std::to_string(ITEM_CLASS_ARMOR), std::to_string(itemTemplate->Class)); + + return false; + } + + if (itemTemplate->InventoryType != INVTYPE_BAG) + return false; + + if (this->process(player, item)) + { + LOG_ERROR("playerbots", "Item {} was a useful CONTAINER item", itemTemplate->ItemId); + + return true; + } + + this->magicSell(player, item); + + return true; + } +}; diff --git a/src/service/inventory/gem/GemItemVisitor.h b/src/service/inventory/gem/GemItemVisitor.h new file mode 100644 index 0000000000..ff4d8e9729 --- /dev/null +++ b/src/service/inventory/gem/GemItemVisitor.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#pragma once + +#include "ItemTemplate.h" +#include "AbstractItemVisitor.h" +#include "Player.h" + +class GemItemVisitor : public AbstractItemVisitor +{ +public: + bool process(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + if (item == nullptr) + return false; + + // @TODO: Implement logic on gem processing. + return false; + } + + bool visit(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + if (itemTemplate->Class != ITEM_CLASS_GEM) + { + LOG_ERROR("playerbots", "Item {} was not of class GEM ({}), found {}", itemTemplate->ItemId, std::to_string(ITEM_CLASS_ARMOR), std::to_string(itemTemplate->Class)); + + return false; + } + + if (this->process(player, item)) + { + LOG_ERROR("playerbots", "Item {} was a useful GEM item", itemTemplate->ItemId); + + return true; + } + + this->magicSell(player, item); + + return true; + } +}; diff --git a/src/service/inventory/generic/GenericItemVisitor.h b/src/service/inventory/generic/GenericItemVisitor.h new file mode 100644 index 0000000000..a2cc9087bb --- /dev/null +++ b/src/service/inventory/generic/GenericItemVisitor.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#pragma once + +#include +#include "ItemTemplate.h" +#include "AbstractItemVisitor.h" +#include "Player.h" + +/** + * @brief Handles the inventory management of generic items (class 8). + * + * @remark There is only one 1 generic item in the game (6987 - Fish Scale) and it never made it live. + * This category of item is thus always useless. + * + */ +class GenericItemVisitor : public AbstractItemVisitor +{ +public: + bool process(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + if (player == nullptr) + return false; + + return false; + } + + bool visit(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + if (itemTemplate->Class != ITEM_CLASS_GENERIC) + { + LOG_ERROR("playerbots", "Item {} was not of class GENERIC ({}), found {}", itemTemplate->ItemId, std::to_string(ITEM_CLASS_ARMOR), std::to_string(itemTemplate->Class)); + + return false; + } + + LOG_ERROR("playerbots", "Player (bot) {} (#{}) had item of impossible category GENERIC (8) #{}", + player->GetName(), std::to_string(player->GetGUID().GetEntry()), std::to_string(item->GetTemplate()->ItemId)); + + this->destroy(player, item); + + return true; + } +}; diff --git a/src/service/inventory/glyph/GlyphItemVisitor.h b/src/service/inventory/glyph/GlyphItemVisitor.h new file mode 100644 index 0000000000..dbfcd412fd --- /dev/null +++ b/src/service/inventory/glyph/GlyphItemVisitor.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#pragma once + +#include "ItemTemplate.h" +#include "AbstractItemVisitor.h" +#include "Player.h" + +class GlyphItemVisitor : public AbstractItemVisitor +{ +public: + bool process(Player* , Item* ) override + { + // @TODO: Implement logic on glyph item processing. + return false; + } + + bool visit(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + if (itemTemplate->Class != ITEM_CLASS_GLYPH) + { + LOG_ERROR("playerbots", "Item {} was not of class GLYPH ({}), found {}", itemTemplate->ItemId, std::to_string(ITEM_CLASS_ARMOR), std::to_string(itemTemplate->Class)); + + return false; + } + + if (this->process(player, item)) + { + LOG_ERROR("playerbots", "Item {} was a useful GLYPH item", itemTemplate->ItemId); + + return true; + } + + this->magicSell(player, item); + + return true; + } +}; diff --git a/src/service/inventory/inventory/InventoryService.h b/src/service/inventory/inventory/InventoryService.h new file mode 100644 index 0000000000..9555b88738 --- /dev/null +++ b/src/service/inventory/inventory/InventoryService.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#pragma once + +#include +#include "ItemTemplate.h" +#include "Player.h" + +class InventoryService +{ +public: + + static InventoryService& GetInstance() + { + static InventoryService instance; + + return instance; + } + + InventoryService(const InventoryService&) = delete; + InventoryService& operator=(const InventoryService&) = delete; + + std::vector getItemEquipmentSlots(const ItemTemplate* itemTemplate) const + { + if (itemTemplate == nullptr) + return {}; + + switch (itemTemplate->InventoryType) + { + case INVTYPE_HEAD: + return { EQUIPMENT_SLOT_HEAD }; + + case INVTYPE_NECK: + return { EQUIPMENT_SLOT_NECK }; + + case INVTYPE_SHOULDERS: + return { EQUIPMENT_SLOT_SHOULDERS }; + + case INVTYPE_BODY: + return { EQUIPMENT_SLOT_BODY }; + + case INVTYPE_ROBE: + case INVTYPE_CHEST: + return { EQUIPMENT_SLOT_CHEST }; + + case INVTYPE_WAIST: + return { EQUIPMENT_SLOT_WAIST }; + + case INVTYPE_LEGS: + return { EQUIPMENT_SLOT_LEGS }; + + case INVTYPE_FEET: + return { EQUIPMENT_SLOT_FEET }; + + case INVTYPE_WRISTS: + return { EQUIPMENT_SLOT_WRISTS }; + + case INVTYPE_HANDS: + return { EQUIPMENT_SLOT_HANDS }; + + case INVTYPE_FINGER: + return { EQUIPMENT_SLOT_FINGER1, EQUIPMENT_SLOT_FINGER2 }; + + case INVTYPE_TRINKET: + return { EQUIPMENT_SLOT_TRINKET1, EQUIPMENT_SLOT_TRINKET2 }; + + case INVTYPE_WEAPON: + return { EQUIPMENT_SLOT_MAINHAND, EQUIPMENT_SLOT_OFFHAND }; + + case INVTYPE_WEAPONOFFHAND: + case INVTYPE_SHIELD: + return { EQUIPMENT_SLOT_OFFHAND }; + + case INVTYPE_RANGED: + case INVTYPE_THROWN: + case INVTYPE_RELIC: + return { EQUIPMENT_SLOT_RANGED }; + + case INVTYPE_CLOAK: + return { EQUIPMENT_SLOT_BACK }; + + case INVTYPE_WEAPONMAINHAND: + case INVTYPE_2HWEAPON: + return { EQUIPMENT_SLOT_MAINHAND }; + + case INVTYPE_TABARD: + return { EQUIPMENT_SLOT_TABARD }; + + case INVTYPE_BAG: + case INVTYPE_HOLDABLE: + case INVTYPE_AMMO: + case INVTYPE_RANGEDRIGHT: + case INVTYPE_QUIVER: + default: + return {}; + } + } +private: + InventoryService() = default; + ~InventoryService() = default; +}; diff --git a/src/service/inventory/key/KeyItemVisitor.h b/src/service/inventory/key/KeyItemVisitor.h new file mode 100644 index 0000000000..51307dfc6f --- /dev/null +++ b/src/service/inventory/key/KeyItemVisitor.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#pragma once + +#include "ItemTemplate.h" +#include "AbstractItemVisitor.h" +#include "Player.h" + +class KeyItemVisitor : public AbstractItemVisitor +{ +public: + bool process(Player* , Item* ) override + { + return true; + } + + bool visit(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + if (itemTemplate->Class != ITEM_CLASS_QUEST) + { + LOG_ERROR("playerbots", "Item {} was not of class QUEST ({}), found {}", itemTemplate->ItemId, std::to_string(ITEM_CLASS_ARMOR), std::to_string(itemTemplate->Class)); + + return false; + } + + if (this->process(player, item)) + { + LOG_ERROR("playerbots", "Item {} was a useful KEY item", itemTemplate->ItemId); + + return true; + } + + this->destroy(player, item); + + return true; + } +}; diff --git a/src/service/inventory/miscellaneous/MiscellaneousItemVisitor.h b/src/service/inventory/miscellaneous/MiscellaneousItemVisitor.h new file mode 100644 index 0000000000..631220c7fd --- /dev/null +++ b/src/service/inventory/miscellaneous/MiscellaneousItemVisitor.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#pragma once + +#include "ItemTemplate.h" +#include "AbstractItemVisitor.h" +#include "Player.h" + +class MiscellaneousItemVisitor : public AbstractItemVisitor +{ +public: + bool process(Player* , Item* ) override + { + // @TODO: Implement logic on miscellaneous item processing. + return false; + } + + bool visit(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + if (itemTemplate->Class != ITEM_CLASS_MISC) + { + LOG_ERROR("playerbots", "Item {} was not of class MISC ({}), found {}", itemTemplate->ItemId, std::to_string(ITEM_CLASS_ARMOR), std::to_string(itemTemplate->Class)); + + return false; + } + + if (this->process(player, item)) + { + LOG_ERROR("playerbots", "Item {} was a useful MISCELLANEOUS item", itemTemplate->ItemId); + + return true; + } + + this->magicSell(player, item); + + return true; + } +}; diff --git a/src/service/inventory/money/MoneyItemVisitor.h b/src/service/inventory/money/MoneyItemVisitor.h new file mode 100644 index 0000000000..0323b8dac0 --- /dev/null +++ b/src/service/inventory/money/MoneyItemVisitor.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#pragma once + +#include +#include "ItemTemplate.h" +#include "AbstractItemVisitor.h" +#include "Player.h" + +// Currency items +class MoneyItemVisitor : public AbstractItemVisitor +{ +public: + bool process(Player* player, Item* item) override + { + return true; + } + + bool visit(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + if (itemTemplate->Class != ITEM_CLASS_MONEY) + { + LOG_ERROR("playerbots", "Item {} was not of class MONEY ({}), found {}", itemTemplate->ItemId, std::to_string(ITEM_CLASS_ARMOR), std::to_string(itemTemplate->Class)); + + return false; + } + + if (!this->isAllowed(item)) + { + this->destroyAll(player, item); + + return true; + } + + if (this->process(player, item)) + { + LOG_ERROR("playerbots", "Item {} was a useful MONEY item", itemTemplate->ItemId); + + return true; + } + + this->magicSell(player, item); + + return true; + } + +protected: + + const std::unordered_set getForbiddenItemsGUIDs() override + { + return { + 37711, // Currency Token Test Token 1 + 37742, // Currency Token Test Token 2 + 38644, // Currency Token Test Token 3 + 41749, // Birmingham Test Item 3 + 43308, // Honor Points (item, not the real currency) + 43949, // zzzOLDDaily Quest Faction Token + 44209, // NPC Equip 44209 => Illegal item that should not even be present in the core as it is not present in any WotLK database + }; + } +}; diff --git a/src/service/inventory/permanent/PermanentItemVisitor.h b/src/service/inventory/permanent/PermanentItemVisitor.h new file mode 100644 index 0000000000..ef6337d7b2 --- /dev/null +++ b/src/service/inventory/permanent/PermanentItemVisitor.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#pragma once + +#include "ItemTemplate.h" +#include "AbstractItemVisitor.h" +#include "Player.h" + +/** + * @brief Handles the inventory management of generic items (class 14). + * + * @remark There is no item of this category in the game data. + * This category of item is thus always useless. + * + */ +class PermanentItemVisitor : public AbstractItemVisitor +{ +public: + bool process(Player* , Item* ) override + { + return true; + } + + bool visit(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + if (itemTemplate->Class != ITEM_CLASS_PERMANENT) + { + LOG_ERROR("playerbots", "Item {} was not of class PERMANENT ({}), found {}", itemTemplate->ItemId, std::to_string(ITEM_CLASS_ARMOR), std::to_string(itemTemplate->Class)); + + return false; + } + + LOG_ERROR("playerbots", "Player (bot) {} (#{}) had item of impossible category PERMANENT (14) #{}", + player->GetName(), std::to_string(player->GetGUID().GetEntry()), std::to_string(item->GetTemplate()->ItemId)); + + this->destroy(player, item); + + return true; + } +}; diff --git a/src/service/inventory/projectile/ProjectileItemVisitor.h b/src/service/inventory/projectile/ProjectileItemVisitor.h new file mode 100644 index 0000000000..3f0baaec7c --- /dev/null +++ b/src/service/inventory/projectile/ProjectileItemVisitor.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#pragma once + +#include "ItemTemplate.h" +#include "AbstractItemVisitor.h" +#include "Player.h" +#include "SharedDefines.h" + +class ProjectileItemVisitor : public AbstractItemVisitor +{ +public: + bool process(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + if (item == nullptr) + return false; + + if (player->getClass() == CLASS_HUNTER) + return true; + + // @TODO: Implement logic on projectile processing. + return false; + } + + bool visit(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + if (itemTemplate->Class != ITEM_CLASS_PROJECTILE) + { + LOG_ERROR("playerbots", "Item {} was not of class PROJECTILE ({}), found {}", itemTemplate->ItemId, std::to_string(ITEM_CLASS_ARMOR), std::to_string(itemTemplate->Class)); + + return false; + } + + if (this->process(player, item)) + { + LOG_ERROR("playerbots", "Item {} was a useful PROJECTILE item", itemTemplate->ItemId); + + return true; + } + + this->magicSell(player, item); + + return true; + } +}; diff --git a/src/service/inventory/quest/QuestItemVisitor.h b/src/service/inventory/quest/QuestItemVisitor.h new file mode 100644 index 0000000000..f840083e5d --- /dev/null +++ b/src/service/inventory/quest/QuestItemVisitor.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#pragma once + +#include +#include "ItemTemplate.h" +#include "AbstractItemVisitor.h" +#include "Log.h" +#include "Player.h" + +class QuestItemVisitor : public AbstractItemVisitor +{ +public: + bool process(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + const bool hasQuestForItem = player->HasQuestForItem(itemTemplate->ItemId, 0, true); + + LOG_ERROR("playerbots", "Has quest for item {}: {}", std::to_string(itemTemplate->ItemId), std::to_string(hasQuestForItem)); + + return hasQuestForItem; + } + + bool visit(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + if (itemTemplate->Class != ITEM_CLASS_QUEST) + { + LOG_ERROR("playerbots", "Item {} was not of class QUEST ({}), found {}", itemTemplate->ItemId, std::to_string(ITEM_CLASS_ARMOR), std::to_string(itemTemplate->Class)); + + return false; + } + + if (this->process(player, item)) + { + LOG_ERROR("playerbots", "Item {} was a useful QUEST item", itemTemplate->ItemId); + + return true; + } + + this->destroy(player, item); + + return true; + } +}; diff --git a/src/service/inventory/quiver/QuiverItemVisitor.h b/src/service/inventory/quiver/QuiverItemVisitor.h new file mode 100644 index 0000000000..35a6dbb5bf --- /dev/null +++ b/src/service/inventory/quiver/QuiverItemVisitor.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#pragma once + +#include "ItemTemplate.h" +#include "AbstractItemVisitor.h" +#include "Player.h" + +class QuiverItemVisitor : public AbstractItemVisitor +{ +public: + bool process(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + if (item == nullptr) + return false; + + // @TODO: Implement logic on quiver processing. + return false; + } + + bool visit(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + if (itemTemplate->Class != ITEM_CLASS_QUIVER) + { + LOG_ERROR("playerbots", "Item {} was not of class QUIVER ({}), found {}", itemTemplate->ItemId, std::to_string(ITEM_CLASS_ARMOR), std::to_string(itemTemplate->Class)); + + return false; + } + + if (this->process(player, item)) + { + LOG_ERROR("playerbots", "Item {} was a useful QUIVER item", itemTemplate->ItemId); + + return true; + } + + + this->magicSell(player, item); + + return true; + } +}; diff --git a/src/service/inventory/reagent/ReagentItemVisitor.h b/src/service/inventory/reagent/ReagentItemVisitor.h new file mode 100644 index 0000000000..721c73ea60 --- /dev/null +++ b/src/service/inventory/reagent/ReagentItemVisitor.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#pragma once + +#include "ItemTemplate.h" +#include "Player.h" + +#include "AbstractItemVisitor.h" + +class ReagentItemVisitor : public AbstractItemVisitor +{ +public: + bool process(Player* , Item* ) override + { + // @TODO: Implement logic on reagent processing. + return false; + } + + bool visit(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + if (itemTemplate->Class != ITEM_CLASS_REAGENT) + { + LOG_ERROR("playerbots", "Item {} was not of class REAGENT ({}), found {}", itemTemplate->ItemId, std::to_string(ITEM_CLASS_ARMOR), std::to_string(itemTemplate->Class)); + + return false; + } + + if (this->process(player, item)) + { + LOG_ERROR("playerbots", "Item {} was a useful REAGENT item", itemTemplate->ItemId); + + return true; + } + + this->magicSell(player, item); + + return true; + } +}; diff --git a/src/service/inventory/recipe/RecipeItemVisitor.h b/src/service/inventory/recipe/RecipeItemVisitor.h new file mode 100644 index 0000000000..32318009cb --- /dev/null +++ b/src/service/inventory/recipe/RecipeItemVisitor.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#pragma once + +#include "ItemTemplate.h" +#include "AbstractItemVisitor.h" +#include "Player.h" + +class RecipeItemVisitor : public AbstractItemVisitor +{ +public: + bool process(Player* , Item* ) override + { + // @TODO: Implement logic on recipe processing. + return false; + } + + bool visit(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + if (itemTemplate->Class != ITEM_CLASS_RECIPE) + { + LOG_ERROR("playerbots", "Item {} was not of class RECIPE ({}), found {}", itemTemplate->ItemId, std::to_string(ITEM_CLASS_ARMOR), std::to_string(itemTemplate->Class)); + + return false; + } + + if (this->process(player, item)) + { + LOG_ERROR("playerbots", "Item {} was a useful RECIPE item", itemTemplate->ItemId); + + return true; + } + + this->magicSell(player, item); + + return true; + } +}; diff --git a/src/service/inventory/trade-good/TradeGoodItemVisitor.h b/src/service/inventory/trade-good/TradeGoodItemVisitor.h new file mode 100644 index 0000000000..929331df28 --- /dev/null +++ b/src/service/inventory/trade-good/TradeGoodItemVisitor.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#pragma once + +#include "ItemTemplate.h" +#include "AbstractItemVisitor.h" +#include "Player.h" + +class TradeGoodItemVisitor : public AbstractItemVisitor +{ +public: + bool process(Player* , Item* ) override + { + // @TODO: Implement logic on projectile processing. + return false; + } + + bool visit(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + if (itemTemplate->Class != ITEM_CLASS_TRADE_GOODS) + { + LOG_ERROR("playerbots", "Item {} was not of class TRADE GOODS ({}), found {}", itemTemplate->ItemId, std::to_string(ITEM_CLASS_ARMOR), std::to_string(itemTemplate->Class)); + + return false; + } + + if (this->process(player, item)) + { + LOG_ERROR("playerbots", "Item {} was a useful TRADE GOODS item", itemTemplate->ItemId); + + return true; + } + + this->magicSell(player, item); + + return true; + } +}; diff --git a/src/service/inventory/weapon/WeaponItemVisitor.h b/src/service/inventory/weapon/WeaponItemVisitor.h new file mode 100644 index 0000000000..b97b440d75 --- /dev/null +++ b/src/service/inventory/weapon/WeaponItemVisitor.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#pragma once + +#include + +#include "ItemTemplate.h" +#include "Player.h" +#include "StatsWeightCalculator.h" + +#include "AbstractItemVisitor.h" +#include "InventoryService.h" + +class WeaponItemVisitor : public AbstractItemVisitor +{ +public: + bool process(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + if (!player->CanUseItem(item)) + return false; + + StatsWeightCalculator statisticsWeightCalculator = StatsWeightCalculator(player); + std::vector slots = InventoryService::GetInstance().getItemEquipmentSlots(itemTemplate); + + float newItemStatisticsWeight = statisticsWeightCalculator.CalculateItem(itemTemplate->ItemId); + + statisticsWeightCalculator.Reset(); + + for (uint8_t i = 0; i < slots.size(); ++i) + { + Item* currentlyEquippedItem = player->GetItemByPos(slots[i]); + + if (currentlyEquippedItem == nullptr) + continue; + + float existingItemStatisticsWeight = statisticsWeightCalculator.CalculateItem(currentlyEquippedItem->GetTemplate()->ItemId); + + if (existingItemStatisticsWeight < newItemStatisticsWeight) + { + this->equipWeapon(player, item, slots[i]); + + return true; + } + } + + return false; + } + + bool visit(Player* player, Item* item) override + { + if (player == nullptr) + return false; + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + if (itemTemplate == nullptr) + { + LOG_ERROR("playerbots", "Item {} had nullptr template", std::to_string(item->GetGUID().GetRawValue())); + + return false; + } + + if (itemTemplate->Class != ITEM_CLASS_WEAPON) + { + LOG_ERROR("playerbots", "Item {} was not of class WEAPON ({}), found {}", itemTemplate->ItemId, std::to_string(ITEM_CLASS_ARMOR), std::to_string(itemTemplate->Class)); + + return false; + } + + if (this->process(player, item)) + { + LOG_ERROR("playerbots", "Item {} was a useful WEAPON item", itemTemplate->ItemId); + + return true; + } + + this->magicSell(player, item); + + return true; + } +}; diff --git a/src/service/statistic/abstract/AbstractItemValueCalculationService.h b/src/service/statistic/abstract/AbstractItemValueCalculationService.h new file mode 100644 index 0000000000..db9c3b787e --- /dev/null +++ b/src/service/statistic/abstract/AbstractItemValueCalculationService.h @@ -0,0 +1,198 @@ +#ifndef _PLAYERBOT_ABSTRACT_ITEM_VALUE_CALCULATION_SERVICE_H +#define _PLAYERBOT_ABSTRACT_ITEM_VALUE_CALCULATION_SERVICE_H + +#include + +#include "ItemTemplate.h" +#include "Player.h" + +class AbstractItemValueCalculationService +{ +public: + + inline uint64_t calculateItemValue(Player* player, ItemTemplate* itemTemplate) + { + uint64_t itemValue = 0; + + for (uint8_t i = 0; i < itemTemplate->StatsCount; ++i) + { + uint8_t statisticWeight = this->getStatisticWeight(player, itemTemplate, itemTemplate->ItemStat[i].ItemStatType); + + itemValue += statisticWeight * itemTemplate->ItemStat[i].ItemStatValue; + } + + if (itemTemplate->Armor > 0) + itemValue += this->getArmorRatingWeight(player) * itemTemplate->Armor; + + if (itemTemplate->FireRes > 0) + itemValue += this->getFireResistanceWeight(player); + + if (itemTemplate->NatureRes > 0) + itemValue += this->getNatureResistanceWeight(player); + + if (itemTemplate->FrostRes > 0) + itemValue += this->getFrostResistanceWeight(player); + + if (itemTemplate->ShadowRes > 0) + itemValue += this->getShadowResistanceWeight(player); + + if (itemTemplate->ArcaneRes > 0) + itemValue += this->getArcaneResistanceWeight(player); + + return itemValue; + } + + inline uint8_t getStatisticWeight(Player* player, ItemTemplate* itemTemplate, uint32_t type) + { + uint8_t primaryStatisticWeight = this->getPrimaryStatisticWeight(player, type); + + if (primaryStatisticWeight != 0) + return primaryStatisticWeight; + + uint8_t physicalStatisticWeight = this->getPhysicalStatisticWeight(player, type); + + if (physicalStatisticWeight != 0) + return physicalStatisticWeight; + + uint8_t spellStatisticWeight = this->getSpellStatisticWeight(player, type); + + if (spellStatisticWeight != 0) + return spellStatisticWeight; + + return this->getDefenseStatisticWeight(player, type); + } + + inline uint8_t getPrimaryStatisticWeight(Player* player, uint32_t type) + { + switch (type) + { + case ITEM_MOD_STRENGTH: + return this->getStrengthWeight(player); + case ITEM_MOD_AGILITY: + return this->getAgilityWeight(player); + case ITEM_MOD_STAMINA: + return this->getStaminaWeight(player); + case ITEM_MOD_INTELLECT: + return this->getIntellectWeight(player); + case ITEM_MOD_SPIRIT: + return this->getSpiritWeight(player); + default: + return 0; + } + } + + inline uint8_t getPhysicalStatisticWeight(Player* player, uint32_t type) + { + switch (type) + { + case ITEM_MOD_ATTACK_POWER: + return this->getAttackPowerWeight(player); + case ITEM_MOD_HASTE_RATING: + return this->getHasteRatingWeight(player); + case ITEM_MOD_HIT_RATING: + return this->getHitRatingWeight(player); + case ITEM_MOD_CRIT_RATING: + return this->getCriticalStrikeRatingWeight(player); + case ITEM_MOD_EXPERTISE_RATING: + return this->getExperiseRatingWeight(player); + case ITEM_MOD_ARMOR_PENETRATION_RATING: + return this->getArmorPenetrationRatingWeight(player); + default: + return 0; + } + } + + inline uint8_t getSpellStatisticWeight(Player* player, uint32_t type) + { + switch (type) + { + case ITEM_MOD_SPELL_POWER: + return this->getSpellPowerWeight(player); + case ITEM_MOD_SPELL_HEALING_DONE: + return this->getHealingPowerWeight(player); + case ITEM_MOD_CRIT_SPELL_RATING: + return this->getSpellCriticalStrikeRatingWeight(player); + case ITEM_MOD_HIT_SPELL_RATING: + return this->getSpellHitRatingWeight(player); + case ITEM_MOD_HASTE_SPELL_RATING: + return this->getSpellHasteRatingWeight(player); + case ITEM_MOD_MANA_REGENERATION: + return this->getManaPer5SecondsWeight(player); + case ITEM_MOD_SPELL_PENETRATION: + return this->getSpellPenetrationRatingWeight(player); + default: + return 0; + } + } + + inline uint8_t getDefenseStatisticWeight(Player* player, uint32_t type) + { + switch (type) + { + case ITEM_MOD_DEFENSE_SKILL_RATING: + return this->getDefenseRatingWeight(player); + case ITEM_MOD_DODGE_RATING: + return this->getDodgeRatingWeight(player); + case ITEM_MOD_PARRY_RATING: + return this->getParryRatingWeight(player); + case ITEM_MOD_BLOCK_RATING: + return this->getBlockRatingWeight(player); + case ITEM_MOD_BLOCK_VALUE: + return this->getBlockValueWeight(player); + case ITEM_MOD_RESILIENCE_RATING: + return this->getResilienceRatingWeight(player); + default: + return 0; + } + } + +protected: + + // Primary + virtual inline const uint8_t getStrengthWeight(Player* player) { return 0; }; + virtual inline const uint8_t getAgilityWeight(Player* player) { return 0; }; + virtual inline const uint8_t getStaminaWeight(Player* player) { return 0; }; + virtual inline const uint8_t getIntellectWeight(Player* player) { return 0; }; + virtual inline const uint8_t getSpiritWeight(Player* player) { return 0; }; + + // Physical + virtual inline const uint8_t getAttackPowerWeight(Player* player) { return 0; }; + virtual inline const uint8_t getHasteRatingWeight(Player* player) { return 0; }; + virtual inline const uint8_t getHitRatingWeight(Player* player) { return 0; }; + virtual inline const uint8_t getCriticalStrikeRatingWeight(Player* player) { return 0; }; + virtual inline const uint8_t getExperiseRatingWeight(Player* player) { return 0; }; + virtual inline const uint8_t getArmorPenetrationRatingWeight(Player* player) { return 0; }; + + // Spell + virtual inline const uint8_t getSpellPowerWeight(Player* player) { return 0; }; + + // Unable to find these in the ItemTemplate struct + // virtual inline const uint8_t getHolySpellPowerWeight(Player* player) { return 0; }; + // virtual inline const uint8_t getFireSpellPowerWeight(Player* player) { return 0; }; + // virtual inline const uint8_t getNatureSpellPowerWeight(Player* player) { return 0; }; + // virtual inline const uint8_t getFrostSpellPowerWeight(Player* player) { return 0; }; + // virtual inline const uint8_t getShadowSpellPowerWeight(Player* player) { return 0; }; + // virtual inline const uint8_t getArcaneSpellPowerWeight(Player* player) { return 0; }; + virtual inline const uint8_t getHealingPowerWeight(Player* player) { return 0; }; + virtual inline const uint8_t getSpellHitRatingWeight(Player* player) { return 0; }; + virtual inline const uint8_t getSpellCriticalStrikeRatingWeight(Player* player) { return 0; }; + virtual inline const uint8_t getSpellHasteRatingWeight(Player* player) { return 0; }; + virtual inline const uint8_t getManaPer5SecondsWeight(Player* player) { return 0; }; + virtual inline const uint8_t getSpellPenetrationRatingWeight(Player* player) { return 0; }; + + // Defense + virtual inline const uint8_t getArmorRatingWeight(Player* player) { return 0; }; + virtual inline const uint8_t getDefenseRatingWeight(Player* player) { return 0; }; + virtual inline const uint8_t getDodgeRatingWeight(Player* player) { return 0; }; + virtual inline const uint8_t getParryRatingWeight(Player* player) { return 0; }; + virtual inline const uint8_t getBlockRatingWeight(Player* player) { return 0; }; + virtual inline const uint8_t getBlockValueWeight(Player* player) { return 0; }; + virtual inline const uint8_t getResilienceRatingWeight(Player* player) { return 0; }; + virtual inline const uint8_t getFireResistanceWeight(Player* player) { return 0; }; + virtual inline const uint8_t getNatureResistanceWeight(Player* player) { return 0; }; + virtual inline const uint8_t getFrostResistanceWeight(Player* player) { return 0; }; + virtual inline const uint8_t getShadowResistanceWeight(Player* player) { return 0; }; + virtual inline const uint8_t getArcaneResistanceWeight(Player* player) { return 0; }; +}; + +#endif diff --git a/src/service/statistic/warrior/GenericWarriorItemValueCalculationService.h b/src/service/statistic/warrior/GenericWarriorItemValueCalculationService.h new file mode 100644 index 0000000000..bd18b1f522 --- /dev/null +++ b/src/service/statistic/warrior/GenericWarriorItemValueCalculationService.h @@ -0,0 +1,75 @@ +#ifndef _PLAYERBOT_GENERIC_WARRIOR_ITEM_VALUE_CALCULATION_SERVICE_H +#define _PLAYERBOT_GENERIC_WARRIOR_ITEM_VALUE_CALCULATION_SERVICE_H + +#include + +#include "AbstractItemValueCalculationService.h" +#include "Player.h" + +class GenericWarriorItemValueCalculationService : public AbstractItemValueCalculationService +{ +protected: + + // Primary + inline const uint8_t getStrengthWeight(Player* player) override + { + return 4; + }; + + inline const uint8_t getAgilityWeight(Player* player) override + { + return 1; + }; + + inline const uint8_t getStaminaWeight(Player* player) override + { + return 2; + }; + + // Physical + inline const uint8_t getAttackPowerWeight(Player* player) override + { + return 2; + }; + + inline const uint8_t getHasteRatingWeight(Player* player) override + { + return 2; + }; + + inline const uint8_t getHitRatingWeight(Player* player) override + { + return 2; + }; + + inline const uint8_t getCriticalStrikeRatingWeight(Player* player) override + { + return 2; + }; + + inline const uint8_t getExperiseRatingWeight(Player* player) override + { + return 2; + }; + + inline const uint8_t getArmorPenetrationRatingWeight(Player* player) override + { + return 2; + }; + + // Defense + // virtual inline const uint8_t getArmorRatingWeight(Player* player) { return 0; }; + // virtual inline const uint8_t getDefenseRatingWeight(Player* player) { return 0; }; + // virtual inline const uint8_t getDodgeRatingWeight(Player* player) { return 0; }; + // virtual inline const uint8_t getParryRatingWeight(Player* player) { return 0; }; + // virtual inline const uint8_t getBlockRatingWeight(Player* player) { return 0; }; + // virtual inline const uint8_t getBlockValueWeight(Player* player) { return 0; }; + // virtual inline const uint8_t getResilienceRatingWeight(Player* player) { return 0; }; + // virtual inline const uint8_t getFireResistanceWeight(Player* player) { return 0; }; + // virtual inline const uint8_t getNatureResistanceWeight(Player* player) { return 0; }; + // virtual inline const uint8_t getFrostResistanceWeight(Player* player) { return 0; }; + // virtual inline const uint8_t getShadowResistanceWeight(Player* player) { return 0; }; + // virtual inline const uint8_t getArcaneResistanceWeight(Player* player) { return 0; }; +}; + +#endif diff --git a/src/strategy/actions/non-combat/drink/DrinkAction.h b/src/strategy/actions/non-combat/drink/DrinkAction.h new file mode 100644 index 0000000000..f0f895cea2 --- /dev/null +++ b/src/strategy/actions/non-combat/drink/DrinkAction.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#ifndef _PLAYERBOT_DRINK_ACTION_H +#define _PLAYERBOT_DRINK_ACTION_H + +#include + +#include "Event.h" +#include "UseItemAction.h" +#include "GlobalPlayerInspector.h" +#include "DrinkAuraEnum.h" + + +class PlayerbotAI; + +class DrinkAction : public UseItemAction +{ +public: + DrinkAction(PlayerbotAI* botAI) : UseItemAction(botAI, "drink") {} + + bool isPossible() override + { + if (this->bot->IsInCombat()) + { + return false; + } + + if (this->bot->IsMounted()) + { + return false; + } + + if (this->botAI->HasAnyAuraOf(GetTarget(), "dire bear form", "bear form", "cat form", "travel form", "aquatic form","flight form", "swift flight form", nullptr)) + { + return false; + } + + if (this->bot->IsCrowdControlled()) + { + return false; + } + + return this->botAI->HasCheat(BotCheatMask::food) || UseItemAction::isPossible(); + } + + bool isUseful() override + { + const GlobalPlayerInspector playerInspector(this->bot->GetGUID().GetRawValue()); + + if (playerInspector.isDrinking()) + return false; + + return playerInspector.shouldBeDrinking(50.0f); + } + + bool Execute(Event event) override + { + std::string name = this->bot->GetName().c_str(); + + this->bot->ClearUnitState(UNIT_STATE_CHASE); + this->bot->ClearUnitState(UNIT_STATE_FOLLOW); + + this->botAI->InterruptSpell(); + + if (this->bot->isMoving()) + this->bot->StopMoving(); + + this->bot->SetStandState(UNIT_STAND_STATE_SIT); + + if (this->botAI->HasCheat(BotCheatMask::food)) + { + this->bot->AddAura(DRINK_AURA_GRACCU_MINCE_MEAT_FRUITCAKE, bot); + + this->botAI->SetNextCheckDelay(1000); + + return true; + } + + this->botAI->SetNextCheckDelay(1000); + + return UseItemAction::Execute(event); + } +}; + +#endif diff --git a/src/strategy/actions/non-combat/drink/definition/enum/DrinkAuraEnum.h b/src/strategy/actions/non-combat/drink/definition/enum/DrinkAuraEnum.h new file mode 100644 index 0000000000..94b5f14f67 --- /dev/null +++ b/src/strategy/actions/non-combat/drink/definition/enum/DrinkAuraEnum.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#ifndef _PLAYERBOT_DRINK_AURA_ENUM_H +#define _PLAYERBOT_DRINK_AURA_ENUM_H + +enum DrinkAuraEnum { + DRINK_AURA_GRACCU_MINCE_MEAT_FRUITCAKE = 25990, + DRINK_AURA_FISH_FEAST = 57426, + DRINK_AURA_GREAT_FEAST = 57301, + DRINK_AURA_DRAGONFIN_FILET = 57370, + DRINK_AURA_GIGANTIC_FEAST = 58465, + DRINK_AURA_BLACKENED_DRAGONFIN = 57366, + DRINK_AURA_BLACK_JELLY = 64354, + DRINK_AURA_FIRECRACKER_SALMON = 57341, + DRINK_AURA_PURIFIED_DRAENIC_WATER = 27089, + DRINK_AURA_DALARAN_CLAM_CHOWDER = 58067, + DRINK_AURA_HOT_BUTTERED_TROUT = 42309, + DRINK_AURA_KUNGALOOSH = 52911, + DRINK_AURA_CRANBERRY_CHUTNEY = 65420, + DRINK_AURA_BAKED_MANTA_RAY = 57101, + DRINK_AURA_SLOW_ROASTED_TURKEY = 65422, + DRINK_AURA_CONJURED_MANA_STRUDEL = 43523, + DRINK_AURA_CANDIED_SWEET_POTATO = 65418, + DRINK_AURA_SPICE_BREAD_STUFFING = 65419, + DRINK_AURA_SMALL_FEAST = 58474, + DRINK_AURA_SMOKED_SAGEFISH = 25690, + DRINK_AURA_YETI_MILK = 43183, + DRINK_AURA_SNAPPER_EXTREME = 57359, + DRINK_AURA_SMOKED_ROCKFIN = 57070, + DRINK_AURA_POACHED_NETTLEFISH = 57098, + DRINK_AURA_BLACK_COFFEE = 27089, + DRINK_AURA_MOUNTAIN_WATER = 27089, + DRINK_AURA_PUMPKIN_PIE = 65421, + DRINK_AURA_FILTERED_DRAENIC_WATER = 34291, + DRINK_AURA_BITTER_PLASMA = 43182, + DRINK_AURA_WORG_TARTARE = 57359, + DRINK_AURA_CLAMLETTE_MAGNIFIQUE = 64056, + DRINK_AURA_BOUNTIFUL_FEAST = 66476, + DRINK_AURA_GRILLED_SCULPIN = 57085, + DRINK_AURA_CONJURED_MANA_PIE = 61828, + DRINK_AURA_CUTTLESTEAK = 57364, + DRINK_AURA_PUNGENT_SEAL_WHEY = 43182, + DRINK_AURA_IMPERIAL_MANTA_STEAK = 57344, + DRINK_AURA_SWEET_NECTAR = 1133, + DRINK_AURA_BOTTLED_WINTERSPRING_WATER = 1135, + DRINK_AURA_CONJURED_MOUNTAIN_SPRING_WATER = 34291, + DRINK_AURA_HONEYMINT_TEA = 43183, + DRINK_AURA_SAUTEED_GOBY = 57070, + DRINK_AURA_REFRESHING_SPRING_WATER = 430, + DRINK_AURA_ENCHANTED_WATER = 1133, + DRINK_AURA_SMOKED_SALMON = 57096, + DRINK_AURA_GRIZZLEBERRY_JUICE = 27089, + DRINK_AURA_STAR_SORROW = 43183, + DRINK_AURA_PICKLED_FANGTOOTH = 57106, + DRINK_AURA_CONJURED_FRESH_WATER = 431, + DRINK_AURA_MORNING_GLORY_DEW = 1137, + DRINK_AURA_CONJURED_GLACIER_WATER = 27089, + DRINK_AURA_SKULLFISH_SOUP = 43706, + DRINK_AURA_SWEETENED_GOAT_MILK = 27089, + DRINK_AURA_BLACKROCK_FORTIFIED_WATER = 27089, + DRINK_AURA_FIZZY_FAIRE_DRINK = 432, + DRINK_AURA_ENRICHED_TEROCONE_JUICE = 41031, + DRINK_AURA_POACHED_NORTHERN_SCULPIN = 57335, + DRINK_AURA_CRUSADER_WATERSKIN = 43183, + DRINK_AURA_ALTERAC_MANNA_BISCUIT = 23692, + DRINK_AURA_HOT_APPLE_CIDER = 45020, + DRINK_AURA_SPICY_FRIED_HERRING = 57354, + DRINK_AURA_CONJURED_WATER = 430, + DRINK_AURA_CONJURED_MINERAL_WATER = 1135, + DRINK_AURA_CONJURED_CRYSTAL_WATER = 22734, + DRINK_AURA_BUBBLING_WATER = 432, + DRINK_AURA_GRILLED_BONESCALE = 57070, + DRINK_AURA_SPICY_BLUE_NETTLEFISH = 57343, + DRINK_AURA_FRESH_APPLE_JUICE = 43182, + DRINK_AURA_ICE_COLD_MILK = 431, + DRINK_AURA_UNDERSPORE_POD = 33772, + DRINK_AURA_FRESH_SQUEEZED_LIMEADE = 43182, + DRINK_AURA_JILLIAN_GOURMET_FISH_FEAST = 57426, + DRINK_AURA_MELON_JUICE = 432, + DRINK_AURA_GILNEAS_SPARKLING_WATER = 27089, + DRINK_AURA_STAR_LAMENT = 22734, + DRINK_AURA_CONJURED_SPRING_WATER = 1133, + DRINK_AURA_HYJAL_NECTAR = 22734, + DRINK_AURA_BLACKROCK_SPRING_WATER = 1137, + DRINK_AURA_BLACKROCK_MINERAL_WATER = 34291, + DRINK_AURA_ETHERMEAD = 27089, + DRINK_AURA_GOLDTHORN_TEA = 1133, + DRINK_AURA_ENRICHED_MANNA_BISCUIT = 18071, + DRINK_AURA_GREEN_TEA_LEAF = 833, + DRINK_AURA_CONJURED_PURIFIED_WATER = 432, + DRINK_AURA_CONJURED_SPARKLING_WATER = 1137, + DRINK_AURA_STAR_TEAR = 27089, + DRINK_AURA_NAARU_RATION = 44166, + DRINK_AURA_MOONBERRY_JUICE = 1135, + DRINK_AURA_SILVERWINE = 34291, + DRINK_AURA_FULL_MOONSHINE = 438, + DRINK_AURA_DOS_OGRIS = 27089, + DRINK_AURA_ESSENCE_MANGO = 24384, + DRINK_AURA_SENGGIN_ROOT = 2639, + DRINK_AURA_BLENDED_BEAN_BREW = 431, + DRINK_AURA_SAGEFISH_DELIGHT = 25691, + DRINK_AURA_SPARKLING_SOUTHSHORE_CIDER = 27089, + DRINK_AURA_CONJURED_MANA_BISCUIT = 44166, + DRINK_AURA_FROSTBERRY_JUICE = 27089 +}; + +#endif diff --git a/src/strategy/actions/player/inventory/ManageInventoryAction.cpp b/src/strategy/actions/player/inventory/ManageInventoryAction.cpp new file mode 100644 index 0000000000..5099e10280 --- /dev/null +++ b/src/strategy/actions/player/inventory/ManageInventoryAction.cpp @@ -0,0 +1,761 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * /modules/playerbots/src/strategy/actions/player/inventoryand/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#include "ManageInventoryAction.h" + +#include +#include +#include +#include + +#include "CreateNextAction.h" +#include "EquipAction.h" +#include "Log.h" +#include "Player.h" +#include "ChatHelper.h" +#include "ItemTemplate.h" + +#include "ItemActionEnum.h" +#include "GlobalPlayerInspector.h" +#include "GlobalItemInspector.h" +#include "PlayerbotAI.h" +#include "Event.h" +#include "RandomPlayerbotMgr.h" +#include "ItemActionStruct.h" +#include "PlayerInventoryFacadeResultEnum.h" +#include "PlayerInventoryFacade.h" +#include "GlobalConsumableInspector.h" +#include "ArmorItemInspector.h" +#include "ConsumableConsumableInspector.h" +#include "ConsumableElixirInspector.h" +#include "ConsumablePotionInspector.h" +#include "ContainerInspector.h" +#include "GemInspector.h" +#include "GenericItemInspector.h" +#include "GlyphInspector.h" +#include "ItemTemplate.h" +#include "KeyInspector.h" +#include "MiscellaneousItemInspector.h" +#include "MoneyInspector.h" +#include "PermanentItemInspector.h" +#include "ProjectItemInspector.h" +#include "QuestItemInspector.h" +#include "QuiverItemInspector.h" +#include "ReagentItemInspector.h" +#include "RecipeItemInspector.h" +#include "TradeGoodItemInspector.h" +#include "WeaponItemInspector.h" + +using InspectorFactory = std::function; +using SubclassMap = std::unordered_map; +using ClassMap = std::unordered_map; + +static const std::vector> arrowsIdsPerLevel = { + { 75, 41586 }, // Terrorshaft Arrow + { 65, 28056 }, // Blackflight Arrow + { 61, 28053 }, // Wicked Arrow => Requires level 55 but is a TBC item so set to level 61 + { 40, 11285 }, // Jagged Arrow + { 25, 3030 }, // Razor Arrow + { 10, 2515 }, // Sharp Arrow + { 0, 2512 } // Rough Arrow +}; + +static const std::vector> bulletsIdsPerLevel = { + { 75, 41584 }, // Frostbite Bullets + { 65, 28061 }, // Ironbite Shell + { 61, 28060 }, // Impact Shot => Requires level 55 but is a TBC item so set to level 61 + { 40, 11284 }, // Accurate Slugs + { 25, 3033 }, // Solid Shot + { 10, 2519 }, // Heavy Shot + { 0, 2516 } // Light Shot +}; + +static const ClassMap inspectorFactories = { + { + ITEM_CLASS_ARMOR, + { + { + ManageInventoryAction::ANY_SUBCLASS, + [](const uint32_t botGUID, const uint64_t itemGUID) + { + LOG_DEBUG("playerbots.action.manage_inventory", "executing ARMOR inspector"); + + return ArmorItemInspector(botGUID, itemGUID).determineItemAction(); + } + } + } + }, + { + ITEM_CLASS_CONSUMABLE, + { + { + { + ITEM_SUBCLASS_CONSUMABLE, + [](const uint32_t botGUID, const uint64_t itemGUID) + { + LOG_DEBUG("playerbots.action.manage_inventory", "executing CONSUMABLE inspector"); + + return ConsumableConsumableInspector(botGUID, itemGUID).determineItemAction(); + } + }, + { + ITEM_SUBCLASS_ELIXIR, + [](const uint32_t botGUID, const uint64_t itemGUID) + { + LOG_DEBUG("playerbots.action.manage_inventory", "executing ELIXIR inspector"); + + return ConsumableElixirInspector(botGUID, itemGUID).determineItemAction(); + } + }, + { + ITEM_SUBCLASS_POTION, + [](const uint32_t botGUID, const uint64_t itemGUID) + { + LOG_DEBUG("playerbots.action.manage_inventory", "executing POTION inspector"); + + return ConsumablePotionInspector(botGUID, itemGUID).determineItemAction(); + } + }, + { + ManageInventoryAction::ANY_SUBCLASS, + [](const uint32_t botGUID, const uint64_t itemGUID) + { + LOG_DEBUG("playerbots.action.manage_inventory", "executing generic consumable inspector"); + + return GlobalConsumableInspector(botGUID, itemGUID).determineItemAction(); + } + } + } + } + }, + { + ITEM_CLASS_CONTAINER, + { + { + ManageInventoryAction::ANY_SUBCLASS, + [](const uint32_t botGUID, const uint64_t itemGUID) + { + LOG_DEBUG("playerbots.action.manage_inventory", "executing CONTAINER inspector"); + + return ContainerInspector(botGUID, itemGUID).determineItemAction(); + } + } + } + }, + { + ITEM_CLASS_GEM, + { + { + ManageInventoryAction::ANY_SUBCLASS, + [](const uint32_t botGUID, const uint64_t itemGUID) + { + LOG_DEBUG("playerbots.action.manage_inventory", "executing GEM inspector"); + + return GemInspector(botGUID, itemGUID).determineItemAction(); + } + } + } + }, + { + ITEM_CLASS_GENERIC, + { + { + ManageInventoryAction::ANY_SUBCLASS, + [](const uint32_t botGUID, const uint64_t itemGUID) + { + LOG_DEBUG("playerbots.action.manage_inventory", "executing GENERIC inspector"); + + return GenericItemInspector(botGUID, itemGUID).determineItemAction(); + } + } + } + }, + { + ITEM_CLASS_GLYPH, + { + { + ManageInventoryAction::ANY_SUBCLASS, + [](const uint32_t botGUID, const uint64_t itemGUID) + { + LOG_DEBUG("playerbots.action.manage_inventory", "executing GLYPH inspector"); + + return GlyphInspector(botGUID, itemGUID).determineItemAction(); + } + } + } + }, + { + ITEM_CLASS_KEY, + { + { + ManageInventoryAction::ANY_SUBCLASS, + [](const uint32_t botGUID, const uint64_t itemGUID) + { + LOG_DEBUG("playerbots.action.manage_inventory", "executing KEY inspector"); + + return KeyInspector(botGUID, itemGUID).determineItemAction(); + } + } + } + }, + { + ITEM_CLASS_MISC, + { + { + ManageInventoryAction::ANY_SUBCLASS, + [](const uint32_t botGUID, const uint64_t itemGUID) + { + LOG_DEBUG("playerbots.action.manage_inventory", "executing MISC inspector"); + + return MiscellaneousItemInspector(botGUID, itemGUID).determineItemAction(); + } + } + } + }, + { + ITEM_CLASS_MONEY, + { + { + ManageInventoryAction::ANY_SUBCLASS, + [](const uint32_t botGUID, const uint64_t itemGUID) + { + LOG_DEBUG("playerbots.action.manage_inventory", "executing MONEY inspector"); + + return MoneyInspector(botGUID, itemGUID).determineItemAction(); + } + } + } + }, + { + ITEM_CLASS_PERMANENT, + { + { + ManageInventoryAction::ANY_SUBCLASS, + [](const uint32_t botGUID, const uint64_t itemGUID) + { + LOG_DEBUG("playerbots.action.manage_inventory", "executing PERMANENT inspector"); + + return PermanentItemInspector(botGUID, itemGUID).determineItemAction(); + } + } + } + }, + { + ITEM_CLASS_PROJECTILE, + { + { + ManageInventoryAction::ANY_SUBCLASS, + [](const uint32_t botGUID, const uint64_t itemGUID) + { + LOG_DEBUG("playerbots.action.manage_inventory", "executing PROJECTILE inspector"); + + return ProjectItemInspector(botGUID, itemGUID).determineItemAction(); + } + } + } + }, + { + ITEM_CLASS_QUEST, + { + { + ManageInventoryAction::ANY_SUBCLASS, + [](const uint32_t botGUID, const uint64_t itemGUID) + { + LOG_DEBUG("playerbots.action.manage_inventory", "executing QUEST inspector"); + + return QuestItemInspector(botGUID, itemGUID).determineItemAction(); + } + } + } + }, + { + ITEM_CLASS_QUIVER, + { + { + ManageInventoryAction::ANY_SUBCLASS, + [](const uint32_t botGUID, const uint64_t itemGUID) + { + LOG_DEBUG("playerbots.action.manage_inventory", "executing QUIVER inspector"); + + return QuiverItemInspector(botGUID, itemGUID).determineItemAction(); + } + } + } + }, + { + ITEM_CLASS_REAGENT, + { + { + ManageInventoryAction::ANY_SUBCLASS, + [](const uint32_t botGUID, const uint64_t itemGUID) + { + LOG_DEBUG("playerbots.action.manage_inventory", "executing REAGENT inspector"); + + return ReagentItemInspector(botGUID, itemGUID).determineItemAction(); + } + } + } + }, + { + ITEM_CLASS_RECIPE, + { + { + ManageInventoryAction::ANY_SUBCLASS, + [](const uint32_t botGUID, const uint64_t itemGUID) + { + LOG_DEBUG("playerbots.action.manage_inventory", "executing RECIPE inspector"); + + return RecipeItemInspector(botGUID, itemGUID).determineItemAction(); + } + } + } + }, + { + ITEM_CLASS_TRADE_GOODS, + { + { + ManageInventoryAction::ANY_SUBCLASS, + [](const uint32_t botGUID, const uint64_t itemGUID) + { + LOG_DEBUG("playerbots.action.manage_inventory", "executing TRADE GOODS inspector"); + + return TradeGoodItemInspector(botGUID, itemGUID).determineItemAction(); + } + } + } + }, + { + ITEM_CLASS_WEAPON, + { + { + ManageInventoryAction::ANY_SUBCLASS, + [](const uint32_t botGUID, const uint64_t itemGUID) + { + LOG_DEBUG("playerbots.action.manage_inventory", "executing WEAPON inspector"); + + return WeaponItemInspector(botGUID, itemGUID).determineItemAction(); + } + } + } + }, +}; + +bool ManageInventoryAction::Execute(Event) +{ + LOG_DEBUG("playerbots.action.manage_inventory", "starting inventory management action"); + + this->itemActions.clear(); + + if (this->bot == nullptr) + { + LOG_DEBUG("playerbots.action.manage_inventory", "ManageInventoryAction::Execute bot is nullptr"); + + return false; + } + + const std::string botName = this->bot->GetName(); + + LOG_DEBUG("playerbots.action.manage_inventory", "managing inventory for {}", botName); + + if (!RandomPlayerbotMgr::instance().IsRandomBot(bot)) + return true; + + this->iterateBags(); + + LOG_DEBUG("playerbots.action.manage_inventory", "done processing bags for {}", botName); + + PlayerInventoryFacade playerInventoryFacade(this->bot->GetGUID().GetRawValue()); + + bool shouldEquipUpgrade = false; + + for (const auto& [itemGUID, action] : this->itemActions) + { + std::string actionName = "UNKNOWN_ACTION"; + + switch (action.action) + { + case ItemActionEnum::NONE: + actionName = "ITEM_ACTION_NONE"; + break; + case ItemActionEnum::EQUIP: + actionName = "ITEM_ACTION_EQUIP"; + break; + case ItemActionEnum::SELL: + actionName = "ITEM_ACTION_SELL"; + break; + case ItemActionEnum::DESTROY: + actionName = "ITEM_ACTION_DESTROY"; + break; + } + + LOG_DEBUG("playerbots.action.manage_inventory", "Item {} action: {}, bagSlot: {}, containerSlot: {}, equipmentSlot: {}", std::to_string(itemGUID), actionName, std::to_string(action.bagSlot), std::to_string(action.containerSlot), std::to_string(action.equipmentSlot)); + + switch (action.action) + { + case ItemActionEnum::EQUIP: + { + // LOG_DEBUG("playerbots.action.manage_inventory", "equipping item through facade"); + + // const PlayerInventoryFacadeResultEnum result = playerInventoryFacade.equipItem(itemGUID, action.equipmentSlot); + + // LOG_DEBUG("playerbots.action.manage_inventory", "Equipped item {}, result: {}", std::to_string(itemGUID), result); + + Item* item = this->bot->GetItemByPos(action.bagSlot, action.containerSlot); + + if (item == nullptr) + continue; + + const ItemTemplate* proto = item->GetTemplate(); + + LOG_DEBUG("playerbots.action.manage_inventory", "Item {} was supposed to be equipped.", proto->ItemId); + + shouldEquipUpgrade = true; + + break; + } + case ItemActionEnum::SELL: + { + LOG_DEBUG("playerbots.action.manage_inventory", "selling item through facade"); + const PlayerInventoryFacadeResultEnum result = playerInventoryFacade.sellItem(itemGUID); + + LOG_DEBUG("playerbots.action.manage_inventory", "Sold item {}, result: {}", std::to_string(itemGUID), result); + + break; + } + case ItemActionEnum::DESTROY: + { + LOG_DEBUG("playerbots.action.manage_inventory", "destroying item through facade"); + const PlayerInventoryFacadeResultEnum result = playerInventoryFacade.destroyItem(itemGUID); + + LOG_DEBUG("playerbots.action.manage_inventory", "Destroyed item {}, result: {}", std::to_string(itemGUID), result); + + break; + } + case ItemActionEnum::NONE: + break; + } + } + + if (shouldEquipUpgrade && this->botAI != nullptr) + { + LOG_DEBUG("playerbots.action.manage_inventory", "Equipping upgrades"); + + this->botAI->DoSpecificAction(CreateNextAction(0.0f).factory); + + LOG_DEBUG("playerbots.action.manage_inventory", "Done equipping upgrades"); + } + + this->refillConsumables(); + + LOG_DEBUG("playerbots.action.manage_inventory", "Done processing inventory"); + + if (this->botAI != nullptr) + { + const Player* const master = botAI->GetMaster(); + + LOG_DEBUG("playerbots.action.manage_inventory", "fetched master for {}", botName); + + if (master != nullptr) + { + const std::string masterName = master->GetName(); + + LOG_DEBUG("playerbots.action.manage_inventory", "telling master ({}) of bot {}", masterName, botName); + + std::ostringstream out; + + out << "I am done sorting my inventory."; + + if (this->botAI != nullptr) + { + this->botAI->TellMaster(out); + } + + LOG_DEBUG("playerbots.action.manage_inventory", "told master ({}) of bot {}", masterName, botName); + } + } + + + return true; + // if (this->bot != nullptr) + // { + // this->bot->SaveToDB(false, false); + + // return true; + // } + + // LOG_DEBUG("playerbots.action.manage_inventory", "ManageInventoryAction::Execute can't save, bot is nullptr"); + + // return true; +} + +void ManageInventoryAction::iterateBags() +{ + LOG_DEBUG("playerbots.action.manage_inventory", "Processing main bag"); + + if (this->bot == nullptr) + { + LOG_DEBUG("playerbots.action.manage_inventory", "ManageInventoryAction::iterateBags bot became nullptr"); + + return; + } + + const GlobalPlayerInspector playerInspector(this->bot->GetGUID().GetRawValue()); + + for (uint8_t slot = INVENTORY_SLOT_ITEM_START; slot < INVENTORY_SLOT_ITEM_END; slot++) + { + LOG_DEBUG("playerbots.action.manage_inventory", "Processing item in main bag slot {}", std::to_string(slot)); + + Item* item = playerInspector.getItemByPosition(INVENTORY_SLOT_BAG_0, slot); + + if (item == nullptr) + { + LOG_DEBUG("playerbots.action.manage_inventory", "Item in main bag slot {} did not exist", std::to_string(slot)); + + continue; + } + + const uint64_t itemLowGUID = item->GetGUID().GetRawValue(); + + this->processItem(itemLowGUID); + } + + for (uint8_t slot = INVENTORY_SLOT_BAG_START; slot < INVENTORY_SLOT_BAG_END; ++slot) + { + LOG_DEBUG("playerbots.action.manage_inventory", "Processing bag in slot {}", std::to_string(slot)); + + if (this->bot == nullptr) + { + LOG_DEBUG("playerbots.action.manage_inventory", "ManageInventoryAction::iterateBags bot became nullptr"); + + return; + } + + // const Item* const possibleBag = playerInspector.getItemByPosition(INVENTORY_SLOT_BAG_0, slot); + + // if (possibleBag == nullptr) + // continue; + + // const uint64_t bagLowGUID = possibleBag->GetGUID().GetRawValue(); + + this->iterateBag(slot); + } + + if (this->bot == nullptr) + { + LOG_DEBUG("playerbots.action.manage_inventory", "ManageInventoryAction::iterateBags bot became nullptr"); + + return; + } + + LOG_DEBUG("playerbots.action.manage_inventory", "done processing bags for {}", this->bot->GetName()); +} + +void ManageInventoryAction::iterateBag(const uint32_t bagSlot) +{ + const GlobalPlayerInspector playerInspector(this->bot->GetGUID().GetRawValue()); + // const Item* const possibleBag = playerInspector.getItemByGUID(bagGUID); + const Item* const possibleBag = playerInspector.getItemByPosition(INVENTORY_SLOT_BAG_0, bagSlot); + + if (possibleBag == nullptr) + return; + + const Bag* bag = possibleBag->ToBag(); + + if (bag == nullptr) + { + LOG_DEBUG("playerbots.action.manage_inventory", "Bag did not exist"); + + return; + } + + const uint8_t size = bag->GetBagSize(); + + for (uint8_t slot = 0; slot < size; ++slot) + { + LOG_DEBUG("playerbots.action.manage_inventory", "Processing item {} in bag", std::to_string(slot)); + + if (bag == nullptr) + { + LOG_DEBUG("playerbots.action.manage_inventory", "ManageInventoryAction::iterateBag bag became nullptr"); + + return; + } + + // Item* item = bag->GetItemByPos(slot); + Item* item = playerInspector.getItemByPosition(bagSlot, slot); + + if (item == nullptr) + { + LOG_DEBUG("playerbots.action.manage_inventory", "Item {} in bag did not exist", std::to_string(slot)); + + continue; + } + + const uint64_t itemGUID = item->GetGUID().GetRawValue(); + + this->processItem(itemGUID); + } + + LOG_DEBUG("playerbots.action.manage_inventory", "done processing bag {}", std::to_string(bag->GetSlot())); +} + +void ManageInventoryAction::processItem(const uint64_t itemGUID) +{ + if (this->bot == nullptr) + { + LOG_DEBUG("playerbots.action.manage_inventory", "ManageInventoryAction::processItem bot became nullptr"); + + return; + } + + const uint32_t botGUID = this->bot->GetGUID().GetRawValue(); + const GlobalPlayerInspector playerInspector(botGUID); + const GlobalItemInspector itemInspector(botGUID, itemGUID); + const ItemUpdateState itemState = itemInspector.getItemUpdateState(); + const uint32_t itemTemplateLowGUID = itemInspector.getCurrentItemTemplateLowGUID(); + + if (itemState == ITEM_REMOVED) + { + LOG_DEBUG("playerbots.action.manage_inventory", "Item {} (template {}) was already flagged for removal.", itemGUID, itemTemplateLowGUID); + + return; + } + + if (!itemInspector.itemIsInWorld()) + { + LOG_DEBUG("playerbots.action.manage_inventory", "Item {} (template {}) is not in world.", itemGUID, itemTemplateLowGUID); + + return; + } + + const uint8_t itemSlot = itemInspector.getItemSlot(); + + if (itemSlot == NULL_SLOT) + { + LOG_DEBUG("playerbots.action.manage_inventory", "Item {} (template {}) is null slot.", itemGUID, itemTemplateLowGUID); + + return; + } + + if (itemInspector.itemIsInUnsafeContainer()) + { + LOG_DEBUG("playerbots.action.manage_inventory", "Item {} (template {}) is in unsafe container", itemGUID, itemTemplateLowGUID); + + return; + } + + const uint32_t itemClass = itemInspector.getCurrentItemClass(); + const uint32_t itemSubClass = itemInspector.getCurrentItemSubclass(); + + LOG_DEBUG("playerbots.action.manage_inventory", "processing item {}", std::to_string(itemTemplateLowGUID)); + + ClassMap::const_iterator classIterator = inspectorFactories.find(itemClass); + + if (classIterator == inspectorFactories.end()) + { + LOG_DEBUG("playerbots.action.manage_inventory", "Unable to locate service for item class {} item service", std::to_string(itemClass)); + + return; + } + + const SubclassMap& subclassMap = classIterator->second; + + SubclassMap::const_iterator subclassIterator = subclassMap.find(itemSubClass); + + if (subclassIterator == subclassMap.end()) + { + subclassIterator = subclassMap.find(ManageInventoryAction::ANY_SUBCLASS); + } + + if (subclassIterator == subclassMap.end()) + { + LOG_DEBUG("playerbots.action.manage_inventory", "Unable to locate service for item class {} subclass {} item service", std::to_string(itemClass), std::to_string(itemSubClass)); + + return; + } + + const InspectorFactory& factoryFunction = subclassIterator->second; + + ItemActionStruct action = factoryFunction(botGUID, itemGUID); + this->itemActions.insert({itemGUID, action}); + + LOG_DEBUG("playerbots.action.manage_inventory", "Done visiting item {}", std::to_string(itemTemplateLowGUID)); +} + +void ManageInventoryAction::refillConsumables() +{ + if (this->bot->IsClass(CLASS_HUNTER)) + { + Item* rangedWeapon = this->bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED); + + if (rangedWeapon == nullptr) + return; + + const ItemTemplate* weaponTemplate = rangedWeapon->GetTemplate(); + + if (weaponTemplate == nullptr) + return; + + if (weaponTemplate->SubClass == ITEM_SUBCLASS_WEAPON_THROWN) + return; + + const uint8_t playerLevel = this->bot->GetLevel(); + + if (weaponTemplate->SubClass == ITEM_SUBCLASS_WEAPON_GUN) + { + for (std::pair bulletPair : bulletsIdsPerLevel) + { + if (playerLevel > bulletPair.first) + { + Item* item = Item::CreateItem(bulletPair.second, 1); + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + const bool hasEnoughAmmunition = this->bot->HasItemCount(bulletPair.second, itemTemplate->GetMaxStackSize()); + + if (!hasEnoughAmmunition) + { + this->bot->AddItem(bulletPair.second, itemTemplate->GetMaxStackSize()); + } + + delete item; + + return; + } + } + } + + for (std::pair arrowPair : arrowsIdsPerLevel) + { + if (playerLevel > arrowPair.first) + { + Item* item = Item::CreateItem(arrowPair.second, 1); + + const ItemTemplate* itemTemplate = item->GetTemplate(); + + const bool hasEnoughAmmunition = this->bot->HasItemCount(arrowPair.second, itemTemplate->GetMaxStackSize()); + + if (!hasEnoughAmmunition) + { + this->bot->AddItem(arrowPair.second, itemTemplate->GetMaxStackSize()); + } + + delete item; + + return; + } + } + } +} + +template +void ManageInventoryAction::determineItemAction(const uint32_t botLowGUID, const uint64_t itemLowGUID) +{ + LOG_DEBUG("playerbots.action.manage_inventory", "Determining action for item {}", std::to_string(itemLowGUID)); + + InspectorT inspector(botLowGUID, itemLowGUID); + const ItemActionStruct action = inspector.determineItemAction(); + this->itemActions.insert({itemLowGUID, action}); +} diff --git a/src/strategy/actions/player/inventory/ManageInventoryAction.h b/src/strategy/actions/player/inventory/ManageInventoryAction.h new file mode 100644 index 0000000000..f9106d6340 --- /dev/null +++ b/src/strategy/actions/player/inventory/ManageInventoryAction.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it + * and/or modify it under version 3 of the License, or (at your option), any later version. + */ + +#pragma once + +#include +#include + +#include "Action.h" +#include "Log.h" +#include "PlayerbotAI.h" +#include "ItemActionStruct.h" + +class ManageInventoryAction : public Action +{ +public: + ManageInventoryAction(PlayerbotAI* botAI) : Action(botAI, "manage_inventory") {} + + static constexpr uint32_t ANY_SUBCLASS = std::numeric_limits::max(); + + bool isPossible() override + { + LOG_DEBUG("playerbots.action.manage_inventory", "Starting manage inventory isPossible evaluation"); + + const Player* const bot = botAI->GetBot(); + + if (bot == nullptr) + { + LOG_DEBUG("playerbots.action.manage_inventory", "Manage inventory impossible bot is nullptr"); + + return false; + } + + const std::string botName = bot->GetName(); + + if (!bot->IsInWorld()) + { + LOG_DEBUG("playerbots.action.manage_inventory", "Manage inventory impossible bot '{}' is non in world", botName); + + return false; + } + + const WorldSession* const session = bot->GetSession(); + + if (session == nullptr) + { + LOG_DEBUG("playerbots.action.manage_inventory", "Manage inventory impossible bot '{}' session is nullptr", botName); + + return false; + } + + if (session->isLogingOut()) + { + LOG_DEBUG("playerbots.action.manage_inventory", "Manage inventory impossible bot '{}' is logging out", botName); + + return false; + } + + return true; + } + + bool Execute(Event event) override; + +private: + + std::unordered_map itemActions = {}; + + void iterateBags(); + void iterateBag(const uint32_t bagSlot); + void processItem(const uint64_t itemGUID); + template + void determineItemAction(const uint32_t botLowGUID, const uint64_t itemLowGUID); + void refillConsumables(); +}; diff --git a/src/utility/UInt32VectorToString.h b/src/utility/UInt32VectorToString.h new file mode 100644 index 0000000000..e517a8d1cf --- /dev/null +++ b/src/utility/UInt32VectorToString.h @@ -0,0 +1,23 @@ +#ifndef UINT32_VECTOR_TO_STRING_H +#define UINT32_VECTOR_TO_STRING_H + +#include +#include +#include +#include + +inline std::string UInt32VectorToString(const std::vector& vec) +{ + std::ostringstream oss; + + for (size_t i = 0; i < vec.size(); ++i) + { + if (i > 0) + oss << ','; + oss << vec[i]; + } + + return oss.str(); +} + +#endif