-
Notifications
You must be signed in to change notification settings - Fork 0
Feature/configurable combat delay #72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
2eb98c3
a1137db
0a8cad3
05b41bd
03841c9
bb4e5d6
f6302f3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,15 +5,18 @@ | |
|
|
||
| #include "AttackAction.h" | ||
|
|
||
| #include <unordered_map> | ||
| #include "CreatureAI.h" | ||
| #include "Event.h" | ||
| #include "LastMovementValue.h" | ||
| #include "LootObjectStack.h" | ||
| #include "PlayerbotAI.h" | ||
| #include "PlayerbotAIConfig.h" | ||
| #include "Playerbots.h" | ||
| #include "ServerFacade.h" | ||
| #include "SharedDefines.h" | ||
| #include "Unit.h" | ||
| #include "Timer.h" | ||
|
|
||
| bool AttackAction::Execute(Event /*event*/) | ||
| { | ||
|
|
@@ -43,14 +46,14 @@ bool AttackMyTargetAction::Execute(Event /*event*/) | |
| } | ||
|
|
||
| botAI->GetAiObjectContext()->GetValue<GuidVector>("prioritized targets")->Set({guid}); | ||
| bool result = Attack(botAI->GetUnit(guid)); | ||
| bool result = Attack(botAI->GetUnit(guid), true, true); // Skip combat delay for explicit commands | ||
| if (result) | ||
| context->GetValue<ObjectGuid>("pull target")->Set(guid); | ||
|
|
||
| return result; | ||
| } | ||
|
|
||
| bool AttackAction::Attack(Unit* target, bool /*with_pet*/ /*true*/) | ||
| bool AttackAction::Attack(Unit* target, bool /*with_pet*/ /*true*/, bool skipCombatDelay /*false*/) | ||
| { | ||
| Unit* oldTarget = context->GetValue<Unit*>("current target")->Get(); | ||
| bool shouldMelee = bot->IsWithinMeleeRange(target) || botAI->IsMelee(bot); | ||
|
|
@@ -59,6 +62,35 @@ bool AttackAction::Attack(Unit* target, bool /*with_pet*/ /*true*/) | |
| bool inCombat = botAI->GetState() == BOT_STATE_COMBAT; | ||
| bool sameAttackMode = bot->HasUnitState(UNIT_STATE_MELEE_ATTACKING) == shouldMelee; | ||
|
|
||
| // Combat delay check - prevent immediate engagement (not for PvP or explicit commands) | ||
| bool isPvPTarget = target->IsPlayer() || (target->IsPet() && target->GetOwner() && target->GetOwner()->IsPlayer()); | ||
| if (!skipCombatDelay && botAI->HasStrategy("combat delay", BOT_STATE_NON_COMBAT) && sPlayerbotAIConfig->combatDelay > 0 && !sameTarget && !inCombat && !isPvPTarget) | ||
| { | ||
| static std::unordered_map<ObjectGuid, uint32> targetFirstSeenTime; | ||
|
||
| static uint32 lastCleanupTime = 0; | ||
| ObjectGuid targetGuid = target->GetGUID(); | ||
| uint32 currentTime = getMSTime(); | ||
| if (targetFirstSeenTime.find(targetGuid) == targetFirstSeenTime.end()) | ||
| targetFirstSeenTime[targetGuid] = currentTime; | ||
|
|
||
| uint32 timeSinceFirstSeen = currentTime - targetFirstSeenTime[targetGuid]; | ||
| if (timeSinceFirstSeen < sPlayerbotAIConfig->combatDelay) | ||
| return false; | ||
|
|
||
| // Clean up old entries to prevent memory leak | ||
| if (currentTime - lastCleanupTime > 60000) | ||
| { | ||
| lastCleanupTime = currentTime; | ||
| for (auto it = targetFirstSeenTime.begin(); it != targetFirstSeenTime.end();) | ||
| { | ||
| if (currentTime - it->second > sPlayerbotAIConfig->combatDelay + 10000) | ||
| it = targetFirstSeenTime.erase(it); | ||
| else | ||
| ++it; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (bot->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE || | ||
| bot->HasUnitState(UNIT_STATE_IN_FLIGHT)) | ||
| { | ||
|
|
@@ -191,4 +223,4 @@ bool AttackAction::Attack(Unit* target, bool /*with_pet*/ /*true*/) | |
|
|
||
| bool AttackDuelOpponentAction::isUseful() { return AI_VALUE(Unit*, "duel target"); } | ||
|
|
||
| bool AttackDuelOpponentAction::Execute(Event /*event*/) { return Attack(AI_VALUE(Unit*, "duel target")); } | ||
| bool AttackDuelOpponentAction::Execute(Event /*event*/) { return Attack(AI_VALUE(Unit*, "duel target"), true, true); } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The default value of 3000ms differs from the documented default in the code (0 = no delay). The config comment states 'Default delay in milliseconds before bots engage in combat (0 = no delay)' but sets it to 3000. This inconsistency is confusing. Either change the default to 0 to match the documentation, or update the comment to clarify that 3000ms is the recommended default.