1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Merge pull request #660 from ShubusCorporation/shc_rmg_issue

Mod system improvement: Patch 2
This commit is contained in:
Alexander Shishkin 2020-10-26 09:26:14 +03:00 committed by GitHub
commit 9ca9c809c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 130 additions and 29 deletions

View File

@ -846,6 +846,23 @@ void CCastleBuildings::enterFountain(const BuildingID & building, BuildingSubID:
{
std::vector<std::shared_ptr<CComponent>> comps(1, std::make_shared<CComponent>(CComponent::building,town->subID, building));
std::string descr = town->town->buildings.find(building)->second->Description();
std::string hasNotProduced;
std::string hasProduced;
if(this->town->town->faction->index == (TFaction)ETownType::RAMPART)
{
hasNotProduced = CGI->generaltexth->allTexts[677];
hasProduced = CGI->generaltexth->allTexts[678];
}
else
{
auto buildingName = town->town->getSpecialBuilding(subID)->Name();
hasNotProduced = std::string(CGI->generaltexth->localizedTexts["townHall"]["hasNotProduced"].String());
hasProduced = std::string(CGI->generaltexth->localizedTexts["townHall"]["hasProduced"].String());
boost::algorithm::replace_first(hasNotProduced, "%s", buildingName);
boost::algorithm::replace_first(hasProduced, "%s", buildingName);
}
bool isMysticPondOrItsUpgrade = subID == BuildingSubID::MYSTIC_POND
|| (upgrades != BuildingID::NONE
@ -857,10 +874,10 @@ void CCastleBuildings::enterFountain(const BuildingID & building, BuildingSubID:
if(isMysticPondOrItsUpgrade) //for vanila Rampart like towns
{
if(town->bonusValue.first == 0) //Mystic Pond produced nothing;
descr += "\n\n" + CGI->generaltexth->allTexts[677];
descr += "\n\n" + hasNotProduced;
else //Mystic Pond produced something;
{
descr += "\n\n" + CGI->generaltexth->allTexts[678];
descr += "\n\n" + hasProduced;
boost::algorithm::replace_first(descr, "%s", CGI->generaltexth->restypes[town->bonusValue.first]);
boost::algorithm::replace_first(descr, "%d", boost::lexical_cast<std::string>(town->bonusValue.second));
}

View File

@ -1269,7 +1269,18 @@ CUniversityWindow::CUniversityWindow(const CGHeroInstance * _hero, const IMarket
bars->preload();
if(market->o->ID == Obj::TOWN)
titlePic = std::make_shared<CAnimImage>(CGI->townh->factions[ETownType::CONFLUX]->town->clientInfo.buildingsIcons, BuildingID::MAGIC_UNIVERSITY);
{
auto town = dynamic_cast<const CGTownInstance *>(_market);
if(town)
{
auto faction = town->town->faction->index;
auto bid = town->town->getSpecialBuilding(BuildingSubID::MAGIC_UNIVERSITY)->bid;
titlePic = std::make_shared<CAnimImage>(CGI->townh->factions[faction]->town->clientInfo.buildingsIcons, bid);
}
else
titlePic = std::make_shared<CAnimImage>(CGI->townh->factions[ETownType::CONFLUX]->town->clientInfo.buildingsIcons, BuildingID::MAGIC_UNIVERSITY);
}
else
titlePic = std::make_shared<CPicture>("UNIVBLDG");

View File

@ -43,7 +43,15 @@
},
"townHall" :
{
"missingBase" : "Base building %s must be built first"
"missingBase" : "Base building %s must be built first",
"greetingManaVortex" : "As you near the %s your body is filled with new energy. You have doubled your normal spell points.",
"greetingKnowledge" : "You study the glyphs on the %s and gain insight into the workings of various magics (+1 Knowledge).",
"greetingSpellPower" : "The %s teaches you new ways to focus your magical powers (+1 Power).",
"greetingExperience" : "A visit to the %s teaches you many new skills (+1000 Experience).",
"greetingAttack" : "Some time spent at the %s allows you to learn more effective combat skills (+1 Attack Skill).",
"greetingDefence" : "Spending time in the %s, the experienced warriors therein teach you additional defensive skills (+1 Defense).",
"hasNotProduced" : "The %s has not produced anything yet.",
"hasProduced" : "The %s produced %d %s this week."
},
"logicalExpressions" :
{

View File

@ -217,6 +217,16 @@ BuildingID::EBuildingID CTown::getBuildingType(BuildingSubID::EBuildingSubID sub
return building == nullptr ? BuildingID::NONE : building->bid.num;
}
const std::string CTown::getGreeting(BuildingSubID::EBuildingSubID subID) const
{
return VLC->townh->getMappedValue<const std::string, BuildingSubID::EBuildingSubID>(subID, std::string(), specialMessages, false);
}
void CTown::setGreeting(BuildingSubID::EBuildingSubID subID, const std::string message) const
{
specialMessages.insert(std::pair<BuildingSubID::EBuildingSubID, const std::string>(subID, message));
}
CTownHandler::CTownHandler()
{
VLC->townh = this;

View File

@ -122,7 +122,7 @@ public:
h & subId;
h & height;
}
else if(!h.saving)
if(!h.saving && version < 793)
{
update792(bid, subId, height);
}
@ -228,6 +228,8 @@ public:
std::string getBuildingScope() const;
std::set<si32> getAllBuildings() const;
const CBuilding * getSpecialBuilding(BuildingSubID::EBuildingSubID subID) const;
const std::string getGreeting(BuildingSubID::EBuildingSubID subID) const;
void setGreeting(BuildingSubID::EBuildingSubID subID, const std::string message) const; //may affect only mutable field
BuildingID::EBuildingID getBuildingType(BuildingSubID::EBuildingSubID subID) const;
CFaction * faction;
@ -335,6 +337,10 @@ public:
}
h & defaultTavernChance;
}
private:
///generated bonusing buildings messages for all towns of this type.
mutable std::map<BuildingSubID::EBuildingSubID, const std::string> specialMessages; //may be changed by CGTownBuilding::getVisitingBonusGreeting() const
};
class DLL_LINKAGE CTownHandler : public IHandlerBase

View File

@ -1644,11 +1644,11 @@ void CGTownInstance::serializeJsonOptions(JsonSerializeFormat & handler)
}
}
COPWBonus::COPWBonus (BuildingID bid, BuildingSubID::EBuildingSubID subId, CGTownInstance *TOWN)
COPWBonus::COPWBonus(BuildingID bid, BuildingSubID::EBuildingSubID subId, CGTownInstance * cgTown)
{
bID = bid;
bType = subId;
town = TOWN;
town = cgTown;
indexOnTV = static_cast<si32>(town->bonusingBuildings.size());
}
@ -1701,7 +1701,7 @@ void COPWBonus::onHeroVisit(const CGHeroInstance * h) const
cb->setManaPoints(heroID, 2 * h->manaLimit());
//TODO: investigate line below
//cb->setObjProperty (town->id, ObjProperty::VISITED, true);
iw.text << VLC->generaltexth->allTexts[579];
iw.text << getVisitingBonusGreeting();
cb->showInfoDialog(&iw);
//extra visit penalty if hero alredy had double mana points (or even more?!)
town->addHeroToStructureVisitors(h, indexOnTV);
@ -1710,11 +1710,11 @@ void COPWBonus::onHeroVisit(const CGHeroInstance * h) const
}
}
}
CTownBonus::CTownBonus (BuildingID index, BuildingSubID::EBuildingSubID subId, CGTownInstance *TOWN)
CTownBonus::CTownBonus(BuildingID index, BuildingSubID::EBuildingSubID subId, CGTownInstance * cgTown)
{
bID = index;
bType = subId;
town = TOWN;
town = cgTown;
indexOnTV = static_cast<si32>(town->bonusingBuildings.size());
}
@ -1729,7 +1729,6 @@ void CTownBonus::onHeroVisit(const CGHeroInstance * h) const
ObjectInstanceID heroID = h->id;
if (town->hasBuilt(bID) && visitors.find(heroID) == visitors.end())
{
si32 mid = 0;
si64 val = 0;
InfoWindow iw;
PrimarySkill::PrimarySkill what = PrimarySkill::ATTACK;
@ -1739,41 +1738,35 @@ void CTownBonus::onHeroVisit(const CGHeroInstance * h) const
case BuildingSubID::KNOWLEDGE_VISITING_BONUS: //wall of knowledge
what = PrimarySkill::KNOWLEDGE;
val = 1;
mid = 581;
iw.components.push_back(Component(Component::PRIM_SKILL, 3, 1, 0));
break;
case BuildingSubID::SPELL_POWER_VISITING_BONUS: //order of fire
what = PrimarySkill::SPELL_POWER;
val = 1;
mid = 582;
iw.components.push_back(Component(Component::PRIM_SKILL, 2, 1, 0));
break;
case BuildingSubID::ATTACK_VISITING_BONUS: //hall of Valhalla
what = PrimarySkill::ATTACK;
val = 1;
mid = 584;
iw.components.push_back(Component(Component::PRIM_SKILL, 0, 1, 0));
break;
case BuildingSubID::EXPERIENCE_VISITING_BONUS: //academy of battle scholars
what = PrimarySkill::EXPERIENCE;
val = static_cast<int>(h->calculateXp(1000));
mid = 583;
iw.components.push_back(Component(Component::EXPERIENCE, 0, val, 0));
break;
case BuildingSubID::DEFENSE_VISITING_BONUS: //cage of warlords
what = PrimarySkill::DEFENSE;
val = 1;
mid = 585;
iw.components.push_back(Component(Component::PRIM_SKILL, 1, 1, 0));
break;
}
assert(mid);
iw.player = cb->getOwner(heroID);
iw.text << VLC->generaltexth->allTexts[mid];
iw.text << getVisitingBonusGreeting();
cb->showInfoDialog(&iw);
cb->changePrimSkill(cb->getHero(heroID), what, val);
town->addHeroToStructureVisitors(h, indexOnTV);
@ -1811,3 +1804,39 @@ int GrowthInfo::totalGrowth() const
return ret;
}
const std::string CGTownBuilding::getVisitingBonusGreeting() const
{
auto bonusGreeting = town->town->getGreeting(bType);
if(!bonusGreeting.empty())
return bonusGreeting;
switch(bType)
{
case BuildingSubID::MANA_VORTEX:
bonusGreeting = std::string(VLC->generaltexth->localizedTexts["townHall"]["greetingManaVortex"].String());
break;
case BuildingSubID::KNOWLEDGE_VISITING_BONUS:
bonusGreeting = std::string(VLC->generaltexth->localizedTexts["townHall"]["greetingKnowledge"].String());
break;
case BuildingSubID::SPELL_POWER_VISITING_BONUS:
bonusGreeting = std::string(VLC->generaltexth->localizedTexts["townHall"]["greetingSpellPower"].String());
break;
case BuildingSubID::ATTACK_VISITING_BONUS:
bonusGreeting = std::string(VLC->generaltexth->localizedTexts["townHall"]["greetingAttack"].String());
break;
case BuildingSubID::EXPERIENCE_VISITING_BONUS:
bonusGreeting = std::string(VLC->generaltexth->localizedTexts["townHall"]["greetingExperience"].String());
break;
case BuildingSubID::DEFENSE_VISITING_BONUS:
bonusGreeting = std::string(VLC->generaltexth->localizedTexts["townHall"]["greetingDefence"].String());
break;
}
assert(!bonusGreeting.empty());
auto buildingName = town->town->getSpecialBuilding(bType)->Name();
boost::algorithm::replace_first(bonusGreeting, "%s", buildingName);
town->town->setGreeting(bType, bonusGreeting);
return bonusGreeting;
}

