- bool line_of_sight = true;
- Ray aim{Target().Position() - diff, norm_diff};
- WorldCollision coll;
- if (world.Intersection(aim, glm::mat4(1.0f), Target().ChunkCoords(), coll)) {
- line_of_sight = coll.depth > dist;
+void AIController::Update(Entity &e, float dt) {
+ // movement: for now, wander only
+ if (wandering) {
+ glm::vec3 displacement(
+ random.SNorm() * wander_disp,
+ random.SNorm() * wander_disp,
+ random.SNorm() * wander_disp
+ );
+ if (!iszero(displacement)) {
+ wander_pos = normalize(wander_pos + displacement * dt) * wander_radius;
+ }
+ }
+
+ if (e.Moving()) {
+ // orient head towards heading
+ glm::vec3 heading(Heading(e.GetState()));
+ float tgt_pitch = std::atan(heading.y / length(glm::vec2(heading.x, heading.z)));
+ float tgt_yaw = std::atan2(-heading.x, -heading.z);
+ e.SetHead(tgt_pitch, tgt_yaw);
+ }
+}
+
+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;
+ }