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/charactercreation.cpp

795 lines
30 KiB
C++
Raw Normal View History

2012-01-30 17:27:49 +00:00
#include "charactercreation.hpp"
2018-08-14 19:05:43 +00:00
#include <components/debug/debuglog.hpp>
2016-01-06 11:46:06 +00:00
#include <components/fallback/fallback.hpp>
2019-08-11 12:22:02 +00:00
#include <components/misc/rng.hpp>
2016-01-06 11:46:06 +00:00
#include "../mwbase/environment.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
2015-01-10 00:00:52 +00:00
#include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwmechanics/npcstats.hpp"
2015-08-21 09:12:39 +00:00
#include "../mwmechanics/actorutil.hpp"
2015-01-10 00:00:52 +00:00
#include "../mwworld/class.hpp"
#include "../mwworld/esmstore.hpp"
#include "../mwworld/player.hpp"
2015-01-10 00:00:52 +00:00
#include "textinput.hpp"
#include "race.hpp"
#include "class.hpp"
#include "birth.hpp"
#include "review.hpp"
#include "inventorywindow.hpp"
namespace
{
2019-08-11 12:22:02 +00:00
struct Response
{
const std::string mText;
const ESM::Class::Specialization mSpecialization;
};
struct Step
{
2013-03-10 14:15:33 +00:00
const std::string mText;
2019-08-11 12:22:02 +00:00
const Response mResponses[3];
2013-03-10 14:15:33 +00:00
const std::string mSound;
};
Step sGenerateClassSteps(int number)
{
2013-03-10 14:03:48 +00:00
number++;
2019-08-11 12:22:02 +00:00
std::string question = Fallback::Map::getString("Question_" + MyGUI::utility::toString(number) + "_Question");
std::string answer0 = Fallback::Map::getString("Question_" + MyGUI::utility::toString(number) + "_AnswerOne");
std::string answer1 = Fallback::Map::getString("Question_" + MyGUI::utility::toString(number) + "_AnswerTwo");
std::string answer2 = Fallback::Map::getString("Question_" + MyGUI::utility::toString(number) + "_AnswerThree");
std::string sound = "vo\\misc\\chargen qa" + MyGUI::utility::toString(number) + ".wav";
Response r0 = {answer0, ESM::Class::Combat};
Response r1 = {answer1, ESM::Class::Magic};
Response r2 = {answer2, ESM::Class::Stealth};
// randomize order in which responses are displayed
int order = Misc::Rng::rollDice(6);
switch (order)
{
case 0:
return {question, {r0, r1, r2}, sound};
case 1:
return {question, {r0, r2, r1}, sound};
case 2:
return {question, {r1, r0, r2}, sound};
case 3:
return {question, {r1, r2, r0}, sound};
case 4:
return {question, {r2, r0, r1}, sound};
default:
return {question, {r2, r1, r0}, sound};
}
}
void updatePlayerHealth()
{
2015-08-21 09:12:39 +00:00
MWWorld::Ptr player = MWMechanics::getPlayer();
MWMechanics::NpcStats& npcStats = player.getClass().getNpcStats(player);
npcStats.updateHealth();
}
}
2013-04-17 22:56:48 +00:00
namespace MWGui
2012-01-30 17:27:49 +00:00
{
CharacterCreation::CharacterCreation(osg::Group* parent, Resource::ResourceSystem* resourceSystem)
: mParent(parent)
2015-05-20 00:18:20 +00:00
, mResourceSystem(resourceSystem)
2020-11-13 07:39:47 +00:00
, mNameDialog(nullptr)
, mRaceDialog(nullptr)
, mClassChoiceDialog(nullptr)
, mGenerateClassQuestionDialog(nullptr)
, mGenerateClassResultDialog(nullptr)
, mPickClassDialog(nullptr)
, mCreateClassDialog(nullptr)
, mBirthSignDialog(nullptr)
, mReviewDialog(nullptr)
2013-04-17 22:56:48 +00:00
, mGenerateClassStep(0)
{
2013-04-17 22:56:48 +00:00
mCreationStage = CSE_NotStarted;
2019-08-11 12:22:02 +00:00
mGenerateClassResponses[0] = ESM::Class::Combat;
mGenerateClassResponses[1] = ESM::Class::Magic;
mGenerateClassResponses[2] = ESM::Class::Stealth;
2013-07-31 16:46:32 +00:00
mGenerateClassSpecializations[0] = 0;
mGenerateClassSpecializations[1] = 0;
mGenerateClassSpecializations[2] = 0;
// Setup player stats
for (int i = 0; i < ESM::Attribute::Length; ++i)
mPlayerAttributes.emplace(ESM::Attribute::sAttributeIds[i], MWMechanics::AttributeValue());
for (int i = 0; i < ESM::Skill::Length; ++i)
mPlayerSkillValues.emplace(ESM::Skill::sSkillIds[i], MWMechanics::SkillValue());
}
void CharacterCreation::setValue (const std::string& id, const MWMechanics::AttributeValue& value)
{
static const char *ids[] =
{
"AttribVal1", "AttribVal2", "AttribVal3", "AttribVal4",
"AttribVal5", "AttribVal6", "AttribVal7", "AttribVal8", 0
};
2013-04-17 22:56:48 +00:00
for (int i=0; ids[i]; ++i)
{
if (ids[i]==id)
2013-04-17 22:56:48 +00:00
{
mPlayerAttributes[static_cast<ESM::Attribute::AttributeID>(i)] = value;
if (mReviewDialog)
mReviewDialog->setAttribute(static_cast<ESM::Attribute::AttributeID>(i), value);
break;
2013-04-17 22:56:48 +00:00
}
}
}
2013-04-17 22:56:48 +00:00
void CharacterCreation::setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value)
2012-01-30 17:27:49 +00:00
{
2013-04-17 22:56:48 +00:00
if (mReviewDialog)
{
if (id == "HBar")
{
2013-04-17 22:56:48 +00:00
mReviewDialog->setHealth (value);
}
2013-04-17 22:56:48 +00:00
else if (id == "MBar")
{
2013-04-17 22:56:48 +00:00
mReviewDialog->setMagicka (value);
}
else if (id == "FBar")
{
mReviewDialog->setFatigue (value);
}
2013-04-17 22:56:48 +00:00
}
}
void CharacterCreation::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value)
2013-04-17 22:56:48 +00:00
{
mPlayerSkillValues[parSkill] = value;
2013-04-17 22:56:48 +00:00
if (mReviewDialog)
mReviewDialog->setSkillValue(parSkill, value);
2012-01-30 17:27:49 +00:00
}
2013-04-17 22:56:48 +00:00
void CharacterCreation::configureSkills (const SkillList& major, const SkillList& minor)
{
if (mReviewDialog)
mReviewDialog->configureSkills(major, minor);
mPlayerMajorSkills = major;
mPlayerMinorSkills = minor;
2013-04-17 22:56:48 +00:00
}
void CharacterCreation::onFrame(float duration)
{
if (mReviewDialog)
mReviewDialog->onFrame(duration);
}
2013-04-17 22:56:48 +00:00
void CharacterCreation::spawnDialog(const char id)
{
try
2013-04-17 22:56:48 +00:00
{
switch (id)
{
case GM_Name:
MWBase::Environment::get().getWindowManager()->removeDialog(mNameDialog);
2020-11-13 07:39:47 +00:00
mNameDialog = nullptr;
mNameDialog = new TextInputDialog();
mNameDialog->setTextLabel(MWBase::Environment::get().getWindowManager()->getGameSettingString("sName", "Name"));
mNameDialog->setTextInput(mPlayerName);
mNameDialog->setNextButtonShow(mCreationStage >= CSE_NameChosen);
mNameDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onNameDialogDone);
mNameDialog->setVisible(true);
break;
case GM_Race:
MWBase::Environment::get().getWindowManager()->removeDialog(mRaceDialog);
2020-11-13 07:39:47 +00:00
mRaceDialog = nullptr;
mRaceDialog = new RaceDialog(mParent, mResourceSystem);
mRaceDialog->setNextButtonShow(mCreationStage >= CSE_RaceChosen);
mRaceDialog->setRaceId(mPlayerRaceId);
mRaceDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onRaceDialogDone);
mRaceDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onRaceDialogBack);
mRaceDialog->setVisible(true);
if (mCreationStage < CSE_NameChosen)
mCreationStage = CSE_NameChosen;
break;
case GM_Class:
MWBase::Environment::get().getWindowManager()->removeDialog(mClassChoiceDialog);
2020-11-13 07:39:47 +00:00
mClassChoiceDialog = nullptr;
mClassChoiceDialog = new ClassChoiceDialog();
mClassChoiceDialog->eventButtonSelected += MyGUI::newDelegate(this, &CharacterCreation::onClassChoice);
mClassChoiceDialog->setVisible(true);
if (mCreationStage < CSE_RaceChosen)
mCreationStage = CSE_RaceChosen;
break;
case GM_ClassPick:
MWBase::Environment::get().getWindowManager()->removeDialog(mPickClassDialog);
2020-11-13 07:39:47 +00:00
mPickClassDialog = nullptr;
mPickClassDialog = new PickClassDialog();
mPickClassDialog->setNextButtonShow(mCreationStage >= CSE_ClassChosen);
mPickClassDialog->setClassId(mPlayerClass.mId);
mPickClassDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onPickClassDialogDone);
mPickClassDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onPickClassDialogBack);
mPickClassDialog->setVisible(true);
if (mCreationStage < CSE_RaceChosen)
mCreationStage = CSE_RaceChosen;
break;
case GM_Birth:
MWBase::Environment::get().getWindowManager()->removeDialog(mBirthSignDialog);
2020-11-13 07:39:47 +00:00
mBirthSignDialog = nullptr;
mBirthSignDialog = new BirthDialog();
mBirthSignDialog->setNextButtonShow(mCreationStage >= CSE_BirthSignChosen);
mBirthSignDialog->setBirthId(mPlayerBirthSignId);
mBirthSignDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onBirthSignDialogDone);
mBirthSignDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onBirthSignDialogBack);
mBirthSignDialog->setVisible(true);
if (mCreationStage < CSE_ClassChosen)
mCreationStage = CSE_ClassChosen;
break;
case GM_ClassCreate:
if (!mCreateClassDialog)
{
mCreateClassDialog = new CreateClassDialog();
mCreateClassDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogDone);
mCreateClassDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogBack);
}
mCreateClassDialog->setNextButtonShow(mCreationStage >= CSE_ClassChosen);
mCreateClassDialog->setVisible(true);
if (mCreationStage < CSE_RaceChosen)
mCreationStage = CSE_RaceChosen;
break;
case GM_ClassGenerate:
mGenerateClassStep = 0;
mGenerateClass = "";
mGenerateClassSpecializations[0] = 0;
mGenerateClassSpecializations[1] = 0;
mGenerateClassSpecializations[2] = 0;
showClassQuestionDialog();
if (mCreationStage < CSE_RaceChosen)
mCreationStage = CSE_RaceChosen;
break;
case GM_Review:
MWBase::Environment::get().getWindowManager()->removeDialog(mReviewDialog);
2020-11-13 07:39:47 +00:00
mReviewDialog = nullptr;
mReviewDialog = new ReviewDialog();
MWBase::World *world = MWBase::Environment::get().getWorld();
const ESM::NPC *playerNpc = world->getPlayerPtr().get<ESM::NPC>()->mBase;
const MWWorld::Player player = world->getPlayer();
const ESM::Class *playerClass = world->getStore().get<ESM::Class>().find(playerNpc->mClass);
mReviewDialog->setPlayerName(playerNpc->mName);
mReviewDialog->setRace(playerNpc->mRace);
mReviewDialog->setClass(*playerClass);
mReviewDialog->setBirthSign(player.getBirthSign());
MWWorld::Ptr playerPtr = MWMechanics::getPlayer();
const MWMechanics::CreatureStats& stats = playerPtr.getClass().getCreatureStats(playerPtr);
mReviewDialog->setHealth(stats.getHealth());
mReviewDialog->setMagicka(stats.getMagicka());
mReviewDialog->setFatigue(stats.getFatigue());
for (auto& attributePair : mPlayerAttributes)
2013-04-17 22:56:48 +00:00
{
mReviewDialog->setAttribute(static_cast<ESM::Attribute::AttributeID> (attributePair.first), attributePair.second);
2013-04-17 22:56:48 +00:00
}
for (auto& skillPair : mPlayerSkillValues)
2013-04-17 22:56:48 +00:00
{
mReviewDialog->setSkillValue(static_cast<ESM::Skill::SkillEnum> (skillPair.first), skillPair.second);
2013-04-17 22:56:48 +00:00
}
mReviewDialog->configureSkills(mPlayerMajorSkills, mPlayerMinorSkills);
mReviewDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogDone);
mReviewDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogBack);
mReviewDialog->eventActivateDialog += MyGUI::newDelegate(this, &CharacterCreation::onReviewActivateDialog);
mReviewDialog->setVisible(true);
if (mCreationStage < CSE_BirthSignChosen)
mCreationStage = CSE_BirthSignChosen;
break;
}
}
catch (std::exception& e)
{
2018-08-14 19:05:43 +00:00
Log(Debug::Error) << "Error: Failed to create chargen window: " << e.what();
2013-04-17 22:56:48 +00:00
}
}
2013-04-17 22:56:48 +00:00
void CharacterCreation::onReviewDialogDone(WindowBase* parWindow)
2012-01-30 17:27:49 +00:00
{
2013-04-17 22:56:48 +00:00
MWBase::Environment::get().getWindowManager()->removeDialog(mReviewDialog);
2020-11-13 07:39:47 +00:00
mReviewDialog = nullptr;
2013-04-17 22:56:48 +00:00
MWBase::Environment::get().getWindowManager()->popGuiMode();
2012-01-30 17:27:49 +00:00
}
2013-04-17 22:56:48 +00:00
void CharacterCreation::onReviewDialogBack()
2012-01-30 17:27:49 +00:00
{
2013-04-17 22:56:48 +00:00
MWBase::Environment::get().getWindowManager()->removeDialog(mReviewDialog);
2020-11-13 07:39:47 +00:00
mReviewDialog = nullptr;
mCreationStage = CSE_ReviewBack;
2013-04-17 22:56:48 +00:00
MWBase::Environment::get().getWindowManager()->popGuiMode();
2013-04-17 22:56:48 +00:00
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Birth);
2012-01-30 17:27:49 +00:00
}
2013-04-17 22:56:48 +00:00
void CharacterCreation::onReviewActivateDialog(int parDialog)
{
MWBase::Environment::get().getWindowManager()->removeDialog(mReviewDialog);
2020-11-13 07:39:47 +00:00
mReviewDialog = nullptr;
2013-04-17 22:56:48 +00:00
mCreationStage = CSE_ReviewNext;
2012-01-30 17:27:49 +00:00
2013-04-17 22:56:48 +00:00
MWBase::Environment::get().getWindowManager()->popGuiMode();
2012-01-30 17:27:49 +00:00
2013-04-17 22:56:48 +00:00
switch(parDialog)
{
case ReviewDialog::NAME_DIALOG:
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Name);
break;
case ReviewDialog::RACE_DIALOG:
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Race);
break;
case ReviewDialog::CLASS_DIALOG:
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
break;
case ReviewDialog::BIRTHSIGN_DIALOG:
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Birth);
};
}
2012-05-23 10:23:35 +00:00
void CharacterCreation::selectPickedClass()
2012-01-30 17:27:49 +00:00
{
2013-04-17 22:56:48 +00:00
if (mPickClassDialog)
{
const std::string &classId = mPickClassDialog->getClassId();
if (!classId.empty())
MWBase::Environment::get().getMechanicsManager()->setPlayerClass(classId);
2012-01-30 17:27:49 +00:00
2013-04-17 22:56:48 +00:00
const ESM::Class *klass =
MWBase::Environment::get().getWorld()->getStore().get<ESM::Class>().find(classId);
if (klass)
{
mPlayerClass = *klass;
}
MWBase::Environment::get().getWindowManager()->removeDialog(mPickClassDialog);
2020-11-13 07:39:47 +00:00
mPickClassDialog = nullptr;
2013-04-17 22:56:48 +00:00
}
2012-01-30 17:27:49 +00:00
updatePlayerHealth();
}
void CharacterCreation::onPickClassDialogDone(WindowBase* parWindow)
{
selectPickedClass();
2015-03-11 23:43:28 +00:00
handleDialogDone(CSE_ClassChosen, GM_Birth);
2012-01-30 17:27:49 +00:00
}
2013-04-17 22:56:48 +00:00
void CharacterCreation::onPickClassDialogBack()
2012-05-23 10:23:35 +00:00
{
selectPickedClass();
2013-04-17 22:56:48 +00:00
MWBase::Environment::get().getWindowManager()->popGuiMode();
2013-04-17 22:56:48 +00:00
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
2012-05-23 10:23:35 +00:00
}
2013-04-17 22:56:48 +00:00
void CharacterCreation::onClassChoice(int _index)
2012-01-30 17:27:49 +00:00
{
2013-04-17 22:56:48 +00:00
MWBase::Environment::get().getWindowManager()->removeDialog(mClassChoiceDialog);
2020-11-13 07:39:47 +00:00
mClassChoiceDialog = nullptr;
2013-04-17 22:56:48 +00:00
MWBase::Environment::get().getWindowManager()->popGuiMode();
2012-01-30 17:27:49 +00:00
2013-04-17 22:56:48 +00:00
switch(_index)
{
case ClassChoiceDialog::Class_Generate:
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_ClassGenerate);
break;
case ClassChoiceDialog::Class_Pick:
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_ClassPick);
break;
case ClassChoiceDialog::Class_Create:
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_ClassCreate);
break;
case ClassChoiceDialog::Class_Back:
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Race);
break;
2012-01-30 17:27:49 +00:00
2013-04-17 22:56:48 +00:00
};
}
2012-01-30 17:27:49 +00:00
2013-04-17 22:56:48 +00:00
void CharacterCreation::onNameDialogDone(WindowBase* parWindow)
2012-01-30 17:27:49 +00:00
{
2013-04-17 22:56:48 +00:00
if (mNameDialog)
{
mPlayerName = mNameDialog->getTextInput();
/*
Start of tes3mp change (major)
Ensure names are not longer than the original game's 31 character maximum
*/
if (mPlayerName.length() > 31)
mPlayerName = mPlayerName.substr(0, 31);
/*
End of tes3mp change (major)
*/
2013-04-17 22:56:48 +00:00
MWBase::Environment::get().getMechanicsManager()->setPlayerName(mPlayerName);
MWBase::Environment::get().getWindowManager()->removeDialog(mNameDialog);
2020-11-13 07:39:47 +00:00
mNameDialog = nullptr;
}
2015-03-11 23:43:28 +00:00
handleDialogDone(CSE_NameChosen, GM_Race);
2012-01-30 17:27:49 +00:00
}
void CharacterCreation::selectRace()
2012-05-23 10:23:35 +00:00
{
2013-04-17 22:56:48 +00:00
if (mRaceDialog)
{
const ESM::NPC &data = mRaceDialog->getResult();
mPlayerRaceId = data.mRace;
if (!mPlayerRaceId.empty()) {
MWBase::Environment::get().getMechanicsManager()->setPlayerRace(
data.mRace,
data.isMale(),
data.mHead,
data.mHair
);
}
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->rebuildAvatar();
2013-04-17 22:56:48 +00:00
MWBase::Environment::get().getWindowManager()->removeDialog(mRaceDialog);
2020-11-13 07:39:47 +00:00
mRaceDialog = nullptr;
2013-04-17 22:56:48 +00:00
}
updatePlayerHealth();
}
void CharacterCreation::onRaceDialogBack()
{
selectRace();
MWBase::Environment::get().getWindowManager()->popGuiMode();
2013-04-17 22:56:48 +00:00
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Name);
2012-01-30 17:27:49 +00:00
}
2013-04-17 22:56:48 +00:00
void CharacterCreation::onRaceDialogDone(WindowBase* parWindow)
{
selectRace();
2015-03-11 23:43:28 +00:00
handleDialogDone(CSE_RaceChosen, GM_Class);
}
void CharacterCreation::selectBirthSign()
2012-05-23 10:23:35 +00:00
{
2013-04-17 22:56:48 +00:00
if (mBirthSignDialog)
{
mPlayerBirthSignId = mBirthSignDialog->getBirthId();
if (!mPlayerBirthSignId.empty())
MWBase::Environment::get().getMechanicsManager()->setPlayerBirthsign(mPlayerBirthSignId);
MWBase::Environment::get().getWindowManager()->removeDialog(mBirthSignDialog);
2020-11-13 07:39:47 +00:00
mBirthSignDialog = nullptr;
2013-04-17 22:56:48 +00:00
}
updatePlayerHealth();
}
void CharacterCreation::onBirthSignDialogDone(WindowBase* parWindow)
{
selectBirthSign();
2015-03-11 23:43:28 +00:00
handleDialogDone(CSE_BirthSignChosen, GM_Review);
2012-05-23 10:23:35 +00:00
}
2013-04-17 22:56:48 +00:00
void CharacterCreation::onBirthSignDialogBack()
{
selectBirthSign();
2013-04-17 22:56:48 +00:00
MWBase::Environment::get().getWindowManager()->popGuiMode();
2013-04-17 22:56:48 +00:00
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
}
void CharacterCreation::selectCreatedClass()
{
2013-04-17 22:56:48 +00:00
if (mCreateClassDialog)
{
ESM::Class klass;
klass.mName = mCreateClassDialog->getName();
klass.mDescription = mCreateClassDialog->getDescription();
klass.mData.mSpecialization = mCreateClassDialog->getSpecializationId();
klass.mData.mIsPlayable = 0x1;
std::vector<int> attributes = mCreateClassDialog->getFavoriteAttributes();
assert(attributes.size() == 2);
klass.mData.mAttribute[0] = attributes[0];
klass.mData.mAttribute[1] = attributes[1];
std::vector<ESM::Skill::SkillEnum> majorSkills = mCreateClassDialog->getMajorSkills();
std::vector<ESM::Skill::SkillEnum> minorSkills = mCreateClassDialog->getMinorSkills();
assert(majorSkills.size() >= sizeof(klass.mData.mSkills)/sizeof(klass.mData.mSkills[0]));
assert(minorSkills.size() >= sizeof(klass.mData.mSkills)/sizeof(klass.mData.mSkills[0]));
for (size_t i = 0; i < sizeof(klass.mData.mSkills)/sizeof(klass.mData.mSkills[0]); ++i)
{
klass.mData.mSkills[i][1] = majorSkills[i];
klass.mData.mSkills[i][0] = minorSkills[i];
}
2013-04-17 22:56:48 +00:00
MWBase::Environment::get().getMechanicsManager()->setPlayerClass(klass);
mPlayerClass = klass;
// Do not delete dialog, so that choices are remembered in case we want to go back and adjust them later
mCreateClassDialog->setVisible(false);
}
updatePlayerHealth();
}
void CharacterCreation::onCreateClassDialogDone(WindowBase* parWindow)
{
selectCreatedClass();
2015-03-11 23:43:28 +00:00
handleDialogDone(CSE_ClassChosen, GM_Birth);
2013-04-17 22:56:48 +00:00
}
2013-04-17 22:56:48 +00:00
void CharacterCreation::onCreateClassDialogBack()
{
// not done in MW, but we do it for consistency with the other dialogs
selectCreatedClass();
MWBase::Environment::get().getWindowManager()->popGuiMode();
2013-04-17 22:56:48 +00:00
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
}
2013-04-17 22:56:48 +00:00
void CharacterCreation::onClassQuestionChosen(int _index)
{
MWBase::Environment::get().getSoundManager()->stopSay();
2013-04-17 22:56:48 +00:00
MWBase::Environment::get().getWindowManager()->removeDialog(mGenerateClassQuestionDialog);
2020-11-13 07:39:47 +00:00
mGenerateClassQuestionDialog = nullptr;
2013-04-17 22:56:48 +00:00
if (_index < 0 || _index >= 3)
{
MWBase::Environment::get().getWindowManager()->popGuiMode();
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
return;
}
2019-08-11 12:22:02 +00:00
ESM::Class::Specialization specialization = mGenerateClassResponses[_index];
if (specialization == ESM::Class::Combat)
2013-04-17 22:56:48 +00:00
++mGenerateClassSpecializations[0];
else if (specialization == ESM::Class::Magic)
2019-08-11 12:22:02 +00:00
++mGenerateClassSpecializations[1];
else if (specialization == ESM::Class::Stealth)
2013-04-17 22:56:48 +00:00
++mGenerateClassSpecializations[2];
++mGenerateClassStep;
showClassQuestionDialog();
}
2013-04-17 22:56:48 +00:00
void CharacterCreation::showClassQuestionDialog()
{
2013-04-17 22:56:48 +00:00
if (mGenerateClassStep == 10)
{
2019-08-11 12:22:02 +00:00
unsigned combat = mGenerateClassSpecializations[0];
unsigned magic = mGenerateClassSpecializations[1];
unsigned stealth = mGenerateClassSpecializations[2];
if (combat > 7)
{
2019-08-11 12:22:02 +00:00
mGenerateClass = "Warrior";
}
2019-08-11 12:22:02 +00:00
else if (magic > 7)
{
2019-08-11 12:22:02 +00:00
mGenerateClass = "Mage";
}
else if (stealth > 7)
{
mGenerateClass = "Thief";
}
else
{
switch (combat)
2013-04-17 22:56:48 +00:00
{
2019-08-11 12:22:02 +00:00
case 4:
mGenerateClass = "Rogue";
break;
case 5:
if (stealth == 3)
mGenerateClass = "Scout";
else
mGenerateClass = "Archer";
break;
case 6:
if (stealth == 1)
mGenerateClass = "Barbarian";
else if (stealth == 3)
mGenerateClass = "Crusader";
else
mGenerateClass = "Knight";
break;
case 7:
mGenerateClass = "Warrior";
break;
default:
switch (magic)
{
case 4:
mGenerateClass = "Spellsword";
break;
case 5:
mGenerateClass = "Witchhunter";
break;
case 6:
if (combat == 2)
mGenerateClass = "Sorcerer";
else if (combat == 3)
mGenerateClass = "Healer";
else
mGenerateClass = "Battlemage";
break;
case 7:
mGenerateClass = "Mage";
break;
default:
switch (stealth)
{
case 3:
if (magic == 3)
mGenerateClass = "Bard"; // unreachable
else
mGenerateClass = "Warrior";
break;
case 5:
if (magic == 3)
mGenerateClass = "Monk";
else
mGenerateClass = "Pilgrim";
break;
case 6:
if (magic == 1)
mGenerateClass = "Agent";
else if (magic == 3)
mGenerateClass = "Assassin";
else
mGenerateClass = "Acrobat";
break;
case 7:
mGenerateClass = "Thief";
break;
default:
mGenerateClass = "Warrior";
}
}
2013-04-17 22:56:48 +00:00
}
}
2013-04-17 22:56:48 +00:00
MWBase::Environment::get().getWindowManager()->removeDialog(mGenerateClassResultDialog);
2020-11-13 07:39:47 +00:00
mGenerateClassResultDialog = nullptr;
2013-04-17 22:56:48 +00:00
mGenerateClassResultDialog = new GenerateClassResultDialog();
mGenerateClassResultDialog->setClassId(mGenerateClass);
mGenerateClassResultDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onGenerateClassBack);
mGenerateClassResultDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onGenerateClassDone);
mGenerateClassResultDialog->setVisible(true);
return;
}
2013-04-17 22:56:48 +00:00
if (mGenerateClassStep > 10)
{
MWBase::Environment::get().getWindowManager()->popGuiMode();
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
return;
}
2013-04-17 22:56:48 +00:00
MWBase::Environment::get().getWindowManager()->removeDialog(mGenerateClassQuestionDialog);
2020-11-13 07:39:47 +00:00
mGenerateClassQuestionDialog = nullptr;
2013-04-17 22:56:48 +00:00
mGenerateClassQuestionDialog = new InfoBoxDialog();
2019-08-11 12:22:02 +00:00
Step step = sGenerateClassSteps(mGenerateClassStep);
mGenerateClassResponses[0] = step.mResponses[0].mSpecialization;
mGenerateClassResponses[1] = step.mResponses[1].mSpecialization;
mGenerateClassResponses[2] = step.mResponses[2].mSpecialization;
2013-04-17 22:56:48 +00:00
InfoBoxDialog::ButtonList buttons;
2019-08-11 12:22:02 +00:00
mGenerateClassQuestionDialog->setText(step.mText);
buttons.push_back(step.mResponses[0].mText);
buttons.push_back(step.mResponses[1].mText);
buttons.push_back(step.mResponses[2].mText);
2013-04-17 22:56:48 +00:00
mGenerateClassQuestionDialog->setButtons(buttons);
mGenerateClassQuestionDialog->eventButtonSelected += MyGUI::newDelegate(this, &CharacterCreation::onClassQuestionChosen);
mGenerateClassQuestionDialog->setVisible(true);
2019-08-11 12:22:02 +00:00
MWBase::Environment::get().getSoundManager()->say(step.mSound);
2013-04-17 22:56:48 +00:00
}
void CharacterCreation::selectGeneratedClass()
2013-04-17 22:56:48 +00:00
{
MWBase::Environment::get().getWindowManager()->removeDialog(mGenerateClassResultDialog);
2020-11-13 07:39:47 +00:00
mGenerateClassResultDialog = nullptr;
2013-04-17 22:56:48 +00:00
MWBase::Environment::get().getMechanicsManager()->setPlayerClass(mGenerateClass);
2013-04-17 22:56:48 +00:00
const ESM::Class *klass =
MWBase::Environment::get().getWorld()->getStore().get<ESM::Class>().find(mGenerateClass);
2013-04-17 22:56:48 +00:00
mPlayerClass = *klass;
updatePlayerHealth();
}
void CharacterCreation::onGenerateClassBack()
{
selectGeneratedClass();
MWBase::Environment::get().getWindowManager()->popGuiMode();
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
}
void CharacterCreation::onGenerateClassDone(WindowBase* parWindow)
{
selectGeneratedClass();
2015-03-11 23:43:28 +00:00
handleDialogDone(CSE_ClassChosen, GM_Birth);
2012-05-23 10:23:35 +00:00
}
2013-04-17 22:56:48 +00:00
CharacterCreation::~CharacterCreation()
{
2013-04-17 22:56:48 +00:00
delete mNameDialog;
delete mRaceDialog;
delete mClassChoiceDialog;
delete mGenerateClassQuestionDialog;
delete mGenerateClassResultDialog;
delete mPickClassDialog;
delete mCreateClassDialog;
delete mBirthSignDialog;
delete mReviewDialog;
}
2015-03-11 23:43:28 +00:00
void CharacterCreation::handleDialogDone(CSE currentStage, int nextMode)
{
MWBase::Environment::get().getWindowManager()->popGuiMode();
if (mCreationStage == CSE_ReviewNext)
{
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Review);
}
/*
Start of tes3mp change (major)
Servers have control over character generation in multiplayer, which is why
the automatic transition to the next character generation menu has been
commented out here
*/
/*
2015-03-11 23:43:28 +00:00
else if (mCreationStage >= currentStage)
{
MWBase::Environment::get().getWindowManager()->pushGuiMode((GuiMode)nextMode);
}
*/
/*
End of tes3mp change (major)
*/
2015-03-11 23:43:28 +00:00
else
{
mCreationStage = currentStage;
}
}
2012-01-30 17:27:49 +00:00
}