View File

@ -127,9 +127,12 @@ public:
if(version >= 792)
h & bType;
}
protected:
BuildingID bID; //from buildig list
BuildingSubID::EBuildingSubID bType;
const std::string getVisitingBonusGreeting() const;
};
class DLL_LINKAGE COPWBonus : public CGTownBuilding
@ -251,7 +254,7 @@ public:
return false;
});
if(!h.saving && version < 792)
if(!h.saving && version < 793)
updateBonusingBuildings();
}
//////////////////////////////////////////////////////////////////////////

View File

@ -196,11 +196,27 @@ void CObjectClassesHandler::loadObjectEntry(const std::string & identifier, cons
//some mods redefine content handlers in the decoration.json in such way:
//"core:sign" : { "types" : { "forgeSign" : { ...
if (!obj->subObjects.count(id)) // DO NOT override
static const std::vector<std::string> knownProblemObjects
{
"hota.hota decorations:hotaPandoraBox"
, "hota.hota decorations:hotaSubterreanGate"
};
bool overrideForce = !obj->subObjects.count(id) ||
std::any_of(knownProblemObjects.begin(), knownProblemObjects.end(), [obj, id](const std::string & str)
{
return str.compare(obj->subObjects[id]->subTypeName) == 0;
});
if (overrideForce) // DO NOT override mod handlers by default
{
obj->subObjects[id] = handler;
obj->subIds[convertedId] = id;
}
else
{
logGlobal->warn("Don't override handler %s in object %s(%d)::%s(%d) subTypeName : %s"
, obj->handlerName, obj->identifier, obj->id, convertedId, id, obj->subObjects[id]->subTypeName);
}
}
CObjectClassesHandler::ObjectContainter * CObjectClassesHandler::loadFromJson(const JsonNode & json, const std::string & name)

