forked from teamnwah/openmw-tes3coop
Merge pull request #396 from TES3MP/0.6.3 while resolving conflicts
Conflicts: apps/openmw-mp/Player.cpp apps/openmw-mp/Script/Functions/Settings.cpp apps/openmw-mp/Script/Functions/Settings.hpp apps/openmw-mp/Script/Functions/World.cpp apps/openmw-mp/Script/Functions/World.hpp apps/openmw/mwgui/container.cpp apps/openmw/mwmp/LocalActor.cpp apps/openmw/mwmp/LocalPlayer.cpp apps/openmw/mwmp/WorldEvent.cpp apps/openmw/mwmp/processors/world/ProcessorContainer.hpp components/openmw-mp/Base/BaseEvent.hpp components/openmw-mp/Log.cpp components/openmw-mp/Log.hpp
This commit is contained in:
commit
3d5860d6f4
46 changed files with 565 additions and 207 deletions
|
@ -106,7 +106,7 @@ CSVDoc::StartupDialogue::StartupDialogue() : mWidth (0), mColumn (2)
|
||||||
|
|
||||||
/// \todo remove this label once we are feature complete and convinced that this thing is
|
/// \todo remove this label once we are feature complete and convinced that this thing is
|
||||||
/// working properly.
|
/// working properly.
|
||||||
QLabel *warning = new QLabel ("<font color=Red>WARNING: OpenMW-CS is in alpha stage.<p>The editor is not feature complete and not sufficiently tested.<br>In theory your data should be safe. But we strongly advice to make backups regularly if you are working with live data.</font color>");
|
QLabel *warning = new QLabel ("<font color=Red>WARNING: OpenMW-CS is in alpha stage.<p>The editor is not feature complete and not sufficiently tested.<br>In theory your data should be safe. But we strongly advise to make backups regularly if you are working with live data.</font color>");
|
||||||
|
|
||||||
QFont font;
|
QFont font;
|
||||||
font.setPointSize (12);
|
font.setPointSize (12);
|
||||||
|
|
|
@ -228,6 +228,7 @@ void Object::setMasterState(bool state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Make this actually reflect the capabilities offered by containers in 0.6.3
|
||||||
void Container::Init(LuaState &lua)
|
void Container::Init(LuaState &lua)
|
||||||
{
|
{
|
||||||
lua.getState()->new_usertype<Container>("Container",
|
lua.getState()->new_usertype<Container>("Container",
|
||||||
|
|
|
@ -14,6 +14,7 @@ void GameSettings::Init(LuaState &lua)
|
||||||
{
|
{
|
||||||
lua.getState()->new_usertype<GameSettings>("Settings",
|
lua.getState()->new_usertype<GameSettings>("Settings",
|
||||||
"setDifficulty", &GameSettings::setDifficulty,
|
"setDifficulty", &GameSettings::setDifficulty,
|
||||||
|
"setEnforcedLogLevel", &GameSettings::setEnforcedLogLevel,
|
||||||
"setPhysicsFramerate", &GameSettings::setPhysicsFramerate,
|
"setPhysicsFramerate", &GameSettings::setPhysicsFramerate,
|
||||||
"setConsoleAllowed", &GameSettings::setConsoleAllowed,
|
"setConsoleAllowed", &GameSettings::setConsoleAllowed,
|
||||||
"setBedRestAllowed", &GameSettings::setBedRestAllowed,
|
"setBedRestAllowed", &GameSettings::setBedRestAllowed,
|
||||||
|
@ -39,6 +40,12 @@ void GameSettings::setDifficulty(int difficulty)
|
||||||
setChanged();
|
setChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameSettings::setEnforcedLogLevel(int logLevel)
|
||||||
|
{
|
||||||
|
player->enforcedLogLevel = logLevel;
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
void GameSettings::setPhysicsFramerate(double physicsFramerate)
|
void GameSettings::setPhysicsFramerate(double physicsFramerate)
|
||||||
{
|
{
|
||||||
player->physicsFramerate = physicsFramerate;
|
player->physicsFramerate = physicsFramerate;
|
||||||
|
|
|
@ -22,6 +22,8 @@ public:
|
||||||
|
|
||||||
void setDifficulty(int difficulty);
|
void setDifficulty(int difficulty);
|
||||||
|
|
||||||
|
void setEnforcedLogLevel(int logLevel);
|
||||||
|
|
||||||
void setPhysicsFramerate(double physicsFramerate);
|
void setPhysicsFramerate(double physicsFramerate);
|
||||||
|
|
||||||
void setBedRestAllowed(bool state);
|
void setBedRestAllowed(bool state);
|
||||||
|
|
|
@ -30,8 +30,10 @@ namespace mwmp
|
||||||
if (serverCell != nullptr)
|
if (serverCell != nullptr)
|
||||||
serverCell->sendToLoaded(&packet, &event);
|
serverCell->sendToLoaded(&packet, &event);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
packet.Send(true);
|
// Otherwise, don't have any hardcoded sync and expect Lua scripts to forward
|
||||||
|
// container packets to ensure their integrity based on what exists in the
|
||||||
|
// server data
|
||||||
|
|
||||||
auto objCtrl = Networking::get().getState().getObjectCtrl();
|
auto objCtrl = Networking::get().getState().getObjectCtrl();
|
||||||
auto containers = objCtrl.copyContainers(event);
|
auto containers = objCtrl.copyContainers(event);
|
||||||
|
|
|
@ -145,6 +145,17 @@ namespace MWBase
|
||||||
virtual MWGui::ConfirmationDialog* getConfirmationDialog() = 0;
|
virtual MWGui::ConfirmationDialog* getConfirmationDialog() = 0;
|
||||||
virtual MWGui::TradeWindow* getTradeWindow() = 0;
|
virtual MWGui::TradeWindow* getTradeWindow() = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Start of tes3mp addition
|
||||||
|
|
||||||
|
Make it possible to get the ContainerWindow from elsewhere
|
||||||
|
in the code
|
||||||
|
*/
|
||||||
|
virtual MWGui::ContainerWindow* getContainerWindow() = 0;
|
||||||
|
/*
|
||||||
|
End of tes3mp addition
|
||||||
|
*/
|
||||||
|
|
||||||
/// Make the player use an item, while updating GUI state accordingly
|
/// Make the player use an item, while updating GUI state accordingly
|
||||||
virtual void useItem(const MWWorld::Ptr& item) = 0;
|
virtual void useItem(const MWWorld::Ptr& item) = 0;
|
||||||
|
|
||||||
|
@ -411,7 +422,7 @@ namespace MWBase
|
||||||
/// Cycle to next or previous weapon
|
/// Cycle to next or previous weapon
|
||||||
virtual void cycleWeapon(bool next) = 0;
|
virtual void cycleWeapon(bool next) = 0;
|
||||||
|
|
||||||
virtual void playSound(const std::string& soundId, float volume = 1.f, float pitch = 1.f) = 0;
|
virtual void playSound(const std::string& soundId, bool preventOverlapping = false, float volume = 1.f, float pitch = 1.f) = 0;
|
||||||
|
|
||||||
// In WindowManager for now since there isn't a VFS singleton
|
// In WindowManager for now since there isn't a VFS singleton
|
||||||
virtual std::string correctIconPath(const std::string& path) = 0;
|
virtual std::string correctIconPath(const std::string& path) = 0;
|
||||||
|
|
|
@ -547,12 +547,14 @@ namespace MWBase
|
||||||
virtual void launchProjectile (MWWorld::Ptr actor, MWWorld::ConstPtr projectile,
|
virtual void launchProjectile (MWWorld::Ptr actor, MWWorld::ConstPtr projectile,
|
||||||
const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr bow, float speed, float attackStrength) = 0;
|
const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr bow, float speed, float attackStrength) = 0;
|
||||||
|
|
||||||
|
virtual void applyLoopingParticles(const MWWorld::Ptr& ptr) = 0;
|
||||||
|
|
||||||
virtual const std::vector<std::string>& getContentFiles() const = 0;
|
virtual const std::vector<std::string>& getContentFiles() const = 0;
|
||||||
|
|
||||||
virtual void breakInvisibility (const MWWorld::Ptr& actor) = 0;
|
virtual void breakInvisibility (const MWWorld::Ptr& actor) = 0;
|
||||||
|
|
||||||
// Are we in an exterior or pseudo-exterior cell and it's night?
|
// Allow NPCs to use torches?
|
||||||
virtual bool isDark() const = 0;
|
virtual bool useTorches() const = 0;
|
||||||
|
|
||||||
virtual bool findInteriorPositionInWorldSpace(const MWWorld::CellStore* cell, osg::Vec3f& result) = 0;
|
virtual bool findInteriorPositionInWorldSpace(const MWWorld::CellStore* cell, osg::Vec3f& result) = 0;
|
||||||
|
|
||||||
|
|
|
@ -233,24 +233,6 @@ namespace MWClass
|
||||||
if (!(ref->mBase->mData.mFlags & ESM::Light::Carry))
|
if (!(ref->mBase->mData.mFlags & ESM::Light::Carry))
|
||||||
return std::make_pair(0,"");
|
return std::make_pair(0,"");
|
||||||
|
|
||||||
const MWWorld::InventoryStore& invStore = npc.getClass().getInventoryStore(npc);
|
|
||||||
MWWorld::ConstContainerStoreIterator weapon = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
|
||||||
|
|
||||||
if(weapon == invStore.end())
|
|
||||||
return std::make_pair(1,"");
|
|
||||||
|
|
||||||
/// \todo the 2h check is repeated many times; put it in a function
|
|
||||||
if(weapon->getTypeName() == typeid(ESM::Weapon).name() &&
|
|
||||||
(weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand ||
|
|
||||||
weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::BluntTwoClose ||
|
|
||||||
weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::BluntTwoWide ||
|
|
||||||
weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::SpearTwoWide ||
|
|
||||||
weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::AxeTwoHand ||
|
|
||||||
weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanBow ||
|
|
||||||
weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow))
|
|
||||||
{
|
|
||||||
return std::make_pair(3,"");
|
|
||||||
}
|
|
||||||
return std::make_pair(1,"");
|
return std::make_pair(1,"");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -892,7 +892,7 @@ protected:
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef TypesetBookImpl::StyleImpl Style;
|
typedef TypesetBookImpl::StyleImpl Style;
|
||||||
typedef std::map <TextFormat::Id, TextFormat*> ActiveTextFormats;
|
typedef std::map <TextFormat::Id, std::unique_ptr<TextFormat>> ActiveTextFormats;
|
||||||
|
|
||||||
int mViewTop;
|
int mViewTop;
|
||||||
int mViewBottom;
|
int mViewBottom;
|
||||||
|
@ -1048,7 +1048,7 @@ public:
|
||||||
{
|
{
|
||||||
if (mNode != NULL)
|
if (mNode != NULL)
|
||||||
i->second->destroyDrawItem (mNode);
|
i->second->destroyDrawItem (mNode);
|
||||||
delete i->second;
|
i->second.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
mActiveTextFormats.clear ();
|
mActiveTextFormats.clear ();
|
||||||
|
@ -1115,11 +1115,11 @@ public:
|
||||||
|
|
||||||
if (j == this_->mActiveTextFormats.end ())
|
if (j == this_->mActiveTextFormats.end ())
|
||||||
{
|
{
|
||||||
TextFormat * textFormat = new TextFormat (Font, this_);
|
std::unique_ptr<TextFormat> textFormat(new TextFormat (Font, this_));
|
||||||
|
|
||||||
textFormat->mTexture = Font->getTextureFont ();
|
textFormat->mTexture = Font->getTextureFont ();
|
||||||
|
|
||||||
j = this_->mActiveTextFormats.insert (std::make_pair (Font, textFormat)).first;
|
j = this_->mActiveTextFormats.insert (std::make_pair (Font, std::move(textFormat))).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
j->second->mCountVertex += run.mPrintableChars * 6;
|
j->second->mCountVertex += run.mPrintableChars * 6;
|
||||||
|
|
|
@ -200,7 +200,7 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
if ((mCurrentPage+1)*2 < mPages.size())
|
if ((mCurrentPage+1)*2 < mPages.size())
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWindowManager()->playSound("book page2");
|
MWBase::Environment::get().getWindowManager()->playSound("book page2", true);
|
||||||
|
|
||||||
++mCurrentPage;
|
++mCurrentPage;
|
||||||
|
|
||||||
|
@ -211,7 +211,7 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
if (mCurrentPage > 0)
|
if (mCurrentPage > 0)
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWindowManager()->playSound("book page");
|
MWBase::Environment::get().getWindowManager()->playSound("book page", true);
|
||||||
|
|
||||||
--mCurrentPage;
|
--mCurrentPage;
|
||||||
|
|
||||||
|
|
|
@ -115,35 +115,35 @@ namespace MWGui
|
||||||
worldEvent->reset();
|
worldEvent->reset();
|
||||||
worldEvent->cell = *mPtr.getCell()->getCell();
|
worldEvent->cell = *mPtr.getCell()->getCell();
|
||||||
worldEvent->action = mwmp::BaseEvent::Action::Remove;
|
worldEvent->action = mwmp::BaseEvent::Action::Remove;
|
||||||
|
worldEvent->containerSubAction = mwmp::BaseEvent::ContainerSubAction::Drag;
|
||||||
|
|
||||||
mwmp::WorldObject worldObject;
|
mwmp::WorldObject worldObject = worldEvent->getWorldObject(mPtr);
|
||||||
worldObject.refId = mPtr.getCellRef().getRefId();
|
|
||||||
worldObject.refNumIndex = mPtr.getCellRef().getRefNum().mIndex;
|
|
||||||
worldObject.mpNum = mPtr.getCellRef().getMpNum();
|
|
||||||
|
|
||||||
MWWorld::Ptr itemPtr = mModel->getItem(mSelectedItem).mBase;
|
MWWorld::Ptr itemPtr = mModel->getItem(mSelectedItem).mBase;
|
||||||
|
|
||||||
mwmp::ContainerItem containerItem;
|
worldEvent->addContainerItem(worldObject, itemPtr, count);
|
||||||
containerItem.refId =itemPtr.getCellRef().getRefId();
|
|
||||||
containerItem.count = itemPtr.getRefData().getCount();
|
|
||||||
containerItem.charge = itemPtr.getCellRef().getCharge();
|
|
||||||
containerItem.enchantmentCharge = itemPtr.getCellRef().getEnchantmentCharge();
|
|
||||||
containerItem.actionCount = count;
|
|
||||||
|
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Sending ID_CONTAINER about\n- Ptr cellRef: %s, %i\n- cell: %s\n- item: %s, %i",
|
|
||||||
worldObject.refId.c_str(), worldObject.refNumIndex, worldEvent->cell.getDescription().c_str(),
|
|
||||||
containerItem.refId.c_str(), containerItem.count);
|
|
||||||
|
|
||||||
worldObject.containerItems.push_back(std::move(containerItem));
|
|
||||||
worldEvent->worldObjects.push_back(std::move(worldObject));
|
worldEvent->worldObjects.push_back(std::move(worldObject));
|
||||||
|
|
||||||
mwmp::Main::get().getNetworking()->getWorldPacket(ID_CONTAINER)->setEvent(worldEvent);
|
mwmp::Main::get().getNetworking()->getWorldPacket(ID_CONTAINER)->setEvent(worldEvent);
|
||||||
mwmp::Main::get().getNetworking()->getWorldPacket(ID_CONTAINER)->Send();
|
mwmp::Main::get().getNetworking()->getWorldPacket(ID_CONTAINER)->Send();
|
||||||
|
|
||||||
|
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Sending ID_CONTAINER about\n- Ptr cellRef: %s, %i\n- cell: %s\n- item: %s, %i",
|
||||||
|
worldObject.refId.c_str(), worldObject.refNumIndex, worldEvent->cell.getDescription().c_str(),
|
||||||
|
itemPtr.getCellRef().getRefId().c_str(), itemPtr.getRefData().getCount());
|
||||||
/*
|
/*
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Start of tes3mp change (major)
|
||||||
|
|
||||||
|
Avoid running any of the original code for dragging items, to prevent possibilities
|
||||||
|
for item duping or interaction with restricted containers
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
/*
|
||||||
|
End of tes3mp change (major)
|
||||||
|
*/
|
||||||
|
|
||||||
mDragAndDrop->startDrag(mSelectedItem, mSortModel, mModel, mItemView, count);
|
mDragAndDrop->startDrag(mSelectedItem, mSortModel, mModel, mItemView, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,14 +162,10 @@ namespace MWGui
|
||||||
worldEvent->reset();
|
worldEvent->reset();
|
||||||
worldEvent->cell = *mPtr.getCell()->getCell();
|
worldEvent->cell = *mPtr.getCell()->getCell();
|
||||||
worldEvent->action = mwmp::BaseEvent::Action::Add;
|
worldEvent->action = mwmp::BaseEvent::Action::Add;
|
||||||
|
worldEvent->containerSubAction = mwmp::BaseEvent::ContainerSubAction::Drop;
|
||||||
|
|
||||||
mwmp::WorldObject worldObject;
|
mwmp::WorldObject worldObject = worldEvent->getWorldObject(mPtr);
|
||||||
worldObject.refId = mPtr.getCellRef().getRefId();
|
|
||||||
worldObject.refNumIndex = mPtr.getCellRef().getRefNum().mIndex;
|
|
||||||
worldObject.mpNum = mPtr.getCellRef().getMpNum();
|
|
||||||
|
|
||||||
MWWorld::Ptr itemPtr = mDragAndDrop->mItem.mBase;
|
MWWorld::Ptr itemPtr = mDragAndDrop->mItem.mBase;
|
||||||
|
|
||||||
mwmp::ContainerItem containerItem;
|
mwmp::ContainerItem containerItem;
|
||||||
containerItem.refId = itemPtr.getCellRef().getRefId();
|
containerItem.refId = itemPtr.getCellRef().getRefId();
|
||||||
|
|
||||||
|
@ -179,22 +175,34 @@ namespace MWGui
|
||||||
containerItem.charge = itemPtr.getCellRef().getCharge();
|
containerItem.charge = itemPtr.getCellRef().getCharge();
|
||||||
containerItem.enchantmentCharge = itemPtr.getCellRef().getEnchantmentCharge();
|
containerItem.enchantmentCharge = itemPtr.getCellRef().getEnchantmentCharge();
|
||||||
|
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Sending ID_CONTAINER about\n- Ptr cellRef: %s, %i\n- cell: %s\n- item: %s, %i",
|
|
||||||
worldObject.refId.c_str(), worldObject.refNumIndex, worldEvent->cell.getDescription().c_str(),
|
|
||||||
containerItem.refId.c_str(), containerItem.count);
|
|
||||||
|
|
||||||
worldObject.containerItems.push_back(std::move(containerItem));
|
worldObject.containerItems.push_back(std::move(containerItem));
|
||||||
worldEvent->worldObjects.push_back(std::move(worldObject));
|
worldEvent->worldObjects.push_back(std::move(worldObject));
|
||||||
|
|
||||||
mwmp::Main::get().getNetworking()->getWorldPacket(ID_CONTAINER)->setEvent(worldEvent);
|
mwmp::Main::get().getNetworking()->getWorldPacket(ID_CONTAINER)->setEvent(worldEvent);
|
||||||
mwmp::Main::get().getNetworking()->getWorldPacket(ID_CONTAINER)->Send();
|
mwmp::Main::get().getNetworking()->getWorldPacket(ID_CONTAINER)->Send();
|
||||||
|
|
||||||
|
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Sending ID_CONTAINER about\n- Ptr cellRef: %s, %i\n- cell: %s\n- item: %s, %i, %i",
|
||||||
|
worldObject.refId.c_str(), worldObject.refNumIndex, worldEvent->cell.getDescription().c_str(),
|
||||||
|
containerItem.refId.c_str(), containerItem.count, containerItem.charge);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (success)
|
/*
|
||||||
mDragAndDrop->drop(mModel, mItemView);
|
Start of tes3mp change (major)
|
||||||
|
|
||||||
|
Avoid running any of the original code for dropping items, to prevent possibilities
|
||||||
|
for item duping or interaction with restricted containers
|
||||||
|
|
||||||
|
Instead, finish the drag in a way that removes the items in it
|
||||||
|
*/
|
||||||
|
//if (success)
|
||||||
|
// mDragAndDrop->drop(mModel, mItemView);
|
||||||
|
mDragAndDrop->finish(true);
|
||||||
|
/*
|
||||||
|
End of tes3mp change (major)
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContainerWindow::onBackgroundSelected()
|
void ContainerWindow::onBackgroundSelected()
|
||||||
|
@ -283,6 +291,40 @@ namespace MWGui
|
||||||
if(mDragAndDrop != NULL && mDragAndDrop->mIsOnDragAndDrop)
|
if(mDragAndDrop != NULL && mDragAndDrop->mIsOnDragAndDrop)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Start of tes3mp addition
|
||||||
|
|
||||||
|
Send an ID_CONTAINER packet every time the Take All button is used on
|
||||||
|
a container
|
||||||
|
*/
|
||||||
|
mwmp::WorldEvent *worldEvent = mwmp::Main::get().getNetworking()->getWorldEvent();
|
||||||
|
worldEvent->reset();
|
||||||
|
worldEvent->cell = *mPtr.getCell()->getCell();
|
||||||
|
worldEvent->action = mwmp::BaseEvent::Action::Remove;
|
||||||
|
worldEvent->containerSubAction = mwmp::BaseEvent::ContainerSubAction::TakeAll;
|
||||||
|
worldEvent->addEntireContainer(mPtr);
|
||||||
|
|
||||||
|
mwmp::Main::get().getNetworking()->getWorldPacket(ID_CONTAINER)->setEvent(worldEvent);
|
||||||
|
mwmp::Main::get().getNetworking()->getWorldPacket(ID_CONTAINER)->Send();
|
||||||
|
|
||||||
|
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Sending ID_CONTAINER about\n- Ptr cellRef: %s, %i-%i\n- cell: %s",
|
||||||
|
mPtr.getCellRef().getRefId().c_str(), mPtr.getCellRef().getRefNum().mIndex, mPtr.getCellRef().getMpNum(),
|
||||||
|
worldEvent->cell.getDescription().c_str());
|
||||||
|
/*
|
||||||
|
End of tes3mp addition
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Start of tes3mp change (major)
|
||||||
|
|
||||||
|
Avoid running any of the original code for taking all items, to prevent
|
||||||
|
possibilities for item duping or interaction with restricted containers
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
/*
|
||||||
|
End of tes3mp change (major)
|
||||||
|
*/
|
||||||
|
|
||||||
// transfer everything into the player's inventory
|
// transfer everything into the player's inventory
|
||||||
ItemModel* playerModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getModel();
|
ItemModel* playerModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getModel();
|
||||||
mModel->update();
|
mModel->update();
|
||||||
|
@ -322,33 +364,6 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
|
||||||
|
|
||||||
/*
|
|
||||||
Start of tes3mp addition
|
|
||||||
|
|
||||||
Send an ID_CONTAINER packet every time the Take All button is used on
|
|
||||||
a container
|
|
||||||
*/
|
|
||||||
mwmp::WorldEvent *worldEvent = mwmp::Main::get().getNetworking()->getWorldEvent();
|
|
||||||
worldEvent->reset();
|
|
||||||
worldEvent->cell = *mPtr.getCell()->getCell();
|
|
||||||
worldEvent->action = mwmp::BaseEvent::Action::Set;
|
|
||||||
|
|
||||||
mwmp::WorldObject worldObject;
|
|
||||||
worldObject.refId = mPtr.getCellRef().getRefId();
|
|
||||||
worldObject.refNumIndex = mPtr.getCellRef().getRefNum().mIndex;
|
|
||||||
worldObject.mpNum = mPtr.getCellRef().getMpNum();
|
|
||||||
|
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Sending ID_CONTAINER about\n- Ptr cellRef: %s, %i\n- cell: %s",
|
|
||||||
worldObject.refId.c_str(), worldObject.refNumIndex, worldEvent->cell.getDescription().c_str());
|
|
||||||
|
|
||||||
worldEvent->worldObjects.push_back(std::move(worldObject));
|
|
||||||
|
|
||||||
mwmp::Main::get().getNetworking()->getWorldPacket(ID_CONTAINER)->setEvent(worldEvent);
|
|
||||||
mwmp::Main::get().getNetworking()->getWorldPacket(ID_CONTAINER)->Send();
|
|
||||||
/*
|
|
||||||
End of tes3mp addition
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContainerWindow::onDisposeCorpseButtonClicked(MyGUI::Widget *sender)
|
void ContainerWindow::onDisposeCorpseButtonClicked(MyGUI::Widget *sender)
|
||||||
|
@ -392,4 +407,48 @@ namespace MWGui
|
||||||
return mModel->onTakeItem(item.mBase, count);
|
return mModel->onTakeItem(item.mBase, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Start of tes3mp addition
|
||||||
|
|
||||||
|
Make it possible to check from elsewhere whether there is currently an
|
||||||
|
item being dragged in the container window
|
||||||
|
*/
|
||||||
|
bool ContainerWindow::isOnDragAndDrop()
|
||||||
|
{
|
||||||
|
return mDragAndDrop->mIsOnDragAndDrop;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
End of tes3mp addition
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Start of tes3mp addition
|
||||||
|
|
||||||
|
Make it possible to drag a specific item Ptr instead of having to rely
|
||||||
|
on an index that may have changed in the meantime, for drags that
|
||||||
|
require approval from the server
|
||||||
|
*/
|
||||||
|
bool ContainerWindow::dragItemByPtr(const MWWorld::Ptr& itemPtr, int dragCount)
|
||||||
|
{
|
||||||
|
ItemModel::ModelIndex newIndex = -1;
|
||||||
|
for (unsigned int i = 0; i < mModel->getItemCount(); ++i)
|
||||||
|
{
|
||||||
|
if (mModel->getItem(i).mBase == itemPtr)
|
||||||
|
{
|
||||||
|
newIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newIndex != -1)
|
||||||
|
{
|
||||||
|
mDragAndDrop->startDrag(newIndex, mSortModel, mModel, mItemView, dragCount);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
End of tes3mp addition
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,29 @@ namespace MWGui
|
||||||
|
|
||||||
virtual void resetReference();
|
virtual void resetReference();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Start of tes3mp addition
|
||||||
|
|
||||||
|
Make it possible to check from elsewhere whether there is currently an
|
||||||
|
item being dragged in the container window
|
||||||
|
*/
|
||||||
|
bool isOnDragAndDrop();
|
||||||
|
/*
|
||||||
|
End of tes3mp addition
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Start of tes3mp addition
|
||||||
|
|
||||||
|
Make it possible to drag a specific item Ptr instead of having to rely
|
||||||
|
on an index that may have changed in the meantime, for drags that
|
||||||
|
require approval from the server
|
||||||
|
*/
|
||||||
|
bool dragItemByPtr(const MWWorld::Ptr& itemPtr, int dragCount);
|
||||||
|
/*
|
||||||
|
End of tes3mp addition
|
||||||
|
*/
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DragAndDrop* mDragAndDrop;
|
DragAndDrop* mDragAndDrop;
|
||||||
|
|
||||||
|
|
|
@ -127,10 +127,35 @@ void DragAndDrop::onFrame()
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DragAndDrop::finish()
|
/*
|
||||||
|
Start of tes3mp change (minor)
|
||||||
|
|
||||||
|
Add a deleteDragItems argument that allows the deletion of the
|
||||||
|
items in the drag as oppposed to the regular behavior of returning
|
||||||
|
them to their source model
|
||||||
|
|
||||||
|
This is required to reduce unpredictable behavior for drags approved
|
||||||
|
or rejected by the server
|
||||||
|
*/
|
||||||
|
void DragAndDrop::finish(bool deleteDragItems)
|
||||||
|
/*
|
||||||
|
End of tes3mp change (minor)
|
||||||
|
*/
|
||||||
{
|
{
|
||||||
mIsOnDragAndDrop = false;
|
mIsOnDragAndDrop = false;
|
||||||
mSourceSortModel->clearDragItems();
|
mSourceSortModel->clearDragItems();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Start of tes3mp addition
|
||||||
|
|
||||||
|
Make it possible to entirely delete the items in the drag
|
||||||
|
*/
|
||||||
|
if (deleteDragItems)
|
||||||
|
mSourceModel->removeItem(mItem, mDraggedCount);
|
||||||
|
/*
|
||||||
|
End of tes3mp addition
|
||||||
|
*/
|
||||||
|
|
||||||
// since mSourceView doesn't get updated in drag()
|
// since mSourceView doesn't get updated in drag()
|
||||||
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->updateItemView();
|
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->updateItemView();
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,20 @@ namespace MWGui
|
||||||
void drop (ItemModel* targetModel, ItemView* targetView);
|
void drop (ItemModel* targetModel, ItemView* targetView);
|
||||||
void onFrame();
|
void onFrame();
|
||||||
|
|
||||||
void finish();
|
/*
|
||||||
|
Start of tes3mp change (minor)
|
||||||
|
|
||||||
|
Add a deleteDragItems argument that allows the deletion of the
|
||||||
|
items in the drag as oppposed to the regular behavior of returning
|
||||||
|
them to their source model
|
||||||
|
|
||||||
|
This is required to reduce unpredictable behavior for drags approved
|
||||||
|
or rejected by the server
|
||||||
|
*/
|
||||||
|
void finish(bool deleteDragItems = false);
|
||||||
|
/*
|
||||||
|
End of tes3mp change (minor)
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -616,7 +616,7 @@ namespace
|
||||||
|
|
||||||
if (page+2 < book->pageCount())
|
if (page+2 < book->pageCount())
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWindowManager()->playSound("book page");
|
MWBase::Environment::get().getWindowManager()->playSound("book page", true);
|
||||||
|
|
||||||
page += 2;
|
page += 2;
|
||||||
updateShowingPages ();
|
updateShowingPages ();
|
||||||
|
@ -634,7 +634,7 @@ namespace
|
||||||
|
|
||||||
if(page >= 2)
|
if(page >= 2)
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWindowManager()->playSound("book page");
|
MWBase::Environment::get().getWindowManager()->playSound("book page", true);
|
||||||
|
|
||||||
page -= 2;
|
page -= 2;
|
||||||
updateShowingPages ();
|
updateShowingPages ();
|
||||||
|
|
|
@ -384,10 +384,19 @@ namespace MWGui
|
||||||
mGuiModeStates[GM_Dialogue] = GuiModeState(mDialogueWindow);
|
mGuiModeStates[GM_Dialogue] = GuiModeState(mDialogueWindow);
|
||||||
mTradeWindow->eventTradeDone += MyGUI::newDelegate(mDialogueWindow, &DialogueWindow::onTradeComplete);
|
mTradeWindow->eventTradeDone += MyGUI::newDelegate(mDialogueWindow, &DialogueWindow::onTradeComplete);
|
||||||
|
|
||||||
ContainerWindow* containerWindow = new ContainerWindow(mDragAndDrop);
|
/*
|
||||||
mWindows.push_back(containerWindow);
|
Start of tes3mp change (major)
|
||||||
trackWindow(containerWindow, "container");
|
|
||||||
mGuiModeStates[GM_Container] = GuiModeState({containerWindow, mInventoryWindow});
|
Use a member variable (mContainerWIndow) instead of a local one so
|
||||||
|
we can access it from elsewhere
|
||||||
|
*/
|
||||||
|
mContainerWindow = new ContainerWindow(mDragAndDrop);
|
||||||
|
mWindows.push_back(mContainerWindow);
|
||||||
|
trackWindow(mContainerWindow, "container");
|
||||||
|
mGuiModeStates[GM_Container] = GuiModeState({mContainerWindow, mInventoryWindow});
|
||||||
|
/*
|
||||||
|
End of tes3mp change (major)
|
||||||
|
*/
|
||||||
|
|
||||||
mHud = new HUD(mCustomMarkers, mDragAndDrop, mLocalMapRender);
|
mHud = new HUD(mCustomMarkers, mDragAndDrop, mLocalMapRender);
|
||||||
mWindows.push_back(mHud);
|
mWindows.push_back(mHud);
|
||||||
|
@ -1399,6 +1408,17 @@ namespace MWGui
|
||||||
MWGui::ConfirmationDialog* WindowManager::getConfirmationDialog() { return mConfirmationDialog; }
|
MWGui::ConfirmationDialog* WindowManager::getConfirmationDialog() { return mConfirmationDialog; }
|
||||||
MWGui::TradeWindow* WindowManager::getTradeWindow() { return mTradeWindow; }
|
MWGui::TradeWindow* WindowManager::getTradeWindow() { return mTradeWindow; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
Start of tes3mp addition
|
||||||
|
|
||||||
|
Make it possible to get the ContainerWindow from elsewhere
|
||||||
|
in the code
|
||||||
|
*/
|
||||||
|
MWGui::ContainerWindow* WindowManager::getContainerWindow() { return mContainerWindow; }
|
||||||
|
/*
|
||||||
|
End of tes3mp addition
|
||||||
|
*/
|
||||||
|
|
||||||
void WindowManager::useItem(const MWWorld::Ptr &item)
|
void WindowManager::useItem(const MWWorld::Ptr &item)
|
||||||
{
|
{
|
||||||
if (mInventoryWindow)
|
if (mInventoryWindow)
|
||||||
|
@ -2022,11 +2042,16 @@ namespace MWGui
|
||||||
mInventoryWindow->cycle(next);
|
mInventoryWindow->cycle(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::playSound(const std::string& soundId, float volume, float pitch)
|
void WindowManager::playSound(const std::string& soundId, bool preventOverlapping, float volume, float pitch)
|
||||||
{
|
{
|
||||||
if (soundId.empty())
|
if (soundId.empty())
|
||||||
return;
|
return;
|
||||||
MWBase::Environment::get().getSoundManager()->playSound(soundId, volume, pitch, MWSound::Type::Sfx, MWSound::PlayMode::NoEnv);
|
|
||||||
|
MWBase::SoundManager *sndmgr = MWBase::Environment::get().getSoundManager();
|
||||||
|
if (preventOverlapping && sndmgr->getSoundPlaying(MWWorld::Ptr(), soundId))
|
||||||
|
return;
|
||||||
|
|
||||||
|
sndmgr->playSound(soundId, volume, pitch, MWSound::Type::Sfx, MWSound::PlayMode::NoEnv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::updateSpellWindow()
|
void WindowManager::updateSpellWindow()
|
||||||
|
|
|
@ -184,6 +184,17 @@ namespace MWGui
|
||||||
virtual MWGui::ConfirmationDialog* getConfirmationDialog();
|
virtual MWGui::ConfirmationDialog* getConfirmationDialog();
|
||||||
virtual MWGui::TradeWindow* getTradeWindow();
|
virtual MWGui::TradeWindow* getTradeWindow();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Start of tes3mp addition
|
||||||
|
|
||||||
|
Make it possible to get the ContainerWindow from elsewhere
|
||||||
|
in the code
|
||||||
|
*/
|
||||||
|
virtual MWGui::ContainerWindow* getContainerWindow();
|
||||||
|
/*
|
||||||
|
End of tes3mp addition
|
||||||
|
*/
|
||||||
|
|
||||||
/// Make the player use an item, while updating GUI state accordingly
|
/// Make the player use an item, while updating GUI state accordingly
|
||||||
virtual void useItem(const MWWorld::Ptr& item);
|
virtual void useItem(const MWWorld::Ptr& item);
|
||||||
|
|
||||||
|
@ -440,7 +451,7 @@ namespace MWGui
|
||||||
/// Cycle to next or previous weapon
|
/// Cycle to next or previous weapon
|
||||||
virtual void cycleWeapon(bool next);
|
virtual void cycleWeapon(bool next);
|
||||||
|
|
||||||
virtual void playSound(const std::string& soundId, float volume = 1.f, float pitch = 1.f);
|
virtual void playSound(const std::string& soundId, bool preventOverlapping = false, float volume = 1.f, float pitch = 1.f);
|
||||||
|
|
||||||
// In WindowManager for now since there isn't a VFS singleton
|
// In WindowManager for now since there isn't a VFS singleton
|
||||||
virtual std::string correctIconPath(const std::string& path);
|
virtual std::string correctIconPath(const std::string& path);
|
||||||
|
@ -510,6 +521,17 @@ namespace MWGui
|
||||||
DebugWindow* mDebugWindow;
|
DebugWindow* mDebugWindow;
|
||||||
JailScreen* mJailScreen;
|
JailScreen* mJailScreen;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Start of tes3mp addition
|
||||||
|
|
||||||
|
Keep a pointer to the container window because of its usefulness
|
||||||
|
in multiplayer for container sync
|
||||||
|
*/
|
||||||
|
ContainerWindow* mContainerWindow;
|
||||||
|
/*
|
||||||
|
End of tes3mp addition
|
||||||
|
*/
|
||||||
|
|
||||||
std::vector<WindowBase*> mWindows;
|
std::vector<WindowBase*> mWindows;
|
||||||
|
|
||||||
Translation::Storage& mTranslationDataStorage;
|
Translation::Storage& mTranslationDataStorage;
|
||||||
|
|
|
@ -1066,6 +1066,17 @@ namespace MWInput
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Start of tes3mp addition
|
||||||
|
|
||||||
|
Ignore attempts to rest if the player has not finished character generation yet
|
||||||
|
*/
|
||||||
|
if (!mwmp::Main::get().getLocalPlayer()->hasFinishedCharGen())
|
||||||
|
return;
|
||||||
|
/*
|
||||||
|
End of tes3mp addition
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Start of tes3mp addition
|
Start of tes3mp addition
|
||||||
|
|
||||||
|
|
|
@ -949,7 +949,7 @@ namespace MWMechanics
|
||||||
stats.setTimeToStartDrowning(fHoldBreathTime);
|
stats.setTimeToStartDrowning(fHoldBreathTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Actors::updateEquippedLight (const MWWorld::Ptr& ptr, float duration)
|
void Actors::updateEquippedLight (const MWWorld::Ptr& ptr, float duration, bool mayEquip)
|
||||||
{
|
{
|
||||||
bool isPlayer = (ptr == getPlayer());
|
bool isPlayer = (ptr == getPlayer());
|
||||||
|
|
||||||
|
@ -964,7 +964,7 @@ namespace MWMechanics
|
||||||
Start of tes3mp change (major)
|
Start of tes3mp change (major)
|
||||||
|
|
||||||
We need DedicatedPlayers and DedicatedActors to not automatically
|
We need DedicatedPlayers and DedicatedActors to not automatically
|
||||||
equip their light-emitting items, so additions conditions have been
|
equip their light-emitting items, so additional conditions have been
|
||||||
added for them
|
added for them
|
||||||
*/
|
*/
|
||||||
if (!isPlayer && !mwmp::PlayerList::isDedicatedPlayer(ptr) && !mwmp::Main::get().getCellController()->isDedicatedActor(ptr))
|
if (!isPlayer && !mwmp::PlayerList::isDedicatedPlayer(ptr) && !mwmp::Main::get().getCellController()->isDedicatedActor(ptr))
|
||||||
|
@ -982,7 +982,7 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MWBase::Environment::get().getWorld()->isDark())
|
if (mayEquip)
|
||||||
{
|
{
|
||||||
if (torch != inventoryStore.end())
|
if (torch != inventoryStore.end())
|
||||||
{
|
{
|
||||||
|
@ -991,16 +991,11 @@ namespace MWMechanics
|
||||||
// For non-hostile NPCs, unequip whatever is in the left slot in favor of a light.
|
// For non-hostile NPCs, unequip whatever is in the left slot in favor of a light.
|
||||||
if (heldIter != inventoryStore.end() && heldIter->getTypeName() != typeid(ESM::Light).name())
|
if (heldIter != inventoryStore.end() && heldIter->getTypeName() != typeid(ESM::Light).name())
|
||||||
inventoryStore.unequipItem(*heldIter, ptr);
|
inventoryStore.unequipItem(*heldIter, ptr);
|
||||||
|
|
||||||
// Also unequip twohanded weapons which conflict with anything in CarriedLeft
|
|
||||||
if (torch->getClass().canBeEquipped(*torch, ptr).first == 3)
|
|
||||||
inventoryStore.unequipSlot(MWWorld::InventoryStore::Slot_CarriedRight, ptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
heldIter = inventoryStore.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
|
heldIter = inventoryStore.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
|
||||||
|
|
||||||
// If we have a torch and can equip it (left slot free, no
|
// If we have a torch and can equip it, then equip it now.
|
||||||
// twohanded weapon in right slot), then equip it now.
|
|
||||||
if (heldIter == inventoryStore.end()
|
if (heldIter == inventoryStore.end()
|
||||||
&& torch->getClass().canBeEquipped(*torch, ptr).first == 1)
|
&& torch->getClass().canBeEquipped(*torch, ptr).first == 1)
|
||||||
{
|
{
|
||||||
|
@ -1057,7 +1052,7 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Actors::updateCrimePersuit(const MWWorld::Ptr& ptr, float duration)
|
void Actors::updateCrimePursuit(const MWWorld::Ptr& ptr, float duration)
|
||||||
{
|
{
|
||||||
MWWorld::Ptr player = getPlayer();
|
MWWorld::Ptr player = getPlayer();
|
||||||
if (ptr != player && ptr.getClass().isNpc())
|
if (ptr != player && ptr.getClass().isNpc())
|
||||||
|
@ -1293,6 +1288,9 @@ namespace MWMechanics
|
||||||
if (mTimerDisposeSummonsCorpses >= 0.2f) mTimerDisposeSummonsCorpses = 0;
|
if (mTimerDisposeSummonsCorpses >= 0.2f) mTimerDisposeSummonsCorpses = 0;
|
||||||
if (timerUpdateEquippedLight >= updateEquippedLightInterval) timerUpdateEquippedLight = 0;
|
if (timerUpdateEquippedLight >= updateEquippedLightInterval) timerUpdateEquippedLight = 0;
|
||||||
|
|
||||||
|
// show torches only when there are darkness and no precipitations
|
||||||
|
bool showTorches = MWBase::Environment::get().getWorld()->useTorches();
|
||||||
|
|
||||||
MWWorld::Ptr player = getPlayer();
|
MWWorld::Ptr player = getPlayer();
|
||||||
|
|
||||||
/// \todo move update logic to Actor class where appropriate
|
/// \todo move update logic to Actor class where appropriate
|
||||||
|
@ -1438,7 +1436,7 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iter->first.getClass().isNpc() && iter->first != player && (isLocalActor || isAIActive))
|
if (iter->first.getClass().isNpc() && iter->first != player && (isLocalActor || isAIActive))
|
||||||
updateCrimePersuit(iter->first, duration);
|
updateCrimePursuit(iter->first, duration);
|
||||||
|
|
||||||
if (iter->first != player && (isLocalActor || isAIActive))
|
if (iter->first != player && (isLocalActor || isAIActive))
|
||||||
{
|
{
|
||||||
|
@ -1456,7 +1454,7 @@ namespace MWMechanics
|
||||||
updateNpc(iter->first, duration);
|
updateNpc(iter->first, duration);
|
||||||
|
|
||||||
if (timerUpdateEquippedLight == 0)
|
if (timerUpdateEquippedLight == 0)
|
||||||
updateEquippedLight(iter->first, updateEquippedLightInterval);
|
updateEquippedLight(iter->first, updateEquippedLightInterval, showTorches);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,9 +39,9 @@ namespace MWMechanics
|
||||||
|
|
||||||
void updateDrowning (const MWWorld::Ptr& ptr, float duration);
|
void updateDrowning (const MWWorld::Ptr& ptr, float duration);
|
||||||
|
|
||||||
void updateEquippedLight (const MWWorld::Ptr& ptr, float duration);
|
void updateEquippedLight (const MWWorld::Ptr& ptr, float duration, bool mayEquip);
|
||||||
|
|
||||||
void updateCrimePersuit (const MWWorld::Ptr& ptr, float duration);
|
void updateCrimePursuit (const MWWorld::Ptr& ptr, float duration);
|
||||||
|
|
||||||
void killDeadActors ();
|
void killDeadActors ();
|
||||||
|
|
||||||
|
|
|
@ -189,7 +189,7 @@ void MWMechanics::AiPackage::evadeObstacles(const MWWorld::Ptr& actor, float dur
|
||||||
static float distance = MWBase::Environment::get().getWorld()->getMaxActivationDistance();
|
static float distance = MWBase::Environment::get().getWorld()->getMaxActivationDistance();
|
||||||
|
|
||||||
MWWorld::Ptr door = getNearbyDoor(actor, distance);
|
MWWorld::Ptr door = getNearbyDoor(actor, distance);
|
||||||
if (door != MWWorld::Ptr())
|
if (door != MWWorld::Ptr() && actor.getClass().isBipedal(actor))
|
||||||
{
|
{
|
||||||
// note: AiWander currently does not open doors
|
// note: AiWander currently does not open doors
|
||||||
if (getTypeId() != TypeIdWander && !door.getCellRef().getTeleport() && door.getClass().getDoorState(door) == 0)
|
if (getTypeId() != TypeIdWander && !door.getCellRef().getTeleport() && door.getClass().getDoorState(door) == 0)
|
||||||
|
@ -224,7 +224,7 @@ void MWMechanics::AiPackage::evadeObstacles(const MWWorld::Ptr& actor, float dur
|
||||||
MWBase::Environment::get().getWorld()->activate(door, actor);
|
MWBase::Environment::get().getWorld()->activate(door, actor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // any other obstacle (NPC, crate, etc.)
|
else
|
||||||
{
|
{
|
||||||
mObstacleCheck.takeEvasiveAction(movement);
|
mObstacleCheck.takeEvasiveAction(movement);
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,6 @@
|
||||||
|
|
||||||
#include "../mwrender/animation.hpp"
|
#include "../mwrender/animation.hpp"
|
||||||
|
|
||||||
#include "magiceffects.hpp"
|
|
||||||
#include "npcstats.hpp"
|
#include "npcstats.hpp"
|
||||||
#include "actorutil.hpp"
|
#include "actorutil.hpp"
|
||||||
#include "aifollow.hpp"
|
#include "aifollow.hpp"
|
||||||
|
@ -625,7 +624,6 @@ namespace MWMechanics
|
||||||
|
|
||||||
std::string texture = magicEffect->mParticle;
|
std::string texture = magicEffect->mParticle;
|
||||||
|
|
||||||
// TODO: VFX are no longer active after saving/reloading the game
|
|
||||||
bool loop = (magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx) != 0;
|
bool loop = (magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx) != 0;
|
||||||
// Note: in case of non actor, a free effect should be fine as well
|
// Note: in case of non actor, a free effect should be fine as well
|
||||||
MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(target);
|
MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(target);
|
||||||
|
@ -1383,4 +1381,24 @@ namespace MWMechanics
|
||||||
return MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(it->second)->getString();
|
return MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(it->second)->getString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ApplyLoopingParticlesVisitor::visit (MWMechanics::EffectKey key,
|
||||||
|
const std::string& /*sourceName*/, const std::string& /*sourceId*/, int /*casterActorId*/,
|
||||||
|
float /*magnitude*/, float /*remainingTime*/, float /*totalTime*/)
|
||||||
|
{
|
||||||
|
const ESM::MagicEffect *magicEffect =
|
||||||
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(key.mId);
|
||||||
|
|
||||||
|
const ESM::Static* castStatic;
|
||||||
|
if (!magicEffect->mHit.empty())
|
||||||
|
castStatic = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>().find (magicEffect->mHit);
|
||||||
|
else
|
||||||
|
castStatic = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>().find ("VFX_DefaultHit");
|
||||||
|
|
||||||
|
std::string texture = magicEffect->mParticle;
|
||||||
|
|
||||||
|
bool loop = (magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx) != 0;
|
||||||
|
MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(mActor);
|
||||||
|
if (anim && loop)
|
||||||
|
anim->addEffect("meshes\\" + castStatic->mModel, magicEffect->mIndex, loop, "", texture);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
|
|
||||||
|
#include "magiceffects.hpp"
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
struct Spell;
|
struct Spell;
|
||||||
|
@ -119,6 +121,21 @@ namespace MWMechanics
|
||||||
bool applyInstantEffect (const MWWorld::Ptr& target, const MWWorld::Ptr& caster, const MWMechanics::EffectKey& effect, float magnitude);
|
bool applyInstantEffect (const MWWorld::Ptr& target, const MWWorld::Ptr& caster, const MWMechanics::EffectKey& effect, float magnitude);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ApplyLoopingParticlesVisitor : public EffectSourceVisitor
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
MWWorld::Ptr mActor;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ApplyLoopingParticlesVisitor(const MWWorld::Ptr& actor)
|
||||||
|
: mActor(actor)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void visit (MWMechanics::EffectKey key,
|
||||||
|
const std::string& /*sourceName*/, const std::string& /*sourceId*/, int /*casterActorId*/,
|
||||||
|
float /*magnitude*/, float /*remainingTime*/ = -1, float /*totalTime*/ = -1);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -218,7 +218,6 @@ void mwmp::GUIController::showCustomWindow(const mwmp::BasePlayer::GUIWindow &gu
|
||||||
void mwmp::GUIController::onInputBoxDone(MWGui::WindowBase *parWindow)
|
void mwmp::GUIController::onInputBoxDone(MWGui::WindowBase *parWindow)
|
||||||
{
|
{
|
||||||
//MWBase::WindowManager *windowManager = MWBase::Environment::get().getWindowManager();
|
//MWBase::WindowManager *windowManager = MWBase::Environment::get().getWindowManager();
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "GUIController::onInputBoxDone: %s.",mInputBox->getTextInput().c_str());
|
|
||||||
|
|
||||||
Main::get().getLocalPlayer()->guiMessageBox.data = mInputBox->getTextInput();
|
Main::get().getLocalPlayer()->guiMessageBox.data = mInputBox->getTextInput();
|
||||||
Main::get().getNetworking()->getPlayerPacket(ID_GUI_MESSAGEBOX)->setPlayer(Main::get().getLocalPlayer());
|
Main::get().getNetworking()->getPlayerPacket(ID_GUI_MESSAGEBOX)->setPlayer(Main::get().getLocalPlayer());
|
||||||
|
|
|
@ -205,16 +205,8 @@ void LocalActor::updateEquipment(bool forceUpdate)
|
||||||
|
|
||||||
item.refId = cellRef.getRefId();
|
item.refId = cellRef.getRefId();
|
||||||
item.charge = cellRef.getCharge();
|
item.charge = cellRef.getCharge();
|
||||||
if (slot == MWWorld::InventoryStore::Slot_CarriedRight)
|
item.enchantmentCharge = it->getCellRef().getEnchantmentCharge();
|
||||||
{
|
item.count = it->getRefData().getCount();
|
||||||
MWMechanics::WeaponType weaptype;
|
|
||||||
auto &_class = ptr.getClass();
|
|
||||||
MWMechanics::getActiveWeapon(_class.getCreatureStats(ptr), _class.getInventoryStore(ptr), &weaptype);
|
|
||||||
if (weaptype != MWMechanics::WeapType_Thrown)
|
|
||||||
item.count = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
item.count = invStore.count(cellRef.getRefId());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!item.refId.empty())
|
else if (!item.refId.empty())
|
||||||
|
@ -222,7 +214,8 @@ void LocalActor::updateEquipment(bool forceUpdate)
|
||||||
equipmentChanged = true;
|
equipmentChanged = true;
|
||||||
item.refId = "";
|
item.refId = "";
|
||||||
item.count = 0;
|
item.count = 0;
|
||||||
item.charge = 0;
|
item.charge = -1;
|
||||||
|
item.enchantmentCharge = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,7 @@ LocalPlayer::LocalPlayer()
|
||||||
charGenState.isFinished = false;
|
charGenState.isFinished = false;
|
||||||
|
|
||||||
difficulty = 0;
|
difficulty = 0;
|
||||||
|
enforcedLogLevel = -1;
|
||||||
physicsFramerate = 60.0;
|
physicsFramerate = 60.0;
|
||||||
consoleAllowed = false;
|
consoleAllowed = false;
|
||||||
bedRestAllowed = true;
|
bedRestAllowed = true;
|
||||||
|
@ -455,17 +456,7 @@ void LocalPlayer::updateEquipment(bool forceUpdate)
|
||||||
item.refId = it->getCellRef().getRefId();
|
item.refId = it->getCellRef().getRefId();
|
||||||
item.charge = it->getCellRef().getCharge();
|
item.charge = it->getCellRef().getCharge();
|
||||||
item.enchantmentCharge = it->getCellRef().getEnchantmentCharge();
|
item.enchantmentCharge = it->getCellRef().getEnchantmentCharge();
|
||||||
|
item.count = it->getRefData().getCount();
|
||||||
if (slot == MWWorld::InventoryStore::Slot_CarriedRight)
|
|
||||||
{
|
|
||||||
MWMechanics::WeaponType weaptype;
|
|
||||||
MWMechanics::getActiveWeapon(ptrPlayer.getClass().getCreatureStats(ptrPlayer),
|
|
||||||
ptrPlayer.getClass().getInventoryStore(ptrPlayer), &weaptype);
|
|
||||||
if (weaptype != MWMechanics::WeapType_Thrown)
|
|
||||||
item.count = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
item.count = invStore.count(it->getCellRef().getRefId());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!item.refId.empty())
|
else if (!item.refId.empty())
|
||||||
|
@ -688,6 +679,7 @@ void LocalPlayer::addItem(const Item &item)
|
||||||
LOG_APPEND(Log::LOG_INFO, "- Ignored addition of invalid inventory item %s", item.refId.c_str());
|
LOG_APPEND(Log::LOG_INFO, "- Ignored addition of invalid inventory item %s", item.refId.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->updateItemView();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalPlayer::addSpells()
|
void LocalPlayer::addSpells()
|
||||||
|
@ -1080,6 +1072,8 @@ void LocalPlayer::setEquipment()
|
||||||
else
|
else
|
||||||
ptrInventory.unequipSlot(slot, ptrPlayer);
|
ptrInventory.unequipSlot(slot, ptrPlayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->updatePlayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalPlayer::setInventory()
|
void LocalPlayer::setInventory()
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
#include "../mwbase/soundmanager.hpp"
|
#include "../mwbase/soundmanager.hpp"
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
|
||||||
|
#include "../mwgui/container.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/aifollow.hpp"
|
#include "../mwmechanics/aifollow.hpp"
|
||||||
#include "../mwmechanics/spellcasting.hpp"
|
#include "../mwmechanics/spellcasting.hpp"
|
||||||
#include "../mwmechanics/summoning.hpp"
|
#include "../mwmechanics/summoning.hpp"
|
||||||
|
@ -50,14 +52,20 @@ void WorldEvent::reset()
|
||||||
cell.blank();
|
cell.blank();
|
||||||
worldObjects.clear();
|
worldObjects.clear();
|
||||||
guid = mwmp::Main::get().getNetworking()->getLocalPlayer()->guid;
|
guid = mwmp::Main::get().getNetworking()->getLocalPlayer()->guid;
|
||||||
|
|
||||||
|
action = BaseEvent::Action::Request;
|
||||||
|
containerSubAction = BaseEvent::ContainerSubAction::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldEvent::editContainers(MWWorld::CellStore* cellStore)
|
void WorldEvent::editContainers(MWWorld::CellStore* cellStore)
|
||||||
{
|
{
|
||||||
|
bool isLocalEvent = guid == Main::get().getLocalPlayer()->guid;
|
||||||
|
|
||||||
|
LOG_APPEND(Log::LOG_VERBOSE, "- isLocalEvent? %s", isLocalEvent ? "true" : "false");
|
||||||
|
|
||||||
for (const auto &worldObject : worldObjects)
|
for (const auto &worldObject : worldObjects)
|
||||||
{
|
{
|
||||||
|
//LOG_APPEND(Log::LOG_VERBOSE, "- container cellRef: %s %i-%i", worldObject.refId.c_str(), worldObject.refNumIndex, worldObject.mpNum);
|
||||||
//LOG_APPEND(Log::LOG_VERBOSE, "- cellRef: %s, %i, %i", worldObject.refId.c_str(), worldObject.refNumIndex, worldObject.mpNum);
|
|
||||||
|
|
||||||
MWWorld::Ptr ptrFound = cellStore->searchExact(worldObject.refNumIndex, worldObject.mpNum);
|
MWWorld::Ptr ptrFound = cellStore->searchExact(worldObject.refNumIndex, worldObject.mpNum);
|
||||||
|
|
||||||
|
@ -66,19 +74,41 @@ void WorldEvent::editContainers(MWWorld::CellStore* cellStore)
|
||||||
//LOG_APPEND(Log::LOG_VERBOSE, "-- Found %s, %i, %i", ptrFound.getCellRef().getRefId().c_str(),
|
//LOG_APPEND(Log::LOG_VERBOSE, "-- Found %s, %i, %i", ptrFound.getCellRef().getRefId().c_str(),
|
||||||
// ptrFound.getCellRef().getRefNum().mIndex, ptrFound.getCellRef().getMpNum());
|
// ptrFound.getCellRef().getRefNum().mIndex, ptrFound.getCellRef().getMpNum());
|
||||||
|
|
||||||
|
bool isCurrentContainer = false;
|
||||||
|
|
||||||
|
// If we are in a container, and it happens to be this container, keep track of that
|
||||||
|
if (MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_Container))
|
||||||
|
{
|
||||||
|
CurrentContainer *currentContainer = &mwmp::Main::get().getLocalPlayer()->currentContainer;
|
||||||
|
|
||||||
|
if (currentContainer->refNumIndex == ptrFound.getCellRef().getRefNum().mIndex &&
|
||||||
|
currentContainer->mpNum == ptrFound.getCellRef().getMpNum())
|
||||||
|
{
|
||||||
|
isCurrentContainer = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MWWorld::ContainerStore& containerStore = ptrFound.getClass().getContainerStore(ptrFound);
|
MWWorld::ContainerStore& containerStore = ptrFound.getClass().getContainerStore(ptrFound);
|
||||||
|
|
||||||
// If we are setting the entire contents, clear the current ones
|
// If we are setting the entire contents, clear the current ones
|
||||||
if (action == BaseEvent::Action::Set)
|
if (action == BaseEvent::Action::Set)
|
||||||
containerStore.clear();
|
containerStore.clear();
|
||||||
|
|
||||||
|
bool isLocalDrop = isLocalEvent && containerSubAction == BaseEvent::ContainerSubAction::Drop;
|
||||||
|
bool isLocalDrag = isLocalEvent && containerSubAction == BaseEvent::ContainerSubAction::Drag;
|
||||||
|
bool isLocalTakeAll = isLocalEvent && containerSubAction == BaseEvent::ContainerSubAction::TakeAll;
|
||||||
|
std::string takeAllSound = "";
|
||||||
|
|
||||||
MWWorld::Ptr ownerPtr = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
MWWorld::Ptr ownerPtr = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||||
for (const auto &containerItem : worldObject.containerItems)
|
for (const auto &containerItem : worldObject.containerItems)
|
||||||
{
|
{
|
||||||
|
//LOG_APPEND(Log::LOG_VERBOSE, "-- containerItem cellRef: %s, count: %i, actionCount: %i",
|
||||||
|
// containerItem.refId.c_str(), containerItem.count, containerItem.actionCount);
|
||||||
|
|
||||||
if (containerItem.refId.find("$dynamic") != string::npos)
|
if (containerItem.refId.find("$dynamic") != string::npos)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (action == BaseEvent::Action::Add || action == BaseEvent::Action::Set)
|
if (action == BaseEvent::Action::Set || action == BaseEvent::Action::Add)
|
||||||
{
|
{
|
||||||
// Create a ManualRef to be able to set item charge
|
// Create a ManualRef to be able to set item charge
|
||||||
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), containerItem.refId, 1);
|
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), containerItem.refId, 1);
|
||||||
|
@ -95,28 +125,53 @@ void WorldEvent::editContainers(MWWorld::CellStore* cellStore)
|
||||||
|
|
||||||
containerStore.add(newPtr, containerItem.count, ownerPtr, true);
|
containerStore.add(newPtr, containerItem.count, ownerPtr, true);
|
||||||
}
|
}
|
||||||
else if (action == BaseEvent::Action::Remove)
|
else if (action == BaseEvent::Action::Remove && containerItem.actionCount > 0)
|
||||||
{
|
{
|
||||||
// We have to find the right item ourselves because ContainerStore has no method
|
// We have to find the right item ourselves because ContainerStore has no method
|
||||||
// accounting for charge
|
// accounting for charge
|
||||||
for (const auto ptr : containerStore)
|
for (const auto itemPtr : containerStore)
|
||||||
{
|
{
|
||||||
if (Misc::StringUtils::ciEqual(ptr.getCellRef().getRefId(), containerItem.refId))
|
if (Misc::StringUtils::ciEqual(itemPtr.getCellRef().getRefId(), containerItem.refId))
|
||||||
{
|
{
|
||||||
if (ptr.getRefData().getCount() == containerItem.count &&
|
if (itemPtr.getCellRef().getCharge() == containerItem.charge &&
|
||||||
ptr.getCellRef().getCharge() == containerItem.charge &&
|
itemPtr.getCellRef().getEnchantmentCharge() == containerItem.enchantmentCharge)
|
||||||
ptr.getCellRef().getEnchantmentCharge() == containerItem.enchantmentCharge)
|
|
||||||
{
|
{
|
||||||
|
// Store the sound of the first item in a TAKE_ALL
|
||||||
|
if (isLocalTakeAll && takeAllSound.empty())
|
||||||
|
takeAllSound = itemPtr.getClass().getUpSoundId(itemPtr);
|
||||||
|
|
||||||
// Is this an actor's container? If so, unequip this item if it was equipped
|
// Is this an actor's container? If so, unequip this item if it was equipped
|
||||||
if (ptrFound.getClass().isActor())
|
if (ptrFound.getClass().isActor())
|
||||||
{
|
{
|
||||||
MWWorld::InventoryStore& invStore = ptrFound.getClass().getInventoryStore(ptrFound);
|
MWWorld::InventoryStore& invStore = ptrFound.getClass().getInventoryStore(ptrFound);
|
||||||
|
|
||||||
if (invStore.isEquipped(ptr))
|
if (invStore.isEquipped(itemPtr))
|
||||||
invStore.unequipItemQuantity(ptr, ptrFound, containerItem.count);
|
invStore.unequipItemQuantity(itemPtr, ptrFound, containerItem.count);
|
||||||
}
|
}
|
||||||
|
|
||||||
containerStore.remove(ptr, containerItem.actionCount, ownerPtr);
|
bool isResolved = false;
|
||||||
|
|
||||||
|
if (isLocalDrag && isCurrentContainer)
|
||||||
|
{
|
||||||
|
MWGui::ContainerWindow* containerWindow = MWBase::Environment::get().getWindowManager()->getContainerWindow();
|
||||||
|
|
||||||
|
if (!containerWindow->isOnDragAndDrop())
|
||||||
|
{
|
||||||
|
isResolved = containerWindow->dragItemByPtr(itemPtr, containerItem.actionCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isResolved)
|
||||||
|
{
|
||||||
|
containerStore.remove(itemPtr, containerItem.actionCount, ownerPtr);
|
||||||
|
|
||||||
|
if (isLocalDrag || isLocalTakeAll)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptrPlayer = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||||
|
MWWorld::ContainerStore &playerStore = ptrPlayer.getClass().getContainerStore(ptrPlayer);
|
||||||
|
*playerStore.add(containerItem.refId, containerItem.actionCount, ptrPlayer);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,16 +187,18 @@ void WorldEvent::editContainers(MWWorld::CellStore* cellStore)
|
||||||
invStore.autoEquip(ptrFound);
|
invStore.autoEquip(ptrFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are in a container, and it happens to be this container, update its view
|
// If this container was open for us, update its view
|
||||||
if (MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_Container))
|
if (isCurrentContainer)
|
||||||
{
|
{
|
||||||
CurrentContainer *currentContainer = &mwmp::Main::get().getLocalPlayer()->currentContainer;
|
if (isLocalTakeAll)
|
||||||
|
|
||||||
if (currentContainer->refNumIndex == ptrFound.getCellRef().getRefNum().mIndex &&
|
|
||||||
currentContainer->mpNum == ptrFound.getCellRef().getMpNum())
|
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Container);
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Container);
|
||||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Container, ptrFound);
|
MWBase::Environment::get().getWindowManager()->playSound(takeAllSound);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MWGui::ContainerWindow* containerWindow = MWBase::Environment::get().getWindowManager()->getContainerWindow();
|
||||||
|
containerWindow->setPtr(ptrFound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -610,6 +667,41 @@ void WorldEvent::playVideo()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WorldObject WorldEvent::getWorldObject(const MWWorld::Ptr& ptr)
|
||||||
|
{
|
||||||
|
mwmp::WorldObject worldObject;
|
||||||
|
worldObject.refId = ptr.getCellRef().getRefId();
|
||||||
|
worldObject.refNumIndex = ptr.getCellRef().getRefNum().mIndex;
|
||||||
|
worldObject.mpNum = ptr.getCellRef().getMpNum();
|
||||||
|
return worldObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldEvent::addContainerItem(mwmp::WorldObject& worldObject, const MWWorld::Ptr& itemPtr, int actionCount)
|
||||||
|
{
|
||||||
|
mwmp::ContainerItem containerItem;
|
||||||
|
containerItem.refId = itemPtr.getCellRef().getRefId();
|
||||||
|
containerItem.count = itemPtr.getRefData().getCount();
|
||||||
|
containerItem.charge = itemPtr.getCellRef().getCharge();
|
||||||
|
containerItem.enchantmentCharge = itemPtr.getCellRef().getEnchantmentCharge();
|
||||||
|
containerItem.actionCount = actionCount;
|
||||||
|
|
||||||
|
worldObject.containerItems.push_back(move(containerItem));
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldEvent::addEntireContainer(const MWWorld::Ptr& ptr)
|
||||||
|
{
|
||||||
|
MWWorld::ContainerStore& containerStore = ptr.getClass().getContainerStore(ptr);
|
||||||
|
|
||||||
|
mwmp::WorldObject worldObject = getWorldObject(ptr);
|
||||||
|
|
||||||
|
for (const auto itemPtr : containerStore)
|
||||||
|
{
|
||||||
|
addContainerItem(worldObject, itemPtr, itemPtr.getRefData().getCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
worldObjects.push_back(move(worldObject));
|
||||||
|
}
|
||||||
|
|
||||||
void WorldEvent::addObjectPlace(const MWWorld::Ptr& ptr, bool droppedByPlayer)
|
void WorldEvent::addObjectPlace(const MWWorld::Ptr& ptr, bool droppedByPlayer)
|
||||||
{
|
{
|
||||||
if (ptr.getCellRef().getRefId().find("$dynamic") != string::npos)
|
if (ptr.getCellRef().getRefId().find("$dynamic") != string::npos)
|
||||||
|
@ -980,7 +1072,7 @@ void WorldEvent::sendScriptGlobalShort()
|
||||||
mwmp::Main::get().getNetworking()->getWorldPacket(ID_SCRIPT_GLOBAL_SHORT)->Send();
|
mwmp::Main::get().getNetworking()->getWorldPacket(ID_SCRIPT_GLOBAL_SHORT)->Send();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldEvent::sendContainers(MWWorld::CellStore* cellStore)
|
void WorldEvent::sendCellContainers(MWWorld::CellStore* cellStore)
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
cell = *cellStore->getCell();
|
cell = *cellStore->getCell();
|
||||||
|
@ -999,13 +1091,7 @@ void WorldEvent::sendContainers(MWWorld::CellStore* cellStore)
|
||||||
|
|
||||||
for (const auto &itemPtr : containerStore)
|
for (const auto &itemPtr : containerStore)
|
||||||
{
|
{
|
||||||
mwmp::ContainerItem containerItem;
|
addContainerItem(worldObject, itemPtr, 0);
|
||||||
containerItem.refId = itemPtr.getCellRef().getRefId();
|
|
||||||
containerItem.count = itemPtr.getRefData().getCount();
|
|
||||||
containerItem.charge = itemPtr.getCellRef().getCharge();
|
|
||||||
containerItem.enchantmentCharge = itemPtr.getCellRef().getEnchantmentCharge();
|
|
||||||
|
|
||||||
worldObject.containerItems.push_back(move(containerItem));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
worldObjects.push_back(move(worldObject));
|
worldObjects.push_back(move(worldObject));
|
||||||
|
|
|
@ -40,6 +40,10 @@ namespace mwmp
|
||||||
void playMusic();
|
void playMusic();
|
||||||
void playVideo();
|
void playVideo();
|
||||||
|
|
||||||
|
WorldObject getWorldObject(const MWWorld::Ptr& ptr);
|
||||||
|
void addContainerItem(mwmp::WorldObject& worldObject, const MWWorld::Ptr& itemPtr, int actionCount);
|
||||||
|
void addEntireContainer(const MWWorld::Ptr& ptr);
|
||||||
|
|
||||||
void addObjectPlace(const MWWorld::Ptr& ptr, bool droppedByPlayer = false);
|
void addObjectPlace(const MWWorld::Ptr& ptr, bool droppedByPlayer = false);
|
||||||
void addObjectSpawn(const MWWorld::Ptr& ptr);
|
void addObjectSpawn(const MWWorld::Ptr& ptr);
|
||||||
void addObjectSpawn(const MWWorld::Ptr& ptr, const MWWorld::Ptr& master);
|
void addObjectSpawn(const MWWorld::Ptr& ptr, const MWWorld::Ptr& master);
|
||||||
|
@ -49,6 +53,7 @@ namespace mwmp
|
||||||
void addObjectScale(const MWWorld::Ptr& ptr, float scale);
|
void addObjectScale(const MWWorld::Ptr& ptr, float scale);
|
||||||
void addObjectState(const MWWorld::Ptr& ptr, bool objectState);
|
void addObjectState(const MWWorld::Ptr& ptr, bool objectState);
|
||||||
void addObjectAnimPlay(const MWWorld::Ptr& ptr, std::string group, int mode);
|
void addObjectAnimPlay(const MWWorld::Ptr& ptr, std::string group, int mode);
|
||||||
|
|
||||||
void addDoorState(const MWWorld::Ptr& ptr, int state);
|
void addDoorState(const MWWorld::Ptr& ptr, int state);
|
||||||
void addMusicPlay(std::string filename);
|
void addMusicPlay(std::string filename);
|
||||||
void addVideoPlay(std::string filename, bool allowSkipping);
|
void addVideoPlay(std::string filename, bool allowSkipping);
|
||||||
|
@ -73,7 +78,7 @@ namespace mwmp
|
||||||
void sendScriptMemberShort();
|
void sendScriptMemberShort();
|
||||||
void sendScriptGlobalShort();
|
void sendScriptGlobalShort();
|
||||||
|
|
||||||
void sendContainers(MWWorld::CellStore* cellStore);
|
void sendCellContainers(MWWorld::CellStore* cellStore);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Networking *getNetworking();
|
Networking *getNetworking();
|
||||||
|
|
|
@ -15,6 +15,7 @@ bool ActorProcessor::Process(RakNet::Packet &packet, ActorList &actorList)
|
||||||
{
|
{
|
||||||
RakNet::BitStream bsIn(&packet.data[1], packet.length, false);
|
RakNet::BitStream bsIn(&packet.data[1], packet.length, false);
|
||||||
bsIn.Read(guid);
|
bsIn.Read(guid);
|
||||||
|
actorList.guid = guid;
|
||||||
|
|
||||||
ActorPacket *myPacket = Main::get().getNetworking()->getActorPacket(packet.data[0]);
|
ActorPacket *myPacket = Main::get().getNetworking()->getActorPacket(packet.data[0]);
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ bool WorldProcessor::Process(RakNet::Packet &packet, WorldEvent &event)
|
||||||
{
|
{
|
||||||
RakNet::BitStream bsIn(&packet.data[1], packet.length, false);
|
RakNet::BitStream bsIn(&packet.data[1], packet.length, false);
|
||||||
bsIn.Read(guid);
|
bsIn.Read(guid);
|
||||||
|
event.guid = guid;
|
||||||
|
|
||||||
WorldPacket *myPacket = Main::get().getNetworking()->getWorldPacket(packet.data[0]);
|
WorldPacket *myPacket = Main::get().getNetworking()->getWorldPacket(packet.data[0]);
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,12 @@ namespace mwmp
|
||||||
|
|
||||||
virtual void Do(PlayerPacket &packet, BasePlayer *player)
|
virtual void Do(PlayerPacket &packet, BasePlayer *player)
|
||||||
{
|
{
|
||||||
|
static const int initialLogLevel = Log::GetLevel();
|
||||||
|
|
||||||
if (isLocal())
|
if (isLocal())
|
||||||
{
|
{
|
||||||
|
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Received ID_GAME_SETTINGS");
|
||||||
|
|
||||||
if (MWBase::Environment::get().getWindowManager()->isGuiMode())
|
if (MWBase::Environment::get().getWindowManager()->isGuiMode())
|
||||||
{
|
{
|
||||||
if (MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Console && !player->consoleAllowed)
|
if (MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Console && !player->consoleAllowed)
|
||||||
|
@ -30,6 +34,18 @@ namespace mwmp
|
||||||
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (player->enforcedLogLevel > -1)
|
||||||
|
{
|
||||||
|
LOG_APPEND(Log::LOG_INFO, "- server is enforcing log level %i", player->enforcedLogLevel);
|
||||||
|
|
||||||
|
Log::Get().SetLevel(player->enforcedLogLevel);
|
||||||
|
}
|
||||||
|
else if (initialLogLevel != Log::GetLevel())
|
||||||
|
{
|
||||||
|
LOG_APPEND(Log::LOG_INFO, "- log level has been reset to initial value %i", initialLogLevel);
|
||||||
|
Log::Get().SetLevel(initialLogLevel);
|
||||||
|
}
|
||||||
|
|
||||||
MWBase::Environment::get().getWorld()->setPhysicsFramerate(player->physicsFramerate);
|
MWBase::Environment::get().getWorld()->setPhysicsFramerate(player->physicsFramerate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace mwmp
|
||||||
|
|
||||||
virtual void Do(PlayerPacket &packet, BasePlayer *player)
|
virtual void Do(PlayerPacket &packet, BasePlayer *player)
|
||||||
{
|
{
|
||||||
packet.setPlayer(getLocalPlayer()); // player is 0 because myGuid will be setted after ProcessUserMyID
|
packet.setPlayer(getLocalPlayer()); // player is 0 because myGuid will be set after ProcessUserMyID
|
||||||
packet.Send(serverAddr);
|
packet.Send(serverAddr);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,11 +17,11 @@ namespace mwmp
|
||||||
{
|
{
|
||||||
BaseObjectProcessor::Do(packet, event);
|
BaseObjectProcessor::Do(packet, event);
|
||||||
|
|
||||||
LOG_APPEND(Log::LOG_VERBOSE, "- action: %i", (int)event.action);
|
LOG_APPEND(Log::LOG_VERBOSE, "- action: %i, containerSubAction: %i", (int) event.action, (int) event.containerSubAction);
|
||||||
|
|
||||||
// If we've received a request for information, comply with it
|
// If we've received a request for information, comply with it
|
||||||
if (event.action == mwmp::BaseEvent::Action::Request)
|
if (event.action == mwmp::BaseEvent::Action::Request)
|
||||||
event.sendContainers(ptrCellStore);
|
event.sendCellContainers(ptrCellStore);
|
||||||
// Otherwise, edit containers based on the information received
|
// Otherwise, edit containers based on the information received
|
||||||
else
|
else
|
||||||
event.editContainers(ptrCellStore);
|
event.editContainers(ptrCellStore);
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
#include <BulletCollision/CollisionDispatch/btCollisionObject.h>
|
#include <BulletCollision/CollisionDispatch/btCollisionObject.h>
|
||||||
#include <BulletCollision/CollisionDispatch/btCollisionWorld.h>
|
#include <BulletCollision/CollisionDispatch/btCollisionWorld.h>
|
||||||
#include <BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h>
|
#include <BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h>
|
||||||
#include <BulletCollision/CollisionDispatch/btCollisionWorld.h>
|
|
||||||
#include <BulletCollision/BroadphaseCollision/btDbvtBroadphase.h>
|
#include <BulletCollision/BroadphaseCollision/btDbvtBroadphase.h>
|
||||||
|
|
||||||
#include <LinearMath/btQuickprof.h>
|
#include <LinearMath/btQuickprof.h>
|
||||||
|
|
|
@ -90,6 +90,9 @@ namespace
|
||||||
|
|
||||||
if (ptr.getClass().isActor())
|
if (ptr.getClass().isActor())
|
||||||
rendering.addWaterRippleEmitter(ptr);
|
rendering.addWaterRippleEmitter(ptr);
|
||||||
|
|
||||||
|
// Restore effect particles
|
||||||
|
MWBase::Environment::get().getWorld()->applyLoopingParticles(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateObjectRotation (const MWWorld::Ptr& ptr, MWPhysics::PhysicsSystem& physics,
|
void updateObjectRotation (const MWWorld::Ptr& ptr, MWPhysics::PhysicsSystem& physics,
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#include <components/fallback/fallback.hpp>
|
#include <components/fallback/fallback.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
|
||||||
#include "../mwbase/soundmanager.hpp"
|
#include "../mwbase/soundmanager.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/actorutil.hpp"
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
|
@ -520,6 +519,7 @@ WeatherManager::WeatherManager(MWRender::RenderingManager& rendering, const Fall
|
||||||
, mSecunda("Secunda", fallback)
|
, mSecunda("Secunda", fallback)
|
||||||
, mWindSpeed(0.f)
|
, mWindSpeed(0.f)
|
||||||
, mIsStorm(false)
|
, mIsStorm(false)
|
||||||
|
, mPrecipitation(false)
|
||||||
, mStormDirection(0,1,0)
|
, mStormDirection(0,1,0)
|
||||||
, mCurrentRegion()
|
, mCurrentRegion()
|
||||||
, mTimePassed(0)
|
, mTimePassed(0)
|
||||||
|
@ -608,14 +608,11 @@ void WeatherManager::modRegion(const std::string& regionID, const std::vector<ch
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WeatherManager::playerTeleported()
|
void WeatherManager::playerTeleported(const std::string& playerRegion, bool isExterior)
|
||||||
{
|
{
|
||||||
// If the player teleports to an outdoors cell in a new region (for instance, by travelling), the weather needs to
|
// If the player teleports to an outdoors cell in a new region (for instance, by travelling), the weather needs to
|
||||||
// be changed immediately, and any transitions for the previous region discarded.
|
// be changed immediately, and any transitions for the previous region discarded.
|
||||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
|
||||||
if(world->isCellExterior() || world->isCellQuasiExterior())
|
|
||||||
{
|
{
|
||||||
std::string playerRegion = Misc::StringUtils::lowerCase(world->getPlayerPtr().getCell()->getCell()->mRegion);
|
|
||||||
std::map<std::string, RegionWeather>::iterator it = mRegions.find(playerRegion);
|
std::map<std::string, RegionWeather>::iterator it = mRegions.find(playerRegion);
|
||||||
if(it != mRegions.end() && playerRegion != mCurrentRegion)
|
if(it != mRegions.end() && playerRegion != mCurrentRegion)
|
||||||
{
|
{
|
||||||
|
@ -625,11 +622,9 @@ void WeatherManager::playerTeleported()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WeatherManager::update(float duration, bool paused)
|
void WeatherManager::update(float duration, bool paused, const TimeStamp& time, bool isExterior)
|
||||||
{
|
{
|
||||||
MWWorld::ConstPtr player = MWMechanics::getPlayer();
|
MWWorld::ConstPtr player = MWMechanics::getPlayer();
|
||||||
MWBase::World& world = *MWBase::Environment::get().getWorld();
|
|
||||||
TimeStamp time = world.getTimeStamp();
|
|
||||||
|
|
||||||
if(!paused || mFastForward)
|
if(!paused || mFastForward)
|
||||||
{
|
{
|
||||||
|
@ -647,8 +642,7 @@ void WeatherManager::update(float duration, bool paused)
|
||||||
updateWeatherTransitions(duration);
|
updateWeatherTransitions(duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool exterior = (world.isCellExterior() || world.isCellQuasiExterior());
|
if(!isExterior)
|
||||||
if(!exterior)
|
|
||||||
{
|
{
|
||||||
mRendering.setSkyEnabled(false);
|
mRendering.setSkyEnabled(false);
|
||||||
stopSounds();
|
stopSounds();
|
||||||
|
@ -660,6 +654,10 @@ void WeatherManager::update(float duration, bool paused)
|
||||||
mWindSpeed = mResult.mWindSpeed;
|
mWindSpeed = mResult.mWindSpeed;
|
||||||
mIsStorm = mResult.mIsStorm;
|
mIsStorm = mResult.mIsStorm;
|
||||||
|
|
||||||
|
// For some reason Ash Storm is not considered as a precipitation weather in game
|
||||||
|
mPrecipitation = !(mResult.mParticleEffect.empty() && mResult.mRainEffect.empty())
|
||||||
|
&& mResult.mParticleEffect != "meshes\\ashcloud.nif";
|
||||||
|
|
||||||
if (mIsStorm)
|
if (mIsStorm)
|
||||||
{
|
{
|
||||||
osg::Vec3f playerPos (player.getRefData().getPosition().asVec3());
|
osg::Vec3f playerPos (player.getRefData().getPosition().asVec3());
|
||||||
|
@ -777,12 +775,11 @@ unsigned int WeatherManager::getWeatherID() const
|
||||||
return mCurrentWeather;
|
return mCurrentWeather;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WeatherManager::isDark() const
|
bool WeatherManager::useTorches(float hour) const
|
||||||
{
|
{
|
||||||
TimeStamp time = MWBase::Environment::get().getWorld()->getTimeStamp();
|
bool isDark = hour < mSunriseTime || hour > mTimeSettings.mNightStart - 1;
|
||||||
bool exterior = (MWBase::Environment::get().getWorld()->isCellExterior()
|
|
||||||
|| MWBase::Environment::get().getWorld()->isCellQuasiExterior());
|
return isDark && !mPrecipitation;
|
||||||
return exterior && (time.getHour() < mSunriseTime || time.getHour() > mTimeSettings.mNightStart - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WeatherManager::write(ESM::ESMWriter& writer, Loading::Listener& progress)
|
void WeatherManager::write(ESM::ESMWriter& writer, Loading::Listener& progress)
|
||||||
|
|
|
@ -224,14 +224,14 @@ namespace MWWorld
|
||||||
*/
|
*/
|
||||||
void changeWeather(const std::string& regionID, const unsigned int weatherID);
|
void changeWeather(const std::string& regionID, const unsigned int weatherID);
|
||||||
void modRegion(const std::string& regionID, const std::vector<char>& chances);
|
void modRegion(const std::string& regionID, const std::vector<char>& chances);
|
||||||
void playerTeleported();
|
void playerTeleported(const std::string& playerRegion, bool isExterior);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Per-frame update
|
* Per-frame update
|
||||||
* @param duration
|
* @param duration
|
||||||
* @param paused
|
* @param paused
|
||||||
*/
|
*/
|
||||||
void update(float duration, bool paused = false);
|
void update(float duration, bool paused, const TimeStamp& time, bool isExterior);
|
||||||
|
|
||||||
void stopSounds();
|
void stopSounds();
|
||||||
|
|
||||||
|
@ -246,8 +246,7 @@ namespace MWWorld
|
||||||
|
|
||||||
unsigned int getWeatherID() const;
|
unsigned int getWeatherID() const;
|
||||||
|
|
||||||
/// @see World::isDark
|
bool useTorches(float hour) const;
|
||||||
bool isDark() const;
|
|
||||||
|
|
||||||
void write(ESM::ESMWriter& writer, Loading::Listener& progress);
|
void write(ESM::ESMWriter& writer, Loading::Listener& progress);
|
||||||
|
|
||||||
|
@ -281,6 +280,7 @@ namespace MWWorld
|
||||||
|
|
||||||
float mWindSpeed;
|
float mWindSpeed;
|
||||||
bool mIsStorm;
|
bool mIsStorm;
|
||||||
|
bool mPrecipitation;
|
||||||
osg::Vec3f mStormDirection;
|
osg::Vec3f mStormDirection;
|
||||||
|
|
||||||
std::string mCurrentRegion;
|
std::string mCurrentRegion;
|
||||||
|
|
|
@ -2359,6 +2359,8 @@ namespace MWWorld
|
||||||
model = Misc::ResourceHelpers::correctActorModelPath(model, mResourceSystem->getVFS());
|
model = Misc::ResourceHelpers::correctActorModelPath(model, mResourceSystem->getVFS());
|
||||||
mPhysics->remove(getPlayerPtr());
|
mPhysics->remove(getPlayerPtr());
|
||||||
mPhysics->addActor(getPlayerPtr(), model);
|
mPhysics->addActor(getPlayerPtr(), model);
|
||||||
|
|
||||||
|
applyLoopingParticles(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
int World::canRest ()
|
int World::canRest ()
|
||||||
|
@ -3019,6 +3021,19 @@ namespace MWWorld
|
||||||
mProjectileManager->launchMagicBolt(spellId, caster, fallbackDirection);
|
mProjectileManager->launchMagicBolt(spellId, caster, fallbackDirection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void World::applyLoopingParticles(const MWWorld::Ptr& ptr)
|
||||||
|
{
|
||||||
|
const MWWorld::Class &cls = ptr.getClass();
|
||||||
|
if (cls.isActor())
|
||||||
|
{
|
||||||
|
MWMechanics::ApplyLoopingParticlesVisitor visitor(ptr);
|
||||||
|
cls.getCreatureStats(ptr).getActiveSpells().visitEffectSources(visitor);
|
||||||
|
cls.getCreatureStats(ptr).getSpells().visitEffectSources(visitor);
|
||||||
|
if (cls.hasInventoryStore(ptr))
|
||||||
|
cls.getInventoryStore(ptr).visitEffectSources(visitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const std::vector<std::string>& World::getContentFiles() const
|
const std::vector<std::string>& World::getContentFiles() const
|
||||||
{
|
{
|
||||||
return mContentFiles;
|
return mContentFiles;
|
||||||
|
@ -3035,11 +3050,17 @@ namespace MWWorld
|
||||||
MWBase::Environment::get().getMechanicsManager()->updateMagicEffects(actor);
|
MWBase::Environment::get().getMechanicsManager()->updateMagicEffects(actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool World::isDark() const
|
bool World::useTorches() const
|
||||||
{
|
{
|
||||||
|
// If we are in exterior, check the weather manager.
|
||||||
|
// In interiors there are no precipitations and sun, so check the ambient
|
||||||
|
// Looks like pseudo-exteriors considered as interiors in this case
|
||||||
MWWorld::CellStore* cell = mPlayer->getPlayer().getCell();
|
MWWorld::CellStore* cell = mPlayer->getPlayer().getCell();
|
||||||
if (cell->isExterior())
|
if (cell->isExterior())
|
||||||
return mWeatherManager->isDark();
|
{
|
||||||
|
float hour = getTimeStamp().getHour();
|
||||||
|
return mWeatherManager->useTorches(hour);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint32_t ambient = cell->getCell()->mAmbi.mAmbient;
|
uint32_t ambient = cell->getCell()->mAmbi.mAmbient;
|
||||||
|
@ -3200,13 +3221,17 @@ namespace MWWorld
|
||||||
|
|
||||||
void World::updateWeather(float duration, bool paused)
|
void World::updateWeather(float duration, bool paused)
|
||||||
{
|
{
|
||||||
|
bool isExterior = isCellExterior() || isCellQuasiExterior();
|
||||||
if (mPlayer->wasTeleported())
|
if (mPlayer->wasTeleported())
|
||||||
{
|
{
|
||||||
mPlayer->setTeleported(false);
|
mPlayer->setTeleported(false);
|
||||||
mWeatherManager->playerTeleported();
|
|
||||||
|
const std::string playerRegion = Misc::StringUtils::lowerCase(getPlayerPtr().getCell()->getCell()->mRegion);
|
||||||
|
mWeatherManager->playerTeleported(playerRegion, isExterior);
|
||||||
}
|
}
|
||||||
|
|
||||||
mWeatherManager->update(duration, paused);
|
const TimeStamp time = getTimeStamp();
|
||||||
|
mWeatherManager->update(duration, paused, time, isExterior);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AddDetectedReferenceVisitor
|
struct AddDetectedReferenceVisitor
|
||||||
|
|
|
@ -658,12 +658,13 @@ namespace MWWorld
|
||||||
void launchProjectile (MWWorld::Ptr actor, MWWorld::ConstPtr projectile,
|
void launchProjectile (MWWorld::Ptr actor, MWWorld::ConstPtr projectile,
|
||||||
const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr bow, float speed, float attackStrength) override;
|
const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr bow, float speed, float attackStrength) override;
|
||||||
|
|
||||||
|
void applyLoopingParticles(const MWWorld::Ptr& ptr);
|
||||||
|
|
||||||
const std::vector<std::string>& getContentFiles() const override;
|
const std::vector<std::string>& getContentFiles() const override;
|
||||||
|
|
||||||
void breakInvisibility (const MWWorld::Ptr& actor) override;
|
void breakInvisibility (const MWWorld::Ptr& actor) override;
|
||||||
// Are we in an exterior or pseudo-exterior cell and it's night?
|
|
||||||
bool isDark() const override;
|
// Allow NPCs to use torches?
|
||||||
|
bool useTorches() const override;
|
||||||
|
|
||||||
bool findInteriorPositionInWorldSpace(const MWWorld::CellStore* cell, osg::Vec3f& result) override;
|
bool findInteriorPositionInWorldSpace(const MWWorld::CellStore* cell, osg::Vec3f& result) override;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
find_package(GTest REQUIRED)
|
find_package(GTest REQUIRED)
|
||||||
|
|
||||||
if (GTEST_FOUND)
|
if (GTEST_FOUND)
|
||||||
include_directories(${GTEST_INCLUDE_DIRS})
|
include_directories(SYSTEM ${GTEST_INCLUDE_DIRS})
|
||||||
|
|
||||||
file(GLOB UNITTEST_SRC_FILES
|
file(GLOB UNITTEST_SRC_FILES
|
||||||
../openmw/mwworld/store.cpp
|
../openmw/mwworld/store.cpp
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "fallback.hpp"
|
#include "fallback.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,6 +19,7 @@ namespace Fallback
|
||||||
std::map<std::string,std::string>::const_iterator it;
|
std::map<std::string,std::string>::const_iterator it;
|
||||||
if((it = mFallbackMap.find(fall)) == mFallbackMap.end())
|
if((it = mFallbackMap.find(fall)) == mFallbackMap.end())
|
||||||
{
|
{
|
||||||
|
std::cerr << "Warning: fallback value " << fall << " not found." << std::endl;
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
return it->second;
|
return it->second;
|
||||||
|
@ -25,7 +28,7 @@ namespace Fallback
|
||||||
float Map::getFallbackFloat(const std::string& fall) const
|
float Map::getFallbackFloat(const std::string& fall) const
|
||||||
{
|
{
|
||||||
std::string fallback=getFallbackString(fall);
|
std::string fallback=getFallbackString(fall);
|
||||||
if(fallback.empty())
|
if (fallback.empty())
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
return boost::lexical_cast<float>(fallback);
|
return boost::lexical_cast<float>(fallback);
|
||||||
|
@ -34,7 +37,7 @@ namespace Fallback
|
||||||
int Map::getFallbackInt(const std::string& fall) const
|
int Map::getFallbackInt(const std::string& fall) const
|
||||||
{
|
{
|
||||||
std::string fallback=getFallbackString(fall);
|
std::string fallback=getFallbackString(fall);
|
||||||
if(fallback.empty())
|
if (fallback.empty())
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
return std::stoi(fallback);
|
return std::stoi(fallback);
|
||||||
|
@ -43,7 +46,7 @@ namespace Fallback
|
||||||
bool Map::getFallbackBool(const std::string& fall) const
|
bool Map::getFallbackBool(const std::string& fall) const
|
||||||
{
|
{
|
||||||
std::string fallback=getFallbackString(fall);
|
std::string fallback=getFallbackString(fall);
|
||||||
if(fallback.empty())
|
if (fallback.empty())
|
||||||
return false;
|
return false;
|
||||||
else
|
else
|
||||||
return stob(fallback);
|
return stob(fallback);
|
||||||
|
@ -52,8 +55,8 @@ namespace Fallback
|
||||||
osg::Vec4f Map::getFallbackColour(const std::string& fall) const
|
osg::Vec4f Map::getFallbackColour(const std::string& fall) const
|
||||||
{
|
{
|
||||||
std::string sum=getFallbackString(fall);
|
std::string sum=getFallbackString(fall);
|
||||||
if(sum.empty())
|
if (sum.empty())
|
||||||
return osg::Vec4f(0.f,0.f,0.f,1.f);
|
return osg::Vec4f(0.5f,0.5f,0.5f,1.f);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::string ret[3];
|
std::string ret[3];
|
||||||
|
|
|
@ -85,6 +85,14 @@ namespace mwmp
|
||||||
Request
|
Request
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class ContainerSubAction : uint8_t
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Drag,
|
||||||
|
Drop,
|
||||||
|
TakeAll
|
||||||
|
};
|
||||||
|
|
||||||
RakNet::RakNetGUID guid;
|
RakNet::RakNetGUID guid;
|
||||||
|
|
||||||
std::vector<WorldObject> worldObjects;
|
std::vector<WorldObject> worldObjects;
|
||||||
|
@ -93,6 +101,7 @@ namespace mwmp
|
||||||
std::string consoleCommand;
|
std::string consoleCommand;
|
||||||
|
|
||||||
Action action;
|
Action action;
|
||||||
|
ContainerSubAction containerSubAction;
|
||||||
|
|
||||||
bool isValid;
|
bool isValid;
|
||||||
};
|
};
|
||||||
|
|
|
@ -303,6 +303,7 @@ namespace mwmp
|
||||||
} weather;
|
} weather;
|
||||||
|
|
||||||
int difficulty;
|
int difficulty;
|
||||||
|
int enforcedLogLevel;
|
||||||
float physicsFramerate;
|
float physicsFramerate;
|
||||||
bool consoleAllowed;
|
bool consoleAllowed;
|
||||||
bool bedRestAllowed;
|
bool bedRestAllowed;
|
||||||
|
|
|
@ -72,6 +72,11 @@ public:
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int GetLevel()
|
||||||
|
{
|
||||||
|
return Log::Get().logLevel;
|
||||||
|
}
|
||||||
|
|
||||||
void SetLevel(int level)
|
void SetLevel(int level)
|
||||||
{
|
{
|
||||||
logLevel = level;
|
logLevel = level;
|
||||||
|
|
|
@ -14,9 +14,10 @@ void PacketGameSettings::Packet(RakNet::BitStream *bs, bool send)
|
||||||
PlayerPacket::Packet(bs, send);
|
PlayerPacket::Packet(bs, send);
|
||||||
|
|
||||||
RW(player->difficulty, send);
|
RW(player->difficulty, send);
|
||||||
RW(player->physicsFramerate, send);
|
|
||||||
RW(player->consoleAllowed, send);
|
RW(player->consoleAllowed, send);
|
||||||
RW(player->bedRestAllowed, send);
|
RW(player->bedRestAllowed, send);
|
||||||
RW(player->wildernessRestAllowed, send);
|
RW(player->wildernessRestAllowed, send);
|
||||||
RW(player->waitAllowed, send);
|
RW(player->waitAllowed, send);
|
||||||
|
RW(player->enforcedLogLevel, send);
|
||||||
|
RW(player->physicsFramerate, send);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ void PacketContainer::Packet(RakNet::BitStream *bs, bool send)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
RW(event->action, send);
|
RW(event->action, send);
|
||||||
|
RW(event->containerSubAction, send);
|
||||||
|
|
||||||
for (auto &&worldObject : event->worldObjects)
|
for (auto &&worldObject : event->worldObjects)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue