#include "critter-script.hpp" //#include "raycast.hpp" #include "point.hpp" #include "critter.hpp" #include "search-result.hpp" #include "search-astar.hpp" #include "entity/name-of.hpp" #include namespace floormat { using walk_mode = critter_script::walk_mode; namespace { bool walk_line(point dest, const std::shared_ptr& c, size_t& i, const Ns& dt) { auto res = c->move_toward(i, dt, dest); return res.blocked || c->position() == dest; } struct walk_script final : critter_script { struct line_tag_t {}; struct path_tag_t {}; StringView name() const override; const void* id() const override; void on_init(const std::shared_ptr& c) override; void on_update(const std::shared_ptr& c, size_t& i, const Ns& dt) override; void on_destroy(const std::shared_ptr& c, script_destroy_reason reason) override; void delete_self() noexcept override; walk_script(point dest, line_tag_t); //walk_script(point dest, path_search_result path, path_tag_t); private: point dest; Optional path; walk_mode mode = walk_mode::none; }; walk_script::walk_script(point dest, line_tag_t) : dest{dest}, mode{walk_mode::line} { } void walk_script::on_init(const std::shared_ptr& c) { c->movement.AUTO = true; } void walk_script::on_update(const std::shared_ptr& c, size_t& i, const Ns& dt) { auto& m = c->movement; if (m.L | m.R | m.U | m.D) m.AUTO = false; if (!m.AUTO) goto done; switch (mode) { case walk_mode::none: fm_abort("bad walk_mode 'none'"); case walk_mode::line: fm_assert(!path); if (walk_line(dest, c, i, dt)) goto done; return; case walk_mode::path: fm_abort("todo!"); //break; } std::unreachable(); fm_assert(false); done: Debug{} << " finished walking"; m.AUTO = false; c->script.do_clear(c); } constexpr StringView script_name = name_of; StringView walk_script::name() const { return "walk"_s; } const void* walk_script::id() const { return &script_name; } void walk_script::on_destroy(const std::shared_ptr& c, script_destroy_reason reason) { } void walk_script::delete_self() noexcept { delete this; } } // namespace Pointer critter_script::make_walk_script(point dest, const path_search_result& path, walk_mode mode) { switch (mode) { case walk_mode::line: fm_assert(path.empty()); return Pointer(new walk_script{dest, walk_script::line_tag_t{}}); case walk_mode::path: fm_abort("todo!"); fm_assert(!path.empty()); case walk_mode::none: break; } fm_abort("bad walk_mode %d", (int)mode); } } // namespace floormat