From dc9537f9a3adbfa6b8296940be6c0ff4db734344 Mon Sep 17 00:00:00 2001 From: Insineer Date: Wed, 11 Sep 2019 05:49:11 +0300 Subject: [PATCH] feat(bumping): overhaul bumping code fixes #29 --- GameLogic/Object.py | 4 +++ GameLogic/Objects/Creature.py | 3 +- GameLogic/Objects/Creatures/Human.py | 2 +- GameLogic/Objects/Projectile.py | 21 +++++------- GameLogic/Objects/Turfs/Airlock.py | 8 +++-- GameLogic/Objects/Turfs/Wall.py | 3 +- .../Sources/Graphics/TileGrid/Object.cpp | 2 +- .../Sources/Graphics/TileGrid/Object.hpp | 1 + .../Sources/Graphics/TileGrid/Tile.cpp | 3 +- .../Sources/Graphics/TileGrid/Tile.hpp | 2 +- .../Sources/Graphics/TileGrid/TileGrid.cpp | 8 ++--- OSS13 Client/Sources/Network.cpp | 1 + .../ScriptEngine/Module/WorldModule.cpp | 2 +- .../ScriptEngine/Trampoline/PyObject.h | 4 +++ OSS13 Server/Sources/World/Objects/Object.cpp | 27 +++++++++------- OSS13 Server/Sources/World/Objects/Object.hpp | 2 ++ OSS13 Server/Sources/World/Tile.cpp | 32 +++++++++---------- OSS13 Server/Sources/World/Tile.hpp | 5 ++- .../Sources/Shared/Geometry/DirectionSet.h | 2 +- .../Protocol/ServerToClient/WorldInfo.h | 2 ++ 20 files changed, 72 insertions(+), 62 deletions(-) diff --git a/GameLogic/Object.py b/GameLogic/Object.py index f2418ef..3f8835e 100644 --- a/GameLogic/Object.py +++ b/GameLogic/Object.py @@ -11,3 +11,7 @@ def Update(self, timeElapsed): def InteractedBy(self, object): return False + + def BumpedTo(self, object): + print(self.name + " bumped to " + object.name) + return False diff --git a/GameLogic/Objects/Creature.py b/GameLogic/Objects/Creature.py index f0cba53..ab05c0e 100644 --- a/GameLogic/Objects/Creature.py +++ b/GameLogic/Objects/Creature.py @@ -11,6 +11,7 @@ def __init__(self): self.layer = 75 self.name = "Creature" + self.density = True self.__seeInvisibleAbility = False @@ -20,8 +21,6 @@ def __init__(self): self.control = self.GetComponent("Control") self.DefineUI(self.control.ui) - self.AddVerb("drop", lambda player: self.Drop()) - @property def seeInvisibleAbility(self): return self.__seeInvisibleAbility diff --git a/GameLogic/Objects/Creatures/Human.py b/GameLogic/Objects/Creatures/Human.py index 96f32bd..a359a21 100644 --- a/GameLogic/Objects/Creatures/Human.py +++ b/GameLogic/Objects/Creatures/Human.py @@ -12,9 +12,9 @@ def __init__(self): super().__init__() self.name = "Python Human" self.sprite = "human" - self.density = True self.PutOn(CreateObject("Objects.Items.Clothes.Uniform", None)) self.__updateActiveHandIcon() + self.AddVerb("drop", lambda player: self.Drop()) # IHasOrgans methods def CreateOrgans(self): diff --git a/GameLogic/Objects/Projectile.py b/GameLogic/Objects/Projectile.py index 2453614..09c92c3 100644 --- a/GameLogic/Objects/Projectile.py +++ b/GameLogic/Objects/Projectile.py @@ -1,3 +1,5 @@ +from Engine_Geometry import DirectionSet, Direction + from Object import Object from Objects.Creature import Creature @@ -7,27 +9,20 @@ def __init__(self): self.name = "Stun Orb" self.layer = 100 self.sprite = "stunorb" - self.density = False + self.density = True self.startTile = None self.__absoluteSpeed = 7.0 - self.__direction = None - - def Update(self, timeElapsed): - super().Update(timeElapsed) - if self.startTile is None: - self.startTile = self.tile - else: - if self.startTile is not self.tile: - if self.tile.IsDense(): - self.Hit(self.tile.GetDenseObject()) + def BumpedTo(self, object): + super().BumpedTo(object) + self.__hit(object) + return True def SetShotDirection(self, direction): direction = direction.Normalize() self.speed = direction * self.__absoluteSpeed - self.__direction = direction - def Hit(self, hittedObject): + def __hit(self, hittedObject): if isinstance(hittedObject, Creature): hittedObject.Stun() self.Delete() diff --git a/GameLogic/Objects/Turfs/Airlock.py b/GameLogic/Objects/Turfs/Airlock.py index 38f9aa9..e267601 100644 --- a/GameLogic/Objects/Turfs/Airlock.py +++ b/GameLogic/Objects/Turfs/Airlock.py @@ -1,3 +1,4 @@ +from Engine_Geometry import Direction from Objects.Turf import Turf class Airlock(Turf): @@ -5,8 +6,9 @@ def __init__(self): super().__init__() self.name = "Airlock" self.sprite = "airlock" - self.density = True + self.__closedSolidity = [Direction.CENTER] + self.solidity.Add(self.__closedSolidity) self.opened = False self.locked = False @@ -27,7 +29,7 @@ def Activate(self): return self.sprite = "airlock" self.opened = False - self.density = True + self.solidity.Add(self.__closedSolidity) else: if not self.PlayAnimation("airlock_opening", lambda: self.__animationOpeningCallback()): return @@ -41,7 +43,7 @@ def Unlock(self): def __animationOpeningCallback(self): self.opened = True - self.density = False + self.solidity.Reset() def __autocloseCallback(self): if self.opened: diff --git a/GameLogic/Objects/Turfs/Wall.py b/GameLogic/Objects/Turfs/Wall.py index dea9a17..c6f08c9 100644 --- a/GameLogic/Objects/Turfs/Wall.py +++ b/GameLogic/Objects/Turfs/Wall.py @@ -1,3 +1,4 @@ +from Engine_Geometry import Direction from Objects.Turf import Turf class Wall(Turf): @@ -6,4 +7,4 @@ def __init__(self): self.isWall = True self.name = "Wall" self.sprite = "wall" - self.density = True + self.solidity.Add([Direction.CENTER]) diff --git a/OSS13 Client/Sources/Graphics/TileGrid/Object.cpp b/OSS13 Client/Sources/Graphics/TileGrid/Object.cpp index 5417973..a724bc2 100644 --- a/OSS13 Client/Sources/Graphics/TileGrid/Object.cpp +++ b/OSS13 Client/Sources/Graphics/TileGrid/Object.cpp @@ -138,5 +138,5 @@ bool Object::PixelTransparent(uf::vec2i pixel) const { Tile *Object::GetTile() { return tile; } sf::Vector2f Object::GetShift() const { return shift; } sf::Vector2i Object::GetMoveIntent() const { return moveIntent; } -bool Object::IsDense() const { return solidity.IsExistsOne({uf::Direction::CENTER}); } +bool Object::IsDense() const { return density; } uf::DirectionSet Object::GetSolidity() const { return solidity; } diff --git a/OSS13 Client/Sources/Graphics/TileGrid/Object.hpp b/OSS13 Client/Sources/Graphics/TileGrid/Object.hpp index f7b5e31..53f7993 100644 --- a/OSS13 Client/Sources/Graphics/TileGrid/Object.hpp +++ b/OSS13 Client/Sources/Graphics/TileGrid/Object.hpp @@ -71,6 +71,7 @@ class Object { uf::Direction direction; uint layer; + bool density; uf::DirectionSet solidity; uf::DirectionSetFractional opacity; diff --git a/OSS13 Client/Sources/Graphics/TileGrid/Tile.cpp b/OSS13 Client/Sources/Graphics/TileGrid/Tile.cpp index 0601381..a1bf796 100644 --- a/OSS13 Client/Sources/Graphics/TileGrid/Tile.cpp +++ b/OSS13 Client/Sources/Graphics/TileGrid/Tile.cpp @@ -104,9 +104,8 @@ bool Tile::IsBlocked() const { return false; } -bool Tile::IsBlocked(const std::initializer_list &directions) const { +bool Tile::IsBlocked(uf::DirectionSet directions) const { for (auto &obj : content) if (obj->GetSolidity().IsExistsOne(directions)) return true; return false; } - diff --git a/OSS13 Client/Sources/Graphics/TileGrid/Tile.hpp b/OSS13 Client/Sources/Graphics/TileGrid/Tile.hpp index 0aeb50b..f855f40 100644 --- a/OSS13 Client/Sources/Graphics/TileGrid/Tile.hpp +++ b/OSS13 Client/Sources/Graphics/TileGrid/Tile.hpp @@ -40,7 +40,7 @@ class Tile : public INonCopyable { Object *GetObject(uint id); TileGrid *GetTileGrid(); bool IsBlocked() const; - bool IsBlocked(const std::initializer_list &directions) const; + bool IsBlocked(uf::DirectionSet directions) const; friend sf::Packet &operator>>(sf::Packet &packet, Tile &tile); friend std::unique_ptr CreateTileWithInfo(TileGrid *tileGrid, const network::protocol::TileInfo &tileInfo); diff --git a/OSS13 Client/Sources/Graphics/TileGrid/TileGrid.cpp b/OSS13 Client/Sources/Graphics/TileGrid/TileGrid.cpp index 1e8e7af..30ef2ef 100644 --- a/OSS13 Client/Sources/Graphics/TileGrid/TileGrid.cpp +++ b/OSS13 Client/Sources/Graphics/TileGrid/TileGrid.cpp @@ -220,14 +220,14 @@ void MovementPrediction(Object *controllable, uf::vec2i moveCommand) { if (controllable->IsDense()) { auto moveDirection = uf::VectToDirection(moveIntent); - if (lastTile->IsBlocked({ moveDirection })) { // exit from current tile + if (lastTile->IsBlocked(uf::DirectionSet({ moveDirection }))) { // exit from current tile moveIntent = controllable->GetMoveIntent(); } else { - if (!newTileDiag || newTileDiag->IsBlocked({ uf::InvertDirection(moveDirection), uf::Direction::CENTER })) { + if (!newTileDiag || newTileDiag->IsBlocked(uf::DirectionSet({ uf::InvertDirection(moveDirection), uf::Direction::CENTER }))) { return; } else { - if (!newTileX || newTileX != lastTile && newTileX->IsBlocked({ uf::InvertDirection(xDirection), yDirection, uf::Direction::CENTER })) return; - if (!newTileY || newTileY != lastTile && newTileY->IsBlocked({ uf::InvertDirection(yDirection), xDirection, uf::Direction::CENTER })) return; + if (!newTileX || newTileX != lastTile && newTileX->IsBlocked(uf::DirectionSet({ uf::InvertDirection(xDirection), yDirection, uf::Direction::CENTER }))) return; + if (!newTileY || newTileY != lastTile && newTileY->IsBlocked(uf::DirectionSet({ uf::InvertDirection(yDirection), xDirection, uf::Direction::CENTER }))) return; } } } diff --git a/OSS13 Client/Sources/Network.cpp b/OSS13 Client/Sources/Network.cpp index 468a819..76cac63 100644 --- a/OSS13 Client/Sources/Network.cpp +++ b/OSS13 Client/Sources/Network.cpp @@ -99,6 +99,7 @@ std::unique_ptr CreateObjectWithInfo(const network::protocol::ObjectInfo object->name = objectInfo.name; object->layer = objectInfo.layer; object->direction = objectInfo.direction; + object->density = objectInfo.density; object->solidity = objectInfo.solidity; object->opacity = objectInfo.opacity; object->moveSpeed = objectInfo.moveSpeed; diff --git a/OSS13 Server/Sources/ScriptEngine/Module/WorldModule.cpp b/OSS13 Server/Sources/ScriptEngine/Module/WorldModule.cpp index f567d3e..18eb72b 100644 --- a/OSS13 Server/Sources/ScriptEngine/Module/WorldModule.cpp +++ b/OSS13 Server/Sources/ScriptEngine/Module/WorldModule.cpp @@ -34,7 +34,7 @@ PYBIND11_EMBEDDED_MODULE(Engine_World, m) { .def_property_readonly("z", &Tile::Z) .def_property_readonly("pos", &Tile::GetPos) .def_property_readonly("map", &Tile::GetMap) - .def("IsDense", py::overload_cast<>(&Tile::IsDense, py::const_)) + .def("IsDense", &Tile::IsDense) .def("IsSpace", &Tile::IsSpace) .def("GetDenseObject", &Tile::GetDenseObject, py::return_value_policy::reference); diff --git a/OSS13 Server/Sources/ScriptEngine/Trampoline/PyObject.h b/OSS13 Server/Sources/ScriptEngine/Trampoline/PyObject.h index 55992ea..d40da6e 100644 --- a/OSS13 Server/Sources/ScriptEngine/Trampoline/PyObject.h +++ b/OSS13 Server/Sources/ScriptEngine/Trampoline/PyObject.h @@ -22,6 +22,10 @@ class PyObject : public Object, public std::enable_shared_from_this { PYBIND11_OVERLOAD_PURE_NAME(bool, Object, "InteractedBy", InteractedBy, obj); } + bool BumpedTo(Object *obj) override { + PYBIND11_OVERLOAD_PURE_NAME(bool, Object, "BumpedTo", BumpedTo, obj); + } + bool RemoveObject(Object *obj) override { PYBIND11_OVERLOAD_NAME(bool, Object, "RemoveObject", RemoveObject, obj); } diff --git a/OSS13 Server/Sources/World/Objects/Object.cpp b/OSS13 Server/Sources/World/Objects/Object.cpp index f8e9f72..cd3ac14 100644 --- a/OSS13 Server/Sources/World/Objects/Object.cpp +++ b/OSS13 Server/Sources/World/Objects/Object.cpp @@ -62,12 +62,14 @@ void Object::Update(std::chrono::microseconds timeElapsed) { if (iconsOutdated) { updateIcons(); - auto diff = std::make_shared(); - diff->objId = ID(); - for (auto &iconInfo : icons) - diff->iconsIds.push_back(iconInfo.id + static_cast(iconInfo.state)); - GetTile()->AddDiff(diff, this); - iconsOutdated = false; + if (GetTile()) { + auto diff = std::make_shared(); + diff->objId = ID(); + for (auto &iconInfo : icons) + diff->iconsIds.push_back(iconInfo.id + static_cast(iconInfo.state)); + GetTile()->AddDiff(diff, this); + iconsOutdated = false; + } } animationTimer.Update(timeElapsed); @@ -97,15 +99,15 @@ void Object::Move(uf::vec2i order) { if (GetDensity()) { auto moveDirection = uf::VectToDirection(moveIntent); - if (tile->IsDense({moveDirection})) { // exit from current tile + if (tile->IsDense(DirectionSet({moveDirection}))) { // exit from current tile moveIntent = GetMoveIntent(); } else { - if (!newTileDiag || newTileDiag->IsDense({uf::InvertDirection(moveDirection), uf::Direction::CENTER})) { + if (!newTileDiag || newTileDiag->IsDense((DirectionSet({uf::InvertDirection(moveDirection), uf::Direction::CENTER})))) { return; } else { - if (!newTileX || newTileX != tile && newTileX->IsDense({ uf::InvertDirection(xDirection), yDirection, uf::Direction::CENTER })) return; - if (!newTileY || newTileY != tile && newTileY->IsDense({ uf::InvertDirection(yDirection), xDirection, uf::Direction::CENTER })) return; + if (!newTileX || newTileX != tile && newTileX->IsDense((DirectionSet({ uf::InvertDirection(xDirection), yDirection, uf::Direction::CENTER })))) return; + if (!newTileY || newTileY != tile && newTileY->IsDense((DirectionSet({ uf::InvertDirection(yDirection), xDirection, uf::Direction::CENTER })))) return; } } } @@ -204,8 +206,8 @@ bool Object::PlayAnimation(const std::string &animation, std::function c return true; } -bool Object::GetDensity() const { return solidity.IsExistsOne({Direction::CENTER}); }; -void Object::SetDensity(bool density) { density ? solidity.Add({Direction::CENTER}) : solidity.Remove({Direction::CENTER}); } +bool Object::GetDensity() const { return density; }; +void Object::SetDensity(bool density) { this->density = density; } void Object::SetSolidity(uf::DirectionSet directions) { solidity = directions; } const uf::DirectionSet &Object::GetSolidity() const { return solidity; } @@ -316,6 +318,7 @@ network::protocol::ObjectInfo Object::GetObjectInfo() const { objectInfo.name = name; objectInfo.layer = layer; objectInfo.direction = direction; + objectInfo.density = density; objectInfo.solidity = solidity; objectInfo.opacity = opacity; objectInfo.moveSpeed = moveSpeed; diff --git a/OSS13 Server/Sources/World/Objects/Object.hpp b/OSS13 Server/Sources/World/Objects/Object.hpp index 51a0950..bdb7ae1 100644 --- a/OSS13 Server/Sources/World/Objects/Object.hpp +++ b/OSS13 Server/Sources/World/Objects/Object.hpp @@ -30,6 +30,7 @@ class Object : public VerbsHolder, public INonCopyable { virtual void Update(std::chrono::microseconds timeElapsed); virtual bool InteractedBy(Object *) = 0; + virtual bool BumpedTo(Object *) = 0; virtual void Move(uf::vec2i order); virtual void MoveZ(int order) {}; @@ -135,6 +136,7 @@ class Object : public VerbsHolder, public INonCopyable { uint layer; uf::Direction direction; + bool density{false}; // object can't pass through solid objects uf::DirectionSet solidity; uf::DirectionSetFractional opacity; uf::DirectionSetFractional airtightness; diff --git a/OSS13 Server/Sources/World/Tile.cpp b/OSS13 Server/Sources/World/Tile.cpp index f590aff..7f7f0ae 100644 --- a/OSS13 Server/Sources/World/Tile.cpp +++ b/OSS13 Server/Sources/World/Tile.cpp @@ -107,20 +107,24 @@ bool Tile::MoveTo(Object *obj) { return false; } - if (obj->GetDensity()) - for (auto &object : content) - if (object) - if (object->GetDensity()) { - return false; - } - Tile *lastTile = obj->GetTile(); rpos delta = GetPos() - lastTile->GetPos(); + uf::Direction direction = uf::VectToDirection(delta); + + if (obj->GetDensity()) { + auto bumpedTo = lastTile->GetDenseObject(DirectionSet({ direction })); + if (!bumpedTo) + bumpedTo = GetDenseObject(DirectionSet({uf::InvertDirection(direction), uf::Direction::CENTER})); + if (bumpedTo) { + obj->BumpedTo(bumpedTo); + return false; + } + } + if (abs(delta.x) > 1 || abs(delta.y) > 1) LOGW << "Warning! Moving more than a one tile. (Tile::MoveTo)"; if (delta.z) LOGW << "Warning! Moving between Z-levels. (Tile::MoveTo)"; - const uf::Direction direction = uf::VectToDirection(delta); auto relocateAwayDiff = std::make_shared(); // TODO: MoveAway??? relocateAwayDiff->objId = obj->ID(); @@ -196,10 +200,10 @@ const std::list &Tile::Content() const { return content; } -Object *Tile::GetDenseObject() const +Object *Tile::GetDenseObject(DirectionSet directions) const { for (auto &obj : content) - if (obj->GetDensity()) return obj; + if (obj->GetSolidity().IsExistsOne(directions)) return obj; return nullptr; } @@ -209,13 +213,7 @@ uf::vec3i Tile::GetPos() const { Map *Tile::GetMap() const { return map; } -bool Tile::IsDense() const { - for (auto &obj : content) - if (obj->GetDensity()) return true; - return false; -} - -bool Tile::IsDense(const std::initializer_list &directions) const { +bool Tile::IsDense(uf::DirectionSet directions) const { for (auto &obj : content) if (obj->GetSolidity().IsExistsOne(directions)) return true; return false; diff --git a/OSS13 Server/Sources/World/Tile.hpp b/OSS13 Server/Sources/World/Tile.hpp index 3b43c77..f9cdf38 100644 --- a/OSS13 Server/Sources/World/Tile.hpp +++ b/OSS13 Server/Sources/World/Tile.hpp @@ -37,12 +37,11 @@ class Tile { void PlaceTo(Object *); const std::list &Content() const; - Object *GetDenseObject() const; + Object *GetDenseObject(uf::DirectionSet directions) const; uf::vec3i GetPos() const; Map *GetMap() const; - bool IsDense() const; - bool IsDense(const std::initializer_list &directions) const; + bool IsDense(uf::DirectionSet directions) const; bool IsSpace() const; Locale *GetLocale() const; diff --git a/SharedLibrary/Sources/Shared/Geometry/DirectionSet.h b/SharedLibrary/Sources/Shared/Geometry/DirectionSet.h index 9bceb24..9330e8e 100644 --- a/SharedLibrary/Sources/Shared/Geometry/DirectionSet.h +++ b/SharedLibrary/Sources/Shared/Geometry/DirectionSet.h @@ -13,7 +13,7 @@ namespace uf { class DirectionSet { public: DirectionSet() = default; - explicit DirectionSet(std::list directions); + DirectionSet(std::list directions); DirectionSet(const DirectionSet &) = default; DirectionSet(DirectionSet &&) = default; diff --git a/SharedLibrary/Sources/Shared/Network/Protocol/ServerToClient/WorldInfo.h b/SharedLibrary/Sources/Shared/Network/Protocol/ServerToClient/WorldInfo.h index a7abb25..f0aa032 100644 --- a/SharedLibrary/Sources/Shared/Network/Protocol/ServerToClient/WorldInfo.h +++ b/SharedLibrary/Sources/Shared/Network/Protocol/ServerToClient/WorldInfo.h @@ -15,6 +15,7 @@ DEFINE_SERIALIZABLE(ObjectInfo, uf::ISerializable) std::vector spriteIds; uint32_t layer; uf::Direction direction; + bool density; uf::DirectionSet solidity; uf::DirectionSetFractional opacity; @@ -28,6 +29,7 @@ DEFINE_SERIALIZABLE(ObjectInfo, uf::ISerializable) ar & spriteIds; ar & layer; ar & direction; + ar & density; ar & solidity; ar & opacity; ar & moveSpeed;