+ return s.OnGround() && glm::length2(s.Position() - target_pos) < 0.0001;
+}
+
+
+LookAroundGoal::LookAroundGoal(Creature &c)
+: Goal(c)
+, timer(0.0) {
+}
+
+LookAroundGoal::~LookAroundGoal() {
+}
+
+std::string LookAroundGoal::Describe() const {
+ return "look around";
+}
+
+void LookAroundGoal::Enable() {
+ GetSteering().Halt();
+}
+
+void LookAroundGoal::Tick(double dt) {
+ timer -= dt;
+}
+
+void LookAroundGoal::Action() {
+ if (timer < 0.0) {
+ PickDirection();
+ timer = 1.0 + (Random().UNorm() * 4.0);
+ }
+}
+
+void LookAroundGoal::OnBackground() {
+ SetComplete();
+}
+
+void LookAroundGoal::PickDirection() noexcept {
+ double r = Random().SNorm();
+ r *= std::abs(r) * 0.5 * PI;
+ GetCreature().HeadingTarget(glm::rotate(GetSituation().Heading(), r, GetSituation().SurfaceNormal()));
+}
+
+
+StrollGoal::StrollGoal(Creature &c)
+: Goal(c)
+, last(GetSituation().Position())
+, next(last) {
+}
+
+StrollGoal::~StrollGoal() {
+}
+
+std::string StrollGoal::Describe() const {
+ return "take a walk";
+}
+
+void StrollGoal::Enable() {
+ last = GetSituation().Position();
+ GetSteering().Haste(0.0);
+ PickTarget();
+}
+
+void StrollGoal::Action() {
+ if (glm::length2(next - GetSituation().Position()) < 0.0001) {
+ PickTarget();
+ }
+}
+
+void StrollGoal::OnBackground() {
+ SetComplete();
+}
+
+void StrollGoal::PickTarget() noexcept {
+ last = next;
+ next += GetSituation().Heading() * 1.5;
+ const glm::dvec3 normal(GetSituation().GetPlanet().NormalAt(GetSituation().Position()));
+ glm::dvec3 rand_x(GetSituation().Heading());
+ if (std::abs(glm::dot(normal, rand_x)) > 0.999) {
+ rand_x = glm::dvec3(normal.z, normal.x, normal.y);
+ }
+ glm::dvec3 rand_y = glm::cross(normal, rand_x);
+ next += ((rand_x * Random().SNorm()) + (rand_y * Random().SNorm())) * 1.5;
+ next = glm::normalize(next) * GetSituation().GetPlanet().Radius();
+ GetSteering().GoTo(next);