Added merchant repair feature

This commit is contained in:
scrawl 2013-03-22 14:13:10 +01:00
parent 8e2f9f5186
commit 20774f8f81
16 changed files with 244 additions and 21 deletions

View file

@ -31,6 +31,7 @@ add_openmw_dir (mwgui
confirmationdialog alchemywindow referenceinterface spellwindow mainmenu quickkeysmenu confirmationdialog alchemywindow referenceinterface spellwindow mainmenu quickkeysmenu
itemselection spellbuyingwindow loadingscreen levelupdialog waitdialog spellcreationdialog itemselection spellbuyingwindow loadingscreen levelupdialog waitdialog spellcreationdialog
enchantingdialog trainingwindow travelwindow imagebutton exposedwindow cursor spellicons enchantingdialog trainingwindow travelwindow imagebutton exposedwindow cursor spellicons
merchantrepair
) )
add_openmw_dir (mwdialogue add_openmw_dir (mwdialogue

View file

@ -238,6 +238,7 @@ namespace MWBase
virtual void startSpellMaking(MWWorld::Ptr actor) = 0; virtual void startSpellMaking(MWWorld::Ptr actor) = 0;
virtual void startEnchanting(MWWorld::Ptr actor) = 0; virtual void startEnchanting(MWWorld::Ptr actor) = 0;
virtual void startTraining(MWWorld::Ptr actor) = 0; virtual void startTraining(MWWorld::Ptr actor) = 0;
virtual void startRepair(MWWorld::Ptr actor) = 0;
virtual void changePointer (const std::string& name) = 0; virtual void changePointer (const std::string& name) = 0;

View file

@ -367,6 +367,9 @@ namespace MWDialogue
if (services & ESM::NPC::Enchanting) if (services & ESM::NPC::Enchanting)
windowServices |= MWGui::DialogueWindow::Service_Enchant; windowServices |= MWGui::DialogueWindow::Service_Enchant;
if (services & ESM::NPC::Repair)
windowServices |= MWGui::DialogueWindow::Service_Repair;
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
win->setServices (windowServices); win->setServices (windowServices);

View file

@ -280,6 +280,11 @@ void DialogueWindow::onSelectTopic(const std::string& topic, int id)
mWindowManager.pushGuiMode(GM_Training); mWindowManager.pushGuiMode(GM_Training);
mWindowManager.startTraining (mPtr); mWindowManager.startTraining (mPtr);
} }
else if (topic == gmst.find("sRepair")->getString())
{
mWindowManager.pushGuiMode(GM_MerchantRepair);
mWindowManager.startRepair (mPtr);
}
} }
} }
} }
@ -327,6 +332,9 @@ void DialogueWindow::setKeywords(std::list<std::string> keyWords)
if (mServices & Service_Training) if (mServices & Service_Training)
mTopicsList->addItem(gmst.find("sServiceTrainingTitle")->getString()); mTopicsList->addItem(gmst.find("sServiceTrainingTitle")->getString());
if (mServices & Service_Repair)
mTopicsList->addItem(gmst.find("sRepair")->getString());
if (anyService || mPtr.getTypeName() == typeid(ESM::NPC).name()) if (anyService || mPtr.getTypeName() == typeid(ESM::NPC).name())
mTopicsList->addSeparator(); mTopicsList->addSeparator();

View file

@ -81,7 +81,8 @@ namespace MWGui
Service_CreateSpells = 0x04, Service_CreateSpells = 0x04,
Service_Enchant = 0x08, Service_Enchant = 0x08,
Service_Training = 0x10, Service_Training = 0x10,
Service_Travel = 0x20 Service_Travel = 0x20,
Service_Repair = 0x40
}; };
protected: protected:

View file

