Initial commit

This commit is contained in:
Deukhoofd 2019-10-06 13:50:52 +02:00
commit 265923231f
Signed by: Deukhoofd
GPG Key ID: ADF2E9256009EDCE
44 changed files with 16258 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/cmake-build-debug/
/.idea/

45
CMakeLists.txt Normal file
View File

@ -0,0 +1,45 @@
cmake_minimum_required(VERSION 3.15)
if (NOT CMAKE_C_COMPILER)
if (GCC)
set(CMAKE_C_COMPILER "gcc")
set(CMAKE_CXX_COMPILER "g++")
else()
set(CMAKE_C_COMPILER "clang")
set(CMAKE_CXX_COMPILER "clang++")
endif(GCC)
endif(NOT CMAKE_C_COMPILER)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror")
project(CreatureLib)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if (WINDOWS)
ADD_DEFINITIONS(-D WINDOWS=1)
endif(WINDOWS)
file(GLOB_RECURSE CORE_SRC_FILES "src/Core/*.cpp" "src/Core/*.hpp")
add_library(CreatureLibCore SHARED ${CORE_SRC_FILES})
file(GLOB_RECURSE LIBRARY_SRC_FILES "src/Library/*.cpp" "src/Library/*.hpp")
add_library(CreatureLibLibrary SHARED ${LIBRARY_SRC_FILES})
file(GLOB_RECURSE TEST_FILES "tests/*.cpp" "tests/*.hpp")
add_executable(CreatureLibTests ${TEST_FILES} extern/catch.hpp)
target_link_libraries(CreatureLibLibrary -static-libgcc -static-libstdc++)
target_link_libraries(CreatureLibTests -static-libgcc -static-libstdc++)
target_link_libraries(CreatureLibLibrary CreatureLibCore)
target_link_libraries(CreatureLibTests CreatureLibLibrary)
if (WINDOWS)
target_link_libraries(CreatureLibLibrary -static -static-libgcc -static-libstdc++)
target_link_libraries(CreatureLibTests -static -static-libgcc -static-libstdc++)
endif(WINDOWS)
target_compile_definitions(CreatureLibTests PRIVATE TESTS_BUILD)

15003
extern/catch.hpp vendored Normal file

File diff suppressed because it is too large Load Diff

30
src/Core/Random.cpp Normal file
View File

@ -0,0 +1,30 @@
#include "Random.hpp"
#include <limits>
// Seed parameterless constructor with current milliseconds since epoch.
CreatureLib::Core::Random::Random() : _rng(std::mt19937(duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count())){}
float CreatureLib::Core::Random::GetFloat() {
return static_cast<float>(_rng()) / (static_cast<float>(std::mt19937::max() - std::mt19937::min()) - 0.5f);
}
double CreatureLib::Core::Random::GetDouble() {
return static_cast<double>(_rng()) / ((static_cast<double>(std::mt19937::max()) - std::mt19937::min()) - 0.5);
}
int32_t CreatureLib::Core::Random::Get() {
return static_cast<int32_t >(GetDouble() * static_cast<float>(std::numeric_limits<int32_t >::max()));
}
int32_t CreatureLib::Core::Random::Get(int32_t max) {
return static_cast<int32_t >(GetDouble() * static_cast<float>(max));
}
int32_t CreatureLib::Core::Random::Get(int32_t min, int32_t max) {
return static_cast<int32_t >(GetDouble() * static_cast<float>(max - min) + min);
}

23
src/Core/Random.hpp Normal file
View File

@ -0,0 +1,23 @@
#ifndef CREATURELIB_RANDOM_HPP
#define CREATURELIB_RANDOM_HPP
#include <cstdint>
#include <chrono>
#include <random>
using namespace std::chrono;
namespace CreatureLib::Core {
class Random {
private:
std::mt19937 _rng;
public:
Random();
explicit Random(int32_t seed) : _rng(seed){};
[[nodiscard]] float GetFloat();
[[nodiscard]] double GetDouble();
[[nodiscard]] int32_t Get();
[[nodiscard]] int32_t Get(int32_t max);
[[nodiscard]] int32_t Get(int32_t min, int32_t max);
};
}
#endif //CREATURELIB_RANDOM_HPP

17
src/Core/Statistic.hpp Normal file
View File

@ -0,0 +1,17 @@
#ifndef CREATURELIB_STATISTIC_HPP
#define CREATURELIB_STATISTIC_HPP
#include <cstdint>
namespace CreatureLib::Core{
enum Statistic : uint8_t {
Health,
PhysicalAttack,
PhysicalDefense,
MagicalAttack,
MagicalDefense,
Speed
};
}
#endif //CREATURELIB_STATISTIC_HPP

13
src/Core/StatisticSet.cpp Normal file
View File

@ -0,0 +1,13 @@
#include <exception>
#include "StatisticSet.hpp"
CreatureLib::Core::StatisticSet::StatisticSet(uint32_t health, uint32_t physicalAttack, uint32_t physicalDefense,
uint32_t magicalAttack, uint32_t magicalDefense, uint32_t speed)
:
__Health(health),
__PhysicalAttack(physicalAttack),
__PhysicalDefense(physicalDefense),
__MagicalAttack(magicalAttack),
__MagicalDefense(magicalDefense),
__Speed(speed)
{}

35
src/Core/StatisticSet.hpp Normal file
View File

