Skip to content

Commit

Permalink
Added support for conditional requirements strings for unit types and…
Browse files Browse the repository at this point in the history
… unit classes
  • Loading branch information
Andrettin committed Feb 7, 2023
1 parent 175d3e0 commit d3a148f
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ source_group(religion FILES ${religion_SRCS})

set(script_SRCS
src/script/cheat.cpp
src/script/conditional_string.cpp
src/script/context.cpp
src/script/factor.cpp
src/script/factor_modifier.cpp
Expand Down Expand Up @@ -900,6 +901,7 @@ set(wyrmgus_religion_HDRS

set(wyrmgus_script_HDRS
src/script/cheat.h
src/script/conditional_string.h
src/script/context.h
src/script/factor.h
src/script/factor_modifier.h
Expand Down
1 change: 1 addition & 0 deletions src/script/conditional_string.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

#include "database/gsml_property.h"
#include "script/condition/and_condition.h"
#include "util/assert_util.h"

namespace wyrmgus {

Expand Down
2 changes: 1 addition & 1 deletion src/script/conditional_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class conditional_string final

const condition<scope_type> *get_conditions() const
{
return this->conditions;
return this->conditions.get();
}

private:
Expand Down
2 changes: 1 addition & 1 deletion src/stratagus/script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1766,7 +1766,7 @@ std::string EvalString(const StringDesc *s)
case EString_TypeRequirementsString : // name of the unit type's requirements string
type = s->D.Type;
if (type != nullptr) {
return (**type).get_requirements_string();
return (**type).get_requirements_string(CPlayer::GetThisPlayer());
} else { // ERROR.
return std::string();
}
Expand Down
24 changes: 23 additions & 1 deletion src/unit/unit_class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "language/name_generator.h"
#include "map/terrain_type.h"
#include "script/condition/and_condition.h"
#include "script/conditional_string.h"
#include "unit/unit_type.h"
#include "upgrade/upgrade_class.h"
#include "util/vector_util.h"
Expand Down Expand Up @@ -65,7 +66,13 @@ void unit_class::process_gsml_scope(const gsml_data &scope)
const std::string &tag = scope.get_tag();
const std::vector<std::string> &values = scope.get_values();

if (tag == "preconditions") {
if (tag == "conditional_requirements_strings") {
scope.for_each_child([&](const gsml_data &child_scope) {
auto conditional_string = std::make_unique<wyrmgus::conditional_string<CPlayer>>();
database::process_gsml_data(conditional_string, child_scope);
this->conditional_requirements_strings.push_back(std::move(conditional_string));
});
} else if (tag == "preconditions") {
this->preconditions = std::make_unique<and_condition<CPlayer>>();
database::process_gsml_data(this->preconditions, scope);
} else if (tag == "conditions") {
Expand Down Expand Up @@ -121,6 +128,21 @@ void unit_class::set_town_hall(const bool town_hall)
}
}

const std::string &unit_class::get_requirements_string(const CPlayer *player) const
{
const read_only_context ctx = read_only_context::from_scope(player);

for (const auto &conditional_string : this->conditional_requirements_strings) {
if (!conditional_string->get_conditions()->check(player, ctx)) {
continue;
}

return conditional_string->get_text();
}

return this->get_requirements_string();
}

bool unit_class::has_unit_type(unit_type *unit_type) const
{
return vector::contains(this->unit_types, unit_type);
Expand Down
6 changes: 6 additions & 0 deletions src/unit/unit_class.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ class upgrade_class;
template <typename scope_type>
class condition;

template <typename scope_type>
class conditional_string;

class unit_class final : public named_data_entry, public data_type<unit_class>
{
Q_OBJECT
Expand Down Expand Up @@ -138,6 +141,8 @@ class unit_class final : public named_data_entry, public data_type<unit_class>
return this->requirements_string;
}

const std::string &get_requirements_string(const CPlayer *player) const;

const std::vector<unit_type *> &get_unit_types() const
{
return this->unit_types;
Expand Down Expand Up @@ -209,6 +214,7 @@ class unit_class final : public named_data_entry, public data_type<unit_class>
std::unique_ptr<condition<CPlayer>> preconditions;
std::unique_ptr<condition<CPlayer>> conditions;
std::string requirements_string;
std::vector<std::unique_ptr<const conditional_string<CPlayer>>> conditional_requirements_strings;
std::vector<unit_type *> unit_types;
unit_class *tech_tree_parent_unit_class = nullptr;
upgrade_class *tech_tree_parent_upgrade_class = nullptr;
Expand Down
30 changes: 30 additions & 0 deletions src/unit/unit_type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
#include "player/player_type.h"
#include "script.h"
#include "script/condition/and_condition.h"
#include "script/conditional_string.h"
#include "sound/sound.h"
#include "sound/unitsound.h"
#include "species/species.h"
Expand Down Expand Up @@ -808,6 +809,12 @@ void unit_type::process_gsml_scope(const gsml_data &scope)
this->subtypes.push_back(subtype);
}
});
} else if (tag == "conditional_requirements_strings") {
scope.for_each_child([&](const gsml_data &child_scope) {
auto conditional_string = std::make_unique<wyrmgus::conditional_string<CPlayer>>();
database::process_gsml_data(conditional_string, child_scope);
this->conditional_requirements_strings.push_back(std::move(conditional_string));
});
} else if (tag == "hue_ignored_colors") {
scope.for_each_child([&](const gsml_data &child_scope) {
this->hue_ignored_colors.insert(child_scope.to_color());
Expand Down Expand Up @@ -2238,6 +2245,29 @@ const std::string &unit_type::get_requirements_string() const
return this->requirements_string;
}

const std::string &unit_type::get_requirements_string(const CPlayer *player) const
{
const read_only_context ctx = read_only_context::from_scope(player);

for (const auto &conditional_string : this->conditional_requirements_strings) {
if (!conditional_string->get_conditions()->check(player, ctx)) {
continue;
}

return conditional_string->get_text();
}

if (!this->requirements_string.empty()) {
return this->requirements_string;
}

if (this->get_unit_class() != nullptr) {
return this->get_unit_class()->get_requirements_string(player);
}

return this->requirements_string;
}

bool unit_type::can_gain_experience() const
{
return this->BoolFlag[ORGANIC_INDEX].value;
Expand Down
5 changes: 5 additions & 0 deletions src/unit/unit_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ namespace wyrmgus {

template <typename scope_type>
class condition;

template <typename scope_type>
class conditional_string;
}

constexpr int UnitSides = 8;
Expand Down Expand Up @@ -1109,6 +1112,7 @@ class unit_type final : public detailed_data_entry, public data_type<unit_type>
}

const std::string &get_requirements_string() const;
const std::string &get_requirements_string(const CPlayer *player) const;

bool can_gain_experience() const;
bool is_infantry() const;
Expand Down Expand Up @@ -1144,6 +1148,7 @@ class unit_type final : public detailed_data_entry, public data_type<unit_type>
wyrmgus::faction *faction = nullptr; //which faction this unit belongs to, if any
std::vector<const unit_type *> subtypes; //subtypes of this type; when a unit of this type is created, it has a subtype picked automatically instead
std::string requirements_string;
std::vector<std::unique_ptr<const conditional_string<CPlayer>>> conditional_requirements_strings;
public:
std::string ExperienceRequirementsString; /// Experience requirements string of the unit type
std::string BuildingRulesString; /// Building rules string of the unit type
Expand Down

0 comments on commit d3a148f

Please sign in to comment.