1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-15 21:19:57 +00:00
openmw-tes3mp/apps/openmw/mwgui/trainingwindow.cpp
David Cernat 3bd8aa82fe [General] Reduce inventory-sending hooks to just 2 in ContainerStore
Whenever an item is added to or removed from the player's ContainerStore, that player sends a PlayerInventory packet with just that addition or removal.

This eliminates all the unnecessary packet spam related to oversized PlayerInventory packets that had existed in one form or another since the initial implementation of inventory sync in 1b259e2d33

Additionally, move booleans from BasePlayer to LocalPlayer when they are only needed on the client, and make the usage of the isReceivingQuickKeys boolean consistent with the new isReceivingInventory boolean by having them both in the processors of their associated packets.
2018-08-28 05:01:52 +03:00

221 lines
7.5 KiB
C++

#include "trainingwindow.hpp"
#include <MyGUI_Gui.h>
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwworld/esmstore.hpp"
#include "../mwmechanics/npcstats.hpp"
#include "../mwmechanics/actorutil.hpp"
#include "tooltips.hpp"
namespace
{
// Sorts a container descending by skill value. If skill value is equal, sorts ascending by skill ID.
// pair <skill ID, skill value>
bool sortSkills (const std::pair<int, int>& left, const std::pair<int, int>& right)
{
if (left == right)
return false;
if (left.second > right.second)
return true;
else if (left.second < right.second)
return false;
return left.first < right.first;
}
}
namespace MWGui
{
TrainingWindow::TrainingWindow()
: WindowBase("openmw_trainingwindow.layout")
, mTimeAdvancer(0.05f)
{
getWidget(mTrainingOptions, "TrainingOptions");
getWidget(mCancelButton, "CancelButton");
getWidget(mPlayerGold, "PlayerGold");
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TrainingWindow::onCancelButtonClicked);
mTimeAdvancer.eventProgressChanged += MyGUI::newDelegate(this, &TrainingWindow::onTrainingProgressChanged);
mTimeAdvancer.eventFinished += MyGUI::newDelegate(this, &TrainingWindow::onTrainingFinished);
}
void TrainingWindow::onOpen()
{
if (mTimeAdvancer.isRunning())
{
mProgressBar.setVisible(true);
setVisible(false);
}
else
mProgressBar.setVisible(false);
center();
}
void TrainingWindow::setPtr (const MWWorld::Ptr& actor)
{
mPtr = actor;
MWWorld::Ptr player = MWMechanics::getPlayer();
int playerGold = player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId);
mPlayerGold->setCaptionWithReplacing("#{sGold}: " + MyGUI::utility::toString(playerGold));
MWMechanics::NpcStats& npcStats = actor.getClass().getNpcStats (actor);
// NPC can train you in his best 3 skills
std::vector< std::pair<int, int> > skills;
for (int i=0; i<ESM::Skill::Length; ++i)
{
int value = npcStats.getSkill (i).getModified ();
skills.push_back(std::make_pair(i, value));
}
std::sort(skills.begin(), skills.end(), sortSkills);
MyGUI::EnumeratorWidgetPtr widgets = mTrainingOptions->getEnumerator ();
MyGUI::Gui::getInstance ().destroyWidgets (widgets);
MWMechanics::NpcStats& pcStats = player.getClass().getNpcStats (player);
const MWWorld::Store<ESM::GameSetting> &gmst =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
for (int i=0; i<3; ++i)
{
int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer
(mPtr,pcStats.getSkill (skills[i].first).getBase() * gmst.find("iTrainingMod")->getInt (),true);
MyGUI::Button* button = mTrainingOptions->createWidget<MyGUI::Button>(price <= playerGold ? "SandTextButton" : "SandTextButtonDisabled", // can't use setEnabled since that removes tooltip
MyGUI::IntCoord(5, 5+i*18, mTrainingOptions->getWidth()-10, 18), MyGUI::Align::Default);
button->setUserData(skills[i].first);
button->eventMouseButtonClick += MyGUI::newDelegate(this, &TrainingWindow::onTrainingSelected);
button->setCaptionWithReplacing("#{" + ESM::Skill::sSkillNameIds[skills[i].first] + "} - " + MyGUI::utility::toString(price));
button->setSize(button->getTextSize ().width+12, button->getSize().height);
ToolTips::createSkillToolTip (button, skills[i].first);
}
center();
}
void TrainingWindow::onReferenceUnavailable ()
{
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Training);
}
void TrainingWindow::onCancelButtonClicked (MyGUI::Widget *sender)
{
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Training);
}
void TrainingWindow::onTrainingSelected (MyGUI::Widget *sender)
{
int skillId = *sender->getUserData<int>();
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
MWMechanics::NpcStats& pcStats = player.getClass().getNpcStats (player);
const MWWorld::ESMStore &store =
MWBase::Environment::get().getWorld()->getStore();
int price = pcStats.getSkill (skillId).getBase() * store.get<ESM::GameSetting>().find("iTrainingMod")->getInt ();
price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr,price,true);
if (price > player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId))
return;
MWMechanics::NpcStats& npcStats = mPtr.getClass().getNpcStats (mPtr);
if (npcStats.getSkill (skillId).getModified () <= pcStats.getSkill (skillId).getBase ())
{
MWBase::Environment::get().getWindowManager()->messageBox ("#{sServiceTrainingWords}");
return;
}
// You can not train a skill above its governing attribute
const ESM::Skill* skill = MWBase::Environment::get().getWorld()->getStore().get<ESM::Skill>().find(skillId);
if (pcStats.getSkill(skillId).getBase() >= pcStats.getAttribute(skill->mData.mAttribute).getBase())
{
MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage17}");
return;
}
// increase skill
MWWorld::LiveCellRef<ESM::NPC> *playerRef = player.get<ESM::NPC>();
const ESM::Class *class_ =
store.get<ESM::Class>().find(playerRef->mBase->mClass);
pcStats.increaseSkill (skillId, *class_, true);
// remove gold
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price, player);
// add gold to NPC trading gold pool
npcStats.setGoldPool(npcStats.getGoldPool() + price);
// advance time
MWBase::Environment::get().getMechanicsManager()->rest(false);
MWBase::Environment::get().getMechanicsManager()->rest(false);
/*
Start of tes3mp change (major)
Multiplayer requires that time not get advanced here
*/
//MWBase::Environment::get().getWorld ()->advanceTime (2);
/*
End of tes3mp change (major)
*/
setVisible(false);
mProgressBar.setVisible(true);
mProgressBar.setProgress(0, 2);
mTimeAdvancer.run(2);
MWBase::Environment::get().getWindowManager()->fadeScreenOut(0.25);
MWBase::Environment::get().getWindowManager()->fadeScreenIn(0.25, false, 0.25);
}
void TrainingWindow::onTrainingProgressChanged(int cur, int total)
{
mProgressBar.setProgress(cur, total);
}
void TrainingWindow::onTrainingFinished()
{
mProgressBar.setVisible(false);
// go back to game mode
MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Training);
MWBase::Environment::get().getWindowManager()->exitCurrentGuiMode();
}
void TrainingWindow::onFrame(float dt)
{
checkReferenceAvailable();
mTimeAdvancer.onFrame(dt);
}
bool TrainingWindow::exit()
{
return !mTimeAdvancer.isRunning();
}
}