summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/critter.cpp2
-rw-r--r--src/critter.hpp2
-rw-r--r--src/object.hpp2
-rw-r--r--src/world.cpp68
-rw-r--r--src/world.hpp12
5 files changed, 80 insertions, 6 deletions
diff --git a/src/critter.cpp b/src/critter.cpp
index f018f274..b187c33a 100644
--- a/src/critter.cpp
+++ b/src/critter.cpp
@@ -212,7 +212,7 @@ critter::operator critter_proto() const
return ret;
}
-critter::critter(object_id id, class chunk& c, const critter_proto& proto) :
+critter::critter(object_id id, class chunk& c, critter_proto proto) : // todo! check if it gets move-constructed
object{id, c, proto},
name{proto.name},
speed{proto.speed},
diff --git a/src/critter.hpp b/src/critter.hpp
index 01159710..fc3e8f17 100644
--- a/src/critter.hpp
+++ b/src/critter.hpp
@@ -41,7 +41,7 @@ struct critter final : object
private:
friend class world;
- critter(object_id id, class chunk& c, const critter_proto& proto);
+ critter(object_id id, class chunk& c, critter_proto proto);
};
template<> struct object_type_<struct critter> : std::integral_constant<object_type, object_type::critter> {};
diff --git a/src/object.hpp b/src/object.hpp
index f15699bb..49d861aa 100644
--- a/src/object.hpp
+++ b/src/object.hpp
@@ -48,7 +48,7 @@ struct object
const Vector2b offset, bbox_offset;
const Vector2ub bbox_size;
uint16_t delta = 0, frame = 0;
- const rotation r = rotation::N;
+ const rotation r = rotation::N; // todo remove bitfield?
const pass_mode pass = pass_mode::see_through;
bool ephemeral : 1 = false;
//char _pad[4]; // got 4 bytes left
diff --git a/src/world.cpp b/src/world.cpp
index ef0de7ae..650f1494 100644
--- a/src/world.cpp
+++ b/src/world.cpp
@@ -1,6 +1,8 @@
#include "world.hpp"
#include "chunk.hpp"
#include "object.hpp"
+#include "critter.hpp"
+#include "compat/shared-ptr-wrapper.hpp"
#include "compat/int-hash.hpp"
#include "compat/exception.hpp"
#include <cr/GrowableArray.h>
@@ -95,7 +97,7 @@ chunk& world::operator[](chunk_coords_ coord) noexcept
return *c;
}
-auto world::operator[](global_coords pt) noexcept -> pair
+auto world::operator[](global_coords pt) noexcept -> pair_chunk_tile
{
auto& c = operator[](pt.chunk3());
return { c, c[pt.local()] };
@@ -196,4 +198,68 @@ auto world::neighbors(chunk_coords_ coord) -> std::array<chunk*, 8>
return ret;
}
+const critter_proto& world::make_player_proto()
+{
+ static const critter_proto p = []
+ {
+ critter_proto cproto;
+ cproto.name = "Player"_s;
+ cproto.speed = 10;
+ cproto.playable = true;
+ return cproto;
+ }();
+ return p;
+}
+
+shared_ptr_wrapper<critter> world::ensure_player_character(object_id& id)
+{
+ return ensure_player_character(id, make_player_proto());
+}
+
+shared_ptr_wrapper<critter> world::ensure_player_character(object_id& id_, critter_proto p)
+{
+ if (id_)
+ {
+ std::shared_ptr<critter> tmp;
+ if (auto C = find_object(id_); C && C->type() == object_type::critter)
+ {
+ auto ptr = std::static_pointer_cast<critter>(C);
+ return {ptr};
+ }
+ }
+ id_ = 0;
+
+ auto id = (object_id)-1;
+
+ shared_ptr_wrapper<critter> ret;
+
+ for (const auto& [coord, c] : chunks()) // todo use world::_objects
+ {
+ for (const auto& e_ : c.objects())
+ {
+ const auto& e = *e_;
+ if (e.type() == object_type::critter)
+ {
+ const auto& C = static_cast<const critter&>(e);
+ if (C.playable)
+ {
+ id = std::min(id, C.id);
+ ret.ptr = std::static_pointer_cast<critter>(e_);
+ }
+ }
+ }
+ }
+
+ if (id != (object_id)-1)
+ id_ = id;
+ else
+ {
+ p.playable = true;
+ ret.ptr = make_object<critter>(make_id(), global_coords{}, p);
+ id_ = ret.ptr->id;
+ }
+ fm_debug_assert(ret.ptr);
+ return ret;
+}
+
} // namespace floormat
diff --git a/src/world.hpp b/src/world.hpp
index 19a31a46..c6846750 100644
--- a/src/world.hpp
+++ b/src/world.hpp
@@ -10,7 +10,10 @@
namespace floormat {
struct object;
+struct critter;
+struct critter_proto;
template<typename T> struct object_type_;
+template<typename T> struct shared_ptr_wrapper;
class world final
{
@@ -43,6 +46,7 @@ private:
void do_kill_object(object_id id);
std::shared_ptr<object> find_object_(object_id id);
+
[[noreturn]] static void throw_on_wrong_object_type(object_id id, object_type actual, object_type expected);
friend struct object;
@@ -52,10 +56,10 @@ public:
~world() noexcept;
explicit world(std::unordered_map<chunk_coords_, chunk>&& chunks);
- struct pair final { chunk& c; tile_ref t; }; // NOLINT
+ struct pair_chunk_tile final { chunk& c; tile_ref t; }; // NOLINT
chunk& operator[](chunk_coords_ c) noexcept;
- pair operator[](global_coords pt) noexcept; // todo maybe remove this overload?
+ pair_chunk_tile operator[](global_coords pt) noexcept; // todo maybe remove this overload?
chunk* at(chunk_coords_ c) noexcept;
bool contains(chunk_coords_ c) const noexcept;
void clear();
@@ -90,6 +94,10 @@ public:
template<typename T = object> std::shared_ptr<T> find_object(object_id id);
+ shared_ptr_wrapper<critter> ensure_player_character(object_id& id, critter_proto p);
+ shared_ptr_wrapper<critter> ensure_player_character(object_id& id);
+ static const critter_proto& make_player_proto();
+
bool is_teardown() const { return _teardown; }
object_id object_counter() const { return _object_counter; }
[[nodiscard]] object_id make_id() { return ++_object_counter; }