@ -0,0 +1,35 @@
#ifndef CREATURELIB_STATISTICSET_HPP
#define CREATURELIB_STATISTICSET_HPP
#include <stdint.h>
#include "Statistic.hpp"
#include "../GenericTemplates.cpp"
namespace CreatureLib::Core{
class StatisticSet {
public:
StatisticSet(uint32_t health, uint32_t physicalAttack, uint32_t physicalDefense, uint32_t magicalAttack,
uint32_t magicalDefense, uint32_t speed);
GetSetProperty(uint32_t, Health)
GetSetProperty(uint32_t, PhysicalAttack)
GetSetProperty(uint32_t, PhysicalDefense)
GetSetProperty(uint32_t, MagicalAttack)
GetSetProperty(uint32_t, MagicalDefense)
GetSetProperty(uint32_t, Speed)
[[nodiscard]] inline uint32_t GetStat(Statistic stat) const{
switch (stat){
case Health: return __Health;
case PhysicalAttack: return __PhysicalAttack;
case PhysicalDefense: return __PhysicalDefense;
case MagicalAttack: return __MagicalAttack;
case MagicalDefense: return __MagicalDefense;
case Speed: return __Speed;
}
throw std::exception();
}
};
}
#endif //CREATURELIB_STATISTICSET_HPP

15
src/GenericTemplates.cpp Normal file
View File

@ -0,0 +1,15 @@
/*!
\brief GetProperty creates a simple wrapper for a field, creating a private field, and a public getter method.
*/
#define GetProperty(type, name) \
private: type __##name; \
public: [[nodiscard]] inline type Get##name() const{ return __##name; };
/*!
\brief GetProperty creates a simple wrapper for a field, creating a private field, a public getter method, and a public
setter method.
*/
#define GetSetProperty(type, name) \
private: type __##name; \
public: [[nodiscard]] inline type Get##name() const{ return __##name; }; \
public: inline void Set##name(type value) { __##name = value; }; \

View File

@ -0,0 +1,20 @@
#include "AttackLibrary.hpp"
const CreatureLib::Library::AttackData *CreatureLib::Library::AttackLibrary::GetAttack(const std::string &name) const {
return this->_attacks.at(name);
}
const CreatureLib::Library::AttackData *CreatureLib::Library::AttackLibrary::operator[](const std::string &name) const {
return GetAttack(name);
}
void CreatureLib::Library::AttackLibrary::LoadAttack(const std::string &name,
const CreatureLib::Library::AttackData* attack) {
this->_attacks.insert({name, attack});
}
void CreatureLib::Library::AttackLibrary::DeleteAttack(const std::string &name) {
this->_attacks.erase(name);
}

View File

@ -0,0 +1,27 @@
#ifndef CREATURELIB_ATTACKLIBRARY_HPP
#define CREATURELIB_ATTACKLIBRARY_HPP
#include <string>
#include <unordered_map>
#include "Attacks/AttackData.hpp"
namespace CreatureLib::Library {
class AttackLibrary {
private:
std::unordered_map<std::string, const AttackData*> _attacks;
public:
AttackLibrary() = default;
~AttackLibrary(){
_attacks.clear();
}
[[nodiscard]] const AttackData* GetAttack(const std::string& name) const;
[[nodiscard]] const AttackData* operator[] (const std::string& name) const;
void LoadAttack(const std::string& name, const AttackData* attack);
void DeleteAttack(const std::string& name);
};
}
#endif //CREATURELIB_ATTACKLIBRARY_HPP

View File

@ -0,0 +1,14 @@
#ifndef CREATURELIB_ATTACKCATEGORY_HPP
#define CREATURELIB_ATTACKCATEGORY_HPP
#include <cstdint>
namespace CreatureLib::Library {
enum class AttackCategory : uint8_t {
Physical,
Magical,
Status
};
}
#endif //CREATURELIB_ATTACKCATEGORY_HPP

View File

@ -0,0 +1,25 @@
#include "AttackData.hpp"
#include <utility>
CreatureLib::Library::AttackData::AttackData(std::string name, std::string type,
CreatureLib::Library::AttackCategory category, uint8_t power,
uint8_t accuracy, uint8_t baseUsage,
CreatureLib::Library::AttackTarget target, uint8_t priority,
std::unordered_set<std::string> flags)
:
__Name(std::move(name)),
__Type(std::move(type)),
__Category(category),
__BasePower(power),
__Accuracy(accuracy),
__BaseUsages(baseUsage),
__Target(target),
__Priority(priority),
_flags(std::move(flags))
{}
bool CreatureLib::Library::AttackData::HasFlag(const std::string& key) const{
return this->_flags.find(key) != this->_flags.end();
}

View File

@ -0,0 +1,32 @@
#ifndef CREATURELIB_ATTACKDATA_HPP
#define CREATURELIB_ATTACKDATA_HPP
#include <string>
#include <unordered_set>
#include "AttackCategory.hpp"
#include "AttackTarget.hpp"
#include "../../GenericTemplates.cpp"
namespace CreatureLib::Library {
class AttackData {
GetProperty(std::string, Name);
GetProperty(std::string, Type);
GetProperty(AttackCategory , Category);
GetProperty(uint8_t , BasePower);
GetProperty(uint8_t , Accuracy);
GetProperty(uint8_t , BaseUsages);
GetProperty(AttackTarget, Target);
GetProperty(uint8_t , Priority);
private:
std::unordered_set<std::string> _flags;
public:
AttackData(std::string name, std::string type, AttackCategory category, uint8_t power, uint8_t accuracy,
uint8_t baseUsage, AttackTarget target, uint8_t priority, std::unordered_set<std::string> flags);
bool HasFlag(const std::string& key) const;
};
}
#endif //CREATURELIB_ATTACKDATA_HPP

View File

