Skip to content

Commit

Permalink
Reworked player attribute types.
Browse files Browse the repository at this point in the history
Started showing proper attribute values in character sheet.
  • Loading branch information
afritz1 committed Nov 19, 2024
1 parent f41ee20 commit 489d11d
Show file tree
Hide file tree
Showing 31 changed files with 141 additions and 521 deletions.
11 changes: 1 addition & 10 deletions OpenTESArena/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -478,17 +478,8 @@ SET(TES_SKY
"${SRC_ROOT}/Sky/SkyVisibilityManager.h")

SET(TES_STATS
"${SRC_ROOT}/Stats/AttributeModifier.cpp"
"${SRC_ROOT}/Stats/AttributeModifier.h"
"${SRC_ROOT}/Stats/AttributeModifierName.h"
"${SRC_ROOT}/Stats/DerivedAttribute.cpp"
"${SRC_ROOT}/Stats/DerivedAttribute.h"
"${SRC_ROOT}/Stats/DerivedAttributeName.h"
"${SRC_ROOT}/Stats/PrimaryAttribute.cpp"
"${SRC_ROOT}/Stats/PrimaryAttribute.h"
"${SRC_ROOT}/Stats/PrimaryAttributeName.h"
"${SRC_ROOT}/Stats/PrimaryAttributeSet.cpp"
"${SRC_ROOT}/Stats/PrimaryAttributeSet.h")
"${SRC_ROOT}/Stats/PrimaryAttribute.h")

SET(TES_TIME
"${SRC_ROOT}/Time/ArenaClockUtils.cpp"
Expand Down
2 changes: 2 additions & 0 deletions OpenTESArena/src/Assets/ExeData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ bool ExeData::Entities::init(const char *data, const KeyValueFile &keyValueFile)
return false;
}

const int attributeNamesOffset = ExeData::get(*section, "AttributeNames");
const int creatureNamesOffset = ExeData::get(*section, "CreatureNames");
const int creatureLevelsOffset = ExeData::get(*section, "CreatureLevels");
const int creatureHitPointsOffset = ExeData::get(*section, "CreatureHitPoints");
Expand Down Expand Up @@ -389,6 +390,7 @@ bool ExeData::Entities::init(const char *data, const KeyValueFile &keyValueFile)
const int citizenColorBaseOffset = ExeData::get(*section, "CitizenColorBase");
const int citizenSkinColorsOffset = ExeData::get(*section, "CitizenSkinColors");

initStringArray(this->attributeNames, data + attributeNamesOffset);
initStringArray(this->creatureNames, data + creatureNamesOffset);
initInt8Array(this->creatureLevels, data + creatureLevelsOffset);
initInt16PairArray(this->creatureHitPoints, data + creatureHitPointsOffset);
Expand Down
2 changes: 2 additions & 0 deletions OpenTESArena/src/Assets/ExeData.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ class ExeData

