mod-playerbots/src/Ai/Base/Strategy/WaitForAttackStrategy.cpp
kadeshar bbd9d3e37a
Wait for attack strategy migration (#2211)
## Pull Request Description
Migration of "wait for attack" strategy from cmangos playerbots.

Resolves: https://github.com/mod-playerbots/mod-playerbots/issues/990

## Feature Evaluation
Optional strategy for bots which are in party with real player. 

## How to Test the Changes
- add strategy to bot "nc +wait for attack" and "co +wait for attack"
- set time via command "wait for attack time x" where x is time which
they wait in seconds (you should get response from bot)
- attack any target (for example dummy in main city)(bot should wait
with attack)

## Impact Assessment
    - [ ] No, not at all
    - [x] Minimal impact (**explain below**)
    - [ ] Moderate impact (**explain below**)

Performance wise only bots having this optinal strategy have additional
cost in multiplier which check every attack action that should be
execute.

- Does this change modify default bot behavior?
    - [x] No
    - [ ] Yes (**explain why**)



- Does this change add new decision branches or increase maintenance
complexity?
    - [x] No
    - [ ] Yes (**explain below**)



## Messages to Translate
Does this change add bot messages to translate?
- [ ] No
- [x] Yes (**list messages in the table**)

| Message key  | Default message |
| --------------- | ------------------ |
1740 | Please provide a time to set (in seconds)
1741 | Please provide valid time to set (in seconds) between 0 and 99
1742 | Wait for attack time set to %new_time seconds

## AI Assistance
Was AI assistance used while working on this change?
- [ ] No
- [x] Yes (**explain below**)
<!--
If yes, please specify:
- Purpose of usage (e.g. brainstorming, refactoring, documentation, code
generation).
- Which parts of the change were influenced or generated, and whether it
was thoroughly reviewed.
-->

Copilot CLI - help with migration



## Final Checklist

- [x] Stability is not compromised.
- [x] Performance impact is understood, tested, and acceptable.
- [x] Added logic complexity is justified and explained.
- [x] Documentation updated if needed (Conf comments, WiKi commands).

## Notes for Reviewers
<!-- Anything else that's helpful to review or test your pull request.
-->
2026-03-27 10:38:46 -07:00

94 lines
2.8 KiB
C++

/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#include "WaitForAttackStrategy.h"
#include "Action.h"
#include "PlayerbotAI.h"
#include "PlayerbotAIConfig.h"
#include "Playerbots.h"
#include "Strategy.h"
void WaitForAttackStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
triggers.push_back(new TriggerNode(
"wait for attack safe distance",
{
NextAction("wait for attack keep safe distance", ACTION_RAID)
}
));
}
void WaitForAttackStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers)
{
multipliers.push_back(new WaitForAttackMultiplier(botAI));
}
bool WaitForAttackStrategy::ShouldWait(PlayerbotAI* botAI)
{
if (botAI->HasStrategy("wait for attack", BOT_STATE_COMBAT))
{
Player* bot = botAI->GetBot();
if (bot->GetGroup() && botAI->HasRealPlayerMaster())
{
// Don't wait if the current target is an enemy player
Unit* target = botAI->GetAiObjectContext()->GetValue<Unit*>("current target")->Get();
if (target && target->IsPlayer())
return false;
AiObjectContext* context = botAI->GetAiObjectContext();
time_t combatStartTime = context->GetValue<time_t>("combat start time")->Get();
if (bot->IsInCombat())
{
if (combatStartTime == 0)
{
combatStartTime = time(nullptr);
context->GetValue<time_t>("combat start time")->Set(combatStartTime);
}
time_t elapsedTime = time(nullptr) - combatStartTime;
return elapsedTime < GetWaitTime(botAI);
}
else
{
if (combatStartTime != 0)
context->GetValue<time_t>("combat start time")->Set(0);
}
}
}
return false;
}
uint8 WaitForAttackStrategy::GetWaitTime(PlayerbotAI* botAI)
{
return botAI->GetAiObjectContext()->GetValue<uint8>("wait for attack time")->Get();
}
float WaitForAttackStrategy::GetSafeDistance()
{
return sPlayerbotAIConfig.spellDistance;
}
float WaitForAttackMultiplier::GetValue(Action* action)
{
std::string const& actionName = action->getName();
if (actionName != "wait for attack keep safe distance" &&
actionName != "dps assist" &&
actionName != "set facing" &&
actionName != "pull my target" &&
actionName != "pull rti target" &&
actionName != "pull start" &&
actionName != "pull action" &&
actionName != "pull end")
{
return WaitForAttackStrategy::ShouldWait(botAI) ? 0.0f : 1.0f;
}
return 1.0f;
}