@ -0,0 +1,26 @@
#ifndef CREATURELIB_ATTACKTARGET_HPP
#define CREATURELIB_ATTACKTARGET_HPP
#include <cstdint>
namespace CreatureLib::Library {
enum class AttackTarget : uint8_t{
Adjacent,
AdjacentAlly,
AdjacentAllySelf,
AdjacentOpponent,
All,
AllAdjacent,
AllAdjacentOpponent,
AllAlly,
AllOpponent,
Any,
RandomOpponent,
Self,
};
}
#endif //CREATURELIB_ATTACKTARGET_HPP

View File

@ -0,0 +1,97 @@
#include "CreateCreature.hpp"
#include <utility>
using namespace CreatureLib::Library;
CreateCreature* CreateCreature::WithVariant(std::string variant) {
this->_variant = std::move(variant);
return this;
}
CreateCreature *CreateCreature::WithNickname(std::string nickname) {
this->_nickname = std::move(nickname);
return this;
}
CreateCreature *CreateCreature::WithStatPotential(CreatureLib::Core::Statistic stat, uint32_t value) {
switch (stat){
case Core::Health:_healthPotential = value;
case Core::PhysicalAttack: _physAttackPotential = value;
case Core::PhysicalDefense: _physDefensePotential = value;
case Core::MagicalAttack: _magAttackPotential = value;
case Core::MagicalDefense:_magDefensePotential = value;
case Core::Speed: _speedPotential = value;
}
return this;
}
CreateCreature * CreateCreature::WithStatPotentials(uint32_t health, uint32_t physAttack, uint32_t physDefense,
uint32_t magAttack, uint32_t magDefense, uint32_t speed) {
_healthPotential = health;
_physAttackPotential = physAttack;
_physDefensePotential = physDefense;
_magAttackPotential = magAttack;
_magDefensePotential = magDefense;
_speedPotential = speed;
return this;
}
CreateCreature* CreateCreature::WithStatExperience(Core::Statistic stat, uint32_t value) {
switch (stat){
case Core::Health:_healthExperience = value;
case Core::PhysicalAttack: _physAttackExperience = value;
case Core::PhysicalDefense: _physDefenseExperience = value;
case Core::MagicalAttack: _magAttackExperience = value;
case Core::MagicalDefense:_magDefenseExperience = value;
case Core::Speed: _speedExperience = value;
}
return this;
}
CreateCreature *
CreateCreature::WithStatExperiences(uint32_t health, uint32_t physAttack, uint32_t physDefense, uint32_t magAttack,
uint32_t magDefense, uint32_t speed) {
_healthExperience = health;
_physAttackExperience = physAttack;
_physDefenseExperience = physDefense;
_magAttackExperience = magAttack;
_magDefenseExperience = magDefense;
_speedExperience = speed;
return this;
}
CreateCreature *CreateCreature::WithGender(Gender gender) {
this->_gender = gender;
return this;
}
Creature *CreateCreature::Create() {
auto rand = Core::Random();
auto species = this->_library->GetSpeciesLibrary()->GetSpecies(this->_species);
auto variant = species->GetVariant(this->_variant);
int8_t talent;
if (this->_talent.empty()){
talent = variant->GetRandomTalent(&rand);
}
else{
talent = variant->GetTalentIndex(this->_talent);
}
auto identifier = this->_identifier;
if (identifier == 0){
identifier = rand.Get();
}
auto gender = this->_gender;
if (gender == static_cast<Gender >(-1)){
gender = species->GetRandomGender(rand);
}
const Item* heldItem = nullptr;
if (!this->_heldItem.empty()){
heldItem = _library->GetItemLibrary()->GetItem(this->_heldItem);
}
return new Creature(this->_library, species, variant, this->_level, this->_nickname, talent,
Core::StatisticSet(_healthExperience, _physAttackExperience, _physDefenseExperience,
_magAttackExperience, _magDefenseExperience, _speedExperience),
Core::StatisticSet(_healthPotential, _physAttackPotential, _physDefensePotential,
_magAttackPotential, _magDefensePotential, _speedPotential),
identifier, gender, _coloring, heldItem);
}

View File

@ -0,0 +1,58 @@
#ifndef CREATURELIB_CREATECREATURE_HPP
#define CREATURELIB_CREATECREATURE_HPP
#include "DataLibrary.hpp"
#include "Creature.hpp"
namespace CreatureLib::Library {
class CreateCreature {
const DataLibrary *_library;
std::string _species;
std::string _variant = "default";
uint8_t _level;
std::string _nickname = "";
uint32_t _healthPotential = 0;
uint32_t _physAttackPotential = 0;
uint32_t _physDefensePotential = 0;
uint32_t _magAttackPotential = 0;
uint32_t _magDefensePotential = 0;
uint32_t _speedPotential = 0;
uint32_t _healthExperience = 0;
uint32_t _physAttackExperience = 0;
uint32_t _physDefenseExperience = 0;
uint32_t _magAttackExperience = 0;
uint32_t _magDefenseExperience = 0;
uint32_t _speedExperience = 0;
std::string _talent = "";
Gender _gender = static_cast<Gender>(-1);
uint8_t _coloring = 0;
std::string _heldItem = "";
uint32_t _identifier = 0;
public:
CreateCreature(const DataLibrary *library, std::string species, uint8_t level)
: _library(library), _species(std::move(species)), _level(level)
{
}
CreateCreature* WithVariant(std::string variant);
CreateCreature* WithNickname(std::string nickname);
CreateCreature* WithStatPotential(Core::Statistic stat, uint32_t value);
CreateCreature* WithStatPotentials(uint32_t health, uint32_t physAttack, uint32_t physDefense, uint32_t magAttack,
uint32_t magDefense,uint32_t speed);
CreateCreature* WithStatExperience(Core::Statistic stat, uint32_t value);
CreateCreature* WithStatExperiences(uint32_t health, uint32_t physAttack, uint32_t physDefense, uint32_t magAttack,
uint32_t magDefense,uint32_t speed);
CreateCreature* WithGender(Gender gender);
Creature* Create();
};
}
#endif //CREATURELIB_CREATECREATURE_HPP