struct Entities
{
std::array<std::string, 8> attributeNames; // Strength, ... Luck.

// Creature races are 1-based.
std::array<std::string, 23> creatureNames; // Rat, Goblin, ...
std::array<uint8_t, 24> creatureLevels; // Zero-based, as with the player.
Expand Down
12 changes: 5 additions & 7 deletions OpenTESArena/src/Entities/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
#include "../Math/Constants.h"
#include "../Math/Quaternion.h"
#include "../Math/Random.h"
#include "../Stats/PrimaryAttributeName.h"
#include "../Voxels/VoxelChunkManager.h"
#include "../World/CardinalDirection.h"

Expand Down Expand Up @@ -165,7 +164,7 @@ void Player::init(const std::string &displayName, bool male, int raceID, int cha
this->portraitID = portraitID;
this->maxWalkSpeed = maxWalkSpeed;
this->weaponAnimation.init(weaponID, exeData);
this->attributes.init(raceID, male, random);
this->primaryAttributes.init(raceID, male, exeData);
this->inventory.clear();

if (!TryCreatePhysicsCharacters(physicsSystem, &this->physicsCharacter, &this->physicsCharacterVirtual, &this->physicsCharVsCharCollision))
Expand All @@ -179,7 +178,7 @@ void Player::init(const std::string &displayName, bool male, int raceID, int cha
}

void Player::init(const std::string &displayName, bool male, int raceID, int charClassDefID,
PrimaryAttributeSet &&attributes, int portraitID, const CoordDouble3 &position, const Double3 &direction,
const PrimaryAttributes &primaryAttributes, int portraitID, const CoordDouble3 &position, const Double3 &direction,
const Double3 &velocity, double maxWalkSpeed, int weaponID, const ExeData &exeData, JPH::PhysicsSystem &physicsSystem)
{
this->displayName = displayName;
Expand All @@ -189,8 +188,8 @@ void Player::init(const std::string &displayName, bool male, int raceID, int cha
this->charClassDefID = charClassDefID;
this->portraitID = portraitID;
this->maxWalkSpeed = maxWalkSpeed;
this->weaponAnimation.init(weaponID, exeData);
this->attributes = std::move(attributes);
this->weaponAnimation.init(weaponID, exeData);
this->primaryAttributes = primaryAttributes;
this->inventory.clear();

if (!TryCreatePhysicsCharacters(physicsSystem, &this->physicsCharacter, &this->physicsCharacterVirtual, &this->physicsCharVsCharCollision))
Expand All @@ -216,8 +215,7 @@ void Player::initRandom(const CharacterClassLibrary &charClassLibrary, const Exe
const CharacterClassDefinition &charClassDef = charClassLibrary.getDefinition(this->charClassDefID);
const int weaponID = GetRandomWeaponIdForClass(charClassDef, random);
this->weaponAnimation.init(weaponID, exeData);
this->attributes.init(this->raceID, this->male, random);

this->primaryAttributes.init(this->raceID, this->male, exeData);
this->inventory.clear();
const ItemLibrary &itemLibrary = ItemLibrary::getInstance();
for (int i = 0; i < itemLibrary.getCount(); i++)
Expand Down
6 changes: 3 additions & 3 deletions OpenTESArena/src/Entities/Player.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#include "../Assets/MIFUtils.h"
#include "../Items/ItemInventory.h"
#include "../Math/MathUtils.h"
#include "../Stats/PrimaryAttributeSet.h"
#include "../Stats/PrimaryAttribute.h"
#include "../World/Coord.h"

class CharacterClassLibrary;
Expand Down Expand Up @@ -52,7 +52,7 @@ struct Player
int portraitID;
double maxWalkSpeed; // Eventually a function of 'Speed' attribute
WeaponAnimation weaponAnimation;
PrimaryAttributeSet attributes;
PrimaryAttributes primaryAttributes;
ItemInventory inventory;

Player();
Expand All @@ -64,7 +64,7 @@ struct Player
double maxWalkSpeed, int weaponID, const ExeData &exeData, JPH::PhysicsSystem &physicsSystem, Random &random);

// Make player with given attributes.
void init(const std::string &displayName, bool male, int raceID, int charClassDefID, PrimaryAttributeSet &&attributes,
void init(const std::string &displayName, bool male, int raceID, int charClassDefID, const PrimaryAttributes &primaryAttributes,
int portraitID, const CoordDouble3 &position, const Double3 &direction, const Double3 &velocity,
double maxWalkSpeed, int weaponID, const ExeData &exeData, JPH::PhysicsSystem &physicsSystem);

Expand Down
7 changes: 5 additions & 2 deletions OpenTESArena/src/Game/CharacterCreationState.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <cstdio>

#include "CharacterCreationState.h"
#include "../Assets/BinaryAssetLibrary.h"

#include "components/debug/Debug.h"

Expand All @@ -24,7 +25,7 @@ int CharacterCreationState::getRaceIndex() const
return this->raceIndex;
}

const PrimaryAttributeSet &CharacterCreationState::getAttributes() const
const PrimaryAttributes &CharacterCreationState::getAttributes() const
{
return this->attributes;
}
Expand Down Expand Up @@ -56,7 +57,9 @@ void CharacterCreationState::setRaceIndex(int index)

void CharacterCreationState::rollAttributes(Random &random)
{
this->attributes.init(this->raceIndex, this->male, random);
const BinaryAssetLibrary &binaryAssetLibrary = BinaryAssetLibrary::getInstance();
const ExeData &exeData = binaryAssetLibrary.getExeData();
this->attributes.init(this->raceIndex, this->male, exeData);
}

void CharacterCreationState::setPortraitIndex(int index)
Expand Down
6 changes: 3 additions & 3 deletions OpenTESArena/src/Game/CharacterCreationState.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include <string_view>

#include "../Math/Random.h"
#include "../Stats/PrimaryAttributeSet.h"
#include "../Stats/PrimaryAttribute.h"

class CharacterCreationState
{
Expand All @@ -20,14 +20,14 @@ class CharacterCreationState
int raceIndex;
int portraitIndex;
bool male;
PrimaryAttributeSet attributes;
PrimaryAttributes attributes;
public:
CharacterCreationState();

const std::string_view getName() const;
int getClassDefID() const;
int getRaceIndex() const;
const PrimaryAttributeSet &getAttributes() const;
const PrimaryAttributes &getAttributes() const;
int getPortraitIndex() const;
bool isMale() const;

Expand Down
4 changes: 2 additions & 2 deletions OpenTESArena/src/Interface/CharacterCreationUiController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -558,15 +558,15 @@ void ChooseAttributesUiController::onSavedDoneButtonSelected(Game &game)
const int charClassDefID = charCreationState.getClassDefID();
const auto &charClassDef = charClassLibrary.getDefinition(charClassDefID);

PrimaryAttributeSet attributes = charCreationState.getAttributes();
const PrimaryAttributes &attributes = charCreationState.getAttributes();

const int portraitIndex = charCreationState.getPortraitIndex();

const int allowedWeaponCount = charClassDef.getAllowedWeaponCount();
const int weaponID = charClassDef.getAllowedWeapon(game.random.next(allowedWeaponCount));

Player &player = game.player;
player.init(std::string(name), male, raceIndex, charClassDefID, std::move(attributes), portraitIndex,
player.init(std::string(name), male, raceIndex, charClassDefID, attributes, portraitIndex,
dummyPosition, direction, velocity, PlayerConstants::DEFAULT_WALK_SPEED, weaponID, exeData, game.physicsSystem);
};

Expand Down
6 changes: 3 additions & 3 deletions OpenTESArena/src/Interface/CharacterCreationUiModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ std::string CharacterCreationUiModel::getPlayerClassName(Game &game)
return charClassDef.getName();
}

std::vector<PrimaryAttribute> CharacterCreationUiModel::getPlayerAttributes(Game &game)
const PrimaryAttributes &CharacterCreationUiModel::getPlayerAttributes(Game &game)
{
const CharacterCreationState &charCreationState = game.getCharacterCreationState();
const PrimaryAttributeSet &attributeSet = charCreationState.getAttributes();
return attributeSet.getAll();
const PrimaryAttributes &attributes = charCreationState.getAttributes();
return attributes;
}

std::string ChooseClassCreationUiModel::getTitleText(Game &game)
Expand Down
2 changes: 1 addition & 1 deletion OpenTESArena/src/Interface/CharacterCreationUiModel.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace CharacterCreationUiModel
std::string getPlayerName(Game &game);
std::string getPlayerRaceName(Game &game);
std::string getPlayerClassName(Game &game);
std::vector<PrimaryAttribute> getPlayerAttributes(Game &game);
const PrimaryAttributes &getPlayerAttributes(Game &game);
}

namespace ChooseClassCreationUiModel
Expand Down
28 changes: 13 additions & 15 deletions OpenTESArena/src/Interface/CharacterPanel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include "../Input/InputActionMapName.h"
#include "../Input/InputActionName.h"
#include "../Stats/PrimaryAttribute.h"
#include "../Stats/PrimaryAttributeName.h"
#include "../UI/CursorData.h"
#include "../UI/FontLibrary.h"

Expand Down Expand Up @@ -58,20 +57,19 @@ bool CharacterPanel::init()
return false;
}

const std::vector<PrimaryAttribute> playerAttributes = CharacterSheetUiModel::getPlayerAttributes(game);
const std::map<PrimaryAttributeName, TextBox::InitInfo> playerAttributesTextBoxInitInfoMap =
CharacterSheetUiView::getPlayerAttributeTextBoxInitInfoMap(playerAttributes, fontLibrary);
for (const PrimaryAttribute &attribute : playerAttributes)
const PrimaryAttributes &playerAttributes = CharacterSheetUiModel::getPlayerAttributes(game);
const BufferView<const PrimaryAttribute> playerAttributesView = playerAttributes.getAttributes();
const std::vector<TextBox::InitInfo> playerAttributesTextBoxInitInfos = CharacterSheetUiView::getPlayerAttributeTextBoxInitInfos(playerAttributesView, fontLibrary);
for (int i = 0; i < playerAttributesView.getCount(); i++)
{
const int attributeValue = attribute.get();
const PrimaryAttribute &attribute = playerAttributesView.get(i);
const int attributeValue = attribute.maxValue;
const std::string attributeValueText = std::to_string(attributeValue);
const PrimaryAttributeName attributeName = attribute.getAttributeName();
const TextBox::InitInfo attributeTextBoxInitInfo = playerAttributesTextBoxInitInfoMap.at(attributeName);
this->playerAttributeTextBoxes.emplace_back(TextBox());
if (!this->playerAttributeTextBoxes.back().init(attributeTextBoxInitInfo, attributeValueText, renderer))
DebugAssertIndex(playerAttributesTextBoxInitInfos, i);
const TextBox::InitInfo &attributeTextBoxInitInfo = playerAttributesTextBoxInitInfos[i];
if (!this->playerAttributeTextBoxes[i].init(attributeTextBoxInitInfo, attributeValueText, renderer))
{
const std::string attributeNameText = attribute.toString();
DebugLogError("Couldn't init player " + attributeNameText + " text box.");
DebugLogError("Couldn't init player attribute " + std::string(attribute.name) + " text box.");
return false;
}
}
Expand Down Expand Up @@ -173,11 +171,11 @@ bool CharacterPanel::init()
Int2(playerClassTextBoxRect.getWidth(), playerClassTextBoxRect.getHeight()),
PivotType::TopLeft);

for (int i = 0; i < this->playerAttributeTextBoxes.size(); i++)
for (TextBox &playerAttributeTextBox : this->playerAttributeTextBoxes)
{
const Rect &playerAttributeTextBoxRect = this->playerAttributeTextBoxes[i].getRect();
const Rect &playerAttributeTextBoxRect = playerAttributeTextBox.getRect();
this->addDrawCall(
this->playerAttributeTextBoxes[i].getTextureID(),
playerAttributeTextBox.getTextureID(),
playerAttributeTextBoxRect.getTopLeft(),
Int2(playerAttributeTextBoxRect.getWidth(), playerAttributeTextBoxRect.getHeight()),
PivotType::TopLeft);
Expand Down
6 changes: 2 additions & 4 deletions OpenTESArena/src/Interface/CharacterPanel.h
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
#ifndef CHARACTER_PANEL_H
#define CHARACTER_PANEL_H

#include <vector>

#include "Panel.h"
#include "../Stats/PrimaryAttribute.h"
#include "../UI/Button.h"
#include "../UI/TextBox.h"

class Renderer;
class TextBox;

// The character portrait panel that shows the player's attributes and derived stats.
// @todo Maybe rename this to "CharacterStatsPanel"?
class CharacterPanel : public Panel
{
private:
TextBox playerNameTextBox, playerRaceTextBox, playerClassTextBox;
std::vector<TextBox> playerAttributeTextBoxes;
TextBox playerAttributeTextBoxes[PrimaryAttributes::COUNT];
Button<Game&> doneButton, nextPageButton;
ScopedUiTextureRef bodyTextureRef, headTextureRef, shirtTextureRef, pantsTextureRef,
statsBgTextureRef, nextPageTextureRef, cursorTextureRef;
Expand Down
5 changes: 2 additions & 3 deletions OpenTESArena/src/Interface/CharacterSheetUiModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ std::string CharacterSheetUiModel::getPlayerClassName(Game &game)
return charClassDef.getName();
}

std::vector<PrimaryAttribute> CharacterSheetUiModel::getPlayerAttributes(Game &game)
const PrimaryAttributes &CharacterSheetUiModel::getPlayerAttributes(Game &game)
{
const Player &player = game.player;
return player.attributes.getAll();
return game.player.primaryAttributes;
}
2 changes: 1 addition & 1 deletion OpenTESArena/src/Interface/CharacterSheetUiModel.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace CharacterSheetUiModel
std::string getPlayerName(Game &game);
std::string getPlayerRaceName(Game &game);
std::string getPlayerClassName(Game &game);
std::vector<PrimaryAttribute> getPlayerAttributes(Game &game);
const PrimaryAttributes &getPlayerAttributes(Game &game);
}

#endif
13 changes: 5 additions & 8 deletions OpenTESArena/src/Interface/CharacterSheetUiView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
#include "../Entities/CharacterClassLibrary.h"
#include "../Game/Game.h"
#include "../Stats/PrimaryAttribute.h"
#include "../Stats/PrimaryAttributeName.h"

TextBox::InitInfo CharacterSheetUiView::getPlayerNameTextBoxInitInfo(const std::string_view text,
const FontLibrary &fontLibrary)
Expand Down Expand Up @@ -50,16 +49,14 @@ TextBox::InitInfo CharacterSheetUiView::getPlayerClassTextBoxInitInfo(const std:
fontLibrary);
}

