feat: Load character attributes from blueprint and during chargen
This commit is contained in:
parent
8801a22eec
commit
f735bd673d
11 changed files with 214 additions and 33 deletions
|
@ -384,6 +384,7 @@ set(GAME_HEADERS
|
|||
src/game/player.h
|
||||
src/game/portraits.h
|
||||
src/game/room.h
|
||||
src/game/rp/classes.h
|
||||
src/game/rp/types.h
|
||||
src/game/script/routines.h
|
||||
src/game/script/util.h
|
||||
|
@ -456,6 +457,7 @@ set(GAME_SOURCES
|
|||
src/game/player.cpp
|
||||
src/game/portraits.cpp
|
||||
src/game/room.cpp
|
||||
src/game/rp/classes.cpp
|
||||
src/game/script/routines.cpp
|
||||
src/game/script/routines_common.cpp
|
||||
src/game/script/routines_kotor.cpp
|
||||
|
|
|
@ -40,7 +40,28 @@ void CreatureBlueprint::load(const GffStruct &utc) {
|
|||
|
||||
_appearance = utc.getInt("Appearance_Type");
|
||||
_conversation = utc.getString("Conversation");
|
||||
_scripts[ScriptType::Spawn] = utc.getString("ScriptSpawn");
|
||||
|
||||
loadAttributes(utc);
|
||||
loadScripts(utc);
|
||||
}
|
||||
|
||||
void CreatureBlueprint::loadAttributes(const GffStruct &utc) {
|
||||
for (auto &classGff : utc.getList("ClassList")) {
|
||||
int clazz = classGff.getInt("Class");
|
||||
int level = classGff.getInt("ClassLevel");
|
||||
_attributes.classLevels.push_back(make_pair(static_cast<ClassType>(clazz), level));
|
||||
}
|
||||
_attributes.abilities[Ability::Strength] = utc.getInt("Str");
|
||||
_attributes.abilities[Ability::Dexterity] = utc.getInt("Dex");
|
||||
_attributes.abilities[Ability::Constitution] = utc.getInt("Con");
|
||||
_attributes.abilities[Ability::Intelligence] = utc.getInt("Int");
|
||||
_attributes.abilities[Ability::Wisdom] = utc.getInt("Wis");
|
||||
_attributes.abilities[Ability::Charisma] = utc.getInt("Cha");
|
||||
}
|
||||
|
||||
void CreatureBlueprint::loadScripts(const GffStruct &utc) {
|
||||
_onSpawn = utc.getString("ScriptSpawn");
|
||||
_onUserDefined = utc.getString("ScriptUserDefine");
|
||||
}
|
||||
|
||||
const string &CreatureBlueprint::tag() const {
|
||||
|
@ -59,6 +80,18 @@ const string &CreatureBlueprint::conversation() const {
|
|||
return _conversation;
|
||||
}
|
||||
|
||||
const CreatureAttributes &CreatureBlueprint::attributes() const {
|
||||
return _attributes;
|
||||
}
|
||||
|
||||
const string &CreatureBlueprint::onSpawn() const {
|
||||
return _onSpawn;
|
||||
}
|
||||
|
||||
const string &CreatureBlueprint::onUserDefined() const {
|
||||
return _onUserDefined;
|
||||
}
|
||||
|
||||
} // namespace game
|
||||
|
||||
} // namespace reone
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
|
||||
#include "../../resource/gfffile.h"
|
||||
|
||||
#include "../rp/types.h"
|
||||
|
||||
namespace reone {
|
||||
|
||||
namespace game {
|
||||
|
@ -37,32 +39,29 @@ public:
|
|||
const std::vector<std::string> &equipment() const;
|
||||
int appearance() const;
|
||||
const std::string &conversation() const;
|
||||
const CreatureAttributes &attributes() const;
|
||||
const std::string &onSpawn() const;
|
||||
const std::string &onUserDefined() const;
|
||||
|
||||
private:
|
||||
enum class ScriptType {
|
||||
OnNotice,
|
||||
SpellAt,
|
||||
Attacked,
|
||||
Damaged,
|
||||
Disturbed,
|
||||
EndRound,
|
||||
EndDialogu,
|
||||
Dialogue,
|
||||
Spawn,
|
||||
Rested,
|
||||
Death,
|
||||
UserDefine,
|
||||
OnBlocked
|
||||
};
|
||||
|
||||
std::string _tag;
|
||||
std::vector<std::string> _equipment;
|
||||
int _appearance { 0 };
|
||||
std::string _conversation;
|
||||
std::unordered_map<ScriptType, std::string> _scripts;
|
||||
CreatureAttributes _attributes;
|
||||
|
||||
// Scripts
|
||||
|
||||
std::string _onSpawn;
|
||||
std::string _onUserDefined;
|
||||
|
||||
// END Scripts
|
||||
|
||||
CreatureBlueprint(const CreatureBlueprint &) = delete;
|
||||
CreatureBlueprint &operator=(const CreatureBlueprint &) = delete;
|
||||
|
||||
void loadAttributes(const resource::GffStruct &utc);
|
||||
void loadScripts(const resource::GffStruct &utc);
|
||||
};
|
||||
|
||||
} // namespace game
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "../../game.h"
|
||||
#include "../../portraits.h"
|
||||
#include "../../rp/classes.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace std::placeholders;
|
||||
|
@ -65,9 +66,7 @@ void CharacterGeneration::load() {
|
|||
hideControl("NEW_LBL");
|
||||
|
||||
setControlText("LBL_NAME", "");
|
||||
setControlText("LBL_CLASS", "");
|
||||
setControlText("LBL_LEVEL", "");
|
||||
setControlText("LBL_LEVEL_VAL", "");
|
||||
setControlText("LBL_LEVEL_VAL", "1");
|
||||
|
||||
loadClassSelection();
|
||||
loadQuickOrCustom();
|
||||
|
@ -232,9 +231,28 @@ const CreatureConfiguration &CharacterGeneration::character() const {
|
|||
void CharacterGeneration::setCharacter(const CreatureConfiguration &config) {
|
||||
_character = config;
|
||||
loadCharacterModel();
|
||||
updateAttributes();
|
||||
_portraitSelection->updatePortraits();
|
||||
}
|
||||
|
||||
void CharacterGeneration::updateAttributes() {
|
||||
setControlText("LBL_CLASS", getClassTitle(_character.clazz));
|
||||
|
||||
CreatureAttributes attrs(getClassAttributes(_character.clazz));
|
||||
int vitality = getClassHitPoints(_character.clazz, 1) + (attrs.constitution() - 10) / 2;
|
||||
int defense = 10 + getClassDefenseBonus(_character.clazz, 1) + (attrs.dexterity() - 10) / 2;
|
||||
|
||||
setControlText("LBL_VIT", to_string(vitality));
|
||||
setControlText("LBL_DEF", to_string(defense));
|
||||
|
||||
setControlText("STR_AB_LBL", to_string(attrs.strength()));
|
||||
setControlText("DEX_AB_LBL", to_string(attrs.dexterity()));
|
||||
setControlText("CON_AB_LBL", to_string(attrs.constitution()));
|
||||
setControlText("INT_AB_LBL", to_string(attrs.intelligence()));
|
||||
setControlText("WIS_AB_LBL", to_string(attrs.wisdom()));
|
||||
setControlText("CHA_AB_LBL", to_string(attrs.charisma()));
|
||||
}
|
||||
|
||||
void CharacterGeneration::setQuickStep(int step) {
|
||||
_quick->setStep(step);
|
||||
}
|
||||
|
|
|
@ -83,6 +83,7 @@ private:
|
|||
// END Sub GUI
|
||||
|
||||
void loadCharacterModel();
|
||||
void updateAttributes();
|
||||
|
||||
gui::GUI *getSubGUI() const;
|
||||
std::shared_ptr<scene::ModelSceneNode> getCharacterModel(scene::SceneGraph &sceneGraph);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "../../characters.h"
|
||||
#include "../../game.h"
|
||||
#include "../../object/creature.h"
|
||||
#include "../../rp/classes.h"
|
||||
|
||||
#include "../colors.h"
|
||||
|
||||
|
@ -47,15 +48,6 @@ static map<Gender, int> g_genderStrRefs {
|
|||
{ Gender::Female, 647 }
|
||||
};
|
||||
|
||||
static map<ClassType, int> g_classStrRefs {
|
||||
{ ClassType::Scout, 133 },
|
||||
{ ClassType::Soldier, 134 },
|
||||
{ ClassType::Scoundrel, 135 },
|
||||
{ ClassType::JediGuardian, 353 },
|
||||
{ ClassType::JediConsular, 354 },
|
||||
{ ClassType::JediSentinel, 355 }
|
||||
};
|
||||
|
||||
static map<ClassType, int> g_classDescStrRefs {
|
||||
{ ClassType::Scoundrel, 32109 },
|
||||
{ ClassType::Scout, 32110 },
|
||||
|
@ -228,7 +220,7 @@ void ClassSelection::onFocusChanged(const string &control, bool focus) {
|
|||
ClassButton &button = _classButtons[idx];
|
||||
|
||||
string classText(Resources::instance().getString(g_genderStrRefs[button.config.gender]));
|
||||
classText += " " + Resources::instance().getString(g_classStrRefs[button.config.clazz]);
|
||||
classText += " " + getClassTitle(button.config.clazz);
|
||||
|
||||
string descText(Resources::instance().getString(g_classDescStrRefs[button.config.clazz]));
|
||||
|
||||
|
|
|
@ -93,6 +93,10 @@ void Creature::load(const shared_ptr<CreatureBlueprint> &blueprint) {
|
|||
}
|
||||
shared_ptr<TwoDaTable> appearance(Resources::instance().get2DA("appearance"));
|
||||
loadAppearance(*appearance, _blueprint->appearance());
|
||||
|
||||
_attributes = blueprint->attributes();
|
||||
_onSpawn = blueprint->onSpawn();
|
||||
_onUserDefined = blueprint->onUserDefined();
|
||||
}
|
||||
|
||||
void Creature::loadAppearance(const TwoDaTable &table, int row) {
|
||||
|
|
|
@ -116,6 +116,13 @@ private:
|
|||
float _runSpeed { 0.0f };
|
||||
MovementType _movementType { MovementType::None };
|
||||
bool _talking { false };
|
||||
CreatureAttributes _attributes;
|
||||
|
||||
// Scripts
|
||||
|
||||
std::string _onSpawn;
|
||||
|
||||
// END Scripts
|
||||
|
||||
// Loading
|
||||
|
||||
|
|
82
src/game/rp/classes.cpp
Normal file
82
src/game/rp/classes.cpp
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Vsevolod Kremianskii
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "classes.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "../../resource/resources.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
using namespace reone::resource;
|
||||
|
||||
namespace reone {
|
||||
|
||||
namespace game {
|
||||
|
||||
static map<ClassType, int> g_classStrRefs {
|
||||
{ ClassType::Scout, 133 },
|
||||
{ ClassType::Soldier, 134 },
|
||||
{ ClassType::Scoundrel, 135 },
|
||||
{ ClassType::JediGuardian, 353 },
|
||||
{ ClassType::JediConsular, 354 },
|
||||
{ ClassType::JediSentinel, 355 }
|
||||
};
|
||||
|
||||
const string &getClassTitle(ClassType clazz) {
|
||||
int strRef = g_classStrRefs.find(clazz)->second;
|
||||
return Resources::instance().getString(strRef);
|
||||
}
|
||||
|
||||
CreatureAttributes getClassAttributes(ClassType clazz) {
|
||||
shared_ptr<TwoDaTable> classes(Resources::instance().get2DA("classes"));
|
||||
int row = static_cast<int>(clazz);
|
||||
|
||||
CreatureAttributes attrs;
|
||||
attrs.abilities.insert(make_pair(Ability::Strength, classes->getInt(row, "str")));
|
||||
attrs.abilities.insert(make_pair(Ability::Dexterity, classes->getInt(row, "dex")));
|
||||
attrs.abilities.insert(make_pair(Ability::Constitution, classes->getInt(row, "con")));
|
||||
attrs.abilities.insert(make_pair(Ability::Intelligence, classes->getInt(row, "int")));
|
||||
attrs.abilities.insert(make_pair(Ability::Wisdom, classes->getInt(row, "wis")));
|
||||
attrs.abilities.insert(make_pair(Ability::Charisma, classes->getInt(row, "cha")));
|
||||
|
||||
return move(attrs);
|
||||
}
|
||||
|
||||
int getClassHitPoints(ClassType clazz, int level) {
|
||||
shared_ptr<TwoDaTable> classes(Resources::instance().get2DA("classes"));
|
||||
int row = static_cast<int>(clazz);
|
||||
|
||||
return level * classes->getInt(row, "hitdie");
|
||||
}
|
||||
|
||||
int getClassDefenseBonus(ClassType clazz, int level) {
|
||||
switch (clazz) {
|
||||
case ClassType::JediConsular:
|
||||
case ClassType::JediGuardian:
|
||||
case ClassType::JediSentinel:
|
||||
case ClassType::Scoundrel:
|
||||
return 2 + (2 * (level / 6));
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace game
|
||||
|
||||
} // namespace reone
|
35
src/game/rp/classes.h
Normal file
35
src/game/rp/classes.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Vsevolod Kremianskii
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "types.h"
|
||||
|
||||
namespace reone {
|
||||
|
||||
namespace game {
|
||||
|
||||
const std::string &getClassTitle(ClassType clazz);
|
||||
CreatureAttributes getClassAttributes(ClassType clazz);
|
||||
int getClassHitPoints(ClassType clazz, int level);
|
||||
int getClassDefenseBonus(ClassType clazz, int level);
|
||||
|
||||
} // namespace game
|
||||
|
||||
} // namespace reone
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
|
@ -74,8 +75,15 @@ enum class Skill {
|
|||
|
||||
struct CreatureAttributes {
|
||||
std::vector<std::pair<ClassType, int>> classLevels;
|
||||
std::vector<int> abilities;
|
||||
std::vector<int> skills;
|
||||
std::map<Ability, int> abilities;
|
||||
std::map<Skill, int> skills;
|
||||
|
||||
int strength() const { return abilities.find(Ability::Strength)->second; }
|
||||
int dexterity() const { return abilities.find(Ability::Dexterity)->second; }
|
||||
int constitution() const { return abilities.find(Ability::Constitution)->second; }
|
||||
int intelligence() const { return abilities.find(Ability::Intelligence)->second; }
|
||||
int wisdom() const { return abilities.find(Ability::Wisdom)->second; }
|
||||
int charisma() const { return abilities.find(Ability::Charisma)->second; }
|
||||
};
|
||||
|
||||
} // namespace game
|
||||
|
|
Loading…
Reference in a new issue