36
src/Library/Creature.cpp Normal file
View File

@ -0,0 +1,36 @@
#include "Creature.hpp"
CreatureLib::Library::Creature::Creature(const CreatureLib::Library::DataLibrary *library,
const CreatureLib::Library::CreatureSpecies *species,
const CreatureLib::Library::SpeciesVariant *variant, uint8_t level,
std::string nickname, int8_t talentIndex,
CreatureLib::Core::StatisticSet statExperience,
CreatureLib::Core::StatisticSet statPotential,
uint32_t identifier, CreatureLib::Library::Gender gender, uint8_t coloring,
const CreatureLib::Library::Item *heldItem)
:
__Library(library),
__Species(species),
__Variant(variant),
__Level(level),
__StatExperience(statExperience),
__StatPotential(statPotential),
__UniqueIdentifier(identifier),
__Gender(gender),
__Coloring(coloring),
__HeldItem(heldItem),
_nickname(nickname),
_talentIndex(talentIndex)
{
}
std::string CreatureLib::Library::Creature::GetTalent() const {
return __Variant->GetTalent(_talentIndex);
}
std::string CreatureLib::Library::Creature::GetNickname() const {
if (_nickname.empty())
return __Species->GetName();
return _nickname;
}

39
src/Library/Creature.hpp Normal file
View File

@ -0,0 +1,39 @@
#ifndef CREATURELIB_CREATURE_HPP
#define CREATURELIB_CREATURE_HPP
#include "DataLibrary.hpp"
#include "Gender.hpp"
#include "../GenericTemplates.cpp"
#include "../Core/StatisticSet.hpp"
namespace CreatureLib::Library{
class Creature {
GetProperty(const DataLibrary*, Library);
GetProperty(const CreatureSpecies*, Species);
GetProperty(const SpeciesVariant*, Variant);
GetProperty(uint8_t, Level);
GetProperty(uint32_t, Experience);
GetProperty(Core::StatisticSet, StatExperience);
GetProperty(Core::StatisticSet, StatPotential);
GetProperty(uint32_t, UniqueIdentifier);
GetProperty(Gender, Gender);
GetProperty(uint8_t, Coloring);
GetProperty(const Item*, HeldItem);
GetProperty(uint32_t, CurrentHealth);
private:
std::string _nickname = "";
int8_t _talentIndex;
public:
Creature(const DataLibrary* library, const CreatureSpecies* species, const SpeciesVariant* variant,
uint8_t level, std::string nickname, int8_t talentIndex, Core::StatisticSet statExperience,
Core::StatisticSet statPotential, uint32_t identifier, Gender gender,
uint8_t coloring, const Item* heldItem);
std::string GetTalent() const;
std::string GetNickname() const;
};
}
#endif //CREATURELIB_CREATURE_HPP

View File

@ -0,0 +1,16 @@
#include "CreatureMoves.hpp"
#include <utility>
CreatureLib::Library::LevelMove::LevelMove(uint8_t level, std::string name)
:_level(level),
_name(std::move(name))
{}
uint8_t CreatureLib::Library::LevelMove::GetLevel() const {
return this->_level;
}
std::string CreatureLib::Library::LevelMove::GetName() const {
return this->_name;
}

View File

@ -0,0 +1,32 @@
#ifndef CREATURELIB_CREATUREMOVES_HPP
#define CREATURELIB_CREATUREMOVES_HPP
#include <cstdint>
#include <string>
#include <vector>
namespace CreatureLib::Library{
class LevelMove{
private:
uint8_t _level;
std::string _name;
public:
LevelMove(uint8_t level, std::string name);
[[nodiscard]] inline uint8_t GetLevel() const;
[[nodiscard]] inline std::string GetName() const;
};
class CreatureMoves {
private:
std::vector<LevelMove> _levelMoves;
std::vector<std::string> _eggMoves;
std::vector<std::string> _machineMoves;
std::vector<std::string> _tutorMoves;
std::vector<std::string> _variantDependentMoves;
public:
//TODO: Public API funcs
};
}
#endif //CREATURELIB_CREATUREMOVES_HPP

View File

@ -0,0 +1,28 @@
#include "CreatureSpecies.hpp"
#include <utility>
using namespace CreatureLib::Library;
CreatureSpecies::CreatureSpecies(uint16_t id, std::string name, const SpeciesVariant* defaultVariant,
float genderRatio, std::string growthRate, uint8_t captureRate, uint8_t baseHappiness)
:
__Id(id),
__Name(std::move(name)),
__GenderRate(genderRatio),
__GrowthRate(std::move(growthRate)),
__CaptureRate(captureRate),
__BaseHappiness(baseHappiness),
_variants({{"default", defaultVariant}})
{}
const SpeciesVariant *CreatureSpecies::GetVariant(const std::string& key) const {
return _variants.at(key);
}
Gender CreatureSpecies::GetRandomGender(CreatureLib::Core::Random &rand) const {
// TODO: Genderless creatures
auto val = rand.GetDouble();
if (val >= this->__GenderRate) return Gender ::Female;
return Gender ::Male;
}

View File

