From 5cbabd60bceec858174650eb63ec02fa4bf00cf0 Mon Sep 17 00:00:00 2001 From: MaanooAk Date: Thu, 29 Dec 2016 16:29:06 +0200 Subject: [PATCH 01/17] Shared and Unshared attribute container --- libopenage/unit/attribute.h | 139 +++++++++++++++++------------------- 1 file changed, 64 insertions(+), 75 deletions(-) diff --git a/libopenage/unit/attribute.h b/libopenage/unit/attribute.h index 97cfa42048..dc8300ed67 100644 --- a/libopenage/unit/attribute.h +++ b/libopenage/unit/attribute.h @@ -128,23 +128,57 @@ template Attribute get_attr(attr_map_t &map) { return *reinterpret_cast *>(map[T]); } +/** + * Wraps a templated shared attribute + * + * Shared attributes are common across all units of + * one type + */ +class SharedAttributeContainer: public AttributeContainer { +public: + + SharedAttributeContainer(attr_type t) + : + AttributeContainer{t} {} + + bool shared() const override { + return true; + } + +}; + +/** + * Wraps a templated unshared attribute + * + * Shared attributes are copied for each unit of + * one type + */ +class UnsharedAttributeContainer: public AttributeContainer { +public: + + UnsharedAttributeContainer(attr_type t) + : + AttributeContainer{t} {} + + bool shared() const override { + return false; + } + +}; + // ----------------------------- // attribute definitions go here // ----------------------------- class Player; -template<> class Attribute: public AttributeContainer { +template<> class Attribute: public SharedAttributeContainer { public: Attribute(Player &p) : - AttributeContainer{attr_type::owner}, + SharedAttributeContainer{attr_type::owner}, player(p) {} - bool shared() const override { - return false; - } - std::shared_ptr copy() const override { return std::make_shared>(*this); } @@ -152,18 +186,14 @@ template<> class Attribute: public AttributeContainer { Player &player; }; -template<> class Attribute: public AttributeContainer { +template<> class Attribute: public UnsharedAttributeContainer { public: Attribute(unsigned int i) : - AttributeContainer{attr_type::hitpoints}, + UnsharedAttributeContainer{attr_type::hitpoints}, current{i}, max{i} {} - bool shared() const override { - return false; - } - std::shared_ptr copy() const override { return std::make_shared>(*this); } @@ -173,17 +203,13 @@ template<> class Attribute: public AttributeContainer { float hp_bar_height; }; -template<> class Attribute: public AttributeContainer { +template<> class Attribute: public SharedAttributeContainer { public: Attribute(typeamount_map a) : - AttributeContainer{attr_type::armor}, + SharedAttributeContainer{attr_type::armor}, armor{a} {} - bool shared() const override { - return true; - } - std::shared_ptr copy() const override { return std::make_shared>(*this); } @@ -191,7 +217,7 @@ template<> class Attribute: public AttributeContainer { typeamount_map armor; }; -template<> class Attribute: public AttributeContainer { +template<> class Attribute: public UnsharedAttributeContainer { public: // TODO remove (keep for testing) // 4 = gamedata::hit_class::UNITS_MELEE (not exported at the moment) @@ -201,7 +227,7 @@ template<> class Attribute: public AttributeContainer { Attribute(UnitType *type, coord::phys_t r, coord::phys_t h, typeamount_map d, UnitType *reset_type) : - AttributeContainer{attr_type::attack}, + UnsharedAttributeContainer{attr_type::attack}, ptype{type}, range{r}, init_height{h}, @@ -209,10 +235,6 @@ template<> class Attribute: public AttributeContainer { stance{attack_stance::do_nothing}, attack_type{reset_type} {} - bool shared() const override { - return false; - } - std::shared_ptr copy() const override { return std::make_shared>(*this); } @@ -231,20 +253,16 @@ template<> class Attribute: public AttributeContainer { UnitType *attack_type; }; -template<> class Attribute: public AttributeContainer { +template<> class Attribute: public SharedAttributeContainer { public: Attribute(coord::phys_t r, coord::phys_t h, unsigned int l, float ra) : - AttributeContainer{attr_type::heal}, + SharedAttributeContainer{attr_type::heal}, range{r}, init_height{h}, life{l}, rate{ra} {} - bool shared() const override { - return true; - } - std::shared_ptr copy() const override { return std::make_shared>(*this); } @@ -255,18 +273,13 @@ template<> class Attribute: public AttributeContainer { float rate; }; - -template<> class Attribute: public AttributeContainer { +template<> class Attribute: public SharedAttributeContainer { public: Attribute(coord::phys_t sp) : - AttributeContainer{attr_type::speed}, + SharedAttributeContainer{attr_type::speed}, unit_speed{sp} {} - bool shared() const override { - return true; - } - std::shared_ptr copy() const override { return std::make_shared>(*this); } @@ -274,17 +287,13 @@ template<> class Attribute: public AttributeContainer { coord::phys_t unit_speed; // possibly use a pointer to account for tech upgrades }; -template<> class Attribute: public AttributeContainer { +template<> class Attribute: public UnsharedAttributeContainer { public: Attribute(coord::phys3_delta dir) : - AttributeContainer{attr_type::direction}, + UnsharedAttributeContainer{attr_type::direction}, unit_dir(dir) {} - bool shared() const override { - return false; - } - std::shared_ptr copy() const override { return std::make_shared>(*this); } @@ -292,18 +301,14 @@ template<> class Attribute: public AttributeContainer { coord::phys3_delta unit_dir; }; -template<> class Attribute: public AttributeContainer { +template<> class Attribute: public UnsharedAttributeContainer { public: Attribute(float arc) : - AttributeContainer{attr_type::projectile}, + UnsharedAttributeContainer{attr_type::projectile}, projectile_arc{arc}, launched{false} {} - bool shared() const override { - return false; - } - std::shared_ptr copy() const override { return std::make_shared>(*this); } @@ -313,11 +318,11 @@ template<> class Attribute: public AttributeContainer { bool launched; }; -template<> class Attribute: public AttributeContainer { +template<> class Attribute: public UnsharedAttributeContainer { public: Attribute() : - AttributeContainer{attr_type::building}, + UnsharedAttributeContainer{attr_type::building}, completed{.0f}, is_dropsite{true}, foundation_terrain{0} {} @@ -346,18 +351,14 @@ template<> class Attribute: public AttributeContainer { coord::phys3 gather_point; }; -template<> class Attribute: public AttributeContainer { +template<> class Attribute: public SharedAttributeContainer { public: Attribute(std::vector types) : - AttributeContainer{attr_type::dropsite}, + SharedAttributeContainer{attr_type::dropsite}, resource_types{types} {} - bool shared() const override { - return true; - } - std::shared_ptr copy() const override { return std::make_shared>(*this); } @@ -377,18 +378,14 @@ template<> class Attribute: public AttributeContainer { /** * resource capacity of an object, trees, mines, villagers etc. */ -template<> class Attribute: public AttributeContainer { +template<> class Attribute: public UnsharedAttributeContainer { public: Attribute(game_resource type, float init_amount) : - AttributeContainer{attr_type::resource}, + UnsharedAttributeContainer{attr_type::resource}, resource_type{type}, amount{init_amount} {} - bool shared() const override { - return false; - } - std::shared_ptr copy() const override { return std::make_shared>(*this); } @@ -402,17 +399,13 @@ class UnitTexture; /** * TODO: rename to worker */ -template<> class Attribute: public AttributeContainer { +template<> class Attribute: public UnsharedAttributeContainer { public: Attribute() : - AttributeContainer{attr_type::gatherer}, + UnsharedAttributeContainer{attr_type::gatherer}, amount{.0f} {} - bool shared() const override { - return false; - } - std::shared_ptr copy() const override { return std::make_shared>(*this); } @@ -426,15 +419,11 @@ template<> class Attribute: public AttributeContainer { std::unordered_map graphics; }; -template<> class Attribute: public AttributeContainer { +template<> class Attribute: public UnsharedAttributeContainer { public: Attribute() : - AttributeContainer{attr_type::garrison} {} - - bool shared() const override { - return false; - } + UnsharedAttributeContainer{attr_type::garrison} {} std::shared_ptr copy() const override { return std::make_shared>(*this); From fb87130a926203b8191e33c215131b53c079d9fb Mon Sep 17 00:00:00 2001 From: MaanooAk Date: Thu, 29 Dec 2016 18:30:07 +0200 Subject: [PATCH 02/17] Attributes class headers --- libopenage/unit/attribute.h | 48 +++++++++++++++++++++++++++++++++++ libopenage/unit/unit_type.cpp | 1 + 2 files changed, 49 insertions(+) diff --git a/libopenage/unit/attribute.h b/libopenage/unit/attribute.h index dc8300ed67..c281409327 100644 --- a/libopenage/unit/attribute.h +++ b/libopenage/unit/attribute.h @@ -113,8 +113,55 @@ class AttributeContainer { virtual std::shared_ptr copy() const = 0; }; +// TODO be replaced by Attributes using attr_map_t = std::map>; +/** + * Contains a group of attributes. + * Can contain only one attribute of each type. + * + * TODO replace attr_map_t + */ +class Attributes{ +public: + Attributes() {} + + /** + * Add an attribute or replace any attribute of the same type. + */ + bool add(std::shared_ptr attr); + + /** + * Add copies of all the attributes from the given Attributes. + */ + bool addCopies(Attributes & attrs); + + /** + * Remove an attribute based on the type. + */ + bool remove(attr_type type); + + /** + * Check if the attribute of the given type exists. + */ + bool has(attr_type type) const; + + /** + * Get the attribute based on the type. + */ + std::shared_ptr get(attr_type type) const; + + /** + * Get the attribute + */ + template + Attribute get() const; + +private: + + std::map> attrs; +}; + /** * An unordered_map with a int key used as a type id * and a unsigned int value used as the amount @@ -123,6 +170,7 @@ using typeamount_map = std::unordered_map; /** * return attribute from a container + * TODO be replaced by Attributes::get */ template Attribute get_attr(attr_map_t &map) { return *reinterpret_cast *>(map[T]); diff --git a/libopenage/unit/unit_type.cpp b/libopenage/unit/unit_type.cpp index f4e415fd33..adf0f4e3ef 100644 --- a/libopenage/unit/unit_type.cpp +++ b/libopenage/unit/unit_type.cpp @@ -69,6 +69,7 @@ TerrainObject *UnitType::place_beside(Unit *u, TerrainObject const *other) const } void UnitType::copy_attributes(Unit *unit) const { + // TODO be replaced by Attributes::addCopies for (auto &attr : this->default_attributes) { unit->add_attribute(attr.second->copy()); } From f8fbd5b64617b0156c49285548724c206477f79e Mon Sep 17 00:00:00 2001 From: MaanooAk Date: Thu, 29 Dec 2016 21:35:00 +0200 Subject: [PATCH 03/17] Attributes implementation --- libopenage/unit/CMakeLists.txt | 1 + libopenage/unit/attribute.cpp | 43 ++++++++++++++++++++++++++++++++++ libopenage/unit/attribute.h | 9 ++++--- 3 files changed, 48 insertions(+), 5 deletions(-) create mode 100644 libopenage/unit/attribute.cpp diff --git a/libopenage/unit/CMakeLists.txt b/libopenage/unit/CMakeLists.txt index 97734018ed..f2dd73ecf0 100644 --- a/libopenage/unit/CMakeLists.txt +++ b/libopenage/unit/CMakeLists.txt @@ -1,6 +1,7 @@ add_sources(libopenage ability.cpp action.cpp + attribute.cpp command.cpp producer.cpp selection.cpp diff --git a/libopenage/unit/attribute.cpp b/libopenage/unit/attribute.cpp new file mode 100644 index 0000000000..b73ffc0461 --- /dev/null +++ b/libopenage/unit/attribute.cpp @@ -0,0 +1,43 @@ +// Copyright 2016-2017 the openage authors. See copying.md for legal info. + +#include "attribute.h" + +namespace openage { + +void Attributes::add(std::shared_ptr attr) { + this->attrs[attr->type] = attr; +} + +void Attributes::addCopies(Attributes & other) { + for (const auto &i : other.attrs) { + const auto &attr = *i.second.get(); + + if (attr.shared()) { + // pass self + this->add(i.second); + } + else { + // create copy + this->add(attr.copy()); + } + } +} + +bool Attributes::remove(attr_type type) { + return this->attrs.erase(type) > 0; +} + +bool Attributes::has(attr_type type) const { + return this->attrs.find(type) != this->attrs.end(); +} + +std::shared_ptr Attributes::get(attr_type type) const { + return this->attrs.at(type); +} + +template +Attribute Attributes::get() const { + return *reinterpret_cast *>(this->attrs.at(T).get()); +} + +} /* namespace openage */ diff --git a/libopenage/unit/attribute.h b/libopenage/unit/attribute.h index c281409327..7bfa544f87 100644 --- a/libopenage/unit/attribute.h +++ b/libopenage/unit/attribute.h @@ -107,8 +107,7 @@ class AttributeContainer { virtual bool shared() const = 0; /** - * produces an copy of the attribute for non-shared attributes - * shared attributes will return themselves + * Produces an copy of the attribute. */ virtual std::shared_ptr copy() const = 0; }; @@ -122,19 +121,19 @@ using attr_map_t = std::map>; * * TODO replace attr_map_t */ -class Attributes{ +class Attributes { public: Attributes() {} /** * Add an attribute or replace any attribute of the same type. */ - bool add(std::shared_ptr attr); + void add(std::shared_ptr attr); /** * Add copies of all the attributes from the given Attributes. */ - bool addCopies(Attributes & attrs); + void addCopies(Attributes & attrs); /** * Remove an attribute based on the type. From d6502e73eb41f0ca179f50ab16ce4f9ba8b6ac2b Mon Sep 17 00:00:00 2001 From: MaanooAk Date: Thu, 29 Dec 2016 22:37:26 +0200 Subject: [PATCH 04/17] Replace attr_map_t with Attributes --- libopenage/unit/attribute.cpp | 14 +++++++------- libopenage/unit/attribute.h | 25 ++++++------------------- libopenage/unit/unit.cpp | 8 ++++++-- libopenage/unit/unit.h | 12 ++++++++++-- libopenage/unit/unit_type.cpp | 9 +++------ libopenage/unit/unit_type.h | 4 ++-- 6 files changed, 34 insertions(+), 38 deletions(-) diff --git a/libopenage/unit/attribute.cpp b/libopenage/unit/attribute.cpp index b73ffc0461..340fa84886 100644 --- a/libopenage/unit/attribute.cpp +++ b/libopenage/unit/attribute.cpp @@ -1,14 +1,14 @@ -// Copyright 2016-2017 the openage authors. See copying.md for legal info. +// Copyright 2016-2016 the openage authors. See copying.md for legal info. #include "attribute.h" namespace openage { -void Attributes::add(std::shared_ptr attr) { +void Attributes::add(const std::shared_ptr attr) { this->attrs[attr->type] = attr; } -void Attributes::addCopies(Attributes & other) { +void Attributes::addCopies(const Attributes & other) { for (const auto &i : other.attrs) { const auto &attr = *i.second.get(); @@ -23,20 +23,20 @@ void Attributes::addCopies(Attributes & other) { } } -bool Attributes::remove(attr_type type) { +bool Attributes::remove(const attr_type type) { return this->attrs.erase(type) > 0; } -bool Attributes::has(attr_type type) const { +bool Attributes::has(const attr_type type) const { return this->attrs.find(type) != this->attrs.end(); } -std::shared_ptr Attributes::get(attr_type type) const { +std::shared_ptr Attributes::get(const attr_type type) const { return this->attrs.at(type); } template -Attribute Attributes::get() const { +Attribute &Attributes::get() const { return *reinterpret_cast *>(this->attrs.at(T).get()); } diff --git a/libopenage/unit/attribute.h b/libopenage/unit/attribute.h index 7bfa544f87..68e6ef29be 100644 --- a/libopenage/unit/attribute.h +++ b/libopenage/unit/attribute.h @@ -112,14 +112,9 @@ class AttributeContainer { virtual std::shared_ptr copy() const = 0; }; -// TODO be replaced by Attributes -using attr_map_t = std::map>; - /** * Contains a group of attributes. * Can contain only one attribute of each type. - * - * TODO replace attr_map_t */ class Attributes { public: @@ -128,33 +123,33 @@ class Attributes { /** * Add an attribute or replace any attribute of the same type. */ - void add(std::shared_ptr attr); + void add(const std::shared_ptr attr); /** * Add copies of all the attributes from the given Attributes. */ - void addCopies(Attributes & attrs); + void addCopies(const Attributes &attrs); /** * Remove an attribute based on the type. */ - bool remove(attr_type type); + bool remove(const attr_type type); /** * Check if the attribute of the given type exists. */ - bool has(attr_type type) const; + bool has(const attr_type type) const; /** * Get the attribute based on the type. */ - std::shared_ptr get(attr_type type) const; + std::shared_ptr get(const attr_type type) const; /** * Get the attribute */ template - Attribute get() const; + Attribute &get() const; private: @@ -167,14 +162,6 @@ class Attributes { */ using typeamount_map = std::unordered_map; -/** - * return attribute from a container - * TODO be replaced by Attributes::get - */ -template Attribute get_attr(attr_map_t &map) { - return *reinterpret_cast *>(map[T]); -} - /** * Wraps a templated shared attribute * diff --git a/libopenage/unit/unit.cpp b/libopenage/unit/unit.cpp index a57e5ece9b..3ce78590ce 100644 --- a/libopenage/unit/unit.cpp +++ b/libopenage/unit/unit.cpp @@ -243,11 +243,15 @@ void Unit::secondary_action(std::unique_ptr action) { } void Unit::add_attribute(std::shared_ptr attr) { - this->attribute_map.emplace(attr_map_t::value_type(attr->type, attr)); + this->attributes.add(attr); +} + +void Unit::add_attributes(const Attributes &attr) { + this->attributes.addCopies(attr); } bool Unit::has_attribute(attr_type type) const { - return (this->attribute_map.count(type) > 0); + return this->attributes.has(type); } std::shared_ptr Unit::queue_cmd(const Command &cmd) { diff --git a/libopenage/unit/unit.h b/libopenage/unit/unit.h index 2a4bcc20d6..2fa891d939 100644 --- a/libopenage/unit/unit.h +++ b/libopenage/unit/unit.h @@ -173,6 +173,12 @@ class Unit : public log::LogSource { */ void add_attribute(std::shared_ptr attr); + /** + * give a new attributes this this unit + * this is used to add the default attributes + */ + void add_attributes(const Attributes &attr); + /** * returns whether attribute is available */ @@ -183,7 +189,9 @@ class Unit : public log::LogSource { */ template Attribute &get_attribute() { - return *reinterpret_cast *>(attribute_map[T].get()); + return *reinterpret_cast *>(attributes.get(T).get()); + // TODO change to (templates errors) + //return attributes.get(); } /** @@ -266,7 +274,7 @@ class Unit : public log::LogSource { * Unit attributes include color, hitpoints, speed, objects garrisoned etc * contains 0 or 1 values for each type */ - attr_map_t attribute_map; + Attributes attributes; /** diff --git a/libopenage/unit/unit_type.cpp b/libopenage/unit/unit_type.cpp index adf0f4e3ef..30a6ec71ac 100644 --- a/libopenage/unit/unit_type.cpp +++ b/libopenage/unit/unit_type.cpp @@ -69,14 +69,11 @@ TerrainObject *UnitType::place_beside(Unit *u, TerrainObject const *other) const } void UnitType::copy_attributes(Unit *unit) const { - // TODO be replaced by Attributes::addCopies - for (auto &attr : this->default_attributes) { - unit->add_attribute(attr.second->copy()); - } + unit->add_attributes(this->default_attributes); } -void UnitType::upgrade(const AttributeContainer &attr) { - *this->default_attributes[attr.type] = attr; +void UnitType::upgrade(const std::shared_ptr &attr) { + this->default_attributes.add(attr); } UnitType *UnitType::parent_type() const { diff --git a/libopenage/unit/unit_type.h b/libopenage/unit/unit_type.h index f15a886484..be2a90398d 100644 --- a/libopenage/unit/unit_type.h +++ b/libopenage/unit/unit_type.h @@ -119,7 +119,7 @@ class UnitType { /** * upgrades one attribute of this unit type */ - void upgrade(const AttributeContainer &attr); + void upgrade(const std::shared_ptr &attr); /** * returns type matching parent_id() @@ -145,7 +145,7 @@ class UnitType { /** * default attributes which get copied to new units */ - attr_map_t default_attributes; + Attributes default_attributes; /** * The set of graphics used for this type From 70bf490c863a2592edb6924840117d6c06c56314 Mon Sep 17 00:00:00 2001 From: MaanooAk Date: Thu, 29 Dec 2016 23:53:15 +0200 Subject: [PATCH 05/17] Attribute hitpoints split into hitpoints and damaged --- libopenage/unit/ability.cpp | 4 +-- libopenage/unit/action.cpp | 60 ++++++++++++++++++----------------- libopenage/unit/attribute.h | 35 +++++++++++++++++--- libopenage/unit/producer.cpp | 2 ++ libopenage/unit/selection.cpp | 14 ++++---- 5 files changed, 74 insertions(+), 41 deletions(-) diff --git a/libopenage/unit/ability.cpp b/libopenage/unit/ability.cpp index 44baf51bca..c7064ceecd 100644 --- a/libopenage/unit/ability.cpp +++ b/libopenage/unit/ability.cpp @@ -12,8 +12,8 @@ namespace openage { bool UnitAbility::has_hitpoints(Unit &target) { - return target.has_attribute(attr_type::hitpoints) && - target.get_attribute().current > 0; + return target.has_attribute(attr_type::damaged) && + target.get_attribute().hp > 0; } bool UnitAbility::is_damaged(Unit &target) { diff --git a/libopenage/unit/action.cpp b/libopenage/unit/action.cpp index 8cced43fa3..4dd2a5ecaa 100644 --- a/libopenage/unit/action.cpp +++ b/libopenage/unit/action.cpp @@ -98,20 +98,20 @@ void UnitAction::face_towards(const coord::phys3 pos) { // TODO remove (keep for testing) void UnitAction::damage_object(Unit &target, unsigned dmg) { - if (target.has_attribute(attr_type::hitpoints)) { - auto &hp = target.get_attribute(); - if (hp.current > dmg) { - hp.current -= dmg; + if (target.has_attribute(attr_type::damaged)) { + auto &dm = target.get_attribute(); + if (dm.hp > dmg) { + dm.hp -= dmg; } else { - hp.current = 0; + dm.hp = 0; } } } void UnitAction::damage_object(Unit &target) { - if (target.has_attribute(attr_type::hitpoints)) { - auto &hp = target.get_attribute(); + if (target.has_attribute(attr_type::damaged)) { + auto &dm = target.get_attribute(); if (target.has_attribute(attr_type::armor) && this->entity->has_attribute(attr_type::attack)) { auto &armor = target.get_attribute().armor; @@ -131,11 +131,11 @@ void UnitAction::damage_object(Unit &target) { actual_damage = 1; } - if (hp.current > actual_damage) { - hp.current -= actual_damage; + if (dm.hp > actual_damage) { + dm.hp -= actual_damage; } else { - hp.current = 0; + dm.hp = 0; } } else { @@ -317,9 +317,9 @@ DeadAction::DeadAction(Unit *e, std::function on_complete) } void DeadAction::update(unsigned int time) { - if (this->entity->has_attribute(attr_type::hitpoints)) { - auto &h_attr = this->entity->get_attribute(); - h_attr.current = 0; + if (this->entity->has_attribute(attr_type::damaged)) { + auto &dm = this->entity->get_attribute(); + dm.hp = 0; } // inc frame but do not pass the end frame @@ -443,9 +443,9 @@ void IdleAction::update(unsigned int time) { void IdleAction::on_completion() {} bool IdleAction::completed() const { - if (this->entity->has_attribute(attr_type::hitpoints)) { - auto &hp = this->entity->get_attribute(); - return hp.current == 0; + if (this->entity->has_attribute(attr_type::damaged)) { + auto &dm = this->entity->get_attribute(); + return dm.hp == 0; } else if (this->entity->has_attribute(attr_type::resource)) { auto &res_attr = this->entity->get_attribute(); @@ -956,13 +956,13 @@ void GatherAction::update_in_range(unsigned int time, Unit *targeted_resource) { // attack objects which have hitpoints (trees, hunt, sheep) if (this->entity->has_attribute(attr_type::owner) && - targeted_resource->has_attribute(attr_type::hitpoints)) { - auto &pl_attr = this->entity->get_attribute(); - auto &hp_attr = targeted_resource->get_attribute(); + targeted_resource->has_attribute(attr_type::damaged)) { + auto &pl = this->entity->get_attribute(); + auto &dm = targeted_resource->get_attribute(); // only attack if hitpoints remain - if (hp_attr.current > 0) { - Command cmd(pl_attr.player, targeted_resource); + if (dm.hp > 0) { + Command cmd(pl.player, targeted_resource); cmd.set_ability(ability_type::attack); cmd.add_flag(command_flag::attack_res); this->entity->queue_cmd(cmd); @@ -1087,8 +1087,8 @@ void AttackAction::update_in_range(unsigned int time, Unit *target_ptr) { } bool AttackAction::completed_in_range(Unit *target_ptr) const { - auto &h_attr = target_ptr->get_attribute(); - return h_attr.current < 1; // is unit still alive? + auto &dm = target_ptr->get_attribute(); + return dm.hp < 1; // is unit still alive? } void AttackAction::attack(Unit &target) { @@ -1153,8 +1153,9 @@ void HealAction::update_in_range(unsigned int time, Unit *target_ptr) { } bool HealAction::completed_in_range(Unit *target_ptr) const { - auto &h_attr = target_ptr->get_attribute(); - return h_attr.current >= h_attr.max; // is unit at full hitpoints? + auto &hp = target_ptr->get_attribute(); + auto &dm = target_ptr->get_attribute(); + return dm.hp >= hp.hp; // is unit at full hitpoints? } void HealAction::heal(Unit &target) { @@ -1162,13 +1163,14 @@ void HealAction::heal(Unit &target) { // TODO move to seperate function heal_object (like damage_object)? // heal object - if (target.has_attribute(attr_type::hitpoints)) { + if (target.has_attribute(attr_type::hitpoints) && target.has_attribute(attr_type::damaged)) { auto &hp = target.get_attribute(); - if ((hp.current + heal.life) < hp.max) { - hp.current += heal.life; + auto &dm = target.get_attribute(); + if ((dm.hp + heal.life) < hp.hp) { + dm.hp += heal.life; } else { - hp.current = hp.max; + dm.hp = hp.hp; } } diff --git a/libopenage/unit/attribute.h b/libopenage/unit/attribute.h index 68e6ef29be..3b5049550f 100644 --- a/libopenage/unit/attribute.h +++ b/libopenage/unit/attribute.h @@ -58,6 +58,7 @@ using graphic_set = std::map>; */ enum class attr_type { owner, + damaged, hitpoints, armor, attack, @@ -220,23 +221,49 @@ template<> class Attribute: public SharedAttributeContainer { Player &player; }; +/** + * The max hitpoints and health bar information. + * TODO change bar information stucture + */ template<> class Attribute: public UnsharedAttributeContainer { public: Attribute(unsigned int i) : UnsharedAttributeContainer{attr_type::hitpoints}, - current{i}, - max{i} {} + hp{i} {} std::shared_ptr copy() const override { return std::make_shared>(*this); } - unsigned int current; - unsigned int max; + /** + * The max hitpoints + */ + unsigned int hp; float hp_bar_height; }; +/** + * The current hitpoints. + * TODO add last damage taken timestamp + */ +template<> class Attribute: public UnsharedAttributeContainer { +public: + Attribute(unsigned int i) + : + UnsharedAttributeContainer{attr_type::damaged}, + hp{i} {} + + std::shared_ptr copy() const override { + return std::make_shared>(*this); + } + + /** + * The current hitpoint + */ + unsigned int hp; +}; + template<> class Attribute: public SharedAttributeContainer { public: Attribute(typeamount_map a) diff --git a/libopenage/unit/producer.cpp b/libopenage/unit/producer.cpp index eda671e7fa..6464abe149 100644 --- a/libopenage/unit/producer.cpp +++ b/libopenage/unit/producer.cpp @@ -191,6 +191,7 @@ void ObjectProducer::initialise(Unit *unit, Player &player) { // hitpoints if available if (this->unit_data.hit_points > 0) { unit->add_attribute(std::make_shared>(this->unit_data.hit_points)); + unit->add_attribute(std::make_shared>(this->unit_data.hit_points)); } // collectable resources @@ -555,6 +556,7 @@ void BuildingProducer::initialise(Unit *unit, Player &player) { // garrison and hp for all buildings unit->add_attribute(std::make_shared>()); unit->add_attribute(std::make_shared>(this->unit_data.hit_points)); + unit->add_attribute(std::make_shared>(this->unit_data.hit_points)); bool has_destruct_graphic = this->destroyed != nullptr; unit->push_action(std::make_unique(unit, has_destruct_graphic), true); diff --git a/libopenage/unit/selection.cpp b/libopenage/unit/selection.cpp index bfb7c8d0be..4ea1afb6cb 100644 --- a/libopenage/unit/selection.cpp +++ b/libopenage/unit/selection.cpp @@ -47,9 +47,10 @@ bool UnitSelection::on_drawhud() { for (auto u : this->units) { if (u.second.is_valid()) { Unit *unit_ptr = u.second.get(); - if (unit_ptr->location && unit_ptr->has_attribute(attr_type::hitpoints)) { + if (unit_ptr->location && unit_ptr->has_attribute(attr_type::hitpoints) && unit_ptr->has_attribute(attr_type::damaged)) { auto &hp = unit_ptr->get_attribute(); - float percent = static_cast(hp.current) / static_cast(hp.max); + auto &dm = unit_ptr->get_attribute(); + float percent = static_cast(dm.hp) / static_cast(hp.hp); int mid = percent * 28.0f - 14.0f; coord::phys3 &pos_phys3 = unit_ptr->location->pos.draw; @@ -127,7 +128,7 @@ void UnitSelection::toggle_unit(const Player &player, Unit *u, bool append) { void UnitSelection::add_unit(const Player &player, Unit *u, bool append) { // Only select resources and units with hitpoints > 0 if (u->has_attribute(attr_type::resource) || - (u->has_attribute(attr_type::hitpoints) && u->get_attribute().current > 0)) { + (u->has_attribute(attr_type::damaged) && u->get_attribute().hp > 0)) { selection_type_t unit_type = get_unit_selection_type(player, u); int unit_type_i = static_cast(unit_type); @@ -281,9 +282,10 @@ void UnitSelection::show_attributes(Unit *u) { auto &own_attr = u->get_attribute(); lines.push_back(own_attr.player.name); } - if (u->has_attribute(attr_type::hitpoints)) { - auto &hp_attr = u->get_attribute(); - lines.push_back("hitpoints: "+std::to_string(hp_attr.current)+"/"+std::to_string(hp_attr.max)); + if (u->has_attribute(attr_type::hitpoints) && u->has_attribute(attr_type::damaged)) { + auto &hp = u->get_attribute(); + auto &dm = u->get_attribute(); + lines.push_back("hitpoints: "+std::to_string(dm.hp)+"/"+std::to_string(hp.hp)); } if (u->has_attribute(attr_type::resource)) { auto &res_attr = u->get_attribute(); From 0e2126915b3ddff00346cfc16939a68738937b43 Mon Sep 17 00:00:00 2001 From: MaanooAk Date: Fri, 30 Dec 2016 00:29:40 +0200 Subject: [PATCH 06/17] Building and dropsite attributes clean up --- libopenage/unit/attribute.h | 43 +++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/libopenage/unit/attribute.h b/libopenage/unit/attribute.h index 3b5049550f..9d62a84dcf 100644 --- a/libopenage/unit/attribute.h +++ b/libopenage/unit/attribute.h @@ -225,11 +225,11 @@ template<> class Attribute: public SharedAttributeContainer { * The max hitpoints and health bar information. * TODO change bar information stucture */ -template<> class Attribute: public UnsharedAttributeContainer { +template<> class Attribute: public SharedAttributeContainer { public: Attribute(unsigned int i) : - UnsharedAttributeContainer{attr_type::hitpoints}, + SharedAttributeContainer{attr_type::hitpoints}, hp{i} {} std::shared_ptr copy() const override { @@ -385,33 +385,31 @@ template<> class Attribute: public UnsharedAttributeContain : UnsharedAttributeContainer{attr_type::building}, completed{.0f}, - is_dropsite{true}, foundation_terrain{0} {} - bool shared() const override { - return false; - } - std::shared_ptr copy() const override { return std::make_shared>(*this); } float completed; - bool is_dropsite; int foundation_terrain; // set the TerrainObject to this state // once building has been completed object_state completion_state; - // TODO: use unit class, fish and forage have different dropsites - game_resource resource_type; - // TODO: list allowed trainable producers UnitType *pp; + + /** + * The go to point after a unit is created. + */ coord::phys3 gather_point; }; +/** + * The resources that are accepted. + */ template<> class Attribute: public SharedAttributeContainer { public: @@ -425,14 +423,9 @@ template<> class Attribute: public SharedAttributeContainer } bool accepting_resource(game_resource res) { - if (std::find(resource_types.begin(), resource_types.end(), res) != resource_types.end()) { - return true; - } else { - return false; - } + return std::find(resource_types.begin(), resource_types.end(), res) != resource_types.end(); } -private: std::vector resource_types; }; @@ -441,7 +434,7 @@ template<> class Attribute: public SharedAttributeContainer */ template<> class Attribute: public UnsharedAttributeContainer { public: - Attribute(game_resource type, float init_amount) + Attribute(game_resource type, double init_amount) : UnsharedAttributeContainer{attr_type::resource}, resource_type{type}, @@ -452,7 +445,7 @@ template<> class Attribute: public UnsharedAttributeContain } game_resource resource_type; - float amount; + double amount; }; class UnitTexture; @@ -465,21 +458,25 @@ template<> class Attribute: public UnsharedAttributeContain Attribute() : UnsharedAttributeContainer{attr_type::gatherer}, - amount{.0f} {} + amount{.0} {} std::shared_ptr copy() const override { return std::make_shared>(*this); } game_resource current_type; - float amount; - float capacity; - float gather_rate; + double amount; + double capacity; + double gather_rate; // texture sets available for each resource std::unordered_map graphics; }; +/** + * Units put inside a building. + * TODO add capacity per type of unit + */ template<> class Attribute: public UnsharedAttributeContainer { public: Attribute() From 344247fce46d050e5eabc19a8a86c258c1b5fa2b Mon Sep 17 00:00:00 2001 From: MaanooAk Date: Fri, 30 Dec 2016 01:11:36 +0200 Subject: [PATCH 07/17] Worker attribute rename and split carrying resources --- libopenage/unit/ability.cpp | 2 +- libopenage/unit/action.cpp | 63 +++++++++++++++++++----------------- libopenage/unit/attribute.h | 17 +++++----- libopenage/unit/producer.cpp | 46 +++++++++++++------------- libopenage/unit/unit.cpp | 4 +-- 5 files changed, 68 insertions(+), 64 deletions(-) diff --git a/libopenage/unit/ability.cpp b/libopenage/unit/ability.cpp index c7064ceecd..9e2ddbb9e2 100644 --- a/libopenage/unit/ability.cpp +++ b/libopenage/unit/ability.cpp @@ -224,7 +224,7 @@ bool GatherAbility::can_invoke(Unit &to_modify, const Command &cmd) { Unit &target = *cmd.unit(); return &to_modify != &target && to_modify.location && - to_modify.has_attribute(attr_type::gatherer) && + to_modify.has_attribute(attr_type::worker) && has_resource(target); } return false; diff --git a/libopenage/unit/action.cpp b/libopenage/unit/action.cpp index 4dd2a5ecaa..668127867e 100644 --- a/libopenage/unit/action.cpp +++ b/libopenage/unit/action.cpp @@ -425,9 +425,9 @@ void IdleAction::update(unsigned int time) { // unit carrying ressources take the carrying sprite when idle // we're not updating frames because the carying sprite is walking - if (entity->has_attribute(attr_type::gatherer)) { - auto gatherer_attrib = entity->get_attribute(); - if (gatherer_attrib.amount > 0) { + if (entity->has_attribute(attr_type::worker)) { + auto &worker_resource = this->entity->get_attribute(); + if (worker_resource.amount > 0) { this->graphic = graphic_type::carrying; } else { this->graphic = graphic_type::standing; @@ -478,9 +478,9 @@ MoveAction::MoveAction(Unit *e, UnitReference tar, coord::phys_t within_range) void MoveAction::initialise() { // switch workers to the carrying graphic - if (this->entity->has_attribute(attr_type::gatherer)) { - auto &gather_attr = this->entity->get_attribute(); - if (gather_attr.amount > 0) { + if (this->entity->has_attribute(attr_type::worker)) { + auto &worker_resource = this->entity->get_attribute(); + if (worker_resource.amount > 0) { this->graphic = graphic_type::carrying; } } @@ -753,10 +753,10 @@ BuildAction::BuildAction(Unit *e, UnitReference foundation) build_rate{.0001f} { // update the units type - auto &gatherer_attr = this->entity->get_attribute(); + auto &worker = this->entity->get_attribute(); auto building_class = gamedata::unit_classes::BUILDING; - if (gatherer_attr.graphics.count(building_class) > 0) { - auto *new_type = gatherer_attr.graphics.at(building_class); + if (worker.graphics.count(building_class) > 0) { + auto *new_type = worker.graphics.at(building_class); auto &pl_attr = this->entity->get_attribute(); new_type->initialise(this->entity, pl_attr.player); } @@ -829,18 +829,18 @@ void BuildAction::on_completion() { } const graphic_set &BuildAction::current_graphics() const { - if (this->entity->has_attribute(attr_type::gatherer)) { + if (this->entity->has_attribute(attr_type::worker)) { - // the gatherer attributes attached to the unit + // the worker attributes attached to the unit // are used to modify the graphic - auto &gatherer_attr = this->entity->get_attribute(); + auto &worker = this->entity->get_attribute(); if (this->get_target().is_valid() && this->get_target().get()->has_attribute(attr_type::building)) { // set builder graphics if available - if (gatherer_attr.graphics.count(gamedata::unit_classes::BUILDING) > 0) { - return gatherer_attr.graphics[gamedata::unit_classes::BUILDING]->graphics; + if (worker.graphics.count(gamedata::unit_classes::BUILDING) > 0) { + return worker.graphics[gamedata::unit_classes::BUILDING]->graphics; } } } @@ -921,11 +921,12 @@ GatherAction::GatherAction(Unit *e, UnitReference tar) Unit *target = this->target.get(); this->resource_class = target->unit_type->unit_class; - auto &gatherer_attr = this->entity->get_attribute(); + auto &worker = this->entity->get_attribute(); + auto &worker_resource = this->entity->get_attribute(); // handle unit type changes based on resource class - if (gatherer_attr.graphics.count(this->resource_class) > 0) { - auto *new_type = gatherer_attr.graphics.at(this->resource_class); + if (worker.graphics.count(this->resource_class) > 0) { + auto *new_type = worker.graphics.at(this->resource_class); auto &pl_attr = this->entity->get_attribute(); new_type->initialise(this->entity, pl_attr.player); } @@ -933,10 +934,10 @@ GatherAction::GatherAction(Unit *e, UnitReference tar) // set the type of gatherer if (target->has_attribute(attr_type::resource)) { auto &resource_attr = target->get_attribute(); - if (gatherer_attr.current_type != resource_attr.resource_type) { - this->entity->get_attribute().amount = 0; + if (worker_resource.resource_type != resource_attr.resource_type) { + worker_resource.amount = 0; } - gatherer_attr.current_type = resource_attr.resource_type; + worker_resource.resource_type = resource_attr.resource_type; } else { throw std::invalid_argument("Unit reference has no resource attribute"); } @@ -945,7 +946,8 @@ GatherAction::GatherAction(Unit *e, UnitReference tar) GatherAction::~GatherAction() {} void GatherAction::update_in_range(unsigned int time, Unit *targeted_resource) { - auto &gatherer_attr = this->entity->get_attribute(); + auto &worker = this->entity->get_attribute(); + auto &worker_resource = this->entity->get_attribute(); if (this->target_resource) { // the targets attributes @@ -971,11 +973,11 @@ void GatherAction::update_in_range(unsigned int time, Unit *targeted_resource) { } // need to return to dropsite - if (gatherer_attr.amount > gatherer_attr.capacity) { + if (worker_resource.amount > worker.capacity) { // move to dropsite location this->target_resource = false; - this->set_target(this->nearest_dropsite(gatherer_attr.current_type)); + this->set_target(this->nearest_dropsite(worker_resource.resource_type)); } else { @@ -983,9 +985,9 @@ void GatherAction::update_in_range(unsigned int time, Unit *targeted_resource) { if (resource_attr.amount <= 0.0f) { // when the resource runs out - if (gatherer_attr.amount > 0.0f) { + if (worker_resource.amount > 0.0f) { this->target_resource = false; - this->set_target(this->nearest_dropsite(gatherer_attr.current_type)); + this->set_target(this->nearest_dropsite(worker_resource.resource_type)); } else { this->complete = true; @@ -994,8 +996,9 @@ void GatherAction::update_in_range(unsigned int time, Unit *targeted_resource) { else { // transfer using gather rate - gatherer_attr.amount += gatherer_attr.gather_rate * time; - resource_attr.amount -= gatherer_attr.gather_rate * time; + double amount = worker.gather_rate * time; + worker_resource.amount += amount; + resource_attr.amount -= amount; } } } @@ -1004,8 +1007,8 @@ void GatherAction::update_in_range(unsigned int time, Unit *targeted_resource) { // dropsite has been reached // add value to player stockpile Player &player = this->entity->get_attribute().player; - player.receive(gatherer_attr.current_type, gatherer_attr.amount); - gatherer_attr.amount = 0.0f; + player.receive(worker_resource.resource_type, worker_resource.amount); + worker_resource.amount = 0.0f; // make sure the resource stil exists if (this->target.is_valid() && @@ -1063,7 +1066,7 @@ AttackAction::AttackAction(Unit *e, UnitReference tar) rate_of_fire{0.002f} { // switch graphic type for villagers not collecting resources - if (this->entity->has_attribute(attr_type::gatherer) && + if (this->entity->has_attribute(attr_type::worker) && !tar.get()->has_attribute(attr_type::resource)) { auto &att_attr = this->entity->get_attribute(); auto &pl_attr = this->entity->get_attribute(); diff --git a/libopenage/unit/attribute.h b/libopenage/unit/attribute.h index 9d62a84dcf..04900dc66d 100644 --- a/libopenage/unit/attribute.h +++ b/libopenage/unit/attribute.h @@ -69,7 +69,7 @@ enum class attr_type { building, dropsite, resource, - gatherer, + worker, garrison }; @@ -434,6 +434,10 @@ template<> class Attribute: public SharedAttributeContainer */ template<> class Attribute: public UnsharedAttributeContainer { public: + Attribute() + : + Attribute{game_resource::food, 0} {} + Attribute(game_resource type, double init_amount) : UnsharedAttributeContainer{attr_type::resource}, @@ -451,21 +455,18 @@ template<> class Attribute: public UnsharedAttributeContain class UnitTexture; /** - * TODO: rename to worker + * The worker's capacity and gather rates. */ -template<> class Attribute: public UnsharedAttributeContainer { +template<> class Attribute: public UnsharedAttributeContainer { public: Attribute() : - UnsharedAttributeContainer{attr_type::gatherer}, - amount{.0} {} + UnsharedAttributeContainer{attr_type::worker} {} std::shared_ptr copy() const override { - return std::make_shared>(*this); + return std::make_shared>(*this); } - game_resource current_type; - double amount; double capacity; double gather_rate; diff --git a/libopenage/unit/producer.cpp b/libopenage/unit/producer.cpp index 6464abe149..9bd58f8e72 100644 --- a/libopenage/unit/producer.cpp +++ b/libopenage/unit/producer.cpp @@ -416,50 +416,50 @@ void LivingProducer::initialise(Unit *unit, Player &player) { // add worker attributes if (this->unit_data.unit_class == gamedata::unit_classes::CIVILIAN) { - unit->add_attribute(std::make_shared>()); + unit->add_attribute(std::make_shared>()); + unit->add_attribute(std::make_shared>()); // add graphic ids for resource actions - auto &gather_attr = unit->get_attribute(); - gather_attr.current_type = game_resource::wood; - gather_attr.capacity = 10.0f; - gather_attr.gather_rate = 0.002f; + auto &worker_attr = unit->get_attribute(); + worker_attr.capacity = 10.0f; + worker_attr.gather_rate = 0.002f; // currently not sure where the game data keeps these values // todo PREY_ANIMAL SEA_FISH if (this->parent_id() == 83) { // male graphics - gather_attr.graphics[gamedata::unit_classes::BUILDING] = this->owner.get_type(156); // builder 118 - gather_attr.graphics[gamedata::unit_classes::BERRY_BUSH] = this->owner.get_type(120); // forager - gather_attr.graphics[gamedata::unit_classes::SHEEP] = this->owner.get_type(592); // sheperd - gather_attr.graphics[gamedata::unit_classes::TREES] = this->owner.get_type(123); // woodcutter - gather_attr.graphics[gamedata::unit_classes::GOLD_MINE] = this->owner.get_type(579); // gold miner - gather_attr.graphics[gamedata::unit_classes::STONE_MINE] = this->owner.get_type(124); // stone miner + worker_attr.graphics[gamedata::unit_classes::BUILDING] = this->owner.get_type(156); // builder 118 + worker_attr.graphics[gamedata::unit_classes::BERRY_BUSH] = this->owner.get_type(120); // forager + worker_attr.graphics[gamedata::unit_classes::SHEEP] = this->owner.get_type(592); // sheperd + worker_attr.graphics[gamedata::unit_classes::TREES] = this->owner.get_type(123); // woodcutter + worker_attr.graphics[gamedata::unit_classes::GOLD_MINE] = this->owner.get_type(579); // gold miner + worker_attr.graphics[gamedata::unit_classes::STONE_MINE] = this->owner.get_type(124); // stone miner } else { // female graphics - gather_attr.graphics[gamedata::unit_classes::BUILDING] = this->owner.get_type(222); // builder 212 - gather_attr.graphics[gamedata::unit_classes::BERRY_BUSH] = this->owner.get_type(354); // forager - gather_attr.graphics[gamedata::unit_classes::SHEEP] = this->owner.get_type(590); // sheperd - gather_attr.graphics[gamedata::unit_classes::TREES] = this->owner.get_type(218); // woodcutter - gather_attr.graphics[gamedata::unit_classes::GOLD_MINE] = this->owner.get_type(581); // gold miner - gather_attr.graphics[gamedata::unit_classes::STONE_MINE] = this->owner.get_type(220); // stone miner + worker_attr.graphics[gamedata::unit_classes::BUILDING] = this->owner.get_type(222); // builder 212 + worker_attr.graphics[gamedata::unit_classes::BERRY_BUSH] = this->owner.get_type(354); // forager + worker_attr.graphics[gamedata::unit_classes::SHEEP] = this->owner.get_type(590); // sheperd + worker_attr.graphics[gamedata::unit_classes::TREES] = this->owner.get_type(218); // woodcutter + worker_attr.graphics[gamedata::unit_classes::GOLD_MINE] = this->owner.get_type(581); // gold miner + worker_attr.graphics[gamedata::unit_classes::STONE_MINE] = this->owner.get_type(220); // stone miner } unit->give_ability(std::make_shared(this->on_attack)); unit->give_ability(std::make_shared(this->on_attack)); unit->give_ability(std::make_shared(this->on_attack)); } else if (this->unit_data.unit_class == gamedata::unit_classes::FISHING_BOAT) { - unit->add_attribute(std::make_shared>()); + unit->add_attribute(std::make_shared>()); + unit->add_attribute(std::make_shared>()); // add fishing abilites - auto &gather_attr = unit->get_attribute(); - gather_attr.current_type = game_resource::food; - gather_attr.capacity = 15.0f; - gather_attr.gather_rate = 0.002f; - gather_attr.graphics[gamedata::unit_classes::SEA_FISH] = this; + auto &worker_attr = unit->get_attribute(); + worker_attr.capacity = 15.0f; + worker_attr.gather_rate = 0.002f; + worker_attr.graphics[gamedata::unit_classes::SEA_FISH] = this; unit->give_ability(std::make_shared(this->on_attack)); } diff --git a/libopenage/unit/unit.cpp b/libopenage/unit/unit.cpp index 3ce78590ce..5e574973c7 100644 --- a/libopenage/unit/unit.cpp +++ b/libopenage/unit/unit.cpp @@ -283,8 +283,8 @@ void Unit::stop_gather() { void Unit::stop_actions() { - // work around for gatherers continuing to work after retasking - if (this->has_attribute(attr_type::gatherer)) { + // work around for workers continuing to work after retasking + if (this->has_attribute(attr_type::worker)) { this->stop_gather(); } From 12610643616946adfbfa555e99c740ce43115d79 Mon Sep 17 00:00:00 2001 From: MaanooAk Date: Sat, 31 Dec 2016 17:44:29 +0200 Subject: [PATCH 08/17] Repair ability and action upgrade --- libopenage/unit/ability.cpp | 4 ++-- libopenage/unit/action.cpp | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/libopenage/unit/ability.cpp b/libopenage/unit/ability.cpp index 9e2ddbb9e2..59e3ae29db 100644 --- a/libopenage/unit/ability.cpp +++ b/libopenage/unit/ability.cpp @@ -17,8 +17,8 @@ bool UnitAbility::has_hitpoints(Unit &target) { } bool UnitAbility::is_damaged(Unit &target) { - return target.has_attribute(attr_type::hitpoints) && - target.get_attribute().current < target.get_attribute().max; + return target.has_attribute(attr_type::damaged) && target.has_attribute(attr_type::hitpoints) && + target.get_attribute().hp < target.get_attribute().hp; } bool UnitAbility::has_resource(Unit &target) { diff --git a/libopenage/unit/action.cpp b/libopenage/unit/action.cpp index 668127867e..29cc049208 100644 --- a/libopenage/unit/action.cpp +++ b/libopenage/unit/action.cpp @@ -873,16 +873,17 @@ RepairAction::RepairAction(Unit *e, UnitReference tar) //this->cost += get target cost; this->cost[game_resource::wood] = 100; // temp - this->cost *= 0.5 / hp.max; + this->cost *= 0.5 / hp.hp; } } void RepairAction::update_in_range(unsigned int time, Unit *target_unit) { auto &hp = target_unit->get_attribute(); + auto &dm = target_unit->get_attribute(); auto &owner = this->entity->get_attribute(); - if (hp.current >= hp.max) { + if (dm.hp >= hp.hp) { // repaired by something else this->complete = true; } @@ -890,9 +891,9 @@ void RepairAction::update_in_range(unsigned int time, Unit *target_unit) { this->time_left -= time; if (this->time_left <= 0) { - hp.current += 1; + dm.hp += 1; - if (hp.current >= hp.max) { + if (dm.hp >= hp.hp) { this->complete = true; } } From f2eb3d55e8c4b5db5e32feb534c6eba371415d1e Mon Sep 17 00:00:00 2001 From: MaanooAk Date: Sat, 31 Dec 2016 19:46:25 +0200 Subject: [PATCH 09/17] Worker's resource fixes (and debug res type) --- libopenage/gamestate/resource.cpp | 19 +++++++++++++++++++ libopenage/gamestate/resource.h | 2 ++ libopenage/unit/ability.cpp | 2 +- libopenage/unit/action.cpp | 19 ++++++++++--------- libopenage/unit/selection.cpp | 4 ++-- 5 files changed, 34 insertions(+), 12 deletions(-) diff --git a/libopenage/gamestate/resource.cpp b/libopenage/gamestate/resource.cpp index aead52d926..0bb2716042 100644 --- a/libopenage/gamestate/resource.cpp +++ b/libopenage/gamestate/resource.cpp @@ -70,3 +70,22 @@ bool ResourceBundle::deduct(const ResourceBundle& amount) { } } // openage + +namespace std { + +string to_string(const openage::game_resource &res) { + switch (res) { + case openage::game_resource::wood: + return "wood"; + case openage::game_resource::food: + return "food"; + case openage::game_resource::gold: + return "gold"; + case openage::game_resource::stone: + return "stone"; + default: + return "unknown"; + } +} + +} // namespace std diff --git a/libopenage/gamestate/resource.h b/libopenage/gamestate/resource.h index b3f78ebbfa..f110a3b147 100644 --- a/libopenage/gamestate/resource.h +++ b/libopenage/gamestate/resource.h @@ -59,6 +59,8 @@ class ResourceBundle { namespace std { +std::string to_string(const openage::game_resource &res); + /** * hasher for game resource */ diff --git a/libopenage/unit/ability.cpp b/libopenage/unit/ability.cpp index 59e3ae29db..c449a531aa 100644 --- a/libopenage/unit/ability.cpp +++ b/libopenage/unit/ability.cpp @@ -22,7 +22,7 @@ bool UnitAbility::is_damaged(Unit &target) { } bool UnitAbility::has_resource(Unit &target) { - return target.has_attribute(attr_type::resource) && + return target.has_attribute(attr_type::resource) && !target.has_attribute(attr_type::worker) && target.get_attribute().amount > 0; } diff --git a/libopenage/unit/action.cpp b/libopenage/unit/action.cpp index 29cc049208..c3b6364001 100644 --- a/libopenage/unit/action.cpp +++ b/libopenage/unit/action.cpp @@ -229,8 +229,9 @@ void TargetAction::on_completion() { new_target = find_near(*this->entity->location, [this](const TerrainObject &obj) { return obj.unit.unit_type->id() == this->target_type_id && + !obj.unit.has_attribute(attr_type::worker) && obj.unit.has_attribute(attr_type::resource) && - obj.unit.get_attribute().amount > 0.0f; + obj.unit.get_attribute().amount > 0.0; }); } @@ -338,8 +339,8 @@ void DeadAction::on_completion() { bool DeadAction::completed() const { - // check resource, trees/huntables with resource are not removed - if (this->entity->has_attribute(attr_type::resource)) { + // check resource, trees/huntables with resource are not removed but not workers + if (this->entity->has_attribute(attr_type::resource) && !this->entity->has_attribute(attr_type::worker)) { auto &res_attr = this->entity->get_attribute(); return res_attr.amount <= 0; // cannot complete when resource remains } @@ -449,7 +450,7 @@ bool IdleAction::completed() const { } else if (this->entity->has_attribute(attr_type::resource)) { auto &res_attr = this->entity->get_attribute(); - return res_attr.amount <= 0.0f; + return res_attr.amount <= 0.0; } return false; } @@ -983,10 +984,10 @@ void GatherAction::update_in_range(unsigned int time, Unit *targeted_resource) { else { auto &resource_attr = targeted_resource->get_attribute(); - if (resource_attr.amount <= 0.0f) { + if (resource_attr.amount <= 0.0) { // when the resource runs out - if (worker_resource.amount > 0.0f) { + if (worker_resource.amount > 0.0) { this->target_resource = false; this->set_target(this->nearest_dropsite(worker_resource.resource_type)); } @@ -1009,11 +1010,11 @@ void GatherAction::update_in_range(unsigned int time, Unit *targeted_resource) { // add value to player stockpile Player &player = this->entity->get_attribute().player; player.receive(worker_resource.resource_type, worker_resource.amount); - worker_resource.amount = 0.0f; + worker_resource.amount = 0.0; // make sure the resource stil exists if (this->target.is_valid() && - this->target.get()->get_attribute().amount > 0.0f) { + this->target.get()->get_attribute().amount > 0.0) { // return to resouce collection this->target_resource = true; @@ -1068,7 +1069,7 @@ AttackAction::AttackAction(Unit *e, UnitReference tar) // switch graphic type for villagers not collecting resources if (this->entity->has_attribute(attr_type::worker) && - !tar.get()->has_attribute(attr_type::resource)) { + (!tar.get()->has_attribute(attr_type::resource) || tar.get()->has_attribute(attr_type::worker))) { auto &att_attr = this->entity->get_attribute(); auto &pl_attr = this->entity->get_attribute(); att_attr.attack_type->initialise(this->entity, pl_attr.player); diff --git a/libopenage/unit/selection.cpp b/libopenage/unit/selection.cpp index 4ea1afb6cb..c1c91b5f78 100644 --- a/libopenage/unit/selection.cpp +++ b/libopenage/unit/selection.cpp @@ -284,12 +284,12 @@ void UnitSelection::show_attributes(Unit *u) { } if (u->has_attribute(attr_type::hitpoints) && u->has_attribute(attr_type::damaged)) { auto &hp = u->get_attribute(); - auto &dm = u->get_attribute(); + auto &dm = u->get_attribute(); lines.push_back("hitpoints: "+std::to_string(dm.hp)+"/"+std::to_string(hp.hp)); } if (u->has_attribute(attr_type::resource)) { auto &res_attr = u->get_attribute(); - lines.push_back("resource: "+std::to_string(res_attr.amount)); + lines.push_back("resource: "+std::to_string(res_attr.amount)+" "+std::to_string(res_attr.resource_type)); } if (u->has_attribute(attr_type::building)) { auto &build_attr = u->get_attribute(); From 9eb989bc1d41b28063a056f7f27715726ff29f29 Mon Sep 17 00:00:00 2001 From: MaanooAk Date: Sat, 31 Dec 2016 21:15:36 +0200 Subject: [PATCH 10/17] Gather rates and general attribute fixes --- libopenage/unit/action.cpp | 4 ++-- libopenage/unit/attribute.h | 42 ++++++++++++++++++++++++++++++------ libopenage/unit/producer.cpp | 11 ++++++---- 3 files changed, 44 insertions(+), 13 deletions(-) diff --git a/libopenage/unit/action.cpp b/libopenage/unit/action.cpp index c3b6364001..62a0ae9fd4 100644 --- a/libopenage/unit/action.cpp +++ b/libopenage/unit/action.cpp @@ -924,7 +924,6 @@ GatherAction::GatherAction(Unit *e, UnitReference tar) Unit *target = this->target.get(); this->resource_class = target->unit_type->unit_class; auto &worker = this->entity->get_attribute(); - auto &worker_resource = this->entity->get_attribute(); // handle unit type changes based on resource class if (worker.graphics.count(this->resource_class) > 0) { @@ -934,6 +933,7 @@ GatherAction::GatherAction(Unit *e, UnitReference tar) } // set the type of gatherer + auto &worker_resource = this->entity->get_attribute(); if (target->has_attribute(attr_type::resource)) { auto &resource_attr = target->get_attribute(); if (worker_resource.resource_type != resource_attr.resource_type) { @@ -998,7 +998,7 @@ void GatherAction::update_in_range(unsigned int time, Unit *targeted_resource) { else { // transfer using gather rate - double amount = worker.gather_rate * time; + double amount = worker.gather_rate[worker_resource.resource_type] * time; worker_resource.amount += amount; resource_attr.amount -= amount; } diff --git a/libopenage/unit/attribute.h b/libopenage/unit/attribute.h index 04900dc66d..82ca335a17 100644 --- a/libopenage/unit/attribute.h +++ b/libopenage/unit/attribute.h @@ -307,6 +307,8 @@ template<> class Attribute: public UnsharedAttributeContainer coord::phys_t range; coord::phys_t init_height; typeamount_map damage; + + // TODO move elsewhere in order to become shared attribute attack_stance stance; // TODO move elsewhere in order to become shared attribute @@ -314,13 +316,15 @@ template<> class Attribute: public UnsharedAttributeContainer UnitType *attack_type; }; +/** + * Healing capabilities. + */ template<> class Attribute: public SharedAttributeContainer { public: - Attribute(coord::phys_t r, coord::phys_t h, unsigned int l, float ra) + Attribute(coord::phys_t r, unsigned int l, float ra) : SharedAttributeContainer{attr_type::heal}, range{r}, - init_height{h}, life{l}, rate{ra} {} @@ -328,9 +332,19 @@ template<> class Attribute: public SharedAttributeContainer { return std::make_shared>(*this); } + /** + * The max range of the healing. + */ coord::phys_t range; - coord::phys_t init_height; // TODO remove? + + /** + * Life healed in each cycle + */ unsigned int life; + + /** + * The rate of each heal cycle + */ float rate; }; @@ -345,7 +359,9 @@ template<> class Attribute: public SharedAttributeContainer { return std::make_shared>(*this); } - coord::phys_t unit_speed; // possibly use a pointer to account for tech upgrades + // TODO possibly use a pointer to account for tech upgrades + // TODO rename to default or normal + coord::phys_t unit_speed; }; template<> class Attribute: public UnsharedAttributeContainer { @@ -408,7 +424,7 @@ template<> class Attribute: public UnsharedAttributeContain }; /** - * The resources that are accepted. + * The resources that are accepted to be dropped. */ template<> class Attribute: public SharedAttributeContainer { public: @@ -430,7 +446,7 @@ template<> class Attribute: public SharedAttributeContainer }; /** - * resource capacity of an object, trees, mines, villagers etc. + * Resource capacity of a trees, mines, animal, worker etc. */ template<> class Attribute: public UnsharedAttributeContainer { public: @@ -467,10 +483,19 @@ template<> class Attribute: public UnsharedAttributeContainer return std::make_shared>(*this); } + /** + * The max number of resources that can be carried. + */ double capacity; - double gather_rate; + + /** + * The gather rate for each resource. + * The ResourceBundle class is used but instead of amounts it stores gather rates. + */ + ResourceBundle gather_rate; // texture sets available for each resource + // TODO move elsewhere std::unordered_map graphics; }; @@ -488,6 +513,9 @@ template<> class Attribute: public UnsharedAttributeContain return std::make_shared>(*this); } + /** + * The units that are garrisoned. + */ std::vector content; }; diff --git a/libopenage/unit/producer.cpp b/libopenage/unit/producer.cpp index 9bd58f8e72..fc58b56f91 100644 --- a/libopenage/unit/producer.cpp +++ b/libopenage/unit/producer.cpp @@ -421,8 +421,11 @@ void LivingProducer::initialise(Unit *unit, Player &player) { // add graphic ids for resource actions auto &worker_attr = unit->get_attribute(); - worker_attr.capacity = 10.0f; - worker_attr.gather_rate = 0.002f; + worker_attr.capacity = 10.0; + worker_attr.gather_rate[game_resource::wood] = 0.002; + worker_attr.gather_rate[game_resource::food] = 0.002; + worker_attr.gather_rate[game_resource::gold] = 0.002; + worker_attr.gather_rate[game_resource::stone] = 0.002; // currently not sure where the game data keeps these values // todo PREY_ANIMAL SEA_FISH @@ -457,8 +460,8 @@ void LivingProducer::initialise(Unit *unit, Player &player) { // add fishing abilites auto &worker_attr = unit->get_attribute(); - worker_attr.capacity = 15.0f; - worker_attr.gather_rate = 0.002f; + worker_attr.capacity = 15.0; + worker_attr.gather_rate[game_resource::food] = 0.002; worker_attr.graphics[gamedata::unit_classes::SEA_FISH] = this; unit->give_ability(std::make_shared(this->on_attack)); From 840b0cde88f9fb73a149b795234e48b8104ed398 Mon Sep 17 00:00:00 2001 From: MaanooAk Date: Sun, 1 Jan 2017 23:11:18 +0200 Subject: [PATCH 11/17] Multitype, attr graphics clean up, change unit type upgrade --- libopenage/unit/action.cpp | 47 ++++++---------------------- libopenage/unit/action.h | 4 +-- libopenage/unit/attribute.cpp | 30 +++++++++++++----- libopenage/unit/attribute.h | 58 +++++++++++++++++++++++++---------- libopenage/unit/producer.cpp | 36 ++++++++++++---------- libopenage/unit/unit.cpp | 6 +++- libopenage/unit/unit.h | 11 +++++-- libopenage/unit/unit_type.cpp | 7 ++++- libopenage/unit/unit_type.h | 12 +++++++- 9 files changed, 124 insertions(+), 87 deletions(-) diff --git a/libopenage/unit/action.cpp b/libopenage/unit/action.cpp index 62a0ae9fd4..d32e148a5c 100644 --- a/libopenage/unit/action.cpp +++ b/libopenage/unit/action.cpp @@ -754,12 +754,8 @@ BuildAction::BuildAction(Unit *e, UnitReference foundation) build_rate{.0001f} { // update the units type - auto &worker = this->entity->get_attribute(); - auto building_class = gamedata::unit_classes::BUILDING; - if (worker.graphics.count(building_class) > 0) { - auto *new_type = worker.graphics.at(building_class); - auto &pl_attr = this->entity->get_attribute(); - new_type->initialise(this->entity, pl_attr.player); + if (this->entity->has_attribute(attr_type::multitype)) { + this->entity->get_attribute().switchType(gamedata::unit_classes::BUILDING, this->entity); } } @@ -829,25 +825,6 @@ void BuildAction::on_completion() { } } -const graphic_set &BuildAction::current_graphics() const { - if (this->entity->has_attribute(attr_type::worker)) { - - // the worker attributes attached to the unit - // are used to modify the graphic - auto &worker = this->entity->get_attribute(); - - if (this->get_target().is_valid() && - this->get_target().get()->has_attribute(attr_type::building)) { - - // set builder graphics if available - if (worker.graphics.count(gamedata::unit_classes::BUILDING) > 0) { - return worker.graphics[gamedata::unit_classes::BUILDING]->graphics; - } - } - } - return this->entity->unit_type->graphics; -} - RepairAction::RepairAction(Unit *e, UnitReference tar) : TargetAction{e, graphic_type::work, tar}, @@ -923,13 +900,10 @@ GatherAction::GatherAction(Unit *e, UnitReference tar) Unit *target = this->target.get(); this->resource_class = target->unit_type->unit_class; - auto &worker = this->entity->get_attribute(); // handle unit type changes based on resource class - if (worker.graphics.count(this->resource_class) > 0) { - auto *new_type = worker.graphics.at(this->resource_class); - auto &pl_attr = this->entity->get_attribute(); - new_type->initialise(this->entity, pl_attr.player); + if (this->entity->has_attribute(attr_type::multitype)) { + this->entity->get_attribute().switchType(this->resource_class, this->entity); } // set the type of gatherer @@ -1057,22 +1031,19 @@ UnitReference GatherAction::nearest_dropsite(game_resource res_type) { } } -const graphic_set &GatherAction::current_graphics() const { - return this->entity->unit_type->graphics; -} - AttackAction::AttackAction(Unit *e, UnitReference tar) : TargetAction{e, graphic_type::attack, tar, get_attack_range(e)}, strike_percent{0.0f}, rate_of_fire{0.002f} { - // switch graphic type for villagers not collecting resources + // check if attacking a non resource unit if (this->entity->has_attribute(attr_type::worker) && (!tar.get()->has_attribute(attr_type::resource) || tar.get()->has_attribute(attr_type::worker))) { - auto &att_attr = this->entity->get_attribute(); - auto &pl_attr = this->entity->get_attribute(); - att_attr.attack_type->initialise(this->entity, pl_attr.player); + // switch to default villager graphics + if (this->entity->has_attribute(attr_type::multitype)) { + this->entity->get_attribute().switchType(gamedata::unit_classes::CIVILIAN, this->entity); + } } } diff --git a/libopenage/unit/action.h b/libopenage/unit/action.h index 3debea77ac..4ca9b60377 100644 --- a/libopenage/unit/action.h +++ b/libopenage/unit/action.h @@ -1,4 +1,4 @@ -// Copyright 2014-2016 the openage authors. See copying.md for legal info. +// Copyright 2014-2017 the openage authors. See copying.md for legal info. #pragma once @@ -397,7 +397,6 @@ class BuildAction: public TargetAction { bool completed_in_range(Unit *) const override { return this->complete >= 1.0f; } void on_completion() override; std::string name() const override { return "build"; } - const graphic_set ¤t_graphics() const override; private: float complete, build_rate; @@ -441,7 +440,6 @@ class GatherAction: public TargetAction { void update_in_range(unsigned int time, Unit *target_unit) override; bool completed_in_range(Unit *) const override { return this->complete; } std::string name() const override { return "gather"; } - const graphic_set ¤t_graphics() const override; private: bool complete, target_resource; diff --git a/libopenage/unit/attribute.cpp b/libopenage/unit/attribute.cpp index 340fa84886..396cdd35bc 100644 --- a/libopenage/unit/attribute.cpp +++ b/libopenage/unit/attribute.cpp @@ -1,6 +1,8 @@ -// Copyright 2016-2016 the openage authors. See copying.md for legal info. +// Copyright 2016-2017 the openage authors. See copying.md for legal info. #include "attribute.h" +#include "unit.h" +#include "unit_type.h" namespace openage { @@ -8,15 +10,21 @@ void Attributes::add(const std::shared_ptr attr) { this->attrs[attr->type] = attr; } -void Attributes::addCopies(const Attributes & other) { - for (const auto &i : other.attrs) { - const auto &attr = *i.second.get(); +void Attributes::addCopies(const Attributes &other) { + this->addCopies(other, true, true); +} + +void Attributes::addCopies(const Attributes &other, bool shared, bool unshared) { + for (auto &i : other.attrs) { + auto &attr = *i.second.get(); if (attr.shared()) { - // pass self - this->add(i.second); + if (shared) { + // pass self + this->add(i.second); + } } - else { + else if(unshared) { // create copy this->add(attr.copy()); } @@ -40,4 +48,12 @@ Attribute &Attributes::get() const { return *reinterpret_cast *>(this->attrs.at(T).get()); } +void Attribute::switchType(const gamedata::unit_classes cls, Unit *unit) const { + auto search = this->types.find(cls); + if (search != this->types.end()) { + auto &player = unit->get_attribute(); + search->second->reinitialise(unit, player.player); + } +} + } /* namespace openage */ diff --git a/libopenage/unit/attribute.h b/libopenage/unit/attribute.h index 82ca335a17..59df0d9146 100644 --- a/libopenage/unit/attribute.h +++ b/libopenage/unit/attribute.h @@ -1,4 +1,4 @@ -// Copyright 2014-2016 the openage authors. See copying.md for legal info. +// Copyright 2014-2017 the openage authors. See copying.md for legal info. #pragma once @@ -70,6 +70,7 @@ enum class attr_type { dropsite, resource, worker, + multitype, garrison }; @@ -131,6 +132,13 @@ class Attributes { */ void addCopies(const Attributes &attrs); + /** + * Add copies of all the attributes from the given Attributes. + * If shared is false, shared attributes are ignored. + * If unshared is false, unshared attributes are ignored. + */ + void addCopies(const Attributes &attrs, bool shared, bool unshared); + /** * Remove an attribute based on the type. */ @@ -282,19 +290,18 @@ template<> class Attribute: public UnsharedAttributeContainer public: // TODO remove (keep for testing) // 4 = gamedata::hit_class::UNITS_MELEE (not exported at the moment) - Attribute(UnitType *type, coord::phys_t r, coord::phys_t h, unsigned int d, UnitType *reset_type) + Attribute(UnitType *type, coord::phys_t r, coord::phys_t h, unsigned int d) : - Attribute{type, r, h, {{4, d}}, reset_type} {} + Attribute{type, r, h, {{4, d}}} {} - Attribute(UnitType *type, coord::phys_t r, coord::phys_t h, typeamount_map d, UnitType *reset_type) + Attribute(UnitType *type, coord::phys_t r, coord::phys_t h, typeamount_map d) : UnsharedAttributeContainer{attr_type::attack}, ptype{type}, range{r}, init_height{h}, damage{d}, - stance{attack_stance::do_nothing}, - attack_type{reset_type} {} + stance{attack_stance::do_nothing} {} std::shared_ptr copy() const override { return std::make_shared>(*this); @@ -310,10 +317,6 @@ template<> class Attribute: public UnsharedAttributeContainer // TODO move elsewhere in order to become shared attribute attack_stance stance; - - // TODO move elsewhere in order to become shared attribute - // used to change graphics back to normal for villagers - UnitType *attack_type; }; /** @@ -468,16 +471,14 @@ template<> class Attribute: public UnsharedAttributeContain double amount; }; -class UnitTexture; - /** * The worker's capacity and gather rates. */ -template<> class Attribute: public UnsharedAttributeContainer { +template<> class Attribute: public SharedAttributeContainer { public: Attribute() : - UnsharedAttributeContainer{attr_type::worker} {} + SharedAttributeContainer{attr_type::worker} {} std::shared_ptr copy() const override { return std::make_shared>(*this); @@ -493,10 +494,33 @@ template<> class Attribute: public UnsharedAttributeContainer * The ResourceBundle class is used but instead of amounts it stores gather rates. */ ResourceBundle gather_rate; +}; + +class Unit; + +/** + * Stores the collection of unit types based on a unit class. + * It is used mostly for units with multiple graphics (villagers, trebuchets). + */ +template<> class Attribute: public SharedAttributeContainer { +public: + Attribute() + : + SharedAttributeContainer{attr_type::multitype} {} + + std::shared_ptr copy() const override { + return std::make_shared>(*this); + } + + /** + * Switch the type of a unit based on a given unit class + */ + void switchType(const gamedata::unit_classes cls, Unit *unit) const; - // texture sets available for each resource - // TODO move elsewhere - std::unordered_map graphics; + /** + * The collection of unit class to unit type pairs + */ + std::unordered_map types; }; /** diff --git a/libopenage/unit/producer.cpp b/libopenage/unit/producer.cpp index fc58b56f91..c4d14383db 100644 --- a/libopenage/unit/producer.cpp +++ b/libopenage/unit/producer.cpp @@ -380,15 +380,14 @@ void MovableProducer::initialise(Unit *unit, Player &player) { // projectile of melee attacks UnitType *proj_type = this->owner.get_type(this->projectile); - UnitType *reset_type = this->parent_type(); if (this->unit_data.projectile_unit_id > 0 && proj_type) { // calculate requirements for ranged attacks coord::phys_t range_phys = coord::settings::phys_per_tile * this->unit_data.max_range; - unit->add_attribute(std::make_shared>(proj_type, range_phys, 48000, 1, reset_type)); + unit->add_attribute(std::make_shared>(proj_type, range_phys, 48000, 1)); } else { - unit->add_attribute(std::make_shared>(nullptr, 0, 0, 1, reset_type)); + unit->add_attribute(std::make_shared>(nullptr, 0, 0, 1)); } } @@ -418,6 +417,7 @@ void LivingProducer::initialise(Unit *unit, Player &player) { if (this->unit_data.unit_class == gamedata::unit_classes::CIVILIAN) { unit->add_attribute(std::make_shared>()); unit->add_attribute(std::make_shared>()); + unit->add_attribute(std::make_shared>()); // add graphic ids for resource actions auto &worker_attr = unit->get_attribute(); @@ -427,28 +427,31 @@ void LivingProducer::initialise(Unit *unit, Player &player) { worker_attr.gather_rate[game_resource::gold] = 0.002; worker_attr.gather_rate[game_resource::stone] = 0.002; + auto &multitype_attr = unit->get_attribute(); // currently not sure where the game data keeps these values // todo PREY_ANIMAL SEA_FISH if (this->parent_id() == 83) { // male graphics - worker_attr.graphics[gamedata::unit_classes::BUILDING] = this->owner.get_type(156); // builder 118 - worker_attr.graphics[gamedata::unit_classes::BERRY_BUSH] = this->owner.get_type(120); // forager - worker_attr.graphics[gamedata::unit_classes::SHEEP] = this->owner.get_type(592); // sheperd - worker_attr.graphics[gamedata::unit_classes::TREES] = this->owner.get_type(123); // woodcutter - worker_attr.graphics[gamedata::unit_classes::GOLD_MINE] = this->owner.get_type(579); // gold miner - worker_attr.graphics[gamedata::unit_classes::STONE_MINE] = this->owner.get_type(124); // stone miner + multitype_attr.types[gamedata::unit_classes::CIVILIAN] = this->parent_type(); // get default villager + multitype_attr.types[gamedata::unit_classes::BUILDING] = this->owner.get_type(156); // builder 118 + multitype_attr.types[gamedata::unit_classes::BERRY_BUSH] = this->owner.get_type(120); // forager + multitype_attr.types[gamedata::unit_classes::SHEEP] = this->owner.get_type(592); // sheperd + multitype_attr.types[gamedata::unit_classes::TREES] = this->owner.get_type(123); // woodcutter + multitype_attr.types[gamedata::unit_classes::GOLD_MINE] = this->owner.get_type(579); // gold miner + multitype_attr.types[gamedata::unit_classes::STONE_MINE] = this->owner.get_type(124); // stone miner } else { // female graphics - worker_attr.graphics[gamedata::unit_classes::BUILDING] = this->owner.get_type(222); // builder 212 - worker_attr.graphics[gamedata::unit_classes::BERRY_BUSH] = this->owner.get_type(354); // forager - worker_attr.graphics[gamedata::unit_classes::SHEEP] = this->owner.get_type(590); // sheperd - worker_attr.graphics[gamedata::unit_classes::TREES] = this->owner.get_type(218); // woodcutter - worker_attr.graphics[gamedata::unit_classes::GOLD_MINE] = this->owner.get_type(581); // gold miner - worker_attr.graphics[gamedata::unit_classes::STONE_MINE] = this->owner.get_type(220); // stone miner + multitype_attr.types[gamedata::unit_classes::CIVILIAN] = this->parent_type(); // get default villager + multitype_attr.types[gamedata::unit_classes::BUILDING] = this->owner.get_type(222); // builder 212 + multitype_attr.types[gamedata::unit_classes::BERRY_BUSH] = this->owner.get_type(354); // forager + multitype_attr.types[gamedata::unit_classes::SHEEP] = this->owner.get_type(590); // sheperd + multitype_attr.types[gamedata::unit_classes::TREES] = this->owner.get_type(218); // woodcutter + multitype_attr.types[gamedata::unit_classes::GOLD_MINE] = this->owner.get_type(581); // gold miner + multitype_attr.types[gamedata::unit_classes::STONE_MINE] = this->owner.get_type(220); // stone miner } unit->give_ability(std::make_shared(this->on_attack)); unit->give_ability(std::make_shared(this->on_attack)); @@ -462,7 +465,6 @@ void LivingProducer::initialise(Unit *unit, Player &player) { auto &worker_attr = unit->get_attribute(); worker_attr.capacity = 15.0; worker_attr.gather_rate[game_resource::food] = 0.002; - worker_attr.graphics[gamedata::unit_classes::SEA_FISH] = this; unit->give_ability(std::make_shared(this->on_attack)); } @@ -567,7 +569,7 @@ void BuildingProducer::initialise(Unit *unit, Player &player) { UnitType *proj_type = this->owner.get_type(this->projectile); if (this->unit_data.projectile_unit_id > 0 && proj_type) { coord::phys_t range_phys = coord::settings::phys_per_tile * this->unit_data.max_range; - unit->add_attribute(std::make_shared>(proj_type, range_phys, 350000, 1, this)); + unit->add_attribute(std::make_shared>(proj_type, range_phys, 350000, 1)); unit->give_ability(std::make_shared()); } diff --git a/libopenage/unit/unit.cpp b/libopenage/unit/unit.cpp index 5e574973c7..59509699d0 100644 --- a/libopenage/unit/unit.cpp +++ b/libopenage/unit/unit.cpp @@ -1,4 +1,4 @@ -// Copyright 2014-2016 the openage authors. See copying.md for legal info. +// Copyright 2014-2017 the openage authors. See copying.md for legal info. #include #include @@ -250,6 +250,10 @@ void Unit::add_attributes(const Attributes &attr) { this->attributes.addCopies(attr); } +void Unit::add_attributes(const Attributes &attr, bool shared, bool unshared) { + this->attributes.addCopies(attr, shared, unshared); +} + bool Unit::has_attribute(attr_type type) const { return this->attributes.has(type); } diff --git a/libopenage/unit/unit.h b/libopenage/unit/unit.h index 2fa891d939..806ab8781b 100644 --- a/libopenage/unit/unit.h +++ b/libopenage/unit/unit.h @@ -174,11 +174,18 @@ class Unit : public log::LogSource { void add_attribute(std::shared_ptr attr); /** - * give a new attributes this this unit - * this is used to add the default attributes + * Give new attributes to this unit. + * This is used to add the default attributes */ void add_attributes(const Attributes &attr); + /** + * Give new attributes to this unit. + * If shared is false, shared attributes are ignored. + * If unshared is false, unshared attributes are ignored. + */ + void add_attributes(const Attributes &attr, bool shared, bool unshared); + /** * returns whether attribute is available */ diff --git a/libopenage/unit/unit_type.cpp b/libopenage/unit/unit_type.cpp index 30a6ec71ac..4ce4467e33 100644 --- a/libopenage/unit/unit_type.cpp +++ b/libopenage/unit/unit_type.cpp @@ -29,6 +29,11 @@ UnitType::UnitType(const Player &owner) owner{owner} { } +void UnitType::reinitialise(Unit *unit, Player &player) { + // TODO implement it + this->initialise(unit, player); +} + bool UnitType::operator==(const UnitType &other) const { return this->type_abilities == other.type_abilities; } @@ -101,7 +106,7 @@ std::string NyanType::name() const { } void NyanType::initialise(Unit *unit, Player &) { - // reset any existing attributes and type + // removes all actions and abilities unit->reset(); // initialise unit diff --git a/libopenage/unit/unit_type.h b/libopenage/unit/unit_type.h index be2a90398d..0019d3e442 100644 --- a/libopenage/unit/unit_type.h +++ b/libopenage/unit/unit_type.h @@ -1,4 +1,4 @@ -// Copyright 2015-2016 the openage authors. See copying.md for legal info. +// Copyright 2015-2017 the openage authors. See copying.md for legal info. #pragma once @@ -86,6 +86,16 @@ class UnitType { */ virtual void initialise(Unit *, Player &) = 0; + /** + * Initialize units shared attributes only to this type spec + * + * This can be called using existing units to modify type if the type + * Ensure that the unit has been placed before seting the units type + * + * TODO define if pure vitrual or not / should be in nyan? + */ + virtual void reinitialise(Unit *, Player &); + /** * set unit in place -- return if placement was successful * From 087b8360585f8b7278ccbb1db86061c463f24e15 Mon Sep 17 00:00:00 2001 From: MaanooAk Date: Sun, 1 Jan 2017 23:30:17 +0200 Subject: [PATCH 12/17] Reinitialise implementation --- libopenage/unit/unit.h | 13 ++++++------- libopenage/unit/unit_type.cpp | 9 ++++++++- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/libopenage/unit/unit.h b/libopenage/unit/unit.h index 806ab8781b..5416d333e7 100644 --- a/libopenage/unit/unit.h +++ b/libopenage/unit/unit.h @@ -246,6 +246,12 @@ class Unit : public log::LogSource { */ std::string logsource_name() override; + /** + * Unit attributes include color, hitpoints, speed, objects garrisoned etc + * contains 0 or 1 values for each type + */ + Attributes attributes; + private: /** * ability available -- actions that this entity @@ -277,13 +283,6 @@ class Unit : public log::LogSource { std::mutex command_queue_lock; - /** - * Unit attributes include color, hitpoints, speed, objects garrisoned etc - * contains 0 or 1 values for each type - */ - Attributes attributes; - - /** * pop any destructable actions on the next update cycle * and prevent additional actions being added diff --git a/libopenage/unit/unit_type.cpp b/libopenage/unit/unit_type.cpp index 4ce4467e33..33f002241d 100644 --- a/libopenage/unit/unit_type.cpp +++ b/libopenage/unit/unit_type.cpp @@ -30,8 +30,15 @@ UnitType::UnitType(const Player &owner) } void UnitType::reinitialise(Unit *unit, Player &player) { - // TODO implement it + // In case reinitialise is not implemented separately + + Attributes tmp; + // copy only unshared + tmp.addCopies(unit->attributes, false, true); + // initialise the new unit this->initialise(unit, player); + // replace new unshared attributes with the old + unit->attributes.addCopies(tmp); } bool UnitType::operator==(const UnitType &other) const { From c2aa239a9cdd06256348510cd4824ae5e8ef98c4 Mon Sep 17 00:00:00 2001 From: MaanooAk Date: Mon, 2 Jan 2017 12:40:30 +0200 Subject: [PATCH 13/17] Next building selection and other fixes --- libopenage/unit/action.cpp | 7 ++++--- libopenage/unit/attribute.cpp | 10 +++++++--- libopenage/unit/attribute.h | 10 +++------- libopenage/unit/unit.cpp | 4 ++-- libopenage/unit/unit_type.cpp | 4 ++-- 5 files changed, 18 insertions(+), 17 deletions(-) diff --git a/libopenage/unit/action.cpp b/libopenage/unit/action.cpp index d32e148a5c..75c82afed1 100644 --- a/libopenage/unit/action.cpp +++ b/libopenage/unit/action.cpp @@ -807,7 +807,8 @@ void BuildAction::on_completion() { } this->entity->log(MSG(dbg) << "Done building, searching for new building"); auto valid = [this](const TerrainObject &obj) { - if (!obj.unit.has_attribute(attr_type::building) || + if (!this->entity->get_attribute().player.owns(obj.unit) || + !obj.unit.has_attribute(attr_type::building) || obj.unit.get_attribute().completed >= 1.0f) { return false; } @@ -982,7 +983,7 @@ void GatherAction::update_in_range(unsigned int time, Unit *targeted_resource) { // dropsite has been reached // add value to player stockpile - Player &player = this->entity->get_attribute().player; + auto &player = this->entity->get_attribute().player; player.receive(worker_resource.resource_type, worker_resource.amount); worker_resource.amount = 0.0; @@ -1087,7 +1088,7 @@ void AttackAction::fire_projectile(const Attribute &att, cons current_pos.up = att.init_height; // create using the producer - auto player = this->entity->get_attribute().player; + auto &player = this->entity->get_attribute().player; auto projectile_ref = container->new_unit(*att.ptype, player, current_pos); // send towards target using a projectile ability (creates projectile motion action) diff --git a/libopenage/unit/attribute.cpp b/libopenage/unit/attribute.cpp index 396cdd35bc..399778ba17 100644 --- a/libopenage/unit/attribute.cpp +++ b/libopenage/unit/attribute.cpp @@ -10,11 +10,11 @@ void Attributes::add(const std::shared_ptr attr) { this->attrs[attr->type] = attr; } -void Attributes::addCopies(const Attributes &other) { - this->addCopies(other, true, true); +void Attributes::add_copies(const Attributes &other) { + this->add_copies(other, true, true); } -void Attributes::addCopies(const Attributes &other, bool shared, bool unshared) { +void Attributes::add_copies(const Attributes &other, bool shared, bool unshared) { for (auto &i : other.attrs) { auto &attr = *i.second.get(); @@ -48,6 +48,10 @@ Attribute &Attributes::get() const { return *reinterpret_cast *>(this->attrs.at(T).get()); } +bool Attribute::accepting_resource(game_resource res) const { + return std::find(resource_types.begin(), resource_types.end(), res) != resource_types.end(); +} + void Attribute::switchType(const gamedata::unit_classes cls, Unit *unit) const { auto search = this->types.find(cls); if (search != this->types.end()) { diff --git a/libopenage/unit/attribute.h b/libopenage/unit/attribute.h index 59df0d9146..ff9ca28101 100644 --- a/libopenage/unit/attribute.h +++ b/libopenage/unit/attribute.h @@ -130,14 +130,14 @@ class Attributes { /** * Add copies of all the attributes from the given Attributes. */ - void addCopies(const Attributes &attrs); + void add_copies(const Attributes &attrs); /** * Add copies of all the attributes from the given Attributes. * If shared is false, shared attributes are ignored. * If unshared is false, unshared attributes are ignored. */ - void addCopies(const Attributes &attrs, bool shared, bool unshared); + void add_copies(const Attributes &attrs, bool shared, bool unshared); /** * Remove an attribute based on the type. @@ -187,7 +187,6 @@ class SharedAttributeContainer: public AttributeContainer { bool shared() const override { return true; } - }; /** @@ -206,7 +205,6 @@ class UnsharedAttributeContainer: public AttributeContainer { bool shared() const override { return false; } - }; // ----------------------------- @@ -441,9 +439,7 @@ template<> class Attribute: public SharedAttributeContainer return std::make_shared>(*this); } - bool accepting_resource(game_resource res) { - return std::find(resource_types.begin(), resource_types.end(), res) != resource_types.end(); - } + bool accepting_resource(game_resource res) const; std::vector resource_types; }; diff --git a/libopenage/unit/unit.cpp b/libopenage/unit/unit.cpp index 59509699d0..c0d1bac18e 100644 --- a/libopenage/unit/unit.cpp +++ b/libopenage/unit/unit.cpp @@ -247,11 +247,11 @@ void Unit::add_attribute(std::shared_ptr attr) { } void Unit::add_attributes(const Attributes &attr) { - this->attributes.addCopies(attr); + this->attributes.add_copies(attr); } void Unit::add_attributes(const Attributes &attr, bool shared, bool unshared) { - this->attributes.addCopies(attr, shared, unshared); + this->attributes.add_copies(attr, shared, unshared); } bool Unit::has_attribute(attr_type type) const { diff --git a/libopenage/unit/unit_type.cpp b/libopenage/unit/unit_type.cpp index 33f002241d..2fe7828aae 100644 --- a/libopenage/unit/unit_type.cpp +++ b/libopenage/unit/unit_type.cpp @@ -34,11 +34,11 @@ void UnitType::reinitialise(Unit *unit, Player &player) { Attributes tmp; // copy only unshared - tmp.addCopies(unit->attributes, false, true); + tmp.add_copies(unit->attributes, false, true); // initialise the new unit this->initialise(unit, player); // replace new unshared attributes with the old - unit->attributes.addCopies(tmp); + unit->attributes.add_copies(tmp); } bool UnitType::operator==(const UnitType &other) const { From 45bdfcab02721dbc042a8e33ceb2022532fdd9f6 Mon Sep 17 00:00:00 2001 From: MaanooAk Date: Tue, 10 Jan 2017 20:09:50 +0200 Subject: [PATCH 14/17] Added formation attribute --- libopenage/unit/action.cpp | 3 ++- libopenage/unit/attribute.cpp | 2 +- libopenage/unit/attribute.h | 36 ++++++++++++++++++++++++++++++----- libopenage/unit/producer.cpp | 3 +++ 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/libopenage/unit/action.cpp b/libopenage/unit/action.cpp index 75c82afed1..b372b4075a 100644 --- a/libopenage/unit/action.cpp +++ b/libopenage/unit/action.cpp @@ -397,7 +397,8 @@ void IdleAction::update(unsigned int time) { if (this->entity->location && this->entity->has_attribute(attr_type::owner) && this->entity->has_attribute(attr_type::attack) && - this->entity->get_attribute().stance != attack_stance::do_nothing) { + this->entity->has_attribute(attr_type::formation) && + this->entity->get_attribute().stance != attack_stance::do_nothing) { // restart search from new tile when moved auto terrain = this->entity->location->get_terrain(); diff --git a/libopenage/unit/attribute.cpp b/libopenage/unit/attribute.cpp index 399778ba17..bc5b2fc9bb 100644 --- a/libopenage/unit/attribute.cpp +++ b/libopenage/unit/attribute.cpp @@ -24,7 +24,7 @@ void Attributes::add_copies(const Attributes &other, bool shared, bool unshared) this->add(i.second); } } - else if(unshared) { + else if (unshared) { // create copy this->add(attr.copy()); } diff --git a/libopenage/unit/attribute.h b/libopenage/unit/attribute.h index ff9ca28101..1f7aa1790e 100644 --- a/libopenage/unit/attribute.h +++ b/libopenage/unit/attribute.h @@ -62,6 +62,7 @@ enum class attr_type { hitpoints, armor, attack, + formation, heal, speed, direction, @@ -81,6 +82,14 @@ enum class attack_stance { do_nothing }; +enum class attack_formation { + line, + staggered, + box, + flank +}; + + /** * this type gets specialized for each attribute */ @@ -284,7 +293,7 @@ template<> class Attribute: public SharedAttributeContainer { typeamount_map armor; }; -template<> class Attribute: public UnsharedAttributeContainer { +template<> class Attribute: public SharedAttributeContainer { public: // TODO remove (keep for testing) // 4 = gamedata::hit_class::UNITS_MELEE (not exported at the moment) @@ -294,12 +303,11 @@ template<> class Attribute: public UnsharedAttributeContainer Attribute(UnitType *type, coord::phys_t r, coord::phys_t h, typeamount_map d) : - UnsharedAttributeContainer{attr_type::attack}, + SharedAttributeContainer{attr_type::attack}, ptype{type}, range{r}, init_height{h}, - damage{d}, - stance{attack_stance::do_nothing} {} + damage{d} {} std::shared_ptr copy() const override { return std::make_shared>(*this); @@ -312,9 +320,27 @@ template<> class Attribute: public UnsharedAttributeContainer coord::phys_t range; coord::phys_t init_height; typeamount_map damage; +}; + +template<> class Attribute: public UnsharedAttributeContainer { +public: + + Attribute() + : + Attribute{attack_stance::do_nothing} {} + + Attribute(attack_stance stance) + : + UnsharedAttributeContainer{attr_type::formation}, + stance{stance}, + formation{attack_formation::line} {} + + std::shared_ptr copy() const override { + return std::make_shared>(*this); + } - // TODO move elsewhere in order to become shared attribute attack_stance stance; + attack_formation formation; }; /** diff --git a/libopenage/unit/producer.cpp b/libopenage/unit/producer.cpp index c4d14383db..bcc8ba56f9 100644 --- a/libopenage/unit/producer.cpp +++ b/libopenage/unit/producer.cpp @@ -389,6 +389,7 @@ void MovableProducer::initialise(Unit *unit, Player &player) { else { unit->add_attribute(std::make_shared>(nullptr, 0, 0, 1)); } + unit->add_attribute(std::make_shared>()); } TerrainObject *MovableProducer::place(Unit *unit, std::shared_ptr terrain, coord::phys3 init_pos) const { @@ -570,6 +571,8 @@ void BuildingProducer::initialise(Unit *unit, Player &player) { if (this->unit_data.projectile_unit_id > 0 && proj_type) { coord::phys_t range_phys = coord::settings::phys_per_tile * this->unit_data.max_range; unit->add_attribute(std::make_shared>(proj_type, range_phys, 350000, 1)); + // formation is used only for the attack_stance + unit->add_attribute(std::make_shared>(attack_stance::aggresive)); unit->give_ability(std::make_shared()); } From 2e4110e84260a7a262fe34eca466bfd3cb8b1a8e Mon Sep 17 00:00:00 2001 From: MaanooAk Date: Tue, 10 Jan 2017 20:55:11 +0200 Subject: [PATCH 15/17] Added missing doc --- libopenage/unit/attribute.h | 45 +++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/libopenage/unit/attribute.h b/libopenage/unit/attribute.h index 1f7aa1790e..a3594213b4 100644 --- a/libopenage/unit/attribute.h +++ b/libopenage/unit/attribute.h @@ -31,7 +31,7 @@ template<> struct hash { namespace openage { /** - * types of action graphics + * Types of action graphics */ enum class graphic_type { construct, @@ -49,12 +49,12 @@ enum class graphic_type { class UnitTexture; /** - * collection of graphics attached to each unit + * Collection of graphics attached to each unit. */ using graphic_set = std::map>; /** - * list of attribute types + * List of unit's attribute types. */ enum class attr_type { owner, @@ -75,6 +75,10 @@ enum class attr_type { garrison }; +/** + * List of unit's attack stance. + * Can be used for buildings also. + */ enum class attack_stance { aggresive, devensive, @@ -82,6 +86,10 @@ enum class attack_stance { do_nothing }; +/** + * List of unit's formation. + * Effect applys on a group of units. + */ enum class attack_formation { line, staggered, @@ -96,7 +104,7 @@ enum class attack_formation { template class Attribute; /** - * wraps a templated attribute + * Wraps a templated attribute */ class AttributeContainer { public: @@ -293,6 +301,10 @@ template<> class Attribute: public SharedAttributeContainer { typeamount_map armor; }; +/** + * TODO implement min range + * TODO can a unit have multiple attacks such as villagers hunting map target classes onto attacks + */ template<> class Attribute: public SharedAttributeContainer { public: // TODO remove (keep for testing) @@ -313,15 +325,28 @@ template<> class Attribute: public SharedAttributeContainer { return std::make_shared>(*this); } - // TODO: can a unit have multiple attacks such as villagers hunting - // map target classes onto attacks + /** + * The projectile's unit type + */ + UnitType *ptype; - UnitType *ptype; // projectile type + /** + * The max range of the attack + */ coord::phys_t range; + + /** + * The height from which the projectile starts + */ coord::phys_t init_height; + typeamount_map damage; }; +/** + * The attack stance and formation + * TODO store patrol and follow command information + */ template<> class Attribute: public UnsharedAttributeContainer { public: @@ -386,7 +411,6 @@ template<> class Attribute: public SharedAttributeContainer { return std::make_shared>(*this); } - // TODO possibly use a pointer to account for tech upgrades // TODO rename to default or normal coord::phys_t unit_speed; }; @@ -422,6 +446,9 @@ template<> class Attribute: public UnsharedAttributeConta bool launched; }; +/** + * TODO revisit after unit training is improved + */ template<> class Attribute: public UnsharedAttributeContainer { public: Attribute() @@ -455,7 +482,6 @@ template<> class Attribute: public UnsharedAttributeContain */ template<> class Attribute: public SharedAttributeContainer { public: - Attribute(std::vector types) : SharedAttributeContainer{attr_type::dropsite}, @@ -472,6 +498,7 @@ template<> class Attribute: public SharedAttributeContainer /** * Resource capacity of a trees, mines, animal, worker etc. + * TODO add a way to define slower and faster resource gathering time needed */ template<> class Attribute: public UnsharedAttributeContainer { public: From 781f03e6a394436a989bfa39b927dcf6a1a38e71 Mon Sep 17 00:00:00 2001 From: MaanooAk Date: Mon, 23 Jan 2017 11:29:39 +0200 Subject: [PATCH 16/17] Doc, conflicts and small improvments --- libopenage/gamestate/resource.cpp | 2 +- libopenage/gamestate/resource.h | 6 +++++- libopenage/unit/selection.cpp | 3 ++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/libopenage/gamestate/resource.cpp b/libopenage/gamestate/resource.cpp index 0bb2716042..c0c7d5b9e7 100644 --- a/libopenage/gamestate/resource.cpp +++ b/libopenage/gamestate/resource.cpp @@ -62,7 +62,7 @@ bool ResourceBundle::has(const ResourceBundle& amount) const { } bool ResourceBundle::deduct(const ResourceBundle& amount) { - if (*this >= amount) { + if (this->has(amount)) { *this -= amount; return true; } diff --git a/libopenage/gamestate/resource.h b/libopenage/gamestate/resource.h index f110a3b147..699239d815 100644 --- a/libopenage/gamestate/resource.h +++ b/libopenage/gamestate/resource.h @@ -41,6 +41,10 @@ class ResourceBundle { bool has(const ResourceBundle& amount) const; + /** + * If amount can't be deducted return false, else deduct the given amount + * and return true. + */ bool deduct(const ResourceBundle& amount); double& operator[] (const game_resource res) { return value[(int) res]; } @@ -49,7 +53,7 @@ class ResourceBundle { // Getters double get(const game_resource res) const { return value[(int) res]; } - double get(int index) const { return value[index]; } + double get(const int index) const { return value[index]; } private: double value[(int) game_resource::RESOURCE_TYPE_COUNT]; diff --git a/libopenage/unit/selection.cpp b/libopenage/unit/selection.cpp index c1c91b5f78..b6fabb9f97 100644 --- a/libopenage/unit/selection.cpp +++ b/libopenage/unit/selection.cpp @@ -312,7 +312,8 @@ void UnitSelection::show_attributes(Unit *u) { selection_type_t UnitSelection::get_unit_selection_type(const Player &player, Unit *u) { bool is_building = u->has_attribute(attr_type::building); - // Check color + // Check owner + // TODO implement allied units if (u->is_own_unit(player)) { return is_building ? selection_type_t::own_buildings : selection_type_t::own_units; } else { From e72f3761d52b4a11416c88eb38def2627c05bfcd Mon Sep 17 00:00:00 2001 From: MaanooAk Date: Mon, 6 Feb 2017 23:58:11 +0200 Subject: [PATCH 17/17] Moved Attributes to sepearte file --- libopenage/unit/CMakeLists.txt | 1 + libopenage/unit/attribute.cpp | 44 +----------------------- libopenage/unit/attribute.h | 51 ---------------------------- libopenage/unit/attributes.cpp | 49 +++++++++++++++++++++++++++ libopenage/unit/attributes.h | 62 ++++++++++++++++++++++++++++++++++ libopenage/unit/unit.h | 1 + libopenage/unit/unit_type.h | 2 +- 7 files changed, 115 insertions(+), 95 deletions(-) create mode 100644 libopenage/unit/attributes.cpp create mode 100644 libopenage/unit/attributes.h diff --git a/libopenage/unit/CMakeLists.txt b/libopenage/unit/CMakeLists.txt index f2dd73ecf0..fc901e8c87 100644 --- a/libopenage/unit/CMakeLists.txt +++ b/libopenage/unit/CMakeLists.txt @@ -2,6 +2,7 @@ add_sources(libopenage ability.cpp action.cpp attribute.cpp + attributes.cpp command.cpp producer.cpp selection.cpp diff --git a/libopenage/unit/attribute.cpp b/libopenage/unit/attribute.cpp index bc5b2fc9bb..6826bded35 100644 --- a/libopenage/unit/attribute.cpp +++ b/libopenage/unit/attribute.cpp @@ -6,48 +6,6 @@ namespace openage { -void Attributes::add(const std::shared_ptr attr) { - this->attrs[attr->type] = attr; -} - -void Attributes::add_copies(const Attributes &other) { - this->add_copies(other, true, true); -} - -void Attributes::add_copies(const Attributes &other, bool shared, bool unshared) { - for (auto &i : other.attrs) { - auto &attr = *i.second.get(); - - if (attr.shared()) { - if (shared) { - // pass self - this->add(i.second); - } - } - else if (unshared) { - // create copy - this->add(attr.copy()); - } - } -} - -bool Attributes::remove(const attr_type type) { - return this->attrs.erase(type) > 0; -} - -bool Attributes::has(const attr_type type) const { - return this->attrs.find(type) != this->attrs.end(); -} - -std::shared_ptr Attributes::get(const attr_type type) const { - return this->attrs.at(type); -} - -template -Attribute &Attributes::get() const { - return *reinterpret_cast *>(this->attrs.at(T).get()); -} - bool Attribute::accepting_resource(game_resource res) const { return std::find(resource_types.begin(), resource_types.end(), res) != resource_types.end(); } @@ -60,4 +18,4 @@ void Attribute::switchType(const gamedata::unit_classes cl } } -} /* namespace openage */ +} // namespace openage diff --git a/libopenage/unit/attribute.h b/libopenage/unit/attribute.h index a3594213b4..9a81aaac42 100644 --- a/libopenage/unit/attribute.h +++ b/libopenage/unit/attribute.h @@ -131,57 +131,6 @@ class AttributeContainer { virtual std::shared_ptr copy() const = 0; }; -/** - * Contains a group of attributes. - * Can contain only one attribute of each type. - */ -class Attributes { -public: - Attributes() {} - - /** - * Add an attribute or replace any attribute of the same type. - */ - void add(const std::shared_ptr attr); - - /** - * Add copies of all the attributes from the given Attributes. - */ - void add_copies(const Attributes &attrs); - - /** - * Add copies of all the attributes from the given Attributes. - * If shared is false, shared attributes are ignored. - * If unshared is false, unshared attributes are ignored. - */ - void add_copies(const Attributes &attrs, bool shared, bool unshared); - - /** - * Remove an attribute based on the type. - */ - bool remove(const attr_type type); - - /** - * Check if the attribute of the given type exists. - */ - bool has(const attr_type type) const; - - /** - * Get the attribute based on the type. - */ - std::shared_ptr get(const attr_type type) const; - - /** - * Get the attribute - */ - template - Attribute &get() const; - -private: - - std::map> attrs; -}; - /** * An unordered_map with a int key used as a type id * and a unsigned int value used as the amount diff --git a/libopenage/unit/attributes.cpp b/libopenage/unit/attributes.cpp new file mode 100644 index 0000000000..d42069189e --- /dev/null +++ b/libopenage/unit/attributes.cpp @@ -0,0 +1,49 @@ +// Copyright 2017-2017 the openage authors. See copying.md for legal info. + +#include "attributes.h" + +namespace openage { + +void Attributes::add(const std::shared_ptr attr) { + this->attrs[attr->type] = attr; +} + +void Attributes::add_copies(const Attributes &other) { + this->add_copies(other, true, true); +} + +void Attributes::add_copies(const Attributes &other, bool shared, bool unshared) { + for (auto &i : other.attrs) { + auto &attr = *i.second.get(); + + if (attr.shared()) { + if (shared) { + // pass self + this->add(i.second); + } + } + else if (unshared) { + // create copy + this->add(attr.copy()); + } + } +} + +bool Attributes::remove(const attr_type type) { + return this->attrs.erase(type) > 0; +} + +bool Attributes::has(const attr_type type) const { + return this->attrs.find(type) != this->attrs.end(); +} + +std::shared_ptr Attributes::get(const attr_type type) const { + return this->attrs.at(type); +} + +template +Attribute &Attributes::get() const { + return *reinterpret_cast *>(this->attrs.at(T).get()); +} + +} // namespace openage diff --git a/libopenage/unit/attributes.h b/libopenage/unit/attributes.h new file mode 100644 index 0000000000..03f40d3227 --- /dev/null +++ b/libopenage/unit/attributes.h @@ -0,0 +1,62 @@ +// Copyright 2017-2017 the openage authors. See copying.md for legal info. + +#pragma once + +#include + +#include "attribute.h" + +namespace openage { + +/** + * Contains a group of attributes. + * Can contain only one attribute of each type. + */ +class Attributes { +public: + Attributes() {} + + /** + * Add an attribute or replace any attribute of the same type. + */ + void add(const std::shared_ptr attr); + + /** + * Add copies of all the attributes from the given Attributes. + */ + void add_copies(const Attributes &attrs); + + /** + * Add copies of all the attributes from the given Attributes. + * If shared is false, shared attributes are ignored. + * If unshared is false, unshared attributes are ignored. + */ + void add_copies(const Attributes &attrs, bool shared, bool unshared); + + /** + * Remove an attribute based on the type. + */ + bool remove(const attr_type type); + + /** + * Check if the attribute of the given type exists. + */ + bool has(const attr_type type) const; + + /** + * Get the attribute based on the type. + */ + std::shared_ptr get(const attr_type type) const; + + /** + * Get the attribute + */ + template + Attribute &get() const; + +private: + + std::map> attrs; +}; + +} // namespace openage diff --git a/libopenage/unit/unit.h b/libopenage/unit/unit.h index 5416d333e7..81c658632c 100644 --- a/libopenage/unit/unit.h +++ b/libopenage/unit/unit.h @@ -15,6 +15,7 @@ #include "../util/timing.h" #include "ability.h" #include "attribute.h" +#include "attributes.h" #include "command.h" #include "unit_container.h" diff --git a/libopenage/unit/unit_type.h b/libopenage/unit/unit_type.h index 0019d3e442..acb7e0017a 100644 --- a/libopenage/unit/unit_type.h +++ b/libopenage/unit/unit_type.h @@ -8,7 +8,7 @@ #include #include "../coord/phys3.h" -#include "attribute.h" +#include "attributes.h" namespace openage {