1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-20 00:23:51 +00:00
openmw-tes3mp/apps/openmw/mwgui/container.cpp

392 lines
13 KiB
C++
Raw Normal View History

2012-04-15 15:52:39 +00:00
#include "container.hpp"
2015-01-10 01:50:43 +00:00
#include <MyGUI_InputManager.h>
#include <MyGUI_Button.h>
/*
Start of tes3mp addition
Include additional headers for multiplayer purposes
*/
#include <components/openmw-mp/Log.hpp>
2016-12-16 09:27:19 +00:00
#include "../mwmp/Main.hpp"
#include "../mwmp/Networking.hpp"
#include "../mwmp/WorldEvent.hpp"
#include "../mwmp/CellController.hpp"
/*
End of tes3mp addition
*/
2015-01-10 01:50:43 +00:00
2012-05-11 09:52:07 +00:00
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/dialoguemanager.hpp"
2014-01-07 18:49:16 +00:00
#include "../mwbase/mechanicsmanager.hpp"
2013-05-11 16:38:27 +00:00
#include "../mwworld/class.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwmechanics/creaturestats.hpp"
#include "countdialog.hpp"
#include "inventorywindow.hpp"
2012-04-15 15:52:39 +00:00
2013-05-11 16:38:27 +00:00
#include "itemview.hpp"
#include "itemwidget.hpp"
2013-05-11 16:38:27 +00:00
#include "inventoryitemmodel.hpp"
#include "containeritemmodel.hpp"
2013-05-11 16:38:27 +00:00
#include "sortfilteritemmodel.hpp"
#include "pickpocketitemmodel.hpp"
#include "draganddrop.hpp"
2013-05-11 16:38:27 +00:00
2013-04-17 22:56:48 +00:00
namespace MWGui
2012-04-15 15:52:39 +00:00
{
2012-05-12 20:44:12 +00:00
2013-05-11 16:38:27 +00:00
ContainerWindow::ContainerWindow(DragAndDrop* dragAndDrop)
: WindowBase("openmw_container_window.layout")
, mDragAndDrop(dragAndDrop)
, mSortModel(NULL)
, mModel(NULL)
, mSelectedItem(-1)
{
2013-05-11 16:38:27 +00:00
getWidget(mDisposeCorpseButton, "DisposeCorpseButton");
getWidget(mTakeButton, "TakeButton");
getWidget(mCloseButton, "CloseButton");
2013-05-11 16:38:27 +00:00
getWidget(mItemView, "ItemView");
mItemView->eventBackgroundClicked += MyGUI::newDelegate(this, &ContainerWindow::onBackgroundSelected);
mItemView->eventItemClicked += MyGUI::newDelegate(this, &ContainerWindow::onItemSelected);
2013-03-16 18:00:14 +00:00
2013-05-11 16:38:27 +00:00
mDisposeCorpseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onDisposeCorpseButtonClicked);
mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onCloseButtonClicked);
mTakeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onTakeAllButtonClicked);
2013-03-16 18:00:14 +00:00
2013-05-11 16:38:27 +00:00
setCoord(200,0,600,300);
}
2013-03-16 18:00:14 +00:00
2013-05-11 16:38:27 +00:00
void ContainerWindow::onItemSelected(int index)
{
if (mDragAndDrop->mIsOnDragAndDrop && mModel)
{
dropItem();
return;
}
const ItemStack& item = mSortModel->getItem(index);
// We can't take a conjured item from a container (some NPC we're pickpocketing, a box, etc)
if (item.mFlags & ItemStack::Flag_Bound)
{
MWBase::Environment::get().getWindowManager()->messageBox("#{sContentsMessage1}");
return;
}
2013-05-11 16:38:27 +00:00
MWWorld::Ptr object = item.mBase;
int count = item.mCount;
bool shift = MyGUI::InputManager::getInstance().isShiftPressed();
if (MyGUI::InputManager::getInstance().isControlPressed())
count = 1;
2013-05-11 16:38:27 +00:00
mSelectedItem = mSortModel->mapToSource(index);
2012-04-15 15:52:39 +00:00
2013-05-11 16:38:27 +00:00
if (count > 1 && !shift)
2013-04-17 22:56:48 +00:00
{
2013-05-11 16:38:27 +00:00
CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog();
dialog->openCountDialog(object.getClass().getName(object), "#{sTake}", count);
2013-05-11 16:38:27 +00:00
dialog->eventOkClicked.clear();
dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerWindow::dragItem);
2012-05-06 09:04:07 +00:00
}
2013-04-17 22:56:48 +00:00
else
2013-05-11 16:38:27 +00:00
dragItem (NULL, count);
}
2013-05-11 16:38:27 +00:00
void ContainerWindow::dragItem(MyGUI::Widget* sender, int count)
{
if (!onTakeItem(mModel->getItem(mSelectedItem), count))
return;
/*
Start of tes3mp addition
Send an ID_CONTAINER packet every time an item starts being dragged
from a container
*/
mwmp::WorldEvent *worldEvent = mwmp::Main::get().getNetworking()->getWorldEvent();
worldEvent->reset();
worldEvent->cell = *mPtr.getCell()->getCell();
worldEvent->action = mwmp::BaseEvent::REMOVE;
mwmp::WorldObject worldObject;
worldObject.refId = mPtr.getCellRef().getRefId();
worldObject.refNumIndex = mPtr.getCellRef().getRefNum().mIndex;
worldObject.mpNum = mPtr.getCellRef().getMpNum();
MWWorld::Ptr itemPtr = mModel->getItem(mSelectedItem).mBase;
mwmp::ContainerItem containerItem;
containerItem.refId =itemPtr.getCellRef().getRefId();
containerItem.count = itemPtr.getRefData().getCount();
containerItem.charge = itemPtr.getCellRef().getCharge();
containerItem.actionCount = count;
worldObject.containerItems.push_back(containerItem);
worldEvent->addObject(worldObject);
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\n- cell: %s\n- item: %s, %i",
worldObject.refId.c_str(), worldObject.refNumIndex, worldEvent->cell.getDescription().c_str(),
containerItem.refId.c_str(), containerItem.count);
/*
End of tes3mp addition
*/
2013-05-11 16:38:27 +00:00
mDragAndDrop->startDrag(mSelectedItem, mSortModel, mModel, mItemView, count);
}
2013-05-11 16:38:27 +00:00
void ContainerWindow::dropItem()
2013-04-17 22:56:48 +00:00
{
2017-10-04 18:37:08 +00:00
bool success = mModel->onDropItem(mDragAndDrop->mItem.mBase, mDragAndDrop->mDraggedCount);
2012-05-12 20:44:12 +00:00
/*
Start of tes3mp addition
Send an ID_CONTAINER packet every time an item is dropped in a container
*/
if (success)
{
mwmp::WorldEvent *worldEvent = mwmp::Main::get().getNetworking()->getWorldEvent();
worldEvent->reset();
worldEvent->cell = *mPtr.getCell()->getCell();
worldEvent->action = mwmp::BaseEvent::ADD;
mwmp::WorldObject worldObject;
worldObject.refId = mPtr.getCellRef().getRefId();
worldObject.refNumIndex = mPtr.getCellRef().getRefNum().mIndex;
worldObject.mpNum = mPtr.getCellRef().getMpNum();
MWWorld::Ptr itemPtr = mDragAndDrop->mItem.mBase;
mwmp::ContainerItem containerItem;
containerItem.refId = itemPtr.getCellRef().getRefId();
// Make sure we get the drag and drop count, not the count of the original item
containerItem.count = mDragAndDrop->mDraggedCount;
containerItem.charge = itemPtr.getCellRef().getCharge();
worldObject.containerItems.push_back(containerItem);
worldEvent->addObject(worldObject);
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\n- cell: %s\n- item: %s, %i",
worldObject.refId.c_str(), worldObject.refNumIndex, worldEvent->cell.getDescription().c_str(),
containerItem.refId.c_str(), containerItem.count);
}
/*
End of tes3mp addition
*/
2017-10-04 18:37:08 +00:00
if (success)
mDragAndDrop->drop(mModel, mItemView);
2013-04-17 22:56:48 +00:00
}
2012-05-12 20:44:12 +00:00
2013-05-11 16:38:27 +00:00
void ContainerWindow::onBackgroundSelected()
2012-04-30 11:01:18 +00:00
{
if (mDragAndDrop->mIsOnDragAndDrop && mModel)
2013-05-11 16:38:27 +00:00
dropItem();
2012-04-30 11:01:18 +00:00
}
2012-04-15 15:52:39 +00:00
void ContainerWindow::setPtr(const MWWorld::Ptr& container)
2012-05-11 14:58:07 +00:00
{
/*
Start of tes3mp addition
Mark this container as open for multiplayer logic purposes
*/
mwmp::Main::get().getCellController()->openContainer(container);
/*
End of tes3mp addition
*/
2016-12-16 09:27:19 +00:00
2013-05-11 16:38:27 +00:00
mPtr = container;
2012-05-12 12:01:59 +00:00
bool loot = mPtr.getClass().isActor() && mPtr.getClass().getCreatureStats(mPtr).isDead();
if (mPtr.getClass().hasInventoryStore(mPtr))
2013-04-17 22:56:48 +00:00
{
if (mPtr.getClass().isNpc() && !loot)
{
// we are stealing stuff
2017-10-04 17:25:22 +00:00
mModel = new PickpocketItemModel(mPtr, new InventoryItemModel(container),
!mPtr.getClass().getCreatureStats(mPtr).getKnockedDown());
}
else
mModel = new InventoryItemModel(container);
2013-04-17 22:56:48 +00:00
}
2013-05-11 16:38:27 +00:00
else
{
mModel = new ContainerItemModel(container);
}
2013-04-17 22:56:48 +00:00
mDisposeCorpseButton->setVisible(loot);
2012-05-12 12:01:59 +00:00
2013-05-11 16:38:27 +00:00
mSortModel = new SortFilterItemModel(mModel);
mItemView->setModel (mSortModel);
mItemView->resetScrollBars();
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCloseButton);
2014-01-10 23:24:21 +00:00
setTitle(container.getClass().getName(container));
2013-04-17 22:56:48 +00:00
}
void ContainerWindow::resetReference()
{
ReferenceInterface::resetReference();
mItemView->setModel(NULL);
mModel = NULL;
mSortModel = NULL;
}
void ContainerWindow::onClose()
{
/*
Start of tes3mp addition
Mark this container as closed for multiplayer logic purposes
*/
mwmp::Main::get().getCellController()->closeContainer(mPtr);
/*
End of tes3mp addition
*/
WindowBase::onClose();
if (mModel)
mModel->onClose();
}
void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender)
{
2017-09-23 10:18:39 +00:00
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
}
2013-04-17 22:56:48 +00:00
void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender)
{
if(mDragAndDrop != NULL && mDragAndDrop->mIsOnDragAndDrop)
return;
// transfer everything into the player's inventory
ItemModel* playerModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getModel();
mModel->update();
// unequip all items to avoid unequipping/reequipping
if (mPtr.getClass().hasInventoryStore(mPtr))
2013-04-17 22:56:48 +00:00
{
MWWorld::InventoryStore& invStore = mPtr.getClass().getInventoryStore(mPtr);
2013-05-11 16:38:27 +00:00
for (size_t i=0; i<mModel->getItemCount(); ++i)
2012-05-16 12:30:02 +00:00
{
const ItemStack& item = mModel->getItem(i);
if (invStore.isEquipped(item.mBase) == false)
continue;
invStore.unequipItem(item.mBase, mPtr);
}
}
mModel->update();
for (size_t i=0; i<mModel->getItemCount(); ++i)
{
if (i==0)
{
// play the sound of the first object
MWWorld::Ptr item = mModel->getItem(i).mBase;
std::string sound = item.getClass().getUpSoundId(item);
MWBase::Environment::get().getWindowManager()->playSound(sound);
2013-04-17 22:56:48 +00:00
}
const ItemStack& item = mModel->getItem(i);
if (!onTakeItem(item, item.mCount))
break;
mModel->moveItem(item, item.mCount, playerModel);
2013-04-17 22:56:48 +00:00
}
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::SET;
mwmp::WorldObject worldObject;
worldObject.refId = mPtr.getCellRef().getRefId();
worldObject.refNumIndex = mPtr.getCellRef().getRefNum().mIndex;
worldObject.mpNum = mPtr.getCellRef().getMpNum();
worldEvent->addObject(worldObject);
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\n- cell: %s",
worldObject.refId.c_str(), worldObject.refNumIndex, worldEvent->cell.getDescription().c_str());
/*
End of tes3mp addition
*/
2012-05-11 14:58:07 +00:00
}
2013-04-17 22:56:48 +00:00
void ContainerWindow::onDisposeCorpseButtonClicked(MyGUI::Widget *sender)
{
2013-04-17 22:56:48 +00:00
if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop)
{
onTakeAllButtonClicked(mTakeButton);
/*
Start of tes3mp addition
Send an ID_OBJECT_DELETE packet every time a corpse is disposed of
*/
if (!mPtr.getClass().isPersistent(mPtr))
{
mwmp::WorldEvent *worldEvent = mwmp::Main::get().getNetworking()->getWorldEvent();
worldEvent->reset();
worldEvent->addObjectDelete(mPtr);
worldEvent->sendObjectDelete();
}
/*
End of tes3mp addition
*/
if (mPtr.getClass().isPersistent(mPtr))
2013-05-16 16:50:26 +00:00
MWBase::Environment::get().getWindowManager()->messageBox("#{sDisposeCorpseFail}");
else
2013-04-17 22:56:48 +00:00
MWBase::Environment::get().getWorld()->deleteObject(mPtr);
2013-04-17 22:56:48 +00:00
mPtr = MWWorld::Ptr();
}
}
void ContainerWindow::onReferenceUnavailable()
{
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
}
bool ContainerWindow::onTakeItem(const ItemStack &item, int count)
{
2017-10-04 17:25:22 +00:00
return mModel->onTakeItem(item.mBase, count);
}
}