From af674e9361cce8e8e8f5446142dd8a38e649a115 Mon Sep 17 00:00:00 2001 From: Fuzz Date: Tue, 6 Aug 2024 19:26:54 +1000 Subject: [PATCH 1/7] [Battlegrounds] many IOC fixes: fixed bots not being able to revive in their own base GY, fixed bots not able to use flags in IOC at all (couldnt cap anything), added path so bots could reach boss and several other paths too, fixed horde bots not being able to tell that alliance gate is down (stayed outside forever), fixed bots not able to get in vehicles, fixed bots not able to drive vehicles, fixed bots in vehicles becoming unresponsive after a fight (in-combat status seems to never clear in vehicle which may be AC bug), reduced bot 'agro distance' when in vehicle so they can get to their objective, redid selectObject strat completely, prevented bots using cannons (bots are useless in them) and catapults (they dont know how to use them), prevented bots using Glaive Thrower's Blade Salvo as it's bugged (and stops them using any attacks after they use it), many other fixes --- src/strategy/actions/BattleGroundTactics.cpp | 904 +++++++++--------- src/strategy/actions/MovementActions.cpp | 22 + src/strategy/actions/ReleaseSpiritAction.cpp | 6 +- src/strategy/actions/VehicleActions.cpp | 31 +- src/strategy/generic/BattlegroundStrategy.cpp | 5 +- src/strategy/values/EnemyPlayerValue.cpp | 22 +- src/strategy/values/NearestNpcsValue.cpp | 2 +- 7 files changed, 518 insertions(+), 474 deletions(-) diff --git a/src/strategy/actions/BattleGroundTactics.cpp b/src/strategy/actions/BattleGroundTactics.cpp index 03b838d5..7b28a19d 100644 --- a/src/strategy/actions/BattleGroundTactics.cpp +++ b/src/strategy/actions/BattleGroundTactics.cpp @@ -66,18 +66,22 @@ Position const EY_WAITING_POS_ALLIANCE = {2526.020f, 1596.787f, 1270.127f, 3.14f Position const EY_FLAG_RETURN_POS_RETREAT_HORDE = {1885.529f, 1532.157f, 1200.635f, 0.0f}; Position const EY_FLAG_RETURN_POS_RETREAT_ALLIANCE = {2452.253f, 1602.356f, 1203.617f, 0.0f}; -Position const IC_WAITING_POS_HORDE = {1166.322f, -762.402f, 48.628f, 3.14f}; -Position const IC_WAITING_POS_ALLIANCE = {387.893f, -833.384f, 48.714f, 6.28f}; +Position const IC_WAITING_POS_HORDE = {1166.322f, -762.402f, 48.628f}; +Position const IC_WEST_WAITING_POS_HORDE = {1217.666f, -685.449f, 48.915f}; +Position const IC_EAST_WAITING_POS_HORDE = {1219.068f, -838.791f, 48.916f}; -Position const IC_WEST_WAITING_POS_HORDE = {1217.666f, -685.449f, 48.915f, 1.54f}; -Position const IC_EAST_WAITING_POS_HORDE = {1219.068f, -838.791f, 48.916f, 4.72f}; -Position const IC_SIDE_WAITING_POS_ALLIANCE = {351.517f, -882.477f, 48.916f, 4.68f}; +Position const IC_WAITING_POS_ALLIANCE = {387.893f, -833.384f, 48.714f}; +Position const IC_WEST_WAITING_POS_ALLIANCE = {352.129f, -788.029f, 48.916f}; +Position const IC_EAST_WAITING_POS_ALLIANCE = {351.517f, -882.477f, 48.916f}; Position const IC_CANNON_POS_HORDE1 = {1140.938f, -838.685f, 88.124f, 2.30f}; Position const IC_CANNON_POS_HORDE2 = {1139.695f, -686.574f, 88.173f, 3.95f}; Position const IC_CANNON_POS_ALLIANCE1 = {424.860f, -855.795f, 87.96f, 0.44f}; Position const IC_CANNON_POS_ALLIANCE2 = {425.525f, -779.538f, 87.717f, 5.88f}; +Position const IC_GATE_ATTACK_POS_HORDE = {506.782f, -828.594f, 24.313f, 0.0f}; +Position const IC_GATE_ATTACK_POS_ALLIANCE = {1091.273f, -763.619f, 42.352f, 0.0f}; + enum BattleBotWsgWaitSpot { BB_WSG_WAIT_SPOT_SPAWN, @@ -100,9 +104,41 @@ std::vector const vFlagsWS = {BG_OBJECT_A_FLAG_WS_ENTRY, BG_OBJECT_H_FLA std::vector const vFlagsEY = {BG_OBJECT_FLAG2_EY_ENTRY, BG_OBJECT_FLAG3_EY_ENTRY}; -std::vector const vFlagsIC = {BG_IC_GO_HORDE_BANNER, BG_IC_GO_ALLIANCE_BANNER, BG_IC_GO_WORKSHOP_BANNER, - BG_IC_GO_DOCKS_BANNER, BG_IC_GO_HANGAR_BANNER, BG_IC_GO_QUARRY_BANNER, - BG_IC_GO_REFINERY_BANNER}; +std::vector const vFlagsIC = {GO_HORDE_BANNER, + GO_ALLIANCE_BANNER, + GO_WORKSHOP_BANNER, + GO_DOCKS_BANNER, + GO_HANGAR_BANNER, + GO_QUARRY_BANNER, + GO_REFINERY_BANNER, + GO_ALLIANCE_BANNER_DOCK, + GO_ALLIANCE_BANNER_DOCK_CONT, + GO_HORDE_BANNER_DOCK, + GO_HORDE_BANNER_DOCK_CONT, + GO_HORDE_BANNER_HANGAR, + GO_HORDE_BANNER_HANGAR_CONT, + GO_ALLIANCE_BANNER_HANGAR, + GO_ALLIANCE_BANNER_HANGAR_CONT, + GO_ALLIANCE_BANNER_QUARRY, + GO_ALLIANCE_BANNER_QUARRY_CONT, + GO_HORDE_BANNER_QUARRY, + GO_HORDE_BANNER_QUARRY_CONT, + GO_ALLIANCE_BANNER_REFINERY, + GO_ALLIANCE_BANNER_REFINERY_CONT, + GO_HORDE_BANNER_REFINERY, + GO_HORDE_BANNER_REFINERY_CONT, + GO_ALLIANCE_BANNER_WORKSHOP, + GO_ALLIANCE_BANNER_WORKSHOP_CONT, + GO_HORDE_BANNER_WORKSHOP, + GO_HORDE_BANNER_WORKSHOP_CONT, + GO_ALLIANCE_BANNER_GRAVEYARD_A, + GO_ALLIANCE_BANNER_GRAVEYARD_A_CONT, + GO_HORDE_BANNER_GRAVEYARD_A, + GO_HORDE_BANNER_GRAVEYARD_A_CONT, + GO_ALLIANCE_BANNER_GRAVEYARD_H, + GO_ALLIANCE_BANNER_GRAVEYARD_H_CONT, + GO_HORDE_BANNER_GRAVEYARD_H, + GO_HORDE_BANNER_GRAVEYARD_H_CONT}; // BG Waypoints (vmangos) @@ -1024,8 +1060,9 @@ BattleBotPath vPath_AV_Frostdagger_Pass_Lower_to_Iceblood_Garrison = { // path that allows alliance to bypass the mid on way to horde captain BattleBotPath vPath_AV_Icewing_Bunker_Crossroad_to_Frostdagger_Pass_Lower = { - // these are to cause bot to pick this when resurrecting at stonehearth (not really needed anymore as they get - // captain down in first wave since uneeded dismounting was fixed) + // the first 3 are to cause bot to pick this when resurrecting at stonehearth - seems to be key thing to + // stopping alliance getting bogged down in mid fighting, away from their objective (enemy captain) but close to + // horde objectives (advantaging horde significantly) {68.793f, -396.742f, 45.299f, nullptr}, {99.042f, -389.310f, 45.101f, nullptr}, {123.787f, -373.551f, 42.893f, nullptr}, {119.693f, -351.311f, 42.728f, nullptr}, {107.710f, -321.162f, 37.168f, nullptr}, {84.953f, -273.434f, 23.944f, nullptr}, @@ -1328,6 +1365,57 @@ BattleBotPath vPath_IC_Workshop_to_Workshop_Keep = {{773.792f, -825.637f, 8.127f {772.706f, -841.881f, 11.622f, nullptr}, {773.057f, -859.936f, 12.418f, nullptr}}; +BattleBotPath vPath_IC_Alliance_Base = { + {402.020f, -832.289f, 48.627f, nullptr}, {384.784f, -832.551f, 48.830f, nullptr}, + {369.413f, -832.480f, 48.916f, nullptr}, {346.677f, -832.355f, 48.916f, nullptr}, + {326.296f, -832.189f, 48.916f, nullptr}, {311.174f, -832.204f, 48.916f, nullptr}, +}; + +BattleBotPath vPath_IC_Horde_Base = { + {1158.652f, -762.680f, 48.628f, nullptr}, {1171.598f, -762.628f, 48.649f, nullptr}, + {1189.102f, -763.484f, 48.915f, nullptr}, {1208.599f, -764.332f, 48.915f, nullptr}, + {1227.592f, -764.782f, 48.915f, nullptr}, {1253.676f, -765.441f, 48.915f, nullptr}, +}; + +BattleBotPath vPath_IC_Workshop_to_North_West = { + {786.051f, -801.798f, 5.968f, nullptr}, {801.767f, -800.845f, 6.201f, nullptr}, + {830.190f, -800.059f, 5.163f, nullptr}, {858.827f, -797.691f, 5.602f, nullptr}, + {881.579f, -795.190f, 6.441f, nullptr}, {905.796f, -792.252f, 8.008f, nullptr}, + {929.874f, -788.912f, 10.674f, nullptr}, {960.001f, -784.233f, 15.521f, nullptr}, + {991.890f, -780.605f, 22.402f, nullptr}, {1014.062f, -761.863f, 28.672f, nullptr}, + {1019.925f, -730.822f, 27.421f, nullptr}, {1022.320f, -698.581f, 25.993f, nullptr}, + {1022.539f, -665.405f, 24.574f, nullptr}, {1016.279f, -632.780f, 24.487f, nullptr}, + {1004.839f, -602.680f, 24.501f, nullptr}, {992.826f, -567.833f, 24.558f, nullptr}, + {984.998f, -535.303f, 24.485f, nullptr}, +}; + +BattleBotPath vPath_IC_South_West_Crossroads = { + {528.932f, -667.953f, 25.413f, nullptr}, {514.800f, -650.381f, 26.171f, nullptr}, + {488.367f, -621.869f, 25.820f, nullptr}, {479.491f, -594.284f, 26.095f, nullptr}, + {498.094f, -557.031f, 26.015f, nullptr}, {528.272f, -528.761f, 26.015f, nullptr}, + {595.746f, -480.009f, 26.007f, nullptr}, {632.156f, -458.182f, 27.416f, nullptr}, + {656.013f, -446.685f, 28.003f, nullptr}, +}; + +BattleBotPath vPath_IC_Hanger_to_Workshop = { + {808.923f, -1003.441f, 132.380f, nullptr}, {804.031f, -1002.785f, 132.382f, nullptr}, + {798.466f, -1021.472f, 132.292f, nullptr}, {795.472f, -1031.693f, 130.232f, nullptr}, + {804.631f, -1042.672f, 125.310f, nullptr}, {827.549f, -1061.778f, 111.276f, nullptr}, + {847.424f, -1077.930f, 98.061f, nullptr}, {868.225f, -1091.563f, 83.794f, nullptr}, + {894.100f, -1104.828f, 66.570f, nullptr}, {923.615f, -1117.689f, 47.391f, nullptr}, + {954.614f, -1119.716f, 27.880f, nullptr}, {970.397f, -1116.281f, 22.124f, nullptr}, + {985.906f, -1105.714f, 18.572f, nullptr}, {996.308f, -1090.605f, 17.669f, nullptr}, + {1003.693f, -1072.916f, 16.583f, nullptr}, {1008.660f, -1051.310f, 15.970f, nullptr}, + {1008.437f, -1026.678f, 15.623f, nullptr}, {1000.103f, -999.047f, 16.487f, nullptr}, + {988.412f, -971.096f, 17.796f, nullptr}, {971.503f, -945.742f, 14.438f, nullptr}, + {947.420f, -931.306f, 13.209f, nullptr}, {922.920f, -916.960f, 10.859f, nullptr}, + {901.607f, -902.203f, 9.854f, nullptr}, {881.932f, -882.226f, 7.848f, nullptr}, + {861.795f, -862.477f, 6.731f, nullptr}, {844.186f, -845.952f, 6.192f, nullptr}, + {826.565f, -826.551f, 5.171f, nullptr}, {809.497f, -815.351f, 6.179f, nullptr}, + {790.787f, -809.678f, 6.450f, nullptr}, +}; + + std::vector const vPaths_WS = { &vPath_WSG_HordeFlagRoom_to_HordeGraveyard, &vPath_WSG_HordeGraveyard_to_HordeTunnel, &vPath_WSG_HordeTunnel_to_HordeFlagRoom, &vPath_WSG_HordeTunnel_to_AllianceTunnel_1, @@ -1463,6 +1551,11 @@ std::vector const vPaths_IC = { &vPath_IC_Central_Graveyard_to_Workshop, &vPath_IC_Horde_East_Gate_to_Horde_Keep, &vPath_IC_Workshop_to_Workshop_Keep, + &vPath_IC_Alliance_Base, + &vPath_IC_Horde_Base, + &vPath_IC_Workshop_to_North_West, + &vPath_IC_South_West_Crossroads, + &vPath_IC_Hanger_to_Workshop, }; std::vector const vPaths_NoReverseAllowed = { @@ -1535,7 +1628,6 @@ static std::pair AV_AllianceDefendObjectives[] = { }; static uint32 AB_AttackObjectives[] = { - // Attack BG_AB_NODE_STABLES, BG_AB_NODE_BLACKSMITH, BG_AB_NODE_FARM, BG_AB_NODE_LUMBER_MILL, BG_AB_NODE_GOLD_MINE}; static std::tuple EY_AttackObjectives[] = { @@ -1544,6 +1636,12 @@ static std::tuple EY_AttackObjectives[] = { {POINT_DRAENEI_RUINS, BG_EY_OBJECT_FLAG_DRAENEI_RUINS, AT_DRAENEI_RUINS_POINT}, {POINT_MAGE_TOWER, BG_EY_OBJECT_FLAG_MAGE_TOWER, AT_MAGE_TOWER_POINT}}; +static std::pair IC_AttackObjectives[] = { + {NODE_TYPE_WORKSHOP, BG_IC_GO_WORKSHOP_BANNER}, + {NODE_TYPE_DOCKS, BG_IC_GO_DOCKS_BANNER}, + {NODE_TYPE_HANGAR, BG_IC_GO_HANGAR_BANNER}, +}; + // useful commands for fixing BG bugs and checking waypoints/paths bool BGTactics::HandleConsoleCommand(ChatHandler* handler, char const* args) { @@ -1584,7 +1682,11 @@ std::string const BGTactics::HandleConsoleCommandPrivate(WorldSession* session, if (!strncmp(cmd, "showpath", 8)) { int num = -1; - if (!strncmp(cmd, "showpath=", 9)) + if (!strncmp(cmd, "showpath=all", 12)) + { + num = -2; + } + else if (!strncmp(cmd, "showpath=", 9)) { if (sscanf(cmd, "showpath=%d", &num) == -1 || num < 0) return "Bad showpath parameter"; @@ -1631,17 +1733,29 @@ std::string const BGTactics::HandleConsoleCommandPrivate(WorldSession* session, } } } - if (num >= vPaths->size()) - return fmt::format("Path out of range of 0 - {}", vPaths->size() - 1); - auto const& path = (*vPaths)[num]; - for (uint32 i = 0; i < path->size(); i++) + uint32 min = 0u; + uint32 max = vPaths->size() - 1; + if (num >= 0) // num specified or found { - BattleBotWaypoint& waypoint = ((*path)[i]); - Creature* wpCreature = - player->SummonCreature(15631, waypoint.x, waypoint.y, waypoint.z, 0, TEMPSUMMON_TIMED_DESPAWN, 15000u); - wpCreature->SetOwnerGUID(player->GetGUID()); + if (num > max) + return fmt::format("Path {} of range of 0 - {}", num, max); + min = num; + max = num; } - return fmt::format("Showing path {}", num); + for (uint32 j = min; j <= max; j++) + { + auto const& path = (*vPaths)[j]; + for (uint32 i = 0; i < path->size(); i++) + { + BattleBotWaypoint& waypoint = ((*path)[i]); + Creature* wpCreature = player->SummonCreature(15631, waypoint.x, waypoint.y, waypoint.z, 0, + TEMPSUMMON_TIMED_DESPAWN, 15000u); + wpCreature->SetOwnerGUID(player->GetGUID()); + } + } + if (num >= 0) + return fmt::format("Showing path {}", num); + return fmt::format("Showing paths 0 - {}", max); } if (!strncmp(cmd, "showcreature=", 13)) @@ -2150,9 +2264,10 @@ bool BGTactics::Execute(Event event) if (useBuff()) return true; - if (bot->IsInCombat() && - !(bot->HasAura(BG_WS_SPELL_WARSONG_FLAG) || bot->HasAura(BG_WS_SPELL_SILVERWING_FLAG) || - bot->HasAura(BG_EY_NETHERSTORM_FLAG_SPELL))) + // NOTE: can't use IsInCombat() when in vehicle as player is stuck in combat forever while in vehicle (ac bug?) + bool inCombat = bot->GetVehicle() ? (bool)AI_VALUE(Unit*, "enemy player target") : bot->IsInCombat(); + if (inCombat && !(bot->HasAura(BG_WS_SPELL_WARSONG_FLAG) || bot->HasAura(BG_WS_SPELL_SILVERWING_FLAG) || + bot->HasAura(BG_EY_NETHERSTORM_FLAG_SPELL))) { // bot->GetMotionMaster()->MovementExpired(); return false; @@ -2274,53 +2389,33 @@ bool BGTactics::moveToStart(bool force) if (bot->GetTeamId() == TEAM_HORDE) { - if (role < 3) - { - if (urand(0, 1)) - MoveTo(bg->GetMapId(), IC_WEST_WAITING_POS_HORDE.GetPositionX() + frand(-5.0f, 5.0f), - IC_WEST_WAITING_POS_HORDE.GetPositionY() + frand(-5.0f, 5.0f), - IC_WEST_WAITING_POS_HORDE.GetPositionZ()); - else - MoveTo(bg->GetMapId(), IC_WAITING_POS_HORDE.GetPositionX() + frand(-5.0f, 5.0f), - IC_WAITING_POS_HORDE.GetPositionY() + frand(-5.0f, 5.0f), - IC_WAITING_POS_HORDE.GetPositionZ()); - } - else - { - if (urand(0, 1)) - MoveTo(bg->GetMapId(), IC_EAST_WAITING_POS_HORDE.GetPositionX() + frand(-5.0f, 5.0f), - IC_EAST_WAITING_POS_HORDE.GetPositionY() + frand(-5.0f, 5.0f), - IC_EAST_WAITING_POS_HORDE.GetPositionZ()); - else - MoveTo(bg->GetMapId(), IC_WAITING_POS_HORDE.GetPositionX() + frand(-5.0f, 5.0f), - IC_WAITING_POS_HORDE.GetPositionY() + frand(-5.0f, 5.0f), - IC_WAITING_POS_HORDE.GetPositionZ()); - } + if (role == 9) // refinery + MoveTo(bg->GetMapId(), IC_WEST_WAITING_POS_HORDE.GetPositionX() + frand(-5.0f, 5.0f), + IC_WEST_WAITING_POS_HORDE.GetPositionY() + frand(-5.0f, 5.0f), + IC_WEST_WAITING_POS_HORDE.GetPositionZ()); + else if (role >= 3 && role < 6) // hanger + MoveTo(bg->GetMapId(), IC_EAST_WAITING_POS_HORDE.GetPositionX() + frand(-5.0f, 5.0f), + IC_EAST_WAITING_POS_HORDE.GetPositionY() + frand(-5.0f, 5.0f), + IC_EAST_WAITING_POS_HORDE.GetPositionZ()); + else // everything else + MoveTo(bg->GetMapId(), IC_WAITING_POS_HORDE.GetPositionX() + frand(-5.0f, 5.0f), + IC_WAITING_POS_HORDE.GetPositionY() + frand(-5.0f, 5.0f), IC_WAITING_POS_HORDE.GetPositionZ()); } else { - if (role < 3) - { - if (urand(0, 1)) - MoveTo(bg->GetMapId(), IC_SIDE_WAITING_POS_ALLIANCE.GetPositionX() + frand(-5.0f, 5.0f), - IC_SIDE_WAITING_POS_ALLIANCE.GetPositionY() + frand(-5.0f, 5.0f), - IC_SIDE_WAITING_POS_ALLIANCE.GetPositionZ()); - else - MoveTo(bg->GetMapId(), IC_WAITING_POS_ALLIANCE.GetPositionX() + frand(-5.0f, 5.0f), - IC_WAITING_POS_ALLIANCE.GetPositionY() + frand(-5.0f, 5.0f), - IC_WAITING_POS_ALLIANCE.GetPositionZ()); - } - else - { - if (urand(0, 1)) - MoveTo(bg->GetMapId(), IC_SIDE_WAITING_POS_ALLIANCE.GetPositionX() + frand(-5.0f, 5.0f), - IC_SIDE_WAITING_POS_ALLIANCE.GetPositionY() + frand(-5.0f, 5.0f), - IC_SIDE_WAITING_POS_ALLIANCE.GetPositionZ()); - else - MoveTo(bg->GetMapId(), IC_WAITING_POS_ALLIANCE.GetPositionX() + frand(-5.0f, 5.0f), - IC_WAITING_POS_ALLIANCE.GetPositionY() + frand(-5.0f, 5.0f), - IC_WAITING_POS_ALLIANCE.GetPositionZ()); - } + if (role < 3) // docks + MoveTo( + bg->GetMapId(), IC_WAITING_POS_ALLIANCE.GetPositionX() + frand(-5.0f, 5.0f), + IC_WAITING_POS_ALLIANCE.GetPositionY() + frand(-5.0f, 5.0f), + IC_WAITING_POS_ALLIANCE.GetPositionZ()); // dont bother using west, there's no paths to use anyway + else if (role == 9 || (role >= 3 && role < 6)) // quarry and hanger + MoveTo(bg->GetMapId(), IC_EAST_WAITING_POS_ALLIANCE.GetPositionX() + frand(-5.0f, 5.0f), + IC_EAST_WAITING_POS_ALLIANCE.GetPositionY() + frand(-5.0f, 5.0f), + IC_EAST_WAITING_POS_ALLIANCE.GetPositionZ()); + else // everything else + MoveTo(bg->GetMapId(), IC_WAITING_POS_ALLIANCE.GetPositionX() + frand(-5.0f, 5.0f), + IC_WAITING_POS_ALLIANCE.GetPositionY() + frand(-5.0f, 5.0f), + IC_WAITING_POS_ALLIANCE.GetPositionZ()); } } @@ -3238,7 +3333,6 @@ bool BGTactics::selectObjective(bool reset) { BattlegroundIC* isleOfConquestBG = (BattlegroundIC*)bg; - uint32 currentObjective = MAX_NODE_TYPES; uint32 role = context->GetValue("bg role")->Get(); bool inVehicle = botAI->IsInVehicle(); bool controlsVehicle = botAI->IsInVehicle(true); @@ -3251,421 +3345,306 @@ bool BGTactics::selectObjective(bool reset) /* TACTICS */ if (bot->GetTeamId() == TEAM_HORDE) // HORDE { - // If all bases are captured, go to enemy boss - bool allCaptured = true; - for (uint8 i = 0; i < MAX_NODE_TYPES; ++i) + bool gateOpen = false; + if (GameObject* pGO = bg->GetBGObject(BG_IC_GO_DOODAD_PORTCULLISACTIVE02)) { - // skip refinery and keep - if (i == NODE_TYPE_REFINERY || i == NODE_TYPE_GRAVEYARD_H) - continue; - - ICNodePoint const& nodePoint = isleOfConquestBG->GetICNodePoint(i); - if (nodePoint.nodeState != NODE_STATE_CONFLICT_H && nodePoint.nodeState != NODE_STATE_CONTROLLED_H) + if (pGO->isSpawned() && pGO->getLootState() == GO_ACTIVATED) { - allCaptured = false; - break; - } - } - - if (allCaptured) // target enemy boss - { - if (Creature* allyboss = bg->GetBGCreature(BG_IC_NPC_HIGH_COMMANDER_HALFORD_WYRMBANE)) - { - if (allyboss->IsVisible()) - { - BgObjective = allyboss; - // ostringstream out; - // out << "Attackign BOSS! BG objective set to " << BgObjective->GetName(); - // bot->Say(out.str(), LANG_UNIVERSAL); - } - } - } - - // If main bases are not captured, split tasks - if (!BgObjective) - { - bool foundTask = false; - // mount defensive cannons - if (role > 10) // disabled - { - uint32 firstTower = getPlayersInArea(bot->GetTeamId(), IC_CANNON_POS_HORDE1, 10.0f); - uint32 secondTower = getPlayersInArea(bot->GetTeamId(), IC_CANNON_POS_HORDE2, 10.0f); - - if (firstTower < 2) - { - pos.Set(IC_CANNON_POS_HORDE1.GetPositionX(), IC_CANNON_POS_HORDE1.GetPositionY(), - IC_CANNON_POS_HORDE1.GetPositionZ(), bg->GetMapId()); - posMap["bg objective"] = pos; - return true; - } - if (secondTower < 2) - { - pos.Set(IC_CANNON_POS_HORDE2.GetPositionX(), IC_CANNON_POS_HORDE2.GetPositionY(), - IC_CANNON_POS_HORDE2.GetPositionZ(), bg->GetMapId()); - posMap["bg objective"] = pos; - return true; - } - } - if (role < 3) // Capture Side base or Docks - { - // Capture Refinery - ICNodePoint const& nodePoint = isleOfConquestBG->GetICNodePoint(NODE_TYPE_REFINERY); - if (nodePoint.nodeState != NODE_STATE_CONFLICT_H && - nodePoint.nodeState != NODE_STATE_CONTROLLED_H) - { - BgObjective = bg->GetBGObject(BG_IC_GO_REFINERY_BANNER); - currentObjective = BG_IC_GO_REFINERY_BANNER; - foundTask = true; - } - } - - if (!BgObjective && role < 6 && urand(0, 1)) // Capture Docks - { - // Capture Docks - ICNodePoint const& nodePoint = isleOfConquestBG->GetICNodePoint(NODE_TYPE_DOCKS); - if (nodePoint.nodeState != NODE_STATE_CONFLICT_H && - nodePoint.nodeState != NODE_STATE_CONTROLLED_H) - { - if (GameObject* pGO = bg->GetBGObject(BG_IC_GO_DOCKS_BANNER)) - { - BgObjective = pGO; - currentObjective = BG_IC_GO_DOCKS_BANNER; - foundTask = true; - - // ostringstream out; - // out << "DOCKS! BG objective set to " << BgObjective->GetName(); - // bot->Say(out.str(), LANG_UNIVERSAL); - } - } - } - // If docks/side capped, help capture workshop - if (!BgObjective && role < 3) - { - ICNodePoint const& nodePoint = isleOfConquestBG->GetICNodePoint(NODE_TYPE_WORKSHOP); - if (nodePoint.nodeState != NODE_STATE_CONFLICT_H && - nodePoint.nodeState != NODE_STATE_CONTROLLED_H) - { - if (GameObject* pGO = bg->GetBGObject(BG_IC_GO_WORKSHOP_BANNER)) - { - BgObjective = pGO; - currentObjective = BG_IC_GO_WORKSHOP_BANNER; - foundTask = true; - - // ostringstream out; - // out << "WORKSHOP! BG objective set to " << BgObjective->GetName(); - // bot->Say(out.str(), LANG_UNIVERSAL); - } - } - } - if (!BgObjective && role < 6) // Capture Hangar - { - ICNodePoint const& nodePoint = isleOfConquestBG->GetICNodePoint(NODE_TYPE_HANGAR); - if (nodePoint.nodeState != NODE_STATE_CONFLICT_H && - nodePoint.nodeState != NODE_STATE_CONTROLLED_H) - { - if (GameObject* pGO = bg->GetBGObject(BG_IC_GO_HANGAR_BANNER)) - { - BgObjective = pGO; - currentObjective = BG_IC_GO_HANGAR_BANNER; - foundTask = true; - // ostringstream out; - // out << "HANGAR! BG objective set to " << BgObjective->GetName(); - // bot->Say(out.str(), LANG_UNIVERSAL); - } - } - } - bool gateOpen = false; - if (!BgObjective || controlsVehicle) // Check gates - { - // Keep Gates open if any wall is destroyed, check it - if (GameObject* pGO = bg->GetBGObject(BG_IC_GO_DOODAD_PORTCULLISACTIVE01)) - { - if (pGO->isSpawned() && pGO->getLootState() == GO_ACTIVATED) - { - gateOpen = true; - } - else - { - if (GameObject* gate = bg->GetBGObject(BG_IC_GO_ALLIANCE_GATE_3)) - { - if (controlsVehicle) - { - // come close to gate if siege engine - if (vehicleId == NPC_SIEGE_ENGINE_H) - { - BgObjective = gate; - } - else - { - // take a siege position - pos.Set(506.782f + frand(-5, +5), -828.594f + frand(-5, +5), 24.313f, - bot->GetMapId()); - posMap["bg objective"] = pos; - - // set siege position - PositionInfo siegePos = - context->GetValue("position")->Get()["bg siege"]; - siegePos.Set(gate->GetPositionX(), gate->GetPositionY(), - gate->GetPositionZ(), bot->GetMapId()); - posMap["bg siege"] = siegePos; - return true; - } - } - else - { - pos.Set(506.782f + frand(-5, +5), -828.594f + frand(-5, +5), 24.313f, - bot->GetMapId()); - posMap["bg objective"] = pos; - return true; - // BgObjective = gate; - } - } - } - } - } - if (!BgObjective && gateOpen) // Capture Keep - { - // reset siege position + gateOpen = true; PositionInfo siegePos = context->GetValue("position")->Get()["bg siege"]; siegePos.Reset(); posMap["bg siege"] = siegePos; - - ICNodePoint const& nodePoint = isleOfConquestBG->GetICNodePoint(NODE_TYPE_GRAVEYARD_A); - if (nodePoint.nodeState != NODE_STATE_CONFLICT_H && - nodePoint.nodeState != NODE_STATE_CONTROLLED_H) + } + } + if (gateOpen && !controlsVehicle && + isleOfConquestBG->GetICNodePoint(NODE_TYPE_GRAVEYARD_A).nodeState == + NODE_STATE_CONTROLLED_H) // target enemy boss + { + if (Creature* enemyBoss = bg->GetBGCreature(BG_IC_NPC_HIGH_COMMANDER_HALFORD_WYRMBANE)) + { + if (enemyBoss->IsVisible()) { - if (GameObject* pGO = bg->GetBGObject(BG_IC_GO_ALLIANCE_BANNER)) + BgObjective = enemyBoss; + // LOG_INFO("playerbots", "bot={} attack boss", bot->GetName()); + } + } + } + + if (!BgObjective && gateOpen && !controlsVehicle) + { + if (GameObject* pGO = bg->GetBGObject(BG_IC_GO_ALLIANCE_BANNER)) // capture flag within keep + { + BgObjective = pGO; + // LOG_INFO("playerbots", "bot={} attack keep", bot->GetName()); + } + } + + if (!BgObjective && !gateOpen && controlsVehicle) // attack gates + { + // TODO: check for free vehicles + if (GameObject* gate = bg->GetBGObject(BG_IC_GO_ALLIANCE_GATE_3)) + { + if (vehicleId == NPC_SIEGE_ENGINE_H) // target gate directly if siege engine + { + BgObjective = gate; + // LOG_INFO("playerbots", "bot={} (in siege-engine) attack gate", bot->GetName()); + } + else // target gate directly at range if other vehicle + { + // take a siege position + if (sqrt(bot->GetDistance(IC_GATE_ATTACK_POS_HORDE)) < + 5.0f) // just make bot stay where it is (stops them shifting around to the random + // spots) + pos.Set(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), bot->GetMapId()); + else + pos.Set(IC_GATE_ATTACK_POS_HORDE.GetPositionX() + frand(-5.0f, +5.0f), + IC_GATE_ATTACK_POS_HORDE.GetPositionY() + frand(-5.0f, +5.0f), + IC_GATE_ATTACK_POS_HORDE.GetPositionZ(), bot->GetMapId()); + posMap["bg objective"] = pos; + // set siege position + PositionInfo siegePos = context->GetValue("position")->Get()["bg siege"]; + siegePos.Set(gate->GetPositionX(), gate->GetPositionY(), gate->GetPositionZ(), + bot->GetMapId()); + posMap["bg siege"] = siegePos; + // LOG_INFO("playerbots", "bot={} (in vehicle={}) attack gate", bot->GetName(), vehicleId); + return true; + } + } + } + + // If gates arent down and not in vehicle, split tasks + if (!BgObjective && !controlsVehicle && role == 9) // Capture Side base + { + // Capture Refinery + ICNodePoint const& nodePoint = isleOfConquestBG->GetICNodePoint(NODE_TYPE_REFINERY); + if (nodePoint.nodeState != NODE_STATE_CONFLICT_H && nodePoint.nodeState != NODE_STATE_CONTROLLED_H) + { + BgObjective = bg->GetBGObject(BG_IC_GO_REFINERY_BANNER); + // LOG_INFO("playerbots", "bot={} attack refinery", bot->GetName()); + } + } + + if (!BgObjective && !controlsVehicle && role < 3) // Capture Docks + { + ICNodePoint const& nodePoint = isleOfConquestBG->GetICNodePoint(NODE_TYPE_DOCKS); + if (nodePoint.nodeState != NODE_STATE_CONFLICT_H && nodePoint.nodeState != NODE_STATE_CONTROLLED_H) + { + if (GameObject* pGO = bg->GetBGObject(BG_IC_GO_DOCKS_BANNER)) + { + BgObjective = pGO; + // LOG_INFO("playerbots", "bot={} attack docks", bot->GetName()); + } + } + } + if (!BgObjective && !controlsVehicle && role < 6) // Capture Hangar + { + ICNodePoint const& nodePoint = isleOfConquestBG->GetICNodePoint(NODE_TYPE_HANGAR); + if (nodePoint.nodeState != NODE_STATE_CONFLICT_H && nodePoint.nodeState != NODE_STATE_CONTROLLED_H) + { + if (GameObject* pGO = bg->GetBGObject(BG_IC_GO_HANGAR_BANNER)) + { + BgObjective = pGO; + // LOG_INFO("playerbots", "bot={} attack hangar", bot->GetName()); + } + } + } + if (!BgObjective && !controlsVehicle) // Capture Workshop + { + ICNodePoint const& nodePoint = isleOfConquestBG->GetICNodePoint(NODE_TYPE_WORKSHOP); + if (nodePoint.nodeState != NODE_STATE_CONFLICT_H && nodePoint.nodeState != NODE_STATE_CONTROLLED_H) + { + if (GameObject* pGO = bg->GetBGObject(BG_IC_GO_WORKSHOP_BANNER)) + { + BgObjective = pGO; + // LOG_INFO("playerbots", "bot={} attack workshop", bot->GetName()); + } + } + } + if (!BgObjective) // Guard point that's not fully capped (also gets them in place to board vehicle) + { + uint32 len = end(IC_AttackObjectives) - begin(IC_AttackObjectives); + for (uint32 i = 0; i < len; i++) + { + const auto& objective = + IC_AttackObjectives[(i + role) % + len]; // use role to determine which objective checked first + if (isleOfConquestBG->GetICNodePoint(objective.first).nodeState != NODE_STATE_CONTROLLED_H) + { + if (GameObject* pGO = bg->GetBGObject(objective.second)) { BgObjective = pGO; - currentObjective = BG_IC_GO_ALLIANCE_BANNER; - foundTask = true; - - // ostringstream out; - // out << "ALLY KEEP! BG objective set to " << BgObjective->GetName(); - // bot->Say(out.str(), LANG_UNIVERSAL); + // LOG_INFO("playerbots", "bot={} guard point while it captures", bot->GetName()); + break; } } } } + if (!BgObjective) // guard vehicles as they seige + + { + if (sqrt(bot->GetDistance(IC_GATE_ATTACK_POS_HORDE)) < + 5.0f) // just make bot stay where it is (stops them shifting around to the random spots) + pos.Set(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), bot->GetMapId()); + else + pos.Set(IC_GATE_ATTACK_POS_HORDE.GetPositionX() + frand(-5.0f, +5.0f), + IC_GATE_ATTACK_POS_HORDE.GetPositionY() + frand(-5.0f, +5.0f), + IC_GATE_ATTACK_POS_HORDE.GetPositionZ(), bot->GetMapId()); + posMap["bg objective"] = pos; + // LOG_INFO("playerbots", "bot={} guard vehicles as they attack gate", bot->GetName()); + return true; + } } if (bot->GetTeamId() == TEAM_ALLIANCE) // ALLIANCE { - // If all bases are captured, go to enemy boss - bool allCaptured = true; - for (uint8 i = 0; i < MAX_NODE_TYPES; ++i) + bool gateOpen = false; + if (GameObject* pGO = bg->GetBGObject(BG_IC_GO_HORDE_KEEP_PORTCULLIS)) { - // skip quarry and keep - if (i == NODE_TYPE_QUARRY || i == NODE_TYPE_GRAVEYARD_A) - continue; - - ICNodePoint const& nodePoint = isleOfConquestBG->GetICNodePoint(i); - if (nodePoint.nodeState != NODE_STATE_CONFLICT_A && nodePoint.nodeState != NODE_STATE_CONTROLLED_A) + if (pGO->isSpawned() && pGO->getLootState() == GO_ACTIVATED) { - allCaptured = false; - break; - } - } - - if (allCaptured) // target enemy boss - { - if (Creature* hordeboss = bg->GetBGCreature(BG_IC_NPC_OVERLORD_AGMAR)) - { - if (!hordeboss->IsVisible()) - { - BgObjective = hordeboss; - // ostringstream out; - // out << "HORDE BOSS! BG objective set to " << BgObjective->GetName(); - // bot->Say(out.str(), LANG_UNIVERSAL); - } - } - } - - // If main bases are not captured, split tasks - if (!BgObjective) - { - bool foundTask = false; - // mount defensive cannons - if (role > 10) // disabled - { - uint32 firstTower = getPlayersInArea(bot->GetTeamId(), IC_CANNON_POS_ALLIANCE1, 10.0f); - uint32 secondTower = getPlayersInArea(bot->GetTeamId(), IC_CANNON_POS_ALLIANCE2, 10.0f); - - if (firstTower < 3) - { - pos.Set(IC_CANNON_POS_ALLIANCE1.GetPositionX(), IC_CANNON_POS_ALLIANCE1.GetPositionY(), - IC_CANNON_POS_ALLIANCE1.GetPositionZ(), bg->GetMapId()); - posMap["bg objective"] = pos; - return true; - } - if (secondTower < 3) - { - pos.Set(IC_CANNON_POS_ALLIANCE2.GetPositionX(), IC_CANNON_POS_ALLIANCE2.GetPositionY(), - IC_CANNON_POS_ALLIANCE2.GetPositionZ(), bg->GetMapId()); - posMap["bg objective"] = pos; - return true; - } - } - - if (role < 3) // Capture Side base or Docks - { - // Capture Quarry - ICNodePoint const& nodePoint = isleOfConquestBG->GetICNodePoint(NODE_TYPE_QUARRY); - if (nodePoint.nodeState != NODE_STATE_CONFLICT_A && - nodePoint.nodeState != NODE_STATE_CONTROLLED_A) - { - if (GameObject* pGO = bg->GetBGObject(BG_IC_GO_QUARRY_BANNER)) - { - BgObjective = pGO; - currentObjective = BG_IC_GO_QUARRY_BANNER; - foundTask = true; - - // ostringstream out; - // out << "QUARRY! BG objective set to " << BgObjective->GetName(); - // bot->Say(out.str(), LANG_UNIVERSAL); - } - } - } - // take position at cannon - /*if (!BgObjective) - { - if (GameObject* pGO = bg->interactwith(BG_IC_VEHICLE_KEEP_CANNON)) - { - if (sServerFacade->isSpawned(pGO) && pGO->GetLootState() == GO_READY) - isCapping = true; - } - }*/ - if (!BgObjective && role < 6 && urand(0, 1)) - { - // Capture Docks - ICNodePoint const& nodePoint = isleOfConquestBG->GetICNodePoint(NODE_TYPE_DOCKS); - if (nodePoint.nodeState != NODE_STATE_CONFLICT_A && - nodePoint.nodeState != NODE_STATE_CONTROLLED_A) - { - if (GameObject* pGO = bg->GetBGObject(BG_IC_GO_DOCKS_BANNER)) - { - BgObjective = pGO; - currentObjective = BG_IC_GO_DOCKS_BANNER; - foundTask = true; - - // ostringstream out; - // out << "DOCKS! BG objective set to " << BgObjective->GetName(); - // bot->Say(out.str(), LANG_UNIVERSAL); - } - } - } - // If docks/side capped, help capture workshop - if (!BgObjective && role < 3) - { - ICNodePoint const& nodePoint = isleOfConquestBG->GetICNodePoint(NODE_TYPE_WORKSHOP); - if (nodePoint.nodeState != NODE_STATE_CONFLICT_A && - nodePoint.nodeState != NODE_STATE_CONTROLLED_A) - { - if (GameObject* pGO = bg->GetBGObject(BG_IC_GO_WORKSHOP_BANNER)) - { - BgObjective = pGO; - currentObjective = BG_IC_GO_WORKSHOP_BANNER; - foundTask = true; - - // ostringstream out; - // out << "WORKSHOP! BG objective set to " << BgObjective->GetName(); - // bot->Say(out.str(), LANG_UNIVERSAL); - } - } - } - if (!BgObjective && role < 6) // Capture Hangar - { - ICNodePoint const& nodePoint = isleOfConquestBG->GetICNodePoint(NODE_TYPE_HANGAR); - if (nodePoint.nodeState != NODE_STATE_CONFLICT_A && - nodePoint.nodeState != NODE_STATE_CONTROLLED_A) - { - if (GameObject* pGO = bg->GetBGObject(BG_IC_GO_HANGAR_BANNER)) - { - BgObjective = pGO; - currentObjective = BG_IC_GO_HANGAR_BANNER; - foundTask = true; - - // ostringstream out; - // out << "HANGAR! BG objective set to " << BgObjective->GetName(); - // bot->Say(out.str(), LANG_UNIVERSAL); - } - } - } - - bool gateOpen = false; - if (!BgObjective || controlsVehicle) // Check gates - { - // Keep Gates open if any wall is destroyed, check it - if (GameObject* pGO = bg->GetBGObject(BG_IC_GO_HORDE_KEEP_PORTCULLIS)) - { - if (pGO->isSpawned() && pGO->getLootState() == GO_ACTIVATED) - { - gateOpen = true; - } - else - { - if (GameObject* gate = bg->GetBGObject(BG_IC_GO_HORDE_GATE_3)) - { - if (controlsVehicle) - { - // come close to gate if siege engine - if (vehicleId == NPC_SIEGE_ENGINE_A) - { - BgObjective = gate; - } - else - { - // take a siege position - pos.Set(1091.273f + frand(-5, +5), -763.619f + frand(-5, +5), 42.352f, - bot->GetMapId()); - posMap["bg objective"] = pos; - - // set siege position - PositionInfo siegePos = - context->GetValue("position")->Get()["bg siege"]; - siegePos.Set(gate->GetPositionX(), gate->GetPositionY(), - gate->GetPositionZ(), bot->GetMapId()); - posMap["bg siege"] = siegePos; - return true; - } - } - else - { - pos.Set(1091.273f + frand(-5, +5), -763.619f + frand(-5, +5), 42.352f, - bot->GetMapId()); - posMap["bg objective"] = pos; - return true; - // take a siege position - // BgObjective = gate; - } - } - } - } - } - if (!BgObjective && gateOpen) // Capture Keep - { - // reset siege position + gateOpen = true; PositionInfo siegePos = context->GetValue("position")->Get()["bg siege"]; siegePos.Reset(); posMap["bg siege"] = siegePos; + } + } - ICNodePoint const& nodePoint = isleOfConquestBG->GetICNodePoint(NODE_TYPE_GRAVEYARD_H); - if (nodePoint.nodeState != NODE_STATE_CONFLICT_A && - nodePoint.nodeState != NODE_STATE_CONTROLLED_A) + if (gateOpen && !controlsVehicle && + isleOfConquestBG->GetICNodePoint(NODE_TYPE_GRAVEYARD_H).nodeState == + NODE_STATE_CONTROLLED_A) // target enemy boss + { + if (Creature* enemyBoss = bg->GetBGCreature(BG_IC_NPC_OVERLORD_AGMAR)) + { + if (enemyBoss->IsVisible()) { - if (GameObject* pGO = bg->GetBGObject(BG_IC_GO_HORDE_BANNER)) + BgObjective = enemyBoss; + // LOG_INFO("playerbots", "bot={} attack boss", bot->GetName()); + } + } + } + + if (!BgObjective && gateOpen && !controlsVehicle) + { + if (GameObject* pGO = bg->GetBGObject(BG_IC_GO_HORDE_BANNER)) // capture flag within keep + { + BgObjective = pGO; + // LOG_INFO("playerbots", "bot={} attack keep", bot->GetName()); + } + } + + if (!BgObjective && !gateOpen && controlsVehicle) // attack gates + { + // TODO: check for free vehicles + if (GameObject* gate = bg->GetBGObject(BG_IC_GO_HORDE_GATE_1)) + { + if (vehicleId == NPC_SIEGE_ENGINE_A) // target gate directly if siege engine + { + BgObjective = gate; + // LOG_INFO("playerbots", "bot={} (in siege-engine) attack gate", bot->GetName()); + } + else // target gate directly at range if other vehicle + { + // take a siege position + if (sqrt(bot->GetDistance(IC_GATE_ATTACK_POS_ALLIANCE)) < + 5.0f) // just make bot stay where it is (stops them shifting around to the random + // spots) + pos.Set(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), bot->GetMapId()); + else + pos.Set(IC_GATE_ATTACK_POS_ALLIANCE.GetPositionX() + frand(-5.0f, +5.0f), + IC_GATE_ATTACK_POS_ALLIANCE.GetPositionY() + frand(-5.0f, +5.0f), + IC_GATE_ATTACK_POS_ALLIANCE.GetPositionZ(), bot->GetMapId()); + posMap["bg objective"] = pos; + // set siege position + PositionInfo siegePos = context->GetValue("position")->Get()["bg siege"]; + siegePos.Set(gate->GetPositionX(), gate->GetPositionY(), gate->GetPositionZ(), + bot->GetMapId()); + posMap["bg siege"] = siegePos; + // LOG_INFO("playerbots", "bot={} (in vehicle={}) attack gate", bot->GetName(), vehicleId); + return true; + } + } + } + + // If gates arent down and not in vehicle, split tasks + if (!BgObjective && !controlsVehicle && role == 9) // Capture Side base + { + // Capture Refinery + ICNodePoint const& nodePoint = isleOfConquestBG->GetICNodePoint(NODE_TYPE_QUARRY); + if (nodePoint.nodeState != NODE_STATE_CONFLICT_A && nodePoint.nodeState != NODE_STATE_CONTROLLED_A) + { + BgObjective = bg->GetBGObject(BG_IC_GO_QUARRY_BANNER); + // LOG_INFO("playerbots", "bot={} attack quarry", bot->GetName()); + } + } + + if (!BgObjective && !controlsVehicle && role < 3) // Capture Docks + { + ICNodePoint const& nodePoint = isleOfConquestBG->GetICNodePoint(NODE_TYPE_DOCKS); + if (nodePoint.nodeState != NODE_STATE_CONFLICT_A && nodePoint.nodeState != NODE_STATE_CONTROLLED_A) + { + if (GameObject* pGO = bg->GetBGObject(BG_IC_GO_DOCKS_BANNER)) + { + BgObjective = pGO; + // LOG_INFO("playerbots", "bot={} attack docks", bot->GetName()); + } + } + } + if (!BgObjective && !controlsVehicle && role < 6) // Capture Hangar + { + ICNodePoint const& nodePoint = isleOfConquestBG->GetICNodePoint(NODE_TYPE_HANGAR); + if (nodePoint.nodeState != NODE_STATE_CONFLICT_A && nodePoint.nodeState != NODE_STATE_CONTROLLED_A) + { + if (GameObject* pGO = bg->GetBGObject(BG_IC_GO_HANGAR_BANNER)) + { + BgObjective = pGO; + // LOG_INFO("playerbots", "bot={} attack hangar", bot->GetName()); + } + } + } + if (!BgObjective && !controlsVehicle) // Capture Workshop + { + ICNodePoint const& nodePoint = isleOfConquestBG->GetICNodePoint(NODE_TYPE_WORKSHOP); + if (nodePoint.nodeState != NODE_STATE_CONFLICT_A && nodePoint.nodeState != NODE_STATE_CONTROLLED_A) + { + if (GameObject* pGO = bg->GetBGObject(BG_IC_GO_WORKSHOP_BANNER)) + { + BgObjective = pGO; + // LOG_INFO("playerbots", "bot={} attack workshop", bot->GetName()); + } + } + } + if (!BgObjective) // Guard point that's not fully capped (also gets them in place to board vehicle) + { + uint32 len = end(IC_AttackObjectives) - begin(IC_AttackObjectives); + for (uint32 i = 0; i < len; i++) + { + const auto& objective = + IC_AttackObjectives[(i + role) % + len]; // use role to determine which objective checked first + if (isleOfConquestBG->GetICNodePoint(objective.first).nodeState != NODE_STATE_CONTROLLED_H) + { + if (GameObject* pGO = bg->GetBGObject(objective.second)) { BgObjective = pGO; - currentObjective = BG_IC_GO_HORDE_BANNER; - foundTask = true; - - // ostringstream out; - // out << "HORDE KEEP! BG objective set to " << BgObjective->GetName(); - // bot->Say(out.str(), LANG_UNIVERSAL); + // LOG_INFO("playerbots", "bot={} guard point while it captures", bot->GetName()); + break; } } } } + if (!BgObjective) // guard vehicles as they seige + { + if (sqrt(bot->GetDistance(IC_GATE_ATTACK_POS_ALLIANCE)) < + 5.0f) // just make bot stay where it is (stops them shifting around to the random spots) + pos.Set(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), bot->GetMapId()); + else + pos.Set(IC_GATE_ATTACK_POS_ALLIANCE.GetPositionX() + frand(-5.0f, +5.0f), + IC_GATE_ATTACK_POS_ALLIANCE.GetPositionY() + frand(-5.0f, +5.0f), + IC_GATE_ATTACK_POS_ALLIANCE.GetPositionZ(), bot->GetMapId()); + posMap["bg objective"] = pos; + // LOG_INFO("playerbots", "bot={} guard vehicles as they attack gate", bot->GetName()); + return true; + } } if (BgObjective) @@ -3784,7 +3763,10 @@ bool BGTactics::selectObjectiveWp(std::vector const& vPaths) // distance from bot - makes distance from bot more signifcant than distance from destination) if (bgType == BATTLEGROUND_IC) - botDistanceLimit = 80.0f; + { + // botDistanceLimit = 80.0f; + botDistanceScoreMultiply = 8.0f; + } else if (bgType == BATTLEGROUND_AB || bgType == BATTLEGROUND_EY) { botDistanceScoreSubtract = 2.0f; @@ -3879,7 +3861,9 @@ bool BGTactics::resetObjective() // sometimes change role - should do so less often on larger BG's otherwise bots will spend too much time running // around map instead of doing something useful - uint32 rollChangeOdds = BATTLEGROUND_AV == bg->GetBgTypeID() ? 63 : BATTLEGROUND_EY == bg->GetBgTypeID() ? 31 : 5; + uint32 rollChangeOdds = BATTLEGROUND_AV == bg->GetBgTypeID() ? 63 + : BATTLEGROUND_EY == bg->GetBgTypeID() || BATTLEGROUND_IC == bg->GetBgTypeID() ? 31 + : 5; if (!urand(0, rollChangeOdds) && !(bot->HasAura(BG_WS_SPELL_WARSONG_FLAG) || bot->HasAura(BG_WS_SPELL_SILVERWING_FLAG) || bot->HasAura(BG_EY_NETHERSTORM_FLAG_SPELL))) @@ -3900,9 +3884,11 @@ bool BGTactics::moveToObjectiveWp(BattleBotPath* const& currentPath, uint32 curr uint32 const lastPointInPath = reverse ? 0 : ((*currentPath).size() - 1); + // NOTE: can't use IsInCombat() when in vehicle as player is stuck in combat forever while in vehicle (ac bug?) + bool inCombat = bot->GetVehicle() ? (bool)AI_VALUE(Unit*, "enemy player target") : bot->IsInCombat(); if ((currentPoint == lastPointInPath) || - (bot->IsInCombat() && !(bot->HasAura(BG_WS_SPELL_WARSONG_FLAG) || bot->HasAura(BG_WS_SPELL_SILVERWING_FLAG) || - bot->HasAura(BG_EY_NETHERSTORM_FLAG_SPELL))) || + (inCombat && !(bot->HasAura(BG_WS_SPELL_WARSONG_FLAG) || bot->HasAura(BG_WS_SPELL_SILVERWING_FLAG) || + bot->HasAura(BG_EY_NETHERSTORM_FLAG_SPELL))) || !bot->IsAlive()) { // Path is over. diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index 52310f76..c9b825f6 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -177,6 +177,28 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, { return false; } + + if (Vehicle* vehicle = bot->GetVehicle()) + { + VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(bot); + Unit* vehicleBase = vehicle->GetBase(); + if (!vehicleBase || !seat || !seat->CanControl()) // is passenger and cant move anyway + return false; + + float distance = vehicleBase->GetExactDist(x, y, z); + if (distance <= sPlayerbotAIConfig->contactDistance) + return false; + + MotionMaster& mm = *vehicleBase->GetMotionMaster(); // need to move vehicle, not bot + mm.Clear(); + mm.MovePoint(mapId, x, y, z, generatePath); + + float delay = 1000.0f * (distance / vehicleBase->GetSpeed(MOVE_RUN)) - sPlayerbotAIConfig->reactDelay; + delay = std::max(.0f, delay); + delay = std::min((float)sPlayerbotAIConfig->maxWaitForMove, delay); + AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation(), delay); + return true; + } // if (bot->Unit::IsFalling()) { // bot->Say("I'm falling!, flag:" + std::to_string(bot->m_movementInfo.GetMovementFlags()), LANG_UNIVERSAL); // return false; diff --git a/src/strategy/actions/ReleaseSpiritAction.cpp b/src/strategy/actions/ReleaseSpiritAction.cpp index 64521c4e..0d1ad8b6 100644 --- a/src/strategy/actions/ReleaseSpiritAction.cpp +++ b/src/strategy/actions/ReleaseSpiritAction.cpp @@ -119,7 +119,11 @@ bool AutoReleaseSpiritAction::Execute(Event event) } if (bot->GetDistance(unit) >= INTERACTION_DISTANCE) { - bot->GetMotionMaster()->MoveChase(unit); + // bot needs to actually click spirit-healer in BG to get res timer going + // and in IOC it's not within clicking range when they res in own base + MotionMaster& mm = *bot->GetMotionMaster(); + mm.Clear(); + mm.MovePoint(bot->GetMapId(), unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), true); } else { diff --git a/src/strategy/actions/VehicleActions.cpp b/src/strategy/actions/VehicleActions.cpp index b036a036..2fc09cb3 100644 --- a/src/strategy/actions/VehicleActions.cpp +++ b/src/strategy/actions/VehicleActions.cpp @@ -5,11 +5,16 @@ #include "VehicleActions.h" +#include "BattlegroundIC.h" #include "ItemVisitors.h" #include "Playerbots.h" #include "ServerFacade.h" #include "Vehicle.h" +// TODO methods to enter/exit vehicle should be added to BGTactics or MovementAction (so that we can better control +// whether bot is in vehicle, eg: get out of vehicle to cap flag, if we're down to final boss, etc), +// right now they will enter vehicle based only what's available here, then they're stuck in vehicle until they die +// (LeaveVehicleAction doesnt do much seeing as they, or another bot, will get in immediately after exit) bool EnterVehicleAction::Execute(Event event) { // do not switch vehicles yet @@ -21,21 +26,31 @@ bool EnterVehicleAction::Execute(Event event) { Unit* vehicleBase = botAI->GetUnit(*i); if (!vehicleBase) - return false; + continue; + + // dont let them get in the cannons as they'll stay forever and do nothing useful + // dont let them in catapult they cant use them at all + if (NPC_KEEP_CANNON == vehicleBase->GetEntry() || NPC_CATAPULT == vehicleBase->GetEntry()) + continue; if (!vehicleBase->IsFriendlyTo(bot)) - return false; + continue; if (!vehicleBase->GetVehicleKit()->GetAvailableSeatCount()) - return false; + continue; - if (fabs(bot->GetPositionZ() - vehicleBase->GetPositionZ()) < 20.0f) + // this will avoid adding passengers (which dont really do much for the IOC vehicles which is the only place + // this code is used) + if (vehicleBase->GetVehicleKit()->IsVehicleInUse()) + continue; - // if (sServerFacade->GetDistance2d(bot, vehicle) > 100.0f) - // continue; + // if (fabs(bot->GetPositionZ() - vehicleBase->GetPositionZ()) < 20.0f) - if (sServerFacade->GetDistance2d(bot, vehicleBase) > 10.0f) - return MoveTo(vehicleBase, INTERACTION_DISTANCE); + // if (sServerFacade->GetDistance2d(bot, vehicle) > 100.0f) + // continue; + + if (sServerFacade->GetDistance2d(bot, vehicleBase) > INTERACTION_DISTANCE) + return MoveTo(vehicleBase, INTERACTION_DISTANCE - 1.0f); bot->EnterVehicle(vehicleBase); diff --git a/src/strategy/generic/BattlegroundStrategy.cpp b/src/strategy/generic/BattlegroundStrategy.cpp index 2a74b2f0..5a99cedd 100644 --- a/src/strategy/generic/BattlegroundStrategy.cpp +++ b/src/strategy/generic/BattlegroundStrategy.cpp @@ -99,8 +99,9 @@ void IsleStrategy::InitTriggers(std::vector& triggers) new TriggerNode("in vehicle", NextAction::array(0, new NextAction("incendiary rocket", 70.0f), nullptr))); triggers.push_back( new TriggerNode("in vehicle", NextAction::array(0, new NextAction("rocket blast", 70.0f), nullptr))); - triggers.push_back( - new TriggerNode("in vehicle", NextAction::array(0, new NextAction("blade salvo", 71.0f), nullptr))); + // 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::array(0, new NextAction("blade salvo", 71.0f), nullptr))); triggers.push_back( new TriggerNode("in vehicle", NextAction::array(0, new NextAction("glaive throw", 70.0f), nullptr))); } diff --git a/src/strategy/values/EnemyPlayerValue.cpp b/src/strategy/values/EnemyPlayerValue.cpp index ba346a47..5302bde2 100644 --- a/src/strategy/values/EnemyPlayerValue.cpp +++ b/src/strategy/values/EnemyPlayerValue.cpp @@ -7,6 +7,7 @@ #include "Playerbots.h" #include "ServerFacade.h" +#include "Vehicle.h" bool NearestEnemyPlayersValue::AcceptUnit(Unit* unit) { @@ -25,7 +26,19 @@ bool NearestEnemyPlayersValue::AcceptUnit(Unit* unit) Unit* EnemyPlayerValue::Calculate() { - bool inCannon = botAI->IsInVehicle(false, true); + bool controllingCannon = false; + bool controllingVehicle = false; + if (Vehicle* vehicle = bot->GetVehicle()) + { + VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(bot); + if (!seat || !seat->CanControl()) // not in control of vehicle so cant attack anyone + return nullptr; + VehicleEntry const* vi = vehicle->GetVehicleInfo(); + if (vi && vi->m_flags & VEHICLE_FLAG_FIXED_POSITION) + controllingCannon = true; + else + controllingVehicle = true; + } // 1. Check units we are currently in combat with. std::vector targets; @@ -95,12 +108,15 @@ Unit* EnemyPlayerValue::Calculate() } // Aggro weak enemies from further away. - uint32 const aggroDistance = (inCannon || bot->GetHealth() > pTarget->GetHealth()) ? maxAggroDistance : 20.0f; + // If controlling mobile vehicle only agro close enemies (otherwise will never reach objective) + uint32 const aggroDistance = controllingVehicle ? 5.0f + : (controllingCannon || bot->GetHealth() > pTarget->GetHealth()) ? maxAggroDistance + : 20.0f; if (!bot->IsWithinDist(pTarget, aggroDistance)) continue; if (bot->IsWithinLOSInMap(pTarget) && - (inCannon || (fabs(bot->GetPositionZ() - pTarget->GetPositionZ()) < 30.0f))) + (controllingCannon || (fabs(bot->GetPositionZ() - pTarget->GetPositionZ()) < 30.0f))) return pTarget; } diff --git a/src/strategy/values/NearestNpcsValue.cpp b/src/strategy/values/NearestNpcsValue.cpp index c0c21509..cbbc8894 100644 --- a/src/strategy/values/NearestNpcsValue.cpp +++ b/src/strategy/values/NearestNpcsValue.cpp @@ -32,7 +32,7 @@ bool NearestVehiclesValue::AcceptUnit(Unit* unit) if (!unit || !unit->IsVehicle() || !unit->IsAlive()) return false; - Vehicle* veh = unit->GetVehicle(); + Vehicle* veh = unit->GetVehicleKit(); if (!veh || !veh->GetAvailableSeatCount()) return false; From 5ce49299c463fc2aabc4ed24c963f52d97a1cbbe Mon Sep 17 00:00:00 2001 From: Fuzz Date: Tue, 6 Aug 2024 19:56:20 +1000 Subject: [PATCH 2/7] cleaned up movement code (and left comment for liyunfan) --- src/strategy/actions/MovementActions.cpp | 44 ++++++++++++------------ 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index c9b825f6..98018f6d 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -178,27 +178,6 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, return false; } - if (Vehicle* vehicle = bot->GetVehicle()) - { - VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(bot); - Unit* vehicleBase = vehicle->GetBase(); - if (!vehicleBase || !seat || !seat->CanControl()) // is passenger and cant move anyway - return false; - - float distance = vehicleBase->GetExactDist(x, y, z); - if (distance <= sPlayerbotAIConfig->contactDistance) - return false; - - MotionMaster& mm = *vehicleBase->GetMotionMaster(); // need to move vehicle, not bot - mm.Clear(); - mm.MovePoint(mapId, x, y, z, generatePath); - - float delay = 1000.0f * (distance / vehicleBase->GetSpeed(MOVE_RUN)) - sPlayerbotAIConfig->reactDelay; - delay = std::max(.0f, delay); - delay = std::min((float)sPlayerbotAIConfig->maxWaitForMove, delay); - AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation(), delay); - return true; - } // if (bot->Unit::IsFalling()) { // bot->Say("I'm falling!, flag:" + std::to_string(bot->m_movementInfo.GetMovementFlags()), LANG_UNIVERSAL); // return false; @@ -212,7 +191,28 @@ 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()); - if (exact_waypoint || disableMoveSplinePath || !generatePath) + if (Vehicle* vehicle = bot->GetVehicle()) + { + VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(bot); + Unit* vehicleBase = vehicle->GetBase(); + if (!vehicleBase || !seat || !seat->CanControl()) // is passenger and cant move anyway + return false; + + float distance = vehicleBase->GetExactDist(x, y, z); // use vehicle distance, not bot + if (distance > sPlayerbotAIConfig->contactDistance) + { + MotionMaster& mm = *vehicleBase->GetMotionMaster(); // need to move vehicle, not bot + mm.Clear(); + mm.MovePoint(mapId, x, y, z, generatePath); + float delay = 1000.0f * (distance / vehicleBase->GetSpeed(MOVE_RUN)) - sPlayerbotAIConfig->reactDelay; + delay = std::max(.0f, delay); + delay = std::min((float)sPlayerbotAIConfig->maxWaitForMove, delay); + AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation(), delay); + // TODO: is botAI->SetNextCheckDelay() meant to go here or is setting "last movement" value enough? (same question goes for below) + return true; + } + } + else if (exact_waypoint || disableMoveSplinePath || !generatePath) { float distance = bot->GetExactDist(x, y, z); if (distance > sPlayerbotAIConfig->contactDistance) From 45ebef049ffce852a71a74e35ca1ce7a4a80dc32 Mon Sep 17 00:00:00 2001 From: Fuzz Date: Tue, 6 Aug 2024 22:21:55 +1000 Subject: [PATCH 3/7] [Battlegrounds] wsg pathing fix for #442 --- src/strategy/actions/BattleGroundTactics.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/strategy/actions/BattleGroundTactics.cpp b/src/strategy/actions/BattleGroundTactics.cpp index 7b28a19d..4b15eeee 100644 --- a/src/strategy/actions/BattleGroundTactics.cpp +++ b/src/strategy/actions/BattleGroundTactics.cpp @@ -2053,13 +2053,13 @@ bool BGTactics::wsgPaths() return true; } - if (bot->GetPositionX() > 1071.f) // move the ramp up a piece + if (bot->GetPositionX() > 1059.f) // move the ramp up a piece { - MoveTo(bg->GetMapId(), 1070.089478f, 1538.054443f, 332.460388f); + MoveTo(bg->GetMapId(), 1057.551f, 1546.271f, 326.864f); return true; } - if (bot->GetPositionX() > 1050.2f) // move the ramp up a piece + if (bot->GetPositionX() > 1051.2f) // move the ramp up a piece { MoveTo(bg->GetMapId(), 1050.089478f, 1538.054443f, 332.460388f); return true; From 27c5d6b19cb187d5e2f7bf568aaaf8a702a41378 Mon Sep 17 00:00:00 2001 From: Fuzz Date: Wed, 7 Aug 2024 23:40:19 +1000 Subject: [PATCH 4/7] [Battlegrounds] fix for #424 - flag carrier not fighting back when enemy has flag too and bot is hiding --- src/strategy/actions/BattleGroundTactics.cpp | 19 +++++---- src/strategy/actions/ChooseTargetActions.cpp | 9 ++--- src/strategy/actions/VehicleActions.cpp | 11 +++--- src/strategy/triggers/PvpTriggers.cpp | 41 +++++++++++++++++--- src/strategy/triggers/PvpTriggers.h | 3 ++ 5 files changed, 59 insertions(+), 24 deletions(-) diff --git a/src/strategy/actions/BattleGroundTactics.cpp b/src/strategy/actions/BattleGroundTactics.cpp index 4b15eeee..e7f90ea9 100644 --- a/src/strategy/actions/BattleGroundTactics.cpp +++ b/src/strategy/actions/BattleGroundTactics.cpp @@ -22,6 +22,7 @@ #include "Event.h" #include "Playerbots.h" #include "PositionValue.h" +#include "PvpTriggers.h" #include "ServerFacade.h" #include "Vehicle.h" @@ -1771,7 +1772,10 @@ std::string const BGTactics::HandleConsoleCommandPrivate(WorldSession* session, Creature* wpCreature = player->SummonCreature(15631, c->GetPositionX(), c->GetPositionY(), c->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 15000u); wpCreature->SetOwnerGUID(player->GetGUID()); - return fmt::format("Showing location of Creature {}", num); + float distance = player->GetDistance(c); + float exactDistance = player->GetExactDist(c); + return fmt::format("Showing Creature {} location={:.3f},{:.3f},{:.3f} distance={} exactDistance={}", + num, c->GetPositionX(), c->GetPositionY(), c->GetPositionZ(), distance, exactDistance); } if (!strncmp(cmd, "showobject=", 11)) @@ -1787,7 +1791,10 @@ std::string const BGTactics::HandleConsoleCommandPrivate(WorldSession* session, Creature* wpCreature = player->SummonCreature(15631, o->GetPositionX(), o->GetPositionY(), o->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 15000u); wpCreature->SetOwnerGUID(player->GetGUID()); - return fmt::format("Showing location of GameObject {}", num); + float distance = player->GetDistance(o); + float exactDistance = player->GetExactDist(o); + return fmt::format("Showing GameObject {} location={:.3f},{:.3f},{:.3f} distance={} exactDistance={}", + num, o->GetPositionX(), o->GetPositionY(), o->GetPositionZ(), distance, exactDistance); } return "usage: showpath(=[num]) / showcreature=[num] / showobject=[num]"; @@ -2266,8 +2273,7 @@ bool BGTactics::Execute(Event event) // NOTE: can't use IsInCombat() when in vehicle as player is stuck in combat forever while in vehicle (ac bug?) bool inCombat = bot->GetVehicle() ? (bool)AI_VALUE(Unit*, "enemy player target") : bot->IsInCombat(); - if (inCombat && !(bot->HasAura(BG_WS_SPELL_WARSONG_FLAG) || bot->HasAura(BG_WS_SPELL_SILVERWING_FLAG) || - bot->HasAura(BG_EY_NETHERSTORM_FLAG_SPELL))) + if (inCombat && !PlayerHasFlag::IsCapturingFlag(bot)) { // bot->GetMotionMaster()->MovementExpired(); return false; @@ -3886,10 +3892,7 @@ bool BGTactics::moveToObjectiveWp(BattleBotPath* const& currentPath, uint32 curr // NOTE: can't use IsInCombat() when in vehicle as player is stuck in combat forever while in vehicle (ac bug?) bool inCombat = bot->GetVehicle() ? (bool)AI_VALUE(Unit*, "enemy player target") : bot->IsInCombat(); - if ((currentPoint == lastPointInPath) || - (inCombat && !(bot->HasAura(BG_WS_SPELL_WARSONG_FLAG) || bot->HasAura(BG_WS_SPELL_SILVERWING_FLAG) || - bot->HasAura(BG_EY_NETHERSTORM_FLAG_SPELL))) || - !bot->IsAlive()) + if (currentPoint == lastPointInPath || (inCombat && !PlayerHasFlag::IsCapturingFlag(bot)) || !bot->IsAlive()) { // Path is over. // std::ostringstream out; diff --git a/src/strategy/actions/ChooseTargetActions.cpp b/src/strategy/actions/ChooseTargetActions.cpp index 54bf0b1c..dddb3627 100644 --- a/src/strategy/actions/ChooseTargetActions.cpp +++ b/src/strategy/actions/ChooseTargetActions.cpp @@ -11,11 +11,11 @@ #include "Playerbots.h" #include "PossibleRpgTargetsValue.h" #include "ServerFacade.h" +#include "PvpTriggers.h" bool AttackEnemyPlayerAction::isUseful() { - // if carry flag, do not start fight - if (bot->HasAura(23333) || bot->HasAura(23335) || bot->HasAura(34976)) + if (PlayerHasFlag::IsCapturingFlag(bot)) return false; return !sPlayerbotAIConfig->IsPvpProhibited(bot->GetZoneId(), bot->GetAreaId()); @@ -25,7 +25,7 @@ bool AttackEnemyFlagCarrierAction::isUseful() { Unit* target = context->GetValue("enemy flag carrier")->Get(); return target && sServerFacade->IsDistanceLessOrEqualThan(sServerFacade->GetDistance2d(bot, target), 75.0f) && - (bot->HasAura(23333) || bot->HasAura(23335) || bot->HasAura(34976)); + PlayerHasFlag::IsCapturingFlag(bot); } bool AttackAnythingAction::isUseful() @@ -124,8 +124,7 @@ bool AttackAnythingAction::isPossible() { return AttackAction::isPossible() && G bool DpsAssistAction::isUseful() { - // if carry flag, do not start fight - if (bot->HasAura(23333) || bot->HasAura(23335) || bot->HasAura(34976)) + if (PlayerHasFlag::IsCapturingFlag(bot)) return false; return true; diff --git a/src/strategy/actions/VehicleActions.cpp b/src/strategy/actions/VehicleActions.cpp index 2fc09cb3..4683ba7a 100644 --- a/src/strategy/actions/VehicleActions.cpp +++ b/src/strategy/actions/VehicleActions.cpp @@ -44,13 +44,12 @@ bool EnterVehicleAction::Execute(Event event) if (vehicleBase->GetVehicleKit()->IsVehicleInUse()) continue; - // if (fabs(bot->GetPositionZ() - vehicleBase->GetPositionZ()) < 20.0f) + float dist = sServerFacade->GetDistance2d(bot, vehicleBase); + if (dist > 40.0f) + continue; - // if (sServerFacade->GetDistance2d(bot, vehicle) > 100.0f) - // continue; - - if (sServerFacade->GetDistance2d(bot, vehicleBase) > INTERACTION_DISTANCE) - return MoveTo(vehicleBase, INTERACTION_DISTANCE - 1.0f); + if (dist > INTERACTION_DISTANCE) + return MoveTo(vehicleBase); bot->EnterVehicle(vehicleBase); diff --git a/src/strategy/triggers/PvpTriggers.cpp b/src/strategy/triggers/PvpTriggers.cpp index 30d47404..b4a3edfb 100644 --- a/src/strategy/triggers/PvpTriggers.cpp +++ b/src/strategy/triggers/PvpTriggers.cpp @@ -117,22 +117,53 @@ bool PlayerIsInBattlegroundWithoutFlag::IsActive() } bool PlayerHasFlag::IsActive() +{ + return IsCapturingFlag(bot); +} + +bool PlayerHasFlag::IsCapturingFlag(Player* bot) { if (bot->InBattleground()) { if (bot->GetBattlegroundTypeId() == BATTLEGROUND_WS) { - BattlegroundWS* bg = (BattlegroundWS*)botAI->GetBot()->GetBattleground(); - if (bot->GetGUID() == bg->GetFlagPickerGUID(TEAM_ALLIANCE) || - bot->GetGUID() == bg->GetFlagPickerGUID(TEAM_HORDE)) + BattlegroundWS* bg = (BattlegroundWS*)bot->GetBattleground(); + // bot is horde and has ally flag + if (bot->GetGUID() == bg->GetFlagPickerGUID(TEAM_ALLIANCE)) { - return true; + if (bg->GetFlagPickerGUID(TEAM_HORDE)) // enemy has flag too + { + if (GameObject* go = bg->GetBGObject(BG_WS_OBJECT_H_FLAG)) + { + // only indicate capturing if signicant distance from own flag + // (otherwise allow bot to defend itself) + return bot->GetDistance(go) > 36.0f; + } + } + return true; // enemy doesnt have flag so we can cap immediately } + // bot is ally and has horde flag + if (bot->GetGUID() == bg->GetFlagPickerGUID(TEAM_HORDE)) + { + if (bg->GetFlagPickerGUID(TEAM_ALLIANCE)) // enemy has flag too + { + if (GameObject* go = bg->GetBGObject(BG_WS_OBJECT_A_FLAG)) + { + // only indicate capturing if signicant distance from own flag + // (otherwise allow bot to defend itself) + return bot->GetDistance(go) > 36.0f; + } + } + return true; // enemy doesnt have flag so we can cap immediately + } + return false; // bot doesn't have flag } if (bot->GetBattlegroundTypeId() == BATTLEGROUND_EY) { - BattlegroundEY* bg = (BattlegroundEY*)botAI->GetBot()->GetBattleground(); + // TODO we should probably add similiar logic as WSG to allow combat + // when bot has flag but no bases are available to take it to + BattlegroundEY* bg = (BattlegroundEY*)bot->GetBattleground(); return bot->GetGUID() == bg->GetFlagPickerGUID(); } diff --git a/src/strategy/triggers/PvpTriggers.h b/src/strategy/triggers/PvpTriggers.h index 7633c654..34019a67 100644 --- a/src/strategy/triggers/PvpTriggers.h +++ b/src/strategy/triggers/PvpTriggers.h @@ -26,12 +26,15 @@ public: bool IsActive() override; }; +// NOTE this trigger is only active when bot is actively returning flag +// (not when hiding in base because enemy has flag too) class PlayerHasFlag : public Trigger { public: PlayerHasFlag(PlayerbotAI* botAI) : Trigger(botAI, "player has flag") {} bool IsActive() override; + static bool IsCapturingFlag(Player* bot); }; class EnemyFlagCarrierNear : public Trigger From 84e6f6ef9df808fc96bf75acd80f146acd0f6bcb Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Thu, 8 Aug 2024 11:59:01 +0800 Subject: [PATCH 5/7] Fix itemQuality for random bots --- src/PlayerbotFactory.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/PlayerbotFactory.cpp b/src/PlayerbotFactory.cpp index 4591471b..84812822 100644 --- a/src/PlayerbotFactory.cpp +++ b/src/PlayerbotFactory.cpp @@ -55,6 +55,15 @@ PlayerbotFactory::PlayerbotFactory(Player* bot, uint32 level, uint32 itemQuality : level(level), itemQuality(itemQuality), gearScoreLimit(gearScoreLimit), bot(bot) { botAI = GET_PLAYERBOT_AI(bot); + if (!this->itemQuality) + { + uint32 gs = sPlayerbotAIConfig->randomGearScoreLimit == 0 + ? 0 + : PlayerbotFactory::CalcMixedGearScore(sPlayerbotAIConfig->randomGearScoreLimit, + sPlayerbotAIConfig->randomGearQualityLimit); + this->itemQuality = sPlayerbotAIConfig->randomGearQualityLimit; + this->gearScoreLimit = gs; + } } void PlayerbotFactory::Init() @@ -149,16 +158,6 @@ void PlayerbotFactory::Init() void PlayerbotFactory::Prepare() { - if (!itemQuality) - { - uint32 gs = sPlayerbotAIConfig->randomGearScoreLimit == 0 - ? 0 - : PlayerbotFactory::CalcMixedGearScore(sPlayerbotAIConfig->randomGearScoreLimit, - sPlayerbotAIConfig->randomGearQualityLimit); - itemQuality = sPlayerbotAIConfig->randomGearQualityLimit; - gearScoreLimit = gs; - } - if (bot->isDead()) bot->ResurrectPlayer(1.0f, false); From f1bfed190c573305e4c4fbf729f2985514e6992e Mon Sep 17 00:00:00 2001 From: Fuzz Date: Thu, 8 Aug 2024 21:18:52 +1000 Subject: [PATCH 6/7] [Battlegrounds] fixed bug I introduced in PR#422 where bots alternate mount/unmount near flag indefinately, also fixed other erroneous uses of sqrt on distances --- src/PlayerbotAI.cpp | 20 +---- src/strategy/actions/AreaTriggerAction.cpp | 4 +- src/strategy/actions/BattleGroundTactics.cpp | 80 ++++++++++--------- .../actions/ChooseRpgTargetAction.cpp | 2 +- src/strategy/actions/MovementActions.cpp | 9 ++- 5 files changed, 56 insertions(+), 59 deletions(-) diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index 0b4db3ef..feb5c6fd 100644 --- a/src/PlayerbotAI.cpp +++ b/src/PlayerbotAI.cpp @@ -2566,7 +2566,7 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, float x, float y, float z, uint8 if (!itemTarget) { - if (sqrt(bot->GetDistance(x, y, z)) > sPlayerbotAIConfig->sightDistance) + if (bot->GetDistance(x, y, z) > sPlayerbotAIConfig->sightDistance) return false; } @@ -3096,21 +3096,9 @@ bool PlayerbotAI::CastVehicleSpell(uint32 spellId, Unit* target) targets.SetDst(dest); targets.SetSpeed(30.0f); - float distanceToDest = sqrt(vehicleBase->GetPosition().GetExactDist(dest)); - float elev = 0.01f; - if (distanceToDest < 25.0f) - elev = 0.04f; - else if (distanceToDest < 55.0f) - elev = 0.22f; - else if (distanceToDest < 85.0f) - elev = 0.42f; - else if (distanceToDest < 95.0f) - elev = 0.70f; - else if (distanceToDest < 110.0f) - elev = 0.88f; - else - elev = 1.0f; - + float dist = vehicleBase->GetPosition().GetExactDist(dest); + // very much an approximation of the real projectile arc + float elev = dist >= 110.0f ? 1.0f : pow(((dist + 10.0f) / 120.0f), 2.0f); targets.SetElevation(elev); } diff --git a/src/strategy/actions/AreaTriggerAction.cpp b/src/strategy/actions/AreaTriggerAction.cpp index 4bd64ede..5937a0f7 100644 --- a/src/strategy/actions/AreaTriggerAction.cpp +++ b/src/strategy/actions/AreaTriggerAction.cpp @@ -34,7 +34,7 @@ bool ReachAreaTriggerAction::Execute(Event event) return true; } - if (bot->GetMapId() != at->map || sqrt(bot->GetDistance(at->x, at->y, at->z)) > sPlayerbotAIConfig->sightDistance) + if (bot->GetMapId() != at->map) { botAI->TellError("I won't follow: too far away"); return true; @@ -42,7 +42,7 @@ bool ReachAreaTriggerAction::Execute(Event event) bot->GetMotionMaster()->MovePoint(at->map, at->x, at->y, at->z); - float distance = sqrt(bot->GetDistance(at->x, at->y, at->z)); + float distance = bot->GetDistance(at->x, at->y, at->z); float delay = 1000.0f * distance / bot->GetSpeed(MOVE_RUN) + sPlayerbotAIConfig->reactDelay; botAI->TellError("Wait for me"); botAI->SetNextCheckDelay(delay); diff --git a/src/strategy/actions/BattleGroundTactics.cpp b/src/strategy/actions/BattleGroundTactics.cpp index e7f90ea9..9ae91524 100644 --- a/src/strategy/actions/BattleGroundTactics.cpp +++ b/src/strategy/actions/BattleGroundTactics.cpp @@ -2617,8 +2617,8 @@ bool BGTactics::selectObjective(bool reset) { if (GameObject* pGO = bg->GetBGObject(AV_HordeAttackObjectives[0].second)) { - float const distance = sqrt(bot->GetDistance(pGO)); - if (distance < 20.0f) + float const distance = bot->GetDistance(pGO); + if (distance < 400.0f) BgObjective = pGO; } } @@ -2638,7 +2638,7 @@ bool BGTactics::selectObjective(bool reset) { if (GameObject* pGO = bg->GetBGObject(objective.second)) { - float const distance = sqrt(bot->GetDistance(pGO)); + float const distance = bot->GetDistance(pGO); if (attackObjectiveDistance > distance) { BgObjective = pGO; @@ -2808,8 +2808,8 @@ bool BGTactics::selectObjective(bool reset) { if (GameObject* pGO = bg->GetBGObject(AV_AllianceAttackObjectives[0].second)) { - float const distance = sqrt(bot->GetDistance(pGO)); - if (distance < 20.0f) + float const distance = bot->GetDistance(pGO); + if (distance < 400.0f) BgObjective = pGO; } } @@ -2829,7 +2829,7 @@ bool BGTactics::selectObjective(bool reset) { if (GameObject* pGO = bg->GetBGObject(objective.second)) { - float const distance = sqrt(bot->GetDistance(pGO)); + float const distance = bot->GetDistance(pGO); if (attackObjectiveDistance > distance) { BgObjective = pGO; @@ -3022,7 +3022,7 @@ bool BGTactics::selectObjective(bool reset) { if (GameObject* pGO = bg->GetBGObject(objective * BG_AB_OBJECTS_PER_NODE)) { - float const distance = sqrt(bot->GetDistance(pGO)); + float const distance = bot->GetDistance(pGO); if (attackObjectiveDistance > distance) { // do not pick if already in list @@ -3071,7 +3071,7 @@ bool BGTactics::selectObjective(bool reset) { if (GameObject* pGO = bg->GetBGObject(objective * BG_AB_OBJECTS_PER_NODE)) { - float const distance = sqrt(bot->GetDistance(pGO)); + float const distance = bot->GetDistance(pGO); if (attackObjectiveDistance > distance) { // do not pick if already in list @@ -3133,14 +3133,15 @@ bool BGTactics::selectObjective(bool reset) uint8 ownership = pointOwner == bot->GetTeamId() ? 2 : pointOwner == TEAM_NEUTRAL ? 1 : 0; if (closestObjectiveOwnership > ownership) continue; - float dist = sqrt(bot->GetDistance(go)); + float dist = bot->GetDistance(go); + + // select objective when ownership is better + // or distance difference is significantly better + // or distance difference is insignificantly better and coinflip + // the reason it doesn't just check if distance is better is to avoid bot going to same point every time if (closestObjectiveOwnership < ownership || - (closestObjectiveDist > dist && - (closestObjectiveDist - dist > 1 || - urand( - 0, - 1)))) // if distance difference is minor (as it will be when they first pick flag up - // from middle) add some randomness so its not going to same point every time + closestObjectiveDist - 30 > dist || + (closestObjectiveDist > dist && urand(0, 1))) { closestObjectiveOwnership = ownership; closestObjectiveDist = dist; @@ -3397,10 +3398,9 @@ bool BGTactics::selectObjective(bool reset) } else // target gate directly at range if other vehicle { - // take a siege position - if (sqrt(bot->GetDistance(IC_GATE_ATTACK_POS_HORDE)) < - 5.0f) // just make bot stay where it is (stops them shifting around to the random - // spots) + // just make bot stay where it is if already close + // (stops them shifting around between the random spots) + if (bot->GetDistance(IC_GATE_ATTACK_POS_HORDE) < 8.0f) pos.Set(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), bot->GetMapId()); else pos.Set(IC_GATE_ATTACK_POS_HORDE.GetPositionX() + frand(-5.0f, +5.0f), @@ -3486,10 +3486,10 @@ bool BGTactics::selectObjective(bool reset) } } if (!BgObjective) // guard vehicles as they seige - { - if (sqrt(bot->GetDistance(IC_GATE_ATTACK_POS_HORDE)) < - 5.0f) // just make bot stay where it is (stops them shifting around to the random spots) + // just make bot stay where it is if already close + // (stops them shifting around between the random spots) + if (bot->GetDistance(IC_GATE_ATTACK_POS_HORDE) < 8.0f) pos.Set(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), bot->GetMapId()); else pos.Set(IC_GATE_ATTACK_POS_HORDE.GetPositionX() + frand(-5.0f, +5.0f), @@ -3550,10 +3550,9 @@ bool BGTactics::selectObjective(bool reset) } else // target gate directly at range if other vehicle { - // take a siege position - if (sqrt(bot->GetDistance(IC_GATE_ATTACK_POS_ALLIANCE)) < - 5.0f) // just make bot stay where it is (stops them shifting around to the random - // spots) + // just make bot stay where it is if already close + // (stops them shifting around between the random spots) + if (bot->GetDistance(IC_GATE_ATTACK_POS_ALLIANCE) < 8.0f) pos.Set(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), bot->GetMapId()); else pos.Set(IC_GATE_ATTACK_POS_ALLIANCE.GetPositionX() + frand(-5.0f, +5.0f), @@ -3640,8 +3639,9 @@ bool BGTactics::selectObjective(bool reset) } if (!BgObjective) // guard vehicles as they seige { - if (sqrt(bot->GetDistance(IC_GATE_ATTACK_POS_ALLIANCE)) < - 5.0f) // just make bot stay where it is (stops them shifting around to the random spots) + // just make bot stay where it is if already close + // (stops them shifting around between the random spots) + if (bot->GetDistance(IC_GATE_ATTACK_POS_ALLIANCE) < 8.0f) pos.Set(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), bot->GetMapId()); else pos.Set(IC_GATE_ATTACK_POS_ALLIANCE.GetPositionX() + frand(-5.0f, +5.0f), @@ -3700,7 +3700,7 @@ bool BGTactics::moveToObjective() } // don't try to move if already close - if (sqrt(bot->GetDistance(pos.x, pos.y, pos.z)) < 2.0f) + if (bot->GetDistance(pos.x, pos.y, pos.z) < 4.0f) { resetObjective(); @@ -3714,9 +3714,8 @@ bool BGTactics::moveToObjective() if (bgType == BATTLEGROUND_WS) return MoveTo(bot->GetMapId(), pos.x, pos.y, pos.z); else - return MoveNear(bot->GetMapId(), pos.x, pos.y, pos.z, - 1.5f); // note - don't make distance too large or horde bots may struggle to get flags in - // alliance AV towers (because they'll be targetting a spot in midair) + // 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); } return false; } @@ -3745,7 +3744,7 @@ bool BGTactics::selectObjectiveWp(std::vector const& vPaths) // get bots out of cave when they respawn there (otherwise path selection happens while they're deep within cave // and the results arent good) Position const caveSpawn = bot->GetTeamId() == TEAM_ALLIANCE ? AV_CAVE_SPAWN_ALLIANCE : AV_CAVE_SPAWN_HORDE; - if (sqrt(bot->GetDistance(caveSpawn)) < 4.0f) + if (bot->GetDistance(caveSpawn) < 16.0f) { return moveToStart(true); } @@ -3793,6 +3792,12 @@ bool BGTactics::selectObjectiveWp(std::vector const& vPaths) std::find(vPaths_HordeMine.begin(), vPaths_HordeMine.end(), path) != vPaths_HordeMine.end()) continue; + // TODO need to remove sqrt from these two and distToBot but it totally throws path scoring out of + // whack if you do that without changing how its implemented (I'm amazed it works as well as it does + // using sqrt'ed distances) + // In a reworked version maybe compare the differences of path distances to point (ie: against best path) + // or maybe ratio's (where if a path end is twice the difference in distance from destination we basically + // use that to multiply the total score? BattleBotWaypoint& startPoint = ((*path)[0]); float const startPointDistToDestination = sqrt(Position(pos.x, pos.y, pos.z, 0.f).GetExactDist(startPoint.x, startPoint.y, startPoint.z)); @@ -3958,6 +3963,7 @@ bool BGTactics::startNewPathBegin(std::vector const& vPaths) std::find(vPaths_HordeMine.begin(), vPaths_HordeMine.end(), pPath) != vPaths_HordeMine.end()) continue; + // TODO remove sqrt BattleBotWaypoint* pStart = &((*pPath)[0]); if (sqrt(bot->GetDistance(pStart->x, pStart->y, pStart->z)) < INTERACTION_DISTANCE) availablePaths.emplace_back(AvailablePath(pPath, false)); @@ -3967,6 +3973,7 @@ bool BGTactics::startNewPathBegin(std::vector const& vPaths) vPaths_NoReverseAllowed.end()) continue; + // TODO remove sqrt BattleBotWaypoint* pEnd = &((*pPath)[(*pPath).size() - 1]); if (sqrt(bot->GetDistance(pEnd->x, pEnd->y, pEnd->z)) < INTERACTION_DISTANCE) availablePaths.emplace_back(AvailablePath(pPath, true)); @@ -4016,6 +4023,7 @@ bool BGTactics::startNewPathFree(std::vector const& vPaths) for (uint32 i = 0; i < pPath->size(); i++) { BattleBotWaypoint& waypoint = ((*pPath)[i]); + // TODO remove sqrt float const distanceToPoint = sqrt(bot->GetDistance(waypoint.x, waypoint.y, waypoint.z)); if (distanceToPoint < closestDistance) { @@ -4048,7 +4056,7 @@ bool BGTactics::atFlag(std::vector const& vPaths, std::vector const& vPaths, std::vectorCanUseBattlegroundObject(go) && bgType != BATTLEGROUND_WS) continue; - float const dist = sqrt(bot->GetDistance(go)); + float const dist = bot->GetDistance(go); if (flagRange && dist > flagRange) continue; @@ -4422,7 +4430,7 @@ bool BGTactics::IsLockedInsideKeep() // ALLIANCE if (bot->GetTeamId() == TEAM_ALLIANCE) { - if (GameObject* go = bg->GetBGObject(BG_IC_GO_DOODAD_PORTCULLISACTIVE01)) + if (GameObject* go = bg->GetBGObject(BG_IC_GO_DOODAD_PORTCULLISACTIVE02)) { if (go->isSpawned()) { diff --git a/src/strategy/actions/ChooseRpgTargetAction.cpp b/src/strategy/actions/ChooseRpgTargetAction.cpp index e0890c98..8d6594d3 100644 --- a/src/strategy/actions/ChooseRpgTargetAction.cpp +++ b/src/strategy/actions/ChooseRpgTargetAction.cpp @@ -294,7 +294,7 @@ bool ChooseRpgTargetAction::isFollowValid(Player* bot, WorldPosition pos) if (!botAI->HasStrategy("follow", BOT_STATE_NON_COMBAT)) return true; - if (sqrt(bot->GetDistance(master)) > sPlayerbotAIConfig->rpgDistance * 2) + if (bot->GetDistance(master) > sPlayerbotAIConfig->rpgDistance * 2) return false; Formation* formation = AI_VALUE(Formation*, "formation"); diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index 98018f6d..149773a7 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -66,7 +66,6 @@ void MovementAction::JumpTo(uint32 mapId, float x, float y, float z) float botZ = bot->GetPositionZ(); float speed = bot->GetSpeed(MOVE_RUN); MotionMaster& mm = *bot->GetMotionMaster(); - botAI->SetNextCheckDelay(1000); mm.Clear(); mm.MoveJump(x, y, z, speed, speed, 1); AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation(), 1000); @@ -141,7 +140,7 @@ bool MovementAction::MoveToLOS(WorldObject* target, bool ranged) if (botAI->HasStrategy("debug move", BOT_STATE_NON_COMBAT)) CreateWp(bot, point.x, point.y, point.z, 0.0, 2334); - float distPoint = sqrt(target->GetDistance(point.x, point.y, point.z)); + float distPoint = target->GetDistance(point.x, point.y, point.z); if (distPoint < dist && target->IsWithinLOS(point.x, point.y, point.z + bot->GetCollisionHeight())) { dist = distPoint; @@ -208,7 +207,6 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, delay = std::max(.0f, delay); delay = std::min((float)sPlayerbotAIConfig->maxWaitForMove, delay); AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation(), delay); - // TODO: is botAI->SetNextCheckDelay() meant to go here or is setting "last movement" value enough? (same question goes for below) return true; } } @@ -883,7 +881,10 @@ bool MovementAction::IsMovingAllowed(Unit* target) bool MovementAction::IsMovingAllowed(uint32 mapId, float x, float y, float z) { - float distance = sqrt(bot->GetDistance(x, y, z)); + // removed sqrt as means distance limit was effectively 22500 (ReactDistance²) + // leaving it commented incase we find ReactDistance limit causes problems + // float distance = sqrt(bot->GetDistance(x, y, z)); + float distance = bot->GetDistance(x, y, z); if (!bot->InBattleground() && distance > sPlayerbotAIConfig->reactDistance) return false; From e88a93d65e9be0cda925fd90d7dfac7a6361a1ed Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Wed, 7 Aug 2024 17:45:21 +0800 Subject: [PATCH 7/7] Handle command and trade check for summoned bot --- src/PlayerbotAI.cpp | 6 +--- src/PlayerbotSecurity.cpp | 33 +++++++++++----------- src/RandomPlayerbotMgr.cpp | 3 -- src/strategy/actions/TradeStatusAction.cpp | 10 +++++-- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index 0b4db3ef..34fba5ed 100644 --- a/src/PlayerbotAI.cpp +++ b/src/PlayerbotAI.cpp @@ -655,11 +655,7 @@ void PlayerbotAI::HandleCommand(uint32 type, std::string const text, Player* fro } if (!IsAllowedCommand(filtered) && - (master != fromPlayer || - !GetSecurity()->CheckLevelFor(PLAYERBOT_SECURITY_ALLOW_ALL, type != CHAT_MSG_WHISPER, fromPlayer))) - return; - - if (!IsAllowedCommand(filtered) && master != fromPlayer) + (!GetSecurity()->CheckLevelFor(PLAYERBOT_SECURITY_ALLOW_ALL, type != CHAT_MSG_WHISPER, fromPlayer))) return; if (type == CHAT_MSG_RAID_WARNING && filtered.find(bot->GetName()) != std::string::npos && diff --git a/src/PlayerbotSecurity.cpp b/src/PlayerbotSecurity.cpp index e7241004..0a045cdb 100644 --- a/src/PlayerbotSecurity.cpp +++ b/src/PlayerbotSecurity.cpp @@ -55,14 +55,16 @@ PlayerbotSecurityLevel PlayerbotSecurity::LevelFor(Player* from, DenyReason* rea // } Group* group = from->GetGroup(); - if (group) + if (group && group == bot->GetGroup() && !ignoreGroup && botAI->GetMaster() == from) { - for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next()) - { - Player* player = gref->GetSource(); - if (player == bot && !ignoreGroup) - return PLAYERBOT_SECURITY_ALLOW_ALL; - } + return PLAYERBOT_SECURITY_ALLOW_ALL; + } + + if (group && group == bot->GetGroup() && !ignoreGroup && botAI->GetMaster() != from) + { + if (reason) + *reason = PLAYERBOT_DENY_NOT_YOURS; + return PLAYERBOT_SECURITY_TALK; } if (sPlayerbotAIConfig->groupInvitationPermission <= 0) @@ -137,13 +139,6 @@ PlayerbotSecurityLevel PlayerbotSecurity::LevelFor(Player* from, DenyReason* rea return PLAYERBOT_SECURITY_INVITE; } - for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next()) - { - Player* player = gref->GetSource(); - if (player == from) - return PLAYERBOT_SECURITY_ALLOW_ALL; - } - if (group->IsFull()) { if (reason) @@ -169,11 +164,17 @@ PlayerbotSecurityLevel PlayerbotSecurity::LevelFor(Player* from, DenyReason* rea if (reason) *reason = PLAYERBOT_DENY_INVITE; - + return PLAYERBOT_SECURITY_INVITE; } - return PLAYERBOT_SECURITY_ALLOW_ALL; + if (botAI->GetMaster() == from) + return PLAYERBOT_SECURITY_ALLOW_ALL; + + if (reason) + *reason = PLAYERBOT_DENY_NOT_YOURS; + + return PLAYERBOT_SECURITY_INVITE; } bool PlayerbotSecurity::CheckLevelFor(PlayerbotSecurityLevel level, bool silent, Player* from, bool ignoreGroup) diff --git a/src/RandomPlayerbotMgr.cpp b/src/RandomPlayerbotMgr.cpp index 2655052c..29bc672d 100644 --- a/src/RandomPlayerbotMgr.cpp +++ b/src/RandomPlayerbotMgr.cpp @@ -1215,9 +1215,6 @@ void RandomPlayerbotMgr::Revive(Player* player) void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector& locs, bool hearth) { - if (bot->IsBeingTeleported()) - return; - if (bot->InBattleground()) return; diff --git a/src/strategy/actions/TradeStatusAction.cpp b/src/strategy/actions/TradeStatusAction.cpp index b1284a80..4076277c 100644 --- a/src/strategy/actions/TradeStatusAction.cpp +++ b/src/strategy/actions/TradeStatusAction.cpp @@ -10,8 +10,10 @@ #include "GuildTaskMgr.h" #include "ItemUsageValue.h" #include "ItemVisitors.h" +#include "PlayerbotMgr.h" #include "PlayerbotSecurity.h" #include "Playerbots.h" +#include "RandomPlayerbotMgr.h" #include "SetCraftAction.h" bool TradeStatusAction::Execute(Event event) @@ -180,8 +182,12 @@ bool TradeStatusAction::CheckTrade() } return isGettingItem; } - - if (!sRandomPlayerbotMgr->IsRandomBot(bot)) + if (!bot->GetSession()) + { + return false; + } + uint32 accountId = bot->GetSession()->GetAccountId(); + if (!sPlayerbotAIConfig->IsInRandomAccountList(accountId)) { int32 botItemsMoney = CalculateCost(bot, true); int32 botMoney = bot->GetTradeData()->GetMoney() + botItemsMoney;