- if (!line_of_sight) {
- Controlled().Velocity(glm::vec3(0.0f));
- } else if (dist > stop_dist) {
- Controlled().Velocity(norm_diff * chase_speed);
- } else if (dist < flee_dist) {
- Controlled().Velocity(norm_diff * flee_speed);
+glm::vec3 AIController::ControlForce(const Entity &entity, const EntityState &state) const {
+ glm::vec3 force(0.0f);
+ if (IsFleeing()) {
+ glm::vec3 diff(GetFleeTarget().GetState().Diff(state));
+ if (MaxOutForce(force, TargetVelocity(normalize(diff) * flee_speed, state, 0.5f), entity.MaxControlForce())) {
+ return force;
+ }
+ }
+ if (IsSeeking()) {
+ glm::vec3 diff(state.Diff(GetSeekTarget().GetState()));
+ if (MaxOutForce(force, TargetVelocity(normalize(diff) * seek_speed, state, 0.5f), entity.MaxControlForce())) {
+ return force;
+ }
+ }
+ if (wandering) {
+ glm::vec3 wander_target(normalize(Heading(state) * wander_dist + wander_pos) * wander_speed);
+ if (MaxOutForce(force, TargetVelocity(wander_target, state, 2.0f), entity.MaxControlForce())) {
+ return force;
+ }
+ }
+ return force;
+}
+
+glm::vec3 AIController::Heading(const EntityState &state) noexcept {
+ if (dot(state.velocity, state.velocity) > std::numeric_limits<float>::epsilon()) {
+ return normalize(state.velocity);