@ -0,0 +1,31 @@
#ifndef CREATURELIB_CREATURESPECIES_HPP
#define CREATURELIB_CREATURESPECIES_HPP
#include <string>
#include <unordered_map>
#include "SpeciesVariant.hpp"
#include "../Gender.hpp"
namespace CreatureLib::Library {
/*!
\brief This holds the data required for a species of a creature, so the general data we can describe different creatures with.
*/
class CreatureSpecies {
GetProperty(uint16_t, Id);
GetProperty(std::string, Name);
GetProperty(float, GenderRate);
GetProperty(std::string, GrowthRate);
GetProperty(uint8_t, CaptureRate);
GetProperty(uint8_t, BaseHappiness);
private:
std::unordered_map<std::string, const SpeciesVariant*> _variants;
public:
CreatureSpecies(uint16_t id, std::string name, const SpeciesVariant* defaultVariant,
float genderRatio, std::string growthRate, uint8_t captureRate, uint8_t baseHappiness);
[[nodiscard]] const SpeciesVariant* GetVariant(const std::string& key) const;
[[nodiscard]] Gender GetRandomGender(Core::Random& rand) const;
};
}
#endif //CREATURELIB_CREATURESPECIES_HPP

View File

@ -0,0 +1,58 @@
#include "SpeciesVariant.hpp"
#include <algorithm>
size_t CreatureLib::Library::SpeciesVariant::GetTypeCount() const {
return _types.size();
}
std::string CreatureLib::Library::SpeciesVariant::GetType(size_t index) const {
return _types[index];
}
uint32_t CreatureLib::Library::SpeciesVariant::GetStatistic(CreatureLib::Core::Statistic stat) const {
return _baseStatistics.GetStat(stat);
}
std::string CreatureLib::Library::SpeciesVariant::GetTalent(int32_t index) const {
if (index < 0){
index = -index - 1;
return _secretTalents[index];
}
return _talents[index];
}
/*const CreatureLib::Library::CreatureMoves *CreatureLib::Library::SpeciesVariant::GetCreatureMoves() const {
return &_moves;
}*/
int8_t CreatureLib::Library::SpeciesVariant::GetTalentIndex(std::string talent) const{
auto i = std::find(_talents.begin(), _talents.end(), talent);
if (i != _talents.end()){
return std::distance(_talents.begin(), i);
}
i = std::find(_secretTalents.begin(), _secretTalents.end(), talent);
if (i != _secretTalents.end()){
return std::distance(_secretTalents.begin(), i);
}
//TODO: implement better exception.
throw;
}
int8_t CreatureLib::Library::SpeciesVariant::GetRandomTalent(CreatureLib::Core::Random *rand) const {
return rand->Get(_talents.size());
}
CreatureLib::Library::SpeciesVariant::SpeciesVariant(std::string name, float height, float weight,
uint32_t baseExperience, std::vector<std::string> types,
CreatureLib::Core::StatisticSet baseStats,
std::vector<std::string> talents,
std::vector<std::string> secretTalents)
: __Name(name),
__Height(height),
__Weight(weight),
__BaseExperience(baseExperience),
_types(types),
_baseStatistics(baseStats),
_talents(talents),
_secretTalents(secretTalents)
{}

View File

@ -0,0 +1,40 @@
#ifndef CREATURELIB_SPECIESVARIANT_HPP
#define CREATURELIB_SPECIESVARIANT_HPP
#include <string>
#include <vector>
#include "CreatureMoves.hpp"
#include "../../Core/StatisticSet.hpp"
#include "../../GenericTemplates.cpp"
#include "../../Core/Random.hpp"
namespace CreatureLib::Library {
/*!
\brief A single species can have more than one variant. This class holds the data for those variants.
*/
class SpeciesVariant {
GetProperty(std::string, Name);
GetProperty(float, Height);
GetProperty(float, Weight);
GetProperty(uint32_t, BaseExperience);
private:
std::vector<std::string> _types;
const Core::StatisticSet _baseStatistics;
std::vector<std::string> _talents;
std::vector<std::string> _secretTalents;
//CreatureMoves _moves;
public:
SpeciesVariant(std::string name, float height, float weight, uint32_t baseExperience,
std::vector<std::string> types, Core::StatisticSet baseStats, std::vector<std::string> talents,
std::vector<std::string> secretTalents);
[[nodiscard]] size_t GetTypeCount() const;
[[nodiscard]] std::string GetType(size_t index) const;
[[nodiscard]] uint32_t GetStatistic(Core::Statistic stat) const;
[[nodiscard]] std::string GetTalent(int32_t index) const;
//[[nodiscard]] const CreatureMoves* GetCreatureMoves() const;
[[nodiscard]] int8_t GetTalentIndex(std::string talent) const;
[[nodiscard]] int8_t GetRandomTalent(Core::Random* rand) const;
};
}
#endif //CREATURELIB_SPECIESVARIANT_HPP

View File

@ -0,0 +1,29 @@
#include "DataLibrary.hpp"
CreatureLib::Library::DataLibrary::DataLibrary(CreatureLib::Library::SpeciesLibrary *species,
CreatureLib::Library::AttackLibrary *attacks,
CreatureLib::Library::ItemLibrary *items,
CreatureLib::Library::GrowthRateLibrary* growthRates)
:_species(species), _attacks(attacks), _items(items), _growthRates(growthRates)
{
}
const CreatureLib::Library::SpeciesLibrary *CreatureLib::Library::DataLibrary::GetSpeciesLibrary() const {
return _species;
}
const CreatureLib::Library::AttackLibrary *CreatureLib::Library::DataLibrary::GetAttackLibrary() const {
return _attacks;
}
const CreatureLib::Library::ItemLibrary *CreatureLib::Library::DataLibrary::GetItemLibrary() const {
return _items;
}
const CreatureLib::Library::GrowthRateLibrary *CreatureLib::Library::DataLibrary::GetGrowthRates() const {
return _growthRates;
}

