Solo strategy activation (rest, solo_combat, quest, grind, loot, solo)
was positioned after both the AI update throttler and the death recovery
guard in UpdateAI(). Bots that were throttled or dead at login never
reached the activation code, leaving them with Strategies=0 and idle.
Move the one-time strategy activation to run before all guards so it
executes on the first UpdateAI tick regardless of throttle/death state.
Relocate 44 BotMovement files (Controller, StuckDetector, StateMachine,
Pathfinding, Generators, Validation) from src/server/game/Movement/ into
src/modules/Playerbot/Movement/BotMovement/ to comply with module-first
architecture. All playerbot code must live in the module directory.
Updated CMakeLists.txt with all source files in playerbot-gameplay lib
and added 6 include directories for the BotMovement subdirectories.
Also fixes StuckDetector::Reset() to clear position history, preventing
an infinite stuck detection loop where bots were immediately re-detected
as stuck after recovery due to stale position snapshots.
Signed-off-by: luis <[email protected]>
Fix ExteriorComponentHookEntry struct field order to match DB2 LoadInfo
(Position/Rotation before ID when IndexField=2), resolving garbage hook
IDs during fixture resolution.
Replace first-match door hook selection with center-front scoring
heuristic (|X|*2 + Y) to ensure the main entrance spawns at the front
of the house rather than on a side/back wall.
Add fixture validation in SelectFixtureOption: enforce component type
must match hook type, and only one door allowed per house. This prevents
placing windows at door hooks and spawning multiple entrances.
Only auto-resolve the single best door hook during SpawnExtCompTree —
other fixture types (windows, chimneys, dormers) require explicit player
selection, matching retail behavior where they unlock via progression.
Additional fixes: unique fixture GUIDs via atomic counter (subType=5),
size-aware default fixture lookup, range-based DB2 store iteration,
and starter fixture migration that preserves existing roots.
Map player race to house exterior WMO style on purchase:
Night Elf → Woodland (55), Blood Elf → Engraved (56),
other Alliance → Human (9), other Horde → Orc (87).
On house creation, persist starter fixtures (Base + Roof) to
character_housing_fixtures so spawning reads from DB rather than
relying on runtime default resolution. Door auto-resolves from
the hook system via GetDefaultFixtureForType.
Replace the broken GroupXHook→Group→XGroup chain with a direct
_defaultFixtureByTypeWmo index that maps (componentType, wmoDataID)
to the default fixture component ID. This correctly resolves fixtures
for all 4 racial house styles (Human/NightElf/BloodElf/Orc).
Key changes:
- BuildExteriorComponentIndexes: filter structural roots by
ExteriorComponentType.ParentComponentType==0 with hardcoded
fallback for broken DB2 store iteration
- New GetDefaultFixtureForType() replaces GetComponentAtHook()
- SpawnExtCompTree uses type+WMO lookup for hook children
- Door GO spawning fully data-driven from DB2 (entry + position
from hook offset + ExitPoint offset)
- Root selection: rootOverrides → coreExtCompID → default → first
- Fix missing fixture overrides on late-spawn path
- Add GetRootComponentOverrides() for player-selected root variants
- Fix DB2 store iteration bug: ExteriorComponentHook entries with
ParentIndexField were only partially accessible via range-based
iteration (1808 of 23881 entries). Use LookupEntry() over
GetNumRows() to reach all entries, fixing hook resolution
(compByHook was 0, now resolves all 1461 GroupXHook mappings).
- Spawn all root components per HouseExteriorWmoDataID: houses
consist of multiple independent roots (Base type=9, Roof type=10)
sharing the same WMO data ID. Each root spawns independently at
house position with its own hook children (doors on base,
chimney/windows on roof). Filter by Size to avoid spawning
small/medium/large variants simultaneously.
- Build parent-child index from ExteriorComponent.ParentComponentID
for component variants that reference a parent component.
- Add _rootCompsByWmoDataId index for fast lookup of all root
components belonging to a house exterior.
- Fix MeshObject fixture data to pass fixtureGuid and
parentFixtureGuid for proper client-side attachment hierarchy.
- Fix BNetAccount dirty state in fixture edit mode by clearing
update mask after PopulateCatalogStorageEntries.
Comprehensive audit of all neighborhood and housing DB2 tables against
WoWDBDefs canonical field definitions. Renames all misnamed fields across
DB2Structure.h, DB2LoadInfo.h, and internal cache structs in HousingMgr.h.
Key field corrections across 12 DB2 tables:
- NeighborhoodMap: Radius→EntryRotation, PlotCount→UiTextureKitID, FactionRestriction→Flags
- NeighborhoodNameGen: Suffix→Middle, FullName→Suffix
- HouseTheme: IconFileDataID→Flags, CategoryID→ParentThemeID
- HouseDecorMaterial: 5 fields renamed (WMOMaterialReference, MaterialTextureIndex, etc.)
- HouseLevelRewardInfo: HouseLevelID→HouseLevelDataID, RewardType→Field_4, RewardValue→IconFileDataID
- InitiativeCycle: Duration→HouseXPCap
- InitiativeMilestone: 4 fields renamed (MilestoneOrderIndex, RequiredContributionAmount, etc.)
- InitiativeReward: 7 fields renamed (Money, DecorID, DecorQuantity, Favor, RewardQuestID, etc.)
- InitiativeTask: 6 fields renamed (CriteriaTreeID, QuestID, ProgressContributionAmount, etc.)
- DecorCategory/DecorSubcategory/DecorDyeSlot: display fields renamed
Logic bugs revealed and fixed by the audit:
- Budget wiring removed (DB2 has no budget type/value; budgets come from hardcoded table)
- Initiative task type filtering removed (CriteriaTreeID is a FK, not a type enum)
- Initiative target counts fixed (was using QuestID as threshold, now ProgressContributionAmount)
- Initiative duration sourced from NeighborhoodInitiative.Duration, not InitiativeCycle.HouseXPCap
- Initiative rewards rewritten to use correct DB2 fields (Money, DecorID, Favor, etc.)
- Plot count derived from actual plot data instead of misnamed UiTextureKitID field
- NeighborhoodMgr faction checks updated to use Flags with confirmed bitmask values
CriteriaTree-based initiative task matching:
- Replace 4 ad-hoc OnPlayerAction() calls that used non-existent TaskType enum (1-4)
- Add single hook in CriteriaHandler::UpdateCriteria after validation passes
- BuildCriteriaIndex() walks each task's CriteriaTree to find leaf Criteria entries,
builds reverse index CriteriaID → (neighborhood, initiative, task) for O(1) lookup
- OnCriteriaProgress() matches criteria fires against active initiative tasks,
covering all 250+ criteria types (kills, crafting, gathering, quests, etc.) automatically
- Index rebuilt on initiative start/complete to stay current