Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/xp #21

Merged
merged 7 commits into from
Mar 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/cmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,9 @@ jobs:
overwrite: true

emscripten:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
env:
EM_VERSION: 3.1.9
EM_VERSION: 3.1.55
EM_CACHE_FOLDER: "emsdk-cache"
steps:
- uses: actions/checkout@v2
Expand Down
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@
"queue": "cpp",
"regex": "cpp",
"unordered_set": "cpp",
"__availability": "cpp"
"__availability": "cpp",
"span": "cpp"
},
"[cpp]": {
"editor.defaultFormatter": "xaver.clang-format"
Expand Down
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ target_include_directories(${PROJECT_NAME}
)


# Ensure the C++17 standard is available.
# Ensure the C++20 standard is available.
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_20)

# Enforce UTF-8 encoding on MSVC.
Expand All @@ -48,7 +48,7 @@ endif()
if (EMSCRIPTEN)
# Attach data folder to Emscripten builds.
target_link_options(${PROJECT_NAME} PRIVATE --preload-file "${CMAKE_CURRENT_SOURCE_DIR}/data@data" -fexceptions -lidbfs.js)
target_compile_options(${PROJECT_NAME} PRIVATE -fexceptions)
target_compile_options(${PROJECT_NAME} PRIVATE -fexceptions -std=c++20)
# Set output to html to generate preview pages, otherwise you'll have to make your own html.
configure_file(
${PROJECT_SOURCE_DIR}/emscripten/index.html
Expand Down
2 changes: 2 additions & 0 deletions include/colours.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ static constexpr auto DARK_GREEN = tcod::ColorRGB{0, 191, 0};
static constexpr auto BLUE = tcod::ColorRGB{0, 0, 255};
static constexpr auto DARK_BLUE = tcod::ColorRGB{0, 0, 191};
static constexpr auto TEAL = tcod::ColorRGB{0, 128, 128};
static constexpr auto DARK_GREY = tcod::ColorRGB{64, 64, 64};
static constexpr auto LIGHT_BLUE = tcod::ColorRGB{0, 128, 255};

static constexpr auto BAR_TEXT = WHITE;
static constexpr auto INVALID = tcod::ColorRGB{0xFF, 0xFF, 0x00};
Expand Down
64 changes: 62 additions & 2 deletions include/components.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@

namespace cpprl {

class AttackComponent {
class AttackComponent {
public:
AttackComponent() = default;
explicit AttackComponent(int damage) : damage_(damage) {}
virtual ~AttackComponent() = default;
int get_damage() const { return damage_; }
void boost_damage(int amount) { damage_ += amount; }

template <class Archive>
void serialize(Archive& archive) {
Expand All @@ -39,6 +40,7 @@ class DefenseComponent {
int get_hp() const { return hp_; }
int get_max_hp() const { return max_hp_; }
int get_defense() const { return defense_; }
void boost_defense(int amount) { defense_ += amount; }

void take_damage(int damage) { hp_ -= damage; }
int heal(int amount);
Expand Down Expand Up @@ -224,11 +226,69 @@ class ConfusionSpell final : public ConsumableComponent {
}
};

/**
* @brief StatsData
* Simple data structure to hold stats data
*/
struct StatsData {
int xp_;
int level_;
int level_up_base_;
int level_up_factor_;
int stats_points_;

template <class Archive>
void serialize(Archive& archive) {
archive(xp_, level_, level_up_base_, level_up_factor_, stats_points_);
}
};

/**
* @brief StatsComponent
* Component used to manipulate stats data.
*/
class StatsComponent {
public:
StatsComponent() = default;
explicit StatsComponent(StatsData stats_data) : stats_data_(stats_data) {}
StatsComponent(
int xp,
int level,
int level_up_base,
int level_up_factor,
int stats_points)
: stats_data_{xp, level, level_up_base, level_up_factor, stats_points} {}
virtual ~StatsComponent() = default;

int get_xp() const { return stats_data_.xp_; }
int get_level() const { return stats_data_.level_; }
int get_level_up_base() const { return stats_data_.level_up_base_; }
int get_level_up_factor() const { return stats_data_.level_up_factor_; }
void reduce_stats_points(int amount) { stats_data_.stats_points_ -= amount; }
int get_stats_points() const { return stats_data_.stats_points_; }
int get_next_level_xp() const {
return stats_data_.level_up_base_ +
stats_data_.level_ * stats_data_.level_up_factor_;
}

void add_xp(int xp);
void level_up();

template <class Archive>
void serialize(Archive& archive) {
archive(stats_data_);
}

private:
StatsData stats_data_;
};

} // namespace cpprl

CEREAL_REGISTER_TYPE(cpprl::HealingConsumable);
CEREAL_REGISTER_TYPE(cpprl::LightningBolt);
CEREAL_REGISTER_TYPE(cpprl::FireSpell);
CEREAL_REGISTER_TYPE(cpprl::ConfusionSpell);

CEREAL_REGISTER_TYPE(cpprl::StatsComponent);
CEREAL_REGISTER_TYPE(cpprl::AttackComponent);
#endif
2 changes: 1 addition & 1 deletion include/entity_factory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class AbstractEntityFactory {

protected:
Entity* create_base(
std::string name, tcod::ColorRGB color, std::string_view symbol);
const std::string& name, tcod::ColorRGB color, std::string_view symbol);
};

class OrcFactory : public AbstractEntityFactory {
Expand Down
6 changes: 4 additions & 2 deletions include/entity_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
#include "types/map.hpp"

namespace cpprl {

typedef std::optional<std::reference_wrapper<Entity>> OptEntityRef;

class EntityManager {
public:
EntityManager() {
Expand All @@ -21,8 +24,7 @@ class EntityManager {
EntityManager(
std::unique_ptr<AbstractEntityFactory> orc_factory,
std::unique_ptr<AbstractEntityFactory> troll_factory)
: entities_{},
orc_factory_(std::move(orc_factory)),
: orc_factory_(std::move(orc_factory)),
troll_factory_(std::move(troll_factory)){};
void clear();
void clear_except_player();
Expand Down
16 changes: 16 additions & 0 deletions include/events/command.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ class InventoryCommand final : public Command {
StateResult execute() override;
};

class CharacterMenuCommand final : public Command {
public:
using Command::Command;
StateResult execute() override;
};

class MainMenuCommand final : public EngineEvent {
public:
MainMenuCommand(World& world) : EngineEvent(world) {}
Expand Down Expand Up @@ -127,6 +133,16 @@ class UseItemCommand final : public Command {
StateResult execute() override;
};

class BoostStatCommand final : public EngineEvent {
private:
UiWindow& ui_window_;

public:
BoostStatCommand(World& world, UiWindow& ui_window)
: EngineEvent(world), ui_window_(ui_window) {}
StateResult execute() override;
};

class CloseViewCommand final : public EngineEvent {
public:
CloseViewCommand(World& world) : EngineEvent(world){};
Expand Down
19 changes: 19 additions & 0 deletions include/game_entity.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class ASCIIComponent;
class AttackComponent;
class DefenseComponent;
class ConsumableComponent;
class StatsComponent;
class Container;

class Entity {
Expand All @@ -28,6 +29,7 @@ class Entity {
std::unique_ptr<ConsumableComponent> consumableComponent_;
std::unique_ptr<AIComponent> aiComponent_;
std::unique_ptr<Container> container_;
std::unique_ptr<StatsComponent> statsComponent_;

public:
Entity(
Expand All @@ -54,6 +56,15 @@ class Entity {
return std::nullopt;
}
};

std::optional<std::reference_wrapper<StatsComponent>> get_stats_component() {
if (statsComponent_) {
return std::ref(*statsComponent_);
} else {
return std::nullopt;
}
};

std::unique_ptr<AIComponent> transfer_ai_component();
Container& get_container() { return *container_; };
float get_distance_to(Entity* other) const;
Expand All @@ -72,6 +83,7 @@ class Entity {
std::unique_ptr<ConsumableComponent> consumableComponent);
void set_ai_component(std::unique_ptr<AIComponent> aiComponent);
void set_container(std::unique_ptr<Container> container);
void set_stats_component(std::unique_ptr<StatsComponent> aiComponent);

template <class Archive>
void pack(Archive& archive) {
Expand All @@ -83,6 +95,7 @@ class Entity {
archive(asciiComponent_ != nullptr);
archive(aiComponent_ != nullptr);
archive(container_ != nullptr);
archive(statsComponent_ != nullptr);
if (transformComponent_) archive(transformComponent_);

if (asciiComponent_) archive(asciiComponent_);
Expand All @@ -91,6 +104,7 @@ class Entity {
if (consumableComponent_) archive(consumableComponent_);
if (aiComponent_) archive(aiComponent_);
if (container_) archive(container_);
if (statsComponent_) archive(statsComponent_);
}

template <class Archive>
Expand All @@ -102,6 +116,7 @@ class Entity {
bool hasAsciiComponent;
bool hasAIComponent;
bool hasContainer;
bool hasStatsComponent;

archive(name_, blocker_);
archive(hasTransformComponent);
Expand All @@ -111,6 +126,7 @@ class Entity {
archive(hasAsciiComponent);
archive(hasAIComponent);
archive(hasContainer);
archive(hasStatsComponent);

if (hasTransformComponent) {
archive(transformComponent_);
Expand All @@ -133,6 +149,9 @@ class Entity {
if (hasContainer) {
archive(container_);
}
if (hasStatsComponent) {
archive(statsComponent_);
}
}
};

Expand Down
18 changes: 18 additions & 0 deletions include/gui.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,24 @@ class InventoryWindow final : public UiWindow {
virtual void render(tcod::Console& parent_console) override;
};

class CharacterMenuWindow final : public UiWindow {
private:
Entity* entity_;

public:
CharacterMenuWindow(
std::size_t width,
std::size_t height,
Vector2D position,
Entity* entity,
std::string title = "")
: UiWindow(width, height, position, title), entity_(entity) {
UiWindow::set_cursor(1);
};

virtual void render(tcod::Console& parent_console) override;
};

class GameOverWindow final : public UiWindow {
private:
std::string message_;
Expand Down
13 changes: 13 additions & 0 deletions include/input_handler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class GameInputHandler final : public EventHandler {
std::unique_ptr<InventoryCommand> inventory_command_;
std::unique_ptr<MainMenuCommand> main_menu_command_;
std::unique_ptr<UseCommand> use_command_;
std::unique_ptr<CharacterMenuCommand> character_menu_command_;
Entity* controllable_entity_;

public:
Expand Down Expand Up @@ -122,6 +123,18 @@ class InventoryInputHandler final : public GuiInputHandler {
EngineEvent& handle_sdl_event(SDL_Event event) noexcept override;
};

class CharacterMenuInputHandler final : public GuiInputHandler {
private:
std::unique_ptr<BoostStatCommand> boost_stat_command_;

public:
CharacterMenuInputHandler(World& world, UiWindow& ui_window)
: GuiInputHandler(world, ui_window),
boost_stat_command_(
std::make_unique<BoostStatCommand>(world, ui_window)){};
EngineEvent& handle_sdl_event(SDL_Event event) noexcept override;
};

class MainMenuInputHandler final : public GuiInputHandler {
private:
std::unique_ptr<SelectMenuItemCommand> selectMenuItemCommand_;
Expand Down
9 changes: 8 additions & 1 deletion include/state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,14 @@ class MainMenuState final : public GuiViewState {
MainMenuState(World& world, UiWindow* window) : GuiViewState(world, window) {}
~MainMenuState() { delete window_; }
void on_enter() override;
}; // namespace cpprl
};

class CharacterMenuState final : public GuiViewState {
public:
CharacterMenuState(World& world, UiWindow* window)
: GuiViewState(world, window) {}
void on_enter() override;
};

} // namespace cpprl

Expand Down
5 changes: 4 additions & 1 deletion include/ui/ui.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,20 @@

#include "health_bar.hpp"
#include "ui/dungeon_level.hpp"
#include "xp_bar.hpp"

namespace cpprl {
class UI {
private:
std::unique_ptr<DungeonLevel> dungeon_level_;
std::unique_ptr<HealthBar> health_bar_;
std::unique_ptr<XPBar> xp_bar_;

public:
UI(Dungeon& dungeon);
explicit UI(Dungeon& dungeon);

void set_health_bar(DefenseComponent& defense_component);
void set_xp_bar(StatsComponent& stats_component);

void render(tcod::Console& console);
};
Expand Down
2 changes: 0 additions & 2 deletions include/world.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ class World {
std::unique_ptr<EntityManager> entities_;
Dungeon dungeon_;
MessageLog message_log_;
UiWindow* health_bar_;
// TODO: makes more sense as part of a gui class
std::unique_ptr<UI> ui_;
std::unique_ptr<Controller> controller_;
UiWindow* current_window_;
Expand Down