1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-16 05:49:56 +00:00
openmw-tes3mp/apps/openmw/mwclass/door.cpp

347 lines
12 KiB
C++
Raw Normal View History

2010-08-03 13:24:44 +00:00
#include "door.hpp"
#include <components/esm/loaddoor.hpp>
#include <components/esm/doorstate.hpp>
2010-08-03 13:24:44 +00:00
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/soundmanager.hpp"
2010-08-03 15:11:41 +00:00
#include "../mwworld/ptr.hpp"
#include "../mwworld/nullaction.hpp"
2012-11-17 17:17:08 +00:00
#include "../mwworld/failedaction.hpp"
#include "../mwworld/actionteleport.hpp"
2013-04-28 12:59:15 +00:00
#include "../mwworld/actiondoor.hpp"
#include "../mwworld/cellstore.hpp"
#include "../mwworld/physicssystem.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwworld/actiontrap.hpp"
#include "../mwworld/customdata.hpp"
2010-08-03 15:11:41 +00:00
#include "../mwgui/tooltips.hpp"
2011-11-12 20:58:22 +00:00
#include "../mwrender/objects.hpp"
#include "../mwrender/renderinginterface.hpp"
namespace
{
struct DoorCustomData : public MWWorld::CustomData
{
int mDoorState; // 0 = nothing, 1 = opening, 2 = closing
virtual MWWorld::CustomData *clone() const;
};
MWWorld::CustomData *DoorCustomData::clone() const
{
return new DoorCustomData (*this);
}
}
2010-08-03 13:24:44 +00:00
namespace MWClass
{
2011-11-12 04:01:12 +00:00
void Door::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{
2012-07-24 16:22:11 +00:00
const std::string model = getModel(ptr);
if (!model.empty()) {
2013-08-07 10:51:57 +00:00
renderingInterface.getObjects().insertModel(ptr, model);
}
}
void Door::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const
2011-11-12 04:01:12 +00:00
{
2012-07-24 16:22:11 +00:00
const std::string model = getModel(ptr);
if(!model.empty())
physics.addObject(ptr);
// Resume the door's opening/closing animation if it wasn't finished
if (ptr.getRefData().getCustomData())
{
const DoorCustomData& customData = dynamic_cast<const DoorCustomData&>(*ptr.getRefData().getCustomData());
if (customData.mDoorState > 0)
{
MWBase::Environment::get().getWorld()->activateDoor(ptr, customData.mDoorState == 1 ? true : false);
}
}
2012-07-24 16:22:11 +00:00
}
2012-07-27 10:00:10 +00:00
2012-07-24 16:22:11 +00:00
std::string Door::getModel(const MWWorld::Ptr &ptr) const
{
MWWorld::LiveCellRef<ESM::Door> *ref =
2011-11-12 04:01:12 +00:00
ptr.get<ESM::Door>();
2012-11-05 12:07:59 +00:00
assert(ref->mBase != NULL);
2011-11-12 04:01:12 +00:00
2012-11-05 12:07:59 +00:00
const std::string &model = ref->mBase->mModel;
2012-07-24 16:22:11 +00:00
if (!model.empty()) {
return "meshes\\" + model;
2011-11-12 04:01:12 +00:00
}
2012-07-24 16:22:11 +00:00
return "";
2011-11-12 04:01:12 +00:00
}
2010-08-03 15:11:41 +00:00
std::string Door::getName (const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Door> *ref =
2010-08-03 15:11:41 +00:00
ptr.get<ESM::Door>();
if (ptr.getCellRef().getTeleport() && !ptr.getCellRef().getDestCell().empty()) // TODO doors that lead to exteriors
return ptr.getCellRef().getDestCell();
2012-11-05 12:07:59 +00:00
return ref->mBase->mName;
2010-08-03 15:11:41 +00:00
}
boost::shared_ptr<MWWorld::Action> Door::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor) const
{
MWWorld::LiveCellRef<ESM::Door> *ref = ptr.get<ESM::Door>();
2012-11-05 12:07:59 +00:00
const std::string &openSound = ref->mBase->mOpenSound;
2013-04-28 12:59:15 +00:00
const std::string &closeSound = ref->mBase->mCloseSound;
2012-02-27 07:39:35 +00:00
const std::string lockedSound = "LockedDoor";
2012-02-27 14:59:45 +00:00
const std::string trapActivationSound = "Disarm Trap Fail";
2012-02-27 07:39:35 +00:00
MWWorld::ContainerStore &invStore = actor.getClass().getContainerStore(actor);
bool needKey = ptr.getCellRef().getLockLevel() > 0;
bool hasKey = false;
std::string keyName;
2012-11-02 20:43:07 +00:00
// make key id lowercase
std::string keyId = ptr.getCellRef().getKey();
2013-01-09 19:51:52 +00:00
Misc::StringUtils::toLower(keyId);
for (MWWorld::ContainerStoreIterator it = invStore.begin(); it != invStore.end(); ++it)
{
std::string refId = it->getCellRef().getRefId();
2013-01-09 19:51:52 +00:00
Misc::StringUtils::toLower(refId);
if (refId == keyId)
{
hasKey = true;
keyName = it->getClass().getName(*it);
}
}
if (needKey && hasKey)
2012-02-27 14:59:45 +00:00
{
if(actor == MWBase::Environment::get().getWorld()->getPlayerPtr())
MWBase::Environment::get().getWindowManager()->messageBox(keyName + " #{sKeyUsed}");
unlock(ptr); //Call the function here. because that makes sense.
// using a key disarms the trap
ptr.getCellRef().setTrap("");
2012-02-27 14:59:45 +00:00
}
if (!needKey || hasKey)
{
if(!ptr.getCellRef().getTrap().empty())
{
// Trap activation
boost::shared_ptr<MWWorld::Action> action(new MWWorld::ActionTrap(actor, ptr.getCellRef().getTrap(), ptr));
action->setSound(trapActivationSound);
return action;
}
if (ptr.getCellRef().getTeleport())
{
boost::shared_ptr<MWWorld::Action> action(new MWWorld::ActionTeleport (ptr.getCellRef().getDestCell(), ptr.getCellRef().getDoorDest()));
2014-02-17 09:37:11 +00:00
action->setSound(openSound);
2014-02-17 09:37:11 +00:00
return action;
}
else
{
// animated door
2013-04-28 12:59:15 +00:00
boost::shared_ptr<MWWorld::Action> action(new MWWorld::ActionDoor(ptr));
int doorstate = getDoorState(ptr);
bool opening = true;
if (doorstate == 1)
opening = false;
if (doorstate == 0 && ptr.getRefData().getLocalRotation().rot[2] != 0)
opening = false;
if (opening)
{
MWBase::Environment::get().getSoundManager()->fadeOutSound3D(ptr,
closeSound, 0.5);
float offset = ptr.getRefData().getLocalRotation().rot[2]/ 3.14159265 * 2.0;
action->setSoundOffset(offset);
2013-04-28 12:59:15 +00:00
action->setSound(openSound);
}
2013-04-28 12:59:15 +00:00
else
{
MWBase::Environment::get().getSoundManager()->fadeOutSound3D(ptr,
openSound, 0.5);
float offset = 1.0 - ptr.getRefData().getLocalRotation().rot[2]/ 3.14159265 * 2.0;
//most if not all door have closing bang somewhere in the middle of the sound,
//so we divide offset by two
action->setSoundOffset(offset * 0.5);
2013-04-28 12:59:15 +00:00
action->setSound(closeSound);
}
return action;
}
}
else
{
// locked, and we can't open.
2012-11-19 20:04:49 +00:00
boost::shared_ptr<MWWorld::Action> action(new MWWorld::FailedAction);
action->setSound(lockedSound);
return action;
}
}
void Door::lock (const MWWorld::Ptr& ptr, int lockLevel) const
{
if(lockLevel!=0)
ptr.getCellRef().setLockLevel(abs(lockLevel)); //Changes lock to locklevel, in positive
else
ptr.getCellRef().setLockLevel(abs(ptr.getCellRef().getLockLevel())); //No locklevel given, just flip the origional one
}
void Door::unlock (const MWWorld::Ptr& ptr) const
{
ptr.getCellRef().setLockLevel(-abs(ptr.getCellRef().getLockLevel())); //Makes lockLevel negative
}
std::string Door::getScript (const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Door> *ref =
ptr.get<ESM::Door>();
2012-11-05 12:07:59 +00:00
return ref->mBase->mScript;
}
2010-08-03 13:24:44 +00:00
void Door::registerSelf()
{
boost::shared_ptr<Class> instance (new Door);
registerClass (typeid (ESM::Door).name(), instance);
}
bool Door::hasToolTip (const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Door> *ref =
ptr.get<ESM::Door>();
2012-11-05 12:07:59 +00:00
return (ref->mBase->mName != "");
}
MWGui::ToolTipInfo Door::getToolTipInfo (const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Door> *ref =
ptr.get<ESM::Door>();
MWGui::ToolTipInfo info;
2012-11-05 12:07:59 +00:00
info.caption = ref->mBase->mName;
std::string text;
if (ptr.getCellRef().getTeleport())
{
2012-09-22 19:35:57 +00:00
text += "\n#{sTo}";
2012-12-23 19:23:24 +00:00
text += "\n" + getDestination(*ref);
}
if (ptr.getCellRef().getLockLevel() > 0)
text += "\n#{sLockLevel}: " + MWGui::ToolTips::toString(ptr.getCellRef().getLockLevel());
else if (ptr.getCellRef().getLockLevel() < 0)
text += "\n#{sUnlocked}";
if (ptr.getCellRef().getTrap() != "")
2012-09-22 19:35:57 +00:00
text += "\n#{sTrapped}";
if (MWBase::Environment::get().getWindowManager()->getFullHelp())
2014-07-11 09:57:21 +00:00
{
2012-11-05 12:07:59 +00:00
text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script");
2014-07-11 09:57:21 +00:00
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getFaction(), "Faction");
}
info.text = text;
return info;
}
2012-12-23 19:23:24 +00:00
std::string Door::getDestination (const MWWorld::LiveCellRef<ESM::Door>& door)
{
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
std::string dest;
if (door.mRef.getDestCell() != "")
2012-12-23 19:23:24 +00:00
{
// door leads to an interior, use interior name as tooltip
dest = door.mRef.getDestCell();
2012-12-23 19:23:24 +00:00
}
else
{
// door leads to exterior, use cell name (if any), otherwise translated region name
int x,y;
MWBase::Environment::get().getWorld()->positionToIndex (door.mRef.getDoorDest().pos[0], door.mRef.getDoorDest().pos[1], x, y);
2012-12-23 19:23:24 +00:00
const ESM::Cell* cell = store.get<ESM::Cell>().find(x,y);
if (cell->mName != "")
dest = cell->mName;
else
{
const ESM::Region* region =
store.get<ESM::Region>().find(cell->mRegion);
//name as is, not a token
return region->mName;
}
}
return "#{sCell=" + dest + "}";
}
MWWorld::Ptr
Door::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const
{
MWWorld::LiveCellRef<ESM::Door> *ref =
ptr.get<ESM::Door>();
2014-02-23 20:21:27 +00:00
return MWWorld::Ptr(&cell.get<ESM::Door>().insert(*ref), &cell);
}
void Door::ensureCustomData(const MWWorld::Ptr &ptr) const
{
if (!ptr.getRefData().getCustomData())
{
std::auto_ptr<DoorCustomData> data(new DoorCustomData);
data->mDoorState = 0;
ptr.getRefData().setCustomData(data.release());
}
}
int Door::getDoorState (const MWWorld::Ptr &ptr) const
{
ensureCustomData(ptr);
const DoorCustomData& customData = dynamic_cast<const DoorCustomData&>(*ptr.getRefData().getCustomData());
return customData.mDoorState;
}
void Door::setDoorState (const MWWorld::Ptr &ptr, int state) const
{
ensureCustomData(ptr);
DoorCustomData& customData = dynamic_cast<DoorCustomData&>(*ptr.getRefData().getCustomData());
customData.mDoorState = state;
}
void Door::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) const
{
ensureCustomData(ptr);
DoorCustomData& customData = dynamic_cast<DoorCustomData&>(*ptr.getRefData().getCustomData());
const ESM::DoorState& state2 = dynamic_cast<const ESM::DoorState&>(state);
customData.mDoorState = state2.mDoorState;
}
void Door::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state) const
{
ensureCustomData(ptr);
const DoorCustomData& customData = dynamic_cast<const DoorCustomData&>(*ptr.getRefData().getCustomData());
ESM::DoorState& state2 = dynamic_cast<ESM::DoorState&>(state);
state2.mDoorState = customData.mDoorState;
}
2010-08-03 13:24:44 +00:00
}