diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index f785797c1..6c44c97e2 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -27,23 +27,26 @@ #include "../mwmechanics/npcstats.hpp" -namespace +namespace MWClass { - struct ContainerCustomData : public MWWorld::CustomData + class ContainerCustomData : public MWWorld::CustomData { + public: MWWorld::ContainerStore mContainerStore; virtual MWWorld::CustomData *clone() const; + + virtual ContainerCustomData& asContainerCustomData() + { + return *this; + } }; MWWorld::CustomData *ContainerCustomData::clone() const { return new ContainerCustomData (*this); } -} -namespace MWClass -{ std::string Container::getId (const MWWorld::Ptr& ptr) const { return ptr.get()->mBase->mId; @@ -202,7 +205,7 @@ namespace MWClass { ensureCustomData (ptr); - return dynamic_cast (*ptr.getRefData().getCustomData()).mContainerStore; + return ptr.getRefData().getCustomData()->asContainerCustomData().mContainerStore; } std::string Container::getScript (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 95bc429e3..2cd11d113 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -40,14 +40,29 @@ namespace { - struct CreatureCustomData : public MWWorld::CustomData + bool isFlagBitSet(const MWWorld::Ptr &ptr, ESM::Creature::Flags bitMask) { + return (ptr.get()->mBase->mFlags & bitMask) != 0; + } +} + +namespace MWClass +{ + + class CreatureCustomData : public MWWorld::CustomData + { + public: MWMechanics::CreatureStats mCreatureStats; MWWorld::ContainerStore* mContainerStore; // may be InventoryStore for some creatures MWMechanics::Movement mMovement; virtual MWWorld::CustomData *clone() const; + virtual CreatureCustomData& asCreatureCustomData() + { + return *this; + } + CreatureCustomData() : mContainerStore(0) {} virtual ~CreatureCustomData() { delete mContainerStore; } }; @@ -59,14 +74,6 @@ namespace return cloned; } - bool isFlagBitSet(const MWWorld::Ptr &ptr, ESM::Creature::Flags bitMask) - { - return (ptr.get()->mBase->mFlags & bitMask) != 0; - } -} - -namespace MWClass -{ const Creature::GMST& Creature::getGmst() { static GMST gmst; @@ -193,7 +200,7 @@ namespace MWClass { ensureCustomData (ptr); - return dynamic_cast (*ptr.getRefData().getCustomData()).mCreatureStats; + return ptr.getRefData().getCustomData()->asCreatureCustomData().mCreatureStats; } @@ -421,7 +428,7 @@ namespace MWClass { ensureCustomData (ptr); - return *dynamic_cast (*ptr.getRefData().getCustomData()).mContainerStore; + return *ptr.getRefData().getCustomData()->asCreatureCustomData().mContainerStore; } MWWorld::InventoryStore& Creature::getInventoryStore(const MWWorld::Ptr &ptr) const @@ -511,7 +518,7 @@ namespace MWClass { ensureCustomData (ptr); - return dynamic_cast (*ptr.getRefData().getCustomData()).mMovement; + return ptr.getRefData().getCustomData()->asCreatureCustomData().mMovement; } MWGui::ToolTipInfo Creature::getToolTipInfo (const MWWorld::Ptr& ptr) const @@ -711,7 +718,7 @@ namespace MWClass else ensureCustomData(ptr); // in openmw 0.30 savegames not all state was saved yet, so need to load it regardless. - CreatureCustomData& customData = dynamic_cast (*ptr.getRefData().getCustomData()); + CreatureCustomData& customData = ptr.getRefData().getCustomData()->asCreatureCustomData(); customData.mContainerStore->readState (state2.mInventory); customData.mCreatureStats.readState (state2.mCreatureStats); @@ -730,7 +737,7 @@ namespace MWClass ensureCustomData (ptr); - CreatureCustomData& customData = dynamic_cast (*ptr.getRefData().getCustomData()); + CreatureCustomData& customData = ptr.getRefData().getCustomData()->asCreatureCustomData(); customData.mContainerStore->writeState (state2.mInventory); customData.mCreatureStats.writeState (state2.mCreatureStats); diff --git a/apps/openmw/mwclass/creaturelevlist.cpp b/apps/openmw/mwclass/creaturelevlist.cpp index 433e5fcea..c015d53d6 100644 --- a/apps/openmw/mwclass/creaturelevlist.cpp +++ b/apps/openmw/mwclass/creaturelevlist.cpp @@ -7,25 +7,28 @@ #include "../mwworld/customdata.hpp" -namespace +namespace MWClass { - struct CreatureLevListCustomData : public MWWorld::CustomData + class CreatureLevListCustomData : public MWWorld::CustomData { + public: // actorId of the creature we spawned int mSpawnActorId; bool mSpawn; // Should a new creature be spawned? virtual MWWorld::CustomData *clone() const; + + virtual CreatureLevListCustomData& asCreatureLevListCustomData() + { + return *this; + } }; MWWorld::CustomData *CreatureLevListCustomData::clone() const { return new CreatureLevListCustomData (*this); } -} -namespace MWClass -{ std::string CreatureLevList::getId (const MWWorld::Ptr& ptr) const { return ptr.get()->mBase->mId; @@ -40,7 +43,7 @@ namespace MWClass { ensureCustomData(ptr); - CreatureLevListCustomData& customData = dynamic_cast (*ptr.getRefData().getCustomData()); + CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData(); customData.mSpawn = true; } @@ -55,7 +58,7 @@ namespace MWClass { ensureCustomData(ptr); - CreatureLevListCustomData& customData = dynamic_cast (*ptr.getRefData().getCustomData()); + CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData(); if (!customData.mSpawn) return; @@ -104,7 +107,7 @@ namespace MWClass const ESM::CreatureLevListState& state2 = dynamic_cast (state); ensureCustomData(ptr); - CreatureLevListCustomData& customData = dynamic_cast (*ptr.getRefData().getCustomData()); + CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData(); customData.mSpawnActorId = state2.mSpawnActorId; customData.mSpawn = state2.mSpawn; } @@ -115,7 +118,7 @@ namespace MWClass ESM::CreatureLevListState& state2 = dynamic_cast (state); ensureCustomData(ptr); - CreatureLevListCustomData& customData = dynamic_cast (*ptr.getRefData().getCustomData()); + CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData(); state2.mSpawnActorId = customData.mSpawnActorId; state2.mSpawn = customData.mSpawn; } diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 47219deb7..6fee79ddf 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -28,23 +28,26 @@ #include "../mwmechanics/actorutil.hpp" -namespace +namespace MWClass { - struct DoorCustomData : public MWWorld::CustomData + class DoorCustomData : public MWWorld::CustomData { + public: int mDoorState; // 0 = nothing, 1 = opening, 2 = closing virtual MWWorld::CustomData *clone() const; + + virtual DoorCustomData& asDoorCustomData() + { + return *this; + } }; MWWorld::CustomData *DoorCustomData::clone() const { return new DoorCustomData (*this); } -} -namespace MWClass -{ std::string Door::getId (const MWWorld::Ptr& ptr) const { return ptr.get()->mBase->mId; @@ -65,7 +68,7 @@ namespace MWClass // Resume the door's opening/closing animation if it wasn't finished if (ptr.getRefData().getCustomData()) { - const DoorCustomData& customData = dynamic_cast(*ptr.getRefData().getCustomData()); + const DoorCustomData& customData = ptr.getRefData().getCustomData()->asDoorCustomData(); if (customData.mDoorState > 0) { MWBase::Environment::get().getWorld()->activateDoor(ptr, customData.mDoorState); @@ -324,7 +327,7 @@ namespace MWClass int Door::getDoorState (const MWWorld::Ptr &ptr) const { ensureCustomData(ptr); - const DoorCustomData& customData = dynamic_cast(*ptr.getRefData().getCustomData()); + const DoorCustomData& customData = ptr.getRefData().getCustomData()->asDoorCustomData(); return customData.mDoorState; } @@ -334,14 +337,14 @@ namespace MWClass throw std::runtime_error("load doors can't be moved"); ensureCustomData(ptr); - DoorCustomData& customData = dynamic_cast(*ptr.getRefData().getCustomData()); + DoorCustomData& customData = ptr.getRefData().getCustomData()->asDoorCustomData(); customData.mDoorState = state; } void Door::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) const { ensureCustomData(ptr); - DoorCustomData& customData = dynamic_cast(*ptr.getRefData().getCustomData()); + DoorCustomData& customData = ptr.getRefData().getCustomData()->asDoorCustomData(); const ESM::DoorState& state2 = dynamic_cast(state); customData.mDoorState = state2.mDoorState; @@ -350,7 +353,7 @@ namespace MWClass void Door::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state) const { ensureCustomData(ptr); - const DoorCustomData& customData = dynamic_cast(*ptr.getRefData().getCustomData()); + const DoorCustomData& customData = ptr.getRefData().getCustomData()->asDoorCustomData(); ESM::DoorState& state2 = dynamic_cast(state); state2.mDoorState = customData.mDoorState; diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 5679dc3e9..6633b3490 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -42,19 +42,6 @@ namespace { - struct NpcCustomData : public MWWorld::CustomData - { - MWMechanics::NpcStats mNpcStats; - MWMechanics::Movement mMovement; - MWWorld::InventoryStore mInventoryStore; - - virtual MWWorld::CustomData *clone() const; - }; - - MWWorld::CustomData *NpcCustomData::clone() const - { - return new NpcCustomData (*this); - } int is_even(double d) { double int_part; @@ -251,6 +238,27 @@ namespace namespace MWClass { + + class NpcCustomData : public MWWorld::CustomData + { + public: + MWMechanics::NpcStats mNpcStats; + MWMechanics::Movement mMovement; + MWWorld::InventoryStore mInventoryStore; + + virtual MWWorld::CustomData *clone() const; + + virtual NpcCustomData& asNpcCustomData() + { + return *this; + } + }; + + MWWorld::CustomData *NpcCustomData::clone() const + { + return new NpcCustomData (*this); + } + const Npc::GMST& Npc::getGmst() { static GMST gmst; @@ -446,14 +454,14 @@ namespace MWClass { ensureCustomData (ptr); - return dynamic_cast (*ptr.getRefData().getCustomData()).mNpcStats; + return ptr.getRefData().getCustomData()->asNpcCustomData().mNpcStats; } MWMechanics::NpcStats& Npc::getNpcStats (const MWWorld::Ptr& ptr) const { ensureCustomData (ptr); - return dynamic_cast (*ptr.getRefData().getCustomData()).mNpcStats; + return ptr.getRefData().getCustomData()->asNpcCustomData().mNpcStats; } @@ -780,7 +788,7 @@ namespace MWClass { ensureCustomData (ptr); - return dynamic_cast (*ptr.getRefData().getCustomData()).mInventoryStore; + return ptr.getRefData().getCustomData()->asNpcCustomData().mInventoryStore; } MWWorld::InventoryStore& Npc::getInventoryStore (const MWWorld::Ptr& ptr) @@ -788,7 +796,7 @@ namespace MWClass { ensureCustomData (ptr); - return dynamic_cast (*ptr.getRefData().getCustomData()).mInventoryStore; + return ptr.getRefData().getCustomData()->asNpcCustomData().mInventoryStore; } std::string Npc::getScript (const MWWorld::Ptr& ptr) const @@ -897,7 +905,7 @@ namespace MWClass { ensureCustomData (ptr); - return dynamic_cast (*ptr.getRefData().getCustomData()).mMovement; + return ptr.getRefData().getCustomData()->asNpcCustomData().mMovement; } bool Npc::isEssential (const MWWorld::Ptr& ptr) const @@ -1161,7 +1169,7 @@ namespace MWClass else ensureCustomData(ptr); // in openmw 0.30 savegames not all state was saved yet, so need to load it regardless. - NpcCustomData& customData = dynamic_cast (*ptr.getRefData().getCustomData()); + NpcCustomData& customData = ptr.getRefData().getCustomData()->asNpcCustomData(); customData.mInventoryStore.readState (state2.mInventory); customData.mNpcStats.readState (state2.mNpcStats); @@ -1181,7 +1189,7 @@ namespace MWClass ensureCustomData (ptr); - NpcCustomData& customData = dynamic_cast (*ptr.getRefData().getCustomData()); + NpcCustomData& customData = ptr.getRefData().getCustomData()->asNpcCustomData(); customData.mInventoryStore.writeState (state2.mInventory); customData.mNpcStats.writeState (state2.mNpcStats); diff --git a/apps/openmw/mwworld/customdata.cpp b/apps/openmw/mwworld/customdata.cpp new file mode 100644 index 000000000..8edbb345f --- /dev/null +++ b/apps/openmw/mwworld/customdata.cpp @@ -0,0 +1,46 @@ +#include "customdata.hpp" + +#include +#include +#include + +namespace MWWorld +{ + +MWClass::CreatureCustomData &CustomData::asCreatureCustomData() +{ + std::stringstream error; + error << "bad cast " << typeid(this).name() << " to CreatureCustomData"; + throw std::logic_error(error.str()); +} + +MWClass::NpcCustomData &CustomData::asNpcCustomData() +{ + std::stringstream error; + error << "bad cast " << typeid(this).name() << " to NpcCustomData"; + throw std::logic_error(error.str()); +} + +MWClass::ContainerCustomData &CustomData::asContainerCustomData() +{ + std::stringstream error; + error << "bad cast " << typeid(this).name() << " to ContainerCustomData"; + throw std::logic_error(error.str()); +} + +MWClass::DoorCustomData &CustomData::asDoorCustomData() +{ + std::stringstream error; + error << "bad cast " << typeid(this).name() << " to DoorCustomData"; + throw std::logic_error(error.str()); +} + +MWClass::CreatureLevListCustomData &CustomData::asCreatureLevListCustomData() +{ + std::stringstream error; + error << "bad cast " << typeid(this).name() << " to CreatureLevListCustomData"; + throw std::logic_error(error.str()); +} + + +} diff --git a/apps/openmw/mwworld/customdata.hpp b/apps/openmw/mwworld/customdata.hpp index 588991fe4..8c3890580 100644 --- a/apps/openmw/mwworld/customdata.hpp +++ b/apps/openmw/mwworld/customdata.hpp @@ -1,6 +1,15 @@ #ifndef GAME_MWWORLD_CUSTOMDATA_H #define GAME_MWWORLD_CUSTOMDATA_H +namespace MWClass +{ + class CreatureCustomData; + class NpcCustomData; + class ContainerCustomData; + class DoorCustomData; + class CreatureLevListCustomData; +} + namespace MWWorld { /// \brief Base class for the MW-class-specific part of RefData @@ -11,6 +20,18 @@ namespace MWWorld virtual ~CustomData() {} virtual CustomData *clone() const = 0; + + // Fast version of dynamic_cast. Needs to be overridden in the respective class. + + virtual MWClass::CreatureCustomData& asCreatureCustomData(); + + virtual MWClass::NpcCustomData& asNpcCustomData(); + + virtual MWClass::ContainerCustomData& asContainerCustomData(); + + virtual MWClass::DoorCustomData& asDoorCustomData(); + + virtual MWClass::CreatureLevListCustomData& asCreatureLevListCustomData(); }; }