View File

@ -0,0 +1,36 @@
#ifndef CREATURELIB_DATALIBRARY_HPP
#define CREATURELIB_DATALIBRARY_HPP
#include "SpeciesLibrary.hpp"
#include "AttackLibrary.hpp"
#include "ItemLibrary.hpp"
#include "GrowthRates/GrowthRateLibrary.hpp"
namespace CreatureLib::Library {
/*!
\brief The core library. This library holds all static data for a creature set.
*/
class DataLibrary {
private:
const SpeciesLibrary* _species;
const AttackLibrary* _attacks;
const ItemLibrary* _items;
const GrowthRateLibrary* _growthRates;
public:
DataLibrary(SpeciesLibrary* species, AttackLibrary* attacks, ItemLibrary* items, GrowthRateLibrary* growthRates);
~DataLibrary(){
delete _species;
delete _attacks;
delete _items;
delete _growthRates;
}
[[nodiscard]] const SpeciesLibrary* GetSpeciesLibrary() const;
[[nodiscard]] const AttackLibrary* GetAttackLibrary() const;
[[nodiscard]] const ItemLibrary* GetItemLibrary() const;
[[nodiscard]] const GrowthRateLibrary* GetGrowthRates() const;
};
}
#endif //CREATURELIB_DATALIBRARY_HPP

18
src/Library/Gender.hpp Normal file
View File

@ -0,0 +1,18 @@
#ifndef CREATURELIB_GENDER_HPP
#define CREATURELIB_GENDER_HPP
#include <cstdint>
namespace CreatureLib::Library{
/*!
\brief Might be somewhat controversial nowadays, but as many creature battling games only have two genders, we'll
hardcode those.
*/
enum class Gender : uint8_t {
Male,
Female,
Genderless
};
}
#endif //CREATURELIB_GENDER_HPP

View File

@ -0,0 +1 @@
#include "GrowthRate.hpp"

View File

@ -0,0 +1,14 @@
#ifndef CREATURELIB_GROWTHRATE_HPP
#define CREATURELIB_GROWTHRATE_HPP
#include <cstdint>
namespace CreatureLib::Library {
class GrowthRate {
public:
[[nodiscard]] virtual uint8_t CalculateLevel(uint32_t experience) const = 0;
[[nodiscard]] virtual uint32_t CalculateExperience(uint8_t level) const = 0;
};
}
#endif //CREATURELIB_GROWTHRATE_HPP

View File

@ -0,0 +1,9 @@
#include "GrowthRateLibrary.hpp"
uint8_t CreatureLib::Library::GrowthRateLibrary::CalculateLevel(const std::string &growthRate, uint32_t experience) const {
return _growthRates.at(growthRate)->CalculateLevel(experience);
}
uint32_t CreatureLib::Library::GrowthRateLibrary::CalculateExperience(const std::string &growthRate, uint8_t level) const {
return _growthRates.at(growthRate)->CalculateExperience(level);
}

View File

@ -0,0 +1,19 @@
#ifndef CREATURELIB_GROWTHRATELIBRARY_HPP
#define CREATURELIB_GROWTHRATELIBRARY_HPP
#include <cstdint>
#include <string>
#include <unordered_map>
#include "GrowthRate.hpp"
namespace CreatureLib::Library{
class GrowthRateLibrary {
private:
std::unordered_map<std::string, GrowthRate*> _growthRates;
public:
[[nodiscard]] uint8_t CalculateLevel(const std::string& growthRate, uint32_t experience) const;
[[nodiscard]] uint32_t CalculateExperience(const std::string& growthRate, uint8_t level) const;
};
}
#endif //CREATURELIB_GROWTHRATELIBRARY_HPP

View File

@ -0,0 +1,17 @@
#include "ItemLibrary.hpp"
const CreatureLib::Library::Item *CreatureLib::Library::ItemLibrary::GetItem(const std::string &name) const {
return this->_items.at(name);
}
const CreatureLib::Library::Item *CreatureLib::Library::ItemLibrary::operator[](const std::string &name) const {
return this->GetItem(name);
}
void CreatureLib::Library::ItemLibrary::LoadItem(const std::string &name, const CreatureLib::Library::Item *item) {
this->_items.insert({name, item});
}
void CreatureLib::Library::ItemLibrary::DeleteItem(const std::string &name) {
this->_items.erase(name);
}

View File

@ -0,0 +1,28 @@
#ifndef CREATURELIB_ITEMLIBRARY_HPP
#define CREATURELIB_ITEMLIBRARY_HPP
#include <string>
#include <unordered_map>
#include "Items/Item.hpp"
namespace CreatureLib::Library {
class ItemLibrary {
private:
std::unordered_map<std::string, const Item *> _items;
public:
ItemLibrary() = default;
~ItemLibrary(){
_items.clear();
}
[[nodiscard]] const Item* GetItem(const std::string& name) const;
[[nodiscard]] const Item* operator[] (const std::string& name) const;
void LoadItem(const std::string& name, const Item* item);
void DeleteItem(const std::string& name);
};
}
#endif //CREATURELIB_ITEMLIBRARY_HPP

View File

