Потихоньку переношу мозги мобов на Behaviour Trees. NPC стали более адекватно себя вести. На текущий момент код мозгов NPC такой.
mBehaviour = bt::Builder()
.Parallel()
.Sequence("Heal")
.Condition([this] { return NeedHealing(); })
.Do([this] { return UseHealingPotion(); })
.End()
.Selector("Behaviour")
.Sequence("Attack")
.Condition([this] { return !NeedHealing(); })
.Do([this] { return LookForTarget(); })
.Condition([this] { return IsEnemyCloseEnoughToDefaultPosition(); })
.Do([this] { return SelectWeapon(); })
.Selector()
.Sequence()
.Condition([this] { return IsTooCloseToEnemy(); })
.Do([this] { return SetMoveDestinationFarEnoughFromEnemy(); })
.End()
.Do([this] { return SetMoveDestinationEnemyPosition(); })
.End()
.Do([this] { return OpenNearbyDoors(); })
.Do([this] { return MoveToDestination(); })
.Do([this] { return LookAtActor(); })
.Do([this] { return AimAtLookPoint(); })
.Do([this] { return UseWeapons(); })
.End()
.Sequence("WalkAway")
.Selector("Position")
.Sequence("Danger")
.Condition([this] { return IsDefaultPositionTooDangerous(); })
.Do([this] { return SetMoveDestinationSafePoint(); })
.End()
.Do([this] { return SetMoveDestinationDefault(); })
.End()
.Condition([this] { return !ReachDestination(); })
.Do([this] { return LookAtWaypoint(); })
.Do([this] { return AimAtLookPoint(); })
.Do([this] { return OpenNearbyDoors(); })
.Do([this] { return MoveToDestination(); })
.End()
.Sequence("Idle")
.Condition([this] { return ReachDestination(); })
.Do([this] { return StayStill(); })
.End()
.End()
.End()
.Build();
Самая мякотка в том что при помощи Behaviour Tree я могу рандомизировать еще и поведение мобов, а не только их внешний вид. Больше рандома богу рандома!