|
|
|
#include "charactercreation.hpp"
|
|
|
|
|
|
|
|
#include <components/fallback/fallback.hpp>
|
|
|
|
|
|
|
|
#include "../mwbase/environment.hpp"
|
|
|
|
#include "../mwbase/soundmanager.hpp"
|
|
|
|
#include "../mwbase/mechanicsmanager.hpp"
|
|
|
|
#include "../mwbase/world.hpp"
|
|
|
|
#include "../mwbase/windowmanager.hpp"
|
|
|
|
|
|
|
|
#include "../mwmechanics/npcstats.hpp"
|
|
|
|
#include "../mwmechanics/actorutil.hpp"
|
|
|
|
|
|
|
|
#include "../mwworld/class.hpp"
|
|
|
|
#include "../mwworld/esmstore.hpp"
|
|
|
|
#include "../mwworld/player.hpp"
|
|
|
|
|
|
|
|
#include "textinput.hpp"
|
|
|
|
#include "race.hpp"
|
|
|
|
#include "class.hpp"
|
|
|
|
#include "birth.hpp"
|
|
|
|
#include "review.hpp"
|
|
|
|
#include "inventorywindow.hpp"
|
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
struct Step
|
|
|
|
{
|
|
|
|
const std::string mText;
|
|
|
|
const std::string mButtons[3];
|
|
|
|
const std::string mSound;
|
|
|
|
};
|
|
|
|
|
|
|
|
const ESM::Class::Specialization mSpecializations[3]={ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}; // The specialization for each answer
|
|
|
|
Step sGenerateClassSteps(int number) {
|
|
|
|
number++;
|
|
|
|
const Fallback::Map* fallback=MWBase::Environment::get().getWorld()->getFallback();
|
|
|
|
Step step = {fallback->getFallbackString("Question_"+MyGUI::utility::toString(number)+"_Question"),
|
|
|
|
{fallback->getFallbackString("Question_"+MyGUI::utility::toString(number)+"_AnswerOne"),
|
|
|
|
fallback->getFallbackString("Question_"+MyGUI::utility::toString(number)+"_AnswerTwo"),
|
|
|
|
fallback->getFallbackString("Question_"+MyGUI::utility::toString(number)+"_AnswerThree")},
|
|
|
|
"vo\\misc\\chargen qa"+MyGUI::utility::toString(number)+".wav"
|
|
|
|
};
|
|
|
|
return step;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct ClassPoint
|
|
|
|
{
|
|
|
|
const char *id;
|
|
|
|
// Specialization points to match, in order: Stealth, Combat, Magic
|
|
|
|
// Note: Order is taken from http://www.uesp.net/wiki/Morrowind:Class_Quiz
|
|
|
|
unsigned int points[3];
|
|
|
|
};
|
|
|
|
|
|
|
|
void updatePlayerHealth()
|
|
|
|
{
|
|
|
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
|
|
|
MWMechanics::NpcStats& npcStats = player.getClass().getNpcStats(player);
|
|
|
|
npcStats.updateHealth();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace MWGui
|
|
|
|
{
|
|
|
|
|
|
|
|
CharacterCreation::CharacterCreation(osg::Group* parent, Resource::ResourceSystem* resourceSystem)
|
|
|
|
: mParent(parent)
|
|
|
|
, mResourceSystem(resourceSystem)
|
|
|
|
, mNameDialog(0)
|
|
|
|
, mRaceDialog(0)
|
|
|
|
, mClassChoiceDialog(0)
|
|
|
|
, mGenerateClassQuestionDialog(0)
|
|
|
|
, mGenerateClassResultDialog(0)
|
|
|
|
, mPickClassDialog(0)
|
|
|
|
, mCreateClassDialog(0)
|
|
|
|
, mBirthSignDialog(0)
|
|
|
|
, mReviewDialog(0)
|
|
|
|
, mGenerateClassStep(0)
|
|
|
|
{
|
|
|
|
mCreationStage = CSE_NotStarted;
|
|
|
|
mGenerateClassSpecializations[0] = 0;
|
|
|
|
mGenerateClassSpecializations[1] = 0;
|
|
|
|
mGenerateClassSpecializations[2] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::setValue (const std::string& id, const MWMechanics::AttributeValue& value)
|
|
|
|
{
|
|
|
|
if (mReviewDialog)
|
|
|
|
{
|
|
|
|
static const char *ids[] =
|
|
|
|
{
|
|
|
|
"AttribVal1", "AttribVal2", "AttribVal3", "AttribVal4", "AttribVal5",
|
|
|
|
"AttribVal6", "AttribVal7", "AttribVal8",
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
for (int i=0; ids[i]; ++i)
|
|
|
|
{
|
|
|
|
if (ids[i]==id)
|
|
|
|
mReviewDialog->setAttribute(ESM::Attribute::AttributeID(i), value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value)
|
|
|
|
{
|
|
|
|
if (mReviewDialog)
|
|
|
|
{
|
|
|
|
if (id == "HBar")
|
|
|
|
{
|
|
|
|
mReviewDialog->setHealth (value);
|
|
|
|
}
|
|
|
|
else if (id == "MBar")
|
|
|
|
{
|
|
|
|
mReviewDialog->setMagicka (value);
|
|
|
|
}
|
|
|
|
else if (id == "FBar")
|
|
|
|
{
|
|
|
|
mReviewDialog->setFatigue (value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value)
|
|
|
|
{
|
|
|
|
if (mReviewDialog)
|
|
|
|
mReviewDialog->setSkillValue(parSkill, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::configureSkills (const SkillList& major, const SkillList& minor)
|
|
|
|
{
|
|
|
|
if (mReviewDialog)
|
|
|
|
mReviewDialog->configureSkills(major, minor);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::onFrame(float duration)
|
|
|
|
{
|
|
|
|
if (mReviewDialog)
|
|
|
|
mReviewDialog->onFrame(duration);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::spawnDialog(const char id)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
switch (id)
|
|
|
|
{
|
|
|
|
case GM_Name:
|
|
|
|
MWBase::Environment::get().getWindowManager()->removeDialog(mNameDialog);
|
|
|
|
mNameDialog = 0;
|
|
|
|
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);
|
|
|
|
mRaceDialog = 0;
|
|
|
|
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);
|
|
|
|
mClassChoiceDialog = 0;
|
|
|
|
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);
|
|
|
|
mPickClassDialog = 0;
|
|
|
|
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);
|
|
|
|
mBirthSignDialog = 0;
|
|
|
|
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);
|
|
|
|
mReviewDialog = 0;
|
|
|
|
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() );
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
std::map<int, MWMechanics::AttributeValue > attributes = MWBase::Environment::get().getWindowManager()->getPlayerAttributeValues();
|
|
|
|
for (std::map<int, MWMechanics::AttributeValue >::iterator it = attributes.begin();
|
|
|
|
it != attributes.end(); ++it)
|
|
|
|
{
|
|
|
|
mReviewDialog->setAttribute(static_cast<ESM::Attribute::AttributeID> (it->first), it->second);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
std::map<int, MWMechanics::SkillValue > skills = MWBase::Environment::get().getWindowManager()->getPlayerSkillValues();
|
|
|
|
for (std::map<int, MWMechanics::SkillValue >::iterator it = skills.begin();
|
|
|
|
it != skills.end(); ++it)
|
|
|
|
{
|
|
|
|
mReviewDialog->setSkillValue(static_cast<ESM::Skill::SkillEnum> (it->first), it->second);
|
|
|
|
}
|
|
|
|
mReviewDialog->configureSkills(MWBase::Environment::get().getWindowManager()->getPlayerMajorSkills(), MWBase::Environment::get().getWindowManager()->getPlayerMinorSkills());
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
std::cerr << "Error: Failed to create chargen window: " << e.what() << std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::onReviewDialogDone(WindowBase* parWindow)
|
|
|
|
{
|
|
|
|
MWBase::Environment::get().getWindowManager()->removeDialog(mReviewDialog);
|
|
|
|
mReviewDialog = 0;
|
|
|
|
|
|
|
|
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::onReviewDialogBack()
|
|
|
|
{
|
|
|
|
MWBase::Environment::get().getWindowManager()->removeDialog(mReviewDialog);
|
|
|
|
mReviewDialog = 0;
|
|
|
|
mCreationStage = CSE_ReviewBack;
|
|
|
|
|
|
|
|
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
|
|
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Birth);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::onReviewActivateDialog(int parDialog)
|
|
|
|
{
|
|
|
|
MWBase::Environment::get().getWindowManager()->removeDialog(mReviewDialog);
|
|
|
|
mReviewDialog = 0;
|
|
|
|
mCreationStage = CSE_ReviewNext;
|
|
|
|
|
|
|
|
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
|
|
|
|
|
|
|
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);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::selectPickedClass()
|
|
|
|
{
|
|
|
|
if (mPickClassDialog)
|
|
|
|
{
|
|
|
|
const std::string &classId = mPickClassDialog->getClassId();
|
|
|
|
if (!classId.empty())
|
|
|
|
MWBase::Environment::get().getMechanicsManager()->setPlayerClass(classId);
|
|
|
|
|
|
|
|
const ESM::Class *klass =
|
|
|
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::Class>().find(classId);
|
|
|
|
if (klass)
|
|
|
|
{
|
|
|
|
mPlayerClass = *klass;
|
|
|
|
MWBase::Environment::get().getWindowManager()->setPlayerClass(mPlayerClass);
|
|
|
|
}
|
|
|
|
MWBase::Environment::get().getWindowManager()->removeDialog(mPickClassDialog);
|
|
|
|
mPickClassDialog = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
updatePlayerHealth();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::onPickClassDialogDone(WindowBase* parWindow)
|
|
|
|
{
|
|
|
|
selectPickedClass();
|
|
|
|
|
|
|
|
handleDialogDone(CSE_ClassChosen, GM_Birth);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::onPickClassDialogBack()
|
|
|
|
{
|
|
|
|
selectPickedClass();
|
|
|
|
|
|
|
|
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
|
|
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::onClassChoice(int _index)
|
|
|
|
{
|
|
|
|
MWBase::Environment::get().getWindowManager()->removeDialog(mClassChoiceDialog);
|
|
|
|
mClassChoiceDialog = 0;
|
|
|
|
|
|
|
|
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::onNameDialogDone(WindowBase* parWindow)
|
|
|
|
{
|
|
|
|
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)
|
|
|
|
*/
|
|
|
|
|
|
|
|
MWBase::Environment::get().getWindowManager()->setValue("name", mPlayerName);
|
|
|
|
MWBase::Environment::get().getMechanicsManager()->setPlayerName(mPlayerName);
|
|
|
|
MWBase::Environment::get().getWindowManager()->removeDialog(mNameDialog);
|
|
|
|
mNameDialog = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
handleDialogDone(CSE_NameChosen, GM_Race);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::selectRace()
|
|
|
|
{
|
|
|
|
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();
|
|
|
|
|
|
|
|
MWBase::Environment::get().getWindowManager()->removeDialog(mRaceDialog);
|
|
|
|
mRaceDialog = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
updatePlayerHealth();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::onRaceDialogBack()
|
|
|
|
{
|
|
|
|
selectRace();
|
|
|
|
|
|
|
|
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
|
|
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Name);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::onRaceDialogDone(WindowBase* parWindow)
|
|
|
|
{
|
|
|
|
selectRace();
|
|
|
|
|
|
|
|
handleDialogDone(CSE_RaceChosen, GM_Class);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::selectBirthSign()
|
|
|
|
{
|
|
|
|
if (mBirthSignDialog)
|
|
|
|
{
|
|
|
|
mPlayerBirthSignId = mBirthSignDialog->getBirthId();
|
|
|
|
if (!mPlayerBirthSignId.empty())
|
|
|
|
MWBase::Environment::get().getMechanicsManager()->setPlayerBirthsign(mPlayerBirthSignId);
|
|
|
|
MWBase::Environment::get().getWindowManager()->removeDialog(mBirthSignDialog);
|
|
|
|
mBirthSignDialog = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
updatePlayerHealth();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::onBirthSignDialogDone(WindowBase* parWindow)
|
|
|
|
{
|
|
|
|
selectBirthSign();
|
|
|
|
|
|
|
|
handleDialogDone(CSE_BirthSignChosen, GM_Review);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::onBirthSignDialogBack()
|
|
|
|
{
|
|
|
|
selectBirthSign();
|
|
|
|
|
|
|
|
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
|
|
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::selectCreatedClass()
|
|
|
|
{
|
|
|
|
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];
|
|
|
|
}
|
|
|
|
|
|
|
|
MWBase::Environment::get().getMechanicsManager()->setPlayerClass(klass);
|
|
|
|
mPlayerClass = klass;
|
|
|
|
MWBase::Environment::get().getWindowManager()->setPlayerClass(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();
|
|
|
|
|
|
|
|
handleDialogDone(CSE_ClassChosen, GM_Birth);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::onCreateClassDialogBack()
|
|
|
|
{
|
|
|
|
// not done in MW, but we do it for consistency with the other dialogs
|
|
|
|
selectCreatedClass();
|
|
|
|
|
|
|
|
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
|
|
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::onClassQuestionChosen(int _index)
|
|
|
|
{
|
|
|
|
MWBase::Environment::get().getSoundManager()->stopSay();
|
|
|
|
|
|
|
|
MWBase::Environment::get().getWindowManager()->removeDialog(mGenerateClassQuestionDialog);
|
|
|
|
mGenerateClassQuestionDialog = 0;
|
|
|
|
|
|
|
|
if (_index < 0 || _index >= 3)
|
|
|
|
{
|
|
|
|
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
|
|
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ESM::Class::Specialization specialization = mSpecializations[_index];
|
|
|
|
if (specialization == ESM::Class::Stealth)
|
|
|
|
++mGenerateClassSpecializations[0];
|
|
|
|
else if (specialization == ESM::Class::Combat)
|
|
|
|
++mGenerateClassSpecializations[1];
|
|
|
|
else if (specialization == ESM::Class::Magic)
|
|
|
|
++mGenerateClassSpecializations[2];
|
|
|
|
++mGenerateClassStep;
|
|
|
|
showClassQuestionDialog();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::showClassQuestionDialog()
|
|
|
|
{
|
|
|
|
if (mGenerateClassStep == 10)
|
|
|
|
{
|
|
|
|
static boost::array<ClassPoint, 23> classes = { {
|
|
|
|
{"Acrobat", {6, 2, 2}},
|
|
|
|
{"Agent", {6, 1, 3}},
|
|
|
|
{"Archer", {3, 5, 2}},
|
|
|
|
{"Archer", {5, 5, 0}},
|
|
|
|
{"Assassin", {6, 3, 1}},
|
|
|
|
{"Barbarian", {3, 6, 1}},
|
|
|
|
{"Bard", {3, 3, 3}},
|
|
|
|
{"Battlemage", {1, 3, 6}},
|
|
|
|
{"Crusader", {1, 6, 3}},
|
|
|
|
{"Healer", {3, 1, 6}},
|
|
|
|
{"Knight", {2, 6, 2}},
|
|
|
|
{"Monk", {5, 3, 2}},
|
|
|
|
{"Nightblade", {4, 2, 4}},
|
|
|
|
{"Pilgrim", {5, 2, 3}},
|
|
|
|
{"Rogue", {3, 4, 3}},
|
|
|
|
{"Rogue", {4, 4, 2}},
|
|
|
|
{"Rogue", {5, 4, 1}},
|
|
|
|
{"Scout", {2, 5, 3}},
|
|
|
|
{"Sorcerer", {2, 2, 6}},
|
|
|
|
{"Spellsword", {2, 4, 4}},
|
|
|
|
{"Spellsword", {5, 1, 4}},
|
|
|
|
{"Witchhunter", {2, 3, 5}},
|
|
|
|
{"Witchhunter", {5, 0, 5}}
|
|
|
|
} };
|
|
|
|
|
|
|
|
int match = -1;
|
|
|
|
for (unsigned i = 0; i < classes.size(); ++i)
|
|
|
|
{
|
|
|
|
if (mGenerateClassSpecializations[0] == classes[i].points[0] &&
|
|
|
|
mGenerateClassSpecializations[1] == classes[i].points[1] &&
|
|
|
|
mGenerateClassSpecializations[2] == classes[i].points[2])
|
|
|
|
{
|
|
|
|
match = i;
|
|
|
|
mGenerateClass = classes[i].id;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (match == -1)
|
|
|
|
{
|
|
|
|
if (mGenerateClassSpecializations[0] >= 7)
|
|
|
|
mGenerateClass = "Thief";
|
|
|
|
else if (mGenerateClassSpecializations[1] >= 7)
|
|
|
|
mGenerateClass = "Warrior";
|
|
|
|
else if (mGenerateClassSpecializations[2] >= 7)
|
|
|
|
mGenerateClass = "Mage";
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::cout << "Failed to deduce class from chosen answers in generate class dialog" << std::endl;
|
|
|
|
mGenerateClass = "Thief";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MWBase::Environment::get().getWindowManager()->removeDialog(mGenerateClassResultDialog);
|
|
|
|
mGenerateClassResultDialog = 0;
|
|
|
|
|
|
|
|
mGenerateClassResultDialog = new GenerateClassResultDialog();
|
|
|
|
mGenerateClassResultDialog->setClassId(mGenerateClass);
|
|
|
|
mGenerateClassResultDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onGenerateClassBack);
|
|
|
|
mGenerateClassResultDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onGenerateClassDone);
|
|
|
|
mGenerateClassResultDialog->setVisible(true);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mGenerateClassStep > 10)
|
|
|
|
{
|
|
|
|
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
|
|
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
MWBase::Environment::get().getWindowManager()->removeDialog(mGenerateClassQuestionDialog);
|
|
|
|
mGenerateClassQuestionDialog = 0;
|
|
|
|
|
|
|
|
mGenerateClassQuestionDialog = new InfoBoxDialog();
|
|
|
|
|
|
|
|
InfoBoxDialog::ButtonList buttons;
|
|
|
|
mGenerateClassQuestionDialog->setText(sGenerateClassSteps(mGenerateClassStep).mText);
|
|
|
|
buttons.push_back(sGenerateClassSteps(mGenerateClassStep).mButtons[0]);
|
|
|
|
buttons.push_back(sGenerateClassSteps(mGenerateClassStep).mButtons[1]);
|
|
|
|
buttons.push_back(sGenerateClassSteps(mGenerateClassStep).mButtons[2]);
|
|
|
|
mGenerateClassQuestionDialog->setButtons(buttons);
|
|
|
|
mGenerateClassQuestionDialog->eventButtonSelected += MyGUI::newDelegate(this, &CharacterCreation::onClassQuestionChosen);
|
|
|
|
mGenerateClassQuestionDialog->setVisible(true);
|
|
|
|
|
|
|
|
MWBase::Environment::get().getSoundManager()->say(sGenerateClassSteps(mGenerateClassStep).mSound);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::selectGeneratedClass()
|
|
|
|
{
|
|
|
|
MWBase::Environment::get().getWindowManager()->removeDialog(mGenerateClassResultDialog);
|
|
|
|
mGenerateClassResultDialog = 0;
|
|
|
|
|
|
|
|
MWBase::Environment::get().getMechanicsManager()->setPlayerClass(mGenerateClass);
|
|
|
|
|
|
|
|
const ESM::Class *klass =
|
|
|
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::Class>().find(mGenerateClass);
|
|
|
|
|
|
|
|
mPlayerClass = *klass;
|
|
|
|
MWBase::Environment::get().getWindowManager()->setPlayerClass(mPlayerClass);
|
|
|
|
|
|
|
|
updatePlayerHealth();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::onGenerateClassBack()
|
|
|
|
{
|
|
|
|
selectGeneratedClass();
|
|
|
|
|
|
|
|
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
|
|
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::onGenerateClassDone(WindowBase* parWindow)
|
|
|
|
{
|
|
|
|
selectGeneratedClass();
|
|
|
|
|
|
|
|
handleDialogDone(CSE_ClassChosen, GM_Birth);
|
|
|
|
}
|
|
|
|
|
|
|
|
CharacterCreation::~CharacterCreation()
|
|
|
|
{
|
|
|
|
delete mNameDialog;
|
|
|
|
delete mRaceDialog;
|
|
|
|
delete mClassChoiceDialog;
|
|
|
|
delete mGenerateClassQuestionDialog;
|
|
|
|
delete mGenerateClassResultDialog;
|
|
|
|
delete mPickClassDialog;
|
|
|
|
delete mCreateClassDialog;
|
|
|
|
delete mBirthSignDialog;
|
|
|
|
delete mReviewDialog;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CharacterCreation::handleDialogDone(CSE currentStage, int nextMode)
|
|
|
|
{
|
|
|
|
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
|
|
|
if (mCreationStage == CSE_ReviewNext)
|
|
|
|
{
|
|
|
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Review);
|
|
|
|
}
|
[Client] Disable automatic transition to other chargen menus from OpenMW
Previously, after finishing the TES3MP chargen once, mCreationStage was set to 4 in OpenMW, which in turn made it impossible to go through only specific chargen menus again as the result of the relevant TES3MP script function (tes3mp.SetCharGenStage(pid, startStage, endStage) in 0.6.3, player:setCharGenStages(startStage, endStage) in 0.7). In other words, trying to allow a player to just choose their class again made it so the player started at that menu and went through all the other subsequent menus as well, i.e. the player went through the class, birthsign and review menus.
7 years ago
|
|
|
/*
|
|
|
|
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
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
else if (mCreationStage >= currentStage)
|
|
|
|
{
|
|
|
|
MWBase::Environment::get().getWindowManager()->pushGuiMode((GuiMode)nextMode);
|
|
|
|
}
|
[Client] Disable automatic transition to other chargen menus from OpenMW
Previously, after finishing the TES3MP chargen once, mCreationStage was set to 4 in OpenMW, which in turn made it impossible to go through only specific chargen menus again as the result of the relevant TES3MP script function (tes3mp.SetCharGenStage(pid, startStage, endStage) in 0.6.3, player:setCharGenStages(startStage, endStage) in 0.7). In other words, trying to allow a player to just choose their class again made it so the player started at that menu and went through all the other subsequent menus as well, i.e. the player went through the class, birthsign and review menus.
7 years ago
|
|
|
*/
|
|
|
|
/*
|
|
|
|
End of tes3mp change (major)
|
|
|
|
*/
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mCreationStage = currentStage;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|