@ -0,0 +1,16 @@
#ifndef CREATURELIB_BATTLEITEMCATEGORY_HPP
#define CREATURELIB_BATTLEITEMCATEGORY_HPP
#include <cstdint>
namespace CreatureLib::Library {
enum class BattleItemCategory : uint8_t {
None,
Healing,
StatusHealing,
CaptureDevice,
MiscBattleItem
};
}
#endif //CREATURELIB_BATTLEITEMCATEGORY_HPP

View File

@ -0,0 +1,5 @@
#include "Item.hpp"
bool CreatureLib::Library::Item::HasFlag(const std::string& flag) const {
return this->_flags.find(flag) != this->_flags.end();
}

View File

@ -0,0 +1,26 @@
#ifndef CREATURELIB_ITEM_HPP
#define CREATURELIB_ITEM_HPP
#include <string>
#include <unordered_set>
#include "ItemCategory.hpp"
#include "BattleItemCategory.hpp"
#include "../../GenericTemplates.cpp"
namespace CreatureLib::Library {
class Item {
GetProperty(std::string, Name);
GetProperty(ItemCategory, Category);
GetProperty(BattleItemCategory, BattleCategory);
GetProperty(int32_t , Price);
private:
std::unordered_set<std::string> _flags;
public:
Item(std::string name, ItemCategory category, BattleItemCategory battleCategory, int32_t price,
std::unordered_set<std::string> flags);
bool HasFlag(const std::string& flag) const;
};
}
#endif //CREATURELIB_ITEM_HPP

View File

@ -0,0 +1,19 @@
#ifndef CREATURELIB_ITEMCATEGORY_HPP
#define CREATURELIB_ITEMCATEGORY_HPP
#include <cstdint>
namespace CreatureLib::Library{
enum class ItemCategory : uint8_t {
MiscItem,
CaptureDevice,
Medicine,
Berry,
TM,
VariantChanger,
KeyItem,
Mail,
};
}
#endif //CREATURELIB_ITEMCATEGORY_HPP

View File

@ -0,0 +1,19 @@
#include "SpeciesLibrary.hpp"
const CreatureLib::Library::CreatureSpecies *CreatureLib::Library::SpeciesLibrary::GetSpecies(const std::string& name) const{
return _species.at(name);
}
const CreatureLib::Library::CreatureSpecies* CreatureLib::Library::SpeciesLibrary::operator[](const std::string &name) const{
return GetSpecies(name);
}
void CreatureLib::Library::SpeciesLibrary::LoadSpecies(const std::string &name,
const CreatureLib::Library::CreatureSpecies* species) {
_species.insert({name, species});
}
void CreatureLib::Library::SpeciesLibrary::DeleteSpecies(const std::string &name) {
_species.erase(name);
}

View File

@ -0,0 +1,28 @@
#ifndef CREATURELIB_SPECIESLIBRARY_HPP
#define CREATURELIB_SPECIESLIBRARY_HPP
#include <string>
#include <unordered_map>
#include "CreatureData/CreatureSpecies.hpp"
namespace CreatureLib::Library {
class SpeciesLibrary {
private:
std::unordered_map<std::string, const CreatureSpecies*> _species;
public:
SpeciesLibrary() = default;
~SpeciesLibrary(){
_species.clear();
}
[[nodiscard]] const CreatureSpecies* GetSpecies(const std::string& name) const;
[[nodiscard]] const CreatureSpecies* operator[] (const std::string& name) const;
void LoadSpecies(const std::string& name, const CreatureSpecies* species);
void DeleteSpecies(const std::string& name);
};
}
#endif //CREATURELIB_SPECIESLIBRARY_HPP

View File

@ -0,0 +1,66 @@
#ifdef TESTS_BUILD
#include "../../src/Library/CreateCreature.hpp"
#include "TestLibrary.cpp"
using namespace CreatureLib::Library;
TEST_CASE( "Create basic creature", "[Library]" ) {
auto library = GetLibrary();
auto creature = CreateCreature(library, "testSpecies1", 1).Create();
delete creature;
}
TEST_CASE( "Get creature species", "[Library]" ) {
auto library = GetLibrary();
auto creature = CreateCreature(library, "testSpecies1", 1).Create();
REQUIRE(creature->GetSpecies()->GetName() == "testSpecies1");
delete creature;
}
TEST_CASE( "Get creature level", "[Library]" ) {
auto library = GetLibrary();
auto creature = CreateCreature(library, "testSpecies1", 1).Create();
REQUIRE(creature->GetLevel() == 1);
delete creature;
}
TEST_CASE( "Get creature variant when unset", "[Library]" ) {
auto library = GetLibrary();
auto creature = CreateCreature(library, "testSpecies1", 1).Create();
REQUIRE(creature->GetVariant()->GetName() == "default");
delete creature;
}
TEST_CASE( "Get creature nickname when unset", "[Library]" ) {
auto library = GetLibrary();
auto creature = CreateCreature(library, "testSpecies1", 1).Create();
REQUIRE(creature->GetNickname() == "testSpecies1");
delete creature;
}
TEST_CASE( "Get creature stat potentials when unset", "[Library]" ) {
auto library = GetLibrary();
auto creature = CreateCreature(library, "testSpecies1", 1).Create();
auto potentials = creature->GetStatPotential();
REQUIRE(potentials.GetHealth() == 0);
REQUIRE(potentials.GetPhysicalAttack() == 0);
REQUIRE(potentials.GetPhysicalDefense() == 0);
REQUIRE(potentials.GetMagicalAttack() == 0);
REQUIRE(potentials.GetMagicalDefense() == 0);
REQUIRE(potentials.GetSpeed() == 0);
delete creature;
}
TEST_CASE( "Get creature stat experience when unset", "[Library]" ) {
auto library = GetLibrary();
auto creature = CreateCreature(library, "testSpecies1", 1).Create();
auto experiences = creature->GetStatExperience();
REQUIRE(experiences.GetHealth() == 0);
REQUIRE(experiences.GetPhysicalAttack() == 0);
REQUIRE(experiences.GetPhysicalDefense() == 0);
REQUIRE(experiences.GetMagicalAttack() == 0);
REQUIRE(experiences.GetMagicalDefense() == 0);
REQUIRE(experiences.GetSpeed() == 0);
delete creature;
}
#endif