@ -0,0 +1,132 @@
#include "merchantrepair.hpp"
#include <boost/lexical_cast.hpp>
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwworld/class.hpp"
#include "list.hpp"
#include "inventorywindow.hpp"
#include "tradewindow.hpp"
namespace MWGui
{
MerchantRepair::MerchantRepair(MWBase::WindowManager &parWindowManager)
: WindowBase("openmw_merchantrepair.layout", parWindowManager)
{
getWidget(mList, "RepairView");
getWidget(mOkButton, "OkButton");
getWidget(mGoldLabel, "PlayerGold");
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MerchantRepair::onOkButtonClick);
}
void MerchantRepair::startRepair(const MWWorld::Ptr &actor)
{
mActor = actor;
while (mList->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(mList->getChildAt(0));
int currentY = 0;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player);
for (MWWorld::ContainerStoreIterator iter (store.begin());
iter!=store.end(); ++iter)
{
if (MWWorld::Class::get(*iter).hasItemHealth(*iter))
{
int maxDurability = MWWorld::Class::get(*iter).getItemMaxHealth(*iter);
int durability = (iter->getCellRef().mCharge == -1) ? maxDurability : iter->getCellRef().mCharge;
if (maxDurability == durability)
continue;
int basePrice = MWWorld::Class::get(*iter).getValue(*iter);
float fRepairMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("fRepairMult")->getFloat();
float p = std::max(1, basePrice);
float r = std::max(1, static_cast<int>(maxDurability / p));
int x = ((maxDurability - durability) / r);
x = (fRepairMult * x);
int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mActor, x, true);
std::string name = MWWorld::Class::get(*iter).getName(*iter)
+ " - " + boost::lexical_cast<std::string>(price)
+ MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("sgp")->getString();;
MyGUI::Button* button =
mList->createWidget<MyGUI::Button>(
(price>mWindowManager.getInventoryWindow()->getPlayerGold()) ? "SandTextGreyedOut" : "SandTextButton",
0,
currentY,
0,
18,
MyGUI::Align::Default
);
currentY += 18;
button->setEnabled(price<=mWindowManager.getInventoryWindow()->getPlayerGold());
button->setUserString("Price", boost::lexical_cast<std::string>(price));
button->setUserData(*iter);
button->setCaptionWithReplacing(name);
button->setSize(button->getTextSize().width,18);
button->eventMouseWheel += MyGUI::newDelegate(this, &MerchantRepair::onMouseWheel);
button->setUserString("ToolTipType", "ItemPtr");
button->eventMouseButtonClick += MyGUI::newDelegate(this, &MerchantRepair::onRepairButtonClick);
}
}
mList->setCanvasSize (MyGUI::IntSize(mList->getWidth(), std::max(mList->getHeight(), currentY)));
mGoldLabel->setCaptionWithReplacing("#{sGold}: "
+ boost::lexical_cast<std::string>(mWindowManager.getInventoryWindow()->getPlayerGold()));
}
void MerchantRepair::onMouseWheel(MyGUI::Widget* _sender, int _rel)
{
if (mList->getViewOffset().top + _rel*0.3 > 0)
mList->setViewOffset(MyGUI::IntPoint(0, 0));
else
mList->setViewOffset(MyGUI::IntPoint(0, mList->getViewOffset().top + _rel*0.3));
}
void MerchantRepair::open()
{
center();
}
void MerchantRepair::onRepairButtonClick(MyGUI::Widget *sender)
{
// repair
MWWorld::Ptr item = *sender->getUserData<MWWorld::Ptr>();
item.getCellRef().mCharge = MWWorld::Class::get(item).getItemMaxHealth(item);
MWBase::Environment::get().getSoundManager()->playSound("Repair",1,1);
int price = boost::lexical_cast<int>(sender->getUserString("Price"));
mWindowManager.getTradeWindow()->addOrRemoveGold(-price);
startRepair(mActor);
}
void MerchantRepair::onOkButtonClick(MyGUI::Widget *sender)
{
mWindowManager.removeGuiMode(GM_MerchantRepair);
}
}

View file

