2012-10-17 18:03:02 +02:00
|
|
|
#include "trainingwindow.hpp"
|
|
|
|
|
2022-06-04 15:26:36 +02:00
|
|
|
#include <MyGUI_Button.h>
|
2015-01-10 02:50:43 +01:00
|
|
|
#include <MyGUI_Gui.h>
|
|
|
|
|
2012-10-17 18:03:02 +02:00
|
|
|
#include "../mwbase/environment.hpp"
|
2012-11-05 19:53:55 +01:00
|
|
|
#include "../mwbase/mechanicsmanager.hpp"
|
2022-09-22 21:26:05 +03:00
|
|
|
#include "../mwbase/windowmanager.hpp"
|
|
|
|
#include "../mwbase/world.hpp"
|
2012-10-17 18:03:02 +02:00
|
|
|
|
2013-05-11 18:38:27 +02:00
|
|
|
#include "../mwworld/class.hpp"
|
2013-11-21 04:27:53 +01:00
|
|
|
#include "../mwworld/containerstore.hpp"
|
2014-12-19 11:26:54 +01:00
|
|
|
#include "../mwworld/esmstore.hpp"
|
2012-10-17 18:03:02 +02:00
|
|
|
|
2015-08-21 21:12:39 +12:00
|
|
|
#include "../mwmechanics/actorutil.hpp"
|
2022-09-22 21:26:05 +03:00
|
|
|
#include "../mwmechanics/npcstats.hpp"
|
2012-10-17 18:03:02 +02:00
|
|
|
|
2022-09-05 19:35:15 +02:00
|
|
|
#include <components/esm3/loadclas.hpp>
|
2022-09-22 21:26:05 +03:00
|
|
|
#include <components/settings/settings.hpp>
|
2020-07-06 20:28:08 +02:00
|
|
|
|
2012-10-17 18:03:02 +02:00
|
|
|
#include "tooltips.hpp"
|
|
|
|
|
2014-06-09 03:40:14 +02:00
|
|
|
namespace
|
|
|
|
{
|
2022-09-22 21:26:05 +03:00
|
|
|
// 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;
|
2014-06-09 03:40:14 +02:00
|
|
|
|
2022-09-22 21:26:05 +03:00
|
|
|
if (left.second > right.second)
|
|
|
|
return true;
|
|
|
|
else if (left.second < right.second)
|
|
|
|
return false;
|
2014-06-09 03:40:14 +02:00
|
|
|
|
2022-09-22 21:26:05 +03:00
|
|
|
return left.first < right.first;
|
|
|
|
}
|
2014-06-09 03:40:14 +02:00
|
|
|
}
|
|
|
|
|
2012-10-17 18:03:02 +02:00
|
|
|
namespace MWGui
|
|
|
|
{
|
|
|
|
|
2013-04-10 14:46:21 -04:00
|
|
|
TrainingWindow::TrainingWindow()
|
|
|
|
: WindowBase("openmw_trainingwindow.layout")
|
2015-03-08 13:07:29 +13:00
|
|
|
, mTimeAdvancer(0.05f)
|
2022-09-22 21:26:05 +03:00
|
|
|
, mTrainingSkillBasedOnBaseSkill(
|
|
|
|
Settings::Manager::getBool("trainers training skills based on base skill", "Game"))
|
2012-10-17 18:03:02 +02:00
|
|
|
{
|
|
|
|
getWidget(mTrainingOptions, "TrainingOptions");
|
|
|
|
getWidget(mCancelButton, "CancelButton");
|
|
|
|
getWidget(mPlayerGold, "PlayerGold");
|
|
|
|
|
|
|
|
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TrainingWindow::onCancelButtonClicked);
|
2015-02-07 04:05:28 +01:00
|
|
|
|
|
|
|
mTimeAdvancer.eventProgressChanged += MyGUI::newDelegate(this, &TrainingWindow::onTrainingProgressChanged);
|
|
|
|
mTimeAdvancer.eventFinished += MyGUI::newDelegate(this, &TrainingWindow::onTrainingFinished);
|
2012-10-17 18:03:02 +02:00
|
|
|
}
|
|
|
|
|
2017-09-22 17:10:53 +02:00
|
|
|
void TrainingWindow::onOpen()
|
2012-10-17 18:03:02 +02:00
|
|
|
{
|
2017-09-24 12:58:14 +02:00
|
|
|
if (mTimeAdvancer.isRunning())
|
|
|
|
{
|
|
|
|
mProgressBar.setVisible(true);
|
|
|
|
setVisible(false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
mProgressBar.setVisible(false);
|
|
|
|
|
2012-10-17 18:03:02 +02:00
|
|
|
center();
|
|
|
|
}
|
|
|
|
|
2022-09-22 21:26:05 +03:00
|
|
|
void TrainingWindow::setPtr(const MWWorld::Ptr& actor)
|
2012-10-17 18:03:02 +02:00
|
|
|
{
|
|
|
|
mPtr = actor;
|
|
|
|
|
2015-08-21 21:12:39 +12:00
|
|
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
2014-01-08 23:37:46 +01:00
|
|
|
int playerGold = player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId);
|
|
|
|
|
2015-01-10 03:01:01 +01:00
|
|
|
mPlayerGold->setCaptionWithReplacing("#{sGold}: " + MyGUI::utility::toString(playerGold));
|
2012-10-17 18:03:02 +02:00
|
|
|
|
|
|
|
// NPC can train you in his best 3 skills
|
2022-09-22 21:26:05 +03:00
|
|
|
std::vector<std::pair<int, float>> skills;
|
2012-10-17 18:03:02 +02:00
|
|
|
|
2020-07-06 20:28:08 +02:00
|
|
|
MWMechanics::NpcStats const& actorStats(actor.getClass().getNpcStats(actor));
|
2022-09-22 21:26:05 +03:00
|
|
|
for (int i = 0; i < ESM::Skill::Length; ++i)
|
2012-10-17 18:03:02 +02:00
|
|
|
{
|
2020-07-06 20:28:08 +02:00
|
|
|
float value = getSkillForTraining(actorStats, i);
|
2012-10-17 18:03:02 +02:00
|
|
|
|
2020-10-17 12:26:35 +04:00
|
|
|
skills.emplace_back(i, value);
|
2012-10-17 18:03:02 +02:00
|
|
|
}
|
|
|
|
|
2014-06-09 03:40:14 +02:00
|
|
|
std::sort(skills.begin(), skills.end(), sortSkills);
|
|
|
|
|
2022-09-22 21:26:05 +03:00
|
|
|
MyGUI::EnumeratorWidgetPtr widgets = mTrainingOptions->getEnumerator();
|
|
|
|
MyGUI::Gui::getInstance().destroyWidgets(widgets);
|
2012-10-17 18:03:02 +02:00
|
|
|
|
2022-09-22 21:26:05 +03:00
|
|
|
MWMechanics::NpcStats& pcStats = player.getClass().getNpcStats(player);
|
2012-10-17 18:03:02 +02:00
|
|
|
|
2022-09-22 21:26:05 +03:00
|
|
|
const MWWorld::Store<ESM::GameSetting>& gmst
|
|
|
|
= MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
2012-11-06 13:43:48 +04:00
|
|
|
|
2022-08-30 07:54:20 +00:00
|
|
|
const int lineHeight = MWBase::Environment::get().getWindowManager()->getFontHeight() + 2;
|
|
|
|
|
2022-09-22 21:26:05 +03:00
|
|
|
for (int i = 0; i < 3; ++i)
|
2012-10-17 18:03:02 +02:00
|
|
|
{
|
2022-09-22 21:26:05 +03:00
|
|
|
int price = static_cast<int>(
|
|
|
|
pcStats.getSkill(skills[i].first).getBase() * gmst.find("iTrainingMod")->mValue.getInteger());
|
2020-09-08 16:55:12 +04:00
|
|
|
price = std::max(1, price);
|
|
|
|
price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, price, true);
|
2012-10-17 18:03:02 +02:00
|
|
|
|
2022-09-22 21:26:05 +03:00
|
|
|
MyGUI::Button* button = mTrainingOptions->createWidget<MyGUI::Button>(price <= playerGold
|
|
|
|
? "SandTextButton"
|
|
|
|
: "SandTextButtonDisabled", // can't use setEnabled since that removes tooltip
|
|
|
|
MyGUI::IntCoord(5, 5 + i * lineHeight, mTrainingOptions->getWidth() - 10, lineHeight),
|
|
|
|
MyGUI::Align::Default);
|
2012-10-17 18:03:02 +02:00
|
|
|
|
2014-06-09 03:40:14 +02:00
|
|
|
button->setUserData(skills[i].first);
|
2012-10-17 18:03:02 +02:00
|
|
|
button->eventMouseButtonClick += MyGUI::newDelegate(this, &TrainingWindow::onTrainingSelected);
|
|
|
|
|
2022-09-22 21:26:05 +03:00
|
|
|
button->setCaptionWithReplacing(
|
|
|
|
"#{" + ESM::Skill::sSkillNameIds[skills[i].first] + "} - " + MyGUI::utility::toString(price));
|
2012-10-17 18:03:02 +02:00
|
|
|
|
2022-09-22 21:26:05 +03:00
|
|
|
button->setSize(button->getTextSize().width + 12, button->getSize().height);
|
2012-10-17 18:03:02 +02:00
|
|
|
|
2022-09-22 21:26:05 +03:00
|
|
|
ToolTips::createSkillToolTip(button, skills[i].first);
|
2012-10-17 18:03:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
center();
|
|
|
|
}
|
|
|
|
|
2022-09-22 21:26:05 +03:00
|
|
|
void TrainingWindow::onReferenceUnavailable()
|
2012-10-17 18:03:02 +02:00
|
|
|
{
|
2013-04-10 00:32:05 -04:00
|
|
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Training);
|
2012-10-17 18:03:02 +02:00
|
|
|
}
|
|
|
|
|
2022-09-22 21:26:05 +03:00
|
|
|
void TrainingWindow::onCancelButtonClicked(MyGUI::Widget* sender)
|
2012-10-17 18:03:02 +02:00
|
|
|
{
|
2017-09-23 12:18:39 +02:00
|
|
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Training);
|
2012-10-17 18:03:02 +02:00
|
|
|
}
|
|
|
|
|
2022-09-22 21:26:05 +03:00
|
|
|
void TrainingWindow::onTrainingSelected(MyGUI::Widget* sender)
|
2012-10-17 18:03:02 +02:00
|
|
|
{
|
|
|
|
int skillId = *sender->getUserData<int>();
|
|
|
|
|
2022-09-22 21:26:05 +03:00
|
|
|
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
|
|
|
MWMechanics::NpcStats& pcStats = player.getClass().getNpcStats(player);
|
2012-10-17 18:03:02 +02:00
|
|
|
|
2022-09-22 21:26:05 +03:00
|
|
|
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
|
2012-11-06 11:29:18 +04:00
|
|
|
|
2022-09-22 21:26:05 +03:00
|
|
|
int price = pcStats.getSkill(skillId).getBase()
|
|
|
|
* store.get<ESM::GameSetting>().find("iTrainingMod")->mValue.getInteger();
|
|
|
|
price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, price, true);
|
2012-10-17 18:03:02 +02:00
|
|
|
|
2014-10-17 18:58:20 +02:00
|
|
|
if (price > player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId))
|
|
|
|
return;
|
|
|
|
|
2020-07-06 20:30:14 +02:00
|
|
|
if (getSkillForTraining(mPtr.getClass().getNpcStats(mPtr), skillId) <= pcStats.getSkill(skillId).getBase())
|
2012-10-17 18:48:29 +02:00
|
|
|
{
|
2022-09-22 21:26:05 +03:00
|
|
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sServiceTrainingWords}");
|
2012-10-17 18:48:29 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-01-10 20:53:53 +01:00
|
|
|
// 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())
|
|
|
|
{
|
2022-09-22 21:26:05 +03:00
|
|
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage17}");
|
2014-01-10 20:53:53 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-17 18:03:02 +02:00
|
|
|
// increase skill
|
2022-09-22 21:26:05 +03:00
|
|
|
MWWorld::LiveCellRef<ESM::NPC>* playerRef = player.get<ESM::NPC>();
|
2012-11-06 11:29:18 +04:00
|
|
|
|
2022-09-22 21:26:05 +03:00
|
|
|
const ESM::Class* class_ = store.get<ESM::Class>().find(playerRef->mBase->mClass);
|
|
|
|
pcStats.increaseSkill(skillId, *class_, true);
|
2012-10-17 18:03:02 +02:00
|
|
|
|
|
|
|
// remove gold
|
2014-01-08 23:37:46 +01:00
|
|
|
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price, player);
|
2012-10-17 18:03:02 +02:00
|
|
|
|
2014-07-28 00:55:57 +02:00
|
|
|
// add gold to NPC trading gold pool
|
2018-10-08 17:06:30 +03:00
|
|
|
MWMechanics::NpcStats& npcStats = mPtr.getClass().getNpcStats(mPtr);
|
2014-07-28 00:55:57 +02:00
|
|
|
npcStats.setGoldPool(npcStats.getGoldPool() + price);
|
|
|
|
|
2012-10-17 18:03:02 +02:00
|
|
|
// advance time
|
2019-01-25 20:04:35 +04:00
|
|
|
MWBase::Environment::get().getMechanicsManager()->rest(2, false);
|
2022-09-22 21:26:05 +03:00
|
|
|
MWBase::Environment::get().getWorld()->advanceTime(2);
|
2012-10-17 18:03:02 +02:00
|
|
|
|
2017-09-24 12:58:14 +02:00
|
|
|
setVisible(false);
|
2015-02-07 04:05:28 +01:00
|
|
|
mProgressBar.setVisible(true);
|
|
|
|
mProgressBar.setProgress(0, 2);
|
|
|
|
mTimeAdvancer.run(2);
|
|
|
|
|
2014-08-01 16:25:41 +02:00
|
|
|
MWBase::Environment::get().getWindowManager()->fadeScreenOut(0.25);
|
2017-09-24 19:15:39 +02:00
|
|
|
MWBase::Environment::get().getWindowManager()->fadeScreenIn(0.25, false, 0.25);
|
2012-10-17 18:03:02 +02:00
|
|
|
}
|
|
|
|
|
2015-02-07 04:05:28 +01:00
|
|
|
void TrainingWindow::onTrainingProgressChanged(int cur, int total)
|
|
|
|
{
|
|
|
|
mProgressBar.setProgress(cur, total);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TrainingWindow::onTrainingFinished()
|
|
|
|
{
|
|
|
|
mProgressBar.setVisible(false);
|
2017-09-24 12:58:14 +02:00
|
|
|
|
|
|
|
// go back to game mode
|
2022-09-22 21:26:05 +03:00
|
|
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Training);
|
2017-09-26 23:27:53 +02:00
|
|
|
MWBase::Environment::get().getWindowManager()->exitCurrentGuiMode();
|
2015-02-07 04:05:28 +01:00
|
|
|
}
|
|
|
|
|
2020-07-07 09:50:02 +02:00
|
|
|
float TrainingWindow::getSkillForTraining(const MWMechanics::NpcStats& stats, int skillId) const
|
|
|
|
{
|
|
|
|
if (mTrainingSkillBasedOnBaseSkill)
|
|
|
|
return stats.getSkill(skillId).getBase();
|
|
|
|
return stats.getSkill(skillId).getModified();
|
|
|
|
}
|
|
|
|
|
2012-10-17 18:03:02 +02:00
|
|
|
void TrainingWindow::onFrame(float dt)
|
|
|
|
{
|
2017-09-23 22:00:15 +02:00
|
|
|
checkReferenceAvailable();
|
2015-02-07 04:05:28 +01:00
|
|
|
mTimeAdvancer.onFrame(dt);
|
2012-10-17 18:03:02 +02:00
|
|
|
}
|
2017-10-08 20:38:20 +00:00
|
|
|
|
|
|
|
bool TrainingWindow::exit()
|
|
|
|
{
|
|
|
|
return !mTimeAdvancer.isRunning();
|
|
|
|
}
|
|
|
|
|
2012-10-17 18:03:02 +02:00
|
|
|
}
|