View File

@ -0,0 +1,51 @@
#ifdef TESTS_BUILD
#include "../../extern/catch.hpp"
#include "../../src/Library/DataLibrary.hpp"
using namespace CreatureLib::Core;
using namespace CreatureLib::Library;
static DataLibrary* __library = nullptr;
static SpeciesLibrary* BuildSpeciesLibrary(){
auto l = new SpeciesLibrary();
l->LoadSpecies("testSpecies1", new CreatureSpecies(0, "testSpecies1",
new SpeciesVariant("default", 1,1, 10, {"fire", "water"}, StatisticSet(10,10,10,10,10,10),
{"testTalent"}, {"testSecretTalent"}),
0.5f, "testGrowthRate", 5, 100));
return l;
}
static AttackLibrary* BuildAttackLibrary(){
auto l = new AttackLibrary();
return l;
}
static ItemLibrary* BuildItemLibrary(){
auto l = new ItemLibrary();
return l;
}
static GrowthRateLibrary* BuildGrowthRateLibrary(){
auto l = new GrowthRateLibrary();
return l;
}
static DataLibrary* BuildLibrary(){
auto l = new DataLibrary(BuildSpeciesLibrary(), BuildAttackLibrary(), BuildItemLibrary(), BuildGrowthRateLibrary());
return l;
}
[[maybe_unused]]
static DataLibrary* GetLibrary(){
if (__library == nullptr){
__library = BuildLibrary();
}
return __library;
}
#ifndef LIBRARY_BUILD_TESTS
#define LIBRARY_BUILD_TESTS
#endif
#endif

View File

@ -0,0 +1,37 @@
#ifdef TESTS_BUILD
#define CATCH_CONFIG_MAIN
#include "../../extern/catch.hpp"
#include "TestLibrary.cpp"
TEST_CASE( "Can Create Species Library", "[Library]" ) {
auto l = BuildSpeciesLibrary();
REQUIRE(l != nullptr);
delete l;
}
TEST_CASE( "Can Create Attack Library", "[Library]" ) {
auto l = BuildAttackLibrary();
REQUIRE(l != nullptr);
delete l;
}
TEST_CASE( "Can Create Item Library", "[Library]" ) {
auto l = BuildItemLibrary();
REQUIRE(l != nullptr);
delete l;
}
TEST_CASE( "Can Create Growthrate Library", "[Library]" ) {
auto l = BuildGrowthRateLibrary();
REQUIRE(l != nullptr);
delete l;
}
TEST_CASE( "Can Create Data Library", "[Library]" ) {
auto l = BuildLibrary();
REQUIRE(l != nullptr);
delete l;
}
#endif

58
tests/RandomTests.cpp Normal file
View File

@ -0,0 +1,58 @@
#ifdef TESTS_BUILD
#include "../extern/catch.hpp"
#include "../src/Core/Random.hpp"
TEST_CASE( "Random ints", "[Utilities]" ) {
auto rand = CreatureLib::Core::Random(10);
CHECK(rand.Get() == 1656398469);
CHECK(rand.Get() == 641584702);
CHECK(rand.Get() == 44564466);
CHECK(rand.Get() == 1062123783);
CHECK(rand.Get() == 1360749216);
CHECK(rand.Get() == 951367352);
CHECK(rand.Get() == 1608044094);
CHECK(rand.Get() == 1786516046);
CHECK(rand.Get() == 1070535660);
CHECK(rand.Get() == 1252673902);
}
TEST_CASE( "Random ints with limit", "[Utilities]" ) {
auto rand = CreatureLib::Core::Random(10);
CHECK(rand.Get(10) == 7);
CHECK(rand.Get(10) == 2);
CHECK(rand.Get(10) == 0);
CHECK(rand.Get(10) == 4);
CHECK(rand.Get(10) == 6);
CHECK(rand.Get(10) == 4);
CHECK(rand.Get(10) == 7);
CHECK(rand.Get(10) == 8);
CHECK(rand.Get(10) == 4);
CHECK(rand.Get(10) == 5);
CHECK(rand.Get(2) == 0);
CHECK(rand.Get(2) == 0);
CHECK(rand.Get(2) == 0);
CHECK(rand.Get(2) == 1);
CHECK(rand.Get(2) == 1);
CHECK(rand.Get(2) == 0);
CHECK(rand.Get(2) == 0);
CHECK(rand.Get(2) == 0);
CHECK(rand.Get(2) == 0);
}
TEST_CASE( "Random ints with upper and bottom", "[Utilities]" ) {
auto rand = CreatureLib::Core::Random(10);
CHECK(rand.Get(10, 30) == 25);
CHECK(rand.Get(10, 30) == 15);
CHECK(rand.Get(10, 30) == 10);
CHECK(rand.Get(10, 30) == 19);
CHECK(rand.Get(10, 30) == 22);
CHECK(rand.Get(10, 30) == 18);
CHECK(rand.Get(10, 30) == 24);
CHECK(rand.Get(10, 30) == 26);
CHECK(rand.Get(10, 30) == 19);
CHECK(rand.Get(10, 30) == 21);
}
#endif