@ -0,0 +1,37 @@
#ifndef OPENMW_MWGUI_MERCHANTREPAIR_H
#define OPENMW_MWGUI_MERCHANTREPAIR_H
#include "window_base.hpp"
#include "../mwworld/ptr.hpp"
namespace MWGui
{
class MerchantRepair : public WindowBase
{
public:
MerchantRepair(MWBase::WindowManager &parWindowManager);
virtual void open();
void startRepair(const MWWorld::Ptr& actor);
private:
MyGUI::ScrollView* mList;
MyGUI::Button* mOkButton;
MyGUI::TextBox* mGoldLabel;
MWWorld::Ptr mActor;
protected:
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
void onRepairButtonClick(MyGUI::Widget* sender);
void onOkButtonClick(MyGUI::Widget* sender);
};
}
#endif

View file

@ -16,6 +16,7 @@ namespace MWGui
GM_Scroll, // Read scroll GM_Scroll, // Read scroll
GM_Book, // Read book GM_Book, // Read book
GM_Alchemy, // Make potions GM_Alchemy, // Make potions
GM_Repair,
GM_Dialogue, // NPC interaction GM_Dialogue, // NPC interaction
GM_Barter, GM_Barter,
@ -26,6 +27,7 @@ namespace MWGui
GM_SpellCreation, GM_SpellCreation,
GM_Enchanting, GM_Enchanting,
GM_Training, GM_Training,
GM_MerchantRepair,
GM_Levelup, GM_Levelup,

View file

@ -32,20 +32,9 @@ namespace MWGui
getWidget(mCancelButton, "CancelButton"); getWidget(mCancelButton, "CancelButton");
getWidget(mPlayerGold, "PlayerGold"); getWidget(mPlayerGold, "PlayerGold");
getWidget(mSelect, "Select");
getWidget(mSpells, "Spells");
getWidget(mSpellsView, "SpellsView"); getWidget(mSpellsView, "SpellsView");
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellBuyingWindow::onCancelButtonClicked); mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellBuyingWindow::onCancelButtonClicked);
mSpells->setCoord(450/2-mSpells->getTextSize().width/2,
mSpells->getTop(),
mSpells->getTextSize().width,
mSpells->getHeight());
mSelect->setCoord(8,
mSelect->getTop(),
mSelect->getTextSize().width,
mSelect->getHeight());
} }
void SpellBuyingWindow::addSpell(const std::string& spellId) void SpellBuyingWindow::addSpell(const std::string& spellId)

View file

@ -28,8 +28,6 @@ namespace MWGui
protected: protected:
MyGUI::Button* mCancelButton; MyGUI::Button* mCancelButton;
MyGUI::TextBox* mPlayerGold; MyGUI::TextBox* mPlayerGold;
MyGUI::TextBox* mSpells;
MyGUI::TextBox* mSelect;
MyGUI::ScrollView* mSpellsView; MyGUI::ScrollView* mSpellsView;

View file

