ModernUO/Projects/UOContent
Kamron Batman 4e57ec2373
fix: monster ability queries no longer have side effects (#2716)
## Problem
`GetMonsterAbilities()` answers three questions through one virtual: which abilities a creature has (`GetAbility`, `AOS.cs` reflect/barrier, bard fire-breath difficulty), which abilities are enabled right now, and where cooldown state must be cleaned up (`InvalidateNextAbilityTriggers` on death and delete). Every caller assumes it is a pure, stable list. About 70 creatures return a static array; only LordOaks computed it:

```
Mobile.Delete()
 → BaseCreature.OnDelete() → CreatureDeletedEvent
 → MonsterAbility.InvalidateNextAbilityTriggers()
 → LordOaks.GetMonsterAbilities() → CheckQueen() → new Silvani().MoveToWorld(...)
```

- Deleting a Lord Oaks nobody had fought (champion reset, `DeleteCreatures`, GM delete) spawned an orphaned Silvani where he stood.
- The spell damage scalar (`AlterDamageScalarFrom`) spawned her too.
- With the queen dead his list was empty, so cleanup skipped his cooldown entries. The static `Dictionary<BaseCreature, long>` on the ability singleton kept a reference to the deleted creature. `MonsterAbilityGroup` children's entries were never cleaned either.
- Neira threw unholy bones from `AlterDamageScalarFrom`, so any caller asking for a damage scalar (a preview gump, for example) could fire the effect.

## Changes
- **Per-creature cooldowns:** a lazy `Dictionary<MonsterAbility, long>` on `BaseCreature` (`IsAbilityOnCooldown`, `SetAbilityCooldown`, `ClearAbilityCooldowns`). The static dictionaries and the query-driven cleanup are gone, and death still resets cooldowns. Tick comparisons are wraparound-safe.
- **Pure contract:** `GetMonsterAbilities()` is documented as pure. The new `virtual bool CanUseAbility(MonsterAbility)` gates abilities that only work some of the time. Every `TriggerAbility*` loop and `GetAbility` check it.
- **LordOaks:** always lists his abilities; `CanUseAbility` and the 10% spell shield read "queen alive". The queen spawns when he is first aggressed or first given a combatant, never on the internal map. Aggression lands before the damage it causes, so the first spell is still shielded, as before.
- **Neira:** the unholy bone throw moves to `OnDamagedBySpell`.

A follow-up PR makes minions such as the queen, pixies and Barracoon's rats belong to their champion spawn, so a spawn reset cleans them up.

## Testing
- `LordOaksTests` covers three cases:
  - querying or deleting an unengaged Lord Oaks spawns nothing;
  - aggression spawns the queen exactly once, and the shield and abilities follow her life;
  - an Oaks on the internal map never spawns her.
- UOContent.Tests: 1234 passed, 2 skipped.
- A local constructor sweep (every Mobile built and deleted repeatedly) no longer reports LordOaks.
2026-10-18 17:41:27 -07:00
..
Accounting perf(login): run password hashing on a parked worker thread (#2566) 2026-08-09 00:13:34 -07:00
Assistants chore: Use var everywhere (#2294) 2025-12-27 16:47:28 -08:00
Commands refactor: master views over BaseCreature's one master reference (#2674) 2026-09-24 22:45:24 -07:00
Compression feat: Implements new robust/pluggable backup/archive system. (#2388) 2026-03-22 19:51:20 -07:00
Configuration fix: Streamlines insurance. Insurance only executes when enabled. (#2550) 2026-07-26 09:47:49 -07:00
Console feat: Adds console commands (#1714) 2024-03-30 09:40:43 -07:00
Context Menus fix: Moves ContextMenu out of core, streamlines code, fixes bugs (#1873) 2024-07-20 21:33:23 -07:00
Engines fix: fishing by era: deep water, serpents, SOS, big fish and magic fish (#2718) 2026-10-18 17:34:10 -07:00
Gumps fix: release a connection's gumps on disconnect (#2689) 2026-10-04 17:53:41 -07:00
Holiday Stuff perf: Migrate Veteran Reward gumps to DynamicGump/StaticGump (#2415) 2026-04-25 20:09:27 -07:00
Items fix: fishing by era: deep water, serpents, SOS, big fish and magic fish (#2718) 2026-10-18 17:34:10 -07:00
Migrations fix: bound and purge NPC vendor buyback stock (#2677) 2026-10-09 22:56:39 -07:00
Misc fix: Skip karma message when karma change is zero (#2710) 2026-10-17 13:55:17 -07:00
Mobiles fix: monster ability queries no longer have side effects (#2716) 2026-10-18 17:41:27 -07:00
Multis fix: enumerators that end early, repeat entries, or never end (#2685) 2026-09-30 21:24:44 -07:00
Network fix: Fixes tick count wrap-around in movement throttle, and eliminates more allocations in NetState (#2603) 2026-09-01 20:25:20 -07:00
Regions fix(regions): correct end Z coordinate assignment in InitRectangles (#2597) 2026-08-27 06:51:42 -07:00
Skills fix: stealing from a container on the ground follows its lift rules (#2697) 2026-10-09 00:21:43 -07:00
Special Systems feat: Add zero-alloc interpolation handler to ValueStringBuilder, replace all StringBuilder usage (#2387) 2026-03-22 14:23:44 -07:00
Spells fix: MeteorSwarm resist halves that target's damage, not the shared pool (#2691) 2026-10-06 16:30:05 -07:00
Systems/JailSystem fix: players jailed across a restart can be jailed again after release (#2690) 2026-10-04 18:21:50 -07:00
Targets chore: Use var everywhere (#2294) 2025-12-27 16:47:28 -08:00
Text fix: Bumps deps. Updates copyrights (#2353) 2026-03-05 19:36:54 -08:00
Utilities fix(commands): parse and edit IPoint2D/IPoint3D properties (#2646) 2026-09-14 21:20:22 -07:00
World Saves perf(messages): mechanical interpolation cleanups (#2436) 2026-05-03 18:26:49 -07:00
Module.cs fix: Fixes sending packets and sidesteps a major issue with stackalloc and PGO in .NET 8 (#1607) 2023-11-21 12:18:20 -08:00
UOContent.csproj fix: Updates dependencies (#2714) 2026-10-17 13:54:25 -07:00