From b0c0002206c0d7f4f1c5c94799215d6db104924e Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Sat, 3 Aug 2024 11:52:02 +0800 Subject: [PATCH 01/14] Make better move point for follow and reach combat --- src/strategy/actions/MovementActions.cpp | 17 +++++- src/strategy/values/Arrow.cpp | 3 +- src/strategy/values/Formations.cpp | 76 +++++++++++++----------- 3 files changed, 57 insertions(+), 39 deletions(-) diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index 670735e4..de4cc750 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -789,15 +789,28 @@ bool MovementAction::ReachCombatTo(Unit* target, float distance) float dx = cos(angle) * needToGo + bx; float dy = sin(angle) * needToGo + by; - float dz; // = std::max(bz, tz); // calc accurate z position to avoid stuck - if (distanceToTarget > CONTACT_DISTANCE) + float dz; // = std::max(bz, tz); // calc accurate z position to avoid stuck + + if (target->HasUnitMovementFlag(MOVEMENTFLAG_FORWARD)) // target is moving forward, predict the position { + float timeToGo = MoveDelay(abs(needToGo)); + float targetMoveDist = timeToGo * target->GetSpeed(MOVE_RUN); + targetMoveDist = std::min(5.0f, targetMoveDist); + dx += targetMoveDist * cos(target->GetOrientation()); + dy += targetMoveDist * sin(target->GetOrientation()); + } + + if (distanceToTarget > CONTACT_DISTANCE) { dz = bz + (tz - bz) * (needToGo / distanceToTarget); } else { dz = tz; } + + if (!bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), dx, dy, dz)) + return false; + return MoveTo(target->GetMapId(), dx, dy, dz); } diff --git a/src/strategy/values/Arrow.cpp b/src/strategy/values/Arrow.cpp index adcfcde4..ff52c81d 100644 --- a/src/strategy/values/Arrow.cpp +++ b/src/strategy/values/Arrow.cpp @@ -48,8 +48,7 @@ WorldLocation ArrowFormation::GetLocationInternal() float y = master->GetPositionY() - masterUnit->GetY() + botUnit->GetY(); float z = master->GetPositionZ(); - float ground = master->GetMapHeight(x, y, z + 30.0f); - if (ground <= INVALID_HEIGHT) + if (!master->GetMap()->CheckCollisionAndGetValidCoords(master, master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(), x, y, z)) return Formation::NullLocation; // master->UpdateGroundPositionZ(x, y, z); return WorldLocation(master->GetMapId(), x, y, z); diff --git a/src/strategy/values/Formations.cpp b/src/strategy/values/Formations.cpp index 7036609f..be1d53c7 100644 --- a/src/strategy/values/Formations.cpp +++ b/src/strategy/values/Formations.cpp @@ -83,19 +83,15 @@ public: if (!master) return WorldLocation(); - float range = sPlayerbotAIConfig->followDistance; - float angle = GetFollowAngle(); - float x = master->GetPositionX() + cos(angle) * range; - float y = master->GetPositionY() + sin(angle) * range; - float z = master->GetPositionZ(); - - float ground = master->GetMapHeight(x, y, z + 30.0f); - if (ground <= INVALID_HEIGHT) - return Formation::NullLocation; - - // z += CONTACT_DISTANCE; - // bot->UpdateAllowedPositionZ(x, y, z); - return WorldLocation(master->GetMapId(), x, y, z); + float range = sPlayerbotAIConfig->followDistance; + float angle = GetFollowAngle(); + float x = master->GetPositionX() + cos(angle) * range; + float y = master->GetPositionY() + sin(angle) * range; + float z = master->GetPositionZ(); + + if (!master->GetMap()->CheckCollisionAndGetValidCoords(master, master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(), x, y, z)) + return Formation::NullLocation; + return WorldLocation(master->GetMapId(), x, y, z); } float GetMaxDistance() override { return sPlayerbotAIConfig->followDistance; } @@ -118,21 +114,36 @@ public: time_t now = time(nullptr); if (!lastChangeTime || now - lastChangeTime >= 3) { - lastChangeTime = now; - dx = (urand(0, 10) / 10.0 - 0.5) * sPlayerbotAIConfig->tooCloseDistance; - dy = (urand(0, 10) / 10.0 - 0.5) * sPlayerbotAIConfig->tooCloseDistance; - dr = sqrt(dx * dx + dy * dy); + Player* master = botAI->GetGroupMaster(); + if (!master) + return WorldLocation(); + + float range = sPlayerbotAIConfig->followDistance; + float angle = GetFollowAngle(); + + time_t now = time(nullptr); + if (!lastChangeTime || now - lastChangeTime >= 3) + { + lastChangeTime = now; + dx = (urand(0, 10) / 10.0 - 0.5) * sPlayerbotAIConfig->tooCloseDistance; + dy = (urand(0, 10) / 10.0 - 0.5) * sPlayerbotAIConfig->tooCloseDistance; + dr = sqrt(dx*dx + dy*dy); + } + + float x = master->GetPositionX() + cos(angle) * range + dx; + float y = master->GetPositionY() + sin(angle) * range + dy; + float z = master->GetPositionZ(); + if (!master->GetMap()->CheckCollisionAndGetValidCoords(master, master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(), x, y, z)) + return Formation::NullLocation; + // bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), x, y, z); + return WorldLocation(master->GetMapId(), x, y, z); } float x = master->GetPositionX() + cos(angle) * range + dx; float y = master->GetPositionY() + sin(angle) * range + dy; float z = master->GetPositionZ(); - float ground = master->GetMapHeight(x, y, z + 30.0f); - if (ground <= INVALID_HEIGHT) + if (!master->GetMap()->CheckCollisionAndGetValidCoords(master, master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(), x, y, z)) return Formation::NullLocation; - - z += CONTACT_DISTANCE; - bot->UpdateAllowedPositionZ(x, y, z); return WorldLocation(master->GetMapId(), x, y, z); } @@ -184,13 +195,9 @@ public: float x = target->GetPositionX() + cos(angle) * range; float y = target->GetPositionY() + sin(angle) * range; float z = target->GetPositionZ(); - float ground = target->GetMapHeight(x, y, z + 30.0f); - if (ground <= INVALID_HEIGHT) + if (!master->GetMap()->CheckCollisionAndGetValidCoords(master, master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(), x, y, z)) return Formation::NullLocation; - z += CONTACT_DISTANCE; - bot->UpdateAllowedPositionZ(x, y, z); - return WorldLocation(bot->GetMapId(), x, y, z); } }; @@ -350,16 +357,16 @@ public: if (minDist) { - z += CONTACT_DISTANCE; - bot->UpdateAllowedPositionZ(minX, minY, z); + if (!master->GetMap()->CheckCollisionAndGetValidCoords(master, master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(), x, y, z)) + return Formation::NullLocation; return WorldLocation(bot->GetMapId(), minX, minY, z); } return Formation::NullLocation; } - z += CONTACT_DISTANCE; - bot->UpdateAllowedPositionZ(x, y, z); + if (!master->GetMap()->CheckCollisionAndGetValidCoords(master, master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(), x, y, z)) + return Formation::NullLocation; return WorldLocation(bot->GetMapId(), x, y, z); } }; @@ -618,12 +625,11 @@ WorldLocation MoveFormation::MoveSingleLine(std::vector line, float dif float lx = x + cos(angle) * radius; float ly = y + sin(angle) * radius; float lz = cz; - float ground = bot->GetMapHeight(lx, ly, lz + 30.0f); - if (ground <= INVALID_HEIGHT) + + Player* master = botAI->GetMaster(); + if (!master->GetMap()->CheckCollisionAndGetValidCoords(master, master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(), lx, ly, lz)) return Formation::NullLocation; - lz += CONTACT_DISTANCE; - bot->UpdateAllowedPositionZ(lx, ly, lz); return WorldLocation(bot->GetMapId(), lx, ly, lz); } From d33c565e31aac67bee157fdfebf78c99df8f14ed Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Sat, 3 Aug 2024 12:42:20 +0800 Subject: [PATCH 02/14] Check mount state --- src/strategy/actions/CheckMountStateAction.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/strategy/actions/CheckMountStateAction.cpp b/src/strategy/actions/CheckMountStateAction.cpp index 17660836..01b8d342 100644 --- a/src/strategy/actions/CheckMountStateAction.cpp +++ b/src/strategy/actions/CheckMountStateAction.cpp @@ -18,12 +18,11 @@ bool CheckMountStateAction::Execute(Event event) AI_VALUE2(bool, "combat", "self target") ? (AI_VALUE(uint8, "attacker count") > 0 ? false : true) : true; bool enemy = AI_VALUE(Unit*, "enemy player target"); // ignore grind target in BG or bots will dismount near any creature (eg: the rams in AV) - bool dps = (AI_VALUE(Unit*, "dps target") || (!bot->InBattleground() && AI_VALUE(Unit*, "grind target"))); - bool fartarget = - (enemy && sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", "enemy player target"), 40.0f)) || + bool dps = AI_VALUE(Unit*, "dps target"); + bool fartarget = (enemy && sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", "enemy player target"), 40.0f)) || (dps && sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", "dps target"), 50.0f)); bool attackdistance = false; - bool chasedistance = false; + // bool chasedistance = false; float attack_distance = 35.0f; if (PlayerbotAI::IsMelee(bot)) { @@ -38,11 +37,9 @@ bool CheckMountStateAction::Execute(Event event) if (dps || enemy) { - attackdistance = (enemy || dps) && sServerFacade->IsDistanceLessThan( - AI_VALUE2(float, "distance", "current target"), attack_distance); - chasedistance = - enemy && sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", "enemy player target"), 45.0f) && - AI_VALUE2(bool, "moving", "enemy player target"); + Unit* currentTarget = AI_VALUE(Unit*, "current target"); + attackdistance = (enemy || dps) && currentTarget && sServerFacade->IsDistanceLessThan(AI_VALUE2(float, "distance", "current target"), attack_distance); + // chasedistance = enemy && sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", "enemy player target"), 45.0f) && AI_VALUE2(bool, "moving", "enemy player target"); } if (bot->IsMounted() && attackdistance) From fe94083a3f4c6377eaba554e66cb5503a58422ec Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Sun, 4 Aug 2024 23:35:55 +0800 Subject: [PATCH 03/14] Dismount distance check --- src/strategy/actions/CheckMountStateAction.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/strategy/actions/CheckMountStateAction.cpp b/src/strategy/actions/CheckMountStateAction.cpp index 01b8d342..1e560e5d 100644 --- a/src/strategy/actions/CheckMountStateAction.cpp +++ b/src/strategy/actions/CheckMountStateAction.cpp @@ -24,22 +24,16 @@ bool CheckMountStateAction::Execute(Event event) bool attackdistance = false; // bool chasedistance = false; float attack_distance = 35.0f; - if (PlayerbotAI::IsMelee(bot)) - { - attack_distance = 10.0f; + if (PlayerbotAI::IsMelee(bot)) { + attack_distance = 5.0f; + } else { + attack_distance = 30.0f; } - else - { - attack_distance = 40.0f; - } - if (enemy) - attack_distance /= 2; if (dps || enemy) { Unit* currentTarget = AI_VALUE(Unit*, "current target"); attackdistance = (enemy || dps) && currentTarget && sServerFacade->IsDistanceLessThan(AI_VALUE2(float, "distance", "current target"), attack_distance); - // chasedistance = enemy && sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", "enemy player target"), 45.0f) && AI_VALUE2(bool, "moving", "enemy player target"); } if (bot->IsMounted() && attackdistance) From de37cfd5aa58146fd7beb118faf1ed41813115ba Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Sun, 4 Aug 2024 23:44:24 +0800 Subject: [PATCH 04/14] Code style --- .../actions/CheckMountStateAction.cpp | 14 ++++-- src/strategy/actions/MovementActions.cpp | 12 ++--- src/strategy/values/Arrow.cpp | 3 +- src/strategy/values/Formations.cpp | 44 +++++++++++-------- 4 files changed, 45 insertions(+), 28 deletions(-) diff --git a/src/strategy/actions/CheckMountStateAction.cpp b/src/strategy/actions/CheckMountStateAction.cpp index 1e560e5d..12909414 100644 --- a/src/strategy/actions/CheckMountStateAction.cpp +++ b/src/strategy/actions/CheckMountStateAction.cpp @@ -19,21 +19,27 @@ bool CheckMountStateAction::Execute(Event event) bool enemy = AI_VALUE(Unit*, "enemy player target"); // ignore grind target in BG or bots will dismount near any creature (eg: the rams in AV) bool dps = AI_VALUE(Unit*, "dps target"); - bool fartarget = (enemy && sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", "enemy player target"), 40.0f)) || + bool fartarget = + (enemy && sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", "enemy player target"), 40.0f)) || (dps && sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", "dps target"), 50.0f)); bool attackdistance = false; // bool chasedistance = false; float attack_distance = 35.0f; - if (PlayerbotAI::IsMelee(bot)) { + if (PlayerbotAI::IsMelee(bot)) + { attack_distance = 5.0f; - } else { + } + else + { attack_distance = 30.0f; } if (dps || enemy) { Unit* currentTarget = AI_VALUE(Unit*, "current target"); - attackdistance = (enemy || dps) && currentTarget && sServerFacade->IsDistanceLessThan(AI_VALUE2(float, "distance", "current target"), attack_distance); + attackdistance = + (enemy || dps) && currentTarget && + sServerFacade->IsDistanceLessThan(AI_VALUE2(float, "distance", "current target"), attack_distance); } if (bot->IsMounted() && attackdistance) diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index de4cc750..f6be6af8 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -789,9 +789,9 @@ bool MovementAction::ReachCombatTo(Unit* target, float distance) float dx = cos(angle) * needToGo + bx; float dy = sin(angle) * needToGo + by; - float dz; // = std::max(bz, tz); // calc accurate z position to avoid stuck + float dz; // = std::max(bz, tz); // calc accurate z position to avoid stuck - if (target->HasUnitMovementFlag(MOVEMENTFLAG_FORWARD)) // target is moving forward, predict the position + if (target->HasUnitMovementFlag(MOVEMENTFLAG_FORWARD)) // target is moving forward, predict the position { float timeToGo = MoveDelay(abs(needToGo)); float targetMoveDist = timeToGo * target->GetSpeed(MOVE_RUN); @@ -799,8 +799,9 @@ bool MovementAction::ReachCombatTo(Unit* target, float distance) dx += targetMoveDist * cos(target->GetOrientation()); dy += targetMoveDist * sin(target->GetOrientation()); } - - if (distanceToTarget > CONTACT_DISTANCE) { + + if (distanceToTarget > CONTACT_DISTANCE) + { dz = bz + (tz - bz) * (needToGo / distanceToTarget); } else @@ -808,7 +809,8 @@ bool MovementAction::ReachCombatTo(Unit* target, float distance) dz = tz; } - if (!bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), dx, dy, dz)) + if (!bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(), + bot->GetPositionZ(), dx, dy, dz)) return false; return MoveTo(target->GetMapId(), dx, dy, dz); diff --git a/src/strategy/values/Arrow.cpp b/src/strategy/values/Arrow.cpp index ff52c81d..a981eade 100644 --- a/src/strategy/values/Arrow.cpp +++ b/src/strategy/values/Arrow.cpp @@ -48,7 +48,8 @@ WorldLocation ArrowFormation::GetLocationInternal() float y = master->GetPositionY() - masterUnit->GetY() + botUnit->GetY(); float z = master->GetPositionZ(); - if (!master->GetMap()->CheckCollisionAndGetValidCoords(master, master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(), x, y, z)) + if (!master->GetMap()->CheckCollisionAndGetValidCoords(master, master->GetPositionX(), master->GetPositionY(), + master->GetPositionZ(), x, y, z)) return Formation::NullLocation; // master->UpdateGroundPositionZ(x, y, z); return WorldLocation(master->GetMapId(), x, y, z); diff --git a/src/strategy/values/Formations.cpp b/src/strategy/values/Formations.cpp index be1d53c7..9418b441 100644 --- a/src/strategy/values/Formations.cpp +++ b/src/strategy/values/Formations.cpp @@ -83,15 +83,16 @@ public: if (!master) return WorldLocation(); - float range = sPlayerbotAIConfig->followDistance; - float angle = GetFollowAngle(); - float x = master->GetPositionX() + cos(angle) * range; - float y = master->GetPositionY() + sin(angle) * range; - float z = master->GetPositionZ(); - - if (!master->GetMap()->CheckCollisionAndGetValidCoords(master, master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(), x, y, z)) - return Formation::NullLocation; - return WorldLocation(master->GetMapId(), x, y, z); + float range = sPlayerbotAIConfig->followDistance; + float angle = GetFollowAngle(); + float x = master->GetPositionX() + cos(angle) * range; + float y = master->GetPositionY() + sin(angle) * range; + float z = master->GetPositionZ(); + + if (!master->GetMap()->CheckCollisionAndGetValidCoords(master, master->GetPositionX(), master->GetPositionY(), + master->GetPositionZ(), x, y, z)) + return Formation::NullLocation; + return WorldLocation(master->GetMapId(), x, y, z); } float GetMaxDistance() override { return sPlayerbotAIConfig->followDistance; } @@ -119,7 +120,7 @@ public: return WorldLocation(); float range = sPlayerbotAIConfig->followDistance; - float angle = GetFollowAngle(); + float angle = GetFollowAngle(); time_t now = time(nullptr); if (!lastChangeTime || now - lastChangeTime >= 3) @@ -127,22 +128,25 @@ public: lastChangeTime = now; dx = (urand(0, 10) / 10.0 - 0.5) * sPlayerbotAIConfig->tooCloseDistance; dy = (urand(0, 10) / 10.0 - 0.5) * sPlayerbotAIConfig->tooCloseDistance; - dr = sqrt(dx*dx + dy*dy); + dr = sqrt(dx * dx + dy * dy); } float x = master->GetPositionX() + cos(angle) * range + dx; float y = master->GetPositionY() + sin(angle) * range + dy; float z = master->GetPositionZ(); - if (!master->GetMap()->CheckCollisionAndGetValidCoords(master, master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(), x, y, z)) + if (!master->GetMap()->CheckCollisionAndGetValidCoords( + master, master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(), x, y, z)) return Formation::NullLocation; - // bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), x, y, z); + // bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(), + // bot->GetPositionZ(), x, y, z); return WorldLocation(master->GetMapId(), x, y, z); } float x = master->GetPositionX() + cos(angle) * range + dx; float y = master->GetPositionY() + sin(angle) * range + dy; float z = master->GetPositionZ(); - if (!master->GetMap()->CheckCollisionAndGetValidCoords(master, master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(), x, y, z)) + if (!master->GetMap()->CheckCollisionAndGetValidCoords(master, master->GetPositionX(), master->GetPositionY(), + master->GetPositionZ(), x, y, z)) return Formation::NullLocation; return WorldLocation(master->GetMapId(), x, y, z); } @@ -195,7 +199,8 @@ public: float x = target->GetPositionX() + cos(angle) * range; float y = target->GetPositionY() + sin(angle) * range; float z = target->GetPositionZ(); - if (!master->GetMap()->CheckCollisionAndGetValidCoords(master, master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(), x, y, z)) + if (!master->GetMap()->CheckCollisionAndGetValidCoords(master, master->GetPositionX(), master->GetPositionY(), + master->GetPositionZ(), x, y, z)) return Formation::NullLocation; return WorldLocation(bot->GetMapId(), x, y, z); @@ -357,7 +362,8 @@ public: if (minDist) { - if (!master->GetMap()->CheckCollisionAndGetValidCoords(master, master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(), x, y, z)) + if (!master->GetMap()->CheckCollisionAndGetValidCoords( + master, master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(), x, y, z)) return Formation::NullLocation; return WorldLocation(bot->GetMapId(), minX, minY, z); } @@ -365,7 +371,8 @@ public: return Formation::NullLocation; } - if (!master->GetMap()->CheckCollisionAndGetValidCoords(master, master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(), x, y, z)) + if (!master->GetMap()->CheckCollisionAndGetValidCoords(master, master->GetPositionX(), master->GetPositionY(), + master->GetPositionZ(), x, y, z)) return Formation::NullLocation; return WorldLocation(bot->GetMapId(), x, y, z); } @@ -627,7 +634,8 @@ WorldLocation MoveFormation::MoveSingleLine(std::vector line, float dif float lz = cz; Player* master = botAI->GetMaster(); - if (!master->GetMap()->CheckCollisionAndGetValidCoords(master, master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(), lx, ly, lz)) + if (!master->GetMap()->CheckCollisionAndGetValidCoords( + master, master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(), lx, ly, lz)) return Formation::NullLocation; return WorldLocation(bot->GetMapId(), lx, ly, lz); From e35fc087e17be89bb6afd3357c06fbbaf3123ae1 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Mon, 5 Aug 2024 00:40:34 +0800 Subject: [PATCH 05/14] Revert reach combat to --- src/strategy/actions/MovementActions.cpp | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index f6be6af8..670735e4 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -790,16 +790,6 @@ bool MovementAction::ReachCombatTo(Unit* target, float distance) float dx = cos(angle) * needToGo + bx; float dy = sin(angle) * needToGo + by; float dz; // = std::max(bz, tz); // calc accurate z position to avoid stuck - - if (target->HasUnitMovementFlag(MOVEMENTFLAG_FORWARD)) // target is moving forward, predict the position - { - float timeToGo = MoveDelay(abs(needToGo)); - float targetMoveDist = timeToGo * target->GetSpeed(MOVE_RUN); - targetMoveDist = std::min(5.0f, targetMoveDist); - dx += targetMoveDist * cos(target->GetOrientation()); - dy += targetMoveDist * sin(target->GetOrientation()); - } - if (distanceToTarget > CONTACT_DISTANCE) { dz = bz + (tz - bz) * (needToGo / distanceToTarget); @@ -808,11 +798,6 @@ bool MovementAction::ReachCombatTo(Unit* target, float distance) { dz = tz; } - - if (!bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(), - bot->GetPositionZ(), dx, dy, dz)) - return false; - return MoveTo(target->GetMapId(), dx, dy, dz); } From 1a92743dfdd59d46b5a59b4c85588fbc582464e6 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Sat, 3 Aug 2024 15:37:10 +0800 Subject: [PATCH 06/14] Allow spell casting during movement --- src/PlayerbotAI.cpp | 10 +- .../actions/CheckMountStateAction.cpp | 12 +- src/strategy/actions/MovementActions.cpp | 51 ++- src/strategy/actions/MovementActions.h | 2 + src/strategy/triggers/TriggerContext.h | 393 +++++++++--------- src/strategy/values/LastMovementValue.cpp | 9 +- src/strategy/values/LastMovementValue.h | 4 +- src/strategy/values/PartyMemberToHeal.cpp | 3 +- 8 files changed, 263 insertions(+), 221 deletions(-) diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index 5394959f..3c610ad0 100644 --- a/src/PlayerbotAI.cpp +++ b/src/PlayerbotAI.cpp @@ -1441,7 +1441,7 @@ bool PlayerbotAI::IsCaster(Player* player) { return IsRanged(player) && player-> bool PlayerbotAI::IsCombo(Player* player) { - int tab = AiFactory::GetPlayerSpecTab(player); + // int tab = AiFactory::GetPlayerSpecTab(player); return player->getClass() == CLASS_ROGUE || (player->getClass() == CLASS_DRUID && player->HasAura(768)); // cat druid } @@ -2634,8 +2634,8 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget) return true; } - aiObjectContext->GetValue("last movement")->Get().Set(nullptr); - aiObjectContext->GetValue("stay time")->Set(0); + // aiObjectContext->GetValue("last movement")->Get().Set(nullptr); + // aiObjectContext->GetValue("stay time")->Set(0); if (bot->IsFlying() || bot->HasUnitState(UNIT_STATE_IN_FLIGHT)) { @@ -2820,8 +2820,8 @@ bool PlayerbotAI::CastSpell(uint32 spellId, float x, float y, float z, Item* ite return true; } - aiObjectContext->GetValue("last movement")->Get().Set(nullptr); - aiObjectContext->GetValue("stay time")->Set(0); + // aiObjectContext->GetValue("last movement")->Get().Set(nullptr); + // aiObjectContext->GetValue("stay time")->Set(0); MotionMaster& mm = *bot->GetMotionMaster(); diff --git a/src/strategy/actions/CheckMountStateAction.cpp b/src/strategy/actions/CheckMountStateAction.cpp index 12909414..6a51fd92 100644 --- a/src/strategy/actions/CheckMountStateAction.cpp +++ b/src/strategy/actions/CheckMountStateAction.cpp @@ -19,9 +19,9 @@ bool CheckMountStateAction::Execute(Event event) bool enemy = AI_VALUE(Unit*, "enemy player target"); // ignore grind target in BG or bots will dismount near any creature (eg: the rams in AV) bool dps = AI_VALUE(Unit*, "dps target"); - bool fartarget = - (enemy && sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", "enemy player target"), 40.0f)) || - (dps && sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", "dps target"), 50.0f)); + // bool fartarget = (enemy && sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", "enemy player + // target"), 40.0f)) || + // (dps && sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", "dps target"), 50.0f)); bool attackdistance = false; // bool chasedistance = false; float attack_distance = 35.0f; @@ -34,6 +34,9 @@ bool CheckMountStateAction::Execute(Event event) attack_distance = 30.0f; } + // if (enemy) + // attack_distance /= 2; + if (dps || enemy) { Unit* currentTarget = AI_VALUE(Unit*, "current target"); @@ -91,8 +94,7 @@ bool CheckMountStateAction::Execute(Event event) } } - if (bot->InBattleground() && !attackdistance && (noattackers || fartarget) && !bot->IsInCombat() && - !bot->IsMounted()) + if (bot->InBattleground() && !attackdistance && noattackers && !bot->IsInCombat() && !bot->IsMounted()) { if (bot->GetBattlegroundTypeId() == BATTLEGROUND_WS) { diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index 670735e4..eba8022d 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -68,7 +68,7 @@ void MovementAction::JumpTo(uint32 mapId, float x, float y, float z) 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()); + AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation(), 1000); } bool MovementAction::MoveNear(uint32 mapId, float x, float y, float z, float distance) @@ -167,6 +167,14 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, { return false; } + if (IsDuplicateMove(mapId, x, y, z)) + { + return false; + } + if (IsWaitingForLastMove()) + { + return false; + } // if (bot->Unit::IsFalling()) { // bot->Say("I'm falling!, flag:" + std::to_string(bot->m_movementInfo.GetMovementFlags()), LANG_UNIVERSAL); // return false; @@ -177,8 +185,9 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, // if (bot->Unit::IsFalling()) { // bot->Say("I'm falling", LANG_UNIVERSAL); // } - bool generatePath = !bot->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) && !bot->IsFlying() && - !bot->HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING) && !bot->IsInWater(); + // !bot->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) && + + bool generatePath = !bot->IsFlying() && !bot->isSwimming(); bool disableMoveSplinePath = sPlayerbotAIConfig->disableMoveSplinePath >= 2 || (sPlayerbotAIConfig->disableMoveSplinePath == 1 && bot->InBattleground()); if (disableMoveSplinePath || !generatePath) @@ -186,8 +195,6 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, float distance = bot->GetExactDist(x, y, z); if (distance > sPlayerbotAIConfig->contactDistance) { - WaitForReach(distance); - if (bot->IsSitState()) bot->SetStandState(UNIT_STAND_STATE_STAND); @@ -199,7 +206,8 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, MotionMaster& mm = *bot->GetMotionMaster(); mm.Clear(); mm.MovePoint(mapId, x, y, z, generatePath); - AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation()); + float delay = std::min((float)sPlayerbotAIConfig->maxWaitForMove, 1000.0f * MoveDelay(distance)); + AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation(), delay); return true; } } @@ -215,8 +223,6 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, float distance = bot->GetExactDist(x, y, modifiedZ); if (distance > sPlayerbotAIConfig->contactDistance) { - WaitForReach(distance); - if (bot->IsSitState()) bot->SetStandState(UNIT_STAND_STATE_STAND); @@ -229,7 +235,9 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, mm.Clear(); mm.MoveSplinePath(&path); - AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation()); + // mm.MoveSplinePath(&path); + float delay = std::min((float)sPlayerbotAIConfig->maxWaitForMove, 1000.0f * MoveDelay(distance)); + AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation(), delay); return true; } } @@ -847,6 +855,29 @@ bool MovementAction::IsMovingAllowed(uint32 mapId, float x, float y, float z) return IsMovingAllowed(); } +bool MovementAction::IsDuplicateMove(uint32 mapId, float x, float y, float z) +{ + LastMovement& lastMove = *context->GetValue("last movement"); + + // heuristic 5s + if (lastMove.msTime + sPlayerbotAIConfig->maxWaitForMove < getMSTime() || + lastMove.lastMoveShort.GetExactDist(x, y, z) > 0.01f) + return false; + + return true; +} + +bool MovementAction::IsWaitingForLastMove() +{ + LastMovement& lastMove = *context->GetValue("last movement"); + + // heuristic 5s + if (lastMove.lastdelayTime + lastMove.msTime > getMSTime()) + return true; + + return false; +} + bool MovementAction::IsMovingAllowed() { // do not allow if not vehicle driver @@ -878,7 +909,7 @@ void MovementAction::UpdateMovementState() { bot->SetSwim(true); } - else + else if (!bot->Unit::IsInWater()) { bot->SetSwim(false); } diff --git a/src/strategy/actions/MovementActions.h b/src/strategy/actions/MovementActions.h index c0a5b888..d8b178c2 100644 --- a/src/strategy/actions/MovementActions.h +++ b/src/strategy/actions/MovementActions.h @@ -39,6 +39,8 @@ protected: void WaitForReach(float distance); bool IsMovingAllowed(Unit* target); bool IsMovingAllowed(uint32 mapId, float x, float y, float z); + bool IsDuplicateMove(uint32 mapId, float x, float y, float z); + bool IsWaitingForLastMove(); bool IsMovingAllowed(); bool Flee(Unit* target); void ClearIdleState(); diff --git a/src/strategy/triggers/TriggerContext.h b/src/strategy/triggers/TriggerContext.h index e0b7ce99..2b5cbd06 100644 --- a/src/strategy/triggers/TriggerContext.h +++ b/src/strategy/triggers/TriggerContext.h @@ -183,202 +183,203 @@ public: creators["petition signed"] = &TriggerContext::petition_signed; creators["buy tabard"] = &TriggerContext::buy_tabard; creators["leave large guild"] = &TriggerContext::leave_large_guild; - - creators["rpg"] = &TriggerContext::rpg; - creators["rpg taxi"] = &TriggerContext::rpg_taxi; - creators["rpg discover"] = &TriggerContext::rpg_discover; - creators["rpg start quest"] = &TriggerContext::rpg_start_quest; - creators["rpg end quest"] = &TriggerContext::rpg_end_quest; - creators["rpg buy"] = &TriggerContext::rpg_buy; - creators["rpg sell"] = &TriggerContext::rpg_sell; - creators["rpg repair"] = &TriggerContext::rpg_repair; - creators["rpg train"] = &TriggerContext::rpg_train; - creators["rpg heal"] = &TriggerContext::rpg_heal; - creators["rpg home bind"] = &TriggerContext::rpg_home_bind; - creators["rpg queue bg"] = &TriggerContext::rpg_queue_bg; - creators["rpg buy petition"] = &TriggerContext::rpg_buy_petition; - creators["rpg use"] = &TriggerContext::rpg_use; - creators["rpg spell"] = &TriggerContext::rpg_spell; - creators["rpg craft"] = &TriggerContext::rpg_craft; - creators["rpg trade useful"] = &TriggerContext::rpg_trade_useful; - creators["rpg duel"] = &TriggerContext::rpg_duel; } - -private: - static Trigger* give_food(PlayerbotAI* botAI) { return new GiveFoodTrigger(botAI); } - static Trigger* give_water(PlayerbotAI* botAI) { return new GiveWaterTrigger(botAI); } - static Trigger* no_rti(PlayerbotAI* botAI) { return new NoRtiTrigger(botAI); } - static Trigger* _return(PlayerbotAI* botAI) { return new ReturnTrigger(botAI); } - static Trigger* sit(PlayerbotAI* botAI) { return new SitTrigger(botAI); } - static Trigger* far_from_rpg_target(PlayerbotAI* botAI) { return new FarFromRpgTargetTrigger(botAI); } - static Trigger* near_rpg_target(PlayerbotAI* botAI) { return new NearRpgTargetTrigger(botAI); } - static Trigger* far_from_travel_target(PlayerbotAI* botAI) { return new FarFromTravelTargetTrigger(botAI); } - static Trigger* no_travel_target(PlayerbotAI* botAI) { return new NoTravelTargetTrigger(botAI); } - static Trigger* no_rpg_target(PlayerbotAI* botAI) { return new NoRpgTargetTrigger(botAI); } - static Trigger* has_rpg_target(PlayerbotAI* botAI) { return new HasRpgTargetTrigger(botAI); } - static Trigger* collision(PlayerbotAI* botAI) { return new CollisionTrigger(botAI); } - static Trigger* lfg_proposal_active(PlayerbotAI* botAI) { return new LfgProposalActiveTrigger(botAI); } - static Trigger* unknown_dungeon(PlayerbotAI* botAI) { return new UnknownDungeonTrigger(botAI); } - static Trigger* invalid_target(PlayerbotAI* botAI) { return new InvalidTargetTrigger(botAI); } - static Trigger* critical_aoe_heal(PlayerbotAI* botAI) - { - return new AoeHealTrigger(botAI, "critical aoe heal", "critical", 2); - } - static Trigger* low_aoe_heal(PlayerbotAI* botAI) { return new AoeHealTrigger(botAI, "low aoe heal", "low", 2); } - static Trigger* medium_aoe_heal(PlayerbotAI* botAI) - { - return new AoeHealTrigger(botAI, "medium aoe heal", "medium", 2); - } - static Trigger* almost_full_aoe_heal(PlayerbotAI* botAI) - { - return new AoeHealTrigger(botAI, "almost full aoe heal", "almost full", 2); - } - static Trigger* group_heal_occasion(PlayerbotAI* ai) - { - return new AoeInGroupTrigger(ai, "group heal occasion", "almost full", 0.6); - } - static Trigger* medium_group_heal_occasion(PlayerbotAI* ai) - { - return new AoeInGroupTrigger(ai, "group heal occasion", "medium", 0.4); - } - static Trigger* target_changed(PlayerbotAI* botAI) { return new TargetChangedTrigger(botAI); } - static Trigger* swimming(PlayerbotAI* botAI) { return new IsSwimmingTrigger(botAI); } - static Trigger* no_possible_targets(PlayerbotAI* botAI) { return new NoPossibleTargetsTrigger(botAI); } - static Trigger* possible_adds(PlayerbotAI* botAI) { return new PossibleAddsTrigger(botAI); } - static Trigger* can_loot(PlayerbotAI* botAI) { return new CanLootTrigger(botAI); } - static Trigger* far_from_loot_target(PlayerbotAI* botAI) { return new FarFromCurrentLootTrigger(botAI); } - static Trigger* far_from_master(PlayerbotAI* botAI) { return new FarFromMasterTrigger(botAI); } - static Trigger* behind_target(PlayerbotAI* botAI) { return new IsBehindTargetTrigger(botAI); } - static Trigger* not_behind_target(PlayerbotAI* botAI) { return new IsNotBehindTargetTrigger(botAI); } - static Trigger* not_facing_target(PlayerbotAI* botAI) { return new IsNotFacingTargetTrigger(botAI); } - static Trigger* panic(PlayerbotAI* botAI) { return new PanicTrigger(botAI); } - static Trigger* outnumbered(PlayerbotAI* botAI) { return new OutNumberedTrigger(botAI); } - static Trigger* no_drink(PlayerbotAI* botAI) { return new NoDrinkTrigger(botAI); } - static Trigger* no_food(PlayerbotAI* botAI) { return new NoFoodTrigger(botAI); } - static Trigger* LightAoe(PlayerbotAI* botAI) { return new LightAoeTrigger(botAI); } - static Trigger* MediumAoe(PlayerbotAI* botAI) { return new MediumAoeTrigger(botAI); } - static Trigger* HighAoe(PlayerbotAI* botAI) { return new HighAoeTrigger(botAI); } - static Trigger* HasAreaDebuff(PlayerbotAI* botAI) { return new HasAreaDebuffTrigger(botAI); } - static Trigger* LoseAggro(PlayerbotAI* botAI) { return new LoseAggroTrigger(botAI); } - static Trigger* HasAggro(PlayerbotAI* botAI) { return new HasAggroTrigger(botAI); } - static Trigger* LowHealth(PlayerbotAI* botAI) { return new LowHealthTrigger(botAI); } - static Trigger* MediumHealth(PlayerbotAI* botAI) { return new MediumHealthTrigger(botAI); } - static Trigger* AlmostFullHealth(PlayerbotAI* botAI) { return new AlmostFullHealthTrigger(botAI); } - static Trigger* CriticalHealth(PlayerbotAI* botAI) { return new CriticalHealthTrigger(botAI); } - static Trigger* TargetCriticalHealth(PlayerbotAI* botAI) { return new TargetCriticalHealthTrigger(botAI); } - static Trigger* LowMana(PlayerbotAI* botAI) { return new LowManaTrigger(botAI); } - static Trigger* MediumMana(PlayerbotAI* botAI) { return new MediumManaTrigger(botAI); } - static Trigger* HighMana(PlayerbotAI* botAI) { return new HighManaTrigger(botAI); } - static Trigger* AlmostFullMana(PlayerbotAI* botAI) { return new AlmostFullManaTrigger(botAI); } - static Trigger* EnoughMana(PlayerbotAI* botAI) { return new EnoughManaTrigger(botAI); } - static Trigger* LightRageAvailable(PlayerbotAI* botAI) { return new LightRageAvailableTrigger(botAI); } - static Trigger* MediumRageAvailable(PlayerbotAI* botAI) { return new MediumRageAvailableTrigger(botAI); } - static Trigger* HighRageAvailable(PlayerbotAI* botAI) { return new HighRageAvailableTrigger(botAI); } - static Trigger* LightEnergyAvailable(PlayerbotAI* botAI) { return new LightEnergyAvailableTrigger(botAI); } - static Trigger* MediumEnergyAvailable(PlayerbotAI* botAI) { return new MediumEnergyAvailableTrigger(botAI); } - static Trigger* HighEnergyAvailable(PlayerbotAI* botAI) { return new HighEnergyAvailableTrigger(botAI); } - static Trigger* LootAvailable(PlayerbotAI* botAI) { return new LootAvailableTrigger(botAI); } - static Trigger* NoAttackers(PlayerbotAI* botAI) { return new NoAttackersTrigger(botAI); } - static Trigger* TankAssist(PlayerbotAI* botAI) { return new TankAssistTrigger(botAI); } - static Trigger* Timer(PlayerbotAI* botAI) { return new TimerTrigger(botAI); } - static Trigger* NoTarget(PlayerbotAI* botAI) { return new NoTargetTrigger(botAI); } - static Trigger* TargetInSight(PlayerbotAI* botAI) { return new TargetInSightTrigger(botAI); } - static Trigger* not_dps_target_active(PlayerbotAI* botAI) { return new NotDpsTargetActiveTrigger(botAI); } - static Trigger* not_dps_aoe_target_active(PlayerbotAI* botAI) { return new NotDpsAoeTargetActiveTrigger(botAI); } - static Trigger* has_nearest_adds(PlayerbotAI* botAI) { return new HasNearestAddsTrigger(botAI); } - static Trigger* enemy_player_near(PlayerbotAI* botAI) { return new EnemyPlayerNear(botAI); } - static Trigger* Random(PlayerbotAI* botAI) { return new RandomTrigger(botAI, "random", 20); } - static Trigger* seldom(PlayerbotAI* botAI) { return new RandomTrigger(botAI, "seldom", 300); } - static Trigger* often(PlayerbotAI* botAI) { return new RandomTrigger(botAI, "often", 5); } - static Trigger* EnemyOutOfMelee(PlayerbotAI* botAI) { return new EnemyOutOfMeleeTrigger(botAI); } - static Trigger* EnemyOutOfSpell(PlayerbotAI* botAI) { return new EnemyOutOfSpellRangeTrigger(botAI); } - static Trigger* enemy_too_close_for_spell(PlayerbotAI* botAI) { return new EnemyTooCloseForSpellTrigger(botAI); } - static Trigger* enemy_too_close_for_auto_shot(PlayerbotAI* botAI) - { - return new EnemyTooCloseForAutoShotTrigger(botAI); - } - static Trigger* enemy_too_close_for_shoot(PlayerbotAI* botAI) { return new EnemyTooCloseForShootTrigger(botAI); } - static Trigger* enemy_too_close_for_melee(PlayerbotAI* botAI) { return new EnemyTooCloseForMeleeTrigger(botAI); } - static Trigger* enemy_is_close(PlayerbotAI* botAI) { return new EnemyIsCloseTrigger(botAI); } - static Trigger* enemy_within_melee(PlayerbotAI* botAI) { return new EnemyWithinMeleeTrigger(botAI); } - static Trigger* party_member_to_heal_out_of_spell_range(PlayerbotAI* botAI) - { - return new PartyMemberToHealOutOfSpellRangeTrigger(botAI); - } - static Trigger* ComboPointsAvailable(PlayerbotAI* botAI) { return new ComboPointsAvailableTrigger(botAI); } - static Trigger* ComboPoints3Available(PlayerbotAI* botAI) { return new ComboPointsAvailableTrigger(botAI, 3); } - static Trigger* MediumThreat(PlayerbotAI* botAI) { return new MediumThreatTrigger(botAI); } - static Trigger* Dead(PlayerbotAI* botAI) { return new DeadTrigger(botAI); } - static Trigger* corpse_near(PlayerbotAI* botAI) { return new CorpseNearTrigger(botAI); } - static Trigger* PartyMemberDead(PlayerbotAI* botAI) { return new PartyMemberDeadTrigger(botAI); } - static Trigger* CombatPartyMemberDead(PlayerbotAI* botAI) { return new CombatPartyMemberDeadTrigger(botAI); } - static Trigger* PartyMemberLowHealth(PlayerbotAI* botAI) { return new PartyMemberLowHealthTrigger(botAI); } - static Trigger* PartyMemberMediumHealth(PlayerbotAI* botAI) { return new PartyMemberMediumHealthTrigger(botAI); } - static Trigger* PartyMemberAlmostFullHealth(PlayerbotAI* botAI) - { - return new PartyMemberAlmostFullHealthTrigger(botAI); - } - static Trigger* PartyMemberCriticalHealth(PlayerbotAI* botAI) - { - return new PartyMemberCriticalHealthTrigger(botAI); - } - static Trigger* protect_party_member(PlayerbotAI* botAI) { return new ProtectPartyMemberTrigger(botAI); } - static Trigger* no_pet(PlayerbotAI* botAI) { return new NoPetTrigger(botAI); } - static Trigger* has_pet(PlayerbotAI* botAI) { return new HasPetTrigger(botAI); } - static Trigger* pet_attack(PlayerbotAI* botAI) { return new PetAttackTrigger(botAI); } - static Trigger* has_attackers(PlayerbotAI* botAI) { return new HasAttackersTrigger(botAI); } - static Trigger* random_bot_update_trigger(PlayerbotAI* botAI) { return new RandomBotUpdateTrigger(botAI); } - static Trigger* no_non_bot_players_around(PlayerbotAI* botAI) { return new NoNonBotPlayersAroundTrigger(botAI); } - static Trigger* new_player_nearby(PlayerbotAI* botAI) { return new NewPlayerNearbyTrigger(botAI); } - static Trigger* bg_waiting(PlayerbotAI* botAI) { return new BgWaitingTrigger(botAI); } - static Trigger* bg_active(PlayerbotAI* botAI) { return new BgActiveTrigger(botAI); } - static Trigger* bg_invite_active(PlayerbotAI* botAI) { return new BgInviteActiveTrigger(botAI); } - static Trigger* inside_bg(PlayerbotAI* botAI) { return new InsideBGTrigger(botAI); } - static Trigger* player_has_no_flag(PlayerbotAI* botAI) { return new PlayerHasNoFlag(botAI); } - static Trigger* player_has_flag(PlayerbotAI* botAI) { return new PlayerHasFlag(botAI); } - static Trigger* team_has_flag(PlayerbotAI* botAI) { return new TeamHasFlag(botAI); } - static Trigger* enemy_team_has_flag(PlayerbotAI* botAI) { return new EnemyTeamHasFlag(botAI); } - static Trigger* enemy_flagcarrier_near(PlayerbotAI* botAI) { return new EnemyFlagCarrierNear(botAI); } - static Trigger* player_is_in_BATTLEGROUND(PlayerbotAI* botAI) { return new PlayerIsInBattleground(botAI); } - static Trigger* player_is_in_BATTLEGROUND_no_flag(PlayerbotAI* botAI) - { - return new PlayerIsInBattlegroundWithoutFlag(botAI); - } - static Trigger* mounted(PlayerbotAI* botAI) { return new IsMountedTrigger(botAI); } - static Trigger* at_dark_portal_outland(PlayerbotAI* botAI) { return new AtDarkPortalOutlandTrigger(botAI); } - static Trigger* at_dark_portal_azeroth(PlayerbotAI* botAI) { return new AtDarkPortalAzerothTrigger(botAI); } - static Trigger* in_vehicle(PlayerbotAI* botAI) { return new InVehicleTrigger(botAI); } - static Trigger* vehicle_near(PlayerbotAI* botAI) { return new VehicleNearTrigger(botAI); } - static Trigger* near_dark_portal(PlayerbotAI* botAI) { return new NearDarkPortalTrigger(botAI); } - static Trigger* need_world_buff(PlayerbotAI* botAI) { return new NeedWorldBuffTrigger(botAI); } - static Trigger* falling(PlayerbotAI* botAI) { return new IsFallingTrigger(botAI); } - static Trigger* falling_far(PlayerbotAI* botAI) { return new IsFallingFarTrigger(botAI); } - static Trigger* move_stuck(PlayerbotAI* botAI) { return new MoveStuckTrigger(botAI); } - static Trigger* move_long_stuck(PlayerbotAI* botAI) { return new MoveLongStuckTrigger(botAI); } - static Trigger* combat_stuck(PlayerbotAI* botAI) { return new CombatStuckTrigger(botAI); } - static Trigger* combat_long_stuck(PlayerbotAI* botAI) { return new CombatLongStuckTrigger(botAI); } - static Trigger* player_wants_in_bg(PlayerbotAI* botAI) { return new PlayerWantsInBattlegroundTrigger(botAI); } - static Trigger* petition_signed(PlayerbotAI* botAI) { return new PetitionTurnInTrigger(botAI); } - static Trigger* buy_tabard(PlayerbotAI* botAI) { return new BuyTabardTrigger(botAI); } - static Trigger* leave_large_guild(PlayerbotAI* botAI) { return new LeaveLargeGuildTrigger(botAI); } - static Trigger* rpg(PlayerbotAI* botAI) { return new RpgTrigger(botAI); } - static Trigger* rpg_taxi(PlayerbotAI* botAI) { return new RpgTaxiTrigger(botAI); } - static Trigger* rpg_discover(PlayerbotAI* botAI) { return new RpgDiscoverTrigger(botAI); } - static Trigger* rpg_start_quest(PlayerbotAI* botAI) { return new RpgStartQuestTrigger(botAI); } - static Trigger* rpg_end_quest(PlayerbotAI* botAI) { return new RpgEndQuestTrigger(botAI); } - static Trigger* rpg_buy(PlayerbotAI* botAI) { return new RpgBuyTrigger(botAI); } - static Trigger* rpg_sell(PlayerbotAI* botAI) { return new RpgSellTrigger(botAI); } - static Trigger* rpg_repair(PlayerbotAI* botAI) { return new RpgRepairTrigger(botAI); } - static Trigger* rpg_train(PlayerbotAI* botAI) { return new RpgTrainTrigger(botAI); } - static Trigger* rpg_heal(PlayerbotAI* botAI) { return new RpgHealTrigger(botAI); } - static Trigger* rpg_home_bind(PlayerbotAI* botAI) { return new RpgHomeBindTrigger(botAI); } - static Trigger* rpg_queue_bg(PlayerbotAI* botAI) { return new RpgQueueBGTrigger(botAI); } - static Trigger* rpg_buy_petition(PlayerbotAI* botAI) { return new RpgBuyPetitionTrigger(botAI); } - static Trigger* rpg_use(PlayerbotAI* botAI) { return new RpgUseTrigger(botAI); } - static Trigger* rpg_spell(PlayerbotAI* botAI) { return new RpgUseTrigger(botAI); } - static Trigger* rpg_craft(PlayerbotAI* botAI) { return new RpgCraftTrigger(botAI); } - static Trigger* rpg_trade_useful(PlayerbotAI* botAI) { return new RpgTradeUsefulTrigger(botAI); } - static Trigger* rpg_duel(PlayerbotAI* botAI) { return new RpgDuelTrigger(botAI); } -}; + private: + static Trigger* give_food(PlayerbotAI * botAI) { return new GiveFoodTrigger(botAI); } + static Trigger* give_water(PlayerbotAI * botAI) { return new GiveWaterTrigger(botAI); } + static Trigger* no_rti(PlayerbotAI * botAI) { return new NoRtiTrigger(botAI); } + static Trigger* _return(PlayerbotAI * botAI) { return new ReturnTrigger(botAI); } + static Trigger* sit(PlayerbotAI * botAI) { return new SitTrigger(botAI); } + static Trigger* far_from_rpg_target(PlayerbotAI * botAI) { return new FarFromRpgTargetTrigger(botAI); } + static Trigger* near_rpg_target(PlayerbotAI * botAI) { return new NearRpgTargetTrigger(botAI); } + static Trigger* far_from_travel_target(PlayerbotAI * botAI) { return new FarFromTravelTargetTrigger(botAI); } + static Trigger* no_travel_target(PlayerbotAI * botAI) { return new NoTravelTargetTrigger(botAI); } + static Trigger* no_rpg_target(PlayerbotAI * botAI) { return new NoRpgTargetTrigger(botAI); } + static Trigger* has_rpg_target(PlayerbotAI * botAI) { return new HasRpgTargetTrigger(botAI); } + static Trigger* collision(PlayerbotAI * botAI) { return new CollisionTrigger(botAI); } + static Trigger* lfg_proposal_active(PlayerbotAI * botAI) { return new LfgProposalActiveTrigger(botAI); } + static Trigger* unknown_dungeon(PlayerbotAI * botAI) { return new UnknownDungeonTrigger(botAI); } + static Trigger* invalid_target(PlayerbotAI * botAI) { return new InvalidTargetTrigger(botAI); } + static Trigger* critical_aoe_heal(PlayerbotAI * botAI) + { + return new AoeHealTrigger(botAI, "critical aoe heal", "critical", 2); + } + static Trigger* low_aoe_heal(PlayerbotAI * botAI) + { + return new AoeHealTrigger(botAI, "low aoe heal", "low", 2); + } + static Trigger* medium_aoe_heal(PlayerbotAI * botAI) + { + return new AoeHealTrigger(botAI, "medium aoe heal", "medium", 2); + } + static Trigger* almost_full_aoe_heal(PlayerbotAI * botAI) + { + return new AoeHealTrigger(botAI, "almost full aoe heal", "almost full", 2); + } + static Trigger* group_heal_occasion(PlayerbotAI * ai) + { + return new AoeInGroupTrigger(ai, "group heal occasion", "almost full", 0.6); + } + static Trigger* medium_group_heal_occasion(PlayerbotAI * ai) + { + return new AoeInGroupTrigger(ai, "group heal occasion", "medium", 0.6); + } + static Trigger* target_changed(PlayerbotAI * botAI) { return new TargetChangedTrigger(botAI); } + static Trigger* swimming(PlayerbotAI * botAI) { return new IsSwimmingTrigger(botAI); } + static Trigger* no_possible_targets(PlayerbotAI * botAI) { return new NoPossibleTargetsTrigger(botAI); } + static Trigger* possible_adds(PlayerbotAI * botAI) { return new PossibleAddsTrigger(botAI); } + static Trigger* can_loot(PlayerbotAI * botAI) { return new CanLootTrigger(botAI); } + static Trigger* far_from_loot_target(PlayerbotAI * botAI) { return new FarFromCurrentLootTrigger(botAI); } + static Trigger* far_from_master(PlayerbotAI * botAI) { return new FarFromMasterTrigger(botAI); } + static Trigger* behind_target(PlayerbotAI * botAI) { return new IsBehindTargetTrigger(botAI); } + static Trigger* not_behind_target(PlayerbotAI * botAI) { return new IsNotBehindTargetTrigger(botAI); } + static Trigger* not_facing_target(PlayerbotAI * botAI) { return new IsNotFacingTargetTrigger(botAI); } + static Trigger* panic(PlayerbotAI * botAI) { return new PanicTrigger(botAI); } + static Trigger* outnumbered(PlayerbotAI * botAI) { return new OutNumberedTrigger(botAI); } + static Trigger* no_drink(PlayerbotAI * botAI) { return new NoDrinkTrigger(botAI); } + static Trigger* no_food(PlayerbotAI * botAI) { return new NoFoodTrigger(botAI); } + static Trigger* LightAoe(PlayerbotAI * botAI) { return new LightAoeTrigger(botAI); } + static Trigger* MediumAoe(PlayerbotAI * botAI) { return new MediumAoeTrigger(botAI); } + static Trigger* HighAoe(PlayerbotAI * botAI) { return new HighAoeTrigger(botAI); } + static Trigger* HasAreaDebuff(PlayerbotAI * botAI) { return new HasAreaDebuffTrigger(botAI); } + static Trigger* LoseAggro(PlayerbotAI * botAI) { return new LoseAggroTrigger(botAI); } + static Trigger* HasAggro(PlayerbotAI * botAI) { return new HasAggroTrigger(botAI); } + static Trigger* LowHealth(PlayerbotAI * botAI) { return new LowHealthTrigger(botAI); } + static Trigger* MediumHealth(PlayerbotAI * botAI) { return new MediumHealthTrigger(botAI); } + static Trigger* AlmostFullHealth(PlayerbotAI * botAI) { return new AlmostFullHealthTrigger(botAI); } + static Trigger* CriticalHealth(PlayerbotAI * botAI) { return new CriticalHealthTrigger(botAI); } + static Trigger* TargetCriticalHealth(PlayerbotAI * botAI) { return new TargetCriticalHealthTrigger(botAI); } + static Trigger* LowMana(PlayerbotAI * botAI) { return new LowManaTrigger(botAI); } + static Trigger* MediumMana(PlayerbotAI * botAI) { return new MediumManaTrigger(botAI); } + static Trigger* HighMana(PlayerbotAI * botAI) { return new HighManaTrigger(botAI); } + static Trigger* AlmostFullMana(PlayerbotAI * botAI) { return new AlmostFullManaTrigger(botAI); } + static Trigger* EnoughMana(PlayerbotAI * botAI) { return new EnoughManaTrigger(botAI); } + static Trigger* LightRageAvailable(PlayerbotAI * botAI) { return new LightRageAvailableTrigger(botAI); } + static Trigger* MediumRageAvailable(PlayerbotAI * botAI) { return new MediumRageAvailableTrigger(botAI); } + static Trigger* HighRageAvailable(PlayerbotAI * botAI) { return new HighRageAvailableTrigger(botAI); } + static Trigger* LightEnergyAvailable(PlayerbotAI * botAI) { return new LightEnergyAvailableTrigger(botAI); } + static Trigger* MediumEnergyAvailable(PlayerbotAI * botAI) { return new MediumEnergyAvailableTrigger(botAI); } + static Trigger* HighEnergyAvailable(PlayerbotAI * botAI) { return new HighEnergyAvailableTrigger(botAI); } + static Trigger* LootAvailable(PlayerbotAI * botAI) { return new LootAvailableTrigger(botAI); } + static Trigger* NoAttackers(PlayerbotAI * botAI) { return new NoAttackersTrigger(botAI); } + static Trigger* TankAssist(PlayerbotAI * botAI) { return new TankAssistTrigger(botAI); } + static Trigger* Timer(PlayerbotAI * botAI) { return new TimerTrigger(botAI); } + static Trigger* NoTarget(PlayerbotAI * botAI) { return new NoTargetTrigger(botAI); } + static Trigger* TargetInSight(PlayerbotAI * botAI) { return new TargetInSightTrigger(botAI); } + static Trigger* not_dps_target_active(PlayerbotAI * botAI) { return new NotDpsTargetActiveTrigger(botAI); } + static Trigger* not_dps_aoe_target_active(PlayerbotAI * botAI) + { + return new NotDpsAoeTargetActiveTrigger(botAI); + } + static Trigger* has_nearest_adds(PlayerbotAI * botAI) { return new HasNearestAddsTrigger(botAI); } + static Trigger* enemy_player_near(PlayerbotAI * botAI) { return new EnemyPlayerNear(botAI); } + static Trigger* Random(PlayerbotAI * botAI) { return new RandomTrigger(botAI, "random", 20); } + static Trigger* seldom(PlayerbotAI * botAI) { return new RandomTrigger(botAI, "seldom", 300); } + static Trigger* often(PlayerbotAI * botAI) { return new RandomTrigger(botAI, "often", 5); } + static Trigger* EnemyOutOfMelee(PlayerbotAI * botAI) { return new EnemyOutOfMeleeTrigger(botAI); } + static Trigger* EnemyOutOfSpell(PlayerbotAI * botAI) { return new EnemyOutOfSpellRangeTrigger(botAI); } + static Trigger* enemy_too_close_for_spell(PlayerbotAI * botAI) + { + return new EnemyTooCloseForSpellTrigger(botAI); + } + static Trigger* enemy_too_close_for_auto_shot(PlayerbotAI * botAI) + { + return new EnemyTooCloseForAutoShotTrigger(botAI); + } + static Trigger* enemy_too_close_for_shoot(PlayerbotAI * botAI) + { + return new EnemyTooCloseForShootTrigger(botAI); + } + static Trigger* enemy_too_close_for_melee(PlayerbotAI * botAI) + { + return new EnemyTooCloseForMeleeTrigger(botAI); + } + static Trigger* enemy_is_close(PlayerbotAI * botAI) { return new EnemyIsCloseTrigger(botAI); } + static Trigger* enemy_within_melee(PlayerbotAI * botAI) { return new EnemyWithinMeleeTrigger(botAI); } + static Trigger* party_member_to_heal_out_of_spell_range(PlayerbotAI * botAI) + { + return new PartyMemberToHealOutOfSpellRangeTrigger(botAI); + } + static Trigger* ComboPointsAvailable(PlayerbotAI * botAI) { return new ComboPointsAvailableTrigger(botAI); } + static Trigger* ComboPoints3Available(PlayerbotAI * botAI) { return new ComboPointsAvailableTrigger(botAI, 3); } + static Trigger* MediumThreat(PlayerbotAI * botAI) { return new MediumThreatTrigger(botAI); } + static Trigger* Dead(PlayerbotAI * botAI) { return new DeadTrigger(botAI); } + static Trigger* corpse_near(PlayerbotAI * botAI) { return new CorpseNearTrigger(botAI); } + static Trigger* PartyMemberDead(PlayerbotAI * botAI) { return new PartyMemberDeadTrigger(botAI); } + static Trigger* CombatPartyMemberDead(PlayerbotAI * botAI) { return new CombatPartyMemberDeadTrigger(botAI); } + static Trigger* PartyMemberLowHealth(PlayerbotAI * botAI) { return new PartyMemberLowHealthTrigger(botAI); } + static Trigger* PartyMemberMediumHealth(PlayerbotAI * botAI) + { + return new PartyMemberMediumHealthTrigger(botAI); + } + static Trigger* PartyMemberAlmostFullHealth(PlayerbotAI * botAI) + { + return new PartyMemberAlmostFullHealthTrigger(botAI); + } + static Trigger* PartyMemberCriticalHealth(PlayerbotAI * botAI) + { + return new PartyMemberCriticalHealthTrigger(botAI); + } + static Trigger* protect_party_member(PlayerbotAI * botAI) { return new ProtectPartyMemberTrigger(botAI); } + static Trigger* no_pet(PlayerbotAI * botAI) { return new NoPetTrigger(botAI); } + static Trigger* has_pet(PlayerbotAI * botAI) { return new HasPetTrigger(botAI); } + static Trigger* pet_attack(PlayerbotAI * botAI) { return new PetAttackTrigger(botAI); } + static Trigger* has_attackers(PlayerbotAI * botAI) { return new HasAttackersTrigger(botAI); } + static Trigger* random_bot_update_trigger(PlayerbotAI * botAI) { return new RandomBotUpdateTrigger(botAI); } + static Trigger* no_non_bot_players_around(PlayerbotAI * botAI) + { + return new NoNonBotPlayersAroundTrigger(botAI); + } + static Trigger* new_player_nearby(PlayerbotAI * botAI) { return new NewPlayerNearbyTrigger(botAI); } + static Trigger* bg_waiting(PlayerbotAI * botAI) { return new BgWaitingTrigger(botAI); } + static Trigger* bg_active(PlayerbotAI * botAI) { return new BgActiveTrigger(botAI); } + static Trigger* bg_invite_active(PlayerbotAI * botAI) { return new BgInviteActiveTrigger(botAI); } + static Trigger* inside_bg(PlayerbotAI * botAI) { return new InsideBGTrigger(botAI); } + static Trigger* player_has_no_flag(PlayerbotAI * botAI) { return new PlayerHasNoFlag(botAI); } + static Trigger* player_has_flag(PlayerbotAI * botAI) { return new PlayerHasFlag(botAI); } + static Trigger* team_has_flag(PlayerbotAI * botAI) { return new TeamHasFlag(botAI); } + static Trigger* enemy_team_has_flag(PlayerbotAI * botAI) { return new EnemyTeamHasFlag(botAI); } + static Trigger* enemy_flagcarrier_near(PlayerbotAI * botAI) { return new EnemyFlagCarrierNear(botAI); } + static Trigger* player_is_in_BATTLEGROUND(PlayerbotAI * botAI) { return new PlayerIsInBattleground(botAI); } + static Trigger* player_is_in_BATTLEGROUND_no_flag(PlayerbotAI * botAI) + { + return new PlayerIsInBattlegroundWithoutFlag(botAI); + } + static Trigger* mounted(PlayerbotAI * botAI) { return new IsMountedTrigger(botAI); } + static Trigger* at_dark_portal_outland(PlayerbotAI * botAI) { return new AtDarkPortalOutlandTrigger(botAI); } + static Trigger* at_dark_portal_azeroth(PlayerbotAI * botAI) { return new AtDarkPortalAzerothTrigger(botAI); } + static Trigger* in_vehicle(PlayerbotAI * botAI) { return new InVehicleTrigger(botAI); } + static Trigger* vehicle_near(PlayerbotAI * botAI) { return new VehicleNearTrigger(botAI); } + static Trigger* near_dark_portal(PlayerbotAI * botAI) { return new NearDarkPortalTrigger(botAI); } + static Trigger* need_world_buff(PlayerbotAI * botAI) { return new NeedWorldBuffTrigger(botAI); } + static Trigger* falling(PlayerbotAI * botAI) { return new IsFallingTrigger(botAI); } + static Trigger* falling_far(PlayerbotAI * botAI) { return new IsFallingFarTrigger(botAI); } + static Trigger* move_stuck(PlayerbotAI * botAI) { return new MoveStuckTrigger(botAI); } + static Trigger* move_long_stuck(PlayerbotAI * botAI) { return new MoveLongStuckTrigger(botAI); } + static Trigger* combat_stuck(PlayerbotAI * botAI) { return new CombatStuckTrigger(botAI); } + static Trigger* combat_long_stuck(PlayerbotAI * botAI) { return new CombatLongStuckTrigger(botAI); } + static Trigger* player_wants_in_bg(PlayerbotAI * botAI) { return new PlayerWantsInBattlegroundTrigger(botAI); } + static Trigger* petition_signed(PlayerbotAI * botAI) { return new PetitionTurnInTrigger(botAI); } + static Trigger* buy_tabard(PlayerbotAI * botAI) { return new BuyTabardTrigger(botAI); } + static Trigger* leave_large_guild(PlayerbotAI * botAI) { return new LeaveLargeGuildTrigger(botAI); } + static Trigger* rpg(PlayerbotAI * botAI) { return new RpgTrigger(botAI); } + static Trigger* rpg_taxi(PlayerbotAI * botAI) { return new RpgTaxiTrigger(botAI); } + static Trigger* rpg_discover(PlayerbotAI * botAI) { return new RpgDiscoverTrigger(botAI); } + static Trigger* rpg_start_quest(PlayerbotAI * botAI) { return new RpgStartQuestTrigger(botAI); } + static Trigger* rpg_end_quest(PlayerbotAI * botAI) { return new RpgEndQuestTrigger(botAI); } + static Trigger* rpg_buy(PlayerbotAI * botAI) { return new RpgBuyTrigger(botAI); } + static Trigger* rpg_sell(PlayerbotAI * botAI) { return new RpgSellTrigger(botAI); } + static Trigger* rpg_repair(PlayerbotAI * botAI) { return new RpgRepairTrigger(botAI); } + static Trigger* rpg_train(PlayerbotAI * botAI) { return new RpgTrainTrigger(botAI); } + static Trigger* rpg_heal(PlayerbotAI * botAI) { return new RpgHealTrigger(botAI); } + static Trigger* rpg_home_bind(PlayerbotAI * botAI) { return new RpgHomeBindTrigger(botAI); } + static Trigger* rpg_queue_bg(PlayerbotAI * botAI) { return new RpgQueueBGTrigger(botAI); } + static Trigger* rpg_buy_petition(PlayerbotAI * botAI) { return new RpgBuyPetitionTrigger(botAI); } + static Trigger* rpg_use(PlayerbotAI * botAI) { return new RpgUseTrigger(botAI); } + static Trigger* rpg_spell(PlayerbotAI * botAI) { return new RpgUseTrigger(botAI); } + static Trigger* rpg_craft(PlayerbotAI * botAI) { return new RpgCraftTrigger(botAI); } + static Trigger* rpg_trade_useful(PlayerbotAI * botAI) { return new RpgTradeUsefulTrigger(botAI); } + static Trigger* rpg_duel(PlayerbotAI * botAI) { return new RpgDuelTrigger(botAI); } + }; #endif diff --git a/src/strategy/values/LastMovementValue.cpp b/src/strategy/values/LastMovementValue.cpp index 767bc89e..f7b5488e 100644 --- a/src/strategy/values/LastMovementValue.cpp +++ b/src/strategy/values/LastMovementValue.cpp @@ -6,6 +6,7 @@ #include "LastMovementValue.h" #include "Playerbots.h" +#include "Timer.h" LastMovement::LastMovement() { clear(); } @@ -38,17 +39,19 @@ void LastMovement::clear() lastAreaTrigger = 0; lastFlee = 0; nextTeleport = 0; + msTime = 0; + lastdelayTime = 0; } void LastMovement::Set(Unit* follow) { - Set(0, 0.0f, 0.0f, 0.0f, 0.0f); + Set(0, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); setShort(WorldPosition()); setPath(TravelPath()); lastFollow = follow; } -void LastMovement::Set(uint32 mapId, float x, float y, float z, float ori) +void LastMovement::Set(uint32 mapId, float x, float y, float z, float ori, float delayTime) { lastMoveToMapId = mapId; lastMoveToX = x; @@ -57,6 +60,8 @@ void LastMovement::Set(uint32 mapId, float x, float y, float z, float ori) lastMoveToOri = ori; lastFollow = nullptr; lastMoveShort = WorldPosition(mapId, x, y, z, ori); + msTime = getMSTime(); + lastdelayTime = delayTime; } void LastMovement::setShort(WorldPosition point) diff --git a/src/strategy/values/LastMovementValue.h b/src/strategy/values/LastMovementValue.h index 89277014..fc073a2a 100644 --- a/src/strategy/values/LastMovementValue.h +++ b/src/strategy/values/LastMovementValue.h @@ -35,7 +35,7 @@ public: void clear(); void Set(Unit* follow); - void Set(uint32 mapId, float x, float y, float z, float ori); + void Set(uint32 mapId, float x, float y, float z, float ori, float delayTime); void setShort(WorldPosition point); void setPath(TravelPath path); @@ -50,7 +50,9 @@ public: float lastMoveToY; float lastMoveToZ; float lastMoveToOri; + float lastdelayTime; WorldPosition lastMoveShort; + uint32 msTime; TravelPath lastPath; time_t nextTeleport; std::future future; diff --git a/src/strategy/values/PartyMemberToHeal.cpp b/src/strategy/values/PartyMemberToHeal.cpp index 31a8f00a..5c158428 100644 --- a/src/strategy/values/PartyMemberToHeal.cpp +++ b/src/strategy/values/PartyMemberToHeal.cpp @@ -82,8 +82,7 @@ bool PartyMemberToHeal::Check(Unit* player) // sServerFacade->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->IsWithinLOS(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ()); + bot->GetDistance2d(player) < sPlayerbotAIConfig->healDistance * 2 && bot->IsWithinLOSInMap(player); } Unit* PartyMemberToProtect::Calculate() From f706fa2ba6a3c6d66a8c5476f82a2eebefa9903f Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Mon, 5 Aug 2024 12:08:14 +0800 Subject: [PATCH 07/14] Better waypoints for combat reach --- src/strategy/actions/FollowActions.cpp | 2 +- src/strategy/actions/MovementActions.cpp | 60 ++++++++++++++---------- src/strategy/actions/MovementActions.h | 2 +- 3 files changed, 36 insertions(+), 28 deletions(-) diff --git a/src/strategy/actions/FollowActions.cpp b/src/strategy/actions/FollowActions.cpp index 7a4a4bdb..d0e6fb6b 100644 --- a/src/strategy/actions/FollowActions.cpp +++ b/src/strategy/actions/FollowActions.cpp @@ -29,7 +29,7 @@ bool FollowAction::Execute(Event event) if (Formation::IsNullLocation(loc) || loc.GetMapId() == -1) return false; - moved = MoveTo(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ()); + moved = MoveTo(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ(), false, false, false, true); } if (Pet* pet = bot->GetPet()) diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index eba8022d..38ac44a1 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -12,6 +12,7 @@ #include "Event.h" #include "FleeManager.h" +#include "G3D/Vector3.h" #include "GameObject.h" #include "Geometry.h" #include "LastMovementValue.h" @@ -160,7 +161,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 idle, bool react, bool normal_only, bool exact_waypoint) { UpdateMovementState(); if (!IsMovingAllowed(mapId, x, y, z)) @@ -190,7 +191,7 @@ 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 (disableMoveSplinePath || !generatePath) + if (exact_waypoint || disableMoveSplinePath || !generatePath) { float distance = bot->GetExactDist(x, y, z); if (distance > sPlayerbotAIConfig->contactDistance) @@ -785,28 +786,34 @@ bool MovementAction::ReachCombatTo(Unit* target, float distance) float ty = target->GetPositionY(); float tz = target->GetPositionZ(); float combatDistance = bot->GetCombatReach() + target->GetCombatReach(); - float distanceToTarget = bot->GetExactDist(target) - combatDistance; - float angle = bot->GetAngle(target); - float needToGo = distanceToTarget - distance; + distance += combatDistance; - float maxDistance = sPlayerbotAIConfig->spellDistance; - if (needToGo > 0 && needToGo > maxDistance) - needToGo = maxDistance; - else if (needToGo < 0 && needToGo < -maxDistance) - needToGo = -maxDistance; + if (target->HasUnitMovementFlag(MOVEMENTFLAG_FORWARD)) // target is moving forward, predict the position + { + float needToGo = bot->GetExactDist(target) - distance; + float timeToGo = MoveDelay(abs(needToGo)) + sPlayerbotAIConfig->reactDelay; + float targetMoveDist = timeToGo * target->GetSpeed(MOVE_RUN); + targetMoveDist = std::min(5.0f, targetMoveDist); + tx += targetMoveDist * cos(target->GetOrientation()); + ty += targetMoveDist * sin(target->GetOrientation()); + if (!target->GetMap()->CheckCollisionAndGetValidCoords(target, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), + tx, ty, tz)) + { + // disable prediction if position is invalid + tx = target->GetPositionX(); + ty = target->GetPositionY(); + tz = target->GetPositionZ(); + } + } - float dx = cos(angle) * needToGo + bx; - float dy = sin(angle) * needToGo + by; - float dz; // = std::max(bz, tz); // calc accurate z position to avoid stuck - if (distanceToTarget > CONTACT_DISTANCE) - { - dz = bz + (tz - bz) * (needToGo / distanceToTarget); - } - else - { - dz = tz; - } - return MoveTo(target->GetMapId(), dx, dy, dz); + PathGenerator path(bot); + path.CalculatePath(tx, ty, tz, false); + PathType type = path.GetPathType(); + if (type != PATHFIND_NORMAL && type != PATHFIND_INCOMPLETE) + return false; + path.ShortenPathUntilDist(G3D::Vector3(tx, ty, tz), distance); + G3D::Vector3 endPos = path.GetPath().back(); + return MoveTo(target->GetMapId(), endPos.x, endPos.y, endPos.z); } float MovementAction::GetFollowAngle() @@ -1560,13 +1567,14 @@ const Movement::PointsArray MovementAction::SearchForBestPath(float x, float y, gen.CalculatePath(x, y, tempZ); Movement::PointsArray result = gen.GetPath(); float min_length = gen.getPathLength(); - if ((gen.GetPathType() & PATHFIND_NORMAL) && abs(tempZ - z) < 0.5f) + int typeOk = PATHFIND_NORMAL | PATHFIND_INCOMPLETE; + if ((gen.GetPathType() & typeOk) && abs(tempZ - z) < 0.5f) { modified_z = tempZ; return result; } // Start searching - if (gen.GetPathType() & PATHFIND_NORMAL) + if (gen.GetPathType() & typeOk) { modified_z = tempZ; found = true; @@ -1581,7 +1589,7 @@ const Movement::PointsArray MovementAction::SearchForBestPath(float x, float y, } PathGenerator gen(bot); gen.CalculatePath(x, y, tempZ); - if ((gen.GetPathType() & PATHFIND_NORMAL) && gen.getPathLength() < min_length) + if ((gen.GetPathType() & typeOk) && gen.getPathLength() < min_length) { found = true; min_length = gen.getPathLength(); @@ -1598,7 +1606,7 @@ const Movement::PointsArray MovementAction::SearchForBestPath(float x, float y, } PathGenerator gen(bot); gen.CalculatePath(x, y, tempZ); - if ((gen.GetPathType() & PATHFIND_NORMAL) && gen.getPathLength() < min_length) + if ((gen.GetPathType() & typeOk) && gen.getPathLength() < min_length) { found = true; min_length = gen.getPathLength(); diff --git a/src/strategy/actions/MovementActions.h b/src/strategy/actions/MovementActions.h index d8b178c2..2b8a82fe 100644 --- a/src/strategy/actions/MovementActions.h +++ b/src/strategy/actions/MovementActions.h @@ -27,7 +27,7 @@ protected: bool MoveNear(uint32 mapId, float x, float y, float z, float distance = sPlayerbotAIConfig->contactDistance); bool MoveToLOS(WorldObject* target, bool ranged = false); bool MoveTo(uint32 mapId, float x, float y, float z, bool idle = false, bool react = false, - bool normal_only = false); + bool normal_only = false, bool exact_waypoint = false); bool MoveTo(Unit* target, float distance = 0.0f); bool MoveNear(WorldObject* target, float distance = sPlayerbotAIConfig->contactDistance); float GetFollowAngle(); From bb67c45e64a23779f9678bb1ca687dce651f8470 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Mon, 5 Aug 2024 12:12:00 +0800 Subject: [PATCH 08/14] Code style --- src/strategy/actions/FollowActions.cpp | 3 +- src/strategy/actions/MovementActions.cpp | 7 +- src/strategy/triggers/TriggerContext.h | 374 +++++++++++------------ 3 files changed, 183 insertions(+), 201 deletions(-) diff --git a/src/strategy/actions/FollowActions.cpp b/src/strategy/actions/FollowActions.cpp index d0e6fb6b..81be99a6 100644 --- a/src/strategy/actions/FollowActions.cpp +++ b/src/strategy/actions/FollowActions.cpp @@ -29,7 +29,8 @@ bool FollowAction::Execute(Event event) if (Formation::IsNullLocation(loc) || loc.GetMapId() == -1) return false; - moved = MoveTo(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ(), false, false, false, true); + moved = MoveTo(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ(), false, false, false, + true); } if (Pet* pet = bot->GetPet()) diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index 38ac44a1..3bc458af 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -161,7 +161,8 @@ 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 exact_waypoint) +bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, bool react, bool normal_only, + bool exact_waypoint) { UpdateMovementState(); if (!IsMovingAllowed(mapId, x, y, z)) @@ -796,8 +797,8 @@ bool MovementAction::ReachCombatTo(Unit* target, float distance) targetMoveDist = std::min(5.0f, targetMoveDist); tx += targetMoveDist * cos(target->GetOrientation()); ty += targetMoveDist * sin(target->GetOrientation()); - if (!target->GetMap()->CheckCollisionAndGetValidCoords(target, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), - tx, ty, tz)) + if (!target->GetMap()->CheckCollisionAndGetValidCoords(target, target->GetPositionX(), target->GetPositionY(), + target->GetPositionZ(), tx, ty, tz)) { // disable prediction if position is invalid tx = target->GetPositionX(); diff --git a/src/strategy/triggers/TriggerContext.h b/src/strategy/triggers/TriggerContext.h index 2b5cbd06..d7853110 100644 --- a/src/strategy/triggers/TriggerContext.h +++ b/src/strategy/triggers/TriggerContext.h @@ -184,202 +184,182 @@ public: creators["buy tabard"] = &TriggerContext::buy_tabard; creators["leave large guild"] = &TriggerContext::leave_large_guild; } - private: - static Trigger* give_food(PlayerbotAI * botAI) { return new GiveFoodTrigger(botAI); } - static Trigger* give_water(PlayerbotAI * botAI) { return new GiveWaterTrigger(botAI); } - static Trigger* no_rti(PlayerbotAI * botAI) { return new NoRtiTrigger(botAI); } - static Trigger* _return(PlayerbotAI * botAI) { return new ReturnTrigger(botAI); } - static Trigger* sit(PlayerbotAI * botAI) { return new SitTrigger(botAI); } - static Trigger* far_from_rpg_target(PlayerbotAI * botAI) { return new FarFromRpgTargetTrigger(botAI); } - static Trigger* near_rpg_target(PlayerbotAI * botAI) { return new NearRpgTargetTrigger(botAI); } - static Trigger* far_from_travel_target(PlayerbotAI * botAI) { return new FarFromTravelTargetTrigger(botAI); } - static Trigger* no_travel_target(PlayerbotAI * botAI) { return new NoTravelTargetTrigger(botAI); } - static Trigger* no_rpg_target(PlayerbotAI * botAI) { return new NoRpgTargetTrigger(botAI); } - static Trigger* has_rpg_target(PlayerbotAI * botAI) { return new HasRpgTargetTrigger(botAI); } - static Trigger* collision(PlayerbotAI * botAI) { return new CollisionTrigger(botAI); } - static Trigger* lfg_proposal_active(PlayerbotAI * botAI) { return new LfgProposalActiveTrigger(botAI); } - static Trigger* unknown_dungeon(PlayerbotAI * botAI) { return new UnknownDungeonTrigger(botAI); } - static Trigger* invalid_target(PlayerbotAI * botAI) { return new InvalidTargetTrigger(botAI); } - static Trigger* critical_aoe_heal(PlayerbotAI * botAI) - { - return new AoeHealTrigger(botAI, "critical aoe heal", "critical", 2); - } - static Trigger* low_aoe_heal(PlayerbotAI * botAI) - { - return new AoeHealTrigger(botAI, "low aoe heal", "low", 2); - } - static Trigger* medium_aoe_heal(PlayerbotAI * botAI) - { - return new AoeHealTrigger(botAI, "medium aoe heal", "medium", 2); - } - static Trigger* almost_full_aoe_heal(PlayerbotAI * botAI) - { - return new AoeHealTrigger(botAI, "almost full aoe heal", "almost full", 2); - } - static Trigger* group_heal_occasion(PlayerbotAI * ai) - { - return new AoeInGroupTrigger(ai, "group heal occasion", "almost full", 0.6); - } - static Trigger* medium_group_heal_occasion(PlayerbotAI * ai) - { - return new AoeInGroupTrigger(ai, "group heal occasion", "medium", 0.6); - } - static Trigger* target_changed(PlayerbotAI * botAI) { return new TargetChangedTrigger(botAI); } - static Trigger* swimming(PlayerbotAI * botAI) { return new IsSwimmingTrigger(botAI); } - static Trigger* no_possible_targets(PlayerbotAI * botAI) { return new NoPossibleTargetsTrigger(botAI); } - static Trigger* possible_adds(PlayerbotAI * botAI) { return new PossibleAddsTrigger(botAI); } - static Trigger* can_loot(PlayerbotAI * botAI) { return new CanLootTrigger(botAI); } - static Trigger* far_from_loot_target(PlayerbotAI * botAI) { return new FarFromCurrentLootTrigger(botAI); } - static Trigger* far_from_master(PlayerbotAI * botAI) { return new FarFromMasterTrigger(botAI); } - static Trigger* behind_target(PlayerbotAI * botAI) { return new IsBehindTargetTrigger(botAI); } - static Trigger* not_behind_target(PlayerbotAI * botAI) { return new IsNotBehindTargetTrigger(botAI); } - static Trigger* not_facing_target(PlayerbotAI * botAI) { return new IsNotFacingTargetTrigger(botAI); } - static Trigger* panic(PlayerbotAI * botAI) { return new PanicTrigger(botAI); } - static Trigger* outnumbered(PlayerbotAI * botAI) { return new OutNumberedTrigger(botAI); } - static Trigger* no_drink(PlayerbotAI * botAI) { return new NoDrinkTrigger(botAI); } - static Trigger* no_food(PlayerbotAI * botAI) { return new NoFoodTrigger(botAI); } - static Trigger* LightAoe(PlayerbotAI * botAI) { return new LightAoeTrigger(botAI); } - static Trigger* MediumAoe(PlayerbotAI * botAI) { return new MediumAoeTrigger(botAI); } - static Trigger* HighAoe(PlayerbotAI * botAI) { return new HighAoeTrigger(botAI); } - static Trigger* HasAreaDebuff(PlayerbotAI * botAI) { return new HasAreaDebuffTrigger(botAI); } - static Trigger* LoseAggro(PlayerbotAI * botAI) { return new LoseAggroTrigger(botAI); } - static Trigger* HasAggro(PlayerbotAI * botAI) { return new HasAggroTrigger(botAI); } - static Trigger* LowHealth(PlayerbotAI * botAI) { return new LowHealthTrigger(botAI); } - static Trigger* MediumHealth(PlayerbotAI * botAI) { return new MediumHealthTrigger(botAI); } - static Trigger* AlmostFullHealth(PlayerbotAI * botAI) { return new AlmostFullHealthTrigger(botAI); } - static Trigger* CriticalHealth(PlayerbotAI * botAI) { return new CriticalHealthTrigger(botAI); } - static Trigger* TargetCriticalHealth(PlayerbotAI * botAI) { return new TargetCriticalHealthTrigger(botAI); } - static Trigger* LowMana(PlayerbotAI * botAI) { return new LowManaTrigger(botAI); } - static Trigger* MediumMana(PlayerbotAI * botAI) { return new MediumManaTrigger(botAI); } - static Trigger* HighMana(PlayerbotAI * botAI) { return new HighManaTrigger(botAI); } - static Trigger* AlmostFullMana(PlayerbotAI * botAI) { return new AlmostFullManaTrigger(botAI); } - static Trigger* EnoughMana(PlayerbotAI * botAI) { return new EnoughManaTrigger(botAI); } - static Trigger* LightRageAvailable(PlayerbotAI * botAI) { return new LightRageAvailableTrigger(botAI); } - static Trigger* MediumRageAvailable(PlayerbotAI * botAI) { return new MediumRageAvailableTrigger(botAI); } - static Trigger* HighRageAvailable(PlayerbotAI * botAI) { return new HighRageAvailableTrigger(botAI); } - static Trigger* LightEnergyAvailable(PlayerbotAI * botAI) { return new LightEnergyAvailableTrigger(botAI); } - static Trigger* MediumEnergyAvailable(PlayerbotAI * botAI) { return new MediumEnergyAvailableTrigger(botAI); } - static Trigger* HighEnergyAvailable(PlayerbotAI * botAI) { return new HighEnergyAvailableTrigger(botAI); } - static Trigger* LootAvailable(PlayerbotAI * botAI) { return new LootAvailableTrigger(botAI); } - static Trigger* NoAttackers(PlayerbotAI * botAI) { return new NoAttackersTrigger(botAI); } - static Trigger* TankAssist(PlayerbotAI * botAI) { return new TankAssistTrigger(botAI); } - static Trigger* Timer(PlayerbotAI * botAI) { return new TimerTrigger(botAI); } - static Trigger* NoTarget(PlayerbotAI * botAI) { return new NoTargetTrigger(botAI); } - static Trigger* TargetInSight(PlayerbotAI * botAI) { return new TargetInSightTrigger(botAI); } - static Trigger* not_dps_target_active(PlayerbotAI * botAI) { return new NotDpsTargetActiveTrigger(botAI); } - static Trigger* not_dps_aoe_target_active(PlayerbotAI * botAI) - { - return new NotDpsAoeTargetActiveTrigger(botAI); - } - static Trigger* has_nearest_adds(PlayerbotAI * botAI) { return new HasNearestAddsTrigger(botAI); } - static Trigger* enemy_player_near(PlayerbotAI * botAI) { return new EnemyPlayerNear(botAI); } - static Trigger* Random(PlayerbotAI * botAI) { return new RandomTrigger(botAI, "random", 20); } - static Trigger* seldom(PlayerbotAI * botAI) { return new RandomTrigger(botAI, "seldom", 300); } - static Trigger* often(PlayerbotAI * botAI) { return new RandomTrigger(botAI, "often", 5); } - static Trigger* EnemyOutOfMelee(PlayerbotAI * botAI) { return new EnemyOutOfMeleeTrigger(botAI); } - static Trigger* EnemyOutOfSpell(PlayerbotAI * botAI) { return new EnemyOutOfSpellRangeTrigger(botAI); } - static Trigger* enemy_too_close_for_spell(PlayerbotAI * botAI) - { - return new EnemyTooCloseForSpellTrigger(botAI); - } - static Trigger* enemy_too_close_for_auto_shot(PlayerbotAI * botAI) - { - return new EnemyTooCloseForAutoShotTrigger(botAI); - } - static Trigger* enemy_too_close_for_shoot(PlayerbotAI * botAI) - { - return new EnemyTooCloseForShootTrigger(botAI); - } - static Trigger* enemy_too_close_for_melee(PlayerbotAI * botAI) - { - return new EnemyTooCloseForMeleeTrigger(botAI); - } - static Trigger* enemy_is_close(PlayerbotAI * botAI) { return new EnemyIsCloseTrigger(botAI); } - static Trigger* enemy_within_melee(PlayerbotAI * botAI) { return new EnemyWithinMeleeTrigger(botAI); } - static Trigger* party_member_to_heal_out_of_spell_range(PlayerbotAI * botAI) - { - return new PartyMemberToHealOutOfSpellRangeTrigger(botAI); - } - static Trigger* ComboPointsAvailable(PlayerbotAI * botAI) { return new ComboPointsAvailableTrigger(botAI); } - static Trigger* ComboPoints3Available(PlayerbotAI * botAI) { return new ComboPointsAvailableTrigger(botAI, 3); } - static Trigger* MediumThreat(PlayerbotAI * botAI) { return new MediumThreatTrigger(botAI); } - static Trigger* Dead(PlayerbotAI * botAI) { return new DeadTrigger(botAI); } - static Trigger* corpse_near(PlayerbotAI * botAI) { return new CorpseNearTrigger(botAI); } - static Trigger* PartyMemberDead(PlayerbotAI * botAI) { return new PartyMemberDeadTrigger(botAI); } - static Trigger* CombatPartyMemberDead(PlayerbotAI * botAI) { return new CombatPartyMemberDeadTrigger(botAI); } - static Trigger* PartyMemberLowHealth(PlayerbotAI * botAI) { return new PartyMemberLowHealthTrigger(botAI); } - static Trigger* PartyMemberMediumHealth(PlayerbotAI * botAI) - { - return new PartyMemberMediumHealthTrigger(botAI); - } - static Trigger* PartyMemberAlmostFullHealth(PlayerbotAI * botAI) - { - return new PartyMemberAlmostFullHealthTrigger(botAI); - } - static Trigger* PartyMemberCriticalHealth(PlayerbotAI * botAI) - { - return new PartyMemberCriticalHealthTrigger(botAI); - } - static Trigger* protect_party_member(PlayerbotAI * botAI) { return new ProtectPartyMemberTrigger(botAI); } - static Trigger* no_pet(PlayerbotAI * botAI) { return new NoPetTrigger(botAI); } - static Trigger* has_pet(PlayerbotAI * botAI) { return new HasPetTrigger(botAI); } - static Trigger* pet_attack(PlayerbotAI * botAI) { return new PetAttackTrigger(botAI); } - static Trigger* has_attackers(PlayerbotAI * botAI) { return new HasAttackersTrigger(botAI); } - static Trigger* random_bot_update_trigger(PlayerbotAI * botAI) { return new RandomBotUpdateTrigger(botAI); } - static Trigger* no_non_bot_players_around(PlayerbotAI * botAI) - { - return new NoNonBotPlayersAroundTrigger(botAI); - } - static Trigger* new_player_nearby(PlayerbotAI * botAI) { return new NewPlayerNearbyTrigger(botAI); } - static Trigger* bg_waiting(PlayerbotAI * botAI) { return new BgWaitingTrigger(botAI); } - static Trigger* bg_active(PlayerbotAI * botAI) { return new BgActiveTrigger(botAI); } - static Trigger* bg_invite_active(PlayerbotAI * botAI) { return new BgInviteActiveTrigger(botAI); } - static Trigger* inside_bg(PlayerbotAI * botAI) { return new InsideBGTrigger(botAI); } - static Trigger* player_has_no_flag(PlayerbotAI * botAI) { return new PlayerHasNoFlag(botAI); } - static Trigger* player_has_flag(PlayerbotAI * botAI) { return new PlayerHasFlag(botAI); } - static Trigger* team_has_flag(PlayerbotAI * botAI) { return new TeamHasFlag(botAI); } - static Trigger* enemy_team_has_flag(PlayerbotAI * botAI) { return new EnemyTeamHasFlag(botAI); } - static Trigger* enemy_flagcarrier_near(PlayerbotAI * botAI) { return new EnemyFlagCarrierNear(botAI); } - static Trigger* player_is_in_BATTLEGROUND(PlayerbotAI * botAI) { return new PlayerIsInBattleground(botAI); } - static Trigger* player_is_in_BATTLEGROUND_no_flag(PlayerbotAI * botAI) - { - return new PlayerIsInBattlegroundWithoutFlag(botAI); - } - static Trigger* mounted(PlayerbotAI * botAI) { return new IsMountedTrigger(botAI); } - static Trigger* at_dark_portal_outland(PlayerbotAI * botAI) { return new AtDarkPortalOutlandTrigger(botAI); } - static Trigger* at_dark_portal_azeroth(PlayerbotAI * botAI) { return new AtDarkPortalAzerothTrigger(botAI); } - static Trigger* in_vehicle(PlayerbotAI * botAI) { return new InVehicleTrigger(botAI); } - static Trigger* vehicle_near(PlayerbotAI * botAI) { return new VehicleNearTrigger(botAI); } - static Trigger* near_dark_portal(PlayerbotAI * botAI) { return new NearDarkPortalTrigger(botAI); } - static Trigger* need_world_buff(PlayerbotAI * botAI) { return new NeedWorldBuffTrigger(botAI); } - static Trigger* falling(PlayerbotAI * botAI) { return new IsFallingTrigger(botAI); } - static Trigger* falling_far(PlayerbotAI * botAI) { return new IsFallingFarTrigger(botAI); } - static Trigger* move_stuck(PlayerbotAI * botAI) { return new MoveStuckTrigger(botAI); } - static Trigger* move_long_stuck(PlayerbotAI * botAI) { return new MoveLongStuckTrigger(botAI); } - static Trigger* combat_stuck(PlayerbotAI * botAI) { return new CombatStuckTrigger(botAI); } - static Trigger* combat_long_stuck(PlayerbotAI * botAI) { return new CombatLongStuckTrigger(botAI); } - static Trigger* player_wants_in_bg(PlayerbotAI * botAI) { return new PlayerWantsInBattlegroundTrigger(botAI); } - static Trigger* petition_signed(PlayerbotAI * botAI) { return new PetitionTurnInTrigger(botAI); } - static Trigger* buy_tabard(PlayerbotAI * botAI) { return new BuyTabardTrigger(botAI); } - static Trigger* leave_large_guild(PlayerbotAI * botAI) { return new LeaveLargeGuildTrigger(botAI); } - static Trigger* rpg(PlayerbotAI * botAI) { return new RpgTrigger(botAI); } - static Trigger* rpg_taxi(PlayerbotAI * botAI) { return new RpgTaxiTrigger(botAI); } - static Trigger* rpg_discover(PlayerbotAI * botAI) { return new RpgDiscoverTrigger(botAI); } - static Trigger* rpg_start_quest(PlayerbotAI * botAI) { return new RpgStartQuestTrigger(botAI); } - static Trigger* rpg_end_quest(PlayerbotAI * botAI) { return new RpgEndQuestTrigger(botAI); } - static Trigger* rpg_buy(PlayerbotAI * botAI) { return new RpgBuyTrigger(botAI); } - static Trigger* rpg_sell(PlayerbotAI * botAI) { return new RpgSellTrigger(botAI); } - static Trigger* rpg_repair(PlayerbotAI * botAI) { return new RpgRepairTrigger(botAI); } - static Trigger* rpg_train(PlayerbotAI * botAI) { return new RpgTrainTrigger(botAI); } - static Trigger* rpg_heal(PlayerbotAI * botAI) { return new RpgHealTrigger(botAI); } - static Trigger* rpg_home_bind(PlayerbotAI * botAI) { return new RpgHomeBindTrigger(botAI); } - static Trigger* rpg_queue_bg(PlayerbotAI * botAI) { return new RpgQueueBGTrigger(botAI); } - static Trigger* rpg_buy_petition(PlayerbotAI * botAI) { return new RpgBuyPetitionTrigger(botAI); } - static Trigger* rpg_use(PlayerbotAI * botAI) { return new RpgUseTrigger(botAI); } - static Trigger* rpg_spell(PlayerbotAI * botAI) { return new RpgUseTrigger(botAI); } - static Trigger* rpg_craft(PlayerbotAI * botAI) { return new RpgCraftTrigger(botAI); } - static Trigger* rpg_trade_useful(PlayerbotAI * botAI) { return new RpgTradeUsefulTrigger(botAI); } - static Trigger* rpg_duel(PlayerbotAI * botAI) { return new RpgDuelTrigger(botAI); } - }; + +private: + static Trigger* give_food(PlayerbotAI* botAI) { return new GiveFoodTrigger(botAI); } + static Trigger* give_water(PlayerbotAI* botAI) { return new GiveWaterTrigger(botAI); } + static Trigger* no_rti(PlayerbotAI* botAI) { return new NoRtiTrigger(botAI); } + static Trigger* _return(PlayerbotAI* botAI) { return new ReturnTrigger(botAI); } + static Trigger* sit(PlayerbotAI* botAI) { return new SitTrigger(botAI); } + static Trigger* far_from_rpg_target(PlayerbotAI* botAI) { return new FarFromRpgTargetTrigger(botAI); } + static Trigger* near_rpg_target(PlayerbotAI* botAI) { return new NearRpgTargetTrigger(botAI); } + static Trigger* far_from_travel_target(PlayerbotAI* botAI) { return new FarFromTravelTargetTrigger(botAI); } + static Trigger* no_travel_target(PlayerbotAI* botAI) { return new NoTravelTargetTrigger(botAI); } + static Trigger* no_rpg_target(PlayerbotAI* botAI) { return new NoRpgTargetTrigger(botAI); } + static Trigger* has_rpg_target(PlayerbotAI* botAI) { return new HasRpgTargetTrigger(botAI); } + static Trigger* collision(PlayerbotAI* botAI) { return new CollisionTrigger(botAI); } + static Trigger* lfg_proposal_active(PlayerbotAI* botAI) { return new LfgProposalActiveTrigger(botAI); } + static Trigger* unknown_dungeon(PlayerbotAI* botAI) { return new UnknownDungeonTrigger(botAI); } + static Trigger* invalid_target(PlayerbotAI* botAI) { return new InvalidTargetTrigger(botAI); } + static Trigger* critical_aoe_heal(PlayerbotAI* botAI) + { + return new AoeHealTrigger(botAI, "critical aoe heal", "critical", 2); + } + static Trigger* low_aoe_heal(PlayerbotAI* botAI) { return new AoeHealTrigger(botAI, "low aoe heal", "low", 2); } + static Trigger* medium_aoe_heal(PlayerbotAI* botAI) + { + return new AoeHealTrigger(botAI, "medium aoe heal", "medium", 2); + } + static Trigger* almost_full_aoe_heal(PlayerbotAI* botAI) + { + return new AoeHealTrigger(botAI, "almost full aoe heal", "almost full", 2); + } + static Trigger* group_heal_occasion(PlayerbotAI* ai) + { + return new AoeInGroupTrigger(ai, "group heal occasion", "almost full", 0.6); + } + static Trigger* medium_group_heal_occasion(PlayerbotAI* ai) + { + return new AoeInGroupTrigger(ai, "group heal occasion", "medium", 0.6); + } + static Trigger* target_changed(PlayerbotAI* botAI) { return new TargetChangedTrigger(botAI); } + static Trigger* swimming(PlayerbotAI* botAI) { return new IsSwimmingTrigger(botAI); } + static Trigger* no_possible_targets(PlayerbotAI* botAI) { return new NoPossibleTargetsTrigger(botAI); } + static Trigger* possible_adds(PlayerbotAI* botAI) { return new PossibleAddsTrigger(botAI); } + static Trigger* can_loot(PlayerbotAI* botAI) { return new CanLootTrigger(botAI); } + static Trigger* far_from_loot_target(PlayerbotAI* botAI) { return new FarFromCurrentLootTrigger(botAI); } + static Trigger* far_from_master(PlayerbotAI* botAI) { return new FarFromMasterTrigger(botAI); } + static Trigger* behind_target(PlayerbotAI* botAI) { return new IsBehindTargetTrigger(botAI); } + static Trigger* not_behind_target(PlayerbotAI* botAI) { return new IsNotBehindTargetTrigger(botAI); } + static Trigger* not_facing_target(PlayerbotAI* botAI) { return new IsNotFacingTargetTrigger(botAI); } + static Trigger* panic(PlayerbotAI* botAI) { return new PanicTrigger(botAI); } + static Trigger* outnumbered(PlayerbotAI* botAI) { return new OutNumberedTrigger(botAI); } + static Trigger* no_drink(PlayerbotAI* botAI) { return new NoDrinkTrigger(botAI); } + static Trigger* no_food(PlayerbotAI* botAI) { return new NoFoodTrigger(botAI); } + static Trigger* LightAoe(PlayerbotAI* botAI) { return new LightAoeTrigger(botAI); } + static Trigger* MediumAoe(PlayerbotAI* botAI) { return new MediumAoeTrigger(botAI); } + static Trigger* HighAoe(PlayerbotAI* botAI) { return new HighAoeTrigger(botAI); } + static Trigger* HasAreaDebuff(PlayerbotAI* botAI) { return new HasAreaDebuffTrigger(botAI); } + static Trigger* LoseAggro(PlayerbotAI* botAI) { return new LoseAggroTrigger(botAI); } + static Trigger* HasAggro(PlayerbotAI* botAI) { return new HasAggroTrigger(botAI); } + static Trigger* LowHealth(PlayerbotAI* botAI) { return new LowHealthTrigger(botAI); } + static Trigger* MediumHealth(PlayerbotAI* botAI) { return new MediumHealthTrigger(botAI); } + static Trigger* AlmostFullHealth(PlayerbotAI* botAI) { return new AlmostFullHealthTrigger(botAI); } + static Trigger* CriticalHealth(PlayerbotAI* botAI) { return new CriticalHealthTrigger(botAI); } + static Trigger* TargetCriticalHealth(PlayerbotAI* botAI) { return new TargetCriticalHealthTrigger(botAI); } + static Trigger* LowMana(PlayerbotAI* botAI) { return new LowManaTrigger(botAI); } + static Trigger* MediumMana(PlayerbotAI* botAI) { return new MediumManaTrigger(botAI); } + static Trigger* HighMana(PlayerbotAI* botAI) { return new HighManaTrigger(botAI); } + static Trigger* AlmostFullMana(PlayerbotAI* botAI) { return new AlmostFullManaTrigger(botAI); } + static Trigger* EnoughMana(PlayerbotAI* botAI) { return new EnoughManaTrigger(botAI); } + static Trigger* LightRageAvailable(PlayerbotAI* botAI) { return new LightRageAvailableTrigger(botAI); } + static Trigger* MediumRageAvailable(PlayerbotAI* botAI) { return new MediumRageAvailableTrigger(botAI); } + static Trigger* HighRageAvailable(PlayerbotAI* botAI) { return new HighRageAvailableTrigger(botAI); } + static Trigger* LightEnergyAvailable(PlayerbotAI* botAI) { return new LightEnergyAvailableTrigger(botAI); } + static Trigger* MediumEnergyAvailable(PlayerbotAI* botAI) { return new MediumEnergyAvailableTrigger(botAI); } + static Trigger* HighEnergyAvailable(PlayerbotAI* botAI) { return new HighEnergyAvailableTrigger(botAI); } + static Trigger* LootAvailable(PlayerbotAI* botAI) { return new LootAvailableTrigger(botAI); } + static Trigger* NoAttackers(PlayerbotAI* botAI) { return new NoAttackersTrigger(botAI); } + static Trigger* TankAssist(PlayerbotAI* botAI) { return new TankAssistTrigger(botAI); } + static Trigger* Timer(PlayerbotAI* botAI) { return new TimerTrigger(botAI); } + static Trigger* NoTarget(PlayerbotAI* botAI) { return new NoTargetTrigger(botAI); } + static Trigger* TargetInSight(PlayerbotAI* botAI) { return new TargetInSightTrigger(botAI); } + static Trigger* not_dps_target_active(PlayerbotAI* botAI) { return new NotDpsTargetActiveTrigger(botAI); } + static Trigger* not_dps_aoe_target_active(PlayerbotAI* botAI) { return new NotDpsAoeTargetActiveTrigger(botAI); } + static Trigger* has_nearest_adds(PlayerbotAI* botAI) { return new HasNearestAddsTrigger(botAI); } + static Trigger* enemy_player_near(PlayerbotAI* botAI) { return new EnemyPlayerNear(botAI); } + static Trigger* Random(PlayerbotAI* botAI) { return new RandomTrigger(botAI, "random", 20); } + static Trigger* seldom(PlayerbotAI* botAI) { return new RandomTrigger(botAI, "seldom", 300); } + static Trigger* often(PlayerbotAI* botAI) { return new RandomTrigger(botAI, "often", 5); } + static Trigger* EnemyOutOfMelee(PlayerbotAI* botAI) { return new EnemyOutOfMeleeTrigger(botAI); } + static Trigger* EnemyOutOfSpell(PlayerbotAI* botAI) { return new EnemyOutOfSpellRangeTrigger(botAI); } + static Trigger* enemy_too_close_for_spell(PlayerbotAI* botAI) { return new EnemyTooCloseForSpellTrigger(botAI); } + static Trigger* enemy_too_close_for_auto_shot(PlayerbotAI* botAI) + { + return new EnemyTooCloseForAutoShotTrigger(botAI); + } + static Trigger* enemy_too_close_for_shoot(PlayerbotAI* botAI) { return new EnemyTooCloseForShootTrigger(botAI); } + static Trigger* enemy_too_close_for_melee(PlayerbotAI* botAI) { return new EnemyTooCloseForMeleeTrigger(botAI); } + static Trigger* enemy_is_close(PlayerbotAI* botAI) { return new EnemyIsCloseTrigger(botAI); } + static Trigger* enemy_within_melee(PlayerbotAI* botAI) { return new EnemyWithinMeleeTrigger(botAI); } + static Trigger* party_member_to_heal_out_of_spell_range(PlayerbotAI* botAI) + { + return new PartyMemberToHealOutOfSpellRangeTrigger(botAI); + } + static Trigger* ComboPointsAvailable(PlayerbotAI* botAI) { return new ComboPointsAvailableTrigger(botAI); } + static Trigger* ComboPoints3Available(PlayerbotAI* botAI) { return new ComboPointsAvailableTrigger(botAI, 3); } + static Trigger* MediumThreat(PlayerbotAI* botAI) { return new MediumThreatTrigger(botAI); } + static Trigger* Dead(PlayerbotAI* botAI) { return new DeadTrigger(botAI); } + static Trigger* corpse_near(PlayerbotAI* botAI) { return new CorpseNearTrigger(botAI); } + static Trigger* PartyMemberDead(PlayerbotAI* botAI) { return new PartyMemberDeadTrigger(botAI); } + static Trigger* CombatPartyMemberDead(PlayerbotAI* botAI) { return new CombatPartyMemberDeadTrigger(botAI); } + static Trigger* PartyMemberLowHealth(PlayerbotAI* botAI) { return new PartyMemberLowHealthTrigger(botAI); } + static Trigger* PartyMemberMediumHealth(PlayerbotAI* botAI) { return new PartyMemberMediumHealthTrigger(botAI); } + static Trigger* PartyMemberAlmostFullHealth(PlayerbotAI* botAI) + { + return new PartyMemberAlmostFullHealthTrigger(botAI); + } + static Trigger* PartyMemberCriticalHealth(PlayerbotAI* botAI) + { + return new PartyMemberCriticalHealthTrigger(botAI); + } + static Trigger* protect_party_member(PlayerbotAI* botAI) { return new ProtectPartyMemberTrigger(botAI); } + static Trigger* no_pet(PlayerbotAI* botAI) { return new NoPetTrigger(botAI); } + static Trigger* has_pet(PlayerbotAI* botAI) { return new HasPetTrigger(botAI); } + static Trigger* pet_attack(PlayerbotAI* botAI) { return new PetAttackTrigger(botAI); } + static Trigger* has_attackers(PlayerbotAI* botAI) { return new HasAttackersTrigger(botAI); } + static Trigger* random_bot_update_trigger(PlayerbotAI* botAI) { return new RandomBotUpdateTrigger(botAI); } + static Trigger* no_non_bot_players_around(PlayerbotAI* botAI) { return new NoNonBotPlayersAroundTrigger(botAI); } + static Trigger* new_player_nearby(PlayerbotAI* botAI) { return new NewPlayerNearbyTrigger(botAI); } + static Trigger* bg_waiting(PlayerbotAI* botAI) { return new BgWaitingTrigger(botAI); } + static Trigger* bg_active(PlayerbotAI* botAI) { return new BgActiveTrigger(botAI); } + static Trigger* bg_invite_active(PlayerbotAI* botAI) { return new BgInviteActiveTrigger(botAI); } + static Trigger* inside_bg(PlayerbotAI* botAI) { return new InsideBGTrigger(botAI); } + static Trigger* player_has_no_flag(PlayerbotAI* botAI) { return new PlayerHasNoFlag(botAI); } + static Trigger* player_has_flag(PlayerbotAI* botAI) { return new PlayerHasFlag(botAI); } + static Trigger* team_has_flag(PlayerbotAI* botAI) { return new TeamHasFlag(botAI); } + static Trigger* enemy_team_has_flag(PlayerbotAI* botAI) { return new EnemyTeamHasFlag(botAI); } + static Trigger* enemy_flagcarrier_near(PlayerbotAI* botAI) { return new EnemyFlagCarrierNear(botAI); } + static Trigger* player_is_in_BATTLEGROUND(PlayerbotAI* botAI) { return new PlayerIsInBattleground(botAI); } + static Trigger* player_is_in_BATTLEGROUND_no_flag(PlayerbotAI* botAI) + { + return new PlayerIsInBattlegroundWithoutFlag(botAI); + } + static Trigger* mounted(PlayerbotAI* botAI) { return new IsMountedTrigger(botAI); } + static Trigger* at_dark_portal_outland(PlayerbotAI* botAI) { return new AtDarkPortalOutlandTrigger(botAI); } + static Trigger* at_dark_portal_azeroth(PlayerbotAI* botAI) { return new AtDarkPortalAzerothTrigger(botAI); } + static Trigger* in_vehicle(PlayerbotAI* botAI) { return new InVehicleTrigger(botAI); } + static Trigger* vehicle_near(PlayerbotAI* botAI) { return new VehicleNearTrigger(botAI); } + static Trigger* near_dark_portal(PlayerbotAI* botAI) { return new NearDarkPortalTrigger(botAI); } + static Trigger* need_world_buff(PlayerbotAI* botAI) { return new NeedWorldBuffTrigger(botAI); } + static Trigger* falling(PlayerbotAI* botAI) { return new IsFallingTrigger(botAI); } + static Trigger* falling_far(PlayerbotAI* botAI) { return new IsFallingFarTrigger(botAI); } + static Trigger* move_stuck(PlayerbotAI* botAI) { return new MoveStuckTrigger(botAI); } + static Trigger* move_long_stuck(PlayerbotAI* botAI) { return new MoveLongStuckTrigger(botAI); } + static Trigger* combat_stuck(PlayerbotAI* botAI) { return new CombatStuckTrigger(botAI); } + static Trigger* combat_long_stuck(PlayerbotAI* botAI) { return new CombatLongStuckTrigger(botAI); } + static Trigger* player_wants_in_bg(PlayerbotAI* botAI) { return new PlayerWantsInBattlegroundTrigger(botAI); } + static Trigger* petition_signed(PlayerbotAI* botAI) { return new PetitionTurnInTrigger(botAI); } + static Trigger* buy_tabard(PlayerbotAI* botAI) { return new BuyTabardTrigger(botAI); } + static Trigger* leave_large_guild(PlayerbotAI* botAI) { return new LeaveLargeGuildTrigger(botAI); } + static Trigger* rpg(PlayerbotAI* botAI) { return new RpgTrigger(botAI); } + static Trigger* rpg_taxi(PlayerbotAI* botAI) { return new RpgTaxiTrigger(botAI); } + static Trigger* rpg_discover(PlayerbotAI* botAI) { return new RpgDiscoverTrigger(botAI); } + static Trigger* rpg_start_quest(PlayerbotAI* botAI) { return new RpgStartQuestTrigger(botAI); } + static Trigger* rpg_end_quest(PlayerbotAI* botAI) { return new RpgEndQuestTrigger(botAI); } + static Trigger* rpg_buy(PlayerbotAI* botAI) { return new RpgBuyTrigger(botAI); } + static Trigger* rpg_sell(PlayerbotAI* botAI) { return new RpgSellTrigger(botAI); } + static Trigger* rpg_repair(PlayerbotAI* botAI) { return new RpgRepairTrigger(botAI); } + static Trigger* rpg_train(PlayerbotAI* botAI) { return new RpgTrainTrigger(botAI); } + static Trigger* rpg_heal(PlayerbotAI* botAI) { return new RpgHealTrigger(botAI); } + static Trigger* rpg_home_bind(PlayerbotAI* botAI) { return new RpgHomeBindTrigger(botAI); } + static Trigger* rpg_queue_bg(PlayerbotAI* botAI) { return new RpgQueueBGTrigger(botAI); } + static Trigger* rpg_buy_petition(PlayerbotAI* botAI) { return new RpgBuyPetitionTrigger(botAI); } + static Trigger* rpg_use(PlayerbotAI* botAI) { return new RpgUseTrigger(botAI); } + static Trigger* rpg_spell(PlayerbotAI* botAI) { return new RpgUseTrigger(botAI); } + static Trigger* rpg_craft(PlayerbotAI* botAI) { return new RpgCraftTrigger(botAI); } + static Trigger* rpg_trade_useful(PlayerbotAI* botAI) { return new RpgTradeUsefulTrigger(botAI); } + static Trigger* rpg_duel(PlayerbotAI* botAI) { return new RpgDuelTrigger(botAI); } +}; #endif From f801fbdf30d112e9ea14a3c7643d242ba02ffe85 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Mon, 5 Aug 2024 13:39:44 +0800 Subject: [PATCH 09/14] Config for fast react in bg --- conf/playerbots.conf.dist | 3 +++ src/PlayerbotAI.cpp | 4 +++- src/PlayerbotAIConfig.cpp | 2 +- src/PlayerbotAIConfig.h | 1 + 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index 2cf012a7..9be0057e 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -691,6 +691,9 @@ AiPlayerbot.PvpProhibitedZoneIds = "2255,656,2361,2362,2363,976,35,2268,3425,392 # PvP Restricted Areas (bots don't pvp) AiPlayerbot.PvpProhibitedAreaIds = "976,35,392" +# Improve react speed in battleground and arena (may cause lag) +AiPlayerbot.FastReactInBG = 1 + # # # diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index 3c610ad0..1b8b7314 100644 --- a/src/PlayerbotAI.cpp +++ b/src/PlayerbotAI.cpp @@ -30,6 +30,7 @@ #include "ObjectGuid.h" #include "PerformanceMonitor.h" #include "Player.h" +#include "PlayerbotAIConfig.h" #include "PlayerbotDbStore.h" #include "PlayerbotMgr.h" #include "Playerbots.h" @@ -334,10 +335,11 @@ void PlayerbotAI::UpdateAI(uint32 elapsed, bool minimal) UpdateAIInternal(elapsed, min); inCombat = bot->IsInCombat(); // test fix lags because of BG + bool inBG = bot->InBattleground() || bot->InArena(); if (bot && !inCombat) min = true; - if (HasRealPlayerMaster()) + if (HasRealPlayerMaster() || (sPlayerbotAIConfig->fastReactInBG && inBG)) min = false; YieldThread(min); diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index d567e058..2ec92965 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -125,7 +125,7 @@ bool PlayerbotAIConfig::Initialize() pvpProhibitedZoneIds); LoadList>(sConfigMgr->GetOption("AiPlayerbot.PvpProhibitedAreaIds", "976,35"), pvpProhibitedAreaIds); - + fastReactInBG = sConfigMgr->GetOption("AiPlayerbot.FastReactInBG", true); LoadList>( sConfigMgr->GetOption("AiPlayerbot.RandomBotQuestIds", "7848,3802,5505,6502,7761"), randomBotQuestIds); diff --git a/src/PlayerbotAIConfig.h b/src/PlayerbotAIConfig.h index c4209bd9..804f273f 100644 --- a/src/PlayerbotAIConfig.h +++ b/src/PlayerbotAIConfig.h @@ -139,6 +139,7 @@ public: std::vector randomBotGuilds; std::vector pvpProhibitedZoneIds; std::vector pvpProhibitedAreaIds; + bool fastReactInBG; bool randombotsWalkingRPG; bool randombotsWalkingRPGInDoors; From 22bb8d83c71469e731da4336a11c1c0e6f99a2f4 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Mon, 5 Aug 2024 13:40:53 +0800 Subject: [PATCH 10/14] Ensure move to rpg target a valid position --- src/strategy/actions/MoveToRpgTargetAction.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/strategy/actions/MoveToRpgTargetAction.cpp b/src/strategy/actions/MoveToRpgTargetAction.cpp index d13b5669..9640fc5c 100644 --- a/src/strategy/actions/MoveToRpgTargetAction.cpp +++ b/src/strategy/actions/MoveToRpgTargetAction.cpp @@ -94,15 +94,21 @@ bool MoveToRpgTargetAction::Execute(Event event) x += cos(angle) * INTERACTION_DISTANCE * distance; y += sin(angle) * INTERACTION_DISTANCE * distance; - + if (!wo->GetMap()->CheckCollisionAndGetValidCoords(wo, wo->GetPositionX(), wo->GetPositionY(), wo->GetPositionZ(), + x, y, z)) + { + x = wo->GetPositionX(); + y = wo->GetPositionY(); + z = wo->GetPositionZ(); + } // WaitForReach(distance); bool couldMove = false; - if (bot->IsWithinLOS(x, y, z)) - couldMove = MoveNear(mapId, x, y, z, 0); - else - couldMove = MoveTo(mapId, x, y, z); + // if (bot->IsWithinLOS(x, y, z)) + // couldMove = MoveNear(mapId, x, y, z, 0); + // else + couldMove = MoveTo(mapId, x, y, z, false, false, false, true); if (!couldMove && WorldPosition(mapId, x, y, z).distance(bot) > INTERACTION_DISTANCE) { From 4754252eeb6cf02e556087eaf7c5a94ee8b49048 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Mon, 5 Aug 2024 14:14:43 +0800 Subject: [PATCH 11/14] Waypoint for move random --- src/strategy/actions/MovementActions.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index 3bc458af..fc999005 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -2325,12 +2325,15 @@ 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); - bot->UpdateGroundPositionZ(x, y, z); - + if (!bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(), + bot->GetPositionZ(), x, y, z)) + { + continue; + } if (map->IsInWater(bot->GetPhaseMask(), x, y, z, bot->GetCollisionHeight())) continue; - bool moved = MoveTo(bot->GetMapId(), x, y, z); + bool moved = MoveTo(bot->GetMapId(), x, y, z, false, false, false, true); if (moved) return true; } From 5504f36a9c804fb63f074291ca12fa6b57f0bbc6 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Mon, 5 Aug 2024 14:34:27 +0800 Subject: [PATCH 12/14] Try to fix macos CI --- .github/workflows/macos_build.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/macos_build.yml b/.github/workflows/macos_build.yml index 3fd3ec97..42415caf 100644 --- a/.github/workflows/macos_build.yml +++ b/.github/workflows/macos_build.yml @@ -29,14 +29,14 @@ jobs: with: repository: 'liyunfan1223/mod-playerbots' path: 'modules/mod-playerbots' - - name: Cache - uses: actions/cache@v3 - with: - path: ~/Library/Caches/ccache - key: ccache:${{ matrix.os }}:${{ github.ref }}:${{ github.sha }} - restore-keys: | - ccache:${{ matrix.os }}:${{ github.ref }} - ccache:${{ matrix.os }} + # - name: Cache + # uses: actions/cache@v3 + # with: + # path: ~/Library/Caches/ccache + # key: ccache:${{ matrix.os }}:${{ github.ref }}:${{ github.sha }} + # restore-keys: | + # ccache:${{ matrix.os }}:${{ github.ref }} + # ccache:${{ matrix.os }} - name: Install latest bash run: brew install bash - name: Configure OS From 8638e3bebef51c9c6c674ab1d83ceeaa7d5356c1 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Mon, 5 Aug 2024 21:26:24 +0800 Subject: [PATCH 13/14] macos CI --- .github/workflows/macos_build.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/macos_build.yml b/.github/workflows/macos_build.yml index 42415caf..5ea55963 100644 --- a/.github/workflows/macos_build.yml +++ b/.github/workflows/macos_build.yml @@ -20,23 +20,23 @@ jobs: name: ${{ matrix.os }} steps: - name: Checkout AzerothCore - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: 'liyunfan1223/azerothcore-wotlk' ref: 'Playerbot' - name: Checkout Playerbot Module - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: 'liyunfan1223/mod-playerbots' path: 'modules/mod-playerbots' - # - name: Cache - # uses: actions/cache@v3 - # with: - # path: ~/Library/Caches/ccache - # key: ccache:${{ matrix.os }}:${{ github.ref }}:${{ github.sha }} - # restore-keys: | - # ccache:${{ matrix.os }}:${{ github.ref }} - # ccache:${{ matrix.os }} + - name: Cache + uses: actions/cache@v4 + with: + path: ~/Library/Caches/ccache + key: ccache:${{ matrix.os }}:${{ github.ref }}:${{ github.sha }} + restore-keys: | + ccache:${{ matrix.os }}:${{ github.ref }} + ccache:${{ matrix.os }} - name: Install latest bash run: brew install bash - name: Configure OS From 72b32a159082483438e3bca1ed222a51c11adbe6 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Mon, 5 Aug 2024 21:41:39 +0800 Subject: [PATCH 14/14] Add missing rpg triggers --- src/strategy/triggers/TriggerContext.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/strategy/triggers/TriggerContext.h b/src/strategy/triggers/TriggerContext.h index d7853110..a10d9ca7 100644 --- a/src/strategy/triggers/TriggerContext.h +++ b/src/strategy/triggers/TriggerContext.h @@ -183,6 +183,25 @@ public: creators["petition signed"] = &TriggerContext::petition_signed; creators["buy tabard"] = &TriggerContext::buy_tabard; creators["leave large guild"] = &TriggerContext::leave_large_guild; + + creators["rpg"] = &TriggerContext::rpg; + creators["rpg taxi"] = &TriggerContext::rpg_taxi; + creators["rpg discover"] = &TriggerContext::rpg_discover; + creators["rpg start quest"] = &TriggerContext::rpg_start_quest; + creators["rpg end quest"] = &TriggerContext::rpg_end_quest; + creators["rpg buy"] = &TriggerContext::rpg_buy; + creators["rpg sell"] = &TriggerContext::rpg_sell; + creators["rpg repair"] = &TriggerContext::rpg_repair; + creators["rpg train"] = &TriggerContext::rpg_train; + creators["rpg heal"] = &TriggerContext::rpg_heal; + creators["rpg home bind"] = &TriggerContext::rpg_home_bind; + creators["rpg queue bg"] = &TriggerContext::rpg_queue_bg; + creators["rpg buy petition"] = &TriggerContext::rpg_buy_petition; + creators["rpg use"] = &TriggerContext::rpg_use; + creators["rpg spell"] = &TriggerContext::rpg_spell; + creators["rpg craft"] = &TriggerContext::rpg_craft; + creators["rpg trade useful"] = &TriggerContext::rpg_trade_useful; + creators["rpg duel"] = &TriggerContext::rpg_duel; } private: