Commit Graph

10 Commits

Author SHA1 Message Date
dillyns
629aa19dbd Add aggressive non combat targeting strategy (#2117)
# Pull Request

Tired of failing that escort quest because your bots stood and watched
while the escort npc got swarmed and killed?
Tired of your bots standing around doing nothing while the npc you are
supposed to be guarding for 5 minutes is getting attacked?
Don't want to use the grind strategy because it is too heavy-handed and
has too many restrictions?

Look no further! Just do "nc +aggressive" and your bots will pick a
fight with anything they can in a 30 yard radius.

The aggressive targetting is a stripped down version of the grind
target.

## Feature Evaluation

Please answer the following:

- Describe the **minimum logic** required to achieve the intended
behavior?
Add a strategy, action, and targetting that will cause bots to attack
nearby enemies when out of combat.

- Describe the **cheapest implementation** that produces an acceptable
result?
Hopefully this is the cheapest.

- Describe the **runtime cost** when this logic executes across many
bots?
Minimal runtime cost as this strategy needs to be added specifically to
bots.

---

## How to Test the Changes

- Add a bot to party, or use selfbot
- Give them the aggressive strategy via "nc +aggressive"
- They should attack anything within 30 yards.
- If it is a bot with a master, the 30 yards should be centered around
the master not the bot (prevent chaining from enemy to enemy)

## Complexity & Impact

Does this change add new decision branches?
```
[] No
[x] Yes (**explain below**)
Only for bots that have the added strategy, adds decision to attack nearby targets when out of combat.
```

Does this change increase per-bot or per-tick processing?
```
[] No
[x] Yes (**describe and justify impact**)
Minimal increase to only bots that have this strategy added.
```

Could this logic scale poorly under load?
```
[x] No
[ ] Yes (**explain why**)
```
---

## Defaults & Configuration

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

If this introduces more advanced or AI-heavy logic:
```
[x] Lightweight mode remains the default
[ ] More complex behavior is optional and thereby configurable
```
---

## AI Assistance

Was AI assistance (e.g. ChatGPT or similar tools) used while working on
this change?
```
[ ] No
[x] Yes (**explain below**)
```
Claude is used to explore the codebase to find similar implementations
to be used for examples.

---

## 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

---

## Notes for Reviewers

Anything that significantly improves realism at the cost of stability or
performance should be carefully discussed
before merging.
2026-02-23 11:00:55 -08:00
privatecore
2f7dfdbbfc Fix rest of trainers' related stuff + codestyle changes and corrections (#2104)
# Pull Request

* Fix the rest of the trainer-related functionality: list spells and
learn (cast vs. direct learn) spells.
* Rewrite `TrainerAction`: split the logic between appropriate methods
(`GetTarget`, `isUseful`, `isPossible`) instead of pushing everything
inside a single `Execute` method.
* Change method definitions to remove unnecessary declarations and
parameters overhead.
* Move the `Trainer` header into the implementation. Rewrite
`RpgTrainTrigger` to fit the original logic and move all validation to
`RpgTrainAction` (`isUseful` + `isPossible`).
* Implement "can train" context value calculation to use with
`RpgTrainTrigger`.
* Update and optimize "train cost" context value calculation -- it
should be much faster.
* Replace `AiPlayerbot.AutoTrainSpells` with
`AiPlayerbot.AllowLearnTrainerSpells` and remove the "free" value
behavior — please use `AiPlayerbot.BotCheats` if you want bots to learn
trainer's spells for "free".
* Add `nullptr` checks wherever necessary (only inside targeted
methods/functions).
* Make some codestyle changes and corrections based on the AC codestyle
guide.

---

## Design Philosophy

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.

---

## How to Test the Changes

Force bots to learn spells from trainers using the chat command `trainer
learn` or `trainer learn <spellId>`. Bots should properly list available
spells (`trainer` command) or learn them (based on configuration and
command).

## Complexity & Impact

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

- Does this change increase per-bot or per-tick processing?
    - [x] No
    - [ ] Yes (**describe and justify impact**)

- Could this logic scale poorly under load?
    - [x] No
    - [ ] Yes (**explain why**)

---

## Defaults & Configuration

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

If this introduces more advanced or AI-heavy logic:

- [x] Lightweight mode remains the default
- [ ] More complex behavior is optional and thereby configurable

---

## AI Assistance

- Was AI assistance (e.g. ChatGPT or similar tools) used while working
on this change?
    - [x] No
    - [ ] Yes (**explain below**)

If yes, please specify:

- 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

- [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

---

## Notes for Reviewers

Anything that significantly improves realism at the cost of stability or
performance should be carefully discussed
before merging.

---------

Co-authored-by: bashermens <31279994+hermensbas@users.noreply.github.com>
2026-02-23 11:00:24 -08:00
Keleborn
441f9f7552 Warnings PR 1: Event warnings and headers (#2106)
# Pull Request

This is the first in a series of PRs intended to eliminate warnings in
the module. The design intent is to eliminate the calling event when not
needed in the body of the function. Based off of SmashingQuasars work.

---

## How to Test the Changes

- 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

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

- Does this change increase per-bot or per-tick processing?
    - [x] No
    - [ ] Yes (**describe and justify impact**)

- Could this logic scale poorly under load?
    - [x] No
    - [ ] Yes (**explain why**)

---

## Defaults & Configuration

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

If this introduces more advanced or AI-heavy logic:

- [ ] Lightweight mode remains the default
- [ ] More complex behavior is optional and thereby configurable

---

## AI Assistance

- Was AI assistance (e.g. ChatGPT or similar tools) used while working
on this change?
    - [x] No
    - [ ] Yes (**explain below**)

---

## 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

---

## Notes for Reviewers

Anything that significantly improves realism at the cost of stability or
performance should be carefully discussed
before merging.

---------

Co-authored-by: bashermens <31279994+hermensbas@users.noreply.github.com>
2026-02-14 20:55:10 +01:00
NoxMax
25800f54e8 Fix/Feat: PVP with master and PVP probablity system (thread-safe remake) (#2008)
This is a remake of #1914 that had to be reverted. Original PR had a
thread-safe issue where a crash happens if multiple threads access the
cache at the same time. Unfortunately this problem was not caught in
earlier testing. I don't know if because I was testing on a month old
branch, if my settings had only ~2000, or if I needed test runs longer
than an hour to find out.

Regardless, this has all been addressed. Test have been run on the
latest commits from today (2026/1/11), with all 7500 of my bots active,
with a test run that lasted 15 hours. All stable and bots are following
the probability system without issue.

~~The new edit uses mutex locking, preventing simultaneous access of the
cache by multiple threads.~~
The new edit uses deterministic hashing, thereby not having issues with
cache thread safety to begin with. Thank you @hermensbas for catching
and reverting the original problem PR. Apologies for not catching the
issue myself.

---
Original PR description:

There are two related PVP components in this PR. First is the simple yet
fundamental change to bot behaviour when they are in party. Right now
bots with a master will go into PVP when there's a nearby PVP target,
even if master is not in PVP. This absolutely should not happen. Bots
should not consider PVP at all if master is not in PVP. The fix is only
3 lines in EnemyPlayerValue

The second component is introducing PVP probabilities, to make decisions
more realistic. Right now even a level 1 bot will 100% go into PVP if it
sees a level 80 PVP target. They can't help themselves. So the change
here addresses that insanity. Several thresholds (subject to community
review) are introduced:

1. Bots will not fight a target 5 or more levels higher than them
2. Bots have a 25% chance starting a fight with a target +/- 4 levels
from them.
3. Bots have a 50% chance starting a fight with a target +/- 3 levels
from them.
4. Bots have a 75% chance starting a fight with a target +/- 2 levels
from them.
5. Bots have a 100% chance starting a fight with a target +/- 1 level
from them.
6. Bots have a 25% chance starting a fight with a target 5 or more
levels below them (ganking. thought it would be funny, and technically
realistic of player behaviour)

Exception of course exist for BG/Arena/Duel, and in capitals where bots
will always PVP. Also bots will always defend themselves if attacked.

Few notes: 
1. The if/ else if logic can be further simplified, but only if we use
thresholds that are different by one. So current logic allows for
flexibility of using values like 10/7/5/3 instead of 5/4/3/2.
2. The caching system is per-bot basis. So for some target X, if some
bot decides to attack it, another bot will make its own decision. At
first I used a simplified global system (thinking there might be
performance concerns) where if one bot decides to attack a target then
they all do, but when I switched to the more realistic per-bot basis, I
didn't see an effect on performance.
3. Variables are obviously not configurable right now. I'm starting to
see Bash's POV that maybe we have too many configs 😬 Still,
they can be easily exposed in the future, and if someone is reading this
then, remember to change constexpr to const.

---------

Co-authored-by: bashermens <31279994+hermensbas@users.noreply.github.com>
2026-02-13 09:31:55 -08:00
Keleborn
ee2a399ac8 Refactor newrpginfo data union to std::variant (#2079)
# Pull Request

As I began modifying the newrpginfo to change the types of data it
stored, or add new data I found myself with the issue of ending up
either with garbage memory if the information wasnt properly stored on
status change, or needing complicated destructor patterns for non
trivial data sets.

---

## Design Philosophy

Make rpginfo able to handle more complicated information in a strongly 

---

## Feature Evaluation

No Feature changes

---

## How to Test the Changes

-  Server should be stable for an extended period of time. 
- Bots should be able to complete quests, fly, etc as they did before.

## Complexity & Impact

- Does this change add new decision branches?
    - [X ] No
    - [ ] Yes (**explain below**)

- Does this change increase per-bot or per-tick processing?
    - [ ] No
    - [ X] Yes (**describe and justify impact**)
Potentially as there can be more memory involved in the object.

- Could this logic scale poorly under load?
    - [X ] No
    - [ ] Yes (**explain why**)

---

## Defaults & Configuration

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

If this introduces more advanced or AI-heavy logic:

- [ ] Lightweight mode remains the default
- [ ] More complex behavior is optional and thereby configurable

---

## AI Assistance

- Was AI assistance (e.g. ChatGPT or similar tools) used while working
on this change?
    - [ ] No
    - [ X] Yes (**explain below**)

If yes, please specify:

- Gemini suggested the use of std::variant as an alternative data
structure. I found additinal external references that correlated with
the same suggestion of moving away from a union.
- Implementation was performed manually with Co-pilot auto-complete

---

## Final Checklist 
In progress.
- [ ] 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

Im not 100% sure if this is a good design choice. There are some things
I didnt quite like by the end of this, specifically having to double
check whenever accessing data whether exists or not even though an
action has already been triggered. But I have a PR in the works where I
want to store a full flight path vector, and the union was giving me
issues. (It appears that state changes may be occuring in the same tick
between RPG status update and the stated action, leading to incorrect
data gathering.

I ended up solving it by first checking a pointer to the object, and
then getting the reference.
```c++
    auto* dataPtr = std::get_if<NewRpgInfo::DoQuest>(&info.data);
    if (!dataPtr)
        return false;
    auto& data = *dataPtr;
```

---------

Co-authored-by: bashermens <31279994+hermensbas@users.noreply.github.com>
2026-02-13 09:19:54 -08:00
privatecore
610fdc16d7 Fix bug with GetCreature + GetGameObject = use ObjectAccessor's methods instead (#2105)
# Pull Request

https://en.cppreference.com/w/cpp/algorithm/equal_range.html
> second is an iterator to the first element of the range [first, last)
ordered after value (or last if no such element is found).

The original code uses `return bounds.second->second`, which causes the
wrong creature/gameobject to be returned. Instead, both methods
(`GetCreature` and `GetGameObject`) now utilize ObjectAccessor's methods
to retrieve the correct entities. These built-in methods offer a safer
way to access objects. Additionally, `GetUnit` no longer includes
redundant creature processing before checks and now has the same logic
as the `ObjectAccessor::GetUnit` method.

Furthermore, `GuidPosition::isDead` method has been renamed to
`GuidPosition::IsCreatureOrGOAccessible` and updated, as it is used only
for creatures (NOT units) and gameobjects.

---

## Design Philosophy

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.

---

## How to Test the Changes

The behavior has not changed after all.

## Complexity & Impact

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

- Does this change increase per-bot or per-tick processing?
    - [x] No
    - [ ] Yes (**describe and justify impact**)

- Could this logic scale poorly under load?
    - [x] No
    - [ ] Yes (**explain why**)

---

## Defaults & Configuration

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

If this introduces more advanced or AI-heavy logic:

- [ ] Lightweight mode remains the default
- [ ] More complex behavior is optional and thereby configurable

---

## AI Assistance

- Was AI assistance (e.g. ChatGPT or similar tools) used while working
on this change?
    - [x] No
    - [ ] Yes (**explain below**)

If yes, please specify:

- 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

- [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

---

## Notes for Reviewers

Anything that significantly improves realism at the cost of stability or
performance should be carefully discussed
before merging.

---------

Co-authored-by: bashermens <31279994+hermensbas@users.noreply.github.com>
2026-02-08 09:36:56 -08:00
Keleborn
3db2a5a193 Refactor of EquipActions (#1994)
#PR Description 

The root cause of issue #1987 was the AI Value item usage becoming a
very expensive call when bots gained professions accidentally.

My original approach was to eliminate it entirely, but after inputs and
testing I decided to introduce a more focused Ai value "Item upgrade"
that only checks equipment and ammo inheriting directly from item usage,
so the logic is unified between them.

Upgrades are now only assessed when receiving an item that can be
equipped.

Additionally, I noticed that winning loot rolls did not trigger the
upgrade action, so I added a new package handler for that.


Performance needs to be re-evaluated, but I expect a reduction in calls
and in the cost of each call.

I tested with bots and selfbot in deadmines and ahadowfang keep.

---------

Co-authored-by: bashermens <31279994+hermensbas@users.noreply.github.com>
2026-02-08 12:41:33 +01:00
bashermens
13fff46fa0 Improper singletons migration to clean Meyer's singletons (cherry-pick) (#2082)
# Pull Request

- Applies the clean and corrected singletons, Meyer pattern. (cherry
picked from @SmashingQuasar )

Testing by just playing the game in various ways. Been tested by myself
@Celandriel and @SmashingQuasar
---

## Complexity & Impact

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

- Does this change increase per-bot or per-tick processing?
    - [x] No
    - [ ] Yes (**describe and justify impact**)

- Could this logic scale poorly under load?
    - [x] No
    - [ ] Yes (**explain why**)

---

## Defaults & Configuration

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

---

## AI Assistance

- Was AI assistance (e.g. ChatGPT or similar tools) used while working
on this change?
    - [x] No
    - [ ] Yes (**explain below**)
---

## 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

---

## Notes for Reviewers

Anything that significantly improves realism at the cost of stability or
performance should be carefully discussed
before merging.

---------

Co-authored-by: Nicolas Lebacq <nicolas.cordier@outlook.com>
Co-authored-by: Keleborn <22352763+Celandriel@users.noreply.github.com>
2026-01-30 21:49:37 +01:00
bashermens
3d467ce3bb Added some additional defense checks around isHostile and unit/target (#2056)
Needs second pair of eyes, they appear in crash logs here and there. Its
merely a patch on a open wound.

----
As in aslong there multithreads in mapupdate, which we need for decent
performance and core calls are not done correctly due various reasons.
These type of issues remain.

Although i am planning to experiment a little with threadsafe execution
of our strategies vs performance.

The most effective thing we could do is check every single action and
check its stateless and where it does effect the state or read the state
of a core object its done in the safest way. flags, worldthread where
possible and/ot simply taking into account the state might be invalid.
2026-01-24 20:41:12 +01:00
bashermens
41c53365ae [HOT FIX] MS build issues regarding folder / command lenght usage or rc.exe (#2038) 2026-01-19 22:45:28 +01:00