diff options
| author | Loek Le Blansch <loek@pipeframe.xyz> | 2024-10-30 12:24:43 +0100 | 
|---|---|---|
| committer | Loek Le Blansch <loek@pipeframe.xyz> | 2024-10-30 12:24:43 +0100 | 
| commit | b1d5d7936bed17a684daff15b0294ef70754e8b9 (patch) | |
| tree | 85ee543a15b42c7f854e4ce403bcff3dff5a3bd4 | |
| parent | 991c9aac53fa3562b0fdc03d74b398052b207d2c (diff) | |
more more WIP
| -rw-r--r-- | backend/ArmorObject.cpp | 6 | ||||
| -rw-r--r-- | backend/ArmorObject.h | 3 | ||||
| -rw-r--r-- | backend/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | backend/ConsumableObject.cpp | 3 | ||||
| -rw-r--r-- | backend/GoldObject.cpp | 6 | ||||
| -rw-r--r-- | backend/GoldObject.h | 3 | ||||
| -rw-r--r-- | backend/ObjectFactory.cpp | 33 | ||||
| -rw-r--r-- | backend/ObjectFactory.h | 12 | ||||
| -rw-r--r-- | backend/WeaponObject.cpp | 10 | ||||
| -rw-r--r-- | backend/WeaponObject.h | 4 | ||||
| -rw-r--r-- | frontend/DB.cpp | 24 | ||||
| -rw-r--r-- | frontend/DB.h | 4 | ||||
| -rw-r--r-- | frontend/GameData.cpp | 35 | ||||
| -rw-r--r-- | frontend/Player.h | 2 | ||||
| -rw-r--r-- | frontend/cmd/view.cpp | 7 | ||||
| -rw-r--r-- | frontend/load_dungeon.cpp | 10 | 
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) { |