@ -55,6 +55,7 @@
#include "exposedwindow.hpp" #include "exposedwindow.hpp"
#include "cursor.hpp" #include "cursor.hpp"
#include "spellicons.hpp" #include "spellicons.hpp"
#include "merchantrepair.hpp"
using namespace MWGui; using namespace MWGui;
@ -90,6 +91,7 @@ WindowManager::WindowManager(
, mSpellCreationDialog(NULL) , mSpellCreationDialog(NULL)
, mEnchantingDialog(NULL) , mEnchantingDialog(NULL)
, mTrainingWindow(NULL) , mTrainingWindow(NULL)
, mMerchantRepair(NULL)
, mPlayerName() , mPlayerName()
, mPlayerRaceId() , mPlayerRaceId()
, mPlayerAttributes() , mPlayerAttributes()
@ -180,6 +182,7 @@ WindowManager::WindowManager(
mSpellCreationDialog = new SpellCreationDialog(*this); mSpellCreationDialog = new SpellCreationDialog(*this);
mEnchantingDialog = new EnchantingDialog(*this); mEnchantingDialog = new EnchantingDialog(*this);
mTrainingWindow = new TrainingWindow(*this); mTrainingWindow = new TrainingWindow(*this);
mMerchantRepair = new MerchantRepair(*this);
mLoadingScreen = new LoadingScreen(mRendering->getScene (), mRendering->getWindow (), *this); mLoadingScreen = new LoadingScreen(mRendering->getScene (), mRendering->getWindow (), *this);
mLoadingScreen->onResChange (w,h); mLoadingScreen->onResChange (w,h);
@ -245,6 +248,7 @@ WindowManager::~WindowManager()
delete mTrainingWindow; delete mTrainingWindow;
delete mCountDialog; delete mCountDialog;
delete mQuickKeysMenu; delete mQuickKeysMenu;
delete mMerchantRepair;
delete mCursor; delete mCursor;
cleanupGarbage(); cleanupGarbage();
@ -303,6 +307,7 @@ void WindowManager::updateVisible()
mSpellCreationDialog->setVisible(false); mSpellCreationDialog->setVisible(false);
mEnchantingDialog->setVisible(false); mEnchantingDialog->setVisible(false);
mTrainingWindow->setVisible(false); mTrainingWindow->setVisible(false);
mMerchantRepair->setVisible(false);
mHud->setVisible(mHudEnabled); mHud->setVisible(mHudEnabled);
@ -428,6 +433,9 @@ void WindowManager::updateVisible()
case GM_Training: case GM_Training:
mTrainingWindow->setVisible(true); mTrainingWindow->setVisible(true);
break; break;
case GM_MerchantRepair:
mMerchantRepair->setVisible(true);
break;
case GM_InterMessageBox: case GM_InterMessageBox:
break; break;
case GM_Journal: case GM_Journal:
@ -1132,6 +1140,11 @@ void WindowManager::startTraining(MWWorld::Ptr actor)
mTrainingWindow->startTraining(actor); mTrainingWindow->startTraining(actor);
} }
void WindowManager::startRepair(MWWorld::Ptr actor)
{
mMerchantRepair->startRepair(actor);
}
const Translation::Storage& WindowManager::getTranslationDataStorage() const const Translation::Storage& WindowManager::getTranslationDataStorage() const
{ {
return mTranslationDataStorage; return mTranslationDataStorage;

View file

@ -74,6 +74,7 @@ namespace MWGui
class TrainingWindow; class TrainingWindow;
class Cursor; class Cursor;
class SpellIcons; class SpellIcons;
class MerchantRepair;
class WindowManager : public MWBase::WindowManager class WindowManager : public MWBase::WindowManager
{ {
@ -229,6 +230,7 @@ namespace MWGui
virtual void startSpellMaking(MWWorld::Ptr actor); virtual void startSpellMaking(MWWorld::Ptr actor);
virtual void startEnchanting(MWWorld::Ptr actor); virtual void startEnchanting(MWWorld::Ptr actor);
virtual void startTraining(MWWorld::Ptr actor); virtual void startTraining(MWWorld::Ptr actor);
virtual void startRepair(MWWorld::Ptr actor);
virtual void changePointer (const std::string& name); virtual void changePointer (const std::string& name);
@ -266,6 +268,8 @@ namespace MWGui
SpellCreationDialog* mSpellCreationDialog; SpellCreationDialog* mSpellCreationDialog;
EnchantingDialog* mEnchantingDialog; EnchantingDialog* mEnchantingDialog;
TrainingWindow* mTrainingWindow; TrainingWindow* mTrainingWindow;
MerchantRepair* mMerchantRepair;
Translation::Storage& mTranslationDataStorage; Translation::Storage& mTranslationDataStorage;
Cursor* mCursor; Cursor* mCursor;

View file

@ -62,13 +62,13 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::end()
bool MWWorld::ContainerStore::stacks(const Ptr& ptr1, const Ptr& ptr2) bool MWWorld::ContainerStore::stacks(const Ptr& ptr1, const Ptr& ptr2)
{ {
/// \todo add current weapon/armor health, remaining lockpick/repair uses, current enchantment charge here as soon as they are implemented /// \todo add current enchantment charge here when it is implemented
if ( ptr1.mCellRef->mRefID == ptr2.mCellRef->mRefID if ( ptr1.mCellRef->mRefID == ptr2.mCellRef->mRefID
&& MWWorld::Class::get(ptr1).getScript(ptr1) == "" // item with a script never stacks && MWWorld::Class::get(ptr1).getScript(ptr1) == "" // item with a script never stacks
&& MWWorld::Class::get(ptr1).getEnchantment(ptr1) == "" // item with enchantment never stacks (we could revisit this later, but for now it makes selecting items in the spell window much easier) && MWWorld::Class::get(ptr1).getEnchantment(ptr1) == "" // item with enchantment never stacks (we could revisit this later, but for now it makes selecting items in the spell window much easier)
&& ptr1.mCellRef->mOwner == ptr2.mCellRef->mOwner && ptr1.mCellRef->mOwner == ptr2.mCellRef->mOwner
&& ptr1.mCellRef->mSoul == ptr2.mCellRef->mSoul && ptr1.mCellRef->mSoul == ptr2.mCellRef->mSoul
&& ptr1.mCellRef->mCharge == ptr2.mCellRef->mCharge) && ptr1.mCellRef->mCharge == -1) // item that is already partly used up never stacks
return true; return true;
return false; return false;

View file

@ -78,6 +78,7 @@ set(MYGUI_FILES
openmw_trainingwindow.layout openmw_trainingwindow.layout
openmw_travel_window.layout openmw_travel_window.layout
openmw_persuasion_dialog.layout openmw_persuasion_dialog.layout
openmw_merchantrepair.layout
smallbars.png smallbars.png
DejaVuLGCSansMono.ttf DejaVuLGCSansMono.ttf
markers.png markers.png

View file

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<MyGUI type="Layout">
<Widget type="Window" skin="MW_Dialog" layer="Windows" position="0 0 418 248" name="_Main">
<Property key="Visible" value="false"/>
<Widget type="TextBox" skin="SandText" position="8 18 418 24" align="Right Top">
<Property key="TextAlign" value="Left"/>
<Property key="Caption" value="#{sRepairServiceTitle}"/>
</Widget>
<Widget type="TextBox" skin="NormalText" position="0 0 418 24" align="Right Top">
<Property key="TextAlign" value="Center"/>
<Property key="Caption" value="#{sServiceRepairTitle}"/>
</Widget>
<Widget type="Widget" skin="MW_Box" position="10 46 389 156" align="Left Stretch">
<Widget type="ScrollView" skin="MW_ScrollView" position="4 4 381 147" align="Left Top Stretch" name="RepairView">
<Property key="CanvasAlign" value="Left"/>
</Widget>
</Widget>
<Widget type="TextBox" skin="SandText" position="10 210 300 24" name="PlayerGold" align="Right Top">
<Property key="TextAlign" value="Left"/>
</Widget>
<Widget type="AutoSizedButton" skin="MW_Button" position="343 210 60 24" name="OkButton" align="Right Top">
<Property key="ExpandDirection" value="Left"/>
<Property key="Caption" value="#{sOK}"/>
</Widget>
</Widget>
</MyGUI>

View file

@ -5,13 +5,13 @@
<Property key="Visible" value="false"/> <Property key="Visible" value="false"/>
<Widget type="TextBox" skin="SandText" position="8 10 24 24" name="Select" align="Right Top"> <Widget type="TextBox" skin="SandText" position="8 10 450 18" align="Right Top">
<Property key="TextAlign" value="Right"/> <Property key="TextAlign" value="Left"/>
<Property key="Caption" value="#{sSpellServiceTitle}"/> <Property key="Caption" value="#{sSpellServiceTitle}"/>
</Widget> </Widget>
<Widget type="TextBox" skin="SandText" position="0 0 24 24" name="Spells" align="Right Top"> <Widget type="TextBox" skin="NormalText" position="0 0 450 18" align="Right Top">
<Property key="TextAlign" value="Right"/> <Property key="TextAlign" value="Center"/>
<Property key="Caption" value="#D8C09A#{sSpells}"/> <Property key="Caption" value="#{sSpells}"/>
</Widget> </Widget>