mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-06-20 15:39:25 +02:00
Compare commits
No commits in common. "1a3468368d37b3220369b6382bcfd452ed697637" and "ca9f23a8e39fff4fbc80dec31577ac5d08916a0a" have entirely different histories.
1a3468368d
...
ca9f23a8e3
@ -1,103 +1,124 @@
|
||||
<!--
|
||||
Thank you for contributing to mod-playerbots, please make sure that you...
|
||||
1. Submit your PR to the test-staging branch, not master.
|
||||
2. Read the guidelines below before submitting.
|
||||
3. Don't delete parts of this template.
|
||||
# Pull Request
|
||||
|
||||
DESIGN PHILOSOPHY: We prioritize STABILITY, PERFORMANCE, AND PREDICTABILITY over behavioral realism.
|
||||
Describe what this change does and why it is needed...
|
||||
|
||||
Every action and decision executes PER BOT AND PER TRIGGER. Small increases in logic complexity scale
|
||||
poorly across thousands of bots and negatively affect all. We prioritize a stable system over a smarter
|
||||
one. Bots don't need to behave perfectly; believable behavior is the goal, not human simulation.
|
||||
Default behavior must be cheap in processing; expensive behavior must be opt-in.
|
||||
---
|
||||
|
||||
Before submitting, make sure your changes aligns with these principles.
|
||||
-->
|
||||
## Design Philosophy
|
||||
|
||||
## Pull Request Description
|
||||
<!-- Describe what this change does and why it is needed -->
|
||||
We prioritize **stability, performance, and predictability** over behavioral realism.
|
||||
Complex player-mimicking logic is intentionally limited due to its negative impact on scalability, maintainability, and
|
||||
long-term robustness.
|
||||
|
||||
Excessive processing overhead can lead to server hiccups, increased CPU usage, and degraded performance for all
|
||||
participants. Because every action and
|
||||
decision tree is executed **per bot and per trigger**, even small increases in logic complexity can scale poorly and
|
||||
negatively affect both players and
|
||||
world (random) bots. Bots are not expected to behave perfectly, and perfect simulation of human decision-making is not a
|
||||
project goal. Increased behavioral
|
||||
realism often introduces disproportionate cost, reduced predictability, and significantly higher maintenance overhead.
|
||||
|
||||
Every additional branch of logic increases long-term responsibility. All decision paths must be tested, validated, and
|
||||
maintained continuously as the system evolves.
|
||||
If advanced or AI-intensive behavior is introduced, the **default configuration must remain the lightweight decision
|
||||
model**. More complex behavior should only be
|
||||
available as an **explicit opt-in option**, clearly documented as having a measurable performance cost.
|
||||
|
||||
Principles:
|
||||
|
||||
- **Stability before intelligence**
|
||||
A stable system is always preferred over a smarter one.
|
||||
|
||||
- **Performance is a shared resource**
|
||||
Any increase in bot cost affects all players and all bots.
|
||||
|
||||
- **Simple logic scales better than smart logic**
|
||||
Predictable behavior under load is more valuable than perfect decisions.
|
||||
|
||||
- **Complexity must justify itself**
|
||||
If a feature cannot clearly explain its cost, it should not exist.
|
||||
|
||||
- **Defaults must be cheap**
|
||||
Expensive behavior must always be optional and clearly communicated.
|
||||
|
||||
- **Bots should look reasonable, not perfect**
|
||||
The goal is believable behavior, not human simulation.
|
||||
|
||||
Before submitting, confirm that this change aligns with those principles.
|
||||
|
||||
---
|
||||
|
||||
## Feature Evaluation
|
||||
<!--
|
||||
If your PR is very minimal (comment typo, wrong ID reference, etc), and it is very obvious it will not have
|
||||
any impact on performance, you may skip these question. If necessary, a maintainer may ask you for them later.
|
||||
-->
|
||||
|
||||
<!-- Please answer the following: -->
|
||||
- Describe the **minimum logic** required to achieve the intended behavior.
|
||||
- Describe the **processing cost** when this logic executes across many bots.
|
||||
Please answer the following:
|
||||
|
||||
- Describe the **minimum logic** required to achieve the intended behavior?
|
||||
- Describe the **cheapest implementation** that produces an acceptable result?
|
||||
- Describe the **runtime cost** when this logic executes across many bots?
|
||||
|
||||
---
|
||||
|
||||
## How to Test the Changes
|
||||
<!--
|
||||
- Step-by-step instructions to test the change.
|
||||
- Any required setup (e.g. multiple players, number of bots, specific configuration).
|
||||
- Expected behavior and how to verify it.
|
||||
-->
|
||||
|
||||
- Step-by-step instructions to test the change
|
||||
- Any required setup (e.g. multiple players, bots, specific configuration)
|
||||
- Expected behavior and how to verify it
|
||||
|
||||
## Complexity & Impact
|
||||
|
||||
## Impact Assessment
|
||||
<!-- As a generic test, before and after measure of pmon (playerbot pmon tick) can help you here. -->
|
||||
- Does this change increase per-bot/per-tick processing or risk scaling poorly with thousands of bots?
|
||||
- [ ] No, not at all
|
||||
- [ ] Minimal impact (**explain below**)
|
||||
- [ ] Moderate impact (**explain below**)
|
||||
Does this change add new decision branches?
|
||||
- - [ ] No
|
||||
- - [ ] Yes (**explain below**)
|
||||
|
||||
Does this change increase per-bot or per-tick processing?
|
||||
- - [ ] No
|
||||
- - [ ] Yes (**describe and justify impact**)
|
||||
|
||||
Could this logic scale poorly under load?
|
||||
- - [ ] No
|
||||
- - [ ] Yes (**explain why**)
|
||||
---
|
||||
|
||||
- Does this change modify default bot behavior?
|
||||
- [ ] No
|
||||
- [ ] Yes (**explain why**)
|
||||
## Defaults & Configuration
|
||||
|
||||
Does this change modify default bot behavior?
|
||||
- - [ ] No
|
||||
- - [ ] Yes (**explain why**)
|
||||
|
||||
|
||||
- Does this change add new decision branches or increase maintenance complexity?
|
||||
- [ ] No
|
||||
- [ ] Yes (**explain below**)
|
||||
|
||||
|
||||
|
||||
## Messages to Translate
|
||||
<!--
|
||||
Bot messages have to be translatable, but you don't need to do the translations here. You only need to make sure
|
||||
the message is in a translatable format, and list in the table the message_key and the default English message.
|
||||
Search for GetBotTextOrDefault in the codebase for examples.
|
||||
-->
|
||||
Does this change add bot messages to translate?
|
||||
- [ ] No
|
||||
- [ ] Yes (**list messages in the table**)
|
||||
|
||||
| Message key | Default message |
|
||||
| --------------- | ------------------ |
|
||||
| | |
|
||||
| | |
|
||||
If this introduces more advanced or AI-heavy logic:
|
||||
- - [ ] Lightweight mode remains the default
|
||||
- - [ ] More complex behavior is optional and thereby configurable
|
||||
---
|
||||
|
||||
## AI Assistance
|
||||
<!--
|
||||
AI assistance is allowed, but all submitted code must be fully understood, reviewed, and owned by the contributor.
|
||||
We expect contributors to be honest about what they do and do not understand.
|
||||
-->
|
||||
Was AI assistance used while working on this change?
|
||||
- [ ] No
|
||||
- [ ] Yes (**explain below**)
|
||||
<!--
|
||||
|
||||
Was AI assistance (e.g. ChatGPT or similar tools) used while working on this change?
|
||||
- - [ ] No
|
||||
- - [ ] 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.
|
||||
-->
|
||||
|
||||
- AI tool or model used (e.g. ChatGPT, GPT-4, Claude, etc.)
|
||||
- Purpose of usage (e.g. brainstorming, refactoring, documentation, code generation)
|
||||
- Which parts of the change were influenced or generated
|
||||
- Whether the result was manually reviewed and adapted
|
||||
|
||||
AI assistance is allowed, but all submitted code must be fully understood, reviewed, and owned by the contributor.
|
||||
Any AI-influenced changes must be verified against existing CORE and PB logic. We expect contributors to be honest
|
||||
about what they do and do not understand.
|
||||
|
||||
---
|
||||
|
||||
## Final Checklist
|
||||
|
||||
- [ ] Stability is not compromised.
|
||||
- [ ] Performance impact is understood, tested, and acceptable.
|
||||
- [ ] Added logic complexity is justified and explained.
|
||||
- [ ] Documentation updated if needed (Conf comments, WiKi commands).
|
||||
- - [ ] Stability is not compromised
|
||||
- - [ ] Performance impact is understood, tested, and acceptable
|
||||
- - [ ] Added logic complexity is justified and explained
|
||||
- - [ ] Documentation updated if needed
|
||||
|
||||
---
|
||||
|
||||
## Notes for Reviewers
|
||||
<!-- Anything else that's helpful to review or test your pull request. -->
|
||||
|
||||
Anything that significantly improves realism at the cost of stability or performance should be carefully discussed
|
||||
before merging.
|
||||
|
||||
@ -1 +0,0 @@
|
||||
UPDATE `ai_playerbot_texts` SET `text_loc3`='%s, du hörst den triefenden Sarkasmus in meinem text nicht' WHERE `id`=1353;
|
||||
@ -598,9 +598,9 @@ uint32 ChatHelper::parseSlot(std::string const text)
|
||||
return EQUIPMENT_SLOT_END;
|
||||
}
|
||||
|
||||
bool ChatHelper::parseableItem(std::string const text)
|
||||
bool ChatHelper::parseable(std::string const text)
|
||||
{
|
||||
return text.find("|Hitem:") != std::string::npos || text == "questitem" || text == "ammo" ||
|
||||
return text.find("|H") != std::string::npos || text == "questitem" || text == "ammo" ||
|
||||
substrContainsInMap<uint32>(text, consumableSubClasses) ||
|
||||
substrContainsInMap<uint32>(text, tradeSubClasses) || substrContainsInMap<uint32>(text, itemQualities) ||
|
||||
substrContainsInMap<uint32>(text, slots) || substrContainsInMap<ChatMsg>(text, chats) ||
|
||||
|
||||
@ -66,7 +66,7 @@ public:
|
||||
static uint32 parseSlot(std::string const text);
|
||||
uint32 parseSkill(std::string const text);
|
||||
|
||||
static bool parseableItem(std::string const text);
|
||||
static bool parseable(std::string const text);
|
||||
|
||||
void eraseAllSubStr(std::string& mainStr, std::string const toErase);
|
||||
|
||||
|
||||
@ -30,7 +30,7 @@ bool ExternalEventHelper::ParseChatCommand(std::string const command, Player* ow
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ChatHelper::parseableItem(command))
|
||||
if (!ChatHelper::parseable(command))
|
||||
return false;
|
||||
|
||||
HandleCommand("c", command, owner);
|
||||
|
||||
@ -9,7 +9,6 @@
|
||||
#include "ArenaTeamMgr.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "PlayerbotAI.h"
|
||||
#include "RaceMgr.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "SocialMgr.h"
|
||||
@ -61,7 +60,7 @@ Player* RandomPlayerbotFactory::CreateRandomBot(WorldSession* session, uint8 cls
|
||||
const bool alliance = static_cast<bool>(urand(0, 1));
|
||||
|
||||
std::vector<uint8> raceOptions;
|
||||
for (uint8 race = RACE_HUMAN; race < sRaceMgr->GetMaxRaces(); ++race)
|
||||
for (uint8 race = RACE_HUMAN; race < MAX_RACES; ++race)
|
||||
{
|
||||
// skip disabled with config races
|
||||
if ((1 << (race - 1)) & sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK))
|
||||
|
||||
@ -1532,21 +1532,6 @@ std::vector<std::string> PlayerbotAI::GetStrategies(BotState type)
|
||||
|
||||
void PlayerbotAI::ApplyInstanceStrategies(uint32 mapId, bool tellMaster)
|
||||
{
|
||||
static const std::vector<std::string> allInstanceStrategies =
|
||||
{
|
||||
"aq20", "bwl", "karazhan", "gruulslair", "icc", "magtheridon", "moltencore",
|
||||
"naxx", "onyxia", "ssc", "tempestkeep", "ulduar", "voa", "wotlk-an", "wotlk-cos",
|
||||
"wotlk-dtk", "wotlk-eoe", "wotlk-fos", "wotlk-gd", "wotlk-hol", "wotlk-hor",
|
||||
"wotlk-hos", "wotlk-nex", "wotlk-occ", "wotlk-ok", "wotlk-os", "wotlk-pos",
|
||||
"wotlk-toc", "wotlk-uk", "wotlk-up", "wotlk-vh"
|
||||
};
|
||||
|
||||
for (const std::string& strat : allInstanceStrategies)
|
||||
{
|
||||
engines[BOT_STATE_COMBAT]->removeStrategy(strat);
|
||||
engines[BOT_STATE_NON_COMBAT]->removeStrategy(strat);
|
||||
}
|
||||
|
||||
std::string strategyName;
|
||||
switch (mapId)
|
||||
{
|
||||
@ -1646,13 +1631,10 @@ void PlayerbotAI::ApplyInstanceStrategies(uint32 mapId, bool tellMaster)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (strategyName.empty())
|
||||
return;
|
||||
|
||||
engines[BOT_STATE_COMBAT]->addStrategy(strategyName);
|
||||
engines[BOT_STATE_NON_COMBAT]->addStrategy(strategyName);
|
||||
|
||||
if (tellMaster && !strategyName.empty())
|
||||
{
|
||||
std::ostringstream out;
|
||||
|
||||
@ -37,7 +37,6 @@
|
||||
#include "PlayerbotFactory.h"
|
||||
#include "Playerbots.h"
|
||||
#include "Position.h"
|
||||
#include "RaceMgr.h"
|
||||
#include "Random.h"
|
||||
#include "RandomPlayerbotFactory.h"
|
||||
#include "ServerFacade.h"
|
||||
@ -1996,7 +1995,7 @@ void RandomPlayerbotMgr::PrepareTeleportCache()
|
||||
}
|
||||
|
||||
// add all initial position
|
||||
for (uint32 i = 1; i < sRaceMgr->GetMaxRaces(); i++)
|
||||
for (uint32 i = 1; i < MAX_RACES; i++)
|
||||
{
|
||||
for (uint32 j = 1; j < MAX_CLASSES; j++)
|
||||
{
|
||||
@ -2009,7 +2008,7 @@ void RandomPlayerbotMgr::PrepareTeleportCache()
|
||||
|
||||
for (int32 l = 1; l <= 5; l++)
|
||||
{
|
||||
if ((1 << (i - 1)) & sRaceMgr->GetAllianceRaceMask())
|
||||
if ((1 << (i - 1)) & RACEMASK_ALLIANCE)
|
||||
allianceStarterPerLevelCache[(uint8)l].push_back(pos);
|
||||
else
|
||||
hordeStarterPerLevelCache[(uint8)l].push_back(pos);
|
||||
@ -3127,7 +3126,7 @@ void RandomPlayerbotMgr::PrintStats()
|
||||
|
||||
std::map<uint8, uint32> lvlPerRace;
|
||||
std::map<uint8, uint32> lvlPerClass;
|
||||
for (uint8 race = RACE_HUMAN; race < sRaceMgr->GetMaxRaces(); ++race)
|
||||
for (uint8 race = RACE_HUMAN; race < MAX_RACES; ++race)
|
||||
{
|
||||
perRace[race] = 0;
|
||||
lvlPerRace[race] = 0;
|
||||
@ -3274,7 +3273,7 @@ void RandomPlayerbotMgr::PrintStats()
|
||||
}
|
||||
|
||||
LOG_INFO("playerbots", "Bots race:");
|
||||
for (uint8 race = RACE_HUMAN; race < sRaceMgr->GetMaxRaces(); ++race)
|
||||
for (uint8 race = RACE_HUMAN; race < MAX_RACES; ++race)
|
||||
{
|
||||
if (perRace[race])
|
||||
{
|
||||
|
||||
@ -14,7 +14,6 @@
|
||||
#include "MapMgr.h"
|
||||
#include "PathGenerator.h"
|
||||
#include "Playerbots.h"
|
||||
#include "RaceMgr.h"
|
||||
#include "TransportMgr.h"
|
||||
#include "VMapFactory.h"
|
||||
#include "VMapMgr2.h"
|
||||
@ -3336,7 +3335,7 @@ void TravelMgr::LoadQuestTravelTable()
|
||||
|
||||
std::ostringstream out;
|
||||
|
||||
for (uint8 race = RACE_HUMAN; race < sRaceMgr->GetMaxRaces(); race++)
|
||||
for (uint8 race = RACE_HUMAN; race < MAX_RACES; race++)
|
||||
{
|
||||
for (uint8 cls = CLASS_WARRIOR; cls < MAX_CLASSES; ++cls)
|
||||
{
|
||||
|
||||
@ -11,7 +11,6 @@
|
||||
#include "BudgetValues.h"
|
||||
#include "PathGenerator.h"
|
||||
#include "Playerbots.h"
|
||||
#include "RaceMgr.h"
|
||||
#include "ServerFacade.h"
|
||||
#include "TransportMgr.h"
|
||||
|
||||
@ -1661,7 +1660,7 @@ void TravelNodeMap::generateStartNodes()
|
||||
startNames[RACE_GNOME] = "Dwarf and Gnome";
|
||||
startNames[RACE_TROLL] = "Orc and Troll";
|
||||
|
||||
for (uint32 i = 0; i < sRaceMgr->GetMaxRaces(); i++)
|
||||
for (uint32 i = 0; i < MAX_RACES; i++)
|
||||
{
|
||||
for (uint32 j = 0; j < MAX_CLASSES; j++)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user