std::map<PrimaryAttributeName, TextBox::InitInfo> CharacterSheetUiView::getPlayerAttributeTextBoxInitInfoMap(
BufferView<const PrimaryAttribute> attributes, const FontLibrary &fontLibrary)
std::vector<TextBox::InitInfo> CharacterSheetUiView::getPlayerAttributeTextBoxInitInfos(BufferView<const PrimaryAttribute> attributes, const FontLibrary &fontLibrary)
{
std::map<PrimaryAttributeName, TextBox::InitInfo> textBoxInitInfoMap;
std::vector<TextBox::InitInfo> textBoxInitInfos;

for (int i = 0; i < attributes.getCount(); i++)
{
const PrimaryAttribute &attribute = attributes[i];
const PrimaryAttributeName attributeName = attribute.getAttributeName();
const int attributeValue = attribute.get();
const int attributeValue = attribute.maxValue;
const std::string attributeValueStr = std::to_string(attributeValue);
TextBox::InitInfo initInfo = TextBox::InitInfo::makeWithXY(
attributeValueStr,
Expand All @@ -70,10 +67,10 @@ std::map<PrimaryAttributeName, TextBox::InitInfo> CharacterSheetUiView::getPlaye
CharacterSheetUiView::PlayerAttributeTextBoxAlignment,
fontLibrary);

textBoxInitInfoMap.emplace(attributeName, std::move(initInfo));
textBoxInitInfos.emplace_back(std::move(initInfo));
}

return textBoxInitInfoMap;
return textBoxInitInfos;
}