View File

@ -610,15 +610,16 @@ void CMapGenerator::createConnections2()
std::vector<int3> commonTiles;
//required for set_intersection
boost::sort(tilesA);
boost::sort(tilesB);
boost::set_intersection(tilesA, tilesB, std::back_inserter(commonTiles), [](const int3 &lhs, const int3 &rhs) -> bool
auto lambda = [](const int3 & lhs, const int3 & rhs) -> bool
{
//ignore z coordinate
return lhs.x < rhs.x || lhs.y < rhs.y;
});
//https://stackoverflow.com/questions/45966807/c-invalid-comparator-assert
return std::tie(lhs.x, lhs.y) < std::tie(rhs.x, rhs.y); //ignore z coordinate
};
//required for set_intersection
boost::sort(tilesA, lambda);
boost::sort(tilesB, lambda);
boost::set_intersection(tilesA, tilesB, std::back_inserter(commonTiles), lambda);
vstd::erase_if(commonTiles, [](const int3 &tile) -> bool
{

View File

@ -12,7 +12,7 @@
#include "../ConstTransitivePtr.h"
#include "../GameConstants.h"
const ui32 SERIALIZATION_VERSION = 792;
const ui32 SERIALIZATION_VERSION = 793;
const ui32 MINIMAL_SERIALIZATION_VERSION = 753;
const std::string SAVEGAME_MAGIC = "VCMISVG";