From 845c81e2e6d6ce8ab97ba26dcd9af309db7ee150 Mon Sep 17 00:00:00 2001 From: Andrettin Date: Sun, 15 Nov 2015 20:19:53 +0100 Subject: [PATCH] Updates to ruler/hero code --- src/include/grand_strategy.h | 15 +++++-- src/stratagus/grand_strategy.cpp | 74 +++++++++++++++++++++++++++++--- src/stratagus/util.cpp | 5 +++ src/unit/script_unit.cpp | 24 +++++++++-- 4 files changed, 104 insertions(+), 14 deletions(-) diff --git a/src/include/grand_strategy.h b/src/include/grand_strategy.h index a01e0c200..34f7da8ab 100644 --- a/src/include/grand_strategy.h +++ b/src/include/grand_strategy.h @@ -255,6 +255,7 @@ class CGrandStrategyFaction void FormFaction(int civilization, int faction); void AcquireFactionTechnologies(int civilization, int faction); void SetRuler(std::string hero_full_name); + void RulerSuccession(); bool IsAlive(); bool HasTechnologyClass(std::string technology_class_name); bool CanFormFaction(int civilization, int faction); @@ -298,8 +299,10 @@ class CGrandStrategyHero public: CGrandStrategyHero() : State(0), Year(0), DeathYear(0), Civilization(-1), + Generated(false), Name(""), Dynasty(""), ProvinceOfOrigin(""), - DefaultType(NULL), Type(NULL), Province(NULL) + DefaultType(NULL), Type(NULL), Province(NULL), + Father(NULL), Mother(NULL) { } @@ -311,12 +314,16 @@ class CGrandStrategyHero int Year; /// Year in which the hero historically starts being active int DeathYear; /// Year in which the hero dies of natural causes int Civilization; /// Culture to which the hero belongs - std::string Name; /// given name of the hero - std::string Dynasty; /// name of the hero's dynasty - std::string ProvinceOfOrigin; /// province from which the hero originates + bool Generated; /// Whether the hero has been generated during gameplay or is a preset hero + std::string Name; /// Given name of the hero + std::string Dynasty; /// Name of the hero's dynasty + std::string ProvinceOfOrigin; /// Province from which the hero originates CUnitType *DefaultType; CUnitType *Type; CProvince *Province; + CGrandStrategyHero *Father; /// Hero's father + CGrandStrategyHero *Mother; /// Hero's mother + std::vector Children; /// Children of the hero }; /** diff --git a/src/stratagus/grand_strategy.cpp b/src/stratagus/grand_strategy.cpp index d3688aa48..4d422201f 100644 --- a/src/stratagus/grand_strategy.cpp +++ b/src/stratagus/grand_strategy.cpp @@ -514,6 +514,10 @@ void CGrandStrategyGame::DrawInterface() std::string ruler_name_string = GrandStrategyGame.Provinces[this->SelectedProvince]->Owner->Ruler->GetFullName(); CLabel(GetGameFont()).Draw(UI.InfoPanel.X + ((218 - 6) / 2) - (GetGameFont().Width(ruler_name_string) / 2), UI.InfoPanel.Y + 180 - 94 + (item_y * 23), ruler_name_string); item_y += 1; + + std::string ruler_class_string = "Class: " + GrandStrategyGame.Provinces[this->SelectedProvince]->Owner->Ruler->Type->Name; + CLabel(GetGameFont()).Draw(UI.InfoPanel.X + ((218 - 6) / 2) - (GetGameFont().Width(ruler_class_string) / 2), UI.InfoPanel.Y + 180 - 94 + (item_y * 23), ruler_class_string); + item_y += 1; } } @@ -871,7 +875,7 @@ void CGrandStrategyGame::DoTurn() } } - //check if any heroes should begin activity or die in this year + //check if any heroes should begin activity this year for (size_t i = 0; i < this->Heroes.size(); ++i) { int province_of_origin_id = GetProvinceId(this->Heroes[i]->ProvinceOfOrigin); if ( @@ -885,6 +889,10 @@ void CGrandStrategyGame::DoTurn() //make heroes appear in their start year this->Heroes[i]->Create(); } + } + + //check if any heroes should die this year (this needs to be done as its own loop to allow new rulers to appear in the same year their predecessor dies, and succeede him) + for (size_t i = 0; i < this->Heroes.size(); ++i) { if ( this->Heroes[i]->DeathYear == GrandStrategyYear && this->Heroes[i]->State != 0 @@ -3264,7 +3272,7 @@ void CGrandStrategyFaction::AcquireFactionTechnologies(int civilization, int fac void CGrandStrategyFaction::SetRuler(std::string hero_full_name) { if (hero_full_name.empty()) { - this->Ruler = NULL; + this->RulerSuccession(); return; } @@ -3282,13 +3290,45 @@ void CGrandStrategyFaction::SetRuler(std::string hero_full_name) char buf[256]; snprintf( buf, sizeof(buf), "if (GenericDialog ~= nil) then GenericDialog(\"%s\", \"%s\") end;", - ("Ruler " + this->GetFullName()).c_str(), - ("A new ruler has come to power in our realm, " + this->GetFullName() + "!").c_str() + ("Ruler " + this->Ruler->GetFullName()).c_str(), + ("A new ruler has come to power in our realm, " + this->Ruler->GetFullName() + "!").c_str() ); CclCommand(buf); } } +void CGrandStrategyFaction::RulerSuccession() +{ + if (this->GovernmentType == GovernmentTypeMonarchy) { //if is a monarchy, put the next in line on the throne + for (size_t i = 0; i < this->Ruler->Children.size(); ++i) { + if (this->Ruler->Children[i]->State != 0) { + this->SetRuler(this->Ruler->Children[i]->GetFullName()); + return; + } + } + } + + std::vector ruler_candidates; + for (size_t i = 0; i < GrandStrategyGame.Heroes.size(); ++i) { + int province_of_origin_id = GetProvinceId(GrandStrategyGame.Heroes[i]->ProvinceOfOrigin); + if ( + GrandStrategyGame.Heroes[i]->State != 0 + && ( + (GrandStrategyGame.Heroes[i]->Province != NULL && GrandStrategyGame.Heroes[i]->Province->Owner == this) + || (GrandStrategyGame.Heroes[i]->Province == NULL && province_of_origin_id != -1 && GrandStrategyGame.Provinces[province_of_origin_id]->Owner == this) + ) + ) { + ruler_candidates.push_back(GrandStrategyGame.Heroes[i]); + } + } + if (ruler_candidates.size() > 0) { + this->SetRuler(ruler_candidates[SyncRand(ruler_candidates.size())]->GetFullName()); + return; + } + + this->Ruler = NULL; +} + bool CGrandStrategyFaction::IsAlive() { return this->ProvinceCount > 0; @@ -3406,8 +3446,8 @@ void CGrandStrategyHero::Die() char buf[256]; snprintf( buf, sizeof(buf), "if (GenericDialog ~= nil) then GenericDialog(\"%s\", \"%s\") end;", - ("Ruler" + this->GetFullName() + " Dies").c_str(), - ("Our ruler " + this->GetFullName() + " has died! May his soul rest in peace!").c_str() + ("Ruler " + this->GetFullName() + " Dies").c_str(), + ("Tragic news spread throughout our realm. Our ruler, " + this->GetFullName() + ", has died! May his soul rest in peace.").c_str() ); CclCommand(buf); } else if ( @@ -3445,7 +3485,7 @@ void CGrandStrategyHero::Die() for (int j = 0; j < FactionMax; ++j) { if (GrandStrategyGame.Factions[i][j]) { if (GrandStrategyGame.Factions[i][j]->Ruler == this) { - GrandStrategyGame.Factions[i][j]->Ruler = NULL; + GrandStrategyGame.Factions[i][j]->SetRuler(""); } } else { break; @@ -4859,8 +4899,28 @@ void CleanGrandStrategyGame() GrandStrategyGame.Heroes[i]->State = 0; GrandStrategyGame.Heroes[i]->Province = NULL; GrandStrategyGame.Heroes[i]->Type = NULL; + for (size_t j = 0; j < GrandStrategyGame.Heroes[i]->Children.size(); ++j) { + if (GrandStrategyGame.Heroes[i]->Children[j]->Generated) { //remove children generated during gameplay + GrandStrategyGame.Heroes[i]->Children.erase(GrandStrategyGame.Heroes[i]->Children.begin() + j); + } + } + if (GrandStrategyGame.Heroes[i]->Father && GrandStrategyGame.Heroes[i]->Father->Generated) { + GrandStrategyGame.Heroes[i]->Father = NULL; + } + if (GrandStrategyGame.Heroes[i]->Mother && GrandStrategyGame.Heroes[i]->Mother->Generated) { + GrandStrategyGame.Heroes[i]->Mother = NULL; + } } + for (size_t i = 0; i < GrandStrategyGame.Heroes.size();) { + if (GrandStrategyGame.Heroes[i]->Generated) { //if hero was generated during the game, delete it + delete GrandStrategyGame.Heroes[i]; + GrandStrategyGame.Heroes.erase(GrandStrategyGame.Heroes.begin() + i); + } else { + ++i; + } + } + GrandStrategyGame.WorldMapWidth = 0; GrandStrategyGame.WorldMapHeight = 0; GrandStrategyGame.ProvinceCount = 0; diff --git a/src/stratagus/util.cpp b/src/stratagus/util.cpp index 099861229..6a41362fd 100644 --- a/src/stratagus/util.cpp +++ b/src/stratagus/util.cpp @@ -549,6 +549,10 @@ std::string FindAndReplaceStringBeginning(std::string text, const std::string& f std::string TransliterateText(std::string text) //convert special characters into ones more legible for English-speakers { + text = FindAndReplaceString(text, "Á", "A"); + text = FindAndReplaceString(text, "á", "a"); + text = FindAndReplaceString(text, "À", "A"); + text = FindAndReplaceString(text, "à", "a"); text = FindAndReplaceString(text, "Ä", "A"); text = FindAndReplaceString(text, "ä", "a"); text = FindAndReplaceString(text, "Ā", "A"); @@ -615,6 +619,7 @@ std::string TransliterateText(std::string text) //convert special characters int //replace endings in -r after consonants (which happens in the nominative for Old Norse); Source: Henry Adams Bellows (transl.), "The Poetic Edda", p. xxviii. text = FindAndReplaceStringEnding(text, "dr", "d"); + text = FindAndReplaceStringEnding(text, "fr", "f"); text = FindAndReplaceStringEnding(text, "gr", "g"); text = FindAndReplaceStringEnding(text, "kr", "k"); text = FindAndReplaceStringEnding(text, "nr", "n"); diff --git a/src/unit/script_unit.cpp b/src/unit/script_unit.cpp index 0c0095ab2..811ac8522 100644 --- a/src/unit/script_unit.cpp +++ b/src/unit/script_unit.cpp @@ -1661,7 +1661,7 @@ static int CclDefineGrandStrategyHero(lua_State *l) LuaError(l, "incorrect argument (expected table)"); } - std::string hero_full_name = LuaToString(l, 1); + std::string hero_full_name = TransliterateText(LuaToString(l, 1)); CGrandStrategyHero *hero = GrandStrategyGame.GetHero(hero_full_name); if (!hero) { hero = new CGrandStrategyHero; @@ -1674,9 +1674,9 @@ static int CclDefineGrandStrategyHero(lua_State *l) const char *value = LuaToString(l, -2); if (!strcmp(value, "Name")) { - hero->Name = LuaToString(l, -1); + hero->Name = TransliterateText(LuaToString(l, -1)); } else if (!strcmp(value, "Dynasty")) { - hero->Dynasty = LuaToString(l, -1); + hero->Dynasty = TransliterateText(LuaToString(l, -1)); } else if (!strcmp(value, "DefaultType")) { hero->DefaultType = const_cast(&(*UnitTypes[UnitTypeIdByIdent(LuaToString(l, -1))])); } else if (!strcmp(value, "Year")) { @@ -1687,6 +1687,24 @@ static int CclDefineGrandStrategyHero(lua_State *l) hero->Civilization = PlayerRaces.GetRaceIndexByName(LuaToString(l, -1)); } else if (!strcmp(value, "ProvinceOfOrigin")) { hero->ProvinceOfOrigin = LuaToString(l, -1); + } else if (!strcmp(value, "Father")) { + std::string father_name = TransliterateText(LuaToString(l, -1)); + CGrandStrategyHero *father = GrandStrategyGame.GetHero(father_name); + if (father) { + hero->Father = const_cast(&(*father)); + father->Children.push_back(hero); + } else { + LuaError(l, "Hero \"%s\" doesn't exist." _C_ father_name.c_str()); + } + } else if (!strcmp(value, "Mother")) { + std::string mother_name = TransliterateText(LuaToString(l, -1)); + CGrandStrategyHero *mother = GrandStrategyGame.GetHero(mother_name); + if (mother) { + hero->Mother = const_cast(&(*mother)); + mother->Children.push_back(hero); + } else { + LuaError(l, "Hero \"%s\" doesn't exist." _C_ mother_name.c_str()); + } } else { LuaError(l, "Unsupported tag: %s" _C_ value); }