Int2 CharacterSheetUiView::getBodyOffset(Game &game)
Expand Down
4 changes: 1 addition & 3 deletions OpenTESArena/src/Interface/CharacterSheetUiView.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include "../Rendering/ArenaRenderUtils.h"
#include "../Rendering/RenderTextureUtils.h"
#include "../Stats/PrimaryAttribute.h"
#include "../Stats/PrimaryAttributeName.h"
#include "../UI/ArenaFontName.h"
#include "../UI/TextAlignment.h"
#include "../UI/TextBox.h"
Expand Down Expand Up @@ -50,8 +49,7 @@ namespace CharacterSheetUiView
TextBox::InitInfo getPlayerNameTextBoxInitInfo(const std::string_view text, const FontLibrary &fontLibrary);
TextBox::InitInfo getPlayerRaceTextBoxInitInfo(const std::string_view text, const FontLibrary &fontLibrary);
TextBox::InitInfo getPlayerClassTextBoxInitInfo(const std::string_view text, const FontLibrary &fontLibrary);
std::map<PrimaryAttributeName, TextBox::InitInfo> getPlayerAttributeTextBoxInitInfoMap(
BufferView<const PrimaryAttribute> attributes, const FontLibrary &fontLibrary);
std::vector<TextBox::InitInfo> getPlayerAttributeTextBoxInitInfos(BufferView<const PrimaryAttribute> attributes, const FontLibrary &fontLibrary);

const Int2 DoneButtonCenterPoint(25, ArenaRenderUtils::SCREEN_HEIGHT - 15);
constexpr int DoneButtonWidth = 21;
Expand Down
Loading

0 comments on commit 489d11d

Please sign in to comment.