aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoek Le Blansch <loek@pipeframe.xyz>2024-10-30 12:24:43 +0100
committerLoek Le Blansch <loek@pipeframe.xyz>2024-10-30 12:24:43 +0100
commitb1d5d7936bed17a684daff15b0294ef70754e8b9 (patch)
tree85ee543a15b42c7f854e4ce403bcff3dff5a3bd4
parent991c9aac53fa3562b0fdc03d74b398052b207d2c (diff)
more more WIP
-rw-r--r--backend/ArmorObject.cpp6
-rw-r--r--backend/ArmorObject.h3
-rw-r--r--backend/CMakeLists.txt4
-rw-r--r--backend/ConsumableObject.cpp3
-rw-r--r--backend/GoldObject.cpp6
-rw-r--r--backend/GoldObject.h3
-rw-r--r--backend/ObjectFactory.cpp33
-rw-r--r--backend/ObjectFactory.h12
-rw-r--r--backend/WeaponObject.cpp10
-rw-r--r--backend/WeaponObject.h4
-rw-r--r--frontend/DB.cpp24
-rw-r--r--frontend/DB.h4
-rw-r--r--frontend/GameData.cpp35
-rw-r--r--frontend/Player.h2
-rw-r--r--frontend/cmd/view.cpp7
-rw-r--r--frontend/load_dungeon.cpp10
16 files changed, 138 insertions, 28 deletions
diff --git a/backend/ArmorObject.cpp b/backend/ArmorObject.cpp
new file mode 100644
index 0000000..5b921fe
--- /dev/null
+++ b/backend/ArmorObject.cpp
@@ -0,0 +1,6 @@
+#include "ArmorObject.h"
+
+void ArmorObject::set_protection(int protection) {
+ this->protection = protection;
+}
+
diff --git a/backend/ArmorObject.h b/backend/ArmorObject.h
index 112997b..a476740 100644
--- a/backend/ArmorObject.h
+++ b/backend/ArmorObject.h
@@ -5,6 +5,9 @@
class ArmorObject : public Object {
using Object::Object;
+public:
+ void set_protection(int protection);
+
private:
int protection = 0;
diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt
index b508654..8797bca 100644
--- a/backend/CMakeLists.txt
+++ b/backend/CMakeLists.txt
@@ -7,5 +7,9 @@ target_sources(main PUBLIC
Location.cpp
util.cpp
RNG.cpp
+ ArmorObject.cpp
+ ConsumableObject.cpp
+ GoldObject.cpp
+ WeaponObject.cpp
)
diff --git a/backend/ConsumableObject.cpp b/backend/ConsumableObject.cpp
new file mode 100644
index 0000000..cfede41
--- /dev/null
+++ b/backend/ConsumableObject.cpp
@@ -0,0 +1,3 @@
+#include "ConsumableObject.h"
+
+
diff --git a/backend/GoldObject.cpp b/backend/GoldObject.cpp
new file mode 100644
index 0000000..624fdf9
--- /dev/null
+++ b/backend/GoldObject.cpp
@@ -0,0 +1,6 @@
+#include "GoldObject.h"
+
+void GoldObject::set_count(int count) {
+ this->count = count;
+}
+
diff --git a/backend/GoldObject.h b/backend/GoldObject.h
index 6f65c1d..ea473d4 100644
--- a/backend/GoldObject.h
+++ b/backend/GoldObject.h
@@ -5,6 +5,9 @@
class GoldObject : public Object {
using Object::Object;
+public:
+ void set_count(int count);
+
private:
int count = 0;
};
diff --git a/backend/ObjectFactory.cpp b/backend/ObjectFactory.cpp
index 4a0642b..d8e1c21 100644
--- a/backend/ObjectFactory.cpp
+++ b/backend/ObjectFactory.cpp
@@ -4,15 +4,34 @@
#include "ConsumableObject.h"
#include "GoldObject.h"
#include "WeaponObject.h"
+#include "RNG.h"
-Object * ObjectFactory::create_object(ObjectType type, const char * name, const char * description) {
- switch (type) {
- case ARMOR: return new ArmorObject(name, description);
- case CONSUMABLE: return new ConsumableObject(name, description);
- case GOLD: return new GoldObject(name, description);
- case WEAPON: return new WeaponObject(name, description);
+Object * ObjectFactory::create_object(const UniversalObject & data) {
+ switch (data.type) {
+ case ARMOR: {
+ ArmorObject * object = new ArmorObject(data.name, data.description);
+ object->set_protection(data.protection);
+ return object;
+ }
+ case CONSUMABLE: {
+ ConsumableObject * object = new ConsumableObject(data.name, data.description);
+ // TODO: read database item explanation
+ return object;
+ }
+ case GOLD: {
+ GoldObject * object = new GoldObject(data.name, data.description);
+ object->set_count(RNG::get().rand_int(data.min_value, data.max_value));
+ return object;
+ }
+ case WEAPON: {
+ WeaponObject * object = new WeaponObject(data.name, data.description);
+ object->set_damage_min(data.min_value);
+ object->set_damage_max(data.max_value);
+ return object;
+ }
+ default: break;
}
- return ObjectFactory::create_object(name, description);
+ return ObjectFactory::create_object(data.name, data.description);
}
Object * ObjectFactory::create_object(const char * name, const char * description) {
diff --git a/backend/ObjectFactory.h b/backend/ObjectFactory.h
index adf960b..60123bd 100644
--- a/backend/ObjectFactory.h
+++ b/backend/ObjectFactory.h
@@ -9,9 +9,19 @@ enum ObjectType {
WEAPON,
};
+// database object table row
+struct UniversalObject {
+ const char * name;
+ const char * description;
+ ObjectType type;
+ int min_value;
+ int max_value;
+ int protection;
+};
+
class ObjectFactory {
public:
- static Object * create_object(ObjectType type, const char * name = "", const char * description = "");
+ static Object * create_object(const UniversalObject & universal);
static Object * create_object(const char * name = "", const char * description = "");
private:
diff --git a/backend/WeaponObject.cpp b/backend/WeaponObject.cpp
new file mode 100644
index 0000000..ac7defd
--- /dev/null
+++ b/backend/WeaponObject.cpp
@@ -0,0 +1,10 @@
+#include "WeaponObject.h"
+
+void WeaponObject::set_damage_min(int damage_min) {
+ this->damage_min = damage_min;
+}
+
+void WeaponObject::set_damage_max(int damage_max) {
+ this->damage_max = damage_max;
+}
+
diff --git a/backend/WeaponObject.h b/backend/WeaponObject.h
index 8b1bc58..d4cfa7a 100644
--- a/backend/WeaponObject.h
+++ b/backend/WeaponObject.h
@@ -5,6 +5,10 @@
class WeaponObject : public Object {
using Object::Object;
+public:
+ void set_damage_min(int damage_min);
+ void set_damage_max(int damage_max);
+
private:
int damage_min;
int damage_max;
diff --git a/frontend/DB.cpp b/frontend/DB.cpp
index 28fd164..d4527b8 100644
--- a/frontend/DB.cpp
+++ b/frontend/DB.cpp
@@ -51,7 +51,10 @@ DBStatement & DBStatement::bind(const int & number) {
return *this;
}
-DBStatement & DBStatement::unbind() {
+DBStatement & DBStatement::reset() {
+ int ret = sqlite3_reset(this->stmt.get());
+ if (ret != SQLITE_OK)
+ throw Exception("sqlite3_reset: %d", ret);
this->param_index = 1;
return *this;
}
@@ -64,7 +67,7 @@ void DBStatement::execute() {
DBQueryRow DBStatement::row() {
int ret = sqlite3_step(this->stmt.get());
- if (ret != SQLITE_ROW)
+ if (ret != SQLITE_ROW && ret != SQLITE_DONE)
throw Exception("sqlite3_step: %d", ret);
return { *this };
@@ -72,13 +75,26 @@ DBQueryRow DBStatement::row() {
DBQueryRow::DBQueryRow(DBStatement & parent) : parent(parent) { }
+
template <>
-const char * DBQueryRow::col<const char*>(int index) {
+const char * DBQueryRow::col<const char*>(int index, const char * const & default_value) {
+ int type = sqlite3_column_type(this->parent.stmt.get(), index);
+ if (type == SQLITE_NULL) return default_value;
return reinterpret_cast<const char *>(sqlite3_column_text(this->parent.stmt.get(), index));
}
+template <>
+const char * DBQueryRow::col<const char*>(int index) {
+ return this->col<const char *>(index, "");
+}
template <>
-int DBQueryRow::col<int>(int index) {
+int DBQueryRow::col<int>(int index, const int & default_value) {
+ int type = sqlite3_column_type(this->parent.stmt.get(), index);
+ if (type == SQLITE_NULL) return default_value;
return sqlite3_column_int(this->parent.stmt.get(), index);
}
+template <>
+int DBQueryRow::col<int>(int index) {
+ return this->col<int>(index, 0);
+}
diff --git a/frontend/DB.h b/frontend/DB.h
index 77b3f7a..f6907bc 100644
--- a/frontend/DB.h
+++ b/frontend/DB.h
@@ -13,6 +13,8 @@ public:
public:
template <typename T>
+ T col(int index, const T & default_value);
+ template <typename T>
T col(int index);
private:
@@ -52,7 +54,7 @@ public:
DBStatement(DB &, const std::string & query);
public:
- DBStatement & unbind();
+ DBStatement & reset();
DBStatement & bind(const std::string & text);
DBStatement & bind(const int & number);
public:
diff --git a/frontend/GameData.cpp b/frontend/GameData.cpp
index b036695..c8f47e3 100644
--- a/frontend/GameData.cpp
+++ b/frontend/GameData.cpp
@@ -34,24 +34,47 @@ static const unordered_map<string, ObjectType> type_map = {
};
Object * GameData::create_object(const string & name) {
- DBStatement query = this->db->prepare("select type, omschrijving from Objecten where naam = ?");
- query.bind(name);
+ static DBStatement query = this->db->prepare(R"(
+ select
+ type,
+ omschrijving,
+ minimumwaarde,
+ maximumwaarde,
+ bescherming
+ from Objecten
+ where lower(naam) = lower(?)
+ limit 1
+ )");
+ query.reset()
+ .bind(name)
+ ;
try {
auto row = query.row();
string type = row.col<const char *>(0);
- const char * description = row.col<const char *>(1);
if (!type_map.contains(type)) throw std::exception();
- return ObjectFactory::create_object(type_map.at(type), name.c_str(), description);
+ return ObjectFactory::create_object({
+ .name = name.c_str(),
+ .description = row.col<const char *>(1),
+ .type = type_map.at(type),
+ .min_value = row.col<int>(2),
+ .max_value = row.col<int>(3),
+ .protection = row.col<int>(4),
+ });
} catch (...) {
return ObjectFactory::create_object(name.c_str());
}
}
void GameData::leaderbord_add(const string & name, unsigned int gold) {
- this->db->prepare("insert into Leaderboard (naam, goudstukken) values (?, ?)")
+ static DBStatement stmt = this->db->prepare(R"(
+ insert into Leaderboard (naam, goudstukken)
+ values (?, ?)
+ )");
+ stmt.reset()
.bind(name)
.bind(gold)
- .execute();
+ ;
+ stmt.execute();
}
diff --git a/frontend/Player.h b/frontend/Player.h
index c590aa9..94ec6a3 100644
--- a/frontend/Player.h
+++ b/frontend/Player.h
@@ -22,8 +22,8 @@ private:
std::string name;
unsigned int health_points = 20;
float attack_chance = 0.4;
+ unsigned int gold = 0;
// TODO: WeaponObject[]
- // TODO: GoldObject[]
// TODO: ArmorObject[]
Location & location;
bool cheating = false;
diff --git a/frontend/cmd/view.cpp b/frontend/cmd/view.cpp
index 7998a4a..0636cac 100644
--- a/frontend/cmd/view.cpp
+++ b/frontend/cmd/view.cpp
@@ -1,5 +1,6 @@
#include "../print.h"
#include "../Player.h"
+#include "../strings.h"
FollowupAction Player::cmd_view(Argv argv) {
if (argv.size() == 0) {
@@ -7,12 +8,12 @@ FollowupAction Player::cmd_view(Argv argv) {
return FollowupAction::NONE;
}
- if (argv[0] == "Zelf") {
+ if (str_lower(argv[0]) == "zelf") {
lprtf("Je hebt %d levenspunten.\n", this->health_points);
- lprtf("Je hebt een aanvalskans van %.0f%%.\n", this->attack_chance * 100);
+ lprtf("Je hebt een aanvalskans van %.0f%%.\n", this->get_attack() * 100);
// TODO: weapon
// TODO: armor
- // TODO: gold
+ lprtf("Je hebt %u goundstuk%s.\n", this->gold, this->gold == 1 ? "" : "ken");
// TODO: inventory
}
diff --git a/frontend/load_dungeon.cpp b/frontend/load_dungeon.cpp
index 41c7fc4..23b4094 100644
--- a/frontend/load_dungeon.cpp
+++ b/frontend/load_dungeon.cpp
@@ -31,7 +31,7 @@ unique_ptr<Dungeon> load_dungeon(const string & filename) {
throw Exception("Kon bestand niet vinden");
}
- xml_parse_result result = doc.load_file(canonical.c_str());
+ xml_parse_result result = doc.load_file(canonical.c_str(), parse_default, encoding_latin1);
if (!result)
throw Exception("Kon XML-bestand niet lezen");
@@ -48,10 +48,10 @@ unique_ptr<Dungeon> load_dungeon(const string & filename) {
map<unsigned, TempData> temp_map;
for (xml_node & tag : locations) {
- const char * name = tag.text().as_string();
- const char * description = tag.child("beschrijving").text().as_string();
-
- Location * location = LocationFactory::create_location(name, description);
+ Location * location = LocationFactory::create_location(
+ tag.text().as_string(),
+ tag.child("beschrijving").text().as_string()
+ );
vector<string> objects_hidden = str_split(tag.attribute("objectenverborgen").as_string(), ";");
for (string & name : objects_hidden) {