+AIController::~AIController() {
+ // ignore this for now
+ // state->Exit(*this, entity);
+}
+
+void AIController::SetState(const AIState &s, Entity &entity) {
+ state->Exit(*this, entity);
+ state = &s;
+ state->Enter(*this, entity);
+}
+
+void AIController::Update(Entity &e, float dt) {
+ think_timer.Update(dt);
+ decision_timer.Update(dt);
+ state->Update(*this, e, dt);
+
+ if (e.Moving()) {
+ // orient head towards heading
+ glm::vec3 heading(e.Heading());
+ // only half pitch, so we don't crane our neck
+ float tgt_pitch = std::atan(heading.y / glm::length(glm::vec2(heading.x, heading.z))) * 0.5f;
+ // always look straight ahead
+ // maybe look at the pursuit target if there is one
+ float tgt_yaw = 0.0f;
+ e.SetHead(tgt_pitch, tgt_yaw);
+ e.OrientBody(dt);